diff --git a/DEPS b/DEPS
index 60a5148..bebb6f06 100644
--- a/DEPS
+++ b/DEPS
@@ -129,11 +129,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'e25b4472cdd9f09cd393c9c34651218507c9847b',
+  'skia_revision': 'dde12a25bb5e05ab929590cc7b71851ee76378ec',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'c0843ced0895d1a1415bdd39650994ba574ff5a3',
+  'v8_revision': 'b9fd9ceb186882b6ceab2afeef4a58352022e109',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -141,11 +141,11 @@
   # 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': '5688c85b3c393ff6e549dd3b22b641e710078041',
+  'angle_revision': '43997017b0ed205e1b82c130e201554c0c06545a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '2b9fb4bf5ece8b42101a21693aac22b3f16983f4',
+  'swiftshader_revision': '225a13016b1c34dd7458d01204d89e561a3ea0b3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -196,7 +196,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': 'e1fc0b0b3dfcb5f4bfff02f30566b950aaa06c3f',
+  'catapult_revision': '63e0762df0c5f474b5a9eceb25251d6f06a73aa3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -212,7 +212,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'feed_revision': '23ca33876e4ef3128673ec2b20c7fa4ffdce0bb0',
+  'feed_revision': 'd1e6b4e648a89fb58f706eb182f16053fa95f1fe',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling android_sdk_build-tools_version
   # and whatever else without interference from each other.
@@ -252,7 +252,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': 'e2ddb9371edb03c43b0fe386ef340db2697eede1',
+  'spv_tools_revision': '26c1b8878315a7a5c188df45e0bc236bb222b698',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -272,7 +272,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '09d925aeae2de5482a024f27cd7cb2f659500020',
+  'quiche_revision': 'a8d9355b5dbfcfd8f34a7b4a1d30c2325958f3f8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -287,12 +287,12 @@
   # revisions.
 
   # GN CIPD package version.
-  'gn_version': 'git_revision:0790d3043387c762a6bacb1ae0a9ebe883188ab2',
+  'gn_version': 'git_revision:64b846c96daeb3eaf08e26d8a84d8451c6cb712b',
 
-  # Also, if you change these, make sure you update the svn_revisions in
-  # //buildtools/deps_revisions.gni.
+  # Also, if you change these, update buildtools/DEPS too. Also update the
+  # libc++ svn_revision in //buildtools/deps_revisions.gni.
   'clang_format_revision': '96636aa0e9f047f17447f2d45a094d0b59ed7917',
-  'libcxx_revision': '955113db37563c8632e31ddcff2047845553d7ff',
+  'libcxx_revision': 'fbddc46986100095d5f7ed1bc2bf795d3bb3e9e4',
   'libcxxabi_revision': '0d529660e32d77d9111912d73f2c74fc5fa2a858',
   'libunwind_revision': '69d9b84cca8354117b9fe9705a4430d789ee599b',
 }
@@ -805,7 +805,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '2f8cd2bbcb496e0ac9591092d508c5617c7fe5c7',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '0b63029f96dd8e791b832212638d3356cd8def40',
       'condition': 'checkout_linux',
   },
 
@@ -825,12 +825,12 @@
   },
 
   'src/third_party/custom_tabs_client/src': {
-      'url': Var('chromium_git') + '/custom-tabs-client.git' + '@' + 'cea0bcafdebe711f0f83a5f05e07bc367ca18422',
+      'url': Var('chromium_git') + '/custom-tabs-client.git' + '@' + '26f06b877be8654c3f51928ec713a283d5ce3a88',
       'condition': 'checkout_android',
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '865445eb8a457bd1acf643d427e722f640c31f6f',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b8268cad11b722e682b519f78990205f3f98f6c0',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -899,7 +899,7 @@
   },
 
   'src/third_party/glslang/src':
-    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'e0d59bbe1857e75134989eddb7437e9c068ec915',
+    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'ef807f4bc543e061f25dbbee6cb64dd5053b2adc',
 
   'src/third_party/google_toolbox_for_mac/src': {
       'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'),
@@ -1172,7 +1172,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '2ba54ced73cba6639dfc4db4820e76b0233c89ab',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '17cb775f71f2df3ae071a2059620482a93562b46',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1343,7 +1343,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '688fbfe33779392aa210d67d4aa12cb012f112c2',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'd98cbd8f91a3d94c08e3154ec78c2e54dbd3564e',
+    Var('webrtc_git') + '/src.git' + '@' + '1c1b1ea137cef7b40e569eb79ff21849ddbdc3c5',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1384,7 +1384,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1e9a676900b263e30f7b46530208d9150f6d99f7',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ec1d75214da72e048db7fb377abaebf27be7b530',
     'condition': 'checkout_src_internal',
   },
 
@@ -1405,7 +1405,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/android_deps/libs/android_arch_core_common',
-              'version': 'version:1.0.0-cr0',
+              'version': 'version:1.1.1-cr0',
           },
       ],
       'condition': 'checkout_android',
@@ -1416,7 +1416,18 @@
       'packages': [
           {
               'package': 'chromium/third_party/android_deps/libs/android_arch_lifecycle_common',
-              'version': 'version:1.0.0-cr0',
+              'version': 'version:1.1.1-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
+  'src/third_party/android_deps/libs/android_arch_lifecycle_common_java8': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/android_deps/libs/android_arch_lifecycle_common_java8',
+              'version': 'version:1.1.1-cr0',
           },
       ],
       'condition': 'checkout_android',
@@ -1427,7 +1438,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/android_deps/libs/android_arch_lifecycle_runtime',
-              'version': 'version:1.0.0-cr0',
+              'version': 'version:1.1.1-cr0',
           },
       ],
       'condition': 'checkout_android',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 8e1a84c6..9e2e1414 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -582,7 +582,7 @@
       (),
     ),
     (
-      r'base::SharedMemory(|Handle)',
+      r'/base::SharedMemory(|Handle)',
       (
           'base::SharedMemory is deprecated. Please use',
           '{Writable,ReadOnly}SharedMemoryRegion instead.',
diff --git a/WATCHLISTS b/WATCHLISTS
index 91789156..738b479 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1825,8 +1825,7 @@
                                 'wnwen+watch@chromium.org'],
     'android_crazy_linker': ['johnmaguire+watch@google.com'],
     'android_deps': ['wnwen+watch@chromium.org'],
-    'android_features': ['wnwen+watch@chromium.org',
-                         'tiborg+watch@chromium.org'],
+    'android_features': ['tiborg+watch@chromium.org'],
     'android_infobars': ['dfalcantara+watch@chromium.org'],
     'android_infra': ['agrieve+watch@chromium.org',
                       'estevenson+watch@chromium.org',
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc
index 0581366..a6a8a54 100644
--- a/android_webview/browser/aw_contents.cc
+++ b/android_webview/browser/aw_contents.cc
@@ -63,7 +63,6 @@
 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
 #include "components/autofill/core/browser/autofill_manager.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
-#include "components/content_capture/android/content_capture_receiver_manager_android.h"
 #include "components/navigation_interception/intercept_navigation_delegate.h"
 #include "content/public/browser/android/child_process_importance.h"
 #include "content/public/browser/android/synchronous_compositor.h"
@@ -281,8 +280,7 @@
     const JavaParamRef<jobject>& contents_client_bridge,
     const JavaParamRef<jobject>& io_thread_client,
     const JavaParamRef<jobject>& intercept_navigation_delegate,
-    const JavaParamRef<jobject>& autofill_provider,
-    const JavaParamRef<jobject>& content_capture_receiver_manager) {
+    const JavaParamRef<jobject>& autofill_provider) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   // The |aw_content| param is technically spurious as it duplicates |obj| but
   // is passed over anyway to make the binding more explicit.
@@ -302,10 +300,7 @@
   InterceptNavigationDelegate::Associate(
       web_contents_.get(), std::make_unique<InterceptNavigationDelegate>(
                                env, intercept_navigation_delegate));
-  if (content_capture_receiver_manager) {
-    content_capture::ContentCaptureReceiverManagerAndroid::Create(
-        web_contents_.get(), content_capture_receiver_manager);
-  }
+
   if (!autofill_provider.is_null()) {
     autofill_provider_ = std::make_unique<autofill::AutofillProviderAndroid>(
         autofill_provider, web_contents_.get());
diff --git a/android_webview/browser/aw_contents.h b/android_webview/browser/aw_contents.h
index f67e852..bc7e248 100644
--- a/android_webview/browser/aw_contents.h
+++ b/android_webview/browser/aw_contents.h
@@ -97,9 +97,7 @@
       const base::android::JavaParamRef<jobject>& contents_client_bridge,
       const base::android::JavaParamRef<jobject>& io_thread_client,
       const base::android::JavaParamRef<jobject>& intercept_navigation_delegate,
-      const base::android::JavaParamRef<jobject>& autofill_provider,
-      const base::android::JavaParamRef<jobject>&
-          content_capture_receiver_manager);
+      const base::android::JavaParamRef<jobject>& autofill_provider);
   base::android::ScopedJavaLocalRef<jobject> GetWebContents(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
diff --git a/android_webview/browser/gfx/aw_vulkan_context_provider.cc b/android_webview/browser/gfx/aw_vulkan_context_provider.cc
index fb632cc..77011da 100644
--- a/android_webview/browser/gfx/aw_vulkan_context_provider.cc
+++ b/android_webview/browser/gfx/aw_vulkan_context_provider.cc
@@ -68,8 +68,8 @@
 AwVulkanContextProvider::GetOrCreateInstance(AwDrawFn_InitVkParams* params) {
   DCHECK(g_vulkan_context_provider || params);
   if (g_vulkan_context_provider) {
-    DCHECK_EQ(params->device, g_vulkan_context_provider->device());
-    DCHECK_EQ(params->queue, g_vulkan_context_provider->queue());
+    DCHECK(!params || params->device == g_vulkan_context_provider->device());
+    DCHECK(!params || params->queue == g_vulkan_context_provider->queue());
     return base::WrapRefCounted(g_vulkan_context_provider);
   }
 
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc
index 0e947ea..beb8a91 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -309,6 +309,9 @@
   builder.SetHttpAuthHandlerFactory(CreateAuthHandlerFactory());
   builder.set_host_mapping_rules(GetCmdlineOverridesForHostResolver());
 
+  // Context copy allowed because NetworkService is confirmed disabled.
+  builder.set_allow_copy();
+
   url_request_context_ = builder.Build();
 
   // For Android WebView, do not enforce policies that are not consistent with
diff --git a/android_webview/browser/network_service/README.md b/android_webview/browser/network_service/README.md
new file mode 100644
index 0000000..5833ee7
--- /dev/null
+++ b/android_webview/browser/network_service/README.md
@@ -0,0 +1,25 @@
+# Android WebView Network Service
+
+This folder contains Android WebView's code for interacting with the Network
+Service (including code shared with the legacy code path, while that path is
+still supported). For details on the Network Service in general, see
+[`//services/network/`](/services/network/README.md).
+
+## In-process
+
+Android WebView aims to run with the Network Service in-process
+(`features::kNetworkServiceInProcess`). For details, see
+https://crbug.com/882650.
+
+## Testing with the Network Service
+
+Please see [general testing
+instructions](/android_webview/docs/test-instructions.md). Until the feature is
+on-by-default, you can enable the Network Service in tests like so:
+
+```shell
+$ autoninja -C out/Default webview_instrumentation_test_apk
+$ out/Default/bin/run_webview_instrumentation_test_apk \
+    --enable-features="NetworkService,NetworkServiceInProcess" \
+    -f <some test filter>  # See general instructions for test filtering
+```
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
index 6a457e6..0a4cb7887 100644
--- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
+++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
@@ -13,7 +13,6 @@
 #include "base/optional.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
-#include "net/base/completion_callback.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/resource_response.h"
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index ce068430..3ab4f14 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -67,8 +67,6 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.components.autofill.AutofillProvider;
 import org.chromium.components.content_capture.ContentCaptureConsumer;
-import org.chromium.components.content_capture.ContentCaptureFeatures;
-import org.chromium.components.content_capture.ContentCaptureReceiverManager;
 import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
 import org.chromium.components.navigation_interception.NavigationParams;
 import org.chromium.content_public.browser.ChildProcessImportance;
@@ -483,7 +481,7 @@
 
     private JavascriptInjector mJavascriptInjector;
 
-    private ContentCaptureReceiverManager mContentCaptureReceiverManager;
+    private ContentCaptureConsumer mContentCaptureConsumer;
 
     private static class WebContentsInternalsHolder implements WebContents.InternalsHolder {
         private final WeakReference<AwContents> mAwContentsRef;
@@ -936,10 +934,6 @@
             setOverScrollMode(mContainerView.getOverScrollMode());
             setScrollBarStyle(mInternalAccessAdapter.super_getScrollBarStyle());
 
-            if (ContentCaptureFeatures.isEnabled()) {
-                mContentCaptureReceiverManager = new ContentCaptureReceiverManager();
-            }
-
             setNewAwContents(nativeInit(mBrowserContext));
 
             onContainerViewChanged();
@@ -1120,9 +1114,6 @@
         awViewMethodsImpl.onWindowFocusChanged(mContainerView.hasWindowFocus());
         awViewMethodsImpl.onFocusChanged(mContainerView.hasFocus(), 0, null);
         mContainerView.requestLayout();
-        if (mContentCaptureReceiverManager != null) {
-            mContentCaptureReceiverManager.onContainerViewChanged(mContainerView);
-        }
         if (mAutofillProvider != null) mAutofillProvider.onContainerViewChanged(mContainerView);
     }
 
@@ -1225,6 +1216,9 @@
             setNewAwContentsPreO(newAwContentsPtr);
             if (textClassifier != null) setTextClassifier(textClassifier);
         }
+        if (mContentCaptureConsumer != null) {
+            mContentCaptureConsumer.onWebContentsChanged(mWebContents);
+        }
     }
 
     // Helper for setNewAwContents containing everything which applies to pre-O.
@@ -1255,8 +1249,7 @@
         initWebContents(mViewAndroidDelegate, mInternalAccessAdapter, mWebContents,
                 mWindowAndroid.getWindowAndroid(), mWebContentsInternalsHolder);
         nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge,
-                mIoThreadClient, mInterceptNavigationDelegate, mAutofillProvider,
-                mContentCaptureReceiverManager);
+                mIoThreadClient, mInterceptNavigationDelegate, mAutofillProvider);
         GestureListenerManager.fromWebContents(mWebContents)
                 .addListener(new AwGestureStateListener());
 
@@ -1417,6 +1410,11 @@
         if (TRACE) Log.i(TAG, "%s destroy", this);
         if (isDestroyed(NO_WARN)) return;
 
+        if (mContentCaptureConsumer != null) {
+            mContentCaptureConsumer.destroy();
+            mContentCaptureConsumer = null;
+        }
+
         // Remove pending messages
         mContentsClient.getCallbackHelper().removeCallbacksAndMessages();
 
@@ -1565,8 +1563,7 @@
     }
 
     public void setContentCaptureConsumer(ContentCaptureConsumer consumer) {
-        if (mContentCaptureReceiverManager != null)
-            mContentCaptureReceiverManager.setContentCaptureConsumer(consumer);
+        mContentCaptureConsumer = consumer;
     }
 
     //--------------------------------------------------------------------------------------------
@@ -3867,8 +3864,7 @@
             AwWebContentsDelegate webViewWebContentsDelegate,
             AwContentsClientBridge contentsClientBridge, AwContentsIoThreadClient ioThreadClient,
             InterceptNavigationDelegate navigationInterceptionDelegate,
-            AutofillProvider autofillProvider,
-            ContentCaptureReceiverManager contentCaptureReceiverManager);
+            AutofillProvider autofillProvider);
     private native WebContents nativeGetWebContents(long nativeAwContents);
     private native void nativeSetCompositorFrameConsumer(
             long nativeAwContents, long nativeCompositorFrameConsumer);
diff --git a/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/DropDownListTest.java b/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/DropDownListTest.java
index 2643721..84e7cb88 100644
--- a/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/DropDownListTest.java
+++ b/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/DropDownListTest.java
@@ -30,6 +30,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.webview_ui_test.R;
 import org.chromium.webview_ui_test.WebViewUiTestActivity;
 import org.chromium.webview_ui_test.test.util.Actions;
@@ -37,7 +38,6 @@
 import org.chromium.webview_ui_test.test.util.UseLayout;
 import org.chromium.webview_ui_test.test.util.WebViewUiTestRule;
 
-
 /**
  * Tests for WebView ActionMode.
  */
@@ -84,6 +84,8 @@
     /**
      * Test Drop Down List works in ViewPort Scale Factor > 1 in wideViewPortMode
      */
+    // TODO(aluo): Re-enable once crbug.com/947352 is fixed.
+    @DisableIf.Build(product_name_includes = "walleye")
     @Test
     @SmallTest
     @UseLayout("edittext_webview")
diff --git a/apps/ui/views/app_window_frame_view.cc b/apps/ui/views/app_window_frame_view.cc
index 3d3e6dd..0caa47b 100644
--- a/apps/ui/views/app_window_frame_view.cc
+++ b/apps/ui/views/app_window_frame_view.cc
@@ -4,6 +4,9 @@
 
 #include "apps/ui/views/app_window_frame_view.h"
 
+#include <memory>
+#include <utility>
+
 #include "base/strings/utf_string_conversions.h"
 #include "cc/paint/paint_flags.h"
 #include "chrome/grit/theme_resources.h"
@@ -25,8 +28,6 @@
 
 namespace {
 
-const int kDefaultResizeInsideBoundsSize = 5;
-const int kDefaultResizeAreaCornerSize = 16;
 const int kCaptionHeight = 25;
 
 }  // namespace
@@ -45,68 +46,60 @@
       window_(window),
       draw_frame_(draw_frame),
       active_frame_color_(active_frame_color),
-      inactive_frame_color_(inactive_frame_color),
-      close_button_(NULL),
-      maximize_button_(NULL),
-      restore_button_(NULL),
-      minimize_button_(NULL),
-      resize_inside_bounds_size_(kDefaultResizeInsideBoundsSize),
-      resize_outside_bounds_size_(0),
-      resize_area_corner_size_(kDefaultResizeAreaCornerSize) {
-}
+      inactive_frame_color_(inactive_frame_color) {}
 
 AppWindowFrameView::~AppWindowFrameView() = default;
 
 void AppWindowFrameView::Init() {
   if (draw_frame_) {
     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-    close_button_ = new views::ImageButton(this);
-    close_button_->SetImage(
+    auto close_button = std::make_unique<views::ImageButton>(this);
+    close_button->SetImage(
         views::Button::STATE_NORMAL,
         rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE).ToImageSkia());
-    close_button_->SetImage(
+    close_button->SetImage(
         views::Button::STATE_HOVERED,
         rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE_H).ToImageSkia());
-    close_button_->SetImage(
+    close_button->SetImage(
         views::Button::STATE_PRESSED,
         rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE_P).ToImageSkia());
-    close_button_->SetAccessibleName(
+    close_button->SetAccessibleName(
         l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE));
-    AddChildView(close_button_);
+    close_button_ = AddChildView(std::move(close_button));
     // STATE_NORMAL images are set in SetButtonImagesForFrame, not here.
-    maximize_button_ = new views::ImageButton(this);
-    maximize_button_->SetImage(
+    auto maximize_button = std::make_unique<views::ImageButton>(this);
+    maximize_button->SetImage(
         views::Button::STATE_HOVERED,
         rb.GetNativeImageNamed(IDR_APP_WINDOW_MAXIMIZE_H).ToImageSkia());
-    maximize_button_->SetImage(
+    maximize_button->SetImage(
         views::Button::STATE_PRESSED,
         rb.GetNativeImageNamed(IDR_APP_WINDOW_MAXIMIZE_P).ToImageSkia());
-    maximize_button_->SetImage(
+    maximize_button->SetImage(
         views::Button::STATE_DISABLED,
         rb.GetNativeImageNamed(IDR_APP_WINDOW_MAXIMIZE_D).ToImageSkia());
-    maximize_button_->SetAccessibleName(
+    maximize_button->SetAccessibleName(
         l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE));
-    AddChildView(maximize_button_);
-    restore_button_ = new views::ImageButton(this);
-    restore_button_->SetImage(
+    maximize_button_ = AddChildView(std::move(maximize_button));
+    auto restore_button = std::make_unique<views::ImageButton>(this);
+    restore_button->SetImage(
         views::Button::STATE_HOVERED,
         rb.GetNativeImageNamed(IDR_APP_WINDOW_RESTORE_H).ToImageSkia());
-    restore_button_->SetImage(
+    restore_button->SetImage(
         views::Button::STATE_PRESSED,
         rb.GetNativeImageNamed(IDR_APP_WINDOW_RESTORE_P).ToImageSkia());
-    restore_button_->SetAccessibleName(
+    restore_button->SetAccessibleName(
         l10n_util::GetStringUTF16(IDS_APP_ACCNAME_RESTORE));
-    AddChildView(restore_button_);
-    minimize_button_ = new views::ImageButton(this);
-    minimize_button_->SetImage(
+    restore_button_ = AddChildView(std::move(restore_button));
+    auto minimize_button = std::make_unique<views::ImageButton>(this);
+    minimize_button->SetImage(
         views::Button::STATE_HOVERED,
         rb.GetNativeImageNamed(IDR_APP_WINDOW_MINIMIZE_H).ToImageSkia());
-    minimize_button_->SetImage(
+    minimize_button->SetImage(
         views::Button::STATE_PRESSED,
         rb.GetNativeImageNamed(IDR_APP_WINDOW_MINIMIZE_P).ToImageSkia());
-    minimize_button_->SetAccessibleName(
+    minimize_button->SetAccessibleName(
         l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MINIMIZE));
-    AddChildView(minimize_button_);
+    minimize_button_ = AddChildView(std::move(minimize_button));
 
     SetButtonImagesForFrame();
   }
diff --git a/apps/ui/views/app_window_frame_view.h b/apps/ui/views/app_window_frame_view.h
index b9c1490f..8c4c610 100644
--- a/apps/ui/views/app_window_frame_view.h
+++ b/apps/ui/views/app_window_frame_view.h
@@ -96,19 +96,19 @@
   bool draw_frame_;
   SkColor active_frame_color_;
   SkColor inactive_frame_color_;
-  views::ImageButton* close_button_;
-  views::ImageButton* maximize_button_;
-  views::ImageButton* restore_button_;
-  views::ImageButton* minimize_button_;
+  views::ImageButton* close_button_ = nullptr;
+  views::ImageButton* maximize_button_ = nullptr;
+  views::ImageButton* restore_button_ = nullptr;
+  views::ImageButton* minimize_button_ = nullptr;
 
   // Allow resize for clicks this many pixels inside the bounds.
-  int resize_inside_bounds_size_;
+  int resize_inside_bounds_size_ = 5;
 
   // Allow resize for clicks  this many pixels outside the bounds.
-  int resize_outside_bounds_size_;
+  int resize_outside_bounds_size_ = 0;
 
   // Size in pixels of the lower-right corner resize handle.
-  int resize_area_corner_size_;
+  int resize_area_corner_size_ = 16;
 
   DISALLOW_COPY_AND_ASSIGN(AppWindowFrameView);
 };
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 488123e..5f276141 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1386,7 +1386,8 @@
     "//ui/accessibility",
     "//ui/base",
     "//ui/base:ui_data_pack",
-    "//ui/base/ime",
+    "//ui/base/ime/chromeos",
+    "//ui/base/ime/init",
     "//ui/chromeos",
     "//ui/chromeos/events",
     "//ui/chromeos/resources",
@@ -1546,7 +1547,8 @@
     "//skia",
     "//ui/aura",
     "//ui/base",
-    "//ui/base/ime",
+    "//ui/base/ime/chromeos",
+    "//ui/base/ime/init",
     "//ui/compositor",
     "//ui/display",
     "//ui/events/devices",
@@ -1967,6 +1969,7 @@
     "//ui/base",
     "//ui/base:test_support",
     "//ui/base/ime",
+    "//ui/base/ime/chromeos",
     "//ui/chromeos",
     "//ui/chromeos/events",
     "//ui/compositor",
diff --git a/ash/accelerators/accelerator_confirmation_dialog.cc b/ash/accelerators/accelerator_confirmation_dialog.cc
index 603ee2d..9e63cc7 100644
--- a/ash/accelerators/accelerator_confirmation_dialog.cc
+++ b/ash/accelerators/accelerator_confirmation_dialog.cc
@@ -33,7 +33,8 @@
   SetBorder(views::CreateEmptyBorder(
       views::LayoutProvider::Get()->GetDialogInsetsForContentType(
           views::TEXT, views::TEXT)));
-  AddChildView(new views::Label(l10n_util::GetStringUTF16(dialog_text_id)));
+  AddChildView(std::make_unique<views::Label>(
+      l10n_util::GetStringUTF16(dialog_text_id)));
 
   // Parent the dialog widget to the LockSystemModalContainer, or
   // OverlayContainer to ensure that it will get displayed on respective
diff --git a/ash/accelerators/exit_warning_handler.cc b/ash/accelerators/exit_warning_handler.cc
index a2773a0..b8499e3d 100644
--- a/ash/accelerators/exit_warning_handler.cc
+++ b/ash/accelerators/exit_warning_handler.cc
@@ -53,14 +53,14 @@
     SetPreferredSize(
         gfx::Size(text_width_ + kHorizontalMarginAroundText,
                   font_list.GetHeight() + kVerticalMarginAroundText));
-    views::Label* label = new views::Label();
+    auto label = std::make_unique<views::Label>();
     label->SetText(text_);
     label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
     label->SetFontList(font_list);
     label->SetEnabledColor(kTextColor);
     label->SetAutoColorReadabilityEnabled(false);
     label->SetSubpixelRenderingEnabled(false);
-    AddChildView(label);
+    AddChildView(std::move(label));
     SetLayoutManager(std::make_unique<views::FillLayout>());
   }
 
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc
index d8fc685..88610f81 100644
--- a/ash/accessibility/accessibility_controller.cc
+++ b/ash/accessibility/accessibility_controller.cc
@@ -1253,11 +1253,11 @@
   if (virtual_keyboard_enabled_ == enabled)
     return;
 
-  const bool was_enabled = virtual_keyboard_enabled_;
   virtual_keyboard_enabled_ = enabled;
 
   NotifyAccessibilityStatusChanged();
 
+  const bool was_enabled = keyboard::IsKeyboardEnabled();
   keyboard::SetAccessibilityKeyboardEnabled(enabled);
 
   if (::features::IsMultiProcessMash()) {
@@ -1283,4 +1283,13 @@
       true /* Enables full description*/));
 }
 
+void AccessibilityController::SetVirtualKeyboardVisible(bool is_visible) {
+  if (is_visible) {
+    Shell::Get()->ash_keyboard_controller()->ShowKeyboard();
+  } else {
+    Shell::Get()->ash_keyboard_controller()->HideKeyboard(
+        mojom::HideReason::kUser);
+  }
+}
+
 }  // namespace ash
diff --git a/ash/accessibility/accessibility_controller.h b/ash/accessibility/accessibility_controller.h
index 1b5adb9f..640fc34 100644
--- a/ash/accessibility/accessibility_controller.h
+++ b/ash/accessibility/accessibility_controller.h
@@ -186,6 +186,7 @@
   void ToggleDictationFromSource(mojom::DictationToggleSource source) override;
   void ForwardKeyEventsToSwitchAccess(bool should_forward) override;
   void GetBatteryDescription(GetBatteryDescriptionCallback callback) override;
+  void SetVirtualKeyboardVisible(bool is_visible) override;
 
   // SessionObserver:
   void OnSigninScreenPrefServiceInitialized(PrefService* prefs) override;
diff --git a/ash/accessibility/accessibility_controller_unittest.cc b/ash/accessibility/accessibility_controller_unittest.cc
index 59210e29..ae3dc44 100644
--- a/ash/accessibility/accessibility_controller_unittest.cc
+++ b/ash/accessibility/accessibility_controller_unittest.cc
@@ -21,7 +21,9 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "components/prefs/pref_service.h"
+#include "ui/keyboard/keyboard_controller.h"
 #include "ui/keyboard/keyboard_util.h"
+#include "ui/keyboard/test/test_keyboard_controller_observer.h"
 #include "ui/message_center/message_center.h"
 
 using message_center::MessageCenter;
@@ -293,6 +295,29 @@
   controller->RemoveObserver(&observer);
 }
 
+// See https://crbug.com/946358.
+TEST_F(AccessibilityControllerTest, RebuildsVirtualKeyboardWhenPrefChanges) {
+  AccessibilityController* controller =
+      Shell::Get()->accessibility_controller();
+  EXPECT_FALSE(controller->virtual_keyboard_enabled());
+
+  // Virtual keyboard enabled with compact layout.
+  keyboard::SetTouchKeyboardEnabled(true);
+
+  keyboard::TestKeyboardControllerObserver observer;
+  keyboard::KeyboardController::Get()->AddObserver(&observer);
+
+  // Virtual keyboard should rebuild to switch to a11y layout.
+  controller->SetVirtualKeyboardEnabled(true);
+  EXPECT_EQ(1, observer.enabled_count);
+
+  // Virtual keyboard should rebuild to switch back to compact layout.
+  controller->SetVirtualKeyboardEnabled(false);
+  EXPECT_EQ(2, observer.enabled_count);
+
+  keyboard::KeyboardController::Get()->RemoveObserver(&observer);
+}
+
 // Tests that ash's controller gets shutdown sound duration properly from
 // remote client.
 TEST_F(AccessibilityControllerTest, GetShutdownSoundDuration) {
diff --git a/ash/app_list/BUILD.gn b/ash/app_list/BUILD.gn
index 0e3b4521..ae94c47 100644
--- a/ash/app_list/BUILD.gn
+++ b/ash/app_list/BUILD.gn
@@ -131,6 +131,7 @@
     "//ui/aura",
     "//ui/base",
     "//ui/base/ime",
+    "//ui/base/ime/chromeos",
     "//ui/chromeos/search_box",
     "//ui/compositor",
     "//ui/display",
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc
index 8e11977..4394d784 100644
--- a/ash/app_list/app_list_controller_impl.cc
+++ b/ash/app_list/app_list_controller_impl.cc
@@ -28,7 +28,9 @@
 #include "ash/public/cpp/app_list/app_list_features.h"
 #include "ash/public/cpp/app_list/app_list_metrics.h"
 #include "ash/public/cpp/shell_window_ids.h"
+#include "ash/root_window_controller.h"
 #include "ash/session/session_controller.h"
+#include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shell.h"
 #include "ash/voice_interaction/voice_interaction_controller.h"
 #include "ash/wallpaper/wallpaper_controller.h"
@@ -550,6 +552,14 @@
 }
 
 void AppListControllerImpl::OnTabletModeEnded() {
+  base::Optional<app_list::AppListPresenterImpl::ScopedDismissAnimationDisabler>
+      dismiss_animation_disabler;
+  aura::Window* window = presenter_.GetWindow();
+  if (window && RootWindowController::ForWindow(window)
+                    ->GetShelfLayoutManager()
+                    ->HasVisibleWindow()) {
+    dismiss_animation_disabler.emplace(presenter());
+  }
   if (IsVisible())
     presenter_.GetView()->OnTabletModeChanged(false);
 
diff --git a/ash/app_list/presenter/app_list_presenter_impl.cc b/ash/app_list/presenter/app_list_presenter_impl.cc
index 0b6b82e..559146d 100644
--- a/ash/app_list/presenter/app_list_presenter_impl.cc
+++ b/ash/app_list/presenter/app_list_presenter_impl.cc
@@ -153,7 +153,7 @@
     view_->GetWidget()->Deactivate();
 
   delegate_->OnClosing();
-  ScheduleAnimation();
+  ScheduleDismissAnimation();
   NotifyTargetVisibilityChanged(GetTargetVisibility());
   base::RecordAction(base::UserMetricsAction("Launcher_Dismiss"));
 }
@@ -309,7 +309,7 @@
   view_ = nullptr;
 }
 
-void AppListPresenterImpl::ScheduleAnimation() {
+void AppListPresenterImpl::ScheduleDismissAnimation() {
   // Stop observing previous animation.
   StopObservingImplicitAnimations();
 
@@ -320,8 +320,9 @@
   const gfx::Vector2d offset =
       delegate_->GetVisibilityAnimationOffset(root_window);
   const base::TimeDelta animation_duration =
-      delegate_->GetVisibilityAnimationDuration(root_window,
-                                                view_->is_fullscreen());
+      dismiss_without_animation_ ? base::TimeDelta::FromMilliseconds(0)
+                                 : delegate_->GetVisibilityAnimationDuration(
+                                       root_window, /*is_visible=*/false);
   gfx::Rect target_bounds = widget->GetNativeView()->bounds();
   target_bounds.Offset(offset);
   widget->GetNativeView()->SetBounds(target_bounds);
diff --git a/ash/app_list/presenter/app_list_presenter_impl.h b/ash/app_list/presenter/app_list_presenter_impl.h
index d2a78d37..c102ca0 100644
--- a/ash/app_list/presenter/app_list_presenter_impl.h
+++ b/ash/app_list/presenter/app_list_presenter_impl.h
@@ -44,6 +44,23 @@
       base::RepeatingCallback<void(ui::ScopedLayerAnimationSettings* settings,
                                    bool observe)>;
 
+  // Used to dismiss the app list without animations.
+  class ScopedDismissAnimationDisabler {
+   public:
+    explicit ScopedDismissAnimationDisabler(AppListPresenterImpl* presenter)
+        : presenter_(presenter) {
+      presenter_->dismiss_without_animation_ = true;
+    }
+    ~ScopedDismissAnimationDisabler() {
+      presenter_->dismiss_without_animation_ = false;
+    }
+
+   private:
+    AppListPresenterImpl* const presenter_;
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedDismissAnimationDisabler);
+  };
+
   explicit AppListPresenterImpl(
       std::unique_ptr<AppListPresenterDelegate> delegate);
   ~AppListPresenterImpl() override;
@@ -118,8 +135,8 @@
   // Forgets the view.
   void ResetView();
 
-  // Starts show/hide animation.
-  void ScheduleAnimation();
+  // Starts dismiss animation.
+  void ScheduleDismissAnimation();
 
   // Returns the id of the display containing the app list, if visible. If not
   // visible returns kInvalidDisplayId.
@@ -178,6 +195,9 @@
   bool last_visible_ = false;
   int64_t last_display_id_ = display::kInvalidDisplayId;
 
+  // If true, dismiss the app list immediately.
+  bool dismiss_without_animation_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(AppListPresenterImpl);
 };
 
diff --git a/ash/app_list/views/app_list_folder_view.cc b/ash/app_list/views/app_list_folder_view.cc
index 32635de..76e8c59 100644
--- a/ash/app_list/views/app_list_folder_view.cc
+++ b/ash/app_list/views/app_list_folder_view.cc
@@ -244,18 +244,18 @@
                                   ? top_item_views_bounds[i]
                                   : folder_view_->folder_item_icon_bounds();
 
-      TopIconAnimationView* icon_view = new TopIconAnimationView(
+      auto icon_view = std::make_unique<TopIconAnimationView>(
           top_item->icon(), base::UTF8ToUTF16(top_item->GetDisplayName()),
           scaled_rect, show_, item_in_folder_icon);
+      auto* icon_view_ptr = icon_view.get();
 
-      icon_view->AddObserver(this);
-      top_icon_views_.push_back(icon_view);
-
+      icon_view_ptr->AddObserver(this);
       // Add the transitional views into child views, and set its bounds to the
       // same location of the item in the folder list view.
-      folder_view_->background_view()->AddChildView(top_icon_views_.back());
-      icon_view->SetBoundsRect(first_page_item_views_bounds[i]);
-      icon_view->TransformView();
+      top_icon_views_.push_back(
+          folder_view_->background_view()->AddChildView(std::move(icon_view)));
+      icon_view_ptr->SetBoundsRect(first_page_item_views_bounds[i]);
+      icon_view_ptr->TransformView();
     }
   }
 
@@ -438,37 +438,32 @@
                                      ContentsView* contents_view)
     : container_view_(container_view),
       contents_view_(contents_view),
-      background_view_(new views::View),
-      contents_container_(new views::View),
-      folder_header_view_(new FolderHeaderView(this)),
       view_model_(new views::ViewModel),
-      model_(model),
-      folder_item_(NULL),
-      hide_for_reparent_(false),
-      animation_start_frame_number_(0) {
+      model_(model) {
   // The background's corner radius cannot be changed in the same layer of the
   // contents container using layer animation, so use another layer to perform
   // such changes.
+  background_view_ = AddChildView(std::make_unique<views::View>());
   background_view_->SetPaintToLayer();
   background_view_->layer()->SetFillsBoundsOpaquely(false);
-  AddChildView(background_view_);
   view_model_->Add(background_view_, kIndexBackground);
 
+  contents_container_ = AddChildView(std::make_unique<views::View>());
   contents_container_->SetPaintToLayer(ui::LAYER_NOT_DRAWN);
-  AddChildView(contents_container_);
   view_model_->Add(contents_container_, kIndexContentsContainer);
 
-  items_grid_view_ = new AppsGridView(contents_view_, this);
+  items_grid_view_ = contents_container_->AddChildView(
+      std::make_unique<AppsGridView>(contents_view_, this));
   items_grid_view_->SetModel(model);
-  contents_container_->AddChildView(items_grid_view_);
   view_model_->Add(items_grid_view_, kIndexChildItems);
 
-  contents_container_->AddChildView(folder_header_view_);
+  folder_header_view_ = contents_container_->AddChildView(
+      std::make_unique<FolderHeaderView>(this));
   view_model_->Add(folder_header_view_, kIndexFolderHeader);
 
-  page_switcher_ = new PageSwitcher(items_grid_view_->pagination_model(),
-                                    false /* vertical */);
-  contents_container_->AddChildView(page_switcher_);
+  page_switcher_ =
+      contents_container_->AddChildView(std::make_unique<PageSwitcher>(
+          items_grid_view_->pagination_model(), false /* vertical */));
   view_model_->Add(page_switcher_, kIndexPageSwitcher);
 
   model_->AddObserver(this);
@@ -657,7 +652,7 @@
       views::Painter::CreateSolidRoundRectPainter(SK_ColorBLACK, corner_radius,
                                                   insets));
   background_mask_->layer()->SetFillsBoundsOpaquely(false);
-  background_mask_->layer()->SetBounds(background_view_->GetContentsBounds());
+  background_mask_->layer()->SetBounds(background_view_->GetLocalBounds());
   background_view_->layer()->SetMaskLayer(background_mask_->layer());
 }
 
diff --git a/ash/app_list/views/app_list_folder_view.h b/ash/app_list/views/app_list_folder_view.h
index 295fa7c..c212504 100644
--- a/ash/app_list/views/app_list_folder_view.h
+++ b/ash/app_list/views/app_list_folder_view.h
@@ -175,8 +175,8 @@
 
   std::unique_ptr<views::ViewModel> view_model_;
 
-  AppListModel* model_;             // Not owned.
-  AppListFolderItem* folder_item_;  // Not owned.
+  AppListModel* model_;                       // Not owned.
+  AppListFolderItem* folder_item_ = nullptr;  // Not owned.
 
   // The bounds of the activated folder item icon relative to this view.
   gfx::Rect folder_item_icon_bounds_;
@@ -184,7 +184,7 @@
   // The preferred bounds of this view relative to AppsContainerView.
   gfx::Rect preferred_bounds_;
 
-  bool hide_for_reparent_;
+  bool hide_for_reparent_ = false;
 
   std::unique_ptr<gfx::SlideAnimation> background_animation_;
   std::unique_ptr<gfx::SlideAnimation> folder_item_title_animation_;
@@ -195,7 +195,7 @@
   std::unique_ptr<ui::LayerOwner> background_mask_ = nullptr;
 
   // The compositor frame number when animation starts.
-  int animation_start_frame_number_;
+  int animation_start_frame_number_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(AppListFolderView);
 };
diff --git a/ash/app_list/views/suggestion_chip_view.cc b/ash/app_list/views/suggestion_chip_view.cc
index fbb4fa1..9da0ea25a 100644
--- a/ash/app_list/views/suggestion_chip_view.cc
+++ b/ash/app_list/views/suggestion_chip_view.cc
@@ -167,7 +167,7 @@
 
 void SuggestionChipView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
   if (chip_mask_)
-    chip_mask_->layer()->SetBounds(GetContentsBounds());
+    chip_mask_->layer()->SetBounds(GetLocalBounds());
 }
 
 bool SuggestionChipView::OnKeyPressed(const ui::KeyEvent& event) {
diff --git a/ash/app_list/views/top_icon_animation_view.cc b/ash/app_list/views/top_icon_animation_view.cc
index f0a4a90f..ea045f2 100644
--- a/ash/app_list/views/top_icon_animation_view.cc
+++ b/ash/app_list/views/top_icon_animation_view.cc
@@ -19,8 +19,8 @@
                                            const gfx::Rect& scaled_rect,
                                            bool open_folder,
                                            bool item_in_folder_icon)
-    : icon_(new views::ImageView),
-      title_(new views::Label),
+    : icon_(nullptr),
+      title_(nullptr),
       scaled_rect_(scaled_rect),
       open_folder_(open_folder),
       item_in_folder_icon_(item_in_folder_icon) {
@@ -28,24 +28,27 @@
   DCHECK(!icon.isNull());
   gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage(
       icon, skia::ImageOperations::RESIZE_BEST, icon_size_));
-  icon_->SetImage(resized);
-  AddChildView(icon_);
+  auto icon_image = std::make_unique<views::ImageView>();
+  icon_image->SetImage(resized);
+  icon_ = AddChildView(std::move(icon_image));
 
-  title_->SetBackgroundColor(SK_ColorTRANSPARENT);
-  title_->SetAutoColorReadabilityEnabled(false);
-  title_->SetHandlesTooltips(false);
-  title_->SetFontList(AppListConfig::instance().app_title_font());
-  title_->SetLineHeight(AppListConfig::instance().app_title_max_line_height());
-  title_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
-  title_->SetEnabledColor(SK_ColorBLACK);
-  title_->SetText(title);
+  auto title_label = std::make_unique<views::Label>();
+  title_label->SetBackgroundColor(SK_ColorTRANSPARENT);
+  title_label->SetAutoColorReadabilityEnabled(false);
+  title_label->SetHandlesTooltips(false);
+  title_label->SetFontList(AppListConfig::instance().app_title_font());
+  title_label->SetLineHeight(
+      AppListConfig::instance().app_title_max_line_height());
+  title_label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+  title_label->SetEnabledColor(SK_ColorBLACK);
+  title_label->SetText(title);
   if (item_in_folder_icon_) {
     // The title's opacity of the item should be changed separately if it is in
     // the folder item's icon.
-    title_->SetPaintToLayer();
-    title_->layer()->SetFillsBoundsOpaquely(false);
+    title_label->SetPaintToLayer();
+    title_label->layer()->SetFillsBoundsOpaquely(false);
   }
-  AddChildView(title_);
+  title_ = AddChildView(std::move(title_label));
 
   SetPaintToLayer();
   layer()->SetFillsBoundsOpaquely(false);
diff --git a/ash/autoclick/autoclick_controller.cc b/ash/autoclick/autoclick_controller.cc
index fa85823..c03ceee 100644
--- a/ash/autoclick/autoclick_controller.cc
+++ b/ash/autoclick/autoclick_controller.cc
@@ -186,26 +186,29 @@
   aura::Window* root_window = wm::GetRootWindowAt(anchor_location_);
   DCHECK(root_window) << "Root window not found while attempting autoclick.";
 
-  gfx::Point location_in_pixels(anchor_location_);
-  ::wm::ConvertPointFromScreen(root_window, &location_in_pixels);
-  aura::WindowTreeHost* host = root_window->GetHost();
-  host->ConvertDIPToPixels(&location_in_pixels);
+  // But if the thing that would be acted upon is an autoclick menu button, do a
+  // fake click instead of whatever other action type we would have done. This
+  // ensures that no matter the autoclick setting, users can always change to
+  // another autoclick setting. By using a fake click we avoid closing dialogs
+  // and menus, allowing autoclick users to interact with those items.
+  if (!DragInProgress() && AutoclickMenuContainsPoint(anchor_location_)) {
+    menu_bubble_controller_->ClickOnBubble(anchor_location_,
+                                           mouse_event_flags_);
+    // Reset UI.
+    CancelAutoclickAction();
+    return;
+  }
 
   // Set the in-progress event type locally so that if the event type is updated
   // in the middle of this event being executed it doesn't change execution.
   mojom::AutoclickEventType in_progress_event_type = event_type_;
-
-  // But if the thing that would be acted upon is an autoclick menu button, do a
-  // left click instead of whatever other action type we would have done. This
-  // ensures that no matter the autoclick setting, users can always change to
-  // another autoclick setting.
-  if (event_type_ != mojom::AutoclickEventType::kLeftClick &&
-      !DragInProgress() && AutoclickMenuContainsPoint(anchor_location_)) {
-    // TODO: Check if the keyboard is up too, so we know if it's blocked.
-    in_progress_event_type = mojom::AutoclickEventType::kLeftClick;
-  }
   RecordUserAction(in_progress_event_type);
 
+  gfx::Point location_in_pixels(anchor_location_);
+  ::wm::ConvertPointFromScreen(root_window, &location_in_pixels);
+  aura::WindowTreeHost* host = root_window->GetHost();
+  host->ConvertDIPToPixels(&location_in_pixels);
+
   bool drag_start =
       in_progress_event_type == mojom::AutoclickEventType::kDragAndDrop &&
       !drag_event_rewriter_->IsEnabled();
diff --git a/ash/autoclick/autoclick_drag_event_rewriter.cc b/ash/autoclick/autoclick_drag_event_rewriter.cc
index a2eaf88..0dc4a29c 100644
--- a/ash/autoclick/autoclick_drag_event_rewriter.cc
+++ b/ash/autoclick/autoclick_drag_event_rewriter.cc
@@ -32,11 +32,13 @@
     return SendEvent(continuation, &event);
 
   const ui::MouseEvent* mouse_event = event.AsMouseEvent();
+  // "Press" the left mouse button to make it seem like the user is holding it
+  // down.
+  int flags = mouse_event->flags() | ui::EF_LEFT_MOUSE_BUTTON;
   ui::MouseEvent rewritten_event(
       ui::ET_MOUSE_DRAGGED, mouse_event->location(),
-      mouse_event->root_location(), mouse_event->time_stamp(),
-      mouse_event->flags(), mouse_event->changed_button_flags(),
-      mouse_event->pointer_details());
+      mouse_event->root_location(), mouse_event->time_stamp(), flags,
+      mouse_event->changed_button_flags(), mouse_event->pointer_details());
   return SendEventFinally(continuation, &rewritten_event);
 }
 
diff --git a/ash/autoclick/autoclick_drag_event_rewriter_unittest.cc b/ash/autoclick/autoclick_drag_event_rewriter_unittest.cc
index f3032b7a..98f2ec8 100644
--- a/ash/autoclick/autoclick_drag_event_rewriter_unittest.cc
+++ b/ash/autoclick/autoclick_drag_event_rewriter_unittest.cc
@@ -170,12 +170,14 @@
   // The type should be a drag.
   ASSERT_EQ(ui::ET_MOUSE_DRAGGED, rewritten_event->type());
 
+  // Flags should include left mouse button.
+  EXPECT_EQ(flags | ui::EF_LEFT_MOUSE_BUTTON, rewritten_event->flags());
+
   // Everything else should be the same as the original.
   ui::MouseEvent* rewritten_mouse_event = rewritten_event->AsMouseEvent();
   EXPECT_EQ(location, rewritten_mouse_event->location());
   EXPECT_EQ(root_location, rewritten_mouse_event->root_location());
   EXPECT_EQ(time_stamp, rewritten_mouse_event->time_stamp());
-  EXPECT_EQ(flags, rewritten_mouse_event->flags());
   EXPECT_EQ(changed_button_flags,
             rewritten_mouse_event->changed_button_flags());
 }
diff --git a/ash/autoclick/autoclick_unittest.cc b/ash/autoclick/autoclick_unittest.cc
index ba69e25..3912d0f6 100644
--- a/ash/autoclick/autoclick_unittest.cc
+++ b/ash/autoclick/autoclick_unittest.cc
@@ -142,6 +142,13 @@
         ->menu_view_;
   }
 
+  views::View* GetMenuButton(AutoclickMenuView::ButtonId view_id) {
+    AutoclickMenuView* menu_view = GetAutoclickMenuView();
+    if (!menu_view)
+      return nullptr;
+    return menu_view->GetViewByID(static_cast<int>(view_id));
+  }
+
   void ClearMouseEvents() { mouse_event_capturer_.Reset(); }
 
   const std::vector<ui::MouseEvent>& GetMouseEvents() {
@@ -600,57 +607,100 @@
   EXPECT_EQ(gfx::Point(105, 105), events[0].location());
 }
 
-TEST_F(AutoclickTest, LeftClicksOnBubbleWhenInDifferentModes) {
+TEST_F(AutoclickTest, DoesActionOnBubbleWhenInDifferentModes) {
+  AccessibilityController* accessibility_controller =
+      Shell::Get()->accessibility_controller();
   // Enable autoclick from the accessibility controller so that the bubble is
   // constructed too.
-  Shell::Get()->accessibility_controller()->SetAutoclickEnabled(true);
+  accessibility_controller->SetAutoclickEnabled(true);
   GetAutoclickController()->set_revert_to_left_click(false);
-  GetAutoclickController()->SetAutoclickEventType(
-      mojom::AutoclickEventType::kRightClick);
-  Shell::Get()->accessibility_controller()->SetAutoclickMenuPosition(
-      mojom::AutoclickMenuPosition::kBottomRight);
   std::vector<ui::MouseEvent> events;
 
-  AutoclickMenuView* menu = GetAutoclickMenuView();
-  ASSERT_TRUE(menu);
+  // Test at different screen sizes and densities because the fake click on
+  // the button involves coordinating between dips and pixels. Try two different
+  // positions to ensure offsets are calculated correctly.
+  const struct {
+    const std::string display_spec;
+    float scale;
+    mojom::AutoclickMenuPosition position;
+  } kTestCases[] = {
+      {"800x600", 1.0f, mojom::AutoclickMenuPosition::kBottomRight},
+      {"1024x800*2.0", 2.0f, mojom::AutoclickMenuPosition::kBottomRight},
+      {"800x600", 1.0f, mojom::AutoclickMenuPosition::kTopLeft},
+      {"1024x800*2.0", 2.0f, mojom::AutoclickMenuPosition::kTopLeft},
+  };
+  for (const auto& test : kTestCases) {
+    UpdateDisplay(test.display_spec);
+    accessibility_controller->SetAutoclickMenuPosition(test.position);
+    accessibility_controller->SetAutoclickEventType(
+        mojom::AutoclickEventType::kRightClick);
 
-  // Outside of the bubble, a right-click still occurs.
-  GetEventGenerator()->MoveMouseTo(30, 30);
-  events = WaitForMouseEvents();
-  ASSERT_EQ(2u, events.size());
-  EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & events[0].flags());
-  EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & events[1].flags());
+    AutoclickMenuView* menu = GetAutoclickMenuView();
+    ASSERT_TRUE(menu);
 
-  // But over the bubble, we get a left click.
-  GetEventGenerator()->MoveMouseTo(menu->GetBoundsInScreen().origin());
-  events = WaitForMouseEvents();
-  ASSERT_EQ(2u, events.size());
-  EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & events[0].flags());
-  EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & events[1].flags());
+    // Outside of the bubble, a right-click still occurs.
+    // Move to a central position which will not have any menu but will still be
+    // on-screen.
+    GetEventGenerator()->MoveMouseTo(200 * test.scale, 200 * test.scale);
+    events = WaitForMouseEvents();
+    ASSERT_EQ(2u, events.size());
+    EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & events[0].flags());
+    EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & events[1].flags());
 
-  // Change to a pause action type.
-  GetAutoclickController()->SetAutoclickEventType(
-      mojom::AutoclickEventType::kNoAction);
+    // Over the bubble, we get no real click, although the autoclick event
+    // type does get changed properly over a button.
+    gfx::Point button_location = gfx::ScaleToRoundedPoint(
+        GetMenuButton(AutoclickMenuView::ButtonId::kDoubleClick)
+            ->GetBoundsInScreen()
+            .CenterPoint(),
+        test.scale);
+    GetEventGenerator()->MoveMouseTo(button_location);
+    events = WaitForMouseEvents();
+    EXPECT_EQ(0u, events.size());
+    // But the event type did change with a the hover on the button.
+    EXPECT_EQ(mojom::AutoclickEventType::kDoubleClick,
+              accessibility_controller->GetAutoclickEventType());
 
-  // Outside the bubble, no action occurs.
-  GetEventGenerator()->MoveMouseTo(30, 30);
-  events = WaitForMouseEvents();
-  EXPECT_EQ(0u, events.size());
+    // Change to a pause action type.
+    accessibility_controller->SetAutoclickEventType(
+        mojom::AutoclickEventType::kNoAction);
 
-  // If we move over the bubble than a click occurs.
-  GetEventGenerator()->MoveMouseTo(menu->GetBoundsInScreen().origin());
-  events = WaitForMouseEvents();
-  ASSERT_EQ(2u, events.size());
-  EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & events[0].flags());
-  EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & events[1].flags());
+    // Outside the bubble, no action occurs.
+    GetEventGenerator()->MoveMouseTo(200 * test.scale, 200 * test.scale);
+    events = WaitForMouseEvents();
+    EXPECT_EQ(0u, events.size());
 
-  // But leaving the bubble we are still paused.
-  GetEventGenerator()->MoveMouseTo(60, 60);
-  events = WaitForMouseEvents();
-  EXPECT_EQ(0u, events.size());
+    // If we move over the bubble but not over any button than no real click
+    // occurs.
+    button_location = gfx::ScaleToRoundedPoint(
+        GetAutoclickMenuView()->GetBoundsInScreen().CenterPoint(), test.scale);
+    GetEventGenerator()->MoveMouseTo(button_location);
+    events = WaitForMouseEvents();
+    EXPECT_EQ(0u, events.size());
+    // The event type did not change because we were not over any button.
+    EXPECT_EQ(mojom::AutoclickEventType::kNoAction,
+              accessibility_controller->GetAutoclickEventType());
+
+    // Leaving the bubble we are still paused.
+    GetEventGenerator()->MoveMouseTo(200 * test.scale, 200 * test.scale);
+    events = WaitForMouseEvents();
+    EXPECT_EQ(0u, events.size());
+
+    // Moving over another button takes an action.
+    button_location = gfx::ScaleToRoundedPoint(
+        GetMenuButton(AutoclickMenuView::ButtonId::kLeftClick)
+            ->GetBoundsInScreen()
+            .CenterPoint(),
+        test.scale);
+    GetEventGenerator()->MoveMouseTo(button_location);
+    events = WaitForMouseEvents();
+    EXPECT_EQ(0u, events.size());
+    EXPECT_EQ(mojom::AutoclickEventType::kLeftClick,
+              accessibility_controller->GetAutoclickEventType());
+  }
 
   // Reset state.
-  Shell::Get()->accessibility_controller()->SetAutoclickEnabled(false);
+  accessibility_controller->SetAutoclickEnabled(false);
 }
 
 TEST_F(AutoclickTest,
diff --git a/ash/components/strings/ash_components_strings_ja.xtb b/ash/components/strings/ash_components_strings_ja.xtb
index 7b3a32c4..486d5a1 100644
--- a/ash/components/strings/ash_components_strings_ja.xtb
+++ b/ash/components/strings/ash_components_strings_ja.xtb
@@ -167,7 +167,7 @@
 <translation id="7787242579016742662">ブラウザ内でファイルを開く</translation>
 <translation id="7917881398263220094">現在のページの読み込みを停止する</translation>
 <translation id="7952165122793773711">1~8 番目のタブに移動します</translation>
-<translation id="8026334261755873520">閲覧履歴データを削除する</translation>
+<translation id="8026334261755873520">閲覧履歴データの削除</translation>
 <translation id="8130528849632411619">ドキュメントの先頭に移動する</translation>
 <translation id="8147954207400281792"><ph name="CTRL" /><ph name="SEPARATOR" /><ph name="K" /> または <ph name="E" /> キーを押す</translation>
 <translation id="8232835244134740473">フォーカスを次の順に切り替えます: アカウント画像が表示されているステータス領域、ランチャー、アドレスバー、ブックマーク バー(表示されている場合)、開いているウェブページ、ダウンロード バー(表示されている場合)</translation>
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc
index 07a44f85..fc2c50dc 100644
--- a/ash/display/window_tree_host_manager.cc
+++ b/ash/display/window_tree_host_manager.cc
@@ -39,7 +39,7 @@
 #include "ui/aura/window_tracker.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/class_property.h"
-#include "ui/base/ime/input_method_factory.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/base/ui_base_switches_util.h"
diff --git a/ash/frame/caption_buttons/frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc
index 9cb28af3..108523e3 100644
--- a/ash/frame/caption_buttons/frame_size_button_unittest.cc
+++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc
@@ -7,6 +7,7 @@
 #include "ash/frame/ash_frame_caption_controller.h"
 #include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/public/cpp/vector_icons/vector_icons.h"
+#include "ash/public/cpp/window_properties.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/window_state.h"
@@ -288,6 +289,41 @@
   EXPECT_TRUE(window_state()->IsNormalStateType());
 }
 
+// Test that during the waiting to snap mode, if the window's state is changed,
+// or the window is put in overview, we should cancel the waiting to snap mode.
+TEST_F(FrameSizeButtonTest, CancelSnapTest) {
+  EXPECT_EQ(views::Button::STATE_NORMAL, size_button()->state());
+
+  // Press on the size button and drag toward to close buton to enter waiting-
+  // for-snap mode.
+  ui::test::EventGenerator* generator = GetEventGenerator();
+  generator->MoveMouseTo(CenterPointInScreen(size_button()));
+  generator->PressLeftButton();
+  generator->MoveMouseTo(CenterPointInScreen(close_button()));
+  EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
+  EXPECT_TRUE(
+      static_cast<FrameSizeButton*>(size_button())->in_snap_mode_for_testing());
+  // Maximize the window.
+  window_state()->Maximize();
+  EXPECT_EQ(views::Button::STATE_NORMAL, size_button()->state());
+  EXPECT_FALSE(
+      static_cast<FrameSizeButton*>(size_button())->in_snap_mode_for_testing());
+  generator->ReleaseLeftButton();
+
+  // Test that if window is put in overview, the waiting-to-snap is canceled.
+  generator->MoveMouseTo(CenterPointInScreen(size_button()));
+  generator->PressLeftButton();
+  generator->MoveMouseTo(CenterPointInScreen(close_button()));
+  EXPECT_EQ(views::Button::STATE_PRESSED, size_button()->state());
+  EXPECT_TRUE(
+      static_cast<FrameSizeButton*>(size_button())->in_snap_mode_for_testing());
+  window_state()->window()->SetProperty(kIsShowingInOverviewKey, true);
+  EXPECT_EQ(views::Button::STATE_NORMAL, size_button()->state());
+  EXPECT_FALSE(
+      static_cast<FrameSizeButton*>(size_button())->in_snap_mode_for_testing());
+  generator->ReleaseLeftButton();
+}
+
 // Test that upon releasing the mouse button after having pressed the size
 // button
 // - The state of all the caption buttons is reset.
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc
index de85407..cd6f9c84 100644
--- a/ash/public/cpp/ash_features.cc
+++ b/ash/public/cpp/ash_features.cc
@@ -26,6 +26,9 @@
     "LockScreenHideSensitiveNotificationsSupport",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kHideArcMediaNotifications{
+    "HideArcMediaNotifications", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kMediaSessionNotification{
     "MediaSessionNotification", base::FEATURE_DISABLED_BY_DEFAULT};
 
@@ -69,6 +72,11 @@
 const base::Feature kNotificationStackingBarRedesign{
     "NotificationStackingBarRedesign", base::FEATURE_DISABLED_BY_DEFAULT};
 
+bool IsHideArcMediaNotificationsEnabled() {
+  return base::FeatureList::IsEnabled(kMediaSessionNotification) &&
+         base::FeatureList::IsEnabled(kHideArcMediaNotifications);
+}
+
 bool IsLockScreenNotificationsEnabled() {
   return base::FeatureList::IsEnabled(kLockScreenNotifications);
 }
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h
index f473621..740cc81d 100644
--- a/ash/public/cpp/ash_features.h
+++ b/ash/public/cpp/ash_features.h
@@ -33,6 +33,12 @@
 ASH_PUBLIC_EXPORT extern const base::Feature
     kLockScreenHideSensitiveNotificationsSupport;
 
+// Enables hiding of ARC media notifications. If this is enabled, all ARC
+// notifications that are of the media type will not be shown. This
+// is because they will be replaced by native media session notifications.
+// TODO(beccahughes): Remove after launch. (https://crbug.com/897836)
+ASH_PUBLIC_EXPORT extern const base::Feature kHideArcMediaNotifications;
+
 // Enables the media session notification. If this is enabled, we will show
 // a notification that shows the currently playing media with controls.
 // TODO(beccahughes): Remove after launch. (https://crbug.com/897836)
@@ -82,6 +88,8 @@
 // Enables the notification stacking bar redesigned UI.
 ASH_PUBLIC_EXPORT extern const base::Feature kNotificationStackingBarRedesign;
 
+ASH_PUBLIC_EXPORT bool IsHideArcMediaNotificationsEnabled();
+
 ASH_PUBLIC_EXPORT bool IsKeyboardShortcutViewerAppEnabled();
 
 ASH_PUBLIC_EXPORT bool IsLockScreenNotificationsEnabled();
diff --git a/ash/public/cpp/ash_pref_names.cc b/ash/public/cpp/ash_pref_names.cc
index 10710d1..f1ff21f 100644
--- a/ash/public/cpp/ash_pref_names.cc
+++ b/ash/public/cpp/ash_pref_names.cc
@@ -284,6 +284,12 @@
 const char kPowerForceNonzeroBrightnessForUserActivity[] =
     "power.force_nonzero_brightness_for_user_activity";
 
+// Boolean controlling whether a shorter suspend delay should be used after the
+// user forces the display off by pressing the power button. Provided to allow
+// policy to control this behavior.
+const char kPowerFastSuspendWhenBacklightsForcedOff[] =
+    "power.fast_suspend_when_backlights_forced_off";
+
 // Boolean controlling whether smart dim model is enabled.
 const char kPowerSmartDimEnabled[] = "power.smart_dim_enabled";
 
diff --git a/ash/public/cpp/ash_pref_names.h b/ash/public/cpp/ash_pref_names.h
index 6a5e4f93..8903bd578 100644
--- a/ash/public/cpp/ash_pref_names.h
+++ b/ash/public/cpp/ash_pref_names.h
@@ -106,6 +106,7 @@
 ASH_PUBLIC_EXPORT extern const char kPowerWaitForInitialUserActivity[];
 ASH_PUBLIC_EXPORT extern const char
     kPowerForceNonzeroBrightnessForUserActivity[];
+ASH_PUBLIC_EXPORT extern const char kPowerFastSuspendWhenBacklightsForcedOff[];
 ASH_PUBLIC_EXPORT extern const char kPowerSmartDimEnabled[];
 
 ASH_PUBLIC_EXPORT extern const char kShelfAlignment[];
diff --git a/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc
index 01c34c7..35aa67c 100644
--- a/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc
+++ b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc
@@ -14,6 +14,7 @@
 #include "ash/public/cpp/window_properties.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
+#include "ui/aura/env.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/hit_test.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -491,6 +492,12 @@
   }
 }
 
+aura::Window* FrameCaptionButtonContainerView::GetFrameWindow() {
+  aura::Window* window = frame_->GetNativeWindow();
+  return window->env()->mode() == aura::Env::Mode::MUS ? window->GetRootWindow()
+                                                       : window;
+}
+
 bool FrameCaptionButtonContainerView::CanSnap() {
   return delegate_->CanSnap(frame_->GetNativeWindow());
 }
diff --git a/ash/public/cpp/caption_buttons/frame_caption_button_container_view.h b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.h
index 79d70e9..36005b5 100644
--- a/ash/public/cpp/caption_buttons/frame_caption_button_container_view.h
+++ b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.h
@@ -136,6 +136,7 @@
   void SetHoveredAndPressedButtons(
       const views::FrameCaptionButton* to_hover,
       const views::FrameCaptionButton* to_press) override;
+  aura::Window* GetFrameWindow() override;
   bool CanSnap() override;
   void ShowSnapPreview(mojom::SnapDirection snap) override;
   void CommitSnap(mojom::SnapDirection snap) override;
diff --git a/ash/public/cpp/caption_buttons/frame_size_button.cc b/ash/public/cpp/caption_buttons/frame_size_button.cc
index 3673bea8..e2a052d5 100644
--- a/ash/public/cpp/caption_buttons/frame_size_button.cc
+++ b/ash/public/cpp/caption_buttons/frame_size_button.cc
@@ -10,6 +10,7 @@
 #include "base/i18n/rtl.h"
 #include "base/metrics/user_metrics.h"
 #include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
 #include "ui/base/hit_test.h"
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/views/widget/widget.h"
@@ -66,6 +67,50 @@
 
 }  // namespace
 
+// The class to observe the to-be-snapped window during the waiting-for-snap
+// mode. If the window's window state is changed or the window is put in
+// overview during the waiting mode, cancel the snap.
+class FrameSizeButton::SnappingWindowObserver : public aura::WindowObserver {
+ public:
+  SnappingWindowObserver(aura::Window* window, FrameSizeButton* size_button)
+      : window_(window), size_button_(size_button) {
+    window_->AddObserver(this);
+  }
+  ~SnappingWindowObserver() override {
+    if (window_) {
+      window_->RemoveObserver(this);
+      window_ = nullptr;
+    }
+  }
+
+  // aura::WindowObserver:
+  void OnWindowPropertyChanged(aura::Window* window,
+                               const void* key,
+                               intptr_t old) override {
+    DCHECK_EQ(window_, window);
+    if ((key == kIsShowingInOverviewKey &&
+         window_->GetProperty(kIsShowingInOverviewKey)) ||
+        key == kWindowStateTypeKey) {
+      // If the window is put in overview while we're in waiting-for-snapping
+      // mode, or the window's window state has changed, cancel the snap.
+      size_button_->CancelSnap();
+    }
+  }
+
+  void OnWindowDestroying(aura::Window* window) override {
+    DCHECK_EQ(window_, window);
+    window_->RemoveObserver(this);
+    window_ = nullptr;
+    size_button_->CancelSnap();
+  }
+
+ private:
+  aura::Window* window_;
+  FrameSizeButton* size_button_;
+
+  DISALLOW_COPY_AND_ASSIGN(SnappingWindowObserver);
+};
+
 FrameSizeButton::FrameSizeButton(views::ButtonListener* listener,
                                  FrameSizeButtonDelegate* delegate)
     : views::FrameCaptionButton(listener,
@@ -164,6 +209,10 @@
 
 void FrameSizeButton::AnimateButtonsToSnapMode() {
   SetButtonsToSnapMode(FrameSizeButtonDelegate::ANIMATE_YES);
+
+  // Start observing the to-be-snapped window.
+  snapping_window_observer_ = std::make_unique<SnappingWindowObserver>(
+      delegate_->GetFrameWindow(), this);
 }
 
 void FrameSizeButton::SetButtonsToSnapMode(
@@ -232,6 +281,7 @@
 }
 
 bool FrameSizeButton::CommitSnap(const ui::LocatedEvent& event) {
+  snapping_window_observer_.reset();
   mojom::SnapDirection snap = GetSnapDirection(GetButtonToHover(event));
   delegate_->CommitSnap(snap);
   delegate_->SetHoveredAndPressedButtons(nullptr, nullptr);
@@ -249,6 +299,13 @@
   return true;
 }
 
+void FrameSizeButton::CancelSnap() {
+  snapping_window_observer_.reset();
+  delegate_->CommitSnap(mojom::SnapDirection::kNone);
+  delegate_->SetHoveredAndPressedButtons(nullptr, nullptr);
+  SetButtonsToNormalMode(FrameSizeButtonDelegate::ANIMATE_YES);
+}
+
 void FrameSizeButton::SetButtonsToNormalMode(
     FrameSizeButtonDelegate::Animate animate) {
   in_snap_mode_ = false;
diff --git a/ash/public/cpp/caption_buttons/frame_size_button.h b/ash/public/cpp/caption_buttons/frame_size_button.h
index 75a47285..58023fa 100644
--- a/ash/public/cpp/caption_buttons/frame_size_button.h
+++ b/ash/public/cpp/caption_buttons/frame_size_button.h
@@ -39,11 +39,18 @@
   void OnMouseMoved(const ui::MouseEvent& event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
 
+  // Cancel the snap opereation if we're currently in snap mode. The snap
+  // preview will be deleted and the button will be set back to its normal mode.
+  void CancelSnap();
+
   void set_delay_to_set_buttons_to_snap_mode(int delay_ms) {
     set_buttons_to_snap_mode_delay_ms_ = delay_ms;
   }
+  bool in_snap_mode_for_testing() { return in_snap_mode_; }
 
  private:
+  class SnappingWindowObserver;
+
   // Starts |set_buttons_to_snap_mode_timer_|.
   void StartSetButtonsToSnapModeTimer(const ui::LocatedEvent& event);
 
@@ -75,6 +82,9 @@
   // Not owned.
   FrameSizeButtonDelegate* delegate_;
 
+  // The window observer to observe the to-be-snapped window.
+  std::unique_ptr<SnappingWindowObserver> snapping_window_observer_;
+
   // Location of the event which started |set_buttons_to_snap_mode_timer_| in
   // view coordinates.
   gfx::Point set_buttons_to_snap_mode_timer_event_location_;
diff --git a/ash/public/cpp/caption_buttons/frame_size_button_delegate.h b/ash/public/cpp/caption_buttons/frame_size_button_delegate.h
index fcdd6114..25eb2c44 100644
--- a/ash/public/cpp/caption_buttons/frame_size_button_delegate.h
+++ b/ash/public/cpp/caption_buttons/frame_size_button_delegate.h
@@ -48,6 +48,9 @@
       const views::FrameCaptionButton* to_hover,
       const views::FrameCaptionButton* to_press) = 0;
 
+  // Returns the top level aura::Window that the buttons act on.
+  virtual aura::Window* GetFrameWindow() = 0;
+
   // Thunks to methods of the same name in FrameCaptionDelegate.
   virtual bool CanSnap() = 0;
   virtual void ShowSnapPreview(mojom::SnapDirection snap) = 0;
diff --git a/ash/public/cpp/shell_window_ids.h b/ash/public/cpp/shell_window_ids.h
index 79b6e72..f7a1977 100644
--- a/ash/public/cpp/shell_window_ids.h
+++ b/ash/public/cpp/shell_window_ids.h
@@ -128,6 +128,15 @@
   // TODO(jamescook): Consolidate this with DockedMagnifierContainer.
   kShellWindowId_AccessibilityPanelContainer,
 
+  // The container for the Autoclick bubble that overlays the work area and any
+  // menus and bubbles, but appears under the Autoclick mouse UX in
+  // kShellWindowId_OverlayContainer. Autoclick needs to work with dialogs and
+  // menus, so it must be shown above kShellWindowId_SettingBubbleContainer to
+  // allow the user to access these settings. However, the Autoclick bubble has
+  // buttons with tooltips which must be shown above the Autoclick bubble, so it
+  // must be under kShellWindowId_DragImageAndTooltipContainer.
+  kShellWindowId_AutoclickContainer,
+
   // The container for special components overlaid onscreen, such as the
   // region selector for partial screenshots.
   kShellWindowId_OverlayContainer,
@@ -185,6 +194,7 @@
     kShellWindowId_PowerMenuContainer,
     kShellWindowId_SettingBubbleContainer,
     kShellWindowId_AccessibilityPanelContainer,
+    kShellWindowId_AutoclickContainer,
     kShellWindowId_OverlayContainer,
     kShellWindowId_DockedMagnifierContainer,
     kShellWindowId_MouseCursorContainer,
diff --git a/ash/public/interfaces/accessibility_controller.mojom b/ash/public/interfaces/accessibility_controller.mojom
index 6d8273ed..222ba80 100644
--- a/ash/public/interfaces/accessibility_controller.mojom
+++ b/ash/public/interfaces/accessibility_controller.mojom
@@ -87,6 +87,9 @@
   // Retrieves a string description of the current battery status.
   GetBatteryDescription()
     => (mojo_base.mojom.String16 battery_description);
+
+  // Shows or hides the virtual keyboard.
+  SetVirtualKeyboardVisible(bool is_visible);
 };
 
 // Interface for ash to request accessibility service from its client (e.g.
diff --git a/ash/public/interfaces/shell_test_api.test-mojom b/ash/public/interfaces/shell_test_api.test-mojom
index 4dbd33d1..4b17732 100644
--- a/ash/public/interfaces/shell_test_api.test-mojom
+++ b/ash/public/interfaces/shell_test_api.test-mojom
@@ -27,9 +27,6 @@
   // Enters or exits overview mode.
   ToggleOverviewMode() => ();
 
-  // Returns true if it is in overview selecting mode.
-  IsOverviewSelecting() => (bool is_selecting);
-
   // Used to emulate display change when run in a desktop environment instead
   // of on a device.
   AddRemoveDisplay();
@@ -41,8 +38,4 @@
   // longer holding pointer events. See
   // |aura::WindowTreeHost::holding_pointer_moves_| for details.
   WaitForNoPointerHoldLock() => ();
-
-  // Runs the callback when the compositor of the primary display has presented
-  // a frame on screen.
-  WaitForNextFrame() => ();
 };
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index 2185fef..8dee4e7 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -1009,6 +1009,12 @@
   wm::SetSnapsChildrenToPhysicalPixelBoundary(menu_container);
   menu_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
 
+  aura::Window* autoclick_container = CreateContainer(
+      kShellWindowId_AutoclickContainer, "AutoclickBubbleContainer",
+      lock_screen_related_containers);
+  autoclick_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
+  wm::SetSnapsChildrenToPhysicalPixelBoundary(autoclick_container);
+
   aura::Window* drag_drop_container = CreateContainer(
       kShellWindowId_DragImageAndTooltipContainer,
       "DragImageAndTooltipContainer", lock_screen_related_containers);
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc
index 16ce6f78..3f6df540 100644
--- a/ash/shelf/login_shelf_view.cc
+++ b/ash/shelf/login_shelf_view.cc
@@ -323,7 +323,7 @@
   }
 
   // views::MenuButtonListener:
-  void OnMenuButtonClicked(MenuButton* source,
+  void OnMenuButtonClicked(Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override {
     if (!is_launch_enabled_)
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index 54f79baf..109e84ff 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -497,6 +497,24 @@
          state_.session_state == session_manager::SessionState::ACTIVE;
 }
 
+bool ShelfLayoutManager::HasVisibleWindow() const {
+  aura::Window* root = shelf_widget_->GetNativeWindow()->GetRootWindow();
+  const aura::Window::Windows windows =
+      Shell::Get()->mru_window_tracker()->BuildWindowListIgnoreModal();
+  // Process the window list and check if there are any visible windows.
+  // Ignore app list windows that may be animating to hide after dismissal.
+  for (auto* window : windows) {
+    if (window->IsVisible() && !IsAppListWindow(window) &&
+        root->Contains(window)) {
+      return true;
+    }
+  }
+  auto* pip_container = Shell::GetContainer(root, kShellWindowId_PipContainer);
+  // The PIP window is not activatable and is not in the MRU list, but count
+  // it as a visible window for shelf auto-hide purposes. See crbug.com/942991.
+  return !pip_container->children().empty();
+}
+
 void ShelfLayoutManager::OnWindowResized() {
   LayoutShelf();
 }
@@ -1168,24 +1186,6 @@
                                               shelf_widget_->GetNativeWindow());
 }
 
-bool ShelfLayoutManager::HasVisibleWindow() const {
-  aura::Window* root = shelf_widget_->GetNativeWindow()->GetRootWindow();
-  const aura::Window::Windows windows =
-      Shell::Get()->mru_window_tracker()->BuildWindowListIgnoreModal();
-  // Process the window list and check if there are any visible windows.
-  // Ignore app list windows that may be animating to hide after dismissal.
-  for (auto* window : windows) {
-    if (window->IsVisible() && !IsAppListWindow(window) &&
-        root->Contains(window)) {
-      return true;
-    }
-  }
-  auto* pip_container = Shell::GetContainer(root, kShellWindowId_PipContainer);
-  // The PIP window is not activatable and is not in the MRU list, but count
-  // it as a visible window for shelf auto-hide purposes. See crbug.com/942991.
-  return !pip_container->children().empty();
-}
-
 ShelfAutoHideState ShelfLayoutManager::CalculateAutoHideState(
     ShelfVisibilityState visibility_state) const {
   // Shelf is not available before login.
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h
index b37240bf..ab9c7422 100644
--- a/ash/shelf/shelf_layout_manager.h
+++ b/ash/shelf/shelf_layout_manager.h
@@ -114,6 +114,9 @@
   // state.
   bool ShouldBlurShelfBackground();
 
+  // Returns true if at least one window is visible.
+  bool HasVisibleWindow() const;
+
   // wm::WmSnapToPixelLayoutManager:
   void OnWindowResized() override;
   void SetChildBounds(aura::Window* child,
@@ -335,9 +338,6 @@
   // two displays.
   gfx::Rect GetAutoHideShowShelfRegionInScreen() const;
 
-  // Returns true if at least one window is visible.
-  bool HasVisibleWindow() const;
-
   // Returns the AutoHideState. This value is determined from the shelf and
   // tray.
   ShelfAutoHideState CalculateAutoHideState(
diff --git a/ash/shell/content/client/shell_main_delegate.cc b/ash/shell/content/client/shell_main_delegate.cc
index cd385e5..c48a55712 100644
--- a/ash/shell/content/client/shell_main_delegate.cc
+++ b/ash/shell/content/client/shell_main_delegate.cc
@@ -19,7 +19,7 @@
 #include "services/service_manager/public/cpp/service.h"
 #include "services/ws/ime/test_ime_driver/public/mojom/constants.mojom.h"
 #include "services/ws/ime/test_ime_driver/test_ime_application.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/resource/resource_bundle.h"
 
 namespace ash {
diff --git a/ash/shell_test_api.cc b/ash/shell_test_api.cc
index 15f2654..d1e823bd 100644
--- a/ash/shell_test_api.cc
+++ b/ash/shell_test_api.cc
@@ -167,10 +167,6 @@
   std::move(cb).Run();
 }
 
-void ShellTestApi::IsOverviewSelecting(IsOverviewSelectingCallback callback) {
-  std::move(callback).Run(shell_->overview_controller()->IsSelecting());
-}
-
 void ShellTestApi::AddRemoveDisplay() {
   shell_->display_manager()->AddRemoveDisplay();
 }
@@ -188,16 +184,4 @@
   std::move(callback).Run();
 }
 
-void ShellTestApi::WaitForNextFrame(WaitForNextFrameCallback callback) {
-  Shell::GetPrimaryRootWindowController()
-      ->GetHost()
-      ->compositor()
-      ->RequestPresentationTimeForNextFrame(base::BindOnce(
-          [](WaitForNextFrameCallback callback,
-             const gfx::PresentationFeedback& feedback) {
-            std::move(callback).Run();
-          },
-          std::move(callback)));
-}
-
 }  // namespace ash
diff --git a/ash/shell_test_api.h b/ash/shell_test_api.h
index c883c4d..93e62afa 100644
--- a/ash/shell_test_api.h
+++ b/ash/shell_test_api.h
@@ -61,12 +61,10 @@
                              SnapWindowInSplitViewCallback cb) override;
   void ToggleFullscreen(ToggleFullscreenCallback cb) override;
   void ToggleOverviewMode(ToggleOverviewModeCallback cb) override;
-  void IsOverviewSelecting(IsOverviewSelectingCallback callback) override;
   void AddRemoveDisplay() override;
   void SetMinFlingVelocity(float velocity) override;
   void WaitForNoPointerHoldLock(
       WaitForNoPointerHoldLockCallback callback) override;
-  void WaitForNextFrame(WaitForNextFrameCallback callback) override;
 
  private:
   Shell* shell_;  // not owned
diff --git a/ash/strings/ash_strings_fil.xtb b/ash/strings/ash_strings_fil.xtb
index d322829..a4a2280 100644
--- a/ash/strings/ash_strings_fil.xtb
+++ b/ash/strings/ash_strings_fil.xtb
@@ -199,6 +199,7 @@
 <translation id="397105322502079400">Kinakalkula...</translation>
 <translation id="3995138139523574647">USB-C device (port sa kanang bahagi sa likod)</translation>
 <translation id="4017989525502048489">Laser pointer</translation>
+<translation id="4042660782729322247">Ibinabahagi mo ang iyong screen</translation>
 <translation id="4065525899979931964">{NUM_APPS,plural, =1{Naka-off para sa isang app}one{Naka-off para sa # app}other{Naka-off para sa # na app}}</translation>
 <translation id="4072264167173457037">Katamtaman ang signal</translation>
 <translation id="4129129681837227511">Para makakita ng mga notification sa iyong screen ng lock, i-unlock para baguhin ang setting</translation>
@@ -375,6 +376,7 @@
 <translation id="7067196344162293536">Awtomatikong pag-rotate</translation>
 <translation id="7068360136237591149">Magbukas ng mga file</translation>
 <translation id="7076293881109082629">Nagsa-sign in</translation>
+<translation id="7088960765736518739">Paglipat ng Pag-access</translation>
 <translation id="7092922358121866860">Ipakita ang mga setting ng Night Light</translation>
 <translation id="7098389117866926363">USB-C device (kaliwang port sa likod)</translation>
 <translation id="7131634465328662194">Awtomatiko kang masa-sign out.</translation>
@@ -501,6 +503,7 @@
 <translation id="9074739597929991885">Bluetooth</translation>
 <translation id="9079731690316798640">Wi-Fi: <ph name="ADDRESS" /></translation>
 <translation id="9080206825613744995">Ginagamit ang mikropono.</translation>
+<translation id="9084606467167974638">I-toggle ang posisyon ng menu</translation>
 <translation id="9089416786594320554">Mga pamamaraan ng pag-input</translation>
 <translation id="9091626656156419976">Naalis ang display na <ph name="DISPLAY_NAME" /></translation>
 <translation id="9151726767154816831">I-restart at i-powerwash upang i-update</translation>
diff --git a/ash/strings/ash_strings_ja.xtb b/ash/strings/ash_strings_ja.xtb
index e2bd6536..509ac144 100644
--- a/ash/strings/ash_strings_ja.xtb
+++ b/ash/strings/ash_strings_ja.xtb
@@ -13,7 +13,7 @@
 <translation id="112308213915226829">シェルフを自動的に隠す</translation>
 <translation id="1153356358378277386">ペア設定されたデバイス</translation>
 <translation id="1195412055398077112">オーバースキャン</translation>
-<translation id="119944043368869598">すべてクリア</translation>
+<translation id="119944043368869598">すべて削除</translation>
 <translation id="123828989343052515">新しいデスク</translation>
 <translation id="1247372569136754018">マイク(内蔵)</translation>
 <translation id="1252999807265626933"><ph name="POWER_SOURCE" /> から充電しています</translation>
diff --git a/ash/strings/ash_strings_ml.xtb b/ash/strings/ash_strings_ml.xtb
index 74c9055..ed2faa91 100644
--- a/ash/strings/ash_strings_ml.xtb
+++ b/ash/strings/ash_strings_ml.xtb
@@ -16,7 +16,7 @@
 <translation id="119944043368869598">എല്ലാം നീക്കുക</translation>
 <translation id="123828989343052515">പുതിയ ഡെസ്‌ക്</translation>
 <translation id="1247372569136754018">മൈക്രോഫോൺ (ഇന്റേണൽ)</translation>
-<translation id="1252999807265626933"><ph name="POWER_SOURCE" /> എന്നതിൽ നിന്നും ചാർജ്ജുചെയ്യുന്നു</translation>
+<translation id="1252999807265626933"><ph name="POWER_SOURCE" /> എന്നതിൽ നിന്നും ചാർജ് ചെയ്യുന്നു</translation>
 <translation id="1255033239764210633">കാലാവസ്ഥ എങ്ങനെയുണ്ട്?</translation>
 <translation id="1267032506238418139">കുറുക്കുവഴി മാറ്റം</translation>
 <translation id="1270290102613614947">ഓൺ-സ്‌ക്രീൻ കീബോർഡ് പ്രവർത്തനരഹിതമാക്കി</translation>
@@ -316,7 +316,7 @@
 <translation id="6062360702481658777">നിങ്ങൾ <ph name="LOGOUT_TIME_LEFT" />-നുള്ളിൽ സ്വയമേവ സൈൻ ഔട്ട് ചെയ്യും.</translation>
 <translation id="6064337552080329342">ക്ഷമിക്കണം, നിങ്ങളുടെ പാസ്‌വേഡ് പരിശോധിച്ചുറപ്പിക്കാനായില്ല. വീണ്ടും ശ്രമിക്കുക.</translation>
 <translation id="607652042414456612">നിങ്ങളുടെ കമ്പ്യൂട്ടർ സമീപത്തുള്ള Bluetooth ഉപകരണങ്ങൾക്ക് കണ്ടെത്താനാകുന്നതാണ് ഒപ്പം അത് <ph name="ADDRESS" /> എന്ന വിലാസത്തിൽ "<ph name="NAME" />" എന്നതായി ദൃശ്യമാകും.</translation>
-<translation id="6106745654298855237"><ph name="POWER_SOURCE" /> ചാർജ്ജുചെയ്യുന്നു</translation>
+<translation id="6106745654298855237"><ph name="POWER_SOURCE" /> ചാർജ് ചെയ്യുന്നു</translation>
 <translation id="615957422585914272">ഓൺ-സ്‌ക്രീൻ കീബോർഡ് ദൃശ്യമാക്കുക</translation>
 <translation id="6164005077879661055">സൂപ്പർവൈസുചെയ്‌ത ഉപയോക്താവിനെ നീക്കംചെയ്‌താൽ, സൂപ്പർവൈസുചെയ്‌ത ഉപയോക്താവുമായി ബന്ധപ്പെടുത്തിയിട്ടുള്ള എല്ലാ ഫയലുകളും പ്രാദേശിക ഡാറ്റയും ശാശ്വതമായി ഇല്ലാതാക്കപ്പെടും. സൂപ്പർവൈസുചെയ്‌ത ഈ ഉപയോക്താവിനായി സന്ദർശിച്ച വെബ്‌സൈറ്റുകളും ക്രമീകരണങ്ങളും <ph name="MANAGEMENT_URL" />-ൽ മാനേജർക്ക് തുടർന്നും കാണാനായേക്കും.</translation>
 <translation id="6165508094623778733">കൂടുതലറിയുക</translation>
@@ -409,7 +409,7 @@
 <translation id="7647488630410863958">നിങ്ങളുടെ അറിയിപ്പുകൾ കാണാൻ ഉപകരണം അൺലോക്കുചെയ്യുക</translation>
 <translation id="7649070708921625228">സഹായം</translation>
 <translation id="7654687942625752712">സംഭാഷണ ഫീഡ്‌ബാക്ക് പ്രവർത്തനരഹിതമാക്കാൻ രണ്ട് വോളിയം കീകളും രണ്ട് സെക്കൻഡ് നേരത്തേക്ക് അമർത്തിപ്പിടിക്കുക.</translation>
-<translation id="7692480393933218409">കണക്‌റ്റുചെയ്‌ത USB-C ഉപകരണങ്ങൾ ചാർജ്ജുചെയ്യുന്നു</translation>
+<translation id="7692480393933218409">കണക്‌റ്റുചെയ്‌ത USB-C ഉപകരണങ്ങൾ ചാർജ് ചെയ്യുന്നു</translation>
 <translation id="7705524343798198388">VPN</translation>
 <translation id="7723389094756330927">{NUM_NOTIFICATIONS,plural, =1{ഒരു അറിയിപ്പ്}other{# അറിയിപ്പുകൾ}}</translation>
 <translation id="776344839111254542">അപ്‌ഡേറ്റുചെയ്‌ത വിശദാംശങ്ങൾ കാണാൻ ‌ക്ലിക്കുചെയ്യുക</translation>
diff --git a/ash/strings/ash_strings_ta.xtb b/ash/strings/ash_strings_ta.xtb
index 9c12aa68..fd55a0e 100644
--- a/ash/strings/ash_strings_ta.xtb
+++ b/ash/strings/ash_strings_ta.xtb
@@ -131,7 +131,7 @@
 <translation id="2961963223658824723">ஏதோ தவறாகிவிட்டது. சில வினாடிகள் கழித்து மீண்டும் முயலவும்.</translation>
 <translation id="2963773877003373896">mod3</translation>
 <translation id="2970920913501714344">ஆப்ஸ், நீட்டிப்புகள் மற்றும் தீம்களை நிறுவுதல்</translation>
-<translation id="2977598380246111477">அடுத்த எண்ணை உள்ளிடவும்</translation>
+<translation id="2977598380246111477">அடுத்த எண்</translation>
 <translation id="2995447421581609334">அனுப்பும் சாதனங்களைக் காண்பிக்கும்.</translation>
 <translation id="2996462380875591307">டாக் செய்யப்பட்ட பெரிதாக்கி இயக்கப்பட்டது. அதை முடக்க, Ctrl+Search+Dயை மீண்டும் அழுத்தவும்.</translation>
 <translation id="3000461861112256445">மோனோ ஆடியோ</translation>
diff --git a/ash/strings/ash_strings_zh-CN.xtb b/ash/strings/ash_strings_zh-CN.xtb
index 2d43d14..30c3383 100644
--- a/ash/strings/ash_strings_zh-CN.xtb
+++ b/ash/strings/ash_strings_zh-CN.xtb
@@ -393,7 +393,7 @@
 <translation id="7377169924702866686">大写锁定已打开。</translation>
 <translation id="7384299914270925461"><ph name="SIGN" /><ph name="MINUTES_REMAINING" /> 分 <ph name="SECONDS_REMAINING" /> 秒</translation>
 <translation id="7398254312354928459">已切换网络连接</translation>
-<translation id="7405710164030118432">要解锁此设备,请输入您的 Family Link 家长访问代码</translation>
+<translation id="7405710164030118432">要解锁此设备,请输入您的 Family Link 家长访问码</translation>
 <translation id="742594950370306541">摄像头处于使用状态。</translation>
 <translation id="743058460480092004">摄像头和麦克风处于使用状态。</translation>
 <translation id="7497767806359279797">选择语言和键盘布局</translation>
diff --git a/ash/system/accessibility/autoclick_menu_bubble_controller.cc b/ash/system/accessibility/autoclick_menu_bubble_controller.cc
index 141ed878..6c4afa3a 100644
--- a/ash/system/accessibility/autoclick_menu_bubble_controller.cc
+++ b/ash/system/accessibility/autoclick_menu_bubble_controller.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ash/system/accessibility/autoclick_menu_bubble_controller.h"
+
 #include "ash/public/cpp/app_list/app_list_features.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/shelf/shelf.h"
@@ -10,6 +11,8 @@
 #include "ash/system/tray/tray_background_view.h"
 #include "ash/system/tray/tray_constants.h"
 #include "ash/system/unified/unified_system_tray_view.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/event_utils.h"
 
 namespace ash {
 
@@ -77,10 +80,8 @@
   TrayBubbleView::InitParams init_params;
   init_params.delegate = this;
   // Anchor within the overlay container.
-  // TODO(katie): Use kShellWindowId_AccessibilityPanelContainer. But there's
-  // a crash if I use this now, need to investigate first.
   init_params.parent_window = Shell::GetContainer(
-      Shell::GetPrimaryRootWindow(), kShellWindowId_OverlayContainer);
+      Shell::GetPrimaryRootWindow(), kShellWindowId_AutoclickContainer);
   init_params.anchor_mode = TrayBubbleView::AnchorMode::kRect;
   init_params.insets =
       gfx::Insets(kUnifiedMenuPadding, kUnifiedMenuPadding,
@@ -117,6 +118,29 @@
   bubble_widget_->Close();
 }
 
+void AutoclickMenuBubbleController::ClickOnBubble(gfx::Point location_in_dips,
+                                                  int mouse_event_flags) {
+  if (!bubble_widget_)
+    return;
+
+  // Change the event location bounds to be relative to the menu bubble.
+  location_in_dips -= bubble_view_->GetBoundsInScreen().OffsetFromOrigin();
+
+  // Generate synthesized mouse events for the click.
+  const ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, location_in_dips,
+                                   location_in_dips, ui::EventTimeForNow(),
+                                   mouse_event_flags | ui::EF_LEFT_MOUSE_BUTTON,
+                                   ui::EF_LEFT_MOUSE_BUTTON);
+  const ui::MouseEvent release_event(
+      ui::ET_MOUSE_RELEASED, location_in_dips, location_in_dips,
+      ui::EventTimeForNow(), mouse_event_flags | ui::EF_LEFT_MOUSE_BUTTON,
+      ui::EF_LEFT_MOUSE_BUTTON);
+
+  // Send the press/release events to the widget's root view for processing.
+  bubble_widget_->GetRootView()->OnMousePressed(press_event);
+  bubble_widget_->GetRootView()->OnMouseReleased(release_event);
+}
+
 bool AutoclickMenuBubbleController::ContainsPointInScreen(
     const gfx::Point& point) {
   return bubble_view_ && bubble_view_->GetBoundsInScreen().Contains(point);
diff --git a/ash/system/accessibility/autoclick_menu_bubble_controller.h b/ash/system/accessibility/autoclick_menu_bubble_controller.h
index 984b9eef..f0a047d 100644
--- a/ash/system/accessibility/autoclick_menu_bubble_controller.h
+++ b/ash/system/accessibility/autoclick_menu_bubble_controller.h
@@ -27,6 +27,9 @@
 
   void CloseBubble();
 
+  // Performs the mouse events on the bubble. at the given location in DIPs.
+  void ClickOnBubble(gfx::Point location_in_dips, int mouse_event_flags);
+
   // Whether the tray button or the bubble, if the bubble exists, contain
   // the given screen point.
   bool ContainsPointInScreen(const gfx::Point& point);
diff --git a/ash/system/message_center/arc/arc_notification_manager.cc b/ash/system/message_center/arc/arc_notification_manager.cc
index 61c41a62..72c15f5 100644
--- a/ash/system/message_center/arc/arc_notification_manager.cc
+++ b/ash/system/message_center/arc/arc_notification_manager.cc
@@ -479,6 +479,13 @@
     return true;
   }
 
+  // Media Notifications may be ignored if we have the native views based media
+  // session notifications enabled.
+  if (data->is_media_notification &&
+      features::IsHideArcMediaNotificationsEnabled()) {
+    return true;
+  }
+
   return false;
 }
 
diff --git a/ash/system/network/auto_connect_notifier_unittest.cc b/ash/system/network/auto_connect_notifier_unittest.cc
index 8bab55f..10e2b59 100644
--- a/ash/system/network/auto_connect_notifier_unittest.cc
+++ b/ash/system/network/auto_connect_notifier_unittest.cc
@@ -14,7 +14,7 @@
 #include "base/run_loop.h"
 #include "base/timer/mock_timer.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/auto_connect_handler.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_handler.h"
diff --git a/ash/system/power/power_button_controller.cc b/ash/system/power/power_button_controller.cc
index 1e083b5..1a5b08f 100644
--- a/ash/system/power/power_button_controller.cc
+++ b/ash/system/power/power_button_controller.cc
@@ -195,18 +195,19 @@
 
   if (!down)
     return;
+
+  // Ignore the power button down event if the menu is partially opened.
+  if (IsMenuOpened() && !show_menu_animation_done_)
+    return;
+
   // If power button releases won't get reported correctly because we're not
-  // running on official hardware, just lock the screen or shut down
-  // immediately.
-  const SessionController* const session_controller =
-      Shell::Get()->session_controller();
-  if (session_controller->CanLockScreen() &&
-      !session_controller->IsUserSessionBlocked() &&
-      !lock_state_controller_->LockRequested()) {
-    lock_state_controller_->StartLockAnimationAndLockImmediately();
-  } else {
+  // running on official hardware, show menu animation on the first power
+  // button press. On a further press while the menu is open, simply shut down
+  // (http://crbug.com/945005).
+  if (!show_menu_animation_done_)
+    StartPowerMenuAnimation();
+  else
     lock_state_controller_->RequestShutdown(ShutdownReason::POWER_BUTTON);
-  }
 }
 
 void PowerButtonController::OnPowerButtonEvent(
@@ -522,8 +523,10 @@
 
 void PowerButtonController::SetShowMenuAnimationDone() {
   show_menu_animation_done_ = true;
-  pre_shutdown_timer_.Start(FROM_HERE, kStartShutdownAnimationTimeout, this,
-                            &PowerButtonController::OnPreShutdownTimeout);
+  if (button_type_ != ButtonType::LEGACY) {
+    pre_shutdown_timer_.Start(FROM_HERE, kStartShutdownAnimationTimeout, this,
+                              &PowerButtonController::OnPreShutdownTimeout);
+  }
 }
 
 void PowerButtonController::ParsePowerButtonPositionSwitch() {
diff --git a/ash/system/power/power_button_controller_unittest.cc b/ash/system/power/power_button_controller_unittest.cc
index aee4209bc..044d208 100644
--- a/ash/system/power/power_button_controller_unittest.cc
+++ b/ash/system/power/power_button_controller_unittest.cc
@@ -84,6 +84,9 @@
     // Run the event loop so that PowerButtonDisplayController can receive the
     // initial backlights-forced-off state.
     base::RunLoop().RunUntilIdle();
+
+    a11y_controller_ = Shell::Get()->accessibility_controller();
+    a11y_controller_->SetClient(a11y_client_.CreateInterfacePtrAndBind());
   }
 
  protected:
@@ -150,6 +153,9 @@
     power_button_controller_->OnLockButtonEvent(false, base::TimeTicks::Now());
   }
 
+  AccessibilityController* a11y_controller_ = nullptr;  // not owned
+  TestAccessibilityControllerClient a11y_client_;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(PowerButtonControllerTest);
 };
@@ -770,21 +776,19 @@
 // Tests that a11y alert is sent on tablet power button induced screen state
 // change.
 TEST_F(PowerButtonControllerTest, A11yAlert) {
-  TestAccessibilityControllerClient client;
-  AccessibilityController* controller =
-      Shell::Get()->accessibility_controller();
-  controller->SetClient(client.CreateInterfacePtrAndBind());
   EnableTabletMode(true);
   PressPowerButton();
   ReleasePowerButton();
   SendBrightnessChange(0, kUserCause);
-  controller->FlushMojoForTest();
-  EXPECT_EQ(mojom::AccessibilityAlert::SCREEN_OFF, client.last_a11y_alert());
+  a11y_controller_->FlushMojoForTest();
+  EXPECT_EQ(mojom::AccessibilityAlert::SCREEN_OFF,
+            a11y_client_.last_a11y_alert());
 
   PressPowerButton();
   SendBrightnessChange(kNonZeroBrightness, kUserCause);
-  controller->FlushMojoForTest();
-  EXPECT_EQ(mojom::AccessibilityAlert::SCREEN_ON, client.last_a11y_alert());
+  a11y_controller_->FlushMojoForTest();
+  EXPECT_EQ(mojom::AccessibilityAlert::SCREEN_ON,
+            a11y_client_.last_a11y_alert());
   ReleasePowerButton();
 }
 
@@ -1362,6 +1366,35 @@
       power_button_test_api_->GetMenuBoundsInScreen()));
 }
 
+// Tests that a power button press before the menu is fully shown will not
+// create a new menu.
+TEST_F(PowerButtonControllerTest, LegacyPowerButtonIgnoreExtraPress) {
+  Initialize(ButtonType::LEGACY, LoginStatus::USER);
+
+  // Enable animations so that we can make sure that they occur.
+  ui::ScopedAnimationDurationScaleMode regular_animations(
+      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
+  PressPowerButton();
+  // Power menu is in the partially shown state.
+  ASSERT_TRUE(power_button_test_api_->IsMenuOpened());
+  ASSERT_FALSE(power_button_test_api_->ShowMenuAnimationDone());
+  PowerButtonMenuView* menu_view_before =
+      power_button_test_api_->GetPowerButtonMenuView();
+  // Press power button again and make sure new PowerButtonMenuView is not
+  // created. This makes sure that we do not create a new menu while we are in
+  // the process of creating one for an old power button press.
+  PressPowerButton();
+  EXPECT_EQ(menu_view_before, power_button_test_api_->GetPowerButtonMenuView());
+  // This is needed to simulate the shutdown sound having been played,
+  // which blocks the shutdown timer.
+  a11y_controller_->FlushMojoForTest();
+  // Make sure that the second press did not trigger a shutdown.
+  EXPECT_FALSE(lock_state_test_api_->real_shutdown_timer_is_running());
+  // Make sure that power menu is still in partially shown state.
+  ASSERT_TRUE(power_button_test_api_->IsMenuOpened());
+  ASSERT_FALSE(power_button_test_api_->ShowMenuAnimationDone());
+}
+
 INSTANTIATE_TEST_SUITE_P(AshPowerButtonPosition,
                          PowerButtonControllerWithPositionTest,
                          testing::Values(PowerButtonPosition::LEFT,
diff --git a/ash/system/power/power_button_display_controller.cc b/ash/system/power/power_button_display_controller.cc
index fbdf40a..5fb9bd7 100644
--- a/ash/system/power/power_button_display_controller.cc
+++ b/ash/system/power/power_button_display_controller.cc
@@ -11,6 +11,7 @@
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/time/tick_clock.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power/power_policy_controller.h"
 #include "ui/events/devices/input_device_manager.h"
 #include "ui/events/devices/stylus_state.h"
 #include "ui/events/event.h"
@@ -67,6 +68,11 @@
     backlights_forced_off_.reset();
   }
 
+  // Let PowerPolicyController update inactivity delays:
+  // https://crbug.com/812504
+  chromeos::PowerPolicyController::Get()
+      ->HandleBacklightsForcedOffForPowerButton(forced_off);
+
   if (forced_off)
     Shell::Get()->media_controller()->SuspendMediaSessions();
 }
diff --git a/ash/system/power/power_prefs.cc b/ash/system/power/power_prefs.cc
index 28ea3c66..91bf10a 100644
--- a/ash/system/power/power_prefs.cc
+++ b/ash/system/power/power_prefs.cc
@@ -115,6 +115,8 @@
   registry->RegisterBooleanPref(
       prefs::kPowerForceNonzeroBrightnessForUserActivity, true,
       PrefRegistry::PUBLIC);
+  registry->RegisterBooleanPref(prefs::kPowerFastSuspendWhenBacklightsForcedOff,
+                                true, PrefRegistry::PUBLIC);
   registry->RegisterBooleanPref(prefs::kPowerSmartDimEnabled, true,
                                 PrefRegistry::PUBLIC);
 
@@ -391,6 +393,8 @@
       prefs->GetBoolean(prefs::kPowerWaitForInitialUserActivity);
   values.force_nonzero_brightness_for_user_activity =
       prefs->GetBoolean(prefs::kPowerForceNonzeroBrightnessForUserActivity);
+  values.fast_suspend_when_backlights_forced_off =
+      prefs->GetBoolean(prefs::kPowerFastSuspendWhenBacklightsForcedOff);
 
   if (local_state_->GetBoolean(prefs::kDevicePowerPeakShiftEnabled) &&
       local_state_->IsManagedPreference(prefs::kDevicePowerPeakShiftEnabled) &&
@@ -461,6 +465,8 @@
                           update_callback);
   profile_registrar_->Add(prefs::kAllowScreenLock, update_callback);
   profile_registrar_->Add(prefs::kPowerSmartDimEnabled, update_callback);
+  profile_registrar_->Add(prefs::kPowerFastSuspendWhenBacklightsForcedOff,
+                          update_callback);
 
   UpdatePowerPolicyFromPrefs();
 }
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc
index 1989a63..ebb8983 100644
--- a/ash/test/ash_test_base.cc
+++ b/ash/test/ash_test_base.cc
@@ -61,7 +61,7 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
 #include "ui/aura/window_tree_host.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index 116f88e..663f820 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -55,7 +55,7 @@
 #include "ui/aura/test/event_generator_delegate_aura.h"
 #include "ui/aura/test/test_windows.h"
 #include "ui/aura/window.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/platform_window_defaults.h"
 #include "ui/base/ui_base_features.h"
diff --git a/ash/wm/lock_state_controller_unittest.cc b/ash/wm/lock_state_controller_unittest.cc
index 208eaf2..06daaf8 100644
--- a/ash/wm/lock_state_controller_unittest.cc
+++ b/ash/wm/lock_state_controller_unittest.cc
@@ -288,7 +288,7 @@
   void ShutdownSoundPlayed() { a11y_controller_->FlushMojoForTest(); }
 
   TestShutdownController test_shutdown_controller_;
-  TestSessionStateAnimator* test_animator_ = nullptr;  // not owned
+  TestSessionStateAnimator* test_animator_ = nullptr;   // not owned
   AccessibilityController* a11y_controller_ = nullptr;  // not owned
   TestAccessibilityControllerClient a11y_client_;
 
@@ -296,11 +296,11 @@
   DISALLOW_COPY_AND_ASSIGN(LockStateControllerTest);
 };
 
-// Test the lock-to-shutdown flow for non-Chrome-OS hardware that doesn't
-// correctly report power button releases.  We should lock immediately the first
+// Test the show menu and shutdown flow for non-Chrome-OS hardware that doesn't
+// correctly report power button releases.  We should show menu the first
 // time the button is pressed and shut down when it's pressed from the locked
 // state.
-TEST_F(LockStateControllerTest, LegacyLockAndShutDown) {
+TEST_F(LockStateControllerTest, LegacyShowMenuAndShutDown) {
   Initialize(ButtonType::LEGACY, LoginStatus::USER);
 
   ExpectUnlockedState();
@@ -309,22 +309,7 @@
   // power button get pressed.
   PressPowerButton();
 
-  EXPECT_FALSE(lock_state_test_api_->is_lock_cancellable());
-
-  ExpectPreLockAnimationStarted();
-  test_animator_->CompleteAllAnimations(true);
-  ExpectPreLockAnimationFinished();
-
-  // Notify that we locked successfully.
-  lock_state_controller_->OnStartingLock();
-  EXPECT_EQ(0u, test_animator_->GetAnimationCount());
-
-  Shell::Get()->session_controller()->FlushMojoForTest();
-  EXPECT_TRUE(Shell::Get()->session_controller()->IsScreenLocked());
-
-  ExpectPostLockAnimationStarted();
-  test_animator_->CompleteAllAnimations(true);
-  ExpectPostLockAnimationFinished();
+  EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
 
   // We shouldn't progress towards the shutdown state, however.
   EXPECT_FALSE(lock_state_test_api_->lock_to_shutdown_timer_is_running());
@@ -348,30 +333,6 @@
   EXPECT_EQ(1, NumShutdownRequests());
 }
 
-// Test that we start shutting down immediately if the power button is pressed
-// while we're not logged in on an unofficial system.
-TEST_F(LockStateControllerTest, LegacyNotLoggedIn) {
-  Initialize(ButtonType::LEGACY, LoginStatus::NOT_LOGGED_IN);
-
-  PressPowerButton();
-  ExpectShutdownAnimationStarted();
-
-  ShutdownSoundPlayed();
-  EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
-}
-
-// Test that we start shutting down immediately if the power button is pressed
-// while we're logged in as a guest on an unofficial system.
-TEST_F(LockStateControllerTest, LegacyGuest) {
-  Initialize(ButtonType::LEGACY, LoginStatus::GUEST);
-
-  PressPowerButton();
-  ExpectShutdownAnimationStarted();
-
-  ShutdownSoundPlayed();
-  EXPECT_TRUE(lock_state_test_api_->real_shutdown_timer_is_running());
-}
-
 // Test that we ignore power button presses when the screen is turned off on an
 // unofficial system.
 TEST_F(LockStateControllerTest, LegacyIgnorePowerButtonIfScreenIsOff) {
@@ -381,14 +342,13 @@
   // to power button presses.
   SendBrightnessChange(0, kUserCause);
   PressPowerButton();
-  EXPECT_FALSE(lock_state_test_api_->is_animating_lock());
+  EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
   ReleasePowerButton();
 
-  // After increasing the brightness to 10%, we should start the timer like
-  // usual.
+  // After increasing the brightness to 10%, we should show the menu as usual.
   SendBrightnessChange(10, kUserCause);
   PressPowerButton();
-  EXPECT_TRUE(lock_state_test_api_->is_animating_lock());
+  EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
   ReleasePowerButton();
 }
 
@@ -420,7 +380,7 @@
   external_display->set_current_mode(nullptr);
   power_button_controller_->OnDisplayModeChanged(outputs);
   PressPowerButton();
-  EXPECT_FALSE(lock_state_test_api_->is_animating_lock());
+  EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
   ReleasePowerButton();
 
   // When the screen brightness is 0% but the external display is still turned
@@ -429,7 +389,7 @@
   external_display->set_current_mode(external_display->modes().back().get());
   power_button_controller_->OnDisplayModeChanged(outputs);
   PressPowerButton();
-  EXPECT_TRUE(lock_state_test_api_->is_animating_lock());
+  EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
   ReleasePowerButton();
 }
 
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index f953816..dc4f0bcf 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -1535,8 +1535,8 @@
                                           int* out_max_bottom,
                                           int* out_min_right,
                                           int* out_max_right) {
-  out_rects->resize(window_list_.size());
-  bool windows_fit = true;
+  const size_t window_count = window_list_.size();
+  out_rects->resize(window_count);
 
   // Start in the top-left corner of |bounds|.
   int left = bounds.x();
@@ -1553,21 +1553,18 @@
   // All elements are of same height and only the height is necessary to
   // determine each item's scale.
   const gfx::Size item_size(0, height);
-  size_t i = 0;
-  for (const auto& window : window_list_) {
-    if (window->animating_to_close() ||
-        (ignored_item && ignored_item == window.get())) {
-      // Increment the index anyways. PositionWindows will handle skipping this
-      // entry.
-      ++i;
+  for (size_t i = 0u; i < window_count; ++i) {
+    if (window_list_[i]->animating_to_close() ||
+        (ignored_item && ignored_item == window_list_[i].get())) {
       continue;
     }
 
-    const gfx::RectF target_bounds = window->GetTargetBoundsInScreen();
-    int width = std::max(1, gfx::ToFlooredInt(target_bounds.width() *
-                                              window->GetItemScale(item_size)) +
-                                2 * kWindowMargin);
-    switch (window->GetWindowDimensionsType()) {
+    const gfx::RectF target_bounds = window_list_[i]->GetTargetBoundsInScreen();
+    int width = std::max(
+        1, gfx::ToFlooredInt(target_bounds.width() *
+                             window_list_[i]->GetItemScale(item_size)) +
+               2 * kWindowMargin);
+    switch (window_list_[i]->GetWindowDimensionsType()) {
       case ScopedOverviewTransformWindow::GridWindowFillMode::kLetterBoxed:
         width = ScopedOverviewTransformWindow::kExtremeWindowRatioThreshold *
                 height;
@@ -1592,15 +1589,7 @@
       // row does not fit within the available width.
       if (top + height > bounds.bottom() ||
           bounds.x() + width > bounds.right()) {
-        windows_fit = false;
-        // If the |ignored_item| is the last item, update |out_max_bottom|
-        // before breaking the loop, but no need to add the height, as the last
-        // item does not contribute to the grid bounds.
-        if (window_list_.back()->animating_to_close() ||
-            (ignored_item && ignored_item == window_list_.back().get())) {
-          *out_max_bottom = top;
-        }
-        break;
+        return false;
       }
       left = bounds.x();
     }
@@ -1611,16 +1600,16 @@
     // Increment horizontal position using sanitized positive |width()|.
     left += gfx::ToRoundedInt((*out_rects)[i].width());
 
-    if (++i == out_rects->size()) {
-      // Update the narrowest and widest row width for the last row.
-      if (*out_min_right > left)
-        *out_min_right = left;
-      if (*out_max_right < left)
-        *out_max_right = left;
-    }
     *out_max_bottom = top + height;
   }
-  return windows_fit;
+
+  // Update the narrowest and widest row width for the last row.
+  if (*out_min_right > left)
+    *out_min_right = left;
+  if (*out_max_right < left)
+    *out_max_right = left;
+
+  return true;
 }
 
 void OverviewGrid::CalculateOverviewItemAnimationState(
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 3f07954..a72bc5b1 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -538,6 +538,8 @@
     "observer_list.h",
     "observer_list_threadsafe.cc",
     "observer_list_threadsafe.h",
+    "one_shot_event.cc",
+    "one_shot_event.h",
     "optional.h",
     "os_compat_android.cc",
     "os_compat_android.h",
@@ -1028,6 +1030,8 @@
     "win/event_trace_controller.h",
     "win/event_trace_provider.cc",
     "win/event_trace_provider.h",
+    "win/hstring_reference.cc",
+    "win/hstring_reference.h",
     "win/i18n.cc",
     "win/i18n.h",
     "win/iat_patch_function.cc",
@@ -2487,6 +2491,7 @@
     "no_destructor_unittest.cc",
     "observer_list_threadsafe_unittest.cc",
     "observer_list_unittest.cc",
+    "one_shot_event_unittest.cc",
     "optional_unittest.cc",
     "os_compat_android_unittest.cc",
     "parameter_pack_unittest.cc",
@@ -2660,6 +2665,7 @@
     "win/event_trace_consumer_unittest.cc",
     "win/event_trace_controller_unittest.cc",
     "win/event_trace_provider_unittest.cc",
+    "win/hstring_reference_unittest.cc",
     "win/i18n_unittest.cc",
     "win/iunknown_impl_unittest.cc",
     "win/message_window_unittest.cc",
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index d1dcf4e..1e22c6b 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -238,4 +238,22 @@
 #define PRETTY_FUNCTION __func__
 #endif
 
+#if !defined(CPU_ARM_NEON)
+#if defined(__arm__)
+#if !defined(__ARMEB__) && !defined(__ARM_EABI__) && !defined(__EABI__) && \
+    !defined(__VFP_FP__) && !defined(_WIN32_WCE) && !defined(ANDROID)
+#error Chromium does not support middle endian architecture
+#endif
+#if defined(__ARM_NEON__)
+#define CPU_ARM_NEON 1
+#endif
+#endif  // defined(__arm__)
+#endif  // !defined(CPU_ARM_NEON)
+
+#if !defined(HAVE_MIPS_MSA_INTRINSICS)
+#if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5)
+#define HAVE_MIPS_MSA_INTRINSICS 1
+#endif
+#endif
+
 #endif  // BASE_COMPILER_SPECIFIC_H_
diff --git a/base/json/string_escape.cc b/base/json/string_escape.cc
index 941c8994..3437487 100644
--- a/base/json/string_escape.cc
+++ b/base/json/string_escape.cc
@@ -128,15 +128,13 @@
 
 std::string GetQuotedJSONString(StringPiece str) {
   std::string dest;
-  bool ok = EscapeJSONStringImpl(str, true, &dest);
-  DCHECK(ok);
+  EscapeJSONStringImpl(str, true, &dest);
   return dest;
 }
 
 std::string GetQuotedJSONString(StringPiece16 str) {
   std::string dest;
-  bool ok = EscapeJSONStringImpl(str, true, &dest);
-  DCHECK(ok);
+  EscapeJSONStringImpl(str, true, &dest);
   return dest;
 }
 
diff --git a/base/json/string_escape_unittest.cc b/base/json/string_escape_unittest.cc
index cf43af1..eae302c 100644
--- a/base/json/string_escape_unittest.cc
+++ b/base/json/string_escape_unittest.cc
@@ -26,6 +26,7 @@
       {"Hello\xe2\x80\xa8world", "Hello\\u2028world"},
       {"\xe2\x80\xa9purple", "\\u2029purple"},
       {"\xF3\xBF\xBF\xBF", "\xEF\xBF\xBD"},
+      {"\uFFFF", "\xEF\xBF\xBD"},
   };
 
   for (const auto& i : cases) {
@@ -38,15 +39,13 @@
     EXPECT_TRUE(IsStringUTF8(out));
 
     out.erase();
-    bool convert_ok = EscapeJSONString(in_str, false, &out);
+    EscapeJSONString(in_str, false, &out);
     EXPECT_EQ(std::string(i.escaped), out);
     EXPECT_TRUE(IsStringUTF8(out));
 
-    if (convert_ok) {
-      std::string fooout = GetQuotedJSONString(in_str);
-      EXPECT_EQ("\"" + std::string(i.escaped) + "\"", fooout);
-      EXPECT_TRUE(IsStringUTF8(out));
-    }
+    std::string fooout = GetQuotedJSONString(in_str);
+    EXPECT_EQ("\"" + std::string(i.escaped) + "\"", fooout);
+    EXPECT_TRUE(IsStringUTF8(out));
   }
 
   std::string in = cases[0].to_escape;
@@ -78,14 +77,14 @@
     const wchar_t* to_escape;
     const char* escaped;
   } cases[] = {
-    {L"b\uffb1\u00ff", "b\xEF\xBE\xB1\xC3\xBF"},
-    {L"\b\001aZ\"\\wee", "\\b\\u0001aZ\\\"\\\\wee"},
-    {L"a\b\f\n\r\t\v\1\\.\"z",
-        "a\\b\\f\\n\\r\\t\\u000B\\u0001\\\\.\\\"z"},
-    {L"b\x0f\x7f\xf0\xff!", "b\\u000F\x7F\xC3\xB0\xC3\xBF!"},
-    {L"c<>d", "c\\u003C>d"},
-    {L"Hello\u2028world", "Hello\\u2028world"},
-    {L"\u2029purple", "\\u2029purple"},
+      {L"b\uffb1\u00ff", "b\xEF\xBE\xB1\xC3\xBF"},
+      {L"\b\001aZ\"\\wee", "\\b\\u0001aZ\\\"\\\\wee"},
+      {L"a\b\f\n\r\t\v\1\\.\"z", "a\\b\\f\\n\\r\\t\\u000B\\u0001\\\\.\\\"z"},
+      {L"b\x0f\x7f\xf0\xff!", "b\\u000F\x7F\xC3\xB0\xC3\xBF!"},
+      {L"c<>d", "c\\u003C>d"},
+      {L"Hello\u2028world", "Hello\\u2028world"},
+      {L"\u2029purple", "\\u2029purple"},
+      {L"\uFFFF", "\xEF\xBF\xBD"},
   };
 
   for (const auto& i : cases) {
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc
index 378fc44d..ae42663 100644
--- a/base/metrics/histogram.cc
+++ b/base/metrics/histogram.cc
@@ -93,7 +93,7 @@
 typedef HistogramBase::Sample Sample;
 
 // static
-const uint32_t Histogram::kBucketCount_MAX = 10002u;
+const uint32_t Histogram::kBucketCount_MAX = 1002u;
 
 class Histogram::Factory {
  public:
@@ -441,13 +441,7 @@
     DVLOG(1) << "Histogram: " << name << " has bad maximum: " << *maximum;
     *maximum = kSampleType_MAX - 1;
   }
-  if (*bucket_count >= kBucketCount_MAX) {
-    check_okay = false;
-    DVLOG(1) << "Histogram: " << name << " has bad bucket_count: "
-             << *bucket_count;
-    *bucket_count = kBucketCount_MAX - 1;
-  }
-  if (*bucket_count > 1002) {
+  if (*bucket_count > kBucketCount_MAX) {
     UmaHistogramSparse("Histogram.TooManyBuckets.1000",
                        static_cast<Sample>(HashMetricName(name)));
 
@@ -456,16 +450,16 @@
     // them here.
     // Blink.UseCounter legitimately has more than 1000 entries in its enum.
     // Arc.OOMKills: https://crbug.com/916757
-    // Autofill.FieldPredictionQuality.ByFieldType: https://crbug.com/916752
-    // Bluetooth.MacOS.Errors: https://crbug.com/916754
     // BlinkGC.CommittedSize: https://crbug.com/916761
     // PartitionAlloc.CommittedSize: https://crbug.com/916761
     if (!name.starts_with("Blink.UseCounter") &&
         !name.starts_with("Arc.OOMKills.") &&
-        !name.starts_with("Autofill.FieldPredictionQuality.ByFieldType.") &&
-        !name.starts_with("Bluetooth.MacOS.Errors.") &&
         name != "BlinkGC.CommittedSize" &&
         name != "PartitionAlloc.CommittedSize") {
+      DVLOG(1) << "Histogram: " << name
+               << " has bad bucket_count: " << *bucket_count << " (limit "
+               << kBucketCount_MAX << ")";
+
       // Assume it's a mistake and limit to 100 buckets, plus under and over.
       // If the DCHECK doesn't alert the user then hopefully the small number
       // will be obvious on the dashboard. If not, then it probably wasn't
diff --git a/extensions/common/one_shot_event.cc b/base/one_shot_event.cc
similarity index 69%
rename from extensions/common/one_shot_event.cc
rename to base/one_shot_event.cc
index 46cefec..addd0e1 100644
--- a/extensions/common/one_shot_event.cc
+++ b/base/one_shot_event.cc
@@ -2,29 +2,26 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "extensions/common/one_shot_event.h"
+#include "base/one_shot_event.h"
 
 #include <stddef.h>
 
 #include "base/callback.h"
 #include "base/lazy_instance.h"
 #include "base/location.h"
-#include "base/macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 
-using base::SingleThreadTaskRunner;
-
-namespace extensions {
+namespace base {
 
 struct OneShotEvent::TaskInfo {
   TaskInfo() {}
-  TaskInfo(const base::Location& from_here,
+  TaskInfo(const Location& from_here,
            const scoped_refptr<SingleThreadTaskRunner>& runner,
-           base::OnceClosure task,
-           const base::TimeDelta& delay)
+           OnceClosure task,
+           const TimeDelta& delay)
       : from_here(from_here),
         runner(runner),
         task(std::move(task)),
@@ -33,10 +30,10 @@
   }
   TaskInfo(TaskInfo&&) = default;
 
-  base::Location from_here;
+  Location from_here;
   scoped_refptr<SingleThreadTaskRunner> runner;
-  base::OnceClosure task;
-  base::TimeDelta delay;
+  OnceClosure task;
+  TimeDelta delay;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TaskInfo);
@@ -52,24 +49,22 @@
 }
 OneShotEvent::~OneShotEvent() {}
 
-void OneShotEvent::Post(const base::Location& from_here,
-                        base::OnceClosure task) const {
-  PostImpl(from_here, std::move(task), base::ThreadTaskRunnerHandle::Get(),
-           base::TimeDelta());
+void OneShotEvent::Post(const Location& from_here, OnceClosure task) const {
+  PostImpl(from_here, std::move(task), ThreadTaskRunnerHandle::Get(),
+           TimeDelta());
 }
 
 void OneShotEvent::Post(
-    const base::Location& from_here,
-    base::OnceClosure task,
+    const Location& from_here,
+    OnceClosure task,
     const scoped_refptr<SingleThreadTaskRunner>& runner) const {
-  PostImpl(from_here, std::move(task), runner, base::TimeDelta());
+  PostImpl(from_here, std::move(task), runner, TimeDelta());
 }
 
-void OneShotEvent::PostDelayed(const base::Location& from_here,
-                               base::OnceClosure task,
-                               const base::TimeDelta& delay) const {
-  PostImpl(from_here, std::move(task), base::ThreadTaskRunnerHandle::Get(),
-           delay);
+void OneShotEvent::PostDelayed(const Location& from_here,
+                               OnceClosure task,
+                               const TimeDelta& delay) const {
+  PostImpl(from_here, std::move(task), ThreadTaskRunnerHandle::Get(), delay);
 }
 
 void OneShotEvent::Signal() {
@@ -98,10 +93,10 @@
   DCHECK(tasks_.empty()) << "No new tasks should be added during task running!";
 }
 
-void OneShotEvent::PostImpl(const base::Location& from_here,
-                            base::OnceClosure task,
+void OneShotEvent::PostImpl(const Location& from_here,
+                            OnceClosure task,
                             const scoped_refptr<SingleThreadTaskRunner>& runner,
-                            const base::TimeDelta& delay) const {
+                            const TimeDelta& delay) const {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   if (is_signaled()) {
@@ -114,4 +109,4 @@
   }
 }
 
-}  // namespace extensions
+}  // namespace base
diff --git a/extensions/common/one_shot_event.h b/base/one_shot_event.h
similarity index 77%
rename from extensions/common/one_shot_event.h
rename to base/one_shot_event.h
index 591a75f..7649378 100644
--- a/extensions/common/one_shot_event.h
+++ b/base/one_shot_event.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 EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_
-#define EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_
+#ifndef BASE_ONE_SHOT_EVENT_H_
+#define BASE_ONE_SHOT_EVENT_H_
 
 #include <vector>
 
@@ -14,23 +14,21 @@
 #include "base/threading/thread_checker.h"
 
 namespace base {
+
 class Location;
 class SingleThreadTaskRunner;
 class TimeDelta;
-}
-
-namespace extensions {
 
 // This class represents an event that's expected to happen once.  It
 // allows clients to guarantee that code is run after the OneShotEvent
 // is signaled.  If the OneShotEvent is destroyed before it's
-// signaled, the delayed closures are destroyed without being run.
+// signaled, the Onceclosure are destroyed without being run.
 //
 // This class is similar to a WaitableEvent combined with several
 // WaitableEventWatchers, but using it is simpler.
 //
 // This class is not thread-safe, and must be used from a single thread.
-class OneShotEvent {
+class BASE_EXPORT OneShotEvent {
  public:
   OneShotEvent();
   // Use the following constructor to create an already signaled event. This is
@@ -73,23 +71,23 @@
   //
   // Const because Post() doesn't modify the logical state of this
   // object (which is just the is_signaled() bit).
-  void Post(const base::Location& from_here, base::OnceClosure task) const;
-  void Post(const base::Location& from_here,
-            base::OnceClosure task,
-            const scoped_refptr<base::SingleThreadTaskRunner>& runner) const;
-  void PostDelayed(const base::Location& from_here,
-                   base::OnceClosure task,
-                   const base::TimeDelta& delay) const;
+  void Post(const Location& from_here, OnceClosure task) const;
+  void Post(const Location& from_here,
+            OnceClosure task,
+            const scoped_refptr<SingleThreadTaskRunner>& runner) const;
+  void PostDelayed(const Location& from_here,
+                   OnceClosure task,
+                   const TimeDelta& delay) const;
 
  private:
   struct TaskInfo;
 
-  void PostImpl(const base::Location& from_here,
-                base::OnceClosure task,
-                const scoped_refptr<base::SingleThreadTaskRunner>& runner,
-                const base::TimeDelta& delay) const;
+  void PostImpl(const Location& from_here,
+                OnceClosure task,
+                const scoped_refptr<SingleThreadTaskRunner>& runner,
+                const TimeDelta& delay) const;
 
-  base::ThreadChecker thread_checker_;
+  ThreadChecker thread_checker_;
 
   bool signaled_;
 
@@ -105,6 +103,6 @@
   mutable std::vector<TaskInfo> tasks_;
 };
 
-}  // namespace extensions
+}  // namespace base
 
-#endif  // EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_
+#endif  // BASE_ONE_SHOT_EVENT_H_
diff --git a/extensions/common/one_shot_event_unittest.cc b/base/one_shot_event_unittest.cc
similarity index 96%
rename from extensions/common/one_shot_event_unittest.cc
rename to base/one_shot_event_unittest.cc
index f8e702ee..b873336 100644
--- a/extensions/common/one_shot_event_unittest.cc
+++ b/base/one_shot_event_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "extensions/common/one_shot_event.h"
+#include "base/one_shot_event.h"
 
 #include "base/bind.h"
 #include "base/message_loop/message_loop.h"
@@ -11,11 +11,11 @@
 #include "base/test/test_simple_task_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace extensions {
+namespace base {
 
-namespace {
-
-void Increment(int* i) { ++*i; }
+void Increment(int* i) {
+  ++*i;
+}
 
 // |*did_delete_instance| will be set to true upon its destruction.
 class RefCountedClass : public base::RefCounted<RefCountedClass> {
@@ -171,5 +171,4 @@
   EXPECT_TRUE(did_delete_instance);
 }
 
-}  // namespace
-}  // namespace extensions
+}  // namespace base
diff --git a/base/profiler/stack_sampler_impl.cc b/base/profiler/stack_sampler_impl.cc
index f89be3c..aa7ef25 100644
--- a/base/profiler/stack_sampler_impl.cc
+++ b/base/profiler/stack_sampler_impl.cc
@@ -57,10 +57,10 @@
 // NO HEAP ALLOCATIONS.
 //
 // static
+NO_SANITIZE("address")
 void CopyStackContentsAndRewritePointers(const uintptr_t* original_stack_bottom,
                                          const uintptr_t* original_stack_top,
-                                         uintptr_t* stack_copy_bottom)
-    NO_SANITIZE("address") {
+                                         uintptr_t* stack_copy_bottom) {
   const uintptr_t* src = original_stack_bottom;
   uintptr_t* dst = stack_copy_bottom;
   for (; src < original_stack_top; ++src, ++dst) {
diff --git a/base/type_id.h b/base/type_id.h
index 303e9b10..ac44ee1 100644
--- a/base/type_id.h
+++ b/base/type_id.h
@@ -79,7 +79,7 @@
   constexpr const char* compiler_specific_anonymous_namespace_fragment =
 #if defined(__clang__)
       "base::internal::UniqueIdFromType() [Type = (anonymous namespace)::";
-#elif defined(__clang__)
+#elif defined(COMPILER_GCC)
       "base::internal::UniqueIdFromType() [with T = {anonymous}::";
 #elif defined(COMPILER_MSVC)
       "base::internal::UniqueIdFromType<`anonymous namespace'::";
diff --git a/base/values.cc b/base/values.cc
index 9fed5b52..16d686b0 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -12,6 +12,7 @@
 #include <ostream>
 #include <utility>
 
+#include "base/bit_cast.h"
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
@@ -36,6 +37,9 @@
               "base::Value should be a standard-layout C++ class in order "
               "to avoid undefined behaviour in its implementation!");
 
+static_assert(sizeof(Value::DoubleStorage) == sizeof(double),
+              "The double and DoubleStorage types should have the same size");
+
 namespace {
 
 const char* const kTypeNames[] = {"null",   "boolean", "integer",    "double",
@@ -110,8 +114,6 @@
   InternalMoveConstructFrom(std::move(that));
 }
 
-Value::Value() noexcept : type_(Type::NONE) {}
-
 Value::Value(Type type) : type_(type) {
   // Initialize with the default value.
   switch (type_) {
@@ -125,7 +127,7 @@
       int_value_ = 0;
       return;
     case Type::DOUBLE:
-      double_value_ = 0.0;
+      double_value_ = bit_cast<DoubleStorage>(0.0);
       return;
     case Type::STRING:
       new (&string_value_) std::string();
@@ -149,21 +151,16 @@
   CHECK(false);
 }
 
-Value::Value(bool in_bool)
-    : bool_type_(Type::BOOLEAN),
-      bool_value_(in_bool) {}
+Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {}
 
-Value::Value(int in_int)
-    : int_type_(Type::INTEGER),
-      int_value_(in_int) {}
+Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {}
 
 Value::Value(double in_double)
-    : double_type_(Type::DOUBLE),
-      double_value_(in_double) {
-  if (!std::isfinite(double_value_)) {
+    : type_(Type::DOUBLE), double_value_(bit_cast<DoubleStorage>(in_double)) {
+  if (!std::isfinite(in_double)) {
     NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
                  << "values cannot be represented in JSON";
-    double_value_ = 0.0;
+    double_value_ = bit_cast<DoubleStorage>(0.0);
   }
 }
 
@@ -172,8 +169,7 @@
 Value::Value(StringPiece in_string) : Value(std::string(in_string)) {}
 
 Value::Value(std::string&& in_string) noexcept
-    : string_type_(Type::STRING),
-      string_value_(std::move(in_string)) {
+    : type_(Type::STRING), string_value_(std::move(in_string)) {
   DCHECK(IsStringUTF8(string_value_));
 }
 
@@ -182,19 +178,15 @@
 Value::Value(StringPiece16 in_string16) : Value(UTF16ToUTF8(in_string16)) {}
 
 Value::Value(const std::vector<char>& in_blob)
-    : binary_type_(Type::BINARY),
-      binary_value_(in_blob.begin(), in_blob.end()) {}
+    : type_(Type::BINARY), binary_value_(in_blob.begin(), in_blob.end()) {}
 
 Value::Value(base::span<const uint8_t> in_blob)
-    : binary_type_(Type::BINARY),
-      binary_value_(in_blob.begin(), in_blob.end()) {}
+    : type_(Type::BINARY), binary_value_(in_blob.begin(), in_blob.end()) {}
 
 Value::Value(BlobStorage&& in_blob) noexcept
-    : binary_type_(Type::BINARY),
-      binary_value_(std::move(in_blob)) {}
+    : type_(Type::BINARY), binary_value_(std::move(in_blob)) {}
 
-Value::Value(const DictStorage& in_dict)
-    : dict_type_(Type::DICTIONARY), dict_() {
+Value::Value(const DictStorage& in_dict) : type_(Type::DICTIONARY), dict_() {
   dict_.reserve(in_dict.size());
   for (const auto& it : in_dict) {
     dict_.try_emplace(dict_.end(), it.first,
@@ -203,18 +195,16 @@
 }
 
 Value::Value(DictStorage&& in_dict) noexcept
-    : dict_type_(Type::DICTIONARY),
-      dict_(std::move(in_dict)) {}
+    : type_(Type::DICTIONARY), dict_(std::move(in_dict)) {}
 
-Value::Value(const ListStorage& in_list) : list_type_(Type::LIST), list_() {
+Value::Value(const ListStorage& in_list) : type_(Type::LIST), list_() {
   list_.reserve(in_list.size());
   for (const auto& val : in_list)
     list_.emplace_back(val.Clone());
 }
 
 Value::Value(ListStorage&& in_list) noexcept
-    : list_type_(Type::LIST),
-      list_(std::move(in_list)) {}
+    : type_(Type::LIST), list_(std::move(in_list)) {}
 
 Value& Value::operator=(Value&& that) noexcept {
   InternalCleanup();
@@ -223,6 +213,10 @@
   return *this;
 }
 
+double Value::AsDoubleInternal() const {
+  return bit_cast<double>(double_value_);
+}
+
 Value Value::Clone() const {
   switch (type_) {
     case Type::NONE:
@@ -232,7 +226,7 @@
     case Type::INTEGER:
       return Value(int_value_);
     case Type::DOUBLE:
-      return Value(double_value_);
+      return Value(AsDoubleInternal());
     case Type::STRING:
       return Value(string_value_);
     case Type::BINARY:
@@ -277,7 +271,7 @@
 
 double Value::GetDouble() const {
   if (is_double())
-    return double_value_;
+    return AsDoubleInternal();
   if (is_int())
     return int_value_;
   CHECK(false);
@@ -342,9 +336,10 @@
   const Value* result = FindKey(key);
   if (result) {
     if (result->is_int())
-      return base::make_optional(static_cast<double>(result->int_value_));
-    if (result->is_double())
-      return base::make_optional(result->double_value_);
+      return static_cast<double>(result->int_value_);
+    if (result->is_double()) {
+      return result->AsDoubleInternal();
+    }
   }
   return base::nullopt;
 }
@@ -601,7 +596,7 @@
 
 bool Value::GetAsDouble(double* out_value) const {
   if (out_value && is_double()) {
-    *out_value = double_value_;
+    *out_value = AsDoubleInternal();
     return true;
   }
   if (out_value && is_int()) {
@@ -696,7 +691,7 @@
     case Value::Type::INTEGER:
       return lhs.int_value_ == rhs.int_value_;
     case Value::Type::DOUBLE:
-      return lhs.double_value_ == rhs.double_value_;
+      return lhs.AsDoubleInternal() == rhs.AsDoubleInternal();
     case Value::Type::STRING:
       return lhs.string_value_ == rhs.string_value_;
     case Value::Type::BINARY:
@@ -741,7 +736,7 @@
     case Value::Type::INTEGER:
       return lhs.int_value_ < rhs.int_value_;
     case Value::Type::DOUBLE:
-      return lhs.double_value_ < rhs.double_value_;
+      return lhs.AsDoubleInternal() < rhs.AsDoubleInternal();
     case Value::Type::STRING:
       return lhs.string_value_ < rhs.string_value_;
     case Value::Type::BINARY:
diff --git a/base/values.h b/base/values.h
index 486fe7f..14b76ace 100644
--- a/base/values.h
+++ b/base/values.h
@@ -83,8 +83,10 @@
   using BlobStorage = std::vector<uint8_t>;
   using DictStorage = flat_map<std::string, std::unique_ptr<Value>>;
   using ListStorage = std::vector<Value>;
+  // See technical note below explaining why this is used.
+  using DoubleStorage = struct { alignas(4) char v[sizeof(double)]; };
 
-  enum class Type {
+  enum class Type : unsigned char {
     NONE = 0,
     BOOLEAN,
     INTEGER,
@@ -111,7 +113,10 @@
   static std::unique_ptr<Value> ToUniquePtrValue(Value val);
 
   Value(Value&& that) noexcept;
-  Value() noexcept;  // A null value.
+  Value() noexcept {}  // A null value
+  // Fun fact: using '= default' above instead of '{}' does not work because
+  // the compiler complains that the default constructor was deleted since
+  // the inner union contains fields with non-default constructors.
 
   // Value's copy constructor and copy assignment operator are deleted. Use this
   // to obtain a deep copy explicitly.
@@ -405,82 +410,29 @@
   size_t EstimateMemoryUsage() const;
 
  protected:
-  // Technical note:
-  // The naive way to implement a tagged union leads to wasted bytes
-  // in the object on CPUs like ARM ones, which impose an 8-byte alignment
-  // for double values. I.e. if one does something like:
+  // Special case for doubles, which are aligned to 8 bytes on some
+  // 32-bit architectures. In this case, a simple declaration as a
+  // double member would make the whole union 8 byte-aligned, which
+  // would also force 4 bytes of wasted padding space before it in
+  // the Value layout.
   //
-  //    struct TaggedValue {
-  //      int type_;                    // size = 1, align = 4
-  //      union {
-  //        bool bool_value_;           // size = 1, align = 1
-  //        int int_value_;             // size = 4, align = 4
-  //        double double_value_;       // size = 8, align = 8
-  //        std::string string_value_;  // size = 12, align = 4  (32-bit)
-  //      };
-  //    };
-  //
-  // The end result is that the union will have an alignment of 8, and a size
-  // of 16, due to 4 extra padding bytes following |string_value_| to respect
-  // the alignment requirement.
-  //
-  // As a consequence, the struct TaggedValue will have a size of 24 bytes,
-  // due to the size of the union (16), the size of |type_| (4) and 4 bytes
-  // of padding between |type_| and the union to respect its alignment.
-  //
-  // This means 8 bytes of unused memory per instance on 32-bit ARM!
-  //
-  // To reclaim these, a union of structs is used instead, in order to ensure
-  // that |double_value_| below is always located at an offset that is a
-  // multiple of 8, relative to the start of the overall data structure.
-  //
-  // Each struct must declare its own |type_| field, which must have a different
-  // name, to appease the C++ compiler.
-  //
-  // Using this technique sizeof(base::Value) == 16 on 32-bit ARM instead
-  // of 24, without losing any information. Results are unchanged for x86,
-  // x86_64 and arm64 (16, 32 and 32 bytes respectively).
+  // To override this, store the value as an array of 32-bit integers, and
+  // perform the appropriate bit casts when reading / writing to it.
+  Type type_ = Type::NONE;
+
   union {
-    struct {
-      // TODO(crbug.com/646113): Make these private once DictionaryValue and
-      // ListValue are properly inlined.
-      Type type_ : 8;
-    };
-    struct {
-      Type bool_type_ : 8;
-      bool bool_value_;
-    };
-    struct {
-      Type int_type_ : 8;
-      int int_value_;
-    };
-    struct {
-      Type double_type_ : 8;
-      // Subtle: On architectures that require it, the compiler will ensure
-      // that |double_value_|'s offset is a multiple of 8 (e.g. 32-bit ARM).
-      // See technical note above to understand why it is important.
-      double double_value_;
-    };
-    struct {
-      Type string_type_ : 8;
-      std::string string_value_;
-    };
-    struct {
-      Type binary_type_ : 8;
-      BlobStorage binary_value_;
-    };
-    struct {
-      Type dict_type_ : 8;
-      DictStorage dict_;
-    };
-    struct {
-      Type list_type_ : 8;
-      ListStorage list_;
-    };
+    bool bool_value_;
+    int int_value_;
+    DoubleStorage double_value_;
+    std::string string_value_;
+    BlobStorage binary_value_;
+    DictStorage dict_;
+    ListStorage list_;
   };
 
  private:
   friend class ValuesTest_SizeOfValue_Test;
+  double AsDoubleInternal() const;
   void InternalMoveConstructFrom(Value&& that);
   void InternalCleanup();
 
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index 2dd1c76..f3536a8 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -26,45 +26,89 @@
 
 namespace base {
 
-// Test is currently incorrect on Windows x86.
-#if !defined(OS_WIN) || !defined(ARCH_CPU_X86)
+// Ensure that base::Value is as small as possible, i.e. that there is
+// no wasted space after the inner value due to alignment constraints.
+// Distinguish between the 'header' that includes |type_| and and the inner
+// value that follows it, which can be a bool, int, double, string, blob, list
+// or dict.
+//
+// This test is only enabled when NDEBUG is defined. This way the test will not
+// fail in debug builds that sometimes contain larger versions of the standard
+// containers used inside base::Value.
+#if defined(NDEBUG)
+
+static size_t AlignSizeTo(size_t size, size_t alignment) {
+  EXPECT_TRUE((alignment & (alignment - 1)) == 0)
+      << "Alignment " << alignment << " is not a power of 2!";
+  return (size + (alignment - 1u)) & ~(alignment - 1u);
+}
+
 TEST(ValuesTest, SizeOfValue) {
-  // Ensure that base::Value is as small as possible, i.e. that there is
-  // no wasted space after the inner value due to alignment constraints.
-  // Distinguish between the 'header' that includes |type_| and and the inner
-  // value that follows it, which can be a bool, int, double, string, blob, list
-  // or dict.
-#define INNER_TYPES_LIST(X)            \
-  X(bool, bool_value_)                 \
-  X(int, int_value_)                   \
-  X(double, double_value_)             \
-  X(std::string, string_value_)        \
-  X(Value::BlobStorage, binary_value_) \
-  X(Value::ListStorage, list_)         \
+#define INNER_TYPES_LIST(X)              \
+  X(bool, bool_value_)                   \
+  X(int, int_value_)                     \
+  X(Value::DoubleStorage, double_value_) \
+  X(std::string, string_value_)          \
+  X(Value::BlobStorage, binary_value_)   \
+  X(Value::ListStorage, list_)           \
   X(Value::DictStorage, dict_)
 
-#define INNER_STRUCT_LIMIT(type, value) offsetof(Value, value) + sizeof(type),
+#define INNER_FIELD_ALIGNMENT(type, value) alignof(type),
 
-  // Return the maximum size in bytes of each inner struct inside base::Value
-  size_t max_inner_struct_limit =
-      std::max({INNER_TYPES_LIST(INNER_STRUCT_LIMIT)});
+  // The maximum alignment of each inner struct value field inside base::Value
+  size_t max_inner_value_alignment =
+      std::max({INNER_TYPES_LIST(INNER_FIELD_ALIGNMENT)});
+
+  // Check that base::Value has the smallest alignment possible. This would
+  // fail if the header would contain something that has a larger alignment
+  // than necessary.
+  EXPECT_EQ(max_inner_value_alignment, alignof(Value));
+
+  // Find the offset of each inner value. Which should normally not be
+  // larger than 4. Note that we use std::max(4, ...) because bool_value_
+  // could be stored just after the |bool_type_| field, with an offset of
+  // 1, and that would be ok.
+#define INNER_VALUE_START_OFFSET(type, value) offsetof(Value, value),
+
+  size_t min_inner_value_offset =
+      std::min({INNER_TYPES_LIST(INNER_VALUE_START_OFFSET)});
+
+  // Inner fields may contain pointers, which have an alignment of 8
+  // on most 64-bit platforms.
+  size_t expected_min_offset = alignof(void*);
+
+  EXPECT_EQ(expected_min_offset, min_inner_value_offset);
 
   // Ensure that base::Value is not larger than necessary, i.e. that there is
-  // no un-necessary padding afte the structs due to alignment constraints of
+  // no un-necessary padding after the structs due to alignment constraints of
   // one of the inner fields.
-  EXPECT_EQ(max_inner_struct_limit, sizeof(Value));
-  if (max_inner_struct_limit != sizeof(Value)) {
+#define INNER_STRUCT_END_OFFSET(type, value) \
+  offsetof(Value, value) + sizeof(type),
+
+  // The maximum size in bytes of each inner struct inside base::Value,
+  size_t max_inner_struct_end_offset =
+      std::max({INNER_TYPES_LIST(INNER_STRUCT_END_OFFSET)});
+
+  // The expected value size.
+  size_t expected_value_size =
+      AlignSizeTo(max_inner_struct_end_offset, alignof(Value));
+
+  EXPECT_EQ(expected_value_size, sizeof(Value));
+  if (min_inner_value_offset != expected_min_offset ||
+      expected_value_size != sizeof(Value)) {
     // The following are useful to understand what's wrong when the EXPECT_EQ()
-    // above actually fails.
-#define PRINT_INNER_FIELD_INFO(x, y) \
-  LOG(INFO) << #y " type=" #x " size=" << sizeof(x) << " align=" << alignof(x);
+    // above actually fail.
+#define PRINT_INNER_FIELD_INFO(x, y)                           \
+  LOG(INFO) << #y " type=" #x " offset=" << offsetof(Value, y) \
+            << " size=" << sizeof(x) << " align=" << alignof(x);
 
     LOG(INFO) << "Value size=" << sizeof(Value) << " align=" << alignof(Value);
     INNER_TYPES_LIST(PRINT_INNER_FIELD_INFO)
-    LOG(INFO) << "max_inner_struct_limit=" << max_inner_struct_limit;
+    LOG(INFO) << "max_inner_struct_end_offset=" << max_inner_struct_end_offset;
   }
 }
-#endif
+
+#endif  // NDEBUG
 
 TEST(ValuesTest, TestNothrow) {
   static_assert(std::is_nothrow_move_constructible<Value>::value,
diff --git a/base/win/hstring_reference.cc b/base/win/hstring_reference.cc
new file mode 100644
index 0000000..785618f5
--- /dev/null
+++ b/base/win/hstring_reference.cc
@@ -0,0 +1,61 @@
+// Copyright 2019 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/win/hstring_reference.h"
+
+#include <windows.h>
+
+#include <winstring.h>
+
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/char_traits.h"
+
+namespace base {
+namespace {
+
+bool g_load_succeeded = false;
+
+decltype(&::WindowsCreateStringReference) GetWindowsCreateStringReference() {
+  static auto const create_string_reference_func =
+      []() -> decltype(&::WindowsCreateStringReference) {
+    const HMODULE handle = ::LoadLibrary(L"combase.dll");
+    if (handle) {
+      return reinterpret_cast<decltype(&::WindowsCreateStringReference)>(
+          ::GetProcAddress(handle, "WindowsCreateStringReference"));
+    }
+    return nullptr;
+  }();
+  return create_string_reference_func;
+}
+
+}  // namespace
+
+namespace win {
+
+// static
+bool HStringReference::ResolveCoreWinRTStringDelayload() {
+  g_load_succeeded = GetWindowsCreateStringReference() != nullptr;
+  return g_load_succeeded;
+}
+
+HStringReference::HStringReference(const wchar_t* str, size_t length) {
+  DCHECK(g_load_succeeded);
+  // String must be null terminated for WindowsCreateStringReference.
+  // nullptr str is OK so long as the length is 0.
+  DCHECK(str ? str[length] == L'\0' : length == 0);
+  // If you nullptr crash here, you've failed to call
+  // ResolveCoreWinRTStringDelayLoad and check its return value.
+  const HRESULT hr = GetWindowsCreateStringReference()(
+      str, checked_cast<UINT32>(length), &hstring_header_, &hstring_);
+  // All failure modes of WindowsCreateStringReference are handled gracefully
+  // but this class.
+  DCHECK_EQ(hr, S_OK);
+}
+
+HStringReference::HStringReference(const wchar_t* str)
+    : HStringReference(str, str ? CharTraits<wchar_t>::length(str) : 0) {}
+
+}  // namespace win
+}  // namespace base
diff --git a/base/win/hstring_reference.h b/base/win/hstring_reference.h
new file mode 100644
index 0000000..13fecb7
--- /dev/null
+++ b/base/win/hstring_reference.h
@@ -0,0 +1,73 @@
+// Copyright 2019 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_WIN_HSTRING_REFERENCE_H_
+#define BASE_WIN_HSTRING_REFERENCE_H_
+
+#include <hstring.h>
+
+#include "base/base_export.h"
+
+namespace base {
+namespace win {
+
+// HStringReference is an HSTRING representation of a null terminated
+// string backed by memory that outlives the HStringReference instance.
+//
+// If you need an HSTRING class that manages its own memory, you should
+// use ScopedHString instead.
+//
+// Note that HStringReference requires certain functions that are only
+// available on Windows 8 and later, and that these functions need to be
+// delayloaded to avoid breaking Chrome on Windows 7.
+//
+// Callers MUST check the return value of ResolveCoreWinRTStringDelayLoad()
+// *before* using HStringReference.
+//
+// One-time Initialization for HStringReference:
+//
+//   const bool success = HStringReference::ResolveCoreWinRTStringDelayload();
+//   if (success) {
+//     // HStringReference can be used.
+//   } else {
+//     // Handle error.
+//   }
+//
+// Example use:
+//
+//   HStringReference string(L"abc");
+//
+class BASE_EXPORT HStringReference {
+ public:
+  // Loads all required HSTRING functions, available from Win8 and onwards.
+  static bool ResolveCoreWinRTStringDelayload();
+
+  HStringReference(const wchar_t* str, size_t len);
+  explicit HStringReference(const wchar_t* str);
+
+  HSTRING Get() const { return hstring_; }
+
+  // HSTRING_HEADER is a structure that contains a pointer to the string
+  // passed into the constructor, along with its length.
+
+  // Since HSTRING is a pointer to HSTRING_HEADER, HStringReference
+  // cannot be copyable, moveable or assignable, as that would invalidate
+  // the HSTRING we're passing out to clients.
+
+  // In the future, we can consider implementing these methods by storing
+  // the string passed in the constructor and re-creating the HSTRING and
+  // HSTRING_HEADER datastructures. For now, we'll keep things simple and
+  // forbid these operations.
+  HStringReference(const HStringReference&) = delete;
+  HStringReference& operator=(const HStringReference&) = delete;
+
+ private:
+  HSTRING hstring_ = nullptr;
+  HSTRING_HEADER hstring_header_;
+};
+
+}  // namespace win
+}  // namespace base
+
+#endif  // BASE_WIN_HSTRING_REFERENCE_H_
\ No newline at end of file
diff --git a/base/win/hstring_reference_unittest.cc b/base/win/hstring_reference_unittest.cc
new file mode 100644
index 0000000..c8d0856
--- /dev/null
+++ b/base/win/hstring_reference_unittest.cc
@@ -0,0 +1,55 @@
+// Copyright 2019 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/win/hstring_reference.h"
+#include "base/strings/string_piece.h"
+#include "base/win/scoped_hstring.h"
+
+#include "base/win/windows_version.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace win {
+
+namespace {
+
+constexpr wchar_t kTestString[] = L"123";
+constexpr wchar_t kEmptyString[] = L"";
+
+void VerifyHSTRINGEquals(HSTRING hstring, const wchar_t* test_string) {
+  const ScopedHString scoped_hstring(hstring);
+  const WStringPiece hstring_contents = scoped_hstring.Get();
+  EXPECT_EQ(hstring_contents.compare(test_string), 0);
+}
+
+}  // namespace
+
+TEST(HStringReferenceTest, Init) {
+  // ScopedHString requires WinRT core functions, which are not available in
+  // older versions.
+  if (GetVersion() < VERSION_WIN8) {
+    EXPECT_FALSE(HStringReference::ResolveCoreWinRTStringDelayload());
+    return;
+  }
+
+  EXPECT_TRUE(HStringReference::ResolveCoreWinRTStringDelayload());
+  EXPECT_TRUE(ScopedHString::ResolveCoreWinRTStringDelayload());
+
+  const HStringReference string(kTestString);
+  EXPECT_NE(string.Get(), nullptr);
+  VerifyHSTRINGEquals(string.Get(), kTestString);
+
+  // Empty strings come back as null HSTRINGs, a valid HSTRING.
+  const HStringReference empty_string(kEmptyString);
+  EXPECT_EQ(empty_string.Get(), nullptr);
+  VerifyHSTRINGEquals(empty_string.Get(), kEmptyString);
+
+  // Passing a zero length and null string should also return a null HSTRING.
+  const HStringReference null_string(nullptr, 0);
+  EXPECT_EQ(null_string.Get(), nullptr);
+  VerifyHSTRINGEquals(null_string.Get(), kEmptyString);
+}
+
+}  // namespace win
+}  // namespace base
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index 72bcec92..c5f7cc8c 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -755,17 +755,16 @@
   return Deps([c['path'] for c in configs])
 
 
-def _ExtractSharedLibsFromRuntimeDeps(runtime_deps_files):
+def _ExtractSharedLibsFromRuntimeDeps(runtime_deps_file):
   ret = []
-  for path in runtime_deps_files:
-    with open(path) as f:
-      for line in f:
-        line = line.rstrip()
-        if not line.endswith('.so'):
-          continue
-        # Only unstripped .so files are listed in runtime deps.
-        # Convert to the stripped .so by going up one directory.
-        ret.append(os.path.normpath(line.replace('lib.unstripped/', '')))
+  with open(runtime_deps_file) as f:
+    for line in f:
+      line = line.rstrip()
+      if not line.endswith('.so'):
+        continue
+      # Only unstripped .so files are listed in runtime deps.
+      # Convert to the stripped .so by going up one directory.
+      ret.append(os.path.normpath(line.replace('lib.unstripped/', '')))
   ret.reverse()
   return ret
 
@@ -1569,20 +1568,20 @@
 
     library_paths = []
     java_libraries_list = None
-    runtime_deps_files = build_utils.ParseGnList(
-        options.shared_libraries_runtime_deps or '[]')
-    if runtime_deps_files:
-      library_paths = _ExtractSharedLibsFromRuntimeDeps(runtime_deps_files)
+    if options.shared_libraries_runtime_deps:
+      library_paths = _ExtractSharedLibsFromRuntimeDeps(
+          options.shared_libraries_runtime_deps)
       java_libraries_list = _CreateJavaLibrariesList(library_paths)
+      all_inputs.append(options.shared_libraries_runtime_deps)
 
     secondary_abi_library_paths = []
-    secondary_abi_runtime_deps_files = build_utils.ParseGnList(
-        options.secondary_abi_shared_libraries_runtime_deps or '[]')
-    if secondary_abi_runtime_deps_files:
+    if options.secondary_abi_shared_libraries_runtime_deps:
       secondary_abi_library_paths = _ExtractSharedLibsFromRuntimeDeps(
-          secondary_abi_runtime_deps_files)
-    for gn_list in options.secondary_native_libs:
-      secondary_abi_library_paths.extend(build_utils.ParseGnList(gn_list))
+          options.secondary_abi_shared_libraries_runtime_deps)
+      all_inputs.append(options.secondary_abi_shared_libraries_runtime_deps)
+
+    secondary_abi_library_paths.extend(
+        build_utils.ParseGnList(options.secondary_native_libs))
 
     native_library_placeholder_paths = build_utils.ParseGnList(
         options.native_lib_placeholders)
@@ -1590,11 +1589,8 @@
     secondary_native_library_placeholder_paths = build_utils.ParseGnList(
         options.secondary_native_lib_placeholders)
 
-    extra_shared_libraries = []
-    for gn_list in options.native_libs:
-      extra_shared_libraries.extend(build_utils.ParseGnList(gn_list))
+    extra_shared_libraries = build_utils.ParseGnList(options.native_libs)
 
-    all_inputs.extend(runtime_deps_files)
     config['native'] = {
         'libraries':
         library_paths,
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index 6774381..98b9435 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -381,14 +381,6 @@
         'JUnit4 runner is not provided or specified in test apk manifest.')
 
 
-class UnmatchedFilterException(test_exception.TestException):
-  """Raised when a user specifies a filter that doesn't match any tests."""
-
-  def __init__(self, filter_str):
-    super(UnmatchedFilterException, self).__init__(
-        'Test filter "%s" matched no tests.' % filter_str)
-
-
 def GetTestName(test, sep='#'):
   """Gets the name of the given test.
 
@@ -882,7 +874,7 @@
     if self._test_filter and not filtered_tests:
       for t in inflated_tests:
         logging.debug('  %s', GetUniqueTestName(t))
-      raise UnmatchedFilterException(self._test_filter)
+      logging.warning('Unmatched Filter: %s', self._test_filter)
     return filtered_tests
 
   # pylint: disable=no-self-use
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni
index f3642f5..4b5ffa02 100644
--- a/build/config/ios/rules.gni
+++ b/build/config/ios/rules.gni
@@ -297,7 +297,6 @@
     bundle_contents_dir = bundle_root_dir
     bundle_resources_dir = bundle_contents_dir
     bundle_executable_dir = bundle_contents_dir
-    bundle_plugins_dir = "$bundle_contents_dir/PlugIns"
 
     if (!defined(public_deps)) {
       public_deps = []
@@ -1757,7 +1756,7 @@
         "$root_out_dir/$_output_name.xctest",
       ]
       outputs = [
-        "{{bundle_plugins_dir}}/$_output_name.xctest",
+        "{{bundle_contents_dir}}/PlugIns/$_output_name.xctest",
       ]
     }
   }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 088ba4f..3c3cc14 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8917237935177865184
\ No newline at end of file
+8917163363226451504
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index ed6dca7..7f0158f 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8917240259219031744
\ No newline at end of file
+8917172487945154016
\ No newline at end of file
diff --git a/buildtools/DEPS b/buildtools/DEPS
index 9d87f0e..dc241c18 100644
--- a/buildtools/DEPS
+++ b/buildtools/DEPS
@@ -14,11 +14,11 @@
   #
 
   # GN CIPD package version.
-  'gn_version': 'git_revision:0790d3043387c762a6bacb1ae0a9ebe883188ab2',
+  'gn_version': 'git_revision:64b846c96daeb3eaf08e26d8a84d8451c6cb712b',
 
   # When changing these, also update the svn revisions in deps_revisions.gni
   'clang_format_revision': '96636aa0e9f047f17447f2d45a094d0b59ed7917',
-  'libcxx_revision':       '955113db37563c8632e31ddcff2047845553d7ff',
+  'libcxx_revision':       'fbddc46986100095d5f7ed1bc2bf795d3bb3e9e4',
   'libcxxabi_revision':    '0d529660e32d77d9111912d73f2c74fc5fa2a858',
   'libunwind_revision':    '69d9b84cca8354117b9fe9705a4430d789ee599b',
 }
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni
index 54405d0..fd541ec 100644
--- a/buildtools/deps_revisions.gni
+++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@
 declare_args() {
   # The libc++ svn revision that belongs to the git hash in DEPS. Used to cause
   # full rebuilds on libc++ rolls.
-  libcxx_svn_revision = "357024"
+  libcxx_svn_revision = "357619"
 }
diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc
index a7f9e25..8be2eef3 100644
--- a/cc/animation/animation_host.cc
+++ b/cc/animation/animation_host.cc
@@ -595,24 +595,18 @@
              : true;
 }
 
-bool AnimationHost::MaximumTargetScale(ElementId element_id,
-                                       ElementListType list_type,
-                                       float* max_scale) const {
-  *max_scale = 0.f;
+float AnimationHost::MaximumTargetScale(ElementId element_id,
+                                        ElementListType list_type) const {
   auto element_animations = GetElementAnimationsForElementId(element_id);
-  return element_animations
-             ? element_animations->MaximumTargetScale(list_type, max_scale)
-             : true;
+  return element_animations ? element_animations->MaximumTargetScale(list_type)
+                            : kNotScaled;
 }
 
-bool AnimationHost::AnimationStartScale(ElementId element_id,
-                                        ElementListType list_type,
-                                        float* start_scale) const {
-  *start_scale = 0.f;
+float AnimationHost::AnimationStartScale(ElementId element_id,
+                                         ElementListType list_type) const {
   auto element_animations = GetElementAnimationsForElementId(element_id);
-  return element_animations
-             ? element_animations->AnimationStartScale(list_type, start_scale)
-             : true;
+  return element_animations ? element_animations->AnimationStartScale(list_type)
+                            : kNotScaled;
 }
 
 bool AnimationHost::IsElementAnimating(ElementId element_id) const {
diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h
index 21db692..b5bff9a 100644
--- a/cc/animation/animation_host.h
+++ b/cc/animation/animation_host.h
@@ -148,12 +148,10 @@
                                     ElementListType list_type) const override;
   bool AnimationsPreserveAxisAlignment(ElementId element_id) const override;
 
-  bool MaximumTargetScale(ElementId element_id,
-                          ElementListType list_type,
-                          float* max_scale) const override;
-  bool AnimationStartScale(ElementId element_id,
-                           ElementListType list_type,
-                           float* start_scale) const override;
+  float MaximumTargetScale(ElementId element_id,
+                           ElementListType list_type) const override;
+  float AnimationStartScale(ElementId element_id,
+                            ElementListType list_type) const override;
 
   bool IsElementAnimating(ElementId element_id) const override;
   bool HasTickingKeyframeModelForTesting(ElementId element_id) const override;
@@ -231,6 +229,10 @@
 
   MutatorHostClient* mutator_host_client_;
 
+  // Exactly one of scroll_offset_animations_ and scroll_offset_animations_impl_
+  // will be non-null for a given AnimationHost instance (the former if
+  // thread_instance_ == ThreadInstance::MAIN, the latter if thread_instance_ ==
+  // ThreadInstance::IMPL).
   std::unique_ptr<ScrollOffsetAnimations> scroll_offset_animations_;
   std::unique_ptr<ScrollOffsetAnimationsImpl> scroll_offset_animations_impl_;
 
diff --git a/cc/animation/element_animations.cc b/cc/animation/element_animations.cc
index 66aaa8c2..797464ee 100644
--- a/cc/animation/element_animations.cc
+++ b/cc/animation/element_animations.cc
@@ -50,7 +50,11 @@
       element_id_(element_id),
       has_element_in_active_list_(false),
       has_element_in_pending_list_(false),
-      needs_push_properties_(false) {
+      needs_push_properties_(false),
+      active_maximum_scale_(kNotScaled),
+      active_starting_scale_(kNotScaled),
+      pending_maximum_scale_(kNotScaled),
+      pending_starting_scale_(kNotScaled) {
   InitAffectedElementTypes();
 }
 
@@ -225,38 +229,40 @@
   return true;
 }
 
-bool ElementAnimations::AnimationStartScale(ElementListType list_type,
-                                            float* start_scale) const {
-  *start_scale = 0.f;
+float ElementAnimations::AnimationStartScale(ElementListType list_type) const {
+  float start_scale = kNotScaled;
 
   for (auto& keyframe_effect : keyframe_effects_list_) {
-    float keyframe_effect_start_scale = 0.f;
+    if (keyframe_effect.HasOnlyTranslationTransforms(list_type))
+      continue;
+    float keyframe_effect_start_scale = kNotScaled;
     bool success = keyframe_effect.AnimationStartScale(
         list_type, &keyframe_effect_start_scale);
     if (!success)
-      return false;
+      return kNotScaled;
     // Union: a maximum.
-    *start_scale = std::max(*start_scale, keyframe_effect_start_scale);
+    start_scale = std::max(start_scale, keyframe_effect_start_scale);
   }
 
-  return true;
+  return start_scale;
 }
 
-bool ElementAnimations::MaximumTargetScale(ElementListType list_type,
-                                           float* max_scale) const {
-  *max_scale = 0.f;
+float ElementAnimations::MaximumTargetScale(ElementListType list_type) const {
+  float max_scale = kNotScaled;
 
   for (auto& keyframe_effect : keyframe_effects_list_) {
-    float keyframe_effect_max_scale = 0.f;
+    if (keyframe_effect.HasOnlyTranslationTransforms(list_type))
+      continue;
+    float keyframe_effect_max_scale = kNotScaled;
     bool success = keyframe_effect.MaximumTargetScale(
         list_type, &keyframe_effect_max_scale);
     if (!success)
-      return false;
+      return kNotScaled;
     // Union: a maximum.
-    *max_scale = std::max(*max_scale, keyframe_effect_max_scale);
+    max_scale = std::max(max_scale, keyframe_effect_max_scale);
   }
 
-  return true;
+  return max_scale;
 }
 
 bool ElementAnimations::ScrollOffsetAnimationWasInterrupted() const {
@@ -354,16 +360,45 @@
   DCHECK(active_state_.IsValid());
 
   PropertyToElementIdMap element_id_map = GetPropertyToElementIdMap();
+  ElementId transform_element_id = element_id_map[TargetProperty::TRANSFORM];
 
-  if (has_element_in_active_list() && prev_active != active_state_) {
-    PropertyAnimationState diff_active = prev_active ^ active_state_;
-    animation_host_->mutator_host_client()->ElementIsAnimatingChanged(
-        element_id_map, ElementListType::ACTIVE, diff_active, active_state_);
+  if (has_element_in_active_list()) {
+    if (prev_active != active_state_) {
+      PropertyAnimationState diff_active = prev_active ^ active_state_;
+      animation_host_->mutator_host_client()->ElementIsAnimatingChanged(
+          element_id_map, ElementListType::ACTIVE, diff_active, active_state_);
+    }
+
+    float maximum_scale = MaximumTargetScale(ElementListType::ACTIVE);
+    float starting_scale = AnimationStartScale(ElementListType::ACTIVE);
+    if (maximum_scale != active_maximum_scale_ ||
+        starting_scale != active_starting_scale_) {
+      animation_host_->mutator_host_client()->AnimationScalesChanged(
+          transform_element_id, ElementListType::ACTIVE, maximum_scale,
+          starting_scale);
+      active_maximum_scale_ = maximum_scale;
+      active_starting_scale_ = starting_scale;
+    }
   }
-  if (has_element_in_pending_list() && prev_pending != pending_state_) {
-    PropertyAnimationState diff_pending = prev_pending ^ pending_state_;
-    animation_host_->mutator_host_client()->ElementIsAnimatingChanged(
-        element_id_map, ElementListType::PENDING, diff_pending, pending_state_);
+
+  if (has_element_in_pending_list()) {
+    if (prev_pending != pending_state_) {
+      PropertyAnimationState diff_pending = prev_pending ^ pending_state_;
+      animation_host_->mutator_host_client()->ElementIsAnimatingChanged(
+          element_id_map, ElementListType::PENDING, diff_pending,
+          pending_state_);
+    }
+
+    float maximum_scale = MaximumTargetScale(ElementListType::PENDING);
+    float starting_scale = AnimationStartScale(ElementListType::PENDING);
+    if (maximum_scale != pending_maximum_scale_ ||
+        starting_scale != pending_starting_scale_) {
+      animation_host_->mutator_host_client()->AnimationScalesChanged(
+          transform_element_id, ElementListType::PENDING, maximum_scale,
+          starting_scale);
+      pending_maximum_scale_ = maximum_scale;
+      pending_starting_scale_ = starting_scale;
+    }
   }
 }
 
diff --git a/cc/animation/element_animations.h b/cc/animation/element_animations.h
index 5f0904d..911106b04 100644
--- a/cc/animation/element_animations.h
+++ b/cc/animation/element_animations.h
@@ -111,15 +111,15 @@
 
   bool AnimationsPreserveAxisAlignment() const;
 
-  // Sets |start_scale| to the maximum of starting animation scale along any
-  // dimension at any destination in active animations. Returns false if the
-  // starting scale cannot be computed.
-  bool AnimationStartScale(ElementListType list_type, float* start_scale) const;
+  // Returns the maximum of starting animation scale along any dimension at any
+  // destination in active scale animations, or kNotScaled if there is no active
+  // scale animation or the starting scale cannot be computed.
+  float AnimationStartScale(ElementListType list_type) const;
 
-  // Sets |max_scale| to the maximum scale along any dimension at any
-  // destination in active animations. Returns false if the maximum scale cannot
-  // be computed.
-  bool MaximumTargetScale(ElementListType list_type, float* max_scale) const;
+  // Returns the maximum scale along any dimension at any destination in active
+  // scale animations, or kNotScaled if there is no active scale animation or
+  // the maximum scale cannot be computed.
+  float MaximumTargetScale(ElementListType list_type) const;
 
   bool ScrollOffsetAnimationWasInterrupted() const;
 
@@ -208,6 +208,10 @@
 
   PropertyAnimationState active_state_;
   PropertyAnimationState pending_state_;
+  float active_maximum_scale_;
+  float active_starting_scale_;
+  float pending_maximum_scale_;
+  float pending_starting_scale_;
 };
 
 }  // namespace cc
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 1babd64..9f53aa0c 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -1309,7 +1309,7 @@
             transform_tree_index(), layer_tree_impl());
     float maximum_scale = animation_scales.maximum_animation_scale;
     float starting_scale = animation_scales.starting_animation_scale;
-    if (maximum_scale) {
+    if (maximum_scale != kNotScaled) {
       gfx::Size bounds_at_maximum_scale =
           gfx::ScaleToCeiledSize(raster_source_->GetSize(), maximum_scale);
       int64_t maximum_area =
@@ -1328,7 +1328,7 @@
       if (maximum_area <= squared_viewport_area)
         can_raster_at_maximum_scale = true;
     }
-    if (starting_scale && starting_scale > maximum_scale) {
+    if (starting_scale != kNotScaled && starting_scale > maximum_scale) {
       gfx::Size bounds_at_starting_scale =
           gfx::ScaleToCeiledSize(raster_source_->GetSize(), starting_scale);
       int64_t start_area =
diff --git a/cc/test/animation_timelines_test_common.cc b/cc/test/animation_timelines_test_common.cc
index 0a09931..1db44481 100644
--- a/cc/test/animation_timelines_test_common.cc
+++ b/cc/test/animation_timelines_test_common.cc
@@ -146,6 +146,11 @@
   }
 }
 
+void TestHostClient::AnimationScalesChanged(ElementId element_id,
+                                            ElementListType list_type,
+                                            float maximum_scale,
+                                            float starting_scale) {}
+
 void TestHostClient::SetScrollOffsetForAnimation(
     const gfx::ScrollOffset& scroll_offset) {
   scroll_offset_ = scroll_offset;
diff --git a/cc/test/animation_timelines_test_common.h b/cc/test/animation_timelines_test_common.h
index 8b81333..994e3eb 100644
--- a/cc/test/animation_timelines_test_common.h
+++ b/cc/test/animation_timelines_test_common.h
@@ -123,6 +123,10 @@
                                  ElementListType list_type,
                                  const PropertyAnimationState& mask,
                                  const PropertyAnimationState& state) override;
+  void AnimationScalesChanged(ElementId element_id,
+                              ElementListType list_type,
+                              float maximum_scale,
+                              float starting_scale) override;
 
   void ScrollOffsetAnimationFinished() override {}
 
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 35a22bd..687ab1b 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -1826,8 +1826,17 @@
     const PropertyAnimationState& mask,
     const PropertyAnimationState& state) {
   DCHECK_EQ(ElementListType::ACTIVE, list_type);
-  property_trees()->ElementIsAnimatingChanged(mutator_host(), element_id_map,
-                                              list_type, mask, state, true);
+  property_trees()->ElementIsAnimatingChanged(element_id_map, mask, state,
+                                              true);
+}
+
+void LayerTreeHost::AnimationScalesChanged(ElementId element_id,
+                                           ElementListType list_type,
+                                           float maximum_scale,
+                                           float starting_scale) {
+  DCHECK_EQ(ElementListType::ACTIVE, list_type);
+  property_trees()->AnimationScalesChanged(element_id, maximum_scale,
+                                           starting_scale);
 }
 
 gfx::ScrollOffset LayerTreeHost::GetScrollOffsetForAnimation(
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 64fd6b7..85c520d 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -656,6 +656,10 @@
                                  ElementListType list_type,
                                  const PropertyAnimationState& mask,
                                  const PropertyAnimationState& state) override;
+  void AnimationScalesChanged(ElementId element_id,
+                              ElementListType list_type,
+                              float maximum_scale,
+                              float starting_scale) override;
 
   void ScrollOffsetAnimationFinished() override {}
   gfx::ScrollOffset GetScrollOffsetForAnimation(
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index d9d4b21..37d6f1c 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -7333,15 +7333,15 @@
   ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // No layers have animations.
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw));
 
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw));
 
   TransformOperations translation;
   translation.AppendTranslate(1.f, 2.f, 3.f);
@@ -7380,15 +7380,15 @@
                                   TransformOperations(), translation);
 
   // No layers have scale-affecting animations.
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw));
 
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw));
 
   TransformOperations scale;
   scale.AppendScale(5.f, 4.f, 3.f);
@@ -7399,13 +7399,13 @@
   ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // Only |child| has a scale-affecting animation.
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw));
   EXPECT_EQ(5.f, GetMaximumAnimationScale(child_raw));
   EXPECT_EQ(5.f, GetMaximumAnimationScale(grand_child_raw));
 
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw));
   EXPECT_EQ(1.f, GetStartingAnimationScale(child_raw));
   EXPECT_EQ(1.f, GetStartingAnimationScale(grand_child_raw));
 
@@ -7419,13 +7419,13 @@
   EXPECT_EQ(5.f, GetMaximumAnimationScale(parent_raw));
   // We don't support combining animated scales from two nodes; 0.f means
   // that the maximum scale could not be computed.
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw));
 
   EXPECT_EQ(1.f, GetStartingAnimationScale(grand_parent_raw));
   EXPECT_EQ(1.f, GetStartingAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw));
 
   AddAnimatedTransformToAnimation(parent_animation.get(), 1.0,
                                   TransformOperations(), scale);
@@ -7434,14 +7434,14 @@
 
   // |grand_parent|, |parent|, and |child| have scale-affecting animations.
   EXPECT_EQ(5.f, GetMaximumAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw));
 
   EXPECT_EQ(1.f, GetStartingAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw));
 
   grand_parent_animation->AbortKeyframeModelsWithProperty(
       TargetProperty::TRANSFORM, false);
@@ -7460,15 +7460,15 @@
 
   // |child| has a scale-affecting animation but computing the maximum of this
   // animation is not supported.
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw));
 
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw));
 
   child_animation->AbortKeyframeModelsWithProperty(TargetProperty::TRANSFORM,
                                                    false);
@@ -7485,12 +7485,12 @@
 
   // |grand_parent| and |parent| each have scale 2.f. |parent| has a  scale
   // animation with maximum scale 5.f.
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw));
   EXPECT_EQ(10.f, GetMaximumAnimationScale(parent_raw));
   EXPECT_EQ(10.f, GetMaximumAnimationScale(child_raw));
   EXPECT_EQ(10.f, GetMaximumAnimationScale(grand_child_raw));
 
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw));
   EXPECT_EQ(2.f, GetStartingAnimationScale(parent_raw));
   EXPECT_EQ(2.f, GetStartingAnimationScale(child_raw));
   EXPECT_EQ(2.f, GetStartingAnimationScale(grand_child_raw));
@@ -7502,15 +7502,15 @@
   ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // |child| has a transform that's neither a translation nor a scale.
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw));
   EXPECT_EQ(10.f, GetMaximumAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw));
 
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw));
   EXPECT_EQ(2.f, GetStartingAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw));
 
   parent_raw->test_properties()->transform = perspective_matrix;
   grand_parent_raw->layer_tree_impl()->property_trees()->needs_rebuild = true;
@@ -7518,15 +7518,15 @@
 
   // |parent| and |child| have transforms that are neither translations nor
   // scales.
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw));
 
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw));
 
   parent_raw->test_properties()->transform = gfx::Transform();
   child_raw->test_properties()->transform = gfx::Transform();
@@ -7536,15 +7536,15 @@
   ExecuteCalculateDrawProperties(grand_parent_raw);
 
   // |grand_parent| has a transform that's neither a translation nor a scale.
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw));
 
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw));
-  EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw));
+  EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw));
 }
 
 static void GatherDrawnLayers(LayerTreeImpl* tree_impl,
@@ -7847,8 +7847,8 @@
       child1_layer->test_properties()->mask_layer->GetIdealContentsScale());
   EXPECT_FLOAT_EQ(5.f, child2_layer->GetIdealContentsScale());
 
-  EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(root_layer));
-  EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(child1_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child1_layer));
   EXPECT_FLOAT_EQ(8.f, GetMaximumAnimationScale(child2_layer));
 
   // Changing page-scale would affect ideal_contents_scale and
@@ -7877,8 +7877,8 @@
       child1_layer->test_properties()->mask_layer->GetIdealContentsScale());
   EXPECT_FLOAT_EQ(15.f, child2_layer->GetIdealContentsScale());
 
-  EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(root_layer));
-  EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(child1_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child1_layer));
   EXPECT_FLOAT_EQ(24.f, GetMaximumAnimationScale(child2_layer));
 
   // Changing device-scale would affect ideal_contents_scale and
@@ -7897,8 +7897,8 @@
       child1_layer->test_properties()->mask_layer->GetIdealContentsScale());
   EXPECT_FLOAT_EQ(60.f, child2_layer->GetIdealContentsScale());
 
-  EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(root_layer));
-  EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(child1_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child1_layer));
   EXPECT_FLOAT_EQ(96.f, GetMaximumAnimationScale(child2_layer));
 }
 
@@ -7950,12 +7950,12 @@
   root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true;
   ExecuteCalculateDrawProperties(root_layer);
 
-  EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(root_layer));
-  EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(child1_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child1_layer));
   EXPECT_FLOAT_EQ(24.f, GetMaximumAnimationScale(child2_layer));
 
-  EXPECT_FLOAT_EQ(0.f, GetStartingAnimationScale(root_layer));
-  EXPECT_FLOAT_EQ(0.f, GetStartingAnimationScale(child1_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetStartingAnimationScale(root_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetStartingAnimationScale(child1_layer));
   EXPECT_FLOAT_EQ(3.f, GetStartingAnimationScale(child2_layer));
 
   // Correctly updates animation scale when layer property changes.
@@ -8017,11 +8017,11 @@
   root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true;
   ExecuteCalculateDrawProperties(root_layer);
 
-  EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(root_layer));
-  EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(child_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child_layer));
 
-  EXPECT_FLOAT_EQ(0.f, GetStartingAnimationScale(root_layer));
-  EXPECT_FLOAT_EQ(0.f, GetStartingAnimationScale(child_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetStartingAnimationScale(root_layer));
+  EXPECT_FLOAT_EQ(kNotScaled, GetStartingAnimationScale(child_layer));
 }
 
 TEST_F(LayerTreeHostCommonTest, VisibleContentRectInChildRenderSurface) {
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index c9eed9a..927ca0a 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -5694,12 +5694,23 @@
       list_type == ElementListType::ACTIVE ? active_tree() : pending_tree();
   // TODO(wkorman): Explore enabling DCHECK in ElementIsAnimatingChanged()
   // below. Currently enabling causes batch of unit test failures.
-  if (tree &&
-      tree->property_trees()->ElementIsAnimatingChanged(
-          mutator_host(), element_id_map, list_type, mask, state, false))
+  if (tree && tree->property_trees()->ElementIsAnimatingChanged(
+                  element_id_map, mask, state, false))
     tree->set_needs_update_draw_properties();
 }
 
+void LayerTreeHostImpl::AnimationScalesChanged(ElementId element_id,
+                                               ElementListType list_type,
+                                               float maximum_scale,
+                                               float starting_scale) {
+  if (LayerTreeImpl* tree = list_type == ElementListType::ACTIVE
+                                ? active_tree()
+                                : pending_tree()) {
+    tree->property_trees()->AnimationScalesChanged(element_id, maximum_scale,
+                                                   starting_scale);
+  }
+}
+
 void LayerTreeHostImpl::ScrollOffsetAnimationFinished() {
   TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollOffsetAnimationFinished");
   // ScrollOffsetAnimationFinished is called in two cases: 1- smooth scrolling
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index dc077eff..8e76053 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -370,6 +370,10 @@
                                  ElementListType list_type,
                                  const PropertyAnimationState& mask,
                                  const PropertyAnimationState& state) override;
+  void AnimationScalesChanged(ElementId element_id,
+                              ElementListType list_type,
+                              float maximum_scale,
+                              float starting_scale) override;
 
   void ScrollOffsetAnimationFinished() override;
   gfx::ScrollOffset GetScrollOffsetForAnimation(
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 4fad6b06..8a8fc92 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -861,8 +861,10 @@
                                                                   list_type);
       if (node->has_potential_animation != has_potential_animation) {
         node->has_potential_animation = has_potential_animation;
-        node->has_only_translation_animations =
-            mutator_host()->HasOnlyTranslationTransforms(element_id, list_type);
+        node->maximum_animation_scale =
+            mutator_host()->MaximumTargetScale(element_id, list_type);
+        node->starting_animation_scale =
+            mutator_host()->AnimationStartScale(element_id, list_type);
         transform_tree.set_needs_update(true);
         set_needs_update_draw_properties();
       }
diff --git a/cc/trees/mutator_host.h b/cc/trees/mutator_host.h
index 68ae50d..377579e 100644
--- a/cc/trees/mutator_host.h
+++ b/cc/trees/mutator_host.h
@@ -26,6 +26,11 @@
 class LayerTreeMutator;
 class ScrollTree;
 
+// Used as the return value of MaximumTargetScale() and AnimationStartScale() to
+// indicate that there is no active scale animation or the scale cannot be
+// computed.
+const float kNotScaled = 0;
+
 // A MutatorHost owns all the animation and mutation effects.
 // There is just one MutatorHost for LayerTreeHost on main renderer thread
 // and just one MutatorHost for LayerTreeHostImpl on the impl thread.
@@ -108,12 +113,17 @@
       ElementListType list_type) const = 0;
   virtual bool AnimationsPreserveAxisAlignment(ElementId element_id) const = 0;
 
-  virtual bool MaximumTargetScale(ElementId element_id,
-                                  ElementListType list_type,
-                                  float* max_scale) const = 0;
-  virtual bool AnimationStartScale(ElementId element_id,
-                                   ElementListType list_type,
-                                   float* start_scale) const = 0;
+  // Returns the maximum scale along any dimension at any destination in active
+  // scale animations, or kNotScaled if there is no active scale animation or
+  // the maximum scale cannot be computed.
+  virtual float MaximumTargetScale(ElementId element_id,
+                                   ElementListType list_type) const = 0;
+
+  // Returns the maximum of starting animation scale along any dimension at any
+  // destination in active scale animations, or kNotScaled if there is no active
+  // scale animation or the starting scale cannot be computed.
+  virtual float AnimationStartScale(ElementId element_id,
+                                    ElementListType list_type) const = 0;
 
   virtual bool IsElementAnimating(ElementId element_id) const = 0;
   virtual bool HasTickingKeyframeModelForTesting(
diff --git a/cc/trees/mutator_host_client.h b/cc/trees/mutator_host_client.h
index 40d6b7e..44bad2c 100644
--- a/cc/trees/mutator_host_client.h
+++ b/cc/trees/mutator_host_client.h
@@ -56,6 +56,11 @@
       const PropertyAnimationState& mask,
       const PropertyAnimationState& state) = 0;
 
+  virtual void AnimationScalesChanged(ElementId element_id,
+                                      ElementListType list_type,
+                                      float maximum_scale,
+                                      float starting_scale) = 0;
+
   virtual void ScrollOffsetAnimationFinished() = 0;
   virtual gfx::ScrollOffset GetScrollOffsetForAnimation(
       ElementId element_id) const = 0;
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index 1127f94..0ed2742f 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -17,7 +17,6 @@
 #include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/layer_tree_impl.h"
-#include "cc/trees/mutator_host.h"
 #include "cc/trees/property_tree.h"
 #include "cc/trees/scroll_node.h"
 #include "cc/trees/transform_node.h"
@@ -1859,9 +1858,7 @@
 }
 
 bool PropertyTrees::ElementIsAnimatingChanged(
-    const MutatorHost* mutator_host,
     const PropertyToElementIdMap& element_id_map,
-    ElementListType list_type,
     const PropertyAnimationState& mask,
     const PropertyAnimationState& state,
     bool check_node_existence) {
@@ -1895,9 +1892,6 @@
           if (mask.potentially_animating[property]) {
             transform_node->has_potential_animation =
                 state.potentially_animating[property];
-            transform_node->has_only_translation_animations =
-                mutator_host->HasOnlyTranslationTransforms(element_id,
-                                                           list_type);
             transform_tree.set_needs_update(true);
             // We track transform updates specifically, whereas we
             // don't do so for opacity/filter, because whether a
@@ -1953,6 +1947,17 @@
   return updated_transform;
 }
 
+void PropertyTrees::AnimationScalesChanged(ElementId element_id,
+                                           float maximum_scale,
+                                           float starting_scale) {
+  if (TransformNode* transform_node =
+          transform_tree.FindNodeFromElementId(element_id)) {
+    transform_node->maximum_animation_scale = maximum_scale;
+    transform_node->starting_animation_scale = starting_scale;
+    UpdateTransformTreeUpdateNumber();
+  }
+}
+
 void PropertyTrees::SetInnerViewportScrollBoundsDelta(
     gfx::Vector2dF bounds_delta) {
   inner_viewport_scroll_bounds_delta_ = bounds_delta;
@@ -2042,28 +2047,26 @@
 CombinedAnimationScale PropertyTrees::GetAnimationScales(
     int transform_node_id,
     LayerTreeImpl* layer_tree_impl) {
-  if (cached_data_.animation_scales[transform_node_id].update_number !=
+  AnimationScaleData* animation_scales =
+      &cached_data_.animation_scales[transform_node_id];
+  if (animation_scales->update_number !=
       cached_data_.transform_tree_update_number) {
     if (!layer_tree_impl->settings()
              .layer_transforms_should_scale_layer_contents) {
-      cached_data_.animation_scales[transform_node_id].update_number =
+      animation_scales->update_number =
           cached_data_.transform_tree_update_number;
-      cached_data_.animation_scales[transform_node_id]
-          .combined_maximum_animation_target_scale = 0.f;
-      cached_data_.animation_scales[transform_node_id]
-          .combined_starting_animation_scale = 0.f;
+      animation_scales->combined_maximum_animation_target_scale = kNotScaled;
+      animation_scales->combined_starting_animation_scale = kNotScaled;
       return CombinedAnimationScale(
-          cached_data_.animation_scales[transform_node_id]
-              .combined_maximum_animation_target_scale,
-          cached_data_.animation_scales[transform_node_id]
-              .combined_starting_animation_scale);
+          animation_scales->combined_maximum_animation_target_scale,
+          animation_scales->combined_starting_animation_scale);
     }
 
     TransformNode* node = transform_tree.Node(transform_node_id);
     TransformNode* parent_node = transform_tree.parent(node);
     bool ancestor_is_animating_scale = false;
-    float ancestor_maximum_target_scale = 0.f;
-    float ancestor_starting_animation_scale = 0.f;
+    float ancestor_maximum_target_scale = kNotScaled;
+    float ancestor_starting_animation_scale = kNotScaled;
     if (parent_node) {
       CombinedAnimationScale combined_animation_scale =
           GetAnimationScales(parent_node->id, layer_tree_impl);
@@ -2076,14 +2079,17 @@
               .to_screen_has_scale_animation;
     }
 
-    cached_data_.animation_scales[transform_node_id]
-        .to_screen_has_scale_animation =
-        !node->has_only_translation_animations || ancestor_is_animating_scale;
+    bool node_is_animating_scale =
+        node->maximum_animation_scale != kNotScaled &&
+        node->starting_animation_scale != kNotScaled;
+
+    animation_scales->to_screen_has_scale_animation =
+        node_is_animating_scale || ancestor_is_animating_scale;
 
     // Once we've failed to compute a maximum animated scale at an ancestor, we
     // continue to fail.
-    bool failed_at_ancestor =
-        ancestor_is_animating_scale && ancestor_maximum_target_scale == 0.f;
+    bool failed_at_ancestor = ancestor_is_animating_scale &&
+                              ancestor_maximum_target_scale == kNotScaled;
 
     // Computing maximum animated scale in the presence of non-scale/translation
     // transforms isn't supported.
@@ -2096,90 +2102,46 @@
     // as another node is decreasing scale from 10 to 1. Naively combining these
     // scales would produce a scale of 100.
     bool failed_for_multiple_scale_animations =
-        ancestor_is_animating_scale && !node->has_only_translation_animations;
+        ancestor_is_animating_scale && node_is_animating_scale;
 
     if (failed_at_ancestor || failed_for_non_scale_or_translation ||
         failed_for_multiple_scale_animations) {
       // This ensures that descendants know we've failed to compute a maximum
       // animated scale.
-      cached_data_.animation_scales[transform_node_id]
-          .to_screen_has_scale_animation = true;
-
-      cached_data_.animation_scales[transform_node_id]
-          .combined_maximum_animation_target_scale = 0.f;
-      cached_data_.animation_scales[transform_node_id]
-          .combined_starting_animation_scale = 0.f;
-    } else if (!cached_data_.animation_scales[transform_node_id]
-                    .to_screen_has_scale_animation) {
-      cached_data_.animation_scales[transform_node_id]
-          .combined_maximum_animation_target_scale = 0.f;
-      cached_data_.animation_scales[transform_node_id]
-          .combined_starting_animation_scale = 0.f;
-    } else if (node->has_only_translation_animations) {
+      animation_scales->to_screen_has_scale_animation = true;
+      animation_scales->combined_maximum_animation_target_scale = kNotScaled;
+      animation_scales->combined_starting_animation_scale = kNotScaled;
+    } else if (!animation_scales->to_screen_has_scale_animation) {
+      animation_scales->combined_maximum_animation_target_scale = kNotScaled;
+      animation_scales->combined_starting_animation_scale = kNotScaled;
+    } else if (!node_is_animating_scale) {
       // An ancestor is animating scale.
       gfx::Vector2dF local_scales =
-          MathUtil::ComputeTransform2dScaleComponents(node->local, 0.f);
+          MathUtil::ComputeTransform2dScaleComponents(node->local, kNotScaled);
       float max_local_scale = std::max(local_scales.x(), local_scales.y());
-      cached_data_.animation_scales[transform_node_id]
-          .combined_maximum_animation_target_scale =
+      animation_scales->combined_maximum_animation_target_scale =
           max_local_scale * ancestor_maximum_target_scale;
-      cached_data_.animation_scales[transform_node_id]
-          .combined_starting_animation_scale =
+      animation_scales->combined_starting_animation_scale =
           max_local_scale * ancestor_starting_animation_scale;
     } else {
-      ElementListType list_type = layer_tree_impl->IsActiveTree()
-                                      ? ElementListType::ACTIVE
-                                      : ElementListType::PENDING;
+      gfx::Vector2dF ancestor_scales =
+          parent_node
+              ? MathUtil::ComputeTransform2dScaleComponents(
+                    transform_tree.ToScreen(parent_node->id), kNotScaled)
+              : gfx::Vector2dF(1.f, 1.f);
 
-      layer_tree_impl->mutator_host()->MaximumTargetScale(
-          node->element_id, list_type,
-          &cached_data_.animation_scales[transform_node_id]
-               .local_maximum_animation_target_scale);
-      layer_tree_impl->mutator_host()->AnimationStartScale(
-          node->element_id, list_type,
-          &cached_data_.animation_scales[transform_node_id]
-               .local_starting_animation_scale);
-      gfx::Vector2dF local_scales =
-          MathUtil::ComputeTransform2dScaleComponents(node->local, 0.f);
-      float max_local_scale = std::max(local_scales.x(), local_scales.y());
-
-      if (cached_data_.animation_scales[transform_node_id]
-                  .local_starting_animation_scale == 0.f ||
-          cached_data_.animation_scales[transform_node_id]
-                  .local_maximum_animation_target_scale == 0.f) {
-        cached_data_.animation_scales[transform_node_id]
-            .combined_maximum_animation_target_scale =
-            max_local_scale * ancestor_maximum_target_scale;
-        cached_data_.animation_scales[transform_node_id]
-            .combined_starting_animation_scale =
-            max_local_scale * ancestor_starting_animation_scale;
-      } else {
-        gfx::Vector2dF ancestor_scales =
-            parent_node ? MathUtil::ComputeTransform2dScaleComponents(
-                              transform_tree.ToScreen(parent_node->id), 0.f)
-                        : gfx::Vector2dF(1.f, 1.f);
-
-        float max_ancestor_scale =
-            std::max(ancestor_scales.x(), ancestor_scales.y());
-        cached_data_.animation_scales[transform_node_id]
-            .combined_maximum_animation_target_scale =
-            max_ancestor_scale *
-            cached_data_.animation_scales[transform_node_id]
-                .local_maximum_animation_target_scale;
-        cached_data_.animation_scales[transform_node_id]
-            .combined_starting_animation_scale =
-            max_ancestor_scale *
-            cached_data_.animation_scales[transform_node_id]
-                .local_starting_animation_scale;
-      }
+      float max_ancestor_scale =
+          std::max(ancestor_scales.x(), ancestor_scales.y());
+      animation_scales->combined_maximum_animation_target_scale =
+          max_ancestor_scale * node->maximum_animation_scale;
+      animation_scales->combined_starting_animation_scale =
+          max_ancestor_scale * node->starting_animation_scale;
     }
-    cached_data_.animation_scales[transform_node_id].update_number =
-        cached_data_.transform_tree_update_number;
+    animation_scales->update_number = cached_data_.transform_tree_update_number;
   }
-  return CombinedAnimationScale(cached_data_.animation_scales[transform_node_id]
-                                    .combined_maximum_animation_target_scale,
-                                cached_data_.animation_scales[transform_node_id]
-                                    .combined_starting_animation_scale);
+  return CombinedAnimationScale(
+      animation_scales->combined_maximum_animation_target_scale,
+      animation_scales->combined_starting_animation_scale);
 }
 
 void PropertyTrees::SetAnimationScalesForTesting(
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h
index 42635e1..5fa178a 100644
--- a/cc/trees/property_tree.h
+++ b/cc/trees/property_tree.h
@@ -35,7 +35,6 @@
 namespace cc {
 
 class LayerTreeImpl;
-class MutatorHost;
 class RenderSurfaceImpl;
 class ScrollState;
 struct ClipNode;
@@ -517,14 +516,6 @@
   // updates.
   int update_number;
 
-  // Current animations, considering only scales at keyframes not including the
-  // starting keyframe of each animation.
-  float local_maximum_animation_target_scale;
-
-  // The maximum scale that this node's |local| transform will have during
-  // current animatons, considering only the starting scale of each animation.
-  float local_starting_animation_scale;
-
   // The maximum scale that this node's |to_target| transform will have during
   // current animations, considering only scales at keyframes not incuding the
   // starting keyframe of each animation.
@@ -538,8 +529,6 @@
 
   AnimationScaleData() {
     update_number = -1;
-    local_maximum_animation_target_scale = 0.f;
-    local_starting_animation_scale = 0.f;
     combined_maximum_animation_target_scale = 0.f;
     combined_starting_animation_scale = 0.f;
     to_screen_has_scale_animation = false;
@@ -663,12 +652,13 @@
   // Applies an animation state change for a particular element in
   // this property tree. Returns whether a draw property update is
   // needed.
-  bool ElementIsAnimatingChanged(const MutatorHost* mutator_host,
-                                 const PropertyToElementIdMap& element_id_map,
-                                 ElementListType list_type,
+  bool ElementIsAnimatingChanged(const PropertyToElementIdMap& element_id_map,
                                  const PropertyAnimationState& mask,
                                  const PropertyAnimationState& state,
                                  bool check_node_existence);
+  void AnimationScalesChanged(ElementId element_id,
+                              float maximum_scale,
+                              float starting_scale);
   void SetInnerViewportContainerBoundsDelta(gfx::Vector2dF bounds_delta);
   void SetOuterViewportContainerBoundsDelta(gfx::Vector2dF bounds_delta);
   void SetInnerViewportScrollBoundsDelta(gfx::Vector2dF bounds_delta);
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 58ff863..0e5434e 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -292,6 +292,18 @@
 }
 
 template <typename LayerType>
+float MaximumAnimationScale(const MutatorHost& host, LayerType* layer) {
+  return host.MaximumTargetScale(layer->element_id(),
+                                 layer->GetElementTypeForAnimation());
+}
+
+template <typename LayerType>
+float StartingAnimationScale(const MutatorHost& host, LayerType* layer) {
+  return host.AnimationStartScale(layer->element_id(),
+                                  layer->GetElementTypeForAnimation());
+}
+
+template <typename LayerType>
 bool AnimationsPreserveAxisAlignment(const MutatorHost& host,
                                      LayerType* layer) {
   return host.AnimationsPreserveAxisAlignment(layer->element_id());
@@ -564,10 +576,8 @@
 
   node->has_potential_animation = has_potentially_animated_transform;
   node->is_currently_animating = TransformIsAnimating(mutator_host_, layer);
-  if (has_potentially_animated_transform) {
-    node->has_only_translation_animations =
-        HasOnlyTranslationTransforms(mutator_host_, layer);
-  }
+  node->maximum_animation_scale = MaximumAnimationScale(mutator_host_, layer);
+  node->starting_animation_scale = StartingAnimationScale(mutator_host_, layer);
 
   float post_local_scale_factor = 1.0f;
 
diff --git a/cc/trees/transform_node.cc b/cc/trees/transform_node.cc
index 9964f16..bf8f426 100644
--- a/cc/trees/transform_node.cc
+++ b/cc/trees/transform_node.cc
@@ -6,6 +6,7 @@
 #include "base/trace_event/traced_value.h"
 #include "cc/base/math_util.h"
 #include "cc/layers/layer.h"
+#include "cc/trees/mutator_host.h"
 #include "cc/trees/property_tree.h"
 #include "ui/gfx/geometry/point3_f.h"
 
@@ -24,7 +25,6 @@
       has_potential_animation(false),
       is_currently_animating(false),
       to_screen_is_potentially_animated(false),
-      has_only_translation_animations(true),
       flattens_inherited_transform(false),
       node_and_ancestors_are_flat(true),
       node_and_ancestors_have_only_integer_translation(true),
@@ -36,7 +36,9 @@
       moved_by_outer_viewport_bounds_delta_y(false),
       in_subtree_of_page_scale_layer(false),
       transform_changed(false),
-      post_local_scale_factor(1.0f) {}
+      post_local_scale_factor(1.0f),
+      maximum_animation_scale(kNotScaled),
+      starting_animation_scale(kNotScaled) {}
 
 TransformNode::TransformNode(const TransformNode&) = default;
 
@@ -56,8 +58,6 @@
          is_currently_animating == other.is_currently_animating &&
          to_screen_is_potentially_animated ==
              other.to_screen_is_potentially_animated &&
-         has_only_translation_animations ==
-             other.has_only_translation_animations &&
          flattens_inherited_transform == other.flattens_inherited_transform &&
          node_and_ancestors_are_flat == other.node_and_ancestors_are_flat &&
          node_and_ancestors_have_only_integer_translation ==
@@ -79,7 +79,9 @@
          scroll_offset == other.scroll_offset &&
          snap_amount == other.snap_amount &&
          source_offset == other.source_offset &&
-         source_to_parent == other.source_to_parent;
+         source_to_parent == other.source_to_parent &&
+         maximum_animation_scale == other.maximum_animation_scale &&
+         starting_animation_scale == other.starting_animation_scale;
 }
 
 void TransformNode::update_pre_local_transform(
diff --git a/cc/trees/transform_node.h b/cc/trees/transform_node.h
index c8f8ebf8..b64a230 100644
--- a/cc/trees/transform_node.h
+++ b/cc/trees/transform_node.h
@@ -89,9 +89,6 @@
   // (i.e., irrespective of exact timeline) transform
   // animation.
   bool to_screen_is_potentially_animated : 1;
-  // Whether all animations on this transform node are simple
-  // translations.
-  bool has_only_translation_animations : 1;
 
   // Flattening, when needed, is only applied to a node's inherited transform,
   // never to its local transform.
@@ -139,6 +136,11 @@
   gfx::Vector2dF source_offset;
   gfx::Vector2dF source_to_parent;
 
+  // See ElementAnimations::MaximumTargetScale() and AnimationStartScale() for
+  // their meanings. Updated by PropertyTrees::AnimationScalesChanged().
+  float maximum_animation_scale;
+  float starting_animation_scale;
+
   bool operator==(const TransformNode& other) const;
 
   void set_to_parent(const gfx::Transform& transform) {
diff --git a/cc/trees/tree_synchronizer_unittest.cc b/cc/trees/tree_synchronizer_unittest.cc
index 99b8819c..b7a3dc02 100644
--- a/cc/trees/tree_synchronizer_unittest.cc
+++ b/cc/trees/tree_synchronizer_unittest.cc
@@ -766,7 +766,7 @@
   host_->CommitAndCreatePendingTree();
   host_impl->ActivateSyncTree();
   EXPECT_EQ(
-      CombinedAnimationScale(0.f, 0.f),
+      CombinedAnimationScale(kNotScaled, kNotScaled),
       host_impl->active_tree()->property_trees()->GetAnimationScales(
           transform_layer->transform_tree_index(), host_impl->active_tree()));
 }
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index b371a7d..048d0bd1 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -789,8 +789,8 @@
   }
 
   compile_entitlements("entitlements") {
-    entitlements_templates = [ "app/entitlements.plist" ]
-    output_name = "$target_gen_dir/entitlements.plist"
+    entitlements_templates = [ "app/app-entitlements.plist" ]
+    output_name = "$target_gen_dir/app-entitlements.plist"
     substitutions = [
       "CHROMIUM_BUNDLE_ID=$chrome_mac_bundle_id",
       "CHROMIUM_TEAM_ID=$chrome_mac_team_id",
diff --git a/chrome/VERSION b/chrome/VERSION
index 9ce99783..3aeffdc 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=75
 MINOR=0
-BUILD=3756
+BUILD=3757
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 6fd6cb03..cf80541 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -332,6 +332,7 @@
     "//skia/public/interfaces:interfaces_java",
     "//third_party/android_data_chart:android_data_chart_java",
     "//third_party/android_deps:android_arch_lifecycle_common_java",
+    "//third_party/android_deps:android_arch_lifecycle_common_java8_java",
     "//third_party/android_deps:android_arch_lifecycle_runtime_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
     "//third_party/android_deps:com_android_support_design_java",
@@ -955,6 +956,7 @@
           ]
 
       data = [
+        "//chrome/test/data/android/",
         "//chrome/android/shared_preference_files/test/",
         "//components/test/data/js_dialogs/render_tests/",
         "//components/test/data/permission_dialogs/render_tests/",
diff --git a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_cs.xtb b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_cs.xtb
index dc19b2e8..8ab7bd96 100644
--- a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_cs.xtb
+++ b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_cs.xtb
@@ -7,7 +7,7 @@
 <translation id="5014174725590676422">Je zobrazena obrazovka prvního spuštění Asistenta Google v Chromu</translation>
 <translation id="5188078772080029703">Adresu URL a obsah webu a váš e-mail a typ platební karty uložený v Chromu odešle Chrome do Googlu. Tuto možnost můžete vypnout v nastavení. <ph name="BEGIN_LINK" />Další informace<ph name="END_LINK" /></translation>
 <translation id="5388358297987318779">Otevřít obrázek</translation>
-<translation id="6973932557599545801">Pardon, nedokážu vám pomoct. Pokračujte prosím sami.</translation>
+<translation id="6973932557599545801">Pardon, nedokážu vám pomoct. Je to na vás.</translation>
 <translation id="7658239707568436148">Zrušit</translation>
 <translation id="7670842975141217779">Asistent Google\nv Chromu</translation>
 <translation id="7871791972254842204">Přečíst si a odsouhlasit smluvní podmínky domény <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> později</translation>
diff --git a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_fil.xtb b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_fil.xtb
index 68d9cb3..5a66588b 100644
--- a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_fil.xtb
+++ b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_fil.xtb
@@ -7,7 +7,7 @@
 <translation id="5014174725590676422">Ipinapakita ang screen ng unang pagtakbo ng Google Assistant sa Chrome</translation>
 <translation id="5188078772080029703">Ipapadala ng Chrome sa Google ang URL at content ng site pati na rin ang iyong email at uri ng credit card na naka-save sa Chrome. Puwede mo itong i-off sa mga setting ng Chrome. <ph name="BEGIN_LINK" />Matuto pa<ph name="END_LINK" /></translation>
 <translation id="5388358297987318779">Buksan ang Larawan</translation>
-<translation id="6973932557599545801">Paumanhin, hindi ako makatulong, mangyaring magpatuloy nang mag-isa.</translation>
+<translation id="6973932557599545801">Paumanhin, hindi ako makatulong. Magpatuloy nang mag-isa.</translation>
 <translation id="7658239707568436148">Kanselahin</translation>
 <translation id="7670842975141217779">Google Assistant\nsa Chrome</translation>
 <translation id="7871791972254842204">Basahin at sumang-ayon sa mga tuntunin at kundisyon sa <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> sa ibang pagkakataon</translation>
diff --git a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_iw.xtb b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_iw.xtb
index 240e206..cb7a7f6 100644
--- a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_iw.xtb
+++ b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_iw.xtb
@@ -7,7 +7,7 @@
 <translation id="5014174725590676422">‏מוצג מסך ההפעלה הראשונה של Google Assistant ב-Chrome</translation>
 <translation id="5188078772080029703">‏Chrome ישלח אל Google את כתובת ה-URL של האתר ואת התוכן שלו, כמו גם את כתובת האימייל וסוג כרטיס האשראי ששמרת ב-Chrome. ניתן להשבית את האפשרות הזו בהגדרות Chrome. <ph name="BEGIN_LINK" />מידע נוסף<ph name="END_LINK" /></translation>
 <translation id="5388358297987318779">פתח תמונה</translation>
-<translation id="6973932557599545801">אין לי אפשרות לעזור. עליך להמשיך בעצמך.</translation>
+<translation id="6973932557599545801">לצערי אין לי אפשרות לעזור. עליך להמשיך בעצמך.</translation>
 <translation id="7658239707568436148">ביטול</translation>
 <translation id="7670842975141217779">‏Google Assistant\nב-Chrome</translation>
 <translation id="7871791972254842204">אקרא ואאשר את התנאים וההגבלות ב-<ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> מאוחר יותר</translation>
diff --git a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_vi.xtb b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_vi.xtb
index 0c86daf..b95efcff 100644
--- a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_vi.xtb
+++ b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_vi.xtb
@@ -7,7 +7,7 @@
 <translation id="5014174725590676422">Màn hình chạy đầu tiên của Trợ lý Google trong Chrome đã được hiển thị</translation>
 <translation id="5188078772080029703">Chrome sẽ gửi URL và nội dung của trang web cũng như địa chỉ email và loại thẻ tín dụng bạn đã lưu trong Chrome cho Google. Bạn có thể tắt tính năng này trong phần cài đặt Chrome. <ph name="BEGIN_LINK" />Tìm hiểu thêm<ph name="END_LINK" /></translation>
 <translation id="5388358297987318779">Mở hình ảnh</translation>
-<translation id="6973932557599545801">Rất tiếc, tôi không thể trợ giúp được nữa. Bạn vui lòng tự thực hiện hành động này.</translation>
+<translation id="6973932557599545801">Rất tiếc, tôi không thể trợ giúp được nữa. Bạn vui lòng tự thực hiện việc này.</translation>
 <translation id="7658239707568436148">Hủy</translation>
 <translation id="7670842975141217779">Trợ lý Google\ntrong Chrome</translation>
 <translation id="7871791972254842204">Đọc và đồng ý với điều khoản và điều kiện của <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> vào lúc khác</translation>
diff --git a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_zh-TW.xtb b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_zh-TW.xtb
index dd12ae4..b682cef5 100644
--- a/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_zh-TW.xtb
+++ b/chrome/android/features/autofill_assistant/java/strings/translations/android_chrome_autofill_assistant_strings_zh-TW.xtb
@@ -7,7 +7,7 @@
 <translation id="5014174725590676422">目前顯示 Chrome 版 Google 助理首次執行的畫面</translation>
 <translation id="5188078772080029703">Chrome 會將網站的網址和內容,以及 Chrome 中儲存的電子郵件和信用卡類型資訊傳送給 Google。你可以在 Chrome 設定中關閉這項功能。<ph name="BEGIN_LINK" />瞭解詳情<ph name="END_LINK" /></translation>
 <translation id="5388358297987318779">開啟圖片</translation>
-<translation id="6973932557599545801">抱歉,目前無法提供協助,請您自行填入資料。</translation>
+<translation id="6973932557599545801">抱歉,目前無法提供協助,請自行填入資料。</translation>
 <translation id="7658239707568436148">取消</translation>
 <translation id="7670842975141217779">Chrome 版\nGoogle 助理</translation>
 <translation id="7871791972254842204">稍後閱讀並同意 <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> 的條款及細則</translation>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtils.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtils.java
index 0bbf728..dc60ddb 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtils.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtils.java
@@ -75,7 +75,8 @@
         sTabModelSelectorTabObserver = new TabModelSelectorTabObserver(selector) {
             @Override
             public void onDidFinishNavigation(Tab tab, NavigationHandle navigationHandle) {
-                if (!navigationHandle.isInMainFrame()) return;
+                if (!navigationHandle.isInMainFrame() || navigationHandle.pageTransition() == null)
+                    return;
                 if (tab.isIncognito()) return;
                 if (navigationHandle.pageTransition() == null) return;
 
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
index 359094a..bccdc873 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
@@ -11,9 +11,9 @@
 import com.google.android.libraries.feed.host.logging.BasicLoggingApi;
 import com.google.android.libraries.feed.host.logging.ContentLoggingData;
 import com.google.android.libraries.feed.host.logging.ElementLoggingData;
-import com.google.android.libraries.feed.host.logging.ElementType;
 import com.google.android.libraries.feed.host.logging.InternalFeedError;
 import com.google.android.libraries.feed.host.logging.RequestReason;
+import com.google.android.libraries.feed.host.logging.ScrollType;
 import com.google.android.libraries.feed.host.logging.SessionEvent;
 import com.google.android.libraries.feed.host.logging.SpinnerType;
 import com.google.android.libraries.feed.host.logging.ZeroStateShowReason;
@@ -217,12 +217,12 @@
     }
 
     @Override
-    public void onVisualElementClicked(ElementLoggingData data, @ElementType int elementType) {
+    public void onVisualElementClicked(ElementLoggingData data, int elementType) {
         // TODO(https://crbug.com/924739): Implementation.
     }
 
     @Override
-    public void onVisualElementViewed(ElementLoggingData data, @ElementType int elementType) {
+    public void onVisualElementViewed(ElementLoggingData data, int elementType) {
         // TODO(https://crbug.com/924739): Implementation.
     }
 
@@ -268,6 +268,11 @@
         // TODO(https://crbug.com/924739): Implementation.
     }
 
+    @Override
+    public void onScroll(@ScrollType int scrollType, int distanceScrolled) {
+        // TODO(https://crbug.com/924739): Implementation.
+    }
+
     /**
      * Reports how long a user spends on the page.
      *
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
index 73e4932..77f99b5 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
@@ -376,6 +376,8 @@
                                         chromeActivity.getResources(), mUiConfig),
                                 new BasicSnackbarApi(mNewTabPageManager.getSnackbarManager()),
                                 offlineIndicator, tooltipApi)
+                        .setIsBackgroundDark(
+                                chromeActivity.getNightModeStateProvider().isInNightMode())
                         .build();
 
         mStream = streamScope.getStream();
diff --git a/chrome/android/java/monochrome_public_apk.AndroidManifest.expected b/chrome/android/java/monochrome_public_apk.AndroidManifest.expected
index 809d006..f78d4438 100644
--- a/chrome/android/java/monochrome_public_apk.AndroidManifest.expected
+++ b/chrome/android/java/monochrome_public_apk.AndroidManifest.expected
@@ -1186,7 +1186,6 @@
         android:name="com.google.android.apps.chrome.webapps.WebappManager"
         android:targetActivity="org.chromium.chrome.browser.webapps.WebappLauncherActivity"/>
     <meta-data android:name="android.allow_multiple_resumed_activities" android:value="true"/>
-    <meta-data android:name="android.arch.lifecycle.VERSION" android:value="27.0.0-SNAPSHOT"/>
     <meta-data
         android:name="android.content.APP_RESTRICTIONS"
         android:resource="@xml/app_restrictions"/>
diff --git a/chrome/android/java/monochrome_public_apk.proguard_flags.expected b/chrome/android/java/monochrome_public_apk.proguard_flags.expected
index da7ab5c..59be4b9 100644
--- a/chrome/android/java/monochrome_public_apk.proguard_flags.expected
+++ b/chrome/android/java/monochrome_public_apk.proguard_flags.expected
@@ -409,7 +409,7 @@
 -keep class * implements android.arch.lifecycle.LifecycleObserver {
 }
 
--keep class * implements android.arch.lifecycle.GenericLifecycleObserver {
+-keep class * implements android.arch.lifecycle.GeneratedAdapter {
     <init>(...);
 }
 
diff --git a/chrome/android/java/res/drawable/data_reduction_illustration.xml b/chrome/android/java/res/drawable/data_reduction_illustration.xml
index 979121d..ec8e23f6 100644
--- a/chrome/android/java/res/drawable/data_reduction_illustration.xml
+++ b/chrome/android/java/res/drawable/data_reduction_illustration.xml
@@ -9,9 +9,9 @@
     xmlns:tools="http://schemas.android.com/tools"
     tools:targetApi="21"
     tools:ignore="VectorRaster"
-    android:width="248dp"
+    android:width="232dp"
     android:height="107dp"
-    android:viewportWidth="248"
+    android:viewportWidth="232"
     android:viewportHeight="107">
   <path
       android:pathData="M156.91,3.733l18.155,31.59l-90.126,-1.508l12.968,-31.662z"
diff --git a/chrome/android/java/res/layout/compositor_view_holder.xml b/chrome/android/java/res/layout/compositor_view_holder.xml
new file mode 100644
index 0000000..9496d27
--- /dev/null
+++ b/chrome/android/java/res/layout/compositor_view_holder.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 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. -->
+
+
+<merge
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+<org.chromium.chrome.browser.compositor.CompositorViewHolder
+            android:id="@+id/compositor_view_holder"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+</merge>
diff --git a/chrome/android/java/res/layout/main.xml b/chrome/android/java/res/layout/main.xml
index 833ea76..6d2ede1d 100644
--- a/chrome/android/java/res/layout/main.xml
+++ b/chrome/android/java/res/layout/main.xml
@@ -3,7 +3,7 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<merge 
+<merge
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
@@ -13,10 +13,7 @@
         android:layout_height="match_parent"
         android:layout_weight="1" >
 
-        <org.chromium.chrome.browser.compositor.CompositorViewHolder
-            android:id="@+id/compositor_view_holder"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent" />
+       <include layout="@layout/compositor_view_holder"/>
 
        <FrameLayout
             android:id="@+id/overview_list_layout_holder"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
index 59e8c8ebf..7feb213 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
@@ -59,7 +59,7 @@
     private static ChromeApplication sInstance;
 
     @Nullable
-    private static ChromeAppComponent sComponent;
+    private static volatile ChromeAppComponent sComponent;
 
     @Override
     public void onCreate() {
@@ -240,7 +240,11 @@
     /** Returns the application-scoped component. */
     public static ChromeAppComponent getComponent() {
         if (sComponent == null) {
-            sComponent = createComponent();
+            synchronized (sInstance) {
+                if (sComponent == null) {
+                    sComponent = createComponent();
+                }
+            }
         }
         return sComponent;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
index 5455218..def28e1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -199,10 +199,8 @@
                 // Encode the icon as a base64 string (Launcher drops Bitmaps in the Intent).
                 String encodedIcon = encodeBitmapAsString(icon);
 
-                String nonEmptyScopeUrl =
-                        TextUtils.isEmpty(scopeUrl) ? getScopeFromUrl(url) : scopeUrl;
                 Intent shortcutIntent = createWebappShortcutIntent(id,
-                        sDelegate.getFullscreenAction(), url, nonEmptyScopeUrl, name, shortName,
+                        sDelegate.getFullscreenAction(), url, scopeUrl, name, shortName,
                         encodedIcon, WEBAPP_SHORTCUT_VERSION, displayMode, orientation, themeColor,
                         backgroundColor, splashScreenUrl, iconUrl.isEmpty(), isIconAdaptive);
                 shortcutIntent.putExtra(EXTRA_MAC, getEncodedMac(url));
@@ -633,12 +631,11 @@
     }
 
     /**
-     * Generates a scope URL based on the passed in URL. It should be used if the Web Manifest
-     * does not specify a scope URL.
+     * Generates a scope URL based on the passed in URL. Should only be used for legacy
+     * WebAPKs created prior to the usage of the Web App Manifest scope member.
      * @param url The url to convert to a scope.
      * @return The scope.
      */
-    @CalledByNative
     public static String getScopeFromUrl(String url) {
         // Scope URL is generated by:
         // - Removing last component of the URL if it does not end with a slash.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java
index 0b6f549..4d9d6bef 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java
@@ -18,6 +18,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabBuilder;
 import org.chromium.chrome.browser.tab.TabDelegateFactory;
+import org.chromium.chrome.browser.tab.TabState;
 import org.chromium.chrome.browser.tabmodel.SingleTabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
@@ -35,6 +36,8 @@
 public abstract class SingleTabActivity extends ChromeActivity {
     private static final int PREWARM_RENDERER_DELAY_MS = 500;
 
+    protected static final String BUNDLE_TAB_ID = "tabId";
+
     @Override
     protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
@@ -89,21 +92,28 @@
      */
     protected Tab createTab() {
         Tab tab = null;
-        boolean unfreeze = false;
-
-        if (getSavedInstanceState() != null) {
-            tab = restoreTab(getSavedInstanceState());
-            if (tab != null) unfreeze = true;
+        TabState tabState = null;
+        int tabId = Tab.INVALID_TAB_ID;
+        Bundle savedInstanceState = getSavedInstanceState();
+        if (savedInstanceState != null) {
+            tabId = savedInstanceState.getInt(BUNDLE_TAB_ID, Tab.INVALID_TAB_ID);
+            if (tabId != Tab.INVALID_TAB_ID) {
+                tabState = restoreTabState(savedInstanceState, tabId);
+            }
         }
-
-        if (tab == null) {
+        boolean unfreeze = tabId != Tab.INVALID_TAB_ID && tabState != null;
+        if (unfreeze) {
+            tab = TabBuilder.createFromFrozenState()
+                          .setId(tabId)
+                          .setWindow(getWindowAndroid())
+                          .build();
+        } else {
             tab = new TabBuilder()
                           .setWindow(getWindowAndroid())
                           .setLaunchType(TabLaunchType.FROM_CHROME_UI)
                           .build();
         }
-
-        tab.initialize(null, createTabDelegateFactory(), false, unfreeze);
+        tab.initialize(null, createTabDelegateFactory(), false, tabState, unfreeze);
         return tab;
     }
 
@@ -114,7 +124,12 @@
         return new TabDelegateFactory();
     }
 
-    protected abstract Tab restoreTab(Bundle savedInstanceState);
+    /**
+     * Restore {@link TabState} from a given {@link Bundle} and tabId.
+     * @param saveInstanceState The saved bundle for the last recorded state.
+     * @param tabId ID of the tab restored from.
+     */
+    protected abstract TabState restoreTabState(Bundle savedInstanceState, int tabId);
 
     private boolean supportsAppSwitcher() {
         return getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java
index 8ba36c0..6802bd9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsTabCreatorManager.java
@@ -52,7 +52,7 @@
                               .setWindow(windowAndroid)
                               .setLaunchType(type)
                               .build();
-            tab.initialize(null, new TabDelegateFactory(), true, false);
+            tab.initialize(null, new TabDelegateFactory(), true, null, false);
             mTabModel.addTab(tab, -1, type);
             return tab;
         }
@@ -61,11 +61,8 @@
         public Tab createFrozenTab(TabState state, int id, int index) {
             Context context = ContextUtils.getApplicationContext();
             WindowAndroid windowAndroid = new WindowAndroid(context);
-            Tab tab = TabBuilder.createFromFrozenState(state)
-                              .setId(id)
-                              .setWindow(windowAndroid)
-                              .build();
-            tab.initialize(null, new TabDelegateFactory(), true, false);
+            Tab tab = TabBuilder.createFromFrozenState().setId(id).setWindow(windowAndroid).build();
+            tab.initialize(null, new TabDelegateFactory(), true, state, false);
             mTabModel.addTab(tab, index, TabLaunchType.FROM_RESTORE);
             return tab;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
index 74f7cd5..41ebfbd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
@@ -12,7 +12,9 @@
 import org.chromium.base.Log;
 import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.ChromeVersionInfo;
+import org.chromium.chrome.browser.metrics.WebApkUma;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
+import org.chromium.webapk.lib.common.WebApkConstants;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -93,6 +95,16 @@
         int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
         if (uid == -1) return;
 
+        boolean uninstalled = Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(intent.getAction());
+
+        if (uninstalled && intent.getData() != null) {
+            String packageName = intent.getData().getSchemeSpecificPart();
+            if (packageName != null
+                    && packageName.startsWith(WebApkConstants.WEBAPK_PACKAGE_PREFIX)) {
+                WebApkUma.recordWebApkUninstalled();
+            }
+        }
+
         try (BrowserServicesMetrics.TimingMetric unused =
                      BrowserServicesMetrics.getClientAppDataLoadTimingContext()) {
 
@@ -104,7 +116,6 @@
             }
         }
 
-        boolean uninstalled = Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(intent.getAction());
         mClearDataStrategy.execute(context, mRegister, uid, uninstalled);
         clearPreferences(uid, uninstalled);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashScreenController.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashScreenController.java
index 3727351b..559c3b1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashScreenController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashScreenController.java
@@ -68,13 +68,6 @@
 
     private static final String TAG = "TwaSplashScreens";
 
-    // TODO(pshmakov): Use constants from TrustedWebUtils when they land there.
-    static final String EXTRA_SPLASH_SCREEN_PARAMS =
-            "android.support.customtabs.trusted.EXTRA_SPLASH_SCREEN_PARAMS";
-
-    static final String KEY_SPLASH_SCREEN_BACKGROUND_COLOR =
-            "android.support.customtabs.trusted.KEY_SPLASH_SCREEN_BACKGROUND_COLOR";
-
     private final Activity mActivity;
     private final ActivityLifecycleDispatcher mLifecycleDispatcher;
     private final TabObserverRegistrar mTabObserverRegistrar;
@@ -127,8 +120,10 @@
             mLifecycleDispatcher.unregister(this);
             return;
         }
-        Bundle params = mIntentDataProvider.getIntent().getBundleExtra(EXTRA_SPLASH_SCREEN_PARAMS);
-        int backgroundColor = params.getInt(KEY_SPLASH_SCREEN_BACKGROUND_COLOR, Color.WHITE);
+        Bundle params = mIntentDataProvider.getIntent().getBundleExtra(
+                TrustedWebUtils.EXTRA_SPLASH_SCREEN_PARAMS);
+        int backgroundColor = params.getInt(TrustedWebUtils.SplashScreenParamKey.BACKGROUND_COLOR,
+                Color.WHITE);
 
         mSplashView = new ImageView(mActivity);
         mSplashView.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
@@ -212,8 +207,8 @@
     public static boolean intentIsForTwaWithSplashScreen(Intent intent) {
         boolean isTrustedWebActivity = IntentUtils.safeGetBooleanExtra(intent,
                 TrustedWebUtils.EXTRA_LAUNCH_AS_TRUSTED_WEB_ACTIVITY, false);
-        boolean requestsSplashScreen =
-                IntentUtils.safeGetParcelableExtra(intent, EXTRA_SPLASH_SCREEN_PARAMS) != null;
+        boolean requestsSplashScreen = IntentUtils.safeGetParcelableExtra(intent,
+                        TrustedWebUtils.EXTRA_SPLASH_SCREEN_PARAMS) != null;
         return isTrustedWebActivity && requestsSplashScreen;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
index 6e55a24c..cba212d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -56,6 +56,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.widget.ControlContainer;
+import org.chromium.components.content_capture.ContentCaptureConsumer;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.KeyboardVisibilityDelegate;
 import org.chromium.ui.UiUtils;
@@ -132,6 +133,8 @@
 
     private boolean mIsInVr;
 
+    protected ContentCaptureConsumer mContentCaptureConsumer;
+
     /**
      * This view is created on demand to display debugging information.
      */
@@ -454,6 +457,10 @@
             mInsetObserverView.removeObserver(this);
             mInsetObserverView = null;
         }
+        if (mContentCaptureConsumer != null) {
+            mContentCaptureConsumer.destroy();
+            mContentCaptureConsumer = null;
+        }
     }
 
     /**
@@ -590,7 +597,7 @@
         return tab != null ? tab.getContentView() : null;
     }
 
-    private WebContents getWebContents() {
+    protected WebContents getWebContents() {
         Tab tab = getCurrentTab();
         return tab != null ? tab.getWebContents() : null;
     }
@@ -1063,6 +1070,10 @@
         updateContentOverlayVisibility(mContentOverlayVisiblity);
 
         if (mTabVisible != null) initializeTab(mTabVisible);
+
+        if (mContentCaptureConsumer != null) {
+            mContentCaptureConsumer.onWebContentsChanged(getWebContents());
+        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsClientFileProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsClientFileProcessor.java
index b88f562..81a966c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsClientFileProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsClientFileProcessor.java
@@ -13,6 +13,7 @@
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.support.annotation.WorkerThread;
+import android.support.customtabs.CustomTabsService;
 import android.support.customtabs.CustomTabsSessionToken;
 
 import org.chromium.base.Log;
@@ -35,9 +36,6 @@
 
     private static final String TAG = "CustomTabFiles";
 
-    //TODO(pshmakov): remove when client-side change lands
-    private static final int FILE_PURPOSE_TWA_SPLASH_IMAGE = 1;
-
     private final Context mContext;
     private final Lazy<SplashImageHolder> mTwaSplashImageHolder;
     private boolean mTwaSplashImageHolderCreated;
@@ -61,7 +59,7 @@
             return false;
         }
         switch (purpose) {
-            case FILE_PURPOSE_TWA_SPLASH_IMAGE:
+            case CustomTabsService.FILE_PURPOSE_TWA_SPLASH_IMAGE:
                 return receiveTwaSplashImage(session, uri);
         }
         Log.w(TAG, "Unknown FilePurpose " + purpose);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index be351a73..363abbd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -415,7 +415,7 @@
 
         // (1)
         if (!initialized) {
-            tasks.add(() -> {
+            tasks.add(UiThreadTaskTraits.BOOTSTRAP, () -> {
                 try (TraceEvent e = TraceEvent.scoped("CustomTabsConnection.initializeBrowser()")) {
                     initializeBrowser(ContextUtils.getApplicationContext());
                     ChromeBrowserInitializer.getInstance().initNetworkChangeNotifier();
@@ -426,7 +426,7 @@
 
         // (2)
         if (mayCreateSpareWebContents && !mHiddenTabHolder.hasHiddenTab()) {
-            tasks.add(() -> {
+            tasks.add(UiThreadTaskTraits.BOOTSTRAP, () -> {
                 // Temporary fix for https://crbug.com/797832.
                 // TODO(lizeb): Properly fix instead of papering over the bug, this code should
                 // not be scheduled unless startup is done. See https://crbug.com/797832.
@@ -441,7 +441,7 @@
         }
 
         // (3)
-        tasks.add(() -> {
+        tasks.add(UiThreadTaskTraits.BOOTSTRAP, () -> {
             try (TraceEvent e = TraceEvent.scoped("InitializeViewHierarchy")) {
                 WarmupManager.getInstance().initializeViewHierarchy(
                         ContextUtils.getApplicationContext(),
@@ -450,7 +450,7 @@
         });
 
         if (!initialized) {
-            tasks.add(() -> {
+            tasks.add(UiThreadTaskTraits.BOOTSTRAP, () -> {
                 try (TraceEvent e = TraceEvent.scoped("WarmupInternalFinishInitialization")) {
                     // (4)
                     Profile profile = Profile.getLastUsedProfile();
@@ -465,7 +465,7 @@
             });
         }
 
-        tasks.add(() -> notifyWarmupIsDone(uid));
+        tasks.add(UiThreadTaskTraits.BOOTSTRAP, () -> notifyWarmupIsDone(uid));
         tasks.start(false);
         mWarmupTasks = tasks;
         return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java
index 0c87f123..07eced08 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java
@@ -105,6 +105,7 @@
     }
 
 
+    @Override
     protected boolean receiveFile(@NonNull CustomTabsSessionToken sessionToken, @NonNull Uri uri,
             int purpose, @Nullable Bundle extras) {
         return mConnection.receiveFile(sessionToken, uri, purpose, extras);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java
index caaeb7ff..fb75a3fa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java
@@ -117,7 +117,7 @@
                           .setWindow(new WindowAndroid(context))
                           .setLaunchType(TabLaunchType.FROM_SPECULATIVE_BACKGROUND_CREATION)
                           .build();
-        tab.initialize(null, CustomTabDelegateFactory.createDummy(), true, false);
+        tab.initialize(null, CustomTabDelegateFactory.createDummy(), true, null, false);
 
         // Resize the webContent to avoid expensive post load resize when attaching the tab.
         Rect bounds = ExternalPrerenderHandler.estimateContentSize(context, false);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
index 7c5b70f..05f9087 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
@@ -315,7 +315,7 @@
         }
 
         tab.initialize(webContents, mCustomTabDelegateFactory.get(), false /*initiallyHidden*/,
-                false /*unfreeze*/);
+                null, false /*unfreeze*/);
 
         if (mIntentDataProvider.shouldEnableEmbeddedMediaExperience()) {
             tab.enableEmbeddedMediaExperience(true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ChainedTasks.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ChainedTasks.java
index c2614cc..96ff8e8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ChainedTasks.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ChainedTasks.java
@@ -4,7 +4,11 @@
 
 package org.chromium.chrome.browser.init;
 
+import android.util.Pair;
+
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.task.PostTask;
+import org.chromium.base.task.TaskTraits;
 
 import java.util.LinkedList;
 
@@ -18,15 +22,16 @@
  * - {@link cancel()} must be called from the UI thread.
  */
 public class ChainedTasks {
-    private LinkedList<Runnable> mTasks = new LinkedList<>();
+    private LinkedList<Pair<TaskTraits, Runnable>> mTasks = new LinkedList<>();
     private volatile boolean mFinalized;
 
     private final Runnable mRunAndPost = new Runnable() {
         @Override
         public void run() {
             if (mTasks.isEmpty()) return;
-            mTasks.pop().run();
-            ThreadUtils.postOnUiThread(this);
+            Pair<TaskTraits, Runnable> pair = mTasks.pop();
+            pair.second.run();
+            PostTask.postTask(pair.first, this);
         }
     };
 
@@ -34,9 +39,9 @@
      * Adds a task to the list of tasks to run. Cannot be called once {@link start()} has been
      * called.
      */
-    public void add(Runnable task) {
+    public void add(TaskTraits traits, Runnable task) {
         if (mFinalized) throw new IllegalStateException("Must not call add() after start()");
-        mTasks.add(task);
+        mTasks.add(new Pair<>(traits, task));
     }
 
     /**
@@ -59,16 +64,17 @@
     public void start(final boolean coalesceTasks) {
         if (mFinalized) throw new IllegalStateException("Cannot call start() several times");
         mFinalized = true;
+        if (mTasks.isEmpty()) return;
         if (coalesceTasks) {
-            ThreadUtils.runOnUiThread(new Runnable() {
+            PostTask.runOrPostTask(mTasks.peek().first, new Runnable() {
                 @Override
                 public void run() {
-                    for (Runnable task : mTasks) task.run();
+                    for (Pair<TaskTraits, Runnable> pair : mTasks) pair.second.run();
                     mTasks.clear();
                 }
             });
         } else {
-            ThreadUtils.postOnUiThread(mRunAndPost);
+            PostTask.postTask(mTasks.peek().first, mRunAndPost);
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
index 5380ce0..51a8b66 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
@@ -281,14 +281,15 @@
         // launch its required components.
         if (!delegate.startServiceManagerOnly()
                 && !ProcessInitializationHandler.getInstance().postNativeInitializationComplete()) {
-            tasks.add(() -> ProcessInitializationHandler.getInstance().initializePostNative());
+            tasks.add(UiThreadTaskTraits.BOOTSTRAP,
+                    () -> ProcessInitializationHandler.getInstance().initializePostNative());
         }
 
         if (!mNetworkChangeNotifierInitializationComplete) {
-            tasks.add(this::initNetworkChangeNotifier);
+            tasks.add(UiThreadTaskTraits.BOOTSTRAP, this::initNetworkChangeNotifier);
         }
 
-        tasks.add(() -> {
+        tasks.add(UiThreadTaskTraits.BOOTSTRAP, () -> {
             // This is not broken down as a separate task, since this:
             // 1. Should happen as early as possible
             // 2. Only submits asynchronous work
@@ -301,19 +302,20 @@
             onStartNativeInitialization();
         });
 
-        tasks.add(() -> {
+        tasks.add(UiThreadTaskTraits.BOOTSTRAP, () -> {
             if (delegate.isActivityFinishingOrDestroyed()) return;
             delegate.initializeCompositor();
         });
 
-        tasks.add(() -> {
+        tasks.add(UiThreadTaskTraits.BOOTSTRAP, () -> {
             if (delegate.isActivityFinishingOrDestroyed()) return;
             delegate.initializeState();
         });
 
-        if (!mNativeInitializationComplete) tasks.add(this::onFinishNativeInitialization);
+        if (!mNativeInitializationComplete)
+            tasks.add(UiThreadTaskTraits.DEFAULT, this::onFinishNativeInitialization);
 
-        tasks.add(() -> {
+        tasks.add(UiThreadTaskTraits.DEFAULT, () -> {
             if (delegate.isActivityFinishingOrDestroyed()) return;
             delegate.finishNativeInitialization();
         });
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
index 50298d8..f78e9cc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
@@ -221,6 +221,10 @@
         }
     }
 
+    public static void recordWebApkUninstalled() {
+        RecordHistogram.recordBooleanHistogram("WebApk.Uninstall.Browser", true);
+    }
+
     /**
      * Records the requests of Android runtime permissions which haven't been granted to Chrome when
      * Chrome is running in WebAPK runtime.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
index eb58c8c..fda57921 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
@@ -141,8 +141,8 @@
 
     @Override
     public void onBindViewHolder(NewTabPageViewHolder holder, int position, List<Object> payloads) {
-        if (payloads.isEmpty()) {
-            onBindViewHolder(holder, position);
+        if (payloads == null || payloads.isEmpty()) {
+            mRoot.onBindViewHolder(holder, position, null);
             return;
         }
 
@@ -153,7 +153,7 @@
 
     @Override
     public void onBindViewHolder(NewTabPageViewHolder holder, final int position) {
-        mRoot.onBindViewHolder(holder, position, null);
+        onBindViewHolder(holder, position, null);
     }
 
     @Override
@@ -288,10 +288,12 @@
         return RecyclerView.NO_POSITION;
     }
 
+    @VisibleForTesting
     public SectionList getSectionListForTesting() {
         return mSections;
     }
 
+    @VisibleForTesting
     public InnerNode getRootForTesting() {
         return mRoot;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
index 04958d11..db17acb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
@@ -15,7 +15,6 @@
 import org.chromium.base.CommandLine;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
-import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.task.AsyncTask;
@@ -299,7 +298,8 @@
         initializeAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
 
         // Cancel the initialization if it reaches timeout.
-        ThreadUtils.postOnUiThreadDelayed(() -> initializeAsyncTask.cancel(true), timeoutMs);
+        PostTask.postDelayedTask(
+                UiThreadTaskTraits.DEFAULT, () -> initializeAsyncTask.cancel(true), timeoutMs);
     }
 
     /**
@@ -325,7 +325,7 @@
     public static void setOnInitializeAsyncFinished(final Runnable callback, long timeoutMs) {
         sInitializeAsyncCallbacks.add(callback);
 
-        ThreadUtils.postOnUiThreadDelayed(() -> {
+        PostTask.postDelayedTask(UiThreadTaskTraits.DEFAULT, () -> {
             if (sInitializeAsyncCallbacks.remove(callback)) callback.run();
         }, sIsInitialized ? 0 : timeoutMs);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/AddExceptionPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/AddExceptionPreference.java
index d8c2b27..dd6054c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/AddExceptionPreference.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/AddExceptionPreference.java
@@ -7,7 +7,6 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.Resources;
-import android.graphics.Color;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.os.Vibrator;
@@ -41,6 +40,10 @@
     // The custom message to show in the dialog.
     private String mDialogMessage;
 
+    // The colors for the site URL EditText
+    private int mErrorColor;
+    private int mDefaultColor;
+
     /**
      * An interface to implement to get a callback when a site needs to be added.
      * @param hostname The hostname to add.
@@ -66,6 +69,8 @@
         setKey(key);
         Resources resources = getContext().getResources();
         mPrefAccentColor = ApiCompatibilityUtils.getColor(resources, R.color.pref_accent_color);
+        mErrorColor = resources.getColor(R.color.default_red);
+        mDefaultColor = resources.getColor(R.color.default_text_color);
 
         Drawable plusIcon = ApiCompatibilityUtils.getDrawable(resources, R.drawable.plus);
         plusIcon.mutate();
@@ -159,7 +164,7 @@
                 }
 
                 okButton.setEnabled(!hasError && hostname.length() > 0);
-                input.setTextColor(hasError ? Color.RED : Color.BLACK);
+                input.setTextColor(hasError ? mErrorColor : mDefaultColor);
             }
         });
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
index 939759d..d996efa4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
@@ -172,7 +172,7 @@
                        .setLaunchType(TabLaunchType.FROM_EXTERNAL_APP)
                        .build();
         mTab.initialize(WebContentsFactory.createWebContents(false, false),
-                new TabDelegateFactory(), false, false);
+                new TabDelegateFactory(), false, null, false);
         mTab.loadUrl(new LoadUrlParams(ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL));
 
         mSearchBoxDataProvider.onNativeLibraryReady(mTab);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
index b63085a..3534ea7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
@@ -23,6 +23,9 @@
  */
 public class EmptyTabObserver implements TabObserver {
     @Override
+    public void onInitialized(Tab tab, TabState tabState) {}
+
+    @Override
     public void onShown(Tab tab, @TabSelectionType int type) {}
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index 7d8c14a8..0c501975 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -295,14 +295,12 @@
      * @param window        An instance of a {@link WindowAndroid}.
      * @param launchType    Type indicating how this tab was launched.
      * @param creationState State in which the tab is created.
-     * @param frozenState   State containing information about this Tab, if it was persisted.
      * @param loadUrlParams Parameters used for a lazily loaded Tab.
      */
     @SuppressLint("HandlerLeak")
     Tab(int id, int parentId, boolean incognito, WindowAndroid window,
             @Nullable @TabLaunchType Integer launchType,
-            @Nullable @TabCreationState Integer creationState, TabState frozenState,
-            LoadUrlParams loadUrlParams) {
+            @Nullable @TabCreationState Integer creationState, LoadUrlParams loadUrlParams) {
         mId = TabIdManager.getInstance().generateValidId(id);
         mParentId = parentId;
         mIncognito = incognito;
@@ -331,16 +329,11 @@
 
         TabHelpers.initTabHelpers(this, creationState);
 
-        // Restore data from the TabState, if it existed.
-        if (frozenState != null) {
-            restoreFieldsFromState(frozenState);
+        if (mParentId == INVALID_TAB_ID || getTabModelSelector() == null
+                || getTabModelSelector().getTabById(mParentId) == null) {
+            mRootId = mId;
         } else {
-            if (mParentId == INVALID_TAB_ID || getTabModelSelector() == null
-                    || getTabModelSelector().getTabById(mParentId) == null) {
-                mRootId = mId;
-            } else {
-                mRootId = getTabModelSelector().getTabById(mParentId).getRootId();
-            }
+            mRootId = getTabModelSelector().getTabById(mParentId).getRootId();
         }
 
         mAttachStateChangeListener = new OnAttachStateChangeListener() {
@@ -362,9 +355,8 @@
      * Restores member fields from the given TabState.
      * @param state TabState containing information about this Tab.
      */
-    private void restoreFieldsFromState(TabState state) {
+    void restoreFieldsFromState(TabState state) {
         assert state != null;
-        state.restoreFields(this);
         mFrozenContentsState = state.contentsState;
         mTimestampMillis = state.timestampMillis;
         mUrl = state.getVirtualUrlFromState();
@@ -903,14 +895,17 @@
      * @param initiallyHidden   Only used if {@code webContents} is {@code null}.  Determines
      *                          whether or not the newly created {@link WebContents} will be hidden
      *                          or not.
+     * @param tabState          State containing information about this Tab, if it was persisted.
      * @param unfreeze          Whether there should be an attempt to restore state at the end of
      *                          the initialization.
      */
-    public void initialize(WebContents webContents, TabDelegateFactory delegateFactory,
-            boolean initiallyHidden, boolean unfreeze) {
+    public void initialize(WebContents webContents, @Nullable TabDelegateFactory delegateFactory,
+            boolean initiallyHidden, TabState tabState, boolean unfreeze) {
         try {
             TraceEvent.begin("Tab.initialize");
 
+            if (tabState != null) restoreFieldsFromState(tabState);
+
             mDelegateFactory = delegateFactory;
             initializeNative();
 
@@ -946,7 +941,7 @@
             if (mTimestampMillis == INVALID_TIMESTAMP) {
                 mTimestampMillis = System.currentTimeMillis();
             }
-
+            for (TabObserver observer : mObservers) observer.onInitialized(this, tabState);
             TraceEvent.end("Tab.initialize");
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java
index 36bd42b..ea03941a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAssociatedApp.java
@@ -38,6 +38,11 @@
         super(tab);
         tab.addObserver(new EmptyTabObserver() {
             @Override
+            public void onInitialized(Tab tab, TabState tabState) {
+                if (tabState != null) setAppId(tabState.openerAppId);
+            }
+
+            @Override
             public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) {
                 // Clear the app association if the user navigated to a different page from the
                 // omnibox.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBuilder.java
index 3e16e24..c8f18054 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBuilder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBuilder.java
@@ -20,7 +20,7 @@
     private WindowAndroid mWindow;
     private Integer mLaunchType;
     private Integer mCreationType;
-    private TabState mFrozenState;
+    private boolean mFromFrozenState;
     private LoadUrlParams mLoadUrlParams;
 
     /**
@@ -76,18 +76,18 @@
     public Tab build() {
         // Pre-condition check
         if (mCreationType != null) {
-            if (mFrozenState == null) {
+            if (!mFromFrozenState) {
                 assert mCreationType != TabCreationState.FROZEN_ON_RESTORE;
             } else {
                 assert mLaunchType == TabLaunchType.FROM_RESTORE
                         && mCreationType == TabCreationState.FROZEN_ON_RESTORE;
             }
         } else {
-            if (mFrozenState != null) assert mLaunchType == TabLaunchType.FROM_RESTORE;
+            if (mFromFrozenState) assert mLaunchType == TabLaunchType.FROM_RESTORE;
         }
 
-        return new Tab(mId, mParentId, mIncognito, mWindow, mLaunchType, mCreationType,
-                mFrozenState, mLoadUrlParams);
+        return new Tab(
+                mId, mParentId, mIncognito, mWindow, mLaunchType, mCreationType, mLoadUrlParams);
     }
 
     private TabBuilder setCreationType(@TabCreationState int type) {
@@ -95,8 +95,8 @@
         return this;
     }
 
-    private TabBuilder setFrozenState(TabState frozenState) {
-        mFrozenState = frozenState;
+    private TabBuilder setFromFrozenState(boolean frozenState) {
+        mFromFrozenState = frozenState;
         return this;
     }
 
@@ -109,14 +109,12 @@
      * Creates a TabBuilder for a new, "frozen" tab from a saved state. This can be used for
      * background tabs restored on cold start that should be loaded when switched to. initialize()
      * needs to be called afterwards to complete the second level initialization.
-     * @param state Frozen state from which the tab will be created.
      */
-    public static TabBuilder createFromFrozenState(TabState state) {
-        assert state != null;
+    public static TabBuilder createFromFrozenState() {
         return new TabBuilder()
                 .setLaunchType(TabLaunchType.FROM_RESTORE)
                 .setCreationType(TabCreationState.FROZEN_ON_RESTORE)
-                .setFrozenState(state);
+                .setFromFrozenState(true);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHelpers.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHelpers.java
index b1a46aa..9a866569 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHelpers.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHelpers.java
@@ -11,8 +11,6 @@
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
 import org.chromium.chrome.browser.media.ui.MediaSessionTabHelper;
 import org.chromium.chrome.browser.tab.TabUma.TabCreationState;
-import org.chromium.components.content_capture.ContentCaptureFeatures;
-import org.chromium.components.content_capture.ContentCaptureReceiverManager;
 import org.chromium.content_public.browser.SelectionPopupController;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsAccessibility;
@@ -67,8 +65,5 @@
         // For browser tabs, we want to set accessibility focus to the page when it loads. This
         // is not the default behavior for embedded web views.
         WebContentsAccessibility.fromWebContents(webContents).setShouldFocusOnPageLoad(true);
-
-        // The created object is held by native side.
-        if (ContentCaptureFeatures.isEnabled()) ContentCaptureReceiverManager.create(webContents);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java
index 30a668f..15b5c22 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java
@@ -21,6 +21,14 @@
  */
 public interface TabObserver {
     /**
+     * Called when a {@link Tab} finished initialization. The {@link TabState} contains,
+     * if not {@code null}, various states that a Tab should restore itself from.
+     * @param tab The notifying {@link Tab}.
+     * @param tabState {@link TabState} to restore tab's state from if not {@code null}.
+     */
+    void onInitialized(Tab tab, TabState tabState);
+
+    /**
      * Called when a {@link Tab} is shown.
      * @param tab The notifying {@link Tab}.
      * @param type Specifies how the tab was selected.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java
index fd25a66..01fe3ca2f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabState.java
@@ -371,16 +371,6 @@
         return tabState;
     }
 
-    /**
-     * Restores fields of a Tab from this TabState.
-     * @param tab Tab to restore.
-     */
-    public void restoreFields(Tab tab) {
-        // TODO(jinsukkim): Handle this with a new TabObserver method.
-        TabAssociatedApp.from(tab).setAppId(openerAppId);
-        TabThemeColorHelper.get(tab).updateFromTabState(this);
-    }
-
     /** Returns an object representing the state of the Tab's WebContents. */
     private static WebContentsState getWebContentsState(Tab tab) {
         if (tab.getFrozenContentsState() != null) return tab.getFrozenContentsState();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java
index 4ccbb1f..17db2ae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabThemeColorHelper.java
@@ -67,12 +67,6 @@
                 mTab.getContext().getResources(), mTab.isIncognito());
     }
 
-    void updateFromTabState(TabState state) {
-        mIsDefaultColorUsed = !state.hasThemeColor();
-        mColor = mIsDefaultColorUsed ? getDefaultColor() : state.getThemeColor();
-        updateIfNeeded(false);
-    }
-
     /**
      * Calculate the theme color based on if the page is native, the theme color changed, etc.
      * @param didWebContentsThemeColorChange If the theme color of the web contents is known to have
@@ -152,6 +146,16 @@
     // TabObserver
 
     @Override
+    public void onInitialized(Tab tab, TabState tabState) {
+        if (tabState == null) return;
+
+        // Update from TabState.
+        mIsDefaultColorUsed = !tabState.hasThemeColor();
+        mColor = mIsDefaultColorUsed ? getDefaultColor() : tabState.getThemeColor();
+        updateIfNeeded(false);
+    }
+
+    @Override
     public void onSSLStateUpdated(Tab tab) {
         updateIfNeeded(false);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
index dd75d91..1af4ded2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
@@ -136,7 +136,7 @@
                               .setWindow(mNativeWindow)
                               .setLaunchType(type)
                               .build();
-                tab.initialize(webContents, delegateFactory, !openInForeground, false);
+                tab.initialize(webContents, delegateFactory, !openInForeground, null, false);
                 TabParentIntent.from(tab).set(parentIntent);
                 webContents.resumeLoadingCreatedWebContents();
             } else if (!openInForeground && SysUtils.isLowEndDevice()) {
@@ -149,7 +149,7 @@
                               .setWindow(mNativeWindow)
                               .setLaunchType(type)
                               .build();
-                tab.initialize(null, delegateFactory, !openInForeground, false);
+                tab.initialize(null, delegateFactory, !openInForeground, null, false);
             } else {
                 tab = TabBuilder.createLiveTab(!openInForeground)
                               .setParentId(parentId)
@@ -158,7 +158,7 @@
                               .setLaunchType(type)
                               .build();
 
-                tab.initialize(null, delegateFactory, !openInForeground, false);
+                tab.initialize(null, delegateFactory, !openInForeground, null, false);
                 tab.loadUrl(loadUrlParams);
             }
             TabRedirectHandler.from(tab).updateIntent(intent);
@@ -195,7 +195,7 @@
                           .setWindow(mNativeWindow)
                           .setLaunchType(type)
                           .build();
-        tab.initialize(webContents, delegateFactory, !openInForeground, false);
+        tab.initialize(webContents, delegateFactory, !openInForeground, null, false);
         mTabModel.addTab(tab, position, type);
         return true;
     }
@@ -291,7 +291,7 @@
 
     @Override
     public Tab createFrozenTab(TabState state, int id, int index) {
-        Tab tab = TabBuilder.createFromFrozenState(state)
+        Tab tab = TabBuilder.createFromFrozenState()
                           .setId(id)
                           .setParentId(state.parentId)
                           .setIncognito(state.isIncognito())
@@ -299,7 +299,7 @@
                           .build();
         boolean selectTab = mOrderController.willOpenInForeground(TabLaunchType.FROM_RESTORE,
                 state.isIncognito());
-        tab.initialize(null, createDefaultTabDelegateFactory(), !selectTab, false);
+        tab.initialize(null, createDefaultTabDelegateFactory(), !selectTab, state, false);
         assert state.isIncognito() == mIncognito;
         mTabModel.addTab(tab, index, TabLaunchType.FROM_RESTORE);
         return tab;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java
index 34d92d8..1f228145 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java
@@ -54,7 +54,7 @@
      */
     @Override
     public Tab createFrozenTab(TabState state, int id, int index) {
-        return TabBuilder.createFromFrozenState(state)
+        return TabBuilder.createFromFrozenState()
                 .setId(id)
                 .setIncognito(state.isIncognito())
                 .build();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
index 140278f..4f8cf621 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -1628,6 +1628,9 @@
             ApiCompatibilityUtils.setImageTintList(mExperimentalButton, tint);
         }
 
+        // TODO(amaralp): Have the LocationBar listen to tint changes.
+        if (mLocationBar != null) mLocationBar.updateVisualsForState();
+
         if (mLayoutUpdateHost != null) mLayoutUpdateHost.requestUpdate();
     }
 
@@ -2350,8 +2353,6 @@
         }
 
         if (mVisualState == VisualState.BRAND_COLOR && !visualStateChanged) {
-            boolean useLightToolbarDrawables =
-                    ColorUtils.shouldUseLightForegroundOnBackground(currentPrimaryColor);
             boolean unfocusedLocationBarUsesTransparentBg =
                     !ColorUtils.shouldUseOpaqueTextboxBackground(currentPrimaryColor);
             if (unfocusedLocationBarUsesTransparentBg != mUnfocusedLocationBarUsesTransparentBg) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java
index 231b73a4..c4eb2a7c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkServiceClient.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.webapps;
 
+import android.annotation.TargetApi;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
@@ -137,6 +138,27 @@
                 ContextUtils.getApplicationContext(), webApkPackage, connectionCallback);
     }
 
+    /** Finishes and removes the WebAPK's task. */
+    @TargetApi(Build.VERSION_CODES.M)
+    public void finishAndRemoveTaskSdk23(final WebApkActivity webApkActivity) {
+        final ApiUseCallback connectionCallback = new ApiUseCallback() {
+            @Override
+            public void useApi(IWebApkApi api) throws RemoteException {
+                if (webApkActivity.isActivityFinishingOrDestroyed()) return;
+
+                if (!api.finishAndRemoveTaskSdk23()) {
+                    // If |webApkActivity| is not the root of the task, hopefully the activities
+                    // below this one will close themselves.
+                    webApkActivity.finish();
+                }
+            }
+        };
+
+        String webApkPackage = webApkActivity.getWebApkPackageName();
+        mConnectionManager.connect(
+                ContextUtils.getApplicationContext(), webApkPackage, connectionCallback);
+    }
+
     /** Disconnects all the connections to WebAPK services. */
     public static void disconnectAll() {
         if (sInstance == null) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index de79ee60..647bdfc1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -48,7 +48,6 @@
 import org.chromium.chrome.browser.fullscreen.FullscreenOptions;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabBuilder;
 import org.chromium.chrome.browser.tab.TabDelegateFactory;
 import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.browser.tab.TabState;
@@ -90,8 +89,6 @@
     private static final String HISTOGRAM_NAVIGATION_STATUS = "Webapp.NavigationStatus";
     private static final long MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL = 1000;
 
-    private static final String BUNDLE_TAB_ID = "tabId";
-
     private static final int ENTER_IMMERSIVE_MODE_DELAY_MILLIS = 300;
     private static final int RESTORE_IMMERSIVE_MODE_DELAY_MILLIS = 3000;
     static final int IMMERSIVE_MODE_UI_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
@@ -389,18 +386,8 @@
     }
 
     @Override
-    protected Tab restoreTab(Bundle savedInstanceState) {
-        int tabId = getSavedInstanceState().getInt(BUNDLE_TAB_ID, Tab.INVALID_TAB_ID);
-
-        if (tabId == Tab.INVALID_TAB_ID) return null;
-
-        TabState tabState = TabState.restoreTabState(getActivityDirectory(), tabId);
-        if (tabState == null) return null;
-
-        return TabBuilder.createFromFrozenState(tabState)
-                .setId(tabId)
-                .setWindow(getWindowAndroid())
-                .build();
+    protected TabState restoreTabState(Bundle savedInstanceState, int tabId) {
+        return TabState.restoreTabState(getActivityDirectory(), tabId);
     }
 
     @Override
@@ -709,7 +696,16 @@
                         if (getActivityTab().canGoBack()) {
                             getActivityTab().goBack();
                         } else {
-                            ApiCompatibilityUtils.finishAndRemoveTask(WebappActivity.this);
+                            if (mWebappInfo.isSplashProvidedByWebApk()) {
+                                // We need to call into WebAPK to finish activity stack because:
+                                // 1) WebApkActivity is not the root of the task.
+                                // 2) The activity stack no longer has focus and thus cannot rely on
+                                //    the client's Activity#onResume() behaviour.
+                                WebApkServiceClient.getInstance().finishAndRemoveTaskSdk23(
+                                        (WebApkActivity) WebappActivity.this);
+                            } else {
+                                ApiCompatibilityUtils.finishAndRemoveTask(WebappActivity.this);
+                            }
                         }
                     }
                 }, MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
index 48e8549..d09aee0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -321,6 +321,14 @@
         }
 
         /**
+         * @return Whether this content owns the scrim lifecycle. If false, a default scrim will
+         *         be displayed behind the sheet when this content is shown.
+         */
+        default boolean hasCustomScrimLifecycle() {
+            return false;
+        }
+
+        /**
          * @return The resource id of the content description for the bottom sheet. This is
          *         generally the name of the feature/content that is showing. 'Swipe down to close.'
          *         will be automatically appended after the content description.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java
index ab95312..da49bfb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java
@@ -174,17 +174,32 @@
         mBottomSheet.addObserver(new EmptyBottomSheetObserver() {
             @Override
             public void onSheetOpened(@StateChangeReason int reason) {
+                if (mBottomSheet.getCurrentSheetContent() != null
+                        && mBottomSheet.getCurrentSheetContent().hasCustomScrimLifecycle()) {
+                    return;
+                }
+
                 scrim.showScrim(mScrimParams);
                 scrim.setViewAlpha(0);
             }
 
             @Override
             public void onSheetClosed(@StateChangeReason int reason) {
+                if (mBottomSheet.getCurrentSheetContent() != null
+                        && mBottomSheet.getCurrentSheetContent().hasCustomScrimLifecycle()) {
+                    return;
+                }
+
                 scrim.hideScrim(false);
             }
 
             @Override
             public void onTransitionPeekToHalf(float transitionFraction) {
+                if (mBottomSheet.getCurrentSheetContent() != null
+                        && mBottomSheet.getCurrentSheetContent().hasCustomScrimLifecycle()) {
+                    return;
+                }
+
                 // TODO(mdjones): This event should not occur after the bottom sheet is closed.
                 if (scrim.getVisibility() == View.VISIBLE) {
                     scrim.setViewAlpha(transitionFraction);
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_am.xtb b/chrome/android/java/strings/translations/android_chrome_strings_am.xtb
index c1b685e..dd3d6007 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_am.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_am.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">የዚህን ገጽ የመስመር ውጭ ቅጂ በመመልከት ላይ</translation>
 <translation id="2546283357679194313">ኩኪዎች እና የጣቢያ ውሂብ</translation>
 <translation id="2567385386134582609">ምስል</translation>
+<translation id="257088987046510401">ገፅታዎች </translation>
 <translation id="2570922361219980984">የአካባቢ መዳረሻ እንዲሁም ለዚህ መሣሪያ ጠፍቷል። በ<ph name="BEGIN_LINK" />Android ቅንብሮች<ph name="END_LINK" /> ውስጥ ያብሩት።</translation>
 <translation id="257931822824936280">ተዘርግቷል - ለመሰብሰብ ጠቅ ያድርጉ</translation>
 <translation id="2581165646603367611">ይሄ Chrome አስፈላጊ ናቸው ብሎ የማያስባቸውን ኩኪዎች፣ መሸጎጫ እና ሌሎች ጣቢያዎች ያጸዳል።</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">የአሁኑን ገጽ ዳግም ጫን</translation>
 <translation id="3445014427084483498">ልክ አሁን</translation>
 <translation id="3452612588551937789">የእርስዎን ዕልባቶች፣ የይለፍ ቃላት፣ ታሪክ እና ሌሎች ቅንብሮችን በሁሉም መሣሪያዎችዎ ላይ ለማግኘት በGoogle መለያዎ ይግቡ።</translation>
+<translation id="3478363558367712427">የፍለጋ ፕሮግራምዎን መምረጥ ይችላሉ</translation>
 <translation id="3492207499832628349">አዲስ ማንነት የማያሳውቅ ትር</translation>
 <translation id="3493531032208478708">ስለሚጠቆም ይዘት <ph name="BEGIN_LINK" />የበለጠ ለመረዳት<ph name="END_LINK" /></translation>
 <translation id="3513704683820682405">ትክክለኛ እውነታ</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb
index b34e9bf..806c61ba 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ar.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">عرض نسخة بلا اتصال من هذه الصفحة</translation>
 <translation id="2546283357679194313">ملفات تعريف الارتباط وبيانات المواقع</translation>
 <translation id="2567385386134582609">صورة</translation>
+<translation id="257088987046510401">المظاهر</translation>
 <translation id="2570922361219980984">‏الوصول إلى الموقع الجغرافي متوقف لهذا الجهاز أيضًا. يمكنك تفعليه في <ph name="BEGIN_LINK" />إعدادات Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">تم التوسيع - انقر للتصغير.</translation>
 <translation id="2581165646603367611">‏سيؤدي هذا إلى مسح ملفات تعريف الارتباط وذاكرة التخزين المؤقت والبيانات الأخرى للمواقع التي لا يعتقد Chrome أنها مهمة.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">إعادة تحميل الصفحة الحالية</translation>
 <translation id="3445014427084483498">للتو</translation>
 <translation id="3452612588551937789">‏سجّل الدخول إلى حسابك على Google للحصول على الإشارات المرجعية والسجلّ وكلمات المرور والإعدادات الأخرى واستخدامها على جميع أجهزتك.</translation>
+<translation id="3478363558367712427">يمكنك استخدام محرّك بحث آخر.</translation>
 <translation id="3492207499832628349">علامة تبويب جديدة للتصفح المتخفي </translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />مزيد من المعلومات<ph name="END_LINK" /> حول المحتوى المقترح</translation>
 <translation id="3513704683820682405">الواقع المعزّز</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_bg.xtb b/chrome/android/java/strings/translations/android_chrome_strings_bg.xtb
index 5ffc85e..db0bc540 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_bg.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_bg.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Преглеждате офлайн копие на страницата</translation>
 <translation id="2546283357679194313">„Бисквитки“ и данни за сайтове</translation>
 <translation id="2567385386134582609">ИЗОБРАЖЕНИЕ</translation>
+<translation id="257088987046510401">Теми</translation>
 <translation id="2570922361219980984">Достъпът до местоположението е изключен и за това устройство. Включете го от <ph name="BEGIN_LINK" />настройките на Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Разгънато – кликнете за свиване.</translation>
 <translation id="2581165646603367611">Така ще се изчистят „бисквитките“, кешът и другата информация от сайтове, която не е важна за Chrome.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">Презареждане на текущата страница</translation>
 <translation id="3445014427084483498">Току-що</translation>
 <translation id="3452612588551937789">Влезте с профила си в Google, за да получите своите отметки, история, пароли и други настройки на всичките си устройства.</translation>
+<translation id="3478363558367712427">Можете да изберете търсещата си машина</translation>
 <translation id="3492207499832628349">Нов раздел „инкогнито“</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Научете повече<ph name="END_LINK" /> за предложеното съдържание</translation>
 <translation id="3513704683820682405">Обогатена реалност</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_bn.xtb b/chrome/android/java/strings/translations/android_chrome_strings_bn.xtb
index 09fc29d..60f76dc 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_bn.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_bn.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">এই পৃষ্ঠার একটি অফলাইন অনুলিপি দেখছেন</translation>
 <translation id="2546283357679194313">কুকিজ ও সাইট ডেটা</translation>
 <translation id="2567385386134582609">ছবি</translation>
+<translation id="257088987046510401">থিমসমূহ</translation>
 <translation id="2570922361219980984">এই ডিভাইসেও লোকেশন অ্যাক্সেস বন্ধ আছে। চালু করতে <ph name="BEGIN_LINK" />Android সেটিংসে<ph name="END_LINK" /> যান।</translation>
 <translation id="257931822824936280">প্রসারিত - সঙ্কুচিত করতে ক্লিক করুন৷</translation>
 <translation id="2581165646603367611">এটা কুকিজ, ক্যাশে, এবং সাইটের সেই সব ডেটা যা Chrome গুরুত্বপূর্ণ মনে করে না সেগুলিকে সাফ করবে।</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ca.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ca.xtb
index b76c673..b11e0ac5 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ca.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ca.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">S'està mostrant una còpia sense connexió d'aquesta pàgina</translation>
 <translation id="2546283357679194313">Dades de llocs web i galetes</translation>
 <translation id="2567385386134582609">IMATGE</translation>
+<translation id="257088987046510401">Temes</translation>
 <translation id="2570922361219980984">L'accés a la ubicació també està desactivat en aquest dispositiu. Activa'l a la <ph name="BEGIN_LINK" />configuració d'Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Vista desplegada (feu clic per replegar-la)</translation>
 <translation id="2581165646603367611">Amb aquesta acció, se suprimiran les galetes, la memòria cau i altres dades de llocs que Chrome no consideri importants.</translation>
@@ -328,6 +329,7 @@
 <translation id="3443221991560634068">Torna a carregar la pàgina actual</translation>
 <translation id="3445014427084483498">Ara mateix</translation>
 <translation id="3452612588551937789">Inicia la sessió amb el compte de Google per tenir les adreces d'interès, l'historial, les contrasenyes i altres opcions de configuració en tots els dispositius.</translation>
+<translation id="3478363558367712427">Pots triar el motor de cerca que prefereixis</translation>
 <translation id="3492207499832628349">Pestanya d'incògnit nova</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Més informació<ph name="END_LINK" /> sobre el contingut suggerit</translation>
 <translation id="3513704683820682405">Realitat augmentada</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_cs.xtb b/chrome/android/java/strings/translations/android_chrome_strings_cs.xtb
index 26fcdf4..a7fe741 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_cs.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_cs.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Prohlížíte offline kopii stránky</translation>
 <translation id="2546283357679194313">Soubory cookie a data webových stránek</translation>
 <translation id="2567385386134582609">OBRÁZEK</translation>
+<translation id="257088987046510401">Motivy</translation>
 <translation id="2570922361219980984">Přístup k poloze je vypnut také v tomto zařízení. Zapnete jej v <ph name="BEGIN_LINK" />Nastavení Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Rozbaleno – kliknutím sbalíte</translation>
 <translation id="2581165646603367611">Tímto vymažete soubory cookie, mezipaměť a další data webů, která Chrome považuje za nedůležitá.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">Znovu načíst aktuální stránku</translation>
 <translation id="3445014427084483498">Právě teď</translation>
 <translation id="3452612588551937789">Přihlaste se pomocí účtu Google a získejte záložky, historii, hesla a další nastavení do všech svých zařízení.</translation>
+<translation id="3478363558367712427">Můžete si vybrat vyhledávač</translation>
 <translation id="3492207499832628349">Nová anonymní karta</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Další informace<ph name="END_LINK" /> o navrhovaném obsahu</translation>
 <translation id="3513704683820682405">Rozšířená realita</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_da.xtb b/chrome/android/java/strings/translations/android_chrome_strings_da.xtb
index ad2c4c9e..d11e3ac0 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_da.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_da.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Du ser en offlinekopi af denne side</translation>
 <translation id="2546283357679194313">Cookies og websitedata</translation>
 <translation id="2567385386134582609">BILLEDE</translation>
+<translation id="257088987046510401">Temaer</translation>
 <translation id="2570922361219980984">Placeringsadgang er også deaktiveret for denne enhed. Aktivér det under <ph name="BEGIN_LINK" />indstillinger for Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Udvidet – klik for at skjule.</translation>
 <translation id="2581165646603367611">Dette rydder cookies, cache og andre data fra websites, som ikke er vigtige ifølge Chrome.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_de.xtb b/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
index fe473a8..66d196e 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Eine Offline-Kopie dieser Seite wird angezeigt.</translation>
 <translation id="2546283357679194313">Cookies und Websitedaten</translation>
 <translation id="2567385386134582609">BILD</translation>
+<translation id="257088987046510401">Designs</translation>
 <translation id="2570922361219980984">Der Standortzugriff ist für dieses Gerät ebenfalls deaktiviert. Sie können ihn in den <ph name="BEGIN_LINK" />Android-Einstellungen<ph name="END_LINK" /> aktivieren.</translation>
 <translation id="257931822824936280">Maximiert – zum Minimieren klicken</translation>
 <translation id="2581165646603367611">Alle Cookies, der Cache und andere Daten von Websites, die Chrome nicht für wichtig hält, werden gelöscht.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_el.xtb b/chrome/android/java/strings/translations/android_chrome_strings_el.xtb
index 11ee99f..fa77ac6 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_el.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_el.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Προβολή ενός αντιγράφου αυτής της σελίδας εκτός σύνδεσης</translation>
 <translation id="2546283357679194313">Cookie και δεδομένα ιστότοπου</translation>
 <translation id="2567385386134582609">ΕΙΚΟΝΑ</translation>
+<translation id="257088987046510401">Θέματα</translation>
 <translation id="2570922361219980984">Η πρόσβαση στην Τοποθεσία είναι απενεργοποιημένη επίσης γι' αυτήν τη συσκευή. Ενεργοποιήστε τη στις <ph name="BEGIN_LINK" />Ρυθμίσεις Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Αναπτυγμένη - Κάντε κλικ για σύμπτυξη</translation>
 <translation id="2581165646603367611">Αυτό θα διαγράψει τα cookie, την κρυφή μνήμη και άλλα δεδομένα ιστοτόπων που το Chrome θεωρεί ότι δεν είναι σημαντικά.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_en-GB.xtb b/chrome/android/java/strings/translations/android_chrome_strings_en-GB.xtb
index 213973a..7cf6aad 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_en-GB.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_en-GB.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Viewing an offline copy of this page</translation>
 <translation id="2546283357679194313">Cookies and site data</translation>
 <translation id="2567385386134582609">IMAGE</translation>
+<translation id="257088987046510401">Themes</translation>
 <translation id="2570922361219980984">Location access is also off for this device. Turn it on in <ph name="BEGIN_LINK" />Android Settings<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Expanded – click to collapse.</translation>
 <translation id="2581165646603367611">This will clear cookies, cache and other data of sites Chrome doesn't think is important.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">Reload the current page</translation>
 <translation id="3445014427084483498">Just now</translation>
 <translation id="3452612588551937789">Sign in with your Google Account to get your bookmarks, history, passwords and other settings on all your devices.</translation>
+<translation id="3478363558367712427">You can choose your search engine</translation>
 <translation id="3492207499832628349">New incognito tab</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Find out more<ph name="END_LINK" /> about suggested content</translation>
 <translation id="3513704683820682405">Augmented Reality</translation>
@@ -850,7 +852,7 @@
 <translation id="723171743924126238">Select images</translation>
 <translation id="7243308994586599757">Options available near bottom of the screen</translation>
 <translation id="7250468141469952378"><ph name="ITEM_COUNT" /> selected</translation>
-<translation id="7253272406652746122">Add a Google Accountfrom the Accounts page in your device’s Settings app.</translation>
+<translation id="7253272406652746122">Add a Google Account from the Accounts page in your device’s Settings app.</translation>
 <translation id="7274013316676448362">Blocked site</translation>
 <translation id="7290209999329137901">Rename unavailable</translation>
 <translation id="7291387454912369099">Assistant Triggered Checkout</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb b/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb
index ae149826..ecade44 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_es-419.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Visualizando una copia sin conexión de la página</translation>
 <translation id="2546283357679194313">Datos de sitios y cookies</translation>
 <translation id="2567385386134582609">IMAGEN</translation>
+<translation id="257088987046510401">Temas</translation>
 <translation id="2570922361219980984">El acceso a la ubicación también está desactivado en este dispositivo. Actívalo en la <ph name="BEGIN_LINK" />Configuración de Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Expandido; haz clic para contraer.</translation>
 <translation id="2581165646603367611">Esta acción borrará la caché, cookies y otros datos de sitios que Chrome no considera importantes.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_es.xtb b/chrome/android/java/strings/translations/android_chrome_strings_es.xtb
index 7b4dc42..4d54a79 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_es.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_es.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Viendo una copia sin conexión de esta página</translation>
 <translation id="2546283357679194313">Cookies y datos de sitios</translation>
 <translation id="2567385386134582609">IMAGEN</translation>
+<translation id="257088987046510401">Temas</translation>
 <translation id="2570922361219980984">El acceso a la ubicación también está desactivado en este dispositivo. Actívalo en los <ph name="BEGIN_LINK" />Ajustes de Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Ampliado (hacer clic para contraer)</translation>
 <translation id="2581165646603367611">Se borrarán las cookies, la caché y otros datos de los sitios web que Chrome no considere importantes.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_et.xtb b/chrome/android/java/strings/translations/android_chrome_strings_et.xtb
index 80bd1a6..f090110e 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_et.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_et.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Kuvatakse on lehe võrguühenduseta koopia</translation>
 <translation id="2546283357679194313">Küpsised ja saidiandmed</translation>
 <translation id="2567385386134582609">KUJUTIS</translation>
+<translation id="257088987046510401">Teemad</translation>
 <translation id="2570922361219980984">Ka juurdepääs asukohale on selle seadme puhul välja lülitatud. Lülitage see sisse <ph name="BEGIN_LINK" />Androidi seadetes<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Laiendatud – ahendamiseks klõpsake.</translation>
 <translation id="2581165646603367611">See tühjendab vahemälu, kustutab küpsised ja muud andmed, mis pärinevad Chrome'i arvates ebatähtsatelt saitidelt.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_fa.xtb b/chrome/android/java/strings/translations/android_chrome_strings_fa.xtb
index b6cfd7a..e1fc0a9 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_fa.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_fa.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">مشاهده یک کپی آفلاین از این صفحه</translation>
 <translation id="2546283357679194313">کوکی‌ها و داده‌های سایت</translation>
 <translation id="2567385386134582609">تصویر</translation>
+<translation id="257088987046510401">طرح‌‌های قسمت</translation>
 <translation id="2570922361219980984">‏دسترسی به مکان برای این دستگاه نیز خاموش است. آن را در <ph name="BEGIN_LINK" />تنظیمات Android<ph name="END_LINK" /> روشن کنید.</translation>
 <translation id="257931822824936280">بزرگ‌شده - برای کوچک کردن کلیک کنید.</translation>
 <translation id="2581165646603367611">‏این کار کوکی‌ها، حافظه پنهان و داده‌های دیگر سایت‌ها را که از نظر Chrome مهم نیست پاک می‌کند.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">تازه‌سازی صفحه کنونی</translation>
 <translation id="3445014427084483498">هم‌اکنون</translation>
 <translation id="3452612588551937789">‏برای دسترسی به نشانک‌ها، گذرواژه‌ها، سابقه و تنظیمات دیگر در همه دستگاه‌هایتان، به سیستم حساب Google خود وارد شوید.</translation>
+<translation id="3478363558367712427">می‌توانید موتور جستجویتان را انتخاب کنید</translation>
 <translation id="3492207499832628349">برگه ناشناس جدید</translation>
 <translation id="3493531032208478708">درباره محتوای پیشنهادی <ph name="BEGIN_LINK" />بیشتر بدانید<ph name="END_LINK" /></translation>
 <translation id="3513704683820682405">واقعیت افزوده</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_fi.xtb b/chrome/android/java/strings/translations/android_chrome_strings_fi.xtb
index 9bcc8b4..7a061f3 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_fi.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_fi.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Näkyvissä on sivun offline-versio.</translation>
 <translation id="2546283357679194313">Evästeet ja sivustotiedot</translation>
 <translation id="2567385386134582609">KUVA</translation>
+<translation id="257088987046510401">Teemat</translation>
 <translation id="2570922361219980984">Sijainti on poissa käytöstä myös tällä laitteella. Voit ottaa sen käyttöön <ph name="BEGIN_LINK" />Android-asetuksista<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Laajennettu – tiivistä klikkaamalla.</translation>
 <translation id="2581165646603367611">Evästeet, välimuisti ja muut Chromen vähemmän tärkeinä pitämät sivustotiedot poistetaan.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_fil.xtb b/chrome/android/java/strings/translations/android_chrome_strings_fil.xtb
index 37fc420b..e6950f1 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_fil.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_fil.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Tinitingnan ang isang offline na kopya ng page na ito</translation>
 <translation id="2546283357679194313">Cookies at data ng site</translation>
 <translation id="2567385386134582609">LARAWAN</translation>
+<translation id="257088987046510401">Mga tema</translation>
 <translation id="2570922361219980984">Naka-off din ang access sa lokasyon para sa device na ito. I-on ito sa <ph name="BEGIN_LINK" />Mga Setting ng Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Pinalawak - i-click upang i-collapse.</translation>
 <translation id="2581165646603367611">Iki-clear nito ang cookies, cache at iba pang data ng mga site na sa tingin ng Chrome ay hindi mahalaga.</translation>
@@ -262,6 +263,7 @@
 <translation id="290376772003165898">Hindi nakasalin ang page sa <ph name="LANGUAGE" />?</translation>
 <translation id="2910701580606108292">Magtanong bago payagan ang mga site na mag-play ng pinoprotektahang content</translation>
 <translation id="2913331724188855103">Payagan ang mga site na mag-save at magbasa ng data ng cookie (inirerekomenda)</translation>
+<translation id="2923908459366352541">Di-wasto ang pangalan</translation>
 <translation id="2932150158123903946">Storage ng <ph name="APP_NAME" /> sa Google</translation>
 <translation id="2956410042958133412">Pinapamahalaan ang account na ito ng <ph name="PARENT_NAME_1" /> at <ph name="PARENT_NAME_2" />.</translation>
 <translation id="2960796085439532066">Copyright <ph name="YEAR" /> Google Inc. Nakalaan ang lahat ng karapatan.</translation>
@@ -328,6 +330,7 @@
 <translation id="3443221991560634068">I-reload ang kasalukuyang page</translation>
 <translation id="3445014427084483498">Ngayon Lang</translation>
 <translation id="3452612588551937789">Mag-sign in gamit ang Google Account mo para makuha ang iyong mga bookmark, history, password at iba pang mga setting sa lahat ng device mo.</translation>
+<translation id="3478363558367712427">Maaari mong piliin ang iyong search engine</translation>
 <translation id="3492207499832628349">Bagong tab na incognito</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Matuto pa<ph name="END_LINK" /> tungkol sa iminumungkahing content</translation>
 <translation id="3513704683820682405">Augmented Reality</translation>
@@ -363,6 +366,7 @@
 <translation id="3745176700485982507">Makikita sa page na ito ang mga link sa iyong mga paboritong website</translation>
 <translation id="3771001275138982843">Hindi ma-download ang update</translation>
 <translation id="3773755127849930740"><ph name="BEGIN_LINK" />I-on ang Bluetooth<ph name="END_LINK" /> upang payagan ang pagpapares</translation>
+<translation id="3775705724665058594">Ipadala sa iyong mga device</translation>
 <translation id="3778956594442850293">Idinagdag sa Home screen</translation>
 <translation id="3781011235031427080">Nakabukas sa kalahating bahagi sa ibaba ng screen ang higit pang tulad nito</translation>
 <translation id="3789841737615482174">Mag-install</translation>
@@ -528,6 +532,7 @@
 <translation id="4958708863221495346">Ibinabahagi ng <ph name="URL_OF_THE_CURRENT_TAB" /> ang iyong screen</translation>
 <translation id="4961107849584082341">Isalin ang page na ito sa anumang wika</translation>
 <translation id="4961700429721424617">Nagsa-sign out ka sa account na pinamamahalaan ng <ph name="MANAGED_DOMAIN" />. Ide-delete nito ang data mo sa Chrome mula sa device na ito, ngunit mananatili ang data mo sa iyong Google account.</translation>
+<translation id="4970824347203572753">Hindi available sa iyong lokasyon</translation>
 <translation id="497421865427891073">Sumulong</translation>
 <translation id="4988210275050210843">Nagda-download ng file (<ph name="MEGABYTES" />).</translation>
 <translation id="4988526792673242964">Mga Page</translation>
@@ -597,6 +602,7 @@
 <translation id="5487521232677179737">I-clear ang data</translation>
 <translation id="5494752089476963479">I-block ang mga ad sa mga site na nagpapakita ng mga nakakasagabal o nakakapanlinlang na ad</translation>
 <translation id="5497272504048921382">Mga binuksang tab</translation>
+<translation id="5500777121964041360">Maaaring hindi available sa iyong lokasyon</translation>
 <translation id="550684401320795253">Ina-update ang Chrome...</translation>
 <translation id="5512137114520586844">Pinapamahalaan ang account na ito ng <ph name="PARENT_NAME" />.</translation>
 <translation id="5514904542973294328">Na-disable ng administrator ng device na ito</translation>
@@ -848,6 +854,7 @@
 <translation id="7250468141469952378"><ph name="ITEM_COUNT" /> ang napili</translation>
 <translation id="7253272406652746122">Magdagdag ng Google Account mula sa page na Mga Account sa app na Mga Setting ng iyong device.</translation>
 <translation id="7274013316676448362">Naka-block na site</translation>
+<translation id="7290209999329137901">Hindi available ang pag-rename</translation>
 <translation id="7291387454912369099">Assistant Triggered na Pag-check out</translation>
 <translation id="729975465115245577">Walang app sa iyong device upang ma-store ang file ng mga password.</translation>
 <translation id="7302081693174882195">Mga detalye: Pinagbukud-bukod ayon sa laki ng natipid na data</translation>
@@ -981,6 +988,7 @@
 <translation id="8200772114523450471">Resume</translation>
 <translation id="8209050860603202033">Buksan ang larawan</translation>
 <translation id="8220488350232498290"><ph name="GIGABYTES" /> GB na mga na-download</translation>
+<translation id="8224471946457685718">Mag-download ng mga artikulo para sa iyo sa Wi-Fi</translation>
 <translation id="8232956427053453090">Panatilihin ang data</translation>
 <translation id="8249310407154411074">Ilipat sa itaas</translation>
 <translation id="8250920743982581267">Mga Dokumento</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_fr.xtb b/chrome/android/java/strings/translations/android_chrome_strings_fr.xtb
index 60fba25a..ea1bf2c0 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_fr.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_fr.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Affichage d'une copie hors connexion de la page</translation>
 <translation id="2546283357679194313">Cookies et données de site</translation>
 <translation id="2567385386134582609">IMAGE</translation>
+<translation id="257088987046510401">Thèmes</translation>
 <translation id="2570922361219980984">L'accès à la position est également désactivé pour cet appareil. Activez-le dans les <ph name="BEGIN_LINK" />paramètres Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Développé – Cliquer pour réduire</translation>
 <translation id="2581165646603367611">Cette action aura pour effet de vider le cache et de supprimer les cookies, ainsi que d'autres données de site que Chrome ne considère pas comme importantes.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_gu.xtb b/chrome/android/java/strings/translations/android_chrome_strings_gu.xtb
index 7c8b3cc..7f90f9b 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_gu.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_gu.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">આ પેજની ઓફલાઇન કૉપિ જોઈ રહ્યા છે</translation>
 <translation id="2546283357679194313">કૂકીઝ અને સાઇટ ડેટા</translation>
 <translation id="2567385386134582609">છબી</translation>
+<translation id="257088987046510401">થીમ્સ</translation>
 <translation id="2570922361219980984">આ ઉપકરણ માટે સ્થાન ઍક્સેસ પણ બંધ છે. તેને <ph name="BEGIN_LINK" />Android સેટિંગ<ph name="END_LINK" />માં ચાલુ કરો.</translation>
 <translation id="257931822824936280">વિસ્તૃત - સંકુચિત કરવા માટે ક્લિક કરો.</translation>
 <translation id="2581165646603367611">આ કુકી, કૅશ અને Chromeને લાગતું હોય કે આ મહત્વનું નથી એવા સાઇટના બીજા ડેટાને સાફ કરશે.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_hi.xtb b/chrome/android/java/strings/translations/android_chrome_strings_hi.xtb
index bc46216e..52dc1675 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_hi.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_hi.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">इस पृष्‍ठ की ऑफ़लाइन कॉपी देख रहे हैं</translation>
 <translation id="2546283357679194313">कुकी और साइट डेटा</translation>
 <translation id="2567385386134582609">चित्र</translation>
+<translation id="257088987046510401">थीम</translation>
 <translation id="2570922361219980984">इस डिवाइस के लिए स्थान एक्सेस भी बंद है. उसे <ph name="BEGIN_LINK" />Android सेटिंग<ph name="END_LINK" /> में चालू करें.</translation>
 <translation id="257931822824936280">विस्‍तारित - संक्षिप्‍त करने के लिए क्‍लिक करें.</translation>
 <translation id="2581165646603367611">यह साइट की कुकी, संचय और अन्य डेटा निकाल देगा जो Chrome के विचार में महत्वपूर्ण नहीं है.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_hr.xtb b/chrome/android/java/strings/translations/android_chrome_strings_hr.xtb
index e66fceb8..91442f6 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_hr.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_hr.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Prikaz izvanmrežne kopije stranice</translation>
 <translation id="2546283357679194313">Kolačići i podaci o web-lokacijama</translation>
 <translation id="2567385386134582609">SLIKA</translation>
+<translation id="257088987046510401">Teme</translation>
 <translation id="2570922361219980984">Pristup lokaciji isključen je i za ovaj uređaj. Uključite ga u <ph name="BEGIN_LINK" />postavkama Androida<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Prošireno – kliknite za sažimanje.</translation>
 <translation id="2581165646603367611">Time će se izbrisati kolačići, predmemorija i ostali podaci o web-lokacijama koje Chrome ne smatra važnima.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">Ponovno učitavanje trenutačne stranice</translation>
 <translation id="3445014427084483498">Upravo sada</translation>
 <translation id="3452612588551937789">Prijavite se Google računom da biste imali pristup svojim oznakama, zaporkama, povijesti i ostalim postavkama na svim svojim uređajima.</translation>
+<translation id="3478363558367712427">Možete odabrati tražilicu</translation>
 <translation id="3492207499832628349">Nova anonimna kartica</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Saznajte više<ph name="END_LINK" /> o predloženom sadržaju</translation>
 <translation id="3513704683820682405">Proširena stvarnost</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_hu.xtb b/chrome/android/java/strings/translations/android_chrome_strings_hu.xtb
index c4ff2c3..b700c23 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_hu.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_hu.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Az oldal offline példányának megtekintése</translation>
 <translation id="2546283357679194313">Cookie-k és webhelyadatok</translation>
 <translation id="2567385386134582609">KÉP</translation>
+<translation id="257088987046510401">Témák</translation>
 <translation id="2570922361219980984">A helyhozzáférés is ki van kapcsolva ennél az eszköznél. A funkciót az <ph name="BEGIN_LINK" />Android-beállításokban<ph name="END_LINK" /> tudja bekapcsolni.</translation>
 <translation id="257931822824936280">Kibontva – kattintson az összecsukáshoz.</translation>
 <translation id="2581165646603367611">Ezzel törli a cookie-kat, a gyorsítótárat, valamint a webhelyek összes olyan adatát, amelyről a Chrome úgy véli, hogy nem fontos.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_id.xtb b/chrome/android/java/strings/translations/android_chrome_strings_id.xtb
index 4d5e2ee..c281f29 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_id.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_id.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Melihat salinan offline halaman ini</translation>
 <translation id="2546283357679194313">Cookie dan data situs</translation>
 <translation id="2567385386134582609">GAMBAR</translation>
+<translation id="257088987046510401">Tema</translation>
 <translation id="2570922361219980984">Akses lokasi juga dinonaktifkan untuk perangkat ini. Aktifkan di <ph name="BEGIN_LINK" />Setelan Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Diperluas - klik untuk menciutkan</translation>
 <translation id="2581165646603367611">Tindakan ini akan mengosongkan cache dan menghapus cookie, serta data lain dari situs yang dianggap tidak penting oleh Chrome.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">Memuat ulang halaman saat ini</translation>
 <translation id="3445014427084483498">Baru Saja</translation>
 <translation id="3452612588551937789">Login dengan Akun Google untuk mendapatkan bookmark, sandi, histori, dan setelan lainnya di semua perangkat Anda.</translation>
+<translation id="3478363558367712427">Anda dapat memilih mesin telusur Anda</translation>
 <translation id="3492207499832628349">Tab penyamaran baru</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Pelajari lebih lanjut<ph name="END_LINK" /> konten yang disarankan</translation>
 <translation id="3513704683820682405">Augmented Reality</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_it.xtb b/chrome/android/java/strings/translations/android_chrome_strings_it.xtb
index 892428bd..0814310 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_it.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_it.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">È visualizzata una copia offline della pagina</translation>
 <translation id="2546283357679194313">Cookie e dati dei siti</translation>
 <translation id="2567385386134582609">IMMAGINE</translation>
+<translation id="257088987046510401">Temi</translation>
 <translation id="2570922361219980984">L'accesso alla posizione è disattivato anche per questo dispositivo. Attivalo nelle <ph name="BEGIN_LINK" />Impostazioni Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Espanso. Fai clic per comprimere.</translation>
 <translation id="2581165646603367611">Verrà svuotata la cache e verranno cancellati i cookie e altri dati relativi a siti che Chrome non ritiene importanti.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_iw.xtb b/chrome/android/java/strings/translations/android_chrome_strings_iw.xtb
index 9a9c352..b2005ea 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_iw.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_iw.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">מציג העתק לא מקוון של עמוד זה</translation>
 <translation id="2546283357679194313">‏נתוני אתר וקובצי Cookie</translation>
 <translation id="2567385386134582609">תמונה</translation>
+<translation id="257088987046510401">ערכות נושא</translation>
 <translation id="2570922361219980984">‏גם הגישה למיקום כבויה בשביל המכשיר הזה. יש להפעיל אותה ב<ph name="BEGIN_LINK" />הגדרות Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">מורחב - לחץ כדי לכווץ.</translation>
 <translation id="2581165646603367611">‏פעולה זו תמחק את קובצי ה-Cookie, את המטמון ונתונים אחרים של אתרים ש-Chrome לא מחשיב כחשובים.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">טען מחדש את הדף הנוכחי</translation>
 <translation id="3445014427084483498">ממש עכשיו</translation>
 <translation id="3452612588551937789">‏יש להיכנס באמצעות חשבון Google כדי לקבל גישה אל הסימניות, הסיסמאות, ההיסטוריה והגדרות נוספות בכל המכשירים שלך.</translation>
+<translation id="3478363558367712427">אפשר לבחור את מנוע החיפוש</translation>
 <translation id="3492207499832628349">כרטיסייה חדשה לגלישה בסתר</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />מידע נוסף<ph name="END_LINK" /> על הצעות לתוכן</translation>
 <translation id="3513704683820682405">מציאות רבודה</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb
index 63680438..350794e 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ja.xtb
@@ -26,10 +26,10 @@
 <translation id="1178581264944972037">一時停止</translation>
 <translation id="1181037720776840403">削除</translation>
 <translation id="1197267115302279827">ブックマークを移動</translation>
-<translation id="119944043368869598">すべてクリア</translation>
+<translation id="119944043368869598">すべて削除</translation>
 <translation id="1201402288615127009">次へ</translation>
 <translation id="1204037785786432551">リンクをダウンロード</translation>
-<translation id="1206892813135768548">リンク テキストをコピー</translation>
+<translation id="1206892813135768548">リンクテキストをコピー</translation>
 <translation id="1208340532756947324">複数の端末で独自の設定を同期して共有するには、同期を有効にします</translation>
 <translation id="1209206284964581585">今は表示しない</translation>
 <translation id="1231733316453485619">同期を有効にしますか?</translation>
@@ -49,7 +49,7 @@
 <translation id="1331212799747679585">Chrome を更新できません。その他のオプション</translation>
 <translation id="1332501820983677155">Google Chrome 機能のショートカット</translation>
 <translation id="1360432990279830238">ログアウトして同期をオフにしますか?</translation>
-<translation id="136248372334525878">ページをプリロードすると、読み込みが速くなり、オフラインでの閲覧も可能になります</translation>
+<translation id="136248372334525878">ページをプリロードして、すばやく読み込んだりオフラインで閲覧したりできるようにします</translation>
 <translation id="1369915414381695676">サイト <ph name="SITE_NAME" /> を追加しました</translation>
 <translation id="1373696734384179344">選択したコンテンツをダウンロードするにはメモリが不足しています。</translation>
 <translation id="1376578503827013741">計算中...</translation>
@@ -91,7 +91,7 @@
 <translation id="1644574205037202324">履歴</translation>
 <translation id="1647391597548383849">カメラへのアクセス</translation>
 <translation id="1660204651932907780">音声の再生をサイトに許可する(推奨)</translation>
-<translation id="1670399744444387456">基本</translation>
+<translation id="1670399744444387456">基本設定</translation>
 <translation id="1671236975893690980">ダウンロードを待機しています...</translation>
 <translation id="1672586136351118594">次回から表示しない</translation>
 <translation id="1692118695553449118">同期は有効です</translation>
@@ -156,7 +156,7 @@
 <translation id="2091887806945687916">音声</translation>
 <translation id="2096012225669085171">端末間の同期とカスタマイズ</translation>
 <translation id="2100273922101894616">自動ログイン</translation>
-<translation id="2107397443965016585">保護されたコンテンツの再生をサイトに許可する前に確認します(推奨)</translation>
+<translation id="2107397443965016585">保護されたコンテンツの再生をサイトに許可する前に確認する(推奨)</translation>
 <translation id="2111511281910874386">ページを開く</translation>
 <translation id="2122601567107267586">アプリを開けませんでした</translation>
 <translation id="2126426811489709554">Powered by Chrome</translation>
@@ -183,7 +183,7 @@
 <translation id="2321958826496381788">読みやすくなるまでスライダをドラッグしてください。段落をダブルタップするとテキストがこれより大きくなります。</translation>
 <translation id="2323763861024343754">サイトのストレージ</translation>
 <translation id="2328985652426384049">ログインできません</translation>
-<translation id="2342981853652716282">Chrome にログインすれば、ブックマーク、パスワード、その他の設定をどの端末からでもご利用いただけます。</translation>
+<translation id="2342981853652716282">Chrome にログインすると、ブックマーク、パスワード、その他の設定をどの端末からでもご利用いただけます。</translation>
 <translation id="2349710944427398404">Chrome が使用するデータ全体(アカウント、ブックマーク、保存済みの設定など)</translation>
 <translation id="2351097562818989364">翻訳設定をリセットしました。</translation>
 <translation id="2353636109065292463">インターネット接続を確認しています</translation>
@@ -198,7 +198,7 @@
 <translation id="2426805022920575512">別のアカウントを選択</translation>
 <translation id="2433507940547922241">デザイン</translation>
 <translation id="2434158240863470628">ダウンロードが完了しました<ph name="SEPARATOR" /> <ph name="BYTES_DOWNLOADED" /></translation>
-<translation id="2440823041667407902">現在地情報へのアクセス</translation>
+<translation id="2440823041667407902">位置情報へのアクセス</translation>
 <translation id="2450083983707403292"><ph name="FILE_NAME" /> のダウンロードをやり直してもよろしいですか?</translation>
 <translation id="2476578072172137802">サイトの設定</translation>
 <translation id="2482878487686419369">通知</translation>
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">このページのオフライン コピーを表示しています</translation>
 <translation id="2546283357679194313">Cookie とサイトデータ</translation>
 <translation id="2567385386134582609">画像</translation>
+<translation id="257088987046510401">テーマ</translation>
 <translation id="2570922361219980984">位置情報へのアクセスが端末でもオフになっています。<ph name="BEGIN_LINK" />Android の設定<ph name="END_LINK" />でオンにしてください。</translation>
 <translation id="257931822824936280">展開されています - クリックすると折りたたまれます。</translation>
 <translation id="2581165646603367611">Chrome で重要度が低いと判断されるサイトの Cookie やキャッシュなどのデータを削除します。</translation>
@@ -260,7 +261,7 @@
 <translation id="2900528713135656174">予定を作成</translation>
 <translation id="2902702728133930130">Chrome の起動時に予期しないエラーが発生し、起動できませんでした。</translation>
 <translation id="290376772003165898"><ph name="LANGUAGE" />のページではない場合:</translation>
-<translation id="2910701580606108292">保護されたコンテンツの再生をサイトに許可する前に確認します</translation>
+<translation id="2910701580606108292">保護されたコンテンツの再生をサイトに許可する前に確認する</translation>
 <translation id="2913331724188855103">サイトに Cookie データの保存と読み取りを許可する(推奨)</translation>
 <translation id="2923908459366352541">名前が無効です</translation>
 <translation id="2932150158123903946">Google <ph name="APP_NAME" /> ストレージ</translation>
@@ -272,7 +273,7 @@
 <translation id="2989523299700148168">最近のアクセス</translation>
 <translation id="2996291259634659425">パスフレーズの作成</translation>
 <translation id="2996809686854298943">URLが必要です</translation>
-<translation id="300526633675317032">ウェブサイトのストレージ <ph name="SIZE_IN_KB" /> をすべて消去します。</translation>
+<translation id="300526633675317032">ウェブサイトのストレージ <ph name="SIZE_IN_KB" /> のデータをすべて削除します。</translation>
 <translation id="3029613699374795922"><ph name="KBS" /> KB をダウンロード済み</translation>
 <translation id="3029704984691124060">パスフレーズが一致しません</translation>
 <translation id="3036750288708366620"><ph name="BEGIN_LINK" />ヘルプ<ph name="END_LINK" /></translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">現在のページを再読み込みする</translation>
 <translation id="3445014427084483498">たった今</translation>
 <translation id="3452612588551937789">Google アカウントでログインすると、どの端末からでも同じブックマーク、履歴、パスワードなどの設定を利用できるようになります。</translation>
+<translation id="3478363558367712427">検索エンジンを選択できます</translation>
 <translation id="3492207499832628349">新しいシークレット タブ</translation>
 <translation id="3493531032208478708">詳しくは、<ph name="BEGIN_LINK" />おすすめのコンテンツ<ph name="END_LINK" />についての説明をご覧ください</translation>
 <translation id="3513704683820682405">拡張現実(AR)</translation>
@@ -401,7 +403,7 @@
 <translation id="4046123991198612571">次のトラック</translation>
 <translation id="4048707525896921369">ウェブサイト上のトピックについてページを移動せずに調べられます。「タップして検索」では、単語とその周囲のコンテキストが Google 検索に送信され、定義、画像、検索結果などの情報が返されます。
 
-検索用語を押し続けるとその用語が選択され、選択範囲を調整できます。検索結果を絞り込むには、パネルを上にスライドして検索ボックスをタップします。</translation>
+検索用語を長押しするとその用語が選択され、選択範囲を調整できます。検索結果を絞り込むには、パネルを上にスライドして検索ボックスをタップします。</translation>
 <translation id="4056223980640387499">セピア</translation>
 <translation id="4060598801229743805">画面の上部にあるオプション</translation>
 <translation id="4062305924942672200">法的情報</translation>
@@ -442,7 +444,7 @@
 <translation id="4384468725000734951">検索に Sogou を使用します</translation>
 <translation id="4398088515904522762">この機能を使用するには、[<ph name="BEGIN_LINK" />アクティビティと操作<ph name="END_LINK" />] をオンにしてください。</translation>
 <translation id="4404568932422911380">ブックマークがありません</translation>
-<translation id="4409723563706114196">ページ予測を使用する</translation>
+<translation id="4409723563706114196">ページ予測の使用</translation>
 <translation id="4411535500181276704">ライトモード</translation>
 <translation id="4432792777822557199">今後、<ph name="SOURCE_LANGUAGE" />のページは<ph name="TARGET_LANGUAGE" />に翻訳されます</translation>
 <translation id="4433925000917964731">Google から提供されている軽量版のページ</translation>
@@ -451,7 +453,7 @@
 <translation id="4452411734226507615">「<ph name="TAB_TITLE" />」タブを閉じます</translation>
 <translation id="4452548195519783679">「<ph name="FOLDER_NAME" />」にブックマークしました</translation>
 <translation id="4453340223357552416"><ph name="FILE_NAME" /> を <ph name="PRODUCT_NAME" /> でダウンロードしました</translation>
-<translation id="445467742685312942">保護されたコンテンツの再生をサイトに許可します</translation>
+<translation id="445467742685312942">保護されたコンテンツの再生をサイトに許可する</translation>
 <translation id="4468959413250150279">特定のサイトの音声をミュートします。</translation>
 <translation id="4472118726404937099">複数の端末で独自の設定を同期して共有するには、ログインして同期を有効にします</translation>
 <translation id="447252321002412580">Chrome の機能と動作の改善に協力する</translation>
@@ -506,7 +508,7 @@
 この設定を変更する場合は<ph name="BEGIN_LINK" />同期をリセット<ph name="END_LINK" />してください</translation>
 <translation id="4807098396393229769">カード名義人(半角英文字)</translation>
 <translation id="4807963036345170158">データセーバー OFF</translation>
-<translation id="4816465935029283692">データタイプ</translation>
+<translation id="4816465935029283692">データの種類</translation>
 <translation id="4824958205181053313">同期をキャンセルしますか?</translation>
 <translation id="4837753911714442426">ページの印刷オプションを開く</translation>
 <translation id="4842092870884894799">パスワード作成のポップアップを表示しています</translation>
@@ -554,7 +556,7 @@
 <translation id="5129038482087801250">ウェブアプリをインストール</translation>
 <translation id="5132942445612118989">すべてのデバイスでパスワード、履歴、その他の設定を同期する</translation>
 <translation id="5139940364318403933">Google ドライブの使い方を見る</translation>
-<translation id="515227803646670480">保存したデータの消去</translation>
+<translation id="515227803646670480">保存したデータの削除</translation>
 <translation id="5152843274749979095">サポートされているアプリがインストールされていません</translation>
 <translation id="5161254044473106830">タイトルが必要です</translation>
 <translation id="5162754098604580781">{FILE_COUNT,plural, =1{1 件のダウンロードが失敗しました。}other{# 件のダウンロードが失敗しました。}}</translation>
@@ -598,7 +600,7 @@
 <translation id="5466407412363861127">この機能では<ph name="BEGIN_LINK" />同期<ph name="END_LINK" />が使用されます。</translation>
 <translation id="548278423535722844">マップアプリで開く</translation>
 <translation id="5487521232677179737">データを削除</translation>
-<translation id="5494752089476963479">煩わしい広告や誤解を招く広告が表示されるサイトで広告をブロックします</translation>
+<translation id="5494752089476963479">煩わしい広告や誤解を招く広告が表示されるサイトで広告をブロックする</translation>
 <translation id="5497272504048921382">開いているタブ</translation>
 <translation id="5500777121964041360">お住まいの地域ではご利用になれない可能性があります</translation>
 <translation id="550684401320795253">Chrome を更新しています...</translation>
@@ -615,7 +617,7 @@
 <translation id="5556459405103347317">再読み込み</translation>
 <translation id="5561549206367097665">ネットワーク接続を待機しています…</translation>
 <translation id="557283862590186398">このサイトを利用するには、Chrome でマイクの使用を許可する必要があります。</translation>
-<translation id="55737423895878184">現在地の使用と通知の送信が許可されています</translation>
+<translation id="55737423895878184">位置情報の使用と通知の送信が許可されています</translation>
 <translation id="5578795271662203820">この画像を <ph name="SEARCH_ENGINE" /> で検索</translation>
 <translation id="5581519193887989363">同期する項目はいつでも [<ph name="BEGIN_LINK1" />設定<ph name="END_LINK1" />] で選択できます。</translation>
 <translation id="5595485650161345191">住所の編集</translation>
@@ -629,11 +631,11 @@
 <translation id="5655963694829536461">ダウンロードしたアイテムを検索</translation>
 <translation id="5659593005791499971">メール</translation>
 <translation id="5665379678064389456"><ph name="APP_NAME" /> で予定を作成</translation>
-<translation id="5668404140385795438">ウェブサイトのズーム防止リクエストを上書きする</translation>
+<translation id="5668404140385795438">ウェブサイトのズーム防止リクエストを上書きします</translation>
 <translation id="5677928146339483299">ブロック中</translation>
 <translation id="5684874026226664614">このページを翻訳できませんでした。</translation>
 <translation id="5686790454216892815">ファイル名が長すぎます</translation>
-<translation id="5689516760719285838">現在地</translation>
+<translation id="5689516760719285838">位置情報</translation>
 <translation id="569536719314091526">[その他のオプション] から、このページを任意の言語に翻訳できます</translation>
 <translation id="572328651809341494">最近使ったタブ</translation>
 <translation id="5726692708398506830">ページ上のすべての要素を拡大する</translation>
@@ -689,7 +691,7 @@
 <translation id="6112702117600201073">ページを更新しています</translation>
 <translation id="6127379762771434464">アイテムを削除しました</translation>
 <translation id="6140912465461743537">国 / 地域</translation>
-<translation id="614940544461990577">次をお試しください:</translation>
+<translation id="614940544461990577">次をお試しください</translation>
 <translation id="6154478581116148741">この端末からパスワードをエクスポートするには、[設定] で画面ロックをオンにしてください。</translation>
 <translation id="6159335304067198720"><ph name="PERCENT" /> のデータを削減</translation>
 <translation id="6165508094623778733">詳しく見る</translation>
@@ -706,7 +708,7 @@
 <translation id="6221633008163990886">ロックを解除してパスワードをエクスポート</translation>
 <translation id="6232535412751077445">「トラッキング拒否」を有効にすると、リクエストが閲覧トラフィックに含まれるようになります。ウェブサイトがリクエストに応答するかどうか、またリクエストがどのように解釈されるかによって、この影響は異なります。
 
-たとえば一部のウェブサイトでは、このリクエストに対して、ユーザーが過去にアクセスしたウェブサイトとは関係のない広告が表示されます。トラッキングを拒否しても、実際のところ多くのウェブサイトではユーザーの閲覧データが収集され利用されています。その用途としては、セキュリティの強化、コンテンツ、サービス、広告、おすすめの表示、レポート統計情報の作成などが挙げられます。</translation>
+たとえば一部のウェブサイトでは、このリクエストに対して、ユーザーが過去にアクセスしたウェブサイトとは関係のない広告が表示されます。トラッキングを拒否しても、実際のところ多くのウェブサイトではユーザーの閲覧データが収集され利用されています。その用途としては、セキュリティの強化や、コンテンツ、サービス、広告、おすすめの表示、レポート統計情報の作成などが挙げられます。</translation>
 <translation id="624789221780392884">アップデート準備完了</translation>
 <translation id="6255999984061454636">おすすめのコンテンツ</translation>
 <translation id="6277522088822131679">ページの印刷中に問題が発生しました。もう一度お試しください。</translation>
@@ -725,8 +727,8 @@
 <translation id="6364438453358674297">履歴から候補を削除しますか?</translation>
 <translation id="6369229450655021117">ここからウェブを検索したり、友だちと共有したり、開いたページを表示したりできます</translation>
 <translation id="6378173571450987352">詳細: データ使用量の順</translation>
-<translation id="6383961787135158834">サイトのストレージ削除...</translation>
-<translation id="6388207532828177975">消去してリセット</translation>
+<translation id="6383961787135158834">サイトのストレージ データを削除...</translation>
+<translation id="6388207532828177975">データを削除してリセット</translation>
 <translation id="6393156038355142111">安全なパスワードを自動生成</translation>
 <translation id="6393863479814692971">このサイトを利用するには、Chrome でカメラとマイクの使用を許可する必要があります。</translation>
 <translation id="6395288395575013217">リンク</translation>
@@ -739,7 +741,7 @@
 <translation id="6441734959916820584">名前が長すぎます</translation>
 <translation id="6444421004082850253">{FILE_COUNT,plural, =1{# 個の画像}other{# 個の画像}}</translation>
 <translation id="6447842834002726250">Cookie</translation>
-<translation id="6448273550210938826">検索と URL 候補</translation>
+<translation id="6448273550210938826">検索と URL の候補表示</translation>
 <translation id="6461962085415701688">ファイルを開けません</translation>
 <translation id="6464977750820128603">Chrome でアクセスしたサイトを表示し、タイマーを設定できます。\n\nタイマーを設定したサイトの情報と、サイトでの滞在時間に関する情報が Google に送信されます。送信した情報は Digital Wellbeing の改善に役立てられます。</translation>
 <translation id="6475951671322991020">動画をダウンロード</translation>
@@ -787,7 +789,7 @@
 <translation id="6766758767654711248">タップしてサイトに移動する</translation>
 <translation id="6782111308708962316">サードパーティのウェブサイトが Cookie データを保存したり読み取ったりできないようにします</translation>
 <translation id="6790428901817661496">再生</translation>
-<translation id="679325081238418596">ブックマーク、履歴、パスワードなどの設定がどの端末でも利用できるようになります</translation>
+<translation id="679325081238418596">ブックマーク、履歴、パスワードなどの設定をどの端末でも利用できるようにします</translation>
 <translation id="6803423358608456383">開いているタブは画面の半分の高さで表示されています</translation>
 <translation id="6811034713472274749">ページを表示できます</translation>
 <translation id="6818926723028410516">アイテムを選択</translation>
@@ -819,7 +821,7 @@
 <translation id="6989267951144302301">ダウンロードできませんでした</translation>
 <translation id="6990079615885386641">Google Play ストアからアプリを入手: <ph name="APP_ACTION" /></translation>
 <translation id="6992289844737586249">サイトにマイクの使用を許可する前に確認する(推奨)</translation>
-<translation id="7016516562562142042">現在の検索エンジンに対しては許可</translation>
+<translation id="7016516562562142042">現在の検索エンジンに対して許可</translation>
 <translation id="7021515813996758557"><ph name="FILE_NAME" /> をダウンロードしました</translation>
 <translation id="7022756207310403729">ブラウザで開く</translation>
 <translation id="702463548815491781">TalkBack またはスイッチ アクセスを有効にしている場合におすすめです</translation>
@@ -828,14 +830,14 @@
 <translation id="7032663816368481562">アドレスバーの「もっと見る」<ph name="ICON" /> をタップしたときに関連ページへのクイックリンクを表示します。このとき、アクセスしたページの URL が Google に送信されます。</translation>
 <translation id="7034608350006174882">Google Pay のカードと住所</translation>
 <translation id="7053983685419859001">ブロック</translation>
-<translation id="7055152154916055070">リダイレクトがブロックされました:</translation>
+<translation id="7055152154916055070">リダイレクトがブロックされました</translation>
 <translation id="7062545763355031412">同意してアカウントを切り替える</translation>
 <translation id="7063006564040364415">同期サーバーに接続できませんでした。</translation>
 <translation id="7066151586745993502">{NUM_SELECTED,plural, =1{1 件のアイテムを選択済み}other{# 件のアイテムを選択済み}}</translation>
 <translation id="7077143737582773186">SD カード</translation>
 <translation id="7087918508125750058"><ph name="ITEM_COUNT" /> 件選択されています。オプションは画面上部にあります</translation>
 <translation id="7121362699166175603">アドレスバーの履歴とオートコンプリートを削除します。お使いの Google アカウントの <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> に、他の形式の閲覧履歴が記録されている場合があります。</translation>
-<translation id="7128222689758636196">現在の検索エンジンを許可する</translation>
+<translation id="7128222689758636196">現在の検索エンジンに対して許可</translation>
 <translation id="7138678301420049075">その他</translation>
 <translation id="7139148793369023665">類似するコンテンツを閉じました</translation>
 <translation id="7141896414559753902">サイトでのポップアップ表示とリダイレクトをブロックする(推奨)</translation>
@@ -870,7 +872,7 @@
 <translation id="7423098979219808738">最初に確認する</translation>
 <translation id="7423538860840206698">クリップボードの読み取りがブロックされています</translation>
 <translation id="7431991332293347422">検索などのカスタマイズを目的とした閲覧履歴の使用方法を設定</translation>
-<translation id="7437998757836447326">Chromeからログアウト</translation>
+<translation id="7437998757836447326">Chrome からログアウト</translation>
 <translation id="7438641746574390233">ライトモードをオンにすると、Chrome では Google のサーバーを使用してページの読み込みを高速化します。特に読み込みの遅いページでは、ライトモードにより、主要コンテンツのみを読み込むようページが書き換えられます。なお、ライトモードはシークレット タブには適用されません。</translation>
 <translation id="7444811645081526538">その他のカテゴリ</translation>
 <translation id="7445411102860286510">ミュートされた動画の自動再生をサイトに許可する(推奨)</translation>
@@ -896,19 +898,19 @@
 <translation id="7559975015014302720">ライトモードはオフです</translation>
 <translation id="7562080006725997899">閲覧データの消去</translation>
 <translation id="756809126120519699">Chrome データの消去完了</translation>
-<translation id="757524316907819857">サイトでの保護されたコンテンツの再生をブロックします</translation>
+<translation id="757524316907819857">サイトでの保護されたコンテンツの再生をブロックする</translation>
 <translation id="757855969265046257">{FILES,plural, =1{<ph name="FILES_DOWNLOADED_ONE" /> 件のファイルをダウンロードしました}other{<ph name="FILES_DOWNLOADED_MANY" /> 件のファイルをダウンロードしました}}</translation>
-<translation id="7589445247086920869">現在の検索エンジンをブロックする</translation>
+<translation id="7589445247086920869">現在の検索エンジンに対してブロック</translation>
 <translation id="7593557518625677601">Chrome の同期を開始するには、Android の設定で Android システムの同期を再度有効にします</translation>
 <translation id="7596558890252710462">オペレーティング システム</translation>
 <translation id="7605594153474022051">同期が機能していません</translation>
 <translation id="7606077192958116810">ライトモードはオンです。[設定] で管理できます。</translation>
-<translation id="7612619742409846846">次のユーザーとして Google にログインしています:</translation>
+<translation id="7612619742409846846">次のユーザーとして Google にログインしています</translation>
 <translation id="7619072057915878432">ネットワーク障害が発生したため、<ph name="FILE_NAME" /> をダウンロードできませんでした。</translation>
 <translation id="7624880197989616768"><ph name="BEGIN_LINK1" />ヘルプ<ph name="END_LINK1" />または<ph name="BEGIN_LINK2" />再スキャン<ph name="END_LINK2" /></translation>
 <translation id="7626032353295482388">Chrome へようこそ</translation>
 <translation id="7638584964844754484">パスフレーズが正しくありません</translation>
-<translation id="7641339528570811325">閲覧データを削除…</translation>
+<translation id="7641339528570811325">閲覧履歴データを削除…</translation>
 <translation id="7648422057306047504">Google の認証情報でパスワードを暗号化する</translation>
 <translation id="7649070708921625228">ヘルプ</translation>
 <translation id="7658239707568436148">キャンセル</translation>
@@ -933,7 +935,7 @@
 <translation id="7837721118676387834">特定のサイトに対し、ミュートされた動画の自動再生を許可します。</translation>
 <translation id="7846076177841592234">選択解除</translation>
 <translation id="784934925303690534">期間</translation>
-<translation id="7851858861565204677">その他のデバイス</translation>
+<translation id="7851858861565204677">他のデバイス</translation>
 <translation id="7854964836418414587">類似するコンテンツを閉じる</translation>
 <translation id="7875915731392087153">メールを作成</translation>
 <translation id="7876243839304621966">すべて削除</translation>
@@ -946,17 +948,17 @@
 <translation id="7947953824732555851">同意してログイン</translation>
 <translation id="7963646190083259054">ベンダー:</translation>
 <translation id="7975379999046275268">ページをプレビュー <ph name="BEGIN_NEW" />New<ph name="END_NEW" /></translation>
-<translation id="7981313251711023384">ページをプリロードして閲覧と検索をすばやく行えるようにする</translation>
+<translation id="7981313251711023384">ページをプリロードして、閲覧と検索をすばやく行えるようにします</translation>
 <translation id="79859296434321399">拡張現実(AR)コンテンツを表示するには ARCore をインストールしてください</translation>
 <translation id="7986741934819883144">連絡先の選択</translation>
 <translation id="7987073022710626672">Chrome 利用規約</translation>
 <translation id="7998918019931843664">閉じたタブを開く</translation>
-<translation id="7999064672810608036">すべてのローカルデータ(Cookie を含む)を消去して、このウェブサイトに指定したすべての許可をリセットしてもよろしいですか?</translation>
+<translation id="7999064672810608036">すべてのローカルデータ(Cookie を含む)を削除して、このウェブサイトに指定したすべての権限をリセットしてもよろしいですか?</translation>
 <translation id="8004582292198964060">ブラウザ</translation>
 <translation id="8007176423574883786">このデバイスに対して無効</translation>
 <translation id="8015452622527143194">ページ上のすべての要素をデフォルトのサイズに戻す</translation>
 <translation id="802154636333426148">ダウンロード エラー</translation>
-<translation id="8026334261755873520">閲覧履歴データを削除する</translation>
+<translation id="8026334261755873520">閲覧履歴データの削除</translation>
 <translation id="8035133914807600019">新しいフォルダ...</translation>
 <translation id="8037686209485537503">もっと見る</translation>
 <translation id="8037750541064988519">残り <ph name="DAYS" /> 日</translation>
@@ -1082,7 +1084,7 @@
 <translation id="8970887620466824814">エラーが発生しました。</translation>
 <translation id="8972098258593396643">デフォルトのフォルダにダウンロードしますか?</translation>
 <translation id="8981454092730389528">Google アクティビティ管理</translation>
-<translation id="8983677657449185470">セーフ ブラウジングの改善に協力する</translation>
+<translation id="8983677657449185470">セーフ ブラウジングの改善への協力</translation>
 <translation id="8986494364107987395">使用統計データと障害レポートを Google に自動送信します</translation>
 <translation id="8993760627012879038">新しいタブをシークレット モードで開く</translation>
 <translation id="8998729206196772491"><ph name="MANAGED_DOMAIN" /> で管理されているアカウントでログインして、Chrome データの管理を管理者に委ねようとしています。この操作を行うと、データはこのアカウントに恒久的に関連付けられます。Chrome からログアウトすると、データはこの端末から削除されますが、Google アカウントには残ります。</translation>
@@ -1098,7 +1100,7 @@
 <translation id="9080642952018487277">プライベート モードを開始</translation>
 <translation id="9086455579313502267">ネットワークにアクセスできません</translation>
 <translation id="9099018167121903954"><ph name="KILOBYTES" /> KB をダウンロードで使用中</translation>
-<translation id="9100505651305367705">記事の簡易表示がサポートされている場合、簡易表示を提案する</translation>
+<translation id="9100505651305367705">記事の簡易表示がサポートされている場合、簡易表示を提案します</translation>
 <translation id="9100610230175265781">パスフレーズを入力してください</translation>
 <translation id="9133703968756164531"><ph name="ITEM_NAME" />(<ph name="ITEM_ID" />)</translation>
 <translation id="9137013805542155359">原文のページを表示</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_kn.xtb b/chrome/android/java/strings/translations/android_chrome_strings_kn.xtb
index dd17c34..736a284 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_kn.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_kn.xtb
@@ -215,6 +215,7 @@
 <translation id="2536728043171574184">ಈ ಪುಟದ ಆಫ್‌ಲೈನ್ ನಕಲನ್ನು ವೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ</translation>
 <translation id="2546283357679194313">ಕುಕೀಗಳು ಮತ್ತು ಸೈಟ್ ಡೇಟಾ</translation>
 <translation id="2567385386134582609">ಚಿತ್ರ</translation>
+<translation id="257088987046510401">ಥೀಮ್‌ಗಳು</translation>
 <translation id="2570922361219980984">ಈ ಸಾಧನದ ಸ್ಥಳ ಪ್ರವೇಶ ಸಹ ಆಫ್ ಆಗಿದೆ. ಅದನ್ನು <ph name="BEGIN_LINK" />Android ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ<ph name="END_LINK" /> ಆನ್ ಮಾಡಿ.</translation>
 <translation id="257931822824936280">ವಿಸ್ತರಿಸಲಾಗಿದೆ - ಕುಗ್ಗಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ</translation>
 <translation id="2581165646603367611">ಇದು ಕುಕೀಗಳು, ಸಂಗ್ರಹ ಮತ್ತು ಪ್ರಮುಖವಲ್ಲವೆಂದು Chrome ಭಾವಿಸುವ ಸೈಟ್‌ಗಳ ಇತರ ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸುತ್ತದೆ.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ko.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ko.xtb
index 9c39d4c..db2ca813 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ko.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ko.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">이 페이지의 오프라인 사본 보는 중</translation>
 <translation id="2546283357679194313">쿠키 및 사이트 데이터</translation>
 <translation id="2567385386134582609">이미지</translation>
+<translation id="257088987046510401">테마</translation>
 <translation id="2570922361219980984">이 기기의 위치 정보 액세스도 사용 중지되었습니다. <ph name="BEGIN_LINK" />Android 설정<ph name="END_LINK" />에서 사용 설정하세요.</translation>
 <translation id="257931822824936280">펼쳐짐 - 접으려면 클릭</translation>
 <translation id="2581165646603367611">이를 통해 쿠키, 캐시 및 Chrome에서 중요하다고 간주하지 않는 사이트의 기타 데이터가 삭제됩니다.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_lt.xtb b/chrome/android/java/strings/translations/android_chrome_strings_lt.xtb
index 34455f4e..be3d83831 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_lt.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_lt.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Žiūrima neprisijungus naudojama šio puslapio kopija</translation>
 <translation id="2546283357679194313">Slapukai ir svetainės duomenys</translation>
 <translation id="2567385386134582609">VAIZDAS</translation>
+<translation id="257088987046510401">Temos</translation>
 <translation id="2570922361219980984">Vietos prieiga taip pat išjungta šiame įrenginyje. Įjunkite ją skiltyje <ph name="BEGIN_LINK" />„Android“ nustatymai“<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Išskleista – spustelėkite, kad sutrauktumėte</translation>
 <translation id="2581165646603367611">Bus išvalyti slapukai, talpykla ir kiti svetainių duomenys, kurių „Chrome“ nelaiko svarbiais.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_lv.xtb b/chrome/android/java/strings/translations/android_chrome_strings_lv.xtb
index a20638b..068f3ac 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_lv.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_lv.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Skata šīs lapas kopiju bezsaistē</translation>
 <translation id="2546283357679194313">Sīkfaili un vietņu dati</translation>
 <translation id="2567385386134582609">ATTĒLS</translation>
+<translation id="257088987046510401">Motīvi</translation>
 <translation id="2570922361219980984">Arī piekļuve šīs ierīces atrašanās vietai ir izslēgta. Ieslēdziet to <ph name="BEGIN_LINK" />Android iestatījumos<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Izvērsts — noklikšķiniet, lai sakļautu.</translation>
 <translation id="2581165646603367611">Tādējādi tiks dzēsti sīkfaili, kešatmiņa un citi vietņu dati, kas pārlūkā Chrome netiek uzskatīti par svarīgiem.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ml.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ml.xtb
index 87c0763..9f4407cba 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ml.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ml.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">ഈ പേജിന്റെ ഒരു ഓഫ്‌ലൈൻ പതിപ്പ് കാണുന്നു</translation>
 <translation id="2546283357679194313">കുക്കികളും സൈറ്റ് ഡാറ്റയും</translation>
 <translation id="2567385386134582609">ചിത്രം</translation>
+<translation id="257088987046510401">തീമുകള്‍‌</translation>
 <translation id="2570922361219980984">ഈ ഉപകരണത്തിന്‍റെ ലൊക്കേഷൻ ആക്‌സസും ഓഫാണ്; <ph name="BEGIN_LINK" />Android ക്രമീകരണത്തിൽ<ph name="END_LINK" /> അത് ഓണാക്കുക.</translation>
 <translation id="257931822824936280">വിപുലീകരിച്ചത് - ചുരുക്കാൻ ക്ലിക്ക് ചെയ്യുക</translation>
 <translation id="2581165646603367611">ഇത്, Chrome പ്രധാനമായി കണക്കാക്കാത്ത സൈറ്റുകളുടെ കുക്കികളും കാഷെയും മറ്റ് വിവരങ്ങളും മായ്‌ക്കും.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_mr.xtb b/chrome/android/java/strings/translations/android_chrome_strings_mr.xtb
index d618abab..d83b136 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_mr.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_mr.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">या पेजची ऑफलाइन प्रत पाहत आहे</translation>
 <translation id="2546283357679194313">कुकीज आणि साइट डेटा</translation>
 <translation id="2567385386134582609">इमेज</translation>
+<translation id="257088987046510401">थीम</translation>
 <translation id="2570922361219980984">या डिव्हाइससाठी स्थान अ‍ॅक्सेस देखील बंद आहे, <ph name="BEGIN_LINK" />Android सेटिंग्‍ज<ph name="END_LINK" /> मध्‍ये हे सुरू करा.</translation>
 <translation id="257931822824936280">विस्‍तृत केले - संकुचित करण्‍यासाठी क्‍लिक करा.</translation>
 <translation id="2581165646603367611">हे सर्व कुकी, कॅशे आणि साइटचा अन्य डेटा साफ करेल जो Chrome ला महत्त्वाचा वाटत नाही.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ms.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ms.xtb
index 1b77fd9..a228190 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ms.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ms.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Melihat salinan luar talian halaman ini</translation>
 <translation id="2546283357679194313">Kuki dan data tapak</translation>
 <translation id="2567385386134582609">IMEJ</translation>
+<translation id="257088987046510401">Tema</translation>
 <translation id="2570922361219980984">Akses lokasi turut dimatikan untuk peranti ini. Hidupkannya dalam <ph name="BEGIN_LINK" />Tetapan Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Dikembangkan - klik untuk meruntuhkan.</translation>
 <translation id="2581165646603367611">Tindakan ini akan menghapuskan kuki, cache dan data tapak yang lain yang Chrome anggap tidak penting.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">Muat semula halaman semasa</translation>
 <translation id="3445014427084483498">Sebentar Tadi</translation>
 <translation id="3452612588551937789">Log masuk dengan Akaun Google anda untuk mendapatkan penanda halaman, sejarah, kata laluan dan tetapan anda yang lain pada semua peranti anda.</translation>
+<translation id="3478363558367712427">Anda boleh memilih enjin carian anda</translation>
 <translation id="3492207499832628349">Tab inkognito baharu</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Ketahui lebih lanjut<ph name="END_LINK" /> tentang kandungan yang disyorkan</translation>
 <translation id="3513704683820682405">Realiti Tambahan</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_nl.xtb b/chrome/android/java/strings/translations/android_chrome_strings_nl.xtb
index 2813b9c..64a2395 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_nl.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_nl.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Een offline exemplaar van deze pagina bekijken</translation>
 <translation id="2546283357679194313">Cookies en sitegegevens</translation>
 <translation id="2567385386134582609">AFBEELDING</translation>
+<translation id="257088987046510401">Thema's</translation>
 <translation id="2570922361219980984">Locatietoegang is ook uitgeschakeld voor dit apparaat. Schakel dit in via de <ph name="BEGIN_LINK" />Android-instellingen<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Uitgevouwen; klik om samen te vouwen.</translation>
 <translation id="2581165646603367611">Hiermee worden cookies, het cachegeheugen en andere gegevens gewist van sites waarvan Chrome denkt dat deze niet belangrijk zijn.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">De huidige pagina opnieuw laden</translation>
 <translation id="3445014427084483498">Zojuist</translation>
 <translation id="3452612588551937789">Log in met je Google-account om je bladwijzers, geschiedenis, wachtwoorden en andere instellingen op al je apparaten te gebruiken.</translation>
+<translation id="3478363558367712427">Je kunt je zoekmachine kiezen</translation>
 <translation id="3492207499832628349">Nieuw incognitotabblad</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Meer informatie<ph name="END_LINK" /> over voorgestelde content</translation>
 <translation id="3513704683820682405">Augmented reality</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_no.xtb b/chrome/android/java/strings/translations/android_chrome_strings_no.xtb
index 58500a7..af08fb7e 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_no.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_no.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Ser på en lokalt lagret versjon av denne siden</translation>
 <translation id="2546283357679194313">Informasjonskapsler og data fra nettsteder</translation>
 <translation id="2567385386134582609">BILDE</translation>
+<translation id="257088987046510401">Temaer</translation>
 <translation id="2570922361219980984">Posisjonstilgang er også slått av for denne enheten. Slå den på i <ph name="BEGIN_LINK" />Android-innstillingene<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Utvidet – klikk for å minimere.</translation>
 <translation id="2581165646603367611">Dette sletter informasjonskapsler, buffere og annen data fra nettsteder Chrome ikke tror er viktige.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_pl.xtb b/chrome/android/java/strings/translations/android_chrome_strings_pl.xtb
index 931e48b..0ccf175 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_pl.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_pl.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Oglądasz kopię offline tej strony</translation>
 <translation id="2546283357679194313">Pliki cookie i dane stron</translation>
 <translation id="2567385386134582609">OBRAZ</translation>
+<translation id="257088987046510401">Motywy</translation>
 <translation id="2570922361219980984">Dostęp do lokalizacji jest wyłączony też na tym urządzeniu. Włącz go w <ph name="BEGIN_LINK" />Ustawieniach Androida<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Rozwinięty – kliknij, by zwinąć.</translation>
 <translation id="2581165646603367611">Spowoduje to skasowanie plików cookie, pamięci podręcznej i innych danych witryn, które Chrome uzna za nieistotne.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">Ponownie załaduj bieżącą stronę</translation>
 <translation id="3445014427084483498">Przed chwilą</translation>
 <translation id="3452612588551937789">Zaloguj się na konto Google, by korzystać z zakładek, haseł, historii i innych ustawień na wszystkich urządzeniach.</translation>
+<translation id="3478363558367712427">Możesz wybrać wyszukiwarkę</translation>
 <translation id="3492207499832628349">Nowa karta incognito</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Dowiedz się więcej<ph name="END_LINK" /> o proponowanej treści</translation>
 <translation id="3513704683820682405">Rzeczywistość rozszerzona</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb b/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb
index 461df80..1d2b124 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_pt-BR.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Vendo uma cópia off-line desta página</translation>
 <translation id="2546283357679194313">Cookies e dados do site</translation>
 <translation id="2567385386134582609">IMAGEM</translation>
+<translation id="257088987046510401">Temas</translation>
 <translation id="2570922361219980984">O acesso ao local também está desativado para este dispositivo. Ative-o nas <ph name="BEGIN_LINK" />Configurações do Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Visualização expandida. Clique para recolher</translation>
 <translation id="2581165646603367611">Essa ação limpará os cookies, cache e outros dados de sites que o Chrome não acredita serem importantes.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_pt-PT.xtb b/chrome/android/java/strings/translations/android_chrome_strings_pt-PT.xtb
index a6f1802a..a601f80 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_pt-PT.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_pt-PT.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Visualização de uma cópia offline desta página</translation>
 <translation id="2546283357679194313">Cookies e dados de Web sites</translation>
 <translation id="2567385386134582609">IMAGEM</translation>
+<translation id="257088987046510401">Temas</translation>
 <translation id="2570922361219980984">O acesso à localização também está desativado para este dispositivo. Ative-o nas <ph name="BEGIN_LINK" />Definições do Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Expandido. Clique para reduzir.</translation>
 <translation id="2581165646603367611">Esta ação elimina os cookies, a cache e outros dados de sites que o Chrome não considera importantes.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">Atualizar a página atual</translation>
 <translation id="3445014427084483498">Agora mesmo</translation>
 <translation id="3452612588551937789">Inicie sessão com a sua Conta Google para aceder aos marcadores, ao histórico, às palavras-passe e a outras definições em todos os dispositivos.</translation>
+<translation id="3478363558367712427">Pode escolher o seu motor de pesquisa.</translation>
 <translation id="3492207499832628349">Novo separador anónimo</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Saiba mais<ph name="END_LINK" /> acerca do conteúdo sugerido</translation>
 <translation id="3513704683820682405">Realidade aumentada</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ro.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ro.xtb
index e928885..b669c21 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ro.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ro.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Se afișează o versiune offline a acestei pagini</translation>
 <translation id="2546283357679194313">Cookie-uri și date privind site-ul</translation>
 <translation id="2567385386134582609">IMAGINE</translation>
+<translation id="257088987046510401">Teme</translation>
 <translation id="2570922361219980984">Accesul la locație este dezactivat și pentru acest dispozitiv. Activează-l în <ph name="BEGIN_LINK" />Setări Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Afișare extinsă – dă clic pentru a restrânge.</translation>
 <translation id="2581165646603367611">Astfel, vor fi șterse cookie-urile, memoria cache și alte date ale site-urilor pe care Chrome nu le consideră importante.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb
index 54ecf81..a83f010 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ru.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Офлайн-копия страницы</translation>
 <translation id="2546283357679194313">Файлы сookie и данные сайтов</translation>
 <translation id="2567385386134582609">ИЗОБРАЖЕНИЕ</translation>
+<translation id="257088987046510401">Темы</translation>
 <translation id="2570922361219980984">Определение местоположения отключено и для самого устройства. Включите эту функцию в <ph name="BEGIN_LINK" />настройках Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Развернуто. Нажмите, чтобы свернуть.</translation>
 <translation id="2581165646603367611">Будет очищен кеш, а также удалены файлы cookie и другие данные, которые система сочтет маловажными.</translation>
@@ -883,7 +884,7 @@
 <translation id="7475688122056506577">SD-карта не найдена. Некоторые файлы могут отсутствовать.</translation>
 <translation id="7479104141328977413">Управление вкладками</translation>
 <translation id="7481312909269577407">Вперед</translation>
-<translation id="7482697587265222445">Вкладка отправлена на другие устройства</translation>
+<translation id="7482697587265222445">Вкладка отправлена на другие устройства.</translation>
 <translation id="7493994139787901920"><ph name="VERSION" /> (последнее обновление: <ph name="TIME_SINCE_UPDATE" />)</translation>
 <translation id="7494879913343971937">Показать пароли</translation>
 <translation id="7494974237137038751">сэкономлено</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_sk.xtb b/chrome/android/java/strings/translations/android_chrome_strings_sk.xtb
index ed5c8a6a..1a19bd79 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_sk.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_sk.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Zobrazuje sa offline kópia tejto stránky</translation>
 <translation id="2546283357679194313">Súbory cookie a dáta webov</translation>
 <translation id="2567385386134582609">OBRÁZOK</translation>
+<translation id="257088987046510401">Motívy</translation>
 <translation id="2570922361219980984">Prístup k polohe je vypnutý aj v tomto zariadení. Zapnite ho v <ph name="BEGIN_LINK" />Nastaveniach Androidu<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Rozbalená (zbalíte ju kliknutím)</translation>
 <translation id="2581165646603367611">Táto akcia vymaže súbory cookie, vyrovnávaciu pamäť a ďalšie údaje webov, ktoré Chrome nepovažuje za dôležité.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_sl.xtb b/chrome/android/java/strings/translations/android_chrome_strings_sl.xtb
index d0573fd..df8bf9f 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_sl.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_sl.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Ogled kopije te strani za način brez povezave.</translation>
 <translation id="2546283357679194313">Piškotki in podatki o spletnih mestih</translation>
 <translation id="2567385386134582609">SLIKA</translation>
+<translation id="257088987046510401">Teme</translation>
 <translation id="2570922361219980984">Dostop do lokacije je tudi izklopljen za to napravo. Vklopite ga lahko v <ph name="BEGIN_LINK" />nastavitvah za Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Razširjeno – kliknite, če želite strniti.</translation>
 <translation id="2581165646603367611">S tem bodo izbrisani piškotki, predpomnilnik in drugi podatki spletnih mest, ki se Chromu ne zdijo pomembni.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_sr.xtb b/chrome/android/java/strings/translations/android_chrome_strings_sr.xtb
index 021f0e3..a7a0e97c 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_sr.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_sr.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Прегледате офлајн копију ове странице</translation>
 <translation id="2546283357679194313">Колачићи и подаци о сајтовима</translation>
 <translation id="2567385386134582609">СЛИКА</translation>
+<translation id="257088987046510401">Теме</translation>
 <translation id="2570922361219980984">Приступ локацији је искључен и за овај уређај. Укључите га у <ph name="BEGIN_LINK" />Android подешавањима<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Проширено је – Кликните да бисте скупили.</translation>
 <translation id="2581165646603367611">Овим ћете обрисати колачиће, кеш и друге податке сајтова које Chrome не сматра важним.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_sv.xtb b/chrome/android/java/strings/translations/android_chrome_strings_sv.xtb
index cffccd7..485f736 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_sv.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_sv.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">En offlinekopia av sidan visas</translation>
 <translation id="2546283357679194313">Cookies och webbplatsdata</translation>
 <translation id="2567385386134582609">BILD</translation>
+<translation id="257088987046510401">Teman</translation>
 <translation id="2570922361219980984">Platsåtkomst har inaktiverats på enheten också. Aktivera det i <ph name="BEGIN_LINK" />Android-inställningarna<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Vyn har expanderats. Komprimera den genom att klicka.</translation>
 <translation id="2581165646603367611">Det här alternativet rensar cookies, cacheminnet och annan data från webbplatser som bedöms vara oviktiga.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">Läs in den aktuella sidan igen</translation>
 <translation id="3445014427084483498">Alldeles nyss</translation>
 <translation id="3452612588551937789">Logga in med ditt Google-konto så att du kan använda bokmärken, lösenord, historik med mera på alla dina enheter.</translation>
+<translation id="3478363558367712427">Du kan välja din sökmotor</translation>
 <translation id="3492207499832628349">Ny inkognitoflik</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Läs mer<ph name="END_LINK" /> om förslag på innehåll</translation>
 <translation id="3513704683820682405">Förstärkt verklighet</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_sw.xtb b/chrome/android/java/strings/translations/android_chrome_strings_sw.xtb
index f8836e3..bfe93af 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_sw.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_sw.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Unaangalia nakala ya nje ya mtandao ya ukurasa huu</translation>
 <translation id="2546283357679194313">Data ya vidakuzi na tovuti</translation>
 <translation id="2567385386134582609">PICHA</translation>
+<translation id="257088987046510401">Mandhari</translation>
 <translation id="2570922361219980984">Kipengele cha mahali pia kimezimwa kwenye kifaa hiki. Kiwashe katika <ph name="BEGIN_LINK" />Mipangilio ya Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Imepanuliwa - bofya ili ukunje.</translation>
 <translation id="2581165646603367611">Hatua hii itafuta vidakuzi, akiba na data nyingine ya tovuti ambazo Chrome haidhani kuwa muhimu.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">Pakia upya ukurasa wa sasa</translation>
 <translation id="3445014427084483498">Sasa Hivi</translation>
 <translation id="3452612588551937789">Ingia kwa kutumia Akaunti yako ya Google ili upate alamisho, historia, manenosiri na mipangilio mingine kwenye vifaa vyako vyote.</translation>
+<translation id="3478363558367712427">Unaweza kuchagua mtambo wako wa kutafuta</translation>
 <translation id="3492207499832628349">Kichupo fiche kipya</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Pata maelezo zaidi<ph name="END_LINK" /> kuhusu maudhui yaliyopendekezwa</translation>
 <translation id="3513704683820682405">Uhalisia Ulioboreshwa</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_ta.xtb b/chrome/android/java/strings/translations/android_chrome_strings_ta.xtb
index a3811e1..af8d1fd 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_ta.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_ta.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">இந்தப் பக்கத்தின் ஆஃப்லைன் நகலைப் பார்க்கிறீர்கள்</translation>
 <translation id="2546283357679194313">குக்கீகளும் தள தரவும்</translation>
 <translation id="2567385386134582609">படம்</translation>
+<translation id="257088987046510401">தீம்கள்</translation>
 <translation id="2570922361219980984">இந்தச் சாதனத்திற்கான இருப்பிட அணுகலும் முடக்கப்பட்டுள்ளது. அதை <ph name="BEGIN_LINK" />Android அமைப்புகளில்<ph name="END_LINK" /> இயக்கவும்.</translation>
 <translation id="257931822824936280">விரிவாக்கப்பட்டது - சுருக்க, கிளிக் செய்யவும்.</translation>
 <translation id="2581165646603367611">முக்கியமில்லை என்று Chrome கருதும் குக்கீகள், தற்காலிகச் சேமிப்பு, தளங்களின் பிற தரவு ஆகியவற்றை இது அழிக்கும்.</translation>
@@ -222,6 +223,7 @@
 <translation id="2593272815202181319">மோனோஸ்பேஸ்</translation>
 <translation id="2610239185026711824">கடவுச்சொல்லைப் பரிந்துரை</translation>
 <translation id="2612676031748830579">கார்டு எண்</translation>
+<translation id="2613747923081026172">குழுவை உருவாக்கு</translation>
 <translation id="2621115761605608342">குறிப்பிட்ட தளத்திற்கு JavaScriptஐ அனுமதி.</translation>
 <translation id="2625189173221582860">கடவுச்சொல் நகலெடுக்கப்பட்டது</translation>
 <translation id="2631006050119455616">சேமிக்கப்பட்டது</translation>
@@ -327,6 +329,7 @@
 <translation id="3443221991560634068">தற்போதைய பக்கத்தை மீண்டும் ஏற்றும்</translation>
 <translation id="3445014427084483498">சற்றுமுன்</translation>
 <translation id="3452612588551937789">உங்கள் எல்லா சாதனங்களிலும் புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளைப் பெற, உங்கள் Google கணக்கு மூலம் உள்நுழையவும்.</translation>
+<translation id="3478363558367712427">உங்கள் தேடல் இன்ஜினை தேர்வுசெய்யலாம்</translation>
 <translation id="3492207499832628349">புதிய மறைநிலைத் தாவல்</translation>
 <translation id="3493531032208478708">பரிந்துரைக்கப்படும் உள்ளடக்கம் பற்றி <ph name="BEGIN_LINK" />மேலும் அறிக<ph name="END_LINK" /></translation>
 <translation id="3513704683820682405">ஆக்மென்ட்டட் ரியாலிட்டி</translation>
@@ -875,7 +878,9 @@
 <translation id="7473891865547856676">வேண்டாம் நன்றி</translation>
 <translation id="7475192538862203634">இதை அடிக்கடி காண்கிறீர்கள் எனில், இந்தப் <ph name="BEGIN_LINK" />பரிந்துரைகளைப்<ph name="END_LINK" /> பயன்படுத்திப் பார்க்கவும்.</translation>
 <translation id="7475688122056506577">SD கார்டு உள்ளது. உங்கள் கோப்புகளில் சில இல்லாமல் இருக்கலாம்.</translation>
+<translation id="7479104141328977413">தாவல் நிர்வாகம்</translation>
 <translation id="7481312909269577407">அடுத்த பக்கம்</translation>
+<translation id="7482697587265222445">தாவல் உங்கள் சாதனங்களுக்கு அனுப்பப்பட்டது</translation>
 <translation id="7493994139787901920"><ph name="VERSION" /> (புதுப்பித்தது: <ph name="TIME_SINCE_UPDATE" />)</translation>
 <translation id="7494879913343971937">கடவுச்சொற்களைக் காட்டும்</translation>
 <translation id="7494974237137038751">சேமித்த டேட்டா</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_te.xtb b/chrome/android/java/strings/translations/android_chrome_strings_te.xtb
index 7322f1a..7545da21 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_te.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_te.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">ఈ పేజీ ఆఫ్‌లైన్ కాపీని వీక్షిస్తున్నారు</translation>
 <translation id="2546283357679194313">కుక్కీలు మరియు సైట్ డేటా</translation>
 <translation id="2567385386134582609">చిత్రం</translation>
+<translation id="257088987046510401">థీమ్‌లు</translation>
 <translation id="2570922361219980984">ఈ పరికరానికి స్థానం యాక్సెస్ కూడా ఆఫ్ చేయబడింది. దీనిని <ph name="BEGIN_LINK" />Android సెట్టింగ్‌లు<ph name="END_LINK" />లో తిరిగి ఆన్ చేయండి.</translation>
 <translation id="257931822824936280">విస్తరించ‌బడింది - కుదించడానికి క్లిక్ చేయండి.</translation>
 <translation id="2581165646603367611">ఇది Chrome ముఖ్యమైనదిగా భావించని కుక్కీలు, కాష్, సైట్‌ల ఇతర డేటాను తీసివేస్తుంది.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_th.xtb b/chrome/android/java/strings/translations/android_chrome_strings_th.xtb
index 4e8c74c..8a22a6a 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_th.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_th.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">ดูสำเนาแบบออฟไลน์ของหน้านี้</translation>
 <translation id="2546283357679194313">คุกกี้และข้อมูลเว็บไซต์</translation>
 <translation id="2567385386134582609">รูปภาพ</translation>
+<translation id="257088987046510401">ธีม</translation>
 <translation id="2570922361219980984">การเข้าถึงตำแหน่งสำหรับอุปกรณ์เครื่องนี้ปิดอยู่ เปิดการเข้าถึงได้ใน<ph name="BEGIN_LINK" />การตั้งค่า Android<ph name="END_LINK" /></translation>
 <translation id="257931822824936280">ขยาย - คลิกเพื่อยุบ</translation>
 <translation id="2581165646603367611">การดำเนินการนี้จะล้างคุกกี้ แคช และข้อมูลอื่นๆ ของเว็บไซต์ที่ Chrome คิดว่าไม่สำคัญ</translation>
@@ -348,7 +349,7 @@
 <translation id="3600792891314830896">ปิดเสียงเว็บไซต์ที่เล่นเสียง</translation>
 <translation id="3616113530831147358">เสียง</translation>
 <translation id="3620176948598597475">การรีเซ็ตจะลบประวัติโปรแกรมประหยัดอินเทอร์เน็ต รวมถึงรายการเว็บไซต์ที่เข้าชม</translation>
-<translation id="3630011985153972676">อนุญาตให้ Chrome ดาวน์โหลดบทความให้คุณเมื่อเชื่อมต่อ Wi-Fi ภายใต้การตั้งค่า</translation>
+<translation id="3630011985153972676">อนุญาตให้ Chrome ดาวน์โหลดบทความสำหรับคุณเมื่อเชื่อมต่อ Wi-Fi ภายใต้การตั้งค่า</translation>
 <translation id="3632295766818638029">เปิดเผยรหัสผ่าน</translation>
 <translation id="363596933471559332">ลงชื่อเข้าใช้เว็บไซต์โดยอัตโนมัติโดยใช้ข้อมูลเข้าสู่ระบบที่เก็บไว้ เมื่อฟีเจอร์นี้ปิดอยู่ ระบบจะขอให้คุณยืนยันทุกครั้งก่อนลงชื่อเข้าใช้เว็บไซต์</translation>
 <translation id="3658159451045945436">การรีเซ็ตจะลบประวัติการประหยัดเน็ต รวมถึงรายการเว็บไซต์ที่เข้าชม</translation>
@@ -986,7 +987,7 @@
 <translation id="8200772114523450471">ทำต่อ</translation>
 <translation id="8209050860603202033">เปิดรูปภาพ</translation>
 <translation id="8220488350232498290">พื้นที่ที่ใช้ไปสำหรับการดาวน์โหลด <ph name="GIGABYTES" /> GB</translation>
-<translation id="8224471946457685718">ดาวน์โหลดบทความให้คุณผ่าน Wi-Fi</translation>
+<translation id="8224471946457685718">ดาวน์โหลดบทความสำหรับคุณผ่าน Wi-Fi</translation>
 <translation id="8232956427053453090">เก็บข้อมูลไว้</translation>
 <translation id="8249310407154411074">เลื่อนไปบนสุด</translation>
 <translation id="8250920743982581267">เอกสาร</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_tr.xtb b/chrome/android/java/strings/translations/android_chrome_strings_tr.xtb
index e97f8f2..b3c92173 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_tr.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_tr.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Bu sayfanın çevrimdışı bir kopyası görüntüleniyor</translation>
 <translation id="2546283357679194313">Çerezler ve site verileri</translation>
 <translation id="2567385386134582609">IMAGE</translation>
+<translation id="257088987046510401">Temalar</translation>
 <translation id="2570922361219980984">Konum erişimi bu cihaz için de kapalı. Konum erişimini <ph name="BEGIN_LINK" />Android Ayarları<ph name="END_LINK" />'ndan açın.</translation>
 <translation id="257931822824936280">Genişletildi - Daraltmak için tıklayın.</translation>
 <translation id="2581165646603367611">Bu işlem Chrome'un önemli olmadığını düşündüğü çerezleri, önbelleği ve diğer site verilerini temizleyecek.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_uk.xtb b/chrome/android/java/strings/translations/android_chrome_strings_uk.xtb
index 713c069b..758c58a 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_uk.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_uk.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Перегляд копії сторінки в режимі офлайн</translation>
 <translation id="2546283357679194313">Файли cookie та дані із сайтів</translation>
 <translation id="2567385386134582609">ЗОБРАЖЕННЯ</translation>
+<translation id="257088987046510401">Теми</translation>
 <translation id="2570922361219980984">На цьому пристрої також вимкнено доступ до геоданих. Увімкніть його в <ph name="BEGIN_LINK" />налаштуваннях Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Розгорнуто – натисніть, щоб згорнути.</translation>
 <translation id="2581165646603367611">Буде видалено файли cookie, кеш та інші дані сайтів, які Chrome визначив як неважливі.</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_vi.xtb b/chrome/android/java/strings/translations/android_chrome_strings_vi.xtb
index 2baf07423..765bde2 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_vi.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_vi.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">Xem bản sao ngoại tuyến của trang này</translation>
 <translation id="2546283357679194313">Cookie và dữ liệu trang web</translation>
 <translation id="2567385386134582609">HÌNH ẢNH</translation>
+<translation id="257088987046510401">Chủ đề</translation>
 <translation id="2570922361219980984">Quyền truy cập vị trí cũng đã bị tắt đối với thiết bị này. Hãy bật trong <ph name="BEGIN_LINK" />Cài đặt Android<ph name="END_LINK" />.</translation>
 <translation id="257931822824936280">Đã mở rộng - nhấp để thu gọn.</translation>
 <translation id="2581165646603367611">Thao tác này sẽ xóa cookie, bộ nhớ đệm và các dữ liệu khác của các trang web mà Chrome cho rằng không quan trọng.</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">Tải lại trang hiện tại</translation>
 <translation id="3445014427084483498">Vừa xong</translation>
 <translation id="3452612588551937789">Đăng nhập bằng Tài khoản Google để sử dụng dấu trang, lịch sử hoạt động, mật khẩu và các tùy chọn cài đặt khác trên tất cả thiết bị của bạn.</translation>
+<translation id="3478363558367712427">Bạn có thể chọn công cụ tìm kiếm</translation>
 <translation id="3492207499832628349">Tab ẩn danh mới</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />Tìm hiểu thêm<ph name="END_LINK" /> về nội dung được đề xuất</translation>
 <translation id="3513704683820682405">Thực tế tăng cường</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb b/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb
index 7be1fd5..7072399 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_zh-CN.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">正在查看此网页的离线副本</translation>
 <translation id="2546283357679194313">Cookie 和网站数据</translation>
 <translation id="2567385386134582609">图片</translation>
+<translation id="257088987046510401">主题背景</translation>
 <translation id="2570922361219980984">此设备的位置信息使用权也已关闭;若想开启这项权限,请转到 <ph name="BEGIN_LINK" />Android 设置<ph name="END_LINK" />。</translation>
 <translation id="257931822824936280">已展开 - 点击此处即可收起。</translation>
 <translation id="2581165646603367611">这会清除 Chrome 认为不重要的网站的 Cookie、缓存和其他数据。</translation>
@@ -328,6 +329,7 @@
 <translation id="3443221991560634068">重新加载当前网页</translation>
 <translation id="3445014427084483498">刚刚</translation>
 <translation id="3452612588551937789">登录 Google 帐号,即可获取您在任何登录过的设备上的书签、密码、历史记录及其他设置。</translation>
+<translation id="3478363558367712427">您可自行选择要使用的搜索引擎</translation>
 <translation id="3492207499832628349">打开新的无痕式标签页</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />详细了解<ph name="END_LINK" />推荐内容</translation>
 <translation id="3513704683820682405">增强现实</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_zh-TW.xtb b/chrome/android/java/strings/translations/android_chrome_strings_zh-TW.xtb
index 1119f6d..71f3219 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_zh-TW.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_zh-TW.xtb
@@ -214,6 +214,7 @@
 <translation id="2536728043171574184">目前瀏覽的是這個網頁的離線複本</translation>
 <translation id="2546283357679194313">Cookie 和網站資料</translation>
 <translation id="2567385386134582609">圖片</translation>
+<translation id="257088987046510401">主題</translation>
 <translation id="2570922361219980984">此外,這部裝置的位置資訊存取權已關閉。請在 <ph name="BEGIN_LINK" />Android 設定<ph name="END_LINK" />中予以開啟。</translation>
 <translation id="257931822824936280">已展開 - 按一下即可收合。</translation>
 <translation id="2581165646603367611">這項操作會清除不重要的網站 Cookie、快取等其他資料 (Chrome 會自動判斷資料的重要性)。</translation>
@@ -329,6 +330,7 @@
 <translation id="3443221991560634068">重新載入目前網頁</translation>
 <translation id="3445014427084483498">剛剛</translation>
 <translation id="3452612588551937789">只要登入 Google 帳戶,即可在你的所有裝置上使用自己的書籤、密碼、歷史記錄和其他設定。</translation>
+<translation id="3478363558367712427">你可以選擇搜尋引擎</translation>
 <translation id="3492207499832628349">新無痕式分頁</translation>
 <translation id="3493531032208478708"><ph name="BEGIN_LINK" />進一步瞭解<ph name="END_LINK" />建議的內容</translation>
 <translation id="3513704683820682405">擴增實境</translation>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeHttpAuthHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeHttpAuthHandlerTest.java
index ff0586a1..d3ae0bb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeHttpAuthHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeHttpAuthHandlerTest.java
@@ -19,8 +19,8 @@
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.tab.SadTab;
 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;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
@@ -37,8 +37,7 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ChromeHttpAuthHandlerTest {
     @Rule
-    public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
     private EmbeddedTestServer mTestServer;
 
     @Before
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ExampleUiCaptureTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ExampleUiCaptureTest.java
index ad9d5ec..3ad26ae 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ExampleUiCaptureTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ExampleUiCaptureTest.java
@@ -15,8 +15,8 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.test.ScreenShooter;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.ui.test.util.UiRestriction;
 
 import java.io.IOException;
@@ -29,8 +29,7 @@
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // Tab switcher button only exists on phones.
 public class ExampleUiCaptureTest {
     @Rule
-    public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     @Rule
     public ScreenShooter mScreenShooter = new ScreenShooter();
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 b49ae78..bd78420bc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/NavigationPopupTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/NavigationPopupTest.java
@@ -26,8 +26,8 @@
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.profiles.Profile;
-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;
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.NavigationEntry;
@@ -47,8 +47,7 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class NavigationPopupTest {
     @Rule
-    public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     private static final int INVALID_NAVIGATION_INDEX = -1;
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/bar_component/KeyboardAccessoryViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/bar_component/KeyboardAccessoryViewTest.java
index 079ab95..8f2a39bcb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/bar_component/KeyboardAccessoryViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/bar_component/KeyboardAccessoryViewTest.java
@@ -42,14 +42,13 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.bar_component.KeyboardAccessoryProperties.AutofillBarItem;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.bar_component.KeyboardAccessoryProperties.BarItem;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.bar_component.KeyboardAccessoryProperties.TabLayoutBarItem;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.data.KeyboardAccessoryData;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.tab_layout_component.KeyboardAccessoryTabLayoutCoordinator;
-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.Features;
 import org.chromium.components.autofill.AutofillSuggestion;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -74,8 +73,7 @@
     private BlockingQueue<KeyboardAccessoryView> mKeyboardAccessoryView;
 
     @Rule
-    public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     @Before
     public void setUp() throws InterruptedException {
@@ -226,4 +224,4 @@
 
         assertTrue(clickRecorded.get());
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_component/AccessorySheetViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_component/AccessorySheetViewTest.java
index d16257c..8209dbe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_component/AccessorySheetViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_component/AccessorySheetViewTest.java
@@ -41,11 +41,10 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.AccessoryTabType;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.data.KeyboardAccessoryData.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.ViewUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.DeferredViewStubInflationProvider;
@@ -68,8 +67,7 @@
     private BlockingQueue<AccessorySheetView> mViewPager;
 
     @Rule
-    public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     @Before
     public void setUp() throws InterruptedException {
@@ -236,4 +234,4 @@
                     public void onTabShown() {}
                 });
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/AccessorySheetTabViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/AccessorySheetTabViewTest.java
index c4bf29a..4aee97a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/AccessorySheetTabViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/AccessorySheetTabViewTest.java
@@ -25,14 +25,13 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.AccessoryTabType;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.data.KeyboardAccessoryData;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.sheet_component.AccessorySheetCoordinator;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.sheet_tabs.AccessorySheetTabModel.AccessorySheetDataPiece;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.sheet_tabs.AccessorySheetTabModel.AccessorySheetDataPiece.Type;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -53,8 +52,7 @@
     private AtomicReference<RecyclerView> mView = new AtomicReference<>();
 
     @Rule
-    public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     /**
      * This helper method inflates the accessory sheet and loads the given layout as minimalistic
@@ -146,4 +144,4 @@
         TestThreadUtils.runOnUiThreadBlocking(btn::performClick);
         assertThat(clicked.get(), is(true));
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/PasswordAccessorySheetModernViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/PasswordAccessorySheetModernViewTest.java
index 1a0c1220..e935aa8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/PasswordAccessorySheetModernViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/PasswordAccessorySheetModernViewTest.java
@@ -27,14 +27,13 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.AccessoryTabType;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.data.KeyboardAccessoryData;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.data.KeyboardAccessoryData.UserInfo;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.sheet_component.AccessorySheetCoordinator;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.sheet_tabs.AccessorySheetTabModel.AccessorySheetDataPiece;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -53,8 +52,7 @@
     private AtomicReference<RecyclerView> mView = new AtomicReference<>();
 
     @Rule
-    public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     @Before
     public void setUp() throws InterruptedException {
@@ -155,4 +153,4 @@
         assertThat(view, instanceOf(ChipView.class));
         return (ChipView) view;
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/PasswordAccessorySheetViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/PasswordAccessorySheetViewTest.java
index 7323193..6d53036 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/PasswordAccessorySheetViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/sheet_tabs/PasswordAccessorySheetViewTest.java
@@ -28,14 +28,13 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.AccessoryTabType;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.data.KeyboardAccessoryData;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.data.KeyboardAccessoryData.UserInfo;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.sheet_component.AccessorySheetCoordinator;
 import org.chromium.chrome.browser.autofill.keyboard_accessory.sheet_tabs.AccessorySheetTabModel.AccessorySheetDataPiece;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -53,8 +52,7 @@
     private AtomicReference<RecyclerView> mView = new AtomicReference<>();
 
     @Rule
-    public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     /**
      * This helper method inflates the accessory sheet and loads the given layout as minimalistic
@@ -166,4 +164,4 @@
         assertThat(view, instanceOf(TextView.class));
         return (TextView) view;
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/tab_layout_component/KeyboardAccessoryTabLayoutViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/tab_layout_component/KeyboardAccessoryTabLayoutViewTest.java
index 3d7df67..cb30ab4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/tab_layout_component/KeyboardAccessoryTabLayoutViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/tab_layout_component/KeyboardAccessoryTabLayoutViewTest.java
@@ -142,4 +142,4 @@
         onView(isTabWithDescription("SecondTab")).check(matches(isDisplayed()));
         onView(isTabWithDescription("ThirdTab")).check(matches(isDisplayed()));
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
index 32cd764..88b0510d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
@@ -36,7 +36,6 @@
 import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -72,8 +71,6 @@
 @Features.EnableFeatures(ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS)
 @DisableIf.Device(type = {UiDisableIf.TABLET}) // https://crbug.com/944061.
 public class FeedNewTabPageTest {
-    private static final String TEST_FEED =
-            UrlUtils.getIsolatedTestFilePath("/chrome/test/data/android/feed/feed_large.gcl.bin");
     private static final int ARTICLE_SECTION_HEADER_POSITION = 1;
     private static final int SIGNIN_PROMO_POSITION = 2;
 
@@ -92,10 +89,6 @@
 
     @Before
     public void setUp() throws Exception {
-        TestNetworkClient client = new TestNetworkClient();
-        client.setNetworkResponseFile(TEST_FEED);
-        FeedProcessScopeFactory.setTestNetworkClient(client);
-
         mActivityTestRule.startMainActivityWithURL("about:blank");
 
         mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/init/ChainedTasksTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/init/ChainedTasksTest.java
index 1ab18b2..1bfa1f7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/init/ChainedTasksTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/init/ChainedTasksTest.java
@@ -50,11 +50,16 @@
                 Arrays.asList(new String[] {"First", "Second", "Third"});
         final List<String> messages = new ArrayList<>();
         final ChainedTasks tasks = new ChainedTasks();
-        for (String message : expectedMessages) tasks.add(new TestRunnable(messages, message));
+        for (String message : expectedMessages) {
+            tasks.add(UiThreadTaskTraits.DEFAULT, new TestRunnable(messages, message));
+        }
 
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            tasks.start(true);
-            Assert.assertEquals(expectedMessages, messages);
+        TestThreadUtils.runBlockingWithTraits(UiThreadTaskTraits.DEFAULT, new Runnable() {
+            @Override
+            public void run() {
+                tasks.start(true);
+                Assert.assertEquals(expectedMessages, messages);
+            }
         });
     }
 
@@ -65,7 +70,7 @@
         final Semaphore finished = new Semaphore(0);
         final ChainedTasks tasks = new ChainedTasks();
 
-        tasks.add(new Runnable() {
+        tasks.add(UiThreadTaskTraits.DEFAULT, new Runnable() {
             @Override
             public void run() {
                 try {
@@ -78,8 +83,10 @@
 
         List<String> expectedMessages = Arrays.asList(new String[] {"First", "Second", "Third"});
         final List<String> messages = new ArrayList<>();
-        for (String message : expectedMessages) tasks.add(new TestRunnable(messages, message));
-        tasks.add(new Runnable() {
+        for (String message : expectedMessages) {
+            tasks.add(UiThreadTaskTraits.DEFAULT, new TestRunnable(messages, message));
+        }
+        tasks.add(UiThreadTaskTraits.DEFAULT, new Runnable() {
             @Override
             public void run() {
                 finished.release();
@@ -102,8 +109,10 @@
         final ChainedTasks tasks = new ChainedTasks();
         final Semaphore finished = new Semaphore(0);
 
-        for (String message : expectedMessages) tasks.add(new TestRunnable(messages, message));
-        tasks.add(new Runnable() {
+        for (String message : expectedMessages) {
+            tasks.add(UiThreadTaskTraits.DEFAULT, new TestRunnable(messages, message));
+        }
+        tasks.add(UiThreadTaskTraits.DEFAULT, new Runnable() {
             @Override
             public void run() {
                 finished.release();
@@ -131,9 +140,9 @@
 
         // Posts 2 tasks, waits for a high priority task to be posted from another thread, and
         // carries on.
-        tasks.add(new TestRunnable(messages, "First"));
-        tasks.add(new TestRunnable(messages, "Second"));
-        tasks.add(new Runnable() {
+        tasks.add(UiThreadTaskTraits.DEFAULT, new TestRunnable(messages, "First"));
+        tasks.add(UiThreadTaskTraits.DEFAULT, new TestRunnable(messages, "Second"));
+        tasks.add(UiThreadTaskTraits.DEFAULT, new Runnable() {
             @Override
             public void run() {
                 try {
@@ -144,8 +153,8 @@
                 }
             }
         });
-        tasks.add(new TestRunnable(messages, "Third"));
-        tasks.add(new Runnable() {
+        tasks.add(UiThreadTaskTraits.DEFAULT, new TestRunnable(messages, "Third"));
+        tasks.add(UiThreadTaskTraits.DEFAULT, new Runnable() {
             @Override
             public void run() {
                 finished.release();
@@ -169,16 +178,16 @@
         final ChainedTasks tasks = new ChainedTasks();
         final Semaphore finished = new Semaphore(0);
 
-        tasks.add(new TestRunnable(messages, "First"));
-        tasks.add(new TestRunnable(messages, "Second"));
-        tasks.add(new Runnable() {
+        tasks.add(UiThreadTaskTraits.DEFAULT, new TestRunnable(messages, "First"));
+        tasks.add(UiThreadTaskTraits.DEFAULT, new TestRunnable(messages, "Second"));
+        tasks.add(UiThreadTaskTraits.DEFAULT, new Runnable() {
             @Override
             public void run() {
                 tasks.cancel();
             }
         });
-        tasks.add(new TestRunnable(messages, "Third"));
-        tasks.add(new Runnable() {
+        tasks.add(UiThreadTaskTraits.DEFAULT, new TestRunnable(messages, "Third"));
+        tasks.add(UiThreadTaskTraits.DEFAULT, new Runnable() {
             @Override
             public void run() {
                 finished.release();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/init/ChromeBrowserInitializerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/init/ChromeBrowserInitializerTest.java
index a4e2cb0..e9e05cb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/init/ChromeBrowserInitializerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/init/ChromeBrowserInitializerTest.java
@@ -12,6 +12,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 import java.util.concurrent.Semaphore;
@@ -31,7 +32,7 @@
     @Test
     @SmallTest
     public void testSynchronousInitialization() throws Exception {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
+        TestThreadUtils.runBlockingWithTraits(UiThreadTaskTraits.BOOTSTRAP, () -> {
             Assert.assertFalse(mInstance.hasNativeInitializationCompleted());
             mInstance.handleSynchronousStartup();
             Assert.assertTrue(mInstance.hasNativeInitializationCompleted());
@@ -49,7 +50,7 @@
                 done.release();
             }
         };
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
+        TestThreadUtils.runBlockingWithTraits(UiThreadTaskTraits.BOOTSTRAP, () -> {
             Assert.assertFalse(mInstance.hasNativeInitializationCompleted());
             mInstance.handlePreNativeStartup(parts);
             mInstance.handlePostNativeStartup(true, parts);
@@ -58,8 +59,9 @@
                     "Should not be synchronous", mInstance.hasNativeInitializationCompleted());
             return true;
         });
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertFalse("Inititialization tasks should yield to new UI thread tasks",
+        TestThreadUtils.runBlockingWithTraits(UiThreadTaskTraits.BOOTSTRAP, () -> {
+            Assert.assertFalse(
+                    "Inititialization tasks should yield to new high priority UI thread tasks",
                     mInstance.hasNativeInitializationCompleted());
         });
         Assert.assertTrue(done.tryAcquire(10, TimeUnit.SECONDS));
@@ -69,14 +71,14 @@
     @SmallTest
     public void testDelayedTasks() throws Exception {
         final Semaphore done = new Semaphore(0);
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
+        TestThreadUtils.runBlockingWithTraits(UiThreadTaskTraits.BOOTSTRAP, () -> {
             mInstance.runNowOrAfterNativeInitialization(done::release);
             Assert.assertFalse("Should not run synchronously", done.tryAcquire());
             mInstance.handleSynchronousStartup();
             Assert.assertTrue(done.tryAcquire());
             return true;
         });
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
+        TestThreadUtils.runBlockingWithTraits(UiThreadTaskTraits.BOOTSTRAP, () -> {
             mInstance.runNowOrAfterNativeInitialization(done::release);
             // Runs right away in the same task is initialization is done.
             Assert.assertTrue(done.tryAcquire());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java
index 4d5d01a6..fd093d0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java
@@ -23,8 +23,8 @@
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 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.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.test.util.Criteria;
@@ -51,8 +51,7 @@
     @Rule
     public UiThreadTestRule mUiThreadTestRule = new UiThreadTestRule();
     @Rule
-    public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     private EmbeddedTestServer mTestServer;
     private ChromeTabbedActivity mActivity;
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 1c10062..beba824 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
@@ -38,6 +38,7 @@
 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.ActivityUtils;
 import org.chromium.chrome.test.util.MenuUtils;
 import org.chromium.chrome.test.util.OmniboxTestUtils;
@@ -59,8 +60,7 @@
     private static final long HOURS_IN_MS = 60 * 60 * 1000L;
 
     @Rule
-    public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     private UserActionTester mActionTester;
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java
index 1eb8265d..5f3dbdf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java
@@ -27,6 +27,7 @@
 import org.chromium.chrome.browser.webapps.WebApkActivity;
 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;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.content_public.browser.test.util.Criteria;
@@ -54,8 +55,8 @@
     private static final String WEBAPK_SUFFIX = WebApkActivity.STARTUP_UMA_HISTOGRAM_SUFFIX;
 
     @Rule
-    public ChromeActivityTestRule<ChromeTabbedActivity> mTabbedActivityTestRule =
-            new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+    public ChromeTabbedActivityTestRule mTabbedActivityTestRule =
+            new ChromeTabbedActivityTestRule();
     @Rule
     public ChromeActivityTestRule<WebApkActivity> mWebApkActivityTestRule =
             new ChromeActivityTestRule<>(WebApkActivity.class);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationTestRule.java
index a6bd7873..e0c96046 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationTestRule.java
@@ -10,10 +10,9 @@
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 
-import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.preferences.website.ContentSettingValues;
 import org.chromium.chrome.browser.preferences.website.PermissionInfo;
-import org.chromium.chrome.test.ChromeActivityTestRule;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.notifications.MockNotificationManagerProxy;
 import org.chromium.chrome.test.util.browser.notifications.MockNotificationManagerProxy.NotificationEntry;
 import org.chromium.content_public.browser.test.util.Criteria;
@@ -28,7 +27,7 @@
  *
  * Web Notifications are only supported on Android JellyBean and beyond.
  */
-public class NotificationTestRule extends ChromeActivityTestRule<ChromeTabbedActivity> {
+public class NotificationTestRule extends ChromeTabbedActivityTestRule {
     /** The maximum time to wait for a criteria to become valid. */
     private static final long MAX_TIME_TO_POLL_MS = scaleTimeout(6000);
 
@@ -37,10 +36,6 @@
 
     private MockNotificationManagerProxy mMockNotificationManager;
 
-    public NotificationTestRule() {
-        super(ChromeTabbedActivity.class);
-    }
-
     private void setUp() throws Exception {
         // The NotificationPlatformBridge must be overriden prior to the browser process starting.
         mMockNotificationManager = new MockNotificationManagerProxy();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableBookmarksEditingUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableBookmarksEditingUnitTest.java
index 971cf9a..3d341c3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableBookmarksEditingUnitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableBookmarksEditingUnitTest.java
@@ -21,6 +21,7 @@
 
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.partnercustomizations.TestPartnerBrowserCustomizationsDelayedProvider;
 import org.chromium.chrome.test.partnercustomizations.TestPartnerBrowserCustomizationsProvider;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
@@ -140,13 +141,12 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             PartnerBrowserCustomizations.initializeAsync(mTestRule.getContextWrapper(), 2000);
         });
-        PartnerBrowserCustomizations.setOnInitializeAsyncFinished(mTestRule.getCallback(), 300);
-
-        mTestRule.getCallbackLock().acquire();
+        PartnerBrowserCustomizations.setOnInitializeAsyncFinished(mTestRule.getCallback());
 
         Assert.assertFalse(PartnerBrowserCustomizations.isInitialized());
         Assert.assertFalse(PartnerBrowserCustomizations.isBookmarksEditingDisabled());
 
+        TestPartnerBrowserCustomizationsDelayedProvider.unblockQuery();
         PartnerBrowserCustomizations.setOnInitializeAsyncFinished(mTestRule.getCallback(), 3000);
 
         mTestRule.getCallbackLock().acquire();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeUnitTest.java
index 1cbd880e..324cf389 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeUnitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeUnitTest.java
@@ -21,6 +21,7 @@
 
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.partnercustomizations.TestPartnerBrowserCustomizationsDelayedProvider;
 import org.chromium.chrome.test.partnercustomizations.TestPartnerBrowserCustomizationsProvider;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
@@ -140,13 +141,12 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             PartnerBrowserCustomizations.initializeAsync(mTestRule.getContextWrapper(), 2000);
         });
-        PartnerBrowserCustomizations.setOnInitializeAsyncFinished(mTestRule.getCallback(), 300);
-
-        mTestRule.getCallbackLock().acquire();
+        PartnerBrowserCustomizations.setOnInitializeAsyncFinished(mTestRule.getCallback());
 
         Assert.assertFalse(PartnerBrowserCustomizations.isInitialized());
         Assert.assertFalse(PartnerBrowserCustomizations.isIncognitoDisabled());
 
+        TestPartnerBrowserCustomizationsDelayedProvider.unblockQuery();
         PartnerBrowserCustomizations.setOnInitializeAsyncFinished(mTestRule.getCallback(), 3000);
 
         mTestRule.getCallbackLock().acquire();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java
index 1e81e38..42ca009 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java
@@ -24,7 +24,6 @@
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.autofill.CardUnmaskPrompt;
 import org.chromium.chrome.browser.autofill.CardUnmaskPrompt.CardUnmaskObserverForTest;
 import org.chromium.chrome.browser.payments.PaymentRequestImpl.PaymentRequestServiceObserverForTest;
@@ -34,7 +33,7 @@
 import org.chromium.chrome.browser.payments.ui.PaymentRequestUI.PaymentRequestObserverForTest;
 import org.chromium.chrome.browser.widget.prefeditor.EditorObserverForTest;
 import org.chromium.chrome.browser.widget.prefeditor.EditorTextField;
-import org.chromium.chrome.test.ChromeActivityTestRule;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.test.util.Criteria;
@@ -61,7 +60,7 @@
 /**
  * Custom ActivityTestRule for integration test for payments.
  */
-public class PaymentRequestTestRule extends ChromeActivityTestRule<ChromeTabbedActivity>
+public class PaymentRequestTestRule extends ChromeTabbedActivityTestRule
         implements PaymentRequestObserverForTest, PaymentRequestServiceObserverForTest,
                    CardUnmaskObserverForTest, EditorObserverForTest {
     /** Flag for installing a payment app without instruments. */
@@ -129,7 +128,7 @@
     private final MainActivityStartCallback mCallback;
 
     public PaymentRequestTestRule(String testFileName, MainActivityStartCallback callback) {
-        super(ChromeTabbedActivity.class);
+        super();
         mReadyForInput = new PaymentsCallbackHelper<>();
         mReadyToPay = new PaymentsCallbackHelper<>();
         mSelectionChecked = new PaymentsCallbackHelper<>();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/MockTab.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/MockTab.java
index 6f855669..62f4c76 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/MockTab.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/MockTab.java
@@ -13,6 +13,6 @@
      * these two fields only.
      */
     public MockTab(int id, boolean incognito) {
-        super(id, Tab.INVALID_TAB_ID, incognito, null, null, null, null, null);
+        super(id, Tab.INVALID_TAB_ID, incognito, null, null, null, null);
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabTestUtils.java
index 1707c75..4fa0b33e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabTestUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabTestUtils.java
@@ -89,4 +89,13 @@
         RewindableIterator<TabObserver> observers = tab.getTabObservers();
         while (observers.hasNext()) observers.next().onDidChangeThemeColor(tab, color);
     }
+
+    /**
+     * Restore tab's internal states from a given {@link TabState}.
+     * @param tab {@link Tab} to restore.
+     * @param state {@link TabState} containing the state info to restore the tab with.
+     */
+    public static void restoreFieldsFromState(Tab tab, TabState state) {
+        tab.restoreFieldsFromState(state);
+    }
 }
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 5db9ee6..ba308bc8 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
@@ -74,7 +74,7 @@
                                     .setWindow(mActivityTestRule.getActivity().getWindowAndroid())
                                     .setLaunchType(TabLaunchType.FROM_LONGPRESS_BACKGROUND)
                                     .build();
-                bgTab.initialize(null, new TabDelegateFactory(), true, false);
+                bgTab.initialize(null, new TabDelegateFactory(), true, null, false);
                 return bgTab;
             }
         });
@@ -119,7 +119,7 @@
                                     .setWindow(mActivityTestRule.getActivity().getWindowAndroid())
                                     .setLaunchType(TabLaunchType.FROM_LONGPRESS_BACKGROUND)
                                     .build();
-                bgTab.initialize(null, new TabDelegateFactory(), true, false);
+                bgTab.initialize(null, new TabDelegateFactory(), true, null, false);
                 bgTab.loadUrl(new LoadUrlParams(mTestUrl));
                 bgTab.show(TabSelectionType.FROM_USER);
                 return bgTab;
@@ -137,7 +137,7 @@
                                     .setWindow(mActivityTestRule.getActivity().getWindowAndroid())
                                     .setLaunchType(TabLaunchType.FROM_LONGPRESS_BACKGROUND)
                                     .build();
-                bgTab.initialize(null, new TabDelegateFactory(), true, false);
+                bgTab.initialize(null, new TabDelegateFactory(), true, null, false);
                 bgTab.loadUrl(new LoadUrlParams(mTestUrl));
                 // Simulate the renderer being killed by the OS.
                 ChromeTabUtils.simulateRendererKilledForTesting(bgTab, false);
@@ -157,7 +157,7 @@
                                     .setWindow(mActivityTestRule.getActivity().getWindowAndroid())
                                     .setLaunchType(TabLaunchType.FROM_LONGPRESS_BACKGROUND)
                                     .build();
-                bgTab.initialize(null, new TabDelegateFactory(), true, false);
+                bgTab.initialize(null, new TabDelegateFactory(), true, null, false);
                 bgTab.show(TabSelectionType.FROM_USER);
                 return bgTab;
             }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
index 5a57f1f..6b7b103 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -34,6 +34,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabBuilder;
 import org.chromium.chrome.browser.tab.TabState;
+import org.chromium.chrome.browser.tab.TabTestUtils;
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator;
 import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabModelSelectorMetadata;
 import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabPersistentStoreObserver;
@@ -111,11 +112,12 @@
 
         @Override
         public Tab createFrozenTab(TabState state, int id, int index) {
-            Tab tab = TabBuilder.createFromFrozenState(state)
+            Tab tab = TabBuilder.createFromFrozenState()
                               .setId(id)
                               .setParentId(state.parentId)
                               .setIncognito(state.isIncognito())
                               .build();
+            TabTestUtils.restoreFieldsFromState(tab, state);
             mSelector.getModel(mIsIncognito).addTab(tab, index, TabLaunchType.FROM_RESTORE);
             storeTabInfo(state, id);
             return tab;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java
index 878de8b..18a35b61 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java
@@ -70,8 +70,8 @@
  * &#064;Restriction(RESTRICTION_TYPE_PHONE) // Tab switcher button only exists on phones.
  * public class ExampleUiCaptureTest {
  *     &#064;Rule
- *     public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
- *             new ChromeActivityTestRule<>(ChromeTabbedActivity.class);
+ *     public ChromeTabbedActivityTestRule mActivityTestRule =
+ *             new ChromeTabbedActivityTestRule();
  *
  *     &#064;Rule
  *     public ScreenShooter mScreenShooter = new ScreenShooter();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
index 448e7b1..823e5225 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
@@ -119,7 +119,7 @@
                 activityTabObserverCaptor.capture());
         doNothing()
                 .when(tabFromFactory)
-                .initialize(webContentsCaptor.capture(), any(), anyBoolean(), anyBoolean());
+                .initialize(webContentsCaptor.capture(), any(), anyBoolean(), any(), anyBoolean());
     }
 
     @Override
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 9fe6a0a..c18ee29 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-75.0.3754.0_rc-r1-merged.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-75.0.3755.0_rc-r1-merged.afdo.bz2
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/values-v17/dimens.xml b/chrome/android/touchless/java/res/values-v17/dimens.xml
index f02e1e1b..baeac27 100644
--- a/chrome/android/touchless/java/res/values-v17/dimens.xml
+++ b/chrome/android/touchless/java/res/values-v17/dimens.xml
@@ -24,7 +24,6 @@
     <dimen name="open_last_tab_button_padding_vertical">8dp</dimen>
     <dimen name="open_last_tab_icon_size">16dp</dimen>
     <dimen name="open_last_tab_primary_text_margin_left">8dp</dimen>
-    <dimen name="open_last_tab_timestamp_min_width">105dp</dimen>
 
     <!-- Most likely carousel dimensions. -->
     <dimen name="most_likely_tile_horizontal_spacer">6dp</dimen>
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ContentSuggestionsViewBinder.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ContentSuggestionsViewBinder.java
index c6aa5f81..5781f7e 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ContentSuggestionsViewBinder.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ContentSuggestionsViewBinder.java
@@ -30,6 +30,10 @@
                     callback.onResult(new ScrollPositionInfo(index, offset));
                 }
             });
+        } else if (TouchlessNewTabPageProperties.FOCUS_CHANGE_CALLBACK == propertyKey) {
+            // Ignored.
+        } else if (TouchlessNewTabPageProperties.INITIAL_FOCUS == propertyKey) {
+            // Ignored.
         } else if (TouchlessNewTabPageProperties.INITIAL_SCROLL_POSITION == propertyKey) {
             ScrollPositionInfo position =
                     model.get(TouchlessNewTabPageProperties.INITIAL_SCROLL_POSITION);
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
index f2ba2f18..719b821d 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
@@ -17,6 +17,7 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.AppHooks;
+import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeInactivityTracker;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
@@ -26,7 +27,6 @@
 import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabBuilder;
 import org.chromium.chrome.browser.tab.TabRedirectHandler;
 import org.chromium.chrome.browser.tab.TabState;
 import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogPresenter;
@@ -44,7 +44,6 @@
  * An Activity used to display WebContents on devices that don't support touch.
  */
 public class NoTouchActivity extends SingleTabActivity {
-    private static final String BUNDLE_TAB_ID = "tabId";
     public static final String DINOSAUR_GAME_INTENT =
             "org.chromium.chrome.browser.touchless.DinoActivity";
 
@@ -242,18 +241,8 @@
     }
 
     @Override
-    protected Tab restoreTab(Bundle savedInstanceState) {
-        int tabId = getSavedInstanceState().getInt(BUNDLE_TAB_ID, Tab.INVALID_TAB_ID);
-
-        if (tabId == Tab.INVALID_TAB_ID) return null;
-
-        TabState tabState = TabState.restoreTabState(savedInstanceState);
-        assert tabState != null;
-
-        return TabBuilder.createFromFrozenState(tabState)
-                .setId(tabId)
-                .setWindow(getWindowAndroid())
-                .build();
+    protected TabState restoreTabState(Bundle savedInstanceState, int tabId) {
+        return TabState.restoreTabState(savedInstanceState);
     }
 
     @Override
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabMediator.java
index 60b83c86..1911c54 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabMediator.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabMediator.java
@@ -29,6 +29,7 @@
 /**
  * Mediator used to look for history events and update the model accordingly.
  */
+// TODO(crbug.com/948858): Add unit tests for this behavior.
 class OpenLastTabMediator implements HistoryProvider.BrowsingHistoryObserver {
     private final Context mContext;
     private final Profile mProfile;
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java
index f835517..442c26e4 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java
@@ -22,6 +22,7 @@
 /**
  * View for the button to open the last tab.
  */
+// TODO(crbug.com/948858): Add render tests for this view.
 public class OpenLastTabView extends FrameLayout {
     private LinearLayout mPlaceholder;
     private ChipView mLastTabChip;
@@ -44,8 +45,10 @@
         TextView primaryTextView = mLastTabChip.getPrimaryTextView();
         TextView secondaryTextView = mLastTabChip.getSecondaryTextView();
 
-        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
-                LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+        LinearLayout.LayoutParams params =
+                new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT);
+        // Allow timestamp to expand to as much as it needs.
+        params.weight = 1;
         primaryTextView.setLayoutParams(params);
         primaryTextView.setSingleLine(true);
         primaryTextView.setEllipsize(TextUtils.TruncateAt.END);
@@ -58,8 +61,9 @@
         params = new LinearLayout.LayoutParams(
                 LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
         secondaryTextView.setLayoutParams(params);
-        secondaryTextView.setMinWidth(getContext().getResources().getDimensionPixelSize(
-                R.dimen.open_last_tab_timestamp_min_width));
+        secondaryTextView.setSingleLine(true);
+        // Note: this should never actually need to truncate, but I've included it as a fallback.
+        secondaryTextView.setEllipsize(TextUtils.TruncateAt.END);
         secondaryTextView.setTextAlignment(TEXT_ALIGNMENT_VIEW_END);
         ApiCompatibilityUtils.setTextAppearance(
                 secondaryTextView, R.style.TextAppearance_BlackCaption);
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java
index d97592ad..0b4d6a5b 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java
@@ -8,7 +8,11 @@
 import android.graphics.BitmapFactory;
 import android.support.annotation.Nullable;
 
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.task.AsyncTask;
+import org.chromium.chrome.browser.explore_sites.ExploreSitesBridge;
+import org.chromium.chrome.browser.explore_sites.ExploreSitesCategory;
+import org.chromium.chrome.browser.explore_sites.ExploreSitesEnums;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.suggestions.ImageFetcher;
 import org.chromium.chrome.browser.suggestions.MostVisitedSites;
@@ -37,6 +41,7 @@
     private PropertyModel mModel;
     private ImageFetcher mImageFetcher;
     private MostVisitedSites mMostVisitedSites;
+    private Profile mProfile;
     private int mIconSize;
 
     SiteSuggestionsMediator(
@@ -44,10 +49,12 @@
         mModel = model;
         mImageFetcher = imageFetcher;
         mIconSize = minIconSize;
+        mProfile = profile;
         mMostVisitedSites =
-                SuggestionsDependencyFactory.getInstance().createMostVisitedSites(profile);
+                SuggestionsDependencyFactory.getInstance().createMostVisitedSites(mProfile);
         mMostVisitedSites.setObserver(this, NUM_FETCHED_SITES);
         mModel.get(SiteSuggestionsCoordinator.SUGGESTIONS_KEY).addObserver(this);
+        ExploreSitesBridge.getEspCatalog(mProfile, this::onGetEspCatalog);
     }
 
     @Override
@@ -138,4 +145,16 @@
                     }
                 });
     }
+
+    private void onGetEspCatalog(List<ExploreSitesCategory> categoryList) {
+        boolean loadCatalogFromNetwork = categoryList == null || categoryList.isEmpty();
+        if (loadCatalogFromNetwork) {
+            ExploreSitesBridge.updateCatalogFromNetwork(mProfile, true, (success) -> {});
+            RecordHistogram.recordEnumeratedHistogram("ExploreSites.CatalogUpdateRequestSource",
+                    ExploreSitesEnums.CatalogUpdateRequestSource.NEW_TAB_PAGE,
+                    ExploreSitesEnums.CatalogUpdateRequestSource.NUM_ENTRIES);
+        }
+        RecordHistogram.recordBooleanHistogram(
+                "ExploreSites.NTPLoadingCatalogFromNetwork", loadCatalogFromNetwork);
+    }
 }
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java
index d7d2165..6e73ecd 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java
@@ -132,10 +132,10 @@
         mSiteSuggestionsCoordinator = new SiteSuggestionsCoordinator(mRecyclerTopmostView, profile,
                 navigationDelegate, mContextMenuManager, suggestionsUiDelegate.getImageFetcher());
 
-        NewTabPageAdapter newTabPageAdapter =
-                new NewTabPageAdapter(suggestionsUiDelegate, mRecyclerTopmostView, uiConfig,
-                        SuggestionsDependencyFactory.getInstance().getOfflinePageBridge(profile),
-                        mContextMenuManager);
+        NewTabPageAdapter newTabPageAdapter = new TouchlessNewTabPageAdapter(suggestionsUiDelegate,
+                mRecyclerTopmostView, uiConfig,
+                SuggestionsDependencyFactory.getInstance().getOfflinePageBridge(profile),
+                mContextMenuManager, mMediator.getModel());
 
         PropertyModelChangeProcessor.create(
                 mMediator.getModel(), mRecyclerView, ContentSuggestionsViewBinder::bind);
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageAdapter.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageAdapter.java
new file mode 100644
index 0000000..657f5bdc
--- /dev/null
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageAdapter.java
@@ -0,0 +1,81 @@
+// Copyright 2019 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.touchless;
+
+import android.support.annotation.Nullable;
+import android.view.View;
+
+import org.chromium.base.Callback;
+import org.chromium.chrome.browser.native_page.ContextMenuManager;
+import org.chromium.chrome.browser.ntp.cards.ItemViewType;
+import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter;
+import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
+import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
+import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
+import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
+import org.chromium.ui.modelutil.PropertyModel;
+
+import java.util.List;
+
+/**
+ * Adds touchless specific logic that needs to be attached and/or interacted with view holders.
+ */
+public class TouchlessNewTabPageAdapter extends NewTabPageAdapter {
+    private PropertyModel mModel;
+
+    // Initial focus should only be set once. After that happens this sentinel is sent to false and
+    // the initial focus field should not be used.
+    private boolean mCheckInitialFocus = true;
+
+    /**
+     * Creates the adapter that will manage all the cards to display on the NTP.
+     * @param uiDelegate used to interact with the rest of the system.
+     * @param aboveTheFoldView the layout encapsulating all the above-the-fold elements
+     *         (logo, search box, most visited tiles), or null if only suggestions should
+     *         be displayed.
+     * @param uiConfig the NTP UI configuration, to be passed to created views.
+     * @param offlinePageBridge used to determine if articles are available.
+     * @param contextMenuManager used to build context menus.
+     * @param model the model of the recycler view component.
+     */
+    public TouchlessNewTabPageAdapter(SuggestionsUiDelegate uiDelegate,
+            @Nullable View aboveTheFoldView, UiConfig uiConfig, OfflinePageBridge offlinePageBridge,
+            ContextMenuManager contextMenuManager, PropertyModel model) {
+        super(uiDelegate, aboveTheFoldView, uiConfig, offlinePageBridge, contextMenuManager);
+        mModel = model;
+    }
+
+    @Override
+    public void onBindViewHolder(NewTabPageViewHolder holder, int position, List<Object> payloads) {
+        super.onBindViewHolder(holder, position, payloads);
+
+        Callback<TouchlessNewTabPageFocusInfo> focusCallback =
+                mModel.get(TouchlessNewTabPageProperties.FOCUS_CHANGE_CALLBACK);
+        if (focusCallback != null && holder.getItemViewType() == ItemViewType.SNIPPET) {
+            holder.itemView.setOnFocusChangeListener((View view, boolean hasFocus) -> {
+                if (hasFocus) {
+                    focusCallback.onResult(new TouchlessNewTabPageFocusInfo(
+                            TouchlessNewTabPageFocusInfo.FocusType.ARTICLE,
+                            holder.getAdapterPosition()));
+
+                    // If focus is changing due to user interactions, the initial focus is no longer
+                    // needed. While this flag is typically flipped when the initial focus is set,
+                    // if the initial focus is not restored successfully, for example when the
+                    // initial focus would be on an index larger than the initial number of cards,
+                    // then it needs to be cleared here.
+                    mCheckInitialFocus = false;
+                }
+            });
+        }
+
+        TouchlessNewTabPageFocusInfo focus =
+                mModel.get(TouchlessNewTabPageProperties.INITIAL_FOCUS);
+        if (mCheckInitialFocus && focus != null && focus.index == holder.getAdapterPosition()
+                && focus.type == holder.getItemViewType()) {
+            holder.itemView.requestFocus();
+            mCheckInitialFocus = false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageFocusInfo.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageFocusInfo.java
new file mode 100644
index 0000000..22c90a1
--- /dev/null
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageFocusInfo.java
@@ -0,0 +1,85 @@
+// Copyright 2019 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.touchless;
+
+import android.support.annotation.IntDef;
+import android.support.v7.widget.RecyclerView;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Holds onto fields that represent the focused view on a page, and the ability to be round tripped
+ * through a String.
+ */
+public class TouchlessNewTabPageFocusInfo {
+    @IntDef({FocusType.UNKNOWN, FocusType.LAST_TAB, FocusType.MOST_LIKELY, FocusType.ARTICLE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FocusType {
+        int UNKNOWN = 0;
+        int LAST_TAB = 1;
+        int MOST_LIKELY = 2;
+        int ARTICLE = 3;
+    }
+
+    private static final String TYPE_KEY = "type";
+    private static final String INDEX_KEY = "index";
+
+    public final @FocusType int type;
+
+    /** Depending on the type, the index may be meaningful or instead hold FocusType.UNKNOWN. */
+    public final int index;
+
+    public TouchlessNewTabPageFocusInfo(@FocusType int type, int index) {
+        this.type = type;
+        this.index = index;
+    }
+
+    public TouchlessNewTabPageFocusInfo(@FocusType int type) {
+        this(type, RecyclerView.NO_POSITION);
+    }
+
+    /**
+     * Turns the current TouchlessNewTabPageFocus object into a String that can be more easily
+     * stored and restored. If anything goes wrong then an empty string is returned instead.
+     * @return The values encoded into a String.
+     */
+    public String serialize() {
+        try {
+            JSONObject json = new JSONObject();
+            json.put(TYPE_KEY, type);
+            json.put(INDEX_KEY, index);
+            return json.toString();
+        } catch (JSONException e) {
+            return "";
+        }
+    }
+
+    /**
+     * Turns the given String into a TouchlessNewTabPageFocus object. If anything goes wrong a
+     * default value TouchlessNewTabPageFocus is returned that essentially means nothing is focused.
+     * @param str The serialized form of a TouchlessNewTabPageFocus.
+     * @return An instantiated TouchlessNewTabPageFocus object.
+     */
+    public static TouchlessNewTabPageFocusInfo deserialize(String str) {
+        if (str == null || str.isEmpty()) return newDefault();
+        try {
+            JSONObject json = new JSONObject(str);
+            return new TouchlessNewTabPageFocusInfo(json.getInt(TYPE_KEY), json.getInt(INDEX_KEY));
+        } catch (JSONException e) {
+            return newDefault();
+        }
+    }
+
+    /**
+     * @return A new focus object that means nothing is currently focused.
+     */
+    private static TouchlessNewTabPageFocusInfo newDefault() {
+        return new TouchlessNewTabPageFocusInfo(FocusType.UNKNOWN, RecyclerView.NO_POSITION);
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediator.java
index 8bf05f14..abdb797 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediator.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediator.java
@@ -15,12 +15,14 @@
 
 class TouchlessNewTabPageMediator extends EmptyTabObserver {
     private static final String NAVIGATION_ENTRY_SCROLL_POSITION_KEY = "TouchlessScrollPosition";
+    private static final String NAVIGATION_ENTRY_FOCUS_KEY = "TouchlessFocus";
 
     private final PropertyModel mModel;
     private final Tab mTab;
     private long mLastShownTimeNs;
 
     private ScrollPositionInfo mScrollPosition;
+    private TouchlessNewTabPageFocusInfo mFocus;
 
     public TouchlessNewTabPageMediator(Tab tab) {
         mTab = tab;
@@ -28,8 +30,13 @@
 
         ScrollPositionInfo initialScrollPosition = ScrollPositionInfo.deserialize(
                 NewTabPage.getStringFromNavigationEntry(tab, NAVIGATION_ENTRY_SCROLL_POSITION_KEY));
+        TouchlessNewTabPageFocusInfo initialFocus = TouchlessNewTabPageFocusInfo.deserialize(
+                NewTabPage.getStringFromNavigationEntry(tab, NAVIGATION_ENTRY_FOCUS_KEY));
 
         mModel = new PropertyModel.Builder(TouchlessNewTabPageProperties.ALL_KEYS)
+                         .with(TouchlessNewTabPageProperties.FOCUS_CHANGE_CALLBACK,
+                                 (newFocus) -> mFocus = newFocus)
+                         .with(TouchlessNewTabPageProperties.INITIAL_FOCUS, initialFocus)
                          .with(TouchlessNewTabPageProperties.INITIAL_SCROLL_POSITION,
                                  initialScrollPosition)
                          .with(TouchlessNewTabPageProperties.SCROLL_POSITION_CALLBACK,
@@ -51,9 +58,14 @@
 
     @Override
     public void onPageLoadStarted(Tab tab, String url) {
-        if (mScrollPosition == null) return;
-        NewTabPage.saveStringToNavigationEntry(
-                tab, NAVIGATION_ENTRY_SCROLL_POSITION_KEY, mScrollPosition.serialize());
+        if (mScrollPosition != null) {
+            NewTabPage.saveStringToNavigationEntry(
+                    tab, NAVIGATION_ENTRY_SCROLL_POSITION_KEY, mScrollPosition.serialize());
+        }
+        if (mFocus != null) {
+            NewTabPage.saveStringToNavigationEntry(
+                    tab, NAVIGATION_ENTRY_FOCUS_KEY, mFocus.serialize());
+        }
     }
 
     public PropertyModel getModel() {
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageProperties.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageProperties.java
index fda2d41..c9858a39 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageProperties.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageProperties.java
@@ -10,6 +10,14 @@
 
 class TouchlessNewTabPageProperties {
     public static final PropertyModel
+            .ReadableObjectPropertyKey<Callback<TouchlessNewTabPageFocusInfo>>
+                    FOCUS_CHANGE_CALLBACK = new PropertyModel.ReadableObjectPropertyKey<>();
+
+    public static final PropertyModel
+            .ReadableObjectPropertyKey<TouchlessNewTabPageFocusInfo> INITIAL_FOCUS =
+            new PropertyModel.ReadableObjectPropertyKey<>();
+
+    public static final PropertyModel
             .ReadableObjectPropertyKey<ScrollPositionInfo> INITIAL_SCROLL_POSITION =
             new PropertyModel.ReadableObjectPropertyKey<>();
 
@@ -17,6 +25,6 @@
             .ReadableObjectPropertyKey<Callback<ScrollPositionInfo>> SCROLL_POSITION_CALLBACK =
             new PropertyModel.ReadableObjectPropertyKey<>();
 
-    public static final PropertyKey[] ALL_KEYS = {
+    public static final PropertyKey[] ALL_KEYS = {FOCUS_CHANGE_CALLBACK, INITIAL_FOCUS,
             INITIAL_SCROLL_POSITION, SCROLL_POSITION_CALLBACK};
 }
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_fil.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_fil.xtb
index 9a8f137..e27d37b2 100644
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_fil.xtb
+++ b/chrome/android/touchless/java/strings/translations/touchless_strings_fil.xtb
@@ -1,5 +1,7 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="fil">
+<translation id="2169830938017475061">Ngayon</translation>
+<translation id="4976607328574506118">Welcome sa Chrome Explore</translation>
 <translation id="5901398892005759450">Lahat ng app</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageFocusInfoTest.java b/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageFocusInfoTest.java
new file mode 100644
index 0000000..fae205e
--- /dev/null
+++ b/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageFocusInfoTest.java
@@ -0,0 +1,82 @@
+// Copyright 2019 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.touchless;
+
+import android.support.v7.widget.RecyclerView;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/**
+ * Unit tests for the TouchlessNewTabPageFocus class.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class TouchlessNewTabPageFocusInfoTest {
+    @Test
+    public void roundTripSimple() {
+        TouchlessNewTabPageFocusInfo original = new TouchlessNewTabPageFocusInfo(
+                TouchlessNewTabPageFocusInfo.FocusType.ARTICLE, 34);
+        TouchlessNewTabPageFocusInfo roundTripped =
+                TouchlessNewTabPageFocusInfo.deserialize(original.serialize());
+        Assert.assertEquals(original.type, roundTripped.type);
+        Assert.assertEquals(original.index, roundTripped.index);
+    }
+
+    @Test
+    public void roundTripNegative() {
+        TouchlessNewTabPageFocusInfo original = new TouchlessNewTabPageFocusInfo(
+                TouchlessNewTabPageFocusInfo.FocusType.ARTICLE, -34);
+        TouchlessNewTabPageFocusInfo roundTripped =
+                TouchlessNewTabPageFocusInfo.deserialize(original.serialize());
+        Assert.assertEquals(original.type, roundTripped.type);
+        Assert.assertEquals(original.index, roundTripped.index);
+    }
+
+    @Test
+    public void roundTripZero() {
+        TouchlessNewTabPageFocusInfo original =
+                new TouchlessNewTabPageFocusInfo(TouchlessNewTabPageFocusInfo.FocusType.ARTICLE, 0);
+        TouchlessNewTabPageFocusInfo roundTripped =
+                TouchlessNewTabPageFocusInfo.deserialize(original.serialize());
+        Assert.assertEquals(original.type, roundTripped.type);
+        Assert.assertEquals(original.index, roundTripped.index);
+    }
+
+    @Test
+    public void roundTripNoIndex() {
+        TouchlessNewTabPageFocusInfo original =
+                new TouchlessNewTabPageFocusInfo(TouchlessNewTabPageFocusInfo.FocusType.LAST_TAB);
+        TouchlessNewTabPageFocusInfo roundTripped =
+                TouchlessNewTabPageFocusInfo.deserialize(original.serialize());
+        Assert.assertEquals(original.type, roundTripped.type);
+        Assert.assertEquals(original.index, roundTripped.index);
+    }
+
+    @Test
+    public void deserializeFailure() {
+        TouchlessNewTabPageFocusInfo position = TouchlessNewTabPageFocusInfo.deserialize("invalid");
+        Assert.assertEquals(TouchlessNewTabPageFocusInfo.FocusType.UNKNOWN, position.type);
+        Assert.assertEquals(RecyclerView.NO_POSITION, position.index);
+    }
+
+    @Test
+    public void deserializeEmpty() {
+        TouchlessNewTabPageFocusInfo position = TouchlessNewTabPageFocusInfo.deserialize("");
+        Assert.assertEquals(TouchlessNewTabPageFocusInfo.FocusType.UNKNOWN, position.type);
+        Assert.assertEquals(RecyclerView.NO_POSITION, position.index);
+    }
+
+    @Test
+    public void deserializeNull() {
+        TouchlessNewTabPageFocusInfo position = TouchlessNewTabPageFocusInfo.deserialize(null);
+        Assert.assertEquals(TouchlessNewTabPageFocusInfo.FocusType.UNKNOWN, position.type);
+        Assert.assertEquals(RecyclerView.NO_POSITION, position.index);
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/touchless/touchless_java_sources.gni b/chrome/android/touchless/touchless_java_sources.gni
index 03b9813..0dd4ec3 100644
--- a/chrome/android/touchless/touchless_java_sources.gni
+++ b/chrome/android/touchless/touchless_java_sources.gni
@@ -21,6 +21,8 @@
   "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsViewHolderFactory.java",
   "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java",
   "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java",
+  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageAdapter.java",
+  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageFocusInfo.java",
   "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediator.java",
   "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageProperties.java",
   "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageTopLayout.java",
@@ -44,7 +46,10 @@
 
 touchless_test_java_sources = [ "touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java" ]
 
-touchless_junit_test_java_sources = [ "touchless/junit/src/org/chromium/chrome/browser/touchless/ScrollPositionInfoTest.java" ]
+touchless_junit_test_java_sources = [
+  "touchless/junit/src/org/chromium/chrome/browser/touchless/ScrollPositionInfoTest.java",
+  "touchless/junit/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageFocusInfoTest.java",
+]
 
 touchess_fallback_java_sources = [
   "touchless/fallback/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java",
diff --git a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/IWebApkApi.aidl b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/IWebApkApi.aidl
index 2a7f70f7..5bfdd402 100644
--- a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/IWebApkApi.aidl
+++ b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/IWebApkApi.aidl
@@ -26,4 +26,7 @@
     // Display a notification with a specified channel name.
     void notifyNotificationWithChannel(String platformTag, int platformID,
                                        in Notification notification, String channelName);
+
+   // Finishes and removes the WebAPK's task. Returns true on success.
+   boolean finishAndRemoveTaskSdk23();
 }
diff --git a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java
index 7fc589f..49130a3aa 100644
--- a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java
+++ b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java
@@ -4,6 +4,9 @@
 
 package org.chromium.webapk.lib.runtime_library;
 
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
@@ -14,6 +17,7 @@
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.support.v4.app.NotificationManagerCompat;
+import android.text.TextUtils;
 import android.util.Log;
 
 /**
@@ -83,6 +87,36 @@
         return NotificationManagerCompat.from(mContext).areNotificationsEnabled();
     }
 
+    @SuppressLint("NewApi")
+    @Override
+    public boolean finishAndRemoveTaskSdk23() {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false;
+
+        ActivityManager manager =
+                (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+        String webApkPackageName = mContext.getPackageName();
+        for (ActivityManager.AppTask task : manager.getAppTasks()) {
+            if (TextUtils.equals(getTaskBaseActivityPackageName(task), webApkPackageName)) {
+                task.finishAndRemoveTask();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** Returns the package name of the task's base activity. */
+    @TargetApi(Build.VERSION_CODES.M)
+    private static String getTaskBaseActivityPackageName(ActivityManager.AppTask task) {
+        try {
+            ActivityManager.RecentTaskInfo info = task.getTaskInfo();
+            if (info != null && info.baseActivity != null) {
+                return info.baseActivity.getPackageName();
+            }
+        } catch (IllegalArgumentException e) {
+        }
+        return null;
+    }
+
     @SuppressWarnings("NewApi")
     @Override
     public void notifyNotificationWithChannel(
@@ -100,4 +134,4 @@
     private NotificationManager getNotificationManager() {
         return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/webapk/libs/runtime_library_version.gni b/chrome/android/webapk/libs/runtime_library_version.gni
index 88cc0557..5b177316 100644
--- a/chrome/android/webapk/libs/runtime_library_version.gni
+++ b/chrome/android/webapk/libs/runtime_library_version.gni
@@ -5,4 +5,4 @@
 # Must be incremented whenever the runtime library is updated. The WebAPK
 # re-extracts the runtime library from the Chrome APK when
 # |runtime_library_version| is incremented.
-runtime_library_version = 5
+runtime_library_version = 6
diff --git a/chrome/app/entitlements.plist b/chrome/app/app-entitlements.plist
similarity index 100%
rename from chrome/app/entitlements.plist
rename to chrome/app/app-entitlements.plist
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 5b5844d9..87b2a02 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -428,23 +428,43 @@
                desc="Message shown on the download shelf when the download is known to change settings in the browser in a malicious way.">
         <ph name="FILE_NAME">$1<ex>bla.exe</ex></ph> may be dangerous, so Chromium has blocked it.
       </message>
+      <message name="IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS_IN_ADVANCED_PROTECTION"
+               desc="Message shown on the download shelf when the download is known to change settings in the browser in a malicious way. This variant is shown when the user is enrolled in the Advanced Protection program.">
+        <ph name="FILE_NAME">$1<ex>bla.exe</ex></ph> may be dangerous, so Chromium has blocked it. You're defended by Advanced Protection.
+      </message>
 
       <message name="IDS_PROMPT_MALICIOUS_DOWNLOAD_URL"
          desc="Message shown to the user to validate the download when the download url is classified to lead to malware by the safebrowsing database.">
         This file is dangerous, so Chromium has blocked it.
       </message>
+      <message name="IDS_PROMPT_MALICIOUS_DOWNLOAD_URL_IN_ADVANCED_PROTECTION"
+         desc="Message shown to the user to validate the download when the download url is classified to lead to malware by the safebrowsing database. This variant is shown when the user is enrolled in this Advanced Protection program.">
+        This file is dangerous, so Chromium has blocked it. You're defended by Advanced Protection.
+      </message>
       <message name="IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT"
          desc="Message shown to the user to validate the download when the download content is classified to lead to malware by safebrowsing.">
         <ph name="FILE_NAME">$1<ex>malware.exe</ex></ph> is dangerous, so Chromium has blocked it.
       </message>
+      <message name="IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION"
+         desc="Message shown to the user to validate the download when the download content is classified to lead to malware by safebrowsing. This variant is shown when the user is enrolled in the Advanced Protection program.">
+        <ph name="FILE_NAME">$1<ex>malware.exe</ex></ph> is dangerous, so Chromium has blocked it. You're defended by Advanced Protection.
+      </message>
       <message name="IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD"
          desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it is malware.">
         This file is dangerous, so Chromium has blocked it.
       </message>
+      <message name="IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD_IN_ADVANCED_PROTECTION"
+         desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it is malware. This variant is shown when the user is enrolled in the Advanced Protection program.">
+        This file is dangerous, so Chromium has blocked it. You're defended by Advanced Protection.
+      </message>
       <message name="IDS_BLOCK_REASON_UNWANTED_DOWNLOAD"
          desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it is unwanted sofware.">
         This file may be dangerous, so Chromium has blocked it.
       </message>
+      <message name="IDS_BLOCK_REASON_UNWANTED_DOWNLOAD_IN_ADVANCED_PROTECTION"
+         desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it is unwanted sofware. This variant is shown when the user is enrolled in the Advanced Protection program.">
+        This file may be dangerous, so Chromium has blocked it. You're defended by Advanced Protection.
+      </message>
 
       <!-- Abandon in-progress downloads confirmation dialog -->
       <if expr="not is_macosx">
diff --git a/chrome/app/chromium_strings_grd/IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1 b/chrome/app/chromium_strings_grd/IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1
new file mode 100644
index 0000000..7ff0038c
--- /dev/null
+++ b/chrome/app/chromium_strings_grd/IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1
@@ -0,0 +1 @@
+5c865831385d99ae49626bef0555a4d78e58dd49
\ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_BLOCK_REASON_UNWANTED_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1 b/chrome/app/chromium_strings_grd/IDS_BLOCK_REASON_UNWANTED_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1
new file mode 100644
index 0000000..a38e3d06
--- /dev/null
+++ b/chrome/app/chromium_strings_grd/IDS_BLOCK_REASON_UNWANTED_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1
@@ -0,0 +1 @@
+e71305276bd714642fb5775005f8af8a5c060fd9
\ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS_IN_ADVANCED_PROTECTION.png.sha1 b/chrome/app/chromium_strings_grd/IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS_IN_ADVANCED_PROTECTION.png.sha1
new file mode 100644
index 0000000..d23231c
--- /dev/null
+++ b/chrome/app/chromium_strings_grd/IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS_IN_ADVANCED_PROTECTION.png.sha1
@@ -0,0 +1 @@
+8803efcf4bce6bdbc0a5aa263f8790333fd5af85
\ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION.png.png.sha1 b/chrome/app/chromium_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION.png.png.sha1
new file mode 100644
index 0000000..badfdb7
--- /dev/null
+++ b/chrome/app/chromium_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION.png.png.sha1
@@ -0,0 +1 @@
+265c2634cfab673e9d3bd92b5837e904e2830015
\ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_URL_IN_ADVANCED_PROTECTION.png.sha1 b/chrome/app/chromium_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_URL_IN_ADVANCED_PROTECTION.png.sha1
new file mode 100644
index 0000000..9125b7dc
--- /dev/null
+++ b/chrome/app/chromium_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_URL_IN_ADVANCED_PROTECTION.png.sha1
@@ -0,0 +1 @@
+c2dd31a8cedc9a38e18698ffa005e84e5c7167b3
\ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index d948222..cd69176 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -550,7 +550,7 @@
             No thanks
           </message>
           <message name="IDS_CONTENT_CONTEXT_SPELLING_ASK_GOOGLE" desc="The context-menu item that asks whether to integrate the spelling service of Google to Chrome. This text is also used as the title of a bubble which confirms it.">
-            Ask Google for suggestions
+            Use enhanced spell check
           </message>
           <message name="IDS_CONTENT_CONTEXT_SPELLING_BUBBLE_ENABLE" desc="The button text that allows integrating the spelling service of Google.">
             Enable
@@ -783,7 +783,7 @@
             No Thanks
           </message>
           <message name="IDS_CONTENT_CONTEXT_SPELLING_ASK_GOOGLE" desc="In Title Case: The context-menu item that asks whether to integrate the spelling service of Google to Chrome. This text is also used as the title of a bubble which confirms it.">
-            Ask Google for Suggestions
+            Use Enhanced Spell Check
           </message>
           <message name="IDS_CONTENT_CONTEXT_SPELLING_BUBBLE_ENABLE" desc="In Title Case: The button text that allows integrating the spelling service of Google.">
             Enable
@@ -852,8 +852,8 @@
         <message name="IDS_CONTENT_CONTEXT_SPELLCHECK_MULTI_LINGUAL" desc="The name of the menu item that enables spellcheck in all of the languages that the user has selected in settings">
           &amp;All your languages
         </message>
-        <message name="IDS_CONTENT_CONTEXT_CHECK_SPELLING_WHILE_TYPING" desc="The name of the menu item that toggles spellcheck on or off">
-          &amp;Check the spelling of text fields
+        <message name="IDS_CONTENT_CONTEXT_CHECK_SPELLING_WHILE_TYPING" desc="The name of the menu item that toggles the local built-in spellcheck on or off and specifically disables using Google's spelling service.">
+          &amp;Use basic spell check
         </message>
       </if>
 
@@ -1535,10 +1535,18 @@
          desc="Message shown to the user to validate the download when the download content is classified as uncommon by safebrowsing.">
         <ph name="FILE_NAME">$1<ex>bla.exe</ex></ph> is not commonly downloaded and may be dangerous.
       </message>
+      <message name="IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION"
+         desc="Message shown to the user to validate the download when the download content is classified as uncommon by safebrowsing. This variant is shown when the user is enrolled in the Advanced Protection program.">
+        <ph name="FILE_NAME">$1<ex>bla.exe</ex></ph> is not commonly downloaded and may be dangerous. You're defended by Advanced Protection.
+      </message>
       <message name="IDS_BLOCK_REASON_UNCOMMON_DOWNLOAD"
          desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it is uncommon.">
         This file is not commonly downloaded and may be dangerous.
       </message>
+      <message name="IDS_BLOCK_REASON_UNCOMMON_DOWNLOAD_IN_ADVANCED_PROTECTION"
+         desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it is uncommon. This variant is shown when the user is enrolled in the Advanced Protection program.">
+        This file is not commonly downloaded and may be dangerous. You're defended by Advanced Protection.
+      </message>
       <message name="IDS_BLOCK_REASON_GENERIC_DOWNLOAD"
          desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it may be dangerous.">
         This type of file may harm your computer.
@@ -6676,6 +6684,10 @@
                  desc="Text for the context menu item that creates an app shortcut. (In sentence case.)">
           Create shortcuts...
         </message>
+        <message name="IDS_NEW_TAB_APP_INSTALL_LOCALLY"
+                 desc="Text for the context menu item that locally installs an app or shortcut. (In sentence case.)">
+          Install on this device
+        </message>
         <message name="IDS_APP_CONTEXT_MENU_SHOW_INFO"
                  desc="Text for the context menu item that shows the application information. (In sentence case.)">
           App info
@@ -6737,6 +6749,10 @@
             Create Shortcuts...
           </message>
         </if>
+        <message name="IDS_NEW_TAB_APP_INSTALL_LOCALLY"
+                 desc="Text for the context menu item that locally installs an app or shortcut. (In title case.)">
+          Install on this Device
+        </message>
         <message name="IDS_APP_CONTEXT_MENU_SHOW_INFO"
                  desc="Text for the context menu item that shows the application information. (In title case.)">
           App Info
@@ -8730,9 +8746,6 @@
       <message name="IDS_TOOLTIP_TAB_ALERT_STATE_USB_CONNECTED" desc="Extra tool tip text, when tab is connected to a USB device.">
         This tab is connected to a USB device.
       </message>
-      <message name="IDS_TOOLTIP_TAB_ALERT_STATE_SERIAL_CONNECTED" desc="Extra tool tip text, when tab is connected to a serial port.">
-        This tab is connected to a serial port.
-      </message>
       <message name="IDS_TOOLTIP_TAB_ALERT_STATE_PIP_PLAYING" desc="Extra tool tip text, when tab is playing a video in Picture-in-Picture.">
         This tab is playing a video in picture-in-picture mode.
       </message>
@@ -8765,9 +8778,6 @@
       <message name="IDS_TAB_AX_LABEL_USB_CONNECTED_FORMAT" desc="Accessibility label text, when a tab is connected to a USB device. Example: 'Google Photos - USB device connected'">
         <ph name="WINDOW_TITLE">$1<ex>Google Photos</ex></ph> - USB device connected
       </message>
-      <message name="IDS_TAB_AX_LABEL_SERIAL_CONNECTED_FORMAT" desc="Accessibility label text, when a tab is connected to a serial port. Example: 'Google Photos - Serial port connected'">
-        <ph name="WINDOW_TITLE">$1<ex>Google Photos</ex></ph> - Serial port connected
-      </message>
       <message name="IDS_TAB_AX_LABEL_NETWORK_ERROR_FORMAT" desc="Accessibility label text, when tab has encountered a network error such as being disconnected from the internet. Example: 'www.google.com - Network error'">
         <ph name="WINDOW_TITLE">$1<ex>www.google.com</ex></ph> - Network error
       </message>
@@ -9320,10 +9330,7 @@
         External security key or built-in sensor
       </message>
       <message name="IDS_WEBAUTHN_USB_ACTIVATE_DESCRIPTION" desc="Description in the dialog instructing the user to plug in and activate (e.g. press a button on) their USB security key (an external physical device for user authentication).">
-        Plug in your security key and activate it
-      </message>
-      <message name="IDS_WEBAUTHN_USB_SUCCESS_TITLE" desc="Title of the dialog informing the user that Chrome detected that they activated (e.g. pressed a button on) an external physical device used for authentication.">
-        Security key activated...
+        Insert your security key and touch it
       </message>
       <message name="IDS_WEBAUTHN_ERROR_GENERIC_TITLE" desc="Title of most dialogs shown when an error occurs while the user trying to sign in to a web site using a hardware-based authentication mechanism.">
         Something went wrong
@@ -9442,6 +9449,8 @@
       <message name="IDS_WEBAUTHN_CABLE_ACTIVATE_DESCRIPTION" desc="Contents of the dialog shown when the user tries to sign-in using a phone as a security key.">
         A notification was sent to your phone to confirm it's you.
       </message>
+
+      <!-- WebAuthn authenticator PIN entry/setup -->
       <message name="IDS_WEBAUTHN_PIN_ENTRY_TITLE" desc="Title of the dialog shown when instructing the user to enter the PIN code to use a security key (an external physical device for user authentication) with their computer.">
         PIN required
       </message>
@@ -9464,34 +9473,36 @@
         PIN contains invalid characters
       </message>
       <message name="IDS_WEBAUTHN_PIN_ENTRY_ERROR_TOO_SHORT" desc="Error message. Displayed when the user attempts to set a PIN code for their security key (an external physical device for user authentication), and the PIN chosen by them is too short.">
-        PIN is too short.
+        PIN must be at least 4 characters
       </message>
       <message name="IDS_WEBAUTHN_PIN_ENTRY_ERROR_FAILED_RETRIES" desc="Error message. Displayed when the user enters the wrong PIN code for their security key (an external physical device for user authentication)">
         {NUM_ATTEMPTS, plural,
-          =1 {Incorrect PIN. You have only one attempt remaining.}
+          =1 {Incorrect PIN. You have one attempt remaining.}
           other {Incorrect PIN. You have # attempts remaining.}}
       </message>
       <message name="IDS_WEBAUTHN_PIN_ENTRY_ERROR_FAILED" desc="Error message. Displayed when the user attempts to enter the PIN code for their security key (an external physical device for user authentication), but the entered PIN is incorrect.">
-        Incorrect PIN.
+        Incorrect PIN
       </message>
       <message name="IDS_WEBAUTHN_PIN_SETUP_ERROR_FAILED" desc="Error message. Displayed when the user attempts to set up a PIN code for their security key (an external physical device for user authentication), and but the entered PIN contains invalid characters.">
-        PIN contains invalid characters.
+        PIN contains invalid characters
       </message>
       <message name="IDS_WEBAUTHN_PIN_TAP_AGAIN_DESCRIPTION" desc="Description of a dialog shown after the user first activated their security key (an external physical device for user authentication) and provided the PIN for it.">
-        Tap your security key again to complete the request.
+        Touch your security key again to complete the request.
       </message>
       <message name="IDS_WEBAUTHN_PIN_ENTRY_ERROR_MISMATCH" desc="Error message. Displayed when the user attempts to set a PIN code for their security key (an external physical device for user authentication), and the confirmation value does not match the first value they entered.">
-        Confirmation does not match.
+        The PINs you entered don’t match
       </message>
       <message name="IDS_WEBAUTHN_CLIENT_PIN_SOFT_BLOCK_DESCRIPTION" desc="Description in the error dialog shown after their security key (an external physical device for user authentication) was blocked due to the user entering a wrong security key PIN too many times">
-        That security key is temporarily locked due to too many incorrect PIN attempts. Remove it and reinsert to unlock.
+        The security key is locked because the wrong PIN was entered too many times. To unlock it, remove and reinsert it.
       </message>
       <message name="IDS_WEBAUTHN_CLIENT_PIN_HARD_BLOCK_DESCRIPTION" desc="Description in the error dialog shown after their security key (an external physical device for user authentication) was blocked due to the user entering a wrong security key PIN too many times">
-        That security key is locked due to too many incorrect PIN attempts. It must be reset in order to perform any PIN-based operations.
+        The security key is locked because the wrong PIN was entered too many times. You’ll need to reset the security key.
       </message>
       <message name="IDS_WEBAUTHN_CLIENT_PIN_AUTHENTICATOR_REMOVED_DESCRIPTION" desc="Description in the error dialog shown after their security key (an external physical device for user authentication) was removed while the application was waiting for the security key PIN to be entered.">
-        Your security key has been removed.
+        Reinsert your security key and try again
       </message>
+
+      <!-- WebAuthn account selection for resident keys -->
       <message name="IDS_WEBAUTHN_ACCOUNT_COLUMN" desc="The title of a column in a table under which will be a list of usernames or email addresses, e.g. joe@gmail.com.">
         Account
       </message>
@@ -9499,13 +9510,13 @@
         Name
       </message>
       <message name="IDS_WEBAUTHN_SELECT_ACCOUNT" desc="The title on a dialog where the user is expected to select an account from a list. For example, the list may include several identities, e.g. joe@gmail.com, mary@gmail.com, and the user has to select one to login as.">
-        Select Account
+        Select account
       </message>
       <message name="IDS_WEBAUTHN_SELECT_ACCOUNT_DESC" desc="The description on a dialog where the user is expected to select an account from a list. For example, the list may include several identities, e.g. joe@gmail.com, mary@gmail.com, and the user has to select one to login as.">
-        Select an account to log in with:
+        Select an account to sign in:
       </message>
       <message name="IDS_WEBAUTHN_ERROR_MISSING_CAPABILITY_TITLE" desc="Title of the dialog informing the user that the security key (an external physical device for user authentication) that they selected does not support some capability that the site requested.">
-        Security key does not support requested feature.
+        This security key can’t be used in this way
       </message>
       <message name="IDS_WEBAUTHN_MISSING_RESIDENT_KEYS_DESC" desc="The description on a dialog informing the user that the security key (an external physical device for user authentication) that they selected does not support storing credentials, but the website demanded this feature">
         That security key does not support internal storage of credentials, but that feature was requested.
diff --git a/chrome/app/generated_resources_grd/IDS_BLOCK_REASON_UNCOMMON_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_BLOCK_REASON_UNCOMMON_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1
new file mode 100644
index 0000000..31868fd
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_BLOCK_REASON_UNCOMMON_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1
@@ -0,0 +1 @@
+eeffd0a109d6fea67dc0fb0b24f6373d4266314a
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION.png.sha1
new file mode 100644
index 0000000..b8d364e
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION.png.sha1
@@ -0,0 +1 @@
+d90c3cd318ea03d835ef7fccf2e46b368f680a56
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TOOLTIP_TAB_ALERT_STATE_SERIAL_CONNECTED.png.sha1 b/chrome/app/generated_resources_grd/IDS_TOOLTIP_TAB_ALERT_STATE_SERIAL_CONNECTED.png.sha1
deleted file mode 100644
index af8326e..0000000
--- a/chrome/app/generated_resources_grd/IDS_TOOLTIP_TAB_ALERT_STATE_SERIAL_CONNECTED.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d067f692af0231441e02b61aa8d578119d81ec87
\ No newline at end of file
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index cf0de83..813421d 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -439,23 +439,44 @@
                desc="Message shown on the download shelf when the download is known to change settings in the browser.">
         <ph name="FILE_NAME">$1<ex>bla.exe</ex></ph> may be dangerous, so Chrome has blocked it.
       </message>
+      <message name="IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS_IN_ADVANCED_PROTECTION"
+               desc="Message shown on the download shelf when the download is known to change settings in the browser. This variant is shown when the user is enrolled in the Advanced Protection program.">
+        <ph name="FILE_NAME">$1<ex>bla.exe</ex></ph> may be dangerous, so Chrome has blocked it. You're defended by Advanced Protection.
+      </message>
 
       <message name="IDS_PROMPT_MALICIOUS_DOWNLOAD_URL"
          desc="Message shown to the user to validate the download when the download url is classified to lead to malware by the safebrowsing database.">
         This file is dangerous, so Chrome has blocked it.
       </message>
+      <message name="IDS_PROMPT_MALICIOUS_DOWNLOAD_URL_IN_ADVANCED_PROTECTION"
+         desc="Message shown to the user to validate the download when the download url is classified to lead to malware by the safebrowsing database. This variant is shown when the user is enrolled in the Advanced Protection program.">
+        This file is dangerous, so Chrome has blocked it. Your'e defended by Advanced Protection.
+      </message>
       <message name="IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT"
          desc="Message shown to the user to validate the download when the download content is classified to lead to malware by safebrowsing.">
         <ph name="FILE_NAME">$1<ex>malware.exe</ex></ph> is dangerous, so Chrome has blocked it.
       </message>
+      <message name="IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION"
+         desc="Message shown to the user to validate the download when the download content is classified to lead to malware by safebrowsing. This variant is shown when the user is enrolled in the Advanced Protection program.">
+        <ph name="FILE_NAME">$1<ex>malware.exe</ex></ph> is dangerous, so Chrome has blocked it. You're defended by Advanced Protection.
+      </message>
       <message name="IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD"
          desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it is malware.">
         This file is dangerous, so Chrome has blocked it.
       </message>
+      <message name="IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD_IN_ADVANCED_PROTECTION"
+         desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it is malware. This variant is shown when the user is enrolled in the Advanced Protection program.">
+        This file is dangerous, so Chrome has blocked it. You're defended by Advanced Protection.
+      </message>
+
       <message name="IDS_BLOCK_REASON_UNWANTED_DOWNLOAD"
          desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it is unwanted sofware.">
         This file may be dangerous, so Chrome has blocked it.
       </message>
+      <message name="IDS_BLOCK_REASON_UNWANTED_DOWNLOAD_IN_ADVANCED_PROTECTION"
+         desc="Message shown to the user on chrome://downloads page to explain that this download is blocked because it is unwanted sofware. This variant is shown when the user is enrolled in the Advanced Protection program.">
+        This file may be dangerous, so Chrome has blocked it. You're defended by Advanced Protection.
+      </message>
 
       <!-- Abandon in-progress downloads confirmation dialog -->
       <if expr="not is_macosx">
diff --git a/chrome/app/google_chrome_strings_grd/IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1
new file mode 100644
index 0000000..c9dc4c0
--- /dev/null
+++ b/chrome/app/google_chrome_strings_grd/IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1
@@ -0,0 +1 @@
+d0737777f714f744ce780f8cbadeaa936a2d83b6
\ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_BLOCK_REASON_UNWANTED_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_BLOCK_REASON_UNWANTED_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1
new file mode 100644
index 0000000..a054aaa
--- /dev/null
+++ b/chrome/app/google_chrome_strings_grd/IDS_BLOCK_REASON_UNWANTED_DOWNLOAD_IN_ADVANCED_PROTECTION.png.sha1
@@ -0,0 +1 @@
+0baafa004c20bf074ebd2bafd80a196a7fa1b0ca
\ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS_IN_ADVANCED_PROTECTION.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS_IN_ADVANCED_PROTECTION.png.sha1
new file mode 100644
index 0000000..7326cfe9
--- /dev/null
+++ b/chrome/app/google_chrome_strings_grd/IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS_IN_ADVANCED_PROTECTION.png.sha1
@@ -0,0 +1 @@
+d3c66276c5c17525a13729707c0d5c9300ad619c
\ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION.png.sha1
new file mode 100644
index 0000000..a9cfb3d
--- /dev/null
+++ b/chrome/app/google_chrome_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION.png.sha1
@@ -0,0 +1 @@
+fbc7689648a2a22e1648aa4161b8343cfd932c9a
\ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_URL_IN_ADVANCED_PROTECTION.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_URL_IN_ADVANCED_PROTECTION.png.sha1
new file mode 100644
index 0000000..695e7860
--- /dev/null
+++ b/chrome/app/google_chrome_strings_grd/IDS_PROMPT_MALICIOUS_DOWNLOAD_URL_IN_ADVANCED_PROTECTION.png.sha1
@@ -0,0 +1 @@
+21697942f7143eca3cbec0520194a2d775068ee7
\ No newline at end of file
diff --git a/chrome/app/printing_strings.grdp b/chrome/app/printing_strings.grdp
index 1a79a8d..a752a3f3 100644
--- a/chrome/app/printing_strings.grdp
+++ b/chrome/app/printing_strings.grdp
@@ -111,6 +111,9 @@
     <message name="IDS_PRINT_PREVIEW_SUMMARY_FORMAT_SHORT" desc="Print summary, explaining to the user how many pages will be printed.">
       Total: <ph name="NUMBER_OF_SHEETS">$1<ex>10</ex></ph> <ph name="SHEETS_LABEL">$2<ex>sheets of paper</ex></ph>
     </message>
+    <message name="IDS_PRINT_PREVIEW_NEW_SUMMARY_FORMAT_SHORT" desc="Print summary, explaining to the user how many pages will be printed. Same use as above, but omits the 'Total: '.">
+      <ph name="NUMBER_OF_SHEETS">$1<ex>10</ex></ph> <ph name="SHEETS_LABEL">$2<ex>sheets of paper</ex></ph>
+    </message>
     <message name="IDS_PRINT_PREVIEW_SHEETS_LABEL_PLURAL" desc="Label shown in the print preview summary.">
       sheets of paper
     </message>
diff --git a/chrome/app/resources/chromium_strings_en-GB.xtb b/chrome/app/resources/chromium_strings_en-GB.xtb
index f4da3d877..9d36859 100644
--- a/chrome/app/resources/chromium_strings_en-GB.xtb
+++ b/chrome/app/resources/chromium_strings_en-GB.xtb
@@ -172,7 +172,7 @@
 <translation id="6434250628340475518">Chromium OS System</translation>
 <translation id="6457450909262716557">{SECONDS,plural, =1{Chromium will restart in 1 second}other{Chromium will restart in # seconds}}</translation>
 <translation id="6475912303565314141">It also controls what page is shown when you start Chromium.</translation>
-<translation id="6485906693002546646">You're using <ph name="PROFILE_EMAIL" /> to sync your Chromium stuff. To update your sync preference or to use Chromium without aGoogle Account, visit <ph name="SETTINGS_LINK" />.</translation>
+<translation id="6485906693002546646">You're using <ph name="PROFILE_EMAIL" /> to sync your Chromium stuff. To update your sync preference or to use Chromium without a Google Account, visit <ph name="SETTINGS_LINK" />.</translation>
 <translation id="6510925080656968729">Uninstall Chromium</translation>
 <translation id="6570579332384693436">To fix spelling errors, Chromium sends the text that you type in text fields to Google</translation>
 <translation id="6598877126913850652">Go to Chromium notification settings</translation>
diff --git a/chrome/app/resources/chromium_strings_fil.xtb b/chrome/app/resources/chromium_strings_fil.xtb
index 0f18a7c54..5725502 100644
--- a/chrome/app/resources/chromium_strings_fil.xtb
+++ b/chrome/app/resources/chromium_strings_fil.xtb
@@ -211,6 +211,7 @@
 <ph name="BEGIN_LINK_2" />Matuto pa<ph name="END_LINK_2" />
 
 Pakitingnan ang iyong email sa <ph name="ACCOUNT_EMAIL" /> para sa mga karagdagang tagubilin.</translation>
+<translation id="7349591376906416160">Na-configure ng iyong system administrator ang Chromium para buksan ang <ph name="ALTERNATIVE_BROWSER_NAME" /> para ma-access ang <ph name="TARGET_URL_HOSTNAME" />.</translation>
 <translation id="7448255348454382571">I-restart ang Chromium OS</translation>
 <translation id="7449453770951226939"><ph name="PAGE_TITLE" /> - Chromium Dev</translation>
 <translation id="7451052299415159299">Kailangan ng Chromium ng pahintulot na i-access ang iyong camera para sa site na ito</translation>
diff --git a/chrome/app/resources/chromium_strings_pt-PT.xtb b/chrome/app/resources/chromium_strings_pt-PT.xtb
index 29e0e3f..8f8224c0 100644
--- a/chrome/app/resources/chromium_strings_pt-PT.xtb
+++ b/chrome/app/resources/chromium_strings_pt-PT.xtb
@@ -209,7 +209,7 @@
 <ph name="BEGIN_LINK_2" />Saber mais<ph name="END_LINK_2" />
 
 Para obter mais instruções, verifique o seu email em <ph name="ACCOUNT_EMAIL" />.</translation>
-<translation id="7349591376906416160">O administrador do sistema configurou o Chromium para abrir <ph name="ALTERNATIVE_BROWSER_NAME" /> e aceder a <ph name="TARGET_URL_HOSTNAME" />.</translation>
+<translation id="7349591376906416160">O administrador do sistema configurou o Chromium para abrir o <ph name="ALTERNATIVE_BROWSER_NAME" /> e aceder a <ph name="TARGET_URL_HOSTNAME" />.</translation>
 <translation id="7448255348454382571">Reiniciar o Chromium OS</translation>
 <translation id="7449453770951226939"><ph name="PAGE_TITLE" /> – Chromium Dev</translation>
 <translation id="7451052299415159299">O Chromium necessita de autorização de acesso à câmara para este site.</translation>
diff --git a/chrome/app/resources/generated_resources_am.xtb b/chrome/app/resources/generated_resources_am.xtb
index 1a9f7730..4397d4d 100644
--- a/chrome/app/resources/generated_resources_am.xtb
+++ b/chrome/app/resources/generated_resources_am.xtb
@@ -1533,7 +1533,6 @@
 <translation id="3435688026795609344">«<ph name="EXTENSION_NAME" />» የእርስዎን <ph name="CODE_TYPE" /> እየጠየቀ ነው</translation>
 <translation id="3435738964857648380">የደህንነት ጥበቃ</translation>
 <translation id="3435896845095436175">አንቃ</translation>
-<translation id="3436038974659740746">ብጁ የፊደል አጻጻፍ</translation>
 <translation id="3438633801274389918">ኒንጃ</translation>
 <translation id="3439153939049640737"><ph name="HOST" /> ሁልጊዜ የማይክሮፎንዎ መዳረሻ ይፈቀድለት</translation>
 <translation id="3439970425423980614">PDF በቅድመ እይታ በመክፈት ላይ</translation>
@@ -1863,7 +1862,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> ጊዜ ያለፈበት ነው</translation>
 <translation id="3908501907586732282">ቅጥያውን አንቃ</translation>
 <translation id="3909477809443608991"><ph name="URL" /> የተጠበቀ ይዘትን ማጫወት ይፈልጋል። የመሣሪያዎ ማንነት በGoogle የሚረጋገጥ ሲሆን በዚህ ጣቢያ ሊደረስበት ይችላል።</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />፣ <ph name="LANGUAGE_2" /> እና 1 ሌላ</translation>
 <translation id="3909791450649380159">&amp;ቁረጥ</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (በዚህ መሣሪያ ላይ ስራ ላይ የዋለው ስም)</translation>
 <translation id="3911824782900911339">የአዲስ ትር ገጽ</translation>
@@ -2126,7 +2124,6 @@
 <translation id="435527878592612277">የእርስዎን ፎቶ ይምረጡ</translation>
 <translation id="4356334633973342967">ወይም የራስዎን ነጂ ይጠቀሱ፦</translation>
 <translation id="4358169392473932247">ይህ የደህንነት ቁልፍ የምስክርነቶች ውስጣዊ ማከማቻን አይደግፍም፣ ነገር ግን ባህሪው ተጠይቋል።</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />፣ <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">በጥገኛ ቅጥያ(ዎች) ምክንያት ተጭኗል።</translation>
 <translation id="4359717112757026264">ሲቲስኬፕ</translation>
 <translation id="4361142739114356624">የዚህ ደንበኛ የእውቅና ማረጋገጫ የሆነው የግል ቁልፍ ይጎድላል ወይም አይሠራም</translation>
@@ -2178,7 +2175,6 @@
 <translation id="443475966875174318">ተኳኋኝ ያልሆኑ መተግበሪያዎችን ያዘምኑ ወይም ያስወግዱ</translation>
 <translation id="4441124369922430666">ማሽኑ ሲበራ ይህን መተግበሪያ በራስ-ሰር እንዲጀመር ይፈልጋሉ?</translation>
 <translation id="444134486829715816">ዘርጋ...</translation>
-<translation id="4441548209689510310">የፊደል አራሚ አማራጮችን አሳይ</translation>
 <translation id="4442424173763614572">የዲ ኤን ኤስ ፍለጋ አልተሳካም</translation>
 <translation id="4443536555189480885">&amp;እገዛ</translation>
 <translation id="4444304522807523469">በዩ.ኤስ.ቢ ወይም በአካባቢ አውታረ መረብ በኩል የተያያዙ የሰነድ ቃኚዎችን ይድረስባቸው</translation>
@@ -2974,7 +2970,6 @@
 <translation id="5736796278325406685">እባክዎ የሚሠራ የተጠቃሚ ስም ያስገቡ</translation>
 <translation id="5739235828260127894">ማረጋገጫን በመጠበቅ ላይ። <ph name="LINK_BEGIN" />የበለጠ ለመረዳት<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">በጣም ትልቅ</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />፣ <ph name="LANGUAGE_2" /> እና <ph name="NUM_ADDITIONAL_LANGUAGES" /> ሌሎች</translation>
 <translation id="574209121243317957">ቅላፄ</translation>
 <translation id="5746169159649715125">እንደ PDF አስቀምጥ</translation>
 <translation id="5747552184818312860">ጊዜው አልፎበታል</translation>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb
index 6f52fdf..7644e99 100644
--- a/chrome/app/resources/generated_resources_ar.xtb
+++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -1532,7 +1532,6 @@
 <translation id="3435688026795609344">تطلب الإضافة "<ph name="EXTENSION_NAME" />" الرمز <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">أمن المعلومات</translation>
 <translation id="3435896845095436175">تفعيل الإضافات</translation>
-<translation id="3436038974659740746">تدقيق إملائي مخصص</translation>
 <translation id="3438633801274389918">النينجا</translation>
 <translation id="3439153939049640737">السماح دائمًا لـ <ph name="HOST" /> بالدخول إلى الميكروفون</translation>
 <translation id="3439970425423980614">‏جارٍ فتح ملف PDF في تطبيق المعاينة</translation>
@@ -1849,7 +1848,7 @@
 <translation id="3892414795099177503">‏إضافة OpenVPN / L2TP...</translation>
 <translation id="3893536212201235195">قراءة وتغيير إعدادات إمكانية الوصول</translation>
 <translation id="3893630138897523026">‏ChromeVox (التعليق المنطوق)</translation>
-<translation id="3894123633473837029">‏تضمين سجل "مساعد Google" الأخير خلال Sherlog. قد يتضمن هذا الهوية والموقع الجغرافي ومعلومات تصحيح الأخطاء. <ph name="BEGIN_LINK" />مزيد من المعلومات<ph name="END_LINK" /></translation>
+<translation id="3894123633473837029">‏تضمين سجل "مساعد Google" الأخير عبر Sherlog. قد يتضمن هذا الهوية والموقع الجغرافي ومعلومات تصحيح الأخطاء. <ph name="BEGIN_LINK" />مزيد من المعلومات<ph name="END_LINK" /></translation>
 <translation id="3894427358181296146">إضافة مجلد</translation>
 <translation id="389589731200570180">مشاركة مع الضيوف</translation>
 <translation id="3898521660513055167">حالة الرمز المميز</translation>
@@ -1862,7 +1861,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> قديم</translation>
 <translation id="3908501907586732282">تفعيل الإضافة</translation>
 <translation id="3909477809443608991">‏يريد <ph name="URL" /> تشغيل المحتوى المُحمي. ستتحقَّق Google من هوية جهازك ويمكن الوصول إليه من خلال هذا الموقع.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />، و<ph name="LANGUAGE_2" />، ولغة أخرى</translation>
 <translation id="3909791450649380159">&amp;قص</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (الاسم المستخدم على هذا الجهاز)</translation>
 <translation id="3911824782900911339">صفحة "علامة تبويب جديدة"</translation>
@@ -2124,7 +2122,6 @@
 <translation id="435527878592612277">اختيار صورتك</translation>
 <translation id="4356334633973342967">أو تحديد برنامج تشغيلك الخاص:</translation>
 <translation id="4358169392473932247">لا يتيح مفتاح الأمان ذلك وحدة تخزين داخلية لبيانات الاعتماد، ولكن تم طلب هذه الميزة.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />، و<ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">تم التثبيت بسبب الإضافة (الإضافات) التابعة.</translation>
 <translation id="4359717112757026264">مناظر المدن</translation>
 <translation id="4361142739114356624">المفتاح الخاص لشهادة العميل هذه مفقود أو غير صالح</translation>
@@ -2176,7 +2173,6 @@
 <translation id="443475966875174318">تحديث التطبيقات غير المتوافقة أو إزالتها</translation>
 <translation id="4441124369922430666">هل ترغب في تشغيل هذا التطبيق تلقائيًا عند تشغيل الجهاز؟</translation>
 <translation id="444134486829715816">توسيع...</translation>
-<translation id="4441548209689510310">عرض خيارات التدقيق الإملائي</translation>
 <translation id="4442424173763614572">تعذّر البحث في نظام أسماء النطاقات</translation>
 <translation id="4443536555189480885">&amp;تعليمات</translation>
 <translation id="4444304522807523469">‏الدخول إلى الماسحات الضوئية للمستند الملحق عبر جهاز USB أو على الشبكة المحلية</translation>
@@ -2972,7 +2968,6 @@
 <translation id="5736796278325406685">يُرجى إدخال اسم مستخدم صالح</translation>
 <translation id="5739235828260127894">في انتظار التحقُّق من صحة الاتصال. <ph name="LINK_BEGIN" />مزيد من المعلومات<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">كبير جدًا</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />، و<ph name="LANGUAGE_2" />، و<ph name="NUM_ADDITIONAL_LANGUAGES" /> من اللغات الأخرى</translation>
 <translation id="574209121243317957">درجة الصوت</translation>
 <translation id="5746169159649715125">‏حفظ بتنسيق ملف PDF</translation>
 <translation id="5747552184818312860">تاريخ انتهاء الصلاحية</translation>
diff --git a/chrome/app/resources/generated_resources_bg.xtb b/chrome/app/resources/generated_resources_bg.xtb
index d75f2e99..474da53 100644
--- a/chrome/app/resources/generated_resources_bg.xtb
+++ b/chrome/app/resources/generated_resources_bg.xtb
@@ -1531,7 +1531,6 @@
 <translation id="3435688026795609344"><ph name="EXTENSION_NAME" /> изисква вашия <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Сигурност</translation>
 <translation id="3435896845095436175">Активиране</translation>
-<translation id="3436038974659740746">Персонализиран правопис</translation>
 <translation id="3438633801274389918">Нинджа</translation>
 <translation id="3439153939049640737">Достъпът на <ph name="HOST" /> до микрофона ви винаги да е разрешен</translation>
 <translation id="3439970425423980614">Отваря се визуализация на PDF</translation>
@@ -1863,7 +1862,6 @@
 <translation id="3908393983276948098">Приставката <ph name="PLUGIN_NAME" /> не е актуална</translation>
 <translation id="3908501907586732282">Активиране на разширението</translation>
 <translation id="3909477809443608991"><ph name="URL" /> иска разрешение за възпроизвеждане на защитено съдържание. Идентичността на устройството ви ще бъде потвърдена от Google и този сайт може да осъществи достъп до нея.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> и още 1</translation>
 <translation id="3909791450649380159">Изрязва&amp;не</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (името се използва на това устройство)</translation>
 <translation id="3911824782900911339">Нов раздел в браузъра</translation>
@@ -2128,7 +2126,6 @@
 <translation id="435527878592612277">Изберете своя снимка</translation>
 <translation id="4356334633973342967">Или ръчно посочете драйвер:</translation>
 <translation id="4358169392473932247">Този ключ за сигурност не поддържа заявената функция за вътрешно хранилище за идентификационни данни.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" /> и <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Инсталирано заради зависимо разширение или съответно разширения.</translation>
 <translation id="4359717112757026264">Градски пейзажи</translation>
 <translation id="4361142739114356624">Частният ключ за този клиентски сертификат липсва или е невалиден</translation>
@@ -2180,7 +2177,6 @@
 <translation id="443475966875174318">Актуализиране или премахване на несъвместими приложения</translation>
 <translation id="4441124369922430666">Искате ли това приложение да стартира автоматично при включването на компютъра?</translation>
 <translation id="444134486829715816">Разгъване...</translation>
-<translation id="4441548209689510310">Показване на опциите за проверка на правописа</translation>
 <translation id="4442424173763614572">Търсенето в DNS не бе успешно</translation>
 <translation id="4443536555189480885">&amp;Помощ</translation>
 <translation id="4444304522807523469">Достъп до скенери на документи, свързани чрез USB или с локалната мрежа</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">Моля, въведете валидно потребителско име</translation>
 <translation id="5739235828260127894">Чака се потвърждение. <ph name="LINK_BEGIN" />Научете повече<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Много голям</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> и още <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Височина</translation>
 <translation id="5746169159649715125">Запазване като PDF файл</translation>
 <translation id="5747552184818312860">Изтича на</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index b66ccd1..5ad9718 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -1531,7 +1531,6 @@
 <translation id="3435688026795609344">আপনার  "<ph name="EXTENSION_NAME" />" <ph name="CODE_TYPE" /> এর অনুরোধ করছে</translation>
 <translation id="3435738964857648380">নিরাপত্তা</translation>
 <translation id="3435896845095436175">সক্ষম করুন</translation>
-<translation id="3436038974659740746">কাস্টম বানান</translation>
 <translation id="3438633801274389918">নিনজা</translation>
 <translation id="3439153939049640737"><ph name="HOST" /> কে সর্বদা আপনার মাইক্রোফোন অ্যাক্সেস করতে অনুমতি দিন</translation>
 <translation id="3439970425423980614">পূর্বরুপের মধ্যে PDF খোলা হচ্ছে</translation>
@@ -1861,7 +1860,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> পুরনো হয়ে গেছে</translation>
 <translation id="3908501907586732282">এক্সটেনশন চালু করুন</translation>
 <translation id="3909477809443608991"><ph name="URL" /> সুরক্ষিত কন্টেন্ট চালাতে চায়। আপনার ডিভাইসের পরিচয় Google যাচাই করে দেখবে এবং এই সাইট সম্ভবত সেটি অ্যাক্সেস করবে।</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, এবং আরও ১টি</translation>
 <translation id="3909791450649380159">কা&amp;ট করুন</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (এই ডিভাইসে ব্যবহৃত নাম)</translation>
 <translation id="3911824782900911339">নতুন ট্যাব পৃষ্ঠা</translation>
@@ -2125,7 +2123,6 @@
 <translation id="435527878592612277">আপনার ফটো বেছে নিন</translation>
 <translation id="4356334633973342967">অথবা আপনার নিজের ড্রাইভার উল্লেখ করুন:</translation>
 <translation id="4358169392473932247">নিরাপত্তা কী ডিভাইসে ক্রেডেনশিয়াল স্টোর করে রাখা যায় না, কিন্তু ফিচারটির জন্য অনুরোধ করা হয়েছে।</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">নির্ভরশীল এক্সটেনশন(গুলি) বলে ইনস্টল রয়েছে৷</translation>
 <translation id="4359717112757026264">শহরের দৃশ্য</translation>
 <translation id="4361142739114356624">এই ক্লায়েন্ট সার্টিফিকেটের জন্য ব্যক্তিগত কী পাওয়া যাচ্ছে না বা এটি ভুল</translation>
@@ -2177,7 +2174,6 @@
 <translation id="443475966875174318">অসঙ্গত অ্যাপ্লিকেশনগুলি আপডেট করুন অথবা সরিয়ে দিন</translation>
 <translation id="4441124369922430666">আপনি কি মেশিন চালু হওয়ার সময় স্বয়ংক্রিয়ভাবে এই অ্যাপ্লিকেশানটিকে চালু করতে চান?</translation>
 <translation id="444134486829715816">প্রসারিত করুন...</translation>
-<translation id="4441548209689510310">বানান পরীক্ষার বিকল্পগুলি দেখান</translation>
 <translation id="4442424173763614572">DNS খোঁজ ব্যর্থ হয়েছে</translation>
 <translation id="4443536555189480885">&amp;Help</translation>
 <translation id="4444304522807523469">USB বা স্থানীয় নেটওয়ার্কের মাধ্যমে সংযুক্ত দস্তাবেজ স্ক্যানার অ্যাক্সেস করে</translation>
@@ -2974,7 +2970,6 @@
 <translation id="5736796278325406685">অনুগ্রহ করে একটি সঠিক ইউজারনেম লিখুন</translation>
 <translation id="5739235828260127894">যাচাইকরণের জন্য অপেক্ষা করা হচ্ছে। <ph name="LINK_BEGIN" />আরও জানুন<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">খুব বড়</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, এবং আরও <ph name="NUM_ADDITIONAL_LANGUAGES" />টি</translation>
 <translation id="574209121243317957">পিচ</translation>
 <translation id="5746169159649715125">PDF রূপে সেভ করুন</translation>
 <translation id="5747552184818312860">মেয়াদ শেষ হবে</translation>
diff --git a/chrome/app/resources/generated_resources_ca.xtb b/chrome/app/resources/generated_resources_ca.xtb
index 01fbf82..f8def663 100644
--- a/chrome/app/resources/generated_resources_ca.xtb
+++ b/chrome/app/resources/generated_resources_ca.xtb
@@ -193,7 +193,7 @@
 <translation id="1277908057200820621">Mostra la llista de dispositius</translation>
 <translation id="1280820357415527819">S'estan cercant xarxes mòbils</translation>
 <translation id="1285320974508926690">No tradueixis mai aquest lloc</translation>
-<translation id="1285484354230578868">Emmagatzema les dades al compte de Google Drive</translation>
+<translation id="1285484354230578868">Emmagatzemar les dades al compte de Google Drive</translation>
 <translation id="1288037062697528143">La funció Llum nocturna s'activarà automàticament quan es pongui el sol</translation>
 <translation id="1288300545283011870">Propietats de la veu</translation>
 <translation id="1293264513303784526">Dispositiu USB-C (port esquerre)</translation>
@@ -279,7 +279,7 @@
 <translation id="1426870617281699524">Fes clic a Torna-ho a provar i accepta la sol·licitud que veuràs a l'ordinador</translation>
 <translation id="1427269577154060167">País</translation>
 <translation id="142758023928848008">Activa les tecles permanents (per fer tecles de drecera en escriure-les en ordre)</translation>
-<translation id="143027896309062157">Llegeix i modifica totes les dades de l'ordinador i els llocs web que es visitin</translation>
+<translation id="143027896309062157">Llegir i canviar totes les dades de l'ordinador i els llocs web que es visitin</translation>
 <translation id="1430915738399379752">Imprimeix</translation>
 <translation id="1432581352905426595">Gestiona els motors de cerca</translation>
 <translation id="1433811987160647649">Demana permís abans d'accedir</translation>
@@ -763,7 +763,7 @@
 <translation id="2202898655984161076">S'ha produït un problema en enumerar les impressores. Pot ser que algunes impressores no s'hagin registrat correctament a <ph name="CLOUD_PRINT_NAME" />.</translation>
 <translation id="2203484353475059657">La confirmació no coincideix.</translation>
 <translation id="2203682048752833055">Motor de cerca utilitzat a la <ph name="BEGIN_LINK" />barra d'adreces<ph name="END_LINK" /></translation>
-<translation id="2204034823255629767">Llegeix i modifica tot el que s'escrigui</translation>
+<translation id="2204034823255629767">Llegir i canviar tot el que s'escrigui</translation>
 <translation id="220792432208469595">Envia dades d'ús i de diagnòstic. En aquests moments aquest dispositiu envia automàticament a Google dades de diagnòstic, del dispositiu i d''ús d'aplicacions. Aquestes dades ajudaran a millorar l'estabilitat del sistema i de les aplicacions, entre altres característiques. Una part de les dades agregades també serà útil per a les aplicacions i els col·laboradors de Google, com ara els desenvolupadors d'Android. El propietari ha aplicat aquesta opció de configuració. Si tens activada l'opció Activitat al web i en aplicacions addicional, és possible que aquestes dades es desin al teu Compte de Google. <ph name="BEGIN_LINK1" />Més informació<ph name="END_LINK1" /></translation>
 <translation id="220858061631308971">Introduïu aquest codi PIN a "<ph name="DEVICE_NAME" />":</translation>
 <translation id="2213140827792212876">Deixa de compartir</translation>
@@ -938,7 +938,7 @@
 <translation id="2476578072172137802">Configuració del lloc web</translation>
 <translation id="2478176599153288112">Permisos de fitxer multimèdia per a "<ph name="EXTENSION" />"</translation>
 <translation id="247949520305900375">Comparteix l'àudio</translation>
-<translation id="2480868415629598489">Modifica les dades que copies i enganxes</translation>
+<translation id="2480868415629598489">Modificar les dades que copies i enganxes</translation>
 <translation id="2482878487686419369">Notificacions</translation>
 <translation id="2484959914739448251">Per esborrar les dades de navegació de tots els dispositius sincronitzats i del Compte de Google, <ph name="BEGIN_LINK" />introdueix la frase de contrasenya<ph name="END_LINK" />.</translation>
 <translation id="2485422356828889247">Desinstal·la</translation>
@@ -1082,7 +1082,7 @@
 <translation id="2691385045260836588">Model</translation>
 <translation id="2693176596243495071">S'ha produït un error desconegut. Torna-ho a provar més tard o contacta amb l'administrador si el problema no es resol.</translation>
 <translation id="2695749433451188613">Protocol d'impressió per Internet (HTTPS)</translation>
-<translation id="2699911226086014512">L'operació amb el PIN ha fallat; codi: <ph name="RETRIES" />.</translation>
+<translation id="2699911226086014512">Ha fallat l'operació del PIN; codi: <ph name="RETRIES" />.</translation>
 <translation id="270358213449696159">Contingut de les Condicions de Google Chrome OS</translation>
 <translation id="2704184184447774363">Signatura de documents de Microsoft</translation>
 <translation id="270516211545221798">Velocitat del ratolí tàctil</translation>
@@ -1522,14 +1522,13 @@
 <translation id="3428419049384081277">Has iniciat la sessió</translation>
 <translation id="3429275422858276529">Afegeix aquesta pàgina a les adreces d'interès per trobar-la fàcilment més endavant</translation>
 <translation id="3432227430032737297">Suprimeix totes les que es mostren</translation>
-<translation id="3432757130254800023">Envia àudio i vídeo a les visualitzacions de la xarxa local</translation>
+<translation id="3432757130254800023">Enviar àudio i vídeo a les visualitzacions de la xarxa local</translation>
 <translation id="3432762828853624962">Treballadors compartits</translation>
 <translation id="3433621910545056227">El sistema no ha pogut establir el bloqueig dels atributs del temps d'instal·lació del dispositiu.</translation>
 <translation id="3434107140712555581"><ph name="BATTERY_PERCENTAGE" />%</translation>
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" sol·licita el teu codi <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Seguretat</translation>
 <translation id="3435896845095436175">Activa</translation>
-<translation id="3436038974659740746">Ortografia personalitzada</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Permet sempre que <ph name="HOST" /> accedeixi al micròfon</translation>
 <translation id="3439970425423980614">S'està obrint la previsualització en PDF</translation>
@@ -1752,7 +1751,7 @@
 <translation id="375841316537350618">S'està baixant l'script de servidor intermediari...</translation>
 <translation id="3758842566811519622">S'han establert les galetes</translation>
 <translation id="3759371141211657149">Gestiona la configuració de gestors...</translation>
-<translation id="3759933321830434300">Bloqueig d'elements de pàgines web</translation>
+<translation id="3759933321830434300">Bloquejar elements de pàgines web</translation>
 <translation id="3760460896538743390">Inspecciona la &amp;pàgina de fons</translation>
 <translation id="37613671848467444">Obre en una &amp;finestra d'incògnit</translation>
 <translation id="3764314093345384080">Informació detallada de la compilació</translation>
@@ -1846,7 +1845,7 @@
 <translation id="3892414795099177503">Afegeix OpenVPN/L2TP…</translation>
 <translation id="3893536212201235195">Llegir i canviar la configuració d'accessibilitat</translation>
 <translation id="3893630138897523026">ChromeVox (comentaris de veu)</translation>
-<translation id="3894123633473837029">Inclou l'historial recent de l'Assistent a través de Sherlog. Pot incloure la teva identitat, la teva ubicació i dades de depuració. <ph name="BEGIN_LINK" />Més informació<ph name="END_LINK" /></translation>
+<translation id="3894123633473837029">Inclou l'historial recent de l'Assistent a través de Sherlog. Pot incloure informació sobre la teva identitat, la teva ubicació i dades de depuració. <ph name="BEGIN_LINK" />Més informació<ph name="END_LINK" /></translation>
 <translation id="3894427358181296146">Afegeix una carpeta</translation>
 <translation id="389589731200570180">Compartiu amb els convidats</translation>
 <translation id="3898521660513055167">Estat del testimoni</translation>
@@ -1859,7 +1858,6 @@
 <translation id="3908393983276948098">El connector <ph name="PLUGIN_NAME" /> no està actualitzat</translation>
 <translation id="3908501907586732282">Activa l'extensió</translation>
 <translation id="3909477809443608991"><ph name="URL" /> vol reproduir contingut protegit. Google verificarà la identitat del teu dispositiu i aquest lloc web hi podrà accedir.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> i 1 més</translation>
 <translation id="3909791450649380159">Re&amp;talla</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nom utilitzat en aquest dispositiu)</translation>
 <translation id="3911824782900911339">Pàgina Pestanya nova</translation>
@@ -1993,7 +1991,7 @@
 <translation id="4100733287846229632">Queda molt poc espai al dispositiu</translation>
 <translation id="4103091233824664032">Introdueix la contrasenya per configurar el bloqueig de pantalla i l'inici de sessió</translation>
 <translation id="4104163789986725820">E&amp;xporta...</translation>
-<translation id="4107048419833779140">Identifica i expulsa els dispositius d'emmagatzematge</translation>
+<translation id="4107048419833779140">Identificar i expulsar els dispositius d'emmagatzematge</translation>
 <translation id="4109135793348361820">Mou la finestra a <ph name="USER_NAME" /> (<ph name="USER_EMAIL" />)</translation>
 <translation id="4110490973560452005">S'ha completat la baixada: <ph name="FILE_NAME" />. Prem Maj+F6 per anar a l'àrea de la barra de baixades.</translation>
 <translation id="4110895898888439383">Navega per Internet en mode d'alt contrast</translation>
@@ -2123,7 +2121,6 @@
 <translation id="435527878592612277">Selecciona la teva foto</translation>
 <translation id="4356334633973342967">O especifica el teu controlador:</translation>
 <translation id="4358169392473932247">Tot i que aquesta clau de seguretat no admet l'emmagatzematge intern de credencials, aquesta funció s'ha sol·licitat.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" /> i <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">S'ha instal·lat perquè té extensions que en depenen.</translation>
 <translation id="4359717112757026264">Paisatge urbà</translation>
 <translation id="4361142739114356624">Falta la clau privada d'aquest certificat del client o no és vàlida</translation>
@@ -2175,7 +2172,6 @@
 <translation id="443475966875174318">Actualitza o suprimeix les aplicacions incompatibles</translation>
 <translation id="4441124369922430666">Voleu que aquesta aplicació s'iniciï automàticament en engegar l'ordinador?</translation>
 <translation id="444134486829715816">Amplia...</translation>
-<translation id="4441548209689510310">Mostra les opcions del corrector ortogràfic</translation>
 <translation id="4442424173763614572">La cerca de DNS ha fallat</translation>
 <translation id="4443536555189480885">&amp;Ajuda</translation>
 <translation id="4444304522807523469">Accedir als escàners del document adjunts mitjançant USB o a la xarxa local</translation>
@@ -2581,7 +2577,7 @@
 <translation id="5121130586824819730">El vostre disc dur és ple. Deseu-ho en una altra ubicació o allibereu espai del disc dur.</translation>
 <translation id="5125751979347152379">URL no vàlid.</translation>
 <translation id="5127805178023152808">Sincronització desactivada</translation>
-<translation id="5127881134400491887">Gestioneu les connexions de xarxa</translation>
+<translation id="5127881134400491887">Gestionar les connexions de xarxa</translation>
 <translation id="512903556749061217">connectat</translation>
 <translation id="5133483819862530305">De la posta de sol a l'alba</translation>
 <translation id="5135533361271311778">No s'ha pogut crear l'element d'adreça d'interès.</translation>
@@ -2640,7 +2636,7 @@
 <translation id="5233736638227740678">&amp;Enganxa</translation>
 <translation id="5234764350956374838">Omet</translation>
 <translation id="5235050375939235066">Vols desinstal·lar l'aplicació?</translation>
-<translation id="5235750401727657667">Substitueix la pàgina que veus en obrir una pestanya nova</translation>
+<translation id="5235750401727657667">Substituir la pàgina que veus en obrir una pestanya nova</translation>
 <translation id="5238278114306905396">L'aplicació "<ph name="EXTENSION_NAME" />" s'ha eliminat automàticament.</translation>
 <translation id="5238369540257804368">Àmbits</translation>
 <translation id="5241128660650683457">Llegir totes les dades dels llocs web que es visitin</translation>
@@ -2973,7 +2969,6 @@
 <translation id="5736796278325406685">Introdueix un nom d'usuari vàlid</translation>
 <translation id="5739235828260127894">S'està esperant la verificació. <ph name="LINK_BEGIN" />Més informació<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Molt gran</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> i <ph name="NUM_ADDITIONAL_LANGUAGES" /> més</translation>
 <translation id="574209121243317957">To</translation>
 <translation id="5746169159649715125">Desa com a PDF</translation>
 <translation id="5747552184818312860">Data de caducitat</translation>
@@ -3390,7 +3385,7 @@
 <translation id="6374469231428023295">Torna-ho a provar</translation>
 <translation id="6377268785556383139">1 resultat per a "<ph name="SEARCH_TEXT" />"</translation>
 <translation id="6380143666419481200">Accepta i continua</translation>
-<translation id="6384275966486438344">Canvia la configuració de la cerca a: <ph name="SEARCH_HOST" /></translation>
+<translation id="6384275966486438344">Canviar la configuració de la cerca a: <ph name="SEARCH_HOST" /></translation>
 <translation id="6385543213911723544">Els llocs poden desar i llegir dades de galetes</translation>
 <translation id="6386099547750337629">Si no esperaves aquest canvi, contacta amb el servei d'assistència.</translation>
 <translation id="6388429472088318283">Cerca idiomes</translation>
@@ -3787,7 +3782,7 @@
 <translation id="7017219178341817193">Afegeix una pàgina nova</translation>
 <translation id="7017354871202642555">No es pot configurar el mode després d'haver configurat la finestra.</translation>
 <translation id="7017480957358237747">permet o prohibeix llocs web determinats,</translation>
-<translation id="7018275672629230621">Llegeix i modifica l'historial de navegació</translation>
+<translation id="7018275672629230621">Llegir i canviar l'historial de navegació</translation>
 <translation id="7019805045859631636">Ràpid</translation>
 <translation id="7022562585984256452">S'ha definit la pàgina d'inici.</translation>
 <translation id="7025190659207909717">Gestió de serveis de dades mòbils</translation>
@@ -4227,7 +4222,7 @@
 <translation id="7724603315864178912">Retalla</translation>
 <translation id="7728570244950051353">Bloqueja la pantalla des del mode de repòs</translation>
 <translation id="7728668285692163452">El canvi de canal s'aplicarà més tard</translation>
-<translation id="7730449930968088409">Captura del contingut de la pantalla</translation>
+<translation id="7730449930968088409">Capturar el contingut de la pantalla</translation>
 <translation id="7732111077498238432">La xarxa està controlada per una política</translation>
 <translation id="7737238973539693982">Suprimeix Linux (versió beta)</translation>
 <translation id="773905249182896430">Et protegeix i protegeix el teu dispositiu de llocs web perillosos</translation>
@@ -4393,7 +4388,7 @@
 <translation id="7961015016161918242">Mai</translation>
 <translation id="7963826112438303517">L'Assistent utilitza aquestes gravacions i les sol·licituds de veu per crear i actualitzar el teu model de veu, que només es desa als dispositius en què has activat Voice Match. Consulta l'activitat de veu o torna a entrenar el model a Configuració de l'Assistent.</translation>
 <translation id="7966241909927244760">C&amp;opia l'adreça de la imatge</translation>
-<translation id="7968742106503422125">Llegeix i modifica les dades que copies i enganxes</translation>
+<translation id="7968742106503422125">Llegir i modificar les dades que copies i enganxes</translation>
 <translation id="7968833647796919681">Activa la recollida de dades de rendiment</translation>
 <translation id="7969046989155602842">Ordre</translation>
 <translation id="7972714317346275248">PKCS #1 SHA-384 amb encriptació RSA</translation>
@@ -4410,7 +4405,7 @@
 <translation id="7982083145464587921">Reinicieu el dispositiu per corregir aquest error.</translation>
 <translation id="7982789257301363584">Xarxa</translation>
 <translation id="7984068253310542383">Projecta la pantalla <ph name="DISPLAY_NAME" /></translation>
-<translation id="7986295104073916105">Llegiu i canvieu la configuració de les contrasenyes desades</translation>
+<translation id="7986295104073916105">Llegir i canviar la configuració de les contrasenyes desades</translation>
 <translation id="7987814697832569482">Connecta't sempre a través d'aquesta VPN</translation>
 <translation id="798835209536175951">Envia i rep missatges de text amb Chromebook. <ph name="LINK_BEGIN" />Més informació<ph name="LINK_END" /></translation>
 <translation id="7988355189918024273">Activa les funcions d'accessibilitat</translation>
@@ -4819,7 +4814,7 @@
 <translation id="8662671328352114214">Connecta't a una xarxa <ph name="TYPE" /></translation>
 <translation id="8662795692588422978">Usuaris</translation>
 <translation id="8662811608048051533">Et tanca la sessió de la majoria de llocs.</translation>
-<translation id="8662911384982557515">Canvia la pàgina d'inici per: <ph name="HOME_PAGE" /></translation>
+<translation id="8662911384982557515">Canviar la pàgina d'inici per: <ph name="HOME_PAGE" /></translation>
 <translation id="8662978096466608964">Chrome no pot establir un fons de pantalla.</translation>
 <translation id="8663099077749055505">Bloqueja sempre les baixades automàtiques múltiples a l'amfitrió <ph name="HOST" /></translation>
 <translation id="8664389313780386848">&amp;Visualitza l'origen de la pàgina</translation>
@@ -4872,7 +4867,7 @@
 <translation id="8726206820263995930">S'ha produït un error en recuperar la configuració de la política del servidor: <ph name="CLIENT_ERROR" />.</translation>
 <translation id="8730621377337864115">Fet</translation>
 <translation id="8732030010853991079">Per fer servir aquesta extensió, feu clic en aquesta icona.</translation>
-<translation id="8732212173949624846">Llegeix i modifica l'historial de navegació en tots els dispositius on s'hagi iniciat la sessió</translation>
+<translation id="8732212173949624846">Llegir i canviar l'historial de navegació en tots els dispositius on s'hagi iniciat la sessió</translation>
 <translation id="8732844209475700754">Més opcions de configuració relacionades amb la privadesa, la seguretat i la recollida de dades</translation>
 <translation id="8734073480934656039">Si s'activa aquesta configuració, les aplicacions de quiosc es podran iniciar automàticament en iniciar el dispositiu.</translation>
 <translation id="873545264931343897">Quan el connector <ph name="PLUGIN_NAME" /> s'acabi d'actualitzar, torna a carregar la pàgina per activar-lo</translation>
@@ -4949,7 +4944,7 @@
 <translation id="883911313571074303">Afegeix una anotació a la imatge</translation>
 <translation id="8845001906332463065">Obteniu ajuda</translation>
 <translation id="8845164297565101021">Insereix la clau de seguretat i toca-la per crear un PIN o canviar l'existent.</translation>
-<translation id="8846132060409673887">Consulta el fabricant i el model d'aquest ordinador</translation>
+<translation id="8846132060409673887">Consultar el fabricant i el model d'aquest ordinador</translation>
 <translation id="8846141544112579928">S'està cercant el teclat...</translation>
 <translation id="8847988622838149491">USB</translation>
 <translation id="8848561196844274665">En connectar els dispositius, acceptes que Chromebook pugui fer el següent:</translation>
@@ -5053,7 +5048,7 @@
 <translation id="9013707997379828817">L'administrador ha canviat la versió del dispositiu a una d'anterior. Desa els fitxers importants i, després, reinicia el dispositiu. Se'n suprimiran totes les dades.</translation>
 <translation id="9018218886431812662">La instal·lació s'ha completat</translation>
 <translation id="901834265349196618">correu electrònic</translation>
-<translation id="9019062154811256702">Llegiu i canvieu la configuració d'Emplenament automàtic</translation>
+<translation id="9019062154811256702">Llegir i canviar la configuració d'Emplenament automàtic</translation>
 <translation id="9020362265352758658">4x</translation>
 <translation id="9021662811137657072">S'ha detectat un virus</translation>
 <translation id="9022847679183471841"><ph name="AVATAR_NAME" /> ja utilitza aquest compte en aquest equip.</translation>
diff --git a/chrome/app/resources/generated_resources_cs.xtb b/chrome/app/resources/generated_resources_cs.xtb
index 2e30484..55c8ab6 100644
--- a/chrome/app/resources/generated_resources_cs.xtb
+++ b/chrome/app/resources/generated_resources_cs.xtb
@@ -1531,7 +1531,6 @@
 <translation id="3435688026795609344">Rozšíření <ph name="EXTENSION_NAME" /> požaduje váš kód <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Zabezpečení</translation>
 <translation id="3435896845095436175">Aktivovat</translation>
-<translation id="3436038974659740746">Vlastní pravopis</translation>
 <translation id="3438633801274389918">Nindža</translation>
 <translation id="3439153939049640737">Vždy povolit webu <ph name="HOST" /> přístup k mikrofonu</translation>
 <translation id="3439970425423980614">Otevírání souboru PDF v náhledu</translation>
@@ -1861,7 +1860,6 @@
 <translation id="3908393983276948098">Plugin <ph name="PLUGIN_NAME" /> je zastaralý</translation>
 <translation id="3908501907586732282">Aktivovat rozšíření</translation>
 <translation id="3909477809443608991"><ph name="URL" /> chce přehrávat chráněný obsah. Google ověří identitu vašeho zařízení a tento web k ní může získat přístup.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> a jeden další jazyk</translation>
 <translation id="3909791450649380159">Vyjmou&amp;t</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (jméno používané v tomto zařízení)</translation>
 <translation id="3911824782900911339">Stránka Nová karta</translation>
@@ -2125,7 +2123,6 @@
 <translation id="435527878592612277">Vyberte svou fotografii</translation>
 <translation id="4356334633973342967">Případně zadejte vlastní ovladač:</translation>
 <translation id="4358169392473932247">Tento bezpečnostní klíč nepodporuje interní úložiště identifikačních údajů, ale tato funkce byla vyžádána.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Rozšíření bylo nainstalováno kvůli závislým rozšířením.</translation>
 <translation id="4359717112757026264">Města</translation>
 <translation id="4361142739114356624">Soukromý klíč tohoto klientského certifikátu chybí nebo je neplatný</translation>
@@ -2177,7 +2174,6 @@
 <translation id="443475966875174318">Aktualizujte nebo odstraňte nekompatibilní aplikace</translation>
 <translation id="4441124369922430666">Chcete tuto aplikaci automaticky spustit, když se zařízení zapne?</translation>
 <translation id="444134486829715816">Rozbalit...</translation>
-<translation id="4441548209689510310">Zobrazit možnosti kontroly pravopisu</translation>
 <translation id="4442424173763614572">Nepodařilo se nalézt server DNS.</translation>
 <translation id="4443536555189480885">&amp;Nápověda</translation>
 <translation id="4444304522807523469">Přístup ke skenerům dokumentů připojeným přes USB nebo v místní síti</translation>
@@ -2973,7 +2969,6 @@
 <translation id="5736796278325406685">Zadejte prosím platné uživatelské jméno</translation>
 <translation id="5739235828260127894">Čeká na ověření. <ph name="LINK_BEGIN" />Další informace<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Velmi velké</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> a další <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Výška</translation>
 <translation id="5746169159649715125">Uložit jako PDF</translation>
 <translation id="5747552184818312860">Konec platnosti</translation>
@@ -4678,7 +4673,7 @@
 <translation id="8431190899827883166">Zobrazovat klepnutí</translation>
 <translation id="8431909052837336408">Změnit PIN SIM karty</translation>
 <translation id="8434480141477525001">Port ladění klientu NaCl</translation>
-<translation id="8435395510592618362">Ověřte svou identitu pomocí aplikace <ph name="APP_NAME" /></translation>
+<translation id="8435395510592618362">Ověření identity pomocí domény <ph name="APP_NAME" /></translation>
 <translation id="843760761634048214">Uložit platební kartu</translation>
 <translation id="8438328416656800239">Přejděte na chytrý prohlížeč</translation>
 <translation id="8438566539970814960">Vylepšit vyhledávání a procházení</translation>
diff --git a/chrome/app/resources/generated_resources_da.xtb b/chrome/app/resources/generated_resources_da.xtb
index 1dc6668..86199b6c 100644
--- a/chrome/app/resources/generated_resources_da.xtb
+++ b/chrome/app/resources/generated_resources_da.xtb
@@ -116,7 +116,7 @@
 <translation id="1168100932582989117">Googles navneservere</translation>
 <translation id="1169909785351611170">Pinkoden er forkert.</translation>
 <translation id="1171135284592304528">Fremhæv elementet med tastaturfokus, når det ændres.</translation>
-<translation id="1172750555846831341">Vend efter kort kant</translation>
+<translation id="1172750555846831341">Vend ved kort kant</translation>
 <translation id="1173894706177603556">Omdøb</translation>
 <translation id="1173919438868967364">Vælg konto</translation>
 <translation id="1174073918202301297">Genvejen blev tilføjet</translation>
@@ -1269,7 +1269,7 @@
 <translation id="2993517869960930405">Oplysninger om appen</translation>
 <translation id="299483336428448530">Installeret af din forælder.</translation>
 <translation id="2996286169319737844">Dataene er krypteret med din adgangssætning til synkronisering. Dette omfatter ikke betalingsmetoder og adresser fra Google Pay.</translation>
-<translation id="2996722619877761919">Vend efter lang kant</translation>
+<translation id="2996722619877761919">Vend ved lang kant</translation>
 <translation id="3003144360685731741">Favoritter netværk</translation>
 <translation id="3003623123441819449">CSS-cache</translation>
 <translation id="3003828226041301643">Enheden kunne ikke knyttes til domænet. Sørg for, at din konto har tilladelse til at tilføje enheder.</translation>
@@ -1532,7 +1532,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" anmoder om <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Sikkerhed</translation>
 <translation id="3435896845095436175">Aktivér</translation>
-<translation id="3436038974659740746">Tilpasset stavning</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Tillad altid, at <ph name="HOST" /> har adgang til din mikrofon</translation>
 <translation id="3439970425423980614">Åbner PDF i fremviseren</translation>
@@ -1862,7 +1861,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> er forældet</translation>
 <translation id="3908501907586732282">Aktivér udvidelse</translation>
 <translation id="3909477809443608991"><ph name="URL" /> vil afspille beskyttet indhold. Din enheds identitet bekræftes af Google, og dette website får muligvis adgang til enheden.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> og ét mere</translation>
 <translation id="3909791450649380159">Kli&amp;p</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (det navn, der anvendes på enheden)</translation>
 <translation id="3911824782900911339">Siden Ny fane</translation>
@@ -2127,7 +2125,6 @@
 <translation id="435527878592612277">Vælg dit billede</translation>
 <translation id="4356334633973342967">Du kan også angive din egen driver:</translation>
 <translation id="4358169392473932247">Der blev anmodet om intern lagring af loginoplysninger, men sikkerhedsnøglen understøtter ikke denne funktion.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Installeret på grund af andre udvidelser, der er afhængige af den.</translation>
 <translation id="4359717112757026264">Cityscape</translation>
 <translation id="4361142739114356624">Den private nøgle til dette klientcertifikat mangler eller er ugyldig</translation>
@@ -2179,7 +2176,6 @@
 <translation id="443475966875174318">Opdater eller fjern ikke-kompatible apps</translation>
 <translation id="4441124369922430666">Skal denne app startes automatisk, når du tænder computeren?</translation>
 <translation id="444134486829715816">Udvid...</translation>
-<translation id="4441548209689510310">Vis indstillinger for stavekontrol</translation>
 <translation id="4442424173763614572">DNS-opslag mislykkedes</translation>
 <translation id="4443536555189480885">&amp;Hjælp</translation>
 <translation id="4444304522807523469">Få adgang til dokumentscannere, der er forbundet via USB eller det lokale netværk</translation>
@@ -2975,7 +2971,6 @@
 <translation id="5736796278325406685">Angiv et gyldigt brugernavn</translation>
 <translation id="5739235828260127894">Venter på bekræftelse. <ph name="LINK_BEGIN" />Få flere oplysninger<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Meget stor</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> og <ph name="NUM_ADDITIONAL_LANGUAGES" /> andre</translation>
 <translation id="574209121243317957">Toneleje</translation>
 <translation id="5746169159649715125">Gem som PDF</translation>
 <translation id="5747552184818312860">Udløber</translation>
@@ -3256,7 +3251,7 @@
 <translation id="6156323911414505561">Vis bogmærkelinjen</translation>
 <translation id="6156863943908443225">Scriptcache</translation>
 <translation id="6156960295318603523">Sprogindstillinger</translation>
-<translation id="6159328879826063795">Sikkerhedsnøglen understøtter ikke den anmodede funktion.</translation>
+<translation id="6159328879826063795">Sikkerhedsnøglen understøtter ikke den funktion, der anmodes om.</translation>
 <translation id="6160625263637492097">Levér certifikater til godkendelse</translation>
 <translation id="6163363155248589649">&amp;Normal</translation>
 <translation id="6163522313638838258">Udvid alle...</translation>
diff --git a/chrome/app/resources/generated_resources_de.xtb b/chrome/app/resources/generated_resources_de.xtb
index b22ee66..13797e7c 100644
--- a/chrome/app/resources/generated_resources_de.xtb
+++ b/chrome/app/resources/generated_resources_de.xtb
@@ -1529,7 +1529,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" fordert Ihren <ph name="CODE_TYPE" /> an.</translation>
 <translation id="3435738964857648380">Sicherheit</translation>
 <translation id="3435896845095436175">Aktivieren</translation>
-<translation id="3436038974659740746">Benutzerdefinierte Rechtschreibprüfung</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737"><ph name="HOST" /> immer Zugriff auf Ihr Mikrofon gestatten</translation>
 <translation id="3439970425423980614">PDF-Vorschau wird geöffnet...</translation>
@@ -1859,7 +1858,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> ist veraltet</translation>
 <translation id="3908501907586732282">Erweiterung aktivieren</translation>
 <translation id="3909477809443608991"><ph name="URL" /> möchte geschützten Inhalt abspielen. Die Identität Ihres Geräts wird von Google überprüft, weshalb möglicherweise ein Zugriff durch diese Website erfolgt.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> und eine andere Sprache</translation>
 <translation id="3909791450649380159">&amp;Ausschneiden</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (auf diesem Gerät verwendeter Name)</translation>
 <translation id="3911824782900911339">"Neuer Tab"-Seite</translation>
@@ -2124,7 +2122,6 @@
 <translation id="435527878592612277">Foto auswählen</translation>
 <translation id="4356334633973342967">Oder eigenen Treiber angeben:</translation>
 <translation id="4358169392473932247">Dieser Sicherheitsschlüssel unterstützt keine interne Speicherung von Anmeldedaten. Eine entsprechende Funktionsanfrage wurde jedoch gestellt.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Wurde aufgrund der abhängigen Erweiterungen installiert</translation>
 <translation id="4359717112757026264">Stadtlandschaft</translation>
 <translation id="4361142739114356624">Der private Schlüssel für dieses Clientzertifikat fehlt oder ist ungültig</translation>
@@ -2176,7 +2173,6 @@
 <translation id="443475966875174318">Nicht kompatible Anwendungen aktualisieren oder entfernen</translation>
 <translation id="4441124369922430666">Soll diese App beim Einschalten des Geräts automatisch gestartet werden?</translation>
 <translation id="444134486829715816">Anzeigen...</translation>
-<translation id="4441548209689510310">Optionen für die Rechtschreibprüfung anzeigen</translation>
 <translation id="4442424173763614572">DNS-Suche fehlgeschlagen</translation>
 <translation id="4443536555189480885">&amp;Hilfe</translation>
 <translation id="4444304522807523469">Auf Dokumentenscanner zugreifen, die per USB angeschlossen sind oder sich im lokalen Netzwerk befinden</translation>
@@ -2972,7 +2968,6 @@
 <translation id="5736796278325406685">Bitte geben Sie einen gültigen Nutzernamen ein</translation>
 <translation id="5739235828260127894">Bestätigung steht aus. <ph name="LINK_BEGIN" />Weitere Informationen<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Sehr groß</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> und <ph name="NUM_ADDITIONAL_LANGUAGES" /> andere Sprachen</translation>
 <translation id="574209121243317957">Tonhöhe</translation>
 <translation id="5746169159649715125">Als PDF speichern</translation>
 <translation id="5747552184818312860">Ablaufdatum</translation>
diff --git a/chrome/app/resources/generated_resources_el.xtb b/chrome/app/resources/generated_resources_el.xtb
index 2a4704f..b525c9a6 100644
--- a/chrome/app/resources/generated_resources_el.xtb
+++ b/chrome/app/resources/generated_resources_el.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">Η επέκταση "<ph name="EXTENSION_NAME" />" ζητά το <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Ασφάλεια</translation>
 <translation id="3435896845095436175">Ενεργοποίηση</translation>
-<translation id="3436038974659740746">Προσαρμοσμένη ορθογραφία</translation>
 <translation id="3438633801274389918">Νίντζα</translation>
 <translation id="3439153939049640737">Να επιτρέπεται πάντα στο <ph name="HOST" /> η πρόσβαση στο μικρόφωνό σας</translation>
 <translation id="3439970425423980614">Άνοιγμα PDF σε προεπισκόπηση</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">Η προσθήκη <ph name="PLUGIN_NAME" /> δεν είναι ενημερωμένη</translation>
 <translation id="3908501907586732282">Ενεργοποίηση επέκτασης</translation>
 <translation id="3909477809443608991">Το <ph name="URL" /> επιθυμεί την αναπαραγωγή προστατευμένου περιεχομένου. Η ταυτότητα της συσκευής σας θα επαληθευτεί από την Google και αυτός ο ιστότοπος μπορεί να αποκτήσει πρόσβαση σε αυτήν.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> και 1 ακόμη</translation>
 <translation id="3909791450649380159">Απο&amp;κοπή</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (το όνομα χρησιμοποιείται ήδη σε αυτήν τη συσκευή)</translation>
 <translation id="3911824782900911339">Σελίδα νέας καρτέλας</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Επιλέξτε τη φωτογραφία σας</translation>
 <translation id="4356334633973342967">Εναλλακτικά, ορίστε το δικό σας πρόγραμμα οδήγησης:</translation>
 <translation id="4358169392473932247">Αυτό το κλειδί ασφαλείας δεν υποστηρίζει τον εσωτερικό αποθηκευτικό χώρο των διαπιστευτηρίων, αλλά αυτή η λειτουργία έχει ζητηθεί.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Εγκαταστάθηκε λόγω των εξαρτώμενων επεκτάσεων</translation>
 <translation id="4359717112757026264">Αστικό τοπίο</translation>
 <translation id="4361142739114356624">Το Ιδιωτικό κλειδί για αυτό το Πιστοποιητικό πελάτη λείπει ή δεν είναι έγκυρο</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Ενημέρωση ή κατάργηση μη συμβατών εφαρμογών</translation>
 <translation id="4441124369922430666">Θέλετε να ξεκινά αυτόματα αυτή η εφαρμογή όταν η συσκευή τίθεται σε λειτουργία;</translation>
 <translation id="444134486829715816">Ανάπτυξη...</translation>
-<translation id="4441548209689510310">Εμφάνιση επιλογών ορθογραφικού ελέγχου</translation>
 <translation id="4442424173763614572">Η αναζήτηση DNS απέτυχε</translation>
 <translation id="4443536555189480885">&amp;Βοήθεια</translation>
 <translation id="4444304522807523469">Πρόσβαση στους σαρωτές εγγράφων που προσαρτώνται μέσω USB ή σε κάποιο τοπικό δίκτυο</translation>
@@ -2978,7 +2974,6 @@
 <translation id="5736796278325406685">Καταχωρίστε ένα έγκυρο όνομα χρήστη</translation>
 <translation id="5739235828260127894">Αναμονή για επαλήθευση. <ph name="LINK_BEGIN" />Μάθετε περισσότερα<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Πολύ μεγάλο</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> και <ph name="NUM_ADDITIONAL_LANGUAGES" /> ακόμη</translation>
 <translation id="574209121243317957">Τόνος</translation>
 <translation id="5746169159649715125">Αποθήκευση ως PDF</translation>
 <translation id="5747552184818312860">Λήγει</translation>
diff --git a/chrome/app/resources/generated_resources_en-GB.xtb b/chrome/app/resources/generated_resources_en-GB.xtb
index 47c9a31..da0632f1 100644
--- a/chrome/app/resources/generated_resources_en-GB.xtb
+++ b/chrome/app/resources/generated_resources_en-GB.xtb
@@ -1533,7 +1533,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" is requesting your <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Security</translation>
 <translation id="3435896845095436175">Enable</translation>
-<translation id="3436038974659740746">Customised spelling</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Always allow <ph name="HOST" /> to access your microphone</translation>
 <translation id="3439970425423980614">Opening PDF in Preview</translation>
@@ -1863,7 +1862,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> is out of date</translation>
 <translation id="3908501907586732282">Enable extension</translation>
 <translation id="3909477809443608991"><ph name="URL" /> wants to play protected content. Your device's identity will be verified by Google and may be accessed by this site.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, and 1 other</translation>
 <translation id="3909791450649380159">Cu&amp;t</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (name used on this device)</translation>
 <translation id="3911824782900911339">New Tab page</translation>
@@ -2128,7 +2126,6 @@
 <translation id="435527878592612277">Select your photo</translation>
 <translation id="4356334633973342967">Or specify your own driver:</translation>
 <translation id="4358169392473932247">That security key does not support internal storage of credentials, but that feature was requested.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Installed because of dependent extension(s).</translation>
 <translation id="4359717112757026264">Cityscape</translation>
 <translation id="4361142739114356624">The Private Key for this Client Certificate is missing or invalid</translation>
@@ -2164,7 +2161,7 @@
 <translation id="44141919652824029">Allow '<ph name="APP_NAME" />' to get the list of your attached USB devices?</translation>
 <translation id="4414232939543644979">New &amp;Incognito Window</translation>
 <translation id="4415245286584082850">No devices found. Open a help centre article in a new tab.</translation>
-<translation id="4415276339145661267">Manage yourGoogle Account</translation>
+<translation id="4415276339145661267">Manage your Google Account</translation>
 <translation id="4415748029120993980">SECG elliptic curve secp384r1 (aka NIST P-384)</translation>
 <translation id="4416582610654027550">Type a valid URL</translation>
 <translation id="4419409365248380979">Always allow <ph name="HOST" /> to set cookies</translation>
@@ -2180,7 +2177,6 @@
 <translation id="443475966875174318">Update or remove incompatible applications</translation>
 <translation id="4441124369922430666">Do you want to automatically start this app when the machine turns on?</translation>
 <translation id="444134486829715816">Expand...</translation>
-<translation id="4441548209689510310">Show spell check options</translation>
 <translation id="4442424173763614572">DNS lookup failed</translation>
 <translation id="4443536555189480885">&amp;Help</translation>
 <translation id="4444304522807523469">Access document scanners attached via USB or on the local network</translation>
@@ -2459,7 +2455,7 @@
 <translation id="4907161631261076876">This file is not commonly downloaded and may be dangerous.</translation>
 <translation id="4907306957610201395">Permission Category</translation>
 <translation id="4908811072292128752">Open a new tab to browse two sites at once</translation>
-<translation id="4909038193460299775">Because this account is managed by <ph name="DOMAIN" />, your bookmarks, history, passwords and other settings will be cleared from this device. However, your data will remain stored in your Google Accountand can be managed on <ph name="BEGIN_LINK" />Google Dashboard<ph name="END_LINK" />.</translation>
+<translation id="4909038193460299775">Because this account is managed by <ph name="DOMAIN" />, your bookmarks, history, passwords and other settings will be cleared from this device. However, your data will remain stored in your Google Account and can be managed on <ph name="BEGIN_LINK" />Google Dashboard<ph name="END_LINK" />.</translation>
 <translation id="4909359680501173791">You are enrolled successfully</translation>
 <translation id="4912643508233590958">Idle Wake Ups</translation>
 <translation id="491691592645955587">Switch to a secure browser</translation>
@@ -2490,7 +2486,7 @@
 <translation id="4955710816792587366">Choose your PIN</translation>
 <translation id="4955814292505481804">Annual</translation>
 <translation id="4957949153200969297">Only enable features related to <ph name="IDS_SHORT_PRODUCT_NAME" /> Sync</translation>
-<translation id="4959262764292427323">Passwords are saved in your Google Accountso that you can use them on any device</translation>
+<translation id="4959262764292427323">Passwords are saved in your Google Account so that you can use them on any device</translation>
 <translation id="4960294539892203357"><ph name="WINDOW_TITLE" /> – <ph name="PROFILE_NAME" /></translation>
 <translation id="4964455510556214366">Arrangement</translation>
 <translation id="4964673849688379040">Checking...</translation>
@@ -2976,7 +2972,6 @@
 <translation id="5736796278325406685">Please enter a valid username</translation>
 <translation id="5739235828260127894">Waiting for verification. <ph name="LINK_BEGIN" />Find out more<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Very large</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, and <ph name="NUM_ADDITIONAL_LANGUAGES" /> others</translation>
 <translation id="574209121243317957">Pitch</translation>
 <translation id="5746169159649715125">Save as PDF</translation>
 <translation id="5747552184818312860">Expires</translation>
@@ -5185,7 +5180,7 @@
 <translation id="93343527085570547">Go to the <ph name="BEGIN_LINK1" />Legal Help page<ph name="END_LINK1" /> to request content changes for legal reasons. Some account and system information may be sent to Google. We will use the information that you give us to help address technical issues and to improve our services, subject to our <ph name="BEGIN_LINK2" />Privacy Policy<ph name="END_LINK2" /> and <ph name="BEGIN_LINK3" />Terms of Service<ph name="END_LINK3" />.</translation>
 <translation id="93393615658292258">Password only</translation>
 <translation id="934503638756687833">Items not listed here will also be removed, if needed. Learn more about &lt;a href="<ph name="URL" />"&gt;unwanted software protection&lt;/a&gt; in the Chrome privacy white paper.</translation>
-<translation id="935490618240037774">Your bookmarks, history, passwords and other settings will be synced to yourGoogle Accountso that you can use them on all of your devices.</translation>
+<translation id="935490618240037774">Your bookmarks, history, passwords and other settings will be synced to your Google Account so that you can use them on all of your devices.</translation>
 <translation id="935854577147268200">Smart Lock phone changed. Enter your password to update Smart Lock. Next time, your phone will unlock your <ph name="DEVICE_TYPE" />. You can turn off Smart Lock in Settings</translation>
 <translation id="936801553271523408">System diagnostic data</translation>
 <translation id="93766956588638423">Repair extension</translation>
diff --git a/chrome/app/resources/generated_resources_es-419.xtb b/chrome/app/resources/generated_resources_es-419.xtb
index 8ad90a4..4082758d 100644
--- a/chrome/app/resources/generated_resources_es-419.xtb
+++ b/chrome/app/resources/generated_resources_es-419.xtb
@@ -1531,7 +1531,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" solicita tu <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Seguridad</translation>
 <translation id="3435896845095436175">Habilitar</translation>
-<translation id="3436038974659740746">Ortografía personalizada</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Permitir siempre que <ph name="HOST" /> acceda al micrófono</translation>
 <translation id="3439970425423980614">Abriendo PDF en vista previa</translation>
@@ -1861,7 +1860,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> no está actualizado</translation>
 <translation id="3908501907586732282">Habilitar extensión</translation>
 <translation id="3909477809443608991"><ph name="URL" /> quiere reproducir contenido protegido. Google verificará la identidad de tu dispositivo, y es posible que este sitio acceda a ella.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> y 1 más</translation>
 <translation id="3909791450649380159">Cor&amp;tar</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nombre utilizado en este dispositivo)</translation>
 <translation id="3911824782900911339">Página Nueva pestaña</translation>
@@ -2126,7 +2124,6 @@
 <translation id="435527878592612277">Seleccionar tu foto</translation>
 <translation id="4356334633973342967">O especifica tu propio controlador:</translation>
 <translation id="4358169392473932247">Esa llave de seguridad no permite almacenar las credenciales de forma interna, como fue solicitado.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Instalada a causa de las extensiones dependientes</translation>
 <translation id="4359717112757026264">Paisaje urbano</translation>
 <translation id="4361142739114356624">Falta la clave privada para este Certificado de cliente o no es válida</translation>
@@ -2178,7 +2175,6 @@
 <translation id="443475966875174318">Actualizar o quitar las aplicaciones incompatibles</translation>
 <translation id="4441124369922430666">¿Quieres que esta aplicación se inicie de forma automática cuando se encienda el equipo?</translation>
 <translation id="444134486829715816">Mostrar...</translation>
-<translation id="4441548209689510310">Mostrar opciones de corrector ortográfico</translation>
 <translation id="4442424173763614572">Error al buscar DNS</translation>
 <translation id="4443536555189480885">&amp;Ayuda</translation>
 <translation id="4444304522807523469">Acceder a los escáneres de documentos conectados vía USB o en la red local</translation>
@@ -2974,7 +2970,6 @@
 <translation id="5736796278325406685">Ingresa un nombre de usuario válido</translation>
 <translation id="5739235828260127894">La verificación está pendiente. <ph name="LINK_BEGIN" />Más información<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Muy grande</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> y <ph name="NUM_ADDITIONAL_LANGUAGES" /> más</translation>
 <translation id="574209121243317957">Tono</translation>
 <translation id="5746169159649715125">Guardar como PDF</translation>
 <translation id="5747552184818312860">Caduca</translation>
diff --git a/chrome/app/resources/generated_resources_es.xtb b/chrome/app/resources/generated_resources_es.xtb
index 06a9c63..7d6f008e 100644
--- a/chrome/app/resources/generated_resources_es.xtb
+++ b/chrome/app/resources/generated_resources_es.xtb
@@ -1532,7 +1532,6 @@
 <translation id="3435688026795609344"><ph name="EXTENSION_NAME" /> está solicitando tu <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Seguridad</translation>
 <translation id="3435896845095436175">Habilitar</translation>
-<translation id="3436038974659740746">Ortografía personalizada</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Permitir siempre que <ph name="HOST" /> acceda al micrófono</translation>
 <translation id="3439970425423980614">Abriendo archivo PDF en la vista previa</translation>
@@ -1862,7 +1861,6 @@
 <translation id="3908393983276948098">El complemento <ph name="PLUGIN_NAME" /> no está actualizado</translation>
 <translation id="3908501907586732282">Habilitar extensión</translation>
 <translation id="3909477809443608991"><ph name="URL" /> solicita reproducir contenido protegido. Google verificará la identidad de tu dispositivo y el sitio web podrá consultarla.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> y otro</translation>
 <translation id="3909791450649380159">Cor&amp;tar</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nombre utilizado en este dispositivo)</translation>
 <translation id="3911824782900911339">Página Nueva pestaña</translation>
@@ -2126,7 +2124,6 @@
 <translation id="435527878592612277">Selecciona una foto</translation>
 <translation id="4356334633973342967">O especificar un controlador:</translation>
 <translation id="4358169392473932247">Esta llave de seguridad no admite el almacenamiento interno de credenciales, pero se ha solicitado esa función.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" /> y <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Instalada debido a las extensiones dependientes</translation>
 <translation id="4359717112757026264">Paisaje urbano</translation>
 <translation id="4361142739114356624">Falta la clave privada de este certificado de cliente o no es válida</translation>
@@ -2178,7 +2175,6 @@
 <translation id="443475966875174318">Actualizar o quitar aplicaciones incompatibles</translation>
 <translation id="4441124369922430666">¿Quieres que esta aplicación se inicie de forma automática cuando se active el ordenador?</translation>
 <translation id="444134486829715816">Ampliar...</translation>
-<translation id="4441548209689510310">Mostrar opciones de revisión ortográfica</translation>
 <translation id="4442424173763614572">Error al buscar DNS</translation>
 <translation id="4443536555189480885">&amp;Ayuda</translation>
 <translation id="4444304522807523469">Acceder a escáneres de documentos conectados a través de USB o en la red local</translation>
@@ -2974,7 +2970,6 @@
 <translation id="5736796278325406685">Introduce un nombre de usuario válido</translation>
 <translation id="5739235828260127894">Esperando verificación. <ph name="LINK_BEGIN" />Más información<ph name="LINK_END" />.</translation>
 <translation id="5739458112391494395">Muy grande</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> y otros <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Tono</translation>
 <translation id="5746169159649715125">Guardar como PDF</translation>
 <translation id="5747552184818312860">Caduca</translation>
diff --git a/chrome/app/resources/generated_resources_et.xtb b/chrome/app/resources/generated_resources_et.xtb
index 331b1d2b..1be11ae 100644
--- a/chrome/app/resources/generated_resources_et.xtb
+++ b/chrome/app/resources/generated_resources_et.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">„<ph name="EXTENSION_NAME" />” taotleb koodi <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Turvalisus</translation>
 <translation id="3435896845095436175">Luba</translation>
-<translation id="3436038974659740746">Õigekirja kohandamine</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Luba saidil <ph name="HOST" /> alati mikrofoni juurde pääseda</translation>
 <translation id="3439970425423980614">PDF-i eelvaate avamine</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">Pistikprogramm <ph name="PLUGIN_NAME" /> on aegunud</translation>
 <translation id="3908501907586732282">Luba laiendus</translation>
 <translation id="3909477809443608991"><ph name="URL" /> soovib esitada kaitstud sisu. Google kinnitab teie seadme identiteedi ning sait võib sellele juurde pääseda.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> ja veel 1 keel</translation>
 <translation id="3909791450649380159">Lõ&amp;ika</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nimi on selles seadmes juba kasutusel)</translation>
 <translation id="3911824782900911339">Uus vaheleht</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Valige foto</translation>
 <translation id="4356334633973342967">Või määrake oma draiver:</translation>
 <translation id="4358169392473932247">See turvavõti ei toeta mandaatide salvestamist sisemällu, kuid seda funktsiooni sooviti kasutada.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Installitud sõltuva(te) laiendus(t)e tõttu.</translation>
 <translation id="4359717112757026264">Linna panoraam</translation>
 <translation id="4361142739114356624">Selle kliendi sertifikaadi privaatvõti puudub või on sobimatu</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Ühildumatute rakenduste värskendamine või eemaldamine</translation>
 <translation id="4441124369922430666">Kas soovite selle rakenduse seadme sisselülitamisel automaatselt käivitada?</translation>
 <translation id="444134486829715816">Laienda ...</translation>
-<translation id="4441548209689510310">Kuva õigekirjakontrolli seaded</translation>
 <translation id="4442424173763614572">DNS-i otsing nurjus</translation>
 <translation id="4443536555189480885">&amp;Abi</translation>
 <translation id="4444304522807523469">Juurdepääs dokumendiskänneritele USB või kohaliku võrgu kaudu</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">Sisestage kehtiv kasutajanimi</translation>
 <translation id="5739235828260127894">Kinnitamise ootel. <ph name="LINK_BEGIN" />Lisateave<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Väga suur</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> ja veel <ph name="NUM_ADDITIONAL_LANGUAGES" /> keelt</translation>
 <translation id="574209121243317957">Helikõrgus</translation>
 <translation id="5746169159649715125">Salvesta PDF-ina</translation>
 <translation id="5747552184818312860">Aegub</translation>
diff --git a/chrome/app/resources/generated_resources_fa.xtb b/chrome/app/resources/generated_resources_fa.xtb
index 14b934df..1b67f1d0b3 100644
--- a/chrome/app/resources/generated_resources_fa.xtb
+++ b/chrome/app/resources/generated_resources_fa.xtb
@@ -1530,7 +1530,6 @@
 <translation id="3435688026795609344">«<ph name="EXTENSION_NAME" />» <ph name="CODE_TYPE" /> شما را درخواست می‌کند</translation>
 <translation id="3435738964857648380">امنیت</translation>
 <translation id="3435896845095436175">فعال کردن</translation>
-<translation id="3436038974659740746">املای سفارشی</translation>
 <translation id="3438633801274389918">نینجا</translation>
 <translation id="3439153939049640737">دسترسی <ph name="HOST" /> به میکروفون شما همیشه مجاز باشد</translation>
 <translation id="3439970425423980614">‏در حال باز کردن PDF در پیشنمایش</translation>
@@ -1860,7 +1859,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> قدیمی است</translation>
 <translation id="3908501907586732282">فعال کردن برنامه افزودنی</translation>
 <translation id="3909477809443608991">‏<ph name="URL" /> می‌خواهد محتوای محافظت‌شده پخش کند. هویت دستگاهتان توسط Google به‌تأیید می‌رسد و ممکن است این سایت به آن دسترسی داشته باشد.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />، <ph name="LANGUAGE_2" /> و ۱ زبان دیگر</translation>
 <translation id="3909791450649380159">&amp;برش</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (نام مورد استفاده در این دستگاه)</translation>
 <translation id="3911824782900911339">صفحه «برگه جدید»</translation>
@@ -2125,7 +2123,6 @@
 <translation id="435527878592612277">انتخاب عکس</translation>
 <translation id="4356334633973342967">یا درایور خود را مشخص کنید</translation>
 <translation id="4358169392473932247">این کلید امنیتی فضای ذخیره‌سازی داخلی مربوط به اطلاعات کاربری را پشتیبانی نمی‌کند، اما این ویژگی درخواست شده است.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />، <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">به دلیل برنامه(های) افزودنی وابسته نصب شد.</translation>
 <translation id="4359717112757026264">نمای شهر</translation>
 <translation id="4361142739114356624">کلید خصوصی برای این گواهی کارخواه موجود نیست یا نامعتبر است</translation>
@@ -2177,7 +2174,6 @@
 <translation id="443475966875174318">به‌روزرسانی یا برداشتن برنامه‌های ناسازگار</translation>
 <translation id="4441124369922430666">آیا می‌خواهید با روشن شدن دستگاه، این برنامه به‌طور خودکار شروع شود؟</translation>
 <translation id="444134486829715816">گسترده کردن...</translation>
-<translation id="4441548209689510310">نمایش گزینه‌های غلط‌گیر املا</translation>
 <translation id="4442424173763614572">‏جستجوی DNS انجام نشد</translation>
 <translation id="4443536555189480885">&amp;راهنما</translation>
 <translation id="4444304522807523469">‏دسترسی به اسکنرهای سند متصل شده از طریق USB یا در شبکه محلی</translation>
@@ -2973,7 +2969,6 @@
 <translation id="5736796278325406685">لطفاً نام کاربری معتبری وارد کنید.</translation>
 <translation id="5739235828260127894">در انتظار تأیید. <ph name="LINK_BEGIN" />بیشتر بدانید.<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">خیلی بزرگ</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />، <ph name="LANGUAGE_2" /> و <ph name="NUM_ADDITIONAL_LANGUAGES" /> زبان دیگر</translation>
 <translation id="574209121243317957">زیروبمی صدا</translation>
 <translation id="5746169159649715125">‏ذخیره به‌عنوان PDF</translation>
 <translation id="5747552184818312860">تاریخ انقضا</translation>
diff --git a/chrome/app/resources/generated_resources_fi.xtb b/chrome/app/resources/generated_resources_fi.xtb
index 7bf7813a..98ee570 100644
--- a/chrome/app/resources/generated_resources_fi.xtb
+++ b/chrome/app/resources/generated_resources_fi.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344"><ph name="EXTENSION_NAME" /> pyytää kohdetta <ph name="CODE_TYPE" />.</translation>
 <translation id="3435738964857648380">Turvallisuus</translation>
 <translation id="3435896845095436175">Ota käyttöön</translation>
-<translation id="3436038974659740746">Muokkaa tarkistuksen sanaluetteloa</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Anna sivuston <ph name="HOST" /> aina käyttää mikrofoniasi</translation>
 <translation id="3439970425423980614">PDF:n avaaminen esikatselussa</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> on vanhentunut.</translation>
 <translation id="3908501907586732282">Ota laajennus käyttöön</translation>
 <translation id="3909477809443608991"><ph name="URL" /> haluaa toistaa suojattua sisältöä. Google vahvistaa laitteesi identiteetin, ja myös sivusto voi saada pääsyn laitteesi identiteettitietoihin.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> ja 1 muu</translation>
 <translation id="3909791450649380159">L&amp;eikkaa</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nimi on jo käytössä tällä laitteella)</translation>
 <translation id="3911824782900911339">Uusi välilehti -sivu</translation>
@@ -2126,7 +2124,6 @@
 <translation id="435527878592612277">Valitse valokuva</translation>
 <translation id="4356334633973342967">Tai määritä oma ajuri:</translation>
 <translation id="4358169392473932247">Kyseinen suojausavain ei tue kirjautumistietojen sisäistä tallennustilaa, mutta ominaisuutta on pyydetty.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Asennettiin, koska muut laajennukset ovat riippuvaisia tästä laajennuksesta.</translation>
 <translation id="4359717112757026264">Kaupunkimaisema</translation>
 <translation id="4361142739114356624">Tämän käyttöoikeusvarmenteen yksityinen avain puuttuu tai on virheellinen.</translation>
@@ -2178,7 +2175,6 @@
 <translation id="443475966875174318">Päivitä yhteensopimattomat sovellukset tai poista ne</translation>
 <translation id="4441124369922430666">Haluatko käynnistää tämän sovelluksen automaattisesti koneen käynnistyessä?</translation>
 <translation id="444134486829715816">Laajenna...</translation>
-<translation id="4441548209689510310">Näytä oikeinkirjoituksen tarkistusasetukset</translation>
 <translation id="4442424173763614572">DNS-haku epäonnistui</translation>
 <translation id="4443536555189480885">O&amp;hje</translation>
 <translation id="4444304522807523469">Käyttää USB:n tai lähiverkon kautta yhdistettyjä dokumenttiskannereita</translation>
@@ -2974,7 +2970,6 @@
 <translation id="5736796278325406685">Anna kelvollinen käyttäjänimi</translation>
 <translation id="5739235828260127894">Odotetaan vahvistusta. <ph name="LINK_BEGIN" />Lisätietoja<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Hyvin suuri</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> ja <ph name="NUM_ADDITIONAL_LANGUAGES" /> muuta</translation>
 <translation id="574209121243317957">Äänenkorkeus</translation>
 <translation id="5746169159649715125">Tallenna PDF-muodossa</translation>
 <translation id="5747552184818312860">Vanhenee</translation>
diff --git a/chrome/app/resources/generated_resources_fil.xtb b/chrome/app/resources/generated_resources_fil.xtb
index 93c7dcd..d25904e8 100644
--- a/chrome/app/resources/generated_resources_fil.xtb
+++ b/chrome/app/resources/generated_resources_fil.xtb
@@ -116,7 +116,9 @@
 <translation id="1168100932582989117">Mga server ng pangalan ng Google</translation>
 <translation id="1169909785351611170">Mali ang PIN.</translation>
 <translation id="1171135284592304528">I-highlight ang object gamit ang keyboard focus kapag nagbago ito</translation>
+<translation id="1172750555846831341">Baligtarin sa maikling dulo</translation>
 <translation id="1173894706177603556">Pangalanang muli</translation>
+<translation id="1173919438868967364">Pumili ng Account</translation>
 <translation id="1174073918202301297">Naidagdag na ang shortcut</translation>
 <translation id="117445914942805388">Para i-clear ang data sa pag-browse sa lahat ng iyong naka-sync na device at sa Google Account mo, <ph name="BEGIN_LINK" />bisitahin ang mga setting ng pag-sync<ph name="END_LINK" />.</translation>
 <translation id="1175364870820465910">&amp;I-print...</translation>
@@ -301,6 +303,7 @@
 <translation id="1465827627707997754">Hiwa ng pizza</translation>
 <translation id="1468571364034902819">Hindi magagamit ang profile na ito</translation>
 <translation id="1470811252759861213">Upang mailagay ang iyong mga extension sa lahat ng iyong computer, <ph name="SIGN_IN_LINK" />.</translation>
+<translation id="1470967055429794975">Buburahin nito ang lahat ng data sa security key, kabilang ang PIN nito</translation>
 <translation id="1475502736924165259">Mayroon kang mga certificate sa file na hindi umaangkop sa alinman sa iba pang mga kategorya</translation>
 <translation id="1476607407192946488">&amp;Mga Setting ng Wika</translation>
 <translation id="1477301030751268706">Identity API Token Cache</translation>
@@ -554,6 +557,7 @@
 <translation id="1856715684130786728">Magdagdag ng lokasyon...</translation>
 <translation id="1858585891038687145">Pagkatiwalaan ang certificate na ito para sa pagtukoy sa mga gumawa ng software</translation>
 <translation id="1861262398884155592">Walang laman ang folder na ito</translation>
+<translation id="1863182668524159459">Walang nakitang serial port</translation>
 <translation id="1864111464094315414">Mag-login</translation>
 <translation id="1864400682872660285">Cooler</translation>
 <translation id="1864454756846565995">USB-C device (port sa rear)</translation>
@@ -583,6 +587,7 @@
 <translation id="1904394285866191268">{NUM_TABS,plural, =1{I-mute ang tab}one{I-mute ang mga tab}other{I-mute ang mga tab}}</translation>
 <translation id="1905375423839394163">Pangalan ng Chromebook device</translation>
 <translation id="1905710495812624430">Nalampasan na ang maximum na pinapahintulutang bilang ng pagsubok</translation>
+<translation id="1906828677882361942">Huwag payagan ang anumang site na i-access ang mga serial port</translation>
 <translation id="1909880997794698664">Sigurado ka bang gusto mong permanenteng panatilihin sa kiosk mode ang device na ito?</translation>
 <translation id="1910721550319506122">Maligayang pagdating!</translation>
 <translation id="1914326953223720820">I-unzip ang Serbisyo</translation>
@@ -625,6 +630,7 @@
 <translation id="1976323404609382849">Na-block ang cookies mula sa maraming site.</translation>
 <translation id="1977965994116744507">Ilapit pa ang iyong telepono upang ma-unlock ang <ph name="DEVICE_TYPE" /> mo.</translation>
 <translation id="1979280758666859181">Lumilipat ka sa isang channel na may lumang bersyon ng <ph name="PRODUCT_NAME" />. Ilalapat ang paglilipat ng channel kapag tumugma ang bersyon ng channel sa bersyong kasalukuyang naka-install sa iyong device.</translation>
+<translation id="1981544341227357861">Alisin ang iyong security key mula sa device mo, pagkatapos ay muling ipasok at pindutin ito.</translation>
 <translation id="1982354452682152483">Walang available na paglalarawan.</translation>
 <translation id="1983959805486816857">Pagkatapos mong gumawa ng bagong pinangangasiwaang user, maaari mong pamahalaan ang mga setting anumang oras mula sa anumang device, sa <ph name="MANAGEMENT_URL" />.</translation>
 <translation id="1987317783729300807">Mga Account</translation>
@@ -836,6 +842,7 @@
 <translation id="2318817390901984578">Upang gamitin ang mga Android app, i-charge at i-update ang iyong <ph name="DEVICE_TYPE" />.</translation>
 <translation id="2318923050469484167">Kasalukuyang incognito na session (<ph name="EMBEDDING" />)</translation>
 <translation id="2322193970951063277">Mga header at footer</translation>
+<translation id="2322318151094136999">Magtanong kapag gustong i-access ng isang site ang mga serial port (inirerekomenda)</translation>
 <translation id="2326931316514688470">I-&amp;reload ang app</translation>
 <translation id="2327492829706409234">Paganahin ang app</translation>
 <translation id="2329597144923131178">Mag-sign in upang makuha ang iyong mga bookmark, history, password at ibang mga setting sa lahat ng iyong device.</translation>
@@ -903,7 +910,9 @@
 <translation id="2435457462613246316">Ipakita ang password</translation>
 <translation id="2436186046335138073">Papayagan ang <ph name="HANDLER_HOSTNAME" /> na buksan ang lahat ng link ng <ph name="PROTOCOL" />?</translation>
 <translation id="2436707352762155834">Minimum</translation>
+<translation id="2439545803278355377">Ilagay ang bago mong PIN. Dapat ay may hindi bababa sa apat na character ang isang PIN at maaaring maglaman ng mga titik, numero, at iba pang character.</translation>
 <translation id="2440604414813129000">Tingnan s&amp;ource</translation>
+<translation id="2442182690962765671">Hindi tumutugon ang page. Magagawa mong maghintay o alisin ang headset.</translation>
 <translation id="2445081178310039857">Kinakailangan ang pinagmulang direktoryo ng extension.</translation>
 <translation id="2445484935443597917">Gumawa ng Bagong Profile</translation>
 <translation id="2446585455334014596">Gustong i-verify ng <ph name="APP_NAME" /> ang iyong pagkakakilanlan</translation>
@@ -1034,6 +1043,7 @@
 <translation id="2633199387167390344">Gumagamit ang <ph name="NAME" /> ng <ph name="USAGE" /> MB ng disk space.</translation>
 <translation id="2633212996805280240">Alisin ang "<ph name="EXTENSION_NAME" />"?</translation>
 <translation id="263325223718984101">Hindi makumpleto ng <ph name="PRODUCT_NAME" /> ang pag-install, ngunit patuloy na gagana mula sa larawan ng disk nito.</translation>
+<translation id="2633764681656412085">FIDO</translation>
 <translation id="2635094637295383009">Twitter</translation>
 <translation id="2635276683026132559">Paglagda</translation>
 <translation id="2636625531157955190">Hindi ma-access ng Chrome ang larawan.</translation>
@@ -1261,6 +1271,7 @@
 <translation id="2993517869960930405">Impormasyon ng App</translation>
 <translation id="299483336428448530">Na-install ng iyong magulang.</translation>
 <translation id="2996286169319737844">Ine-encrypt ang data gamit ang iyong passphrase sa pag-sync. Hindi kasama rito ang mga paraan ng pagbabayad at address mula sa Google Pay.</translation>
+<translation id="2996722619877761919">Baligtarin sa mahabang dulo</translation>
 <translation id="3003144360685731741">Mga gustong network</translation>
 <translation id="3003623123441819449">Cache ng CSS</translation>
 <translation id="3003828226041301643">Hindi maisama ang device sa domain. Suriin ang iyong account para matiyak na mayroon kang mga pribilehiyong magdagdag ng mga device.</translation>
@@ -1329,6 +1340,7 @@
 <translation id="3101709781009526431">Petsa at oras</translation>
 <translation id="310671807099593501">Gumagamit ng bluetooth ang site</translation>
 <translation id="3115147772012638511">Naghihintay para sa cache...</translation>
+<translation id="3115580024857770654">I-collapse lahat</translation>
 <translation id="3118319026408854581"><ph name="PRODUCT_NAME" /> Help</translation>
 <translation id="3120430004221004537">Hindi sapat ang pag-encrypt para sa isang partikular na operation sa: "<ph name="DEVICE_NAME" />".</translation>
 <translation id="3121793941267913344">I-reset ang <ph name="IDS_SHORT_PRODUCT_NAME" /> device na ito</translation>
@@ -1522,7 +1534,6 @@
 <translation id="3435688026795609344">Hinihiling ng "<ph name="EXTENSION_NAME" />" ang iyong <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Seguridad</translation>
 <translation id="3435896845095436175">I-enable</translation>
-<translation id="3436038974659740746">Custom na pagbabaybay</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Palaging pahintulutan ang <ph name="HOST" /> na i-access ang iyong mikropono</translation>
 <translation id="3439970425423980614">Binubuksan ang PDF sa Preview</translation>
@@ -1555,6 +1566,7 @@
 <translation id="347785443197175480">Magpatuloy sa pagpayag sa <ph name="HOST" /> na i-access ang iyong camera at mikropono</translation>
 <translation id="3478685642445675458">Paki-unlock ang iyong profile bago mag-alis ng tao.</translation>
 <translation id="3479552764303398839">Hindi ngayon</translation>
+<translation id="3481268647794498892">Binubuksan sa <ph name="ALTERNATIVE_BROWSER_NAME" /> sa loob ng <ph name="COUNTDOWN_SECONDS" /> segundo</translation>
 <translation id="3484273680291419129">Inaalis ang mapaminsalang software...</translation>
 <translation id="3484869148456018791">Kumuha ng bagong certificate</translation>
 <translation id="3487007233252413104">hindi kilalang function</translation>
@@ -1673,6 +1685,7 @@
 <translation id="3654045516529121250">Basahin ang iyong mga setting ng pagiging naa-access</translation>
 <translation id="3655712721956801464">{NUM_FILES,plural, =1{May permanenteng access ito sa isang file.}one{May permanenteng access ito sa # file.}other{May permanenteng access ito sa # na file.}}</translation>
 <translation id="3660234220361471169">Hindi pinagkakatiwalaan</translation>
+<translation id="3661172646479098821">Ang mga Android device lang ang kasalukuyang sinusuportahan.</translation>
 <translation id="3664511988987167893">Icon ng Extension</translation>
 <translation id="3665589677786828986">Natunton ng Chrome na ilan sa iyong mga setting ay nasira ng isa pang program at ni-reset ang mga ito sa kanilang mga orihinal na default.</translation>
 <translation id="3668570675727296296">Mga setting ng wika</translation>
@@ -1753,6 +1766,7 @@
 <translation id="3768037234834996183">Nagsi-sync ng iyong mga kagustuhan...</translation>
 <translation id="3771294271822695279">Mga Video File</translation>
 <translation id="3775432569830822555">SSL Server Certificate</translation>
+<translation id="3775705724665058594">Ipadala sa iyong mga device</translation>
 <translation id="3776796446459804932">Lumalabag ang extension na ito sa patakaran ng Chrome Web Store.</translation>
 <translation id="3777806571986431400">Pinagana na ang Extension</translation>
 <translation id="3778152852029592020">Kinansela ang pag-download.</translation>
@@ -1836,7 +1850,7 @@
 <translation id="3892414795099177503">Idagdag ang OpenVPN / L2TP...</translation>
 <translation id="3893536212201235195">Basahin at baguhin ang iyong mga setting ng accessibility</translation>
 <translation id="3893630138897523026">ChromeVox (pasalitang feedback)</translation>
-<translation id="3894123633473837029">Isama ang kamakailang history ng Assistant sa pamamagitan ng Sherlog. Maaaring kasama rito ang iyong pagkakakilanlan, lokasyon, at impormasyon sa pag-debug. <ph name="BEGIN_LINK" />Matuto pa<ph name="END_LINK" /></translation>
+<translation id="3894123633473837029">Isama ang kamakailang history ng Assistant sa pamamagitan ng Sherlog. Puwedeng kasama rito ang iyong pagkakakilanlan, lokasyon, at impormasyon sa pag-debug. <ph name="BEGIN_LINK" />Matuto pa<ph name="END_LINK" /></translation>
 <translation id="3894427358181296146">Magdagdag ng folder</translation>
 <translation id="389589731200570180">Ibahagi sa mga bisita</translation>
 <translation id="3898521660513055167">Status ng Token</translation>
@@ -1849,7 +1863,6 @@
 <translation id="3908393983276948098">Hindi napapanahon ang <ph name="PLUGIN_NAME" /></translation>
 <translation id="3908501907586732282">Paganahin ang extension</translation>
 <translation id="3909477809443608991">Gusto ng <ph name="URL" /> na mag-play ng pinoprotektahang content. Ive-verify ng Google ang pagkakakilanlan ng iyong device, at maaari itong i-access ng site na ito.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> at 1 pa</translation>
 <translation id="3909791450649380159">Al&amp;isin</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (pangalang ginamit sa device na ito)</translation>
 <translation id="3911824782900911339">Page na Bagong Tab</translation>
@@ -1963,6 +1976,7 @@
 <translation id="4081242589061676262">Hindi ma-cast ang file.</translation>
 <translation id="4084682180776658562">Bookmark</translation>
 <translation id="4084835346725913160">Isara ang <ph name="TAB_NAME" /></translation>
+<translation id="4085270836953633510">Tanungin kung kailan gusto ng site na i-access ang mga serial port</translation>
 <translation id="4085298594534903246">Ang JavaScript ay hinarang sa pahinang ito.</translation>
 <translation id="4087089424473531098">Nilikha ang extension na:
 
@@ -2065,6 +2079,7 @@
 <translation id="4258348331913189841">Mga system ng file</translation>
 <translation id="4263757076580287579">Nakansela ang pagpaparehistro ng printer.</translation>
 <translation id="426564820080660648">Upang tumingin ng mga update, pakigamit ang Ethernet, Wi-Fi o mobile data.</translation>
+<translation id="4267953847983678297">Awtomatikong kumonekta sa cellular network</translation>
 <translation id="4268025649754414643">Pag-encipher ng Key</translation>
 <translation id="4270393598798225102">Bersyon <ph name="NUMBER" /></translation>
 <translation id="4271396100647220620">Walang mga pagtutugma</translation>
@@ -2111,7 +2126,7 @@
 <translation id="4354344420232759511">Lalabas dito ang mga site na binibisita mo</translation>
 <translation id="435527878592612277">Piliin ang iyong larawan</translation>
 <translation id="4356334633973342967">O tukuyin ang sarili mong driver:</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
+<translation id="4358169392473932247">Hindi sinusuportahan ng naturang security key ang internal storage ng mga kredensyal pero hiniling ang naturang feature.</translation>
 <translation id="4359408040881008151">Na-install dahil sa (mga) nakadependeng extension.</translation>
 <translation id="4359717112757026264">Cityscape</translation>
 <translation id="4361142739114356624">Nawawala o di-wasto ang Pribadong Key para sa Client Certificate na ito</translation>
@@ -2163,7 +2178,6 @@
 <translation id="443475966875174318">I-update o alisin ang mga hindi compatible na application</translation>
 <translation id="4441124369922430666">Nais mo bang awtomatikong simulan ang app na ito kapag nag-on ang makina?</translation>
 <translation id="444134486829715816">Palawakin...</translation>
-<translation id="4441548209689510310">Ipakita ang mga opsyon sa pang-check ng pagbabaybay</translation>
 <translation id="4442424173763614572">Nabigo ang paghahanap sa DNS</translation>
 <translation id="4443536555189480885">&amp;Tulong</translation>
 <translation id="4444304522807523469">I-access ang mga scanner ng dokumento na naka-attach sa pamamagitan ng USB o sa lokal na network</translation>
@@ -2290,6 +2304,7 @@
 <translation id="4665014895760275686">Manufacturer</translation>
 <translation id="4665446389743427678">Ide-delete ang lahat ng data na naka-store sa <ph name="SITE" />.</translation>
 <translation id="4668721319092543482">I-click upang i-enable ang <ph name="PLUGIN_NAME" /></translation>
+<translation id="4670688170798478686">Kumpirmahin ang pag-reset</translation>
 <translation id="4672657274720418656">Distill Page</translation>
 <translation id="4673442866648850031">Buksan ang mga stylus tool kapag inalis ang stylus</translation>
 <translation id="4677585247300749148">Gustong tumugon ng <ph name="URL" /> sa mga kaganapan ng pagiging accessible</translation>
@@ -2519,6 +2534,7 @@
 <translation id="5037676449506322593">Select All</translation>
 <translation id="5038863510258510803">Pinapagana...</translation>
 <translation id="5039804452771397117">Payagan</translation>
+<translation id="5042282098504489593">Buksan ang Mga Setting para ikonekta ang <ph name="USB_DEVICE_NAME" /> sa Linux</translation>
 <translation id="5045550434625856497">Hindi wastong password</translation>
 <translation id="504561833207953641">Binubuksan sa kasalukuyang session ng browser.</translation>
 <translation id="5047421709274785093">I-block ang paggamit ng mga site ng mga motion at light sensor</translation>
@@ -2685,6 +2701,7 @@
 <translation id="5319359161174645648">Inirerekomenda ng Google ang Chrome</translation>
 <translation id="5319566035256672173">Hindi na matatanggap ng device na ito ang mga pinakabagong update sa software. Pag-isipang mag-upgrade.</translation>
 <translation id="532247166573571973">Maaaring hindi makakonekta sa server. Subukang muli sa ibang pagkakataon.</translation>
+<translation id="5324245805087635250">Ilagay ang iyong &lt;i&gt;kasalukuyang&lt;/i&gt; PIN para palitan ito. Kung hindi mo alam ang kasalukuyang PIN, kailangang i-reset ang security key para i-clear ito.</translation>
 <translation id="5324780743567488672">Awtomatikong itakda ang time zone gamit ang iyong lokasyon</translation>
 <translation id="5327248766486351172">Pangalan</translation>
 <translation id="5327570636534774768">Minarkahan ang device na ito para mapamahalaan ng ibang domain. I-deprovision ito mula sa domain na iyon bago i-set up ang demo mode.</translation>
@@ -2901,6 +2918,7 @@
 <translation id="5637476008227280525">Pag-enable sa mobile data</translation>
 <translation id="5638309510554459422">Maghanap ng mga extension at tema sa <ph name="BEGIN_LINK" />Chrome Web Store<ph name="END_LINK" /></translation>
 <translation id="5639549361331209298">I-reload ang pahinang ito, pindutin nang matagal upang makakita ng higit pang mga pagpipilian</translation>
+<translation id="5640133431808313291">Pamahalaan ang mga security key</translation>
 <translation id="5642508497713047">Tagapaglagda ng CRL</translation>
 <translation id="5643620609347735571">I-clear at magpatuloy</translation>
 <translation id="5646376287012673985">Lokasyon</translation>
@@ -2955,7 +2973,6 @@
 <translation id="5736796278325406685">Mangyaring maglagay ng wastong username</translation>
 <translation id="5739235828260127894">Naghihintay ng pag-verify. <ph name="LINK_BEGIN" />Matuto pa<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Napakalaki</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> at <ph name="NUM_ADDITIONAL_LANGUAGES" /> pa</translation>
 <translation id="574209121243317957">Pitch</translation>
 <translation id="5746169159649715125">I-save bilang PDF</translation>
 <translation id="5747552184818312860">Mag-e-expire sa</translation>
@@ -3000,6 +3017,7 @@
 <translation id="5804241973901381774">Mga Pahintulot</translation>
 <translation id="5805697420284793859">Window manager</translation>
 <translation id="5811750797187914944">Handa na ang lahat</translation>
+<translation id="5812674658566766066">I-expand lahat</translation>
 <translation id="5814126672212206791">Uri ng koneksyon</translation>
 <translation id="5815645614496570556">Address na X.400</translation>
 <translation id="5816434091619127343">Magiging hindi magagamit ang printer dahil sa mga hiniling na pagbabago sa printer.</translation>
@@ -3112,6 +3130,7 @@
 <translation id="5972666587303800813">No-op na Serbisyo</translation>
 <translation id="5972708806901999743">Ilipat sa itaas</translation>
 <translation id="5972826969634861500">Simulan ang <ph name="PRODUCT_NAME" /></translation>
+<translation id="5973605538625120605">Magpalit ng PIN</translation>
 <translation id="5975792506968920132">Porsyento ng Charge ng Baterya</translation>
 <translation id="5976160379964388480">Iba Pa</translation>
 <translation id="5979421442488174909">&amp;Isalin sa <ph name="LANGUAGE" /></translation>
@@ -3234,6 +3253,7 @@
 <translation id="6156323911414505561">Ipakita ang bookmarks bar</translation>
 <translation id="6156863943908443225">Script cache</translation>
 <translation id="6156960295318603523">Mga Setting ng Wika</translation>
+<translation id="6159328879826063795">Hindi sinusuportahan ng security key ang hiniling na feature.</translation>
 <translation id="6160625263637492097">Magbigay ng mga certificate para sa pagpapatotoo</translation>
 <translation id="6163363155248589649">&amp;Normal</translation>
 <translation id="6163522313638838258">Palawakin lahat...</translation>
@@ -3284,6 +3304,7 @@
 <translation id="6238923052227198598">Panatilihin ang pinakabagong tala sa lock screen</translation>
 <translation id="6239558157302047471">I-reload ang &amp;frame</translation>
 <translation id="6241530762627360640">Mag-access ng impormasyon tungkol sa mga Bluetooth device na nakapares sa iyong system at tumuklas ng mga kalapit na Bluetooth device.</translation>
+<translation id="6242589501614145408">I-reset ang iyong security key</translation>
 <translation id="6242852299490624841">I-focus ang tab na ito</translation>
 <translation id="6243280677745499710">Kasalukuyang nakatakda</translation>
 <translation id="6243774244933267674">Hindi available ang server</translation>
@@ -3701,6 +3722,7 @@
 <translation id="6916590542764765824">Pamahalaan ang Mga Extension</translation>
 <translation id="6920989436227028121">Buksan bilang regular na tab</translation>
 <translation id="6921104647315081813">I-clear ang mga aktibidad</translation>
+<translation id="692114467174262153">Hindi mabuksan ang <ph name="ALTERNATIVE_BROWSER_NAME" /></translation>
 <translation id="6921709132208495314">Ihinto ang paggamit ng data sa page na ito</translation>
 <translation id="6922128026973287222">Mag-save ng data at mag-browse nang mas mabilis gamit ang Data Saver ng Google. I-click upang matuto pa.</translation>
 <translation id="6923132443355966645">Mag-scroll / Mag-click</translation>
@@ -3789,6 +3811,7 @@
 <translation id="7063129466199351735">Kasalukuyang pinoproseso ang mga shortcut...</translation>
 <translation id="7063311912041006059">URL na may <ph name="SPECIAL_SYMBOL" /> sa halip na query</translation>
 <translation id="7063957500469387217">I-set up o pamahalaan ang mga printer sa Google Cloud Print.</translation>
+<translation id="7064482796689484940">Hindi sinusuportahan ng naturang security key ang anumang paraan ng pagtukoy ng personal na pagkakakilanlan (hal. isang fingerprint reader, o paglagay ng PIN) pero hiniling ang naturang feature.</translation>
 <translation id="7065223852455347715">Naka-lock ang device sa mode na pumipigil sa pag-enroll ng enterprise. Kung gusto mong i-enroll ang device kailangan mo munang gawin ang pag-recover sa device.</translation>
 <translation id="7065534935986314333">Tungkol sa System</translation>
 <translation id="706626672220389329">Nagka-error sa pag-mount ng share. Naka-mount na ang isinaad na share.</translation>
@@ -3849,6 +3872,7 @@
 <translation id="713888829801648570">Paumanhin, hindi ma-verify ang iyong password dahil offline ka.</translation>
 <translation id="7140928199327930795">Walang ibang available na mga device.</translation>
 <translation id="7141105143012495934">Hindi nakapag-sign dahil hindi maibalik ang mga detalye ng iyong account. Mangyaring makipag-ugnayan sa iyong administrator o subukang muli.</translation>
+<translation id="714285394257538643">Para kumpirmahing gusto mong i-reset ang iyong security key, pindutin itong muli. Buburahin ang lahat ng kredensyal na nakaimbak sa security key at PIN nito.</translation>
 <translation id="7143092389027215216">Sinisimulan ang demo mode</translation>
 <translation id="7143207342074048698">Kumokonekta</translation>
 <translation id="7144878232160441200">Subukang muli</translation>
@@ -3987,6 +4011,7 @@
 <translation id="7364796246159120393">Pumili ng File</translation>
 <translation id="7366415735885268578">Magdagdag ng site</translation>
 <translation id="7366909168761621528">Data sa pag-browse</translation>
+<translation id="736877393389250337">Hindi mabuksan ang <ph name="URL" /> sa <ph name="ALTERNATIVE_BROWSER_NAME" />. Mangyaring makipag-ugnayan sa iyong system administrator.</translation>
 <translation id="7371006317849674875">Oras ng pagsisimula</translation>
 <translation id="7375053625150546623">EAP</translation>
 <translation id="7376553024552204454">I-highlight ang cursor ng mouse kapag gumagalaw ito</translation>
@@ -3995,6 +4020,7 @@
 <translation id="7378627244592794276">Hindi</translation>
 <translation id="73786666777299047">Buksan ang Chrome Web Store</translation>
 <translation id="7378812711085314936">Kumuha ng koneksyon ng data</translation>
+<translation id="7380768571499464492">Na-update ang <ph name="PRINTER_NAME" /></translation>
 <translation id="7384292194278095697">Hindi na sinusuportahan ang device na ito</translation>
 <translation id="7385854874724088939">May nangyaring mali noong sinusubukang mag-print.  Pakisuri ang iyong printer at subukang muli.</translation>
 <translation id="7385896526023870365">Walang karagdagang access sa site ang extension na ito.</translation>
@@ -4026,11 +4052,13 @@
 <translation id="7433692219247014412">{COUNT,plural, =0{Buksan Lahat sa &amp;Bagong Window}=1{Buksan sa &amp;Bagong Window}one{Buksan Lahat (#) sa &amp;Bagong Window}other{Buksan Lahat (#) sa &amp;Bagong Window}}</translation>
 <translation id="7434509671034404296">Bumubuo</translation>
 <translation id="7436921188514130341">Naku! Nagka-error habang pinapalitan ang pangalan.</translation>
+<translation id="7438976808740265764">Hindi na susuportahan ang Flash Player pagkatapos ng Disyembre 2020.</translation>
 <translation id="7441736921018636843">Para baguhin ang setting na ito, <ph name="BEGIN_LINK" />i-reset ang pag-sync<ph name="END_LINK" /> para alisin ang iyong passphrase sa pag-sync</translation>
 <translation id="7441830548568730290">Iba pang mga user</translation>
 <translation id="7442465037756169001">Handa nang ma-set up ang iyong Hangouts Meet hardware.</translation>
 <translation id="744341768939279100">Gumawa ng bagong profile</translation>
 <translation id="7444983668544353857">Huwag paganahin <ph name="NETWORKDEVICE" /></translation>
+<translation id="7450761244949417357">Binubuksan ngayon sa <ph name="ALTERNATIVE_BROWSER_NAME" /></translation>
 <translation id="7453008956351770337">Sa pamamagitan ng pagpili sa printer na ito, binibigyan mo ng pahintulot ang sumusunod na extension upang i-access ang iyong printer:</translation>
 <translation id="7456142309650173560">dev</translation>
 <translation id="7456847797759667638">Buksan ang Lokasyon...</translation>
@@ -4135,7 +4163,9 @@
 <translation id="7631014249255418691">Matagumpay na na-back up ang mga app at file ng Linux</translation>
 <translation id="7631887513477658702">&amp;Palaging Magbukas ng Mga File na Ganitong Uri</translation>
 <translation id="7632948528260659758">Hindi na-update ang mga sumusunod na kiosk app:</translation>
+<translation id="76341863042884733">Pinoprotektahan ng PIN ang iyong security key</translation>
 <translation id="763632859238619983">Huwag payagan ang anumang site na mag-install ng mga tagapangasiwa ng pagbabayad</translation>
+<translation id="7638605456503525968">Mga serial port</translation>
 <translation id="7639178625568735185">Nakuha ko!</translation>
 <translation id="764017888128728">Awtomatiko kang sina-sign in ng <ph name="PASSWORD_MANAGER_BRAND" /> sa mga kwalipikadong site gamit ang mga password na na-save mo.</translation>
 <translation id="7642778300616172920">Itago ang sensitibong content</translation>
@@ -4147,6 +4177,7 @@
 <translation id="7650511557061837441">Gustong alisin ng "<ph name="TRIGGERING_EXTENSION_NAME" />" ang "<ph name="EXTENSION_NAME" />".</translation>
 <translation id="7652808307838961528">I-edit ang tao, <ph name="PROFILE_NAME" /></translation>
 <translation id="765293928828334535">Hindi maidadagdag mula sa website na ito ang mga app, extension, at script ng user</translation>
+<translation id="7652954539215530680">Gumawa ng PIN</translation>
 <translation id="7654941827281939388">Ginagamit na ang account na ito sa computer na ito.</translation>
 <translation id="7658239707568436148">Kanselahin</translation>
 <translation id="7659584679870740384">Wala kang pahintulot na gamitin ang device na ito. Mangyaring makipag-ugnayan sa administrator upang makakuha ng pahintulot sa pag-sign in.</translation>
@@ -4458,6 +4489,7 @@
     <ph name="BEGIN_PARAGRAPH3" />Ang data ng app ay maaaring anumang data na na-save ng app (batay sa mga setting ng developer), kabilang ang data gaya ng mga contact, mensahe, at larawan.<ph name="END_PARAGRAPH3" />
     <ph name="BEGIN_PARAGRAPH4" />Hindi mabibilang sa quota sa storage ng iyong Drive ang data ng backup.<ph name="END_PARAGRAPH4" />
     <ph name="BEGIN_PARAGRAPH5" />Maaari mong i-off ang serbisyong ito sa Mga Setting.<ph name="END_PARAGRAPH5" /></translation>
+<translation id="8096438328987289870">Pumili ng account na gagamitin sa pag-log in:</translation>
 <translation id="80974698889265265">Hindi nagtutugma ang mga PIN</translation>
 <translation id="8101987792947961127">Kinakailangan ng Powerwash sa susunod na reboot</translation>
 <translation id="8102159139658438129">Pumunta sa <ph name="LINK_BEGIN" />Mga Setting<ph name="LINK_END" /> para makakita ng mga opsyon para sa iyong nakakonektang telepono</translation>
@@ -4546,6 +4578,7 @@
 <translation id="8246209727385807362">Hindi kilalang carrier</translation>
 <translation id="8248050856337841185">I-&amp;paste</translation>
 <translation id="8249048954461686687">Folder ng OEM</translation>
+<translation id="8249615410597138718">Ipadala sa Iyong Mga Device</translation>
 <translation id="8249672078237421304">Mag-alok na isalin ang mga page na wala sa wikang nababasa mo</translation>
 <translation id="8251578425305135684">Naalis ang thumbnail.</translation>
 <translation id="8252569384384439529">Ina-upload...</translation>
@@ -4697,6 +4730,7 @@
 <translation id="8502536196501630039">Para magamit ang mga app mula sa Google Play, dapat mo munang i-restore ang iyong mga app. Maaaring mawala ang ilang data.</translation>
 <translation id="8503813439785031346">Username</translation>
 <translation id="850875081535031620">Walang nahanap na mapaminsalang software</translation>
+<translation id="8509177919508253835">I-reset ang mga security key at gumawa ng mga PIN</translation>
 <translation id="8509646642152301857">Nabigo ang pag-download ng diksyunaryo ng pang-check ng pagbabaybay.</translation>
 <translation id="8512476990829870887">Tapusin ang Proseso</translation>
 <translation id="851263357009351303">Palaging hayaan ang <ph name="HOST" /> na magpakita ng mga larawan</translation>
@@ -4920,6 +4954,7 @@
 <translation id="8838770651474809439">Hamburger</translation>
 <translation id="883911313571074303">I-annotate ang larawan</translation>
 <translation id="8845001906332463065">Humingi ng tulong</translation>
+<translation id="8845164297565101021">Ipasok at pindutin ang iyong security key para gumawa o magpalit ng PIN.</translation>
 <translation id="8846132060409673887">I-read ang manufacturer at modelo ng computer na ito</translation>
 <translation id="8846141544112579928">Naghahanap ng keyboard...</translation>
 <translation id="8847988622838149491">USB</translation>
@@ -5052,6 +5087,7 @@
 <translation id="9052208328806230490">Inirehistro mo ang iyong mga printer sa <ph name="CLOUD_PRINT_NAME" /> gamit ang account na <ph name="EMAIL" /></translation>
 <translation id="9052404922357793350">Patuloy na i-block</translation>
 <translation id="9053091947372579468">May lisensya sa Chrome ang iyong device, ngunit hindi nauugnay ang username mo sa isang Admin console. Gumawa ng Admin console account para magpatuloy sa pag-enroll. Tandaan: Kung pipiliin mong gamitin ang iyong sariling domain para makagawa ng bagong Admin console account, dapat mo ring kumpletuhin ang pag-verify ng domain pagkatapos mag-sign up. https://g.co/ChromeEnterpriseAccount</translation>
+<translation id="9053563360605707198">Mag-print sa magkabilang bahagi</translation>
 <translation id="9053893665344928494">Tandaan ang aking pinili</translation>
 <translation id="9055636786322918818">Ipatupad ang RC4 encryption. Magiging mas mapanganib para sa iyo kapag ginamit ang opsyong ito, dahil hindi secure ang mga RC4 cipher.</translation>
 <translation id="9056810968620647706">Walang nakitang tugma.</translation>
diff --git a/chrome/app/resources/generated_resources_fr.xtb b/chrome/app/resources/generated_resources_fr.xtb
index d841a67..7b4707b 100644
--- a/chrome/app/resources/generated_resources_fr.xtb
+++ b/chrome/app/resources/generated_resources_fr.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" demande votre <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Sécurité</translation>
 <translation id="3435896845095436175">Activer</translation>
-<translation id="3436038974659740746">Dictionnaire personnalisé</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Toujours autoriser <ph name="HOST" /> à accéder à votre micro</translation>
 <translation id="3439970425423980614">Ouverture du PDF dans Aperçu</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> est obsolète.</translation>
 <translation id="3908501907586732282">Activer l'extension</translation>
 <translation id="3909477809443608991"><ph name="URL" /> souhaite lire un contenu protégé. L'identité de votre appareil sera validée par Google et peut être accessible à ce site.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> et 1 autre</translation>
 <translation id="3909791450649380159">Cou&amp;per</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nom utilisé sur cet appareil)</translation>
 <translation id="3911824782900911339">Page Nouvel onglet</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Sélectionner votre photo</translation>
 <translation id="4356334633973342967">Vous pouvez également indiquer votre propre pilote :</translation>
 <translation id="4358169392473932247">Le stockage interne d'identifiants a été demandé, mais la clé de sécurité n'est pas compatible avec cette fonctionnalité.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Installée, car une ou plusieurs extensions dépendent de celle-ci.</translation>
 <translation id="4359717112757026264">Paysage urbain</translation>
 <translation id="4361142739114356624">La clé privée de ce certificat client est manquante ou incorrecte</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Mettre à jour ou supprimer des applications incompatibles</translation>
 <translation id="4441124369922430666">Voulez-vous démarrer automatiquement cette application à la mise sous tension de l'ordinateur ?</translation>
 <translation id="444134486829715816">Développer...</translation>
-<translation id="4441548209689510310">Afficher les options du correcteur orthographique</translation>
 <translation id="4442424173763614572">Échec de la résolution DNS.</translation>
 <translation id="4443536555189480885">&amp;Aide</translation>
 <translation id="4444304522807523469">Accéder aux scanners de documents connectés via USB ou sur le réseau local</translation>
@@ -2978,7 +2974,6 @@
 <translation id="5736796278325406685">Veuillez saisir un nom d'utilisateur valide</translation>
 <translation id="5739235828260127894">En attente de validation. <ph name="LINK_BEGIN" />En savoir plus<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Très grande</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> et <ph name="NUM_ADDITIONAL_LANGUAGES" /> autres</translation>
 <translation id="574209121243317957">Ton</translation>
 <translation id="5746169159649715125">Enregistrer au format PDF</translation>
 <translation id="5747552184818312860">Date d'expiration</translation>
diff --git a/chrome/app/resources/generated_resources_gu.xtb b/chrome/app/resources/generated_resources_gu.xtb
index 80c30ac7..e792faa5 100644
--- a/chrome/app/resources/generated_resources_gu.xtb
+++ b/chrome/app/resources/generated_resources_gu.xtb
@@ -1530,7 +1530,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />", તમારા <ph name="CODE_TYPE" /> ની વિનંતી કરી રહ્યું છે</translation>
 <translation id="3435738964857648380">સુરક્ષા</translation>
 <translation id="3435896845095436175">ચાલુ કરો</translation>
-<translation id="3436038974659740746">કસ્ટમ જોડણી</translation>
 <translation id="3438633801274389918">નીન્જા</translation>
 <translation id="3439153939049640737"><ph name="HOST" /> ને હંમેશા તમારા માઇક્રોફોનને ઍક્સેસ કરવાની મંજૂરી આપો</translation>
 <translation id="3439970425423980614">PDFને પ્રીવ્યૂમાં ખોલી રહ્યાં છે</translation>
@@ -1860,7 +1859,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> જૂનું થઈ ગયું છે</translation>
 <translation id="3908501907586732282">એક્સ્ટેંશન ચાલુ કરો</translation>
 <translation id="3909477809443608991"><ph name="URL" /> સુરક્ષિત કન્ટેન્ટ ચલાવવા માગે છે. Google દ્વારા તમારા ડિવાઇસની ઓળખ ચકાસવામાં આવશે અને તે આ સાઇટ દ્વારા ઍક્સેસ કરવામાં આવી શકે છે.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> અને 1 અન્ય ભાષા</translation>
 <translation id="3909791450649380159">કા&amp;પો</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (આ ઉપકરણ પર ઉપયોગમાં લેવાયેલ નામ)</translation>
 <translation id="3911824782900911339">નવું ટૅબ પૃષ્ઠ</translation>
@@ -2125,7 +2123,6 @@
 <translation id="435527878592612277">તમારો ફોટો પસંદ કરો</translation>
 <translation id="4356334633973342967">અથવા તમારા પોતાના ડ્રાઇવરનો ઉલ્લેખ કરો:</translation>
 <translation id="4358169392473932247">તે સુરક્ષા કોડ, લૉગ ઇન વિગતના આંતરિક સ્ટોરેજઈપ સપોર્ટ કરતું નથી, પરંતુ તે સુવિધાની વિનંતી કરી હતી.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">નિર્ભર એક્સ્ટેન્શન(એક્સ્ટેન્શન્સ)ને લીધે ઇન્સ્ટોલ કર્યું.</translation>
 <translation id="4359717112757026264">સિટિસ્કેપ</translation>
 <translation id="4361142739114356624">આ ક્લાઇન્ટ પ્રમાણપત્ર માટેની ખાનગી કી ખૂટે છે અથવા તો અમાન્ય છે</translation>
@@ -2177,7 +2174,6 @@
 <translation id="443475966875174318">અસંગત ઍપ્લિકેશનોને અપડેટ કરો અથવા કાઢી નાખો</translation>
 <translation id="4441124369922430666">શું જ્યારે મશીન ચાલુ થાય ત્યારે તમે આ એપ્લિકેશનને આપમેળે પ્રારંભ કરવા માંગો છો?</translation>
 <translation id="444134486829715816">વિસ્તૃત કરો...</translation>
-<translation id="4441548209689510310">જોડણીની તપાસ વિકલ્પો બતાવો</translation>
 <translation id="4442424173763614572">DNS લુકઅપ નિષ્ફળ ગયું</translation>
 <translation id="4443536555189480885">&amp;Help</translation>
 <translation id="4444304522807523469">USB અથવા સ્થાનિક નેટવર્ક મારફતે જોડાયેલ દસ્તાવેજ સ્કેનર્સની ઍક્સેસ</translation>
@@ -2974,7 +2970,6 @@
 <translation id="5736796278325406685">કૃપા કરીને એક માન્ય વપરાશકર્તાનામ દાખલ કરો</translation>
 <translation id="5739235828260127894">ચકાસણીની રાહ જોઈ રહ્યાં છીએ. <ph name="LINK_BEGIN" />વધુ જાણો<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">બહુ મોટું</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> અને <ph name="NUM_ADDITIONAL_LANGUAGES" /> અન્ય ભાષા</translation>
 <translation id="574209121243317957">પિચ</translation>
 <translation id="5746169159649715125">PDF તરીકે સાચવો</translation>
 <translation id="5747552184818312860">સમાપ્ત થાય છે</translation>
diff --git a/chrome/app/resources/generated_resources_hi.xtb b/chrome/app/resources/generated_resources_hi.xtb
index 0bf115e..35df96c 100644
--- a/chrome/app/resources/generated_resources_hi.xtb
+++ b/chrome/app/resources/generated_resources_hi.xtb
@@ -1511,7 +1511,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" आपके <ph name="CODE_TYPE" /> का अनुरोध कर रहा है</translation>
 <translation id="3435738964857648380">सुरक्षा</translation>
 <translation id="3435896845095436175">सक्षम करें</translation>
-<translation id="3436038974659740746">कस्टम वर्तनी</translation>
 <translation id="3438633801274389918">निंजा</translation>
 <translation id="3439153939049640737"><ph name="HOST" /> को हमेशा अपना माइक्रोफ़ोन एक्सेस करने दें</translation>
 <translation id="3439970425423980614">पीडीएफ़ की झलक देखें</translation>
@@ -1836,7 +1835,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> पुराना है</translation>
 <translation id="3908501907586732282">एक्‍सटेंशन सक्षम करें</translation>
 <translation id="3909477809443608991"><ph name="URL" /> सुरक्षित सामग्री चलाना चाहता है . Google आपके डिवाइस की पहचान की पुष्टि कर सकता है और यह साइट उसे एक्सेस कर सकती है.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> और 1 अन्य</translation>
 <translation id="3909791450649380159">&amp;काटें</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (इस डिवाइस पर उपयोग किया गया नाम)</translation>
 <translation id="3911824782900911339">नया टैब पेज</translation>
@@ -2095,7 +2093,6 @@
 <translation id="4354344420232759511">आपकी देखी गई साइटें यहां दिखाई देंगी</translation>
 <translation id="435527878592612277">अपनी फ़ोटो चुनें</translation>
 <translation id="4356334633973342967">या अपना स्वयं का ड्राइवर निर्दिष्ट करें:</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">निर्भर एक्सटेंशन के कारण इंस्टॉल किया गया.</translation>
 <translation id="4359717112757026264">सिटीस्केप</translation>
 <translation id="4361142739114356624">इस क्‍लाइंट प्रमाणपत्र की निजी कुंजी मौजूद नहीं है या अमान्‍य है</translation>
@@ -2146,7 +2143,6 @@
 <translation id="443475966875174318">उन ऐप्लिकेशन को अपडेट करें या हटाएं जो संगत नहीं हैं</translation>
 <translation id="4441124369922430666">क्या आप चाहते हैं कि मशीन चालू होने पर यह ऐप्स  स्वचालित रूप से प्रारंभ हो जाए?</translation>
 <translation id="444134486829715816">विस्तृत करें...</translation>
-<translation id="4441548209689510310">वर्तनी परीक्षण के विकल्प दिखाएं</translation>
 <translation id="4442424173763614572">DNS लुकअप विफल</translation>
 <translation id="4443536555189480885">&amp;मदद</translation>
 <translation id="4444304522807523469">USB के द्वारा संलग्‍न किए गए या स्‍थानीय नेटवर्क पर मौजूद दस्‍तावेज़ स्‍कैनर ऐक्‍सेस करें</translation>
@@ -2935,7 +2931,6 @@
 <translation id="5736796278325406685">कृपया कोई मान्य उपयोगकर्ता नाम डालें</translation>
 <translation id="5739235828260127894">पुष्टि होने का इंतज़ार किया जा रहा है. <ph name="LINK_BEGIN" />ज़्यादा जानें<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">बहुत बड़ा</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> और <ph name="NUM_ADDITIONAL_LANGUAGES" /> अन्य</translation>
 <translation id="574209121243317957">पिच</translation>
 <translation id="5746169159649715125">PDF के तौर पर सेव करें</translation>
 <translation id="5747552184818312860">समय सीमा समाप्ति दिनांक</translation>
diff --git a/chrome/app/resources/generated_resources_hr.xtb b/chrome/app/resources/generated_resources_hr.xtb
index b3d170c..41eb01da 100644
--- a/chrome/app/resources/generated_resources_hr.xtb
+++ b/chrome/app/resources/generated_resources_hr.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" zahtijeva vaš <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Sigurnost</translation>
 <translation id="3435896845095436175">Omogući</translation>
-<translation id="3436038974659740746">Prilagođen način pisanja</translation>
 <translation id="3438633801274389918">Nindža</translation>
 <translation id="3439153939049640737">Uvijek dopusti hostu <ph name="HOST" /> pristup mikrofonu</translation>
 <translation id="3439970425423980614">Otvori PDF u Pregledu</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">Dodatak <ph name="PLUGIN_NAME" /> zastario je</translation>
 <translation id="3908501907586732282">Omogući proširenje</translation>
 <translation id="3909477809443608991"><ph name="URL" /> želi reproducirati zaštićeni sadržaj. Google će potvrditi identitet vašeg uređaja i ta će mu web-lokacija moći pristupiti.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> i još jedan</translation>
 <translation id="3909791450649380159">Iz&amp;reži</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (ime koji se upotrebljava na tom uređaju)</translation>
 <translation id="3911824782900911339">Stranica Nova kartica</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Odaberite fotografiju</translation>
 <translation id="4356334633973342967">Možete i navesti vlastiti upravljački program:</translation>
 <translation id="4358169392473932247">Taj sigurnosni ključ ne podržava internu pohranu vjerodajnica, no zatražena je ta značajka.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Instalirano zbog ovisnih proširenja.</translation>
 <translation id="4359717112757026264">Gradski krajolik</translation>
 <translation id="4361142739114356624">Privatni ključ za ovaj certifikat klijenta nedostaje ili nije važeći</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Ažuriranje ili uklanjanje nekompatibilnih aplikacija</translation>
 <translation id="4441124369922430666">Želite li automatski pokrenuti tu aplikaciju kada se uređaj uključi?</translation>
 <translation id="444134486829715816">Proširi...</translation>
-<translation id="4441548209689510310">Prikaži opcije provjere pravopisa</translation>
 <translation id="4442424173763614572">Nije uspjelo pretraživanje DNS poslužitelja</translation>
 <translation id="4443536555189480885">&amp;Help (Pomoć)</translation>
 <translation id="4444304522807523469">pristupiti skenerima dokumenata priključenim preko USB-a ili na lokalnu mrežu</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">Unesite važeće korisničko ime</translation>
 <translation id="5739235828260127894">Čeka se potvrda. <ph name="LINK_BEGIN" />Saznajte više<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Vrlo velik</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> i još <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Visina glasa</translation>
 <translation id="5746169159649715125">Spremi kao PDF</translation>
 <translation id="5747552184818312860">Istječe</translation>
diff --git a/chrome/app/resources/generated_resources_hu.xtb b/chrome/app/resources/generated_resources_hu.xtb
index 2d448fa..a39d9c4 100644
--- a/chrome/app/resources/generated_resources_hu.xtb
+++ b/chrome/app/resources/generated_resources_hu.xtb
@@ -1535,7 +1535,6 @@
 <translation id="3435688026795609344">A(z) „<ph name="EXTENSION_NAME" />” bővítmény kéri a <ph name="CODE_TYPE" />-kódját</translation>
 <translation id="3435738964857648380">Biztonság</translation>
 <translation id="3435896845095436175">Engedélyezés</translation>
-<translation id="3436038974659740746">Helyesírási szótár testreszabása</translation>
 <translation id="3438633801274389918">Nindzsa</translation>
 <translation id="3439153939049640737">A(z) <ph name="HOST" /> mindig hozzáférhet az Ön mikrofonjához</translation>
 <translation id="3439970425423980614">PDF megnyitása előnézetben</translation>
@@ -1687,7 +1686,7 @@
 <translation id="3654045516529121250">A kisegítő lehetőségek beállításainak áttekintése</translation>
 <translation id="3655712721956801464">{NUM_FILES,plural, =1{Állandó hozzáférése van egy fájlhoz.}other{Állandó hozzáférése van # fájlhoz.}}</translation>
 <translation id="3660234220361471169">Nem megbízható</translation>
-<translation id="3661172646479098821">Jelenleg csak az Android-eszközök támogatottak.</translation>
+<translation id="3661172646479098821">A rendszer jelenleg csak az Android-eszközöket támogatja.</translation>
 <translation id="3664511988987167893">Bővítmény ikonja</translation>
 <translation id="3665589677786828986">A Chrome azt észlelte, hogy egy másik program miatt megsérült néhány beállítás, ezért visszaállítja őket az eredeti alapértelmezett értékekre.</translation>
 <translation id="3668570675727296296">Nyelvi beállítások</translation>
@@ -1865,7 +1864,6 @@
 <translation id="3908393983276948098">A(z) <ph name="PLUGIN_NAME" /> elavult</translation>
 <translation id="3908501907586732282">Bővítmény engedélyezése</translation>
 <translation id="3909477809443608991">A(z) <ph name="URL" /> védett tartalmat szeretne lejátszani. Miután a Google azonosítja az eszközt, hozzáférést adhat a webhely számára.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> és 1 további</translation>
 <translation id="3909791450649380159">Ki&amp;vágás</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (a név már használatban van ezen az eszközön)</translation>
 <translation id="3911824782900911339">Új lap oldal</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Válassza ki a fotóját</translation>
 <translation id="4356334633973342967">Vagy adja meg saját illesztőprogramját:</translation>
 <translation id="4358169392473932247">A biztonsági hardverkulcs nem támogatja a hitelesítési adatok belső tárolását, de erre irányuló kérés érkezett.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Telepítve az ezt nélkülözni nem tudó bővítmény(ek) miatt.</translation>
 <translation id="4359717112757026264">Városkép</translation>
 <translation id="4361142739114356624">Az ügyféltanúsítvány privát kulcsa hiányzik vagy érvénytelen</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Nem kompatibilis alkalmazások frissítése és eltávolítása</translation>
 <translation id="4441124369922430666">Szeretné automatikusan elindítani ezt az alkalmazást, amikor bekapcsolja a számítógépet?</translation>
 <translation id="444134486829715816">Részletes nézet...</translation>
-<translation id="4441548209689510310">Helyesírás-ellenőrzési lehetőségek megjelenítése</translation>
 <translation id="4442424173763614572">A DNS keresése sikertelen</translation>
 <translation id="4443536555189480885">&amp;Súgó</translation>
 <translation id="4444304522807523469">USB-kapcsolaton vagy a helyi hálózaton keresztül csatlakoztatott szkennerek elérése</translation>
@@ -2979,7 +2975,6 @@
 <translation id="5736796278325406685">Érvényes felhasználónevet adjon meg</translation>
 <translation id="5739235828260127894">Várakozás az ellenőrzésre. <ph name="LINK_BEGIN" />További információ<ph name="LINK_END" />.</translation>
 <translation id="5739458112391494395">Nagyon nagy</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> és <ph name="NUM_ADDITIONAL_LANGUAGES" /> további</translation>
 <translation id="574209121243317957">Hangmagasság</translation>
 <translation id="5746169159649715125">Mentés PDF-ként</translation>
 <translation id="5747552184818312860">Lejár</translation>
@@ -3818,7 +3813,7 @@
 <translation id="7063129466199351735">Parancsikonok feldolgozása...</translation>
 <translation id="7063311912041006059">URL, ahol a lekérdezést a(z) <ph name="SPECIAL_SYMBOL" /> helyettesíti</translation>
 <translation id="7063957500469387217">Nyomtatók beállítása és kezelése a Google Cloud Print szolgáltatásban.</translation>
-<translation id="7064482796689484940">A biztonsági hardverkulcs nem támogat személyes azonosításra szolgáló módszereket (például ujjlenyomat beolvasását vagy PIN-kód megadását), de erre irányuló kérés érkezett.</translation>
+<translation id="7064482796689484940">A biztonsági hardverkulcs nem támogat személyazonosításra szolgáló módszereket (például ujjlenyomat beolvasását vagy PIN-kód megadását), de erre irányuló kérés érkezett.</translation>
 <translation id="7065223852455347715">Ez az eszköz olyan módban van rögzítve, amely megakadályozza a vállalati regisztrációt. Ha szeretné regisztrálni azt, először vissza kell állítania az eszköz beállításait.</translation>
 <translation id="7065534935986314333">A rendszerről</translation>
 <translation id="706626672220389329">Hiba történt a megosztott tároló csatlakoztatása során. Az adott megosztott tároló már csatlakoztatva van.</translation>
diff --git a/chrome/app/resources/generated_resources_id.xtb b/chrome/app/resources/generated_resources_id.xtb
index 32b603b..78dd9b9 100644
--- a/chrome/app/resources/generated_resources_id.xtb
+++ b/chrome/app/resources/generated_resources_id.xtb
@@ -1532,7 +1532,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" meminta <ph name="CODE_TYPE" /> Anda</translation>
 <translation id="3435738964857648380">Keamanan</translation>
 <translation id="3435896845095436175">Aktifkan</translation>
-<translation id="3436038974659740746">Ejaan khusus</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Selalu izinkan <ph name="HOST" /> mengakses mikrofon Anda</translation>
 <translation id="3439970425423980614">Membuka PDF dalam Pratinjau</translation>
@@ -1862,7 +1861,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> sudah usang</translation>
 <translation id="3908501907586732282">Aktifkan ekstensi</translation>
 <translation id="3909477809443608991"><ph name="URL" /> ingin memutar konten yang dilindungi. Identitas perangkat Anda akan diverifikasi oleh Google dan akan dapat diakses oleh situs ini.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, dan 1 lainnya</translation>
 <translation id="3909791450649380159">Po&amp;tong</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nama yang digunakan pada perangkat ini)</translation>
 <translation id="3911824782900911339">Halaman Tab Baru</translation>
@@ -2127,7 +2125,6 @@
 <translation id="435527878592612277">Pilih foto Anda</translation>
 <translation id="4356334633973342967">Atau tentukan driver Anda sendiri:</translation>
 <translation id="4358169392473932247">Kunci keamanan tersebut tidak mendukung penyimpanan internal kredensial, tetapi fitur tersebut diminta.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Dipasang karena ekstensi dependen.</translation>
 <translation id="4359717112757026264">Pemandangan Kota</translation>
 <translation id="4361142739114356624">Kunci Pribadi untuk Sertifikat Klien ini tidak ditemukan atau tidak valid</translation>
@@ -2179,7 +2176,6 @@
 <translation id="443475966875174318">Update atau hapus aplikasi yang tidak kompatibel</translation>
 <translation id="4441124369922430666">Ingin memulai aplikasi ini secara otomatis saat komputer diaktifkan?</translation>
 <translation id="444134486829715816">Luaskan...</translation>
-<translation id="4441548209689510310">Tampilkan opsi periksa ejaan</translation>
 <translation id="4442424173763614572">Pencarian DNS gagal</translation>
 <translation id="4443536555189480885">&amp;Bantuan</translation>
 <translation id="4444304522807523469">Mengakses pemindai dokumen yang terpasang melalui USB atau pada jaringan lokal</translation>
@@ -2975,7 +2971,6 @@
 <translation id="5736796278325406685">Masukkan nama pengguna yang valid</translation>
 <translation id="5739235828260127894">Menunggu verifikasi. <ph name="LINK_BEGIN" />Pelajari lebih lanjut<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Sangat besar</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, dan <ph name="NUM_ADDITIONAL_LANGUAGES" /> lainnya</translation>
 <translation id="574209121243317957">Tinggi nada</translation>
 <translation id="5746169159649715125">Simpan sebagai PDF</translation>
 <translation id="5747552184818312860">Kedaluwarsa</translation>
diff --git a/chrome/app/resources/generated_resources_it.xtb b/chrome/app/resources/generated_resources_it.xtb
index 1a4fd79..50d2f341 100644
--- a/chrome/app/resources/generated_resources_it.xtb
+++ b/chrome/app/resources/generated_resources_it.xtb
@@ -1530,7 +1530,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" richiede il tuo codice <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Sicurezza</translation>
 <translation id="3435896845095436175">Abilita</translation>
-<translation id="3436038974659740746">Ortografia personalizzata</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Consenti sempre a <ph name="HOST" /> di accedere al microfono</translation>
 <translation id="3439970425423980614">Apertura PDF in anteprima in corso</translation>
@@ -1860,7 +1859,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> è obsoleto</translation>
 <translation id="3908501907586732282">Attiva estensione</translation>
 <translation id="3909477809443608991"><ph name="URL" /> chiede di riprodurre contenuti protetti. Google verificherà l'identità del tuo dispositivo e questo sito potrebbe avervi accesso.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> e 1 altra</translation>
 <translation id="3909791450649380159">T&amp;aglia</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nome utilizzato su questo dispositivo)</translation>
 <translation id="3911824782900911339">Pagina Nuova scheda</translation>
@@ -2125,7 +2123,6 @@
 <translation id="435527878592612277">Seleziona la foto</translation>
 <translation id="4356334633973342967">In alternativa specifica il tuo driver:</translation>
 <translation id="4358169392473932247">Quel token di sicurezza non supporta la memorizzazione interna di credenziali, ma la funzionalità era richiesta.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Installata a causa di estensioni dipendenti.</translation>
 <translation id="4359717112757026264">Cityscape</translation>
 <translation id="4361142739114356624">La chiave privata per il certificato client manca o non è valida</translation>
@@ -2177,7 +2174,6 @@
 <translation id="443475966875174318">Aggiorna o rimuovi le applicazioni non compatibili</translation>
 <translation id="4441124369922430666">Vuoi avviare automaticamente questa app all'accensione del computer?</translation>
 <translation id="444134486829715816">Espandi...</translation>
-<translation id="4441548209689510310">Mostra opzioni per il controllo ortografico</translation>
 <translation id="4442424173763614572">Ricerca DNS non riuscita</translation>
 <translation id="4443536555189480885">&amp;Guida</translation>
 <translation id="4444304522807523469">Accesso a scanner di documenti aggiunti tramite USB o sulla rete locale</translation>
@@ -2973,7 +2969,6 @@
 <translation id="5736796278325406685">Inserisci un nome utente valido</translation>
 <translation id="5739235828260127894">In attesa di verifica. <ph name="LINK_BEGIN" />Ulteriori informazioni<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Molto grandi</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> e altre <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Tono</translation>
 <translation id="5746169159649715125">Salva come PDF</translation>
 <translation id="5747552184818312860">Scadenza</translation>
diff --git a/chrome/app/resources/generated_resources_iw.xtb b/chrome/app/resources/generated_resources_iw.xtb
index 8a06137..9ca3f29 100644
--- a/chrome/app/resources/generated_resources_iw.xtb
+++ b/chrome/app/resources/generated_resources_iw.xtb
@@ -1307,7 +1307,7 @@
 <translation id="3045447014237878114">האתר הזה הוריד קבצים מרובים באופן אוטומטי</translation>
 <translation id="3046910703532196514">דף אינטרנט, שלם</translation>
 <translation id="304747341537320566">מנועי דיבור</translation>
-<translation id="3047644958362961983">‏המידע הזה עוזר לנו להבין בצורה טובה יותר את הבעיה שלך ב-Assistant. המידע נשמר לתקופה של עד 90 ימים והגישה אליו מוגבלת רק לצוותי ההנדסה והמשוב המתאימים.</translation>
+<translation id="3047644958362961983">‏המידע הזה עוזר לנו להבין בצורה טובה יותר את הבעיה שלך ב-Assistant. הוא נשמר לתקופה של עד 90 ימים והגישה אליו מוגבלת: רק צוותי ההנדסה והמשוב המתאימים רשאים לגשת אליו.</translation>
 <translation id="3053013834507634016">שימוש במפתח אישור </translation>
 <translation id="3058498974290601450">אפשר להפעיל את הסנכרון בכל זמן דרך ההגדרות</translation>
 <translation id="3060379269883947824">הפעלת הקראה</translation>
@@ -1531,7 +1531,6 @@
 <translation id="3435688026795609344">התוסף "<ph name="EXTENSION_NAME" />" מבקש את ה-<ph name="CODE_TYPE" /> שלך</translation>
 <translation id="3435738964857648380">אבטחה</translation>
 <translation id="3435896845095436175">הפעל</translation>
-<translation id="3436038974659740746">איות מותאם אישית</translation>
 <translation id="3438633801274389918">נינג'ה</translation>
 <translation id="3439153939049640737">אפשר תמיד ל-<ph name="HOST" /> לגשת למיקרופון שלך</translation>
 <translation id="3439970425423980614">‏פתיחת PDF בתצוגה מקדימה</translation>
@@ -1861,7 +1860,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> לא מעודכן</translation>
 <translation id="3908501907586732282">הפעל תוסף</translation>
 <translation id="3909477809443608991">‏<ph name="URL" /> רוצה להציג תוכן מוגן. הזהות של המכשיר שלך תאומת על ידי Google ולאתר תהיה גישה אליה.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />‏, <ph name="LANGUAGE_2" /> ואחת נוספת</translation>
 <translation id="3909791450649380159">גז&amp;ור</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (נעשה שימוש בשם במכשיר הזה)</translation>
 <translation id="3911824782900911339">דף 'כרטיסייה חדשה'</translation>
@@ -2126,7 +2124,6 @@
 <translation id="435527878592612277">בחירת התמונה שלך</translation>
 <translation id="4356334633973342967">או ציין מנהל התקן משלך:</translation>
 <translation id="4358169392473932247">מפתח האבטחה הזה לא תומך באחסון פנימי של פרטי כניסה, אבל התכונה הזו התבקשה.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />‏, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">הותקן מפני שיש תוספים התלויים בו.</translation>
 <translation id="4359717112757026264">נוף עירוני</translation>
 <translation id="4361142739114356624">המפתח הפרטי לאישור לקוח זה חסר או אינו חוקי</translation>
@@ -2178,7 +2175,6 @@
 <translation id="443475966875174318">עדכון או הסרה של אפליקציות לא תואמות</translation>
 <translation id="4441124369922430666">האם ברצונך להפעיל יישום זה באופן אוטומטי בעת הפעלת המחשב?</translation>
 <translation id="444134486829715816">הרחב...</translation>
-<translation id="4441548209689510310">הצג אפשרויות של בדיקת איות</translation>
 <translation id="4442424173763614572">‏חיפוש ה-DNS נכשל</translation>
 <translation id="4443536555189480885">&amp;עזרה</translation>
 <translation id="4444304522807523469">‏גישה לסורקי מסמכים המחוברים באמצעות USB או ברשת המקומית</translation>
@@ -2974,7 +2970,6 @@
 <translation id="5736796278325406685">הזן שם משתמש חוקי</translation>
 <translation id="5739235828260127894">בהמתנה לאימות. <ph name="LINK_BEGIN" />מידע נוסף<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">גדול מאוד</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />‏, <ph name="LANGUAGE_2" /> ו-<ph name="NUM_ADDITIONAL_LANGUAGES" /> נוספות</translation>
 <translation id="574209121243317957">גובה צליל</translation>
 <translation id="5746169159649715125">‏שמור כקובץ PDF</translation>
 <translation id="5747552184818312860">מועד תפוגה</translation>
@@ -4268,7 +4263,7 @@
 <translation id="7788383851298063850">ספר לנו מה קורה</translation>
 <translation id="7788444488075094252">שפות וקלט</translation>
 <translation id="7788668840732459509">מיקום:</translation>
-<translation id="7789963078219276159">הרקע של דף הפתיחה השתנה לרקע <ph name="CATEGORY" />.</translation>
+<translation id="7789963078219276159">הרקע של דף הפתיחה הוחלף, ועכשיו מופיעה בו התמונה<ph name="CATEGORY" />.</translation>
 <translation id="7791543448312431591">הוספה</translation>
 <translation id="7792012425874949788">משהו השתבש בכניסה לחשבון</translation>
 <translation id="7792388396321542707">הפסק שיתוף</translation>
diff --git a/chrome/app/resources/generated_resources_ja.xtb b/chrome/app/resources/generated_resources_ja.xtb
index 3e912f26..a8953cb 100644
--- a/chrome/app/resources/generated_resources_ja.xtb
+++ b/chrome/app/resources/generated_resources_ja.xtb
@@ -138,7 +138,7 @@
 <translation id="1193273168751563528">管理対象セッションを開始します</translation>
 <translation id="1195447618553298278">不明なエラーです。</translation>
 <translation id="1197979282329025000"><ph name="PRINTER_NAME" /> プリンタのプリンタ機能の取得中にエラーが発生しました。このプリンタを <ph name="CLOUD_PRINT_NAME" /> に登録できませんでした。</translation>
-<translation id="119944043368869598">すべてクリア</translation>
+<translation id="119944043368869598">すべて削除</translation>
 <translation id="1201402288615127009">次へ</translation>
 <translation id="1202596434010270079">キオスクアプリを更新しました。USB スティックを取り外してください。</translation>
 <translation id="120368089816228251">音符</translation>
@@ -435,7 +435,7 @@
 <translation id="16620462294541761">パスワードを確認できませんでした。もう一度お試しください。</translation>
 <translation id="166278006618318542">サブジェクトの公開鍵アルゴリズム</translation>
 <translation id="166439687370499867">共有のネットワーク設定を変更することはできません</translation>
-<translation id="1670399744444387456">基本</translation>
+<translation id="1670399744444387456">基本設定</translation>
 <translation id="167160931442925455">最大</translation>
 <translation id="1673137583248014546"><ph name="URL" /> よりセキュリティ キーのメーカーとモデルの読み取り許可を求められています</translation>
 <translation id="1679068421605151609">デベロッパー ツール</translation>
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">「<ph name="EXTENSION_NAME" />」が <ph name="CODE_TYPE" /> をリクエストしています</translation>
 <translation id="3435738964857648380">セキュリティ</translation>
 <translation id="3435896845095436175">有効にする</translation>
-<translation id="3436038974659740746">カスタム スペルチェック</translation>
 <translation id="3438633801274389918">忍者</translation>
 <translation id="3439153939049640737"><ph name="HOST" /> によるマイクへのアクセスを常に許可する</translation>
 <translation id="3439970425423980614">PDF をプレビューしています</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> は期限切れです</translation>
 <translation id="3908501907586732282">拡張機能を有効にする</translation>
 <translation id="3909477809443608991"><ph name="URL" /> が保護されたコンテンツの再生を要求しています。デバイスの認証情報が Google によって確認され、このサイトによる認証情報へのアクセスが許可されます。</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />、<ph name="LANGUAGE_2" />、他 1 言語</translation>
 <translation id="3909791450649380159">切り取り(&amp;T)</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" />(このデバイスで使用されている名前)</translation>
 <translation id="3911824782900911339">新しいタブ ページ</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">写真を選択</translation>
 <translation id="4356334633973342967">または独自のドライバを指定:</translation>
 <translation id="4358169392473932247">認証情報の内部保存がリクエストされましたが、そのセキュリティ キーはこの機能に対応していません。</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />、<ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">依存関係にある拡張機能によってインストールされました。</translation>
 <translation id="4359717112757026264">Cityscape</translation>
 <translation id="4361142739114356624">このクライアント証明書には秘密鍵がないか、秘密鍵が無効です</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">互換性のないアプリケーションの更新または削除</translation>
 <translation id="4441124369922430666">マシンの起動時にこのアプリを自動的に起動しますか?</translation>
 <translation id="444134486829715816">展開...</translation>
-<translation id="4441548209689510310">スペルチェック オプションを表示</translation>
 <translation id="4442424173763614572">DNS を検索できませんでした</translation>
 <translation id="4443536555189480885">ヘルプ(&amp;H)</translation>
 <translation id="4444304522807523469">USB 接続またはローカル ネットワーク上のドキュメント スキャナーへのアクセス</translation>
@@ -2947,7 +2943,7 @@
 <translation id="5678955352098267522"><ph name="WEBSITE_1" /> でのユーザーデータの読み取り</translation>
 <translation id="5684661240348539843">アセット ID</translation>
 <translation id="5687326903064479980">タイムゾーン</translation>
-<translation id="5689516760719285838">現在地</translation>
+<translation id="5689516760719285838">位置情報</translation>
 <translation id="56907980372820799">データをリンク</translation>
 <translation id="5691511426247308406">ファミリー</translation>
 <translation id="5696143504434933566">「<ph name="EXTENSION_NAME" />」の不正行為を報告する</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">有効なユーザー名を入力してください</translation>
 <translation id="5739235828260127894">確認を待っています。<ph name="LINK_BEGIN" />詳細<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">極大</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />、<ph name="LANGUAGE_2" />、他 <ph name="NUM_ADDITIONAL_LANGUAGES" /> 言語</translation>
 <translation id="574209121243317957">高さ</translation>
 <translation id="5746169159649715125">PDF に保存</translation>
 <translation id="5747552184818312860">有効期限</translation>
@@ -3248,7 +3243,7 @@
 <translation id="6143186082490678276">ヘルプ</translation>
 <translation id="6144938890088808325">Chromebooks の改善にご協力ください</translation>
 <translation id="6147020289383635445">印刷プレビューの表示に失敗しました。</translation>
-<translation id="614940544461990577">次をお試しください:</translation>
+<translation id="614940544461990577">次をお試しください</translation>
 <translation id="6150961653851236686">この言語がページを翻訳する場合に使用されます</translation>
 <translation id="6151323131516309312"><ph name="SEARCH_KEY" /> を押して <ph name="SITE_NAME" /> を検索</translation>
 <translation id="6151771661215463137">このファイルはダウンロード フォルダにすでにあります。</translation>
@@ -3808,7 +3803,7 @@
 <translation id="7051943809462976355">マウスを探しています...</translation>
 <translation id="7052237160939977163">パフォーマンス追跡データを送信する</translation>
 <translation id="7053983685419859001">ブロック</translation>
-<translation id="7055152154916055070">リダイレクトがブロックされました:</translation>
+<translation id="7055152154916055070">リダイレクトがブロックされました</translation>
 <translation id="7056526158851679338">デバイスを検証(&amp;I)</translation>
 <translation id="7059858479264779982">自動起動に設定する</translation>
 <translation id="7059893117020417984">シークレット モードを使うには、その他アイコンのメニューからシークレット ウィンドウを開きます</translation>
@@ -4414,7 +4409,7 @@
 <translation id="7978450511781612192">この操作を行うと Google アカウントからログアウトし、ブックマーク、履歴、パスワードなどの設定は同期されなくなります。</translation>
 <translation id="7979036127916589816">同期エラー</translation>
 <translation id="7980084013673500153">アセット ID: <ph name="ASSET_ID" /></translation>
-<translation id="7981313251711023384">ページをプリロードして閲覧と検索をすばやく行えるようにする</translation>
+<translation id="7981313251711023384">ページをプリロードして、閲覧と検索をすばやく行えるようにします</translation>
 <translation id="798145602633458219">検索ボックスに候補<ph name="SUGGESTION_NAME" />を追加します</translation>
 <translation id="7982083145464587921">このエラーを修正するには、デバイスを再起動してください。</translation>
 <translation id="7982789257301363584">ネットワーク</translation>
@@ -4451,7 +4446,7 @@
       購入した映画、テレビ番組、音楽、書籍、その他のアプリ内購入のコンテンツも削除される可能性があります。
       <ph name="LINE_BREAKS2" />
       他の端末のアプリやコンテンツに影響はありません。</translation>
-<translation id="8026334261755873520">閲覧履歴データを削除する</translation>
+<translation id="8026334261755873520">閲覧履歴データの削除</translation>
 <translation id="8028060951694135607">Microsoft キー回復</translation>
 <translation id="8028803902702117856"><ph name="FILE_NAME" /> をダウンロードしています。<ph name="SIZE" /> 完了</translation>
 <translation id="8028993641010258682">サイズ</translation>
@@ -5046,7 +5041,7 @@
 <translation id="8978154919215542464">オン - すべて同期</translation>
 <translation id="897939795688207351"><ph name="ORIGIN" /></translation>
 <translation id="8980951173413349704"><ph name="WINDOW_TITLE" /> - クラッシュしました</translation>
-<translation id="8983677657449185470">セーフ ブラウジングの改善に協力する</translation>
+<translation id="8983677657449185470">セーフ ブラウジングの改善への協力</translation>
 <translation id="8986362086234534611">削除</translation>
 <translation id="8986494364107987395">使用統計データと障害レポートを Google に自動送信します</translation>
 <translation id="8987927404178983737">月</translation>
diff --git a/chrome/app/resources/generated_resources_kn.xtb b/chrome/app/resources/generated_resources_kn.xtb
index ccd8300..0497074 100644
--- a/chrome/app/resources/generated_resources_kn.xtb
+++ b/chrome/app/resources/generated_resources_kn.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" ನಿಮ್ಮ <ph name="CODE_TYPE" /> ಅನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ</translation>
 <translation id="3435738964857648380">ಭದ್ರತೆ</translation>
 <translation id="3435896845095436175">ಸಕ್ರಿಯಗೊಳಿಸು</translation>
-<translation id="3436038974659740746">ಕಸ್ಟಮ್ ಕಾಗುಣಿತ</translation>
 <translation id="3438633801274389918">ನಿಂಜಾ</translation>
 <translation id="3439153939049640737">ನಿಮ್ಮ ಮೈಕ್ರೋಫೋನ್ ಪ್ರವೇಶಿಸಲು ಯಾವಾಗಲೂ <ph name="HOST" /> ಅನ್ನು ಅನುಮತಿಸಿ</translation>
 <translation id="3439970425423980614">PDF ಅನ್ನು ಪೂರ್ವವೀಕ್ಷಣೆಯಲ್ಲಿ ತೆರೆಯುವುದು</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> ಅವಧಿ ಮುಗಿದಿದೆ</translation>
 <translation id="3908501907586732282">ವಿಸ್ತರಣೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸು</translation>
 <translation id="3909477809443608991"><ph name="URL" />, ಸಂರಕ್ಷಿತ ವಿಷಯವನ್ನು ಪ್ಲೇ ಮಾಡಲು ಬಯಸುತ್ತದೆ. ನಿಮ್ಮ ಸಾಧನದ ಗುರುತನ್ನು Google ಪರಿಶೀಲಿಸುತ್ತದೆ ಮತ್ತು ಅದಕ್ಕೆ ಈ ಸೈಟ್ ಪ್ರವೇಶ ಪಡೆಯಬಹುದು.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, ಹಾಗೂ ಮತ್ತೊಂದು</translation>
 <translation id="3909791450649380159">ಕತ್ತರಿ&amp;ಸು</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (ಈ ಸಾಧನದಲ್ಲಿ ಬಳಸಿದ ಹೆಸರು)</translation>
 <translation id="3911824782900911339">ಹೊಸ ಟ್ಯಾಬ್ ಪುಟ</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">ನಿಮ್ಮ ಫೋಟೋ ಆಯ್ಕೆಮಾಡಿ</translation>
 <translation id="4356334633973342967">ಅಥವಾ ನಿಮ್ಮ ಸ್ವಂತ ಡ್ರೈವರ್ ನಿರ್ದಿಷ್ಟಪಡಿಸಿ:</translation>
 <translation id="4358169392473932247">ರುಜುವಾತುಗಳನ್ನು ಆಂತರಿಕವಾಗಿ ಸಂಗ್ರಹಣೆ ಮಾಡುವುದನ್ನು ಆ ಸುರಕ್ಷತಾ ಕೀಯು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ, ಆದರೆ ಆ ವೈಶಿಷ್ಟ್ಯವನ್ನು ವಿನಂತಿಸಲಾಗಿದೆ.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">ಅವಲಂಬಿತ ವಿಸ್ತರಣೆ(ಗಳು) ಯಿಂದಾಗಿ ಸ್ಥಾಪಿಸಲಾಗಿದೆ.</translation>
 <translation id="4359717112757026264">Cityscape</translation>
 <translation id="4361142739114356624">ಈ ಕ್ಲೈಂಟ್ ಪ್ರಮಾಣಪತ್ರಕ್ಕೆ ವೈಯಕ್ತಿಕ ಕೀ ಕಾಣೆಯಾಗಿದೆ ಅಥವಾ ಅಮಾನ್ಯವಾಗಿದೆ</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">ಹೊಂದಾಣಿಕೆಯಾಗದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಿ ಅಥವಾ ತೆಗೆದುಹಾಕಿ</translation>
 <translation id="4441124369922430666">ಯಂತ್ರವು ಆನ್ ಆದ ಸಂದರ್ಭದಲ್ಲಿ ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ನೀವು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆರಂಭಿಸಲು ಬಯಸುವಿರಾ?</translation>
 <translation id="444134486829715816">ವಿಸ್ತರಿಸಿ...</translation>
-<translation id="4441548209689510310">ಕಾಗುಣಿತ ಪರಿಶೀಲನೆ ಆಯ್ಕೆಗಳನ್ನು ತೋರಿಸು</translation>
 <translation id="4442424173763614572">DNS ಲುಕಪ್ ವಿಫಲವಾಗಿದೆ</translation>
 <translation id="4443536555189480885">&amp;ಸಹಾಯ</translation>
 <translation id="4444304522807523469">USB ಅಥವಾ ಸ್ಥಳೀಯ ನೆಟ್‌ವರ್ಕ್ ಮೂಲಕ ಲಗತ್ತಿಸಲಾದ ಡಾಕ್ಯುಮೆಂಟ್ ಸ್ಕ್ಯಾನರ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಿ</translation>
@@ -2979,7 +2975,6 @@
 <translation id="5736796278325406685">ದಯವಿಟ್ಟು ಮಾನ್ಯವಾದ ಬಳಕೆದಾರ ಹೆಸರನ್ನು ನಮೂದಿಸಿ</translation>
 <translation id="5739235828260127894">ಪರಿಶೀಲನೆಗಾಗಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ. <ph name="LINK_BEGIN" />ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">ಅತ್ಯಂತ ದೊಡ್ಡದು</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> ಮತ್ತು <ph name="NUM_ADDITIONAL_LANGUAGES" /> ಇತರೆ</translation>
 <translation id="574209121243317957">ಪಿಚ್</translation>
 <translation id="5746169159649715125">PDF ನಂತೆ ಉಳಿಸಿ</translation>
 <translation id="5747552184818312860">ಅವಧಿ ಮೀರುವುದು</translation>
diff --git a/chrome/app/resources/generated_resources_ko.xtb b/chrome/app/resources/generated_resources_ko.xtb
index 4f92252..1dec636 100644
--- a/chrome/app/resources/generated_resources_ko.xtb
+++ b/chrome/app/resources/generated_resources_ko.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">'<ph name="EXTENSION_NAME" />'이(가) <ph name="CODE_TYPE" />을(를) 요청하고 있습니다.</translation>
 <translation id="3435738964857648380">보안</translation>
 <translation id="3435896845095436175">사용</translation>
-<translation id="3436038974659740746">사용자 정의 맞춤법</translation>
 <translation id="3438633801274389918">닌자</translation>
 <translation id="3439153939049640737"><ph name="HOST" />에서 마이크에 액세스하도록 항상 허용</translation>
 <translation id="3439970425423980614">미리보기에서 PDF 여는 중</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" />이(가) 이전 버전입니다.</translation>
 <translation id="3908501907586732282">확장 프로그램 사용</translation>
 <translation id="3909477809443608991"><ph name="URL" />에서 보호된 콘텐츠를 재생하려고 합니다. Google에서 이 기기의 신원을 확인하며 이 사이트에서 이 기기에 액세스할 수 있습니다.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> 외 1개</translation>
 <translation id="3909791450649380159">잘라내기(&amp;T)</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" />(이 기기에서 사용된 이름)</translation>
 <translation id="3911824782900911339">새 탭 페이지</translation>
@@ -2127,7 +2125,6 @@
 <translation id="435527878592612277">사진 선택</translation>
 <translation id="4356334633973342967">또는 드라이버 지정:</translation>
 <translation id="4358169392473932247">사용자 인증 정보의 내부 저장이 요청되었으나, 보안 키가 이 기능을 지원하지 않습니다.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">함께 설치된 확장 프로그램입니다.</translation>
 <translation id="4359717112757026264">도시 풍경</translation>
 <translation id="4361142739114356624">이 클라이언트 인증서의 비공개 키가 없거나 잘못되었습니다.</translation>
@@ -2179,7 +2176,6 @@
 <translation id="443475966875174318">호환되지 않는 애플리케이션 업데이트 또는 삭제</translation>
 <translation id="4441124369922430666">컴퓨터를 켤 때 이 앱을 자동으로 시작하시겠습니까?</translation>
 <translation id="444134486829715816">펼치기...</translation>
-<translation id="4441548209689510310">맞춤법 검사기 옵션 표시</translation>
 <translation id="4442424173763614572">DNS 조회 실패</translation>
 <translation id="4443536555189480885">도움말(&amp;H)</translation>
 <translation id="4444304522807523469">USB나 로컬 네트워크에 포함된 문서 스캐너에 액세스</translation>
@@ -2975,7 +2971,6 @@
 <translation id="5736796278325406685">올바른 사용자 이름을 입력하세요.</translation>
 <translation id="5739235828260127894">확인을 기다리는 중입니다. <ph name="LINK_BEGIN" />자세히 알아보기<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">아주 크게</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> 외 <ph name="NUM_ADDITIONAL_LANGUAGES" />개</translation>
 <translation id="574209121243317957">높낮이</translation>
 <translation id="5746169159649715125">PDF로 저장</translation>
 <translation id="5747552184818312860">만료</translation>
diff --git a/chrome/app/resources/generated_resources_lt.xtb b/chrome/app/resources/generated_resources_lt.xtb
index e4572a7..d79c3d2b 100644
--- a/chrome/app/resources/generated_resources_lt.xtb
+++ b/chrome/app/resources/generated_resources_lt.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">„<ph name="EXTENSION_NAME" />“ prašo pateikti <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Sauga</translation>
 <translation id="3435896845095436175">Įgalinti</translation>
-<translation id="3436038974659740746">Tinkinta rašyba</translation>
 <translation id="3438633801274389918">Nindzė</translation>
 <translation id="3439153939049640737">Visada leisti <ph name="HOST" /> pasiekti mikrofoną</translation>
 <translation id="3439970425423980614">Atidaromas PDF peržiūros režimu</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">„<ph name="PLUGIN_NAME" />“ pasenęs</translation>
 <translation id="3908501907586732282">Įgalinti plėtinį</translation>
 <translation id="3909477809443608991"><ph name="URL" /> nori paleisti saugomą turinį Įrenginio tapatybę patvirtins „Google“ ir įrenginį galės pasiekti ši svetainė.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> ir dar 1</translation>
 <translation id="3909791450649380159">Iškir&amp;pti</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (šiame įrenginyje naudojamas vardas)</translation>
 <translation id="3911824782900911339">Naujo skirtuko puslapis</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Pasirinkite nuotrauką</translation>
 <translation id="4356334633973342967">Arba nurodykite savo tvarkyklę:</translation>
 <translation id="4358169392473932247">Šis saugos raktas nepalaiko prisijungimo duomenų vidinės atminties, bet pateikta šios funkcijos užklausa.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Įdiegta, nes priklauso nuo plėtinio (-ių).</translation>
 <translation id="4359717112757026264">Miesto architektūra</translation>
 <translation id="4361142739114356624">Trūksta šio kliento sertifikato privataus rakto arba jis netinkamas</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Nesuderinamų programų atnaujinimas arba pašalinimas</translation>
 <translation id="4441124369922430666">Norite automatiškai paleisti šią programą, kai įjungiamas įrenginys?</translation>
 <translation id="444134486829715816">Išskleisti...</translation>
-<translation id="4441548209689510310">Rodyti rašybos tikrinimo parinktis</translation>
 <translation id="4442424173763614572">Įvyko DNS paieškos klaida</translation>
 <translation id="4443536555189480885">&amp;Pagalba</translation>
 <translation id="4444304522807523469">Pasiekti dokumentų skaitytuvus, prijungtus per USB jungtį ar vietiniame tinkle</translation>
@@ -2978,7 +2974,6 @@
 <translation id="5736796278325406685">Įveskite tinkamą naudotojo vardą</translation>
 <translation id="5739235828260127894">Laukiama patvirtinimo. <ph name="LINK_BEGIN" />Sužinokite daugiau<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Labai didelis</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> ir dar <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Tonas</translation>
 <translation id="5746169159649715125">Išsaugoti kaip PDF</translation>
 <translation id="5747552184818312860">Galioja iki</translation>
diff --git a/chrome/app/resources/generated_resources_lv.xtb b/chrome/app/resources/generated_resources_lv.xtb
index c7f999e..a70b57b 100644
--- a/chrome/app/resources/generated_resources_lv.xtb
+++ b/chrome/app/resources/generated_resources_lv.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">Paplašinājumā <ph name="EXTENSION_NAME" /> tiek pieprasīts jūsu <ph name="CODE_TYPE" />.</translation>
 <translation id="3435738964857648380">Drošība</translation>
 <translation id="3435896845095436175">Iespējot</translation>
-<translation id="3436038974659740746">Pielāgot pareizrakstību</translation>
 <translation id="3438633801274389918">Nindzja</translation>
 <translation id="3439153939049640737">Vienmēr ļaut vietnei <ph name="HOST" /> piekļūt mikrofonam</translation>
 <translation id="3439970425423980614">Notiek PDF priekšskatījuma atvēršana</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">Spraudnis <ph name="PLUGIN_NAME" /> ir novecojis</translation>
 <translation id="3908501907586732282">Iespējot paplašinājumu</translation>
 <translation id="3909477809443608991">Vietne <ph name="URL" /> vēlas atskaņot aizsargātu saturu. Jūsu ierīces identitāti pārbaudīs Google, un tai var piekļūt šī vietne.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> un vēl 1</translation>
 <translation id="3909791450649380159">Izgrie&amp;zt</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (šajā ierīcē lietotais nosaukums)</translation>
 <translation id="3911824782900911339">Jaunas cilnes lapa</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Atlasiet savu fotoattēlu</translation>
 <translation id="4356334633973342967">Varat arī norādīt savu dzini:</translation>
 <translation id="4358169392473932247">Šī drošības atslēga neatbalsta akreditācijas datu iekšējo uzglabāšanu, taču šī funkcija tika pieprasīta.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Paplašinājums tika instalēts atkarīga(-u) paplašinājuma(-u) dēļ.</translation>
 <translation id="4359717112757026264">Pilsētu fotoattēli</translation>
 <translation id="4361142739114356624">Nav norādīta šī klienta sertifikāta privātā atslēga, vai tā nav derīga.</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Nesaderīgu lietojumprogrammu atjaunināšana vai noņemšana</translation>
 <translation id="4441124369922430666">Vai vēlaties automātiski startēt šo lietotni, kad tiek ieslēgta ierīce?</translation>
 <translation id="444134486829715816">Izvērst...</translation>
-<translation id="4441548209689510310">Rādīt pareizrakstības pārbaudes iespējas</translation>
 <translation id="4442424173763614572">DNS uzmeklēšana neizdevās</translation>
 <translation id="4443536555189480885">&amp;Palīdzība</translation>
 <translation id="4444304522807523469">Piekļūt dokumentu skeneriem, kas pievienoti, izmantojot USB vai lokālajā tīklā</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">Lūdzu, ievadiet derīgu lietotājvārdu.</translation>
 <translation id="5739235828260127894">Tiek gaidīta verifikācija. <ph name="LINK_BEGIN" />Uzziniet vairāk<ph name="LINK_END" />.</translation>
 <translation id="5739458112391494395">Ļoti liels</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> un vēl <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Tonis</translation>
 <translation id="5746169159649715125">Saglabāt kā PDF failu</translation>
 <translation id="5747552184818312860">Termiņš</translation>
diff --git a/chrome/app/resources/generated_resources_ml.xtb b/chrome/app/resources/generated_resources_ml.xtb
index a1b5579..39803c51 100644
--- a/chrome/app/resources/generated_resources_ml.xtb
+++ b/chrome/app/resources/generated_resources_ml.xtb
@@ -1531,7 +1531,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" നിങ്ങളുടെ <ph name="CODE_TYPE" /> അഭ്യർത്ഥിക്കുന്നു</translation>
 <translation id="3435738964857648380">സുരക്ഷ</translation>
 <translation id="3435896845095436175">തയ്യാറാക്കുക</translation>
-<translation id="3436038974659740746">ഇഷ്‌ടാനുസൃത അക്ഷരത്തെറ്റ് പരിശോധന</translation>
 <translation id="3438633801274389918">നിൻജ</translation>
 <translation id="3439153939049640737"><ph name="HOST" /> എന്നതിനെ നിങ്ങളുടെ മൈക്രോഫോൺ ആക്‌സസ്സുചെയ്യാൻ എല്ലായ്‌പ്പോഴും അനുവദിക്കുക</translation>
 <translation id="3439970425423980614">PDF പ്രിവ്യുവിൽ തുറക്കുന്നു</translation>
@@ -1861,7 +1860,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> കാലഹരണപ്പെട്ടു</translation>
 <translation id="3908501907586732282">വിപുലീകരണം പ്രാപ്‌തമാക്കുക</translation>
 <translation id="3909477809443608991">പരിരക്ഷിത ഉള്ളടക്കം പ്ലേ ചെയ്യാൻ <ph name="URL" /> താൽപ്പര്യപ്പെടുന്നു. നിങ്ങളുടെ ഉപകരണത്തിന്‍റെ ഐഡന്‍റിറ്റി Google പരിശോധിച്ചുറപ്പിക്കും, ഈ സൈറ്റ് ആക്‌സസ് ചെയ്യാനായേക്കാം.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> എന്നിവയും മറ്റൊരു ഭാഷയും</translation>
 <translation id="3909791450649380159">&amp;മുറിക്കുക</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (ഈ ഉപകരണത്തിൽ ഉപയോഗിച്ച പേര്)</translation>
 <translation id="3911824782900911339">പുതിയ ടാബ് പേജ്</translation>
@@ -2072,7 +2070,7 @@
 <translation id="4252899949534773101">Bluetooth പ്രവർത്തനരഹിതമാക്കി</translation>
 <translation id="4252996741873942488"><ph name="WINDOW_TITLE" /> - ടാബ് ഉള്ളടക്കം പങ്കിട്ടു</translation>
 <translation id="4254813446494774748">വിവർത്തന ഭാഷ:</translation>
-<translation id="425573743389990240">ബാറ്ററി ഡിസ്‌ചാർജ്ജ് നിരക്ക് വാട്‌സിൽ (നെഗറ്റീവ് മൂല്യം അർത്ഥമാക്കുന്നത് ബാറ്ററി ചാർജ്ജുചെയ്യുന്നു എന്നാണ്)</translation>
+<translation id="425573743389990240">ബാറ്ററി ഡിസ്‌ചാർജ് നിരക്ക് വാട്‌സിൽ (നെഗറ്റീവ് മൂല്യം അർത്ഥമാക്കുന്നത് ബാറ്ററി ചാർജ് ചെയ്യുന്നു എന്നാണ്)</translation>
 <translation id="4256316378292851214">വീഡിയോ ഇതായി സംരക്ഷി&amp;ക്കുക...</translation>
 <translation id="4258348331913189841">ഫയല്‍ സിസ്റ്റങ്ങൾ</translation>
 <translation id="4263757076580287579">പ്രിന്റർ രജിസ്ട്രേഷൻ റദ്ദാക്കി.</translation>
@@ -2125,7 +2123,6 @@
 <translation id="435527878592612277">നിങ്ങളുടെ ഫോട്ടോ തിരഞ്ഞെടുക്കുക</translation>
 <translation id="4356334633973342967">അല്ലെങ്കിൽ നിങ്ങളുടേത് മാത്രമായ ഡ്രൈവറെ വ്യക്തമാക്കുക:</translation>
 <translation id="4358169392473932247">ആ സുരക്ഷാ കോഡ് ക്രെഡൻഷ്യലുകളിലെ ഉള്ളിലെ മെമ്മറി പിന്തുണയ്‌ക്കുന്നില്ല, എന്നാൽ ആ ഫീച്ചർ അഭ്യർത്ഥിച്ചു.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> എന്നീ ഭാഷകൾ</translation>
 <translation id="4359408040881008151">ആശ്രയിച്ചിരിക്കുന്ന വിപുലീകരണം (വിപുലീകരണങ്ങൾ) കാരണം ഇൻസ്‌റ്റാളുചെയ്തു.</translation>
 <translation id="4359717112757026264">സിറ്റി‌സ്‌കേപ്പ്</translation>
 <translation id="4361142739114356624">ഈ ക്ലയന്റ് സർട്ടിഫിക്കറ്റിന്റെ സ്വകാര്യ കീ നഷ്‌ടമായി അല്ലെങ്കിൽ അസാധുവാണ്</translation>
@@ -2177,7 +2174,6 @@
 <translation id="443475966875174318">അനുയോജ്യതയില്ലാത്ത അപ്ലിക്കേഷനുകൾ അപ്‌ഡേറ്റ് ചെയ്യുക അല്ലെങ്കിൽ നീക്കം ചെയ്യുക</translation>
 <translation id="4441124369922430666">മെഷീൻ ഓണാകുമ്പോൾ ഈ അപ്ലിക്കേഷൻ സ്വയമേവ ആരംഭിക്കാൻ നിങ്ങൾക്ക് താൽപ്പര്യമുണ്ടോ?</translation>
 <translation id="444134486829715816">വികസിപ്പിക്കുക...</translation>
-<translation id="4441548209689510310">അക്ഷരത്തെറ്റ് പരിശോധന ഓപ്‌ഷനുകൾ കാണിക്കുക</translation>
 <translation id="4442424173763614572">DNS തിരയൽ പരാജയപ്പെട്ടു</translation>
 <translation id="4443536555189480885">&amp;സഹായം</translation>
 <translation id="4444304522807523469">USB വഴിയോ പ്രാദേശിക നെറ്റ്‌വർക്കിലോ അറ്റാച്ചുചെയ്‌ത പ്രമാണ സ്‌കാനറുകൾ ആക്‌സസ്സുചെയ്യുക</translation>
@@ -2974,7 +2970,6 @@
 <translation id="5736796278325406685">ശരിയായ ഉപയോക്തൃനാമം നൽകുക</translation>
 <translation id="5739235828260127894">പരിശോധിച്ചുറപ്പിക്കാൻ കാത്തിരിക്കുന്നു. <ph name="LINK_BEGIN" />കൂടുതലറിയുക<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">വളരെ വലുത്</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> എന്നിവയും മറ്റ് <ph name="NUM_ADDITIONAL_LANGUAGES" /> ഭാഷകളും</translation>
 <translation id="574209121243317957">പിച്ച്</translation>
 <translation id="5746169159649715125">PDF ആയി സംരക്ഷിക്കുക</translation>
 <translation id="5747552184818312860">കാലഹരണപ്പെടുന്നു</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb
index 1ea174b2..6bb42dda 100644
--- a/chrome/app/resources/generated_resources_mr.xtb
+++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" आपल्या <ph name="CODE_TYPE" /> ची विनंती करीत आहे</translation>
 <translation id="3435738964857648380">सुरक्षितता</translation>
 <translation id="3435896845095436175">सक्षम करा</translation>
-<translation id="3436038974659740746">सानुकूल शब्दलेखन</translation>
 <translation id="3438633801274389918">निन्जा</translation>
 <translation id="3439153939049640737">आपल्या मायक्रोफोनवर प्रवेश करण्यासाठी <ph name="HOST" /> ला नेहमी अनुमती द्या</translation>
 <translation id="3439970425423980614">पूर्वावलोकनात पीडीएफ उघडत आहे</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> कालबाह्य आहे</translation>
 <translation id="3908501907586732282">विस्तार सक्षम करा</translation>
 <translation id="3909477809443608991"><ph name="URL" /> ला संरक्षित आशय प्ले करायचा आहे. तुमच्या डिव्हाइसच्या ओळखीची Google कडून पडताळणी केली जाईल आणि कदाचित या साइटकडून अ‍ॅक्सेस केली जाईल.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> आणि अन्य 1</translation>
 <translation id="3909791450649380159">क&amp;ट करा</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (या डिव्हाइसवर वापरलेले नाव)</translation>
 <translation id="3911824782900911339">नवीन टॅब पृष्‍ठ</translation>
@@ -2128,7 +2126,6 @@
 <translation id="435527878592612277">तुमचा फोटो निवडा</translation>
 <translation id="4356334633973342967">किंवा आपल्या स्वत:चा ड्राइव्हर नमूद करा:</translation>
 <translation id="4358169392473932247">ती सिक्युरिटी की क्रेडेंशियलच्या अंतर्गत स्टोरेजला सपोर्ट करत नाही, परंतु त्या वैशिष्ट्याची विनंती केली गेली होती.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">अवलंबून असलेल्या विस्तारा(रां) मुळे इंस्टॉल केले.</translation>
 <translation id="4359717112757026264">शहराचे दृश्य</translation>
 <translation id="4361142739114356624">या क्लायंट प्रमाणपत्रासाठी खाजगी, की अनुपलब्ध किंवा अवैध आहे</translation>
@@ -2180,7 +2177,6 @@
 <translation id="443475966875174318">कंपॅटिबल नसलेली अॅप्लिकेशन अपडेट करा किंवा काढून टाका</translation>
 <translation id="4441124369922430666">मशीन चालू होते तेव्हा तुम्ही हा ॲप स्वयंचलितपणे प्रारंभ करू इच्छिता?</translation>
 <translation id="444134486829715816">विस्तृत करा...</translation>
-<translation id="4441548209689510310">शब्दलेखन तपासणी पर्याय दर्शवा</translation>
 <translation id="4442424173763614572">DNS लुकअप अयश्सवी</translation>
 <translation id="4443536555189480885">&amp;मदत</translation>
 <translation id="4444304522807523469">USB द्वारा संलग्न केलेल्या किंवा स्थानिक नेटवर्कवरील दस्तऐवज स्कॅनरवर प्रवेश करा</translation>
@@ -2976,7 +2972,6 @@
 <translation id="5736796278325406685">कृपया एक वैध वापरकर्तानाव एंटर करा</translation>
 <translation id="5739235828260127894">पडताळणीसाठी वाट पाहत आहे. <ph name="LINK_BEGIN" />अधिक जाणून घ्या.<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">खूप मोठा</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> आणि अन्य <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">पिच</translation>
 <translation id="5746169159649715125">PDF म्हणून सेव्ह करा</translation>
 <translation id="5747552184818312860">कालबाह्य होईल</translation>
diff --git a/chrome/app/resources/generated_resources_ms.xtb b/chrome/app/resources/generated_resources_ms.xtb
index 088ca8e..6655e84 100644
--- a/chrome/app/resources/generated_resources_ms.xtb
+++ b/chrome/app/resources/generated_resources_ms.xtb
@@ -1535,7 +1535,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" meminta <ph name="CODE_TYPE" /> anda</translation>
 <translation id="3435738964857648380">Keselamatan</translation>
 <translation id="3435896845095436175">Dayakan</translation>
-<translation id="3436038974659740746">Ejaan tersuai</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Sentiasa benarkan <ph name="HOST" /> mengakses mikrofon anda</translation>
 <translation id="3439970425423980614">Membuka PDF dalam Pratonton</translation>
@@ -1865,7 +1864,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> sudah lapuk</translation>
 <translation id="3908501907586732282">Dayakan sambungan</translation>
 <translation id="3909477809443608991"><ph name="URL" /> mahu memainkan kandungan yang dilindungi. Identiti peranti anda akan disahkan oleh Google dan mungkin diakses oleh tapak ini.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> dan 1 yang lain</translation>
 <translation id="3909791450649380159">Po&amp;tong</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nama yang digunakan pada peranti ini)</translation>
 <translation id="3911824782900911339">Halaman Tab Baharu</translation>
@@ -2130,7 +2128,6 @@
 <translation id="435527878592612277">Pilih foto anda</translation>
 <translation id="4356334633973342967">Atau, tentukan pemacu anda sendiri:</translation>
 <translation id="4358169392473932247">Kunci keselamatan itu tidak menyokong penyimpanan dalaman bukti kelayakan, tetapi ciri itu diminta.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Dipasang kerana sambungan yang bergantung.</translation>
 <translation id="4359717112757026264">Pandangan bandar</translation>
 <translation id="4361142739114356624">Kunci Peribadi untuk Sijil Pelanggan ini tiada atau tidak sah</translation>
@@ -2182,7 +2179,6 @@
 <translation id="443475966875174318">Kemas kini atau alih keluar aplikasi yang tidak serasi</translation>
 <translation id="4441124369922430666">Adakah anda ingin mulakan apl ini secara automatik apabila mesin ini dihidupkan?</translation>
 <translation id="444134486829715816">Kembangkan...</translation>
-<translation id="4441548209689510310">Tunjukkan pilihan semak ejaan</translation>
 <translation id="4442424173763614572">Carian DNS gagal</translation>
 <translation id="4443536555189480885">&amp;Bantuan</translation>
 <translation id="4444304522807523469">Akses pengimbas dokumen yang disambungkan melalui USB atau pada rangkaian tempatan</translation>
@@ -2978,7 +2974,6 @@
 <translation id="5736796278325406685">Sila masukkan nama pengguna yang sah</translation>
 <translation id="5739235828260127894">Menunggu pengesahan. <ph name="LINK_BEGIN" />Ketahui lebih lanjut<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Sangat besar</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> dan <ph name="NUM_ADDITIONAL_LANGUAGES" /> yang lain</translation>
 <translation id="574209121243317957">Nada</translation>
 <translation id="5746169159649715125">Simpan sebagai PDF</translation>
 <translation id="5747552184818312860">Tamat tempoh</translation>
diff --git a/chrome/app/resources/generated_resources_nl.xtb b/chrome/app/resources/generated_resources_nl.xtb
index 67bc38a..b0d9395 100644
--- a/chrome/app/resources/generated_resources_nl.xtb
+++ b/chrome/app/resources/generated_resources_nl.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344"><ph name="EXTENSION_NAME" /> vraagt om je <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Beveiliging</translation>
 <translation id="3435896845095436175">Inschakelen</translation>
-<translation id="3436038974659740746">Aangepaste spelling</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737"><ph name="HOST" /> altijd toegang tot je microfoon geven</translation>
 <translation id="3439970425423980614">Pdf openen in voorbeeldweergave</translation>
@@ -1851,7 +1850,7 @@
 <translation id="3892414795099177503">OpenVPN/L2TP toevoegen...</translation>
 <translation id="3893536212201235195">Je toegankelijkheidsinstellingen lezen en wijzigen</translation>
 <translation id="3893630138897523026">ChromeVox (gesproken feedback)</translation>
-<translation id="3894123633473837029">Neem recente Assistent-geschiedenis op via Sherlog. Deze geschiedenis kan je identiteit, locatie en foutopsporingsinformatie omvatten. <ph name="BEGIN_LINK" />Meer informatie<ph name="END_LINK" /></translation>
+<translation id="3894123633473837029">Ook de recente Assistent-geschiedenis opnemen via Sherlog. Deze geschiedenis kan je identiteit, locatie en foutopsporingsinformatie omvatten. <ph name="BEGIN_LINK" />Meer informatie<ph name="END_LINK" /></translation>
 <translation id="3894427358181296146">Map toevoegen</translation>
 <translation id="389589731200570180">Delen met gasten</translation>
 <translation id="3898521660513055167">Status van token</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> is verouderd</translation>
 <translation id="3908501907586732282">Extensie inschakelen</translation>
 <translation id="3909477809443608991"><ph name="URL" /> wil beschermde content afspelen. De identiteit van je apparaat wordt geverifieerd door Google en is mogelijk toegankelijk voor deze site.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> en 1 andere</translation>
 <translation id="3909791450649380159">&amp;Knippen</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (de op dit apparaat gebruikte naam)</translation>
 <translation id="3911824782900911339">Pagina 'Nieuw tabblad'</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Selecteer je foto</translation>
 <translation id="4356334633973342967">Of geef je eigen stuurprogramma op:</translation>
 <translation id="4358169392473932247">De interne opslag van inloggegevens wordt niet ondersteund door deze beveiligingssleutel, maar hier is wel om gevraagd.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Geïnstalleerd vanwege afhankelijke extensie(s).</translation>
 <translation id="4359717112757026264">Stadsgezicht</translation>
 <translation id="4361142739114356624">De privésleutel voor dit clientcertificaat ontbreekt of is ongeldig</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Ongeschikte apps updaten en verwijderen</translation>
 <translation id="4441124369922430666">Wil je dat deze app automatisch start wanneer het apparaat wordt ingeschakeld?</translation>
 <translation id="444134486829715816">Uitvouwen...</translation>
-<translation id="4441548209689510310">Opties voor spellingcontrole weergeven</translation>
 <translation id="4442424173763614572">DNS-lookup mislukt</translation>
 <translation id="4443536555189480885">&amp;Help</translation>
 <translation id="4444304522807523469">Toegang tot documentscanners die zijn aangesloten via USB of die zich op het lokale netwerk bevinden</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">Geef een geldige gebruikersnaam op</translation>
 <translation id="5739235828260127894">Wachten op verificatie. <ph name="LINK_BEGIN" />Meer informatie.<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Zeer groot</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> en <ph name="NUM_ADDITIONAL_LANGUAGES" /> andere</translation>
 <translation id="574209121243317957">Toonhoogte</translation>
 <translation id="5746169159649715125">Opslaan als pdf</translation>
 <translation id="5747552184818312860">Verloopt</translation>
diff --git a/chrome/app/resources/generated_resources_no.xtb b/chrome/app/resources/generated_resources_no.xtb
index 51a1e3f..f41cbdb 100644
--- a/chrome/app/resources/generated_resources_no.xtb
+++ b/chrome/app/resources/generated_resources_no.xtb
@@ -907,7 +907,7 @@
 <translation id="2435457462613246316">Vis passord</translation>
 <translation id="2436186046335138073">Vil du la <ph name="HANDLER_HOSTNAME" /> åpne alle <ph name="PROTOCOL" />-linker?</translation>
 <translation id="2436707352762155834">Minimum</translation>
-<translation id="2439545803278355377">Skriv inn den nye PIN-koden din. En PIN-kode må ha minst fire tegn og kan bestå av bokstaver, tall og andre tegn.</translation>
+<translation id="2439545803278355377">Skriv inn den nye PIN-koden. En PIN-kode må ha minst fire tegn og kan bestå av bokstaver, tall og andre tegn.</translation>
 <translation id="2440604414813129000">Vis &amp;kilde</translation>
 <translation id="2442182690962765671">Siden svarer ikke. Du kan vente, eller du kan ta av VR-brillene.</translation>
 <translation id="2445081178310039857">Det kreves en rotkatalog for utvidelsen</translation>
@@ -1529,7 +1529,6 @@
 <translation id="3435688026795609344">«<ph name="EXTENSION_NAME" />» ber om <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Sikkerhet</translation>
 <translation id="3435896845095436175">Slå på</translation>
-<translation id="3436038974659740746">Egendefinert staving</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Tillat alltid at <ph name="HOST" /> bruker mikrofonen din</translation>
 <translation id="3439970425423980614">Åpner PDF i forhåndsvisning</translation>
@@ -1859,7 +1858,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> er foreldet</translation>
 <translation id="3908501907586732282">Aktiver utvidelsen</translation>
 <translation id="3909477809443608991"><ph name="URL" /> ber om tillatelse til å spille beskyttet innhold. Identiteten til enheten din bekreftes av Google og kan bli gjort tilgjengelig for dette nettstedet.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> og ett til</translation>
 <translation id="3909791450649380159">Klipp u&amp;t</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (navnet som brukes på denne enheten)</translation>
 <translation id="3911824782900911339">Siden Ny fane</translation>
@@ -2122,7 +2120,6 @@
 <translation id="435527878592612277">Velg bilde</translation>
 <translation id="4356334633973342967">Du kan også angi driveren manuelt:</translation>
 <translation id="4358169392473932247">Den sikkerhetsnøkkelen støtter ikke internlagring av legitimasjon, men det er den forespurte funksjonen.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Installert på grunn av avhengige utvidelser.</translation>
 <translation id="4359717112757026264">Bybilde</translation>
 <translation id="4361142739114356624">Privatnøkkelen for dette klientsertifikatet mangler eller er ugyldig</translation>
@@ -2174,7 +2171,6 @@
 <translation id="443475966875174318">Oppdater eller fjern inkompatible programmer</translation>
 <translation id="4441124369922430666">Vil du starte denne appen automatisk når maskinen slås på?</translation>
 <translation id="444134486829715816">Utvid</translation>
-<translation id="4441548209689510310">Vis alternativer for stavekontroll</translation>
 <translation id="4442424173763614572">DNS-søk mislyktes</translation>
 <translation id="4443536555189480885">&amp;Hjelp</translation>
 <translation id="4444304522807523469">Få tilgang til dokumentskannere som er tilkoblet via USB eller på det lokale nettverket</translation>
@@ -2970,7 +2966,6 @@
 <translation id="5736796278325406685">Skriv inn et gyldig brukernavn</translation>
 <translation id="5739235828260127894">Venter på bekreftelse. <ph name="LINK_BEGIN" />Finn ut mer<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Veldig stor</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> og <ph name="NUM_ADDITIONAL_LANGUAGES" /> til</translation>
 <translation id="574209121243317957">Stemmeleie</translation>
 <translation id="5746169159649715125">Lagre som PDF</translation>
 <translation id="5747552184818312860">Utløper</translation>
@@ -3809,7 +3804,7 @@
 <translation id="7063129466199351735">Behandler snarveier …</translation>
 <translation id="7063311912041006059">Nettadresse med <ph name="SPECIAL_SYMBOL" /> i stedet for søket</translation>
 <translation id="7063957500469387217">Konfigurer eller administrer skrivere i Google Cloud Print.</translation>
-<translation id="7064482796689484940">Den sikkerhetsnøkkelen støtter ikke noen former for personlig identifisering (f.eks. en fingeravtrykkssensor eller PIN-kode), men det er den forespurte funksjonen.</translation>
+<translation id="7064482796689484940">Den sikkerhetsnøkkelen støtter ikke noen former for personlig identifisering (f.eks. fingeravtrykkssensor eller PIN-kode), men det er den forespurte funksjonen.</translation>
 <translation id="7065223852455347715">Denne enheten er låst i en modus som forhindrer bedriftsregistrering. Hvis du vil registrere enheten, må du du gjenopprette enheten først.</translation>
 <translation id="7065534935986314333">Om systemet</translation>
 <translation id="706626672220389329">Feil ved aktivering av deling. Den spesifiserte delingen er allerede aktivert.</translation>
diff --git a/chrome/app/resources/generated_resources_pl.xtb b/chrome/app/resources/generated_resources_pl.xtb
index 1e8f62b..387ace2 100644
--- a/chrome/app/resources/generated_resources_pl.xtb
+++ b/chrome/app/resources/generated_resources_pl.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344"><ph name="EXTENSION_NAME" /> żąda kodu <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Bezpieczeństwo</translation>
 <translation id="3435896845095436175">Włącz</translation>
-<translation id="3436038974659740746">Niestandardowe sprawdzanie pisowni</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Zawsze zezwalaj witrynie <ph name="HOST" /> na dostęp do mikrofonu</translation>
 <translation id="3439970425423980614">Otwieranie podglądu PDF</translation>
@@ -1851,7 +1850,7 @@
 <translation id="3892414795099177503">Dodaj OpenVPN/L2TP…</translation>
 <translation id="3893536212201235195">Odczytywanie i zmiana ustawień ułatwień dostępu</translation>
 <translation id="3893630138897523026">ChromeVox (potwierdzenia głosowe)</translation>
-<translation id="3894123633473837029">Uwzględnij ostatnią historię Asystenta w Sherlog. Może ona obejmować Twoją tożsamość, lokalizację i dane debugowania. <ph name="BEGIN_LINK" />Więcej informacji<ph name="END_LINK" /></translation>
+<translation id="3894123633473837029">Uwzględnij ostatnią historię Asystenta w Sherlog. Może ona obejmować informacje na temat Twojej tożsamości i lokalizacji oraz dane debugowania. <ph name="BEGIN_LINK" />Więcej informacji<ph name="END_LINK" /></translation>
 <translation id="3894427358181296146">Dodaj folder</translation>
 <translation id="389589731200570180">Udostępnij gościom</translation>
 <translation id="3898521660513055167">Stan tokena</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">Wtyczka <ph name="PLUGIN_NAME" /> jest nieaktualna</translation>
 <translation id="3908501907586732282">Włącz rozszerzenie</translation>
 <translation id="3909477809443608991"><ph name="URL" /> chce odtworzyć treść chronioną. Tożsamość Twojego urządzenia zostanie sprawdzona przez Google i może być dostępna dla tej strony.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> i 1 inny</translation>
 <translation id="3909791450649380159">Wy&amp;tnij</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nazwa używana na tym urządzeniu)</translation>
 <translation id="3911824782900911339">Strona „Nowa karta”</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Wybierz swoje zdjęcie</translation>
 <translation id="4356334633973342967">Możesz też wybrać własny sterownik:</translation>
 <translation id="4358169392473932247">Ten klucz bezpieczeństwa nie obsługuje żądanej funkcji przechowywania danych logowania w pamięci wewnętrznej.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Zainstalowane ponieważ jest wymagane przez inne rozszerzenia.</translation>
 <translation id="4359717112757026264">Pejzaż miejski</translation>
 <translation id="4361142739114356624">Klucz prywatny tego certyfikatu klienta jest nieprawidłowy lub nie istnieje</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Zaktualizuj lub usuń niezgodne aplikacje</translation>
 <translation id="4441124369922430666">Chcesz, by ta aplikacja była uruchamiana automatycznie po włączeniu urządzenia?</translation>
 <translation id="444134486829715816">Rozwiń...</translation>
-<translation id="4441548209689510310">Pokaż opcje sprawdzania pisowni</translation>
 <translation id="4442424173763614572">Wyszukiwanie DNS nie powiodło się.</translation>
 <translation id="4443536555189480885">&amp;Pomoc</translation>
 <translation id="4444304522807523469">Dostęp do skanerów podłączonych przez USB lub do sieci lokalnej</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">Wpisz prawidłową nazwę użytkownika</translation>
 <translation id="5739235828260127894">Czekam na weryfikację. <ph name="LINK_BEGIN" />Więcej informacji<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Bardzo duża</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> i jeszcze <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Ton</translation>
 <translation id="5746169159649715125">Zapisz jako PDF</translation>
 <translation id="5747552184818312860">Wygasa</translation>
diff --git a/chrome/app/resources/generated_resources_pt-BR.xtb b/chrome/app/resources/generated_resources_pt-BR.xtb
index ccfe5531..56618815 100644
--- a/chrome/app/resources/generated_resources_pt-BR.xtb
+++ b/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">A extensão "<ph name="EXTENSION_NAME" />" está solicitando seu <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Segurança</translation>
 <translation id="3435896845095436175">Ativar</translation>
-<translation id="3436038974659740746">Personalizar ortografia</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Sempre permitir que <ph name="HOST" /> acesse seu microfone</translation>
 <translation id="3439970425423980614">Abrindo visualização do PDF</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">O plug-in <ph name="PLUGIN_NAME" /> está desatualizado</translation>
 <translation id="3908501907586732282">Ativar extensão</translation>
 <translation id="3909477809443608991">Solicitação para reproduzir conteúdo protegido feita por <ph name="URL" />. A identidade do seu dispositivo será verificada pelo Google e poderá ser acessada por esse site.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> e mais 1 idioma</translation>
 <translation id="3909791450649380159">&amp;Recortar</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nome usado neste dispositivo)</translation>
 <translation id="3911824782900911339">Página Nova guia</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Selecione sua foto</translation>
 <translation id="4356334633973342967">Ou especifique seu próprio driver:</translation>
 <translation id="4358169392473932247">Essa chave de segurança não é compatível com armazenamento interno de credenciais, mas esse recurso foi solicitado.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Instalada devido a extensões dependentes.</translation>
 <translation id="4359717112757026264">Paisagem urbana</translation>
 <translation id="4361142739114356624">A chave particular desse certificado do cliente está ausente ou é inválida</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Atualizar ou remover aplicativos incompatíveis</translation>
 <translation id="4441124369922430666">Quer iniciar automaticamente este aplicativo quando o computador for ligado?</translation>
 <translation id="444134486829715816">Expandir...</translation>
-<translation id="4441548209689510310">Mostrar opções de verificação ortográfica</translation>
 <translation id="4442424173763614572">A busca de DNS falhou</translation>
 <translation id="4443536555189480885">&amp;Ajuda</translation>
 <translation id="4444304522807523469">Acessar scanners de documentos acoplados via USB ou na rede local</translation>
@@ -2978,7 +2974,6 @@
 <translation id="5736796278325406685">Insira um nome de usuário válido</translation>
 <translation id="5739235828260127894">Aguardando verificação. <ph name="LINK_BEGIN" />Saiba mais<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Muito grande</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> e outros <ph name="NUM_ADDITIONAL_LANGUAGES" /> idiomas</translation>
 <translation id="574209121243317957">Tom da fala</translation>
 <translation id="5746169159649715125">Salvar como PDF</translation>
 <translation id="5747552184818312860">Expira em</translation>
diff --git a/chrome/app/resources/generated_resources_pt-PT.xtb b/chrome/app/resources/generated_resources_pt-PT.xtb
index eae8019b..af471583 100644
--- a/chrome/app/resources/generated_resources_pt-PT.xtb
+++ b/chrome/app/resources/generated_resources_pt-PT.xtb
@@ -842,7 +842,7 @@
 <translation id="2318817390901984578">Para utilizar aplicações para Android, carregue e atualize o seu <ph name="DEVICE_TYPE" />.</translation>
 <translation id="2318923050469484167">Sessão no modo de navegação anónima atual (<ph name="EMBEDDING" />)</translation>
 <translation id="2322193970951063277">Cabeçalhos e rodapés</translation>
-<translation id="2322318151094136999">Perguntar quando um site pretender aceder a portas de série (recomendado)</translation>
+<translation id="2322318151094136999">Quando um site pretender aceder a portas de série, perguntar se tem autorização (recomendado)</translation>
 <translation id="2326931316514688470">&amp;Recarregar aplicação</translation>
 <translation id="2327492829706409234">Ativar aplicação</translation>
 <translation id="2329597144923131178">Inicie sessão para aceder aos marcadores, ao histórico, às palavras-passe e a outras definições em todos os dispositivos.</translation>
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" está a solicitar o seu <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Segurança</translation>
 <translation id="3435896845095436175">Ativar</translation>
-<translation id="3436038974659740746">Ortografia personalizada</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Permitir sempre que <ph name="HOST" /> aceda ao seu microfone</translation>
 <translation id="3439970425423980614">A abrir PDF na Pré-visualização</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">O <ph name="PLUGIN_NAME" /> está desatualizado</translation>
 <translation id="3908501907586732282">Ativar extensão</translation>
 <translation id="3909477809443608991"><ph name="URL" /> pretende reproduzir conteúdo protegido. A identidade do seu dispositivo será validada pela Google e este site poderá aceder à mesma.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> e mais 1 idioma</translation>
 <translation id="3909791450649380159">Cor&amp;tar</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (nome utilizado neste dispositivo)</translation>
 <translation id="3911824782900911339">Página Novo separador</translation>
@@ -1978,7 +1976,7 @@
 <translation id="4081242589061676262">Não é possível transmitir o ficheiro.</translation>
 <translation id="4084682180776658562">Marcar</translation>
 <translation id="4084835346725913160">Fechar <ph name="TAB_NAME" /></translation>
-<translation id="4085270836953633510">Perguntar quando um site pretender aceder a portas de série</translation>
+<translation id="4085270836953633510">Quando um site pretender aceder a portas de série, perguntar se tem autorização</translation>
 <translation id="4085298594534903246">O JavaScript foi bloqueado nesta página.</translation>
 <translation id="4087089424473531098">Criou a extensão:
 
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Selecionar a sua foto</translation>
 <translation id="4356334633973342967">Em alternativa, especifique o seu próprio controlador:</translation>
 <translation id="4358169392473932247">Essa chave de segurança não suporta o armazenamento interno de credenciais, mas a funcionalidade foi solicitada.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Instalada devido a extensão(ões) dependente(s).</translation>
 <translation id="4359717112757026264">Paisagens urbanas</translation>
 <translation id="4361142739114356624">A chave privada para este certificado de cliente está em falta ou é inválida</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Atualizar ou remover aplicações incompatíveis</translation>
 <translation id="4441124369922430666">Pretende iniciar automaticamente esta aplicação quando o computador é ligado?</translation>
 <translation id="444134486829715816">Expandir...</translation>
-<translation id="4441548209689510310">Mostrar opções de verificação ortográfica</translation>
 <translation id="4442424173763614572">A procura de DNS falhou</translation>
 <translation id="4443536555189480885">&amp;Ajuda</translation>
 <translation id="4444304522807523469">Aceder a scanners de documentos anexados através de USB ou na rede local</translation>
@@ -2978,7 +2974,6 @@
 <translation id="5736796278325406685">Introduza um nome de utilizador válido</translation>
 <translation id="5739235828260127894">A aguardar a validação. <ph name="LINK_BEGIN" />Saiba mais<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Muito grande</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> e mais <ph name="NUM_ADDITIONAL_LANGUAGES" /> idiomas</translation>
 <translation id="574209121243317957">Tonalidade</translation>
 <translation id="5746169159649715125">Guardar como PDF</translation>
 <translation id="5747552184818312860">Expira</translation>
@@ -4064,7 +4059,7 @@
 <translation id="7442465037756169001">O hardware Hangouts Meet está pronto para ser configurado.</translation>
 <translation id="744341768939279100">Criar um novo perfil</translation>
 <translation id="7444983668544353857">Desactivar <ph name="NETWORKDEVICE" /></translation>
-<translation id="7450761244949417357">A abrir o <ph name="ALTERNATIVE_BROWSER_NAME" /> agora</translation>
+<translation id="7450761244949417357">A abrir no <ph name="ALTERNATIVE_BROWSER_NAME" /> agora</translation>
 <translation id="7453008956351770337">Ao selecionar esta impressora, está a conceder à seguinte extensão a autorização para aceder à sua impressora:</translation>
 <translation id="7456142309650173560">programador</translation>
 <translation id="7456847797759667638">Abrir localização...</translation>
diff --git a/chrome/app/resources/generated_resources_ro.xtb b/chrome/app/resources/generated_resources_ro.xtb
index 5163b868..d02ea3b 100644
--- a/chrome/app/resources/generated_resources_ro.xtb
+++ b/chrome/app/resources/generated_resources_ro.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">„<ph name="EXTENSION_NAME" />” solicită <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Securitate</translation>
 <translation id="3435896845095436175">Activează</translation>
-<translation id="3436038974659740746">Ortografie personalizată</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Permiteți întotdeauna accesul <ph name="HOST" /> la microfonul dvs.</translation>
 <translation id="3439970425423980614">Se deschide PDF în Previzualizare</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">Pluginul <ph name="PLUGIN_NAME" /> este învechit</translation>
 <translation id="3908501907586732282">Activați extensia</translation>
 <translation id="3909477809443608991"><ph name="URL" /> vrea să redea conținut protejat. Identitatea dispozitivului tău va fi verificată de Google și poate fi accesată de acest site.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> și încă una</translation>
 <translation id="3909791450649380159">&amp;Taie</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (numele utilizat pe acest dispozitiv)</translation>
 <translation id="3911824782900911339">Pagina Filă nouă</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Selectează fotografia</translation>
 <translation id="4356334633973342967">Sau specifică ce driver ai:</translation>
 <translation id="4358169392473932247">Acea cheie de securitate nu acceptă stocarea internă a certificatelor, dar funcția a fost solicitată.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Instalată din cauza extensiilor dependente.</translation>
 <translation id="4359717112757026264">Cityscape</translation>
 <translation id="4361142739114356624">Cheia privată pentru acest Certificat de client lipsește sau nu este validă</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Actualizează sau elimină aplicațiile incompatibile</translation>
 <translation id="4441124369922430666">Doriți ca această aplicație să fie lansată automat la pornirea dispozitivului?</translation>
 <translation id="444134486829715816">Extinde...</translation>
-<translation id="4441548209689510310">Afișează opțiunile pentru verificarea ortografiei</translation>
 <translation id="4442424173763614572">Căutarea DNS nu a reușit</translation>
 <translation id="4443536555189480885">&amp;Ajutor</translation>
 <translation id="4444304522807523469">Accesează scanerele de documente atașate prin USB sau dintr-o rețea locală</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">Introdu un nume de utilizator valid</translation>
 <translation id="5739235828260127894">Se așteaptă confirmarea. <ph name="LINK_BEGIN" />Află mai multe<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Foarte mare</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> și încă <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Tonalitatea</translation>
 <translation id="5746169159649715125">Salvați ca PDF</translation>
 <translation id="5747552184818312860">Expiră</translation>
diff --git a/chrome/app/resources/generated_resources_ru.xtb b/chrome/app/resources/generated_resources_ru.xtb
index d5cb6e9..f2fd6f7 100644
--- a/chrome/app/resources/generated_resources_ru.xtb
+++ b/chrome/app/resources/generated_resources_ru.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">Расширение "<ph name="EXTENSION_NAME" />" запрашивает <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Безопасность</translation>
 <translation id="3435896845095436175">Включить</translation>
-<translation id="3436038974659740746">Пользовательский словарь</translation>
 <translation id="3438633801274389918">Ниндзя</translation>
 <translation id="3439153939049640737">Всегда предоставлять <ph name="HOST" /> доступ к моему микрофону</translation>
 <translation id="3439970425423980614">Открытие PDF для просмотра</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">Плагин <ph name="PLUGIN_NAME" /> устарел</translation>
 <translation id="3908501907586732282">Включить расширение</translation>
 <translation id="3909477809443608991">Сайт <ph name="URL" /> собирается воспроизвести защищенный контент. Ваше устройство пройдет проверку в Google, и этот сайт сможет получать к нему доступ.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> и ещё 1 язык</translation>
 <translation id="3909791450649380159">Выре&amp;зать</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (имя используется на этом устройстве)</translation>
 <translation id="3911824782900911339">Страница быстрого доступа</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Выберите фото</translation>
 <translation id="4356334633973342967">Или укажите другой драйвер:</translation>
 <translation id="4358169392473932247">Этот электронный ключ не поддерживает хранение учетных данных, но функция была запрошена.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Установлено, так как есть зависимые расширения.</translation>
 <translation id="4359717112757026264">Городской пейзаж</translation>
 <translation id="4361142739114356624">Закрытый ключ для клиентского сертификата отсутствует или недействителен</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Обновление или удаление несовместимых приложений</translation>
 <translation id="4441124369922430666">Автоматически запускать это приложение при включении устройства?</translation>
 <translation id="444134486829715816">Развернуть...</translation>
-<translation id="4441548209689510310">Показать настройки проверки правописания</translation>
 <translation id="4442424173763614572">Произошла ошибка при поиске сервера DNS</translation>
 <translation id="4443536555189480885">&amp;Справка</translation>
 <translation id="4444304522807523469">Доступ к сканерам, подключенным через USB-порт или локальную сеть</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">Введите действительное имя пользователя</translation>
 <translation id="5739235828260127894">Требуется подтверждение. <ph name="LINK_BEGIN" />Подробнее…<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Очень крупный</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, а также другие языки (<ph name="NUM_ADDITIONAL_LANGUAGES" />)</translation>
 <translation id="574209121243317957">Высота звука</translation>
 <translation id="5746169159649715125">Сохранить как PDF</translation>
 <translation id="5747552184818312860">Срок действия</translation>
diff --git a/chrome/app/resources/generated_resources_sk.xtb b/chrome/app/resources/generated_resources_sk.xtb
index 9817b7e..1e0e9d2bc 100644
--- a/chrome/app/resources/generated_resources_sk.xtb
+++ b/chrome/app/resources/generated_resources_sk.xtb
@@ -1532,7 +1532,6 @@
 <translation id="3435688026795609344">Rozšírenie <ph name="EXTENSION_NAME" /> požaduje <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Bezpečnosť</translation>
 <translation id="3435896845095436175">Aktivovať</translation>
-<translation id="3436038974659740746">Vlastný pravopis</translation>
 <translation id="3438633801274389918">Nindža</translation>
 <translation id="3439153939049640737">Vždy povoliť stránkam <ph name="HOST" /> prístup k mikrofónu</translation>
 <translation id="3439970425423980614">Prebieha otváranie súboru PDF v aplikácii Preview</translation>
@@ -1862,7 +1861,6 @@
 <translation id="3908393983276948098">Doplnok <ph name="PLUGIN_NAME" /> je zastaraný</translation>
 <translation id="3908501907586732282">Povoliť rozšírenie</translation>
 <translation id="3909477809443608991"><ph name="URL" /> chce prehrať chránený obsah. Google overí totožnosť vášho zariadenia a tento web k nej môže získať prístup.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> a 1 ďalší</translation>
 <translation id="3909791450649380159">&amp;Vystrihnúť</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (meno používané na tomto zariadení)</translation>
 <translation id="3911824782900911339">Stránka na novej karte</translation>
@@ -2127,7 +2125,6 @@
 <translation id="435527878592612277">Vyberte fotku</translation>
 <translation id="4356334633973342967">Alebo vyberte vlastný ovládač:</translation>
 <translation id="4358169392473932247">Daný bezpečnostný kľúč nepodporuje interné úložisko poverení, ale táto funkcia bola vyžiadaná.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Nainštalované pre závislé rozšírenia.</translation>
 <translation id="4359717112757026264">Mestá</translation>
 <translation id="4361142739114356624">Súkromný kľúč pre tento klientsky certifikát chýba alebo je neplatný</translation>
@@ -2179,7 +2176,6 @@
 <translation id="443475966875174318">Aktualizácia a odstránenie nekompatibilných aplikácií</translation>
 <translation id="4441124369922430666">Chcete automaticky spustiť túto aplikáciu po zapnutí zariadenia?</translation>
 <translation id="444134486829715816">Rozbaliť...</translation>
-<translation id="4441548209689510310">Zobraziť možnosti kontroly pravopisu</translation>
 <translation id="4442424173763614572">Vyhľadanie DNS zlyhalo</translation>
 <translation id="4443536555189480885">&amp;Pomocník</translation>
 <translation id="4444304522807523469">Mať prístup ku skenerom dokumentov pripojeným cez USB alebo v miestnej sieti</translation>
@@ -2975,7 +2971,6 @@
 <translation id="5736796278325406685">Zadajte platné používateľské meno</translation>
 <translation id="5739235828260127894">Čaká sa na overenie. <ph name="LINK_BEGIN" />Ďalšie informácie<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Veľmi veľké</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> a ďalšie (<ph name="NUM_ADDITIONAL_LANGUAGES" />)</translation>
 <translation id="574209121243317957">Výška hlasu</translation>
 <translation id="5746169159649715125">Uložiť ako PDF</translation>
 <translation id="5747552184818312860">Koniec platnosti</translation>
diff --git a/chrome/app/resources/generated_resources_sl.xtb b/chrome/app/resources/generated_resources_sl.xtb
index 8066e1b..f58713a9 100644
--- a/chrome/app/resources/generated_resources_sl.xtb
+++ b/chrome/app/resources/generated_resources_sl.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">Razširitev »<ph name="EXTENSION_NAME" />« zahteva to: <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Varnost</translation>
 <translation id="3435896845095436175">Omogoči</translation>
-<translation id="3436038974659740746">Preverjanje črkovanja po meri</translation>
 <translation id="3438633801274389918">Nindža</translation>
 <translation id="3439153939049640737">Vedno dovoli gostitelju <ph name="HOST" /> dostop do mikrofona</translation>
 <translation id="3439970425423980614">Odpiranje PDF-ja v predogledu</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">Vtičnik <ph name="PLUGIN_NAME" /> je zastarel.</translation>
 <translation id="3908501907586732282">Omogoči razširitev</translation>
 <translation id="3909477809443608991"><ph name="URL" /> želi predvajati zaščiteno vsebino. Google bo preveril identiteto naprave in do nje bo morda dostopalo to spletno mesto.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> in še en jezik</translation>
 <translation id="3909791450649380159">Izrež&amp;i</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (ime, ki se uporablja v tej napravi)</translation>
 <translation id="3911824782900911339">Nov zavihek s povezavami</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Izberite fotografijo</translation>
 <translation id="4356334633973342967">Ali navedite svoj gonilnik:</translation>
 <translation id="4358169392473932247">Ta varnostni ključ ne podpira notranje shrambe poverilnic, vendar je bila ta funkcija zahtevana.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Nameščeno zaradi odvisnih razširitev.</translation>
 <translation id="4359717112757026264">Urbana pokrajina</translation>
 <translation id="4361142739114356624">Zasebni ključ za to potrdilo odjemalca manjka ali je neveljaven</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Posodabljanje ali odstranjevanje nezdružljivih aplikacij</translation>
 <translation id="4441124369922430666">Ali želite samodejno zagnati to aplikacijo, ko se naprava vklopi?</translation>
 <translation id="444134486829715816">Razširi ...</translation>
-<translation id="4441548209689510310">Pokaži možnosti preverjanja črkovanja</translation>
 <translation id="4442424173763614572">Iskanje DNS ni uspelo</translation>
 <translation id="4443536555189480885">&amp;Pomoč</translation>
 <translation id="4444304522807523469">Dostop do optičnih bralnikov, priklopljenih prek USB-ja ali povezanih v lokalno omrežje.</translation>
@@ -2979,7 +2975,6 @@
 <translation id="5736796278325406685">Vnesite veljavno uporabniško ime</translation>
 <translation id="5739235828260127894">Čakanje na potrditev. <ph name="LINK_BEGIN" />Več o tem<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Zelo velika</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> in toliko drugih jezikov: <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Višina tona</translation>
 <translation id="5746169159649715125">Shrani kot PDF</translation>
 <translation id="5747552184818312860">Poteče</translation>
diff --git a/chrome/app/resources/generated_resources_sr.xtb b/chrome/app/resources/generated_resources_sr.xtb
index 261502b..2acc152 100644
--- a/chrome/app/resources/generated_resources_sr.xtb
+++ b/chrome/app/resources/generated_resources_sr.xtb
@@ -1530,7 +1530,6 @@
 <translation id="3435688026795609344">„<ph name="EXTENSION_NAME" />“ захтева <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Безбедност</translation>
 <translation id="3435896845095436175">Омогући</translation>
-<translation id="3436038974659740746">Прилагођена провера правописа</translation>
 <translation id="3438633801274389918">Нинџа</translation>
 <translation id="3439153939049640737">Увек дозволи да <ph name="HOST" /> приступа микрофону</translation>
 <translation id="3439970425423980614">Отварање PDF-а у прегледу</translation>
@@ -1860,7 +1859,6 @@
 <translation id="3908393983276948098">Додатна компонента <ph name="PLUGIN_NAME" /> је застарела</translation>
 <translation id="3908501907586732282">Омогући додатак</translation>
 <translation id="3909477809443608991"><ph name="URL" /> жели да пусти заштићени садржај. Google ће потврдити идентитет уређаја и овај сајт ће моћи да му приступа.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> и још 1</translation>
 <translation id="3909791450649380159">Ис&amp;еци</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (име се користи на овом уређају)</translation>
 <translation id="3911824782900911339">Страница Нова картица</translation>
@@ -2125,7 +2123,6 @@
 <translation id="435527878592612277">Изаберите слику</translation>
 <translation id="4356334633973342967">Или наведите свој управљачки програм:</translation>
 <translation id="4358169392473932247">Тај безбедносни кључ не подржава интерно складиштење акредитива, али та функција је захтевана.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Инсталиран је због зависних додатака.</translation>
 <translation id="4359717112757026264">Градски пејзажи</translation>
 <translation id="4361142739114356624">Приватни кључ за овај сертификат клијента недостаје или је неважећи</translation>
@@ -2177,7 +2174,6 @@
 <translation id="443475966875174318">Ажурирајте или уклоните некомпатибилне апликације</translation>
 <translation id="4441124369922430666">Желите ли да се ова апликација покреће аутоматски када укључите уређај?</translation>
 <translation id="444134486829715816">Прошири...</translation>
-<translation id="4441548209689510310">Приказуј опције за проверу правописа</translation>
 <translation id="4442424173763614572">DNS претрага није успела</translation>
 <translation id="4443536555189480885">&amp;Help (Помоћ)</translation>
 <translation id="4444304522807523469">Приступ скенерима за документе прикљученим преко USB-а или на локалној мрежи</translation>
@@ -2975,7 +2971,6 @@
 <translation id="5736796278325406685">Унесите важеће корисничко име</translation>
 <translation id="5739235828260127894">Чека се верификација. <ph name="LINK_BEGIN" />Сазнајте више<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Јако велики</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> и још <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Ниво</translation>
 <translation id="5746169159649715125">Сачувај као PDF</translation>
 <translation id="5747552184818312860">Истиче</translation>
diff --git a/chrome/app/resources/generated_resources_sv.xtb b/chrome/app/resources/generated_resources_sv.xtb
index 31d8529..3b8e5b25 100644
--- a/chrome/app/resources/generated_resources_sv.xtb
+++ b/chrome/app/resources/generated_resources_sv.xtb
@@ -1533,7 +1533,6 @@
 <translation id="3435688026795609344"><ph name="EXTENSION_NAME" /> vill att du anger din <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Säkerhet</translation>
 <translation id="3435896845095436175">Aktivera</translation>
-<translation id="3436038974659740746">Anpassad stavning</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Låt alltid <ph name="HOST" /> använda din mikrofon</translation>
 <translation id="3439970425423980614">Öppnar PDF i förhandsgranskning</translation>
@@ -1863,7 +1862,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> är inaktuellt.</translation>
 <translation id="3908501907586732282">Aktivera tillägg</translation>
 <translation id="3909477809443608991"><ph name="URL" /> vill spela upp skyddat innehåll. Enhetens identitet verifieras av Google och kan öppnas av webbplatsen.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> och ett till</translation>
 <translation id="3909791450649380159">&amp;Klipp ut</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (namn som används på enheten)</translation>
 <translation id="3911824782900911339">Sidan Ny flik</translation>
@@ -2128,7 +2126,6 @@
 <translation id="435527878592612277">Välj foto</translation>
 <translation id="4356334633973342967">Eller ange en egen drivrutin:</translation>
 <translation id="4358169392473932247">Den säkerhetsnyckeln har inte stöd för att spara användaruppgifter internt, men en sådan funktion begärdes.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Installerades på grund av ett eller flera tillägg som är beroende av detta tillägg.</translation>
 <translation id="4359717112757026264">Cityscape</translation>
 <translation id="4361142739114356624">Det här klientcertifikatets privata nyckel saknas eller är tom</translation>
@@ -2180,7 +2177,6 @@
 <translation id="443475966875174318">Uppdatera och ta bort inkompatibla appar</translation>
 <translation id="4441124369922430666">Vill du starta denna app automatiskt när maskinen slås på?</translation>
 <translation id="444134486829715816">Expandera..</translation>
-<translation id="4441548209689510310">Visa alternativ för stavningskontrollen</translation>
 <translation id="4442424173763614572">DNS-sökning misslyckades</translation>
 <translation id="4443536555189480885">&amp;Hjälp</translation>
 <translation id="4444304522807523469">Åtkomst till dokumentskannrar som är anslutna via USB eller i det lokala nätverket</translation>
@@ -2976,7 +2972,6 @@
 <translation id="5736796278325406685">Ange ett giltigt användarnamn</translation>
 <translation id="5739235828260127894">Väntar på verifiering. <ph name="LINK_BEGIN" />Läs mer<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Mycket stor</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> och <ph name="NUM_ADDITIONAL_LANGUAGES" /> till</translation>
 <translation id="574209121243317957">Ton</translation>
 <translation id="5746169159649715125">Spara som PDF</translation>
 <translation id="5747552184818312860">Upphör att gälla</translation>
diff --git a/chrome/app/resources/generated_resources_sw.xtb b/chrome/app/resources/generated_resources_sw.xtb
index fa53454..c53effb 100644
--- a/chrome/app/resources/generated_resources_sw.xtb
+++ b/chrome/app/resources/generated_resources_sw.xtb
@@ -1527,7 +1527,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" kinaomba <ph name="CODE_TYPE" /> yako</translation>
 <translation id="3435738964857648380">Usalama</translation>
 <translation id="3435896845095436175">Washa</translation>
-<translation id="3436038974659740746">Maendelezo maalum</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Ruhusu <ph name="HOST" /> kufikia maikrofoni yako kila wakati</translation>
 <translation id="3439970425423980614">Inafungua PDF katika Kihakiki</translation>
@@ -1857,7 +1856,6 @@
 <translation id="3908393983276948098">Toleo hili la <ph name="PLUGIN_NAME" /> limepitwa na wakati</translation>
 <translation id="3908501907586732282">Washa kiendelezi</translation>
 <translation id="3909477809443608991"><ph name="URL" /> inataka kucheza maudhui yanayolindwa. Utambulisho wa kifaa chako utathibitishwa na Google na kinaweza kufikiwa na tovuti hii.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, na nyingine 1</translation>
 <translation id="3909791450649380159">&amp;Kata</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (jina lilitumiwa kwenye kifaa hiki)</translation>
 <translation id="3911824782900911339">Ukurasa wa Kichupo Kipya</translation>
@@ -2120,7 +2118,6 @@
 <translation id="435527878592612277">Chagua picha yako</translation>
 <translation id="4356334633973342967">Au bainisha kiendeshaji chako mwenyewe:</translation>
 <translation id="4358169392473932247">Ufunguo huo wa usalama hauruhusu kuhifadhi vitambulisho kwenye hifadhi ya ndani, lakini kipengele hicho kimeombwa.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Kilisakinishwa kwa sababu ya kiendelezi au viendelezi vinavyotegemea.</translation>
 <translation id="4359717112757026264">Mandhari ya jiji</translation>
 <translation id="4361142739114356624">Ufunguo wa Faragha wa Cheti hiki cha Seva Teja haupo au si sahihi</translation>
@@ -2172,7 +2169,6 @@
 <translation id="443475966875174318">Sasisha au uondoe programu ambazo hazioani</translation>
 <translation id="4441124369922430666">Je, ungependa kuanzisha programu hii kiotomatiki mashine itakapowashwa?</translation>
 <translation id="444134486829715816">Panua...</translation>
-<translation id="4441548209689510310">Onyesha chaguo za kikagua maendelezo</translation>
 <translation id="4442424173763614572">Mwonekano wa DNS umeshindikana</translation>
 <translation id="4443536555189480885">&amp;Msaada</translation>
 <translation id="4444304522807523469">Fikia vichunguzi vya hati vilivyoambatishwa kupitia USB au kwenye mtandao wa karibu</translation>
@@ -2968,7 +2964,6 @@
 <translation id="5736796278325406685">Tafadhali andika jina sahihi la mtumiaji</translation>
 <translation id="5739235828260127894">Inasubiri uthibitishaji. <ph name="LINK_BEGIN" />Pata maelezo zaidi.<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Kubwa sana</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, na nyingine <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Uzito wa sauti</translation>
 <translation id="5746169159649715125">Hifadhi kama PDF</translation>
 <translation id="5747552184818312860">Muda wake unakwisha</translation>
diff --git a/chrome/app/resources/generated_resources_ta.xtb b/chrome/app/resources/generated_resources_ta.xtb
index da50096..52a14c3 100644
--- a/chrome/app/resources/generated_resources_ta.xtb
+++ b/chrome/app/resources/generated_resources_ta.xtb
@@ -54,6 +54,7 @@
 <ph name="EXTENSION_NAME" /></translation>
 <translation id="1070705170564860382"><ph name="COUNTDOWN_SECONDS" /> நொடிகளில் மாற்று உலாவித் திறக்கப்படும்</translation>
 <translation id="1071917609930274619">தரவு மாற்றம்</translation>
+<translation id="1072700771426194907">USB சாதனம் கண்டறியப்பட்டுள்ளது</translation>
 <translation id="1076698951459398590">தீமினை இயக்கு</translation>
 <translation id="1076818208934827215">Microsoft Internet Explorer</translation>
 <translation id="1079766198702302550">கேமரா அணுகலை எப்போதும் தடு</translation>
@@ -113,6 +114,7 @@
 <translation id="1167199480815330007">உங்கள் பாதுகாப்பு விசையின் பின்புறத்தில் உள்ள 6 இலக்கப் பின்னைக் கண்டறியவும்</translation>
 <translation id="1168020859489941584"><ph name="TIME_REMAINING" /> இல் திறக்கிறது…</translation>
 <translation id="1168100932582989117">Google பெயர் சேவையகங்கள்</translation>
+<translation id="1169909785351611170">தவறான பின்.</translation>
 <translation id="1171135284592304528">விசைப்பலகை ஃபோகஸ் மாறும் போது, ஃபோகஸைக் கொண்டுள்ள பொருளைத்  தனிப்படுத்து.</translation>
 <translation id="1173894706177603556">மறுபெயரிடு</translation>
 <translation id="1174073918202301297">ஷார்ட்கட் சேர்க்கப்பட்டது</translation>
@@ -233,6 +235,7 @@
 <translation id="1361655923249334273">பயன்படுத்தாத</translation>
 <translation id="1361872463926621533">தொடக்கத்தில் ஒலியை இயக்கு</translation>
 <translation id="1364702626840264065">{NUM_TABS,plural, =1{தாவலை மூடுக}other{தாவல்களை மூடுக}}</translation>
+<translation id="1365804713255256726">சாதனத்தை மீட்டமைக்க இயலவில்லை. பிழை <ph name="ERROR_CODE" />.</translation>
 <translation id="1366177842110999534">உங்கள் <ph name="DEVICE_TYPE" /> சாதனத்தில் Linux கருவிகள், எடிட்டர்கள், IDEகள் போன்றவற்றை இயக்கும். &lt;a target="_blank" href="<ph name="URL" />"&gt;மேலும் அறிக&lt;/a&gt;</translation>
 <translation id="1367951781824006909">கோப்பைத் தேர்வுசெய்க</translation>
 <translation id="1371301976177520732">உங்கள் எல்லாச் சாதனங்களிலும் உங்கள் புக்மார்க்குகள், கடவுச்சொற்கள், வரலாறு, மேலும் பலவற்றைப் பெறலாம்</translation>
@@ -490,6 +493,7 @@
 <translation id="1763808908432309942">புதிய தாவலில் திறக்கும்</translation>
 <translation id="1764226536771329714">பீட்டா</translation>
 <translation id="176587472219019965">&amp;புதிய சாளரம்</translation>
+<translation id="1766575458646819543">முழுத்திரையிலிருந்து வெளியேறியது</translation>
 <translation id="1768278914020124551">அச்சச்சோ!  உள்நுழைவுச் சேவையகத்தைத் தொடர்புகொள்வதில் பிழை ஏற்பட்டது. நெட்வொர்க் இணைப்பையும் டொமைன் பெயரையும் சரிபார்த்து, மீண்டும் முயலவும்.</translation>
 <translation id="1769104665586091481">இணைப்பை புதிய &amp;சாளரத்தில் திற</translation>
 <translation id="1773212559869067373">அங்கீகரிப்புச் சான்றிதழ் உள்ளிடையாக நிராகரிக்கப்பட்டது</translation>
@@ -497,6 +501,7 @@
 <translation id="1774833706453699074">திறந்திருக்கும் பக்கங்களைப் புக்மார்க் செய்...</translation>
 <translation id="1776883657531386793"><ph name="OID" />: <ph name="INFO" /></translation>
 <translation id="1779652936965200207">"<ph name="DEVICE_NAME" />" இல் இந்தக் கடவுவிசையை உள்ளிடுக:</translation>
+<translation id="1781291988450150470">தற்போதைய பின்</translation>
 <translation id="1781502536226964113">புதிய தாவல் பக்கத்தைத் திற</translation>
 <translation id="1781771911845953849">கணக்குகளும் ஒத்திசைவும்</translation>
 <translation id="1782196717298160133">ஃபோனைக் கண்டறிகிறது</translation>
@@ -910,6 +915,7 @@
 <translation id="2453021845418314664">மேம்பட்ட ஒத்திசைவு அமைப்புகள்</translation>
 <translation id="2453860139492968684">முடி</translation>
 <translation id="2454247629720664989">திறவுச்சொல்</translation>
+<translation id="2455122176076606103">பின்னைப் பலமுறை தவறாக உள்ளிட்டதால் பாதுகாப்பு விசை பூட்டப்பட்டது. அதை மீட்டமைத்தால் மட்டுமே பின் தொடர்பான செயல்பாடுகளை மேற்கொள்ள இயலும்.</translation>
 <translation id="245661998428026871">பிக்ச்சர்-இன்-பிக்ச்சர் பயன்முறையில் இயக்கப்படும் வீடியோ நிறுத்தப்படும்.</translation>
 <translation id="2457246892030921239"><ph name="APP_NAME" />, <ph name="VOLUME_NAME" /> இலிருந்து கோப்புகளை நகலெடுக்க விரும்புகிறது.</translation>
 <translation id="2458591546854598341">சாதன நிர்வாக டோக்கன் தவறானது.</translation>
@@ -931,6 +937,7 @@
 <translation id="2487067538648443797">புதிய புத்தகக்குறியைச் சேர்</translation>
 <translation id="2489829450872380594">அடுத்த முறை, இந்த <ph name="DEVICE_TYPE" /> சாதனத்தை புதிய ஃபோன் திறக்கும். அமைப்புகளில் Smart Lockகை முடக்கலாம்.</translation>
 <translation id="2489918096470125693">&amp;கோப்புறையைச் சேர்...</translation>
+<translation id="2490575462301446554">பின் அமைக்கப்பட்டது.</translation>
 <translation id="249113932447298600">இந்த நேரத்தில் <ph name="DEVICE_LABEL" /> சாதனத்தை ஆதரிக்க முடியவில்லை. மன்னிக்கவும்.</translation>
 <translation id="249303669840926644">பதிவுசெய்தலை நிறைவுசெய்ய முடியவில்லை</translation>
 <translation id="2495777824269688114">அதிகமான அம்சங்களைப் பற்றி தெரிந்துகொள்ளுங்கள் அல்லது பதில்களைப் பெறுங்கள். உதவிக்கு, “?”ஐத் தேர்ந்தெடுக்கவும்.</translation>
@@ -1068,6 +1075,7 @@
 <translation id="2691385045260836588">மாடல்</translation>
 <translation id="2693176596243495071">அச்சச்சோ! எதிர்பாராத பிழை ஏற்பட்டது. பிறகு முயலவும் அல்லது சிக்கல் தொடர்ந்தால், உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்.</translation>
 <translation id="2695749433451188613">இன்டர்நெட் பிரிண்டிங் புரோட்டோகால் (HTTPS)</translation>
+<translation id="2699911226086014512">பின்னை அமைக்க இயலவில்லை, பிழைக் குறியீடு: <ph name="RETRIES" /></translation>
 <translation id="270358213449696159">Google Chrome OS விதிமுறைகளின் உள்ளடக்கம்</translation>
 <translation id="2704184184447774363">Microsoft Document Signing</translation>
 <translation id="270516211545221798">டச்பேடின் வேகம்</translation>
@@ -1292,7 +1300,7 @@
 <translation id="3045447014237878114">இந்தத் தளம் தானாகவே பல கோப்புகளைப் பதிவிறக்கம் செய்தது</translation>
 <translation id="3046910703532196514">வலைப்பக்கம், முழுமையாக</translation>
 <translation id="304747341537320566">பேச்சு என்ஜின்கள்</translation>
-<translation id="3047644958362961983">அசிஸ்டண்ட்டிலுள்ள சிக்கலைப் புரிந்துகொள்ள இந்தத் தகவல் எங்களுக்கு உதவும். இவை 90 நாட்கள் வரை சேமித்து வைக்கப்படும், சம்பந்தப்பட்ட தொழில்நுட்ப மற்றும் கருத்துக் குழுக்களுக்கு மட்டுமே இதற்கான அணுகல் வழங்கப்படும்.</translation>
+<translation id="3047644958362961983">நீங்கள் எதிர்கொள்ளும் அசிஸ்டண்ட் சிக்கலை நாங்கள் புரிந்து கொள்ள இந்தத் தகவல் உதவும். இவை 90 நாட்கள் வரை சேமித்து வைக்கப்படும், சம்பந்தப்பட்ட தொழில்நுட்ப மற்றும் கருத்துக் குழுக்களுக்கு மட்டுமே இதற்கான அணுகல் வழங்கப்படும்.</translation>
 <translation id="3053013834507634016">சான்றிதழ் விசைப் பயன்பாடு</translation>
 <translation id="3058498974290601450">அமைப்புகளில் ஒத்திசைவை எந்த நேரத்திலும் இயக்கலாம்</translation>
 <translation id="3060379269883947824">பேசும் திரையை இயக்கு</translation>
@@ -1315,6 +1323,7 @@
 <translation id="3085752524577180175">SOCKS ஹோஸ்ட்</translation>
 <translation id="3088325635286126843">&amp;மறுபெயரிடுக...</translation>
 <translation id="3089137131053189723">தேடல் அழிக்கப்பட்டது</translation>
+<translation id="3089732468175192706">{NUM_ATTEMPTS,plural, =1{தவறான பின். இன்னும் ஒரு முறை முயலலாம்.}other{தவறான பின். இன்னும் # முறை முயலலாம்.}}</translation>
 <translation id="3090193911106258841">ஆடியோ மற்றும் வீடியோ உள்ளீட்டை அணுகுகிறது</translation>
 <translation id="3090819949319990166">வெளிப்புற crx கோப்பை <ph name="TEMP_CRX_FILE" />க்கு நகலெடுக்க முடியாது.</translation>
 <translation id="3090871774332213558">"<ph name="DEVICE_NAME" />" இணைக்கப்பட்டது</translation>
@@ -1373,6 +1382,7 @@
 <translation id="3192947282887913208">ஆடியோ கோப்புகள்</translation>
 <translation id="3194737229810486521">உங்கள் சாதனத்தில், தரவை நிரந்தரமாகச் சேமிக்க <ph name="URL" /> விரும்புகிறது</translation>
 <translation id="3199127022143353223">சேவைகங்கள்</translation>
+<translation id="3201422919974259695">கிடைக்கக்கூடிய USB சாதனங்கள் இங்குத் தோன்றும்.</translation>
 <translation id="3202131003361292969">தடம்</translation>
 <translation id="3202173864863109533">இந்தத் தாவலின் ஆடியோ முடக்கப்படுகிறது.</translation>
 <translation id="3208703785962634733">உறுதிசெய்யப்படாதது</translation>
@@ -1393,6 +1403,7 @@
 <translation id="323803881985677942">நீட்டிப்பு விருப்பங்களைத் திற</translation>
 <translation id="3241680850019875542">தொகுக்க வேண்டிய நீட்டிப்பின் மூல இருப்பிடத்தைத் தேர்ந்தெடு. ஒரு நீட்டிப்பைப் புதுப்பிக்க, மீண்டும் பயன்படுத்துவதற்கு தனிப்பட்ட விசைக் கோப்பையும் தேர்ந்தெடு.</translation>
 <translation id="3244294424315804309">தொடர்ந்து ஒலியடக்கு</translation>
+<translation id="3246263372552241767">பாதுகாப்பு விசை அகற்றப்பட்டுள்ளது.</translation>
 <translation id="324849028894344899"><ph name="WINDOW_TITLE" /> - நெட்வொர்க் பிழை</translation>
 <translation id="3249950116250264636"><ph name="APP_NAME" /> (<ph name="APP_URL" />)</translation>
 <translation id="3251759466064201842">&lt;சான்றிதழின் பகுதியல்ல&gt;</translation>
@@ -1511,7 +1522,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" உங்கள் <ph name="CODE_TYPE" />ஐக் கோருகிறது</translation>
 <translation id="3435738964857648380">பாதுகாப்பு</translation>
 <translation id="3435896845095436175">இயக்கு</translation>
-<translation id="3436038974659740746">தனிப்பயன் சொற்கள்</translation>
 <translation id="3438633801274389918">நிஞ்சா</translation>
 <translation id="3439153939049640737">உங்கள் மைக்ரோஃபோனை எப்போதும் அணுக <ph name="HOST" /> அனுமதிக்கவும்</translation>
 <translation id="3439970425423980614">PDF ஐ மாதிரிக்காட்யில் திறக்கிறது</translation>
@@ -1617,6 +1627,7 @@
 <translation id="3593965109698325041">சான்றிதழ் பெயர் கட்டுப்பாடுகள்</translation>
 <translation id="3596235046596950091">கிளவுட் சேவைகளை இயக்கு</translation>
 <translation id="3599863153486145794">உள்நுழைந்த எல்லாச் சாதனங்களிலிருந்தும் வரலாற்றை அழிக்கும். உங்கள் Google கணக்கு, <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> என்ற இணைப்பில் உலாவல் வரலாறு தொடர்பான பிற தகவல்களைக் கொண்டிருக்கக்கூடும்.</translation>
+<translation id="3600051066689725006">இணையக் கோரிக்கைத் தகவல்</translation>
 <translation id="3600792891314830896">ஒலியை இயக்கும் தளங்களில் ஒலியடக்கு</translation>
 <translation id="360180734785106144">புதிய அம்சங்கள் கிடைக்கும்போது அவற்றை வழங்கும்</translation>
 <translation id="3602290021589620013">மாதிரிக்காட்சி</translation>
@@ -1830,13 +1841,13 @@
 <translation id="3898521660513055167">டோக்கன் நிலை</translation>
 <translation id="389901847090970821">விசைப்பலகையைத் தேர்ந்தெடுக்கவும்</translation>
 <translation id="3899879303189199559">ஒரு வருடத்திற்கும் மேலாக ஆஃப்லைனில் உள்ளது</translation>
+<translation id="3900105072479897941">மீட்டமைத்தல் அனுமதிக்கப்படவில்லை. சில பாதுகாப்பு விசைகளைச் செருகிய சில வினாடிகளுக்குள்ளேயே மீட்டமைக்க வேண்டும், எனவே மீண்டும் முயலும்போது விரைந்து செயல்படவும்.</translation>
 <translation id="3900966090527141178">கடவுச்சொற்களை ஏற்று</translation>
 <translation id="3901991538546252627"><ph name="NAME" /> க்கு இணைக்கிறது</translation>
 <translation id="3905761538810670789">பயன்பாட்டை பழுதுநீக்கு</translation>
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> காலாவதியாகிவிட்டது</translation>
 <translation id="3908501907586732282">நீட்டிப்பை இயக்கு</translation>
 <translation id="3909477809443608991">பாதுகாக்கப்பட்ட உள்ளடக்கத்தை <ph name="URL" /> இயக்க விரும்புகிறது. உங்கள் சாதனத்தின் அடையாளத்தை Google சரிபார்க்கும், சாதன அடையாளத்தை இந்தத் தளம் அணுகக்கூடும்.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, மேலும் 1 மொழி</translation>
 <translation id="3909791450649380159">வெட்&amp;டு</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (இந்தச் சாதனத்தில் பயன்படுத்தப்படும் பெயர்)</translation>
 <translation id="3911824782900911339">புதிய தாவல் பக்கம்</translation>
@@ -1891,6 +1902,7 @@
 <translation id="3981760180856053153">செல்லாத சேமிப்பு வகை உள்ளிடப்பட்டது.</translation>
 <translation id="3982375475032951137">உங்கள் உலாவியை ஒரு சில எளிய படிகளில் அமைக்கலாம்</translation>
 <translation id="3983400541576569538">சில ஆப்ஸின் தரவு அழிக்கப்படலாம்</translation>
+<translation id="3983503144326094739">பின்னைப் பலமுறை தவறாக உள்ளிட்டதால் பாதுகாப்பு விசை தற்காலிகமாகப் பூட்டப்பட்டது. திறப்பதற்கு அதை அகற்றி மீண்டும் செருகவும்.</translation>
 <translation id="3983586614702900908">அறியப்படாத விற்பனையாளரிடமிருந்து சாதனங்கள்</translation>
 <translation id="3984159763196946143">டெமோ பயன்முறையைத் தொடங்க முடியவில்லை</translation>
 <translation id="3987348946546879621">தரவு உபயோகம் குறைக்கப்பட்டது</translation>
@@ -2054,6 +2066,7 @@
 <translation id="4268025649754414643">விசை மாற்றம்</translation>
 <translation id="4270393598798225102">பதிப்பு <ph name="NUMBER" /></translation>
 <translation id="4271396100647220620">பொருத்தங்கள் இல்லை</translation>
+<translation id="4273065492769210106">இன்னும் <ph name="RETRIES" /> முறை முயலலாம்.</translation>
 <translation id="4275830172053184480">உங்கள் சாதனத்தை மீண்டும் தொடங்கவும்</translation>
 <translation id="4278101229438943600">உங்கள் அசிஸ்டண்ட் தயாராகிவிட்டது</translation>
 <translation id="4278390842282768270">அனுமதிக்கப்பட்டது</translation>
@@ -2096,7 +2109,6 @@
 <translation id="4354344420232759511">நீங்கள் பார்வையிட்ட தளங்கள் இங்கே தோன்றும்</translation>
 <translation id="435527878592612277">உங்கள் படத்தைத் தேர்ந்தெடுக்கவும்</translation>
 <translation id="4356334633973342967">அல்லது உங்கள் சொந்த இயக்கியைக் குறிப்பிடவும்:</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">நீட்டிப்பு(கள்) சார்ந்திருப்பதன் காரணமாக நிறுவப்பட்டது.</translation>
 <translation id="4359717112757026264">நகரக் காட்சி</translation>
 <translation id="4361142739114356624">இந்தக் கிளையண்ட் சான்றிதழுக்கான தனிப்பட்ட குறியீடு இல்லை அல்லது தவறானது</translation>
@@ -2113,6 +2125,7 @@
 <translation id="4378154925671717803">மொபைல்</translation>
 <translation id="4378551569595875038">இணைக்கிறது...</translation>
 <translation id="4378556263712303865">சாதனக் கோரிக்கை</translation>
+<translation id="4380648069038809855">முழுத்திரையில் காட்டப்படுகிறது</translation>
 <translation id="4384312707950789900">விருப்பப்பட்டியலில் சேர்</translation>
 <translation id="4384652540891215547">நீட்டிப்பைச் செயல்படுத்து</translation>
 <translation id="438503109373656455">சரடோகா</translation>
@@ -2147,7 +2160,6 @@
 <translation id="443475966875174318">இணங்காத பயன்பாடுகளைப் புதுப்பிக்கவும் அல்லது அகற்றவும்</translation>
 <translation id="4441124369922430666">கணினி தொடங்கப்பட்டவுடன் தானாகவே இந்தப் பயன்பாட்டைத் தொடங்க விரும்புகிறீர்களா?</translation>
 <translation id="444134486829715816">விரிவாக்கு...</translation>
-<translation id="4441548209689510310">எழுத்துப் பிழை சரிபார்ப்பு விருப்பங்களைக் காட்டு</translation>
 <translation id="4442424173763614572">DNS தேடுதல் தோல்வி</translation>
 <translation id="4443536555189480885">&amp;Help</translation>
 <translation id="4444304522807523469">USB அல்லது அக நெட்வொர்க் மூலம் இணைக்கப்பட்ட ஆவண ஸ்கேனர்களை அணுகுதல்</translation>
@@ -2192,6 +2204,7 @@
 <translation id="4524832533047962394">வழங்கப்பட்ட பதிவுப் பயன்முறையை இந்த ஆப்ரேட்டிங் சிஸ்டத்தின் பதிப்பு ஆதரிக்கவில்லை. புதிய பதிப்பில் இயக்குவதை உறுதிசெய்யவும்.</translation>
 <translation id="4525382759303819021">Play Store ஆப்ஸ் குறித்த சமீபத்திய அறிவிப்புகளையும் பரிந்துரைகளையும் பெறுக</translation>
 <translation id="4530494379350999373">அசல்</translation>
+<translation id="4531586020343813806">இந்தப் பாதுகாப்பு விசையை மீட்டமைக்க இயலாது.</translation>
 <translation id="4533846798469727141">இப்போது "Hey Google" எனக் கூறவும்</translation>
 <translation id="4533985347672295764">CPU நேரம்</translation>
 <translation id="4534661889221639075">மீண்டும் முயலவும்.</translation>
@@ -2715,6 +2728,7 @@
 <translation id="540296380408672091">எப்போதும் <ph name="HOST" /> இல் குக்கீகளைத் தடு</translation>
 <translation id="5405146885510277940">அமைப்புகளை மீட்டமை</translation>
 <translation id="5408750356094797285">அளவு மாற்றம்: <ph name="PERCENT" /></translation>
+<translation id="5409075533903495802">பின்னில் செல்லாத எழுத்துருக்கள் உள்ளன.</translation>
 <translation id="5411472733320185105">இந்த வழங்குநர்களுக்கு மற்றும் டொமைன்களுக்கு, ப்ராக்ஸி அமைப்புகளைப் பயன்படுத்த வேண்டாம்:</translation>
 <translation id="5414566801737831689">பார்வையிடும் இணையதளங்களின் ஐகான்களைப் படிக்கலாம்</translation>
 <translation id="5417312524372586921">உலாவித் தீம்கள்</translation>
@@ -2914,6 +2928,7 @@
 <translation id="5696143504434933566">"<ph name="EXTENSION_NAME" />" இலிருந்து தவறான செயல்பாடு நடந்தது எனப் புகாரளி</translation>
 <translation id="5696679855467848181">தற்போது உபயோகத்திலுள்ள PPD கோப்பு: <ph name="PPD_NAME" /></translation>
 <translation id="5699533844376998780">"<ph name="EXTENSION_NAME" />" என்ற நீட்டிப்பு சேர்க்கப்பட்டது.</translation>
+<translation id="5699804453758089950">கோரிக்கையை நிறைவுசெய்ய பாதுகாப்பு விசையை மீண்டும் தட்டவும்.</translation>
 <translation id="570043786759263127">Google Play பயன்பாடுகள் மற்றும் சேவைகள்</translation>
 <translation id="5700836101007545240">உங்கள் நிர்வாகி இணைய இணைப்பைச் சேர்ப்பதை முடக்கியுள்ளார்</translation>
 <translation id="5701080607174488915">சேவையகத்திலிருந்து கொள்கையைப் பெறுவதில் பிழை.</translation>
@@ -2937,7 +2952,6 @@
 <translation id="5736796278325406685">சரியான பயனர்பெயரை உள்ளிடவும்</translation>
 <translation id="5739235828260127894">சரிபார்ப்புக்காகக் காத்திருக்கிறது. <ph name="LINK_BEGIN" />மேலும் அறிக<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">மிகப் பெரியது</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" />, மேலும் <ph name="NUM_ADDITIONAL_LANGUAGES" /> மொழிகள்</translation>
 <translation id="574209121243317957">குரல் அழுத்தம்</translation>
 <translation id="5746169159649715125">PDFஆக சேமி</translation>
 <translation id="5747552184818312860">காலாவதியாகும் தேதி</translation>
@@ -3272,6 +3286,7 @@
 <translation id="6247708409970142803"><ph name="PERCENTAGE" />%</translation>
 <translation id="6247802389331535091">சிஸ்டம்: <ph name="ARC_PROCESS_NAME" /></translation>
 <translation id="624789221780392884">புதுப்பிப்பு தயார்</translation>
+<translation id="6248279564564080162">மீட்டமைக்கப்பட்டது.</translation>
 <translation id="6248988683584659830">தேடல் அமைப்புகள்</translation>
 <translation id="6251870443722440887">GDI ஹேண்டில்ஸ்</translation>
 <translation id="6251889282623539337"><ph name="DOMAIN" /> சேவை விதிமுறைகள்</translation>
@@ -3501,6 +3516,7 @@
 <translation id="6622980291894852883">படங்களைத் தடுப்பதைத் தொடர்க</translation>
 <translation id="6624687053722465643">ஸ்வீட்னஸ்</translation>
 <translation id="6628328486509726751">பதிவேற்றப்பட்ட நேரம் <ph name="WEBRTC_LOG_UPLOAD_TIME" /></translation>
+<translation id="662887686112111256">இன்னும் ஒரு முறை முயலலாம்!</translation>
 <translation id="6630752851777525409">உங்கள் சார்பாக தன்னை அங்கீகரித்துக் கொள்ள, ஒரு சான்றிதழுக்கான நிரந்தர அணுகலை <ph name="EXTENSION_NAME" /> கோருகிறது.</translation>
 <translation id="6635956300022133031">உரையிலிருந்து பேச்சுக்கான குரல்களைத் தேர்ந்தெடுக்கலாம், தனிப்பயனாக்கலாம்</translation>
 <translation id="6637585982786704944">உங்களிடம் அனுமதி பெற்றுள்ள ஆப்ஸும் இணையதளங்களும் அவை சரியாக வேலை செய்வதற்குத் தேவையான கணக்குத் தகவலை அணுகலாம்.
@@ -3533,6 +3549,7 @@
 <translation id="6673391612973410118"><ph name="PRINTER_MAKE_OR_MODEL" /> (USB)</translation>
 <translation id="667517062706956822">இந்தப் பக்கத்தை <ph name="SOURCE_LANGUAGE" /> மொழியிலிருந்து <ph name="TARGET_LANGUAGE" /> மொழிக்கு Google மொழிபெயர்க்க வேண்டும் என விரும்புகிறீர்களா?</translation>
 <translation id="6675665718701918026">சுட்டும் சாதனம் இணைக்கப்பட்டது</translation>
+<translation id="6676212663108450937">உங்கள் குரலுடன் பொருத்துவதற்காகப் பதிவு செய்யும் போது ஹெட்ஃபோன்களைப் பயன்படுத்தவும்</translation>
 <translation id="6678717876183468697">வினவல் URL</translation>
 <translation id="6680442031740878064">இருக்கும் இடம்: <ph name="AVAILABLE_SPACE" /></translation>
 <translation id="6680650203439190394">மதிப்பிடு</translation>
@@ -3798,6 +3815,7 @@
 <translation id="7099337801055912064">அதிகபட்ச அளவு 250 கி.பை. என்பதால், பெரிய PPDஐ ஏற்ற முடியாது.</translation>
 <translation id="7102687220333134671">தானியங்கு புதுப்பிப்புகள் இயக்கப்பட்டுள்ளன</translation>
 <translation id="7102832101143475489">கோரிக்கை காலாவதியானது</translation>
+<translation id="7105390788077117391">USB விருப்பத்தேர்வுகள்</translation>
 <translation id="7108338896283013870">மறை</translation>
 <translation id="7108634116785509031"><ph name="HOST" /> உங்கள் கேமராவைப் பயன்படுத்த விரும்புகிறது</translation>
 <translation id="7108668606237948702">உள்ளிடு</translation>
@@ -3901,6 +3919,7 @@
 <translation id="7257666756905341374">நீங்கள் நகலெடுத்து ஒட்டும் தரவைப் படிக்கலாம்</translation>
 <translation id="7258697411818564379">உங்கள் பின் சேர்க்கப்பட்டது</translation>
 <translation id="7262004276116528033">உள்நுழைவுச் சாதனத்தை <ph name="SAML_DOMAIN" /> ஹோஸ்ட் செய்கிறது</translation>
+<translation id="7268127947535186412">இந்த அமைப்பைச் சாதனத்தின் உரிமையாளர் நிர்வகிக்கிறார்.</translation>
 <translation id="7270858098575133036">MIDI சாதனங்களை அணுகுவதற்காக, தளமானது சாதனத்தின் தனிப்பட்ட செய்திகளைப் பயன்படுத்த விரும்பும் போது, கேள்</translation>
 <translation id="7272674038937250585">விளக்கம் எதுவும் வழங்கப்படவில்லை</translation>
 <translation id="7273110280511444812">கடைசியாக இணைத்த தேதி <ph name="DATE" /></translation>
@@ -4213,6 +4232,7 @@
 <translation id="7788383851298063850">என்ன நடக்கிறது என்பதை எங்களிடம் கூறவும்</translation>
 <translation id="7788444488075094252">மொழிகள் மற்றும் உள்ளீடு</translation>
 <translation id="7788668840732459509">நிலை:</translation>
+<translation id="7789963078219276159">தொடக்கப் பக்கப் பின்புலம் <ph name="CATEGORY" />க்கு மாற்றப்பட்டது.</translation>
 <translation id="7791543448312431591">சேர்</translation>
 <translation id="7792012425874949788">உள்நுழைவதில் ஏதோ தவறு ஏற்பட்டது</translation>
 <translation id="7792388396321542707">பகிர்தலை நிறுத்து</translation>
@@ -4399,6 +4419,7 @@
 <translation id="8030656706657716245">பிரிண்டரைச் சேர்</translation>
 <translation id="8032244173881942855">தாவலை அலைபரப்ப முடியவில்லை.</translation>
 <translation id="803435727213847625">{COUNT,plural, =0{எல்லாவற்றையும் &amp;மறைநிலைச் சாளரத்தில் திற}=1{&amp;மறைநிலைச் சாளரத்தில் திற}other{எல்லாவற்றையும் (#) &amp;மறைநிலைச் சாளரத்தில் திற}}</translation>
+<translation id="8034467234497743242">இந்தப் பாதுகாப்பு விசையில் பின்னை அமைக்க இயலாது.</translation>
 <translation id="8037117027592400564">தொகுக்கப்பட்ட பேச்சைப் பயன்படுத்திப் பேசப்படும் எல்லா உரையையும் படிக்கலாம்</translation>
 <translation id="8037357227543935929">கேள் (இயல்பு)</translation>
 <translation id="803771048473350947">கோப்பு</translation>
@@ -4438,6 +4459,7 @@
 <translation id="80974698889265265">பின்கள் பொருந்தவில்லை</translation>
 <translation id="8101987792947961127">அடுத்த மறுதொடக்கத்திற்கு பவர்வாஷ் தேவைப்படுகிறது</translation>
 <translation id="8102159139658438129">இணைக்கப்பட்ட உங்கள் ஃபோனுக்கான விருப்பத்தேர்வுகளைப் பார்க்க, <ph name="LINK_BEGIN" />அமைப்புகளுக்குச்<ph name="LINK_END" /> செல்லவும்</translation>
+<translation id="8102652888659661176">தவறான பின்.</translation>
 <translation id="8104696615244072556"><ph name="IDS_SHORT_PRODUCT_NAME" /> சாதனத்தை பவர்வாஷ் செய்து, முந்தைய பதிப்பிற்கு மாறவும்.</translation>
 <translation id="8105368624971345109">முடக்கு</translation>
 <translation id="8107015733319732394">உங்கள் <ph name="DEVICE_TYPE" /> இல் Google Play ஸ்டோரை நிறுவுகிறது. இதற்குச் சில நிமிடங்கள் ஆகலாம்.</translation>
@@ -4846,6 +4868,7 @@
 <translation id="8767621466733104912">எல்லாப் பயனர்களுக்கும் தானாகவே Chromeஐப் புதுப்பி</translation>
 <translation id="8770406935328356739">நீட்டிப்பு மூலக் கோப்பகம்</translation>
 <translation id="8770507190024617908">நபர்களை நிர்வகி</translation>
+<translation id="8771300903067484968">தொடக்கப் பக்கத்தின் பின்புலமானது இயல்புநிலைப் பின்புலமாக மீட்டமைக்கப்பட்டது.</translation>
 <translation id="8774934320277480003">மேல் ஓரம்</translation>
 <translation id="8775144690796719618">தவறான URL</translation>
 <translation id="8777628254805677039">மூல கடவுச்சொல்</translation>
@@ -4899,6 +4922,7 @@
 <translation id="8847988622838149491">USB</translation>
 <translation id="8848561196844274665">உங்கள் சாதனங்களை இணைக்கும்போது, ​​உங்கள் Chromebook இவற்றைச் செய்யலாம் என்பதை ஏற்கிறீர்கள்:</translation>
 <translation id="8850251000316748990">மேலும் காட்டு...</translation>
+<translation id="885246833287407341">API செயல்பாட்டுத் தருமதிப்புகள்</translation>
 <translation id="8853586775156634952">இந்தக் கார்டு இச்சாதனத்தில் மட்டும் சேமிக்கப்படும்</translation>
 <translation id="8859057652521303089">உங்கள் மொழியைத் தேர்ந்தெடுங்கள்:</translation>
 <translation id="8859174528519900719">துணைச்சட்டகம்: <ph name="SUBFRAME_SITE" /></translation>
@@ -5036,6 +5060,7 @@
 <translation id="9065203028668620118">திருத்து</translation>
 <translation id="9066773882585798925">படிக்கப்படும் உரையைக் கேட்கலாம்</translation>
 <translation id="9066782832737749352">உரையிலிருந்து பேச்சு</translation>
+<translation id="907264006778172906">USB சாதனங்களை அணுகுவதற்கான அனுமதியை Linuxஸுக்கு வழங்கும். அகற்றப்பட்ட USB சாதனத்தை Linux நினைவில் வைத்திருக்காது.</translation>
 <translation id="9073281213608662541">PAP</translation>
 <translation id="9074739597929991885">புளூடூத்</translation>
 <translation id="9074836595010225693">USB மவுஸ் இணைக்கப்பட்டது</translation>
diff --git a/chrome/app/resources/generated_resources_te.xtb b/chrome/app/resources/generated_resources_te.xtb
index d950f21..46de3179 100644
--- a/chrome/app/resources/generated_resources_te.xtb
+++ b/chrome/app/resources/generated_resources_te.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" మీ <ph name="CODE_TYPE" />ని అభ్యర్థిస్తోంది</translation>
 <translation id="3435738964857648380">భద్రత</translation>
 <translation id="3435896845095436175">ప్రారంభించండి</translation>
-<translation id="3436038974659740746">అనుకూల స్పెల్ చెక్</translation>
 <translation id="3438633801274389918">నింజా</translation>
 <translation id="3439153939049640737">మీ మైక్రోఫోన్‌ను యాక్సెస్ చేయడానికి <ph name="HOST" />ని ఎల్లప్పుడూ అనుమతించండి</translation>
 <translation id="3439970425423980614">PDFను ప్రివ్యూలో తెరుస్తోంది</translation>
@@ -1857,14 +1856,13 @@
 <translation id="3898521660513055167">టోకెన్ స్థితి</translation>
 <translation id="389901847090970821">కీబోర్డ్‌ను ఎంచుకోండి</translation>
 <translation id="3899879303189199559">సంవత్సరానికి పైగా ఆఫ్‌లైన్‌లో ఉంది</translation>
-<translation id="3900105072479897941">రీసెట్ చేయడానికి అనుమతించబడలేదు. కొన్ని సెక్యూరిటీ కీలను చొప్పించిన తర్వాత కొన్ని సెకన్లలోపు మాత్రమే రీసెట్ చేయడానికి అవి అనుమతించవచ్చు—మీరు ప్రక్రియను మరింత త్వరగా తిరిగి పూర్తి చేయాలని భావింవచ్చు.</translation>
+<translation id="3900105072479897941">రీసెట్ చేయడానికి అనుమతించబడలేదు. కొన్ని సెక్యూరిటీ కీలను చొప్పించిన తర్వాత కొన్ని సెకన్లలోపు మాత్రమే రీసెట్ చేయడానికి అవి అనుమతించవచ్చు—మీరు ప్రక్రియను మరింత త్వరగా తిరిగి పూర్తి చేయాలని భావించవచ్చు.</translation>
 <translation id="3900966090527141178">పాస్‌వర్డ్‌లను ఎగుమతి చేయండి</translation>
 <translation id="3901991538546252627"><ph name="NAME" />కి కనెక్ట్ చేస్తోంది</translation>
 <translation id="3905761538810670789">యాప్‌ను సరి చేయి</translation>
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> కాలం చెల్లినది</translation>
 <translation id="3908501907586732282">ఎక్స్‌టెన్ష‌న్‌ను ప్రారంభించు</translation>
 <translation id="3909477809443608991">రక్షిత కంటెంట్‌ను ప్లే చేయడానికి <ph name="URL" /> అనుమతి కోరుతుంది. మీ పరికరం గుర్తింపు Google ద్వారా ధృవీకరించబడుతుంది, దీనిని ఈ సైట్ ద్వారా యాక్సెస్ చేయవచ్చు</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> మరియు మరొకటి</translation>
 <translation id="3909791450649380159">క&amp;త్తిరించు</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (ఈ పరికరంలో ఉపయోగించబడిన పేరు)</translation>
 <translation id="3911824782900911339">కొత్త‌ ట్యాబ్ పేజీ</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">మీ ఫోటోని ఎంచుకోండి</translation>
 <translation id="4356334633973342967">లేదంటే, మీ స్వంత డ్రైవర్‌ను పేర్కొనండి:</translation>
 <translation id="4358169392473932247">ఆధారాల అంతర్గత నిల్వకు ఆ భద్రతా కీ మద్దతు ఇవ్వదు, కానీ ఆ ఫీచర్ అభ్యర్థించబడింది.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">ఆధారిత పొడిగింపు(లు) కారణంగా ఇన్‌స్టాల్ చేయబడింది.</translation>
 <translation id="4359717112757026264">నగర చిత్రాలు</translation>
 <translation id="4361142739114356624">ఈ క్లయింట్ ప్రమాణపత్రం యొక్క ప్రైవేట్ కీ లేదు లేదా చెల్లదు</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">అనుకూలంగా లేని అప్లికేషన్‌లను అప్‌డేట్ చేయండి లేదా తీసివేయండి</translation>
 <translation id="4441124369922430666">మెషీన్ ప్రారంభించబడినప్పుడు ఆటోమేటిక్‌గా ఈ యాప్ ప్రారంభించబడాలని మీరు కోరుకుంటున్నారా?</translation>
 <translation id="444134486829715816">విస్తరించు...</translation>
-<translation id="4441548209689510310">స్పెల్ చెక్ ఎంపికలను చూపు</translation>
 <translation id="4442424173763614572">DNS శోధన విఫలమైంది</translation>
 <translation id="4443536555189480885">&amp;సహాయం</translation>
 <translation id="4444304522807523469">USB ద్వారా లేదా స్థానిక నెట్‌వర్క్‌లో జోడించిన పత్రం స్కానర్‌లను యాక్సెస్ చేయండి</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">దయచేసి చెల్లుబాటు అయ్యే వినియోగదారు పేరును నమోదు చేయండి</translation>
 <translation id="5739235828260127894">ధృవీకరణ కోసం వేచి ఉంది. <ph name="LINK_BEGIN" />మరింత తెలుసుకోండి<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">చాలా పెద్దవిగా</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> మరియు మరో <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">పిచ్</translation>
 <translation id="5746169159649715125">PDF లాగా సేవ్ చేయి</translation>
 <translation id="5747552184818312860">గడువు ముగింపు</translation>
diff --git a/chrome/app/resources/generated_resources_th.xtb b/chrome/app/resources/generated_resources_th.xtb
index 70ce5b8..20d9963 100644
--- a/chrome/app/resources/generated_resources_th.xtb
+++ b/chrome/app/resources/generated_resources_th.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" ขอ <ph name="CODE_TYPE" /> ของคุณ</translation>
 <translation id="3435738964857648380">ความปลอดภัย</translation>
 <translation id="3435896845095436175">เปิดการใช้งาน</translation>
-<translation id="3436038974659740746">ตัวสะกดที่กำหนดเอง</translation>
 <translation id="3438633801274389918">นินจา</translation>
 <translation id="3439153939049640737">อนุญาตให้ <ph name="HOST" /> เข้าถึงไมโครโฟนของคุณเสมอ</translation>
 <translation id="3439970425423980614">กำลังเปิด PDF ในหน้าตัวอย่าง</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> ล้าสมัย</translation>
 <translation id="3908501907586732282">เปิดใช้งานส่วนขยาย</translation>
 <translation id="3909477809443608991"><ph name="URL" /> ต้องการเล่นเนื้อหาที่ได้รับความคุ้มครอง ข้อมูลประจำตัวของอุปกรณ์จะได้รับการยืนยันโดย Google และเว็บไซต์นี้อาจเข้าถึงข้อมูลดังกล่าว</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> และอีก 1 ภาษา</translation>
 <translation id="3909791450649380159">&amp;ตัด</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (ชื่อที่ใช้ในอุปกรณ์นี้)</translation>
 <translation id="3911824782900911339">หน้าแท็บใหม่</translation>
@@ -2128,8 +2126,7 @@
 <translation id="4354344420232759511">เว็บไซต์ที่คุณเข้าชมจะปรากฏที่นี่</translation>
 <translation id="435527878592612277">เลือกรูปภาพของคุณ</translation>
 <translation id="4356334633973342967">หรือระบุไดรเวอร์ของคุณเอง:</translation>
-<translation id="4358169392473932247">คีย์ความปลอดภัยไม่รองรับที่จัดเก็บข้อมูลภายในของข้อมูลเข้าสู่ระบบ แต่เว็บไซต์ขอฟีเจอร์ดังกล่าว</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
+<translation id="4358169392473932247">คีย์ความปลอดภัยนั้นไม่รองรับที่จัดเก็บข้อมูลภายในของข้อมูลเข้าสู่ระบบ แต่มีการขอฟีเจอร์ดังกล่าว</translation>
 <translation id="4359408040881008151">ติดตั้งแล้วเนื่องจากมีส่วนขยายที่ต้องพึ่งพา</translation>
 <translation id="4359717112757026264">ทิวทัศน์ของเมือง</translation>
 <translation id="4361142739114356624">คีย์ส่วนตัวของใบรับรองไคลเอ็นต์นี้หายไปหรือไม่ถูกต้อง</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">อัปเดตหรือนำแอปพลิเคชันที่ใช้ร่วมกันไม่ได้ออก</translation>
 <translation id="4441124369922430666">คุณต้องการเริ่มแอปนี้โดยอัตโนมัติเมื่อเครื่องเปิดไหม</translation>
 <translation id="444134486829715816">ขยาย...</translation>
-<translation id="4441548209689510310">แสดงตัวเลือกการตรวจตัวสะกด</translation>
 <translation id="4442424173763614572">การค้นหา DNS ล้มเหลว</translation>
 <translation id="4443536555189480885">&amp;ความช่วยเหลือ</translation>
 <translation id="4444304522807523469">เข้าถึงเครื่องสแกนเอกสารที่เชื่อมต่อผ่าน USB หรือบนเครือข่าย LAN</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">โปรดป้อนชื่อผู้ใช้ที่ถูกต้อง</translation>
 <translation id="5739235828260127894">กำลังรอการยืนยัน <ph name="LINK_BEGIN" />ดูข้อมูลเพิ่มเติม<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">ใหญ่มาก</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> และอีก <ph name="NUM_ADDITIONAL_LANGUAGES" /> ภาษา</translation>
 <translation id="574209121243317957">ระดับเสียงสูงต่ำ</translation>
 <translation id="5746169159649715125">บันทึกเป็น PDF</translation>
 <translation id="5747552184818312860">หมดอายุ</translation>
@@ -4494,7 +4489,7 @@
     <ph name="BEGIN_PARAGRAPH3" />ข้อมูลแอปอาจเป็นข้อมูลใดก็ตามที่แอปบันทึกไว้ (โดยอิงตามการตั้งค่าของนักพัฒนาซอฟต์แวร์) ซึ่งรวมถึงข้อมูลอย่างเช่น รายชื่อติดต่อ ข้อความ และรูปภาพ<ph name="END_PARAGRAPH3" />
     <ph name="BEGIN_PARAGRAPH4" />ข้อมูลสำรองจะไม่นับรวมอยู่ในโควต้าพื้นที่เก็บข้อมูล Google ไดรฟ์<ph name="END_PARAGRAPH4" />
     <ph name="BEGIN_PARAGRAPH5" />คุณปิดบริการนี้ได้ในการตั้งค่า<ph name="END_PARAGRAPH5" /></translation>
-<translation id="8096438328987289870">เลือกบัญชีที่จะใช้ลงชื่อเข้าสู่ระบบ:</translation>
+<translation id="8096438328987289870">เลือกบัญชีที่จะใช้ลงชื่อเข้าสู่ระบบ</translation>
 <translation id="80974698889265265">PIN ไม่ตรงกัน</translation>
 <translation id="8101987792947961127">ต้องใช้ Powerwash ในการรีบูตครั้งถัดไป</translation>
 <translation id="8102159139658438129">ไปที่<ph name="LINK_BEGIN" />การตั้งค่า<ph name="LINK_END" />เพื่อดูตัวเลือกสำหรับโทรศัพท์ที่เชื่อมต่อ</translation>
diff --git a/chrome/app/resources/generated_resources_tr.xtb b/chrome/app/resources/generated_resources_tr.xtb
index 8ace30a1..f104403 100644
--- a/chrome/app/resources/generated_resources_tr.xtb
+++ b/chrome/app/resources/generated_resources_tr.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" uzantısı sizden <ph name="CODE_TYPE" /> istiyor.</translation>
 <translation id="3435738964857648380">Güvenlik</translation>
 <translation id="3435896845095436175">Etkinleştir</translation>
-<translation id="3436038974659740746">Özel yazım</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Mikrofonuma <ph name="HOST" /> tarafından erişilmesine her zaman izin ver</translation>
 <translation id="3439970425423980614">PDF Önizlemede Açılıyor</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> güncel değil</translation>
 <translation id="3908501907586732282">Uzantıyı etkinleştir</translation>
 <translation id="3909477809443608991"><ph name="URL" />, korunan içeriği oynatmak istiyor. Cihazınızın kimliği Google tarafından doğrulanır ve bu site tarafından erişilebilir.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> ve 1 dil daha</translation>
 <translation id="3909791450649380159">&amp;Kes</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (ad bu cihazda kullanılıyor)</translation>
 <translation id="3911824782900911339">Yeni Sekme sayfası</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Fotoğrafınızı seçin</translation>
 <translation id="4356334633973342967">Kendi sürücünüzü de belirtebilirsiniz:</translation>
 <translation id="4358169392473932247">Bu güvenlik anahtarı, kimlik bilgilerinin dahili olarak depolanmasını desteklememesine rağmen bu özellik için istekte bulunuldu.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Bağımlı uzantılar nedeniyle yüklendi.</translation>
 <translation id="4359717112757026264">Şehir manzaraları</translation>
 <translation id="4361142739114356624">Bu İstemci Sertifikası'nın Özel Anahtarı eksik veya geçersiz</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Uyumsuz uygulamaları güncelleyin veya kaldırın</translation>
 <translation id="4441124369922430666">Makine açıldığında bu uygulamayı otomatik olarak başlatmak istiyor musunuz?</translation>
 <translation id="444134486829715816">Genişlet...</translation>
-<translation id="4441548209689510310">Yazım denetimi seçeneklerini göster</translation>
 <translation id="4442424173763614572">DNS arama başarısız oldu</translation>
 <translation id="4443536555189480885">&amp;Yardım</translation>
 <translation id="4444304522807523469">USB üzerinden bağlı veya yerel ağda bulunan doküman tarayıcılara erişme</translation>
@@ -2978,7 +2974,6 @@
 <translation id="5736796278325406685">Lütfen geçerli bir kullanıcı adı girin</translation>
 <translation id="5739235828260127894">Doğrulama bekleniyor. <ph name="LINK_BEGIN" />Daha fazla bilgi<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Çok büyük</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> ve <ph name="NUM_ADDITIONAL_LANGUAGES" /> dil daha</translation>
 <translation id="574209121243317957">Ses Kalınlığı</translation>
 <translation id="5746169159649715125">PDF olarak kaydet</translation>
 <translation id="5747552184818312860">Süre sonu tarihi</translation>
diff --git a/chrome/app/resources/generated_resources_uk.xtb b/chrome/app/resources/generated_resources_uk.xtb
index decc121e..17cbb8d 100644
--- a/chrome/app/resources/generated_resources_uk.xtb
+++ b/chrome/app/resources/generated_resources_uk.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">Розширення "<ph name="EXTENSION_NAME" />" просить надати ваш <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">Безпека</translation>
 <translation id="3435896845095436175">Увімкнути</translation>
-<translation id="3436038974659740746">Користувацький правопис</translation>
 <translation id="3438633801274389918">Ніндзя</translation>
 <translation id="3439153939049640737">Завжди дозволяти хосту <ph name="HOST" /> доступ до вашого мікрофона</translation>
 <translation id="3439970425423980614">Відкривання файлу PDF у вікні попереднього перегляду</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098">Плагін <ph name="PLUGIN_NAME" /> застарів</translation>
 <translation id="3908501907586732282">Увімкнути розширення</translation>
 <translation id="3909477809443608991"><ph name="URL" /> хоче відтворити захищений вміст. Ми перевіримо ідентифікаційні дані вашого пристрою, і сайт зможе отримати до нього доступ.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> та ще 1 мова</translation>
 <translation id="3909791450649380159">Вирізат&amp;и</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (ім’я використовується на цьому пристрої)</translation>
 <translation id="3911824782900911339">Сторінка нової вкладки</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Виберіть фотографію</translation>
 <translation id="4356334633973342967">Або виберіть свій драйвер:</translation>
 <translation id="4358169392473932247">Цей ключ безпеки не підтримує зберігання облікових даних у внутрішній пам’яті, однак є запит на таку функцію.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Установлено, оскільки є залежні розширення.</translation>
 <translation id="4359717112757026264">Міський пейзаж</translation>
 <translation id="4361142739114356624">Секретний ключ цього сертифіката клієнта відсутній або недійсний</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Оновити або видалити несумісні додатки</translation>
 <translation id="4441124369922430666">Запускати цю програму автоматично під час увімкнення комп’ютера?</translation>
 <translation id="444134486829715816">Розгорнути...</translation>
-<translation id="4441548209689510310">Показати налаштування перевірки правопису</translation>
 <translation id="4442424173763614572">Помилка пошуку DNS</translation>
 <translation id="4443536555189480885">&amp;Довідка</translation>
 <translation id="4444304522807523469">Отримувати доступ до сканерів документів, під’єднаних через USB або локальну мережу</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">Введіть дійсне ім’я користувача</translation>
 <translation id="5739235828260127894">Очікується підтвердження. <ph name="LINK_BEGIN" />Докладніше<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Дуже великий</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> та ще стільки мов: <ph name="NUM_ADDITIONAL_LANGUAGES" /></translation>
 <translation id="574209121243317957">Тон</translation>
 <translation id="5746169159649715125">Зберегти у форматі PDF</translation>
 <translation id="5747552184818312860">Діє до</translation>
diff --git a/chrome/app/resources/generated_resources_vi.xtb b/chrome/app/resources/generated_resources_vi.xtb
index cb7ce11..ab03243 100644
--- a/chrome/app/resources/generated_resources_vi.xtb
+++ b/chrome/app/resources/generated_resources_vi.xtb
@@ -1534,7 +1534,6 @@
 <translation id="3435688026795609344">"<ph name="EXTENSION_NAME" />" đang yêu cầu <ph name="CODE_TYPE" /> của bạn</translation>
 <translation id="3435738964857648380">Bảo mật</translation>
 <translation id="3435896845095436175">Bật</translation>
-<translation id="3436038974659740746">Chính tả tùy chỉnh</translation>
 <translation id="3438633801274389918">Ninja</translation>
 <translation id="3439153939049640737">Luôn cho phép <ph name="HOST" /> truy cập micrô của bạn</translation>
 <translation id="3439970425423980614">Mở PDF ở chế độ xem trước</translation>
@@ -1851,7 +1850,7 @@
 <translation id="3892414795099177503">Thêm OpenVPN / L2TP...</translation>
 <translation id="3893536212201235195">Đọc và thay đổi cài đặt khả năng truy cập của bạn</translation>
 <translation id="3893630138897523026">ChromeVox (phản hồi bằng giọng nói)</translation>
-<translation id="3894123633473837029">Thêm lịch sử gần đây của Trợ lý qua Sherlog. Lịch sử này có thể bao gồm thông tin gỡ lỗi, vị trí và danh tính của bạn. <ph name="BEGIN_LINK" />Tìm hiểu thêm<ph name="END_LINK" /></translation>
+<translation id="3894123633473837029">Thêm lịch sử hoạt động gần đây của Trợ lý qua Sherlog. Lịch sử này có thể bao gồm thông tin gỡ lỗi, vị trí và danh tính của bạn. <ph name="BEGIN_LINK" />Tìm hiểu thêm<ph name="END_LINK" /></translation>
 <translation id="3894427358181296146">Thêm thư mục</translation>
 <translation id="389589731200570180">Chia sẻ với khách</translation>
 <translation id="3898521660513055167">Trạng thái mã thông báo</translation>
@@ -1864,7 +1863,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> đã lỗi thời</translation>
 <translation id="3908501907586732282">Bật tiện ích</translation>
 <translation id="3909477809443608991"><ph name="URL" /> muốn phát nội dung được bảo vệ. Thông tin định danh của thiết bị sẽ được Google xác minh và trang web này có thể truy cập vào thông tin đó.</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> và 1 ngôn ngữ khác</translation>
 <translation id="3909791450649380159">Cắ&amp;t</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (tên sử dụng trên thiết bị này)</translation>
 <translation id="3911824782900911339">Trang tab mới</translation>
@@ -2129,7 +2127,6 @@
 <translation id="435527878592612277">Chọn ảnh của bạn</translation>
 <translation id="4356334633973342967">Hoặc chỉ định trình điều khiển của riêng bạn:</translation>
 <translation id="4358169392473932247">Khóa bảo mật đó không hỗ trợ lưu thông tin xác thực vào bộ nhớ trong, nhưng trang web lại yêu cầu tính năng đó.</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">Đã được cài đặt vì (các) tiện ích phụ thuộc.</translation>
 <translation id="4359717112757026264">Cảnh quan thành phố</translation>
 <translation id="4361142739114356624">Khóa cá nhân cho chứng chỉ ứng dụng này còn thiếu hoặc không hợp lệ</translation>
@@ -2181,7 +2178,6 @@
 <translation id="443475966875174318">Cập nhật hoặc xóa các ứng dụng không tương thích</translation>
 <translation id="4441124369922430666">Bạn có muốn tự động khởi động ứng dụng này khi máy bật không?</translation>
 <translation id="444134486829715816">Mở rộng...</translation>
-<translation id="4441548209689510310">Hiển thị tùy chọn kiểm tra lỗi chính tả</translation>
 <translation id="4442424173763614572">Tìm kiếm DNS không thành công</translation>
 <translation id="4443536555189480885">&amp;Trợ giúp</translation>
 <translation id="4444304522807523469">Truy cập máy quét tài liệu được lắp qua USB hoặc trên mạng cục bộ</translation>
@@ -2977,7 +2973,6 @@
 <translation id="5736796278325406685">Vui lòng nhập tên người dùng hợp lệ</translation>
 <translation id="5739235828260127894">Đang chờ xác minh. <ph name="LINK_BEGIN" />Tìm hiểu thêm<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">Rất lớn</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> và <ph name="NUM_ADDITIONAL_LANGUAGES" /> ngôn ngữ khác</translation>
 <translation id="574209121243317957">Cao độ</translation>
 <translation id="5746169159649715125">Lưu dưới dạng PDF</translation>
 <translation id="5747552184818312860">Hết hạn</translation>
diff --git a/chrome/app/resources/generated_resources_zh-CN.xtb b/chrome/app/resources/generated_resources_zh-CN.xtb
index cab31f5d..639cf15 100644
--- a/chrome/app/resources/generated_resources_zh-CN.xtb
+++ b/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -1527,7 +1527,6 @@
 <translation id="3435688026795609344">“<ph name="EXTENSION_NAME" />”正在请求您提供 <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">安全</translation>
 <translation id="3435896845095436175">启用</translation>
-<translation id="3436038974659740746">自定义拼写检查</translation>
 <translation id="3438633801274389918">忍者</translation>
 <translation id="3439153939049640737">始终允许 <ph name="HOST" /> 使用您的麦克风</translation>
 <translation id="3439970425423980614">准备使用预览程序打开 PDF</translation>
@@ -1857,7 +1856,6 @@
 <translation id="3908393983276948098"><ph name="PLUGIN_NAME" /> 不是最新版本</translation>
 <translation id="3908501907586732282">启用扩展程序</translation>
 <translation id="3909477809443608991"><ph name="URL" /> 想播放受保护内容。Google 将会验证您的设备身份,而且此网站可能会查看您的设备身份。</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />、<ph name="LANGUAGE_2" />和另外 1 种语言</translation>
 <translation id="3909791450649380159">剪切(&amp;T)</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" />(已在此设备上使用的名称)</translation>
 <translation id="3911824782900911339">打开新的标签页</translation>
@@ -2121,7 +2119,6 @@
 <translation id="435527878592612277">选择您的照片</translation>
 <translation id="4356334633973342967">或指定您自己的驱动程序:</translation>
 <translation id="4358169392473932247">该安全密钥不支持在内部存储凭据,但网站所请求的功能正是这项。</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />、<ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">安装此扩展程序是因为某个/些扩展程序需要安装它才能正常使用。</translation>
 <translation id="4359717112757026264">城市景观</translation>
 <translation id="4361142739114356624">缺少此客户端证书的私钥,或私钥无效</translation>
@@ -2173,7 +2170,6 @@
 <translation id="443475966875174318">更新或卸载不兼容的应用</translation>
 <translation id="4441124369922430666">要在设备开启时自动启动此应用吗?</translation>
 <translation id="444134486829715816">展开...</translation>
-<translation id="4441548209689510310">显示拼写检查选项</translation>
 <translation id="4442424173763614572">DNS 查找失败</translation>
 <translation id="4443536555189480885">帮助(&amp;H)</translation>
 <translation id="4444304522807523469">使用通过 USB 连接的或本地网络中的文档扫描仪</translation>
@@ -2969,7 +2965,6 @@
 <translation id="5736796278325406685">请输入有效的用户名</translation>
 <translation id="5739235828260127894">正在等待验证。<ph name="LINK_BEGIN" />了解详情<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">特大</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />、<ph name="LANGUAGE_2" />和另外 <ph name="NUM_ADDITIONAL_LANGUAGES" /> 种语言</translation>
 <translation id="574209121243317957">音高</translation>
 <translation id="5746169159649715125">另存为 PDF</translation>
 <translation id="5747552184818312860">到期时间</translation>
diff --git a/chrome/app/resources/generated_resources_zh-TW.xtb b/chrome/app/resources/generated_resources_zh-TW.xtb
index 5f5346a1e..65f7980 100644
--- a/chrome/app/resources/generated_resources_zh-TW.xtb
+++ b/chrome/app/resources/generated_resources_zh-TW.xtb
@@ -1533,7 +1533,6 @@
 <translation id="3435688026795609344">「<ph name="EXTENSION_NAME" />」要求你提供 <ph name="CODE_TYPE" /></translation>
 <translation id="3435738964857648380">安全性</translation>
 <translation id="3435896845095436175">啟用</translation>
-<translation id="3436038974659740746">自訂拼字</translation>
 <translation id="3438633801274389918">忍者</translation>
 <translation id="3439153939049640737">一律允許 <ph name="HOST" /> 存取你的麥克風</translation>
 <translation id="3439970425423980614">正在預覽中開啟 PDF</translation>
@@ -1863,7 +1862,6 @@
 <translation id="3908393983276948098">「<ph name="PLUGIN_NAME" />」版本過舊</translation>
 <translation id="3908501907586732282">啟用擴充功能</translation>
 <translation id="3909477809443608991"><ph name="URL" /> 想要播放受到保護的內容。Google 會驗證你的裝置身分,這個網站可能也會存取你的裝置身分。</translation>
-<translation id="3909690856344416952"><ph name="LANGUAGE_1" />、<ph name="LANGUAGE_2" />和另外 1 種語言</translation>
 <translation id="3909791450649380159">剪下(&amp;T)</translation>
 <translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (這個裝置上已其他人使用這個名稱)</translation>
 <translation id="3911824782900911339">新分頁</translation>
@@ -2127,7 +2125,6 @@
 <translation id="435527878592612277">請選取你的相片</translation>
 <translation id="4356334633973342967">或指定你自己的硬碟:</translation>
 <translation id="4358169392473932247">這個安全金鑰不支援將憑證儲存在內部儲存空間,但網站要求執行這項功能。</translation>
-<translation id="4358353773267946514"><ph name="LANGUAGE_1" />、<ph name="LANGUAGE_2" /></translation>
 <translation id="4359408040881008151">你已安裝相依的擴充功能,因此必須一併安裝這個擴充功能。</translation>
 <translation id="4359717112757026264">城市景觀</translation>
 <translation id="4361142739114356624">這個用戶端憑證沒有私密金鑰或私密金鑰無效</translation>
@@ -2179,7 +2176,6 @@
 <translation id="443475966875174318">更新或移除不相容的應用程式</translation>
 <translation id="4441124369922430666">你要在裝置開機時自動啟動這個應用程式嗎?</translation>
 <translation id="444134486829715816">展開...</translation>
-<translation id="4441548209689510310">顯示拼字檢查選項</translation>
 <translation id="4442424173763614572">DNS 查詢失敗</translation>
 <translation id="4443536555189480885">說明(&amp;H)</translation>
 <translation id="4444304522807523469">存取透過 USB 附加或是在區域網路上的文件掃描器</translation>
@@ -2975,7 +2971,6 @@
 <translation id="5736796278325406685">請輸入有效的使用者名稱</translation>
 <translation id="5739235828260127894">等待驗證中。<ph name="LINK_BEGIN" />瞭解詳情<ph name="LINK_END" /></translation>
 <translation id="5739458112391494395">非常大</translation>
-<translation id="5740331643563157105"><ph name="LANGUAGE_1" />、<ph name="LANGUAGE_2" />和另外 <ph name="NUM_ADDITIONAL_LANGUAGES" /> 種語言</translation>
 <translation id="574209121243317957">音調</translation>
 <translation id="5746169159649715125">另存為 PDF</translation>
 <translation id="5747552184818312860">有效期限</translation>
diff --git a/chrome/app/resources/google_chrome_strings_en-GB.xtb b/chrome/app/resources/google_chrome_strings_en-GB.xtb
index ed839c0..84bc43a8 100644
--- a/chrome/app/resources/google_chrome_strings_en-GB.xtb
+++ b/chrome/app/resources/google_chrome_strings_en-GB.xtb
@@ -200,7 +200,7 @@
 <translation id="6468844726266617801">{0,plural, =1{Relaunch Chrome within a day}other{Relaunch Chrome within # days}}</translation>
 <translation id="6515495397637126556"><ph name="PAGE_TITLE" /> – Google Chrome Dev</translation>
 <translation id="6566149418543181476">Updating Google Chrome (<ph name="PROGRESS_PERCENT" />)</translation>
-<translation id="6598387184982954187">You're using <ph name="PROFILE_EMAIL" /> to sync your Chrome stuff. To update your sync preference or to use Chrome without aGoogle Account, visit <ph name="SETTINGS_LINK" />.</translation>
+<translation id="6598387184982954187">You're using <ph name="PROFILE_EMAIL" /> to sync your Chrome stuff. To update your sync preference or to use Chrome without a Google Account, visit <ph name="SETTINGS_LINK" />.</translation>
 <translation id="6600954340915313787">Copied to Chrome</translation>
 <translation id="6634887557811630702">Google Chrome is up to date.</translation>
 <translation id="6676384891291319759">Access the Internet</translation>
diff --git a/chrome/app/resources/google_chrome_strings_fil.xtb b/chrome/app/resources/google_chrome_strings_fil.xtb
index 5ac208bb..f973896 100644
--- a/chrome/app/resources/google_chrome_strings_fil.xtb
+++ b/chrome/app/resources/google_chrome_strings_fil.xtb
@@ -236,6 +236,7 @@
 <translation id="7589360514048265910">Hindi na makakatanggap ng mga update sa Google Chrome ang computer na ito dahil hindi na sinusuportahan ang Mac OS X 10.9.</translation>
 <translation id="7592736734348559088">Hindi mai-sync ng Google Chrome ang iyong data dahil hindi napapanahon ang mga detalye sa pag-sign in ng iyong account.</translation>
 <translation id="7626032353295482388">Welcome sa Chrome</translation>
+<translation id="7641148173327520642">Na-configure ng iyong system administrator ang Google Chrome para buksan ang <ph name="ALTERNATIVE_BROWSER_NAME" /> para ma-access ang <ph name="TARGET_URL_HOSTNAME" />.</translation>
 <translation id="7651907282515937834">Logo ng Chrome Enterprise</translation>
 <translation id="7747138024166251722">Hindi makalikha ng pansamantalang direktoryo ang installer. Paki-suri para sa puwang sa disk na walang laman at pahintulot upang i-install ang software.</translation>
 <translation id="7761834446675418963">I-click ang iyong pangalan upang buksan ang Chrome at simulan ang pagba-browse.</translation>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index f139f5a..ff8d90b1 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -4655,7 +4655,7 @@
     Create a PIN
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_SET_PIN_DESC" desc="A description that appears in the Settings subpage for security keys (which are external devices for user authentication). PINs are often four-digit codes, commonly used to authorise the use of ATM cards. A similar mechanism can be used with security keys and this is the description for the section about settings them.">
-    A PIN protects your security key
+    Protect your security key with a PIN (Personal Identification Number)
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_SET_PIN_INITIAL_TITLE" desc="The title of a dialog for setting the PIN of a security key (which are external devices for user authentication). PINs are often four-digit codes, commonly used to authorise the use of ATM cards. A similar mechanism can be used with security keys and this is the heading for the section about settings them.">
     Create a PIN
@@ -4685,34 +4685,34 @@
     To confirm you want to reset your security key, touch it again. All credentials stored on the security key and its PIN will be erased.
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_NO_RESET" desc="A failure message reporting to the user that it is not possible to reset the security key that they selected because the device does not support that operation.">
-    That security key does not support being reset.
+    Can’t reset this security key
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_RESET_ERROR" desc="A failure message reporting to the user that the attempt to reset their security key (which is an external device for user authentication) failed. This is message is shown in uncommon cases when we don't have a more specific message to show the user and have fallen back to displaying a numerical error code reported by the device.">
-    Failed to reset device. Error <ph name="ERROR_CODE">$1<ex>22</ex></ph>.
+    Can’t reset this security key. Error <ph name="ERROR_CODE">$1<ex>22</ex></ph>.
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_RESET_SUCCESS" desc="A mesasge to the user that they have successfully reset (i.e. erased) their security key (which is an external device for user authentication).">
-    Reset successful.
+    Your security key has been reset
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_RESET_NOTALLOWED" desc="A mesasge to the user that an attempt to reset (i.e. erase) their security key (an external device for user authentication) failed because the security key refused to be reset. This is usually caused because a reset is only allowed within the first few seconds after being plugged in, so the user has to perform the operation quickly.">
-    Reset was not permitted. Some security keys may only allow a reset within the first few seconds after being inserted—you may wish to reattempt the process more quickly.
+    Can’t reset this security key. Try resetting the key immediately after inserting it.
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_PIN_TOUCH" desc="An instruction to a user to physically the activation button on their security key (which is an external device for user authentication).">
     Insert and touch your security key to create or change a PIN.
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_NO_PIN" desc="A failure message shown to a user when they attempt to set a PIN on a security key that does not support PINs. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
-    That security key does not support setting a PIN.
+    This security key doesn’t support PINs
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_CURRENT_PIN_INTRO" desc="A message shown when a user is trying to change the PIN on a security key to prompt the user to enter the current PIN for the device. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
-    Enter your &lt;i&gt;current&lt;/i&gt; PIN to change it. If you do not know the current PIN then the security key has to be reset to clear it.
+    Enter your current PIN to change it. If you don’t know your PIN, you’ll need to reset the security key, then create a new PIN.
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_PIN_INCORRECT" desc="A message shown to the user when they enter an incorrect PIN for a security key. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
-    PIN incorrect.
+    Incorrect PIN
   </message>
-  <message name="IDS_SETTINGS_SECURITY_KEYS_CURRENT_PIN_RETRIES_PL" desc="A message shown when a user is trying the change the PIN on a security key to inform them of the number of attempts remaining for them to enter the correct, current PIN. The number in the placeholder will always be more than one. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
-    You have <ph name="RETRIES">$1<ex>8</ex></ph> attempts remaining.
+  <message name="IDS_SETTINGS_SECURITY_KEYS_PIN_INCORRECT_RETRIES_SIN" desc="A message shown to the user when they enter an incorrect PIN for a security key. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
+    Incorrect PIN. You have one attempt remaining.
   </message>
-  <message name="IDS_SETTINGS_SECURITY_KEYS_CURRENT_PIN_RETRIES_SIN" desc="A message shown when a user is trying the change the PIN on a security key to inform them that they only have a single chance to get it right. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
-    You have only one attempt remaining!
+  <message name="IDS_SETTINGS_SECURITY_KEYS_PIN_INCORRECT_RETRIES_PL" desc="A message shown to the user when they enter an incorrect PIN for a security key. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
+    Incorrect PIN. You have <ph name="RETRIES">$1<ex>8</ex></ph> attempts remaining.
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_NEW_PIN" desc="A message shown when a user is trying to set a PIN on a security key. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
     Enter your new PIN. A PIN must be at least four characters long and can contain letters, numbers, and other characters.
@@ -4730,15 +4730,15 @@
     Confirm PIN
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_PIN_SUCCESS" desc="A message shown when the user has successfully set a PIN on a security key. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
-    PIN successfully set.
+    Your PIN was created
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_PIN_ERROR" desc="A message shown when setting a PIN on a security key failed with an unhandled error code. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
     PIN operation failed with code <ph name="RETRIES">$1<ex>18</ex></ph>.
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_PIN_HARD_LOCK" desc="A message shown when the user attempts to change the PIN on a security key that has been locked due to too many incorrect PIN attempts. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
-    That security key is locked due to too many incorrect PIN attempts. It must be reset in order to perform any PIN-based operations.
+    The security key is locked because the wrong PIN was entered too many times. You’ll need to reset the security key.
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_PIN_SOFT_LOCK" desc="A message shown when the user attempts to change the PIN on a security key that has been locked due to too many incorrect PIN attempts. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people.">
-    That security key is temporarily locked due to too many incorrect PIN attempts. Remove it and reinsert to unlock.
+    The security key is locked because the wrong PIN was entered too many times. To unlock it, remove and reinsert it.
   </message>
 </grit-part>
diff --git a/chrome/app/vr_strings.grdp b/chrome/app/vr_strings.grdp
index 5f0fbd0..cb80b37a 100644
--- a/chrome/app/vr_strings.grdp
+++ b/chrome/app/vr_strings.grdp
@@ -60,7 +60,7 @@
       Remove headset to block or allow.
     </message>
     <message name="IDS_VR_DESKTOP_GENERIC_PERMISSION_PROMPT" desc="Text displayed in a dialog in VR headset to notify the user that the current webpage is requesting a new permission, but we don't know which one specifically.">
-      <ph name="URL_HOST">$1<ex>google.com</ex></ph> has requested additional permissions.
+      The site has requested additional permissions.
     </message>
   </if>
 
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index a5f858f3..5329cce2 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1013,8 +1013,6 @@
     "page_load_metrics/observers/service_worker_page_load_metrics_observer.h",
     "page_load_metrics/observers/signed_exchange_page_load_metrics_observer.cc",
     "page_load_metrics/observers/signed_exchange_page_load_metrics_observer.h",
-    "page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer.cc",
-    "page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer.h",
     "page_load_metrics/observers/tab_restore_page_load_metrics_observer.cc",
     "page_load_metrics/observers/tab_restore_page_load_metrics_observer.h",
     "page_load_metrics/observers/ukm_page_load_metrics_observer.cc",
@@ -1077,8 +1075,8 @@
     "performance_manager/graph/system_node_impl.cc",
     "performance_manager/graph/system_node_impl.h",
     "performance_manager/observers/background_metrics_reporter.h",
-    "performance_manager/observers/coordination_unit_graph_observer.cc",
-    "performance_manager/observers/coordination_unit_graph_observer.h",
+    "performance_manager/observers/graph_observer.cc",
+    "performance_manager/observers/graph_observer.h",
     "performance_manager/observers/metrics_collector.cc",
     "performance_manager/observers/metrics_collector.h",
     "performance_manager/observers/page_signal_generator_impl.cc",
@@ -1087,12 +1085,12 @@
     "performance_manager/observers/working_set_trimmer_win.h",
     "performance_manager/performance_manager.cc",
     "performance_manager/performance_manager.h",
+    "performance_manager/performance_manager_clock.cc",
+    "performance_manager/performance_manager_clock.h",
     "performance_manager/performance_manager_tab_helper.cc",
     "performance_manager/performance_manager_tab_helper.h",
     "performance_manager/render_process_user_data.cc",
     "performance_manager/render_process_user_data.h",
-    "performance_manager/resource_coordinator_clock.cc",
-    "performance_manager/resource_coordinator_clock.h",
     "performance_manager/webui_graph_dump_impl.cc",
     "performance_manager/webui_graph_dump_impl.h",
     "performance_monitor/metric_evaluator_helper_win.cc",
@@ -3472,6 +3470,13 @@
     ]
   }
 
+  if (is_chromeos || enable_extensions) {
+    sources += [
+      "metrics/cached_metrics_profile.cc",
+      "metrics/cached_metrics_profile.h",
+    ]
+  }
+
   if (is_win) {
     sources += [
       "badging/badge_manager_delegate_win.cc",
@@ -5297,6 +5302,8 @@
       "chromeos/login/test/js_checker.h",
       "chromeos/login/test/oobe_configuration_waiter.cc",
       "chromeos/login/test/oobe_configuration_waiter.h",
+      "chromeos/login/test/oobe_screen_exit_waiter.cc",
+      "chromeos/login/test/oobe_screen_exit_waiter.h",
       "chromeos/login/test/oobe_screen_waiter.cc",
       "chromeos/login/test/oobe_screen_waiter.h",
       "chromeos/login/ui/fake_login_display_host.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index dbbcbf2..e61cd91 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1733,6 +1733,10 @@
     {"isolate-origins", flag_descriptions::kIsolateOriginsName,
      flag_descriptions::kIsolateOriginsDescription, kOsAll,
      ORIGIN_LIST_VALUE_TYPE(switches::kIsolateOrigins, "")},
+    {"kids-management-url-classification",
+     flag_descriptions::kKidsManagementUrlClassificationName,
+     flag_descriptions::kKidsManagementUrlClassificationDescription, kOsAll,
+     FEATURE_VALUE_TYPE(features::kKidsManagementUrlClassification)},
     {"site-isolation-trial-opt-out",
      flag_descriptions::kSiteIsolationOptOutName,
      flag_descriptions::kSiteIsolationOptOutDescription, kOsAll,
@@ -3387,6 +3391,12 @@
      FEATURE_VALUE_TYPE(app_list_features::kEnableAppGridGhost)},
 #endif  // OS_CHROMEOS
 
+    {"enable-accessibility-image-descriptions",
+     flag_descriptions::kEnableAccessibilityImageDescriptionsName,
+     flag_descriptions::kEnableAccessibilityImageDescriptionsDescription,
+     kOsDesktop,
+     FEATURE_VALUE_TYPE(features::kExperimentalAccessibilityLabels)},
+
     {"enable-accessibility-object-model",
      flag_descriptions::kEnableAccessibilityObjectModelName,
      flag_descriptions::kEnableAccessibilityObjectModelDescription, kOsAll,
@@ -3810,7 +3820,8 @@
     {"enable-safe-browsing-ap-download-verdicts",
      flag_descriptions::kSafeBrowsingUseAPDownloadVerdictsName,
      flag_descriptions::kSafeBrowsingUseAPDownloadVerdictsDescription,
-     kOsDesktop, FEATURE_VALUE_TYPE(safe_browsing::kUseAPDownloadProtection)},
+     kOsDesktop,
+     FEATURE_VALUE_TYPE(safe_browsing::kForceUseAPDownloadProtection)},
     {"enable-autocomplete-data-retention-policy",
      flag_descriptions::kEnableAutocompleteDataRetentionPolicyName,
      flag_descriptions::kEnableAutocompleteDataRetentionPolicyDescription,
diff --git a/chrome/browser/accessibility/accessibility_extension_api.cc b/chrome/browser/accessibility/accessibility_extension_api.cc
index c692768..9862d5b 100644
--- a/chrome/browser/accessibility/accessibility_extension_api.cc
+++ b/chrome/browser/accessibility/accessibility_extension_api.cc
@@ -497,4 +497,16 @@
   controller_.reset();
 }
 
+ExtensionFunction::ResponseAction
+AccessibilityPrivateSetVirtualKeyboardVisibleFunction::Run() {
+  std::unique_ptr<accessibility_private::SetVirtualKeyboardVisible::Params>
+      params = accessibility_private::SetVirtualKeyboardVisible::Params::Create(
+          *args_);
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  GetAccessibilityController()->SetVirtualKeyboardVisible(params->is_visible);
+
+  return RespondNow(NoArguments());
+}
+
 #endif  // defined (OS_CHROMEOS)
diff --git a/chrome/browser/accessibility/accessibility_extension_api.h b/chrome/browser/accessibility/accessibility_extension_api.h
index db273888c..36bb5d7b 100644
--- a/chrome/browser/accessibility/accessibility_extension_api.h
+++ b/chrome/browser/accessibility/accessibility_extension_api.h
@@ -164,6 +164,14 @@
   ash::mojom::AccessibilityControllerPtr controller_ = nullptr;
 };
 
+// API function that opens or closes the virtual keyboard.
+class AccessibilityPrivateSetVirtualKeyboardVisibleFunction
+    : public UIThreadExtensionFunction {
+  ~AccessibilityPrivateSetVirtualKeyboardVisibleFunction() override {}
+  ResponseAction Run() override;
+  DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.setVirtualKeyboardVisible",
+                             ACCESSIBILITY_PRIVATE_SETVIRTUALKEYBOARDVISIBLE)
+};
 #endif  // defined (OS_CHROMEOS)
 
 #endif  // CHROME_BROWSER_ACCESSIBILITY_ACCESSIBILITY_EXTENSION_API_H_
diff --git a/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc b/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc
index 776d18c..929dcce 100644
--- a/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc
+++ b/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc
@@ -116,8 +116,8 @@
   // We can skip transcoding here because this method is used in java as
   // ImageFetcher.fetchGif, which decodes the data in a Java-only library.
   params.set_skip_transcoding(true);
-  // TODO(wylieb): We checked disk in Java, so provide a way to tell
-  // ImageFetcher to skip checking disk in native.
+  // We checked disk in Java, so we can skip it for native.
+  params.set_skip_disk_cache_read(true);
   image_fetcher_service_
       ->GetImageFetcher(image_fetcher::ImageFetcherConfig::kDiskCacheOnly)
       ->FetchImageData(GURL(url),
@@ -140,8 +140,8 @@
       base::android::ConvertJavaStringToUTF8(j_client_name);
 
   ImageFetcherParams params(kTrafficAnnotation, client_name);
-  // TODO(wylieb): We checked disk in Java, so provide a way to tell
-  // ImageFetcher to skip checking disk in native.
+  // We checked disk in Java, so we can skip it for native.
+  params.set_skip_disk_cache_read(true);
   image_fetcher_service_->GetImageFetcher(config)->FetchImage(
       GURL(url),
       base::BindOnce(&ImageFetcherBridge::OnImageFetched,
diff --git a/chrome/browser/android/shortcut_helper.cc b/chrome/browser/android/shortcut_helper.cc
index 003c314..6b5d8cc2 100644
--- a/chrome/browser/android/shortcut_helper.cc
+++ b/chrome/browser/android/shortcut_helper.cc
@@ -324,15 +324,6 @@
              ->IsInstallInProgress(manifest_url);
 }
 
-GURL ShortcutHelper::GetScopeFromURL(const GURL& url) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> java_url =
-      base::android::ConvertUTF8ToJavaString(env, url.spec());
-  ScopedJavaLocalRef<jstring> java_scope_url =
-      Java_ShortcutHelper_getScopeFromUrl(env, java_url);
-  return GURL(base::android::ConvertJavaStringToUTF16(env, java_scope_url));
-}
-
 void ShortcutHelper::RetrieveWebApks(const WebApkInfoCallback& callback) {
   uintptr_t callback_pointer =
       reinterpret_cast<uintptr_t>(new WebApkInfoCallback(callback));
diff --git a/chrome/browser/android/shortcut_helper.h b/chrome/browser/android/shortcut_helper.h
index c1d1656..3edc5160 100644
--- a/chrome/browser/android/shortcut_helper.h
+++ b/chrome/browser/android/shortcut_helper.h
@@ -100,10 +100,6 @@
                                 const GURL& start_url,
                                 const GURL& manifest_url);
 
-  // Generates a scope URL based on the passed in |url|. It should be used
-  // when the Web Manifest does not specify a scope URL.
-  static GURL GetScopeFromURL(const GURL& url);
-
   // Fetches information on all the WebAPKs installed on the device and returns
   // the info to the |callback|.
   static void RetrieveWebApks(const WebApkInfoCallback& callback);
diff --git a/chrome/browser/android/shortcut_info.cc b/chrome/browser/android/shortcut_info.cc
index 322a4775..b7a73e1 100644
--- a/chrome/browser/android/shortcut_info.cc
+++ b/chrome/browser/android/shortcut_info.cc
@@ -53,8 +53,7 @@
   if (manifest.start_url.is_valid())
     url = manifest.start_url;
 
-  if (manifest.scope.is_valid())
-    scope = manifest.scope;
+  scope = manifest.scope;
 
   // Set the display based on the manifest value, if any.
   if (manifest.display != blink::kWebDisplayModeUndefined)
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device.cc b/chrome/browser/android/vr/arcore_device/arcore_device.cc
index 9e1ac6d..fdc03ed 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_device.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_device.cc
@@ -94,7 +94,15 @@
     : ArCoreDevice(std::make_unique<ArCoreImplFactory>(),
                    std::make_unique<ArImageTransportFactory>(),
                    std::make_unique<vr::MailboxToSurfaceBridge>(),
-                   std::make_unique<vr::ArCoreJavaUtils>(this),
+                   std::make_unique<vr::ArCoreJavaUtils>(
+                       base::BindRepeating(
+                           &ArCoreDevice::OnRequestInstallArModuleResult,
+                           base::Unretained(
+                               this)),  // unretained is fine since ArCoreDevice
+                                        // owns the ArCoreJavaUtils instance
+                       base::BindRepeating(
+                           &ArCoreDevice::OnRequestInstallSupportedArCoreResult,
+                           base::Unretained(this))),  // ditto
                    std::make_unique<ArCorePermissionHelper>()) {}
 
 ArCoreDevice::~ArCoreDevice() {
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device.h b/chrome/browser/android/vr/arcore_device/arcore_device.h
index f62d33a1..583e74a6 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_device.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_device.h
@@ -49,12 +49,10 @@
     return weak_ptr_factory_.GetWeakPtr();
   }
 
-  // TODO(crbug.com/893348): these should not be public.
-  // Use callbacks instead.
+ private:
   void OnRequestInstallArModuleResult(bool success);
   void OnRequestInstallSupportedArCoreResult(bool success);
 
- private:
   // VRDeviceBase implementation
   void OnMailboxBridgeReady();
   void OnArCoreGlThreadInitialized();
diff --git a/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc b/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc
index 9b32de40..c461e2d 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc
@@ -6,7 +6,6 @@
 
 #include "base/android/jni_string.h"
 #include "chrome/browser/android/tab_android.h"
-#include "chrome/browser/android/vr/arcore_device/arcore_device.h"
 #include "chrome/browser/android/vr/arcore_device/arcore_device_provider.h"
 #include "chrome/browser/android/vr/arcore_device/arcore_shim.h"
 #include "content/public/browser/render_frame_host.h"
@@ -39,10 +38,11 @@
 
 }  // namespace
 
-ArCoreJavaUtils::ArCoreJavaUtils(device::ArCoreDevice* arcore_device)
-    : arcore_device_(arcore_device) {
-  DCHECK(arcore_device_);
-
+ArCoreJavaUtils::ArCoreJavaUtils(
+    base::RepeatingCallback<void(bool)> ar_module_installation_callback,
+    base::RepeatingCallback<void(bool)> ar_core_installation_callback)
+    : ar_module_installation_callback_(ar_module_installation_callback),
+      ar_core_installation_callback_(ar_core_installation_callback) {
   JNIEnv* env = AttachCurrentThread();
   if (!env)
     return;
@@ -62,8 +62,7 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& obj,
     bool success) {
-  // TODO(crbug.com/893348): don't reach back into arcore device like this.
-  arcore_device_->OnRequestInstallSupportedArCoreResult(success);
+  ar_core_installation_callback_.Run(success);
 }
 
 bool ArCoreJavaUtils::CanRequestInstallArModule() {
@@ -103,8 +102,7 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& obj,
     bool success) {
-  // TODO(crbug.com/893348): don't reach back into arcore device like this.
-  arcore_device_->OnRequestInstallArModuleResult(success);
+  ar_module_installation_callback_.Run(success);
 }
 
 bool ArCoreJavaUtils::EnsureLoaded() {
diff --git a/chrome/browser/android/vr/arcore_device/arcore_java_utils.h b/chrome/browser/android/vr/arcore_device/arcore_java_utils.h
index 96208b8..5920f64 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_java_utils.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_java_utils.h
@@ -7,18 +7,17 @@
 
 #include <jni.h>
 #include "base/android/scoped_java_ref.h"
+#include "base/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/android/vr/arcore_device/arcore_install_utils.h"
 
-namespace device {
-class ArCoreDevice;
-}
-
 namespace vr {
 
 class ArCoreJavaUtils : public ArCoreInstallUtils {
  public:
-  explicit ArCoreJavaUtils(device::ArCoreDevice* arcore_device);
+  explicit ArCoreJavaUtils(
+      base::RepeatingCallback<void(bool)> ar_module_installation_callback,
+      base::RepeatingCallback<void(bool)> ar_core_installation_callback);
   ~ArCoreJavaUtils() override;
   bool ShouldRequestInstallArModule() override;
   bool CanRequestInstallArModule() override;
@@ -46,7 +45,9 @@
       int render_process_id,
       int render_frame_id);
 
-  device::ArCoreDevice* arcore_device_;
+  base::RepeatingCallback<void(bool)> ar_module_installation_callback_;
+  base::RepeatingCallback<void(bool)> ar_core_installation_callback_;
+
   base::android::ScopedJavaGlobalRef<jobject> j_arcore_java_utils_;
 };
 
diff --git a/chrome/browser/android/webapk/webapk_installer.cc b/chrome/browser/android/webapk/webapk_installer.cc
index 76be59e3..2f74028 100644
--- a/chrome/browser/android/webapk/webapk_installer.cc
+++ b/chrome/browser/android/webapk/webapk_installer.cc
@@ -109,13 +109,6 @@
                                      : GURL(kDefaultServerUrl);
 }
 
-// Returns the scope from |info| if it is specified. Otherwise, returns the
-// default scope.
-GURL GetScope(const ShortcutInfo& info) {
-  return (info.scope.is_valid()) ? info.scope
-                                 : ShortcutHelper::GetScopeFromURL(info.url);
-}
-
 webapk::WebApk_UpdateReason ConvertUpdateReasonToProtoEnum(
     WebApkUpdateReason update_reason) {
   switch (update_reason) {
@@ -212,7 +205,7 @@
       OptionalSkColorToString(shortcut_info.theme_color));
 
   std::string* scope = web_app_manifest->add_scopes();
-  scope->assign(GetScope(shortcut_info).spec());
+  scope->assign(shortcut_info.scope.spec());
 
   if (shortcut_info.share_target) {
     webapk::ShareTarget* share_target = web_app_manifest->add_share_targets();
diff --git a/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
index bcdd142..68d235c 100644
--- a/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
+++ b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/common/chrome_paths.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "components/arc/arc_service_manager.h"
 #include "components/arc/arc_util.h"
@@ -57,11 +56,9 @@
   void SetUpInProcessBrowserTestFixture() override {
     extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture();
     arc::ArcSessionManager::SetUiEnabledForTesting(false);
-    std::unique_ptr<chromeos::FakeSessionManagerClient> session_manager_client =
-        std::make_unique<chromeos::FakeSessionManagerClient>();
-    session_manager_client->set_arc_available(true);
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::move(session_manager_client));
+    // SessionManagerClient will be destroyed in ChromeBrowserMain.
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    chromeos::FakeSessionManagerClient::Get()->set_arc_available(true);
   }
 
   void SetUpOnMainThread() override {
diff --git a/chrome/browser/apps/platform_apps/shortcut_manager.cc b/chrome/browser/apps/platform_apps/shortcut_manager.cc
index 7acc62e..e675b62 100644
--- a/chrome/browser/apps/platform_apps/shortcut_manager.cc
+++ b/chrome/browser/apps/platform_apps/shortcut_manager.cc
@@ -8,6 +8,7 @@
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
+#include "base/one_shot_event.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
@@ -28,7 +29,6 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension_set.h"
-#include "extensions/common/one_shot_event.h"
 
 using extensions::Extension;
 
@@ -84,8 +84,8 @@
   // UpdateShortcutsForAllAppsIfNeeded.
   extensions::ExtensionSystem::Get(profile)->ready().Post(
       FROM_HERE,
-      base::Bind(&AppShortcutManager::UpdateShortcutsForAllAppsIfNeeded,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindOnce(&AppShortcutManager::UpdateShortcutsForAllAppsIfNeeded,
+                     weak_ptr_factory_.GetWeakPtr()));
 
   ProfileManager* profile_manager = g_browser_process->profile_manager();
   // profile_manager might be NULL in testing environments.
diff --git a/chrome/browser/background/background_application_list_model.cc b/chrome/browser/background/background_application_list_model.cc
index 84bccb3c..b7c54661 100644
--- a/chrome/browser/background/background_application_list_model.cc
+++ b/chrome/browser/background/background_application_list_model.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/one_shot_event.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/background/background_contents_service.h"
@@ -33,7 +34,6 @@
 #include "extensions/common/extension_set.h"
 #include "extensions/common/manifest_handlers/background_info.h"
 #include "extensions/common/manifest_handlers/icons_handler.h"
-#include "extensions/common/one_shot_event.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/permissions/permissions_data.h"
 #include "ui/base/l10n/l10n_util_collator.h"
@@ -159,8 +159,8 @@
                  content::Source<Profile>(profile));
   extensions::ExtensionSystem::Get(profile_)->ready().Post(
       FROM_HERE,
-      base::Bind(&BackgroundApplicationListModel::OnExtensionSystemReady,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindOnce(&BackgroundApplicationListModel::OnExtensionSystemReady,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 void BackgroundApplicationListModel::AddObserver(Observer* observer) {
diff --git a/chrome/browser/background/background_contents_service.cc b/chrome/browser/background/background_contents_service.cc
index f8c67a1..b97054aa 100644
--- a/chrome/browser/background/background_contents_service.cc
+++ b/chrome/browser/background/background_contents_service.cc
@@ -12,6 +12,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/one_shot_event.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -49,7 +50,6 @@
 #include "extensions/common/extension_set.h"
 #include "extensions/common/manifest_handlers/background_info.h"
 #include "extensions/common/manifest_handlers/icons_handler.h"
-#include "extensions/common/one_shot_event.h"
 #include "extensions/grit/extensions_browser_resources.h"
 #include "ipc/ipc_message.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -304,8 +304,9 @@
 void BackgroundContentsService::StartObserving(Profile* profile) {
   // On startup, load our background pages after extension-apps have loaded.
   extensions::ExtensionSystem::Get(profile)->ready().Post(
-      FROM_HERE, base::Bind(&BackgroundContentsService::OnExtensionSystemReady,
-                            weak_ptr_factory_.GetWeakPtr(), profile));
+      FROM_HERE,
+      base::BindOnce(&BackgroundContentsService::OnExtensionSystemReady,
+                     weak_ptr_factory_.GetWeakPtr(), profile));
 
   // Track the lifecycle of all BackgroundContents in the system to allow us
   // to store an up-to-date list of the urls. Start tracking contents when they
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc
index 6c7273c..a23bde0 100644
--- a/chrome/browser/background/background_mode_manager.cc
+++ b/chrome/browser/background/background_mode_manager.cc
@@ -19,6 +19,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
+#include "base/one_shot_event.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -64,7 +65,6 @@
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest_handlers/options_page_info.h"
-#include "extensions/common/one_shot_event.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -376,9 +376,8 @@
   // loaded, to handle the case where an extension has been manually removed
   // while Chrome was not running.
   extensions::ExtensionSystem::Get(profile)->ready().Post(
-      FROM_HERE,
-      base::Bind(&BackgroundModeManager::OnExtensionsReady,
-        weak_factory_.GetWeakPtr(), profile));
+      FROM_HERE, base::BindOnce(&BackgroundModeManager::OnExtensionsReady,
+                                weak_factory_.GetWeakPtr(), profile));
 
   bmd_ptr->applications()->AddObserver(this);
 
diff --git a/chrome/browser/banners/app_banner_manager_android.cc b/chrome/browser/banners/app_banner_manager_android.cc
index efb53ae..4d3b7053 100644
--- a/chrome/browser/banners/app_banner_manager_android.cc
+++ b/chrome/browser/banners/app_banner_manager_android.cc
@@ -7,6 +7,7 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/android/shortcut_helper.h"
 #include "chrome/browser/android/tab_android.h"
@@ -17,6 +18,7 @@
 #include "chrome/browser/banners/app_banner_settings_helper.h"
 #include "chrome/browser/banners/app_banner_ui_delegate_android.h"
 #include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/common/chrome_features.h"
 #include "components/infobars/core/infobar.h"
 #include "components/infobars/core/infobar_delegate.h"
 #include "content/public/browser/manifest_icon_downloader.h"
@@ -384,6 +386,9 @@
 }
 
 void AppBannerManagerAndroid::MaybeShowAmbientBadge() {
+  if (!base::FeatureList::IsEnabled(features::kInstallableAmbientBadgeInfoBar))
+    return;
+
   // Do not show the ambient badge if it was recently dismissed.
   if (AppBannerSettingsHelper::WasBannerRecentlyBlocked(
           web_contents(), validated_url_, GetAppIdentifier(),
diff --git a/chrome/browser/banners/app_banner_manager_desktop.cc b/chrome/browser/banners/app_banner_manager_desktop.cc
index 821d627..2e6523e 100644
--- a/chrome/browser/banners/app_banner_manager_desktop.cc
+++ b/chrome/browser/banners/app_banner_manager_desktop.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/browser/web_applications/extensions/bookmark_app_util.h"
 #include "chrome/common/chrome_features.h"
-#include "chrome/common/web_application_info.h"
 #include "extensions/common/constants.h"
 
 namespace {
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index b32fecd7..ba0b51fb 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -87,11 +87,11 @@
     "//chromeos/components/tether",
     "//chromeos/cryptohome",
     "//chromeos/dbus",
-    "//chromeos/dbus:authpolicy_proto",
-    "//chromeos/dbus:login_manager_proto",
     "//chromeos/dbus:metrics_event_proto",
     "//chromeos/dbus:oobe_config_proto",
     "//chromeos/dbus:plugin_vm_service_proto",
+    "//chromeos/dbus/auth_policy",
+    "//chromeos/dbus/auth_policy:authpolicy_proto",
     "//chromeos/dbus/biod",
     "//chromeos/dbus/constants",
     "//chromeos/dbus/cryptohome",
@@ -103,7 +103,10 @@
     "//chromeos/dbus/media_analytics",
     "//chromeos/dbus/media_analytics:media_perception_proto",
     "//chromeos/dbus/services:services",
+    "//chromeos/dbus/session_manager",
+    "//chromeos/dbus/session_manager:login_manager_proto",
     "//chromeos/dbus/system_clock",
+    "//chromeos/dbus/upstart",
     "//chromeos/disks",
     "//chromeos/geolocation",
     "//chromeos/login/auth",
@@ -240,6 +243,7 @@
     "//ui/aura",
     "//ui/base",
     "//ui/base/idle",
+    "//ui/base/ime/chromeos",
     "//ui/chromeos",
     "//ui/chromeos/events",
     "//ui/compositor",
@@ -470,6 +474,8 @@
     "arc/fileapi/arc_content_file_system_backend_delegate.h",
     "arc/fileapi/arc_content_file_system_file_stream_reader.cc",
     "arc/fileapi/arc_content_file_system_file_stream_reader.h",
+    "arc/fileapi/arc_content_file_system_file_stream_writer.cc",
+    "arc/fileapi/arc_content_file_system_file_stream_writer.h",
     "arc/fileapi/arc_content_file_system_url_util.cc",
     "arc/fileapi/arc_content_file_system_url_util.h",
     "arc/fileapi/arc_documents_provider_async_file_util.cc",
@@ -478,6 +484,8 @@
     "arc/fileapi/arc_documents_provider_backend_delegate.h",
     "arc/fileapi/arc_documents_provider_file_stream_reader.cc",
     "arc/fileapi/arc_documents_provider_file_stream_reader.h",
+    "arc/fileapi/arc_documents_provider_file_stream_writer.cc",
+    "arc/fileapi/arc_documents_provider_file_stream_writer.h",
     "arc/fileapi/arc_documents_provider_root.cc",
     "arc/fileapi/arc_documents_provider_root.h",
     "arc/fileapi/arc_documents_provider_root_map.cc",
@@ -564,6 +572,10 @@
     "arc/screen_capture/arc_screen_capture_bridge.h",
     "arc/screen_capture/arc_screen_capture_session.cc",
     "arc/screen_capture/arc_screen_capture_session.h",
+    "arc/tracing/arc_cpu_event.cc",
+    "arc/tracing/arc_cpu_event.h",
+    "arc/tracing/arc_cpu_model.cc",
+    "arc/tracing/arc_cpu_model.h",
     "arc/tracing/arc_graphics_jank_detector.cc",
     "arc/tracing/arc_graphics_jank_detector.h",
     "arc/tracing/arc_tracing_bridge.cc",
@@ -2138,6 +2150,7 @@
     "login/test/test_condition_waiter.h",
     "login/test/test_predicate_waiter.cc",
     "login/test/test_predicate_waiter.h",
+    "printing/printing_fakes.h",
     "scoped_set_running_on_chromeos_for_testing.cc",
     "scoped_set_running_on_chromeos_for_testing.h",
     "settings/scoped_testing_cros_settings.cc",
@@ -2210,6 +2223,7 @@
     "arc/file_system_watcher/arc_file_system_watcher_service_unittest.cc",
     "arc/fileapi/arc_content_file_system_async_file_util_unittest.cc",
     "arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc",
+    "arc/fileapi/arc_content_file_system_file_stream_writer_unittest.cc",
     "arc/fileapi/arc_content_file_system_url_util_unittest.cc",
     "arc/fileapi/arc_documents_provider_root_unittest.cc",
     "arc/fileapi/arc_documents_provider_util_unittest.cc",
@@ -2233,6 +2247,7 @@
     "arc/pip/arc_pip_bridge_unittest.cc",
     "arc/policy/arc_policy_bridge_unittest.cc",
     "arc/process/arc_process_unittest.cc",
+    "arc/tracing/arc_cpu_event_unittest.cc",
     "arc/tracing/arc_graphics_jank_detector_unittest.cc",
     "arc/tracing/arc_tracing_model_unittest.cc",
     "arc/tts/arc_tts_service_unittest.cc",
@@ -2616,7 +2631,6 @@
     "//chrome/common",
     "//chromeos/components/multidevice:test_support",
     "//chromeos/components/tether:test_support",
-    "//chromeos/dbus:login_manager_proto",
     "//chromeos/dbus:test_support",
     "//chromeos/dbus/services:test_support",
     "//chromeos/ime:gencode",
@@ -2650,7 +2664,8 @@
     "//third_party/blink/public:blink_headers",
     "//third_party/icu",
     "//third_party/leveldatabase",
-    "//ui/base/ime",
+    "//ui/base/ime/chromeos",
+    "//ui/base/ime/init",
     "//ui/chromeos/resources",
   ]
   data = [
diff --git a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc
index 0185f82..128264e 100644
--- a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc
+++ b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc
@@ -13,6 +13,7 @@
 #include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
+#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_applications/components/install_options.h"
@@ -23,6 +24,8 @@
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/storage_partition.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/browser/uninstall_reason.h"
 #include "net/base/url_util.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
 #include "url/gurl.h"
@@ -62,6 +65,17 @@
       ->GetCookieManagerForBrowserProcess();
 }
 
+bool AndroidSmsAppSetupControllerImpl::PwaDelegate::RemovePwa(
+    const extensions::ExtensionId& extension_id,
+    base::string16* error,
+    Profile* profile) {
+  return extensions::ExtensionSystem::Get(profile)
+      ->extension_service()
+      ->UninstallExtension(
+          extension_id,
+          extensions::UNINSTALL_REASON_ORPHANED_EXTERNAL_EXTENSION, error);
+}
+
 AndroidSmsAppSetupControllerImpl::AndroidSmsAppSetupControllerImpl(
     Profile* profile,
     web_app::PendingAppManager* pending_app_manager,
@@ -129,30 +143,37 @@
     const GURL& install_url,
     const GURL& migrated_to_app_url,
     SuccessCallback callback) {
+  const extensions::Extension* extension =
+      pwa_delegate_->GetPwaForUrl(install_url, profile_);
+
   // If there is no app installed at |url|, there is nothing more to do.
-  if (!pwa_delegate_->GetPwaForUrl(install_url, profile_)) {
+  if (!extension) {
     PA_LOG(VERBOSE) << "AndroidSmsAppSetupControllerImpl::RemoveApp(): No app "
                     << "is installed at " << install_url
-                    << "; skipping removal "
-                    << "process.";
+                    << "; skipping removal process.";
     std::move(callback).Run(true /* success */);
     return;
   }
 
   PA_LOG(INFO) << "AndroidSmsAppSetupControllerImpl::RemoveApp(): "
                << "Uninstalling app at " << install_url << ".";
-  // UninstallApps() takes a base::RepeatedCallback, but |callback| is a
-  // base::OnceCallback; thus, |callback| cannot be included in the closure
-  // because it has move-only semantics. Assign this uninstall attempt an ID
-  // associated with |callback| so that it can be retrieved in
-  // OnAppUninstallResult().
-  auto id = base::UnguessableToken::Create();
-  uninstall_id_to_callback_map_.emplace(id, std::move(callback));
-  pending_app_manager_->UninstallApps(
-      std::vector<GURL>{install_url},
-      base::BindRepeating(
-          &AndroidSmsAppSetupControllerImpl::OnAppUninstallResult,
-          weak_ptr_factory_.GetWeakPtr(), id, app_url, migrated_to_app_url));
+
+  const extensions::ExtensionId& extension_id = extension->id();
+  base::string16 error;
+  bool uninstalled_successfully =
+      pwa_delegate_->RemovePwa(extension_id, &error, profile_);
+  UMA_HISTOGRAM_BOOLEAN("AndroidSms.PWAUninstallationResult",
+                        uninstalled_successfully);
+
+  if (!uninstalled_successfully) {
+    PA_LOG(ERROR) << "AndroidSmsAppSetupControllerImpl::RemoveApp(): "
+                  << "PWA for " << install_url << " failed to uninstall. "
+                  << error;
+    std::move(callback).Run(false /* success */);
+    return;
+  }
+
+  SetMigrationCookie(app_url, migrated_to_app_url, std::move(callback));
 }
 
 void AndroidSmsAppSetupControllerImpl::OnSetRememberDeviceByDefaultCookieResult(
@@ -244,28 +265,10 @@
   std::move(callback).Run(true /* success */);
 }
 
-void AndroidSmsAppSetupControllerImpl::OnAppUninstallResult(
-    const base::UnguessableToken& id,
+void AndroidSmsAppSetupControllerImpl::SetMigrationCookie(
     const GURL& app_url,
     const GURL& migrated_to_app_url,
-    const GURL& install_url,
-    bool succeeded) {
-  UMA_HISTOGRAM_BOOLEAN("AndroidSms.PWAUninstallationResult", succeeded);
-
-  // OnAppUninstallResult() should only be called once per ID, so the uninstall
-  // callback is always expected to exist in the map.
-  SuccessCallback callback = std::move(uninstall_id_to_callback_map_[id]);
-  CHECK(callback);
-  uninstall_id_to_callback_map_.erase(id);
-
-  if (!succeeded) {
-    PA_LOG(ERROR)
-        << "AndroidSmsAppSetupControllerImpl::OnAppUninstallResult(): "
-        << "PWA for " << install_url << " failed to uninstall.";
-    std::move(callback).Run(false /* success */);
-    return;
-  }
-
+    SuccessCallback callback) {
   // Set migration cookie on the client for which the PWA was just uninstalled.
   // The client checks for this cookie to redirect users to the new domain. This
   // prevents unwanted connection stealing between old and new clients should
diff --git a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.h b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.h
index 12c9724..10308d048 100644
--- a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.h
+++ b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.h
@@ -9,6 +9,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/unguessable_token.h"
 #include "chrome/browser/chromeos/android_sms/android_sms_app_setup_controller.h"
+#include "extensions/common/extension_id.h"
 #include "net/cookies/canonical_cookie.h"
 #include "url/gurl.h"
 
@@ -52,6 +53,10 @@
                                                       Profile* profile);
     virtual network::mojom::CookieManager* GetCookieManager(const GURL& app_url,
                                                             Profile* profile);
+    // |error| will contain the failure reason if RemovePwa returns false.
+    virtual bool RemovePwa(const extensions::ExtensionId& extension_id,
+                           base::string16* error,
+                           Profile* profile);
   };
 
   // AndroidSmsAppSetupController:
@@ -80,11 +85,9 @@
                           const GURL& app_url,
                           const GURL& install_url,
                           web_app::InstallResultCode code);
-  void OnAppUninstallResult(const base::UnguessableToken& id,
-                            const GURL& app_url,
-                            const GURL& migrated_to_app_url,
-                            const GURL& install_url,
-                            bool succeeded);
+  void SetMigrationCookie(const GURL& app_url,
+                          const GURL& migrated_to_app_url,
+                          SuccessCallback callback);
   void OnDeleteRememberDeviceByDefaultCookieResult(const GURL& app_url,
                                                    SuccessCallback callback,
                                                    uint32_t num_deleted);
@@ -100,8 +103,6 @@
   HostContentSettingsMap* host_content_settings_map_;
 
   std::unique_ptr<PwaDelegate> pwa_delegate_;
-  base::flat_map<base::UnguessableToken, SuccessCallback>
-      uninstall_id_to_callback_map_;
   base::WeakPtrFactory<AndroidSmsAppSetupControllerImpl> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(AndroidSmsAppSetupControllerImpl);
diff --git a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl_unittest.cc b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl_unittest.cc
index 18daeb4..105e26b8 100644
--- a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl_unittest.cc
+++ b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl_unittest.cc
@@ -135,13 +135,7 @@
         : fake_cookie_manager_(fake_cookie_manager) {}
     ~TestPwaDelegate() override = default;
 
-    void SetHasPwa(const GURL& url, bool has_pwa) {
-      // If no PWA should exist, erase any existing entry and return.
-      if (!has_pwa) {
-        url_to_pwa_map_.erase(url);
-        return;
-      }
-
+    void SetHasPwa(const GURL& url) {
       // If a PWA already exists for this URL, there is nothing to do.
       if (base::ContainsKey(url_to_pwa_map_, url))
         return;
@@ -168,6 +162,19 @@
       return fake_cookie_manager_;
     }
 
+    bool RemovePwa(const extensions::ExtensionId& extension_id,
+                   base::string16* error,
+                   Profile* profile) override {
+      for (const auto& url_pwa_pair : url_to_pwa_map_) {
+        if (url_pwa_pair.second->id() == extension_id) {
+          url_to_pwa_map_.erase(url_pwa_pair.first);
+          return true;
+        }
+      }
+
+      return false;
+    }
+
    private:
     FakeCookieManager* fake_cookie_manager_;
     base::flat_map<GURL, scoped_refptr<const extensions::Extension>>
@@ -271,13 +278,11 @@
                      const GURL& install_url,
                      const GURL& migrated_to_app_url,
                      size_t num_expected_app_uninstalls) {
-    const auto& uninstall_requests =
-        test_pending_app_manager_->uninstall_requests();
-    size_t num_uninstall_requests_before_call = uninstall_requests.size();
-
     base::RunLoop run_loop;
     base::HistogramTester histogram_tester;
 
+    bool was_installed =
+        test_pwa_delegate_->GetPwaForUrl(install_url, &profile_) != nullptr;
     setup_controller_->RemoveApp(
         app_url, install_url, migrated_to_app_url,
         base::BindOnce(&AndroidSmsAppSetupControllerImplTest::OnRemoveAppResult,
@@ -285,10 +290,8 @@
 
     // If the PWA was already installed at the URL, RemoveApp() should uninstall
     // the it.
-    if (test_pwa_delegate_->GetPwaForUrl(install_url, &profile_)) {
-      EXPECT_EQ(num_uninstall_requests_before_call + 1u,
-                uninstall_requests.size());
-      EXPECT_EQ(install_url, uninstall_requests.back());
+    if (was_installed) {
+      EXPECT_FALSE(test_pwa_delegate()->GetPwaForUrl(install_url, &profile_));
 
       fake_cookie_manager_->InvokePendingSetCanonicalCookieCallback(
           "cros_migrated_to" /* expected_cookie_name */,
@@ -368,14 +371,14 @@
 
 TEST_F(AndroidSmsAppSetupControllerImplTest, SetUpApp_AppAlreadyInstalled) {
   // Start with a PWA already installed at the URL.
-  test_pwa_delegate()->SetHasPwa(GURL(kTestInstallUrl1), true);
+  test_pwa_delegate()->SetHasPwa(GURL(kTestInstallUrl1));
   CallSetUpApp(GURL(kTestUrl1), GURL(kTestInstallUrl1),
                0u /* num_expected_app_installs */);
 }
 
 TEST_F(AndroidSmsAppSetupControllerImplTest, SetUpApp_OtherPwaInstalled) {
   // Start with a PWA already installed at a different URL.
-  test_pwa_delegate()->SetHasPwa(GURL(kTestUrl2), true);
+  test_pwa_delegate()->SetHasPwa(GURL(kTestUrl2));
   CallSetUpApp(GURL(kTestUrl1), GURL(kTestInstallUrl1),
                1u /* num_expected_app_installs */);
 }
@@ -390,20 +393,18 @@
   // Install and remove.
   CallSetUpApp(GURL(kTestUrl1), GURL(kTestInstallUrl1),
                1u /* num_expected_app_installs */);
-  test_pwa_delegate()->SetHasPwa(GURL(kTestInstallUrl1), true);
+  test_pwa_delegate()->SetHasPwa(GURL(kTestInstallUrl1));
   CallRemoveApp(GURL(kTestUrl1), GURL(kTestInstallUrl1),
                 GURL(kTestUrl2) /* migrated_to_app_url */,
                 1u /* num_expected_app_uninstalls */);
-  test_pwa_delegate()->SetHasPwa(GURL(kTestInstallUrl1), false);
 
   // Repeat once more.
   CallSetUpApp(GURL(kTestUrl1), GURL(kTestInstallUrl1),
                1u /* num_expected_app_installs */);
-  test_pwa_delegate()->SetHasPwa(GURL(kTestInstallUrl1), true);
+  test_pwa_delegate()->SetHasPwa(GURL(kTestInstallUrl1));
   CallRemoveApp(GURL(kTestUrl1), GURL(kTestInstallUrl1),
                 GURL(kTestUrl2) /* migrated_to_app_url */,
                 1u /* num_expected_app_uninstalls */);
-  test_pwa_delegate()->SetHasPwa(GURL(kTestInstallUrl1), false);
 }
 
 TEST_F(AndroidSmsAppSetupControllerImplTest, RemoveApp_NoInstalledApp) {
diff --git a/chrome/browser/chromeos/app_mode/arc/DEPS b/chrome/browser/chromeos/app_mode/arc/DEPS
index fa19670..3386e05 100644
--- a/chrome/browser/chromeos/app_mode/arc/DEPS
+++ b/chrome/browser/chromeos/app_mode/arc/DEPS
@@ -1,5 +1,6 @@
 specific_include_rules = {
-  # crbug.com/887156
+  # TODO(mash): Find another way to observe for ARC++ window creation.
+  # https://crbug.com/887156
   "arc_kiosk_app_launcher\.cc": [
     "+ash/shell.h",
   ],
diff --git a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_launcher.cc b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_launcher.cc
index 099d05d..bdd5a0b 100644
--- a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_launcher.cc
+++ b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_launcher.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h"
 #include "components/arc/metrics/arc_metrics_constants.h"
 #include "ui/aura/env.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/events/event_constants.h"
 
 namespace chromeos {
@@ -24,8 +25,10 @@
                                          Delegate* delegate)
     : app_id_(app_id), prefs_(prefs), delegate_(delegate) {
   prefs_->AddObserver(this);
-  // crbug.com/887156
-  ash::Shell::Get()->aura_env()->AddObserver(this);
+  // TODO(mash): Find another way to observe for ARC++ window creation.
+  // https://crbug.com/887156
+  if (!features::IsMultiProcessMash())
+    ash::Shell::Get()->aura_env()->AddObserver(this);
   // Launching the app by app id in landscape mode and in non-touch mode.
   arc::LaunchApp(context, app_id_, ui::EF_NONE,
                  arc::UserInteractionType::NOT_USER_INITIATED);
@@ -91,7 +94,8 @@
 }
 
 void ArcKioskAppLauncher::StopObserving() {
-  ash::Shell::Get()->aura_env()->AddObserver(this);
+  if (!features::IsMultiProcessMash())
+    ash::Shell::Get()->aura_env()->RemoveObserver(this);
   for (auto* window : windows_)
     window->RemoveObserver(this);
   windows_.clear();
diff --git a/chrome/browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc
index a883586..286bc2a 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_crash_restore_browsertest.cc
@@ -24,7 +24,6 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "components/ownership/mock_owner_key_util.h"
 #include "extensions/common/value_builder.h"
@@ -59,7 +58,16 @@
   }
 
   void SetUpInProcessBrowserTestFixture() override {
-    OverrideDevicePolicy();
+    // Override device policy.
+    OwnerSettingsServiceChromeOSFactory::GetInstance()
+        ->SetOwnerKeyUtilForTesting(owner_key_util_);
+    owner_key_util_->SetPublicKeyFromPrivateKey(
+        *device_policy_.GetSigningKey());
+
+    // SessionManagerClient will be destroyed in ChromeBrowserMain.
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    chromeos::FakeSessionManagerClient::Get()->set_device_policy(
+        device_policy_.GetBlob());
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -128,24 +136,10 @@
                     local_state_json.size());
   }
 
-  void OverrideDevicePolicy() {
-    OwnerSettingsServiceChromeOSFactory::GetInstance()
-        ->SetOwnerKeyUtilForTesting(owner_key_util_);
-    owner_key_util_->SetPublicKeyFromPrivateKey(
-        *device_policy_.GetSigningKey());
-
-    session_manager_client_ = new FakeSessionManagerClient;
-    session_manager_client_->set_device_policy(device_policy_.GetBlob());
-
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(session_manager_client_));
-  }
-
   std::string test_app_id_ = kTestKioskApp;
 
   policy::DevicePolicyBuilder device_policy_;
   scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_;
-  FakeSessionManagerClient* session_manager_client_;
   std::unique_ptr<FakeCWS> fake_cws_;
 
   DISALLOW_COPY_AND_ASSIGN(KioskCrashRestoreTest);
diff --git a/chrome/browser/chromeos/arc/arc_play_store_enabled_preference_handler_unittest.cc b/chrome/browser/chromeos/arc/arc_play_store_enabled_preference_handler_unittest.cc
index e1be996..6cc764a 100644
--- a/chrome/browser/chromeos/arc/arc_play_store_enabled_preference_handler_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_play_store_enabled_preference_handler_unittest.cc
@@ -20,8 +20,7 @@
 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "components/arc/arc_prefs.h"
 #include "components/arc/arc_util.h"
@@ -53,9 +52,7 @@
             std::make_unique<chromeos::FakeChromeUserManager>()) {}
 
   void SetUp() override {
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::make_unique<chromeos::FakeSessionManagerClient>());
-    chromeos::DBusThreadManager::Initialize();
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
     chromeos::UpstartClient::InitializeFake();
 
     SetArcAvailableCommandLineForTesting(
@@ -95,7 +92,7 @@
     identity_test_env_profile_adaptor_.reset();
     profile_.reset();
     chromeos::UpstartClient::Shutdown();
-    chromeos::DBusThreadManager::Shutdown();
+    chromeos::SessionManagerClient::Shutdown();
   }
 
   TestingProfile* profile() const { return profile_.get(); }
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc
index 48fb457..43ff86f3 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -83,16 +83,6 @@
   UpdateOptInCancelUMA(OptInCancelReason::USER_CANCEL);
 }
 
-chromeos::SessionManagerClient* GetSessionManagerClient() {
-  // If the DBusThreadManager or the SessionManagerClient aren't available,
-  // there isn't much we can do. This should only happen when running tests.
-  if (!chromeos::DBusThreadManager::IsInitialized() ||
-      !chromeos::DBusThreadManager::Get() ||
-      !chromeos::DBusThreadManager::Get()->GetSessionManagerClient())
-    return nullptr;
-  return chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
-}
-
 // Returns true if launching the Play Store on OptIn succeeded is needed.
 // Launch Play Store app, except for the following cases:
 // * When Opt-in verification is disabled (for tests);
@@ -219,18 +209,16 @@
   DCHECK(!g_arc_session_manager);
   g_arc_session_manager = this;
   arc_session_runner_->AddObserver(this);
-  chromeos::SessionManagerClient* client = GetSessionManagerClient();
-  if (client)
-    client->AddObserver(this);
+  if (chromeos::SessionManagerClient::Get())
+    chromeos::SessionManagerClient::Get()->AddObserver(this);
   ResetStabilityMetrics();
 }
 
 ArcSessionManager::~ArcSessionManager() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  chromeos::SessionManagerClient* client = GetSessionManagerClient();
-  if (client)
-    client->RemoveObserver(this);
+  if (chromeos::SessionManagerClient::Get())
+    chromeos::SessionManagerClient::Get()->RemoveObserver(this);
 
   Shutdown();
   arc_session_runner_->RemoveObserver(this);
diff --git a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
index d553c78..7aa4aa3 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
@@ -40,9 +40,8 @@
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
-#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "components/account_id/account_id.h"
 #include "components/arc/arc_features.h"
@@ -101,8 +100,7 @@
   ArcSessionManagerInLoginScreenTest()
       : user_manager_enabler_(
             std::make_unique<chromeos::FakeChromeUserManager>()) {
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::make_unique<chromeos::FakeSessionManagerClient>());
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
 
     ArcSessionManager::SetUiEnabledForTesting(false);
     SetArcBlockedDueToIncompatibleFileSystemForTesting(false);
@@ -117,7 +115,7 @@
     arc_session_manager_->Shutdown();
     arc_session_manager_.reset();
     arc_service_manager_.reset();
-    chromeos::DBusThreadManager::Shutdown();
+    chromeos::SessionManagerClient::Shutdown();
   }
 
  protected:
@@ -147,9 +145,7 @@
 
   SetArcAvailableCommandLineForTesting(base::CommandLine::ForCurrentProcess());
 
-  chromeos::DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->EmitLoginPromptVisible();
+  chromeos::SessionManagerClient::Get()->EmitLoginPromptVisible();
   ASSERT_TRUE(arc_session());
   EXPECT_FALSE(arc_session()->is_running());
   EXPECT_EQ(ArcSessionManager::State::NOT_INITIALIZED,
@@ -161,9 +157,7 @@
 TEST_F(ArcSessionManagerInLoginScreenTest, EmitLoginPromptVisible_NoOp) {
   EXPECT_FALSE(arc_session());
 
-  chromeos::DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->EmitLoginPromptVisible();
+  chromeos::SessionManagerClient::Get()->EmitLoginPromptVisible();
   EXPECT_FALSE(arc_session());
   EXPECT_EQ(ArcSessionManager::State::NOT_INITIALIZED,
             arc_session_manager()->state());
@@ -178,10 +172,8 @@
   ~ArcSessionManagerTestBase() override = default;
 
   void SetUp() override {
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::make_unique<chromeos::FakeSessionManagerClient>());
-
     chromeos::PowerManagerClient::InitializeFake();
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
     chromeos::UpstartClient::InitializeFake();
 
     SetArcAvailableCommandLineForTesting(
@@ -211,8 +203,8 @@
     arc_session_manager_.reset();
     arc_service_manager_.reset();
     chromeos::UpstartClient::Shutdown();
+    chromeos::SessionManagerClient::Shutdown();
     chromeos::PowerManagerClient::Shutdown();
-    chromeos::DBusThreadManager::Shutdown();
   }
 
   chromeos::FakeChromeUserManager* GetFakeUserManager() const {
diff --git a/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc b/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc
index 0f0cc2f6e5..6a45ddb 100644
--- a/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc
+++ b/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc
@@ -10,6 +10,7 @@
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/one_shot_event.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/arc/boot_phase_monitor/arc_instance_throttle.h"
 #include "chrome/browser/profiles/profile.h"
@@ -25,7 +26,6 @@
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/extension_system_provider.h"
 #include "extensions/browser/extensions_browser_client.h"
-#include "extensions/common/one_shot_event.h"
 
 namespace arc {
 namespace {
@@ -124,8 +124,8 @@
   auto* extension_system = extensions::ExtensionSystem::Get(profile);
   DCHECK(extension_system);
   extension_system->ready().Post(
-      FROM_HERE, base::Bind(&ArcBootPhaseMonitorBridge::OnExtensionsReady,
-                            weak_ptr_factory_.GetWeakPtr()));
+      FROM_HERE, base::BindOnce(&ArcBootPhaseMonitorBridge::OnExtensionsReady,
+                                weak_ptr_factory_.GetWeakPtr()));
 
   // Initialize |enabled_by_policy_| now.
   OnArcPlayStoreEnabledChanged(IsArcPlayStoreEnabledForProfile(profile));
@@ -160,9 +160,7 @@
   VLOG(2) << "OnBootCompleted";
   boot_completed_ = true;
 
-  chromeos::SessionManagerClient* session_manager_client =
-      chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
-  session_manager_client->EmitArcBooted(
+  chromeos::SessionManagerClient::Get()->EmitArcBooted(
       cryptohome::CreateAccountIdentifierFromAccountId(account_id_),
       base::BindOnce(&OnEmitArcBooted));
 
diff --git a/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc b/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc
index 764fbfe3..d88922e5 100644
--- a/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc
+++ b/chrome/browser/chromeos/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc
@@ -12,13 +12,12 @@
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "chrome/test/base/testing_profile.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "components/arc/arc_prefs.h"
 #include "components/arc/arc_service_manager.h"
 #include "components/arc/arc_util.h"
 #include "components/arc/test/fake_arc_session.h"
-#include "components/browser_sync/profile_sync_test_util.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -39,8 +38,7 @@
         testing_profile_(std::make_unique<TestingProfile>()),
         disable_cpu_restriction_counter_(0),
         record_uma_counter_(0) {
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::make_unique<chromeos::FakeSessionManagerClient>());
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
 
     SetArcAvailableCommandLineForTesting(
         base::CommandLine::ForCurrentProcess());
@@ -59,7 +57,7 @@
 
   ~ArcBootPhaseMonitorBridgeTest() override {
     boot_phase_monitor_bridge_->Shutdown();
-    chromeos::DBusThreadManager::Shutdown();
+    chromeos::SessionManagerClient::Shutdown();
   }
 
  protected:
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer.cc b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer.cc
new file mode 100644
index 0000000..7e7d6bf
--- /dev/null
+++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer.cc
@@ -0,0 +1,237 @@
+// Copyright 2019 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/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <utility>
+
+#include "base/files/file.h"
+#include "base/logging.h"
+#include "base/task/post_task.h"
+#include "base/threading/scoped_blocking_call.h"
+#include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/public/cpp/platform/platform_handle.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+
+namespace arc {
+
+namespace {
+
+// Calls base::File::WriteAtCurrentPosNoBestEffort with the given buffer.
+// Returns the number of bytes written, or -1 on error.
+int WriteFile(base::File* file,
+              scoped_refptr<net::IOBuffer> buffer,
+              int buffer_length) {
+  return file->WriteAtCurrentPosNoBestEffort(buffer->data(), buffer_length);
+}
+
+// Seeks the file, returns 0 on success, or errno on an error.
+int SeekFile(base::File* file, size_t offset) {
+  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                base::BlockingType::MAY_BLOCK);
+  // lseek() instead of |file|'s method for errno.
+  off_t result = lseek(file->GetPlatformFile(), offset, SEEK_SET);
+  return result < 0 ? errno : 0;
+}
+
+// Flushes the file, returns 0 on success, or errno on an error.
+int FlushFile(base::File* file) {
+  bool success = file->Flush();
+  return success ? 0 : errno;
+}
+
+}  // namespace
+
+ArcContentFileSystemFileStreamWriter::ArcContentFileSystemFileStreamWriter(
+    const GURL& arc_url,
+    int64_t offset)
+    : arc_url_(arc_url),
+      offset_(offset),
+      task_runner_(base::CreateSequencedTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
+      has_pending_operation_(false),
+      weak_ptr_factory_(this) {}
+
+ArcContentFileSystemFileStreamWriter::~ArcContentFileSystemFileStreamWriter() {
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&base::DeletePointer<base::File>, file_.release()));
+}
+
+int ArcContentFileSystemFileStreamWriter::Write(
+    net::IOBuffer* buffer,
+    int buffer_length,
+    net::CompletionOnceCallback callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  DCHECK(!has_pending_operation_);
+  DCHECK(cancel_callback_.is_null());
+
+  has_pending_operation_ = true;
+  if (file_) {
+    WriteInternal(buffer, buffer_length, std::move(callback));
+    return net::ERR_IO_PENDING;
+  }
+  file_system_operation_runner_util::OpenFileToWriteOnIOThread(
+      arc_url_,
+      base::BindOnce(&ArcContentFileSystemFileStreamWriter::OnOpenFile,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     base::WrapRefCounted(buffer), buffer_length,
+                     std::move(callback)));
+  return net::ERR_IO_PENDING;
+}
+
+int ArcContentFileSystemFileStreamWriter::Cancel(
+    net::CompletionOnceCallback callback) {
+  if (!has_pending_operation_)
+    return net::ERR_UNEXPECTED;
+
+  DCHECK(!callback.is_null());
+  cancel_callback_ = std::move(callback);
+  return net::ERR_IO_PENDING;
+}
+
+int ArcContentFileSystemFileStreamWriter::Flush(
+    net::CompletionOnceCallback callback) {
+  DCHECK(!has_pending_operation_);
+  DCHECK(cancel_callback_.is_null());
+
+  // Write() is not called yet, so there's nothing to flush.
+  if (!file_)
+    return net::OK;
+
+  has_pending_operation_ = true;
+
+  // |file_| is alive on FlushFile(), since the descructor will destruct
+  // |task_runner_| along with |file_| and FlushFile() won't be called.
+  base::PostTaskAndReplyWithResult(
+      task_runner_.get(), FROM_HERE, base::BindOnce(&FlushFile, file_.get()),
+      base::BindOnce(&ArcContentFileSystemFileStreamWriter::OnFlushFile,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  return net::ERR_IO_PENDING;
+}
+
+void ArcContentFileSystemFileStreamWriter::WriteInternal(
+    net::IOBuffer* buffer,
+    int buffer_length,
+    net::CompletionOnceCallback callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  DCHECK(file_);
+  DCHECK(file_->IsValid());
+  DCHECK(has_pending_operation_);
+
+  // |file_| is alive on WriteFile(), since the descructor will destruct
+  // |task_runner_| along with |file_| and WriteFile() won't be called.
+  base::PostTaskAndReplyWithResult(
+      task_runner_.get(), FROM_HERE,
+      base::BindOnce(&WriteFile, file_.get(), base::WrapRefCounted(buffer),
+                     buffer_length),
+      base::BindOnce(&ArcContentFileSystemFileStreamWriter::OnWrite,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void ArcContentFileSystemFileStreamWriter::OnWrite(
+    net::CompletionOnceCallback callback,
+    int result) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  DCHECK(has_pending_operation_);
+
+  if (CancelIfRequested())
+    return;
+
+  has_pending_operation_ = false;
+  std::move(callback).Run(result < 0 ? net::ERR_FAILED : result);
+}
+
+void ArcContentFileSystemFileStreamWriter::OnOpenFile(
+    scoped_refptr<net::IOBuffer> buf,
+    int buffer_length,
+    net::CompletionOnceCallback callback,
+    mojo::ScopedHandle handle) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  DCHECK(!file_);
+  DCHECK(has_pending_operation_);
+
+  if (CancelIfRequested())
+    return;
+
+  mojo::PlatformHandle platform_handle =
+      mojo::UnwrapPlatformHandle(std::move(handle));
+  if (!platform_handle.is_valid()) {
+    has_pending_operation_ = false;
+    LOG(ERROR) << "PassWrappedInternalPlatformHandle failed";
+    std::move(callback).Run(net::ERR_FAILED);
+    return;
+  }
+  file_ = std::make_unique<base::File>(platform_handle.ReleaseFD());
+  DCHECK(file_->IsValid());
+  if (offset_ == 0) {
+    // We can skip the step to seek the file.
+    OnSeekFile(buf, buffer_length, std::move(callback), 0);
+    return;
+  }
+  // |file_| is alive on SeekFile(), since the descructor will destruct
+  // |task_runner_| along with |file_| and SeekFile() won't be called.
+  base::PostTaskAndReplyWithResult(
+      task_runner_.get(), FROM_HERE,
+      base::BindOnce(&SeekFile, file_.get(), offset_),
+      base::BindOnce(&ArcContentFileSystemFileStreamWriter::OnSeekFile,
+                     weak_ptr_factory_.GetWeakPtr(), buf, buffer_length,
+                     std::move(callback)));
+}
+
+void ArcContentFileSystemFileStreamWriter::OnSeekFile(
+    scoped_refptr<net::IOBuffer> buf,
+    int buffer_length,
+    net::CompletionOnceCallback callback,
+    int seek_result) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  DCHECK(file_);
+  DCHECK(file_->IsValid());
+  DCHECK(has_pending_operation_);
+
+  if (CancelIfRequested())
+    return;
+
+  if (seek_result == 0) {
+    // File stream is ready. Resume Write().
+    WriteInternal(buf.get(), buffer_length, std::move(callback));
+  } else {
+    has_pending_operation_ = false;
+    LOG(ERROR) << "Failed to seek: "
+               << logging::SystemErrorCodeToString(seek_result);
+    std::move(callback).Run(
+        net::FileErrorToNetError(base::File::OSErrorToFileError(seek_result)));
+  }
+}
+
+void ArcContentFileSystemFileStreamWriter::OnFlushFile(
+    net::CompletionOnceCallback callback,
+    int flush_result) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  DCHECK(has_pending_operation_);
+
+  if (CancelIfRequested())
+    return;
+  has_pending_operation_ = false;
+  std::move(callback).Run(flush_result);
+}
+
+bool ArcContentFileSystemFileStreamWriter::CancelIfRequested() {
+  DCHECK(has_pending_operation_);
+
+  if (cancel_callback_.is_null())
+    return false;
+
+  has_pending_operation_ = false;
+  std::move(cancel_callback_).Run(net::OK);
+  return true;
+}
+
+}  // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer.h b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer.h
new file mode 100644
index 0000000..3ca6a3e
--- /dev/null
+++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer.h
@@ -0,0 +1,86 @@
+// Copyright 2019 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_CHROMEOS_ARC_FILEAPI_ARC_CONTENT_FILE_SYSTEM_FILE_STREAM_WRITER_H_
+#define CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_CONTENT_FILE_SYSTEM_FILE_STREAM_WRITER_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "mojo/public/cpp/system/handle.h"
+#include "net/base/completion_once_callback.h"
+#include "storage/browser/fileapi/file_stream_writer.h"
+#include "url/gurl.h"
+
+namespace base {
+class File;
+class SequencedTaskRunner;
+}  // namespace base
+
+namespace net {
+class IOBuffer;
+}  // namespace net
+
+namespace arc {
+
+// FileStreamWriter implementation for ARC content file system.
+class ArcContentFileSystemFileStreamWriter : public storage::FileStreamWriter {
+ public:
+  ArcContentFileSystemFileStreamWriter(const GURL& arc_url, int64_t offset);
+  ~ArcContentFileSystemFileStreamWriter() override;
+
+  // storage::FileStreamReader override:
+  int Write(net::IOBuffer* buffer,
+            int bufffer_length,
+            net::CompletionOnceCallback callback) override;
+  int Cancel(net::CompletionOnceCallback callback) override;
+  int Flush(net::CompletionOnceCallback callback) override;
+
+ private:
+  // Actually performs read.
+  void WriteInternal(net::IOBuffer* buffer,
+                     int buffer_length,
+                     net::CompletionOnceCallback callback);
+
+  // Called when read completes.
+  void OnWrite(net::CompletionOnceCallback callback, int result);
+
+  // Called when opening file completes.
+  void OnOpenFile(scoped_refptr<net::IOBuffer> buf,
+                  int buffer_length,
+                  net::CompletionOnceCallback callback,
+                  mojo::ScopedHandle handle);
+
+  // Called when seek completes.
+  void OnSeekFile(scoped_refptr<net::IOBuffer> buf,
+                  int buffer_length,
+                  net::CompletionOnceCallback callback,
+                  int seek_result);
+
+  // Called when flush completes
+  void OnFlushFile(net::CompletionOnceCallback callback, int flush_result);
+
+  // Stops the in-flight operation and calls |cancel_callback_| if it has been
+  // set by Cancel() for the current operation.
+  bool CancelIfRequested();
+
+  const GURL arc_url_;
+  const int64_t offset_;
+
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+  std::unique_ptr<base::File> file_;
+  bool has_pending_operation_;
+  net::CompletionOnceCallback cancel_callback_;
+
+  base::WeakPtrFactory<ArcContentFileSystemFileStreamWriter> weak_ptr_factory_;
+  DISALLOW_COPY_AND_ASSIGN(ArcContentFileSystemFileStreamWriter);
+};
+
+}  // namespace arc
+
+#endif  // CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_CONTENT_FILE_SYSTEM_FILE_STREAM_WRITER_H_
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer_unittest.cc
new file mode 100644
index 0000000..8351510
--- /dev/null
+++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer_unittest.cc
@@ -0,0 +1,214 @@
+// Copyright 2019 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 <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer.h"
+#include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/session/arc_bridge_service.h"
+#include "components/arc/test/connection_holder_util.h"
+#include "components/arc/test/fake_file_system_instance.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
+#include "net/base/io_buffer.h"
+#include "net/base/test_completion_callback.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using File = arc::FakeFileSystemInstance::File;
+
+namespace arc {
+
+namespace {
+
+constexpr char kArcUrlPrefix[] = "content://org.chromium.foo/";
+
+std::unique_ptr<KeyedService> CreateFileSystemOperationRunnerForTesting(
+    content::BrowserContext* context) {
+  return ArcFileSystemOperationRunner::CreateForTesting(
+      context, ArcServiceManager::Get()->arc_bridge_service());
+}
+
+class ArcContentFileSystemFileStreamWriterTest : public testing::Test {
+ public:
+  ArcContentFileSystemFileStreamWriterTest() = default;
+
+  ~ArcContentFileSystemFileStreamWriterTest() override = default;
+
+  void SetUp() override {
+    arc_service_manager_ = std::make_unique<ArcServiceManager>();
+    profile_ = std::make_unique<TestingProfile>();
+    arc_service_manager_->set_browser_context(profile_.get());
+    ArcFileSystemOperationRunner::GetFactory()->SetTestingFactoryAndUse(
+        profile_.get(),
+        base::BindRepeating(&CreateFileSystemOperationRunnerForTesting));
+    arc_service_manager_->arc_bridge_service()->file_system()->SetInstance(
+        &fake_file_system_);
+    WaitForInstanceReady(
+        arc_service_manager_->arc_bridge_service()->file_system());
+  }
+
+  void TearDown() override {
+    arc_service_manager_->arc_bridge_service()->file_system()->CloseInstance(
+        &fake_file_system_);
+  }
+
+ protected:
+  std::string ArcUrl(const std::string& name) { return kArcUrlPrefix + name; }
+
+  int WriteStringToWriter(ArcContentFileSystemFileStreamWriter* writer,
+                          const std::string& data) {
+    scoped_refptr<net::StringIOBuffer> buffer =
+        base::MakeRefCounted<net::StringIOBuffer>(data);
+    scoped_refptr<net::DrainableIOBuffer> drainable =
+        base::MakeRefCounted<net::DrainableIOBuffer>(std::move(buffer),
+                                                     data.size());
+
+    while (drainable->BytesRemaining() > 0) {
+      net::TestCompletionCallback callback;
+      int result = writer->Write(drainable.get(), drainable->BytesRemaining(),
+                                 callback.callback());
+      if (result == net::ERR_IO_PENDING)
+        result = callback.WaitForResult();
+      if (result <= 0)
+        return result;
+      drainable->DidConsume(result);
+    }
+    return net::OK;
+  }
+
+  std::string GetFileContent(const std::string& url) {
+    return fake_file_system_.GetFileContent(url);
+  }
+
+  std::string GetFileContent(const std::string& url, size_t bytes) {
+    return fake_file_system_.GetFileContent(url, bytes);
+  }
+
+  std::string CreateFileWithContent(const std::string& name,
+                                    const std::string& data,
+                                    bool seekable) {
+    std::string file_url = ArcUrl(name);
+    fake_file_system_.AddFile(
+        File(ArcUrl(name), data, "application/octet-stream",
+             seekable ? File::Seekable::YES : File::Seekable::NO));
+    return file_url;
+  }
+
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
+  FakeFileSystemInstance fake_file_system_;
+
+  // Use the same initialization/destruction order as
+  // ChromeBrowserMainPartsChromeos.
+  std::unique_ptr<ArcServiceManager> arc_service_manager_;
+  std::unique_ptr<TestingProfile> profile_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArcContentFileSystemFileStreamWriterTest);
+};
+
+void NeverCalled(int unused) {
+  ADD_FAILURE();
+}
+
+}  // namespace
+
+TEST_F(ArcContentFileSystemFileStreamWriterTest, Write) {
+  std::string url =
+      CreateFileWithContent("file_a", std::string(), true /* seekable */);
+  ArcContentFileSystemFileStreamWriter writer(GURL(url), 0);
+  EXPECT_EQ(net::OK, WriteStringToWriter(&writer, "foo"));
+  EXPECT_EQ(net::OK, WriteStringToWriter(&writer, "bar"));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ("foobar", GetFileContent(url));
+}
+
+TEST_F(ArcContentFileSystemFileStreamWriterTest, WriteMiddle) {
+  std::string url =
+      CreateFileWithContent("file_a", "foobar", true /* seekable */);
+  ArcContentFileSystemFileStreamWriter writer(GURL(url), 2);
+  EXPECT_EQ(net::OK, WriteStringToWriter(&writer, "xxx"));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ("foxxxr", GetFileContent(url));
+}
+
+TEST_F(ArcContentFileSystemFileStreamWriterTest, WriteEnd) {
+  std::string url =
+      CreateFileWithContent("file_a", "foobar", true /* seekable */);
+  ArcContentFileSystemFileStreamWriter writer(GURL(url), 6);
+  EXPECT_EQ(net::OK, WriteStringToWriter(&writer, "xxx"));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ("foobarxxx", GetFileContent(url));
+}
+
+TEST_F(ArcContentFileSystemFileStreamWriterTest, WriteFailForNonexistingFile) {
+  std::string url = ArcUrl("file_a");
+  ArcContentFileSystemFileStreamWriter writer(GURL(url), 0);
+  EXPECT_EQ(net::ERR_FAILED, WriteStringToWriter(&writer, "foo"));
+}
+
+TEST_F(ArcContentFileSystemFileStreamWriterTest, WriteNonSeekable) {
+  std::string url =
+      CreateFileWithContent("file_a", std::string(), false /* not seekable */);
+  ArcContentFileSystemFileStreamWriter writer(GURL(url), 0);
+  EXPECT_EQ(net::OK, WriteStringToWriter(&writer, "foo"));
+  EXPECT_EQ(net::OK, WriteStringToWriter(&writer, "bar"));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ("foobar", GetFileContent(url, 6));
+}
+
+TEST_F(ArcContentFileSystemFileStreamWriterTest, WriteNonSeekableFailForSeek) {
+  std::string url =
+      CreateFileWithContent("file_a", "foobar", false /* not seekable */);
+  ArcContentFileSystemFileStreamWriter writer(GURL(url), 2);
+  EXPECT_EQ(net::ERR_FAILED, WriteStringToWriter(&writer, "xxx"));
+}
+
+TEST_F(ArcContentFileSystemFileStreamWriterTest, CancelBeforeOperation) {
+  std::string url =
+      CreateFileWithContent("file_a", std::string(), true /* seekable */);
+  ArcContentFileSystemFileStreamWriter writer(GURL(url), 0);
+  // Cancel immediately fails when there's no in-flight operation.
+  int cancel_result = writer.Cancel(base::BindOnce(&NeverCalled));
+  EXPECT_EQ(net::ERR_UNEXPECTED, cancel_result);
+}
+
+TEST_F(ArcContentFileSystemFileStreamWriterTest, CancelAfterFinishedOperation) {
+  std::string url =
+      CreateFileWithContent("file_a", std::string(), true /* seekable */);
+  ArcContentFileSystemFileStreamWriter writer(GURL(url), 0);
+  EXPECT_EQ(net::OK, WriteStringToWriter(&writer, "foo"));
+
+  // Cancel immediately fails when there's no in-flight operation.
+  int cancel_result = writer.Cancel(base::BindOnce(&NeverCalled));
+  EXPECT_EQ(net::ERR_UNEXPECTED, cancel_result);
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ("foo", GetFileContent(url, 6));
+}
+
+TEST_F(ArcContentFileSystemFileStreamWriterTest, CancelWrite) {
+  std::string url =
+      CreateFileWithContent("file_a", "foobar", true /* seekable */);
+  ArcContentFileSystemFileStreamWriter writer(GURL(url), 0);
+
+  scoped_refptr<net::StringIOBuffer> buffer(
+      base::MakeRefCounted<net::StringIOBuffer>("xxx"));
+  int result =
+      writer.Write(buffer.get(), buffer->size(), base::BindOnce(&NeverCalled));
+  ASSERT_EQ(net::ERR_IO_PENDING, result);
+
+  net::TestCompletionCallback callback;
+  writer.Cancel(callback.callback());
+  int cancel_result = callback.WaitForResult();
+  EXPECT_EQ(net::OK, cancel_result);
+}
+
+}  // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_backend_delegate.cc b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_backend_delegate.cc
index d9ffa81..b43fc16 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_backend_delegate.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_backend_delegate.cc
@@ -8,6 +8,7 @@
 
 #include "base/logging.h"
 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_file_stream_reader.h"
+#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_file_stream_writer.h"
 #include "content/public/browser/browser_thread.h"
 #include "storage/browser/fileapi/file_stream_reader.h"
 #include "storage/browser/fileapi/file_stream_writer.h"
@@ -48,8 +49,8 @@
     int64_t offset,
     storage::FileSystemContext* context) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  NOTREACHED();  // Read-only file system.
-  return nullptr;
+
+  return std::make_unique<ArcDocumentsProviderFileStreamWriter>(url, offset);
 }
 
 storage::WatcherManager* ArcDocumentsProviderBackendDelegate::GetWatcherManager(
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_file_stream_writer.cc b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_file_stream_writer.cc
new file mode 100644
index 0000000..102d8ee0e
--- /dev/null
+++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_file_stream_writer.cc
@@ -0,0 +1,198 @@
+// Copyright 2019 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/chromeos/arc/fileapi/arc_documents_provider_file_stream_writer.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/task/post_task.h"
+#include "chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_writer.h"
+#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h"
+#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root_map.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "url/gurl.h"
+
+using content::BrowserThread;
+
+namespace arc {
+
+namespace {
+
+void OnResolveToContentUrlOnUIThread(
+    ArcDocumentsProviderRoot::ResolveToContentUrlCallback callback,
+    const GURL& url) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+                           base::BindOnce(std::move(callback), url));
+}
+
+void ResolveToContentUrlOnUIThread(
+    const storage::FileSystemURL& url,
+    ArcDocumentsProviderRoot::ResolveToContentUrlCallback callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  ArcDocumentsProviderRootMap* roots =
+      ArcDocumentsProviderRootMap::GetForArcBrowserContext();
+  if (!roots) {
+    OnResolveToContentUrlOnUIThread(std::move(callback), GURL());
+    return;
+  }
+
+  base::FilePath path;
+  ArcDocumentsProviderRoot* root = roots->ParseAndLookup(url, &path);
+  if (!root) {
+    OnResolveToContentUrlOnUIThread(std::move(callback), GURL());
+    return;
+  }
+
+  root->ResolveToContentUrl(
+      path,
+      base::BindOnce(&OnResolveToContentUrlOnUIThread, std::move(callback)));
+}
+
+}  // namespace
+
+ArcDocumentsProviderFileStreamWriter::ArcDocumentsProviderFileStreamWriter(
+    const storage::FileSystemURL& url,
+    int64_t offset)
+    : offset_(offset),
+      content_url_resolved_(false),
+      arc_url_(url),
+      weak_ptr_factory_(this) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+ArcDocumentsProviderFileStreamWriter::~ArcDocumentsProviderFileStreamWriter() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+}
+
+int ArcDocumentsProviderFileStreamWriter::Write(
+    net::IOBuffer* buffer,
+    int buffer_length,
+    net::CompletionOnceCallback callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (!content_url_resolved_) {
+    pending_operations_.emplace_back(base::BindOnce(
+        &ArcDocumentsProviderFileStreamWriter::RunPendingWrite,
+        weak_ptr_factory_.GetWeakPtr(), base::WrapRefCounted(buffer),
+        buffer_length, std::move(callback)));
+
+    // Resolve the |arc_url_| to a Content URL to instantiate the underlying
+    // writer.
+    base::PostTaskWithTraits(
+        FROM_HERE, {BrowserThread::UI},
+        base::BindOnce(
+            &ResolveToContentUrlOnUIThread, arc_url_,
+            base::BindOnce(
+                &ArcDocumentsProviderFileStreamWriter::OnResolveToContentUrl,
+                weak_ptr_factory_.GetWeakPtr())));
+
+    return net::ERR_IO_PENDING;
+  }
+  if (!underlying_writer_)
+    return net::ERR_FILE_NOT_FOUND;
+  return underlying_writer_->Write(buffer, buffer_length, std::move(callback));
+}
+
+int ArcDocumentsProviderFileStreamWriter::Cancel(
+    net::CompletionOnceCallback callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (!content_url_resolved_) {
+    pending_operations_.emplace_back(
+        base::BindOnce(&ArcDocumentsProviderFileStreamWriter::RunPendingCancel,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+    return net::ERR_IO_PENDING;
+  }
+  if (!underlying_writer_)
+    return net::ERR_FILE_NOT_FOUND;
+  return underlying_writer_->Cancel(std::move(callback));
+}
+
+int ArcDocumentsProviderFileStreamWriter::Flush(
+    net::CompletionOnceCallback callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (!content_url_resolved_) {
+    pending_operations_.emplace_back(
+        base::BindOnce(&ArcDocumentsProviderFileStreamWriter::RunPendingFlush,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+    return net::ERR_IO_PENDING;
+  }
+  if (!underlying_writer_)
+    return net::ERR_FILE_NOT_FOUND;
+  return underlying_writer_->Flush(std::move(callback));
+}
+
+void ArcDocumentsProviderFileStreamWriter::OnResolveToContentUrl(
+    const GURL& content_url) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(!content_url_resolved_);
+
+  if (content_url.is_valid()) {
+    underlying_writer_ = std::make_unique<ArcContentFileSystemFileStreamWriter>(
+        content_url, offset_);
+  }
+  content_url_resolved_ = true;
+
+  std::vector<base::OnceClosure> pending_operations;
+  pending_operations.swap(pending_operations_);
+  for (base::OnceClosure& callback : pending_operations)
+    std::move(callback).Run();
+}
+
+void ArcDocumentsProviderFileStreamWriter::RunPendingWrite(
+    scoped_refptr<net::IOBuffer> buffer,
+    int buffer_length,
+    net::CompletionOnceCallback callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(content_url_resolved_);
+  // Create |copyable_callback| which is copyable, though it can still only
+  // called at most once.  This is safe, because Write() is guaranteed not to
+  // call |callback| if it returns synchronously.
+  auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
+  int result = underlying_writer_
+                   ? underlying_writer_->Write(buffer.get(), buffer_length,
+                                               copyable_callback)
+                   : net::ERR_FILE_NOT_FOUND;
+  if (result != net::ERR_IO_PENDING)
+    copyable_callback.Run(result);
+}
+
+void ArcDocumentsProviderFileStreamWriter::RunPendingCancel(
+    net::CompletionOnceCallback callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(content_url_resolved_);
+  // Create |copyable_callback| which is copyable, though it can still only
+  // called at most once.  This is safe, because Cancel() is guaranteed not to
+  // call |callback| if it returns synchronously.
+  auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
+  int result = underlying_writer_
+                   ? underlying_writer_->Cancel(copyable_callback)
+                   : net::ERR_FILE_NOT_FOUND;
+  if (result != net::ERR_IO_PENDING)
+    copyable_callback.Run(result);
+}
+
+void ArcDocumentsProviderFileStreamWriter::RunPendingFlush(
+    net::CompletionOnceCallback callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(content_url_resolved_);
+  // Create |copyable_callback| which is copyable, though it can still only
+  // called at most once.  This is safe, because Flush() is guaranteed not to
+  // call |callback| if it returns synchronously.
+  auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
+  int result = underlying_writer_ ? underlying_writer_->Flush(copyable_callback)
+                                  : net::ERR_FILE_NOT_FOUND;
+  if (result != net::ERR_IO_PENDING)
+    copyable_callback.Run(result);
+}
+
+}  // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_file_stream_writer.h b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_file_stream_writer.h
new file mode 100644
index 0000000..05597d5
--- /dev/null
+++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_file_stream_writer.h
@@ -0,0 +1,61 @@
+// Copyright 2019 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_CHROMEOS_ARC_FILEAPI_ARC_DOCUMENTS_PROVIDER_FILE_STREAM_WRITER_H_
+#define CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_DOCUMENTS_PROVIDER_FILE_STREAM_WRITER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "net/base/completion_once_callback.h"
+#include "storage/browser/fileapi/file_stream_writer.h"
+#include "storage/browser/fileapi/file_system_url.h"
+
+class GURL;
+
+namespace arc {
+
+// FileStreamWriter implementation for ARC documents provider file system.
+// It actually delegates operations to ArcContentFileSystemFileStreamWriter.
+// TODO(crbug.com/678886): Write unit tests.
+class ArcDocumentsProviderFileStreamWriter : public storage::FileStreamWriter {
+ public:
+  ArcDocumentsProviderFileStreamWriter(const storage::FileSystemURL& url,
+                                       int64_t offset);
+  ~ArcDocumentsProviderFileStreamWriter() override;
+
+  // storage::FileStreamWriter overrides:
+  int Write(net::IOBuffer* buffer,
+            int bufffer_length,
+            net::CompletionOnceCallback callback) override;
+  int Cancel(net::CompletionOnceCallback callback) override;
+  int Flush(net::CompletionOnceCallback callback) override;
+
+ private:
+  void OnResolveToContentUrl(const GURL& content_url);
+  void RunPendingWrite(scoped_refptr<net::IOBuffer> buffer,
+                       int buffer_length,
+                       net::CompletionOnceCallback callback);
+  void RunPendingCancel(net::CompletionOnceCallback callback);
+  void RunPendingFlush(net::CompletionOnceCallback callback);
+  const int64_t offset_;
+  bool content_url_resolved_;
+  const storage::FileSystemURL arc_url_;
+  std::unique_ptr<storage::FileStreamWriter> underlying_writer_;
+  std::vector<base::OnceClosure> pending_operations_;
+
+  base::WeakPtrFactory<ArcDocumentsProviderFileStreamWriter> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArcDocumentsProviderFileStreamWriter);
+};
+
+}  // namespace arc
+
+#endif  // CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_DOCUMENTS_PROVIDER_FILE_STREAM_WRITER_H_
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc
index 1ce46fec..91ea21b 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc
@@ -174,6 +174,26 @@
   file_system_instance->OpenFileToRead(url.spec(), std::move(callback));
 }
 
+void ArcFileSystemOperationRunner::OpenFileToWrite(
+    const GURL& url,
+    OpenFileToWriteCallback callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (should_defer_) {
+    deferred_operations_.emplace_back(base::BindOnce(
+        &ArcFileSystemOperationRunner::OpenFileToWrite,
+        weak_ptr_factory_.GetWeakPtr(), url, std::move(callback)));
+    return;
+  }
+  auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD(
+      arc_bridge_service_->file_system(), OpenFileToWrite);
+  if (!file_system_instance) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), mojo::ScopedHandle()));
+    return;
+  }
+  file_system_instance->OpenFileToWrite(url.spec(), std::move(callback));
+}
+
 void ArcFileSystemOperationRunner::GetDocument(const std::string& authority,
                                                const std::string& document_id,
                                                GetDocumentCallback callback) {
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h
index 00953d9..ca9ac20 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h
+++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h
@@ -71,6 +71,8 @@
   using GetMimeTypeCallback = mojom::FileSystemInstance::GetMimeTypeCallback;
   using OpenFileToReadCallback =
       mojom::FileSystemInstance::OpenFileToReadCallback;
+  using OpenFileToWriteCallback =
+      mojom::FileSystemInstance::OpenFileToWriteCallback;
   using GetDocumentCallback = mojom::FileSystemInstance::GetDocumentCallback;
   using GetChildDocumentsCallback =
       mojom::FileSystemInstance::GetChildDocumentsCallback;
@@ -130,6 +132,7 @@
   void GetFileSize(const GURL& url, GetFileSizeCallback callback);
   void GetMimeType(const GURL& url, GetMimeTypeCallback callback);
   void OpenFileToRead(const GURL& url, OpenFileToReadCallback callback);
+  void OpenFileToWrite(const GURL& url, OpenFileToWriteCallback callback);
   void GetDocument(const std::string& authority,
                    const std::string& document_id,
                    GetDocumentCallback callback);
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc
index 5ea0432..2258bb5 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc
@@ -115,6 +115,11 @@
         base::BindOnce(
             [](int* counter, mojo::ScopedHandle handle) { ++*counter; },
             counter));
+    runner_->OpenFileToWrite(
+        GURL(kUrl),
+        base::BindOnce(
+            [](int* counter, mojo::ScopedHandle handle) { ++*counter; },
+            counter));
 
     // RemoveWatcher() is never deferred.
     runner_->RemoveWatcher(
@@ -140,7 +145,7 @@
   CallSetShouldDefer(false);
   CallAllFunctions(&counter);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(9, counter);
+  EXPECT_EQ(10, counter);
 }
 
 TEST_F(ArcFileSystemOperationRunnerTest, DeferAndRun) {
@@ -152,7 +157,7 @@
 
   CallSetShouldDefer(false);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(9, counter);
+  EXPECT_EQ(10, counter);
 }
 
 // TODO(nya,hidehiko): Check if we should keep this test.
@@ -177,7 +182,7 @@
   CallSetShouldDefer(false);
   CallAllFunctions(&counter);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(9, counter);
+  EXPECT_EQ(10, counter);
 }
 
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc
index a74ea4af..b707b6da 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.cc
@@ -62,6 +62,19 @@
   runner->OpenFileToRead(url, std::move(callback));
 }
 
+void OpenFileToWriteOnUIThread(const GURL& url,
+                               OpenFileToWriteCallback callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  auto* runner = GetArcFileSystemOperationRunner();
+  if (!runner) {
+    DLOG(ERROR) << "ArcFileSystemOperationRunner unavailable. "
+                << "File system operations are dropped.";
+    std::move(callback).Run(mojo::ScopedHandle());
+    return;
+  }
+  runner->OpenFileToWrite(url, std::move(callback));
+}
+
 }  // namespace
 
 void GetFileSizeOnIOThread(const GURL& url, GetFileSizeCallback callback) {
@@ -83,6 +96,16 @@
                                     std::move(callback))));
 }
 
+void OpenFileToWriteOnIOThread(const GURL& url,
+                               OpenFileToReadCallback callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  base::PostTaskWithTraits(
+      FROM_HERE, {BrowserThread::UI},
+      base::BindOnce(&OpenFileToWriteOnUIThread, url,
+                     base::BindOnce(&PostToIOThread<mojo::ScopedHandle>,
+                                    std::move(callback))));
+}
+
 }  // namespace file_system_operation_runner_util
 
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h
index 77f7c341..2058d63 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h
+++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_util.h
@@ -19,12 +19,16 @@
 using GetFileSizeCallback = ArcFileSystemOperationRunner::GetFileSizeCallback;
 using OpenFileToReadCallback =
     ArcFileSystemOperationRunner::OpenFileToReadCallback;
+using OpenFileToWriteCallback =
+    ArcFileSystemOperationRunner::OpenFileToWriteCallback;
 
 // Utility functions to post a task to run ArcFileSystemOperationRunner methods.
 // These functions must be called on the IO thread. Callbacks and observers will
 // be called on the IO thread.
 void GetFileSizeOnIOThread(const GURL& url, GetFileSizeCallback callback);
 void OpenFileToReadOnIOThread(const GURL& url, OpenFileToReadCallback callback);
+void OpenFileToWriteOnIOThread(const GURL& url,
+                               OpenFileToWriteCallback callback);
 
 }  // namespace file_system_operation_runner_util
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
index 6a782478..64c5a27 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
@@ -19,8 +19,8 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chrome/browser/chromeos/arc/tracing/arc_cpu_event.cc b/chrome/browser/chromeos/arc/tracing/arc_cpu_event.cc
new file mode 100644
index 0000000..c10f9fd
--- /dev/null
+++ b/chrome/browser/chromeos/arc/tracing/arc_cpu_event.cc
@@ -0,0 +1,197 @@
+// Copyright 2019 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/chromeos/arc/tracing/arc_cpu_event.h"
+
+#include "base/logging.h"
+
+namespace arc {
+
+ArcCpuEvent::ArcCpuEvent(int64_t timestamp, Type type, uint32_t tid)
+    : timestamp(timestamp), type(type), tid(tid) {}
+
+bool ArcCpuEvent::operator==(const ArcCpuEvent& other) const {
+  return timestamp == other.timestamp && type == other.type && tid == other.tid;
+}
+
+bool AddCpuEvent(CpuEvents* cpu_events,
+                 int64_t timestamp,
+                 ArcCpuEvent::Type type,
+                 uint32_t tid) {
+  // Base validation.
+  switch (type) {
+    case ArcCpuEvent::Type::kIdleIn:
+    case ArcCpuEvent::Type::kIdleOut:
+      if (tid) {
+        LOG(ERROR) << "Idle should always be bound to the idle process";
+        return false;
+      }
+      break;
+    case ArcCpuEvent::Type::kWakeUp:
+      if (!tid) {
+        LOG(ERROR) << "Cannot wake-up to idle process";
+        return false;
+      }
+      break;
+    case ArcCpuEvent::Type::kActive:
+      break;
+  }
+
+  if (cpu_events->empty()) {
+    cpu_events->emplace_back(timestamp, type, tid);
+    return true;
+  }
+
+  // Verify new event relative to the last event.
+  const ArcCpuEvent& last = cpu_events->back();
+  if (last.timestamp > timestamp) {
+    LOG(ERROR) << "Time sequence is broken for cpu events: " << last.timestamp
+               << " vs " << timestamp;
+    return false;
+  }
+  // Check transitions from->to.
+  switch (last.type) {
+    case ArcCpuEvent::Type::kIdleIn:
+      switch (type) {
+        case ArcCpuEvent::Type::kIdleOut:
+          break;
+        case ArcCpuEvent::Type::kWakeUp:
+          break;
+        default:
+          LOG(ERROR) << "Unknown CPU transition: " << last.type << "=>" << type;
+          return false;
+      }
+      break;
+    case ArcCpuEvent::Type::kIdleOut:
+      switch (type) {
+        case ArcCpuEvent::Type::kIdleIn:
+          break;
+        case ArcCpuEvent::Type::kWakeUp:
+          break;
+        case ArcCpuEvent::Type::kActive:
+          break;
+        default:
+          LOG(ERROR) << "Unknown CPU transition: " << last.type << "=>" << type;
+          return false;
+      }
+      break;
+    case ArcCpuEvent::Type::kWakeUp:
+      switch (type) {
+        case ArcCpuEvent::Type::kIdleOut:
+          break;
+        case ArcCpuEvent::Type::kWakeUp:
+          break;
+        case ArcCpuEvent::Type::kActive:
+          break;
+        default:
+          LOG(ERROR) << "Unknown CPU transition: " << last.type << "=>" << type;
+          return false;
+      }
+      break;
+    case ArcCpuEvent::Type::kActive:
+      switch (type) {
+        case ArcCpuEvent::Type::kIdleIn:
+          break;
+        case ArcCpuEvent::Type::kWakeUp:
+          break;
+        case ArcCpuEvent::Type::kActive:
+          break;
+        default:
+          LOG(ERROR) << "Unknown CPU transition: " << last.type << "=>" << type;
+          return false;
+      }
+      break;
+  }
+
+  cpu_events->emplace_back(timestamp, type, tid);
+  return true;
+}
+
+bool AddAllCpuEvent(AllCpuEvents* all_cpu_events,
+                    uint32_t cpu_id,
+                    int64_t timestamp,
+                    ArcCpuEvent::Type type,
+                    uint32_t tid) {
+  if (all_cpu_events->size() <= cpu_id)
+    all_cpu_events->resize(cpu_id + 1);
+  return AddCpuEvent(&(*all_cpu_events)[cpu_id], timestamp, type, tid);
+}
+
+base::ListValue SerializeCpuEvents(const CpuEvents& cpu_events) {
+  base::ListValue list;
+  for (const auto& event : cpu_events) {
+    base::ListValue event_value;
+    event_value.GetList().push_back(base::Value(static_cast<int>(event.type)));
+    event_value.GetList().push_back(
+        base::Value(static_cast<double>(event.timestamp)));
+    event_value.GetList().push_back(base::Value(static_cast<int>(event.tid)));
+    list.GetList().emplace_back(std::move(event_value));
+  }
+  return list;
+}
+
+base::ListValue SerializeAllCpuEvents(const AllCpuEvents& all_cpu_events) {
+  base::ListValue list;
+  for (const auto& cpu_events : all_cpu_events)
+    list.GetList().emplace_back(SerializeCpuEvents(cpu_events));
+  return list;
+}
+
+bool LoadCpuEvents(const base::Value* value, CpuEvents* cpu_events) {
+  if (!value || !value->is_list())
+    return false;
+
+  int64_t previous_timestamp = 0;
+  for (const auto& entry : value->GetList()) {
+    if (!entry.is_list() || entry.GetList().size() != 3)
+      return false;
+    if (!entry.GetList()[0].is_int())
+      return false;
+    const ArcCpuEvent::Type type =
+        static_cast<ArcCpuEvent::Type>(entry.GetList()[0].GetInt());
+    switch (type) {
+      case ArcCpuEvent::Type::kIdleIn:
+      case ArcCpuEvent::Type::kIdleOut:
+      case ArcCpuEvent::Type::kWakeUp:
+      case ArcCpuEvent::Type::kActive:
+        break;
+      default:
+        return false;
+    }
+    if (!entry.GetList()[1].is_double() && !entry.GetList()[1].is_int())
+      return false;
+    const int64_t timestamp = entry.GetList()[1].GetDouble();
+    if (timestamp < previous_timestamp)
+      return false;
+    if (!entry.GetList()[2].is_int())
+      return false;
+    const int tid = entry.GetList()[2].GetInt();
+    cpu_events->emplace_back(timestamp, type, tid);
+    previous_timestamp = timestamp;
+  }
+
+  return true;
+}
+
+bool LoadAllCpuEvents(const base::Value* value, AllCpuEvents* all_cpu_events) {
+  if (!value || !value->is_list())
+    return false;
+
+  for (const auto& entry : value->GetList()) {
+    CpuEvents cpu_events;
+    if (!LoadCpuEvents(&entry, &cpu_events))
+      return false;
+    all_cpu_events->emplace_back(std::move(cpu_events));
+  }
+
+  return true;
+}
+
+std::ostream& operator<<(std::ostream& os, ArcCpuEvent::Type event_type) {
+  return os
+         << static_cast<typename std::underlying_type<ArcCpuEvent::Type>::type>(
+                event_type);
+}
+
+}  // namespace arc
diff --git a/chrome/browser/chromeos/arc/tracing/arc_cpu_event.h b/chrome/browser/chromeos/arc/tracing/arc_cpu_event.h
new file mode 100644
index 0000000..92ddf0c
--- /dev/null
+++ b/chrome/browser/chromeos/arc/tracing/arc_cpu_event.h
@@ -0,0 +1,70 @@
+// Copyright 2019 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_CHROMEOS_ARC_TRACING_ARC_CPU_EVENT_H_
+#define CHROME_BROWSER_CHROMEOS_ARC_TRACING_ARC_CPU_EVENT_H_
+
+#include <ostream>
+#include <vector>
+
+#include "base/values.h"
+
+namespace arc {
+
+// Keeps information about CPU event
+struct ArcCpuEvent {
+  enum class Type {
+    kIdleIn = 0,  // CPU is in idle state.
+    kIdleOut,     // CPU is no longer in idle state.
+    kWakeUp,      // Wake up with a task.
+    kActive,      // Task is started on CPU.
+  };
+
+  ArcCpuEvent(int64_t timestamp, Type type, uint32_t tid);
+
+  bool operator==(const ArcCpuEvent& other) const;
+
+  int64_t timestamp;
+  Type type;
+  uint32_t tid;
+};
+
+using CpuEvents = std::vector<ArcCpuEvent>;
+// Represents CPU events for all CPUs in the system. CPUs id is in the range
+// 0..N and corresponds to the index in |AllCpuEvents|, N is CPU count - 1.
+using AllCpuEvents = std::vector<CpuEvents>;
+
+// Helper that adds CPU event into |cpu_events|. Returns true in case event was
+// created and added or false if it breaks any constraint.
+bool AddCpuEvent(CpuEvents* cpu_events,
+                 int64_t timestamp,
+                 ArcCpuEvent::Type type,
+                 uint32_t tid);
+
+// Helper that adds next CPU event to |all_cpu_events|. If needed new entry
+// |CpuEvents| is allocated for |cpu_id|. Returns true in case event was
+// created and added or false if it breaks any constraint.
+bool AddAllCpuEvent(AllCpuEvents* all_cpu_events,
+                    uint32_t cpu_id,
+                    int64_t timestamp,
+                    ArcCpuEvent::Type type,
+                    uint32_t tid);
+
+// Serializes CPU events into |base::ListValue|.
+base::ListValue SerializeCpuEvents(const CpuEvents& cpu_events);
+// Serializes all CPU events into |base::ListValue|.
+base::ListValue SerializeAllCpuEvents(const AllCpuEvents& all_cpu_events);
+
+// Loads CPU events from |base::ListValue|. Returns true in case CPU events were
+// loaded successfully.
+bool LoadCpuEvents(const base::Value* value, CpuEvents* cpu_events);
+// Loads all CPU events from |base::ListValue|. Returns true in case CPU events
+// were loaded successfully.
+bool LoadAllCpuEvents(const base::Value* value, AllCpuEvents* all_cpu_events);
+
+std::ostream& operator<<(std::ostream& os, ArcCpuEvent::Type event_type);
+
+}  // namespace arc
+
+#endif  // CHROME_BROWSER_CHROMEOS_ARC_TRACING_ARC_CPU_EVENT_H_
diff --git a/chrome/browser/chromeos/arc/tracing/arc_cpu_event_unittest.cc b/chrome/browser/chromeos/arc/tracing/arc_cpu_event_unittest.cc
new file mode 100644
index 0000000..2573dc27
--- /dev/null
+++ b/chrome/browser/chromeos/arc/tracing/arc_cpu_event_unittest.cc
@@ -0,0 +1,103 @@
+// Copyright 2019 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/chromeos/arc/tracing/arc_cpu_event.h"
+
+#include "base/bind.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+
+using ArcCpuEventTest = testing::Test;
+using Type = ArcCpuEvent::Type;
+
+namespace {
+
+bool CheckTrasition(Type from_type,
+                    uint32_t from_tid,
+                    Type to_type,
+                    uint32_t to_tid) {
+  CpuEvents cpu_events;
+  const bool added =
+      AddCpuEvent(&cpu_events, 1000 /* timestamp */, from_type, from_tid);
+  DCHECK(added);
+  DCHECK(cpu_events.size() == 1);
+  if (!AddCpuEvent(&cpu_events, 1001 /* timestamp */, to_type, to_tid)) {
+    DCHECK(cpu_events.size() == 1);
+    return false;
+  }
+  DCHECK(cpu_events.size() == 2);
+  return true;
+}
+
+}  // namespace
+
+TEST_F(ArcCpuEventTest, Generic) {
+  constexpr int idle_tid = 0;
+  constexpr int real_tid = 1;
+
+  AllCpuEvents all_cpu_events;
+  EXPECT_TRUE(AddAllCpuEvent(&all_cpu_events, 3 /* cpu_id */,
+                             1000 /* timestamp */, Type::kIdleIn, idle_tid));
+  ASSERT_EQ(4U, all_cpu_events.size());
+  EXPECT_EQ(0U, all_cpu_events[0].size());
+  EXPECT_EQ(0U, all_cpu_events[1].size());
+  EXPECT_EQ(0U, all_cpu_events[2].size());
+  EXPECT_EQ(1U, all_cpu_events[3].size());
+
+  // Timestamp is before but this is separate CPU events band.
+  EXPECT_TRUE(AddAllCpuEvent(&all_cpu_events, 0 /* cpu_id */,
+                             999 /* timestamp */, Type::kIdleIn, idle_tid));
+  ASSERT_EQ(4U, all_cpu_events.size());
+  EXPECT_EQ(1U, all_cpu_events[0].size());
+  EXPECT_EQ(0U, all_cpu_events[1].size());
+  EXPECT_EQ(0U, all_cpu_events[2].size());
+  EXPECT_EQ(1U, all_cpu_events[3].size());
+
+  // Broken timestamp.
+  EXPECT_FALSE(AddAllCpuEvent(&all_cpu_events, 0 /* cpu_id */,
+                              998 /* timestamp */, Type::kIdleOut, idle_tid));
+
+  // Validate transitions.
+  EXPECT_FALSE(
+      CheckTrasition(Type::kIdleIn, idle_tid, Type::kIdleIn, idle_tid));
+  EXPECT_TRUE(
+      CheckTrasition(Type::kIdleIn, idle_tid, Type::kIdleOut, idle_tid));
+  EXPECT_TRUE(CheckTrasition(Type::kIdleIn, idle_tid, Type::kWakeUp, real_tid));
+  EXPECT_FALSE(
+      CheckTrasition(Type::kIdleIn, idle_tid, Type::kActive, real_tid));
+
+  EXPECT_TRUE(
+      CheckTrasition(Type::kIdleOut, idle_tid, Type::kIdleIn, idle_tid));
+  EXPECT_FALSE(
+      CheckTrasition(Type::kIdleOut, idle_tid, Type::kIdleOut, idle_tid));
+  EXPECT_TRUE(
+      CheckTrasition(Type::kIdleOut, idle_tid, Type::kWakeUp, real_tid));
+  EXPECT_TRUE(
+      CheckTrasition(Type::kIdleOut, idle_tid, Type::kActive, real_tid));
+
+  EXPECT_FALSE(
+      CheckTrasition(Type::kWakeUp, real_tid, Type::kIdleIn, idle_tid));
+  EXPECT_TRUE(
+      CheckTrasition(Type::kWakeUp, real_tid, Type::kIdleOut, idle_tid));
+  EXPECT_TRUE(CheckTrasition(Type::kWakeUp, real_tid, Type::kWakeUp, real_tid));
+  EXPECT_TRUE(CheckTrasition(Type::kWakeUp, real_tid, Type::kActive, real_tid));
+
+  EXPECT_TRUE(CheckTrasition(Type::kActive, real_tid, Type::kIdleIn, idle_tid));
+  EXPECT_FALSE(
+      CheckTrasition(Type::kActive, real_tid, Type::kIdleOut, idle_tid));
+  EXPECT_TRUE(CheckTrasition(Type::kActive, real_tid, Type::kWakeUp, real_tid));
+  EXPECT_TRUE(CheckTrasition(Type::kActive, real_tid, Type::kActive, real_tid));
+
+  // tid is not idle for idle events.
+  EXPECT_FALSE(
+      CheckTrasition(Type::kIdleIn, idle_tid, Type::kIdleOut, real_tid));
+  EXPECT_FALSE(
+      CheckTrasition(Type::kIdleOut, idle_tid, Type::kIdleIn, real_tid));
+  // tid is idle for wake-up event.
+  EXPECT_FALSE(
+      CheckTrasition(Type::kIdleIn, idle_tid, Type::kWakeUp, idle_tid));
+}
+
+}  // namespace arc
diff --git a/chrome/browser/chromeos/arc/tracing/arc_cpu_model.cc b/chrome/browser/chromeos/arc/tracing/arc_cpu_model.cc
new file mode 100644
index 0000000..165e8e2
--- /dev/null
+++ b/chrome/browser/chromeos/arc/tracing/arc_cpu_model.cc
@@ -0,0 +1,111 @@
+// Copyright 2019 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/chromeos/arc/tracing/arc_cpu_model.h"
+
+#include <stdio.h>
+
+#include "base/strings/stringprintf.h"
+
+namespace arc {
+
+namespace {
+
+constexpr char kKeyEvents[] = "events";
+constexpr char kKeyName[] = "name";
+constexpr char kKeyPid[] = "pid";
+constexpr char kKeyThreads[] = "threads";
+
+bool LoadThreads(const base::Value* value,
+                 ArcCpuModel::ThreadMap* out_threads) {
+  if (!value || !value->is_dict())
+    return false;
+
+  for (const auto& it : value->DictItems()) {
+    int tid;
+    if (sscanf(it.first.c_str(), "%d", &tid) != 1)
+      return false;
+
+    if (!it.second.is_dict())
+      return false;
+
+    const base::Value* name = it.second.FindKey(kKeyName);
+    if (!name || !name->is_string())
+      return false;
+    const base::Value* pid = it.second.FindKey(kKeyPid);
+    if (!pid || !pid->is_int())
+      return false;
+
+    (*out_threads)[tid] =
+        ArcCpuModel::ThreadInfo(pid->GetInt(), name->GetString());
+  }
+
+  return true;
+}
+
+base::DictionaryValue SerializeThreads(const ArcCpuModel::ThreadMap& threads) {
+  base::DictionaryValue result;
+
+  for (auto& thread_info : threads) {
+    base::DictionaryValue entry;
+    entry.SetKey(kKeyPid, base::Value(thread_info.second.pid));
+    entry.SetKey(kKeyName, base::Value(thread_info.second.name));
+    result.SetKey(base::StringPrintf("%d", thread_info.first),
+                  std::move(entry));
+  }
+
+  return result;
+}
+
+}  // namespace
+
+ArcCpuModel::ThreadInfo::ThreadInfo() = default;
+
+ArcCpuModel::ThreadInfo::ThreadInfo(int pid, const std::string& name)
+    : pid(pid), name(name) {}
+
+bool ArcCpuModel::ThreadInfo::operator==(const ThreadInfo& other) const {
+  return pid == other.pid && name == other.name;
+}
+
+ArcCpuModel::ArcCpuModel() = default;
+
+ArcCpuModel::~ArcCpuModel() = default;
+
+void ArcCpuModel::Reset() {
+  thread_map_.clear();
+  all_cpu_events_.clear();
+}
+
+void ArcCpuModel::CopyFrom(const ArcCpuModel& other) {
+  thread_map_ = other.thread_map_;
+  all_cpu_events_ = other.all_cpu_events_;
+}
+
+base::DictionaryValue ArcCpuModel::Serialize() const {
+  base::DictionaryValue result;
+  result.SetKey(kKeyThreads, SerializeThreads(thread_map_));
+  result.SetKey(kKeyEvents, SerializeAllCpuEvents(all_cpu_events_));
+  return result;
+}
+
+bool ArcCpuModel::Load(const base::Value* root) {
+  if (!root || !root->is_dict())
+    return false;
+
+  if (!LoadThreads(root->FindKey(kKeyThreads), &thread_map_))
+    return false;
+
+  if (!LoadAllCpuEvents(root->FindKey(kKeyEvents), &all_cpu_events_))
+    return false;
+
+  return true;
+}
+
+bool ArcCpuModel::operator==(const ArcCpuModel& other) const {
+  return thread_map_ == other.thread_map_ &&
+         all_cpu_events_ == other.all_cpu_events_;
+}
+
+}  // namespace arc
diff --git a/chrome/browser/chromeos/arc/tracing/arc_cpu_model.h b/chrome/browser/chromeos/arc/tracing/arc_cpu_model.h
new file mode 100644
index 0000000..b3f82ec
--- /dev/null
+++ b/chrome/browser/chromeos/arc/tracing/arc_cpu_model.h
@@ -0,0 +1,61 @@
+// Copyright 2019 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_CHROMEOS_ARC_TRACING_ARC_CPU_MODEL_H_
+#define CHROME_BROWSER_CHROMEOS_ARC_TRACING_ARC_CPU_MODEL_H_
+
+#include <map>
+#include <string>
+
+#include "base/values.h"
+#include "chrome/browser/chromeos/arc/tracing/arc_cpu_event.h"
+
+namespace arc {
+
+// Contains information about CPU activity events and involved threads.
+class ArcCpuModel {
+ public:
+  static constexpr int kUnknownPid = -1;
+
+  struct ThreadInfo {
+    ThreadInfo();
+    ThreadInfo(int pid, const std::string& name);
+
+    bool operator==(const ThreadInfo& other) const;
+
+    // Process id or |kUnknownPid| if unknown.
+    int pid = kUnknownPid;
+    // Name of thread of process in case thread is main thread of the process.
+    std::string name;
+  };
+
+  using ThreadMap = std::map<int, ThreadInfo>;
+
+  ArcCpuModel();
+  ~ArcCpuModel();
+
+  void Reset();
+
+  void CopyFrom(const ArcCpuModel& other);
+  base::DictionaryValue Serialize() const;
+  bool Load(const base::Value* root);
+
+  bool operator==(const ArcCpuModel& other) const;
+
+  ThreadMap& thread_map() { return thread_map_; }
+  const ThreadMap& thread_map() const { return thread_map_; }
+
+  AllCpuEvents& all_cpu_events() { return all_cpu_events_; }
+  const AllCpuEvents& all_cpu_events() const { return all_cpu_events_; }
+
+ private:
+  ThreadMap thread_map_;
+  AllCpuEvents all_cpu_events_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArcCpuModel);
+};
+
+}  // namespace arc
+
+#endif  // CHROME_BROWSER_CHROMEOS_ARC_TRACING_ARC_CPU_MODEL_H_
diff --git a/chrome/browser/chromeos/arc/tracing/arc_graphics_jank_detector_unittest.cc b/chrome/browser/chromeos/arc/tracing/arc_graphics_jank_detector_unittest.cc
index c00b858..2589a7a5e 100644
--- a/chrome/browser/chromeos/arc/tracing/arc_graphics_jank_detector_unittest.cc
+++ b/chrome/browser/chromeos/arc/tracing/arc_graphics_jank_detector_unittest.cc
@@ -9,14 +9,7 @@
 
 namespace arc {
 
-class ArcGraphicsJankDetectorTest : public testing::Test {
- public:
-  ArcGraphicsJankDetectorTest() = default;
-  ~ArcGraphicsJankDetectorTest() override = default;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ArcGraphicsJankDetectorTest);
-};
+using ArcGraphicsJankDetectorTest = testing::Test;
 
 TEST_F(ArcGraphicsJankDetectorTest, Generic) {
   int jank_count = 0;
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc
index 953d792..58ea13f 100644
--- a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc
+++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc
@@ -35,6 +35,7 @@
 constexpr char kKeyAndroid[] = "android";
 constexpr char kKeyBuffers[] = "buffers";
 constexpr char kKeyChrome[] = "chrome";
+constexpr char kKeyCpu[] = "cpu";
 constexpr char kKeyDuration[] = "duration";
 constexpr char kKeyGlobalEvents[] = "global_events";
 constexpr char kKeyViews[] = "views";
@@ -758,12 +759,12 @@
 base::ListValue SerializeEvents(
     const ArcTracingGraphicsModel::BufferEvents& events) {
   base::ListValue list;
-  for (auto& event : events) {
+  for (const auto& event : events) {
     base::ListValue event_value;
     event_value.GetList().push_back(base::Value(static_cast<int>(event.type)));
     event_value.GetList().push_back(
         base::Value(static_cast<double>(event.timestamp)));
-    list.GetList().push_back(std::move(event_value));
+    list.GetList().emplace_back(std::move(event_value));
   }
   return list;
 }
@@ -822,7 +823,7 @@
 
     if (!entry.GetList()[1].is_double() && !entry.GetList()[1].is_int())
       return false;
-    const int timestamp = entry.GetList()[1].GetDouble();
+    const int64_t timestamp = entry.GetList()[1].GetDouble();
     if (timestamp < previous_timestamp)
       return false;
     out_events->emplace_back(
@@ -979,6 +980,8 @@
     return false;
   }
 
+  cpu_model_.CopyFrom(common_model.cpu_model());
+
   NormalizeTimestamps();
 
   return true;
@@ -1009,12 +1012,24 @@
     }
   }
 
+  for (const auto& cpu_events : cpu_model_.all_cpu_events()) {
+    if (!cpu_events.empty()) {
+      min = std::min(min, cpu_events.front().timestamp);
+      max = std::max(max, cpu_events.back().timestamp);
+    }
+  }
+
   duration_ = max - min + 1;
 
   for (BufferEvents* buffer : all_buffers) {
     for (auto& event : *buffer)
       event.timestamp -= min;
   }
+
+  for (auto& cpu_events : cpu_model_.all_cpu_events()) {
+    for (auto& cpu_event : cpu_events)
+      cpu_event.timestamp -= min;
+  }
 }
 
 void ArcTracingGraphicsModel::Reset() {
@@ -1022,6 +1037,7 @@
   android_top_level_.Reset();
   view_buffers_.clear();
   chrome_buffer_id_to_task_id_.clear();
+  cpu_model_.Reset();
   duration_ = 0;
 }
 
@@ -1054,6 +1070,9 @@
   // Chrome top events
   root->SetKey(kKeyChrome, SerializeEventsContainer(chrome_top_level_));
 
+  // CPU.
+  root->SetKey(kKeyCpu, cpu_model_.Serialize());
+
   // Duration.
   root->SetKey(kKeyDuration, base::Value(static_cast<double>(duration_)));
 
@@ -1111,6 +1130,9 @@
   if (!LoadEventsContainer(root.FindKey(kKeyChrome), &chrome_top_level_))
     return false;
 
+  if (!cpu_model_.Load(root.FindKey(kKeyCpu)))
+    return false;
+
   const base::Value* duration = root.FindKey(kKeyDuration);
   if (!duration || (!duration->is_double() && !duration->is_int()))
     return false;
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h
index f8f6324..a62c407c 100644
--- a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h
+++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h
@@ -12,6 +12,7 @@
 
 #include "base/macros.h"
 #include "base/values.h"
+#include "chrome/browser/chromeos/arc/tracing/arc_cpu_model.h"
 
 namespace arc {
 
@@ -153,6 +154,9 @@
 
   const EventsContainer& chrome_top_level() const { return chrome_top_level_; }
 
+  ArcCpuModel& cpu_model() { return cpu_model_; }
+  const ArcCpuModel& cpu_model() const { return cpu_model_; }
+
  private:
   // Normalizes timestamp for all events by subtracting the timestamp of the
   // earliest event.
@@ -173,6 +177,8 @@
   uint32_t duration_ = 0;
   // Map Chrome buffer id to task id.
   std::map<std::string, int> chrome_buffer_id_to_task_id_;
+  // CPU event model.
+  ArcCpuModel cpu_model_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcTracingGraphicsModel);
 };
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_model.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_model.cc
index 38b06e8..8968f308 100644
--- a/chrome/browser/chromeos/arc/tracing/arc_tracing_model.cc
+++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_model.cc
@@ -17,6 +17,12 @@
 constexpr char kAndroidCategory[] = "android";
 constexpr char kTracingMarkWrite[] = ": tracing_mark_write: ";
 constexpr int kTracingMarkWriteLength = sizeof(kTracingMarkWrite) - 1;
+constexpr char kCpuIdle[] = ": cpu_idle: ";
+constexpr int kCpuIdleLength = sizeof(kCpuIdle) - 1;
+constexpr char kSchedWakeUp[] = ": sched_wakeup: ";
+constexpr int kSchedWakeUpLength = sizeof(kSchedWakeUp) - 1;
+constexpr char kSchedSwitch[] = ": sched_switch: ";
+constexpr int kSchedSwitchLength = sizeof(kSchedSwitch) - 1;
 constexpr char kTraceEventClockSync[] = "trace_event_clock_sync: ";
 constexpr int kTraceEventClockSyncLength = sizeof(kTraceEventClockSync) - 1;
 
@@ -83,6 +89,147 @@
   }
 }
 
+struct GraphicsEventsContext {
+  // To keep in correct order of creation. This converts pair of 'B' and 'E'
+  // events to the completed event, 'X'.
+  ArcTracingModel::TracingEvents converted_events;
+  std::map<uint32_t, std::vector<ArcTracingEvent*>>
+      per_thread_pending_events_stack;
+};
+
+bool HandleGraphicsEvent(GraphicsEventsContext* context,
+                         double timestamp,
+                         uint32_t tid,
+                         const std::string& line,
+                         size_t event_position) {
+  if (event_position + kTraceEventClockSyncLength < line.length() &&
+      !strncmp(&line[event_position], kTraceEventClockSync,
+               kTraceEventClockSyncLength)) {
+    // Ignore this service message.
+    return true;
+  }
+
+  if (line[event_position + 1] != '|') {
+    LOG(ERROR) << "Cannot recognize trace marker event: " << line;
+    return false;
+  }
+
+  const char phase = line[event_position];
+
+  uint32_t pid;
+  switch (phase) {
+    case TRACE_EVENT_PHASE_BEGIN:
+    case TRACE_EVENT_PHASE_COUNTER: {
+      const size_t name_pos = ParseUint32(line, event_position + 2, '|', &pid);
+      if (name_pos == std::string::npos) {
+        LOG(ERROR) << "Cannot parse pid of trace event: " << line;
+        return false;
+      }
+      const std::string name = line.substr(name_pos + 1);
+      std::unique_ptr<ArcTracingEvent> event =
+          std::make_unique<ArcTracingEvent>(base::DictionaryValue());
+      event->SetPid(pid);
+      event->SetTid(tid);
+      event->SetTimestamp(timestamp);
+      event->SetCategory(kAndroidCategory);
+      event->SetName(name);
+      if (phase == TRACE_EVENT_PHASE_BEGIN)
+        context->per_thread_pending_events_stack[tid].push_back(event.get());
+      else
+        event->SetPhase(TRACE_EVENT_PHASE_COUNTER);
+      context->converted_events.push_back(std::move(event));
+    } break;
+    case TRACE_EVENT_PHASE_END: {
+      // Beginning event may not exist.
+      if (context->per_thread_pending_events_stack[tid].empty())
+        return true;
+      if (ParseUint32(line, event_position + 2, '\0', &pid) ==
+          std::string::npos) {
+        LOG(ERROR) << "Cannot parse pid of trace event: " << line;
+        return false;
+      }
+      ArcTracingEvent* completed_event =
+          context->per_thread_pending_events_stack[tid].back();
+      context->per_thread_pending_events_stack[tid].pop_back();
+      completed_event->SetPhase(TRACE_EVENT_PHASE_COMPLETE);
+      completed_event->SetDuration(timestamp - completed_event->GetTimestamp());
+    } break;
+    default:
+      LOG(ERROR) << "Unsupported type of trace event: " << line;
+      return false;
+  }
+  return true;
+}
+
+bool HandleCpuIdle(AllCpuEvents* all_cpu_events,
+                   double timestamp,
+                   uint32_t cpu_id,
+                   uint32_t tid,
+                   const std::string& line,
+                   size_t event_position) {
+  if (tid) {
+    LOG(ERROR) << "cpu_idle belongs to non-idle thread: " << line;
+    return false;
+  }
+  uint32_t state;
+  uint32_t cpu_id_from_event;
+  if (sscanf(&line[event_position], "state=%d cpu_id=%d", &state,
+             &cpu_id_from_event) != 2 ||
+      cpu_id != cpu_id_from_event) {
+    LOG(ERROR) << "Failed to parse cpu_idle event: " << line;
+    return false;
+  }
+
+  return AddAllCpuEvent(all_cpu_events, cpu_id, timestamp,
+                        state == 0xffffffff ? ArcCpuEvent::Type::kIdleOut
+                                            : ArcCpuEvent::Type::kIdleIn,
+                        0 /* tid */);
+}
+
+bool HandleSchedWakeUp(AllCpuEvents* all_cpu_events,
+                       double timestamp,
+                       uint32_t cpu_id,
+                       uint32_t tid,
+                       const std::string& line,
+                       size_t event_position) {
+  const char* data = strstr(&line[event_position], " pid=");
+  uint32_t target_tid;
+  uint32_t target_priority;
+  uint32_t target_cpu_id;
+  if (!data || sscanf(data, " pid=%d prio=%d target_cpu=%d", &target_tid,
+                      &target_priority, &target_cpu_id) != 3) {
+    LOG(ERROR) << "Failed to parse sched_wakeup event: " << line;
+    return false;
+  }
+
+  if (!target_tid) {
+    LOG(ERROR) << "Cannot wake-up idle thread: " << line;
+    return false;
+  }
+
+  return AddAllCpuEvent(all_cpu_events, target_cpu_id, timestamp,
+                        ArcCpuEvent::Type::kWakeUp, target_tid);
+}
+
+bool HandleSchedSwitch(AllCpuEvents* all_cpu_events,
+                       double timestamp,
+                       uint32_t cpu_id,
+                       uint32_t tid,
+                       const std::string& line,
+                       size_t event_position) {
+  const char* data = strstr(&line[event_position], " next_pid=");
+  uint32_t next_tid;
+  uint32_t next_priority;
+  if (!data || sscanf(data, " next_pid=%d next_prio=%d", &next_tid,
+                      &next_priority) != 2) {
+    LOG(ERROR) << "Failed to parse sched_switch event: " << line;
+    return false;
+  }
+
+  return AddAllCpuEvent(all_cpu_events, cpu_id, timestamp,
+                        ArcCpuEvent::Type::kActive, next_tid);
+}
+
 }  // namespace
 
 ArcTracingModel::ArcTracingModel() = default;
@@ -240,11 +387,9 @@
 
 bool ArcTracingModel::ConvertSysTraces(const std::string& sys_traces) {
   size_t new_line_pos = 0;
-  // To keep in correct order of creation. This converts pair of 'B' and 'E'
-  // events to the completed event, 'X'.
-  TracingEvents converted_events;
-  std::map<uint32_t, std::vector<ArcTracingEvent*>>
-      per_thread_pending_events_stack;
+
+  GraphicsEventsContext graphics_events_context;
+
   while (true) {
     // Get end of line.
     size_t end_line_pos = sys_traces.find('\n', new_line_pos);
@@ -264,7 +409,8 @@
     //               | |       |   ||||       |         |
     // Until TIMESTAMP we have fixed position for elements.
     if (line.length() < 35 || line[16] != '-' || line[22] != ' ' ||
-        line[28] != ' ' || line[33] != ' ') {
+        line[23] != '[' || line[27] != ']' || line[28] != ' ' ||
+        line[33] != ' ') {
       LOG(ERROR) << "Cannot recognize trace event: " << line;
       return false;
     }
@@ -274,6 +420,22 @@
       LOG(ERROR) << "Cannot parse tid in trace event: " << line;
       return false;
     }
+
+    if (cpu_model_.thread_map().find(tid) == cpu_model_.thread_map().end()) {
+      int thread_name_start = 0;
+      while (line[thread_name_start] == ' ')
+        ++thread_name_start;
+      cpu_model_.thread_map()[tid] = ArcCpuModel::ThreadInfo(
+          ArcCpuModel::kUnknownPid,
+          line.substr(thread_name_start, 16 - thread_name_start));
+    }
+
+    uint32_t cpu_id;
+    if (ParseUint32(line, 24, ']', &cpu_id) == std::string::npos) {
+      LOG(ERROR) << "Cannot parse CPU id in trace event: " << line;
+      return false;
+    }
+
     uint32_t timestamp_high;
     uint32_t timestamp_low;
     const size_t pos_dot = ParseUint32(line, 34, '.', &timestamp_high);
@@ -281,7 +443,6 @@
       LOG(ERROR) << "Cannot parse timestamp in trace event: " << line;
       return false;
     }
-
     const size_t separator_position =
         ParseUint32(line, pos_dot + 1, ':', &timestamp_low);
     if (separator_position == std::string::npos) {
@@ -289,79 +450,41 @@
       return false;
     }
 
-    const size_t event_position = separator_position + kTracingMarkWriteLength;
-    // Skip not relevant information. We only have interest what was written
-    // from Android using tracing marker.
-    if (event_position + 2 >= line.length() ||
-        strncmp(&line[separator_position], kTracingMarkWrite,
-                kTracingMarkWriteLength)) {
-      continue;
-    }
-
-    if (event_position + kTraceEventClockSyncLength < line.length() &&
-        !strncmp(&line[event_position], kTraceEventClockSync,
-                 kTraceEventClockSyncLength)) {
-      // Ignore this service message.
-      continue;
-    }
-
-    if (line[event_position + 1] != '|') {
-      LOG(ERROR) << "Cannot recognize trace marker event: " << line;
-      return false;
-    }
-
-    const char phase = line[event_position];
     const double timestamp = 1000000L * timestamp_high + timestamp_low;
     if (timestamp < min_timestamp_ || timestamp >= max_timestamp_)
       continue;
 
-    uint32_t pid;
-    switch (phase) {
-      case TRACE_EVENT_PHASE_BEGIN:
-      case TRACE_EVENT_PHASE_COUNTER: {
-        const size_t name_pos =
-            ParseUint32(line, event_position + 2, '|', &pid);
-        if (name_pos == std::string::npos) {
-          LOG(ERROR) << "Cannot parse pid of trace event: " << line;
-          return false;
-        }
-        const std::string name = line.substr(name_pos + 1);
-        std::unique_ptr<ArcTracingEvent> event =
-            std::make_unique<ArcTracingEvent>(base::DictionaryValue());
-        event->SetPid(pid);
-        event->SetTid(tid);
-        event->SetTimestamp(timestamp);
-        event->SetCategory(kAndroidCategory);
-        event->SetName(name);
-        if (phase == TRACE_EVENT_PHASE_BEGIN)
-          per_thread_pending_events_stack[tid].push_back(event.get());
-        else
-          event->SetPhase(TRACE_EVENT_PHASE_COUNTER);
-        converted_events.push_back(std::move(event));
-      } break;
-      case TRACE_EVENT_PHASE_END: {
-        // Beginning event may not exist.
-        if (per_thread_pending_events_stack[tid].empty())
-          continue;
-        if (ParseUint32(line, event_position + 2, '\0', &pid) ==
-            std::string::npos) {
-          LOG(ERROR) << "Cannot parse pid of trace event: " << line;
-          return false;
-        }
-        ArcTracingEvent* completed_event =
-            per_thread_pending_events_stack[tid].back();
-        per_thread_pending_events_stack[tid].pop_back();
-        completed_event->SetPhase(TRACE_EVENT_PHASE_COMPLETE);
-        completed_event->SetDuration(timestamp -
-                                     completed_event->GetTimestamp());
-      } break;
-      default:
-        LOG(ERROR) << "Unsupported type of trace event: " << line;
+    if (!strncmp(&line[separator_position], kTracingMarkWrite,
+                 kTracingMarkWriteLength)) {
+      if (!HandleGraphicsEvent(&graphics_events_context, timestamp, tid, line,
+                               separator_position + kTracingMarkWriteLength)) {
         return false;
+      }
+    } else if (!strncmp(&line[separator_position], kCpuIdle, kCpuIdleLength)) {
+      if (!HandleCpuIdle(&cpu_model_.all_cpu_events(), timestamp, cpu_id, tid,
+                         line, separator_position + kCpuIdleLength)) {
+        return false;
+      }
+    } else if (!strncmp(&line[separator_position], kSchedWakeUp,
+                        kSchedWakeUpLength)) {
+      if (!HandleSchedWakeUp(&cpu_model_.all_cpu_events(), timestamp, cpu_id,
+                             tid, line,
+                             separator_position + kSchedWakeUpLength)) {
+        return false;
+      }
+    } else if (!strncmp(&line[separator_position], kSchedSwitch,
+                        kSchedSwitchLength)) {
+      if (!HandleSchedSwitch(&cpu_model_.all_cpu_events(), timestamp, cpu_id,
+                             tid, line,
+                             separator_position + kSchedSwitchLength)) {
+        return false;
+      }
     }
   }
+
   // Close all pending tracing event, assuming last event is 0 duration.
-  for (auto& pending_events : per_thread_pending_events_stack) {
+  for (auto& pending_events :
+       graphics_events_context.per_thread_pending_events_stack) {
     if (pending_events.second.empty())
       continue;
     const double last_timestamp = pending_events.second.back()->GetTimestamp();
@@ -373,7 +496,7 @@
   }
 
   // Now put events to the thread models.
-  for (auto& converted_event : converted_events) {
+  for (auto& converted_event : graphics_events_context.converted_events) {
     if (!AddToThread(std::move(converted_event))) {
       LOG(ERROR) << "Cannot add systrace event to threads";
       return false;
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_model.h b/chrome/browser/chromeos/arc/tracing/arc_tracing_model.h
index 2e30bc21..716c5085 100644
--- a/chrome/browser/chromeos/arc/tracing/arc_tracing_model.h
+++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_model.h
@@ -12,6 +12,7 @@
 
 #include "base/macros.h"
 #include "base/values.h"
+#include "chrome/browser/chromeos/arc/tracing/arc_cpu_model.h"
 
 namespace arc {
 
@@ -56,6 +57,8 @@
   // Dumps this model to |stream|.
   void Dump(std::ostream& stream) const;
 
+  const ArcCpuModel& cpu_model() const { return cpu_model_; }
+
  private:
   // Processes list of events. Returns true in case all events were processed
   // successfully.
@@ -74,6 +77,8 @@
   // tracing events.
   std::map<std::string, TracingEvents> group_events_;
 
+  ArcCpuModel cpu_model_;
+
   // Metadata events.
   TracingEvents metadata_events_;
 
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc
index f6661a8..53ecc86 100644
--- a/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc
+++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc
@@ -53,10 +53,27 @@
 constexpr char kSurfaceAttach[] = "Surface::Attach";
 constexpr char kSurfaceAttachBad[] = "_Surface::Attach";
 
+// Validates that events have increasing timestamp, and all events have allowed
+// transitions from the previous state.
+bool ValidateCpuEvents(const CpuEvents& cpu_events) {
+  if (cpu_events.empty())
+    return false;
+
+  CpuEvents cpu_events_reconstructed;
+  for (const auto& cpu_event : cpu_events) {
+    if (!AddCpuEvent(&cpu_events_reconstructed, cpu_event.timestamp,
+                     cpu_event.type, cpu_event.tid)) {
+      return false;
+    }
+  }
+
+  return cpu_events_reconstructed == cpu_events;
+}
+
 // Validates that events have increasing timestamp, have only allowed types and
 // each type is found at least once.
-bool ValidateGrahpicsEvent(const GraphicsEvents& events,
-                           const std::set<GraphicsEventType>& allowed_types) {
+bool ValidateGrahpicsEvents(const GraphicsEvents& events,
+                            const std::set<GraphicsEventType>& allowed_types) {
   if (events.empty())
     return false;
   int64_t previous_timestamp = 0;
@@ -126,6 +143,11 @@
   ArcTracingModel model;
   ASSERT_TRUE(model.Build(tracing_data));
 
+  // 4 CPU cores.
+  EXPECT_EQ(4U, model.cpu_model().all_cpu_events().size());
+  for (const auto& cpu_events : model.cpu_model().all_cpu_events())
+    EXPECT_TRUE(ValidateCpuEvents(cpu_events));
+
   // Perform several well-known queries.
   EXPECT_FALSE(model.Select(kAcquireBufferQuery).empty());
   EXPECT_FALSE(model.Select(kAttachSurfaceQueury).empty());
@@ -140,20 +162,20 @@
   ASSERT_TRUE(graphics_model.Build(model));
 
   ASSERT_EQ(1U, graphics_model.android_top_level().buffer_events().size());
-  EXPECT_TRUE(ValidateGrahpicsEvent(
+  EXPECT_TRUE(ValidateGrahpicsEvents(
       graphics_model.android_top_level().buffer_events()[0],
       {GraphicsEventType::kSurfaceFlingerInvalidationStart,
        GraphicsEventType::kSurfaceFlingerInvalidationDone,
        GraphicsEventType::kSurfaceFlingerCompositionStart,
        GraphicsEventType::kSurfaceFlingerCompositionDone}));
-  EXPECT_TRUE(ValidateGrahpicsEvent(
+  EXPECT_TRUE(ValidateGrahpicsEvents(
       graphics_model.android_top_level().global_events(),
       {GraphicsEventType::kVsync,
        GraphicsEventType::kSurfaceFlingerCompositionJank}));
   EXPECT_EQ(2U, graphics_model.chrome_top_level().buffer_events().size());
   for (const auto& chrome_top_level_band :
        graphics_model.chrome_top_level().buffer_events()) {
-    EXPECT_TRUE(ValidateGrahpicsEvent(
+    EXPECT_TRUE(ValidateGrahpicsEvents(
         chrome_top_level_band, {
                                    GraphicsEventType::kChromeOSDraw,
                                    GraphicsEventType::kChromeOSSwap,
@@ -169,7 +191,7 @@
     EXPECT_NE(std::string(), view.first.activity);
     EXPECT_FALSE(view.second.buffer_events().empty());
     for (const auto& buffer : view.second.buffer_events()) {
-      EXPECT_TRUE(ValidateGrahpicsEvent(
+      EXPECT_TRUE(ValidateGrahpicsEvents(
           buffer, {
                       GraphicsEventType::kBufferQueueDequeueStart,
                       GraphicsEventType::kBufferQueueDequeueDone,
@@ -187,6 +209,19 @@
                   }));
     }
   }
+
+  // Note, CPU events in |graphics_model| are normalized by timestamp. So they
+  // are not equal and we cannot do direct comparison.
+  ASSERT_EQ(graphics_model.cpu_model().all_cpu_events().size(),
+            model.cpu_model().all_cpu_events().size());
+  EXPECT_EQ(graphics_model.cpu_model().thread_map(),
+            model.cpu_model().thread_map());
+  for (size_t i = 0; i < graphics_model.cpu_model().all_cpu_events().size();
+       ++i) {
+    EXPECT_EQ(graphics_model.cpu_model().all_cpu_events()[i].size(),
+              model.cpu_model().all_cpu_events()[i].size());
+  }
+
   EXPECT_GT(graphics_model.duration(), 0U);
 
   // Serialize and restore;
@@ -203,6 +238,7 @@
             graphics_model_loaded.chrome_top_level());
   EXPECT_EQ(graphics_model.view_buffers(),
             graphics_model_loaded.view_buffers());
+  EXPECT_EQ(graphics_model.cpu_model(), graphics_model_loaded.cpu_model());
   EXPECT_EQ(graphics_model.duration(), graphics_model_loaded.duration());
 }
 
diff --git a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.h b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.h
index 389f7f99..c3f25c38 100644
--- a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.h
+++ b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.h
@@ -11,7 +11,7 @@
 #include "base/cancelable_callback.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/authpolicy/kerberos_files_handler.h"
-#include "chromeos/dbus/authpolicy/active_directory_info.pb.h"
+#include "chromeos/dbus/auth_policy/active_directory_info.pb.h"
 #include "chromeos/network/network_state_handler_observer.h"
 #include "components/account_id/account_id.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
index b0af16c5..7508030 100644
--- a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
+++ b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/ui/ash/media_client.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
@@ -244,12 +243,11 @@
   // cause a bug (https://crbug.com/924844).
   if (base::FeatureList::IsEnabled(features::kDMServerOAuthForChildUser) &&
       session_manager::SessionManager::Get()->session_state() !=
-          session_manager::SessionState::ACTIVE)
+          session_manager::SessionState::ACTIVE) {
     return;
+  }
 
-  chromeos::DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->RequestLockScreen();
+  chromeos::SessionManagerClient::Get()->RequestLockScreen();
 }
 
 void ScreenTimeController::OnScreenLockByPolicy(
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 9dbb61b..62358d8 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -383,7 +383,7 @@
     UpgradeDetectorChromeos::GetInstance()->Init();
 
     DeviceSettingsService::Get()->SetSessionManager(
-        DBusThreadManager::Get()->GetSessionManagerClient(),
+        SessionManagerClient::Get(),
         OwnerSettingsServiceChromeOSFactory::GetInstance()->GetOwnerKeyUtil());
   }
 
diff --git a/chrome/browser/chromeos/dbus/dbus_helper.cc b/chrome/browser/chromeos/dbus/dbus_helper.cc
index 05f6612..9d44510 100644
--- a/chrome/browser/chromeos/dbus/dbus_helper.cc
+++ b/chrome/browser/chromeos/dbus/dbus_helper.cc
@@ -19,6 +19,7 @@
 #include "chromeos/dbus/media_analytics/media_analytics_client.h"
 #include "chromeos/dbus/permission_broker/permission_broker_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/dbus/system_clock/system_clock_client.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "chromeos/tpm/install_attributes.h"
@@ -60,6 +61,7 @@
     MediaAnalyticsClient::Initialize(bus);
     PermissionBrokerClient::Initialize(bus);
     PowerManagerClient::Initialize(bus);
+    SessionManagerClient::Initialize(bus);
     SystemClockClient::Initialize(bus);
     UpstartClient::Initialize(bus);
   } else {
@@ -71,6 +73,7 @@
     MediaAnalyticsClient::InitializeFake();
     PermissionBrokerClient::InitializeFake();
     PowerManagerClient::InitializeFake();
+    SessionManagerClient::InitializeFake();
     SystemClockClient::InitializeFake();
     UpstartClient::InitializeFake();
   }
@@ -85,6 +88,7 @@
 void ShutdownDBus() {
   UpstartClient::Shutdown();
   SystemClockClient::Shutdown();
+  SessionManagerClient::Shutdown();
   PowerManagerClient::Shutdown();
   PermissionBrokerClient::Shutdown();
   MediaAnalyticsClient::Shutdown();
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
index 5eeef7b5..c778271 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -319,9 +319,7 @@
 ExtensionFunction::ResponseAction AutotestPrivateLockScreenFunction::Run() {
   DVLOG(1) << "AutotestPrivateLockScreenFunction";
 
-  chromeos::DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->RequestLockScreen();
+  chromeos::SessionManagerClient::Get()->RequestLockScreen();
   return RespondNow(NoArguments());
 }
 
diff --git a/chrome/browser/chromeos/fileapi/file_system_backend.cc b/chrome/browser/chromeos/fileapi/file_system_backend.cc
index 43a1938..2f324da 100644
--- a/chrome/browser/chromeos/fileapi/file_system_backend.cc
+++ b/chrome/browser/chromeos/fileapi/file_system_backend.cc
@@ -460,10 +460,12 @@
           url.path(), offset, storage::FileStreamWriter::OPEN_EXISTING_FILE);
     case storage::kFileSystemTypeDeviceMediaAsFileStorage:
       return mtp_delegate_->CreateFileStreamWriter(url, offset, context);
+    case storage::kFileSystemTypeArcDocumentsProvider:
+      return arc_documents_provider_delegate_->CreateFileStreamWriter(
+          url, offset, context);
     // Read only file systems.
     case storage::kFileSystemTypeRestrictedNativeLocal:
     case storage::kFileSystemTypeArcContent:
-    case storage::kFileSystemTypeArcDocumentsProvider:
       return std::unique_ptr<storage::FileStreamWriter>();
     default:
       NOTREACHED();
diff --git a/chrome/browser/chromeos/input_method/candidate_window_controller_impl.h b/chrome/browser/chromeos/input_method/candidate_window_controller_impl.h
index 436ee992..fe60df6 100644
--- a/chrome/browser/chromeos/input_method/candidate_window_controller_impl.h
+++ b/chrome/browser/chromeos/input_method/candidate_window_controller_impl.h
@@ -10,7 +10,7 @@
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "chrome/browser/chromeos/input_method/candidate_window_controller.h"
-#include "ui/base/ime/chromeos/ime_candidate_window_handler_interface.h"
+#include "ui/base/ime/ime_candidate_window_handler_interface.h"
 #include "ui/base/ime/infolist_entry.h"
 #include "ui/chromeos/ime/candidate_window_view.h"
 #include "ui/views/widget/widget_observer.h"
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
index ec7414f9fa..6cf7db79 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
@@ -35,7 +35,7 @@
 #include "ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h"
 #include "ui/base/ime/chromeos/mock_ime_engine_handler.h"
 #include "ui/base/ime/ime_bridge.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/input_method/textinput_test_helper.cc b/chrome/browser/chromeos/input_method/textinput_test_helper.cc
index b2cfba3..b69c4df 100644
--- a/chrome/browser/chromeos/input_method/textinput_test_helper.cc
+++ b/chrome/browser/chromeos/input_method/textinput_test_helper.cc
@@ -19,7 +19,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_tree_host.h"
-#include "ui/base/ime/input_method_factory.h"
+#include "ui/base/ime/init/input_method_factory.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/lock_screen_apps/lock_screen_profile_creator_impl.cc b/chrome/browser/chromeos/lock_screen_apps/lock_screen_profile_creator_impl.cc
index c9b69c3..591ba0fa 100644
--- a/chrome/browser/chromeos/lock_screen_apps/lock_screen_profile_creator_impl.cc
+++ b/chrome/browser/chromeos/lock_screen_apps/lock_screen_profile_creator_impl.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/one_shot_event.h"
 #include "base/strings/string16.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
@@ -19,7 +20,6 @@
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/common/one_shot_event.h"
 
 namespace lock_screen_apps {
 
@@ -69,9 +69,10 @@
   // before testing for lock screen enabled app existence.
   extensions::ExtensionSystem::Get(primary_profile_)
       ->ready()
-      .Post(FROM_HERE,
-            base::Bind(&LockScreenProfileCreatorImpl::OnExtensionSystemReady,
-                       weak_ptr_factory_.GetWeakPtr()));
+      .Post(
+          FROM_HERE,
+          base::BindOnce(&LockScreenProfileCreatorImpl::OnExtensionSystemReady,
+                         weak_ptr_factory_.GetWeakPtr()));
 }
 
 void LockScreenProfileCreatorImpl::OnExtensionSystemReady() {
diff --git a/chrome/browser/chromeos/login/active_directory_test_helper.cc b/chrome/browser/chromeos/login/active_directory_test_helper.cc
index 9a94fba..a859aaf 100644
--- a/chrome/browser/chromeos/login/active_directory_test_helper.cc
+++ b/chrome/browser/chromeos/login/active_directory_test_helper.cc
@@ -14,8 +14,8 @@
 #include "chrome/browser/chromeos/authpolicy/authpolicy_helper.h"
 #include "chrome/common/chrome_paths.h"
 #include "chromeos/constants/chromeos_paths.h"
+#include "chromeos/dbus/auth_policy/active_directory_info.pb.h"
 #include "chromeos/dbus/auth_policy/auth_policy_client.h"
-#include "chromeos/dbus/authpolicy/active_directory_info.pb.h"
 #include "chromeos/dbus/cryptohome/tpm_util.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc b/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc
index 65c030b2..835eca5f 100644
--- a/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc
@@ -34,7 +34,7 @@
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/tpm/stub_install_attributes.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -290,7 +290,6 @@
       : install_attributes_(
             chromeos::StubInstallAttributes::CreateCloudManaged("domain.com",
                                                                 "device_id")),
-        fake_session_manager_(new PersistentSessionManagerClient()),
         fake_cws_(new FakeCWS) {
     set_chromeos_user_ = false;
   }
@@ -303,6 +302,9 @@
   }
 
   void SetUp() override {
+    // Will be destroyed in ChromeBrowserMain.
+    fake_session_manager_ = new PersistentSessionManagerClient();
+
     ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
     AppLaunchController::SkipSplashWaitForTesting();
 
@@ -350,8 +352,6 @@
 
     // Arbitrary non-empty state keys.
     fake_session_manager_->set_server_backed_state_keys({"1"});
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::move(fake_session_manager_));
 
     extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture();
   }
@@ -496,7 +496,8 @@
   chromeos::ScopedStubInstallAttributes install_attributes_;
   policy::UserPolicyBuilder device_local_account_policy_;
   policy::DevicePolicyCrosTestHelper device_policy_helper_;
-  std::unique_ptr<PersistentSessionManagerClient> fake_session_manager_;
+  // Owned by SessionManagerClient global instance.
+  PersistentSessionManagerClient* fake_session_manager_;
   std::unique_ptr<FakeCWS> fake_cws_;
 
   DISALLOW_COPY_AND_ASSIGN(AutoLaunchedKioskTest);
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index fd16241c..9d58db3 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -298,7 +298,7 @@
   // Ownership of local_auth_fd is passed to the callback that is to be
   // called on completion of this method call. This keeps the browser end
   // of the socket-pair alive for the duration of the RPC.
-  DBusThreadManager::Get()->GetSessionManagerClient()->RestartJob(
+  SessionManagerClient::Get()->RestartJob(
       remote_auth_fd.get(), argv_,
       base::Bind(&ChromeRestartRequest::OnRestartJob, AsWeakPtr(),
                  base::Passed(&local_auth_fd)));
diff --git a/chrome/browser/chromeos/login/configuration_based_enrollment_browsertest.cc b/chrome/browser/chromeos/login/configuration_based_enrollment_browsertest.cc
index 4c67c37a..c2591f79 100644
--- a/chrome/browser/chromeos/login/configuration_based_enrollment_browsertest.cc
+++ b/chrome/browser/chromeos/login/configuration_based_enrollment_browsertest.cc
@@ -17,7 +17,7 @@
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_update_engine_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/test/chromeos_test_utils.h"
 #include "components/language/core/browser/pref_names.h"
diff --git a/chrome/browser/chromeos/login/crash_restore_browsertest.cc b/chrome/browser/chromeos/login/crash_restore_browsertest.cc
index b0954af..095a815 100644
--- a/chrome/browser/chromeos/login/crash_restore_browsertest.cc
+++ b/chrome/browser/chromeos/login/crash_restore_browsertest.cc
@@ -27,7 +27,6 @@
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/session_manager/core/session_manager.h"
@@ -63,14 +62,11 @@
   }
 
   void SetUpInProcessBrowserTestFixture() override {
-    // Redirect session_manager DBus calls to FakeSessionManagerClient.
-    session_manager_client_ = new FakeSessionManagerClient;
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(session_manager_client_));
-    session_manager_client_->StartSession(cryptohome_id1_);
+    // Override FakeSessionManagerClient. This will be shut down by the browser.
+    SessionManagerClient::InitializeFakeInMemory();
+    FakeSessionManagerClient::Get()->StartSession(cryptohome_id1_);
   }
 
-  FakeSessionManagerClient* session_manager_client_;
   const AccountId account_id1_ = AccountId::FromUserEmail(kUserId1);
   const AccountId account_id2_ = AccountId::FromUserEmail(kUserId2);
   const AccountId account_id3_ = AccountId::FromUserEmail(kUserId3);
@@ -152,8 +148,8 @@
 
   void SetUpInProcessBrowserTestFixture() override {
     CrashRestoreSimpleTest::SetUpInProcessBrowserTestFixture();
-    session_manager_client_->StartSession(cryptohome_id2_);
-    session_manager_client_->StartSession(cryptohome_id3_);
+    FakeSessionManagerClient::Get()->StartSession(cryptohome_id2_);
+    FakeSessionManagerClient::Get()->StartSession(cryptohome_id3_);
   }
 
   // Register test users so that UserManager knows them and make kUserId3 as the
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc
index 60130272..51b52b28 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc
@@ -35,7 +35,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller_unittest.cc
index f68f068..2ab622e6 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller_unittest.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller_unittest.cc
@@ -25,6 +25,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "chromeos/tpm/stub_install_attributes.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
@@ -100,6 +101,7 @@
   void SetUp() override {
     SystemSaltGetter::Initialize();
     DBusThreadManager::Initialize();
+    SessionManagerClient::InitializeFake();
     DeviceSettingsService::Initialize();
     TestingBrowserProcess::GetGlobal()
         ->platform_part()
@@ -112,6 +114,7 @@
 
   void TearDown() override {
     EnterpriseEnrollmentHelper::SetEnrollmentHelperMock(nullptr);
+    SessionManagerClient::Shutdown();
     DBusThreadManager::Shutdown();
     SystemSaltGetter::Shutdown();
     DeviceSettingsService::Shutdown();
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
index 0183820f..47ea9f6 100644
--- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
@@ -781,11 +781,9 @@
 
   // D-Bus services may not be available yet, so we call
   // WaitForServiceToBeAvailable. See https://crbug.com/841627.
-  DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->WaitForServiceToBeAvailable(base::BindOnce(
-          &AutoEnrollmentController::StartClearForcedReEnrollmentVpd,
-          weak_ptr_factory_.GetWeakPtr()));
+  SessionManagerClient::Get()->WaitForServiceToBeAvailable(
+      base::BindOnce(&AutoEnrollmentController::StartClearForcedReEnrollmentVpd,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 void AutoEnrollmentController::StartClearForcedReEnrollmentVpd(
@@ -798,11 +796,9 @@
     return;
   }
 
-  DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->ClearForcedReEnrollmentVpd(base::BindOnce(
-          &AutoEnrollmentController::OnForcedReEnrollmentVpdCleared,
-          weak_ptr_factory_.GetWeakPtr()));
+  SessionManagerClient::Get()->ClearForcedReEnrollmentVpd(
+      base::BindOnce(&AutoEnrollmentController::OnForcedReEnrollmentVpdCleared,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 void AutoEnrollmentController::OnForcedReEnrollmentVpdCleared(bool reply) {
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen_view.h b/chrome/browser/chromeos/login/enrollment/enrollment_screen_view.h
index f527783..d0ce52a9 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen_view.h
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen_view.h
@@ -10,7 +10,7 @@
 #include "base/values.h"
 #include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper.h"
 #include "chrome/browser/chromeos/login/oobe_screen.h"
-#include "chromeos/dbus/authpolicy/active_directory_info.pb.h"
+#include "chromeos/dbus/auth_policy/active_directory_info.pb.h"
 
 class GoogleServiceAuthError;
 
diff --git a/chrome/browser/chromeos/login/enrollment/hands_off_enrollment_browsertest.cc b/chrome/browser/chromeos/login/enrollment/hands_off_enrollment_browsertest.cc
index 5f846eb..b469387 100644
--- a/chrome/browser/chromeos/login/enrollment/hands_off_enrollment_browsertest.cc
+++ b/chrome/browser/chromeos/login/enrollment/hands_off_enrollment_browsertest.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 7efeda45..7253ca4b 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -74,7 +74,6 @@
 #include "chromeos/cryptohome/async_method_caller.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/cryptohome/cryptohome_util.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/login/auth/key.h"
@@ -888,12 +887,12 @@
       last_login_attempt_account_id_);
   if (failure.reason() == AuthFailure::OWNER_REQUIRED) {
     ShowError(IDS_LOGIN_ERROR_OWNER_REQUIRED, error);
+    // Using Untretained here is safe because SessionManagerClient is destroyed
+    // after the task runner, in ChromeBrowserMainParts::PostDestroyThreads().
     base::PostDelayedTaskWithTraits(
         FROM_HERE, {content::BrowserThread::UI},
-        base::BindOnce(
-            &SessionManagerClient::StopSession,
-            base::Unretained(
-                DBusThreadManager::Get()->GetSessionManagerClient())),
+        base::BindOnce(&SessionManagerClient::StopSession,
+                       base::Unretained(SessionManagerClient::Get())),
         base::TimeDelta::FromMilliseconds(kSafeModeRestartUiDelayMs));
   } else if (failure.reason() == AuthFailure::TPM_ERROR) {
     ShowTPMError();
@@ -1168,8 +1167,7 @@
       chromeos::GetDeviceDMTokenForUserPolicyGetter(
           user_context.GetAccountId()));
   pre_signin_policy_fetcher_ = std::make_unique<policy::PreSigninPolicyFetcher>(
-      CryptohomeClient::Get(),
-      DBusThreadManager::Get()->GetSessionManagerClient(),
+      CryptohomeClient::Get(), SessionManagerClient::Get(),
       std::move(cloud_policy_client), IsActiveDirectoryManaged(),
       user_context.GetAccountId(),
       cryptohome::KeyDefinition::CreateForPassword(
diff --git a/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc b/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc
index 4883d7c..658837f 100644
--- a/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller_auto_login_unittest.cc
@@ -17,7 +17,9 @@
 #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
+#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/settings/cros_settings_names.h"
+#include "components/ownership/mock_owner_key_util.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -64,7 +66,10 @@
             auto_login_account_id_)));
 
     settings_helper_.ReplaceDeviceSettingsProviderWithStub();
-    settings_helper_.SetFakeSessionManager();
+
+    DeviceSettingsService::Get()->SetSessionManager(
+        FakeSessionManagerClient::Get(), new ownership::MockOwnerKeyUtil());
+    DeviceSettingsService::Get()->Load();
 
     std::unique_ptr<base::DictionaryValue> account(new base::DictionaryValue);
     account->SetKey(kAccountsPrefDeviceLocalAccountsKeyId,
@@ -140,6 +145,7 @@
   ScopedTestingLocalState local_state_;
 
   // Required by ExistingUserController:
+  FakeSessionManagerClient fake_session_manager_client_;
   ScopedCrosSettingsTestHelper settings_helper_;
   MockUserManager* mock_user_manager_;
   user_manager::ScopedUserManager scoped_user_manager_;
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc
index 648d74f..298c667 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -49,7 +49,6 @@
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/audio/chromeos_sounds.h"
 #include "chromeos/dbus/biod/constants.pb.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/login/auth/authenticator.h"
 #include "chromeos/login/auth/extended_authenticator.h"
@@ -96,15 +95,13 @@
  public:
   ScreenLockObserver() : session_started_(false) {
     session_manager::SessionManager::Get()->AddObserver(this);
-    DBusThreadManager::Get()->GetSessionManagerClient()->SetStubDelegate(this);
+    SessionManagerClient::Get()->SetStubDelegate(this);
   }
 
   ~ScreenLockObserver() override {
     session_manager::SessionManager::Get()->RemoveObserver(this);
-    if (DBusThreadManager::IsInitialized()) {
-      DBusThreadManager::Get()->GetSessionManagerClient()->SetStubDelegate(
-          nullptr);
-    }
+    if (SessionManagerClient::Get())
+      SessionManagerClient::Get()->SetStubDelegate(nullptr);
   }
 
   bool session_started() const { return session_started_; }
@@ -526,7 +523,7 @@
     // screen while remaining secure in the case the user walks away during
     // the sign-in steps. See crbug.com/112225 and crbug.com/110933.
     VLOG(1) << "Calling session manager's StopSession D-Bus method";
-    DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
+    SessionManagerClient::Get()->StopSession();
   }
 }
 
@@ -552,9 +549,7 @@
   } else {
     VLOG(1) << "ScreenLocker " << screen_locker_ << " already exists; "
             << " calling session manager's HandleLockScreenShown D-Bus method";
-    DBusThreadManager::Get()
-        ->GetSessionManagerClient()
-        ->NotifyLockScreenShown();
+    SessionManagerClient::Get()->NotifyLockScreenShown();
   }
 }
 
@@ -641,9 +636,7 @@
       content::Source<ScreenLocker>(this), content::Details<bool>(&state));
 
   VLOG(1) << "Calling session manager's HandleLockScreenDismissed D-Bus method";
-  DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->NotifyLockScreenDismissed();
+  SessionManagerClient::Get()->NotifyLockScreenDismissed();
 
   if (saved_ime_state_.get()) {
     input_method::InputMethodManager::Get()->SetState(saved_ime_state_);
@@ -663,7 +656,7 @@
       chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
       content::Source<ScreenLocker>(this), content::Details<bool>(&state));
   VLOG(1) << "Calling session manager's HandleLockScreenShown D-Bus method";
-  DBusThreadManager::Get()->GetSessionManagerClient()->NotifyLockScreenShown();
+  SessionManagerClient::Get()->NotifyLockScreenShown();
 
   session_manager::SessionManager::Get()->SetSessionState(
       session_manager::SessionState::LOCKED);
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
index dce35e0..2369a05 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
@@ -23,7 +23,6 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/dbus/biod/fake_biod_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "components/prefs/pref_service.h"
 #include "components/session_manager/core/session_manager.h"
@@ -61,15 +60,11 @@
   ~ScreenLockerTest() override = default;
 
   FakeSessionManagerClient* session_manager_client() {
-    return fake_session_manager_client_;
+    return FakeSessionManagerClient::Get();
   }
 
   // InProcessBrowserTest:
   void SetUpInProcessBrowserTestFixture() override {
-    fake_session_manager_client_ = new FakeSessionManagerClient;
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(fake_session_manager_client_));
-
     zero_duration_mode_ =
         std::make_unique<ui::ScopedAnimationDurationScaleMode>(
             ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
@@ -102,8 +97,6 @@
  private:
   void OnStartSession(const dbus::ObjectPath& path) {}
 
-  FakeSessionManagerClient* fake_session_manager_client_ = nullptr;
-
   std::unique_ptr<ui::ScopedAnimationDurationScaleMode> zero_duration_mode_;
 
   DISALLOW_COPY_AND_ASSIGN(ScreenLockerTest);
diff --git a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
index 20e890f..7fe1c264 100644
--- a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
+++ b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
@@ -16,6 +16,8 @@
 #include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
+#include "chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.h"
+#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/test/test_predicate_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
@@ -129,7 +131,7 @@
         chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
         content::NotificationService::AllSources());
     observer.Wait();
-    test::CreateOobeScreenWaiter("connect")->Wait();
+    OobeScreenWaiter(OobeScreen::SCREEN_OOBE_WELCOME).Wait();
   }
 
   void RunWelcomeScreenChecks() {
@@ -155,7 +157,7 @@
   }
 
   void WaitForNetworkSelectionScreen() {
-    test::CreateOobeScreenWaiter("network-selection")->Wait();
+    OobeScreenWaiter(OobeScreen::SCREEN_OOBE_NETWORK).Wait();
     LOG(INFO)
         << "OobeInteractiveUITest: Switched to 'network-selection' screen.";
   }
@@ -173,7 +175,7 @@
   }
 
   void WaitForEulaScreen() {
-    test::CreateOobeScreenWaiter("eula")->Wait();
+    OobeScreenWaiter(OobeScreen::SCREEN_OOBE_EULA).Wait();
     LOG(INFO) << "OobeInteractiveUITest: Switched to 'eula' screen.";
   }
 
@@ -190,7 +192,7 @@
   }
 
   void WaitForUpdateScreen() {
-    test::CreateOobeScreenWaiter("update")->Wait();
+    OobeScreenWaiter(OobeScreen::SCREEN_OOBE_UPDATE).Wait();
     test::OobeJS().CreateVisibilityWaiter(true, {"update"})->Wait();
 
     LOG(INFO) << "OobeInteractiveUITest: Switched to 'update' screen.";
@@ -206,7 +208,7 @@
   }
 
   void WaitForGaiaSignInScreen() {
-    test::CreateOobeScreenWaiter("gaia-signin")->Wait();
+    OobeScreenWaiter(OobeScreen::SCREEN_GAIA_SIGNIN).Wait();
     LOG(INFO) << "OobeInteractiveUITest: Switched to 'gaia-signin' screen.";
   }
 
@@ -222,7 +224,7 @@
 
   void WaitForSyncConsentScreen() {
     LOG(INFO) << "OobeInteractiveUITest: Waiting for 'sync-consent' screen.";
-    test::CreateOobeScreenWaiter("sync-consent")->Wait();
+    OobeScreenWaiter(OobeScreen::SCREEN_SYNC_CONSENT).Wait();
   }
 
   void ExitScreenSyncConsent() {
@@ -234,15 +236,13 @@
     screen->OnStateChanged(nullptr);
     LOG(INFO) << "OobeInteractiveUITest: Waiting for 'sync-consent' screen "
                  "to close.";
-    test::CreatePredicateOrOobeDestroyedWaiter(
-        "Oobe.getInstance().currentScreen.id != 'sync-consent'")
-        ->Wait();
+    OobeScreenExitWaiter(OobeScreen::SCREEN_SYNC_CONSENT).Wait();
   }
 
   void WaitForFingerprintScreen() {
     LOG(INFO)
         << "OobeInteractiveUITest: Waiting for 'fingerprint-setup' screen.";
-    test::CreateOobeScreenWaiter("fingerprint-setup")->Wait();
+    OobeScreenWaiter(OobeScreen::SCREEN_FINGERPRINT_SETUP).Wait();
     LOG(INFO) << "OobeInteractiveUITest: Waiting for fingerprint setup screen "
                  "to show.";
     test::OobeJS().CreateVisibilityWaiter(true, {"fingerprint-setup"})->Wait();
@@ -284,14 +284,12 @@
         "$('fingerprint-setup-impl').$.setupFingerprintLater.click()");
     LOG(INFO) << "OobeInteractiveUITest: Waiting for fingerprint setup screen "
                  "to close.";
-    test::CreatePredicateOrOobeDestroyedWaiter(
-        "Oobe.getInstance().currentScreen.id != 'fingerprint-setup'")
-        ->Wait();
+    OobeScreenExitWaiter(OobeScreen::SCREEN_FINGERPRINT_SETUP).Wait();
     LOG(INFO) << "OobeInteractiveUITest: 'fingerprint-setup' screen done.";
   }
 
   void WaitForDiscoverScreen() {
-    test::CreateOobeScreenWaiter("discover")->Wait();
+    OobeScreenWaiter(OobeScreen::SCREEN_DISCOVER).Wait();
     LOG(INFO) << "OobeInteractiveUITest: Switched to 'discover' screen.";
   }
 
@@ -316,9 +314,7 @@
     test::OobeJS().ExecuteAsync(
         "$('discover-impl').root.querySelector('discover-pin-setup-module')."
         "$.setupSkipButton.click()");
-    test::CreatePredicateOrOobeDestroyedWaiter(
-        "Oobe.getInstance().currentScreen.id != 'discover'")
-        ->Wait();
+    OobeScreenExitWaiter(OobeScreen::SCREEN_DISCOVER).Wait();
     LOG(INFO) << "OobeInteractiveUITest: 'discover' screen done.";
   }
 
diff --git a/chrome/browser/chromeos/login/reset_browsertest.cc b/chrome/browser/chromeos/login/reset_browsertest.cc
index c6d9f10..5eba38b 100644
--- a/chrome/browser/chromeos/login/reset_browsertest.cc
+++ b/chrome/browser/chromeos/login/reset_browsertest.cc
@@ -44,9 +44,6 @@
   void SetUpInProcessBrowserTestFixture() override {
     std::unique_ptr<DBusThreadManagerSetter> dbus_setter =
         chromeos::DBusThreadManager::GetSetterForTesting();
-    session_manager_client_ = new FakeSessionManagerClient;
-    dbus_setter->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(session_manager_client_));
     update_engine_client_ = new FakeUpdateEngineClient;
     dbus_setter->SetUpdateEngineClient(
         std::unique_ptr<UpdateEngineClient>(update_engine_client_));
@@ -97,7 +94,6 @@
   }
 
   FakeUpdateEngineClient* update_engine_client_ = nullptr;
-  FakeSessionManagerClient* session_manager_client_ = nullptr;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ResetTest);
@@ -134,10 +130,10 @@
 
   InvokeResetScreen();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
-  EXPECT_EQ(0, session_manager_client_->start_device_wipe_call_count());
+  EXPECT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   ClickRestartButton();
   ASSERT_EQ(1, FakePowerManagerClient::Get()->num_request_restart_calls());
-  ASSERT_EQ(0, session_manager_client_->start_device_wipe_call_count());
+  ASSERT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
 
   EXPECT_TRUE(prefs->GetBoolean(prefs::kFactoryResetRequested));
 }
@@ -214,13 +210,13 @@
 
   InvokeResetScreen();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
-  EXPECT_EQ(0, session_manager_client_->start_device_wipe_call_count());
+  EXPECT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   EXPECT_EQ(0, update_engine_client_->rollback_call_count());
   InvokeRollbackOption();  // No changes
   ClickToConfirmButton();
   ClickResetButton();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
-  EXPECT_EQ(1, session_manager_client_->start_device_wipe_call_count());
+  EXPECT_EQ(1, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   EXPECT_EQ(0, update_engine_client_->rollback_call_count());
   CloseResetScreen();
   OobeScreenWaiter(OobeScreen::SCREEN_ACCOUNT_PICKER).Wait();
@@ -232,7 +228,7 @@
   ClickToConfirmButton();
   ClickResetButton();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
-  EXPECT_EQ(2, session_manager_client_->start_device_wipe_call_count());
+  EXPECT_EQ(2, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   EXPECT_EQ(0, update_engine_client_->rollback_call_count());
   CloseResetScreen();
 }
@@ -249,12 +245,12 @@
 
   InvokeResetScreen();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
-  EXPECT_EQ(0, session_manager_client_->start_device_wipe_call_count());
+  EXPECT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   EXPECT_EQ(0, update_engine_client_->rollback_call_count());
   ClickToConfirmButton();
   ClickResetButton();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
-  EXPECT_EQ(1, session_manager_client_->start_device_wipe_call_count());
+  EXPECT_EQ(1, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   EXPECT_EQ(0, update_engine_client_->rollback_call_count());
   CloseResetScreen();
   OobeScreenWaiter(OobeScreen::SCREEN_ACCOUNT_PICKER).Wait();
@@ -269,7 +265,7 @@
   ClickToConfirmButton();
   ClickResetButton();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
-  EXPECT_EQ(2, session_manager_client_->start_device_wipe_call_count());
+  EXPECT_EQ(2, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   EXPECT_EQ(0, update_engine_client_->rollback_call_count());
   CloseResetScreen();
   OobeScreenWaiter(OobeScreen::SCREEN_ACCOUNT_PICKER).Wait();
@@ -280,7 +276,7 @@
   ClickToConfirmButton();
   ClickResetButton();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
-  EXPECT_EQ(2, session_manager_client_->start_device_wipe_call_count());
+  EXPECT_EQ(2, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   EXPECT_EQ(1, update_engine_client_->rollback_call_count());
 }
 
@@ -294,14 +290,14 @@
   update_engine_client_->set_can_rollback_check_result(true);
   OobeScreenWaiter(OobeScreen::SCREEN_OOBE_RESET).Wait();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
-  EXPECT_EQ(0, session_manager_client_->start_device_wipe_call_count());
+  EXPECT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   EXPECT_EQ(0, update_engine_client_->rollback_call_count());
   test::OobeJS().ExpectHasNoClass("revert-promise-view", {"reset"});
   InvokeRollbackOption();
   ClickToConfirmButton();
   ClickResetButton();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
-  EXPECT_EQ(0, session_manager_client_->start_device_wipe_call_count());
+  EXPECT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   EXPECT_EQ(1, update_engine_client_->rollback_call_count());
   test::OobeJS().ExpectHasClass("revert-promise-view", {"reset"});
   UpdateEngineClient::Status error_update_status;
@@ -320,7 +316,7 @@
   update_engine_client_->set_can_rollback_check_result(true);
   OobeScreenWaiter(OobeScreen::SCREEN_OOBE_RESET).Wait();
   EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls());
-  EXPECT_EQ(0, session_manager_client_->start_device_wipe_call_count());
+  EXPECT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   EXPECT_EQ(0, update_engine_client_->rollback_call_count());
   test::OobeJS().ExpectHasNoClass("rollback-proposal-view", {"reset"});
   InvokeRollbackOption();
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
index b218c1ca..0196cbf 100644
--- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc
+++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -64,7 +64,7 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/login/auth/key.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "components/account_id/account_id.h"
@@ -468,7 +468,6 @@
   base::ReplaceSubstringsAfterOffset(&js, 0, "$Host", kIdPHost);
   test::OobeJS().ExpectTrue(js);
 
-
   content::DOMMessageQueue message_queue;  // Observe before 'cancel'.
   SetupAuthFlowChangeListener();
   // Click on 'cancel'.
@@ -905,13 +904,8 @@
 
  protected:
   policy::DevicePolicyCrosTestHelper test_helper_;
-
-  // FakeDBusThreadManager uses FakeSessionManagerClient.
-  FakeSessionManagerClient* fake_session_manager_client_;
   policy::DevicePolicyBuilder* device_policy_;
-
   policy::MockConfigurationPolicyProvider provider_;
-
   net::CookieList cookie_list_;
 
  private:
@@ -919,14 +913,12 @@
 };
 
 SAMLPolicyTest::SAMLPolicyTest()
-    : fake_session_manager_client_(new FakeSessionManagerClient),
-      device_policy_(test_helper_.device_policy()) {}
+    : device_policy_(test_helper_.device_policy()) {}
 
 SAMLPolicyTest::~SAMLPolicyTest() {}
 
 void SAMLPolicyTest::SetUpInProcessBrowserTestFixture() {
-  DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-      std::unique_ptr<SessionManagerClient>(fake_session_manager_client_));
+  SessionManagerClient::InitializeFakeInMemory();
 
   SamlTest::SetUpInProcessBrowserTestFixture();
 
@@ -934,7 +926,7 @@
   std::set<std::string> device_affiliation_ids;
   device_affiliation_ids.insert(kAffiliationID);
   auto affiliation_helper = policy::AffiliationTestHelper::CreateForCloud(
-      fake_session_manager_client_);
+      FakeSessionManagerClient::Get());
   ASSERT_NO_FATAL_FAILURE((affiliation_helper.SetDeviceAffiliationIDs(
       &test_helper_, device_affiliation_ids)));
 
@@ -1003,8 +995,8 @@
                                                run_loop.QuitClosure());
   device_policy_->SetDefaultSigningKey();
   device_policy_->Build();
-  fake_session_manager_client_->set_device_policy(device_policy_->GetBlob());
-  fake_session_manager_client_->OnPropertyChangeComplete(true);
+  FakeSessionManagerClient::Get()->set_device_policy(device_policy_->GetBlob());
+  FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
   run_loop.Run();
 }
 
@@ -1020,8 +1012,8 @@
                                                run_loop.QuitClosure());
   device_policy_->SetDefaultSigningKey();
   device_policy_->Build();
-  fake_session_manager_client_->set_device_policy(device_policy_->GetBlob());
-  fake_session_manager_client_->OnPropertyChangeComplete(true);
+  FakeSessionManagerClient::Get()->set_device_policy(device_policy_->GetBlob());
+  FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
   run_loop.Run();
 }
 
@@ -1037,8 +1029,8 @@
                                                run_loop.QuitClosure());
   device_policy_->SetDefaultSigningKey();
   device_policy_->Build();
-  fake_session_manager_client_->set_device_policy(device_policy_->GetBlob());
-  fake_session_manager_client_->OnPropertyChangeComplete(true);
+  FakeSessionManagerClient::Get()->set_device_policy(device_policy_->GetBlob());
+  FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
   run_loop.Run();
 }
 
diff --git a/chrome/browser/chromeos/login/screens/demo_setup_screen.cc b/chrome/browser/chromeos/login/screens/demo_setup_screen.cc
index d2de28ac..0043e96c 100644
--- a/chrome/browser/chromeos/login/screens/demo_setup_screen.cc
+++ b/chrome/browser/chromeos/login/screens/demo_setup_screen.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "chrome/browser/chromeos/login/screens/demo_setup_screen_view.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 
 namespace {
@@ -51,9 +50,7 @@
   } else if (action_id == kUserActionClose) {
     exit_callback_.Run(Result::CANCELED);
   } else if (action_id == kUserActionPowerwash) {
-    chromeos::DBusThreadManager::Get()
-        ->GetSessionManagerClient()
-        ->StartDeviceWipe();
+    SessionManagerClient::Get()->StartDeviceWipe();
   } else {
     BaseScreen::OnUserAction(action_id);
   }
diff --git a/chrome/browser/chromeos/login/screens/error_screen.cc b/chrome/browser/chromeos/login/screens/error_screen.cc
index 1385dd80..54973a7d 100644
--- a/chrome/browser/chromeos/login/screens/error_screen.cc
+++ b/chrome/browser/chromeos/login/screens/error_screen.cc
@@ -32,7 +32,6 @@
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/grit/browser_resources.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/network/network_connection_handler.h"
@@ -310,9 +309,7 @@
 }
 
 void ErrorScreen::OnLocalStateErrorPowerwashButtonClicked() {
-  chromeos::DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->StartDeviceWipe();
+  SessionManagerClient::Get()->StartDeviceWipe();
 }
 
 void ErrorScreen::OnRebootButtonClicked() {
diff --git a/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
index 4340078..aaeeddd 100644
--- a/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
@@ -21,9 +21,6 @@
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -57,8 +54,6 @@
 
   void SetUpInProcessBrowserTestFixture() override {
     InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::make_unique<FakeSessionManagerClient>());
   }
 
   void SetUpOnMainThread() override {
diff --git a/chrome/browser/chromeos/login/screens/reset_screen.cc b/chrome/browser/chromeos/login/screens/reset_screen.cc
index 73d4efbe..2cc87d8 100644
--- a/chrome/browser/chromeos/login/screens/reset_screen.cc
+++ b/chrome/browser/chromeos/login/screens/reset_screen.cc
@@ -72,8 +72,7 @@
     return;
   }
 
-  DBusThreadManager::Get()->GetSessionManagerClient()->StartTPMFirmwareUpdate(
-      mode_string);
+  SessionManagerClient::Get()->StartTPMFirmwareUpdate(mode_string);
 }
 
 }  // namespace
@@ -266,7 +265,7 @@
         base::TimeDelta::FromSeconds(10));
   } else {
     VLOG(1) << "Starting Powerwash";
-    DBusThreadManager::Get()->GetSessionManagerClient()->StartDeviceWipe();
+    SessionManagerClient::Get()->StartDeviceWipe();
   }
 }
 
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager.cc b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
index 67fc6076..f306d370 100644
--- a/chrome/browser/chromeos/login/session/chrome_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
@@ -41,7 +41,6 @@
 #include "chrome/common/pref_names.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/account_id/account_id.h"
 #include "components/prefs/pref_service.h"
@@ -82,7 +81,7 @@
 
   // Login screen is skipped but 'login-prompt-visible' signal is still needed.
   VLOG(1) << "Kiosk app auto launch >> login-prompt-visible";
-  DBusThreadManager::Get()->GetSessionManagerClient()->EmitLoginPromptVisible();
+  SessionManagerClient::Get()->EmitLoginPromptVisible();
 }
 
 // Starts the login/oobe screen.
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc
index bae0d45..ca003a2a 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -568,7 +568,7 @@
   const base::CommandLine user_flags(base::CommandLine::NO_PROGRAM);
   if (!about_flags::AreSwitchesIdenticalToCurrentCommandLine(
           user_flags, *base::CommandLine::ForCurrentProcess(), NULL)) {
-    DBusThreadManager::Get()->GetSessionManagerClient()->SetFlagsForUser(
+    SessionManagerClient::Get()->SetFlagsForUser(
         cryptohome::CreateAccountIdentifierFromAccountId(
             user_manager::GuestAccountId()),
         base::CommandLine::StringVector());
@@ -686,9 +686,8 @@
 
 void UserSessionManager::RestoreActiveSessions() {
   user_sessions_restore_in_progress_ = true;
-  DBusThreadManager::Get()->GetSessionManagerClient()->RetrieveActiveSessions(
-      base::BindOnce(&UserSessionManager::OnRestoreActiveSessions,
-                     AsWeakPtr()));
+  SessionManagerClient::Get()->RetrieveActiveSessions(base::BindOnce(
+      &UserSessionManager::OnRestoreActiveSessions, AsWeakPtr()));
 }
 
 bool UserSessionManager::UserSessionsRestored() const {
@@ -890,9 +889,7 @@
 bool UserSessionManager::RestartToApplyPerSessionFlagsIfNeed(
     Profile* profile,
     bool early_restart) {
-  SessionManagerClient* session_manager_client =
-      DBusThreadManager::Get()->GetSessionManagerClient();
-  if (!session_manager_client->SupportsRestartToApplyUserFlags())
+  if (!SessionManagerClient::Get()->SupportsRestartToApplyUserFlags())
     return false;
 
   if (ProfileHelper::IsSigninProfile(profile) ||
@@ -1128,7 +1125,7 @@
 void UserSessionManager::StartCrosSession() {
   BootTimesRecorder* btl = BootTimesRecorder::Get();
   btl->AddLoginTimeMarker("StartSession-Start", false);
-  DBusThreadManager::Get()->GetSessionManagerClient()->StartSession(
+  SessionManagerClient::Get()->StartSession(
       cryptohome::CreateAccountIdentifierFromAccountId(
           user_context_.GetAccountId()));
   btl->AddLoginTimeMarker("StartSession-End", false);
@@ -1137,7 +1134,7 @@
 void UserSessionManager::OnUserNetworkPolicyParsed(bool send_password) {
   if (send_password) {
     if (user_context_.GetPasswordKey()->GetSecret().size() > 0) {
-      DBusThreadManager::Get()->GetSessionManagerClient()->SaveLoginPassword(
+      SessionManagerClient::Get()->SaveLoginPassword(
           user_context_.GetPasswordKey()->GetSecret());
     } else {
       LOG(WARNING) << "Not saving password because password is empty.";
@@ -1886,7 +1883,7 @@
     LOG(ERROR) << "Could not get list of active user sessions after crash.";
     // If we could not get list of active user sessions it is safer to just
     // sign out so that we don't get in the inconsistent state.
-    DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
+    SessionManagerClient::Get()->StopSession();
     return;
   }
 
@@ -2313,9 +2310,7 @@
                         pair.second.end());
   }
 
-  SessionManagerClient* session_manager_client =
-      DBusThreadManager::Get()->GetSessionManagerClient();
-  session_manager_client->SetFlagsForUser(
+  SessionManagerClient::Get()->SetFlagsForUser(
       cryptohome::CreateAccountIdentifierFromAccountId(account_id),
       all_switches);
 }
diff --git a/chrome/browser/chromeos/login/test/js_checker.cc b/chrome/browser/chromeos/login/test/js_checker.cc
index 8382afa..67cd9ed0 100644
--- a/chrome/browser/chromeos/login/test/js_checker.cc
+++ b/chrome/browser/chromeos/login/test/js_checker.cc
@@ -20,11 +20,6 @@
   return "window.domAutomationController.send(" + expression + ")";
 }
 
-bool CheckConditionIfOobeExists(const std::string& js_condition) {
-  return !chromeos::LoginDisplayHost::default_host() ||
-         chromeos::test::OobeJS().GetBool(js_condition);
-}
-
 bool CheckOobeCondition(content::WebContents* web_contents,
                         const std::string& js_condition) {
   return chromeos::test::JSChecker(web_contents).GetBool(js_condition);
@@ -177,13 +172,6 @@
       web_contents_, WrapSend(expression), result));
 }
 
-std::unique_ptr<TestConditionWaiter> CreatePredicateOrOobeDestroyedWaiter(
-    const std::string& js_condition) {
-  TestPredicateWaiter::PredicateCheck predicate =
-      base::BindRepeating(&CheckConditionIfOobeExists, js_condition);
-  return std::make_unique<TestPredicateWaiter>(predicate);
-}
-
 void JSChecker::ExpectVisiblePath(
     std::initializer_list<base::StringPiece> element_ids) {
   ExpectFalse(GetOobeElementPath(element_ids) + ".hidden");
diff --git a/chrome/browser/chromeos/login/test/js_checker.h b/chrome/browser/chromeos/login/test/js_checker.h
index 0db84970..1ff33c23 100644
--- a/chrome/browser/chromeos/login/test/js_checker.h
+++ b/chrome/browser/chromeos/login/test/js_checker.h
@@ -154,11 +154,6 @@
 std::string GetOobeElementPath(
     std::initializer_list<base::StringPiece> element_ids);
 
-// Helper method to create waiter over js condition that would also be satisfied
-// if oobe UI is destroyed.
-std::unique_ptr<TestConditionWaiter> CreatePredicateOrOobeDestroyedWaiter(
-    const std::string& js_expression);
-
 // Creates a waiter that allows to wait until screen with |oobe_screen_id| is
 // shown in webui.
 std::unique_ptr<TestConditionWaiter> CreateOobeScreenWaiter(
diff --git a/chrome/browser/chromeos/login/test/network_portal_detector_mixin.cc b/chrome/browser/chromeos/login/test/network_portal_detector_mixin.cc
index 7245fde3..035365a 100644
--- a/chrome/browser/chromeos/login/test/network_portal_detector_mixin.cc
+++ b/chrome/browser/chromeos/login/test/network_portal_detector_mixin.cc
@@ -6,7 +6,7 @@
 
 #include "base/run_loop.h"
 #include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h"
-#include "chromeos/dbus/fake_shill_manager_client.h"
+#include "chromeos/dbus/shill/fake_shill_manager_client.h"
 
 namespace chromeos {
 
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc
index ca57face..29e90ab8 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.cc
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -26,7 +26,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/fake_shill_manager_client.h"
+#include "chromeos/dbus/shill/fake_shill_manager_client.h"
 #include "components/policy/core/common/policy_switches.h"
 #include "components/user_manager/fake_user_manager.h"
 #include "content/public/browser/notification_observer.h"
diff --git a/chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.cc b/chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.cc
new file mode 100644
index 0000000..94613331
--- /dev/null
+++ b/chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.cc
@@ -0,0 +1,67 @@
+// Copyright 2019 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/chromeos/login/test/oobe_screen_exit_waiter.h"
+
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "chrome/browser/chromeos/login/ui/login_display_host.h"
+
+namespace chromeos {
+
+OobeScreenExitWaiter::OobeScreenExitWaiter(OobeScreen target_screen)
+    : target_screen_(target_screen) {}
+
+OobeScreenExitWaiter::~OobeScreenExitWaiter() = default;
+
+void OobeScreenExitWaiter::Wait() {
+  DCHECK_EQ(State::IDLE, state_);
+
+  if (GetOobeUI()->current_screen() == target_screen_) {
+    state_ = State::DONE;
+    return;
+  }
+  DCHECK(!run_loop_);
+
+  oobe_ui_observer_.Add(GetOobeUI());
+
+  state_ = State::WAITING_FOR_SCREEN_EXIT;
+
+  run_loop_ = std::make_unique<base::RunLoop>();
+  run_loop_->Run();
+  run_loop_.reset();
+
+  DCHECK_EQ(State::DONE, state_);
+
+  oobe_ui_observer_.RemoveAll();
+}
+
+void OobeScreenExitWaiter::OnCurrentScreenChanged(OobeScreen current_screen,
+                                                  OobeScreen new_screen) {
+  DCHECK_NE(state_, State::IDLE);
+
+  if (new_screen != target_screen_)
+    EndWait();
+}
+
+void OobeScreenExitWaiter::OnDestroyingOobeUI() {
+  oobe_ui_observer_.RemoveAll();
+  EndWait();
+}
+
+OobeUI* OobeScreenExitWaiter::GetOobeUI() {
+  OobeUI* oobe_ui = LoginDisplayHost::default_host()->GetOobeUI();
+  CHECK(oobe_ui);
+  return oobe_ui;
+}
+
+void OobeScreenExitWaiter::EndWait() {
+  if (state_ == State::DONE)
+    return;
+
+  state_ = State::DONE;
+  run_loop_->Quit();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.h b/chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.h
new file mode 100644
index 0000000..5df7c7bf
--- /dev/null
+++ b/chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.h
@@ -0,0 +1,57 @@
+// Copyright 2019 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_CHROMEOS_LOGIN_TEST_OOBE_SCREEN_EXIT_WAITER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_OOBE_SCREEN_EXIT_WAITER_H_
+
+#include "base/macros.h"
+#include "base/scoped_observer.h"
+#include "chrome/browser/chromeos/login/oobe_screen.h"
+#include "chrome/browser/chromeos/login/test/test_condition_waiter.h"
+#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
+
+namespace base {
+class RunLoop;
+}
+
+namespace chromeos {
+
+class OobeUI;
+
+// A waiter that blocks until the the current OOBE screen is different than the
+// target screen, or the OOBE UI is destroyed.
+class OobeScreenExitWaiter : public OobeUI::Observer,
+                             public test::TestConditionWaiter {
+ public:
+  explicit OobeScreenExitWaiter(OobeScreen target_screen);
+  ~OobeScreenExitWaiter() override;
+
+  // OobeUI::Observer implementation:
+  void OnCurrentScreenChanged(OobeScreen current_screen,
+                              OobeScreen new_screen) override;
+  void OnDestroyingOobeUI() override;
+
+  // TestConditionWaiter;
+  void Wait() override;
+
+ private:
+  enum class State { IDLE, WAITING_FOR_SCREEN_EXIT, DONE };
+
+  OobeUI* GetOobeUI();
+  void EndWait();
+
+  const OobeScreen target_screen_;
+
+  State state_ = State::IDLE;
+
+  ScopedObserver<OobeUI, OobeScreenExitWaiter> oobe_ui_observer_{this};
+
+  std::unique_ptr<base::RunLoop> run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(OobeScreenExitWaiter);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_TEST_OOBE_SCREEN_EXIT_WAITER_H_
diff --git a/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc b/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc
index 5d6aefb..72ab872 100644
--- a/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc
+++ b/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc
@@ -66,7 +66,13 @@
     EndWait();
 }
 
-void OobeScreenWaiter::OnScreenInitialized(OobeScreen screen) {}
+void OobeScreenWaiter::OnDestroyingOobeUI() {
+  oobe_ui_observer_.RemoveAll();
+
+  EXPECT_EQ(State::DONE, state_);
+
+  EndWait();
+}
 
 OobeUI* OobeScreenWaiter::GetOobeUI() {
   OobeUI* oobe_ui = LoginDisplayHost::default_host()->GetOobeUI();
diff --git a/chrome/browser/chromeos/login/test/oobe_screen_waiter.h b/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
index 8d79a4d..80c52fe0 100644
--- a/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
+++ b/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
@@ -32,7 +32,7 @@
   // OobeUI::Observer implementation:
   void OnCurrentScreenChanged(OobeScreen current_screen,
                               OobeScreen new_screen) override;
-  void OnScreenInitialized(OobeScreen screen) override;
+  void OnDestroyingOobeUI() override;
 
   // TestConditionWaiter;
   void Wait() override;
diff --git a/chrome/browser/chromeos/login/ui/captive_portal_window_browsertest.cc b/chrome/browser/chromeos/login/ui/captive_portal_window_browsertest.cc
index f9461c7..8c7a5b5 100644
--- a/chrome/browser/chromeos/login/ui/captive_portal_window_browsertest.cc
+++ b/chrome/browser/chromeos/login/ui/captive_portal_window_browsertest.cc
@@ -23,7 +23,7 @@
 #include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/fake_shill_manager_client.h"
+#include "chromeos/dbus/shill/fake_shill_manager_client.h"
 #include "chromeos/network/portal_detector/network_portal_detector.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
index 4517c81d..d3fa96b 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_webui.cc
@@ -65,7 +65,6 @@
 #include "chromeos/audio/chromeos_sounds.h"
 #include "chromeos/constants/chromeos_constants.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/settings/cros_settings_names.h"
@@ -400,7 +399,7 @@
     : initialize_webui_hidden_(ShouldInitializeWebUIHidden()),
       oobe_startup_sound_played_(StartupUtils::IsOobeCompleted()),
       weak_factory_(this) {
-  DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
+  SessionManagerClient::Get()->AddObserver(this);
   CrasAudioHandler::Get()->AddAudioObserver(this);
 
   display::Screen::GetScreen()->AddObserver(this);
@@ -441,7 +440,7 @@
 }
 
 LoginDisplayHostWebUI::~LoginDisplayHostWebUI() {
-  DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
+  SessionManagerClient::Get()->RemoveObserver(this);
   CrasAudioHandler::Get()->RemoveAudioObserver(this);
   display::Screen::GetScreen()->RemoveObserver(this);
 
diff --git a/chrome/browser/chromeos/login/ui/login_display_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_mojo.cc
index ae5753a0..501fe8d 100644
--- a/chrome/browser/chromeos/login/ui/login_display_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_mojo.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/ui/ash/login_screen_client.h"
 #include "chrome/grit/generated_resources.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/user_manager/known_user.h"
@@ -63,9 +62,7 @@
       // does not regress. Autotests may also depend on it (ie,
       // login_SameSessionTwice).
       VLOG(1) << "Emitting login-prompt-visible";
-      chromeos::DBusThreadManager::Get()
-          ->GetSessionManagerClient()
-          ->EmitLoginPromptVisible();
+      SessionManagerClient::Get()->EmitLoginPromptVisible();
 
       content::NotificationService::current()->Notify(
           chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.cc b/chrome/browser/chromeos/login/ui/webui_login_view.cc
index 33a4bd3..eda151e 100644
--- a/chrome/browser/chromeos/login/ui/webui_login_view.cc
+++ b/chrome/browser/chromeos/login/ui/webui_login_view.cc
@@ -33,7 +33,6 @@
 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
 #include "chrome/browser/ui/webui/chromeos/internet_detail_dialog.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
@@ -508,9 +507,7 @@
   TRACE_EVENT0("chromeos", "WebUILoginView::OnLoginPromptVisible");
   if (should_emit_login_prompt_visible_) {
     VLOG(1) << "Login WebUI >> login-prompt-visible";
-    chromeos::DBusThreadManager::Get()
-        ->GetSessionManagerClient()
-        ->EmitLoginPromptVisible();
+    SessionManagerClient::Get()->EmitLoginPromptVisible();
   }
 
   webui_visible_ = true;
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc b/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc
index 7bf9a3a..15a748e 100644
--- a/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc
+++ b/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc
@@ -50,7 +50,6 @@
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/tpm/stub_install_attributes.h"
@@ -612,8 +611,7 @@
                                    public policy::CloudPolicyStore::Observer {
  protected:
   UserImageManagerPolicyTest()
-      : owner_key_util_(new ownership::MockOwnerKeyUtil()),
-        fake_session_manager_client_(new chromeos::FakeSessionManagerClient) {}
+      : owner_key_util_(new ownership::MockOwnerKeyUtil()) {}
 
   // UserImageManagerTest overrides:
   void SetUpInProcessBrowserTestFixture() override {
@@ -622,9 +620,10 @@
         ->SetOwnerKeyUtilForTesting(owner_key_util_);
     owner_key_util_->SetPublicKeyFromPrivateKey(
         *device_policy_.GetSigningKey());
-    fake_session_manager_client_->set_device_policy(device_policy_.GetBlob());
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(fake_session_manager_client_));
+    // Override FakeSessionManagerClient. This will be shut down by the browser.
+    SessionManagerClient::InitializeFakeInMemory();
+    FakeSessionManagerClient::Get()->set_device_policy(
+        device_policy_.GetBlob());
 
     UserImageManagerTest::SetUpInProcessBrowserTestFixture();
   }
@@ -690,7 +689,6 @@
   policy::UserPolicyBuilder user_policy_;
   policy::DevicePolicyBuilder device_policy_;
   scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_;
-  FakeSessionManagerClient* fake_session_manager_client_;
 
   std::unique_ptr<gfx::ImageSkia> policy_image_;
 
@@ -723,8 +721,8 @@
   user_policy_.payload().mutable_useravatarimage()->set_value(
       ConstructPolicy(test::kUserAvatarImage2RelativePath));
   user_policy_.Build();
-  fake_session_manager_client_->set_user_policy(cryptohome_id_,
-                                                user_policy_.GetBlob());
+  FakeSessionManagerClient::Get()->set_user_policy(cryptohome_id_,
+                                                   user_policy_.GetBlob());
   run_loop_.reset(new base::RunLoop);
   store->Load();
   run_loop_->Run();
@@ -748,8 +746,8 @@
   // image.
   user_policy_.payload().Clear();
   user_policy_.Build();
-  fake_session_manager_client_->set_user_policy(cryptohome_id_,
-                                                user_policy_.GetBlob());
+  FakeSessionManagerClient::Get()->set_user_policy(cryptohome_id_,
+                                                   user_policy_.GetBlob());
   run_loop_.reset(new base::RunLoop);
   store->AddObserver(this);
   store->Load();
@@ -830,8 +828,8 @@
   user_policy_.payload().mutable_useravatarimage()->set_value(
       ConstructPolicy(test::kUserAvatarImage2RelativePath));
   user_policy_.Build();
-  fake_session_manager_client_->set_user_policy(cryptohome_id_,
-                                                user_policy_.GetBlob());
+  FakeSessionManagerClient::Get()->set_user_policy(cryptohome_id_,
+                                                   user_policy_.GetBlob());
   run_loop_.reset(new base::RunLoop);
   store->Load();
   run_loop_->Run();
@@ -877,8 +875,8 @@
   user_policy_.payload().mutable_useravatarimage()->set_value(
       ConstructPolicy(test::kUserAvatarImage2RelativePath));
   user_policy_.Build();
-  fake_session_manager_client_->set_user_policy(cryptohome_id_,
-                                                user_policy_.GetBlob());
+  FakeSessionManagerClient::Get()->set_user_policy(cryptohome_id_,
+                                                   user_policy_.GetBlob());
   run_loop_.reset(new base::RunLoop);
   store->Load();
   run_loop_->Run();
diff --git a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
index fb267e7..86f3f889 100644
--- a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
+++ b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
@@ -136,8 +136,7 @@
  protected:
   WallpaperPolicyTest()
       : LoginManagerTest(true, true),
-        owner_key_util_(new ownership::MockOwnerKeyUtil()),
-        fake_session_manager_client_(new FakeSessionManagerClient) {
+        owner_key_util_(new ownership::MockOwnerKeyUtil()) {
     testUsers_.push_back(
         AccountId::FromUserEmailGaiaId(FakeGaiaMixin::kEnterpriseUser1,
                                        FakeGaiaMixin::kEnterpriseUser1GaiaId));
@@ -177,9 +176,9 @@
         ->SetOwnerKeyUtilForTesting(owner_key_util_);
     owner_key_util_->SetPublicKeyFromPrivateKey(
         *device_policy_.GetSigningKey());
-    fake_session_manager_client_->set_device_policy(device_policy_.GetBlob());
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(fake_session_manager_client_));
+    SessionManagerClient::InitializeFakeInMemory();
+    FakeSessionManagerClient::Get()->set_device_policy(
+        device_policy_.GetBlob());
 
     LoginManagerTest::SetUpInProcessBrowserTestFixture();
     ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_));
@@ -187,7 +186,7 @@
     // Set some fake state keys to make sure they are not empty.
     std::vector<std::string> state_keys;
     state_keys.push_back("1");
-    fake_session_manager_client_->set_server_backed_state_keys(state_keys);
+    FakeSessionManagerClient::Get()->set_server_backed_state_keys(state_keys);
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -295,7 +294,7 @@
       builder->payload().Clear();
     }
     builder->Build();
-    fake_session_manager_client_->set_user_policy(
+    FakeSessionManagerClient::Get()->set_user_policy(
         cryptohome::CreateAccountIdentifierFromAccountId(account_id),
         builder->GetBlob());
     const user_manager::User* user =
@@ -320,8 +319,10 @@
       device_policy_.payload().Clear();
     }
     device_policy_.Build();
-    fake_session_manager_client_->set_device_policy(device_policy_.GetBlob());
-    fake_session_manager_client_->OnPropertyChangeComplete(true /* success */);
+    FakeSessionManagerClient::Get()->set_device_policy(
+        device_policy_.GetBlob());
+    FakeSessionManagerClient::Get()->OnPropertyChangeComplete(
+        true /* success */);
   }
 
   ScopedStubInstallAttributes test_install_attributes_{
@@ -333,7 +334,6 @@
   std::unique_ptr<policy::UserPolicyBuilder> user_policy_builders_[2];
   policy::DevicePolicyBuilder device_policy_;
   scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_;
-  FakeSessionManagerClient* fake_session_manager_client_;
   std::vector<AccountId> testUsers_;
   FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
 
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc
index 6fbb4c4..b74a0a1 100644
--- a/chrome/browser/chromeos/login/webview_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -34,7 +34,6 @@
 #include "chrome/browser/ui/login/login_handler.h"
 #include "chrome/browser/ui/webui/signin/signin_utils.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/guest_view/browser/guest_view_manager.h"
@@ -449,11 +448,11 @@
 
     device_policy_test_helper_.device_policy()->Build();
 
-    fake_session_manager_client_->set_device_policy(
+    FakeSessionManagerClient::Get()->set_device_policy(
         device_policy_test_helper_.device_policy()->GetBlob());
     PrefChangeWatcher watcher(prefs::kManagedAutoSelectCertificateForUrls,
                               ProfileHelper::GetSigninProfile()->GetPrefs());
-    fake_session_manager_client_->OnPropertyChangeComplete(true);
+    FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
 
     watcher.Wait();
   }
@@ -478,11 +477,11 @@
 
     device_policy_test_helper_.device_policy()->Build();
 
-    fake_session_manager_client_->set_device_policy(
+    FakeSessionManagerClient::Get()->set_device_policy(
         device_policy_test_helper_.device_policy()->GetBlob());
     PrefChangeWatcher watcher(onc::prefs::kDeviceOpenNetworkConfiguration,
                               g_browser_process->local_state());
-    fake_session_manager_client_->OnPropertyChangeComplete(true);
+    FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
     watcher.Wait();
   }
 
@@ -542,15 +541,12 @@
   }
 
   void SetUpInProcessBrowserTestFixture() override {
-    auto fake_session_manager_client =
-        std::make_unique<FakeSessionManagerClient>();
-    fake_session_manager_client_ = fake_session_manager_client.get();
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::move(fake_session_manager_client));
     device_policy_test_helper_.InstallOwnerKey();
     device_policy_test_helper_.MarkAsEnterpriseOwned();
 
-    fake_session_manager_client_->set_device_policy(
+    // Override FakeSessionManagerClient. This will be shut down by the browser.
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    FakeSessionManagerClient::Get()->set_device_policy(
         device_policy_test_helper_.device_policy()->GetBlob());
 
     WebviewLoginTest::SetUpInProcessBrowserTestFixture();
@@ -605,8 +601,6 @@
   }
 
   policy::DevicePolicyCrosTestHelper device_policy_test_helper_;
-  // Unowned pointer - owned by DBusThreadManager.
-  FakeSessionManagerClient* fake_session_manager_client_;
   std::unique_ptr<crypto::ScopedTestSystemNSSKeySlot> test_system_slot_;
   scoped_refptr<net::X509Certificate> client_cert_;
   std::unique_ptr<net::SpawnedTestServer> https_server_;
@@ -827,7 +821,7 @@
     ASSERT_TRUE(auth_proxy_server_->Start());
 
     // Prepare device policy which will be used for two purposes:
-    // - given to |fake_session_manager_client_|, so the device appears to have
+    // - given to FakeSessionManagerClient, so the device appears to have
     //   registered for policy.
     // - the payload is given to |policy_test_server_|, so we can download fresh
     //   policy.
@@ -850,23 +844,16 @@
   void SetUpInProcessBrowserTestFixture() override {
     WebviewLoginTest::SetUpInProcessBrowserTestFixture();
 
-    // Use a fake SessionManagerClient to be able to pretend that the device has
-    // been enrolled and registered for policy (and has a device DMToken).
-    auto fake_session_manager_client =
-        std::make_unique<FakeSessionManagerClient>();
-    fake_session_manager_client_ = fake_session_manager_client.get();
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::move(fake_session_manager_client));
     device_policy_test_helper_.InstallOwnerKey();
     device_policy_test_helper_.MarkAsEnterpriseOwned();
 
-    fake_session_manager_client_->set_device_policy(
+    FakeSessionManagerClient::Get()->set_device_policy(
         device_policy_builder()->GetBlob());
 
     // Set some fake state keys to make sure they are not empty.
     std::vector<std::string> state_keys;
     state_keys.push_back("1");
-    fake_session_manager_client_->set_server_backed_state_keys(state_keys);
+    FakeSessionManagerClient::Get()->set_server_backed_state_keys(state_keys);
   }
 
   void SetUpOnMainThread() override {
@@ -939,11 +926,6 @@
   LocalPolicyTestServerMixin local_policy_mixin_{&mixin_host_};
   policy::DevicePolicyCrosTestHelper device_policy_test_helper_;
 
-  // FakeDBusThreadManager uses FakeSessionManagerClient.
-  std::unique_ptr<chromeos::DBusThreadManagerSetter> dbus_setter_;
-  // Unowned pointer - owned by DBusThreadManager.
-  chromeos::FakeSessionManagerClient* fake_session_manager_client_;
-
   DISALLOW_COPY_AND_ASSIGN(WebviewProxyAuthLoginTest);
 };
 
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index fe90e16..19c349e 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -985,7 +985,7 @@
       break;
     case TermsOfServiceScreen::Result::DECLINED:
       // End the session and return to the login screen.
-      DBusThreadManager::Get()->GetSessionManagerClient()->StopSession();
+      SessionManagerClient::Get()->StopSession();
       break;
   }
 }
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index 0e53e34..1621c93 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -71,8 +71,8 @@
 #include "chromeos/dbus/constants/dbus_switches.h"
 #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_shill_manager_client.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/dbus/shill/fake_shill_manager_client.h"
 #include "chromeos/dbus/system_clock/system_clock_client.h"
 #include "chromeos/geolocation/simple_geolocation_provider.h"
 #include "chromeos/network/network_state.h"
@@ -1115,7 +1115,7 @@
 
 class WizardControllerDeviceStateTest : public WizardControllerFlowTest {
  protected:
-  WizardControllerDeviceStateTest() : fake_session_manager_client_(nullptr) {
+  WizardControllerDeviceStateTest() {
     fake_statistics_provider_.SetMachineStatistic(
         system::kSerialNumberKeyForTest, "test");
     fake_statistics_provider_.SetMachineStatistic(system::kActivateDateKey,
@@ -1141,10 +1141,11 @@
   void SetUpInProcessBrowserTestFixture() override {
     WizardControllerFlowTest::SetUpInProcessBrowserTestFixture();
 
-    fake_session_manager_client_ = new FakeSessionManagerClient(
-        FakeSessionManagerClient::PolicyStorageType::kOnDisk);
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(fake_session_manager_client_));
+    // We need to initialize some dbus clients here, otherwise this test will
+    // timeout in WaitForAutoEnrollmentState on asan builds. TODO(stevenjb):
+    // Determine which client(s) need to be created and extract and initialize
+    // them. https://crbug.com/949063.
+    DBusThreadManager::GetSetterForTesting();
   }
 
   void SetUpOnMainThread() override {
@@ -1179,9 +1180,6 @@
 
   base::HistogramTester* histogram_tester() { return histogram_tester_.get(); }
 
- protected:
-  FakeSessionManagerClient* fake_session_manager_client_;
-
  private:
   ScopedStubInstallAttributes test_install_attributes_{
       StubInstallAttributes::CreateUnset()};
@@ -1230,7 +1228,7 @@
   EXPECT_EQ(1,
             FakeCryptohomeClient::Get()
                 ->remove_firmware_management_parameters_from_tpm_call_count());
-  EXPECT_EQ(1, fake_session_manager_client_
+  EXPECT_EQ(1, FakeSessionManagerClient::Get()
                    ->clear_forced_re_enrollment_vpd_call_count());
 }
 
@@ -1299,7 +1297,7 @@
   EXPECT_EQ(0,
             FakeCryptohomeClient::Get()
                 ->remove_firmware_management_parameters_from_tpm_call_count());
-  EXPECT_EQ(0, fake_session_manager_client_
+  EXPECT_EQ(0, FakeSessionManagerClient::Get()
                    ->clear_forced_re_enrollment_vpd_call_count());
 
   EXPECT_FALSE(StartupUtils::IsOobeCompleted());
@@ -1391,7 +1389,7 @@
     EXPECT_EQ(
         0, FakeCryptohomeClient::Get()
                ->remove_firmware_management_parameters_from_tpm_call_count());
-    EXPECT_EQ(0, fake_session_manager_client_
+    EXPECT_EQ(0, FakeSessionManagerClient::Get()
                      ->clear_forced_re_enrollment_vpd_call_count());
   } else {
     // Check that guest sign-in is allowed if FRE was not explicitly required.
@@ -1399,7 +1397,7 @@
     EXPECT_EQ(
         1, FakeCryptohomeClient::Get()
                ->remove_firmware_management_parameters_from_tpm_call_count());
-    EXPECT_EQ(1, fake_session_manager_client_
+    EXPECT_EQ(1, FakeSessionManagerClient::Get()
                      ->clear_forced_re_enrollment_vpd_call_count());
   }
 
@@ -1523,7 +1521,7 @@
     EXPECT_EQ(
         0, FakeCryptohomeClient::Get()
                ->remove_firmware_management_parameters_from_tpm_call_count());
-    EXPECT_EQ(0, fake_session_manager_client_
+    EXPECT_EQ(0, FakeSessionManagerClient::Get()
                      ->clear_forced_re_enrollment_vpd_call_count());
   } else {
     // Don't expect that the auto enrollment screen will be hidden, because
@@ -1544,7 +1542,7 @@
     EXPECT_EQ(
         0, FakeCryptohomeClient::Get()
                ->remove_firmware_management_parameters_from_tpm_call_count());
-    EXPECT_EQ(0, fake_session_manager_client_
+    EXPECT_EQ(0, FakeSessionManagerClient::Get()
                      ->clear_forced_re_enrollment_vpd_call_count());
   }
 }
@@ -2033,18 +2031,8 @@
 
 class WizardControllerBrokenLocalStateTest : public WizardControllerTest {
  protected:
-  WizardControllerBrokenLocalStateTest()
-      : fake_session_manager_client_(nullptr) {}
-
-  ~WizardControllerBrokenLocalStateTest() override {}
-
-  void SetUpInProcessBrowserTestFixture() override {
-    WizardControllerTest::SetUpInProcessBrowserTestFixture();
-
-    fake_session_manager_client_ = new FakeSessionManagerClient;
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(fake_session_manager_client_));
-  }
+  WizardControllerBrokenLocalStateTest() = default;
+  ~WizardControllerBrokenLocalStateTest() override = default;
 
   void SetUpOnMainThread() override {
     PrefServiceFactory factory;
@@ -2058,13 +2046,8 @@
     WizardController::default_controller()->is_official_build_ = true;
   }
 
-  FakeSessionManagerClient* fake_session_manager_client() const {
-    return fake_session_manager_client_;
-  }
-
  private:
   std::unique_ptr<PrefService> local_state_;
-  FakeSessionManagerClient* fake_session_manager_client_;
 
   DISALLOW_COPY_AND_ASSIGN(WizardControllerBrokenLocalStateTest);
 };
@@ -2086,10 +2069,10 @@
       "$('error-message').classList.contains('ui-state-local-state-error')"));
 
   // Emulates user click on the "Restart and Powerwash" button.
-  ASSERT_EQ(0, fake_session_manager_client()->start_device_wipe_call_count());
+  ASSERT_EQ(0, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
   ASSERT_TRUE(content::ExecuteScript(
       GetWebContents(), "$('error-message-md-powerwash-button').click();"));
-  ASSERT_EQ(1, fake_session_manager_client()->start_device_wipe_call_count());
+  ASSERT_EQ(1, FakeSessionManagerClient::Get()->start_device_wipe_call_count());
 }
 
 class WizardControllerProxyAuthOnSigninTest : public WizardControllerTest {
diff --git a/chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.cc b/chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.cc
index 6549b21..e3e7aa3 100644
--- a/chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.cc
+++ b/chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.cc
@@ -83,7 +83,7 @@
 }
 
 bool MultiDeviceSetupClientFactory::ServiceIsNULLWhileTesting() const {
-  return true;
+  return service_is_null_while_testing_;
 }
 
 }  // namespace multidevice_setup
diff --git a/chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h b/chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h
index 6fab603..bc4cfe8 100644
--- a/chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h
+++ b/chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h
@@ -8,6 +8,7 @@
 #include "base/memory/singleton.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
+class ChromeOSMetricsProviderTest;
 class Profile;
 
 namespace chromeos {
@@ -26,14 +27,21 @@
 
  private:
   friend struct base::DefaultSingletonTraits<MultiDeviceSetupClientFactory>;
+  friend class ::ChromeOSMetricsProviderTest;
 
   MultiDeviceSetupClientFactory();
   ~MultiDeviceSetupClientFactory() override;
 
+  void SetServiceIsNULLWhileTestingForTesting(
+      bool service_is_null_while_testing) {
+    service_is_null_while_testing_ = service_is_null_while_testing;
+  }
+
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
   bool ServiceIsNULLWhileTesting() const override;
+  bool service_is_null_while_testing_ = true;
 
   DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupClientFactory);
 };
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
index d12bcdfe..77d1e5152 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
@@ -18,7 +18,7 @@
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc b/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
index 89da0274..a3bbd51 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
@@ -25,7 +25,7 @@
 #include "chrome/common/pref_names.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/portal_detector/network_portal_detector.h"
 #include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
 #include "components/account_id/account_id.h"
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
index af62e01..39d7614 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
@@ -26,8 +26,8 @@
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chrome/browser/chromeos/net/network_throttling_observer_unittest.cc b/chrome/browser/chromeos/net/network_throttling_observer_unittest.cc
index 40f1a3b..d280fb4 100644
--- a/chrome/browser/chromeos/net/network_throttling_observer_unittest.cc
+++ b/chrome/browser/chromeos/net/network_throttling_observer_unittest.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/chromeos/net/network_throttling_observer.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/chrome/browser/chromeos/network_change_manager_client_browsertest.cc b/chrome/browser/chromeos/network_change_manager_client_browsertest.cc
index 9b28770..31648821 100644
--- a/chrome/browser/chromeos/network_change_manager_client_browsertest.cc
+++ b/chrome/browser/chromeos/network_change_manager_client_browsertest.cc
@@ -5,8 +5,8 @@
 #include "base/run_loop.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "content/public/browser/network_service_instance.h"
 #include "net/base/network_change_notifier.h"
 #include "services/network/public/cpp/features.h"
diff --git a/chrome/browser/chromeos/note_taking_helper_unittest.cc b/chrome/browser/chromeos/note_taking_helper_unittest.cc
index e22fc228..4ad4fd2 100644
--- a/chrome/browser/chromeos/note_taking_helper_unittest.cc
+++ b/chrome/browser/chromeos/note_taking_helper_unittest.cc
@@ -29,7 +29,6 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "components/arc/arc_prefs.h"
 #include "components/arc/arc_service_manager.h"
@@ -204,14 +203,8 @@
   ~NoteTakingHelperTest() override = default;
 
   void SetUp() override {
-    // This is needed to avoid log spam due to ArcSessionManager's
-    // RemoveArcData() calls failing.
-    if (DBusThreadManager::IsInitialized())
-      DBusThreadManager::Shutdown();
-    session_manager_client_ = new FakeSessionManagerClient();
-    session_manager_client_->set_arc_available(true);
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(session_manager_client_));
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    chromeos::FakeSessionManagerClient::Get()->set_arc_available(true);
 
     BrowserWithTestWindowTest::SetUp();
     InitExtensionService(profile());
@@ -229,7 +222,7 @@
     }
     extensions::ExtensionSystem::Get(profile())->Shutdown();
     BrowserWithTestWindowTest::TearDown();
-    DBusThreadManager::Shutdown();
+    chromeos::SessionManagerClient::Shutdown();
   }
 
  protected:
@@ -499,7 +492,6 @@
   // Has Init() been called?
   bool initialized_ = false;
 
-  FakeSessionManagerClient* session_manager_client_ = nullptr;  // Not owned.
   ArcAppTest arc_test_;
   std::unique_ptr<arc::ArcIntentHelperBridge> intent_helper_bridge_;
   service_manager::TestConnectorFactory connector_factory_;
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
index b5b0c54..9707ca7 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
@@ -27,7 +27,6 @@
 #include "chrome/browser/chromeos/settings/device_settings_provider.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/tpm/install_attributes.h"
 #include "chromeos/tpm/tpm_token_loader.h"
 #include "components/ownership/owner_key_util.h"
@@ -204,10 +203,8 @@
         tpm_token_status == TPMTokenLoader::TPM_TOKEN_STATUS_UNDETERMINED;
   }
 
-  if (DBusThreadManager::IsInitialized() &&
-      DBusThreadManager::Get()->GetSessionManagerClient()) {
-    DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
-  }
+  if (SessionManagerClient::Get())
+    SessionManagerClient::Get()->AddObserver(this);
 
   if (device_settings_service_)
     device_settings_service_->AddObserver(this);
@@ -233,10 +230,8 @@
   if (device_settings_service_)
     device_settings_service_->RemoveObserver(this);
 
-  if (DBusThreadManager::IsInitialized() &&
-      DBusThreadManager::Get()->GetSessionManagerClient()) {
-    DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
-  }
+  if (SessionManagerClient::Get())
+    SessionManagerClient::Get()->RemoveObserver(this);
 }
 
 OwnerSettingsServiceChromeOS* OwnerSettingsServiceChromeOS::FromWebUI(
diff --git a/chrome/browser/chromeos/policy/affiliation_test_helper.cc b/chrome/browser/chromeos/policy/affiliation_test_helper.cc
index 2299301..8618a59b 100644
--- a/chrome/browser/chromeos/policy/affiliation_test_helper.cc
+++ b/chrome/browser/chromeos/policy/affiliation_test_helper.cc
@@ -100,7 +100,9 @@
     chromeos::FakeAuthPolicyClient* fake_auth_policy_client)
     : management_type_(management_type),
       fake_session_manager_client_(fake_session_manager_client),
-      fake_auth_policy_client_(fake_auth_policy_client) {}
+      fake_auth_policy_client_(fake_auth_policy_client) {
+  DCHECK(fake_session_manager_client);
+}
 
 void AffiliationTestHelper::CheckPreconditions() {
   ASSERT_TRUE(fake_session_manager_client_);
diff --git a/chrome/browser/chromeos/policy/app_install_event_log_collector_unittest.cc b/chrome/browser/chromeos/policy/app_install_event_log_collector_unittest.cc
index b861dd3..018ef021d 100644
--- a/chrome/browser/chromeos/policy/app_install_event_log_collector_unittest.cc
+++ b/chrome/browser/chromeos/policy/app_install_event_log_collector_unittest.cc
@@ -20,7 +20,7 @@
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_handler.h"
 #include "components/arc/common/app.mojom.h"
 #include "components/policy/proto/device_management_backend.pb.h"
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
index b26ce8a..31f17e1 100644
--- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
+++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
@@ -53,6 +53,7 @@
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_handler.h"
@@ -129,7 +130,7 @@
               device_active_directory_policy_manager_));
     } else {
       state_keys_broker_ = std::make_unique<ServerBackedStateKeysBroker>(
-          chromeos::DBusThreadManager::Get()->GetSessionManagerClient());
+          chromeos::SessionManagerClient::Get());
 
       base::FilePath device_policy_external_data_path;
       CHECK(base::PathService::Get(chromeos::DIR_DEVICE_POLICY_EXTERNAL_DATA,
@@ -181,7 +182,7 @@
   if (!chromeos::InstallAttributes::Get()->IsActiveDirectoryManaged()) {
     device_local_account_policy_service_ =
         std::make_unique<DeviceLocalAccountPolicyService>(
-            chromeos::DBusThreadManager::Get()->GetSessionManagerClient(),
+            chromeos::SessionManagerClient::Get(),
             chromeos::DeviceSettingsService::Get(),
             chromeos::CrosSettings::Get(),
             affiliated_invalidation_service_provider_.get(),
diff --git a/chrome/browser/chromeos/policy/component_active_directory_policy_browsertest.cc b/chrome/browser/chromeos/policy/component_active_directory_policy_browsertest.cc
index 918793b..6cac1a9 100644
--- a/chrome/browser/chromeos/policy/component_active_directory_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/component_active_directory_policy_browsertest.cc
@@ -17,7 +17,6 @@
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h"
 #include "chromeos/dbus/cryptohome/tpm_util.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/login_manager/policy_descriptor.pb.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/tpm/stub_install_attributes.h"
@@ -82,11 +81,6 @@
   }
 
   void SetUp() override {
-    // Create a fake session manager client to store test policy.
-    session_manager_client_ = new chromeos::FakeSessionManagerClient();
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        base::WrapUnique(session_manager_client_));
-
     // CryptohomeClient needs to be initialized before
     // tpm_util::LockDeviceActiveDirectoryForTesting.
     chromeos::CryptohomeClient::InitializeFake();
@@ -161,7 +155,7 @@
     builder_.set_payload(policy);
     builder_.Build();
     base::RunLoop run_loop;
-    session_manager_client_->StorePolicy(
+    chromeos::FakeSessionManagerClient::Get()->StorePolicy(
         descriptor, builder_.GetBlob(),
         base::BindOnce(&ExpectSuccess, run_loop.QuitClosure()));
     run_loop.Run();
@@ -180,7 +174,6 @@
   scoped_refptr<const extensions::Extension> extension_;
   std::unique_ptr<ExtensionTestMessageListener> event_listener_;
   chromeos::ScopedStubInstallAttributes install_attributes_;
-  chromeos::SessionManagerClient* session_manager_client_;  // Not owned.
   ComponentActiveDirectoryPolicyBuilder builder_;
 };
 
diff --git a/chrome/browser/chromeos/policy/component_active_directory_policy_retriever.cc b/chrome/browser/chromeos/policy/component_active_directory_policy_retriever.cc
index 87f8b19..4b75a414f 100644
--- a/chrome/browser/chromeos/policy/component_active_directory_policy_retriever.cc
+++ b/chrome/browser/chromeos/policy/component_active_directory_policy_retriever.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/policy_namespace.h"
 
@@ -78,9 +78,7 @@
   descriptor.set_domain(MapPolicyDomain(ns.domain));
   descriptor.set_component_id(ns.component_id);
 
-  chromeos::SessionManagerClient* session_manager =
-      chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
-  session_manager->RetrievePolicy(
+  chromeos::SessionManagerClient::Get()->RetrievePolicy(
       descriptor,
       base::BindOnce(
           &ComponentActiveDirectoryPolicyRetriever::OnPolicyRetrieved,
diff --git a/chrome/browser/chromeos/policy/component_active_directory_policy_retriever_unittest.cc b/chrome/browser/chromeos/policy/component_active_directory_policy_retriever_unittest.cc
index 99bc358..4518f0c 100644
--- a/chrome/browser/chromeos/policy/component_active_directory_policy_retriever_unittest.cc
+++ b/chrome/browser/chromeos/policy/component_active_directory_policy_retriever_unittest.cc
@@ -6,8 +6,6 @@
 
 #include "base/bind.h"
 #include "base/test/scoped_task_environment.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/policy/core/common/cloud/policy_builder.h"
 #include "components/policy/core/common/policy_test_utils.h"
@@ -16,10 +14,6 @@
 
 namespace em = enterprise_management;
 
-namespace chromeos {
-class FakeSessionManagerClient;
-}
-
 namespace {
 constexpr char kExtensionId[] = "abcdefghabcdefghabcdefghabcdefgh";
 constexpr char kFakePolicy[] = "fake_policy";
@@ -36,14 +30,14 @@
 
 class ComponentActiveDirectoryPolicyRetrieverTest : public testing::Test {
  protected:
-  ComponentActiveDirectoryPolicyRetrieverTest() {
-    auto session_manager_client =
-        std::make_unique<chromeos::FakeSessionManagerClient>();
-    session_manager_client_ = session_manager_client.get();
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::move(session_manager_client));
+  ComponentActiveDirectoryPolicyRetrieverTest() = default;
+
+  void SetUp() override {
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
   }
 
+  void TearDown() override { chromeos::SessionManagerClient::Shutdown(); }
+
   RetrieveCallback CreateRetrieveCallback() {
     return base::BindOnce(
         &ComponentActiveDirectoryPolicyRetrieverTest::OnPoliciesRetrieved,
@@ -67,7 +61,6 @@
   std::vector<RetrieveResult> results_;
   bool policy_stored_ = false;
   bool callback_called_ = false;
-  chromeos::FakeSessionManagerClient* session_manager_client_;  // Not owned.
 };
 
 TEST_F(ComponentActiveDirectoryPolicyRetrieverTest, RetrieveNoPolicy) {
@@ -108,8 +101,8 @@
   descriptor.set_account_type(login_manager::ACCOUNT_TYPE_DEVICE);
   descriptor.set_domain(login_manager::POLICY_DOMAIN_EXTENSIONS);
   descriptor.set_component_id(kExtensionId);
-  session_manager_client_->StorePolicy(descriptor, policy_blob,
-                                       CreateStoredCallback());
+  chromeos::SessionManagerClient::Get()->StorePolicy(descriptor, policy_blob,
+                                                     CreateStoredCallback());
   scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(policy_stored_);
 
diff --git a/chrome/browser/chromeos/policy/component_active_directory_policy_service_unittest.cc b/chrome/browser/chromeos/policy/component_active_directory_policy_service_unittest.cc
index 40bc155..274b31e4 100644
--- a/chrome/browser/chromeos/policy/component_active_directory_policy_service_unittest.cc
+++ b/chrome/browser/chromeos/policy/component_active_directory_policy_service_unittest.cc
@@ -6,8 +6,7 @@
 
 #include "base/bind.h"
 #include "base/test/scoped_task_environment.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/policy_builder.h"
 #include "components/policy/core/common/policy_bundle.h"
@@ -117,15 +116,11 @@
                          POLICY_SOURCE_ACTIVE_DIRECTORY,
                          std::make_unique<base::Value>("maybe"), nullptr);
 
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
+
     SetPolicy(kTestPolicy);
     SetSchema(kTestSchema);
 
-    auto session_manager_client =
-        std::make_unique<chromeos::FakeSessionManagerClient>();
-    session_manager_client_ = session_manager_client.get();
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::move(session_manager_client));
-
     service_ = std::make_unique<ComponentActiveDirectoryPolicyService>(
         POLICY_SCOPE_USER, POLICY_DOMAIN_EXTENSIONS,
         login_manager::ACCOUNT_TYPE_USER, kTestUserAccountId, &delegate_,
@@ -133,6 +128,7 @@
   }
 
   ~ComponentActiveDirectoryPolicyServiceTest() override {
+    chromeos::SessionManagerClient::Shutdown();
     // Make sure all StorePolicy() calls succeeded.
     EXPECT_EQ(store_policy_call_count_, store_policy_succeeded_count_);
   }
@@ -168,7 +164,7 @@
     descriptor.set_component_id(component_id);
 
     builder_.Build();
-    session_manager_client_->StorePolicy(
+    chromeos::SessionManagerClient::Get()->StorePolicy(
         descriptor, builder_.GetBlob(),
         base::BindOnce(
             &ComponentActiveDirectoryPolicyServiceTest::OnPolicyStored,
@@ -215,7 +211,6 @@
   }
 
   ComponentActiveDirectoryPolicyBuilder builder_;
-  chromeos::FakeSessionManagerClient* session_manager_client_;  // Not owned.
   std::string curr_schema_;
   int store_policy_call_count_ = 0;
   int store_policy_succeeded_count_ = 0;
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
index 4fdc024..4f82271 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
@@ -126,7 +126,7 @@
       public chromeos::SessionManagerClient::Observer {
  protected:
   DeviceCloudPolicyManagerChromeOSTest()
-      : state_keys_broker_(&fake_session_manager_client_), store_(nullptr) {
+      : state_keys_broker_(&session_manager_client_), store_(nullptr) {
     fake_statistics_provider_.SetMachineStatistic(
         chromeos::system::kSerialNumberKeyForTest, "test_sn");
     fake_statistics_provider_.SetMachineStatistic(
@@ -135,7 +135,7 @@
     state_keys.push_back("1");
     state_keys.push_back("2");
     state_keys.push_back("3");
-    fake_session_manager_client_.set_server_backed_state_keys(state_keys);
+    session_manager_client_.set_server_backed_state_keys(state_keys);
     session_manager_client_.AddObserver(this);
   }
 
@@ -289,7 +289,6 @@
   TestingPrefServiceSimple local_state_;
   MockDeviceManagementService device_management_service_;
   chromeos::system::ScopedFakeStatisticsProvider fake_statistics_provider_;
-  chromeos::FakeSessionManagerClient fake_session_manager_client_;
   bool set_empty_system_salt_ = false;
   ServerBackedStateKeysBroker state_keys_broker_;
   StrictMock<chromeos::attestation::MockAttestationFlow>* mock_;
diff --git a/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc b/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc
index bce34a7..b6c285853 100644
--- a/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc
+++ b/chrome/browser/chromeos/policy/device_policy_cros_browser_test.cc
@@ -18,7 +18,6 @@
 #include "chromeos/constants/chromeos_paths.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "chromeos/dbus/cryptohome/tpm_util.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/tpm/install_attributes.h"
 #include "crypto/rsa_private_key.h"
@@ -102,10 +101,6 @@
 void DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture() {
   InstallOwnerKey();
   MarkOwnership();
-  dbus_setter_ = chromeos::DBusThreadManager::GetSetterForTesting();
-  dbus_setter_->SetSessionManagerClient(
-      std::unique_ptr<chromeos::SessionManagerClient>(
-          fake_session_manager_client_));
   chromeos::MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
 }
 
diff --git a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
index 006f219..f2854eb 100644
--- a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
@@ -50,10 +50,10 @@
 #include "chromeos/dbus/fake_update_engine_client.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_ipconfig_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "chromeos/disks/mock_disk_mount_manager.h"
 #include "chromeos/login/login_state/login_state.h"
diff --git a/chrome/browser/chromeos/policy/display_resolution_handler_browsertest.cc b/chrome/browser/chromeos/policy/display_resolution_handler_browsertest.cc
index 0ca8d4c..78edb513 100644
--- a/chrome/browser/chromeos/policy/display_resolution_handler_browsertest.cc
+++ b/chrome/browser/chromeos/policy/display_resolution_handler_browsertest.cc
@@ -20,9 +20,6 @@
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/cryptohome/cryptohome_client.h"
-#include "chromeos/dbus/cryptohome/fake_cryptohome_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/settings/cros_settings_names.h"
@@ -386,25 +383,21 @@
     : public InProcessBrowserTest,
       public testing::WithParamInterface<PolicyValue> {
  protected:
-  DisplayResolutionBootTest()
-      : fake_session_manager_client_(new chromeos::FakeSessionManagerClient) {}
-  ~DisplayResolutionBootTest() override {}
+  DisplayResolutionBootTest() = default;
+  ~DisplayResolutionBootTest() override = default;
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitch(switches::kUseFirstDisplayAsInternal);
   }
 
   void SetUpInProcessBrowserTestFixture() override {
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<chromeos::SessionManagerClient>(
-            fake_session_manager_client_));
-
+    // Override FakeSessionManagerClient. This will be shut down by the browser.
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
     test_helper_.InstallOwnerKey();
     test_helper_.MarkAsEnterpriseOwned();
     ash::DisplayConfigurationController::DisableAnimatorForTest();
   }
 
-  chromeos::FakeSessionManagerClient* fake_session_manager_client_;
   policy::DevicePolicyCrosTestHelper test_helper_;
 };
 
@@ -422,8 +415,9 @@
           chromeos::kDeviceDisplayResolution, run_loop.QuitClosure());
   device_policy->SetDefaultSigningKey();
   device_policy->Build();
-  fake_session_manager_client_->set_device_policy(device_policy->GetBlob());
-  fake_session_manager_client_->OnPropertyChangeComplete(true);
+  chromeos::FakeSessionManagerClient::Get()->set_device_policy(
+      device_policy->GetBlob());
+  chromeos::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
   run_loop.Run();
   // Allow tasks posted by CrosSettings observers to complete:
   base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc b/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc
index a2c8997..c881aaa5 100644
--- a/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc
+++ b/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc
@@ -22,9 +22,6 @@
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/cryptohome/cryptohome_client.h"
-#include "chromeos/dbus/cryptohome/fake_cryptohome_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/settings/cros_settings_names.h"
@@ -263,21 +260,17 @@
     : public InProcessBrowserTest,
       public testing::WithParamInterface<display::Display::Rotation> {
  protected:
-  DisplayRotationBootTest()
-      : fake_session_manager_client_(new chromeos::FakeSessionManagerClient) {}
-  ~DisplayRotationBootTest() override {}
+  DisplayRotationBootTest() = default;
+  ~DisplayRotationBootTest() override = default;
 
   void SetUpInProcessBrowserTestFixture() override {
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<chromeos::SessionManagerClient>(
-            fake_session_manager_client_));
-
+    // Override FakeSessionManagerClient. This will be shut down by the browser.
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
     test_helper_.InstallOwnerKey();
     test_helper_.MarkAsEnterpriseOwned();
     ash::DisplayConfigurationController::DisableAnimatorForTest();
   }
 
-  chromeos::FakeSessionManagerClient* fake_session_manager_client_;
   policy::DevicePolicyCrosTestHelper test_helper_;
 };
 
@@ -297,8 +290,9 @@
           chromeos::kDisplayRotationDefault, run_loop.QuitClosure());
   device_policy->SetDefaultSigningKey();
   device_policy->Build();
-  fake_session_manager_client_->set_device_policy(device_policy->GetBlob());
-  fake_session_manager_client_->OnPropertyChangeComplete(true);
+  chromeos::FakeSessionManagerClient::Get()->set_device_policy(
+      device_policy->GetBlob());
+  chromeos::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
   run_loop.Run();
   // Allow tasks posted by CrosSettings observers to complete:
   base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc b/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc
index 01f5a1e..00fb327 100644
--- a/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc
+++ b/chrome/browser/chromeos/policy/site_isolation_flag_handling_browsertest.cc
@@ -27,7 +27,6 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "chromeos/tpm/stub_install_attributes.h"
@@ -303,19 +302,11 @@
   void SetUpInProcessBrowserTestFixture() override {
     policy::LoginPolicyTestBase::SetUpInProcessBrowserTestFixture();
 
-    // Set up fake_session_manager_client_ so we can verify the flags for the
-    // user session.
-    auto fake_session_manager_client =
-        std::make_unique<FakeSessionManagerClient>(
-            FakeSessionManagerClient::PolicyStorageType::kOnDisk);
-    fake_session_manager_client_ = fake_session_manager_client.get();
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::move(fake_session_manager_client));
-
     // Mark that chrome restart can be requested.
     // Note that AttemptRestart() is mocked out in UserSessionManager through
     // |SetAttemptRestartClosureInTests| (set up in SetUpOnMainThread).
-    fake_session_manager_client_->set_supports_restart_to_apply_user_flags(
+    SessionManagerClient::InitializeFake();
+    FakeSessionManagerClient::Get()->set_supports_restart_to_apply_user_flags(
         true);
   }
 
@@ -355,10 +346,6 @@
 
   bool HasAttemptRestartBeenCalled() const { return attempt_restart_called_; }
 
-  FakeSessionManagerClient* fake_session_manager_client() {
-    return fake_session_manager_client_;
-  }
-
   // Called when log-in was successful.
   bool UserSessionStarted(const content::NotificationSource& source,
                           const content::NotificationDetails& details) {
@@ -388,8 +375,6 @@
   // Observes for user session start.
   std::unique_ptr<content::WindowedNotificationObserver>
       user_session_started_observer_;
-  // Unowned pointer - owned by DBusThreadManager.
-  FakeSessionManagerClient* fake_session_manager_client_;
   policy::MockConfigurationPolicyProvider provider_;
   chromeos::ScopedTestingCrosSettings scoped_testing_cros_settings_;
   DISALLOW_COPY_AND_ASSIGN(SiteIsolationFlagHandlingTest);
@@ -427,7 +412,7 @@
   AccountId test_account_id =
       AccountId::FromUserEmailGaiaId(GetAccount(), kTestUserGaiaId);
   std::vector<std::string> flags_for_user;
-  bool has_flags_for_user = fake_session_manager_client()->GetFlagsForUser(
+  bool has_flags_for_user = FakeSessionManagerClient::Get()->GetFlagsForUser(
       cryptohome::CreateAccountIdentifierFromAccountId(test_account_id),
       &flags_for_user);
   EXPECT_TRUE(has_flags_for_user);
diff --git a/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.cc b/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.cc
index 3c6efc0..ee7af931 100644
--- a/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.cc
+++ b/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #include "chrome/browser/chromeos/tpm_firmware_update.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "chromeos/settings/cros_settings_provider.h"
@@ -115,9 +114,8 @@
   if (!update_available)
     return;
 
-  chromeos::DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->StartTPMFirmwareUpdate("preserve_stateful");
+  chromeos::SessionManagerClient::Get()->StartTPMFirmwareUpdate(
+      "preserve_stateful");
 }
 
 void TPMAutoUpdateModePolicyHandler::SetUpdateCheckerCallbackForTesting(
diff --git a/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler_unittest.cc b/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler_unittest.cc
index 29a476f9..be077a29 100644
--- a/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler_unittest.cc
+++ b/chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler_unittest.cc
@@ -24,16 +24,13 @@
 class TPMAutoUpdateModePolicyHandlerTest : public testing::Test {
  public:
   TPMAutoUpdateModePolicyHandlerTest() : weak_factory_(this) {}
+
   // testing::Test:
   void SetUp() override {
-    testing::Test::SetUp();
-    fake_session_manager_client_ = new chromeos::FakeSessionManagerClient();
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<chromeos::SessionManagerClient>(
-            fake_session_manager_client_));
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
   }
 
-  void TearDown() override { chromeos::DBusThreadManager::Shutdown(); }
+  void TearDown() override { chromeos::SessionManagerClient::Shutdown(); }
 
   void SetAutoUpdateMode(AutoUpdateMode auto_update_mode) {
     base::DictionaryValue dict;
@@ -58,8 +55,6 @@
                                                           "fake-id")};
   chromeos::ScopedTestingCrosSettings scoped_testing_cros_settings_;
 
-  chromeos::FakeSessionManagerClient* fake_session_manager_client_ = nullptr;
-
   base::WeakPtrFactory<TPMAutoUpdateModePolicyHandlerTest> weak_factory_;
 };
 
@@ -74,29 +69,31 @@
 
   update_available_ = true;
 
+  auto* fake_session_manager_client = chromeos::FakeSessionManagerClient::Get();
+
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
-      0, fake_session_manager_client_->start_tpm_firmware_update_call_count());
+      0, fake_session_manager_client->start_tpm_firmware_update_call_count());
 
   SetAutoUpdateMode(AutoUpdateMode::kWithoutAcknowledgment);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
-      1, fake_session_manager_client_->start_tpm_firmware_update_call_count());
+      1, fake_session_manager_client->start_tpm_firmware_update_call_count());
 
   SetAutoUpdateMode(AutoUpdateMode::kNever);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
-      1, fake_session_manager_client_->start_tpm_firmware_update_call_count());
+      1, fake_session_manager_client->start_tpm_firmware_update_call_count());
 
   SetAutoUpdateMode(AutoUpdateMode::kWithoutAcknowledgment);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
-      2, fake_session_manager_client_->start_tpm_firmware_update_call_count());
+      2, fake_session_manager_client->start_tpm_firmware_update_call_count());
 
   SetAutoUpdateMode(AutoUpdateMode::kEnrollment);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
-      2, fake_session_manager_client_->start_tpm_firmware_update_call_count());
+      2, fake_session_manager_client->start_tpm_firmware_update_call_count());
 }
 
 // Verify that the DBus call to start TPM firmware update is not triggered if
@@ -112,8 +109,8 @@
 
   SetAutoUpdateMode(AutoUpdateMode::kWithoutAcknowledgment);
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(
-      0, fake_session_manager_client_->start_tpm_firmware_update_call_count());
+  EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
+                   ->start_tpm_firmware_update_call_count());
 }
 
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc b/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc
index f9c9190..544f849 100644
--- a/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc
+++ b/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc
@@ -157,15 +157,11 @@
     InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
     // Some DBus services rely on paths, so override it here.
     chromeos::active_directory_test_helper::OverridePaths();
-    chromeos::FakeSessionManagerClient* fake_session_manager_client =
-        new chromeos::FakeSessionManagerClient;
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        base::WrapUnique<chromeos::SessionManagerClient>(
-            fake_session_manager_client));
 
     // Initialize clients here so they are available during setup. They will be
     // shutdown in ChromeBrowserMain.
     chromeos::CryptohomeClient::InitializeFake();
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
     chromeos::UpstartClient::InitializeFake();
     chromeos::FakeAuthPolicyClient* fake_auth_policy_client = nullptr;
     if (GetParam().active_directory) {
@@ -180,12 +176,12 @@
     const std::set<std::string> user_affiliation_ids = {
         GetParam().affiliated ? kAffiliationID : kAnotherAffiliationID};
 
+    auto* session_manager_client = chromeos::FakeSessionManagerClient::Get();
     AffiliationTestHelper affiliation_helper =
         GetParam().active_directory
             ? AffiliationTestHelper::CreateForActiveDirectory(
-                  fake_session_manager_client, fake_auth_policy_client)
-            : AffiliationTestHelper::CreateForCloud(
-                  fake_session_manager_client);
+                  session_manager_client, fake_auth_policy_client)
+            : AffiliationTestHelper::CreateForCloud(session_manager_client);
 
     ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetDeviceAffiliationIDs(
         &test_helper, device_affiliation_ids));
diff --git a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
index 5f275c3..9987c53a 100644
--- a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
+++ b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
@@ -36,7 +36,8 @@
 #include "chrome/common/pref_names.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/cryptohome/cryptohome_client.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/tpm/install_attributes.h"
 #include "components/arc/arc_features.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
@@ -344,9 +345,8 @@
   std::unique_ptr<UserCloudPolicyStoreChromeOS> store =
       std::make_unique<UserCloudPolicyStoreChromeOS>(
           chromeos::CryptohomeClient::Get(),
-          chromeos::DBusThreadManager::Get()->GetSessionManagerClient(),
-          background_task_runner, account_id, policy_key_dir,
-          is_active_directory);
+          chromeos::SessionManagerClient::Get(), background_task_runner,
+          account_id, policy_key_dir, is_active_directory);
 
   scoped_refptr<base::SequencedTaskRunner> backend_task_runner =
       base::CreateSequencedTaskRunnerWithTraits(
diff --git a/chrome/browser/chromeos/power/extension_event_observer.cc b/chrome/browser/chromeos/power/extension_event_observer.cc
index 71f82e9..be2aa07 100644
--- a/chrome/browser/chromeos/power/extension_event_observer.cc
+++ b/chrome/browser/chromeos/power/extension_event_observer.cc
@@ -99,8 +99,7 @@
     // There is a suspend attempt pending but this class should no longer be
     // delaying it.  Immediately report readiness.
     suspend_is_pending_ = false;
-    power_manager_callback_.Run();
-    power_manager_callback_.Reset();
+    std::move(power_manager_callback_).Run();
     suspend_readiness_callback_.Cancel();
   }
 }
@@ -269,8 +268,7 @@
     return;
 
   suspend_is_pending_ = false;
-  power_manager_callback_.Run();
-  power_manager_callback_.Reset();
+  std::move(power_manager_callback_).Run();
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/power/extension_event_observer.h b/chrome/browser/chromeos/power/extension_event_observer.h
index 960170c8..d4fe0272 100644
--- a/chrome/browser/chromeos/power/extension_event_observer.h
+++ b/chrome/browser/chromeos/power/extension_event_observer.h
@@ -124,7 +124,7 @@
   bool should_delay_suspend_;
   bool suspend_is_pending_;
   int suspend_keepalive_count_;
-  base::Closure power_manager_callback_;
+  base::OnceClosure power_manager_callback_;
   base::CancelableClosure suspend_readiness_callback_;
 
   content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/chromeos/printing/cups_printers_manager.cc b/chrome/browser/chromeos/printing/cups_printers_manager.cc
index 62dac18f..a4b31cae 100644
--- a/chrome/browser/chromeos/printing/cups_printers_manager.cc
+++ b/chrome/browser/chromeos/printing/cups_printers_manager.cc
@@ -446,21 +446,22 @@
       auto it = detected_printer_ppd_references_.find(detected.printer.id());
       if (it != detected_printer_ppd_references_.end()) {
         if (!it->second) {
+          auto printer = detected.printer;
+          if (!printer.supports_ippusb()) {
+            // We couldn't figure out this printer, so it's in the discovered
+            // class.
+            printers_[kDiscovered].push_back(printer);
+            continue;
+          }
           // If the detected printer supports ipp-over-usb and we could not find
           // a ppd for it, then we switch to the ippusb scheme and mark it as
           // autoconf.
-          auto printer = detected.printer;
-          if (printer.supports_ippusb()) {
-            printer.set_uri(
-                base::StringPrintf("ippusb://%04x_%04x/ipp/print",
-                                   detected.ppd_search_data.usb_vendor_id,
-                                   detected.ppd_search_data.usb_product_id));
-            printer.mutable_ppd_reference()->autoconf = true;
-          }
-
-          // We couldn't figure out this printer, so it's in the discovered
-          // class.
-          printers_[kDiscovered].push_back(printer);
+          printer.set_uri(
+              base::StringPrintf("ippusb://%04x_%04x/ipp/print",
+                                 detected.ppd_search_data.usb_vendor_id,
+                                 detected.ppd_search_data.usb_product_id));
+          printer.mutable_ppd_reference()->autoconf = true;
+          printers_[kAutomatic].push_back(printer);
         } else {
           // We have a ppd reference, so we think we can set this up
           // automatically.
diff --git a/chrome/browser/chromeos/printing/printing_fakes.h b/chrome/browser/chromeos/printing/printing_fakes.h
new file mode 100644
index 0000000..239ca82
--- /dev/null
+++ b/chrome/browser/chromeos/printing/printing_fakes.h
@@ -0,0 +1,67 @@
+// Copyright 2019 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_CHROMEOS_PRINTING_PRINTING_FAKES_H_
+#define CHROME_BROWSER_CHROMEOS_PRINTING_PRINTING_FAKES_H_
+
+#include <vector>
+
+#include "chrome/browser/chromeos/printing/cups_printers_manager.h"
+#include "chrome/browser/chromeos/printing/printer_configurer.h"
+#include "chromeos/printing/printer_configuration.h"
+
+namespace chromeos {
+
+class FakeCupsPrintersManager : public CupsPrintersManager {
+ public:
+  FakeCupsPrintersManager() = default;
+
+  std::vector<Printer> GetPrinters(PrinterClass printer_class) const override {
+    return {};
+  }
+
+  bool IsPrinterInstalled(const Printer& printer) const override {
+    return false;
+  }
+
+  std::unique_ptr<Printer> GetPrinter(const std::string& id) const override {
+    return nullptr;
+  }
+
+  void RemoveUnavailablePrinters(
+      std::vector<Printer>* printers) const override {}
+  void UpdateConfiguredPrinter(const Printer& printer) override {}
+  void RemoveConfiguredPrinter(const std::string& printer_id) override {}
+  void AddObserver(CupsPrintersManager::Observer* observer) override {}
+  void RemoveObserver(CupsPrintersManager::Observer* observer) override {}
+  void PrinterInstalled(const Printer& printer, bool is_automatic) override {}
+  void RecordSetupAbandoned(const Printer& printer) override {}
+};
+
+class FakePrinterConfigurer : public PrinterConfigurer {
+ public:
+  void SetUpPrinter(const Printer&, PrinterSetupCallback callback);
+};
+
+class FakePpdProvider : public PpdProvider {
+ public:
+  void ResolveManufacturers(ResolveManufacturersCallback cb) override {}
+  void ResolvePrinters(const std::string& manufacturer,
+                       ResolvePrintersCallback cb) override {}
+  void ResolvePpdReference(const PrinterSearchData& search_data,
+                           ResolvePpdReferenceCallback cb) override {}
+  void ResolvePpd(const Printer::PpdReference& reference,
+                  ResolvePpdCallback cb) override {}
+  void ReverseLookup(const std::string& effective_make_and_model,
+                     ReverseLookupCallback cb) override {}
+
+ private:
+  // Since PpdProvider is a RefCounted object it's destructor must be either
+  // protected or private.
+  ~FakePpdProvider() override {}
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_PRINTING_PRINTING_FAKES_H_
diff --git a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
index fbebbbd..7507aa4 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
@@ -18,8 +18,8 @@
 #include "base/task/post_task.h"
 #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "chromeos/network/network_state.h"
diff --git a/chrome/browser/chromeos/settings/cros_settings_unittest.cc b/chrome/browser/chromeos/settings/cros_settings_unittest.cc
index a4c97e5..0636107 100644
--- a/chrome/browser/chromeos/settings/cros_settings_unittest.cc
+++ b/chrome/browser/chromeos/settings/cros_settings_unittest.cc
@@ -70,6 +70,10 @@
     thread_bundle_.RunUntilIdle();
   }
 
+  void TearDown() override {
+    DeviceSettingsService::Get()->UnsetSessionManager();
+  }
+
   // Some tests below use an OwnerSettingsService so they can change settings
   // partway through the test - this sets one up for those tests that need it.
   // Other tests below cannot use an OwnerSettingsService, since they change
diff --git a/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.cc b/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.cc
index 2a5f550f..bec8af6 100644
--- a/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.cc
+++ b/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.cc
@@ -134,13 +134,6 @@
   }
 }
 
-void ScopedCrosSettingsTestHelper::SetFakeSessionManager() {
-  DeviceSettingsService::Get()->SetSessionManager(
-      &fake_session_manager_client_, new ownership::MockOwnerKeyUtil());
-  DeviceSettingsService::Get()->Load();
-  content::RunAllTasksUntilIdle();
-}
-
 StubInstallAttributes* ScopedCrosSettingsTestHelper::InstallAttributes() {
   return test_install_attributes_->Get();
 }
diff --git a/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h b/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h
index f4ca8d9..bd9e6b8 100644
--- a/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h
+++ b/chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h
@@ -80,17 +80,11 @@
   // device settings service.
   void StoreCachedDeviceSetting(const std::string& path);
 
-  // Sets the underlying DeviceSettingsService session manager to a
-  // FakeSessionManagerClient.
-  void SetFakeSessionManager();
-
   // Get the scoped install attributes to change them as needed for the
   // current test.
   StubInstallAttributes* InstallAttributes();
 
  private:
-  // Helpers used to mock out cros settings.
-  FakeSessionManagerClient fake_session_manager_client_;
   std::unique_ptr<ScopedStubInstallAttributes> test_install_attributes_;
   std::unique_ptr<ScopedTestDeviceSettingsService>
       test_device_settings_service_;
diff --git a/chrome/browser/chromeos/settings/stats_reporting_controller_unittest.cc b/chrome/browser/chromeos/settings/stats_reporting_controller_unittest.cc
index c500e4b..85c74d1 100644
--- a/chrome/browser/chromeos/settings/stats_reporting_controller_unittest.cc
+++ b/chrome/browser/chromeos/settings/stats_reporting_controller_unittest.cc
@@ -96,9 +96,9 @@
       content::TestBrowserThreadBundle::IO_MAINLOOP};
   TestingPrefServiceSimple local_state_;
   ScopedStubInstallAttributes scoped_install_attributes_;
+  FakeSessionManagerClient fake_session_manager_client_;
   ScopedTestDeviceSettingsService scoped_device_settings_;
   ScopedTestCrosSettings scoped_cros_settings_{RegisterPrefs(&local_state_)};
-  FakeSessionManagerClient fake_session_manager_client_;
   policy::DevicePolicyBuilder device_policy_;
 
   bool value_at_last_notification_{false};
diff --git a/chrome/browser/chromeos/shutdown_policy_browsertest.cc b/chrome/browser/chromeos/shutdown_policy_browsertest.cc
index 77e5e34..7cb0d64 100644
--- a/chrome/browser/chromeos/shutdown_policy_browsertest.cc
+++ b/chrome/browser/chromeos/shutdown_policy_browsertest.cc
@@ -32,9 +32,7 @@
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
-#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_contents.h"
@@ -182,10 +180,6 @@
   ~ShutdownPolicyLockerTest() override = default;
 
   void SetUpInProcessBrowserTestFixture() override {
-    fake_session_manager_client_ = new FakeSessionManagerClient;
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(fake_session_manager_client_));
-
     ShutdownPolicyBaseTest::SetUpInProcessBrowserTestFixture();
     zero_duration_mode_.reset(new ui::ScopedAnimationDurationScaleMode(
         ui::ScopedAnimationDurationScaleMode::ZERO_DURATION));
@@ -207,7 +201,6 @@
 
  private:
   std::unique_ptr<ui::ScopedAnimationDurationScaleMode> zero_duration_mode_;
-  FakeSessionManagerClient* fake_session_manager_client_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(ShutdownPolicyLockerTest);
 };
diff --git a/chrome/browser/chromeos/system/device_disabling_browsertest.cc b/chrome/browser/chromeos/system/device_disabling_browsertest.cc
index fdcb985c..249b50c 100644
--- a/chrome/browser/chromeos/system/device_disabling_browsertest.cc
+++ b/chrome/browser/chromeos/system/device_disabling_browsertest.cc
@@ -24,11 +24,10 @@
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_shill_manager_client.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
-#include "chromeos/dbus/session_manager/session_manager_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/fake_shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/settings/cros_settings_names.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "content/public/browser/web_contents.h"
@@ -59,7 +58,7 @@
     : public OobeBaseTest,
       public NetworkStateInformer::NetworkStateInformerObserver {
  public:
-  DeviceDisablingTest();
+  DeviceDisablingTest() = default;
 
   // Sets up a device state blob that indicates the device is disabled.
   void SetDeviceDisabledPolicy();
@@ -82,23 +81,18 @@
   NetworkPortalDetectorMixin network_portal_detector_{&mixin_host_};
 
  private:
-  FakeSessionManagerClient* fake_session_manager_client_;
   policy::DevicePolicyCrosTestHelper test_helper_;
 
   DISALLOW_COPY_AND_ASSIGN(DeviceDisablingTest);
 };
 
 
-DeviceDisablingTest::DeviceDisablingTest()
-    : fake_session_manager_client_(new FakeSessionManagerClient) {
-}
-
 void DeviceDisablingTest::SetDeviceDisabledPolicy() {
   // Prepare a policy fetch response that indicates the device is disabled.
   test_helper_.device_policy()->policy_data().mutable_device_state()->
       set_device_mode(enterprise_management::DeviceState::DEVICE_MODE_DISABLED);
   test_helper_.device_policy()->Build();
-  fake_session_manager_client_->set_device_policy(
+  FakeSessionManagerClient::Get()->set_device_policy(
       test_helper_.device_policy()->GetBlob());
 }
 
@@ -110,7 +104,7 @@
                                                run_loop.QuitClosure());
   SetDeviceDisabledPolicy();
   // Trigger a policy fetch.
-  fake_session_manager_client_->OnPropertyChangeComplete(true);
+  FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
   // Wait for the policy fetch to complete and the disabled setting to change.
   run_loop.Run();
 }
@@ -128,10 +122,10 @@
 }
 
 void DeviceDisablingTest::SetUpInProcessBrowserTestFixture() {
-  OobeBaseTest::SetUpInProcessBrowserTestFixture();
+  // Override FakeSessionManagerClient. This will be shut down by the browser.
+  chromeos::SessionManagerClient::InitializeFakeInMemory();
 
-  DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-      std::unique_ptr<SessionManagerClient>(fake_session_manager_client_));
+  OobeBaseTest::SetUpInProcessBrowserTestFixture();
 
   test_helper_.InstallOwnerKey();
   test_helper_.MarkAsEnterpriseOwned();
diff --git a/chrome/browser/chromeos/tether/tether_service_unittest.cc b/chrome/browser/chromeos/tether/tether_service_unittest.cc
index c001a85..29d6a99e 100644
--- a/chrome/browser/chromeos/tether/tether_service_unittest.cc
+++ b/chrome/browser/chromeos/tether/tether_service_unittest.cc
@@ -33,9 +33,9 @@
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_connect.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chrome/browser/conflicts/incompatible_applications_updater_win_unittest.cc b/chrome/browser/conflicts/incompatible_applications_updater_win_unittest.cc
index 8b7fc96..5982cc46 100644
--- a/chrome/browser/conflicts/incompatible_applications_updater_win_unittest.cc
+++ b/chrome/browser/conflicts/incompatible_applications_updater_win_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/test_reg_util_win.h"
 #include "base/win/registry.h"
+#include "base/win/windows_version.h"
 #include "chrome/browser/conflicts/module_info_win.h"
 #include "chrome/browser/conflicts/module_list_filter_win.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
@@ -179,6 +180,9 @@
 // Tests that when the Local State cache is empty, no incompatible applications
 // are returned.
 TEST_F(IncompatibleApplicationsUpdaterTest, EmptyCache) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
   EXPECT_TRUE(IncompatibleApplicationsUpdater::GetCachedApplications().empty());
 }
@@ -186,6 +190,9 @@
 // IncompatibleApplicationsUpdater doesn't do anything when there is no
 // registered installed applications.
 TEST_F(IncompatibleApplicationsUpdaterTest, NoIncompatibleApplications) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   auto incompatible_applications_updater =
       CreateIncompatibleApplicationsUpdater();
 
@@ -200,6 +207,9 @@
 }
 
 TEST_F(IncompatibleApplicationsUpdaterTest, NoTiedApplications) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   auto incompatible_applications_updater =
       CreateIncompatibleApplicationsUpdater();
 
@@ -220,6 +230,9 @@
 }
 
 TEST_F(IncompatibleApplicationsUpdaterTest, OneIncompatibility) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
 
   auto incompatible_applications_updater =
@@ -243,6 +256,9 @@
 }
 
 TEST_F(IncompatibleApplicationsUpdaterTest, SameModuleMultipleApplications) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
   AddIncompatibleApplication(dll1_, L"Bar", Option::ADD_REGISTRY_ENTRY);
 
@@ -267,6 +283,9 @@
 
 TEST_F(IncompatibleApplicationsUpdaterTest,
        MultipleCallsToOnModuleDatabaseIdle) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
   AddIncompatibleApplication(dll2_, L"Bar", Option::ADD_REGISTRY_ENTRY);
 
@@ -306,6 +325,9 @@
 // the list isn't tied to the lifetime of the IncompatibleApplicationsUpdater
 // instance. It is assumed that the Local State file works as intended.
 TEST_F(IncompatibleApplicationsUpdaterTest, PersistsThroughRestarts) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
 
   auto incompatible_applications_updater =
@@ -327,6 +349,9 @@
 
 // Tests that applications that do not have a registry entry are removed.
 TEST_F(IncompatibleApplicationsUpdaterTest, StaleEntriesRemoved) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
   AddIncompatibleApplication(dll2_, L"Bar", Option::NO_REGISTRY_ENTRY);
 
@@ -349,6 +374,9 @@
 }
 
 TEST_F(IncompatibleApplicationsUpdaterTest, IgnoreNotLoadedModules) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
 
   auto incompatible_applications_updater =
@@ -374,6 +402,9 @@
 // Tests that modules with a matching certificate subject are whitelisted.
 TEST_F(IncompatibleApplicationsUpdaterTest,
        WhitelistMatchingCertificateSubject) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
 
   auto incompatible_applications_updater =
@@ -398,6 +429,9 @@
 
 // Registered modules are defined as either a shell extension or an IME.
 TEST_F(IncompatibleApplicationsUpdaterTest, IgnoreRegisteredModules) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   AddIncompatibleApplication(dll1_, L"Shell Extension",
                              Option::ADD_REGISTRY_ENTRY);
   AddIncompatibleApplication(dll2_, L"Input Method Editor",
@@ -437,6 +471,9 @@
 }
 
 TEST_F(IncompatibleApplicationsUpdaterTest, IgnoreModulesAddedToTheBlacklist) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   AddIncompatibleApplication(dll1_, L"Blacklisted Application",
                              Option::ADD_REGISTRY_ENTRY);
 
@@ -460,6 +497,9 @@
 }
 
 TEST_F(IncompatibleApplicationsUpdaterTest, DisableModuleAnalysis) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return;
+
   AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
 
   auto incompatible_applications_updater =
diff --git a/chrome/browser/download/download_ui_model.cc b/chrome/browser/download/download_ui_model.cc
index 8dd03fd5..49e41b7b 100644
--- a/chrome/browser/download/download_ui_model.cc
+++ b/chrome/browser/download/download_ui_model.cc
@@ -8,9 +8,11 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "chrome/browser/download/offline_item_utils.h"
+#include "chrome/browser/safe_browsing/advanced_protection_status_manager.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "net/base/mime_util.h"
+#include "net/url_request/url_request_status.h"
 #include "third_party/blink/public/common/mime_util/mime_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/time_format.h"
@@ -247,9 +249,19 @@
   base::string16 elided_filename =
       gfx::ElideFilename(GetFileNameToReportUser(), font_list, base_width,
                          gfx::Typesetter::BROWSER);
+
+  bool request_ap_verdicts = false;
+#if defined(FULL_SAFE_BROWSING)
+  request_ap_verdicts = safe_browsing::AdvancedProtectionStatusManager::
+      RequestsAdvancedProtectionVerdicts(profile());
+#endif
+
   switch (GetDangerType()) {
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: {
-      return l10n_util::GetStringUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
+      return l10n_util::GetStringUTF16(
+          request_ap_verdicts
+              ? IDS_PROMPT_MALICIOUS_DOWNLOAD_URL_IN_ADVANCED_PROTECTION
+              : IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
     }
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
       if (IsExtensionDownload()) {
@@ -262,16 +274,25 @@
     }
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
-      return l10n_util::GetStringFUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
-                                        elided_filename);
+      return l10n_util::GetStringFUTF16(
+          request_ap_verdicts
+              ? IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION
+              : IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
+          elided_filename);
     }
     case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
-      return l10n_util::GetStringFUTF16(IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
-                                        elided_filename);
+      return l10n_util::GetStringFUTF16(
+          request_ap_verdicts
+              ? IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION
+              : IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
+          elided_filename);
     }
     case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
-      return l10n_util::GetStringFUTF16(IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS,
-                                        elided_filename);
+      return l10n_util::GetStringFUTF16(
+          request_ap_verdicts
+              ? IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS_IN_ADVANCED_PROTECTION
+              : IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS,
+          elided_filename);
     }
     case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
     case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc
index d65fbe3..46f0d65 100644
--- a/chrome/browser/download/notification/download_item_notification.cc
+++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/notifications/notification_display_service.h"
 #include "chrome/browser/notifications/notification_display_service_factory.h"
 #include "chrome/browser/notifications/notification_handler.h"
+#include "chrome/browser/safe_browsing/advanced_protection_status_manager.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/chromium_strings.h"
@@ -680,9 +681,14 @@
   DCHECK(item_->IsDangerous());
   base::string16 elided_filename =
       item_->GetFileNameToReportUser().LossyDisplayName();
+  bool requests_ap_verdicts = safe_browsing::AdvancedProtectionStatusManager::
+      RequestsAdvancedProtectionVerdicts(profile());
   switch (item_->GetDangerType()) {
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: {
-      return l10n_util::GetStringUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
+      return l10n_util::GetStringUTF16(
+          requests_ap_verdicts
+              ? IDS_PROMPT_MALICIOUS_DOWNLOAD_URL_IN_ADVANCED_PROTECTION
+              : IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
     }
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
       if (IsExtensionDownload(item_.get())) {
@@ -695,16 +701,25 @@
     }
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
-      return l10n_util::GetStringFUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
-                                        elided_filename);
+      return l10n_util::GetStringFUTF16(
+          requests_ap_verdicts
+              ? IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION
+              : IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
+          elided_filename);
     }
     case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
-      return l10n_util::GetStringFUTF16(IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
-                                        elided_filename);
+      return l10n_util::GetStringFUTF16(
+          requests_ap_verdicts
+              ? IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION
+              : IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
+          elided_filename);
     }
     case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
-      return l10n_util::GetStringFUTF16(IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS,
-                                        elided_filename);
+      return l10n_util::GetStringFUTF16(
+          requests_ap_verdicts
+              ? IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS_IN_ADVANCED_PROTECTION
+              : IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS,
+          elided_filename);
     }
     case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
     case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index c06d454..d663ab68 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -1000,6 +1000,7 @@
       "//remoting/host",
       "//remoting/host/it2me:chrome_os_host",
       "//third_party/protobuf:protobuf_lite",
+      "//ui/base/ime/chromeos",
       "//ui/chromeos",
       "//ui/chromeos/events",
       "//ui/file_manager",
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index b3bf8f3..dab609b 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -15,6 +15,7 @@
 #include "base/json/json_string_value_serializer.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
+#include "base/one_shot_event.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -52,7 +53,6 @@
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_messages.h"
-#include "extensions/common/one_shot_event.h"
 #include "third_party/re2/src/re2/re2.h"
 #include "url/gurl.h"
 
@@ -581,9 +581,8 @@
   extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
   CheckActive(true);  // use cached
   extension_system_->ready().Post(
-      FROM_HERE,
-      base::Bind(&ActivityLog::OnExtensionSystemReady,
-                 weak_factory_.GetWeakPtr()));
+      FROM_HERE, base::BindOnce(&ActivityLog::OnExtensionSystemReady,
+                                weak_factory_.GetWeakPtr()));
 }
 
 void ActivityLog::SetDatabasePolicy(
diff --git a/chrome/browser/extensions/api/automation/automation_apitest.cc b/chrome/browser/extensions/api/automation/automation_apitest.cc
index 5ca838d..8728681 100644
--- a/chrome/browser/extensions/api/automation/automation_apitest.cc
+++ b/chrome/browser/extensions/api/automation/automation_apitest.cc
@@ -2,6 +2,7 @@
 // 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 "base/files/file_path.h"
 #include "base/location.h"
 #include "base/path_service.h"
@@ -30,6 +31,7 @@
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/accessibility_switches.h"
 #include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_serializable_tree.h"
 #include "ui/accessibility/ax_tree.h"
@@ -378,6 +380,23 @@
       << message_;
 }
 
+class AutomationApiTestWithLanguageDetection : public AutomationApiTest {
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    AutomationApiTest::SetUpCommandLine(command_line);
+    command_line->AppendSwitch(
+        ::switches::kEnableExperimentalAccessibilityLanguageDetection);
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(AutomationApiTestWithLanguageDetection,
+                       DetectedLanguage) {
+  StartEmbeddedTestServer();
+  ASSERT_TRUE(
+      RunExtensionSubtest("automation/tests/tabs", "detected_language.html"))
+      << message_;
+}
+
 #if defined(OS_CHROMEOS)
 
 class AutomationApiTestWithDeviceScaleFactor : public AutomationApiTest {
diff --git a/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc b/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
index 9babf90a..75ff22f 100644
--- a/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
+++ b/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
@@ -138,15 +138,10 @@
   void SetUpInProcessBrowserTestFixture() override {
     ExtensionApiTest::SetUpInProcessBrowserTestFixture();
 
-    chromeos::FakeSessionManagerClient* fake_session_manager_client =
-        new chromeos::FakeSessionManagerClient;
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<chromeos::SessionManagerClient>(
-            fake_session_manager_client));
-
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
     policy::AffiliationTestHelper affiliation_helper =
         policy::AffiliationTestHelper::CreateForCloud(
-            fake_session_manager_client);
+            chromeos::FakeSessionManagerClient::Get());
 
     std::set<std::string> device_affiliation_ids;
     device_affiliation_ids.insert(kAffiliationID);
@@ -172,8 +167,9 @@
     device_policy->policy_data().set_annotated_location(kAnnotatedLocation);
     device_policy->Build();
 
-    fake_session_manager_client->set_device_policy(device_policy->GetBlob());
-    fake_session_manager_client->OnPropertyChangeComplete(true);
+    chromeos::FakeSessionManagerClient::Get()->set_device_policy(
+        device_policy->GetBlob());
+    chromeos::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true);
 
     // Init the user policy provider.
     EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc b/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
index 8bfbf82..d3eb91e 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
@@ -6,12 +6,15 @@
 #include "base/run_loop.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/devtools/devtools_window_testing.h"
 #include "chrome/browser/extensions/component_loader.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/feedback/feedback_dialog_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/extensions/extension_constants.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/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
@@ -244,4 +247,41 @@
       &bool_result));
   EXPECT_TRUE(bool_result);
 }
+
+IN_PROC_BROWSER_TEST_F(FeedbackTest, GetTargetTabUrl) {
+  const std::pair<std::string, std::string> test_cases[] = {
+      {"https://www.google.com/", "https://www.google.com/"},
+      {"about://version/", "chrome://version/"},
+      {"chrome://bookmarks/", "chrome://bookmarks/"},
+  };
+
+  for (const auto& test_case : test_cases) {
+    GURL expected_url = GURL(test_case.second);
+
+    ui_test_utils::NavigateToURL(browser(), GURL(test_case.first));
+
+    // Sanity check that we always have one tab in the browser.
+    ASSERT_EQ(browser()->tab_strip_model()->count(), 1);
+
+    ASSERT_EQ(expected_url,
+              browser()->tab_strip_model()->GetWebContentsAt(0)->GetURL());
+
+    ASSERT_EQ(expected_url,
+              chrome::GetTargetTabUrl(browser()->session_id(), 0));
+
+    // Open a DevTools window.
+    DevToolsWindow* devtools_window =
+        DevToolsWindowTesting::OpenDevToolsWindowSync(browser(), false);
+
+    // Verify the expected url returned from GetTargetTabUrl against a
+    // DevTools window.
+    ASSERT_EQ(expected_url, chrome::GetTargetTabUrl(
+                                DevToolsWindowTesting::Get(devtools_window)
+                                    ->browser()
+                                    ->session_id(),
+                                0));
+
+    DevToolsWindowTesting::CloseDevToolsWindowSync(devtools_window);
+  }
+}
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
index 5dbe11e7..c39fd6e 100644
--- a/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
+++ b/chrome/browser/extensions/api/networking_cast_private/networking_cast_private_apitest.cc
@@ -20,8 +20,8 @@
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #endif
 
diff --git a/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc b/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
index 02c0f7c..c27a9c4 100644
--- a/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
+++ b/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
@@ -17,9 +17,9 @@
 #include "chrome/browser/notifications/notification_display_service_tester.h"
 #include "chrome/browser/ui/ash/network/network_portal_notification_controller.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "components/captive_portal/captive_portal_testing_utils.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/test/result_catcher.h"
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index f4ca988..d21e9f5e 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -25,11 +25,11 @@
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_ipconfig_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_certificate_handler.h"
 #include "chromeos/network/network_handler.h"
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
index 958d221..34b6c36 100644
--- a/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
+++ b/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
@@ -14,9 +14,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
-#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/policy_constants.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -94,15 +92,11 @@
 void PlatformKeysTestBase::SetUpInProcessBrowserTestFixture() {
   extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture();
 
-  chromeos::FakeSessionManagerClient* fake_session_manager_client =
-      new chromeos::FakeSessionManagerClient;
-  chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-      std::unique_ptr<chromeos::SessionManagerClient>(
-          fake_session_manager_client));
+  chromeos::SessionManagerClient::InitializeFakeInMemory();
 
   policy::AffiliationTestHelper affiliation_helper =
       policy::AffiliationTestHelper::CreateForCloud(
-          fake_session_manager_client);
+          chromeos::FakeSessionManagerClient::Get());
 
   if (enrollment_status() == EnrollmentStatus::ENROLLED) {
     std::set<std::string> device_affiliation_ids;
diff --git a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
index ba3dfb2c..809b193b 100644
--- a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
+++ b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/one_shot_event.h"
 #include "base/scoped_observer.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/extensions/api/storage/policy_value_store.h"
@@ -41,7 +42,6 @@
 #include "extensions/common/extension_set.h"
 #include "extensions/common/manifest.h"
 #include "extensions/common/manifest_constants.h"
-#include "extensions/common/one_shot_event.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
diff --git a/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc b/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc
index c0830fac..d4506f84 100644
--- a/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc
+++ b/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc
@@ -14,9 +14,9 @@
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_shill_profile_client.h"
-#include "chromeos/dbus/fake_shill_service_client.h"
-#include "chromeos/dbus/fake_shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/fake_shill_profile_client.h"
+#include "chromeos/dbus/shill/fake_shill_service_client.h"
+#include "chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_profile_handler.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/extensions/bookmark_app_helper_unittest.cc b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
index 53ea153..8d0d275 100644
--- a/chrome/browser/extensions/bookmark_app_helper_unittest.cc
+++ b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
@@ -374,6 +374,7 @@
 
   blink::Manifest manifest;
   manifest.start_url = GURL(kAppUrl);
+  manifest.scope = GURL(kAppDefaultScope);
   manifest.name = base::NullableString16(base::UTF8ToUTF16(kAppTitle), false);
   helper.CompleteInstallableCheck(kManifestUrl, manifest, GetParam());
 
diff --git a/chrome/browser/extensions/browsertest_util.cc b/chrome/browser/extensions/browsertest_util.cc
index 687930ce..fb3e30a 100644
--- a/chrome/browser/extensions/browsertest_util.cc
+++ b/chrome/browser/extensions/browsertest_util.cc
@@ -4,10 +4,10 @@
 
 #include "chrome/browser/extensions/browsertest_util.h"
 
+#include <memory>
+
 #include "base/files/file_util.h"
 #include "base/path_service.h"
-#include "chrome/browser/extensions/bookmark_app_helper.h"
-#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/launch_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -15,7 +15,9 @@
 #include "chrome/browser/ui/extensions/app_launch_params.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/web_applications/components/install_manager.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/components/web_app_provider_base.h"
 #include "chrome/browser/web_applications/components/web_app_tab_helper_base.h"
 #include "chrome/common/web_application_info.h"
 #include "content/public/browser/notification_service.h"
@@ -34,14 +36,6 @@
 namespace extensions {
 namespace browsertest_util {
 
-namespace {
-
-ExtensionService* GetExtensionService(Profile* profile) {
-  return ExtensionSystem::Get(profile)->extension_service();
-}
-
-}  // namespace
-
 void CreateAndInitializeLocalCache() {
 #if defined(OS_CHROMEOS)
   base::FilePath extension_cache_dir;
@@ -60,8 +54,12 @@
   content::WindowedNotificationObserver windowed_observer(
       NOTIFICATION_CRX_INSTALLER_DONE,
       content::NotificationService::AllSources());
-  CreateOrUpdateBookmarkApp(GetExtensionService(profile), &info,
-                            true /* locally_installed */);
+
+  auto* provider = web_app::WebAppProviderBase::GetProviderBase(profile);
+  DCHECK(provider);
+  provider->install_manager().InstallWebAppForTesting(
+      std::make_unique<WebApplicationInfo>(info), base::DoNothing());
+
   windowed_observer.Wait();
 
   EXPECT_EQ(++num_extensions,
diff --git a/chrome/browser/extensions/chrome_process_manager_delegate.cc b/chrome/browser/extensions/chrome_process_manager_delegate.cc
index 6076a22..9d7ba9e9 100644
--- a/chrome/browser/extensions/chrome_process_manager_delegate.cc
+++ b/chrome/browser/extensions/chrome_process_manager_delegate.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/one_shot_event.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -21,7 +22,6 @@
 #include "extensions/browser/process_manager.h"
 #include "extensions/browser/process_manager_factory.h"
 #include "extensions/common/extension.h"
-#include "extensions/common/one_shot_event.h"
 #include "extensions/common/permissions/permissions_data.h"
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/extensions/extension_function_registration_test.cc b/chrome/browser/extensions/extension_function_registration_test.cc
index fe75530..8652e41 100644
--- a/chrome/browser/extensions/extension_function_registration_test.cc
+++ b/chrome/browser/extensions/extension_function_registration_test.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/one_shot_event.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "extensions/browser/extension_function_registry.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/common/one_shot_event.h"
 
 namespace extensions {
 
diff --git a/chrome/browser/extensions/extension_garbage_collector.cc b/chrome/browser/extensions/extension_garbage_collector.cc
index e3af0c2..66ea858 100644
--- a/chrome/browser/extensions/extension_garbage_collector.cc
+++ b/chrome/browser/extensions/extension_garbage_collector.cc
@@ -15,6 +15,7 @@
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/one_shot_event.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_util.h"
@@ -37,7 +38,6 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/file_util.h"
 #include "extensions/common/manifest_handlers/app_isolation_info.h"
-#include "extensions/common/one_shot_event.h"
 
 namespace extensions {
 
@@ -118,13 +118,13 @@
 
   extension_system->ready().PostDelayed(
       FROM_HERE,
-      base::Bind(&ExtensionGarbageCollector::GarbageCollectExtensions,
-                 weak_factory_.GetWeakPtr()),
+      base::BindOnce(&ExtensionGarbageCollector::GarbageCollectExtensions,
+                     weak_factory_.GetWeakPtr()),
       kGarbageCollectStartupDelay);
 
   extension_system->ready().Post(
       FROM_HERE,
-      base::Bind(
+      base::BindOnce(
           &ExtensionGarbageCollector::GarbageCollectIsolatedStorageIfNeeded,
           weak_factory_.GetWeakPtr()));
 
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index d58ad80..8756a673 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -18,6 +18,7 @@
 #include "base/location.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/one_shot_event.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -98,7 +99,6 @@
 #include "extensions/common/manifest_constants.h"
 #include "extensions/common/manifest_handlers/shared_module_info.h"
 #include "extensions/common/manifest_url_handlers.h"
-#include "extensions/common/one_shot_event.h"
 #include "extensions/common/permissions/api_permission.h"
 #include "extensions/common/permissions/permission_message_provider.h"
 #include "extensions/common/permissions/permissions_data.h"
@@ -283,7 +283,7 @@
                                    Blacklist* blacklist,
                                    bool autoupdate_enabled,
                                    bool extensions_enabled,
-                                   OneShotEvent* ready)
+                                   base::OneShotEvent* ready)
     : Blacklist::Observer(blacklist),
       command_line_(command_line),
       profile_(profile),
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 06a8838..2c88f65d 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -51,6 +51,7 @@
 
 namespace base {
 class CommandLine;
+class OneShotEvent;
 }
 
 FORWARD_DECLARE_TEST(BlacklistedExtensionSyncServiceTest,
@@ -66,7 +67,6 @@
 class ExtensionSystem;
 class ExtensionUpdater;
 class ExternalInstallManager;
-class OneShotEvent;
 class SharedModuleService;
 class UpdateObserver;
 
@@ -191,7 +191,7 @@
                    Blacklist* blacklist,
                    bool autoupdate_enabled,
                    bool extensions_enabled,
-                   OneShotEvent* ready);
+                   base::OneShotEvent* ready);
 
   ~ExtensionService() override;
 
@@ -619,7 +619,7 @@
   bool extensions_enabled_ = true;
 
   // Signaled when all extensions are loaded.
-  OneShotEvent* const ready_;
+  base::OneShotEvent* const ready_;
 
   // Our extension updater, if updates are turned on.
   std::unique_ptr<ExtensionUpdater> updater_;
diff --git a/chrome/browser/extensions/extension_sync_service.cc b/chrome/browser/extensions/extension_sync_service.cc
index ce809cd..ab64cf35 100644
--- a/chrome/browser/extensions/extension_sync_service.cc
+++ b/chrome/browser/extensions/extension_sync_service.cc
@@ -4,11 +4,13 @@
 
 #include "chrome/browser/extensions/extension_sync_service.h"
 
+#include <memory>
 #include <utility>
 
 #include "base/auto_reset.h"
+#include "base/bind_helpers.h"
+#include "base/one_shot_event.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/extensions/bookmark_app_helper.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_sync_data.h"
 #include "chrome/browser/extensions/extension_sync_service_factory.h"
@@ -16,6 +18,8 @@
 #include "chrome/browser/extensions/launch_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/glue/sync_start_util.h"
+#include "chrome/browser/web_applications/components/install_manager.h"
+#include "chrome/browser/web_applications/components/web_app_provider_base.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/sync_helper.h"
@@ -31,7 +35,6 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/common/image_util.h"
-#include "extensions/common/one_shot_event.h"
 #include "extensions/common/permissions/permission_message_provider.h"
 #include "extensions/common/permissions/permissions_data.h"
 
@@ -530,44 +533,31 @@
     return;
   }
 
-  const Extension* extension =
-      extension_service()->GetInstalledExtension(extension_sync_data.id());
-
-  // Return if there are no bookmark app details that need updating.
-  if (extension &&
-      extension->non_localized_name() == extension_sync_data.name() &&
-      extension->description() ==
-          extension_sync_data.bookmark_app_description()) {
-    return;
-  }
-
-  WebApplicationInfo web_app_info;
-  web_app_info.app_url = bookmark_app_url;
-  web_app_info.title = base::UTF8ToUTF16(extension_sync_data.name());
-  web_app_info.description =
+  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  web_app_info->app_url = bookmark_app_url;
+  web_app_info->title = base::UTF8ToUTF16(extension_sync_data.name());
+  web_app_info->description =
       base::UTF8ToUTF16(extension_sync_data.bookmark_app_description());
-  web_app_info.scope = GURL(extension_sync_data.bookmark_app_scope());
-  web_app_info.theme_color = extension_sync_data.bookmark_app_theme_color();
+  web_app_info->scope = GURL(extension_sync_data.bookmark_app_scope());
+  web_app_info->theme_color = extension_sync_data.bookmark_app_theme_color();
   if (!extension_sync_data.bookmark_app_icon_color().empty()) {
     extensions::image_util::ParseHexColorString(
         extension_sync_data.bookmark_app_icon_color(),
-        &web_app_info.generated_icon_color);
+        &web_app_info->generated_icon_color);
   }
   for (const auto& icon : extension_sync_data.linked_icons()) {
     WebApplicationInfo::IconInfo icon_info;
     icon_info.url = icon.url;
     icon_info.width = icon.size;
     icon_info.height = icon.size;
-    web_app_info.icons.push_back(icon_info);
+    web_app_info->icons.push_back(icon_info);
   }
 
-#if defined(OS_CHROMEOS)
-  bool is_locally_installed = true;
-#else
-  bool is_locally_installed = extension != nullptr;
-#endif
-  CreateOrUpdateBookmarkApp(extension_service(), &web_app_info,
-                            is_locally_installed);
+  auto* provider = web_app::WebAppProviderBase::GetProviderBase(profile_);
+  DCHECK(provider);
+
+  provider->install_manager().InstallOrUpdateWebAppFromSync(
+      extension_sync_data.id(), std::move(web_app_info), base::DoNothing());
 }
 
 void ExtensionSyncService::SetSyncStartFlareForTesting(
diff --git a/chrome/browser/extensions/extension_system_impl.cc b/chrome/browser/extensions/extension_system_impl.cc
index 375d183..2b4d0cc1 100644
--- a/chrome/browser/extensions/extension_system_impl.cc
+++ b/chrome/browser/extensions/extension_system_impl.cc
@@ -411,7 +411,7 @@
 
 InfoMap* ExtensionSystemImpl::info_map() { return shared_->info_map(); }
 
-const OneShotEvent& ExtensionSystemImpl::ready() const {
+const base::OneShotEvent& ExtensionSystemImpl::ready() const {
   return shared_->ready();
 }
 
diff --git a/chrome/browser/extensions/extension_system_impl.h b/chrome/browser/extensions/extension_system_impl.h
index 925637f..98809e1 100644
--- a/chrome/browser/extensions/extension_system_impl.h
+++ b/chrome/browser/extensions/extension_system_impl.h
@@ -8,10 +8,10 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/one_shot_event.h"
 #include "build/build_config.h"
 #include "chrome/browser/extensions/extension_cookie_notifier.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/common/one_shot_event.h"
 
 class Profile;
 
@@ -70,7 +70,7 @@
       const std::string& extension_id,
       const UnloadedExtensionReason reason) override;
 
-  const OneShotEvent& ready() const override;
+  const base::OneShotEvent& ready() const override;
   ContentVerifier* content_verifier() override;  // shared
   std::unique_ptr<ExtensionSet> GetDependentExtensions(
       const Extension* extension) override;
@@ -113,7 +113,7 @@
     InfoMap* info_map();
     QuotaService* quota_service();
     AppSorting* app_sorting();
-    const OneShotEvent& ready() const { return ready_; }
+    const base::OneShotEvent& ready() const { return ready_; }
     ContentVerifier* content_verifier();
 
    private:
@@ -154,7 +154,7 @@
     std::unique_ptr<InstallGate> kiosk_app_update_install_gate_;
 #endif
 
-    OneShotEvent ready_;
+    base::OneShotEvent ready_;
   };
 
   std::unique_ptr<ExtensionCookieNotifier> cookie_notifier_;
diff --git a/chrome/browser/extensions/extension_web_ui_override_registrar.cc b/chrome/browser/extensions/extension_web_ui_override_registrar.cc
index 2e3c41c..15d2feb 100644
--- a/chrome/browser/extensions/extension_web_ui_override_registrar.cc
+++ b/chrome/browser/extensions/extension_web_ui_override_registrar.cc
@@ -6,11 +6,11 @@
 
 #include "base/bind.h"
 #include "base/lazy_instance.h"
+#include "base/one_shot_event.h"
 #include "chrome/browser/extensions/extension_web_ui.h"
 #include "chrome/browser/profiles/profile.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/common/one_shot_event.h"
 
 namespace extensions {
 
@@ -23,9 +23,8 @@
   extension_registry_observer_.Add(ExtensionRegistry::Get(context));
   ExtensionSystem::Get(context)->ready().Post(
       FROM_HERE,
-      base::Bind(&ExtensionWebUIOverrideRegistrar::OnExtensionSystemReady,
-                 weak_factory_.GetWeakPtr(),
-                 context));
+      base::BindOnce(&ExtensionWebUIOverrideRegistrar::OnExtensionSystemReady,
+                     weak_factory_.GetWeakPtr(), context));
 }
 
 ExtensionWebUIOverrideRegistrar::~ExtensionWebUIOverrideRegistrar() {
diff --git a/chrome/browser/extensions/install_verifier.cc b/chrome/browser/extensions/install_verifier.cc
index 1f4e4f2..23b122e 100644
--- a/chrome/browser/extensions/install_verifier.cc
+++ b/chrome/browser/extensions/install_verifier.cc
@@ -13,6 +13,7 @@
 #include "base/command_line.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/one_shot_event.h"
 #include "base/stl_util.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
@@ -33,7 +34,6 @@
 #include "extensions/common/extension_set.h"
 #include "extensions/common/manifest.h"
 #include "extensions/common/manifest_url_handlers.h"
-#include "extensions/common/one_shot_event.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -246,9 +246,8 @@
   }
 
   ExtensionSystem::Get(context_)->ready().Post(
-      FROM_HERE,
-      base::Bind(&InstallVerifier::MaybeBootstrapSelf,
-                 weak_factory_.GetWeakPtr()));
+      FROM_HERE, base::BindOnce(&InstallVerifier::MaybeBootstrapSelf,
+                                weak_factory_.GetWeakPtr()));
 }
 
 void InstallVerifier::VerifyAllExtensions() {
diff --git a/chrome/browser/extensions/service_worker_apitest.cc b/chrome/browser/extensions/service_worker_apitest.cc
index d8c9f5d..9e2077c 100644
--- a/chrome/browser/extensions/service_worker_apitest.cc
+++ b/chrome/browser/extensions/service_worker_apitest.cc
@@ -337,13 +337,27 @@
       << message_;
 }
 
-// Tests chrome.storage APIs.
+// Tests chrome.webRequest APIs.
 IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, WebRequest) {
   ASSERT_TRUE(
       RunExtensionTest("service_worker/worker_based_background/web_request"))
       << message_;
 }
 
+// Tests chrome.webRequest APIs in blocking mode.
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBasedBackgroundTest, WebRequestBlocking) {
+  // Try to load the page before installing the extension, which should work.
+  const GURL url = embedded_test_server()->GetURL("/extensions/test_file.html");
+  EXPECT_EQ(content::PAGE_TYPE_NORMAL, NavigateAndGetPageType(url));
+
+  // Install the extension and navigate again to the page.
+  ExtensionTestMessageListener ready_listener("ready", false);
+  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
+      "service_worker/worker_based_background/web_request_blocking")));
+  ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
+  EXPECT_EQ(content::PAGE_TYPE_ERROR, NavigateAndGetPageType(url));
+}
+
 // Listens for |message| from extension Service Worker early so that tests can
 // wait for the message on startup (and not miss it).
 class ServiceWorkerWithEarlyMessageListenerTest
diff --git a/chrome/browser/extensions/test_extension_system.cc b/chrome/browser/extensions/test_extension_system.cc
index 60b4000..eeec53c3 100644
--- a/chrome/browser/extensions/test_extension_system.cc
+++ b/chrome/browser/extensions/test_extension_system.cc
@@ -143,7 +143,7 @@
   return app_sorting_.get();
 }
 
-const OneShotEvent& TestExtensionSystem::ready() const {
+const base::OneShotEvent& TestExtensionSystem::ready() const {
   return ready_;
 }
 
diff --git a/chrome/browser/extensions/test_extension_system.h b/chrome/browser/extensions/test_extension_system.h
index 812672ec..ec7fe40b 100644
--- a/chrome/browser/extensions/test_extension_system.h
+++ b/chrome/browser/extensions/test_extension_system.h
@@ -7,8 +7,8 @@
 
 #include <memory>
 
+#include "base/one_shot_event.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/common/one_shot_event.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
@@ -71,7 +71,7 @@
   InfoMap* info_map() override;
   QuotaService* quota_service() override;
   AppSorting* app_sorting() override;
-  const OneShotEvent& ready() const override;
+  const base::OneShotEvent& ready() const override;
   ContentVerifier* content_verifier() override;
   std::unique_ptr<ExtensionSet> GetDependentExtensions(
       const Extension* extension) override;
@@ -107,7 +107,7 @@
   scoped_refptr<InfoMap> info_map_;
   std::unique_ptr<QuotaService> quota_service_;
   std::unique_ptr<AppSorting> app_sorting_;
-  OneShotEvent ready_;
+  base::OneShotEvent ready_;
   std::unique_ptr<service_manager::TestConnectorFactory> connector_factory_;
   std::unique_ptr<service_manager::Connector> connector_;
 
diff --git a/chrome/browser/feedback/feedback_dialog_utils.cc b/chrome/browser/feedback/feedback_dialog_utils.cc
index b5741543..0c85856a 100644
--- a/chrome/browser/feedback/feedback_dialog_utils.cc
+++ b/chrome/browser/feedback/feedback_dialog_utils.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/feedback/feedback_dialog_utils.h"
 
+#include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
@@ -30,8 +31,14 @@
   if (index >= 0) {
     content::WebContents* target_tab =
         browser->tab_strip_model()->GetWebContentsAt(index);
-    if (target_tab)
-      return target_tab->GetURL();
+    if (target_tab) {
+      if (browser->is_devtools()) {
+        target_tab = DevToolsWindow::AsDevToolsWindow(target_tab)
+                         ->GetInspectedWebContents();
+      }
+      if (target_tab)
+        return target_tab->GetURL();
+    }
   }
 
   return GURL();
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc
index fcc7e20c..917d3652 100644
--- a/chrome/browser/first_run/first_run.cc
+++ b/chrome/browser/first_run/first_run.cc
@@ -17,6 +17,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/no_destructor.h"
+#include "base/one_shot_event.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
@@ -57,7 +58,6 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/common/one_shot_event.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "url/gurl.h"
 
@@ -142,8 +142,9 @@
         content::BrowserContext* context =
             content::Source<Profile>(source).ptr();
         extensions::ExtensionSystem::Get(context)->ready().Post(
-            FROM_HERE, base::Bind(&FirstRunDelayedTasks::OnExtensionSystemReady,
-                                  weak_ptr_factory_.GetWeakPtr(), context));
+            FROM_HERE,
+            base::BindOnce(&FirstRunDelayedTasks::OnExtensionSystemReady,
+                           weak_ptr_factory_.GetWeakPtr(), context));
         break;
       }
       case chrome::NOTIFICATION_BROWSER_CLOSED: {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index fb1125e..4e6d9ed 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -695,6 +695,11 @@
     "expiry_milestone": 88
   },
   {
+    "name": "enable-accessibility-image-descriptions",
+    "owners": [ "//ui/accessibility/OWNERS" ],
+    "expiry_milestone": 77
+  },
+  {
     "name": "enable-accessibility-object-model",
     "owners": [ "//ui/accessibility/OWNERS" ],
     "expiry_milestone": 76
@@ -2222,6 +2227,11 @@
     "expiry_milestone": 79
   },
   {
+    "name": "kids-management-url-classification",
+    "owners": [ "alanwink", "vtrmc", "unichromeos-eng" ],
+    "expiry_milestone": 80
+  },
+  {
     "name": "language-settings",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index d18903c..c62c5a1e 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -369,6 +369,12 @@
     "Display extension options as an embedded element in chrome://extensions "
     "rather than opening a new tab.";
 
+const char kEnableAccessibilityImageDescriptionsName[] =
+    "Accessibility Image Descriptions";
+const char kEnableAccessibilityImageDescriptionsDescription[] =
+    "Enables screen reader users to request computer-generated descriptions "
+    "of unlabeled images using the page context menu.";
+
 const char kEnableAccessibilityObjectModelName[] = "Accessibility Object Model";
 const char kEnableAccessibilityObjectModelDescription[] =
     "Enables experimental support for Accessibility Object Model APIs "
@@ -1805,6 +1811,11 @@
     "Requires dedicated processes for an additional set of origins, "
     "specified as a comma-separated list.";
 
+const char kKidsManagementUrlClassificationName[] =
+    "KidsMangement Url Classification";
+const char kKidsManagementUrlClassificationDescription[] =
+    "Uses KidsManagementService to classify URLs for Kid Accounts.";
+
 const char kSiteIsolationOptOutName[] = "Disable site isolation";
 const char kSiteIsolationOptOutDescription[] =
     "Disables site isolation "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 066975bf..d3262c47 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -252,6 +252,9 @@
 extern const char kEmbeddedExtensionOptionsName[];
 extern const char kEmbeddedExtensionOptionsDescription[];
 
+extern const char kEnableAccessibilityImageDescriptionsName[];
+extern const char kEnableAccessibilityImageDescriptionsDescription[];
+
 extern const char kEnableAccessibilityObjectModelName[];
 extern const char kEnableAccessibilityObjectModelDescription[];
 
@@ -1082,6 +1085,9 @@
 extern const char kIsolateOriginsName[];
 extern const char kIsolateOriginsDescription[];
 
+extern const char kKidsManagementUrlClassificationName[];
+extern const char kKidsManagementUrlClassificationDescription[];
+
 extern const char kSiteIsolationOptOutName[];
 extern const char kSiteIsolationOptOutDescription[];
 extern const char kSiteIsolationOptOutChoiceDefault[];
diff --git a/chrome/browser/history/chrome_history_backend_client.cc b/chrome/browser/history/chrome_history_backend_client.cc
index 2bf1b26..86c5cc3 100644
--- a/chrome/browser/history/chrome_history_backend_client.cc
+++ b/chrome/browser/history/chrome_history_backend_client.cc
@@ -65,15 +65,6 @@
   return result;
 }
 
-bool ChromeHistoryBackendClient::ShouldReportDatabaseError() {
-  // TODO(shess): For now, don't report on beta or stable so as not to
-  // overwhelm the crash server.  Once the big fish are fried,
-  // consider reporting at a reduced rate on the bigger channels.
-  version_info::Channel channel = chrome::GetChannel();
-  return channel != version_info::Channel::STABLE &&
-         channel != version_info::Channel::BETA;
-}
-
 bool ChromeHistoryBackendClient::IsWebSafe(const GURL& url) {
   return content::ChildProcessSecurityPolicy::GetInstance()->IsWebSafeScheme(
       url.scheme());
diff --git a/chrome/browser/history/chrome_history_backend_client.h b/chrome/browser/history/chrome_history_backend_client.h
index c149944..f6096f4 100644
--- a/chrome/browser/history/chrome_history_backend_client.h
+++ b/chrome/browser/history/chrome_history_backend_client.h
@@ -24,7 +24,6 @@
   // history::HistoryBackendClient implementation.
   bool IsPinnedURL(const GURL& url) override;
   std::vector<history::URLAndTitle> GetPinnedURLs() override;
-  bool ShouldReportDatabaseError() override;
   bool IsWebSafe(const GURL& url) override;
 #if defined(OS_ANDROID)
   void OnHistoryBackendInitialized(
diff --git a/chrome/browser/lifetime/termination_notification.cc b/chrome/browser/lifetime/termination_notification.cc
index d050efc9b..06d4c1bb 100644
--- a/chrome/browser/lifetime/termination_notification.cc
+++ b/chrome/browser/lifetime/termination_notification.cc
@@ -65,9 +65,7 @@
     } else if (chrome::IsAttemptingShutdown()) {
       // Don't ask SessionManager to stop session if the shutdown request comes
       // from session manager.
-      chromeos::DBusThreadManager::Get()
-          ->GetSessionManagerClient()
-          ->StopSession();
+      chromeos::SessionManagerClient::Get()->StopSession();
     }
   } else {
     if (chrome::IsAttemptingShutdown()) {
diff --git a/chrome/browser/metrics/cached_metrics_profile.cc b/chrome/browser/metrics/cached_metrics_profile.cc
new file mode 100644
index 0000000..14f68e70
--- /dev/null
+++ b/chrome/browser/metrics/cached_metrics_profile.cc
@@ -0,0 +1,40 @@
+// Copyright 2019 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/metrics/cached_metrics_profile.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+
+namespace metrics {
+
+CachedMetricsProfile::CachedMetricsProfile() = default;
+
+CachedMetricsProfile::~CachedMetricsProfile() = default;
+
+Profile* CachedMetricsProfile::GetMetricsProfile() {
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  if (!profile_manager)
+    return nullptr;
+
+  // If there is a cached profile, reuse that.  However, check that it is still
+  // valid first.
+  if (cached_profile_ && profile_manager->IsValidProfile(cached_profile_))
+    return cached_profile_;
+
+  // Find a suitable profile to use, and cache it so that we continue to report
+  // statistics on the same profile.  We would simply use
+  // ProfileManager::GetLastUsedProfile(), except that that has the side effect
+  // of creating a profile if it does not yet exist.
+  cached_profile_ = profile_manager->GetProfileByPath(
+      profile_manager->GetLastUsedProfileDir(profile_manager->user_data_dir()));
+  if (cached_profile_) {
+    // Ensure that the returned profile is not an incognito profile.
+    cached_profile_ = cached_profile_->GetOriginalProfile();
+  }
+  return cached_profile_;
+}
+
+}  // namespace metrics
diff --git a/chrome/browser/metrics/cached_metrics_profile.h b/chrome/browser/metrics/cached_metrics_profile.h
new file mode 100644
index 0000000..0d8a839
--- /dev/null
+++ b/chrome/browser/metrics/cached_metrics_profile.h
@@ -0,0 +1,37 @@
+// Copyright 2019 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_METRICS_CACHED_METRICS_PROFILE_H_
+#define CHROME_BROWSER_METRICS_CACHED_METRICS_PROFILE_H_
+
+#include "base/macros.h"
+
+class Profile;
+
+namespace metrics {
+
+// Caches a user profile to use in metrics providers if needed. Uses the first
+// signed-in profile, and sticks with it until that profile becomes invalid.
+class CachedMetricsProfile {
+ public:
+  CachedMetricsProfile();
+  ~CachedMetricsProfile();
+
+  // Returns the profile for which metrics will be gathered. Once a suitable
+  // profile has been found, future calls will continue to return the same
+  // value so that reported metrics are consistent.
+  Profile* GetMetricsProfile();
+
+ private:
+  // The profile for which metrics can be gathered. Once a profile is found,
+  // its value is cached here so that GetMetricsProfile() can return a
+  // consistent value.
+  Profile* cached_profile_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(CachedMetricsProfile);
+};
+
+}  // namespace metrics
+
+#endif  // CHROME_BROWSER_METRICS_CACHED_METRICS_PROFILE_H_
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index d66726f..de04b55 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -53,7 +53,6 @@
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/tracing/background_tracing_metrics_provider.h"
 #include "chrome/browser/translate/translate_ranker_metrics_provider.h"
-#include "chrome/browser/ui/browser_otr_state.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_paths.h"
@@ -590,12 +589,8 @@
           content::CreateNetworkConnectionTrackerAsyncGetter(),
           std::make_unique<metrics::NetworkQualityEstimatorProviderImpl>()));
 
-  // Currently, we configure OmniboxMetricsProvider to not log events to UMA
-  // if there is a single incognito session visible. In the future, it may
-  // be worth revisiting this to still log events from non-incognito sessions.
   metrics_service_->RegisterMetricsProvider(
-      std::make_unique<OmniboxMetricsProvider>(
-          base::Bind(&chrome::IsIncognitoSessionActive)));
+      std::make_unique<OmniboxMetricsProvider>());
 
   metrics_service_->RegisterMetricsProvider(
       std::make_unique<ChromeStabilityMetricsProvider>(local_state));
diff --git a/chrome/browser/metrics/chrome_stability_metrics_provider.cc b/chrome/browser/metrics/chrome_stability_metrics_provider.cc
index eead1e9..a02875f 100644
--- a/chrome/browser/metrics/chrome_stability_metrics_provider.cc
+++ b/chrome/browser/metrics/chrome_stability_metrics_provider.cc
@@ -103,12 +103,9 @@
       break;
     }
 
-    case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG: {
-      const metrics::RendererHangCause* hang_cause =
-          content::Details<metrics::RendererHangCause>(details).ptr();
-      helper_.LogRendererHang(*hang_cause);
+    case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG:
+      helper_.LogRendererHang();
       break;
-    }
 
     case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
       bool was_extension_process = false;
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.cc b/chrome/browser/metrics/chromeos_metrics_provider.cc
index deb0b07..5aff41d 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider.cc
+++ b/chrome/browser/metrics/chromeos_metrics_provider.cc
@@ -11,18 +11,25 @@
 #include "base/barrier_closure.h"
 #include "base/bind.h"
 #include "base/feature_list.h"
+#include "base/hash/md5.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/sys_byteorder.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/arc/arc_optin_uma.h"
+#include "chrome/browser/chromeos/login/users/chrome_user_manager_util.h"
+#include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/metrics/cached_metrics_profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/arc/metrics/stability_metrics_manager.h"
 #include "components/metrics/metrics_service.h"
@@ -31,6 +38,7 @@
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 #include "components/user_manager/user_type.h"
+#include "components/variations/hashing.h"
 #include "components/variations/service/variations_field_trial_creator.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
@@ -98,6 +106,14 @@
   return full_hardware_class;
 }
 
+bool IsFeatureEnabled(
+    const chromeos::multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
+        feature_states_map,
+    chromeos::multidevice_setup::mojom::Feature feature) {
+  return feature_states_map.find(feature)->second ==
+         chromeos::multidevice_setup::mojom::FeatureState::kEnabledByUser;
+}
+
 }  // namespace
 
 namespace features {
@@ -112,7 +128,8 @@
 
 ChromeOSMetricsProvider::ChromeOSMetricsProvider(
     metrics::MetricsLogUploader::MetricServiceType service_type)
-    : registered_user_count_at_log_initialization_(false),
+    : cached_profile_(std::make_unique<metrics::CachedMetricsProfile>()),
+      registered_user_count_at_log_initialization_(false),
       user_count_at_log_initialization_(0),
       weak_ptr_factory_(this) {
   if (service_type == metrics::MetricsLogUploader::UMA)
@@ -203,6 +220,7 @@
 void ChromeOSMetricsProvider::ProvideSystemProfileMetrics(
     metrics::SystemProfileProto* system_profile_proto) {
   WriteBluetoothProto(system_profile_proto);
+  WriteLinkedAndroidPhoneProto(system_profile_proto);
   UpdateMultiProfileUserCount(system_profile_proto);
 
   metrics::SystemProfileProto::Hardware* hardware =
@@ -319,6 +337,41 @@
   }
 }
 
+void ChromeOSMetricsProvider::WriteLinkedAndroidPhoneProto(
+    metrics::SystemProfileProto* system_profile_proto) {
+  chromeos::multidevice_setup::MultiDeviceSetupClient* client =
+      chromeos::multidevice_setup::MultiDeviceSetupClientFactory::GetForProfile(
+          cached_profile_->GetMetricsProfile());
+
+  if (!client)
+    return;
+
+  const chromeos::multidevice_setup::MultiDeviceSetupClient::
+      HostStatusWithDevice& host_status_with_device = client->GetHostStatus();
+  if (host_status_with_device.first !=
+      chromeos::multidevice_setup::mojom::HostStatus::kHostVerified) {
+    return;
+  }
+
+  SystemProfileProto::LinkedAndroidPhoneData* linked_android_phone_data =
+      system_profile_proto->mutable_linked_android_phone_data();
+  const uint32_t hashed_name =
+      variations::HashName(host_status_with_device.second->pii_free_name());
+  linked_android_phone_data->set_phone_model_name_hash(hashed_name);
+
+  const chromeos::multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
+      feature_states_map = client->GetFeatureStates();
+  linked_android_phone_data->set_is_smartlock_enabled(IsFeatureEnabled(
+      feature_states_map,
+      chromeos::multidevice_setup::mojom::Feature::kSmartLock));
+  linked_android_phone_data->set_is_instant_tethering_enabled(IsFeatureEnabled(
+      feature_states_map,
+      chromeos::multidevice_setup::mojom::Feature::kInstantTethering));
+  linked_android_phone_data->set_is_messages_enabled(
+      IsFeatureEnabled(feature_states_map,
+                       chromeos::multidevice_setup::mojom::Feature::kMessages));
+}
+
 void ChromeOSMetricsProvider::UpdateMultiProfileUserCount(
     metrics::SystemProfileProto* system_profile_proto) {
   if (user_manager::UserManager::IsInitialized()) {
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.h b/chrome/browser/metrics/chromeos_metrics_provider.h
index 3477c7304..da949f3 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider.h
+++ b/chrome/browser/metrics/chromeos_metrics_provider.h
@@ -23,6 +23,7 @@
 }
 
 namespace metrics {
+class CachedMetricsProfile;
 class ChromeUserMetricsExtension;
 }
 
@@ -94,9 +95,16 @@
   // Called from the ProvideCurrentSessionData(...) to record UserType.
   void UpdateUserTypeUMA();
 
+  // Writes info about the linked Android phone if there is one.
+  void WriteLinkedAndroidPhoneProto(
+      metrics::SystemProfileProto* system_profile_proto);
+
   // For collecting systemwide performance data via the UMA channel.
   std::unique_ptr<metrics::ProfileProvider> profile_provider_;
 
+  // Use the first signed-in profile for profile-dependent metrics.
+  std::unique_ptr<metrics::CachedMetricsProfile> cached_profile_;
+
   // Bluetooth Adapter instance for collecting information about paired devices.
   scoped_refptr<device::BluetoothAdapter> adapter_;
 
diff --git a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
index bad9e67..1745c5c 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
@@ -12,8 +12,15 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
+#include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/components/multidevice/remote_device_test_util.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/login/login_state/login_state.h"
+#include "chromeos/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h"
+#include "chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client_impl.h"
 #include "chromeos/system/fake_statistics_provider.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/user_manager/scoped_user_manager.h"
@@ -48,6 +55,51 @@
 using bluez::FakeBluetoothGattServiceClient;
 using bluez::FakeBluetoothInputClient;
 
+namespace {
+
+class FakeMultiDeviceSetupClientImplFactory
+    : public chromeos::multidevice_setup::MultiDeviceSetupClientImpl::Factory {
+ public:
+  FakeMultiDeviceSetupClientImplFactory(
+      std::unique_ptr<chromeos::multidevice_setup::FakeMultiDeviceSetupClient>
+          fake_multidevice_setup_client)
+      : fake_multidevice_setup_client_(
+            std::move(fake_multidevice_setup_client)) {}
+
+  ~FakeMultiDeviceSetupClientImplFactory() override = default;
+
+  // chromeos::multidevice_setup::MultiDeviceSetupClientImpl::Factory:
+  // NOTE: At most, one client should be created per-test.
+  std::unique_ptr<chromeos::multidevice_setup::MultiDeviceSetupClient>
+  BuildInstance(service_manager::Connector* connector) override {
+    EXPECT_TRUE(fake_multidevice_setup_client_);
+    return std::move(fake_multidevice_setup_client_);
+  }
+
+ private:
+  std::unique_ptr<chromeos::multidevice_setup::FakeMultiDeviceSetupClient>
+      fake_multidevice_setup_client_;
+};
+
+// Wrapper around ChromeOSMetricsProvider that initializes
+// Bluetooth and hardware class in the constructor.
+class TestChromeOSMetricsProvider : public ChromeOSMetricsProvider {
+ public:
+  TestChromeOSMetricsProvider()
+      : ChromeOSMetricsProvider(metrics::MetricsLogUploader::UMA) {
+    AsyncInit(base::Bind(&TestChromeOSMetricsProvider::GetIdleCallback,
+                         base::Unretained(this)));
+    base::RunLoop().Run();
+  }
+
+  void GetIdleCallback() {
+    ASSERT_TRUE(base::RunLoop::IsRunningOnCurrentThread());
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
+  }
+};
+
+}  // namespace
+
 class ChromeOSMetricsProviderTest : public testing::Test {
  public:
   ChromeOSMetricsProviderTest() {}
@@ -86,6 +138,25 @@
     fake_bluetooth_device_client_ = static_cast<FakeBluetoothDeviceClient*>(
         BluezDBusManager::Get()->GetBluetoothDeviceClient());
 
+    chromeos::multidevice_setup::MultiDeviceSetupClientFactory::GetInstance()
+        ->SetServiceIsNULLWhileTestingForTesting(false);
+    auto fake_multidevice_setup_client = std::make_unique<
+        chromeos::multidevice_setup::FakeMultiDeviceSetupClient>();
+    fake_multidevice_setup_client_ = fake_multidevice_setup_client.get();
+    fake_multidevice_setup_client_impl_factory_ =
+        std::make_unique<FakeMultiDeviceSetupClientImplFactory>(
+            std::move(fake_multidevice_setup_client));
+    chromeos::multidevice_setup::MultiDeviceSetupClientImpl::Factory::
+        SetInstanceForTesting(
+            fake_multidevice_setup_client_impl_factory_.get());
+
+    profile_manager_ = std::make_unique<TestingProfileManager>(
+        TestingBrowserProcess::GetGlobal());
+    ASSERT_TRUE(profile_manager_->SetUp());
+    TestingProfile* profile =
+        profile_manager_->CreateTestingProfile("test_name");
+    profile_manager_->UpdateLastUser(profile);
+
     // Set statistic provider for hardware class tests.
     chromeos::system::StatisticsProvider::SetTestProvider(
         &fake_statistics_provider_);
@@ -99,13 +170,21 @@
     // Destroy the login state tracker if it was initialized.
     chromeos::LoginState::Shutdown();
     chromeos::PowerManagerClient::Shutdown();
+    chromeos::multidevice_setup::MultiDeviceSetupClientImpl::Factory::
+        SetInstanceForTesting(nullptr);
+    profile_manager_.reset();
   }
 
  protected:
   FakeBluetoothAdapterClient* fake_bluetooth_adapter_client_;
   FakeBluetoothDeviceClient* fake_bluetooth_device_client_;
+  chromeos::multidevice_setup::FakeMultiDeviceSetupClient*
+      fake_multidevice_setup_client_;
   base::test::ScopedFeatureList scoped_feature_list_;
   chromeos::system::ScopedFakeStatisticsProvider fake_statistics_provider_;
+  std::unique_ptr<TestingProfileManager> profile_manager_;
+  std::unique_ptr<FakeMultiDeviceSetupClientImplFactory>
+      fake_multidevice_setup_client_impl_factory_;
 
  private:
   content::TestBrowserThreadBundle thread_bundle_;
@@ -113,23 +192,6 @@
   DISALLOW_COPY_AND_ASSIGN(ChromeOSMetricsProviderTest);
 };
 
-// Wrapper around ChromeOSMetricsProvider that initializes
-// Bluetooth and hardware class in the constructor.
-class TestChromeOSMetricsProvider : public ChromeOSMetricsProvider {
- public:
-  TestChromeOSMetricsProvider()
-      : ChromeOSMetricsProvider(metrics::MetricsLogUploader::UMA) {
-    AsyncInit(base::Bind(&TestChromeOSMetricsProvider::GetIdleCallback,
-                         base::Unretained(this)));
-    base::RunLoop().Run();
-  }
-
-  void GetIdleCallback() {
-    ASSERT_TRUE(base::RunLoop::IsRunningOnCurrentThread());
-    base::RunLoop::QuitCurrentWhenIdleDeprecated();
-  }
-};
-
 TEST_F(ChromeOSMetricsProviderTest, MultiProfileUserCount) {
   const AccountId account_id1(AccountId::FromUserEmail("user1@example.com"));
   const AccountId account_id2(AccountId::FromUserEmail("user2@example.com"));
@@ -283,6 +345,47 @@
   EXPECT_EQ(PairedDevice::VENDOR_ID_UNKNOWN, device2.vendor_id_source());
 }
 
+TEST_F(ChromeOSMetricsProviderTest, NoLinkedAndroidPhone) {
+  fake_multidevice_setup_client_->SetHostStatusWithDevice(std::make_pair(
+      chromeos::multidevice_setup::mojom::HostStatus::kNoEligibleHosts,
+      base::nullopt /* host_device */));
+
+  TestChromeOSMetricsProvider provider;
+  metrics::SystemProfileProto system_profile;
+  provider.ProvideSystemProfileMetrics(&system_profile);
+
+  EXPECT_FALSE(system_profile.has_linked_android_phone_data());
+}
+
+TEST_F(ChromeOSMetricsProviderTest, HasLinkedAndroidPhoneAndEnabledFeatures) {
+  fake_multidevice_setup_client_->SetHostStatusWithDevice(std::make_pair(
+      chromeos::multidevice_setup::mojom::HostStatus::kHostVerified,
+      chromeos::multidevice::CreateRemoteDeviceRefForTest()));
+  fake_multidevice_setup_client_->SetFeatureState(
+      chromeos::multidevice_setup::mojom::Feature::kInstantTethering,
+      chromeos::multidevice_setup::mojom::FeatureState::kEnabledByUser);
+  fake_multidevice_setup_client_->SetFeatureState(
+      chromeos::multidevice_setup::mojom::Feature::kSmartLock,
+      chromeos::multidevice_setup::mojom::FeatureState::kEnabledByUser);
+  fake_multidevice_setup_client_->SetFeatureState(
+      chromeos::multidevice_setup::mojom::Feature::kMessages,
+      chromeos::multidevice_setup::mojom::FeatureState::kFurtherSetupRequired);
+
+  TestChromeOSMetricsProvider provider;
+  metrics::SystemProfileProto system_profile;
+  provider.ProvideSystemProfileMetrics(&system_profile);
+
+  EXPECT_TRUE(system_profile.has_linked_android_phone_data());
+  EXPECT_TRUE(
+      system_profile.linked_android_phone_data().has_phone_model_name_hash());
+  EXPECT_TRUE(system_profile.linked_android_phone_data()
+                  .is_instant_tethering_enabled());
+  EXPECT_TRUE(
+      system_profile.linked_android_phone_data().is_smartlock_enabled());
+  EXPECT_FALSE(
+      system_profile.linked_android_phone_data().is_messages_enabled());
+}
+
 TEST_F(ChromeOSMetricsProviderTest, DisableUmaShortHwClass) {
   const std::string expected_full_hw_class = "feature_disabled";
   scoped_feature_list_.InitAndDisableFeature(features::kUmaShortHWClass);
diff --git a/chrome/browser/metrics/extensions_metrics_provider.cc b/chrome/browser/metrics/extensions_metrics_provider.cc
index 715fa4c..9b28a3e0 100644
--- a/chrome/browser/metrics/extensions_metrics_provider.cc
+++ b/chrome/browser/metrics/extensions_metrics_provider.cc
@@ -344,7 +344,7 @@
 
 ExtensionsMetricsProvider::ExtensionsMetricsProvider(
     metrics::MetricsStateManager* metrics_state_manager)
-    : metrics_state_manager_(metrics_state_manager), cached_profile_(NULL) {
+    : metrics_state_manager_(metrics_state_manager) {
   DCHECK(metrics_state_manager_);
 }
 
@@ -361,29 +361,6 @@
   return output % kExtensionListBuckets;
 }
 
-Profile* ExtensionsMetricsProvider::GetMetricsProfile() {
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
-  if (!profile_manager)
-    return NULL;
-
-  // If there is a cached profile, reuse that.  However, check that it is still
-  // valid first.
-  if (cached_profile_ && profile_manager->IsValidProfile(cached_profile_))
-    return cached_profile_;
-
-  // Find a suitable profile to use, and cache it so that we continue to report
-  // statistics on the same profile.  We would simply use
-  // ProfileManager::GetLastUsedProfile(), except that that has the side effect
-  // of creating a profile if it does not yet exist.
-  cached_profile_ = profile_manager->GetProfileByPath(
-      profile_manager->GetLastUsedProfileDir(profile_manager->user_data_dir()));
-  if (cached_profile_) {
-    // Ensure that the returned profile is not an incognito profile.
-    cached_profile_ = cached_profile_->GetOriginalProfile();
-  }
-  return cached_profile_;
-}
-
 std::unique_ptr<extensions::ExtensionSet>
 ExtensionsMetricsProvider::GetInstalledExtensions(Profile* profile) {
   if (profile) {
@@ -458,7 +435,7 @@
   // per-profile.  We return the extensions installed in the primary profile.
   // In the future, we might consider reporting data about extensions in all
   // profiles.
-  Profile* profile = GetMetricsProfile();
+  Profile* profile = cached_profile_.GetMetricsProfile();
 
   std::unique_ptr<extensions::ExtensionSet> extensions(
       GetInstalledExtensions(profile));
diff --git a/chrome/browser/metrics/extensions_metrics_provider.h b/chrome/browser/metrics/extensions_metrics_provider.h
index 65f3e36..1850cb8 100644
--- a/chrome/browser/metrics/extensions_metrics_provider.h
+++ b/chrome/browser/metrics/extensions_metrics_provider.h
@@ -13,6 +13,7 @@
 
 #include "base/macros.h"
 #include "base/time/time.h"
+#include "chrome/browser/metrics/cached_metrics_profile.h"
 #include "components/metrics/metrics_provider.h"
 #include "third_party/metrics_proto/extension_install.pb.h"
 
@@ -69,11 +70,6 @@
                            uint32_t client_key);
 
  private:
-  // Returns the profile for which extensions will be gathered.  Once a
-  // suitable profile has been found, future calls will continue to return the
-  // same value so that reported extensions are consistent.
-  Profile* GetMetricsProfile();
-
   // Writes whether any loaded profiles have extensions not from the webstore.
   void ProvideOffStoreMetric(metrics::SystemProfileProto* system_profile);
 
@@ -89,10 +85,7 @@
   // The MetricsStateManager from which the client ID is obtained.
   metrics::MetricsStateManager* metrics_state_manager_;
 
-  // The profile for which extensions are gathered for the occupied bucket
-  // metric. Once a profile is found its value is cached here so that
-  // GetMetricsProfile() can return a consistent value.
-  Profile* cached_profile_;
+  metrics::CachedMetricsProfile cached_profile_;
 
   // The time of our last recorded sample.
   base::Time last_sample_time_;
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.cc b/chrome/browser/navigation_predictor/navigation_predictor.cc
index 0f1e525a..cc108976 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor.cc
@@ -808,6 +808,12 @@
   if (source_is_default_search_engine_page_)
     return base::nullopt;
 
+  if (base::GetFieldTrialParamByFeatureAsBool(
+          blink::features::kNavigationPredictor, "preconnect_skip_link_scores",
+          false)) {
+    return document_origin;
+  }
+
   // Compute preconnect score for each origins: Multiple anchor elements on
   // the webpage may point to the same origin. The preconnect score for an
   // origin is computed by taking sum of score of all anchor elements that
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
index 3cb077eb..040cc5fd 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
@@ -393,6 +393,90 @@
       NavigationPredictor::Action::kPreconnectOnVisibilityChange, 2);
 }
 
+IN_PROC_BROWSER_TEST_F(
+    NavigationPredictorBrowserTest,
+    DISABLE_ON_CHROMEOS(NoPreconnectNonSearchOnOtherHostLinks)) {
+  std::map<std::string, std::string> parameters;
+  base::test::ScopedFeatureList feature_list;
+  parameters["same_origin_preconnecting_allowed"] = "true";
+  parameters["preconnect_skip_link_scores"] = "false";
+  feature_list.InitAndEnableFeatureWithParameters(
+      blink::features::kNavigationPredictor, parameters);
+
+  base::HistogramTester histogram_tester;
+
+  // This page only has non-same host links.
+  const GURL& url = GetTestURL("/anchors_different_area.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+  base::RunLoop().RunUntilIdle();
+
+  histogram_tester.ExpectUniqueSample(
+      "NavigationPredictor.OnNonDSE.ActionTaken",
+      NavigationPredictor::Action::kNone, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(NavigationPredictorBrowserTest,
+                       DISABLE_ON_CHROMEOS(PreconnectNonSearch)) {
+  std::map<std::string, std::string> parameters;
+  base::test::ScopedFeatureList feature_list;
+  parameters["same_origin_preconnecting_allowed"] = "true";
+  parameters["preconnect_skip_link_scores"] = "true";
+  feature_list.InitAndEnableFeatureWithParameters(
+      blink::features::kNavigationPredictor, parameters);
+
+  base::HistogramTester histogram_tester;
+
+  // This page only has non-same host links.
+  const GURL& url = GetTestURL("/anchors_different_area.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+  base::RunLoop().RunUntilIdle();
+
+  histogram_tester.ExpectUniqueSample(
+      "NavigationPredictor.OnNonDSE.ActionTaken",
+      NavigationPredictor::Action::kPreconnect, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(NavigationPredictorBrowserTest,
+                       DISABLE_ON_CHROMEOS(NoPreconnectSearch)) {
+  static const char kShortName[] = "test";
+  static const char kSearchURL[] =
+      "/anchors_different_area.html?q={searchTerms}";
+
+  // Force Preconnect on
+  std::map<std::string, std::string> parameters;
+  base::test::ScopedFeatureList feature_list;
+  parameters["same_origin_preconnecting_allowed"] = "true";
+  parameters["preconnect_skip_link_scores"] = "true";
+  feature_list.InitAndEnableFeatureWithParameters(
+      blink::features::kNavigationPredictor, parameters);
+
+  // Set up default search engine.
+  TemplateURLService* model =
+      TemplateURLServiceFactory::GetForProfile(browser()->profile());
+  ASSERT_TRUE(model);
+  search_test_utils::WaitForTemplateURLServiceToLoad(model);
+  ASSERT_TRUE(model->loaded());
+
+  TemplateURLData data;
+  data.SetShortName(base::ASCIIToUTF16(kShortName));
+  data.SetKeyword(data.short_name());
+  data.SetURL(GetTestURL(kSearchURL).spec());
+
+  TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data));
+  ASSERT_TRUE(template_url);
+  model->SetUserSelectedDefaultSearchProvider(template_url);
+
+  base::HistogramTester histogram_tester;
+
+  // This page only has non-same host links.
+  const GURL& url = GetTestURL("/anchors_different_area.html?q=cats");
+  ui_test_utils::NavigateToURL(browser(), url);
+  base::RunLoop().RunUntilIdle();
+
+  histogram_tester.ExpectUniqueSample("NavigationPredictor.OnDSE.ActionTaken",
+                                      NavigationPredictor::Action::kNone, 1);
+}
+
 // Simulate a click at the anchor element.
 // Test that the action accuracy is properly recorded.
 // User clicks on an anchor element that points to same URL as the URL
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
index 7ffc890d..eea585ad 100644
--- a/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
+++ b/chrome/browser/offline_pages/prefetch/prefetch_service_factory.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/offline_pages/prefetch/prefetch_instance_id_proxy.h"
 #include "chrome/browser/offline_pages/prefetch/thumbnail_fetcher_impl.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/transition_manager/full_browser_transition_manager.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_constants.h"
 #include "components/feed/feed_feature_list.h"
@@ -41,6 +42,17 @@
 
 namespace offline_pages {
 
+namespace {
+
+void OnProfileCreated(PrefetchServiceImpl* service, Profile* profile) {
+  auto gcm_app_handler = std::make_unique<PrefetchGCMAppHandler>(
+      std::make_unique<PrefetchInstanceIDProxy>(kPrefetchingOfflinePagesAppId,
+                                                profile));
+  service->SetPrefetchGCMHandler(std::move(gcm_app_handler));
+}
+
+}  // namespace
+
 PrefetchServiceFactory::PrefetchServiceFactory()
     : BrowserContextKeyedServiceFactory(
           "OfflinePagePrefetchService",
@@ -80,10 +92,6 @@
   auto prefetch_dispatcher =
       std::make_unique<PrefetchDispatcherImpl>(profile->GetPrefs());
 
-  auto prefetch_gcm_app_handler = std::make_unique<PrefetchGCMAppHandler>(
-      std::make_unique<PrefetchInstanceIDProxy>(kPrefetchingOfflinePagesAppId,
-                                                context));
-
   auto prefetch_network_request_factory =
       std::make_unique<PrefetchNetworkRequestFactoryImpl>(
           profile->GetURLLoaderFactory(), chrome::GetChannel(), GetUserAgent(),
@@ -125,14 +133,19 @@
   auto prefetch_background_task_handler =
       std::make_unique<PrefetchBackgroundTaskHandlerImpl>(profile->GetPrefs());
 
-  return new PrefetchServiceImpl(
+  auto* service = new PrefetchServiceImpl(
       std::move(offline_metrics_collector), std::move(prefetch_dispatcher),
-      std::move(prefetch_gcm_app_handler),
       std::move(prefetch_network_request_factory), offline_page_model,
       std::move(prefetch_store), std::move(suggested_articles_observer),
       std::move(prefetch_downloader), std::move(prefetch_importer),
       std::move(prefetch_background_task_handler), std::move(thumbnail_fetcher),
       thumbnail_image_fetcher);
+
+  auto callback = base::BindOnce(&OnProfileCreated, service);
+  FullBrowserTransitionManager::Get()->RegisterCallbackOnProfileCreation(
+      profile->GetSimpleFactoryKey(), std::move(callback));
+
+  return service;
 }
 
 }  // namespace offline_pages
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
index 167cff4..4a98c64 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -679,7 +679,8 @@
     mojom::PageLoadFeaturesPtr new_features,
     const std::vector<mojom::ResourceDataUpdatePtr>& resources,
     mojom::FrameRenderDataUpdatePtr render_data,
-    mojom::CpuTimingPtr cpu_timing) {
+    mojom::CpuTimingPtr cpu_timing,
+    mojom::DeferredResourceCountsPtr new_deferred_resource_data) {
   // We may receive notifications from frames that have been navigated away
   // from. We simply ignore them.
   if (GetMainFrame(render_frame_host) != web_contents()->GetMainFrame()) {
@@ -714,7 +715,7 @@
     committed_load_->metrics_update_dispatcher()->UpdateMetrics(
         render_frame_host, std::move(timing), std::move(metadata),
         std::move(new_features), resources, std::move(render_data),
-        std::move(cpu_timing));
+        std::move(cpu_timing), std::move(new_deferred_resource_data));
   }
 }
 
@@ -724,12 +725,13 @@
     mojom::PageLoadFeaturesPtr new_features,
     std::vector<mojom::ResourceDataUpdatePtr> resources,
     mojom::FrameRenderDataUpdatePtr render_data,
-    mojom::CpuTimingPtr cpu_timing) {
+    mojom::CpuTimingPtr cpu_timing,
+    mojom::DeferredResourceCountsPtr new_deferred_resource_data) {
   content::RenderFrameHost* render_frame_host =
       page_load_metrics_binding_.GetCurrentTargetFrame();
   OnTimingUpdated(render_frame_host, std::move(timing), std::move(metadata),
                   std::move(new_features), resources, std::move(render_data),
-                  std::move(cpu_timing));
+                  std::move(cpu_timing), std::move(new_deferred_resource_data));
 }
 
 bool MetricsWebContentsObserver::ShouldTrackNavigation(
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
index f4ae56d3..023423eb 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
@@ -166,7 +166,8 @@
       mojom::PageLoadFeaturesPtr new_features,
       const std::vector<mojom::ResourceDataUpdatePtr>& resources,
       mojom::FrameRenderDataUpdatePtr render_data,
-      mojom::CpuTimingPtr cpu_timing);
+      mojom::CpuTimingPtr cpu_timing,
+      mojom::DeferredResourceCountsPtr new_deferred_resource_data);
 
   // Informs the observers of the currently committed load that the event
   // corresponding to |event_key| has occurred. This should not be called within
@@ -178,12 +179,14 @@
   friend class content::WebContentsUserData<MetricsWebContentsObserver>;
 
   // page_load_metrics::mojom::PageLoadMetrics implementation.
-  void UpdateTiming(mojom::PageLoadTimingPtr timing,
-                    mojom::PageLoadMetadataPtr metadata,
-                    mojom::PageLoadFeaturesPtr new_features,
-                    std::vector<mojom::ResourceDataUpdatePtr> resources,
-                    mojom::FrameRenderDataUpdatePtr render_data,
-                    mojom::CpuTimingPtr cpu_timing) override;
+  void UpdateTiming(
+      mojom::PageLoadTimingPtr timing,
+      mojom::PageLoadMetadataPtr metadata,
+      mojom::PageLoadFeaturesPtr new_features,
+      std::vector<mojom::ResourceDataUpdatePtr> resources,
+      mojom::FrameRenderDataUpdatePtr render_data,
+      mojom::CpuTimingPtr cpu_timing,
+      mojom::DeferredResourceCountsPtr new_deferred_resource_data) override;
 
   void HandleFailedNavigationForTrackedLoad(
       content::NavigationHandle* navigation_handle,
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
index b5b9ece..1b0071195 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer_unittest.cc
@@ -276,12 +276,13 @@
 
   void SimulateCpuTimingUpdate(const mojom::CpuTiming& timing,
                                content::RenderFrameHost* render_frame_host) {
-    observer()->OnTimingUpdated(render_frame_host, previous_timing_->Clone(),
-                                mojom::PageLoadMetadataPtr(base::in_place),
-                                mojom::PageLoadFeaturesPtr(base::in_place),
-                                std::vector<mojom::ResourceDataUpdatePtr>(),
-                                mojom::FrameRenderDataUpdatePtr(base::in_place),
-                                timing.Clone());
+    observer()->OnTimingUpdated(
+        render_frame_host, previous_timing_->Clone(),
+        mojom::PageLoadMetadataPtr(base::in_place),
+        mojom::PageLoadFeaturesPtr(base::in_place),
+        std::vector<mojom::ResourceDataUpdatePtr>(),
+        mojom::FrameRenderDataUpdatePtr(base::in_place), timing.Clone(),
+        mojom::DeferredResourceCountsPtr(base::in_place));
   }
 
   void SimulateTimingUpdate(const mojom::PageLoadTiming& timing,
@@ -299,12 +300,14 @@
       const mojom::PageLoadTiming& timing,
       content::RenderFrameHost* render_frame_host) {
     previous_timing_ = timing.Clone();
-    observer()->OnTimingUpdated(render_frame_host, timing.Clone(),
-                                mojom::PageLoadMetadataPtr(base::in_place),
-                                mojom::PageLoadFeaturesPtr(base::in_place),
-                                std::vector<mojom::ResourceDataUpdatePtr>(),
-                                mojom::FrameRenderDataUpdatePtr(base::in_place),
-                                mojom::CpuTimingPtr(base::in_place));
+    observer()->OnTimingUpdated(
+        render_frame_host, timing.Clone(),
+        mojom::PageLoadMetadataPtr(base::in_place),
+        mojom::PageLoadFeaturesPtr(base::in_place),
+        std::vector<mojom::ResourceDataUpdatePtr>(),
+        mojom::FrameRenderDataUpdatePtr(base::in_place),
+        mojom::CpuTimingPtr(base::in_place),
+        mojom::DeferredResourceCountsPtr(base::in_place));
   }
 
   void AttachObserver() {
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
index 45ad2fd..d4ff6d8 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
@@ -481,12 +481,6 @@
     return;
   PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Resources.Bytes.Ads2",
                        aggregate_frame_data_->ad_network_bytes());
-  size_t unfinished_bytes = 0;
-  for (auto const& kv :
-       GetDelegate()->GetResourceTracker().unfinished_resources())
-    unfinished_bytes += kv.second->received_data_length;
-  PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Resources.Bytes.Unfinished",
-                       unfinished_bytes);
   auto* ukm_recorder = ukm::UkmRecorder::Get();
   ukm::builders::AdPageLoad builder(source_id);
   builder.SetTotalBytes(aggregate_frame_data_->network_bytes() >> 10)
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc
index ef87cc5..a06d0b11 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc
@@ -634,10 +634,6 @@
   // and one from the ad script in the main frame.
   histogram_tester.ExpectBucketCount(
       "PageLoad.Clients.Ads.Bytes.MainFrame.Total", 2, 1);
-
-  // 4 resources loaded, one unfinished.
-  histogram_tester.ExpectBucketCount(
-      "PageLoad.Clients.Ads.Resources.Bytes.Unfinished", 1, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverResourceBrowserTest,
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
index e090d2a..954f4588 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
@@ -112,7 +112,8 @@
         page_load_metrics::mojom::PageLoadFeaturesPtr(base::in_place),
         resources,
         page_load_metrics::mojom::FrameRenderDataUpdatePtr(base::in_place),
-        page_load_metrics::mojom::CpuTimingPtr(base::in_place));
+        page_load_metrics::mojom::CpuTimingPtr(base::in_place),
+        page_load_metrics::mojom::DeferredResourceCountsPtr(base::in_place));
   }
 
   DISALLOW_COPY_AND_ASSIGN(ResourceLoadingCancellingThrottle);
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
index 3a08d2e0..b3755a3 100644
--- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
@@ -216,6 +216,8 @@
 const char kHistogramPageLoadCacheBytes[] = "PageLoad.Experimental.Bytes.Cache";
 const char kHistogramPageLoadNetworkBytesIncludingHeaders[] =
     "PageLoad.Experimental.Bytes.NetworkIncludingHeaders";
+const char kHistogramPageLoadUnfinishedBytes[] =
+    "PageLoad.Experimental.Bytes.Unfinished";
 
 const char kHistogramLoadTypeTotalBytesForwardBack[] =
     "PageLoad.Experimental.Bytes.Total.LoadType.ForwardBackNavigation";
@@ -876,6 +878,13 @@
   PAGE_BYTES_HISTOGRAM(internal::kHistogramPageLoadNetworkBytesIncludingHeaders,
                        network_bytes_including_headers_);
 
+  size_t unfinished_bytes = 0;
+  for (auto const& kv :
+       GetDelegate()->GetResourceTracker().unfinished_resources())
+    unfinished_bytes += kv.second->received_data_length;
+  PAGE_BYTES_HISTOGRAM(internal::kHistogramPageLoadUnfinishedBytes,
+                       unfinished_bytes);
+
   switch (GetPageLoadType(transition_)) {
     case LOAD_TYPE_RELOAD:
       PAGE_BYTES_HISTOGRAM(internal::kHistogramLoadTypeNetworkBytesReload,
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h
index 8776cdf..9e77820 100644
--- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h
@@ -71,6 +71,7 @@
 extern const char kHistogramPageLoadNetworkBytes[];
 extern const char kHistogramPageLoadCacheBytes[];
 extern const char kHistogramPageLoadNetworkBytesIncludingHeaders[];
+extern const char kHistogramPageLoadUnfinishedBytes[];
 
 extern const char kHistogramLoadTypeTotalBytesForwardBack[];
 extern const char kHistogramLoadTypeNetworkBytesForwardBack[];
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
index 44b3417..35a6f513 100644
--- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer_unittest.cc
@@ -1440,3 +1440,21 @@
   histogram_tester().ExpectTotalCount(
       internal::kHistogramUserGestureNavigationToForwardBack, 1);
 }
+
+TEST_F(CorePageLoadMetricsObserverTest, UnfinishedBytesRecorded) {
+  NavigateAndCommit(GURL(kDefaultTestUrl));
+
+  std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr> resources;
+  // Incomplete resource.
+  resources.push_back(
+      CreateResource(false /* was_cached */, 10 * 1024 /* delta_bytes */,
+                     0 /* encoded_body_length */, false /* is_complete */));
+  SimulateResourceDataUseUpdate(resources);
+
+  // Navigate again to force histogram recording.
+  NavigateAndCommit(GURL(kDefaultTestUrl2));
+
+  // Verify that the unfinished resource bytes are recorded.
+  histogram_tester().ExpectUniqueSample(
+      internal::kHistogramPageLoadUnfinishedBytes, 10, 1);
+}
diff --git a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc
index 133666e..e7a055f 100644
--- a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h"
 
+#include "base/metrics/field_trial_params.h"
 #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h"
 #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
@@ -12,6 +13,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/content_features.h"
 #include "services/network/public/cpp/features.h"
 #include "url/gurl.h"
 
@@ -95,6 +97,56 @@
   }
 }
 
+void DataSaverSiteBreakdownMetricsObserver::OnNewDeferredResourceCounts(
+    const page_load_metrics::mojom::DeferredResourceCounts&
+        new_deferred_resource_data) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  data_reduction_proxy::DataReductionProxySettings*
+      data_reduction_proxy_settings =
+          DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+              browser_context_);
+  if (!data_reduction_proxy_settings ||
+      !data_reduction_proxy_settings->data_reduction_proxy_service()) {
+    return;
+  }
+  DCHECK(!committed_host_.empty());
+  int64_t previously_reported_savings_that_no_longer_apply = 0;
+  int64_t new_reported_savings = 0;
+
+  int typical_frame_savings = base::GetFieldTrialParamByFeatureAsInt(
+      features::kLazyFrameLoading, "typical_frame_size_in_bytes", 50000);
+
+  int typical_image_savings = base::GetFieldTrialParamByFeatureAsInt(
+      features::kLazyFrameLoading, "typical_image_size_in_bytes", 10000);
+
+  new_reported_savings +=
+      new_deferred_resource_data.deferred_frames * typical_frame_savings;
+  new_reported_savings +=
+      new_deferred_resource_data.deferred_images * typical_image_savings;
+
+  previously_reported_savings_that_no_longer_apply +=
+      new_deferred_resource_data.frames_loaded_after_deferral *
+      typical_frame_savings;
+  previously_reported_savings_that_no_longer_apply +=
+      new_deferred_resource_data.images_loaded_after_deferral *
+      typical_image_savings;
+
+  // This can be negative if we previously recorded savings that need to be
+  // undone.
+  int64_t savings_to_report =
+      new_reported_savings - previously_reported_savings_that_no_longer_apply;
+
+  data_reduction_proxy_settings->data_reduction_proxy_service()
+      ->UpdateDataUseForHost(0, savings_to_report, committed_host_);
+  data_reduction_proxy_settings->data_reduction_proxy_service()
+      ->UpdateContentLengths(
+          0, savings_to_report,
+          data_reduction_proxy_settings->IsDataReductionProxyEnabled(),
+          data_reduction_proxy::HTTPS, std::string() /* mime_type */,
+          true /*is_user_traffic*/,
+          data_use_measurement::DataUseUserData::OTHER, 0);
+}
+
 page_load_metrics::PageLoadMetricsObserver::ObservePolicy
 DataSaverSiteBreakdownMetricsObserver::ShouldObserveMimeType(
     const std::string& mime_type) const {
diff --git a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h
index 5222ece..6c73592 100644
--- a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/sequence_checker.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
+#include "chrome/common/page_load_metrics/page_load_metrics.mojom.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 
 namespace content {
@@ -34,6 +35,9 @@
       content::RenderFrameHost* rfh,
       const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>&
           resources) override;
+  void OnNewDeferredResourceCounts(
+      const page_load_metrics::mojom::DeferredResourceCounts&
+          new_deferred_resource_data) override;
   ObservePolicy ShouldObserveMimeType(
       const std::string& mime_type) const override;
 
diff --git a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc
index b582ba13..f37e0d10 100644
--- a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc
+++ b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc
@@ -29,6 +29,7 @@
 #include "components/previews/core/previews_features.h"
 #include "components/previews/core/previews_switches.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/content_features.h"
 #include "content/public/test/browser_test_base.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -61,8 +62,9 @@
     scoped_feature_list_.InitWithFeatures(
         {data_reduction_proxy::features::
              kDataSaverSiteBreakdownUsingPageLoadMetrics,
-         previews::features::kClientLoFi},
+         previews::features::kClientLoFi, features::kLazyImageLoading},
         {});
+
     InProcessBrowserTest::SetUp();
   }
 
@@ -149,6 +151,57 @@
 }
 
 IN_PROC_BROWSER_TEST_F(DataSaverSiteBreakdownMetricsObserverBrowserTest,
+                       LazyImagesDataSavings) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  GURL test_url(
+      embedded_test_server()->GetURL("/lazyload/css-background-image.html"));
+
+  uint64_t data_savings_before_navigation =
+      GetDataSavings(test_url.HostNoBrackets());
+
+  ui_test_utils::NavigateToURL(browser(), test_url);
+  base::RunLoop().RunUntilIdle();
+
+  // Navigate away to force the histogram recording.
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+
+  // Default image size value.
+  uint64_t image_size = 10000u;
+
+  // 2 deferred images.
+  EXPECT_EQ(image_size * 2u, GetDataSavings(test_url.HostNoBrackets()) -
+                                 data_savings_before_navigation);
+}
+
+// TODO(rajendrant): Re-enable scrolling browser tests. https://crbug.com/949319
+IN_PROC_BROWSER_TEST_F(DataSaverSiteBreakdownMetricsObserverBrowserTest,
+                       DISABLED_LazyImagesDataSavingsScrollRemovesSavings) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  GURL test_url(
+      embedded_test_server()->GetURL("/lazyload/css-background-image.html"));
+
+  uint64_t data_savings_before_navigation =
+      GetDataSavings(test_url.HostNoBrackets());
+
+  ui_test_utils::NavigateToURL(browser(), test_url);
+
+  // Scroll to remove data savings by loading the images.
+  ASSERT_TRUE(content::ExecuteScript(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      "window.scrollTo(0, 10000);"));
+
+  base::RunLoop().RunUntilIdle();
+
+  // Navigate away to force the histogram recording.
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+
+  EXPECT_EQ(0u, GetDataSavings(test_url.HostNoBrackets()) -
+                    data_savings_before_navigation);
+}
+
+IN_PROC_BROWSER_TEST_F(DataSaverSiteBreakdownMetricsObserverBrowserTest,
                        NavigateToPlaintext) {
   std::unique_ptr<net::EmbeddedTestServer> plaintext_server =
       std::make_unique<net::EmbeddedTestServer>(
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc
index fbb6a01..0dd388b4 100644
--- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc
+++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.cc
@@ -76,7 +76,8 @@
     content::RenderFrameHost* rfh) {
   SimulatePageLoadTimingUpdate(
       timing, mojom::PageLoadMetadata(), mojom::PageLoadFeatures(),
-      mojom::FrameRenderDataUpdate(), mojom::CpuTiming(), rfh);
+      mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
+      mojom::DeferredResourceCounts(), rfh);
 }
 
 void PageLoadMetricsObserverTester::SimulateCpuTimingUpdate(
@@ -91,16 +92,17 @@
   page_load_metrics::InitPageLoadTimingForTest(timing.get());
   SimulatePageLoadTimingUpdate(*timing, mojom::PageLoadMetadata(),
                                mojom::PageLoadFeatures(),
-                               mojom::FrameRenderDataUpdate(), cpu_timing, rfh);
+                               mojom::FrameRenderDataUpdate(), cpu_timing,
+                               mojom::DeferredResourceCounts(), rfh);
 }
 
 void PageLoadMetricsObserverTester::SimulateTimingAndMetadataUpdate(
     const mojom::PageLoadTiming& timing,
     const mojom::PageLoadMetadata& metadata) {
-  SimulatePageLoadTimingUpdate(timing, metadata, mojom::PageLoadFeatures(),
-                               mojom::FrameRenderDataUpdate(),
-                               mojom::CpuTiming(),
-                               web_contents()->GetMainFrame());
+  SimulatePageLoadTimingUpdate(
+      timing, metadata, mojom::PageLoadFeatures(),
+      mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
+      mojom::DeferredResourceCounts(), web_contents()->GetMainFrame());
 }
 
 void PageLoadMetricsObserverTester::SimulateMetadataUpdate(
@@ -110,7 +112,8 @@
   InitPageLoadTimingForTest(&timing);
   SimulatePageLoadTimingUpdate(timing, metadata, mojom::PageLoadFeatures(),
                                mojom::FrameRenderDataUpdate(),
-                               mojom::CpuTiming(), rfh);
+                               mojom::CpuTiming(),
+                               mojom::DeferredResourceCounts(), rfh);
 }
 
 void PageLoadMetricsObserverTester::SimulateFeaturesUpdate(
@@ -118,7 +121,7 @@
   SimulatePageLoadTimingUpdate(
       mojom::PageLoadTiming(), mojom::PageLoadMetadata(), new_features,
       mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
-      web_contents()->GetMainFrame());
+      mojom::DeferredResourceCounts(), web_contents()->GetMainFrame());
 }
 
 void PageLoadMetricsObserverTester::SimulateRenderDataUpdate(
@@ -131,9 +134,9 @@
     content::RenderFrameHost* rfh) {
   mojom::PageLoadTiming timing;
   InitPageLoadTimingForTest(&timing);
-  SimulatePageLoadTimingUpdate(timing, mojom::PageLoadMetadata(),
-                               mojom::PageLoadFeatures(), render_data,
-                               mojom::CpuTiming(), rfh);
+  SimulatePageLoadTimingUpdate(
+      timing, mojom::PageLoadMetadata(), mojom::PageLoadFeatures(), render_data,
+      mojom::CpuTiming(), mojom::DeferredResourceCounts(), rfh);
 }
 
 void PageLoadMetricsObserverTester::SimulatePageLoadTimingUpdate(
@@ -142,11 +145,12 @@
     const mojom::PageLoadFeatures& new_features,
     const mojom::FrameRenderDataUpdate& render_data,
     const mojom::CpuTiming& cpu_timing,
+    const mojom::DeferredResourceCounts& new_deferred_resource_data,
     content::RenderFrameHost* rfh) {
-  observer_->OnTimingUpdated(rfh, timing.Clone(), metadata.Clone(),
-                             new_features.Clone(),
-                             std::vector<mojom::ResourceDataUpdatePtr>(),
-                             render_data.Clone(), cpu_timing.Clone());
+  observer_->OnTimingUpdated(
+      rfh, timing.Clone(), metadata.Clone(), new_features.Clone(),
+      std::vector<mojom::ResourceDataUpdatePtr>(), render_data.Clone(),
+      cpu_timing.Clone(), new_deferred_resource_data.Clone());
   // If sending the timing update caused the PageLoadMetricsUpdateDispatcher to
   // schedule a buffering timer, then fire it now so metrics are dispatched to
   // observers.
@@ -170,7 +174,8 @@
                              mojom::PageLoadFeaturesPtr(base::in_place),
                              resources,
                              mojom::FrameRenderDataUpdatePtr(base::in_place),
-                             mojom::CpuTimingPtr(base::in_place));
+                             mojom::CpuTimingPtr(base::in_place),
+                             mojom::DeferredResourceCountsPtr(base::in_place));
 }
 
 void PageLoadMetricsObserverTester::SimulateLoadedResource(
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.h b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.h
index a8b7577..ec5b8e59 100644
--- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.h
+++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_tester.h
@@ -103,6 +103,7 @@
       const mojom::PageLoadFeatures& new_features,
       const mojom::FrameRenderDataUpdate& render_data,
       const mojom::CpuTiming& cpu_timing,
+      const mojom::DeferredResourceCounts& new_deferred_resource_data,
       content::RenderFrameHost* rfh);
 
   content::WebContents* web_contents() const { return web_contents_; }
diff --git a/chrome/browser/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer.cc
deleted file mode 100644
index d0394983..0000000
--- a/chrome/browser/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2018 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/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/page_load_metrics/page_load_metrics_util.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/metrics/public/cpp/ukm_recorder.h"
-#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
-
-namespace internal {
-const char kHistogramSWRFirstContentfulPaintNetwork[] =
-    "PageLoad.Clients.StaleWhileRevalidate.PaintTiming."
-    "FirstContentfulPaint.Network";
-const char kHistogramSWRParseToFirstContentfulPaintNetwork[] =
-    "PageLoad.Clients.StaleWhileRevalidate.PaintTiming."
-    "ParseToFirstContentfulPaint.Network";
-const char kHistogramSWRFirstContentfulPaintStaleCache[] =
-    "PageLoad.Clients.StaleWhileRevalidate.PaintTiming."
-    "FirstContentfulPaint.StaleCache";
-const char kHistogramSWRParseToFirstContentfulPaintStaleCache[] =
-    "PageLoad.Clients.StaleWhileRevalidate.PaintTiming."
-    "ParseToFirstContentfulPaint.StaleCache";
-const char kHistogramSWRFirstContentfulPaintCache[] =
-    "PageLoad.Clients.StaleWhileRevalidate.PaintTiming."
-    "FirstContentfulPaint.Cache";
-const char kHistogramSWRParseToFirstContentfulPaintCache[] =
-    "PageLoad.Clients.StaleWhileRevalidate.PaintTiming."
-    "ParseToFirstContentfulPaint.Cache";
-
-}  // namespace internal
-
-void StaleWhileRevalidatePageLoadMetricsObserver::OnFirstContentfulPaintInPage(
-    const page_load_metrics::mojom::PageLoadTiming& timing,
-    const page_load_metrics::PageLoadExtraInfo& info) {
-  if (!WasStartedInForegroundOptionalEventInForeground(
-          timing.paint_timing->first_contentful_paint, info)) {
-    return;
-  }
-
-  if ((info.main_frame_metadata.behavior_flags &
-       blink::WebLoadingBehaviorFlag::
-           kStaleWhileRevalidateResourceCandidateNetworkLoad)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramSWRFirstContentfulPaintNetwork,
-                        timing.paint_timing->first_contentful_paint.value());
-    PAGE_LOAD_HISTOGRAM(
-        internal::kHistogramSWRParseToFirstContentfulPaintNetwork,
-        timing.paint_timing->first_contentful_paint.value() -
-            timing.parse_timing->parse_start.value());
-  } else if ((info.main_frame_metadata.behavior_flags &
-              blink::WebLoadingBehaviorFlag::
-                  kStaleWhileRevalidateResourceCandidateStaleCacheLoad)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramSWRFirstContentfulPaintStaleCache,
-                        timing.paint_timing->first_contentful_paint.value());
-    PAGE_LOAD_HISTOGRAM(
-        internal::kHistogramSWRParseToFirstContentfulPaintStaleCache,
-        timing.paint_timing->first_contentful_paint.value() -
-            timing.parse_timing->parse_start.value());
-  } else if ((info.main_frame_metadata.behavior_flags &
-              blink::WebLoadingBehaviorFlag::
-                  kStaleWhileRevalidateResourceCandidateCacheLoad)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramSWRFirstContentfulPaintCache,
-                        timing.paint_timing->first_contentful_paint.value());
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramSWRParseToFirstContentfulPaintCache,
-                        timing.paint_timing->first_contentful_paint.value() -
-                            timing.parse_timing->parse_start.value());
-  }
-}
diff --git a/chrome/browser/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer.h
deleted file mode 100644
index ac1f986..0000000
--- a/chrome/browser/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2018 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_PAGE_LOAD_METRICS_OBSERVERS_STALE_WHILE_REVALIDATE_PAGE_LOAD_METRICS_OBSERVER_H_
-#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_STALE_WHILE_REVALIDATE_PAGE_LOAD_METRICS_OBSERVER_H_
-
-#include "base/macros.h"
-#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
-
-namespace internal {
-
-// Expose metrics for tests.
-extern const char kHistogramSWRFirstContentfulPaintNetwork[];
-extern const char kHistogramSWRParseToFirstContentfulPaintNetwork[];
-extern const char kHistogramSWRFirstContentfulPaintStaleCache[];
-extern const char kHistogramSWRParseToFirstContentfulPaintStaleCache[];
-extern const char kHistogramSWRFirstContentfulPaintCache[];
-extern const char kHistogramSWRParseToFirstContentfulPaintCache[];
-
-}  // namespace internal
-
-class StaleWhileRevalidatePageLoadMetricsObserver
-    : public page_load_metrics::PageLoadMetricsObserver {
- public:
-  StaleWhileRevalidatePageLoadMetricsObserver() = default;
-
-  // page_load_metrics::PageLoadMetricsObserver implementation:
-  void OnFirstContentfulPaintInPage(
-      const page_load_metrics::mojom::PageLoadTiming& timing,
-      const page_load_metrics::PageLoadExtraInfo& extra_info) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(StaleWhileRevalidatePageLoadMetricsObserver);
-};
-
-#endif  // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_STALE_WHILE_REVALIDATE_PAGE_LOAD_METRICS_OBSERVER_H_
diff --git a/chrome/browser/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer_unittest.cc
deleted file mode 100644
index 3d25d444..0000000
--- a/chrome/browser/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer_unittest.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2018 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/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer.h"
-
-#include <memory>
-
-#include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h"
-#include "chrome/browser/page_load_metrics/page_load_tracker.h"
-#include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
-
-class StaleWhileRevalidatePageLoadMetricsObserverTest
-    : public page_load_metrics::PageLoadMetricsObserverTestHarness {
- protected:
-  void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override {
-    tracker->AddObserver(
-        std::make_unique<StaleWhileRevalidatePageLoadMetricsObserver>());
-  }
-};
-
-TEST_F(StaleWhileRevalidatePageLoadMetricsObserverTest, TestHistograms) {
-  struct TestCase {
-    blink::WebLoadingBehaviorFlag flag;
-    const char* fcp_histogram;
-    const char* parse_to_fcp_histogram;
-  };
-
-  TestCase test_cases[] = {
-      {blink::WebLoadingBehaviorFlag::
-           kStaleWhileRevalidateResourceCandidateNetworkLoad,
-       internal::kHistogramSWRFirstContentfulPaintNetwork,
-       internal::kHistogramSWRParseToFirstContentfulPaintNetwork},
-      {blink::WebLoadingBehaviorFlag::
-           kStaleWhileRevalidateResourceCandidateStaleCacheLoad,
-       internal::kHistogramSWRFirstContentfulPaintStaleCache,
-       internal::kHistogramSWRParseToFirstContentfulPaintStaleCache},
-      {blink::WebLoadingBehaviorFlag::
-           kStaleWhileRevalidateResourceCandidateCacheLoad,
-       internal::kHistogramSWRFirstContentfulPaintCache,
-       internal::kHistogramSWRParseToFirstContentfulPaintCache}};
-  for (const auto test_case : test_cases) {
-    base::TimeDelta parse_start = base::TimeDelta::FromMilliseconds(1);
-    base::TimeDelta contentful_paint = base::TimeDelta::FromMilliseconds(3);
-    page_load_metrics::mojom::PageLoadTiming timing;
-    page_load_metrics::InitPageLoadTimingForTest(&timing);
-    timing.navigation_start = base::Time::FromDoubleT(1);
-    timing.parse_timing->parse_start = parse_start;
-    timing.paint_timing->first_contentful_paint = contentful_paint;
-    PopulateRequiredTimingFields(&timing);
-
-    page_load_metrics::mojom::PageLoadMetadata metadata;
-    metadata.behavior_flags |= test_case.flag;
-    NavigateAndCommit(GURL("https://www.google.com/"));
-    SimulateTimingAndMetadataUpdate(timing, metadata);
-
-    histogram_tester().ExpectTotalCount(test_case.fcp_histogram, 1);
-    histogram_tester().ExpectBucketCount(test_case.fcp_histogram,
-                                         contentful_paint.InMilliseconds(), 1);
-    histogram_tester().ExpectTotalCount(test_case.parse_to_fcp_histogram, 1);
-    histogram_tester().ExpectBucketCount(
-        test_case.parse_to_fcp_histogram,
-        contentful_paint.InMilliseconds() - parse_start.InMilliseconds(), 1);
-  }
-}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
index a3a675d..fb6772ed 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -41,7 +41,6 @@
 #include "chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.h"
-#include "chrome/browser/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/tab_restore_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.h"
@@ -163,8 +162,6 @@
 #endif
     tracker->AddObserver(
         std::make_unique<LocalNetworkRequestsPageLoadMetricsObserver>());
-    tracker->AddObserver(
-        std::make_unique<StaleWhileRevalidatePageLoadMetricsObserver>());
   }
   tracker->AddObserver(
       std::make_unique<OmniboxSuggestionUsedMetricsObserver>(IsPrerendering()));
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.h b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
index 1939ee40..1b4e4732 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
@@ -499,6 +499,12 @@
       content::RenderFrameHost* rfh,
       const std::vector<mojom::ResourceDataUpdatePtr>& resources) {}
 
+  // Invoked when there is new information about lazy loaded or deferred
+  // resources. |new_deferred_resource_data| only has new deferral/lazy load
+  // events since the last update.
+  virtual void OnNewDeferredResourceCounts(
+      const mojom::DeferredResourceCounts& new_deferred_resource_data) {}
+
   // Invoked when a media element starts playing.
   virtual void MediaStartedPlaying(
       const content::WebContentsObserver::MediaPlayerInfo& video_type,
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
index ebf19dc..0eace5a6 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
@@ -437,7 +437,8 @@
     mojom::PageLoadFeaturesPtr new_features,
     const std::vector<mojom::ResourceDataUpdatePtr>& resources,
     mojom::FrameRenderDataUpdatePtr render_data,
-    mojom::CpuTimingPtr new_cpu_timing) {
+    mojom::CpuTimingPtr new_cpu_timing,
+    mojom::DeferredResourceCountsPtr new_deferred_resource_data) {
   if (render_frame_host->GetLastCommittedURL().SchemeIs(
           extensions::kExtensionScheme)) {
     // Extensions can inject child frames into a page. We don't want to track
@@ -451,6 +452,9 @@
   // both updates.
   client_->UpdateResourceDataUse(render_frame_host, resources);
 
+  // Report new deferral info.
+  client_->OnNewDeferredResourceCounts(*new_deferred_resource_data);
+
   bool is_main_frame = render_frame_host->GetParent() == nullptr;
   if (is_main_frame) {
     UpdateMainFrameMetadata(std::move(new_metadata));
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
index 99a43e06..b9771c67 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.h
@@ -122,6 +122,8 @@
         const std::vector<mojom::ResourceDataUpdatePtr>& resources) = 0;
     virtual void UpdateFrameCpuTiming(content::RenderFrameHost* rfh,
                                       const mojom::CpuTiming& timing) = 0;
+    virtual void OnNewDeferredResourceCounts(
+        const mojom::DeferredResourceCounts& new_deferred_resource_data) = 0;
   };
 
   // The |client| instance must outlive this object.
@@ -131,13 +133,15 @@
       PageLoadMetricsEmbedderInterface* embedder_interface);
   ~PageLoadMetricsUpdateDispatcher();
 
-  void UpdateMetrics(content::RenderFrameHost* render_frame_host,
-                     mojom::PageLoadTimingPtr new_timing,
-                     mojom::PageLoadMetadataPtr new_metadata,
-                     mojom::PageLoadFeaturesPtr new_features,
-                     const std::vector<mojom::ResourceDataUpdatePtr>& resources,
-                     mojom::FrameRenderDataUpdatePtr render_data,
-                     mojom::CpuTimingPtr new_cpu_timing);
+  void UpdateMetrics(
+      content::RenderFrameHost* render_frame_host,
+      mojom::PageLoadTimingPtr new_timing,
+      mojom::PageLoadMetadataPtr new_metadata,
+      mojom::PageLoadFeaturesPtr new_features,
+      const std::vector<mojom::ResourceDataUpdatePtr>& resources,
+      mojom::FrameRenderDataUpdatePtr render_data,
+      mojom::CpuTimingPtr new_cpu_timing,
+      mojom::DeferredResourceCountsPtr new_deferred_resource_data);
 
   // This method is only intended to be called for PageLoadFeatures being
   // recorded directly from the browser process. Features coming from the
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.cc b/chrome/browser/page_load_metrics/page_load_tracker.cc
index 9d9b0e4d1..c3d0f16 100644
--- a/chrome/browser/page_load_metrics/page_load_tracker.cc
+++ b/chrome/browser/page_load_metrics/page_load_tracker.cc
@@ -717,6 +717,13 @@
   }
 }
 
+void PageLoadTracker::OnNewDeferredResourceCounts(
+    const mojom::DeferredResourceCounts& new_deferred_resource_data) {
+  for (const auto& observer : observers_) {
+    observer->OnNewDeferredResourceCounts(new_deferred_resource_data);
+  }
+}
+
 void PageLoadTracker::UpdateFrameCpuTiming(content::RenderFrameHost* rfh,
                                            const mojom::CpuTiming& timing) {
   for (const auto& observer : observers_) {
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.h b/chrome/browser/page_load_metrics/page_load_tracker.h
index 844059a..26ef23e7 100644
--- a/chrome/browser/page_load_metrics/page_load_tracker.h
+++ b/chrome/browser/page_load_metrics/page_load_tracker.h
@@ -193,6 +193,8 @@
   void UpdateResourceDataUse(
       content::RenderFrameHost* rfh,
       const std::vector<mojom::ResourceDataUpdatePtr>& resources) override;
+  void OnNewDeferredResourceCounts(
+      const mojom::DeferredResourceCounts& new_deferred_resource_data) override;
   void UpdateFrameCpuTiming(content::RenderFrameHost* rfh,
                             const mojom::CpuTiming& timing) override;
 
diff --git a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.cc b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.cc
index 20cb749..ed02833 100644
--- a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.cc
+++ b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.cc
@@ -7,7 +7,7 @@
 #include <algorithm>
 
 #include "chrome/browser/performance_manager/graph/node_attached_data_impl.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 
 namespace performance_manager {
 
@@ -110,7 +110,7 @@
     return;
 
   // Update the load idle state of the page associated with this frame.
-  auto* page_node = frame_node->GetPageNode();
+  auto* page_node = frame_node->page_node();
   if (!page_node)
     return;
   UpdateLoadIdleStatePage(page_node);
@@ -128,7 +128,7 @@
 
   // Cancel any ongoing timers. A new timer will be set if necessary.
   data->idling_timer_.Stop();
-  const base::TimeTicks now = ResourceCoordinatorClock::NowTicks();
+  const base::TimeTicks now = PerformanceManagerClock::NowTicks();
 
   // Determine if the overall timeout has fired.
   if ((data->load_idle_state_ == LoadIdleState::kLoadedNotIdling ||
@@ -233,7 +233,7 @@
     return false;
 
   // Get the process CU associated with this main frame.
-  const auto* process_node = main_frame_node->GetProcessNode();
+  const auto* process_node = main_frame_node->process_node();
   if (!process_node)
     return false;
 
diff --git a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h
index 5ab9796a..847af6a 100644
--- a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h
+++ b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h
@@ -11,7 +11,7 @@
 #include "chrome/browser/performance_manager/graph/node_base.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 
 namespace performance_manager {
 
diff --git a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator_unittest.cc b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator_unittest.cc
index 54526f8..44ab8f1 100644
--- a/chrome/browser/performance_manager/decorators/page_almost_idle_decorator_unittest.cc
+++ b/chrome/browser/performance_manager/decorators/page_almost_idle_decorator_unittest.cc
@@ -15,8 +15,8 @@
 #include "chrome/browser/performance_manager/graph/mock_graphs.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -57,11 +57,13 @@
   ~PageAlmostIdleDecoratorTest() override = default;
 
   void SetUp() override {
-    auto paid = std::make_unique<PageAlmostIdleDecorator>();
-    paid_ = paid.get();
-    graph()->RegisterObserver(std::move(paid));
+    paid_ = std::make_unique<PageAlmostIdleDecorator>();
+    graph()->RegisterObserver(paid_.get());
   }
-  void TearDown() override { ResourceCoordinatorClock::ResetClockForTesting(); }
+  void TearDown() override {
+    PerformanceManagerClock::ResetClockForTesting();
+    graph()->UnregisterObserver(paid_.get());
+  }
 
   void TestPageAlmostIdleTransitions(bool timeout);
 
@@ -69,7 +71,7 @@
     return PageAlmostIdleDecorator::IsIdling(page_node);
   }
 
-  PageAlmostIdleDecorator* paid_ = nullptr;
+  std::unique_ptr<PageAlmostIdleDecorator> paid_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(PageAlmostIdleDecoratorTest);
@@ -85,7 +87,7 @@
   using Data = PageAlmostIdleDecorator::Data;
   using LIS = Data::LoadIdleState;
 
-  ResourceCoordinatorClock::SetClockForTesting(task_env().GetMockTickClock());
+  PerformanceManagerClock::SetClockForTesting(task_env().GetMockTickClock());
   task_env().FastForwardBy(base::TimeDelta::FromSeconds(1));
 
   MockSinglePageInSingleProcessGraph mock_graph(graph());
@@ -131,11 +133,11 @@
   EXPECT_EQ(LIS::kLoadedNotIdling, page_data->load_idle_state_);
   EXPECT_TRUE(page_data->idling_timer_.IsRunning());
 
-  base::TimeTicks start = ResourceCoordinatorClock::NowTicks();
+  base::TimeTicks start = PerformanceManagerClock::NowTicks();
   if (timeout) {
     // Let the timeout run down. The final state transition should occur.
     task_env().FastForwardUntilNoTasksRemain();
-    base::TimeTicks end = ResourceCoordinatorClock::NowTicks();
+    base::TimeTicks end = PerformanceManagerClock::NowTicks();
     base::TimeDelta elapsed = end - start;
     EXPECT_LE(kLoadedAndIdlingTimeout, elapsed);
     EXPECT_LE(kWaitingForIdleTimeout, elapsed);
@@ -148,7 +150,7 @@
 
     // Let the idle timer evaluate. The final state transition should occur.
     task_env().FastForwardUntilNoTasksRemain();
-    base::TimeTicks end = ResourceCoordinatorClock::NowTicks();
+    base::TimeTicks end = PerformanceManagerClock::NowTicks();
     base::TimeDelta elapsed = end - start;
     EXPECT_LE(kLoadedAndIdlingTimeout, elapsed);
     EXPECT_GT(kWaitingForIdleTimeout, elapsed);
@@ -162,8 +164,8 @@
   EXPECT_FALSE(Data::GetForTesting(page_node));
 
   // Post a navigation. The state should reset.
-  page_node->OnMainFrameNavigationCommitted(
-      ResourceCoordinatorClock::NowTicks(), 1, "https://www.example.org");
+  page_node->OnMainFrameNavigationCommitted(PerformanceManagerClock::NowTicks(),
+                                            1, GURL("https://www.example.org"));
   page_data = Data::GetForTesting(page_node);
   EXPECT_EQ(LIS::kLoadingNotStarted, page_data->load_idle_state_);
   EXPECT_FALSE(page_data->idling_timer_.IsRunning());
diff --git a/chrome/browser/performance_manager/graph/frame_node_impl.cc b/chrome/browser/performance_manager/graph/frame_node_impl.cc
index 54264ee5..08c6eed3 100644
--- a/chrome/browser/performance_manager/graph/frame_node_impl.cc
+++ b/chrome/browser/performance_manager/graph/frame_node_impl.cc
@@ -6,8 +6,8 @@
 
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 
 namespace performance_manager {
 
@@ -25,38 +25,6 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-void FrameNodeImpl::SetProcess(ProcessNodeImpl* process_node) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(NodeInGraph(process_node));
-  DCHECK(!process_node_);
-  process_node_ = process_node;
-  process_node->AddFrame(this);
-}
-
-void FrameNodeImpl::AddChildFrame(FrameNodeImpl* child_frame_node) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(child_frame_node);
-  DCHECK_EQ(this, child_frame_node->GetParentFrameNode());
-  DCHECK_NE(this, child_frame_node);
-  DCHECK(NodeInGraph(child_frame_node));
-  DCHECK(!HasFrameNodeInAncestors(child_frame_node) &&
-         !child_frame_node->HasFrameNodeInDescendants(this));
-
-  bool inserted = child_frame_nodes_.insert(child_frame_node).second;
-  DCHECK(inserted);
-}
-
-void FrameNodeImpl::RemoveChildFrame(FrameNodeImpl* child_frame_node) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(child_frame_node);
-  DCHECK_EQ(this, child_frame_node->GetParentFrameNode());
-  DCHECK_NE(this, child_frame_node);
-  DCHECK(NodeInGraph(child_frame_node));
-
-  size_t removed = child_frame_nodes_.erase(child_frame_node);
-  DCHECK_EQ(1u, removed);
-}
-
 void FrameNodeImpl::SetNetworkAlmostIdle(bool network_almost_idle) {
   network_almost_idle_.SetAndMaybeNotify(this, network_almost_idle);
 }
@@ -105,10 +73,8 @@
   resource_coordinator::mojom::InterventionPolicy old_policy =
       intervention_policy_[i];
   intervention_policy_[i] = policy;
-  if (auto* page_node = GetPageNode()) {
-    page_node->OnFrameInterventionPolicyChanged(this, intervention, old_policy,
-                                                policy);
-  }
+  page_node_->OnFrameInterventionPolicyChanged(this, intervention, old_policy,
+                                               policy);
 }
 
 void FrameNodeImpl::OnNonPersistentNotificationCreated() {
@@ -116,23 +82,59 @@
       resource_coordinator::mojom::Event::kNonPersistentNotificationCreated);
 }
 
-FrameNodeImpl* FrameNodeImpl::GetParentFrameNode() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+FrameNodeImpl* FrameNodeImpl::parent_frame_node() const {
   return parent_frame_node_;
 }
 
-PageNodeImpl* FrameNodeImpl::GetPageNode() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+PageNodeImpl* FrameNodeImpl::page_node() const {
   return page_node_;
 }
 
-ProcessNodeImpl* FrameNodeImpl::GetProcessNode() const {
+ProcessNodeImpl* FrameNodeImpl::process_node() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return process_node_;
 }
 
-bool FrameNodeImpl::IsMainFrame() const {
+const std::set<FrameNodeImpl*>& FrameNodeImpl::child_frame_nodes() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return child_frame_nodes_;
+}
+
+resource_coordinator::mojom::LifecycleState FrameNodeImpl::lifecycle_state()
+    const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return lifecycle_state_;
+}
+
+bool FrameNodeImpl::has_nonempty_beforeunload() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return has_nonempty_beforeunload_;
+}
+
+const GURL& FrameNodeImpl::url() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return url_;
+}
+
+bool FrameNodeImpl::network_almost_idle() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return network_almost_idle_.value();
+}
+
+void FrameNodeImpl::SetProcess(ProcessNodeImpl* process_node) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(NodeInGraph(process_node));
+  DCHECK(!process_node_);
+  process_node_ = process_node;
+  process_node->AddFrame(this);
+}
+
+void FrameNodeImpl::set_url(const GURL& url) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  url_ = url;
+}
+
+bool FrameNodeImpl::IsMainFrame() const {
   return !parent_frame_node_;
 }
 
@@ -172,6 +174,30 @@
   }
 }
 
+void FrameNodeImpl::AddChildFrame(FrameNodeImpl* child_frame_node) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(child_frame_node);
+  DCHECK_EQ(this, child_frame_node->parent_frame_node());
+  DCHECK_NE(this, child_frame_node);
+  DCHECK(NodeInGraph(child_frame_node));
+  DCHECK(!HasFrameNodeInAncestors(child_frame_node) &&
+         !child_frame_node->HasFrameNodeInDescendants(this));
+
+  bool inserted = child_frame_nodes_.insert(child_frame_node).second;
+  DCHECK(inserted);
+}
+
+void FrameNodeImpl::RemoveChildFrame(FrameNodeImpl* child_frame_node) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(child_frame_node);
+  DCHECK_EQ(this, child_frame_node->parent_frame_node());
+  DCHECK_NE(this, child_frame_node);
+  DCHECK(NodeInGraph(child_frame_node));
+
+  size_t removed = child_frame_nodes_.erase(child_frame_node);
+  DCHECK_EQ(1u, removed);
+}
+
 void FrameNodeImpl::JoinGraph() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
diff --git a/chrome/browser/performance_manager/graph/frame_node_impl.h b/chrome/browser/performance_manager/graph/frame_node_impl.h
index 4dbcaf54..a33e55b9 100644
--- a/chrome/browser/performance_manager/graph/frame_node_impl.h
+++ b/chrome/browser/performance_manager/graph/frame_node_impl.h
@@ -10,7 +10,8 @@
 
 #include "base/macros.h"
 #include "chrome/browser/performance_manager/graph/node_base.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
+#include "url/gurl.h"
 
 namespace performance_manager {
 
@@ -48,27 +49,30 @@
       resource_coordinator::mojom::InterventionPolicy policy) override;
   void OnNonPersistentNotificationCreated() override;
 
+  // Getters for const properties. These can be called from any thread.
+  FrameNodeImpl* parent_frame_node() const;
+  PageNodeImpl* page_node() const;
+
+  // Getters for non-const properties. These are not thread safe.
+  ProcessNodeImpl* process_node() const;
+  const std::set<FrameNodeImpl*>& child_frame_nodes() const;
+  resource_coordinator::mojom::LifecycleState lifecycle_state() const;
+  bool has_nonempty_beforeunload() const;
+  const GURL& url() const;
+  bool network_almost_idle() const;
+
+  // Setters can only be called from the performance manager sequence.
   // TODO(siggi): The process node can be provided at construction.
   void SetProcess(ProcessNodeImpl* process_node);
+  void set_url(const GURL& url);
 
-  FrameNodeImpl* GetParentFrameNode() const;
-  PageNodeImpl* GetPageNode() const;
-  ProcessNodeImpl* GetProcessNode() const;
+  // A frame is a main frame if it has no |parent_frame_node|. This can be
+  // called from any thread.
   bool IsMainFrame() const;
 
-  resource_coordinator::mojom::LifecycleState lifecycle_state() const {
-    return lifecycle_state_;
-  }
-  bool has_nonempty_beforeunload() const { return has_nonempty_beforeunload_; }
-  bool network_almost_idle() const { return network_almost_idle_.value(); }
-
   // Returns true if all intervention policies have been set for this frame.
   bool AreAllInterventionPoliciesSet() const;
 
-  const std::set<FrameNodeImpl*>& child_frame_nodes() const {
-    return child_frame_nodes_;
-  }
-
   // Sets the same policy for all intervention types in this frame. Causes
   // Page::OnFrameInterventionPolicyChanged to be invoked.
   void SetAllInterventionPoliciesForTesting(
@@ -95,12 +99,14 @@
 
   FrameNodeImpl* const parent_frame_node_;
   PageNodeImpl* const page_node_;
+
   ProcessNodeImpl* process_node_;
   std::set<FrameNodeImpl*> child_frame_nodes_;
-
   resource_coordinator::mojom::LifecycleState lifecycle_state_ =
       resource_coordinator::mojom::LifecycleState::kRunning;
   bool has_nonempty_beforeunload_ = false;
+  GURL url_;
+
   // Network is considered almost idle when there are no more than 2 network
   // connections.
   ObservedProperty::
diff --git a/chrome/browser/performance_manager/graph/frame_node_impl_unittest.cc b/chrome/browser/performance_manager/graph/frame_node_impl_unittest.cc
index 6817b1f..bda0fc1d 100644
--- a/chrome/browser/performance_manager/graph/frame_node_impl_unittest.cc
+++ b/chrome/browser/performance_manager/graph/frame_node_impl_unittest.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/performance_manager/graph/mock_graphs.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace performance_manager {
@@ -19,13 +19,13 @@
 class FrameNodeImplTest : public GraphTestHarness {
  public:
   void SetUp() override {
-    ResourceCoordinatorClock::SetClockForTesting(&clock_);
+    PerformanceManagerClock::SetClockForTesting(&clock_);
 
     // Sets a valid starting time.
     clock_.SetNowTicks(base::TimeTicks::Now());
   }
 
-  void TearDown() override { ResourceCoordinatorClock::ResetClockForTesting(); }
+  void TearDown() override { PerformanceManagerClock::ResetClockForTesting(); }
 
  protected:
   void AdvanceClock(base::TimeDelta delta) { clock_.Advance(delta); }
@@ -42,10 +42,19 @@
   auto child2_node = CreateNode<FrameNodeImpl>(page.get(), parent_node.get());
   auto child3_node = CreateNode<FrameNodeImpl>(page.get(), parent_node.get());
 
-  EXPECT_EQ(nullptr, parent_node->GetParentFrameNode());
+  EXPECT_EQ(nullptr, parent_node->parent_frame_node());
   EXPECT_EQ(2u, parent_node->child_frame_nodes().size());
-  EXPECT_EQ(parent_node.get(), child2_node->GetParentFrameNode());
-  EXPECT_EQ(parent_node.get(), child3_node->GetParentFrameNode());
+  EXPECT_EQ(parent_node.get(), child2_node->parent_frame_node());
+  EXPECT_EQ(parent_node.get(), child3_node->parent_frame_node());
+}
+
+TEST_F(FrameNodeImplTest, Url) {
+  auto page = CreateNode<PageNodeImpl>();
+  auto frame_node = CreateNode<FrameNodeImpl>(page.get(), nullptr);
+  EXPECT_TRUE(frame_node->url().is_empty());
+  const GURL url("http://www.foo.com/");
+  frame_node->set_url(url);
+  EXPECT_EQ(url, frame_node->url());
 }
 
 TEST_F(FrameNodeImplTest, RemoveChildFrame) {
@@ -56,15 +65,15 @@
 
   // Ensure correct Parent-child relationships have been established.
   EXPECT_EQ(1u, parent_frame_node->child_frame_nodes().size());
-  EXPECT_TRUE(!parent_frame_node->GetParentFrameNode());
+  EXPECT_TRUE(!parent_frame_node->parent_frame_node());
   EXPECT_EQ(0u, child_frame_node->child_frame_nodes().size());
-  EXPECT_EQ(parent_frame_node.get(), child_frame_node->GetParentFrameNode());
+  EXPECT_EQ(parent_frame_node.get(), child_frame_node->parent_frame_node());
 
   child_frame_node.reset();
 
   // Parent-child relationships should no longer exist.
   EXPECT_EQ(0u, parent_frame_node->child_frame_nodes().size());
-  EXPECT_TRUE(!parent_frame_node->GetParentFrameNode());
+  EXPECT_TRUE(!parent_frame_node->parent_frame_node());
 }
 
 TEST_F(FrameNodeImplTest, LifecycleStatesTransitions) {
@@ -76,10 +85,10 @@
   ASSERT_TRUE(mock_graph.frame->IsMainFrame());
   ASSERT_TRUE(mock_graph.other_frame->IsMainFrame());
   ASSERT_FALSE(mock_graph.child_frame->IsMainFrame());
-  ASSERT_EQ(mock_graph.child_frame->GetParentFrameNode(),
+  ASSERT_EQ(mock_graph.child_frame->parent_frame_node(),
             mock_graph.other_frame.get());
-  ASSERT_EQ(mock_graph.frame->GetPageNode(), mock_graph.page.get());
-  ASSERT_EQ(mock_graph.other_frame->GetPageNode(), mock_graph.other_page.get());
+  ASSERT_EQ(mock_graph.frame->page_node(), mock_graph.page.get());
+  ASSERT_EQ(mock_graph.other_frame->page_node(), mock_graph.other_page.get());
 
   // Freezing a child frame should not affect the page state.
   mock_graph.child_frame->SetLifecycleState(
diff --git a/chrome/browser/performance_manager/graph/graph.cc b/chrome/browser/performance_manager/graph/graph.cc
index decfd88..49b3bcc 100644
--- a/chrome/browser/performance_manager/graph/graph.cc
+++ b/chrome/browser/performance_manager/graph/graph.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
 #include "chrome/browser/performance_manager/graph/system_node_impl.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 #include "services/resource_coordinator/public/cpp/coordination_unit_types.h"
 
 namespace ukm {
@@ -30,6 +30,11 @@
 Graph::~Graph() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
+  // All observers should have been removed before the graph is deleted.
+  DCHECK(observers_.empty());
+  // All process nodes should have been removed already.
+  DCHECK(processes_by_pid_.empty());
+
   // Remove the system node from the graph, this should be the only node left.
   if (system_node_.get()) {
     RemoveNode(system_node_.get());
@@ -37,23 +42,32 @@
   }
 
   DCHECK(nodes_.empty());
-  DCHECK_EQ(0u, processes_by_pid_.size());
-
-  // Kill all the observers.
-  observers_.clear();
 }
 
-void Graph::RegisterObserver(std::unique_ptr<GraphObserver> observer) {
+void Graph::RegisterObserver(GraphObserver* observer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   observer->set_node_graph(this);
-  observers_.push_back(std::move(observer));
+  observers_.push_back(observer);
+}
+
+void Graph::UnregisterObserver(GraphObserver* observer) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  bool removed = false;
+  for (auto it = observers_.begin(); it != observers_.end(); ++it) {
+    if (*it == observer) {
+      observers_.erase(it);
+      removed = true;
+      break;
+    }
+  }
+  DCHECK(removed);
 }
 
 void Graph::OnNodeAdded(NodeBase* node) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  for (auto& observer : observers_) {
+  for (auto* observer : observers_) {
     if (observer->ShouldObserve(node)) {
-      node->AddObserver(observer.get());
+      node->AddObserver(observer);
       observer->OnNodeAdded(node);
     }
   }
diff --git a/chrome/browser/performance_manager/graph/graph.h b/chrome/browser/performance_manager/graph/graph.h
index ac68786..a049fa4 100644
--- a/chrome/browser/performance_manager/graph/graph.h
+++ b/chrome/browser/performance_manager/graph/graph.h
@@ -45,9 +45,12 @@
   }
   ukm::UkmRecorder* ukm_recorder() const { return ukm_recorder_; }
 
-  void RegisterObserver(std::unique_ptr<GraphObserver> observer);
-  void OnNodeAdded(NodeBase* node);
-  void OnBeforeNodeRemoved(NodeBase* node);
+  // Register |observer| on the graph.
+  void RegisterObserver(GraphObserver* observer);
+
+  // Unregister |observer| from observing graph changes. Note that this does not
+  // unregister |observer| from any nodes it's subscribed to.
+  void UnregisterObserver(GraphObserver* observer);
 
   SystemNodeImpl* FindOrCreateSystemNode();
   std::vector<ProcessNodeImpl*> GetAllProcessNodes();
@@ -58,11 +61,10 @@
   ProcessNodeImpl* GetProcessNodeByPid(base::ProcessId pid);
   NodeBase* GetNodeByID(const resource_coordinator::CoordinationUnitID cu_id);
 
-  std::vector<std::unique_ptr<GraphObserver>>& observers_for_testing() {
-    return observers_;
-  }
+  std::vector<GraphObserver*>& observers_for_testing() { return observers_; }
 
-  // Lifetime management functions for node owners.
+  // Management functions for node owners, any node added to the graph must be
+  // removed from the graph before it's deleted.
   void AddNewNode(NodeBase* new_node);
   void RemoveNode(NodeBase* node);
 
@@ -77,6 +79,9 @@
       std::unordered_map<resource_coordinator::CoordinationUnitID, NodeBase*>;
   using ProcessByPidMap = std::unordered_map<base::ProcessId, ProcessNodeImpl*>;
 
+  void OnNodeAdded(NodeBase* node);
+  void OnBeforeNodeRemoved(NodeBase* node);
+
   // Process PID map for use by ProcessNodeImpl.
   friend class ProcessNodeImpl;
   void BeforeProcessPidChange(ProcessNodeImpl* process,
@@ -88,7 +93,7 @@
   std::unique_ptr<SystemNodeImpl> system_node_;
   CUIDMap nodes_;
   ProcessByPidMap processes_by_pid_;
-  std::vector<std::unique_ptr<GraphObserver>> observers_;
+  std::vector<GraphObserver*> observers_;
   ukm::UkmRecorder* ukm_recorder_ = nullptr;
 
   // User data storage for the graph.
diff --git a/chrome/browser/performance_manager/graph/graph_introspector_impl.cc b/chrome/browser/performance_manager/graph/graph_introspector_impl.cc
index 6ee6f8c0..5e0ac80 100644
--- a/chrome/browser/performance_manager/graph/graph_introspector_impl.cc
+++ b/chrome/browser/performance_manager/graph/graph_introspector_impl.cc
@@ -31,7 +31,7 @@
     return false;
   }
 
-  return main_frame->GetProcessNode() == process;
+  return main_frame->process_node() == process;
 }
 
 }  // namespace
diff --git a/chrome/browser/performance_manager/graph/node_base.cc b/chrome/browser/performance_manager/graph/node_base.cc
index c7be5d7..13be796 100644
--- a/chrome/browser/performance_manager/graph/node_base.cc
+++ b/chrome/browser/performance_manager/graph/node_base.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "chrome/browser/performance_manager/graph/graph.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 #include "services/resource_coordinator/public/cpp/coordination_unit_id.h"
 
 namespace performance_manager {
diff --git a/chrome/browser/performance_manager/graph/node_base.h b/chrome/browser/performance_manager/graph/node_base.h
index 59eec51..593ccfce 100644
--- a/chrome/browser/performance_manager/graph/node_base.h
+++ b/chrome/browser/performance_manager/graph/node_base.h
@@ -15,7 +15,7 @@
 #include "base/sequence_checker.h"
 #include "chrome/browser/performance_manager/graph/graph.h"
 #include "chrome/browser/performance_manager/graph/properties.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
diff --git a/chrome/browser/performance_manager/graph/page_node_impl.cc b/chrome/browser/performance_manager/graph/page_node_impl.cc
index adce514..cdf273d3 100644
--- a/chrome/browser/performance_manager/graph/page_node_impl.cc
+++ b/chrome/browser/performance_manager/graph/page_node_impl.cc
@@ -11,8 +11,8 @@
 #include "base/time/default_tick_clock.h"
 #include "chrome/browser/performance_manager/graph/frame_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 
 namespace performance_manager {
 
@@ -44,7 +44,7 @@
 
 PageNodeImpl::PageNodeImpl(Graph* graph)
     : TypedNodeBase(graph),
-      visibility_change_time_(ResourceCoordinatorClock::NowTicks()) {
+      visibility_change_time_(PerformanceManagerClock::NowTicks()) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
@@ -55,10 +55,10 @@
 void PageNodeImpl::AddFrame(FrameNodeImpl* frame_node) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(frame_node);
-  DCHECK_EQ(this, frame_node->GetPageNode());
+  DCHECK_EQ(this, frame_node->page_node());
   DCHECK(NodeInGraph(frame_node));
 
-  if (frame_node->GetParentFrameNode() == nullptr) {
+  if (frame_node->parent_frame_node() == nullptr) {
     main_frame_nodes_.insert(frame_node);
   }
   ++frame_node_count_;
@@ -74,11 +74,11 @@
 void PageNodeImpl::RemoveFrame(FrameNodeImpl* frame_node) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(frame_node);
-  DCHECK_EQ(this, frame_node->GetPageNode());
+  DCHECK_EQ(this, frame_node->page_node());
   DCHECK(NodeInGraph(frame_node));
 
   --frame_node_count_;
-  if (frame_node->GetParentFrameNode() == nullptr) {
+  if (frame_node->parent_frame_node() == nullptr) {
     size_t removed = main_frame_nodes_.erase(frame_node);
     DCHECK_EQ(1u, removed);
   }
@@ -101,7 +101,7 @@
     // use this to determine time passed since the *previous* visibility state
     // change. They can infer the current state change time themselves via
     // NowTicks.
-    visibility_change_time_ = ResourceCoordinatorClock::NowTicks();
+    visibility_change_time_ = PerformanceManagerClock::NowTicks();
   }
 }
 
@@ -120,7 +120,7 @@
 void PageNodeImpl::OnMainFrameNavigationCommitted(
     base::TimeTicks navigation_committed_time,
     int64_t navigation_id,
-    const std::string& url) {
+    const GURL& url) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   navigation_committed_time_ = navigation_committed_time;
   main_frame_url_ = url;
@@ -133,7 +133,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::set<ProcessNodeImpl*> process_nodes;
   ForAllFrameNodes([&process_nodes](FrameNodeImpl* frame_node) -> bool {
-    if (auto* process_node = frame_node->GetProcessNode())
+    if (auto* process_node = frame_node->process_node())
       process_nodes.insert(process_node);
     return true;
   });
@@ -158,12 +158,12 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (navigation_committed_time_.is_null())
     return base::TimeDelta();
-  return ResourceCoordinatorClock::NowTicks() - navigation_committed_time_;
+  return PerformanceManagerClock::NowTicks() - navigation_committed_time_;
 }
 
 base::TimeDelta PageNodeImpl::TimeSinceLastVisibilityChange() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return ResourceCoordinatorClock::NowTicks() - visibility_change_time_;
+  return PerformanceManagerClock::NowTicks() - visibility_change_time_;
 }
 
 std::vector<FrameNodeImpl*> PageNodeImpl::GetFrameNodes() const {
@@ -190,7 +190,7 @@
     FrameNodeImpl* frame_node,
     resource_coordinator::mojom::LifecycleState old_state) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK_EQ(this, frame_node->GetPageNode());
+  DCHECK_EQ(this, frame_node->page_node());
   DCHECK_NE(old_state, frame_node->lifecycle_state());
 
   int delta = 0;
diff --git a/chrome/browser/performance_manager/graph/page_node_impl.h b/chrome/browser/performance_manager/graph/page_node_impl.h
index b7c93b6c..180a3919 100644
--- a/chrome/browser/performance_manager/graph/page_node_impl.h
+++ b/chrome/browser/performance_manager/graph/page_node_impl.h
@@ -12,8 +12,9 @@
 #include "base/time/time.h"
 #include "chrome/browser/performance_manager/graph/node_attached_data.h"
 #include "chrome/browser/performance_manager/graph/node_base.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
+#include "url/gurl.h"
 
 namespace performance_manager {
 
@@ -38,7 +39,7 @@
   void OnTitleUpdated();
   void OnMainFrameNavigationCommitted(base::TimeTicks navigation_committed_time,
                                       int64_t navigation_id,
-                                      const std::string& url);
+                                      const GURL& url);
 
   // There is no direct relationship between processes and pages. However,
   // frames are accessible by both processes and frames, so we find all of the
@@ -96,7 +97,7 @@
   }
   bool page_almost_idle() const { return page_almost_idle_.value(); }
 
-  const std::string& main_frame_url() const { return main_frame_url_; }
+  const GURL& main_frame_url() const { return main_frame_url_; }
   int64_t navigation_id() const { return navigation_id_; }
 
   // Invoked when the state of a frame in this page changes.
@@ -212,7 +213,7 @@
 
   // The URL the main frame last committed a navigation to and the unique ID of
   // the associated navigation handle.
-  std::string main_frame_url_;
+  GURL main_frame_url_;
   int64_t navigation_id_ = 0;
 
   // The aggregate intervention policy states for this page. These are
diff --git a/chrome/browser/performance_manager/graph/page_node_impl_unittest.cc b/chrome/browser/performance_manager/graph/page_node_impl_unittest.cc
index 97921342..57c3e3d 100644
--- a/chrome/browser/performance_manager/graph/page_node_impl_unittest.cc
+++ b/chrome/browser/performance_manager/graph/page_node_impl_unittest.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/performance_manager/graph/mock_graphs.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace performance_manager {
@@ -21,13 +21,13 @@
 class PageNodeImplTest : public GraphTestHarness {
  public:
   void SetUp() override {
-    ResourceCoordinatorClock::SetClockForTesting(&clock_);
+    PerformanceManagerClock::SetClockForTesting(&clock_);
 
     // Sets a valid starting time.
     clock_.SetNowTicks(base::TimeTicks::Now());
   }
 
-  void TearDown() override { ResourceCoordinatorClock::ResetClockForTesting(); }
+  void TearDown() override { PerformanceManagerClock::ResetClockForTesting(); }
 
  protected:
   void AdvanceClock(base::TimeDelta delta) { clock_.Advance(delta); }
@@ -58,7 +58,7 @@
   EXPECT_EQ(1u, page_node->GetFrameNodes().size());
   EXPECT_TRUE(
       base::ContainsValue(page_node->GetFrameNodes(), frame_node.get()));
-  EXPECT_EQ(page_node.get(), frame_node->GetPageNode());
+  EXPECT_EQ(page_node.get(), frame_node->page_node());
 
   frame_node.reset();
 
@@ -118,19 +118,20 @@
   EXPECT_TRUE(mock_graph.page->TimeSinceLastNavigation().is_zero());
 
   // 1st navigation.
+  GURL url("http://www.example.org");
   mock_graph.page->OnMainFrameNavigationCommitted(
-      ResourceCoordinatorClock::NowTicks(), 10u, "http://www.example.org");
-  EXPECT_EQ("http://www.example.org", mock_graph.page->main_frame_url());
+      PerformanceManagerClock::NowTicks(), 10u, url);
+  EXPECT_EQ(url, mock_graph.page->main_frame_url());
   EXPECT_EQ(10u, mock_graph.page->navigation_id());
   AdvanceClock(base::TimeDelta::FromSeconds(11));
   EXPECT_EQ(base::TimeDelta::FromSeconds(11),
             mock_graph.page->TimeSinceLastNavigation());
 
   // 2nd navigation.
+  url = GURL("http://www.example.org/bobcat");
   mock_graph.page->OnMainFrameNavigationCommitted(
-      ResourceCoordinatorClock::NowTicks(), 20u,
-      "http://www.example.org/bobcat");
-  EXPECT_EQ("http://www.example.org/bobcat", mock_graph.page->main_frame_url());
+      PerformanceManagerClock::NowTicks(), 20u, url);
+  EXPECT_EQ(url, mock_graph.page->main_frame_url());
   EXPECT_EQ(20u, mock_graph.page->navigation_id());
   AdvanceClock(base::TimeDelta::FromSeconds(17));
   EXPECT_EQ(base::TimeDelta::FromSeconds(17),
diff --git a/chrome/browser/performance_manager/graph/process_node_impl.cc b/chrome/browser/performance_manager/graph/process_node_impl.cc
index a4db53d..0aeb6ea 100644
--- a/chrome/browser/performance_manager/graph/process_node_impl.cc
+++ b/chrome/browser/performance_manager/graph/process_node_impl.cc
@@ -93,7 +93,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::set<PageNodeImpl*> page_nodes;
   for (auto* frame_node : frame_nodes_) {
-    if (auto* page_node = frame_node->GetPageNode())
+    if (auto* page_node = frame_node->page_node())
       page_nodes.insert(page_node);
   }
   return page_nodes;
diff --git a/chrome/browser/performance_manager/graph/process_node_impl.h b/chrome/browser/performance_manager/graph/process_node_impl.h
index 3f0edb6..b14ee6a 100644
--- a/chrome/browser/performance_manager/graph/process_node_impl.h
+++ b/chrome/browser/performance_manager/graph/process_node_impl.h
@@ -13,7 +13,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/performance_manager/graph/node_base.h"
 #include "chrome/browser/performance_manager/graph/properties.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 
 namespace performance_manager {
 
diff --git a/chrome/browser/performance_manager/graph/process_node_impl_unittest.cc b/chrome/browser/performance_manager/graph/process_node_impl_unittest.cc
index a116eee..4eb90c7 100644
--- a/chrome/browser/performance_manager/graph/process_node_impl_unittest.cc
+++ b/chrome/browser/performance_manager/graph/process_node_impl_unittest.cc
@@ -21,7 +21,10 @@
   MockGraphObserver() = default;
   virtual ~MockGraphObserver() = default;
 
-  bool ShouldObserve(const NodeBase* node) override { return true; }
+  bool ShouldObserve(const NodeBase* node) override {
+    return node->id().type ==
+           resource_coordinator::CoordinationUnitType::kProcess;
+  }
 
   MOCK_METHOD1(OnAllFramesInProcessFrozen, void(ProcessNodeImpl*));
 
@@ -38,10 +41,8 @@
 }
 
 TEST_F(ProcessNodeImplTest, OnAllFramesInProcessFrozen) {
-  auto owned_observer =
-      std::make_unique<testing::StrictMock<MockGraphObserver>>();
-  auto* observer = owned_observer.get();
-  graph()->RegisterObserver(std::move(owned_observer));
+  testing::StrictMock<MockGraphObserver> observer;
+  graph()->RegisterObserver(&observer);
   MockMultiplePagesInSingleProcessGraph mock_graph(graph());
 
   // 1/2 frame in the process is frozen.
@@ -50,23 +51,25 @@
       resource_coordinator::mojom::LifecycleState::kFrozen);
 
   // 2/2 frames in the process are frozen.
-  EXPECT_CALL(*observer, OnAllFramesInProcessFrozen(mock_graph.process.get()));
+  EXPECT_CALL(observer, OnAllFramesInProcessFrozen(mock_graph.process.get()));
   mock_graph.other_frame->SetLifecycleState(
       resource_coordinator::mojom::LifecycleState::kFrozen);
-  testing::Mock::VerifyAndClear(observer);
+  testing::Mock::VerifyAndClear(&observer);
 
   // A frame is unfrozen and frozen.
   mock_graph.frame->SetLifecycleState(
       resource_coordinator::mojom::LifecycleState::kRunning);
-  EXPECT_CALL(*observer, OnAllFramesInProcessFrozen(mock_graph.process.get()));
+  EXPECT_CALL(observer, OnAllFramesInProcessFrozen(mock_graph.process.get()));
   mock_graph.frame->SetLifecycleState(
       resource_coordinator::mojom::LifecycleState::kFrozen);
-  testing::Mock::VerifyAndClear(observer);
+  testing::Mock::VerifyAndClear(&observer);
 
   // A frozen frame is frozen again.
   // No call to OnAllFramesInProcessFrozen() is expected.
   mock_graph.frame->SetLifecycleState(
       resource_coordinator::mojom::LifecycleState::kFrozen);
+
+  graph()->UnregisterObserver(&observer);
 }
 
 TEST_F(ProcessNodeImplTest, ProcessLifeCycle) {
diff --git a/chrome/browser/performance_manager/graph/properties.h b/chrome/browser/performance_manager/graph/properties.h
index 125aa62..a46d5d9 100644
--- a/chrome/browser/performance_manager/graph/properties.h
+++ b/chrome/browser/performance_manager/graph/properties.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_PROPERTIES_H_
 #define CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_PROPERTIES_H_
 
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 
 namespace performance_manager {
 
diff --git a/chrome/browser/performance_manager/graph/system_node_impl.cc b/chrome/browser/performance_manager/graph/system_node_impl.cc
index d4aed5a4f..f660b52d 100644
--- a/chrome/browser/performance_manager/graph/system_node_impl.cc
+++ b/chrome/browser/performance_manager/graph/system_node_impl.cc
@@ -79,7 +79,7 @@
             base::TimeDelta::FromMicroseconds(frames.size());
 
         for (FrameNodeImpl* frame : frames) {
-          PageNodeImpl* page = frame->GetPageNode();
+          PageNodeImpl* page = frame->page_node();
           if (page) {
             page->set_usage_estimate_time(last_measurement_end_time_);
             page->set_cumulative_cpu_usage_estimate(
@@ -142,7 +142,7 @@
     uint64_t private_footprint_kb_sum = 0;
     const auto& frames = page->GetFrameNodes();
     for (FrameNodeImpl* frame : frames) {
-      ProcessNodeImpl* process = frame->GetProcessNode();
+      ProcessNodeImpl* process = frame->process_node();
       if (process) {
         private_footprint_kb_sum +=
             process->private_footprint_kb() / process->GetFrameNodes().size();
diff --git a/chrome/browser/performance_manager/graph/system_node_impl_unittest.cc b/chrome/browser/performance_manager/graph/system_node_impl_unittest.cc
index 32372c6..ec3070a1 100644
--- a/chrome/browser/performance_manager/graph/system_node_impl_unittest.cc
+++ b/chrome/browser/performance_manager/graph/system_node_impl_unittest.cc
@@ -11,8 +11,8 @@
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
 #include "chrome/browser/performance_manager/graph/system_node_impl.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace performance_manager {
@@ -44,13 +44,13 @@
 class SystemNodeImplTest : public GraphTestHarness {
  public:
   void SetUp() override {
-    ResourceCoordinatorClock::SetClockForTesting(&clock_);
+    PerformanceManagerClock::SetClockForTesting(&clock_);
 
     // Sets a valid starting time.
     clock_.SetNowTicks(base::TimeTicks::Now());
   }
 
-  void TearDown() override { ResourceCoordinatorClock::ResetClockForTesting(); }
+  void TearDown() override { PerformanceManagerClock::ResetClockForTesting(); }
 
  protected:
   void AdvanceClock(base::TimeDelta delta) { clock_.Advance(delta); }
diff --git a/chrome/browser/performance_manager/observers/coordination_unit_graph_observer.cc b/chrome/browser/performance_manager/observers/graph_observer.cc
similarity index 77%
rename from chrome/browser/performance_manager/observers/coordination_unit_graph_observer.cc
rename to chrome/browser/performance_manager/observers/graph_observer.cc
index 41d96e9..b83cf800 100644
--- a/chrome/browser/performance_manager/observers/coordination_unit_graph_observer.cc
+++ b/chrome/browser/performance_manager/observers/graph_observer.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 
 namespace performance_manager {
 
diff --git a/chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h b/chrome/browser/performance_manager/observers/graph_observer.h
similarity index 88%
rename from chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h
rename to chrome/browser/performance_manager/observers/graph_observer.h
index c2f72cf..4a026eb 100644
--- a/chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h
+++ b/chrome/browser/performance_manager/observers/graph_observer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_COORDINATION_UNIT_GRAPH_OBSERVER_H_
-#define CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_COORDINATION_UNIT_GRAPH_OBSERVER_H_
+#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_GRAPH_OBSERVER_H_
+#define CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_GRAPH_OBSERVER_H_
 
 #include "base/macros.h"
 #include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h"
@@ -29,8 +29,9 @@
 //
 // To create and install a new observer:
 //   (1) Derive from this class.
-//   (2) Register by calling on |graph().RegisterObserver|
-//       inside of the ResourceCoordinatorService::Create.
+//   (2) Register by calling on |graph().RegisterObserver|.
+//   (3) Before destruction, unregister by calling on
+//       |graph().UnregisterObserver|.
 //
 // TODO: Clean up the observer API, and create a wrapper version that sees
 // const Node* rather then mutable NodeImpl* types for external consumers.
@@ -87,7 +88,7 @@
 
   void set_node_graph(Graph* graph) { node_graph_ = graph; }
 
-  const Graph& graph() const { return *node_graph_; }
+  Graph* graph() const { return node_graph_; }
 
  private:
   Graph* node_graph_ = nullptr;
@@ -97,4 +98,4 @@
 
 }  // namespace performance_manager
 
-#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_COORDINATION_UNIT_GRAPH_OBSERVER_H_
+#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_GRAPH_OBSERVER_H_
diff --git a/chrome/browser/performance_manager/observers/coordination_unit_graph_observer_unittest.cc b/chrome/browser/performance_manager/observers/graph_observer_unittest.cc
similarity index 88%
rename from chrome/browser/performance_manager/observers/coordination_unit_graph_observer_unittest.cc
rename to chrome/browser/performance_manager/observers/graph_observer_unittest.cc
index 2e24edb6..d0d8c771 100644
--- a/chrome/browser/performance_manager/observers/coordination_unit_graph_observer_unittest.cc
+++ b/chrome/browser/performance_manager/observers/graph_observer_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 
 #include <memory>
 
@@ -46,11 +46,10 @@
 
 TEST_F(GraphObserverTest, CallbacksInvoked) {
   EXPECT_TRUE(graph()->observers_for_testing().empty());
-  graph()->RegisterObserver(std::make_unique<TestGraphObserver>());
+  auto observer = std::make_unique<TestGraphObserver>();
+  graph()->RegisterObserver(observer.get());
   EXPECT_EQ(1u, graph()->observers_for_testing().size());
 
-  TestGraphObserver* observer = static_cast<TestGraphObserver*>(
-      graph()->observers_for_testing()[0].get());
 
   {
     auto page_node = CreateNode<PageNodeImpl>();
@@ -63,6 +62,8 @@
   }
 
   EXPECT_EQ(2u, observer->node_destroyed_count());
+
+  graph()->UnregisterObserver(observer.get());
 }
 
 }  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/observers/metrics_collector.cc b/chrome/browser/performance_manager/observers/metrics_collector.cc
index 87933a5..05220b4 100644
--- a/chrome/browser/performance_manager/observers/metrics_collector.cc
+++ b/chrome/browser/performance_manager/observers/metrics_collector.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/performance_manager/graph/graph.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 #include "services/resource_coordinator/public/cpp/coordination_unit_id.h"
 #include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
 
@@ -81,7 +81,7 @@
     resource_coordinator::mojom::Event event) {
   if (event ==
       resource_coordinator::mojom::Event::kNonPersistentNotificationCreated) {
-    auto* page_node = frame_node->GetPageNode();
+    auto* page_node = frame_node->page_node();
     // Only record metrics while it is backgrounded.
     if (!page_node || page_node->is_visible() ||
         !ShouldReportMetrics(page_node)) {
@@ -91,7 +91,7 @@
         metrics_report_record_map_.find(page_node->id())->second;
     record.first_non_persistent_notification_created.OnSignalReceived(
         frame_node->IsMainFrame(), page_node->TimeSinceLastVisibilityChange(),
-        graph().ukm_recorder());
+        graph()->ukm_recorder());
   }
 }
 
@@ -106,7 +106,7 @@
         metrics_report_record_map_.find(page_node->id())->second;
     record.first_title_updated.OnSignalReceived(
         true, page_node->TimeSinceLastVisibilityChange(),
-        graph().ukm_recorder());
+        graph()->ukm_recorder());
   } else if (event == resource_coordinator::mojom::Event::kFaviconUpdated) {
     // Only record metrics while it is backgrounded.
     if (page_node->is_visible() || !ShouldReportMetrics(page_node))
@@ -115,7 +115,7 @@
         metrics_report_record_map_.find(page_node->id())->second;
     record.first_favicon_updated.OnSignalReceived(
         true, page_node->TimeSinceLastVisibilityChange(),
-        graph().ukm_recorder());
+        graph()->ukm_recorder());
   }
 }
 
@@ -144,7 +144,7 @@
   for (auto* frame_node : process_node->GetFrameNodes()) {
     if (!frame_node->IsMainFrame())
       continue;
-    auto* page_node = frame_node->GetPageNode();
+    auto* page_node = frame_node->page_node();
     if (!IsCollectingExpectedQueueingTimeForUkm(page_node->id()))
       continue;
     RecordExpectedQueueingTimeForUkm(page_node->id(), sample);
@@ -169,7 +169,7 @@
   state.num_unreported_eqt_measurements = 0u;
   ukm::builders::ResponsivenessMeasurement(state.ukm_source_id)
       .SetExpectedTaskQueueingDuration(expected_queueing_time.InMilliseconds())
-      .Record(graph().ukm_recorder());
+      .Record(graph()->ukm_recorder());
 }
 
 void MetricsCollector::UpdateUkmSourceIdForPage(
diff --git a/chrome/browser/performance_manager/observers/metrics_collector.h b/chrome/browser/performance_manager/observers/metrics_collector.h
index 09822fa1..d8dd14c 100644
--- a/chrome/browser/performance_manager/observers/metrics_collector.h
+++ b/chrome/browser/performance_manager/observers/metrics_collector.h
@@ -11,7 +11,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/time/time.h"
 #include "chrome/browser/performance_manager/observers/background_metrics_reporter.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 
diff --git a/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc b/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc
index 64c4a20..05072c16 100644
--- a/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc
+++ b/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc
@@ -11,8 +11,9 @@
 #include "chrome/browser/performance_manager/graph/graph_test_harness.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 #include "components/ukm/test_ukm_recorder.h"
+#include "url/gurl.h"
 
 namespace performance_manager {
 
@@ -20,6 +21,7 @@
 const char kExpectedQueueingTime[] = "ExpectedTaskQueueingDuration";
 const base::TimeDelta kTestMetricsReportDelayTimeout =
     kMetricsReportDelayTimeout + base::TimeDelta::FromSeconds(1);
+const GURL kDummyUrl("http://www.example.org");
 
 // TODO(crbug.com/759905) Enable on Windows once this bug is fixed.
 #if defined(OS_WIN)
@@ -32,18 +34,20 @@
   MAYBE_MetricsCollectorTest() : GraphTestHarness() {}
 
   void SetUp() override {
-    MetricsCollector* metrics_collector = new MetricsCollector();
-    ResourceCoordinatorClock::SetClockForTesting(&clock_);
+    metrics_collector_ = std::make_unique<MetricsCollector>();
+    PerformanceManagerClock::SetClockForTesting(&clock_);
 
     // Sets a valid starting time.
     clock_.SetNowTicks(base::TimeTicks::Now());
-    graph()->RegisterObserver(base::WrapUnique(metrics_collector));
+    graph()->RegisterObserver(metrics_collector_.get());
   }
 
-  void TearDown() override { ResourceCoordinatorClock::ResetClockForTesting(); }
+  void TearDown() override {
+    graph()->UnregisterObserver(metrics_collector_.get());
+    PerformanceManagerClock::ResetClockForTesting();
+  }
 
  protected:
-  static constexpr char kDummyUrl[] = "http://www.example.org";
   static constexpr uint64_t kDummyID = 1u;
 
   void AdvanceClock(base::TimeDelta delta) { clock_.Advance(delta); }
@@ -52,16 +56,16 @@
   base::SimpleTestTickClock clock_;
 
  private:
+  std::unique_ptr<MetricsCollector> metrics_collector_;
+
   DISALLOW_COPY_AND_ASSIGN(MAYBE_MetricsCollectorTest);
 };
 
-constexpr char MAYBE_MetricsCollectorTest::kDummyUrl[];
-
 TEST_F(MAYBE_MetricsCollectorTest, FromBackgroundedToFirstTitleUpdatedUMA) {
   auto page_node = CreateNode<PageNodeImpl>();
 
-  page_node->OnMainFrameNavigationCommitted(
-      ResourceCoordinatorClock::NowTicks(), kDummyID, kDummyUrl);
+  page_node->OnMainFrameNavigationCommitted(PerformanceManagerClock::NowTicks(),
+                                            kDummyID, kDummyUrl);
   AdvanceClock(kTestMetricsReportDelayTimeout);
 
   page_node->SetIsVisible(true);
@@ -93,8 +97,8 @@
        FromBackgroundedToFirstTitleUpdatedUMA5MinutesTimeout) {
   auto page_node = CreateNode<PageNodeImpl>();
 
-  page_node->OnMainFrameNavigationCommitted(
-      ResourceCoordinatorClock::NowTicks(), kDummyID, kDummyUrl);
+  page_node->OnMainFrameNavigationCommitted(PerformanceManagerClock::NowTicks(),
+                                            kDummyID, kDummyUrl);
   page_node->SetIsVisible(false);
   page_node->OnTitleUpdated();
   // The page is within 5 minutes after main frame navigation was committed,
@@ -112,8 +116,8 @@
   auto page_node = CreateNode<PageNodeImpl>();
   auto frame_node = CreateNode<FrameNodeImpl>(page_node.get(), nullptr);
 
-  page_node->OnMainFrameNavigationCommitted(
-      ResourceCoordinatorClock::NowTicks(), kDummyID, kDummyUrl);
+  page_node->OnMainFrameNavigationCommitted(PerformanceManagerClock::NowTicks(),
+                                            kDummyID, kDummyUrl);
   AdvanceClock(kTestMetricsReportDelayTimeout);
 
   page_node->SetIsVisible(true);
@@ -147,8 +151,8 @@
   auto page_node = CreateNode<PageNodeImpl>();
   auto frame_node = CreateNode<FrameNodeImpl>(page_node.get(), nullptr);
 
-  page_node->OnMainFrameNavigationCommitted(
-      ResourceCoordinatorClock::NowTicks(), kDummyID, kDummyUrl);
+  page_node->OnMainFrameNavigationCommitted(PerformanceManagerClock::NowTicks(),
+                                            kDummyID, kDummyUrl);
   page_node->SetIsVisible(false);
   frame_node->OnNonPersistentNotificationCreated();
   // The page is within 5 minutes after main frame navigation was committed,
@@ -164,8 +168,8 @@
 TEST_F(MAYBE_MetricsCollectorTest, FromBackgroundedToFirstFaviconUpdatedUMA) {
   auto page_node = CreateNode<PageNodeImpl>();
 
-  page_node->OnMainFrameNavigationCommitted(
-      ResourceCoordinatorClock::NowTicks(), kDummyID, kDummyUrl);
+  page_node->OnMainFrameNavigationCommitted(PerformanceManagerClock::NowTicks(),
+                                            kDummyID, kDummyUrl);
   AdvanceClock(kTestMetricsReportDelayTimeout);
 
   page_node->SetIsVisible(true);
@@ -197,8 +201,8 @@
        FromBackgroundedToFirstFaviconUpdatedUMA5MinutesTimeout) {
   auto page_node = CreateNode<PageNodeImpl>();
 
-  page_node->OnMainFrameNavigationCommitted(
-      ResourceCoordinatorClock::NowTicks(), kDummyID, kDummyUrl);
+  page_node->OnMainFrameNavigationCommitted(PerformanceManagerClock::NowTicks(),
+                                            kDummyID, kDummyUrl);
   page_node->SetIsVisible(false);
   page_node->OnFaviconUpdated();
   // The page is within 5 minutes after main frame navigation was committed,
@@ -226,8 +230,8 @@
   GURL url = GURL("https://google.com/foobar");
   ukm_recorder.UpdateSourceURL(id, url);
   page_node->SetUkmSourceId(id);
-  page_node->OnMainFrameNavigationCommitted(
-      ResourceCoordinatorClock::NowTicks(), kDummyID, kDummyUrl);
+  page_node->OnMainFrameNavigationCommitted(PerformanceManagerClock::NowTicks(),
+                                            kDummyID, kDummyUrl);
 
   for (int count = 1; count < kDefaultFrequencyUkmEQTReported; ++count) {
     process_node->SetExpectedTaskQueueingDuration(
diff --git a/chrome/browser/performance_manager/observers/page_signal_generator_impl.cc b/chrome/browser/performance_manager/observers/page_signal_generator_impl.cc
index 914284f3..94d6d1e 100644
--- a/chrome/browser/performance_manager/observers/page_signal_generator_impl.cc
+++ b/chrome/browser/performance_manager/observers/page_signal_generator_impl.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
 #include "chrome/browser/performance_manager/graph/system_node_impl.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 #include "services/service_manager/public/cpp/bind_source_info.h"
 
 namespace performance_manager {
@@ -38,7 +38,10 @@
 
 PageSignalGeneratorImpl::PageSignalGeneratorImpl() = default;
 
-PageSignalGeneratorImpl::~PageSignalGeneratorImpl() = default;
+PageSignalGeneratorImpl::~PageSignalGeneratorImpl() {
+  // Unregister from the system node, as it may outlive this instance.
+  graph()->FindOrCreateSystemNode()->RemoveObserver(this);
+}
 
 void PageSignalGeneratorImpl::AddReceiver(
     resource_coordinator::mojom::PageSignalReceiverPtr receiver) {
@@ -89,7 +92,7 @@
       resource_coordinator::mojom::Event::kNonPersistentNotificationCreated)
     return;
 
-  auto* page_node = frame_node->GetPageNode();
+  auto* page_node = frame_node->page_node();
   if (!page_node)
     return;
 
@@ -176,7 +179,7 @@
   for (auto* frame_node : process_node->GetFrameNodes()) {
     if (!frame_node->IsMainFrame())
       continue;
-    auto* page_node = frame_node->GetPageNode();
+    auto* page_node = frame_node->page_node();
     DispatchPageSignal(page_node,
                        &resource_coordinator::mojom::PageSignalReceiver::
                            SetExpectedTaskQueueingDuration,
@@ -211,13 +214,13 @@
         (receiver->*m)(
             resource_coordinator::PageNavigationIdentity{
                 page_node->id(), page_node->navigation_id(),
-                page_node->main_frame_url()},
+                page_node->main_frame_url().spec()},
             std::forward<Params>(params)...);
       });
 }
 
 void PageSignalGeneratorImpl::PageData::Reset() {
-  last_state_change = ResourceCoordinatorClock::NowTicks();
+  last_state_change = PerformanceManagerClock::NowTicks();
   performance_estimate_issued = false;
 }
 
diff --git a/chrome/browser/performance_manager/observers/page_signal_generator_impl.h b/chrome/browser/performance_manager/observers/page_signal_generator_impl.h
index f97de4b..2b93910 100644
--- a/chrome/browser/performance_manager/observers/page_signal_generator_impl.h
+++ b/chrome/browser/performance_manager/observers/page_signal_generator_impl.h
@@ -10,7 +10,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/timer/timer.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/interface_ptr_set.h"
 #include "services/resource_coordinator/public/mojom/page_signal.mojom.h"
diff --git a/chrome/browser/performance_manager/observers/page_signal_generator_impl_unittest.cc b/chrome/browser/performance_manager/observers/page_signal_generator_impl_unittest.cc
index c95cb89..83ddb6c 100644
--- a/chrome/browser/performance_manager/observers/page_signal_generator_impl_unittest.cc
+++ b/chrome/browser/performance_manager/observers/page_signal_generator_impl_unittest.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/performance_manager/graph/mock_graphs.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
@@ -89,26 +89,29 @@
 class PageSignalGeneratorImplTest : public GraphTestHarness {
  protected:
   void SetUp() override {
-    std::unique_ptr<MockPageSignalGeneratorImpl> psg(
-        std::make_unique<MockPageSignalGeneratorImpl>());
+    page_signal_generator_ = std::make_unique<MockPageSignalGeneratorImpl>();
 
-    page_signal_generator_ = psg.get();
+    graph()->RegisterObserver(page_signal_generator_.get());
 
-    // The graph takes ownership of the psg.
-    graph()->RegisterObserver(std::move(psg));
-
+    page_almost_idle_decorator_ = std::make_unique<PageAlmostIdleDecorator>();
     // Ensure the PageAlmostIdleDecorator is installed as we depend on state
     // transition driven by it.
-    graph()->RegisterObserver(std::make_unique<PageAlmostIdleDecorator>());
+    graph()->RegisterObserver(page_almost_idle_decorator_.get());
   }
-  void TearDown() override { ResourceCoordinatorClock::ResetClockForTesting(); }
+  void TearDown() override {
+    PerformanceManagerClock::ResetClockForTesting();
+    graph()->UnregisterObserver(page_almost_idle_decorator_.get());
+    graph()->UnregisterObserver(page_signal_generator_.get());
+  }
 
   MockPageSignalGeneratorImpl* page_signal_generator() {
-    return page_signal_generator_;
+    return page_signal_generator_.get();
   }
 
  private:
-  MockPageSignalGeneratorImpl* page_signal_generator_ = nullptr;
+  std::unique_ptr<MockPageSignalGeneratorImpl> page_signal_generator_;
+  std::unique_ptr<PageAlmostIdleDecorator> page_almost_idle_decorator_;
+
   std::unique_ptr<base::test::ScopedFeatureList> feature_list_;
 };
 
@@ -263,7 +266,7 @@
 }  // namespace
 
 TEST_F(PageSignalGeneratorImplTest, OnLoadTimePerformanceEstimate) {
-  ResourceCoordinatorClock::SetClockForTesting(task_env().GetMockTickClock());
+  PerformanceManagerClock::SetClockForTesting(task_env().GetMockTickClock());
 
   MockSinglePageInSingleProcessGraph mock_graph(graph());
 
@@ -278,16 +281,16 @@
 
   // Ensure that a navigation resets the performance measurement state.
   base::TimeTicks navigation_committed_time =
-      ResourceCoordinatorClock::NowTicks();
+      PerformanceManagerClock::NowTicks();
   page_node->OnMainFrameNavigationCommitted(navigation_committed_time, 1,
-                                            "https://www.google.com/");
+                                            GURL("https://www.google.com/"));
   page_node->SetPageAlmostIdleForTesting(false);
   task_env().FastForwardUntilNoTasksRemain();
   EXPECT_FALSE(page_node->page_almost_idle());
   page_node->SetPageAlmostIdleForTesting(true);
   EXPECT_TRUE(page_node->page_almost_idle());
 
-  base::TimeTicks event_time = ResourceCoordinatorClock::NowTicks();
+  base::TimeTicks event_time = PerformanceManagerClock::NowTicks();
 
   // A measurement that starts before an initiating state change should not
   // result in a notification.
@@ -305,11 +308,12 @@
 
   {
     base::RunLoop run_loop;
-    EXPECT_CALL(mock_receiver, OnLoadTimePerformanceEstimate(
-                                   IdentityMatches(mock_graph.page->id(), 1u,
-                                                   "https://www.google.com/"),
-                                   event_time - navigation_committed_time,
-                                   base::TimeDelta::FromMicroseconds(15), 150))
+    EXPECT_CALL(mock_receiver,
+                OnLoadTimePerformanceEstimate(
+                    IdentityMatches(mock_graph.page->id(), 1u,
+                                    GURL("https://www.google.com/")),
+                    event_time - navigation_committed_time,
+                    base::TimeDelta::FromMicroseconds(15), 150))
         .WillOnce(
             ::testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
     run_loop.Run();
@@ -324,16 +328,16 @@
   task_env().FastForwardBy(base::TimeDelta::FromSeconds(1));
 
   // Make sure a second run around the state machine generates a second event.
-  navigation_committed_time = ResourceCoordinatorClock::NowTicks();
+  navigation_committed_time = PerformanceManagerClock::NowTicks();
   page_node->OnMainFrameNavigationCommitted(navigation_committed_time, 2,
-                                            "https://example.org/bobcat");
+                                            GURL("https://example.org/bobcat"));
   page_node->SetPageAlmostIdleForTesting(false);
   task_env().FastForwardUntilNoTasksRemain();
   EXPECT_FALSE(page_node->page_almost_idle());
   page_node->SetPageAlmostIdleForTesting(true);
   EXPECT_TRUE(page_node->page_almost_idle());
 
-  event_time = ResourceCoordinatorClock::NowTicks();
+  event_time = PerformanceManagerClock::NowTicks();
 
   // Dispatch another measurement and verify another notification is fired.
   mock_graph.system->DistributeMeasurementBatch(CreateMeasurementBatch(
@@ -344,7 +348,7 @@
     EXPECT_CALL(mock_receiver,
                 OnLoadTimePerformanceEstimate(
                     IdentityMatches(mock_graph.page->id(), 2u,
-                                    "https://example.org/bobcat"),
+                                    GURL("https://example.org/bobcat")),
                     event_time - navigation_committed_time,
                     base::TimeDelta::FromMicroseconds(25), 250))
         .WillOnce(
diff --git a/chrome/browser/performance_manager/observers/working_set_trimmer_win.h b/chrome/browser/performance_manager/observers/working_set_trimmer_win.h
index 4299c93..a45eca6 100644
--- a/chrome/browser/performance_manager/observers/working_set_trimmer_win.h
+++ b/chrome/browser/performance_manager/observers/working_set_trimmer_win.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_WORKING_SET_TRIMMER_WIN_H_
 
 #include "base/macros.h"
-#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
+#include "chrome/browser/performance_manager/observers/graph_observer.h"
 
 namespace performance_manager {
 
diff --git a/chrome/browser/performance_manager/performance_manager.cc b/chrome/browser/performance_manager/performance_manager.cc
index f361680..246c16f 100644
--- a/chrome/browser/performance_manager/performance_manager.cc
+++ b/chrome/browser/performance_manager/performance_manager.cc
@@ -46,6 +46,9 @@
 
 PerformanceManager::~PerformanceManager() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  for (auto& observer : observers_)
+    graph_.UnregisterObserver(observer.get());
 }
 
 // static
@@ -103,6 +106,12 @@
                                 base::Unretained(this), std::move(nodes)));
 }
 
+void PerformanceManager::RegisterObserver(
+    std::unique_ptr<GraphObserver> observer) {
+  graph_.RegisterObserver(observer.get());
+  observers_.push_back(std::move(observer));
+}
+
 void PerformanceManager::PostBindInterface(
     const std::string& interface_name,
     mojo::ScopedMessagePipeHandle message_pipe) {
@@ -190,14 +199,14 @@
   interface_registry_.AddInterface(
       base::BindRepeating(&PageSignalGeneratorImpl::BindToInterface,
                           base::Unretained(page_signal_generator_impl.get())));
-  graph_.RegisterObserver(std::move(page_signal_generator_impl));
+  RegisterObserver(std::move(page_signal_generator_impl));
 
-  graph_.RegisterObserver(std::make_unique<MetricsCollector>());
-  graph_.RegisterObserver(std::make_unique<PageAlmostIdleDecorator>());
+  RegisterObserver(std::make_unique<MetricsCollector>());
+  RegisterObserver(std::make_unique<PageAlmostIdleDecorator>());
 
 #if defined(OS_WIN)
   if (base::FeatureList::IsEnabled(features::kEmptyWorkingSet))
-    graph_.RegisterObserver(std::make_unique<WorkingSetTrimmer>());
+    RegisterObserver(std::make_unique<WorkingSetTrimmer>());
 #endif
 
   interface_registry_.AddInterface(base::BindRepeating(
diff --git a/chrome/browser/performance_manager/performance_manager.h b/chrome/browser/performance_manager/performance_manager.h
index a57494c5..f2bc634 100644
--- a/chrome/browser/performance_manager/performance_manager.h
+++ b/chrome/browser/performance_manager/performance_manager.h
@@ -91,6 +91,7 @@
 
   PerformanceManager();
 
+  void RegisterObserver(std::unique_ptr<GraphObserver> observer);
   void PostBindInterface(const std::string& interface_name,
                          mojo::ScopedMessagePipeHandle message_pipe);
 
@@ -118,6 +119,10 @@
   // The performance task runner.
   const scoped_refptr<base::SequencedTaskRunner> task_runner_;
   Graph graph_;
+
+  // The registered graph observers.
+  std::vector<std::unique_ptr<GraphObserver>> observers_;
+
   CoordinationUnitIntrospectorImpl introspector_;
 
   // Provided to |graph_|.
diff --git a/chrome/browser/performance_manager/resource_coordinator_clock.cc b/chrome/browser/performance_manager/performance_manager_clock.cc
similarity index 72%
rename from chrome/browser/performance_manager/resource_coordinator_clock.cc
rename to chrome/browser/performance_manager/performance_manager_clock.cc
index a68a0d51..3440de0 100644
--- a/chrome/browser/performance_manager/resource_coordinator_clock.cc
+++ b/chrome/browser/performance_manager/performance_manager_clock.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 
 #include "base/time/tick_clock.h"
 
@@ -17,20 +17,20 @@
 
 }  // namespace
 
-base::TimeTicks ResourceCoordinatorClock::NowTicks() {
+base::TimeTicks PerformanceManagerClock::NowTicks() {
   return g_tick_clock_for_testing() ? g_tick_clock_for_testing()->NowTicks()
                                     : base::TimeTicks::Now();
 }
 
-const base::TickClock* ResourceCoordinatorClock::GetClockForTesting() {
+const base::TickClock* PerformanceManagerClock::GetClockForTesting() {
   return g_tick_clock_for_testing();
 }
 
-void ResourceCoordinatorClock::ResetClockForTesting() {
+void PerformanceManagerClock::ResetClockForTesting() {
   g_tick_clock_for_testing() = nullptr;
 }
 
-void ResourceCoordinatorClock::SetClockForTesting(
+void PerformanceManagerClock::SetClockForTesting(
     const base::TickClock* tick_clock) {
   DCHECK(!g_tick_clock_for_testing());
   g_tick_clock_for_testing() = tick_clock;
diff --git a/chrome/browser/performance_manager/resource_coordinator_clock.h b/chrome/browser/performance_manager/performance_manager_clock.h
similarity index 67%
rename from chrome/browser/performance_manager/resource_coordinator_clock.h
rename to chrome/browser/performance_manager/performance_manager_clock.h
index df1c22c..bb911ea5 100644
--- a/chrome/browser/performance_manager/resource_coordinator_clock.h
+++ b/chrome/browser/performance_manager/performance_manager_clock.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_RESOURCE_COORDINATOR_CLOCK_H_
-#define CHROME_BROWSER_PERFORMANCE_MANAGER_RESOURCE_COORDINATOR_CLOCK_H_
+#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_CLOCK_H_
+#define CHROME_BROWSER_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_CLOCK_H_
 
 #include <memory>
 
@@ -16,10 +16,10 @@
 
 namespace performance_manager {
 
-// ResourceCoordinatorClock provides timing methods that resource_coordinator/
+// PerformanceManagerClock provides timing methods that the performance manager
 // needs at a central place, and facilitates testing across components when
 // clock manipulation is needed.
-class ResourceCoordinatorClock {
+class PerformanceManagerClock {
  public:
   // Returns time from the testing TickClock if set; otherwise returns time from
   // TimeTicks::Now().
@@ -33,9 +33,9 @@
   static void ResetClockForTesting();
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ResourceCoordinatorClock);
+  DISALLOW_COPY_AND_ASSIGN(PerformanceManagerClock);
 };
 
 }  // namespace performance_manager
 
-#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_RESOURCE_COORDINATOR_CLOCK_H_
+#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_CLOCK_H_
diff --git a/chrome/browser/performance_manager/performance_manager_tab_helper.cc b/chrome/browser/performance_manager/performance_manager_tab_helper.cc
index c1148891..6ddcd77 100644
--- a/chrome/browser/performance_manager/performance_manager_tab_helper.cc
+++ b/chrome/browser/performance_manager/performance_manager_tab_helper.cc
@@ -156,35 +156,43 @@
 
 void PerformanceManagerTabHelper::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
-  if (!navigation_handle->HasCommitted() ||
-      navigation_handle->IsSameDocument()) {
+  if (!navigation_handle->HasCommitted())
     return;
-  }
 
   // Grab the current time up front, as this is as close as we'll get to the
   // original commit time.
   base::TimeTicks navigation_committed_time = base::TimeTicks::Now();
 
+  // Find the associated frame node.
   content::RenderFrameHost* render_frame_host =
       navigation_handle->GetRenderFrameHost();
-  // Make sure the hierarchical structure is constructed before sending signal
-  // to the performance manager.
+  auto frame_it = frames_.find(render_frame_host);
   // TODO(siggi): Ideally this would be a DCHECK, but it seems it's possible
   //     to get a DidFinishNavigation notification for a deleted frame with
   //     the network service.
-  auto it = frames_.find(render_frame_host);
-  if (it != frames_.end()) {
-    if (navigation_handle->IsInMainFrame()) {
-      OnMainFrameNavigation(navigation_handle->GetNavigationId());
-      performance_manager_->task_runner()->PostTask(
-          FROM_HERE,
-          base::BindOnce(&PageNodeImpl::OnMainFrameNavigationCommitted,
-                         base::Unretained(page_node_.get()),
-                         navigation_committed_time,
-                         navigation_handle->GetNavigationId(),
-                         navigation_handle->GetURL().spec()));
-    }
+  if (frame_it == frames_.end())
+    return;
+  auto* frame_node = frame_it->second.get();
+
+  // Notify the frame of the committed URL.
+  GURL url = navigation_handle->GetURL();
+  performance_manager_->task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(&FrameNodeImpl::set_url,
+                                base::Unretained(frame_node), url));
+
+  if (navigation_handle->IsSameDocument() ||
+      !navigation_handle->IsInMainFrame()) {
+    return;
   }
+
+  // Make sure the hierarchical structure is constructed before sending signal
+  // to the performance manager.
+  OnMainFrameNavigation(navigation_handle->GetNavigationId());
+  performance_manager_->task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(&PageNodeImpl::OnMainFrameNavigationCommitted,
+                                base::Unretained(page_node_.get()),
+                                navigation_committed_time,
+                                navigation_handle->GetNavigationId(), url));
 }
 
 void PerformanceManagerTabHelper::TitleWasSet(content::NavigationEntry* entry) {
diff --git a/chrome/browser/performance_manager/webui_graph_dump_impl.cc b/chrome/browser/performance_manager/webui_graph_dump_impl.cc
index 5ee6ba3..960d0df 100644
--- a/chrome/browser/performance_manager/webui_graph_dump_impl.cc
+++ b/chrome/browser/performance_manager/webui_graph_dump_impl.cc
@@ -55,10 +55,10 @@
 
       frame_info->id = frame->id().id;
 
-      auto* parent_frame = frame->GetParentFrameNode();
+      auto* parent_frame = frame->parent_frame_node();
       frame_info->parent_frame_id = parent_frame ? parent_frame->id().id : 0;
 
-      auto* process = frame->GetProcessNode();
+      auto* process = frame->process_node();
       frame_info->process_id = process ? process->id().id : 0;
 
       graph->frames.push_back(std::move(frame_info));
@@ -73,7 +73,7 @@
           resource_coordinator::mojom::WebUIPageInfo::New();
 
       page_info->id = page->id().id;
-      page_info->main_frame_url = page->main_frame_url();
+      page_info->main_frame_url = page->main_frame_url().spec();
 
       auto* main_frame = page->GetMainFrameNode();
       page_info->main_frame_id = main_frame ? main_frame->id().id : 0;
diff --git a/chrome/browser/performance_manager/webui_graph_dump_impl_unittest.cc b/chrome/browser/performance_manager/webui_graph_dump_impl_unittest.cc
index e570e511..ddeb11d 100644
--- a/chrome/browser/performance_manager/webui_graph_dump_impl_unittest.cc
+++ b/chrome/browser/performance_manager/webui_graph_dump_impl_unittest.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/performance_manager/graph/graph_test_harness.h"
 #include "chrome/browser/performance_manager/graph/mock_graphs.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
-#include "chrome/browser/performance_manager/resource_coordinator_clock.h"
+#include "chrome/browser/performance_manager/performance_manager_clock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace performance_manager {
@@ -20,9 +20,9 @@
   Graph graph;
   MockMultiplePagesWithMultipleProcessesGraph mock_graph(&graph);
 
-  base::TimeTicks now = ResourceCoordinatorClock::NowTicks();
+  base::TimeTicks now = PerformanceManagerClock::NowTicks();
 
-  constexpr char kExampleUrl[] = "http://www.example.org";
+  const GURL kExampleUrl("http://www.example.org");
   mock_graph.page->OnMainFrameNavigationCommitted(now, 1, kExampleUrl);
   mock_graph.other_page->OnMainFrameNavigationCommitted(now, 2, kExampleUrl);
 
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index e555b0c..8bf7b1ca 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -217,8 +217,7 @@
   DISALLOW_COPY_AND_ASSIGN(FaviconUpdateWatcher);
 };
 
-// Constants used in the test HTML files.
-const char* kReadyTitle = "READY";
+// Constant used in the test HTML files.
 const char* kPassTitle = "PASS";
 
 std::string CreateClientRedirect(const std::string& dest_url) {
@@ -1047,38 +1046,6 @@
       "Prerender.websame_PrefetchTTFCP.Warm.Cacheable.Visible", 0);
 }
 
-// Checks that pending prerenders launch and receive proper event treatment.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPagePending) {
-  std::unique_ptr<TestPrerender> prerender = PrerenderTestURL(
-      "/prerender/prerender_page_pending.html", FINAL_STATUS_USED, 1);
-
-  // Navigate to the prerender.
-  std::unique_ptr<TestPrerender> prerender2 =
-      ExpectPrerender(FINAL_STATUS_USED);
-  NavigateToDestURL();
-  // Abort early if the original prerender didn't swap, so as not to hang.
-  ASSERT_FALSE(prerender->contents());
-
-  // Wait for the new prerender to be ready.
-  prerender2->WaitForStart();
-  prerender2->WaitForLoads(1);
-
-  const GURL prerender_page_url =
-      embedded_test_server()->GetURL("/prerender/prerender_page.html");
-  EXPECT_FALSE(IsEmptyPrerenderLinkManager());
-  EXPECT_TRUE(GetPrerenderContentsFor(prerender_page_url));
-
-  // Now navigate to our target page.
-  NavigationOrSwapObserver swap_observer(current_browser()->tab_strip_model(),
-                                         GetActiveWebContents());
-  ui_test_utils::NavigateToURLWithDisposition(
-      current_browser(), prerender_page_url, WindowOpenDisposition::CURRENT_TAB,
-      ui_test_utils::BROWSER_TEST_NONE);
-  swap_observer.Wait();
-
-  EXPECT_TRUE(IsEmptyPrerenderLinkManager());
-}
-
 // Checks that pending prerenders which are canceled before they are launched
 // never get started.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageRemovesPending) {
@@ -1211,27 +1178,6 @@
   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
 }
 
-// Checks that the prerendering of a page is canceled correctly if we try to
-// swap it in before it commits.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNoCommitNoSwap) {
-  // Navigate to a page that triggers a prerender for a URL that never commits.
-  const GURL kNoCommitUrl("http://never-respond.example.com");
-  base::FilePath file(GetTestPath("prerender_page.html"));
-
-  base::RunLoop prerender_start_loop;
-  CreateHangingFirstRequestInterceptor(kNoCommitUrl, file,
-                                       prerender_start_loop.QuitClosure());
-  DisableJavascriptCalls();
-  PrerenderTestURL(kNoCommitUrl,
-                   FINAL_STATUS_NAVIGATION_UNCOMMITTED,
-                   0);
-  // Wait for the hanging request to be scheduled.
-  prerender_start_loop.Run();
-
-  // Navigate to the URL, but assume the contents won't be swapped in.
-  NavigateToDestURLWithDisposition(WindowOpenDisposition::CURRENT_TAB, false);
-}
-
 // Checks that client redirects don't add alias URLs until after they commit.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNoCommitNoSwap2) {
   // Navigate to a page that then navigates to a URL that never commits.
@@ -1313,36 +1259,6 @@
   EXPECT_TRUE(second_placeholder_present);
 }
 
-// For Content Setting BLOCK, checks that plugins are never loaded.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderContentSettingBlock) {
-  HostContentSettingsMap* content_settings_map =
-      HostContentSettingsMapFactory::GetForProfile(
-          current_browser()->profile());
-  content_settings_map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
-                                                 CONTENT_SETTING_BLOCK);
-
-  PrerenderTestURL("/prerender/prerender_plugin_never_load.html",
-                   FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that we don't load a NaCl plugin when NaCl is disabled.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNaClPluginDisabled) {
-  PrerenderTestURL("/prerender/prerender_plugin_nacl_disabled.html",
-                   FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-
-
-  // Run this check again.  When we try to load aa ppapi plugin, the
-  // "loadstart" event is asynchronously posted to a message loop.
-  // It's possible that earlier call could have been run before the
-  // the "loadstart" event was posted.
-  // TODO(mmenke):  While this should reliably fail on regressions, the
-  //                reliability depends on the specifics of ppapi plugin
-  //                loading.  It would be great if we could avoid that.
-  EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
-}
-
 // Checks that plugins in an iframe are not loaded while a page is
 // being preloaded, but are loaded when the page is displayed.
 #if defined(USE_AURA) && !defined(OS_WIN)
@@ -1384,118 +1300,6 @@
                    FINAL_STATUS_AUTH_NEEDED, 0);
 }
 
-// Checks that client-issued redirects work with prerendering.
-// This version navigates to the page which issues the redirection, rather
-// than the final destination page.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderClientRedirectNavigateToFirst) {
-  PrerenderTestURL(CreateClientRedirect("/prerender/prerender_page.html"),
-                   FINAL_STATUS_USED, 2);
-  NavigateToDestURL();
-}
-
-// Checks that client-issued redirects work with prerendering.
-// This version navigates to the final destination page, rather than the
-// page which does the redirection.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderClientRedirectNavigateToSecond) {
-  PrerenderTestURL(CreateClientRedirect("/prerender/prerender_page.html"),
-                   FINAL_STATUS_USED, 2);
-  NavigateToURL("/prerender/prerender_page.html");
-}
-
-// Checks that redirects with location.replace do not cancel a prerender and
-// and swap when navigating to the first page.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderLocationReplaceNavigateToFirst) {
-  PrerenderTestURL("/prerender/prerender_location_replace.html",
-                   FINAL_STATUS_USED, 2);
-  NavigateToDestURL();
-}
-
-// Checks that redirects with location.replace do not cancel a prerender and
-// and swap when navigating to the second.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderLocationReplaceNavigateToSecond) {
-  PrerenderTestURL("/prerender/prerender_location_replace.html",
-                   FINAL_STATUS_USED, 2);
-  NavigateToURL("/prerender/prerender_page.html");
-}
-
-// Checks that client-issued redirects work with prerendering.
-// This version navigates to the final destination page, rather than the
-// page which does the redirection via a mouse click.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderClientRedirectNavigateToSecondViaClick) {
-  GURL prerender_url = embedded_test_server()->GetURL(
-      CreateClientRedirect("/prerender/prerender_page.html"));
-  GURL destination_url =
-      embedded_test_server()->GetURL("/prerender/prerender_page.html");
-  PrerenderTestURL(prerender_url, FINAL_STATUS_USED, 2);
-  OpenURLViaClick(destination_url);
-}
-
-// Checks that a page served over HTTPS is correctly prerendered.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHttps) {
-  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
-  https_server.ServeFilesFromSourceDirectory(GetChromeTestDataDir());
-  ASSERT_TRUE(https_server.Start());
-  GURL https_url = https_server.GetURL("/prerender/prerender_page.html");
-  PrerenderTestURL(https_url,
-                   FINAL_STATUS_USED,
-                   1);
-  NavigateToDestURL();
-}
-
-// Checks that client-issued redirects within an iframe in a prerendered
-// page will not count as an "alias" for the prerendered page.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderClientRedirectInIframe) {
-  std::string redirect_path =
-      CreateClientRedirect("/prerender/prerender_embedded_content.html");
-  base::StringPairs replacement_text;
-  replacement_text.push_back(std::make_pair("REPLACE_WITH_URL", redirect_path));
-  std::string replacement_path = net::test_server::GetFilePathWithReplacements(
-      "/prerender/prerender_with_iframe.html", replacement_text);
-  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 2);
-  EXPECT_FALSE(
-      UrlIsInPrerenderManager("/prerender/prerender_embedded_content.html"));
-  NavigateToDestURL();
-}
-
-// Checks that server-issued redirects work with prerendering.
-// This version navigates to the page which issues the redirection, rather
-// than the final destination page.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderServerRedirectNavigateToFirst) {
-  PrerenderTestURL(CreateServerRedirect("/prerender/prerender_page.html"),
-                   FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that server-issued redirects work with prerendering.
-// This version navigates to the final destination page, rather than the
-// page which does the redirection.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderServerRedirectNavigateToSecond) {
-  PrerenderTestURL(CreateServerRedirect("/prerender/prerender_page.html"),
-                   FINAL_STATUS_USED, 1);
-  NavigateToURL("/prerender/prerender_page.html");
-}
-
-// Checks that server-issued redirects work with prerendering.
-// This version navigates to the final destination page, rather than the
-// page which does the redirection via a mouse click.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderServerRedirectNavigateToSecondViaClick) {
-  GURL prerender_url = embedded_test_server()->GetURL(
-      CreateServerRedirect("/prerender/prerender_page.html"));
-  GURL destination_url =
-      embedded_test_server()->GetURL("/prerender/prerender_page.html");
-  PrerenderTestURL(prerender_url, FINAL_STATUS_USED, 1);
-  OpenURLViaClick(destination_url);
-}
-
 // Checks that server-issued redirects within an iframe in a prerendered
 // page will not count as an "alias" for the prerendered page.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderServerRedirectInIframe) {
@@ -1676,26 +1480,6 @@
   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, any_prerender));
 }
 
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, OpenTaskManagerAfterSwapIn) {
-  const base::string16 any_prerender = MatchTaskManagerPrerender("*");
-  const base::string16 any_tab = MatchTaskManagerTab("*");
-  const base::string16 final = MatchTaskManagerTab("Prerender Page");
-
-  // Prerender, and swap it in.
-  PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-
-  // Show the task manager. This populates the model. Importantly, we're doing
-  // this after the prerender has been swapped in.
-  chrome::OpenTaskManager(current_browser());
-
-  // We should not see a prerender resource in the task manager, just a normal
-  // page.
-  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, final));
-  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab));
-  ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, any_prerender));
-}
-
 // Checks that audio loads are deferred on prerendering.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5Audio) {
   PrerenderTestURL("/prerender/prerender_html5_audio.html", FINAL_STATUS_USED,
@@ -1713,15 +1497,6 @@
   WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
 }
 
-// Checks that audio loads are deferred on prerendering and played back when
-// the prerender is swapped in if js starts playing.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5AudioJsplay) {
-  PrerenderTestURL("/prerender/prerender_html5_audio_jsplay.html",
-                   FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-  WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
-}
-
 // Checks that video loads are deferred on prerendering.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5Video) {
   PrerenderTestURL("/prerender/prerender_html5_video.html", FINAL_STATUS_USED,
@@ -1730,41 +1505,6 @@
   WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
 }
 
-// Checks that video tags inserted by javascript are deferred and played
-// correctly on swap in.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5VideoJs) {
-  // TODO(crbug.com/887175): flaky.
-  if (features::IsSingleProcessMash())
-    return;
-  PrerenderTestURL("/prerender/prerender_html5_video_script.html",
-                   FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-  WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
-}
-
-// Checks for correct network events by using a busy sleep the javascript.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5VideoNetwork) {
-  DisableJavascriptCalls();
-  std::unique_ptr<TestPrerender> prerender = PrerenderTestURL(
-      "/prerender/prerender_html5_video_network.html", FINAL_STATUS_USED, 1);
-  WaitForASCIITitle(prerender->contents()->prerender_contents(), kReadyTitle);
-  EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents()));
-  NavigateToDestURL();
-  WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
-}
-
-// Checks that scripts can retrieve the correct window size while prerendering.
-// Disabled on ChromeOS. See https://crbug.com/807821.
-#if defined(OS_CHROMEOS)
-#define MAYBE_PrerenderWindowSize DISABLED_PrerenderWindowSize
-#else
-#define MAYBE_PrerenderWindowSize PrerenderWindowSize
-#endif
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MAYBE_PrerenderWindowSize) {
-  PrerenderTestURL("/prerender/prerender_size.html", FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
 // TODO(jam): http://crbug.com/350550
 #if !(defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER))
 
@@ -1870,60 +1610,6 @@
                                WindowOpenDisposition::CURRENT_TAB, false);
 }
 
-// Checks that we correctly use a prerendered page when the page uses JS to set
-// the window.location.hash to a fragment on the same page.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderPageChangeFragmentLocationHash) {
-  PrerenderTestURL("/prerender/prerender_fragment_location_hash.html",
-                   FINAL_STATUS_USED, 1);
-  NavigateToURL("/prerender/prerender_fragment_location_hash.html");
-}
-
-// Checks that prerendering a PNG works correctly.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderImagePng) {
-  DisableJavascriptCalls();
-  PrerenderTestURL("/prerender/image.png", FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that prerendering a JPG works correctly.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderImageJpeg) {
-  DisableJavascriptCalls();
-  PrerenderTestURL(kPrefetchJpeg, FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that xhr GET requests allow prerenders.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrGet) {
-  PrerenderTestURL("/prerender/prerender_xhr_get.html", FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that xhr HEAD requests allow prerenders.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrHead) {
-  PrerenderTestURL("/prerender/prerender_xhr_head.html", FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that xhr OPTIONS requests allow prerenders.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrOptions) {
-  PrerenderTestURL("/prerender/prerender_xhr_options.html", FINAL_STATUS_USED,
-                   1);
-  NavigateToDestURL();
-}
-
-// Checks that xhr TRACE requests allow prerenders.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrTrace) {
-  PrerenderTestURL("/prerender/prerender_xhr_trace.html", FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that xhr POST requests allow prerenders.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrPost) {
-  PrerenderTestURL("/prerender/prerender_xhr_post.html", FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
 // Checks that xhr PUT cancels prerenders.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrPut) {
   PrerenderTestURL("/prerender/prerender_xhr_put.html",
@@ -1947,43 +1633,6 @@
   PrerenderTestURL(https_url, FINAL_STATUS_SSL_ERROR, 0);
 }
 
-// Checks that an SSL error that comes from a subresource does not cancel
-// the page. Non-main-frame requests are simply cancelled if they run into
-// an SSL problem.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorSubresource) {
-  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
-  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
-  https_server.ServeFilesFromSourceDirectory(GetChromeTestDataDir());
-  ASSERT_TRUE(https_server.Start());
-  GURL https_url = https_server.GetURL(kPrefetchJpeg);
-  base::StringPairs replacement_text;
-  replacement_text.push_back(
-      std::make_pair("REPLACE_WITH_IMAGE_URL", https_url.spec()));
-  std::string replacement_path = net::test_server::GetFilePathWithReplacements(
-      "/prerender/prerender_with_image.html", replacement_text);
-  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that an SSL error that comes from an iframe does not cancel
-// the page. Non-main-frame requests are simply cancelled if they run into
-// an SSL problem.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorIframe) {
-  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
-  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
-  https_server.ServeFilesFromSourceDirectory(GetChromeTestDataDir());
-  ASSERT_TRUE(https_server.Start());
-  GURL https_url =
-      https_server.GetURL("/prerender/prerender_embedded_content.html");
-  base::StringPairs replacement_text;
-  replacement_text.push_back(
-      std::make_pair("REPLACE_WITH_URL", https_url.spec()));
-  std::string replacement_path = net::test_server::GetFilePathWithReplacements(
-      "/prerender/prerender_with_iframe.html", replacement_text);
-  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
 // Checks that we cancel correctly when window.print() is called.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPrint) {
   DisableLoadEventCheck();
@@ -1991,19 +1640,6 @@
                    0);
 }
 
-// Checks that prerenders do not get swapped into target pages that have opened
-// popups; the BrowsingInstance is not empty.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderTargetHasPopup) {
-  PrerenderTestURL("/prerender/prerender_page.html",
-                   FINAL_STATUS_NON_EMPTY_BROWSING_INSTANCE, 1);
-  OpenURLViaWindowOpen(GURL(url::kAboutBlankURL));
-
-  // Switch back to the current tab and attempt to swap it in.
-  current_browser()->tab_strip_model()->ActivateTabAt(
-      0, {TabStripModel::GestureType::kOther});
-  NavigateToDestURLWithDisposition(WindowOpenDisposition::CURRENT_TAB, false);
-}
-
 class TestClientCertStore : public net::ClientCertStore {
  public:
   explicit TestClientCertStore(const net::CertificateList& certs)
@@ -2161,20 +1797,6 @@
                    0);
 }
 
-// Checks that a local storage read will not cause prerender to fail.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderLocalStorageRead) {
-  PrerenderTestURL("/prerender/prerender_localstorage_read.html",
-                   FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that a local storage write will not cause prerender to fail.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderLocalStorageWrite) {
-  PrerenderTestURL("/prerender/prerender_localstorage_write.html",
-                   FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
 // Checks that the favicon is properly loaded on prerender.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderFavicon) {
   std::unique_ptr<TestPrerender> prerender = PrerenderTestURL(
@@ -2191,56 +1813,6 @@
   EXPECT_TRUE(favicon_driver->FaviconIsValid());
 }
 
-// Checks that when prerendered page is swapped in and the referring page
-// neither had set an unload nor it had set a beforeunload handler, the old
-// WebContents will not leak.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderOldWebContentsDeleted) {
-  PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
-  WebContentsDestructionObserver destruction_observer(GetActiveWebContents());
-  NavigateToDestURL();
-  destruction_observer.Wait();
-}
-
-// Checks that when a prerendered page is swapped in to a referring page, the
-// unload handlers on the referring page are executed and its WebContents is
-// destroyed.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderUnload) {
-  set_loader_path("/prerender/prerender_loader_with_unload.html");
-  PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
-  WebContentsDestructionObserver destruction_observer(GetActiveWebContents());
-  NavigateToDestURL();
-  // Matches URL in prerender_loader_with_unload.html.
-  WaitForRequestCount(src_server()->GetURL("/unload-url"), 1);
-  destruction_observer.Wait();
-}
-
-// Checks that a beforeunload handler is executed on the referring page when a
-// prerendered page is swapped in. Also checks that the WebContents of the
-// referring page is destroyed.
-// Disabled on Windows. See https://crbug.com/875404.
-#if defined(OS_WIN)
-#define MAYBE_PrerenderBeforeUnload DISABLED_PrerenderBeforeUnload
-#else
-#define MAYBE_PrerenderBeforeUnload PrerenderBeforeUnload
-#endif
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MAYBE_PrerenderBeforeUnload) {
-  set_loader_path("/prerender/prerender_loader_with_beforeunload.html");
-  PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
-  WebContentsDestructionObserver destruction_observer(GetActiveWebContents());
-  NavigateToDestURL();
-  // This URL is requested from prerender_loader_with_beforeunload.html.
-  WaitForRequestCount(src_server()->GetURL("/unload-url"), 1);
-  destruction_observer.Wait();
-}
-
-// Checks that a hanging unload on the referring page of a prerender swap does
-// not crash the browser on exit.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHangingUnload) {
-  set_loader_path("/prerender/prerender_loader_with_hanging_unload.html");
-  PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
 // Checks that when the history is cleared, prerendering is cancelled and
 // prerendering history is cleared.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClearHistory) {
@@ -2307,44 +1879,6 @@
   EXPECT_FALSE(prerender->contents());
 }
 
-// Prerendering and history tests.
-// The prerendered page is navigated to in several ways [navigate via
-// omnibox, click on link, key-modified click to open in background tab, etc],
-// followed by a navigation to another page from the prerendered page, followed
-// by a back navigation.
-
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNavigateClickGoBack) {
-  PrerenderTestURL("/prerender/prerender_page_with_link.html",
-                   FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-  ClickToNextPageAfterPrerender();
-  GoBackToPrerender();
-}
-
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNavigateNavigateGoBack) {
-  PrerenderTestURL("/prerender/prerender_page_with_link.html",
-                   FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-  NavigateToNextPageAfterPrerender();
-  GoBackToPrerender();
-}
-
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickClickGoBack) {
-  PrerenderTestURL("/prerender/prerender_page_with_link.html",
-                   FINAL_STATUS_USED, 1);
-  OpenDestURLViaClick();
-  ClickToNextPageAfterPrerender();
-  GoBackToPrerender();
-}
-
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNavigateGoBack) {
-  PrerenderTestURL("/prerender/prerender_page_with_link.html",
-                   FINAL_STATUS_USED, 1);
-  OpenDestURLViaClick();
-  NavigateToNextPageAfterPrerender();
-  GoBackToPrerender();
-}
-
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewWindow) {
   PrerenderTestURL("/prerender/prerender_page_with_link.html",
                    FINAL_STATUS_APP_TERMINATING, 1);
@@ -2357,21 +1891,6 @@
   OpenDestURLViaClickNewForegroundTab();
 }
 
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       NavigateToPrerenderedPageWhenDevToolsAttached) {
-  DisableJavascriptCalls();
-  WebContents* web_contents =
-      current_browser()->tab_strip_model()->GetActiveWebContents();
-  scoped_refptr<DevToolsAgentHost> agent(
-      DevToolsAgentHost::GetOrCreateFor(web_contents));
-  FakeDevToolsClient client;
-  agent->AttachClient(&client);
-  const char* url = "/prerender/prerender_page.html";
-  PrerenderTestURL(url, FINAL_STATUS_DEVTOOLS_ATTACHED, 1);
-  NavigateToURLWithDisposition(url, WindowOpenDisposition::CURRENT_TAB, false);
-  agent->DetachClient(&client);
-}
-
 // Checks that the referrer policy is used when prerendering.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderReferrerPolicy) {
   set_loader_path("/prerender/prerender_loader_with_referrer_policy.html");
@@ -2514,69 +2033,14 @@
   PrerenderTestURL(replacement_path, FINAL_STATUS_UNSUPPORTED_SCHEME, 0);
 }
 
-// Ensure that about:blank is permitted for any subresource.
+// Checks that non-http/https main page redirects cancel the prerender.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderAllowAboutBlankSubresource) {
-  GURL image_url = GURL("about:blank");
-  base::StringPairs replacement_text;
-  replacement_text.push_back(
-      std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
-  std::string replacement_path = net::test_server::GetFilePathWithReplacements(
-      "/prerender/prerender_with_image.html", replacement_text);
-  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that non-http/https/chrome-extension subresource cancels the prerender
-// on redirect.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderCancelSubresourceRedirectUnsupportedScheme) {
-  GURL image_url = embedded_test_server()->GetURL(
-      CreateServerRedirect("invalidscheme://www.google.com/test.jpg"));
-  base::StringPairs replacement_text;
-  replacement_text.push_back(
-      std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
-  std::string replacement_path = net::test_server::GetFilePathWithReplacements(
-      "/prerender/prerender_with_image.html", replacement_text);
+                       PrerenderCancelMainFrameRedirectUnsupportedScheme) {
   // Disable load event checks because they race with cancellation.
   DisableLoadEventCheck();
-  PrerenderTestURL(replacement_path, FINAL_STATUS_UNSUPPORTED_SCHEME, 0);
-}
-
-// Checks that chrome-extension subresource does not cancel the prerender.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderKeepSubresourceExtensionScheme) {
-  GURL image_url = GURL("chrome-extension://abcdefg/test.jpg");
-  base::StringPairs replacement_text;
-  replacement_text.push_back(
-      std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
-  std::string replacement_path = net::test_server::GetFilePathWithReplacements(
-      "/prerender/prerender_with_image.html", replacement_text);
-  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that redirect to chrome-extension subresource does not cancel the
-// prerender.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderKeepSubresourceRedirectExtensionScheme) {
-  GURL image_url = embedded_test_server()->GetURL(
-      CreateServerRedirect("chrome-extension://abcdefg/test.jpg"));
-  base::StringPairs replacement_text;
-  replacement_text.push_back(
-      std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
-  std::string replacement_path = net::test_server::GetFilePathWithReplacements(
-      "/prerender/prerender_with_image.html", replacement_text);
-  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that media source video loads are deferred on prerendering.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5MediaSourceVideo) {
-  PrerenderTestURL("/prerender/prerender_html5_video_media_source.html",
-                   FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-  WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
+  GURL url = embedded_test_server()->GetURL(
+      CreateServerRedirect("invalidscheme://www.google.com/test.html"));
+  PrerenderTestURL(url, FINAL_STATUS_UNSUPPORTED_SCHEME, 0);
 }
 
 // Checks that a prerender that creates an audio stream (via a WebAudioDevice)
@@ -2587,16 +2051,6 @@
                    FINAL_STATUS_CREATING_AUDIO_STREAM, 0);
 }
 
-// Checks that prerenders do not swap in to WebContents being captured.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCapturedWebContents) {
-  PrerenderTestURL("/prerender/prerender_page.html",
-                   FINAL_STATUS_PAGE_BEING_CAPTURED, 1);
-  WebContents* web_contents = GetActiveWebContents();
-  web_contents->IncrementCapturerCount(gfx::Size());
-  NavigateToDestURLWithDisposition(WindowOpenDisposition::CURRENT_TAB, false);
-  web_contents->DecrementCapturerCount();
-}
-
 // Checks that prerenders are aborted on cross-process navigation from
 // a client redirect.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
@@ -2617,81 +2071,6 @@
                    FINAL_STATUS_OPEN_URL, 1);
 }
 
-// Checks that a deferred redirect to an image is not loaded until the page is
-// visible. Also test the right histogram events are emitted in this case.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDeferredImage) {
-  DisableJavascriptCalls();
-
-  // The prerender will not completely load until after the swap, so wait for a
-  // title change before calling DidPrerenderPass.
-  std::unique_ptr<TestPrerender> prerender = PrerenderTestURL(
-      "/prerender/prerender_deferred_image.html", FINAL_STATUS_USED, 0);
-  WaitForASCIITitle(prerender->contents()->prerender_contents(), kReadyTitle);
-  EXPECT_EQ(1, GetPrerenderDomContentLoadedEventCountForLinkNumber(0));
-  EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents()));
-  EXPECT_EQ(0, prerender->number_of_loads());
-
-  // Swap.
-  NavigationOrSwapObserver swap_observer(current_browser()->tab_strip_model(),
-                                         GetActiveWebContents());
-  ui_test_utils::NavigateToURLWithDisposition(
-      current_browser(), dest_url(), WindowOpenDisposition::CURRENT_TAB,
-      ui_test_utils::BROWSER_TEST_NONE);
-  swap_observer.Wait();
-
-  // The prerender never observes the final load.
-  EXPECT_EQ(0, prerender->number_of_loads());
-
-  // Now check DidDisplayPass.
-  EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
-}
-
-// Checks that a deferred redirect to an image is not loaded until the
-// page is visible, even after another redirect.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderDeferredImageAfterRedirect) {
-  DisableJavascriptCalls();
-
-  // The prerender will not completely load until after the swap, so wait for a
-  // title change before calling DidPrerenderPass.
-  std::unique_ptr<TestPrerender> prerender = PrerenderTestURL(
-      "/prerender/prerender_deferred_image.html", FINAL_STATUS_USED, 0);
-  WaitForASCIITitle(prerender->contents()->prerender_contents(), kReadyTitle);
-  EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents()));
-  EXPECT_EQ(0, prerender->number_of_loads());
-
-  // Swap.
-  NavigationOrSwapObserver swap_observer(current_browser()->tab_strip_model(),
-                                         GetActiveWebContents());
-  ui_test_utils::NavigateToURLWithDisposition(
-      current_browser(), dest_url(), WindowOpenDisposition::CURRENT_TAB,
-      ui_test_utils::BROWSER_TEST_NONE);
-  swap_observer.Wait();
-
-  // The prerender never observes the final load.
-  EXPECT_EQ(0, prerender->number_of_loads());
-
-  // Now check DidDisplayPass.
-  EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
-}
-
-// Checks that deferred redirects in the main frame are followed.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDeferredMainFrame) {
-  DisableJavascriptCalls();
-  PrerenderTestURL("/prerender/image-deferred.png", FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
-// Checks that deferred redirects in the main frame are followed, even
-// with a double-redirect.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderDeferredMainFrameAfterRedirect) {
-  DisableJavascriptCalls();
-  PrerenderTestURL(CreateServerRedirect("/prerender/image-deferred.png"),
-                   FINAL_STATUS_USED, 1);
-  NavigateToDestURL();
-}
-
 // Checks that deferred redirects in a synchronous XHR abort the prerender.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDeferredSynchronousXHR) {
   // Disable load event checks because they race with cancellation.
@@ -2753,34 +2132,6 @@
   NavigateToDestURLWithDisposition(WindowOpenDisposition::CURRENT_TAB, false);
 }
 
-// Checks that prerenders honor |should_replace_current_entry|.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderReplaceCurrentEntry) {
-  PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
-
-  content::OpenURLParams params(dest_url(), Referrer(),
-                                WindowOpenDisposition::CURRENT_TAB,
-                                ui::PAGE_TRANSITION_TYPED, false);
-  params.should_replace_current_entry = true;
-  NavigateToURLWithParams(params, false);
-
-  NavigationController& controller = GetActiveWebContents()->GetController();
-  // First entry is about:blank, second is prerender_page.html.
-  EXPECT_FALSE(controller.GetPendingEntry());
-  ASSERT_EQ(2, controller.GetEntryCount());
-  EXPECT_EQ(GURL(url::kAboutBlankURL), controller.GetEntryAtIndex(0)->GetURL());
-  EXPECT_EQ(dest_url(), controller.GetEntryAtIndex(1)->GetURL());
-}
-
-// Checks that <a ping> requests are not dropped in prerender.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPing) {
-  // Count hits to a certain URL.
-  const GURL kPingURL(src_server()->GetURL("/echo"));
-  PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
-  OpenDestURLViaClickPing(kPingURL);
-
-  WaitForRequestCount(kPingURL, 1);
-}
-
 // Checks that a prerender which calls window.close() on itself is aborted.
 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderWindowClose) {
   DisableLoadEventCheck();
@@ -2879,137 +2230,6 @@
   EXPECT_EQ(0, done_counter.count());
 }
 
-// Checks that the requests from a prerender are IDLE priority before the swap
-// (except on Android), but normal priority after the swap.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ResourcePriority) {
-  GURL before_swap_url = embedded_test_server()->GetURL(kPrefetchJpeg);
-  GURL after_swap_url = embedded_test_server()->GetURL("/prerender/image.png");
-  GURL main_page_url =
-      GetURLWithReplacement("/prerender/prerender_with_image.html",
-                            "REPLACE_WITH_IMAGE_URL", kPrefetchJpeg);
-  net::RequestPriority before_swap_priority = net::THROTTLED;
-  net::RequestPriority after_swap_priority = net::THROTTLED;
-
-  content::URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
-      [&](content::URLLoaderInterceptor::RequestParams* params) {
-        if (params->url_request.url == before_swap_url)
-          before_swap_priority = params->url_request.priority;
-        else if (params->url_request.url == after_swap_url)
-          after_swap_priority = params->url_request.priority;
-        return false;
-      }));
-
-  // Start the prerender.
-  PrerenderTestURL(main_page_url, FINAL_STATUS_USED, 1);
-
-  // Check priority before swap.
-  WaitForRequestCount(before_swap_url, 1);
-#if defined(OS_ANDROID)
-  EXPECT_GT(before_swap_priority, net::IDLE);
-#else
-  EXPECT_EQ(net::IDLE, before_swap_priority);
-#endif
-
-  // Swap.
-  NavigateToDestURL();
-
-  // Check priority after swap.
-  GetActiveWebContents()->GetMainFrame()->ExecuteJavaScriptForTests(
-      base::ASCIIToUTF16("var img=new Image(); img.src='/prerender/image.png'"),
-      base::NullCallback());
-  WaitForRequestCount(after_swap_url, 1);
-  EXPECT_NE(net::IDLE, after_swap_priority);
-}
-
-namespace {
-
-class HangingURLLoader : public network::mojom::URLLoader {
- public:
-  explicit HangingURLLoader(network::mojom::URLLoaderClientPtr client)
-      : client_(std::move(client)) {}
-  ~HangingURLLoader() override {}
-  // mojom::URLLoader implementation:
-  void FollowRedirect(const std::vector<std::string>& removed_headers,
-                      const net::HttpRequestHeaders& modified_headers,
-                      const base::Optional<GURL>& new_url) override {}
-  void ProceedWithResponse() override {}
-  void SetPriority(net::RequestPriority priority,
-                   int32_t intra_priority_value) override {
-    if (set_priority_callback_)
-      std::move(set_priority_callback_).Run(priority);
-  }
-  void PauseReadingBodyFromNet() override {}
-  void ResumeReadingBodyFromNet() override {}
-
-  using SetPriorityCallback = base::OnceCallback<void(net::RequestPriority)>;
-  void set_set_priority_callback(SetPriorityCallback callback) {
-    set_priority_callback_ = std::move(callback);
-  }
-
- private:
-  network::mojom::URLLoaderClientPtr client_;
-  SetPriorityCallback set_priority_callback_;
-};
-
-}  // namespace
-
-// Checks that a request started before the swap gets its original priority back
-// after the swap.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ResourcePriorityOverlappingSwap) {
-  GURL image_url = embedded_test_server()->GetURL(kPrefetchJpeg);
-  GURL main_page_url =
-      GetURLWithReplacement("/prerender/prerender_with_image.html",
-                            "REPLACE_WITH_IMAGE_URL", kPrefetchJpeg);
-
-  net::RequestPriority priority = net::THROTTLED;
-  base::RunLoop load_image_run_loop, set_priority_run_loop;
-  content::URLLoaderInterceptor interceptor(
-      base::BindLambdaForTesting(
-          [&](content::URLLoaderInterceptor::RequestParams* params) {
-            if (params->url_request.url == image_url) {
-              // Check priority before swap.
-              priority = params->url_request.priority;
-              load_image_run_loop.QuitClosure().Run();
-
-              auto loader =
-                  std::make_unique<HangingURLLoader>(std::move(params->client));
-              loader->set_set_priority_callback(base::BindLambdaForTesting(
-                  [&](net::RequestPriority request_priority) {
-                    priority = request_priority;
-                    set_priority_run_loop.QuitClosure().Run();
-                  }));
-              mojo::MakeStrongBinding(std::move(loader),
-                                      std::move(params->request));
-              return true;
-            }
-            return false;
-          }));
-
-  // The prerender will hang on the image resource, can't run the usual checks.
-  DisableLoadEventCheck();
-  DisableJavascriptCalls();
-  // Start the prerender.
-  PrerenderTestURL(main_page_url, FINAL_STATUS_USED, 0);
-
-  // Check priority before swap.
-  load_image_run_loop.Run();
-#if defined(OS_ANDROID)
-  EXPECT_GT(priority, net::IDLE);
-#else
-  EXPECT_EQ(net::IDLE, priority);
-#endif
-
-  // Swap. Cannot use NavigateToDestURL, because it waits for the load to
-  // complete, but the resource is still hung.
-  current_browser()->OpenURL(content::OpenURLParams(
-      dest_url(), Referrer(), WindowOpenDisposition::CURRENT_TAB,
-      ui::PAGE_TRANSITION_TYPED, false));
-
-  // Check priority after swap. The test may timeout in case of failure.
-  set_priority_run_loop.Run();
-  EXPECT_GT(priority, net::IDLE);
-}
-
 // When instantiated, mocks out the global text-to-speech engine with something
 // that emulates speaking any phrase for the duration of 0ms.
 class TtsPlatformMock : public content::TtsPlatform {
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index 77cd9d2c..1f9273e6 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -757,8 +757,10 @@
 
   auto* loading_predictor = predictors::LoadingPredictorFactory::GetForProfile(
       Profile::FromBrowserContext(profile_));
-  loading_predictor->PrepareForPageLoad(
-      url_arg, predictors::HintOrigin::OMNIBOX_PRERENDER_FALLBACK, true);
+  if (loading_predictor) {
+    loading_predictor->PrepareForPageLoad(
+        url_arg, predictors::HintOrigin::OMNIBOX_PRERENDER_FALLBACK, true);
+  }
 }
 
 std::unique_ptr<PrerenderHandle>
diff --git a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
index 19fda2f8..26e0670 100644
--- a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
+++ b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
@@ -777,6 +777,9 @@
 
 // Checks that prefetch requests have net::IDLE priority.
 IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, IssuesIdlePriorityRequests) {
+  // TODO(pasko): Figure out how to test that while a prefetched URL is in IDLE
+  // priority state, a high-priority request with the same URL from a foreground
+  // navigation hits the server.
   GURL script_url = src_server()->GetURL(kPrefetchScript);
   content::URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
       [=](content::URLLoaderInterceptor::RequestParams* params) {
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index b5c7394e..f9bb5a8 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1357,8 +1357,8 @@
       send_tab_to_self::ShouldOfferFeature(
           GetBrowser()->profile(),
           GetBrowser()->tab_strip_model()->GetActiveWebContents())) {
-    base::RecordAction(
-        UserMetricsAction("ViewContextMenu_SendTabToSelf_Shown"));
+    send_tab_to_self::RecordSendTabToSelfClickResult(
+        send_tab_to_self::kContentMenu, SendTabToSelfClickResult::kShowItem);
     menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
     menu_model_.AddItemWithStringIdAndIcon(IDC_SEND_TAB_TO_SELF,
                                            IDS_CONTEXT_MENU_SEND_TAB_TO_SELF,
@@ -2034,8 +2034,8 @@
       break;
 
     case IDC_SEND_TAB_TO_SELF:
-      base::RecordAction(
-          UserMetricsAction("ViewContextMenu_SendTabToSelf_Clicked"));
+      send_tab_to_self::RecordSendTabToSelfClickResult(
+          send_tab_to_self::kContentMenu, SendTabToSelfClickResult::kClickItem);
       send_tab_to_self::CreateNewEntry(embedder_web_contents_, GetProfile());
       break;
 
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.h b/chrome/browser/renderer_context_menu/render_view_context_menu.h
index 8596ecd..81ac11e3 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.h
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -243,7 +243,7 @@
   ProtocolHandlerRegistry* protocol_handler_registry_;
 
   // An observer that handles spelling suggestions, "Add to dictionary", and
-  // "Ask Google for suggestions" items.
+  // "Use enhanced spell check" items.
   std::unique_ptr<SpellingMenuObserver> spelling_suggestions_menu_observer_;
 
   // An observer that handles accessibility labels items.
diff --git a/chrome/browser/renderer_context_menu/spelling_bubble_model.cc b/chrome/browser/renderer_context_menu/spelling_bubble_model.cc
index 4cfa0c3d..06fcdf7 100644
--- a/chrome/browser/renderer_context_menu/spelling_bubble_model.cc
+++ b/chrome/browser/renderer_context_menu/spelling_bubble_model.cc
@@ -69,4 +69,10 @@
   PrefService* pref = profile_->GetPrefs();
   DCHECK(pref);
   pref->SetBoolean(spellcheck::prefs::kSpellCheckUseSpellingService, enabled);
+
+  // If the user has explicitly opted in to using the spelling service,
+  // spellcheck should be enabled so that the spelling service can run.
+  if (enabled) {
+    pref->SetBoolean(spellcheck::prefs::kSpellCheckEnable, true);
+  }
 }
diff --git a/chrome/browser/renderer_context_menu/spelling_menu_observer.cc b/chrome/browser/renderer_context_menu/spelling_menu_observer.cc
index 02d63a50..616642e6 100644
--- a/chrome/browser/renderer_context_menu/spelling_menu_observer.cc
+++ b/chrome/browser/renderer_context_menu/spelling_menu_observer.cc
@@ -276,11 +276,23 @@
   // The spelling service can be toggled by the user only if it is not managed.
   if (command_id == IDC_CONTENT_CONTEXT_SPELLING_TOGGLE &&
       integrate_spelling_service_.IsUserModifiable()) {
-    // When a user enables the "Ask Google for spelling suggestions" item, we
-    // show a bubble to confirm it. On the other hand, when a user disables this
+    bool spellcheckEnabled =
+        profile &&
+        profile->GetPrefs()->GetBoolean(spellcheck::prefs::kSpellCheckEnable);
+
+    // When a user enables the "Use enhanced spell check" item, we check to see
+    // if the user has spellcheck disabled. If the user has spellcheck disabled
+    // but has already enabled the spelling service, we just enable spellcheck.
+    // If spellcheck is enabled but the spelling service is not, we show a
+    // bubble to confirm it. On the other hand, when a user disables this
     // item, we directly update/ the profile and stop integrating the spelling
     // service immediately.
-    if (!integrate_spelling_service_.GetValue()) {
+    if (!spellcheckEnabled && integrate_spelling_service_.GetValue()) {
+      if (profile) {
+        profile->GetPrefs()->SetBoolean(spellcheck::prefs::kSpellCheckEnable,
+                                        true);
+      }
+    } else if (!integrate_spelling_service_.GetValue()) {
       content::RenderViewHost* rvh = proxy_->GetRenderViewHost();
       gfx::Rect rect = rvh->GetWidget()->GetView()->GetViewBounds();
       std::unique_ptr<SpellingBubbleModel> model(
diff --git a/chrome/browser/renderer_context_menu/spelling_menu_observer_browsertest.cc b/chrome/browser/renderer_context_menu/spelling_menu_observer_browsertest.cc
index 65a00c72..23f2a2bc 100644
--- a/chrome/browser/renderer_context_menu/spelling_menu_observer_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/spelling_menu_observer_browsertest.cc
@@ -87,7 +87,7 @@
 }
 
 // Tests that right-clicking a misspelled word adds two items:
-// "Add to dictionary", "Ask Google for suggestions".
+// "Add to dictionary", "Use enhanced spell check".
 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, InitMenuWithMisspelledWord) {
   InitMenu("wiimode", nullptr);
   EXPECT_EQ(2U, menu()->GetMenuSize());
@@ -110,7 +110,7 @@
 }
 
 // Tests that right-clicking a correct word when we enable spelling-service
-// integration to verify an item "Ask Google for suggestions" is checked. Even
+// integration to verify an item "Use enhanced spell check" is checked. Even
 // though this meanu itself does not add this item, its sub-menu adds the item
 // and calls SpellingMenuObserver::IsChecked() to check it.
 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
@@ -124,7 +124,7 @@
 }
 
 // Tests that right-clicking a misspelled word when we enable spelling-service
-// integration to verify an item "Ask Google for suggestions" is checked. (This
+// integration to verify an item "Use enhanced spell check" is checked. (This
 // test does not actually send JSON-RPC requests to the service because it makes
 // this test flaky.)
 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, EnableSpellingService) {
@@ -137,7 +137,7 @@
   InitMenu("wiimode", nullptr);
   EXPECT_EQ(2U, menu()->GetMenuSize());
 
-  // To avoid duplicates, this test reads only the "Ask Google for suggestions"
+  // To avoid duplicates, this test reads only the "Use enhanced spell check"
   // item and verifies it is enabled and checked.
   MockRenderViewContextMenu::MockMenuItem item;
   menu()->GetMenuItem(1, &item);
@@ -147,6 +147,26 @@
   EXPECT_FALSE(item.hidden);
 }
 
+// Tests that right-clicking a misspelled word when spelling-service
+// integration is enabled but the browser's spell check preference is disabled
+// shows the "Use enhanced spell check" as unchecked. Clicking on this item
+// enables spell check on the browser.
+IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
+                       EnableSpellingServiceWhenSpellcheckDisabled) {
+  menu()->GetPrefs()->SetBoolean(spellcheck::prefs::kSpellCheckEnable, false);
+  menu()->GetPrefs()->SetBoolean(
+      spellcheck::prefs::kSpellCheckUseSpellingService, true);
+
+  MockRenderViewContextMenu::MockMenuItem item;
+  menu()->GetMenuItem(1, &item);
+  EXPECT_FALSE(item.checked);
+
+  menu()->ExecuteCommand(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE, 1);
+  EXPECT_TRUE(
+      menu()->GetPrefs()->GetBoolean(spellcheck::prefs::kSpellCheckEnable));
+  EXPECT_TRUE(menu()->IsCommandIdChecked(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE));
+}
+
 // Test that we don't show "No more suggestions from Google" if the spelling
 // service is enabled and that there is only one suggestion.
 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
@@ -165,7 +185,7 @@
   InitMenu("asdfkj", "asdf");
 
   // The test should see a suggestion, separator, "Add to dictionary",
-  // "Ask Google for suggestions".
+  // "Use enhanced spell check".
   // Possibly more items (not relevant here).
   EXPECT_LT(3U, menu()->GetMenuSize());
 
@@ -206,7 +226,7 @@
   NoSpellingServiceWhenOffTheRecord
 #endif
 
-// Test that "Ask Google For Suggestions" is grayed out when using an
+// Test that "Use enhanced spell check" is grayed out when using an
 // off the record profile.
 // TODO(rlp): Include graying out of autocorrect in this test when autocorrect
 // is functional.
@@ -236,7 +256,7 @@
 
   // There should not be a "No more Google suggestions" (from SpellingService)
   // or a separator. The next 2 items should be "Add to Dictionary" followed
-  // by "Ask Google for suggestions" which should be disabled.
+  // by "Use enhanced spell check" which should be disabled.
   // TODO(rlp): add autocorrect here when it is functional.
   EXPECT_LT(1U, menu()->GetMenuSize());
 
diff --git a/chrome/browser/renderer_context_menu/spelling_options_submenu_observer.cc b/chrome/browser/renderer_context_menu/spelling_options_submenu_observer.cc
index 5f743ef..2cf5971 100644
--- a/chrome/browser/renderer_context_menu/spelling_options_submenu_observer.cc
+++ b/chrome/browser/renderer_context_menu/spelling_options_submenu_observer.cc
@@ -78,18 +78,21 @@
                                      IDS_CONTENT_CONTEXT_LANGUAGE_SETTINGS);
   submenu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
 
-  if (num_selected_dictionaries_ > 0) {
-    // Add a 'Check spelling while typing' item in the sub menu.
+  if (dictionaries_.size() > 0) {
+    // Add a 'Use basic spell check' item in the sub menu.
     submenu_model_.AddCheckItem(
         IDC_CHECK_SPELLING_WHILE_TYPING,
         l10n_util::GetStringUTF16(
             IDS_CONTENT_CONTEXT_CHECK_SPELLING_WHILE_TYPING));
-  }
 
-  // Add a check item 'Ask Google for spelling suggestions'. This item is
-  // handled in SpellingMenuObserver.
-  RenderViewContextMenu::AddSpellCheckServiceItem(
-      &submenu_model_, use_spelling_service_.GetValue());
+    // Add a check item 'Use enhanced spell check'. This item is handled in
+    // SpellingMenuObserver.
+    Profile* profile = Profile::FromBrowserContext(proxy_->GetBrowserContext());
+    RenderViewContextMenu::AddSpellCheckServiceItem(
+        &submenu_model_,
+        profile->GetPrefs()->GetBoolean(spellcheck::prefs::kSpellCheckEnable) &&
+            use_spelling_service_.GetValue());
+  }
 
   proxy_->AddSubMenu(
       IDC_SPELLCHECK_MENU,
@@ -132,11 +135,13 @@
     return dictionaries_[dictionary_index].used_for_spellcheck;
   }
 
-  // Check box for 'Check Spelling while typing'.
+  // Check box for 'Use basic spell check'.
   if (command_id == IDC_CHECK_SPELLING_WHILE_TYPING) {
     Profile* profile = Profile::FromBrowserContext(proxy_->GetBrowserContext());
     return profile->GetPrefs()->GetBoolean(
-        spellcheck::prefs::kSpellCheckEnable);
+               spellcheck::prefs::kSpellCheckEnable) &&
+           !profile->GetPrefs()->GetBoolean(
+               spellcheck::prefs::kSpellCheckUseSpellingService);
   }
 
   return false;
@@ -186,14 +191,31 @@
   }
 
   switch (command_id) {
-    case IDC_CHECK_SPELLING_WHILE_TYPING:
-      profile->GetPrefs()->SetBoolean(
-          spellcheck::prefs::kSpellCheckEnable,
-          !profile->GetPrefs()->GetBoolean(
-              spellcheck::prefs::kSpellCheckEnable));
-      break;
+    case IDC_CHECK_SPELLING_WHILE_TYPING: {
+      bool spellCheckEnabled =
+          profile->GetPrefs()->GetBoolean(spellcheck::prefs::kSpellCheckEnable);
+      bool enhancedSpellCheckEnabled = profile->GetPrefs()->GetBoolean(
+          spellcheck::prefs::kSpellCheckUseSpellingService);
 
-    case IDC_SPELLCHECK_MULTI_LINGUAL:
+      if (spellCheckEnabled && !enhancedSpellCheckEnabled) {
+        // User is turning off spell check
+        profile->GetPrefs()->SetBoolean(spellcheck::prefs::kSpellCheckEnable,
+                                        false);
+      } else if (enhancedSpellCheckEnabled) {
+        // Use is choosing 'basic' over 'enhanced'
+        profile->GetPrefs()->SetBoolean(spellcheck::prefs::kSpellCheckEnable,
+                                        true);
+        profile->GetPrefs()->SetBoolean(
+            spellcheck::prefs::kSpellCheckUseSpellingService, false);
+      } else {
+        // User is turning on spell check
+        profile->GetPrefs()->SetBoolean(spellcheck::prefs::kSpellCheckEnable,
+                                        true);
+      }
+      break;
+    }
+
+    case IDC_SPELLCHECK_MULTI_LINGUAL: {
       StringListPrefMember dictionaries_pref;
       dictionaries_pref.Init(spellcheck::prefs::kSpellCheckDictionaries,
                              profile->GetPrefs());
@@ -202,5 +224,6 @@
         all_languages.push_back(dictionary.language);
       dictionaries_pref.SetValue(all_languages);
       break;
+    }
   }
 }
diff --git a/chrome/browser/renderer_context_menu/spelling_options_submenu_observer_browsertest.cc b/chrome/browser/renderer_context_menu/spelling_options_submenu_observer_browsertest.cc
index 5ebfbbb..40f1ab1 100644
--- a/chrome/browser/renderer_context_menu/spelling_options_submenu_observer_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/spelling_options_submenu_observer_browsertest.cc
@@ -41,10 +41,14 @@
   }
 
   void InitMenu(bool enable_spellcheck,
+                bool use_spellchecking_service,
                 const std::string& accept_languages,
                 const std::vector<std::string>& dictionaries) {
     menu()->GetPrefs()->SetBoolean(spellcheck::prefs::kSpellCheckEnable,
                                    enable_spellcheck);
+    menu()->GetPrefs()->SetBoolean(
+        spellcheck::prefs::kSpellCheckUseSpellingService,
+        use_spellchecking_service);
     menu()->GetPrefs()->SetString(language::prefs::kAcceptLanguages,
                                   accept_languages);
     base::ListValue dictionaries_value;
@@ -74,29 +78,53 @@
   DISALLOW_COPY_AND_ASSIGN(SpellingOptionsSubMenuObserverTest);
 };
 
-// Tests that selecting the "Check Spelling While Typing" item toggles the value
+// Tests that selecting the "Use basic spell check" item toggles the value
 // of the "browser.enable_spellchecking" profile.
 IN_PROC_BROWSER_TEST_F(SpellingOptionsSubMenuObserverTest, ToggleSpelling) {
-  InitMenu(true, "en-US", std::vector<std::string>(1, "en-US"));
+  InitMenu(true, false, "en-US", std::vector<std::string>(1, "en-US"));
 
-  // Verify this menu has the "Check Spelling While Typing" item and this item
+  // Verify this menu has the "Use basic spell check" item and this item
   // is checked.
   EXPECT_TRUE(menu()->IsCommandIdEnabled(IDC_CHECK_SPELLING_WHILE_TYPING));
   EXPECT_TRUE(menu()->IsCommandIdChecked(IDC_CHECK_SPELLING_WHILE_TYPING));
+  EXPECT_FALSE(menu()->GetPrefs()->GetBoolean(
+      spellcheck::prefs::kSpellCheckUseSpellingService));
 
-  // Select this item and verify that the "Check Spelling While Typing" item is
+  // Select this item and verify that the "Use basic spell check" item is
   // not checked. Also, verify that the value of "browser.enable_spellchecking"
   // is now false.
   menu()->ExecuteCommand(IDC_CHECK_SPELLING_WHILE_TYPING, 0);
   ExpectPreferences(false, std::vector<std::string>(1, "en-US"));
   EXPECT_FALSE(menu()->IsCommandIdChecked(IDC_CHECK_SPELLING_WHILE_TYPING));
+
+  menu()->ExecuteCommand(IDC_CHECK_SPELLING_WHILE_TYPING, 1);
+  ExpectPreferences(true, std::vector<std::string>(1, "en-US"));
+  EXPECT_TRUE(menu()->IsCommandIdChecked(IDC_CHECK_SPELLING_WHILE_TYPING));
+}
+
+IN_PROC_BROWSER_TEST_F(SpellingOptionsSubMenuObserverTest,
+                       ToggleSpellingWithEnhancedSpellCheck) {
+  InitMenu(true, true, "en-US,es", std::vector<std::string>(1, "en-US"));
+
+  // Verify that because 'Use Enhanced spell check' is checked, the
+  // 'Use basic spell check' is shown as unchecked
+  EXPECT_TRUE(menu()->IsCommandIdEnabled(IDC_CHECK_SPELLING_WHILE_TYPING));
+  EXPECT_FALSE(menu()->IsCommandIdChecked(IDC_CHECK_SPELLING_WHILE_TYPING));
+
+  // Select this item and verify that "Use basic spell check" item is now
+  // checked and that 'spellcheck.use_spelling_service' is now disabled.
+  menu()->ExecuteCommand(IDC_CHECK_SPELLING_WHILE_TYPING, 1);
+  ExpectPreferences(true, std::vector<std::string>(1, "en-US"));
+  EXPECT_TRUE(menu()->IsCommandIdChecked(IDC_CHECK_SPELLING_WHILE_TYPING));
+  EXPECT_FALSE(menu()->GetPrefs()->GetBoolean(
+      spellcheck::prefs::kSpellCheckUseSpellingService));
 }
 
 // Single accept language is selected based on the dictionaries preference.
 // Consequently selecting multilingual spellcheck should copy all accept
 // languages into spellcheck dictionaries preference.
 IN_PROC_BROWSER_TEST_F(SpellingOptionsSubMenuObserverTest, SelectMultilingual) {
-  InitMenu(true, "en-US,es", std::vector<std::string>(1, "en-US"));
+  InitMenu(true, false, "en-US,es", std::vector<std::string>(1, "en-US"));
   EXPECT_FALSE(menu()->IsCommandIdChecked(IDC_SPELLCHECK_MULTI_LINGUAL));
   EXPECT_TRUE(menu()->IsCommandIdChecked(IDC_SPELLCHECK_LANGUAGES_FIRST));
   EXPECT_FALSE(menu()->IsCommandIdChecked(IDC_SPELLCHECK_LANGUAGES_FIRST + 1));
@@ -116,7 +144,7 @@
   std::vector<std::string> dictionaries;
   dictionaries.push_back("en-US");
   dictionaries.push_back("es");
-  InitMenu(true, "en-US,es", dictionaries);
+  InitMenu(true, false, "en-US,es", dictionaries);
   EXPECT_TRUE(menu()->IsCommandIdChecked(IDC_SPELLCHECK_MULTI_LINGUAL));
   EXPECT_FALSE(menu()->IsCommandIdChecked(IDC_SPELLCHECK_LANGUAGES_FIRST));
   EXPECT_FALSE(menu()->IsCommandIdChecked(IDC_SPELLCHECK_LANGUAGES_FIRST + 1));
@@ -128,7 +156,7 @@
 // Single dictionary should be selected based on preferences.
 IN_PROC_BROWSER_TEST_F(SpellingOptionsSubMenuObserverTest,
                        SingleLanguageSelected) {
-  InitMenu(true, "en-US", std::vector<std::string>(1, "en-US"));
+  InitMenu(true, false, "en-US", std::vector<std::string>(1, "en-US"));
   EXPECT_TRUE(menu()->IsCommandIdChecked(IDC_SPELLCHECK_LANGUAGES_FIRST));
 }
 
@@ -136,7 +164,7 @@
 // dictionary should update the preference.
 IN_PROC_BROWSER_TEST_F(SpellingOptionsSubMenuObserverTest,
                        SelectTheOnlyLanguage) {
-  InitMenu(true, "en-US", std::vector<std::string>());
+  InitMenu(true, false, "en-US", std::vector<std::string>());
   EXPECT_FALSE(menu()->IsCommandIdChecked(IDC_SPELLCHECK_LANGUAGES_FIRST));
 
   menu()->ExecuteCommand(IDC_SPELLCHECK_LANGUAGES_FIRST, 0);
diff --git a/chrome/browser/resources/chromeos/camera/BUILD.gn b/chrome/browser/resources/chromeos/camera/BUILD.gn
index 78c0eef..019ea1c7 100644
--- a/chrome/browser/resources/chromeos/camera/BUILD.gn
+++ b/chrome/browser/resources/chromeos/camera/BUILD.gn
@@ -70,6 +70,8 @@
     "src/images/camera_button_timer_on_3s.svg",
     "src/images/camera_focus_aim.svg",
     "src/images/camera_mode_photo.svg",
+    "src/images/camera_mode_portrait.svg",
+    "src/images/camera_mode_square.svg",
     "src/images/camera_mode_video.svg",
     "src/images/camera_shutter_photo_start.svg",
     "src/images/camera_shutter_photo_start_active.svg",
diff --git a/chrome/browser/resources/chromeos/camera/Makefile b/chrome/browser/resources/chromeos/camera/Makefile
index af13b79..bbb7938 100644
--- a/chrome/browser/resources/chromeos/camera/Makefile
+++ b/chrome/browser/resources/chromeos/camera/Makefile
@@ -92,6 +92,8 @@
 	src/images/camera_button_timer_on_3s.svg \
 	src/images/camera_focus_aim.svg \
 	src/images/camera_mode_photo.svg \
+	src/images/camera_mode_portrait.svg \
+	src/images/camera_mode_square.svg \
 	src/images/camera_mode_video.svg \
 	src/images/camera_shutter_photo_start.svg \
 	src/images/camera_shutter_photo_start_active.svg \
diff --git a/chrome/browser/resources/chromeos/camera/src/css/main.css b/chrome/browser/resources/chromeos/camera/src/css/main.css
index 0963a38..621e01518 100644
--- a/chrome/browser/resources/chromeos/camera/src/css/main.css
+++ b/chrome/browser/resources/chromeos/camera/src/css/main.css
@@ -166,52 +166,24 @@
   transform: translateY(-50%);
 }
 
-body.shift-top-stripe .top-stripe {
-  top: 0;  /* Calculate at runtime. */
-}
-
-.bottom-stripe,
-body:not(.tablet-landscape) .actions-group {
+.bottom-stripe {
   bottom: 56px;
   position: absolute;
   transform: translateY(50%);
 }
 
-body.tablet-landscape .bottom-stripe {
-  bottom: 48px;
-}
-
-body.shift-bottom-stripe .bottom-stripe,
-body.shift-bottom-stripe:not(.tablet-landscape) .actions-group {
-  bottom: 0;  /* Calculate at runtime. */
-}
-
 .left-stripe {
-  left: 48px;
+  left: 40px;
   position: absolute;
   transform: translateX(-50%);
 }
 
-body.shift-left-stripe .left-stripe {
-  left: 0;  /* Calculate at runtime. */
-}
-
-.right-stripe,
-body.tablet-landscape .actions-group {
+.right-stripe {
   position: absolute;
   right: 56px;
   transform: translateX(50%);
 }
 
-body:not(.tablet-landscape) .right-stripe {
-  right: 48px;
-}
-
-body.shift-right-stripe .right-stripe,
-body.shift-right-stripe.tablet-landscape .actions-group {
-  right: 0;  /* Calculate at runtime. */
-}
-
 .top-stripe.right-stripe {
   transform: translate(50%, -50%);
 }
@@ -228,16 +200,50 @@
   transform: translate(-50%, 50%);
 }
 
-.actions-group button {
-  margin: 0 8px;
+#shutters-group {
+  bottom: calc((var(--modes-bottom) + var(--modes-height)) + 16px);
 }
 
 body.tablet-landscape .actions-group {
   flex-direction: column-reverse;
 }
 
-body.tablet-landscape .actions-group button {
-  margin: 8px 0;
+#modes-group {
+  -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,0) 0, rgba(0,0,0,1) 10% 90%, rgba(0,0,0,0) 100%);
+  bottom: var(--modes-bottom);
+  flex-direction: column;
+  height: var(--modes-height);
+  justify-content: flex-start;
+  overflow: scroll;
+  pointer-events: auto;
+}
+
+.mode-item {
+  margin: 5px 0;
+  position: relative;
+}
+
+label.mode-item>span {
+  border-radius: 16px / 50%;
+  color: white;
+  display: inline-block;
+  font-family: 'Roboto', sans-serif;
+  font-size: 14px;
+  font-weight: 400;
+  padding: 10px 15px;
+  text-shadow: 2px 3px 3px rgba(32, 33, 36, 0.5);
+}
+
+.mode-item>input {
+  height: 100%;
+  position: absolute;
+  width: 100%;
+}
+
+.mode-item>input:checked + span {
+  background: rgb(238, 238, 238);
+  color: black;
+  text-shadow: none;
 }
 
 button.shutter {
@@ -291,40 +297,6 @@
   background-image: url(../images/camera_shutter_video_stop_hover.svg);
 }
 
-#switch-recordvideo,
-#switch-takephoto {
-  height: 56px;
-  width: 56px;
-}
-
-#switch-recordvideo {
-  background-image: url(../images/camera_button_switch_video.svg);
-  transition: transform 50ms;
-}
-
-#switch-takephoto {
-  background-image: url(../images/camera_button_switch_photo.svg);
-  transition: transform 50ms;
-}
-
-body.video-mode #switch-recordvideo {
-  transform: translateX(-160px);
-}
-
-body.tablet-landscape.video-mode #switch-recordvideo {
-  transform: translateY(160px);
-}
-
-body:not(.video-mode) #switch-takephoto {
-  transform: translateX(160px);
-}
-
-body.tablet-landscape:not(.video-mode) #switch-takephoto {
-  transform: translateY(-160px);
-}
-
-body.video-mode #switch-recordvideo,
-body:not(.video-mode) #switch-takephoto,
 body:not(.video-mode) #toggle-mic,
 body:not(.multi-camera) #switch-device {
   visibility: hidden;
@@ -341,6 +313,14 @@
   background-image: url(../images/camera_mode_video.svg);
 }
 
+body.square-mode #camera-mode {
+  background-image: url(../images/camera_mode_square.svg);
+}
+
+body.portrait-mode #camera-mode {
+  background-image: url(../images/camera_mode_portrait.svg);
+}
+
 body.mode-switching:not(.streaming) #camera-mode {
   visibility: visible;
 }
@@ -361,8 +341,8 @@
 
 #switch-device {
   background-image: url(../images/camera_button_switch_device.svg);
-  height: 48px;
-  width: 48px;
+  height: var(--big-icon);
+  width: var(--big-icon);
 }
 
 #switch-device.animate {
@@ -381,9 +361,9 @@
 #gallery-enter {
   background-color: rgba(24, 24, 24, 1);
   background-size: cover;
-  height: 48px;
+  height: var(--big-icon);
   position: relative;
-  width: 48px;
+  width: var(--big-icon);
 }
 
 .centered-overlay {
@@ -393,11 +373,16 @@
   transform: translate(-50%, -50%);
 }
 
-.options-group {
+#options-group {
+  bottom: calc((var(--bottom-line) + (var(--big-icon)/2)) + 30px);
   flex-direction: column;
 }
 
-.options-group input {
+body:not(.multi-camera) #options-group {
+  bottom: calc((var(--bottom-line) - 18px) - (var(--small-icon)/2));
+}
+
+#options-group input {
   margin: 18px 0;
 }
 
@@ -493,14 +478,34 @@
   overflow: hidden;
 }
 
-body.shift-preview-top #preview-wrapper {
-  position: absolute;
-  top: 0;
+#camera {
+  --big-icon: 48px;
+  --bottom-line: 56px;
+  --modes-height: 120px;
+  --modes-bottom: calc((var(--bottom-line) + (var(--big-icon)/2)) + 24px);
+  --small-icon: 40px;
 }
 
-body.shift-preview-left #preview-wrapper {
-  left: 0;
-  position: absolute;
+body.w-letterbox.w-letterbox-s #camera {
+  justify-content: flex-end;
+}
+
+body.w-letterbox.w-letterbox-m #camera,
+body.w-letterbox.w-letterbox-l #camera {
+  justify-content: flex-start;
+}
+
+body.w-letterbox.w-letterbox-xl #camera {
+  justify-content: center;
+}
+
+body:not(.w-letterbox) #camera {
+  flex-direction: column;
+  justify-content: center;
+}
+
+body:not(.w-letterbox).preview-vertical-dock #camera {
+  justify-content: flex-end;
 }
 
 #preview-wrapper,
@@ -510,6 +515,25 @@
   position: relative;
 }
 
+body:.w-letterbox.w-letterbox-l #preview-wrapper {
+  left: 72px;
+}
+
+body:not(.w-letterbox).preview-vertical-dock #preview-wrapper {
+  bottom: calc((var(--bottom-line) + (var(--big-icon)/2)) + 12px);
+}
+
+body:not(.mode-switching).square-mode #preview-wrapper {
+  height: 0; /* Calculate at runtime. */
+  width: 0; /* Calculate at runtime. */
+}
+
+body:not(.mode-switching).square-mode #preview-video {
+  left: 0; /* Calculate at runtime. */
+  position: absolute;
+  top: 0; /* Calculate at runtime. */
+}
+
 body.streaming #preview-video {
   pointer-events: auto;
 }
@@ -542,17 +566,6 @@
   transform: scale(-1.03, 1.03);
 }
 
-body:not(.mode-switching).square-mode #preview-wrapper {
-  height: 0; /* Calculate at runtime. */
-  width: 0; /* Calculate at runtime. */
-}
-
-body:not(.mode-switching).square-mode #preview-video {
-  left: 0; /* Calculate at runtime. */
-  position: absolute;
-  top: 0; /* Calculate at runtime. */
-}
-
 #preview-grid {
   bottom: 0;
   left: 0;
@@ -566,7 +579,7 @@
 body:not(.streaming) #preview-focus,
 body:not(.streaming) #open-settings,
 body:not(.streaming) #toggle-mic,
-body:not(.streaming) .options-group {
+body:not(.streaming) #options-group {
   visibility: hidden;
 }
 
diff --git a/chrome/browser/resources/chromeos/camera/src/images/camera_mode_portrait.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_mode_portrait.svg
new file mode 100644
index 0000000..f4e04fb
--- /dev/null
+++ b/chrome/browser/resources/chromeos/camera/src/images/camera_mode_portrait.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <!-- Generator: Sketch 53.2 (72643) - https://sketchapp.com -->
+    <title>mode_portrait_1x</title>
+    <desc>Created with Sketch.</desc>
+    <defs>
+        <path d="M31.6666667,5 L8.33333333,5 C6.5,5 5,6.5 5,8.33333333 L5,31.6666667 C5,33.5 6.5,35 8.33333333,35 L31.6666667,35 C33.5,35 35,33.5 35,31.6666667 L35,8.33333333 C35,6.5 33.5,5 31.6666667,5 Z M32,32 L8,32 L8,8 L32,8 L32,32 Z" id="path-1"></path>
+    </defs>
+    <g id="mode_portrait_1x" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="ic_portrait_black_24dp">
+            <polygon id="Path" points="0 0 40 0 40 40 0 40"></polygon>
+            <path d="M20,20.086667 C22.0666667,20.086667 23.75,18.4033337 23.75,16.336667 C23.75,14.2700003 22.0666667,12.586667 20,12.586667 C17.9333333,12.586667 16.25,14.2700003 16.25,16.336667 C16.25,18.4033337 17.9333333,20.086667 20,20.086667 Z M27.5,26.753333 C27.5,24.253333 22.5,23.003333 20,23.003333 C17.5,23.003333 12.5,24.253333 12.5,26.753333 L12.5,28.003333 L27.5,28.003333 L27.5,26.753333 Z" id="Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
+        </g>
+        <mask id="mask-2" fill="white">
+            <use xlink:href="#path-1"></use>
+        </mask>
+        <use id="Shape" fill="#FFFFFF" fill-rule="nonzero" xlink:href="#path-1"></use>
+    </g>
+</svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/camera/src/images/camera_mode_square.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_mode_square.svg
new file mode 100644
index 0000000..a04174f
--- /dev/null
+++ b/chrome/browser/resources/chromeos/camera/src/images/camera_mode_square.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <!-- Generator: Sketch 53.2 (72643) - https://sketchapp.com -->
+    <title>mode_square_1x</title>
+    <desc>Created with Sketch.</desc>
+    <defs>
+        <path d="M26.6666667,0 L3.33333333,0 C1.5,0 0,1.5 0,3.33333333 L0,26.6666667 C0,28.5 1.5,30 3.33333333,30 L26.6666667,30 C28.5,30 30,28.5 30,26.6666667 L30,3.33333333 C30,1.5 28.5,0 26.6666667,0 Z M27,27 L3,27 L3,3 L27,3 L27,27 Z M18.3333333,14.67 L13.3333333,20.87 L10,16.3366667 L5,23.0033333 L25,23.0033333 L18.3333333,14.67 Z" id="path-1"></path>
+    </defs>
+    <g id="mode_square_1x" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="image" transform="translate(5.000000, 5.000000)">
+            <mask id="mask-2" fill="white">
+                <use xlink:href="#path-1"></use>
+            </mask>
+            <use id="Shape" fill="#FFFFFF" fill-rule="nonzero" xlink:href="#path-1"></use>
+        </g>
+    </g>
+</svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
index 076ad3d..38b6516 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
@@ -223,20 +223,26 @@
       (async () => {
         if (!suspend) {
           for (const id of await this.options_.videoDeviceIds()) {
-            for (const [mode, constraints] of await this.modes_
-                     .getConstraitsForModes(id)) {
-              try {
-                const stream =
-                    await navigator.mediaDevices.getUserMedia(constraints);
-                await this.preview_.start(stream);
-                this.facingMode_ =
-                    this.options_.updateValues(constraints, stream);
-                await this.modes_.updateMode(mode, stream);
-                cca.nav.close('warning', 'no-camera');
-                return;
-              } catch (e) {
-                this.preview_.stop();
-                console.error(e);
+            const modesAndConstraints =
+                await this.modes_.getConstraitsForModes(id);
+            this.modes_.updateModeSelectionUI(modesAndConstraints.map(([
+                                                                        m,
+                                                                      ]) => m));
+            for (const [mode, candidates] of modesAndConstraints) {
+              for (const constraints of candidates) {
+                try {
+                  const stream =
+                      await navigator.mediaDevices.getUserMedia(constraints);
+                  await this.preview_.start(stream);
+                  this.facingMode_ =
+                      this.options_.updateValues(constraints, stream);
+                  await this.modes_.updateMode(mode, stream);
+                  cca.nav.close('warning', 'no-camera');
+                  return;
+                } catch (e) {
+                  this.preview_.stop();
+                  console.error(e);
+                }
               }
             }
           }
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera/layout.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/layout.js
index 8124cf9..0a8b693 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera/layout.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera/layout.js
@@ -25,40 +25,6 @@
  */
 cca.views.camera.Layout = function() {
   /**
-   * CSS sylte of the shifted right-stripe.
-   * @type {CSSStyleDeclaration}
-   * @private
-   */
-  this.rightStripe_ = cca.views.camera.Layout.cssStyle_(
-      'body.shift-right-stripe .right-stripe, ' +
-      'body.shift-right-stripe.tablet-landscape .actions-group');
-
-  /**
-   * CSS sylte of the shifted bottom-stripe.
-   * @type {CSSStyleDeclaration}
-   * @private
-   */
-  this.bottomStripe_ = cca.views.camera.Layout.cssStyle_(
-      'body.shift-bottom-stripe .bottom-stripe, ' +
-      'body.shift-bottom-stripe:not(.tablet-landscape) .actions-group');
-
-  /**
-   * CSS sylte of the shifted left-stripe.
-   * @type {CSSStyleDeclaration}
-   * @private
-   */
-  this.leftStripe_ = cca.views.camera.Layout.cssStyle_(
-      'body.shift-left-stripe .left-stripe');
-
-  /**
-   * CSS sylte of the shifted top-stripe.
-   * @type {CSSStyleDeclaration}
-   * @private
-   */
-  this.topStripe_ = cca.views.camera.Layout.cssStyle_(
-      'body.shift-top-stripe .top-stripe');
-
-  /**
    * CSS style of the viewport in square mode.
    * @type {CSSStyleDeclaration}
    * @private
@@ -131,72 +97,32 @@
  * Updates the layout for video-size or window-size changes.
  */
 cca.views.camera.Layout.prototype.update = function() {
-  // TODO(yuli): Replace tablet-landscape with max-wnd/tall.
   var fullWindow = cca.util.isWindowFullSize();
-  var tall = window.innerHeight > window.innerWidth;
-  var tabletLandscape = fullWindow && !tall;
-  cca.state.set('tablet-landscape', tabletLandscape);
-  cca.state.set('max-wnd', fullWindow);
-  cca.state.set('tall', tall);
-
-  var dimens = (shutter) => {
-    // These following constants need kept in sync with relevant values in css.
-    // preset: button-size + preset-margin + min-margin
-    // least: button-size + 2 * min-margin
-    // gap: preset-margin - min-margin
-    // baseline: preset-baseline
-    return shutter ? [100, 88, 12, 56] : [76, 56, 20, 48];
-  };
 
   var [letterboxW, letterboxH] = this.updatePreviewSize_(fullWindow);
-  var [halfW, halfH] = [letterboxW / 2, letterboxH / 2];
+  var isLetterboxW = letterboxH < letterboxW;
 
-  // Shift preview to accommodate the shutter in letterbox if applicable.
-  var accommodate = (measure) => {
-    var [, leastShutter] = dimens(true);
-    return (measure > leastShutter) && (measure < leastShutter * 2);
-  };
-  var cond = fullWindow && tabletLandscape && accommodate(letterboxW);
-  var [rightBox, leftBox] = cond ? [letterboxW, 0] : [halfW, halfW];
-  cca.state.set('shift-preview-left', cond);
-
-  cond = fullWindow && !tabletLandscape && accommodate(letterboxH);
-  var [bottomBox, topBox] = cond ? [letterboxH, 0] : [halfH, halfH];
-  cca.state.set('shift-preview-top', cond);
-
-  // Shift buttons' stripes if necessary. Buttons are either fully on letterbox
-  // or preview while the shutter/options keep minimum margin to either edges.
-  var calc = (measure, least) => {
-    return (measure >= least) ?
-        Math.round(measure / 2) : // Centered in letterbox.
-        Math.round(measure + least / 2); // Inset in preview.
-  };
-  var shift = (stripe, name, measure, shutter) => {
-    var [preset, least, gap, baseline] = dimens(shutter);
-    cond = measure > gap && measure < preset;
-    if (cond) {
-      baseline = calc(measure, least);
-      stripe.setProperty(name, baseline + 'px');
-    }
-    cca.state.set('shift-' + name + '-stripe', cond);
-    // Return shutter's baseline in letterbox if applicable.
-    return (shutter && baseline < measure) ? baseline : 0;
-  };
-  var symm = (stripe, name, measure, shutterBaseline) => {
-    if (measure && shutterBaseline) {
-      cca.state.set('shift-' + name + '-stripe', true);
-      stripe.setProperty(name, shutterBaseline + 'px');
-      return true;
-    }
-    return false;
-  };
-  // Make both letterbox look symmetric if shutter is in either letterbox.
-  if (!symm(this.leftStripe_, 'left', leftBox,
-      shift(this.rightStripe_, 'right', rightBox, tabletLandscape))) {
-    shift(this.leftStripe_, 'left', leftBox, false);
-  }
-  if (!symm(this.topStripe_, 'top', topBox,
-      shift(this.bottomStripe_, 'bottom', bottomBox, !tabletLandscape))) {
-    shift(this.topStripe_, 'top', topBox, false);
+  cca.state.set('w-letterbox', isLetterboxW);
+  if (isLetterboxW) {
+    var modeWidth =
+        document.querySelector('#modes-group').getBoundingClientRect().width;
+    var layoutToggled = false;
+    [[modeWidth + 40, 'w-letterbox-s'],
+     [modeWidth + 40 + 72, 'w-letterbox-m'],
+     [(modeWidth + 40) * 2, 'w-letterbox-l'],
+     [Infinity, 'w-letterbox-xl'],
+    ]
+        .forEach(
+            ([wSize, classname]) => cca.state.set(
+                classname,
+                /* Enable only state which the letterboxW size falls in range
+                 * of its wSize and previous wSize. And disable all other
+                 * states. */
+                !layoutToggled && (layoutToggled = letterboxW <= wSize)));
+  } else {
+    // preview-vertical-dock: Dock bottom line of preview between gallery and
+    //                        mode selector.
+    // otherwise: Vertically center the preview.
+    cca.state.set('preview-vertical-dock', letterboxH / 2 >= 112);
   }
 };
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
index 21d2e08..c3226666 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
@@ -108,15 +108,35 @@
 
   // End of properties, seal the object.
   Object.seal(this);
-
-  [['#switch-recordvideo', 'video-mode'], ['#switch-takephoto', 'photo-mode']]
-      .forEach(
-          ([selector, mode]) =>
-              document.querySelector(selector).addEventListener(
-                  'click', this.switchMode_.bind(this, mode)));
+  document.querySelectorAll('.mode-item>input').forEach((element) => {
+    element.addEventListener('click', (event) => {
+      if (!cca.state.get('streaming') || cca.state.get('taking')) {
+        event.preventDefault();
+      }
+    });
+    element.addEventListener('change', (event) => {
+      if (element.checked) {
+        var mode = element.dataset.mode;
+        this.updateModeUI_(mode);
+        cca.state.set('mode-switching', true);
+        this.doSwitchMode_().then(() => cca.state.set('mode-switching', false));
+      }
+    });
+  });
 
   // Set default mode when app started.
-  cca.state.set('photo-mode', true);
+  this.updateModeUI_('photo-mode');
+};
+
+/**
+ * Updates state of mode related UI to the target mode.
+ * @param {string} mode Mode to be toggled.
+ */
+cca.views.camera.Modes.prototype.updateModeUI_ = function(mode) {
+  Object.keys(this.allModes).forEach((m) => cca.state.set(m, m == mode));
+  const element = document.querySelector(`.mode-item>input[data-mode=${mode}]`);
+  element.checked = true;
+  element.focus();
 };
 
 /**
@@ -184,19 +204,19 @@
   if (!cca.state.get('streaming') || cca.state.get('taking')) {
     return;
   }
-  Object.keys(this.allModes).forEach((m) => cca.state.set(m, m == mode));
+  this.updateModeUI_(mode);
   cca.state.set('mode-switching', true);
   this.doSwitchMode_().then(() => cca.state.set('mode-switching', false));
 };
 
 /**
- * Gets all the supported modes and all their constraints pairs for given
+ * Gets all the supported modes and their constraints-candidates pairs for given
  * deviceId.
  * @async
  * @param {?string} deviceId Id of updated video device.
- * @return {Array<[string, Object]>} Array of supported mode name and
- *     constraints pairs for given deviceId. Mode values in array start with
- *     current mode and follow predefined retry order.
+ * @return {Array<[string, Array<Object>]>} Array of supported mode name and
+ *     constraints-candidates pairs for given deviceId. Mode values in array
+ *     start with current mode and follow predefined retry order.
  */
 cca.views.camera.Modes.prototype.getConstraitsForModes =
     async function(deviceId) {
@@ -207,8 +227,7 @@
     const m = this.allModes[mode];
     tried[mode] = true;
     if (await m.isSupported(deviceId)) {
-      results.push(...m.deviceConstraints(deviceId).map(
-          (constraints) => [mode, constraints]));
+      results.push([mode, m.deviceConstraints(deviceId)]);
     }
     mode = m.nextMode;
   }
@@ -216,6 +235,20 @@
 };
 
 /**
+ * Updates mode selection UI according to input supported modes.
+ * @param {Array<string>} supportedModes Supported mode names to be updated
+ *     with.
+ */
+cca.views.camera.Modes.prototype.updateModeSelectionUI = function(
+    supportedModes) {
+  document.querySelectorAll('.mode-item').forEach((element) => {
+    const radio = element.querySelector('input[type=radio]');
+    element.style.display =
+        supportedModes.includes(radio.dataset.mode) ? '' : 'none';
+  });
+};
+
+/**
  * Creates and updates new current mode object.
  * @async
  * @param {string} mode Classname of mode to be updated.
@@ -225,7 +258,7 @@
   if (this.current != null) {
     await this.current.stopCapture();
   }
-  Object.keys(this.allModes).forEach((m) => cca.state.set(m, m == mode));
+  this.updateModeUI_(mode);
   this.stream_ = stream;
   this.current = this.allModes[mode].captureFactory();
 };
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera/preview.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/preview.js
index ec4fed7c4..8e5611a 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera/preview.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera/preview.js
@@ -220,7 +220,7 @@
     var inner = chrome.app.window.current().innerBounds;
     var innerW = inner.minWidth;
     var innerH = cca.state.get('square-mode') ?
-        Math.round(innerW / (4 / 3)) :
+        innerW :
         Math.round(innerW / this.aspectRatio_);
 
     // Limit window resizing capability by setting min-height. Don't limit
@@ -252,9 +252,9 @@
   this.cancelFocus_();
 
   // Normalize to square space coordinates by W3C spec.
-  var px = (event.offsetX - this.video_.offsetLeft) / this.video_.width;
-  var py = (event.offsetY - this.video_.offsetTop) / this.video_.height;
-  var constraints = {advanced: [{pointsOfInterest: [{px, py}]}]};
+  var x = event.offsetX / this.video_.width;
+  var y = event.offsetY / this.video_.height;
+  var constraints = {advanced: [{pointsOfInterest: [{x, y}]}]};
   var track = this.video_.srcObject.getVideoTracks()[0];
   var focus = track.applyConstraints(constraints).then(() => {
     if (focus != this.focus_) {
@@ -262,8 +262,8 @@
     }
     var aim = document.querySelector('#preview-focus-aim');
     var clone = aim.cloneNode(true);
-    clone.style.left = `${event.offsetX}px`;
-    clone.style.top = `${event.offsetY}px`;
+    clone.style.left = `${event.offsetX + this.video_.offsetLeft}px`;
+    clone.style.top = `${event.offsetY + this.video_.offsetTop}px`;
     clone.hidden = false;
     aim.parentElement.replaceChild(clone, aim);
   }).catch(console.error);
diff --git a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fil.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fil.xtb
index 4948f52..7d36110 100644
--- a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fil.xtb
+++ b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fil.xtb
@@ -31,6 +31,7 @@
 <translation id="5057360777601936059">Kasalukuyang hindi available ang iyong camera.
         Pakitingnan kung maayos na nakakonekta ang camera.</translation>
 <translation id="5152121255775685072">Pumunta sa gallery</translation>
+<translation id="5671277269877808209">Parisukat</translation>
 <translation id="5869546221129391014">Grid</translation>
 <translation id="6073451960410192870">Ihinto ang pag-record</translation>
 <translation id="6233780560267770709">3 by 3</translation>
diff --git a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_ERROR_MSG_TAKE_PORTRAIT_PHOTO_FAILED.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_ERROR_MSG_TAKE_PORTRAIT_PHOTO_FAILED.png.sha1
new file mode 100644
index 0000000..5a61477e6
--- /dev/null
+++ b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_ERROR_MSG_TAKE_PORTRAIT_PHOTO_FAILED.png.sha1
@@ -0,0 +1 @@
+4adb44d1638b8487af48c7d588155117c377e742
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_RECORD_VIDEO_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_RECORD_VIDEO_BUTTON.png.sha1
new file mode 100644
index 0000000..c265ed67
--- /dev/null
+++ b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_RECORD_VIDEO_BUTTON.png.sha1
@@ -0,0 +1 @@
+de87179377d0c069e8a800c779c69ca24ed1ce5a
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PHOTO_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PHOTO_BUTTON.png.sha1
new file mode 100644
index 0000000..c8557c5f
--- /dev/null
+++ b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PHOTO_BUTTON.png.sha1
@@ -0,0 +1 @@
+c1f48f5c48afa182771476d379d7e4b31903e054
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PORTRAIT_PHOTO_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PORTRAIT_PHOTO_BUTTON.png.sha1
new file mode 100644
index 0000000..485c25f
--- /dev/null
+++ b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PORTRAIT_PHOTO_BUTTON.png.sha1
@@ -0,0 +1 @@
+c6c54e9539149a8535573e3a5d3be5d066592a41
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_SQUARE_PHOTO_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_SQUARE_PHOTO_BUTTON.png.sha1
new file mode 100644
index 0000000..c575ceed
--- /dev/null
+++ b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_SQUARE_PHOTO_BUTTON.png.sha1
@@ -0,0 +1 @@
+b716e084e7163cc004c1805a937def1324514949
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/camera/src/views/main.html b/chrome/browser/resources/chromeos/camera/src/views/main.html
index a73ae670..61517a5 100644
--- a/chrome/browser/resources/chromeos/camera/src/views/main.html
+++ b/chrome/browser/resources/chromeos/camera/src/views/main.html
@@ -55,9 +55,37 @@
                   tabindex="-1" hidden></object>
         </div>
       </div>
-      <div class="actions-group buttons circle">
-        <button id="switch-takephoto" tabindex="0"
-                i18n-label="switch_take_photo_button"></button>
+      <div id="modes-group" class="buttons right-stripe">
+        <label class="mode-item" tabindex="-1">
+          <input type="radio" name="mode"
+               data-mode="video-mode" tabindex="0"
+               i18n-aria="switch_record_video_button">
+          <span i18n-content="label_switch_record_video_button"
+                tabindex="-1"></span>
+        </label>
+        <label class="mode-item" tabindex="-1">
+          <input type="radio" name="mode"
+               data-mode="photo-mode" tabindex="0"
+               i18n-aria="switch_take_photo_button">
+          <span i18n-content="label_switch_take_photo_button"
+                tabindex="-1"></span>
+        </label>
+        <label class="mode-item" tabindex="-1">
+          <input type="radio" name="mode"
+               data-mode="square-mode" tabindex="0"
+               i18n-aria="switch_take_square_photo_button">
+          <span i18n-content="label_switch_take_square_photo_button"
+                tabindex="-1"></span>
+        </label>
+        <label class="mode-item" tabindex="-1">
+          <input type="radio" name="mode"
+               data-mode="portrait-mode" tabindex="0"
+               i18n-aria="switch_take_portrait_photo_button">
+          <span i18n-content="label_switch_take_portrait_photo_button"
+                tabindex="-1"></span>
+        </label>
+      </div>
+      <div id="shutters-group" class="buttons right-stripe circle">
         <button id="start-recordvideo" class="shutter" tabindex="0"
                 i18n-label="record_video_start_button"></button>
         <button id="stop-recordvideo" class="shutter" tabindex="0"
@@ -66,8 +94,6 @@
                 i18n-label="take_photo_button"></button>
         <button id="stop-takephoto" class="shutter" tabindex="0"
                 i18n-label="take_photo_cancel_button"></button>
-        <button id="switch-recordvideo" tabindex="0"
-                i18n-label="switch_record_video_button"></button>
       </div>
       <div class="top-stripe right-stripe buttons">
         <input type="checkbox" id="toggle-mic" tabindex="0"
@@ -78,7 +104,7 @@
         <button id="open-settings" tabindex="0"
                 i18n-label="settings_button" aria-haspopup="true"></button>
       </div>
-      <div class="left-stripe options-group buttons">
+      <div id="options-group" class="left-stripe buttons">
         <input type="checkbox" id="toggle-mirror" tabindex="0"
                i18n-label="toggle_mirror_button" data-state="mirror" checked>
         <input type="checkbox" id="toggle-grid" tabindex="0"
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_sk.xtb b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_sk.xtb
index 3d96b74..6b65d21 100644
--- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_sk.xtb
+++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_sk.xtb
@@ -119,7 +119,7 @@
 <translation id="1781173782405573156">Preskočiť kláves</translation>
 <translation id="1787176709638001873">Text úpravy hesla</translation>
 <translation id="1802710350767629429">Zobraziť poznámky k aktualizácii</translation>
-<translation id="1810107444790159527">Pole s ponukou</translation>
+<translation id="1810107444790159527">Zoznamové pole</translation>
 <translation id="1812527064848182527">na šírku</translation>
 <translation id="1828385960365606039">máj</translation>
 <translation id="1834891354138622109">Stĺpec</translation>
@@ -369,7 +369,7 @@
 <translation id="3650317109285159359">chkmnuitm</translation>
 <translation id="3655855170848725876">{COUNT,plural, =1{dolár}few{# znaky dolára}many{# dollar signs}other{# znakov dolára}}</translation>
 <translation id="3659787053479271466">upozornenie</translation>
-<translation id="3665563998540286755"><ph name="VALUE" />, pole zoznamu</translation>
+<translation id="3665563998540286755"><ph name="VALUE" />, zoznamové pole</translation>
 <translation id="3681531118904532409">Papájová</translation>
 <translation id="3687295507293856493">Vykonať odhad v hlavičke stĺpca aktuálnej bunky</translation>
 <translation id="3692274950075847560">V:<ph name="RESULT" /></translation>
@@ -557,7 +557,7 @@
 <translation id="4975416682604111799">milisekundy</translation>
 <translation id="49787999531187221">Rozšírenie ChromeVox je teraz neaktívne</translation>
 <translation id="4979404613699303341">Predchádzajúce tlačidlo</translation>
-<translation id="4982773647088557172"><ph name="VALUE" />, <ph name="NAME" />, pole zoznamu</translation>
+<translation id="4982773647088557172"><ph name="VALUE" />, <ph name="NAME" />, zoznamové pole</translation>
 <translation id="4983588134362688868">Prechod do hornej časti stránky</translation>
 <translation id="4986606102545753256"><ph name="NAME" />, okno</translation>
 <translation id="4993152509206108683">Hodnotenie: <ph name="PERCENT" /> %</translation>
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_ta.xtb b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_ta.xtb
index 2a2bea8..319014f 100644
--- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_ta.xtb
+++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings_ta.xtb
@@ -54,6 +54,7 @@
 <translation id="1319608975892113573">முன் மேற்கோள் குறி இல்லை</translation>
 <translation id="1321576897702511272">ChromeVox உதவியை மறை</translation>
 <translation id="1325946044405407859">டான்</translation>
+<translation id="1331634987653814322">பிரெயில் அமைப்புகள்</translation>
 <translation id="1331702245475014624"><ph name="TOTAL" /> / <ph name="INDEX" /></translation>
 <translation id="1334095593597963605">எழுத்து மற்றும் சொல் எதிரொலி</translation>
 <translation id="1334570596456017464">சப்ஸ்கிரிப்ட்</translation>
@@ -548,6 +549,7 @@
 <translation id="489907760999452556">அக இணைப்பு</translation>
 <translation id="4915087353619183190">’கற்றல் பயன்முறையைத்’ தொடங்குகிறது. அதன் செயல்பாட்டைப் பற்றி அறிய, ஒரு qwerty விசையையோ புதுப்பிக்கக்கூடிய பிரெய்ல் விசையையோ அல்லது தொடு சைகையையோ அழுத்தவும். வெளியேற, 'control + w' அல்லது escape விசையை அழுத்தவும்.</translation>
 <translation id="492295894462528572">அறிமுகம்</translation>
+<translation id="4943781537993885772">காட்சிப்படுத்தும் விதம்</translation>
 <translation id="495170559598752135">செயல்கள்</translation>
 <translation id="4953585991029886728">உரையைத் திருத்து</translation>
 <translation id="4954534434583049121">முந்தைய மேற்கோள் குறி</translation>
@@ -714,6 +716,7 @@
 <translation id="6006050241733874051">படிவம்</translation>
 <translation id="6006064078185310784">{COUNT,plural, =1{பின்கோடு}other{# பின்கோடுகள்}}</translation>
 <translation id="6017514345406065928">பச்சை</translation>
+<translation id="6021969570711251331">ஒன்றன் மேல் ஒன்று காட்சிப்படுத்தப்படும்</translation>
 <translation id="6034000775414344507">வெளிர் சாம்பல்</translation>
 <translation id="6037602951055904232">முன்னோக்கி நகர்த்து</translation>
 <translation id="6042826534790431634">செயல்படுத்த, தேடல்+Space விசைகளை அழுத்தவும்.</translation>
@@ -764,6 +767,7 @@
 <translation id="6438968337250688271"><ph name="NAME" />, மெனு</translation>
 <translation id="6444046323172968959">விழிப்பூட்டல் செய்தி</translation>
 <translation id="6452403590345320472">உள்ளடக்க அட்டவணை</translation>
+<translation id="6454456397828627257">அருகருகே</translation>
 <translation id="6459511626086141404">தட்டையான விசைவரைபடம்</translation>
 <translation id="6468049171101508116">அடுத்த பொத்தான்</translation>
 <translation id="646954774886932461">பொருளடக்கம்</translation>
diff --git a/chrome/browser/resources/chromeos/login/saml_password_attributes.js b/chrome/browser/resources/chromeos/login/saml_password_attributes.js
index d17eaab..0b8d087 100644
--- a/chrome/browser/resources/chromeos/login/saml_password_attributes.js
+++ b/chrome/browser/resources/chromeos/login/saml_password_attributes.js
@@ -17,13 +17,17 @@
   /** @const @private {number} The max length that we are willing to parse. */
   const MAX_SANE_XML_LENGTH = 50 * 1024;  // 50 KB
 
+  /** @const @private {string} Schema name prefix. */
+  const SCHEMA_NAME_PREFIX = 'http://schemas.google.com/saml/2019/';
+
   /** @const @private {string} Schema name for password modified timestamp. */
-  const PASSWORD_MODIFIED_TIMESTAMP_NAME =
-      'http://schemas.google.com/saml/2019/passwordmodifiedtimestamp';
+  const PASSWORD_MODIFIED_TIMESTAMP = 'passwordmodifiedtimestamp';
 
   /** @const @private {string} Schema name for password expiration timestamp. */
-  const PASSWORD_EXPIRATION_TIMESTAMP_NAME =
-      'http://schemas.google.com/saml/2019/passwordexpirationtimestamp';
+  const PASSWORD_EXPIRATION_TIMESTAMP = 'passwordexpirationtimestamp';
+
+  /** @const @private {string} Schema name for password-change URL. */
+  const PASSWORD_CHANGE_URL = 'passwordchangeurl';
 
   /**
    * Query selector for finding an element with tag AttributeValue that is a
@@ -32,13 +36,22 @@
    */
   const QUERY_SELECTOR_FORMAT = 'Attribute[Name="{0}"] > AttributeValue';
 
+  /** Turns a schema name into a query selector to find the AttributeValue. */
+  function makeQuerySelector(schemaName) {
+    return QUERY_SELECTOR_FORMAT.replace(
+        '{0}', SCHEMA_NAME_PREFIX + schemaName);
+  }
+
   /** @const @private {string} Query selector for password modified time. */
   const PASSWORD_MODIFIED_TIMESTAMP_SELECTOR =
-      QUERY_SELECTOR_FORMAT.replace('{0}', PASSWORD_MODIFIED_TIMESTAMP_NAME);
+      makeQuerySelector(PASSWORD_MODIFIED_TIMESTAMP);
 
   /** @const @private {string} Query selector for password expiration time. */
   const PASSWORD_EXPIRATION_TIMESTAMP_SELECTOR =
-      QUERY_SELECTOR_FORMAT.replace('{0}', PASSWORD_EXPIRATION_TIMESTAMP_NAME);
+      makeQuerySelector(PASSWORD_EXPIRATION_TIMESTAMP);
+
+  /** @const @private {string} Query selector for password expiration time. */
+  const PASSWORD_CHANGE_URL_SELECTOR = makeQuerySelector(PASSWORD_CHANGE_URL);
 
   /**
    * Extract password information from the Attribute elements in the given SAML
@@ -49,17 +62,28 @@
   function readPasswordAttributes(xmlStr) {
     if (xmlStr.length < MIN_SANE_XML_LENGTH ||
         xmlStr.length > MAX_SANE_XML_LENGTH) {
-      return new PasswordAttributes(null, null);
+      return new PasswordAttributes(null, null, null);
     }
     const xmlDom = new DOMParser().parseFromString(xmlStr, 'text/xml');
     if (!xmlDom) {
-      return new PasswordAttributes(null, null);
+      return new PasswordAttributes(null, null, null);
     }
 
     return new PasswordAttributes(
         extractTimestampFromXml(xmlDom, PASSWORD_MODIFIED_TIMESTAMP_SELECTOR),
-        extractTimestampFromXml(xmlDom, PASSWORD_EXPIRATION_TIMESTAMP_SELECTOR)
-    );
+        extractTimestampFromXml(xmlDom, PASSWORD_EXPIRATION_TIMESTAMP_SELECTOR),
+        extractStringFromXml(xmlDom, PASSWORD_CHANGE_URL_SELECTOR));
+  }
+
+  /**
+   * Extracts a string from the given XML DOM, using the given query selector.
+   * @param {!XMLDocument} xmlDom The XML DOM.
+   * @param {string} querySelectorStr The query selector to find the string.
+   * @return {?string} The extracted string (null if failed to extract).
+   */
+  function extractStringFromXml(xmlDom, querySelectorStr) {
+    const element = xmlDom.querySelector(querySelectorStr);
+    return (element && element.textContent) ? element.textContent : null;
   }
 
   /**
@@ -70,8 +94,7 @@
    * @return {?Date} The decoded timestamp (null if failed to extract).
    */
   function extractTimestampFromXml(xmlDom, querySelectorStr) {
-    const element = xmlDom.querySelector(querySelectorStr);
-    const valueText = element && element.textContent;
+    const valueText = extractStringFromXml(xmlDom, querySelectorStr);
     return valueText ? samlTimestamps.decodeTimestamp(valueText) : null;
   }
 
@@ -80,12 +103,15 @@
    * @export @final
    */
   class PasswordAttributes {
-    constructor(modifiedTimestamp, expirationTimestamp) {
+    constructor(modifiedTimestamp, expirationTimestamp, passwordChangeUrl) {
       /** @type {?Date} Password last-modified timestamp. */
       this.modifiedTimestamp = modifiedTimestamp;
 
       /** @type {?Date} Password expiration timestamp. */
       this.expirationTimestamp = expirationTimestamp;
+
+      /** @type {?string} Password-change URL. */
+      this.passwordChangeUrl = passwordChangeUrl;
     }
   }
 
diff --git a/chrome/browser/resources/chromeos/login/saml_password_attributes_test.unitjs b/chrome/browser/resources/chromeos/login/saml_password_attributes_test.unitjs
index d03756f6..39b48fc 100644
--- a/chrome/browser/resources/chromeos/login/saml_password_attributes_test.unitjs
+++ b/chrome/browser/resources/chromeos/login/saml_password_attributes_test.unitjs
@@ -45,13 +45,13 @@
 };
 
 let XML_TEST_DATA;
-let XML_TEST_DATA_WITH_TIMESTAMPS_REMOVED;
+let XML_TEST_DATA_WITH_ATTRIBUTES_REMOVED;
 
 const initializeTestData = function(xml_test_data) {
   XML_TEST_DATA = xml_test_data;
   // Strips out the timestamps that are in the <AttributeValue> tags.
-  XML_TEST_DATA_WITH_TIMESTAMPS_REMOVED = XML_TEST_DATA.replace(
-      /<AttributeValue>[0-9]+/g,
+  XML_TEST_DATA_WITH_ATTRIBUTES_REMOVED = XML_TEST_DATA.replace(
+      /<AttributeValue>[^<>]+/g,
       '<AttributeValue>');
 };
 
@@ -60,17 +60,20 @@
   let result = samlPasswordAttributes.readPasswordAttributes('');
   assertEquals(null, result.modifiedTimestamp);
   assertEquals(null, result.expirationTimestamp);
+  assertEquals(null, result.passwordChangeUrl);
 
   // Make sure null is returned for random junk:
   result = samlPasswordAttributes.readPasswordAttributes('<abc></abc>');
   assertEquals(null, result.modifiedTimestamp);
   assertEquals(null, result.expirationTimestamp);
+  assertEquals(null, result.passwordChangeUrl);
 
   // Make sure null is returned when the input is almost valid, but not quite:
   result = samlPasswordAttributes.readPasswordAttributes(
-      XML_TEST_DATA_WITH_TIMESTAMPS_REMOVED);
+      XML_TEST_DATA_WITH_ATTRIBUTES_REMOVED);
   assertEquals(null, result.modifiedTimestamp);
   assertEquals(null, result.expirationTimestamp);
+  assertEquals(null, result.passwordChangeUrl);
 });
 
 TEST_F('SamlPasswordAttributesUnitTest', 'ReadValid', function() {
@@ -80,4 +83,6 @@
                result.modifiedTimestamp.valueOf());
   assertEquals(Date.parse('2019-03-06T11:50:58.421Z'),
                result.expirationTimestamp.valueOf());
+  assertEquals('https://example.com/adfs/portal/updatepassword/',
+               result.passwordChangeUrl);
 });
diff --git a/chrome/browser/resources/chromeos/switch_access/navigation_manager.js b/chrome/browser/resources/chromeos/switch_access/navigation_manager.js
index 912ea2e..bdf66991 100644
--- a/chrome/browser/resources/chromeos/switch_access/navigation_manager.js
+++ b/chrome/browser/resources/chromeos/switch_access/navigation_manager.js
@@ -301,7 +301,8 @@
     if (!this.textInputManager_.enterKeyboard(this.node_))
       return;
 
-    this.selectCurrentNode();
+    chrome.accessibilityPrivate.setVirtualKeyboardVisible(
+        true /* is_visible */);
     this.setScope_(this.textInputManager_.getKeyboard(this.desktop_));
   }
 
@@ -320,6 +321,8 @@
     }
 
     this.textInputManager_.returnToTextFocus();
+    chrome.accessibilityPrivate.setVirtualKeyboardVisible(
+        false /* isVisible */);
     return true;
   }
 
diff --git a/chrome/browser/resources/local_ntp/doodles.js b/chrome/browser/resources/local_ntp/doodles.js
index 89ec7af..9632a182 100644
--- a/chrome/browser/resources/local_ntp/doodles.js
+++ b/chrome/browser/resources/local_ntp/doodles.js
@@ -291,7 +291,6 @@
 
 
 /**
- * TODO(896461): Add more click tracking parameters and testing.
  * Logs a doodle sharing event.
  * Uses the ct param provided in metadata.onClickUrl to track the doodle.
  *
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index bd9a791f..e51029a 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -338,7 +338,6 @@
       alternateLogo: false,
       backgroundColorRgba:
           (isDarkModeEnabled ? [50, 54, 57, 255] : [255, 255, 255, 255]),
-      colorRgba: [255, 255, 255, 255],
       headerColorRgba: [150, 150, 150, 255],
       linkColorRgba: [6, 55, 116, 255],
       sectionBorderColorRgba: [150, 150, 150, 255],
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.js b/chrome/browser/resources/local_ntp/most_visited_single.js
index 8dfe125..fef9f4d4 100644
--- a/chrome/browser/resources/local_ntp/most_visited_single.js
+++ b/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -313,8 +313,9 @@
   if (cmd == 'tile') {
     addTile(data);
   } else if (cmd == 'show') {
-    // TODO(treib): If this happens before we have finished loading the previous
-    // tiles, we probably get into a bad state.
+    // TODO(crbug.com/946225): If this happens before we have finished loading
+    // the previous tiles, we probably get into a bad state. If/when the iframe
+    // is removed this might no longer be a concern.
     showTiles(data);
   } else if (cmd == 'updateTheme') {
     updateTheme(data);
diff --git a/chrome/browser/resources/ntp4/apps_page.js b/chrome/browser/resources/ntp4/apps_page.js
index 72f6795..2336547 100644
--- a/chrome/browser/resources/ntp4/apps_page.js
+++ b/chrome/browser/resources/ntp4/apps_page.js
@@ -90,6 +90,12 @@
       this.createShortcut_.addEventListener(
           'activate', this.onCreateShortcut_.bind(this));
 
+      this.installLocallySeparator_ =
+          menu.appendChild(cr.ui.MenuItem.createSeparator());
+      this.installLocally_ = this.appendMenuItem_('appinstalllocally');
+      this.installLocally_.addEventListener(
+          'activate', this.onInstallLocally_.bind(this));
+
       document.body.appendChild(menu);
     },
 
@@ -175,6 +181,9 @@
 
       this.createShortcutSeparator_.hidden = this.createShortcut_.hidden =
           !app.appData.mayCreateShortcuts;
+
+      this.installLocallySeparator_.hidden = this.installLocally_.hidden =
+          app.appData.isLocallyInstalled;
     },
 
     /** @private */
@@ -230,6 +239,11 @@
     },
 
     /** @private */
+    onInstallLocally_: function() {
+      chrome.send('installAppLocally', [this.app_.appData.id]);
+    },
+
+    /** @private */
     onShowAppInfo_: function() {
       chrome.send('showAppInfo', [this.app_.appData.id]);
     }
diff --git a/chrome/browser/resources/print_preview/new/BUILD.gn b/chrome/browser/resources/print_preview/new/BUILD.gn
index 42b56da..fc5186a 100644
--- a/chrome/browser/resources/print_preview/new/BUILD.gn
+++ b/chrome/browser/resources/print_preview/new/BUILD.gn
@@ -10,6 +10,7 @@
     ":advanced_settings_dialog",
     ":advanced_settings_item",
     ":app",
+    ":button_strip",
     ":color_settings",
     ":copies_settings",
     ":destination_dialog",
@@ -19,6 +20,7 @@
     ":dpi_settings",
     ":duplex_settings",
     ":header",
+    ":header_new",
     ":highlight_utils",
     ":input_behavior",
     ":layout_settings",
@@ -64,12 +66,14 @@
 js_library("print_preview_sidebar") {
   deps = [
     ":advanced_options_settings",
+    ":button_strip",
     ":color_settings",
     ":copies_settings",
     ":destination_settings",
     ":dpi_settings",
     ":duplex_settings",
     ":header",
+    ":header_new",
     ":layout_settings",
     ":link_container",
     ":margins_settings",
@@ -84,17 +88,33 @@
     "..:metrics",
     "../data:destination",
     "//ui/webui/resources/cr_elements:cr_container_shadow_behavior",
+    "//ui/webui/resources/js:load_time_data",
+  ]
+}
+
+js_library("button_strip") {
+  deps = [
+    ":state",
+    "../data:destination",
+    "//ui/webui/resources/js:cr",
   ]
 }
 
 js_library("header") {
   deps = [
-    ":model",
     ":settings_behavior",
     ":state",
     "../data:destination",
     "//ui/webui/resources/js:cr",
-    "//ui/webui/resources/js:load_time_data",
+  ]
+}
+
+js_library("header_new") {
+  deps = [
+    ":settings_behavior",
+    ":state",
+    "../data:destination",
+    "//ui/webui/resources/js:cr",
   ]
 }
 
diff --git a/chrome/browser/resources/print_preview/new/button_strip.html b/chrome/browser/resources/print_preview/new/button_strip.html
new file mode 100644
index 0000000..917c067
--- /dev/null
+++ b/chrome/browser/resources/print_preview/new/button_strip.html
@@ -0,0 +1,53 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="../data/destination.html">
+<link rel="import" href="print_preview_shared_css.html">
+<link rel="import" href="state.html">
+<link rel="import" href="strings.html">
+
+<dom-module id="print-preview-button-strip">
+  <template>
+    <style include="print-preview-shared paper-button-style">
+      :host {
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-end;
+        margin-top: 16px;
+        padding-bottom: 16px;
+        padding-inline-end: 16px;
+      }
+
+      :host-context(html:not([dark])) {
+        background-color: white;
+      }
+
+      :host paper-button:not(:last-child) {
+        margin-inline-end: 8px;
+      }
+
+      :host paper-button:last-child {
+        margin-inline-end: 0;
+      }
+    </style>
+<if expr="not is_win">
+    <paper-button class="cancel-button" on-click="onCancelClick_">
+      $i18n{cancel}
+    </paper-button>
+</if>
+    <paper-button class="action-button" on-click="onPrintClick_"
+        disabled$="[[!printButtonEnabled_]]">
+      [[printButtonLabel_]]
+    </paper-button>
+<if expr="is_win">
+    <paper-button class="cancel-button" on-click="onCancelClick_">
+      $i18n{cancel}
+    </paper-button>
+</if>
+  </template>
+  <script src="button_strip.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/print_preview/new/button_strip.js b/chrome/browser/resources/print_preview/new/button_strip.js
new file mode 100644
index 0000000..66ced12
--- /dev/null
+++ b/chrome/browser/resources/print_preview/new/button_strip.js
@@ -0,0 +1,86 @@
+// Copyright 2019 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.
+
+Polymer({
+  is: 'print-preview-button-strip',
+
+  properties: {
+    /** @type {!print_preview.Destination} */
+    destination: Object,
+
+    /** @type {!print_preview_new.State} */
+    state: {
+      type: Number,
+      observer: 'updatePrintButtonEnabled_',
+    },
+
+    /** @private */
+    printButtonEnabled_: {
+      type: Boolean,
+      value: false,
+    },
+
+    /** @private */
+    printButtonLabel_: {
+      type: String,
+      value: function() {
+        return loadTimeData.getString('printButton');
+      },
+    },
+  },
+
+  observers: ['updatePrintButtonLabel_(destination.id)'],
+
+  /** @private {!print_preview_new.State} */
+  lastState_: print_preview_new.State.NOT_READY,
+
+  /** @private */
+  onPrintClick_: function() {
+    this.fire('print-requested');
+  },
+
+  /** @private */
+  onCancelClick_: function() {
+    this.fire('cancel-requested');
+  },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  isPdfOrDrive_: function() {
+    return this.destination &&
+        (this.destination.id ==
+             print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ||
+         this.destination.id ==
+             print_preview.Destination.GooglePromotedId.DOCS);
+  },
+
+  /** @private */
+  updatePrintButtonLabel_: function() {
+    this.printButtonLabel_ = loadTimeData.getString(
+        this.isPdfOrDrive_() ? 'saveButton' : 'printButton');
+  },
+
+  /** @private */
+  updatePrintButtonEnabled_: function() {
+    switch (this.state) {
+      case (print_preview_new.State.PRINTING):
+        this.printButtonEnabled_ = false;
+        break;
+      case (print_preview_new.State.READY):
+        this.printButtonEnabled_ = true;
+        if (this.lastState_ != this.state &&
+            (document.activeElement == null ||
+             document.activeElement == document.body)) {
+          this.$$('paper-button.action-button').focus();
+        }
+        break;
+      default:
+        this.printButtonEnabled_ = false;
+        break;
+    }
+    this.lastState_ = this.state;
+  },
+});
diff --git a/chrome/browser/resources/print_preview/new/header.html b/chrome/browser/resources/print_preview/new/header.html
index a5feef9..fd39d34 100644
--- a/chrome/browser/resources/print_preview/new/header.html
+++ b/chrome/browser/resources/print_preview/new/header.html
@@ -2,7 +2,6 @@
 
 <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
diff --git a/chrome/browser/resources/print_preview/new/header.js b/chrome/browser/resources/print_preview/new/header.js
index c7bba41..ab6681e 100644
--- a/chrome/browser/resources/print_preview/new/header.js
+++ b/chrome/browser/resources/print_preview/new/header.js
@@ -48,14 +48,12 @@
     /** @private {?string} */
     summary_: {
       type: String,
-      notify: true,
       value: null,
     },
 
     /** @private {?string} */
     summaryLabel_: {
       type: String,
-      notify: true,
       value: null,
     },
   },
diff --git a/chrome/browser/resources/print_preview/new/header_new.html b/chrome/browser/resources/print_preview/new/header_new.html
new file mode 100644
index 0000000..ced5530
--- /dev/null
+++ b/chrome/browser/resources/print_preview/new/header_new.html
@@ -0,0 +1,65 @@
+<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/cr.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="../data/destination.html">
+<link rel="import" href="../icons.html">
+<link rel="import" href="settings_behavior.html">
+<link rel="import" href="print_preview_shared_css.html">
+<link rel="import" href="state.html">
+<link rel="import" href="strings.html">
+
+<dom-module id="print-preview-header-new">
+  <template>
+    <style include="print-preview-shared">
+      :host {
+        align-items: center;
+        display: flex;
+        justify-content: space-between;
+        padding: 20px 16px 12px;
+      }
+
+      :host-context(html:not([dark])) {
+        background-color: white;
+      }
+
+      #headerContainer {
+        align-items: center;
+        display: flex;
+      }
+
+      .summary,
+      .title {
+        color: var(--cr-primary-text-color);
+        line-height: calc(20/13 * 1em);
+        margin: 0;
+      }
+
+      .title {
+        font-size: calc(16/13 * 1em);
+        font-weight: 400;
+      }
+
+      .summary {
+        font-weight: 500;
+      }
+
+      iron-icon {
+        align-self: center;
+        fill: var(--cr-secondary-text-color);
+        height: 16px;
+        margin-inline-start: 8px;
+        width: 16px;
+      }
+    </style>
+    <div id="headerContainer">
+      <h1 class="title">$i18n{title}</h1>
+      <iron-icon hidden$="[[!managed]]" icon="print-preview:business"
+           alt="" title="$i18n{managedSettings}">
+      </iron-icon>
+    </div>
+    <span class="summary" aria-label$="[[summaryLabel_]]">[[summary_]]</span>
+  </template>
+  <script src="header_new.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/print_preview/new/header_new.js b/chrome/browser/resources/print_preview/new/header_new.js
new file mode 100644
index 0000000..9b9926b4
--- /dev/null
+++ b/chrome/browser/resources/print_preview/new/header_new.js
@@ -0,0 +1,159 @@
+// Copyright 2019 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('print_preview.HeaderNew');
+
+/**
+ * @typedef {{numPages: number,
+ *            numSheets: number,
+ *            pagesLabel: string,
+ *            summaryLabel: string}}
+ */
+print_preview.HeaderNew.LabelInfo;
+
+Polymer({
+  is: 'print-preview-header-new',
+
+  behaviors: [SettingsBehavior],
+
+  properties: {
+    cloudPrintErrorMessage: String,
+
+    /** @type {!print_preview.Destination} */
+    destination: Object,
+
+    /** @type {!print_preview_new.Error} */
+    error: Number,
+
+    /** @type {!print_preview_new.State} */
+    state: Number,
+
+    managed: Boolean,
+
+    /** @private {?string} */
+    summary_: {
+      type: String,
+      value: null,
+    },
+
+    /** @private {?string} */
+    summaryLabel_: {
+      type: String,
+      value: null,
+    },
+  },
+
+  observers: [
+    'update_(settings.copies.value, settings.duplex.value, ' +
+        'settings.pages.value, state, destination.id)',
+  ],
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  isPdfOrDrive_: function() {
+    return this.destination &&
+        (this.destination.id ==
+             print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ||
+         this.destination.id ==
+             print_preview.Destination.GooglePromotedId.DOCS);
+  },
+
+  /**
+   * @return {!print_preview.HeaderNew.LabelInfo}
+   * @private
+   */
+  computeLabelInfo_: function() {
+    const saveToPdfOrDrive = this.isPdfOrDrive_();
+    let numPages = this.getSettingValue('pages').length;
+    let numSheets = numPages;
+    if (!saveToPdfOrDrive && this.getSettingValue('duplex')) {
+      numSheets = Math.ceil(numPages / 2);
+    }
+
+    const copies = parseInt(this.getSettingValue('copies'), 10);
+    numSheets *= copies;
+    numPages *= copies;
+
+    const pagesLabel = loadTimeData.getString('printPreviewPageLabelPlural');
+    let summaryLabel;
+    if (numSheets > 1) {
+      summaryLabel = saveToPdfOrDrive ?
+          pagesLabel :
+          loadTimeData.getString('printPreviewSheetsLabelPlural');
+    } else {
+      summaryLabel = loadTimeData.getString(
+          saveToPdfOrDrive ? 'printPreviewPageLabelSingular' :
+                             'printPreviewSheetsLabelSingular');
+    }
+    return {
+      numPages: numPages,
+      numSheets: numSheets,
+      pagesLabel: pagesLabel,
+      summaryLabel: summaryLabel
+    };
+  },
+
+  /** @private */
+  update_: function() {
+    switch (this.state) {
+      case (print_preview_new.State.PRINTING):
+        this.summary_ = loadTimeData.getString(
+            this.isPdfOrDrive_() ? 'saving' : 'printing');
+        this.summaryLabel_ = this.summary_;
+        break;
+      case (print_preview_new.State.READY):
+        const labelInfo = this.computeLabelInfo_();
+        this.summary_ = this.getSummary_(labelInfo);
+        this.summaryLabel_ = this.getSummaryLabel_(labelInfo);
+        break;
+      case (print_preview_new.State.FATAL_ERROR):
+        this.summary_ = this.getErrorMessage_();
+        this.summaryLabel_ = this.getErrorMessage_();
+        break;
+      default:
+        this.summary_ = null;
+        this.summaryLabel_ = null;
+        break;
+    }
+  },
+
+  /**
+   * @return {string} The error message to display.
+   * @private
+   */
+  getErrorMessage_: function() {
+    switch (this.error) {
+      case print_preview_new.Error.PRINT_FAILED:
+        return loadTimeData.getString('couldNotPrint');
+      case print_preview_new.Error.CLOUD_PRINT_ERROR:
+        return this.cloudPrintErrorMessage;
+      default:
+        return '';
+    }
+  },
+
+  /**
+   * @param {!print_preview.HeaderNew.LabelInfo} labelInfo
+   * @return {string}
+   * @private
+   */
+  getSummary_: function(labelInfo) {
+    return loadTimeData.getStringF(
+        'printPreviewNewSummaryFormatShort',
+        labelInfo.numSheets.toLocaleString(), labelInfo.summaryLabel);
+  },
+
+  /**
+   * @param {!print_preview.HeaderNew.LabelInfo} labelInfo
+   * @return {string}
+   * @private
+   */
+  getSummaryLabel_: function(labelInfo) {
+    return loadTimeData.getStringF(
+        'printPreviewNewSummaryFormatShort',
+        labelInfo.numSheets.toLocaleString(), labelInfo.summaryLabel);
+  },
+});
diff --git a/chrome/browser/resources/print_preview/new/print_preview_sidebar.html b/chrome/browser/resources/print_preview/new/print_preview_sidebar.html
index 9ca7ed9c..4e4ad7d 100644
--- a/chrome/browser/resources/print_preview/new/print_preview_sidebar.html
+++ b/chrome/browser/resources/print_preview/new/print_preview_sidebar.html
@@ -3,28 +3,32 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_container_shadow_behavior.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/html/load_time_data.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="../metrics.html">
 <link rel="import" href="../data/destination.html">
-<link rel="import" href="print_preview_shared_css.html">
-<link rel="import" href="strings.html">
-<link rel="import" href="settings_behavior.html">
-<link rel="import" href="state.html">
-<link rel="import" href="header.html">
-<link rel="import" href="destination_settings.html">
-<link rel="import" href="pages_settings.html">
-<link rel="import" href="copies_settings.html">
-<link rel="import" href="layout_settings.html">
+<link rel="import" href="advanced_options_settings.html">
+<link rel="import" href="button_strip.html">
 <link rel="import" href="color_settings.html">
+<link rel="import" href="copies_settings.html">
+<link rel="import" href="destination_settings.html">
+<link rel="import" href="dpi_settings.html">
+<link rel="import" href="duplex_settings.html">
+<link rel="import" href="header.html">
+<link rel="import" href="header_new.html">
+<link rel="import" href="layout_settings.html">
 <link rel="import" href="media_size_settings.html">
 <link rel="import" href="margins_settings.html">
-<link rel="import" href="dpi_settings.html">
-<link rel="import" href="pages_per_sheet_settings.html">
-<link rel="import" href="scaling_settings.html">
-<link rel="import" href="duplex_settings.html">
-<link rel="import" href="other_options_settings.html">
-<link rel="import" href="advanced_options_settings.html">
 <link rel="import" href="more_settings.html">
+<link rel="import" href="other_options_settings.html">
+<link rel="import" href="pages_per_sheet_settings.html">
+<link rel="import" href="pages_settings.html">
+<link rel="import" href="print_preview_shared_css.html">
+<link rel="import" href="scaling_settings.html">
+<link rel="import" href="settings_behavior.html">
+<link rel="import" href="state.html">
+<link rel="import" href="strings.html">
+
 <if expr="not chromeos">
   <link rel="import" href="link_container.html">
 </if>
@@ -46,20 +50,36 @@
         color: var(--cr-primary-text-color);
         flex: 1;
         overflow: overlay;
+      }
+
+      :host(:not([new-print-preview-layout_])) #container {
         padding-bottom: 16px;
       }
 
+      :host([new-print-preview-layout_]) #destinationSettings {
+        margin-top: 12px;
+      }
+
       .settings-section {
         display: block;
         margin-bottom: 16px;
         margin-top: 16px;
       }
     </style>
-    <print-preview-header id="header" destination="[[destination]]"
-        cloud-print-error-message="[[cloudPrintErrorMessage]]"
-        error="[[error]]" state="[[state]]"
-        settings="[[settings]]" managed="[[controlsManaged]]">
-    </print-preview-header>
+    <template is="dom-if" if="[[newPrintPreviewLayout_]]">
+      <print-preview-header-new id="header" destination="[[destination]]"
+          cloud-print-error-message="[[cloudPrintErrorMessage]]"
+          error="[[error]]" state="[[state]]"
+          settings="[[settings]]" managed="[[controlsManaged]]">
+      </print-preview-header-new>
+    </template>
+    <template is="dom-if" if="[[!newPrintPreviewLayout_]]">
+      <print-preview-header id="header" destination="[[destination]]"
+          cloud-print-error-message="[[cloudPrintErrorMessage]]"
+          error="[[error]]" state="[[state]]"
+          settings="[[settings]]" managed="[[controlsManaged]]">
+      </print-preview-header>
+    </template>
     <div id="container">
       <print-preview-destination-settings id="destinationSettings"
           cloud-print-interface="[[cloudPrintInterface]]"
@@ -143,6 +163,11 @@
       </print-preview-link-container>
 </if>
     </div>
+    <template is="dom-if" if="[[newPrintPreviewLayout_]]">
+      <print-preview-button-strip destination="[[destination]]"
+          state="[[state]]">
+      </print-preview-button-strip>
+    </template>
   </template>
   <script src="print_preview_sidebar.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/print_preview/new/print_preview_sidebar.js b/chrome/browser/resources/print_preview/new/print_preview_sidebar.js
index b95a5344..f4eda931 100644
--- a/chrome/browser/resources/print_preview/new/print_preview_sidebar.js
+++ b/chrome/browser/resources/print_preview/new/print_preview_sidebar.js
@@ -45,6 +45,15 @@
       notify: true,
     },
 
+    /** @private {boolean} */
+    newPrintPreviewLayout_: {
+      type: Boolean,
+      value: function() {
+        return loadTimeData.getBoolean('newPrintPreviewLayoutEnabled');
+      },
+      reflectToAttribute: true,
+    },
+
     pageCount: Number,
 
     /** @type {!print_preview_new.State} */
diff --git a/chrome/browser/resources/print_preview/new/scaling_settings.html b/chrome/browser/resources/print_preview/new/scaling_settings.html
index 1daadae..58b147e 100644
--- a/chrome/browser/resources/print_preview/new/scaling_settings.html
+++ b/chrome/browser/resources/print_preview/new/scaling_settings.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/html/md_select_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="number_settings_section.html">
 <link rel="import" href="print_preview_shared_css.html">
 <link rel="import" href="select_behavior.html">
diff --git a/chrome/browser/resources/print_preview/new/scaling_settings.js b/chrome/browser/resources/print_preview/new/scaling_settings.js
index e834886..a852658 100644
--- a/chrome/browser/resources/print_preview/new/scaling_settings.js
+++ b/chrome/browser/resources/print_preview/new/scaling_settings.js
@@ -39,7 +39,8 @@
     /** @private {boolean} */
     customSelected_: {
       type: Boolean,
-      computed: 'computeCustomSelected_(selectedValue)',
+      computed: 'computeCustomSelected_(settings.customScaling.*, ' +
+          'settings.fitToPage.*)',
     },
 
     /** @private {boolean} */
@@ -186,7 +187,9 @@
    * @private
    */
   computeCustomSelected_: function() {
-    return this.selectedValue === ScalingValue.CUSTOM.toString();
+    return /** @type {boolean} */ (this.getSettingValue('customScaling')) &&
+        (!this.getSetting('fitToPage').available ||
+         !(/** @type {boolean} */ (this.getSettingValue('fitToPage'))));
   },
 
   /** @private */
diff --git a/chrome/browser/resources/print_preview/print_preview_resources.grd b/chrome/browser/resources/print_preview/print_preview_resources.grd
index b04bae8..c15bd69 100644
--- a/chrome/browser/resources/print_preview/print_preview_resources.grd
+++ b/chrome/browser/resources/print_preview/print_preview_resources.grd
@@ -194,6 +194,19 @@
       <structure name="IDR_PRINT_PREVIEW_NEW_HEADER_JS"
                  file="new/header.js"
                  type="chrome_html" />
+      <structure name="IDR_PRINT_PREVIEW_NEW_HEADER_NEW_HTML"
+                 file="new/header_new.html"
+                 type="chrome_html" />
+      <structure name="IDR_PRINT_PREVIEW_NEW_HEADER_NEW_JS"
+                 file="new/header_new.js"
+                 type="chrome_html" />
+      <structure name="IDR_PRINT_PREVIEW_NEW_BUTTON_STRIP_HTML"
+                 file="new/button_strip.html"
+                 type="chrome_html"
+                 preprocess="true" />
+      <structure name="IDR_PRINT_PREVIEW_NEW_BUTTON_STRIP_JS"
+                 file="new/button_strip.js"
+                 type="chrome_html" />
       <structure name="IDR_PRINT_PREVIEW_NEW_SETTINGS_BEHAVIOR_HTML"
                  file="new/settings_behavior.html"
                  type="chrome_html" />
diff --git a/chrome/browser/resources/settings/default_browser_page/default_browser_browser_proxy.js b/chrome/browser/resources/settings/default_browser_page/default_browser_browser_proxy.js
index 93f847ef..34fe0350 100644
--- a/chrome/browser/resources/settings/default_browser_page/default_browser_browser_proxy.js
+++ b/chrome/browser/resources/settings/default_browser_page/default_browser_browser_proxy.js
@@ -23,6 +23,7 @@
     /**
      * Get the initial DefaultBrowserInfo and begin sending updates to
      * 'settings.updateDefaultBrowserState'.
+     * @return {!Promise<!DefaultBrowserInfo>}
      */
     requestDefaultBrowserState() {}
 
@@ -39,7 +40,7 @@
   class DefaultBrowserBrowserProxyImpl {
     /** @override */
     requestDefaultBrowserState() {
-      chrome.send('requestDefaultBrowserState');
+      return cr.sendWithPromise('requestDefaultBrowserState');
     }
 
     /** @override */
diff --git a/chrome/browser/resources/settings/default_browser_page/default_browser_page.js b/chrome/browser/resources/settings/default_browser_page/default_browser_page.js
index 39c3f6a..4e3d8eb 100644
--- a/chrome/browser/resources/settings/default_browser_page/default_browser_page.js
+++ b/chrome/browser/resources/settings/default_browser_page/default_browser_page.js
@@ -40,7 +40,8 @@
         'browser-default-state-changed',
         this.updateDefaultBrowserState_.bind(this));
 
-    this.browserProxy_.requestDefaultBrowserState();
+    this.browserProxy_.requestDefaultBrowserState().then(
+        this.updateDefaultBrowserState_.bind(this));
   },
 
   /**
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html
index 207dff3..ba44641 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.html
+++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -359,7 +359,7 @@
             </template>
           </div>
           <div class="settings-box continuation" on-click="onEditDictionaryTap_"
-              actionable>
+              actionable id="spellCheckSubpageTrigger">
             <div class="start settings-box-text" id="customSpelling">
               $i18n{manageSpellCheck}
             </div>
@@ -440,10 +440,12 @@
       </template>
 </if>
 <if expr="not is_macosx">
-      <template is="dom-if" route-path="/editDictionary">
+      <template is="dom-if" route-path="/editDictionary"
+           no-search="[[!prefs.browser.enable_spellchecking.value]]">
         <settings-subpage
             associated-control="[[$$('#spellCheckSubpageTrigger')]]"
-            page-title="$i18n{editDictionaryPageTitle}">
+            page-title="$i18n{editDictionaryPageTitle}"
+            no-search$="[[!prefs.browser.enable_spellchecking.value]]">
           <settings-edit-dictionary-page></settings-edit-dictionary-page>
         </settings-subpage>
       </template>
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.js b/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.js
index aceca3f..1ed18ce 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.js
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.js
@@ -312,16 +312,14 @@
       return '';
     }
 
-    let msg = this.i18n('securityKeysPINIncorrect');
     // Warn the user if the number of retries is getting low.
     if (1 < retries && retries <= 3) {
-      msg += ' ' +
-          this.i18n(
-              'securityKeysCurrentPINRetriesPl', this.retries_.toString());
-    } else if (retries == 1) {
-      msg += ' ' + this.i18n('securityKeysCurrentPINRetriesSin');
+      return this.i18n('securityKeysPINIncorrectRetriesPl', retries.toString());
     }
-    return msg;
+    if (retries == 1) {
+      return this.i18n('securityKeysPINIncorrectRetriesSin');
+    }
+    return this.i18n('securityKeysPINIncorrect');
   },
 
   /**
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/BUILD.gn b/chrome/browser/resources/welcome/onboarding_welcome/BUILD.gn
index f70ea59..7e37a64 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/BUILD.gn
+++ b/chrome/browser/resources/welcome/onboarding_welcome/BUILD.gn
@@ -67,7 +67,6 @@
     "./shared:bookmark_proxy",
     "./shared:nux_types",
     "//ui/webui/resources/cr_elements/cr_view_manager:cr_view_manager",
-    "//ui/webui/resources/js:cr",
     "//ui/webui/resources/js:promise_resolver",
   ]
 }
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/email_app_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/email/email_app_proxy.js
index 6538691..d0bc4e52 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/email/email_app_proxy.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/email/email_app_proxy.js
@@ -5,16 +5,6 @@
 cr.define('nux', function() {
   /** @implements {nux.AppProxy} */
   class EmailAppProxyImpl {
-    constructor() {
-      /** @private {number} */
-      this.savedProvider_;
-    }
-
-    /** @return {number} */
-    getSavedProvider() {
-      return this.savedProvider_;
-    }
-
     /** @override */
     cacheBookmarkIcon(emailProviderId) {
       chrome.send('cacheEmailIcon', [emailProviderId]);
@@ -27,7 +17,6 @@
 
     /** @override */
     recordProviderSelected(providerId) {
-      this.savedProvider_ = providerId;
       chrome.metricsPrivate.recordEnumerationValue(
           'FirstRun.NewUserExperience.EmailProvidersSelection', providerId,
           loadTimeData.getInteger('email_providers_enum_count'));
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/blue_circle.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/blue_circle.svg
index 063f16a..e177d8c 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/blue_circle.svg
+++ b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/blue_circle.svg
@@ -1 +1 @@
-<svg width="43" height="43" xmlns="http://www.w3.org/2000/svg"><circle fill="#1A73E8" fill-rule="evenodd" cx="21.5" cy="21.5" r="21.5"/></svg>
\ No newline at end of file
+<svg width="43" height="43" xmlns="http://www.w3.org/2000/svg"><circle fill-rule="evenodd" cx="21.5" cy="21.5" r="21.5"/></svg>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/green_rectangle.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/green_rectangle.svg
index 90ddf6d..ca840fb1 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/green_rectangle.svg
+++ b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/green_rectangle.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="371" height="371"><path fill="#31A753" fill-rule="evenodd" d="M7.61 166.895L166.896 7.611c10.148-10.148 26.6-10.148 36.748 0l159.293 159.292c10.147 10.148 10.147 26.6 0 36.748L203.65 362.936c-10.147 10.147-26.6 10.147-36.748 0L7.611 203.643c-10.148-10.147-10.148-26.6 0-36.748z"/></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="371" height="371"><path fill-rule="evenodd" d="M7.61 166.895L166.896 7.611c10.148-10.148 26.6-10.148 36.748 0l159.293 159.292c10.147 10.148 10.147 26.6 0 36.748L203.65 362.936c-10.147 10.147-26.6 10.147-36.748 0L7.611 203.643c-10.148-10.147-10.148-26.6 0-36.748z"/></svg>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/grey_oval.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/grey_oval.svg
index 8e01574..e45a4973f 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/grey_oval.svg
+++ b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/grey_oval.svg
@@ -1 +1 @@
-<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><circle fill-rule="evenodd" fill="#F1F3F4" cx="50" cy="50" r="50"/></svg>
\ No newline at end of file
+<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><circle fill-rule="evenodd" cx="50" cy="50" r="50"/></svg>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/grey_rounded_rectangle.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/grey_rounded_rectangle.svg
index 735737c..8154764d 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/grey_rounded_rectangle.svg
+++ b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/grey_rounded_rectangle.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="132" height="132"><path fill="#F1F3F4" fill-rule="evenodd" d="M81.603 14l36.396 36.397c18.668 18.668 18.668 48.935 0 67.602-18.667 18.668-48.934 18.668-67.602 0L14.001 81.603C-4.667 62.935-4.667 32.668 14 14 32.668-4.667 62.935-4.667 81.603 14z"/></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="132" height="132"><path fill-rule="evenodd" d="M81.603 14l36.396 36.397c18.668 18.668 18.668 48.935 0 67.602-18.667 18.668-48.934 18.668-67.602 0L14.001 81.603C-4.667 62.935-4.667 32.668 14 14 32.668-4.667 62.935-4.667 81.603 14z"/></svg>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/red_triangle.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/red_triangle.svg
index ddf10e2..cc7e87d 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/red_triangle.svg
+++ b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/red_triangle.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="65" height="74"><path fill="#E94235" fill-rule="evenodd" d="M64.543 7.293l-.179 60.641c-.202 3.407-3.093 6.003-6.458 5.798a6.05 6.05 0 0 1-2.686-.817L3.607 42.751c-2.92-1.706-3.92-5.485-2.234-8.44a6.149 6.149 0 0 1 1.923-2.067l51.79-30.477c2.814-1.88 6.6-1.096 8.458 1.751a6.236 6.236 0 0 1 .999 3.775z"/></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="65" height="74"><path fill-rule="evenodd" d="M64.543 7.293l-.179 60.641c-.202 3.407-3.093 6.003-6.458 5.798a6.05 6.05 0 0 1-2.686-.817L3.607 42.751c-2.92-1.706-3.92-5.485-2.234-8.44a6.149 6.149 0 0 1 1.923-2.067l51.79-30.477c2.814-1.88 6.6-1.096 8.458 1.751a6.236 6.236 0 0 1 .999 3.775z"/></svg>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/yellow_dots.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/yellow_dots.svg
index c8fe779..cba006f 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/yellow_dots.svg
+++ b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/yellow_dots.svg
@@ -1 +1 @@
-<svg width="76" height="57" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd" fill="#FDD663"><circle cx="14" cy="13" r="2"/><circle cx="14" cy="2" r="2"/><circle cx="14" cy="23" r="2"/><circle cx="14" cy="34" r="2"/><circle cx="14" cy="45" r="2"/><circle cx="14" cy="55" r="2"/><circle cx="2" cy="13" r="2"/><circle cx="2" cy="2" r="2"/><circle cx="2" cy="23" r="2"/><circle cx="2" cy="34" r="2"/><circle cx="2" cy="45" r="2"/><circle cx="2" cy="55" r="2"/><circle cx="26" cy="13" r="2"/><circle cx="26" cy="2" r="2"/><circle cx="26" cy="23" r="2"/><circle cx="26" cy="34" r="2"/><circle cx="26" cy="45" r="2"/><circle cx="26" cy="55" r="2"/><circle cx="38" cy="13" r="2"/><circle cx="38" cy="2" r="2"/><circle cx="38" cy="23" r="2"/><circle cx="38" cy="34" r="2"/><circle cx="38" cy="45" r="2"/><circle cx="38" cy="55" r="2"/><circle cx="50" cy="13" r="2"/><circle cx="50" cy="2" r="2"/><circle cx="50" cy="23" r="2"/><circle cx="50" cy="34" r="2"/><circle cx="50" cy="45" r="2"/><circle cx="50" cy="55" r="2"/><circle cx="62" cy="13" r="2"/><circle cx="62" cy="2" r="2"/><circle cx="62" cy="23" r="2"/><circle cx="62" cy="34" r="2"/><circle cx="62" cy="45" r="2"/><circle cx="62" cy="55" r="2"/><circle cx="74" cy="13" r="2"/><circle cx="74" cy="2" r="2"/><circle cx="74" cy="23" r="2"/><circle cx="74" cy="34" r="2"/><circle cx="74" cy="45" r="2"/><circle cx="74" cy="55" r="2"/></g></svg>
\ No newline at end of file
+<svg width="76" height="57" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><circle cx="14" cy="13" r="2"/><circle cx="14" cy="2" r="2"/><circle cx="14" cy="23" r="2"/><circle cx="14" cy="34" r="2"/><circle cx="14" cy="45" r="2"/><circle cx="14" cy="55" r="2"/><circle cx="2" cy="13" r="2"/><circle cx="2" cy="2" r="2"/><circle cx="2" cy="23" r="2"/><circle cx="2" cy="34" r="2"/><circle cx="2" cy="45" r="2"/><circle cx="2" cy="55" r="2"/><circle cx="26" cy="13" r="2"/><circle cx="26" cy="2" r="2"/><circle cx="26" cy="23" r="2"/><circle cx="26" cy="34" r="2"/><circle cx="26" cy="45" r="2"/><circle cx="26" cy="55" r="2"/><circle cx="38" cy="13" r="2"/><circle cx="38" cy="2" r="2"/><circle cx="38" cy="23" r="2"/><circle cx="38" cy="34" r="2"/><circle cx="38" cy="45" r="2"/><circle cx="38" cy="55" r="2"/><circle cx="50" cy="13" r="2"/><circle cx="50" cy="2" r="2"/><circle cx="50" cy="23" r="2"/><circle cx="50" cy="34" r="2"/><circle cx="50" cy="45" r="2"/><circle cx="50" cy="55" r="2"/><circle cx="62" cy="13" r="2"/><circle cx="62" cy="2" r="2"/><circle cx="62" cy="23" r="2"/><circle cx="62" cy="34" r="2"/><circle cx="62" cy="45" r="2"/><circle cx="62" cy="55" r="2"/><circle cx="74" cy="13" r="2"/><circle cx="74" cy="2" r="2"/><circle cx="74" cy="23" r="2"/><circle cx="74" cy="34" r="2"/><circle cx="74" cy="45" r="2"/><circle cx="74" cy="55" r="2"/></g></svg>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/yellow_semicircle.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/yellow_semicircle.svg
index 706e2fb5..027d197 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/yellow_semicircle.svg
+++ b/chrome/browser/resources/welcome/onboarding_welcome/images/background_svgs/yellow_semicircle.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="211" height="171"><path fill="#FACF4C" fill-rule="evenodd" d="M152.955 155.323c-50.494 29.359-113.79 16.16-148.937-28.546-3.49-4.44-9.18-14.48 5.866-23.227L182.612 3.12c13.636-7.93 17.444 1.232 19.311 5.688 22.418 53.517 2.273 116.722-48.968 146.515z"/></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="211" height="171"><path fill-rule="evenodd" d="M152.955 155.323c-50.494 29.359-113.79 16.16-148.937-28.546-3.49-4.44-9.18-14.48 5.866-23.227L182.612 3.12c13.636-7.93 17.444 1.232 19.311 5.688 22.418 53.517 2.273 116.722-48.968 146.515z"/></svg>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_illustration_1x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_illustration_1x.png
deleted file mode 100644
index 2624306..0000000
--- a/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_illustration_1x.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_illustration_2x.png b/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_illustration_2x.png
deleted file mode 100644
index ff642c38..0000000
--- a/chrome/browser/resources/welcome/onboarding_welcome/images/set_as_default_illustration_2x.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/set_default_dark.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/set_default_dark.svg
new file mode 100644
index 0000000..c17a6050
--- /dev/null
+++ b/chrome/browser/resources/welcome/onboarding_welcome/images/set_default_dark.svg
@@ -0,0 +1 @@
+<svg width="454" height="185" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path id="a" d="M.707.43h56.32v56.32H.707z"/><path d="M7.527 0C3.668 0 .528 3.14.528 7v126c0 3.86 3.14 7 6.999 7h213c3.86 0 7-3.14 7-7V7c0-3.86-3.14-7-7-7" id="c"/><path d="M7.527 0C3.668 0 .528 3.14.528 7v126c0 3.86 3.14 7 6.999 7h213c3.86 0 7-3.14 7-7V7c0-3.86-3.14-7-7-7h-213z" id="e"/><path d="M7.527 0C3.668 0 .528 3.14.528 7v126c0 3.86 3.14 7 6.999 7h213c3.86 0 7-3.14 7-7V7c0-3.86-3.14-7-7-7" id="g"/><path d="M7.527 0C3.668 0 .528 3.14.528 7v126c0 3.86 3.14 7 6.999 7h213c3.86 0 7-3.14 7-7V7c0-3.86-3.14-7-7-7" id="i"/></defs><g fill="none" fill-rule="evenodd"><path d="M292.172 9.494l-38.26 10.251c-2.134.572-2.848 3.24-1.286 4.802l28.008 28.008c1.562 1.562 4.23.847 4.802-1.287l10.252-38.259c.57-2.134-1.382-4.087-3.516-3.515l-38.26 10.251c-2.134.572-2.848 3.24-1.286 4.802l28.008 28.008c1.562 1.562 4.23.847 4.802-1.287l10.252-38.259c.57-2.134-1.382-4.087-3.516-3.515" fill="#F1F3F4"/><path d="M90.398 148.926c-1.172.677-1.51 2.225-.714 3.32 7.039 9.677 20.395 12.674 30.99 6.557 10.595-6.117 14.678-19.182 9.815-30.117-.549-1.237-2.059-1.718-3.231-1.04l-36.86 21.28zM359.03 138.41l-28.754 28.755a3.115 3.115 0 0 1-4.406 0l-28.754-28.754a3.115 3.115 0 0 1 0-4.406l28.754-28.754a3.117 3.117 0 0 1 4.406 0l28.754 28.754a3.115 3.115 0 0 1 0 4.406" fill="#3C4043"/><g transform="translate(116 -.43)"><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><path d="M57.027 28.59c0 15.553-12.607 28.16-28.16 28.16-15.552 0-28.16-12.607-28.16-28.16C.707 13.038 13.315.43 28.867.43c15.553 0 28.16 12.608 28.16 28.16" fill="#3C4043" mask="url(#b)"/></g><path d="M112.527 168.57c-3.859 0-7-3.14-7-7v-126c0-3.86 3.141-7 7-7h213c3.86 0 7 3.14 7 7v126c0 3.86-3.14 7-7 7h-213z" fill="#202124"/><g><g transform="translate(105 28.57)"><mask id="d" fill="#fff"><use xlink:href="#c"/></mask><path d="M186.408-14.069L152.47-4.976c-1.892.508-2.527 2.874-1.14 4.26l24.843 24.844c1.386 1.386 3.753.751 4.26-1.142l9.093-33.937c.507-1.893-1.225-3.625-3.118-3.118L152.47-4.976c-1.892.508-2.527 2.874-1.14 4.26l24.843 24.844c1.386 1.386 3.753.751 4.26-1.142l9.093-33.937c.507-1.893-1.225-3.625-3.118-3.118" fill="#E74133" mask="url(#d)"/></g><g transform="translate(105 28.57)"><mask id="f" fill="#fff"><use xlink:href="#e"/></mask><path d="M-15.803 120.8c-1.191.688-1.535 2.261-.726 3.373 7.154 9.836 20.727 12.881 31.495 6.665 10.768-6.217 14.917-19.495 9.976-30.608-.56-1.257-2.093-1.745-3.284-1.058L-15.803 120.8z" fill="#81C995" mask="url(#f)"/></g><g transform="translate(105 28.57)"><mask id="h" fill="#fff"><use xlink:href="#g"/></mask><path d="M252.702 109.755l-28.26 28.261a3.062 3.062 0 0 1-4.332 0l-28.262-28.26a3.064 3.064 0 0 1 0-4.332l28.262-28.26a3.062 3.062 0 0 1 4.331 0l28.261 28.26a3.064 3.064 0 0 1 0 4.331" fill="#FDDB79" mask="url(#h)"/></g><g transform="translate(105 28.57)"><mask id="j" fill="#fff"><use xlink:href="#i"/></mask><path d="M68.027-.25c0 15.464-12.536 28-28 28s-28-12.536-28-28 12.536-28 28-28 28 12.536 28 28" fill="#8AB4F8" mask="url(#j)"/></g></g><g><path d="M328.527 161.57a3 3 0 0 1-3 3h-213a3 3 0 0 1-3-3v-126a3 3 0 0 1 3-3h213a3 3 0 0 1 3 3v126zm4.5-141.5h-228a6.508 6.508 0 0 0-6.5 6.5v153.5h241V26.57c0-3.584-2.916-6.5-6.5-6.5z" fill="#3C4043"/><path d="M98.527 180.07V26.57c0-3.584 2.916-6.5 6.5-6.5h228c3.584 0 6.5 2.916 6.5 6.5v153.5h-241z" stroke="#202124" stroke-width="2"/><path d="M220.527 26.57a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0" fill="#DADCE0"/><path d="M325.527 176.57h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5M307.527 176.57h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5M289.527 176.57h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5M124.527 176.57h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5M142.527 176.57h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5M160.527 176.57h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5M271.527 176.57h-105a1.5 1.5 0 0 0-1.5 1.5h108a1.5 1.5 0 0 0-1.5-1.5" fill="#202124"/><path d="M222.027 86.382c6.316 0 11.438 5.121 11.438 11.438s-5.122 11.438-11.438 11.438c-6.316 0-11.438-5.121-11.438-11.438s5.122-11.438 11.438-11.438" fill="#F1F1F1"/><path d="M217.527 97.82a7.5 7.5 0 0 1 7.5-7.5h14.701c-2.73-5.342-8.289-9-14.7-9-5.826 0-10.945 3.019-13.882 7.576v12.674h7.386l.001-.001a7.455 7.455 0 0 1-1.006-3.749" fill="#E74133"/><path d="M225.027 105.32a7.496 7.496 0 0 1-6.494-3.75l-7.389-12.671a16.424 16.424 0 0 0-2.617 8.921c0 8.853 6.973 16.077 15.726 16.481l7.271-7.271v-5.46h-.003a7.496 7.496 0 0 1-6.494 3.75" fill="#32A753"/><path d="M239.729 90.32h-14.701a7.5 7.5 0 0 1 6.495 11.248l.002.002-7.28 12.731c.259.012.52.019.783.019 9.112 0 16.5-7.387 16.5-16.5 0-2.701-.65-5.25-1.8-7.5" fill="#F9BB00"/><path d="M225.027 91.82a6 6 0 0 1 0 12 6 6 0 0 1 0-12" fill="#4285F4"/><path d="M81.027 184.57c-1.103 0-2-.897-2-2v-3a.5.5 0 0 1 .5-.5h279a.5.5 0 0 1 .5.5v3c0 1.103-.897 2-2 2h-276zM376.788 48.278c-1.15 1.04-1.092 2.885.145 3.822 5.88 4.453 14.278 4.246 19.948-.884 5.67-5.13 6.714-13.466 2.87-19.76-.81-1.324-2.64-1.567-3.79-.526l-19.173 17.348zM423.668 162.996c-.307 6.134-5.528 10.86-11.663 10.552-6.134-.306-10.858-5.528-10.552-11.662.307-6.135 5.528-10.859 11.662-10.553 6.135.307 10.859 5.53 10.553 11.663" fill="#3C4043"/><path d="M373.426 95.324l.34-6.812c.077-1.538-1.54-2.582-2.91-1.88l-6.07 3.111c-1.37.703-1.465 2.625-.172 3.46l5.729 3.701c1.293.836 3.006-.042 3.083-1.58l.34-6.812c.077-1.538-1.54-2.582-2.91-1.88l-6.07 3.111c-1.37.703-1.465 2.625-.172 3.46l5.729 3.701c1.293.836 3.006-.042 3.083-1.58" fill="#4285F4"/><path d="M67.022 136.045a4.5 4.5 0 1 1-8.99-.45 4.5 4.5 0 0 1 8.99.45" fill="#81C995"/><path d="M28.022 68.045a4.5 4.5 0 1 1-8.99-.45 4.5 4.5 0 0 1 8.99.45" fill="#FDDB79"/><path d="M426.024 87.47a2.999 2.999 0 0 1-3.147 2.846 2.999 2.999 0 1 1 3.146-2.846" fill="#3C4043"/><path d="M441.376 117.08a4 4 0 1 0 5.412 5.892l5.891-5.412a4 4 0 0 0-5.412-5.892l-5.891 5.413z" fill="#EE675C"/><path d="M13.507 125.467c4.518-2.411 6.563-7.644 5.12-12.363a1.701 1.701 0 0 0-2.427-1.013L.897 120.256a1.703 1.703 0 0 0-.511 2.58c3.117 3.827 8.602 5.042 13.12 2.631M67.06 68.092l-4.362-4.362c-2.266-2.266-2.266-5.973 0-8.24 2.266-2.265 5.973-2.265 8.24 0l4.361 4.363c2.266 2.265 2.266 5.973 0 8.239-2.266 2.266-5.973 2.266-8.239 0" fill="#3C4043"/></g></g></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/images/set_default_light.svg b/chrome/browser/resources/welcome/onboarding_welcome/images/set_default_light.svg
new file mode 100644
index 0000000..e2cf756
--- /dev/null
+++ b/chrome/browser/resources/welcome/onboarding_welcome/images/set_default_light.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="454" height="185"><defs><path id="a" d="M.707.43h56.32v56.32H.707z"/><path id="c" d="M7.527 0C3.668 0 .528 3.14.528 7v126c0 3.86 3.14 7 6.999 7h213c3.86 0 7-3.14 7-7V7c0-3.86-3.14-7-7-7"/><path id="e" d="M7.527 0C3.668 0 .528 3.14.528 7v126c0 3.86 3.14 7 6.999 7h213c3.86 0 7-3.14 7-7V7c0-3.86-3.14-7-7-7h-213z"/><path id="g" d="M7.527 0C3.668 0 .528 3.14.528 7v126c0 3.86 3.14 7 6.999 7h213c3.86 0 7-3.14 7-7V7c0-3.86-3.14-7-7-7"/><path id="i" d="M7.527 0C3.668 0 .528 3.14.528 7v126c0 3.86 3.14 7 6.999 7h213c3.86 0 7-3.14 7-7V7c0-3.86-3.14-7-7-7"/></defs><g fill="none" fill-rule="evenodd"><path fill="#F1F3F4" d="M292.172 9.494l-38.26 10.251c-2.134.572-2.848 3.24-1.286 4.802l28.008 28.008c1.562 1.562 4.23.847 4.802-1.287l10.252-38.259c.57-2.134-1.382-4.087-3.516-3.515l-38.26 10.251c-2.134.572-2.848 3.24-1.286 4.802l28.008 28.008c1.562 1.562 4.23.847 4.802-1.287l10.252-38.259c.57-2.134-1.382-4.087-3.516-3.515M90.398 148.926c-1.172.677-1.51 2.225-.714 3.32 7.039 9.677 20.395 12.674 30.99 6.557 10.595-6.117 14.678-19.182 9.815-30.117-.549-1.237-2.059-1.718-3.231-1.04l-36.86 21.28zm268.632-10.515l-28.754 28.754a3.115 3.115 0 0 1-4.406 0l-28.754-28.754a3.115 3.115 0 0 1 0-4.406l28.754-28.754a3.117 3.117 0 0 1 4.406 0l28.754 28.754a3.115 3.115 0 0 1 0 4.406"/><g transform="translate(116 -.43)"><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><path fill="#F1F3F4" d="M57.027 28.59c0 15.553-12.607 28.16-28.16 28.16-15.552 0-28.16-12.607-28.16-28.16C.707 13.038 13.315.43 28.867.43c15.553 0 28.16 12.608 28.16 28.16" mask="url(#b)"/></g><path fill="#FFF" d="M112.527 168.57c-3.859 0-7-3.14-7-7v-126c0-3.86 3.141-7 7-7h213c3.86 0 7 3.14 7 7v126c0 3.86-3.14 7-7 7h-213z"/><g transform="translate(105 28.57)"><mask id="d" fill="#fff"><use xlink:href="#c"/></mask><path fill="#E74133" d="M186.408-14.069L152.47-4.976c-1.892.508-2.527 2.874-1.14 4.26l24.843 24.844c1.386 1.386 3.753.751 4.26-1.142l9.093-33.937c.507-1.893-1.225-3.625-3.118-3.118L152.47-4.976c-1.892.508-2.527 2.874-1.14 4.26l24.843 24.844c1.386 1.386 3.753.751 4.26-1.142l9.093-33.937c.507-1.893-1.225-3.625-3.118-3.118" mask="url(#d)"/><mask id="f" fill="#fff"><use xlink:href="#e"/></mask><path fill="#32A753" d="M-15.803 120.8c-1.191.688-1.535 2.261-.726 3.373 7.154 9.836 20.727 12.881 31.495 6.665 10.768-6.217 14.917-19.495 9.976-30.608-.56-1.257-2.093-1.745-3.284-1.058L-15.803 120.8z" mask="url(#f)"/><mask id="h" fill="#fff"><use xlink:href="#g"/></mask><path fill="#F9BB00" d="M252.702 109.755l-28.26 28.261a3.062 3.062 0 0 1-4.332 0l-28.262-28.26a3.064 3.064 0 0 1 0-4.332l28.262-28.26a3.062 3.062 0 0 1 4.331 0l28.261 28.26a3.064 3.064 0 0 1 0 4.331" mask="url(#h)"/><mask id="j" fill="#fff"><use xlink:href="#i"/></mask><path fill="#4285F4" d="M68.027-.25c0 15.464-12.536 28-28 28s-28-12.536-28-28 12.536-28 28-28 28 12.536 28 28" mask="url(#j)"/></g><g><path fill="#F1F3F4" d="M328.527 161.57a3 3 0 0 1-3 3h-213a3 3 0 0 1-3-3v-126a3 3 0 0 1 3-3h213a3 3 0 0 1 3 3v126zm4.5-141.5h-228a6.508 6.508 0 0 0-6.5 6.5v153.5h241V26.57c0-3.584-2.916-6.5-6.5-6.5z"/><path stroke="#DADCE0" stroke-width="2" d="M98.527 180.07V26.57c0-3.584 2.916-6.5 6.5-6.5h228c3.584 0 6.5 2.916 6.5 6.5v153.5h-241z"/><path fill="#DADCE0" d="M220.527 26.57a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m105 150h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5m-18 0h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5m-18 0h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5m-165 0h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5m18 0h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5m18 0h-12a1.5 1.5 0 0 0-1.5 1.5h15a1.5 1.5 0 0 0-1.5-1.5m111 0h-105a1.5 1.5 0 0 0-1.5 1.5h108a1.5 1.5 0 0 0-1.5-1.5"/><path fill="#F1F1F1" d="M219.027 86.382c6.316 0 11.438 5.121 11.438 11.438s-5.122 11.438-11.438 11.438c-6.316 0-11.438-5.121-11.438-11.438s5.122-11.438 11.438-11.438"/><path fill="#E74133" d="M217.527 97.82a7.5 7.5 0 0 1 7.5-7.5h14.701c-2.73-5.342-8.289-9-14.7-9-5.826 0-10.945 3.019-13.882 7.576v12.674h7.386l.001-.001a7.455 7.455 0 0 1-1.006-3.749"/><path fill="#32A753" d="M225.027 105.32a7.496 7.496 0 0 1-6.494-3.75l-7.389-12.671a16.424 16.424 0 0 0-2.617 8.921c0 8.853 6.973 16.077 15.726 16.481l7.271-7.271v-5.46h-.003a7.496 7.496 0 0 1-6.494 3.75"/><path fill="#F9BB00" d="M239.729 90.32h-14.701a7.5 7.5 0 0 1 6.495 11.248l.002.002-7.28 12.731c.259.012.52.019.783.019 9.112 0 16.5-7.387 16.5-16.5 0-2.701-.65-5.25-1.8-7.5"/><path fill="#4285F4" d="M225.027 91.82a6 6 0 0 1 0 12 6 6 0 0 1 0-12"/><path fill="#F1F3F4" d="M81.027 184.57c-1.103 0-2-.897-2-2v-3a.5.5 0 0 1 .5-.5h279a.5.5 0 0 1 .5.5v3c0 1.103-.897 2-2 2h-276zM376.788 48.278c-1.15 1.04-1.092 2.884.145 3.821 5.88 4.453 14.278 4.246 19.948-.884 5.67-5.13 6.714-13.466 2.87-19.76-.81-1.324-2.64-1.567-3.79-.526l-19.173 17.348zm46.88 114.718c-.307 6.134-5.528 10.86-11.663 10.552-6.134-.306-10.858-5.528-10.552-11.662.307-6.135 5.528-10.859 11.662-10.553 6.135.307 10.859 5.53 10.553 11.663"/><path fill="#4285F4" d="M373.426 95.324l.34-6.812c.077-1.538-1.54-2.582-2.91-1.88l-6.07 3.111c-1.37.703-1.465 2.625-.172 3.46l5.729 3.701c1.293.836 3.006-.042 3.083-1.58l.34-6.812c.077-1.538-1.54-2.582-2.91-1.88l-6.07 3.111c-1.37.703-1.465 2.625-.172 3.46l5.729 3.701c1.293.836 3.006-.042 3.083-1.58"/><path fill="#32A753" d="M67.022 136.045a4.5 4.5 0 1 1-8.99-.45 4.5 4.5 0 0 1 8.99.45"/><path fill="#F9BB00" d="M28.022 68.045a4.5 4.5 0 1 1-8.99-.45 4.5 4.5 0 0 1 8.99.45"/><path fill="#F1F3F4" d="M426.024 87.47a2.999 2.999 0 0 1-3.147 2.846 2.999 2.999 0 1 1 3.146-2.846"/><path fill="#E74133" d="M441.376 117.08a4 4 0 1 0 5.412 5.892l5.891-5.412a4 4 0 0 0-5.412-5.892l-5.891 5.413z"/><path fill="#F1F3F4" d="M13.507 125.467c4.518-2.411 6.563-7.644 5.12-12.363a1.701 1.701 0 0 0-2.427-1.013L.897 120.256a1.703 1.703 0 0 0-.511 2.58c3.117 3.827 8.602 5.042 13.12 2.631M67.06 68.092l-4.362-4.362c-2.266-2.266-2.266-5.973 0-8.24 2.266-2.265 5.973-2.265 8.24 0l4.361 4.363c2.266 2.265 2.266 5.973 0 8.239-2.266 2.266-5.973 2.266-8.239 0"/></g></g></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd b/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd
index 0017267..2f3f089 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd
+++ b/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd
@@ -107,18 +107,20 @@
       <include name="IDR_NUX_NTP_BACKGROUND_THUMBNAIL_LANDSCAPE"
                file="images\ntp_thumbnails\landscape.jpg"
                type="BINDATA" />
-      <include name="IDR_NUX_SET_AS_DEFAULT_ILLUSTRATION_1X"
-               file="images\set_as_default_illustration_1x.png"
-               type="BINDATA" />
-      <include name="IDR_NUX_SET_AS_DEFAULT_ILLUSTRATION_2X"
-               file="images\set_as_default_illustration_2x.png"
-               type="BINDATA" />
       <include name="IDR_NUX_SET_AS_DEFAULT_LOGO_1X"
                file="images\set_as_default_1x.png"
                type="BINDATA" />
       <include name="IDR_NUX_SET_AS_DEFAULT_LOGO_2X"
                file="images\set_as_default_2x.png"
                type="BINDATA" />
+      <include name="IDR_NUX_SET_DEFAULT_DARK"
+               file="images\set_default_dark.svg"
+               compress="gzip"
+               type="BINDATA" />
+      <include name="IDR_NUX_SET_DEFAULT_LIGHT"
+               file="images\set_default_light.svg"
+               compress="gzip"
+               type="BINDATA" />
       <include name="IDR_WELCOME_ONBOARDING_WELCOME_IMAGES_BACKGROUND_SVGS_BLUE_CIRCLE_SVG"
                file="images\background_svgs\blue_circle.svg"
                compress="gzip"
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/BUILD.gn b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/BUILD.gn
index 70d75a1..e633bc8 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/BUILD.gn
+++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/BUILD.gn
@@ -22,6 +22,7 @@
 
 js_library("nux_set_as_default_proxy") {
   deps = [
+    "../shared:nux_types",
     "//ui/webui/resources/js:cr",
   ]
   externs_list = [
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
index 427566b..303d6e2 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
@@ -31,13 +31,15 @@
       }
 
       .illustration {
-        content: -webkit-image-set(
-          url(../images/set_as_default_illustration_1x.png) 1x,
-          url(../images/set_as_default_illustration_2x.png) 2x);
+        content: url(../images/set_default_light.svg);
         margin: auto;
         width: 454px;
       }
 
+      :host-context([dark]) .illustration {
+        content: url(../images/set_default_dark.svg);
+      }
+
       h1 {
         color: var(--cr-primary-text-color);
         font-size: 1.5rem;
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js
index eb7ae332..6f0477b 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.js
@@ -95,8 +95,10 @@
     // <if expr="is_macosx">
     // On Mac OS, we do not get a notification when the default browser changes.
     // This will fake the notification.
-    window.setTimeout(
-        () => this.browserProxy_.requestDefaultBrowserState(), 100);
+    window.setTimeout(() => {
+      this.browserProxy_.requestDefaultBrowserState().then(
+          this.onDefaultBrowserChange_.bind(this));
+    }, 100);
     // </if>
   },
 
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.js
index 1596232..1fe1cec 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default_proxy.js
@@ -26,6 +26,7 @@
 
   /** @interface */
   class NuxSetAsDefaultProxy {
+    /** @return {!Promise<!nux.DefaultBrowserInfo>} */
     requestDefaultBrowserState() {}
     setAsDefault() {}
     recordPageShown() {}
@@ -40,7 +41,7 @@
   class NuxSetAsDefaultProxyImpl {
     /** @override */
     requestDefaultBrowserState() {
-      chrome.send('requestDefaultBrowserState');
+      return cr.sendWithPromise('requestDefaultBrowserState');
     }
 
     /** @override */
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/navi_colors_css.html b/chrome/browser/resources/welcome/onboarding_welcome/shared/navi_colors_css.html
index 2daae91..49e2818a 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/shared/navi_colors_css.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/navi_colors_css.html
@@ -14,6 +14,12 @@
             0 1px 2px 0 rgba(var(--google-grey-800-rgb), .3),
             0 3px 6px 2px rgba(var(--google-grey-800-rgb), .15);
         --navi-option-icon-shadow-color: var(--google-grey-refresh-100);
+        --navi-shape-blue-color: rgb(26, 115, 232);  /* #1A73E8 */
+        --navi-shape-green-color: rgb(49, 167, 83); /* #31A753 */
+        --navi-shape-grey-color: rgb(241, 243, 244); /* #F1F3F4 */
+        --navi-shape-red-color: rgb(233, 66, 53); /* #E94235 */
+        --navi-shape-yellow-dots-color: rgb(253, 214, 99); /* #FDD663 */
+        --navi-shape-yellow-semicircle-color: rgb(250, 207, 76); /* #FACF4C */
       }
 
       :host-context([dark]) {
@@ -24,6 +30,12 @@
         --navi-option-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .3),
                                   0 3px 6px 2px rgba(0, 0, 0, .15);
         --navi-option-icon-shadow-color: var(--google-grey-800);
+        --navi-shape-blue-color: rgb(138, 180, 248); /* #8AB4F8 */
+        --navi-shape-green-color: rgb(129, 201, 149); /* #81C995 */
+        --navi-shape-grey-color: rgb(154, 160, 166); /* #9AA0A6 */
+        --navi-shape-red-color: rgb(238, 103, 92); /* #EE675C */
+        /* --navi-shape-yellow-dots-color is same color in dark mode */
+        --navi-shape-yellow-semicircle-color: rgb(253, 214, 99); /* #FDD663 */
       }
     </style>
   </template>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/nux_types.js b/chrome/browser/resources/welcome/onboarding_welcome/shared/nux_types.js
index e429b90..f022277 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/shared/nux_types.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/nux_types.js
@@ -23,7 +23,7 @@
 nux.stepIndicatorModel;
 
 /**
- * TODO(scottchen): somehow reuse from
+ * TODO(hcarmona): somehow reuse from
  * chrome/browser/resources/settings/default_browser_page/default_browser_browser_proxy.js
  * @typedef {{
  *   canBeDefault: boolean,
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/onboarding_background.html b/chrome/browser/resources/welcome/onboarding_welcome/shared/onboarding_background.html
index 6df7693a..b77b594 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/shared/onboarding_background.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/onboarding_background.html
@@ -80,47 +80,92 @@
       }
 
       #blue-circle-container::after {
+        -webkit-mask: url(../images/background_svgs/blue_circle.svg) no-repeat
+            top left;
         animation: blue-circle-anim-y 9s cubic-bezier(0.25, 0, 0.2, 1) infinite;
-        content: url(../images/background_svgs/blue_circle.svg);
+        background-color: var(--navi-shape-blue-color);
+        content: ' '; /* Content needs to be non-empty */
+        height: 43px;
         position: absolute;
+        width: 43px;
       }
 
       #yellow-dots {
+        -webkit-mask: url(../images/background_svgs/yellow_dots.svg) no-repeat
+            top left;
+        background-color: var(--navi-shape-yellow-dots-color);
+        content: ' '; /* Content needs to be non-empty */
+        height: 57px;
         left: 13%;
         top: 18%;
+        width: 76px;
       }
 
       #grey-rounded-rectangle {
+        -webkit-mask: url(../images/background_svgs/grey_rounded_rectangle.svg)
+            no-repeat top left;
         animation: grey-rounded-rectangle-anim 10s cubic-bezier(0.4, 0, 0.2, 1)
             infinite;
+        background-color: var(--navi-shape-grey-color);
+        content: ' '; /* Content needs to be non-empty */
+        height: 132px;
         left: -42px;
         top: 45%;
+        width: 132px;
       }
 
       #red-triangle {
+        -webkit-mask: url(../images/background_svgs/red_triangle.svg) no-repeat
+            bottom left;
         animation: red-triangle-anim 9.6s cubic-bezier(0.4, 0, 0.2, 1) infinite;
+        background-color: var(--navi-shape-red-color);
         bottom: 15%;
+        content: ' '; /* Content needs to be non-empty */
+        height: 74px;
         left: 12%;
+        width: 65px;
       }
 
       #yellow-semicircle {
+        -webkit-mask: url(../images/background_svgs/yellow_semicircle.svg)
+            no-repeat top right;
         animation: yellow-semicircle-anim 10s cubic-bezier(0.4, 0, 0.2, 1)
             infinite;
+        background-color: var(--navi-shape-yellow-semicircle-color);
+        content: ' '; /* Content needs to be non-empty */
+        height: 171px;
         right: 28.5%;
         top: -50px;
         transform: rotate(-7deg);
+        width: 211px;
       }
 
       #green-rectangle {
+        -webkit-mask: url(../images/background_svgs/green_rectangle.svg)
+            no-repeat bottom right;
         animation: green-rectangle-anim 40s infinite linear;
+        background-color: var(--navi-shape-green-color);
         bottom: 8%;
+        content: ' '; /* Content needs to be non-empty */
+        height: 371px;
         right: -255px;
+        width: 371px;
       }
 
       #grey-oval {
+        -webkit-mask: url(../images/background_svgs/grey_oval.svg) no-repeat
+            bottom right;
+        background-color: var(--navi-shape-grey-color);
         bottom: calc(8% + 24px);  /* Relative to green-rectangle. */
+        content: ' '; /* Content needs to be non-empty */
+        height: 100px;
         mix-blend-mode: multiply;
         right: 48px;
+        width: 100px;
+      }
+
+      :host-context([dark]) #grey-oval {
+        mix-blend-mode: screen;
       }
     </style>
     <div id="container">
@@ -128,17 +173,12 @@
            the blue-circle svg, because the animation needs to curve so x and y
            needs to be animated separately. -->
       <span id="blue-circle-container"></span>
-      <img id="green-rectangle" alt=""
-          src="../images/background_svgs/green_rectangle.svg">
-      <img id="grey-oval" alt="" src="../images/background_svgs/grey_oval.svg">
-      <img id="grey-rounded-rectangle" alt=""
-          src="../images/background_svgs/grey_rounded_rectangle.svg">
-      <img id="red-triangle" alt=""
-          src="../images/background_svgs/red_triangle.svg">
-      <img id="yellow-dots" alt=""
-          src="../images/background_svgs/yellow_dots.svg">
-      <img id="yellow-semicircle" alt=""
-          src="../images/background_svgs/yellow_semicircle.svg">
+      <span id="green-rectangle"></span>
+      <span id="grey-oval"></span>
+      <span id="grey-rounded-rectangle"></span>
+      <span id="red-triangle"></span>
+      <span id="yellow-dots"></span>
+      <span id="yellow-semicircle"></span>
     </div>
   </template>
   <script src="onboarding_background.js"></script>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html
index ea2ce1e..93a454f 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html
+++ b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html
@@ -3,7 +3,6 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_toast/cr_toast.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_view_manager/cr_view_manager.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
-<link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/promise_resolver.html">
 <link rel="import" href="google_apps/nux_google_apps.html">
 <link rel="import" href="email/nux_email.html">
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js
index 90e75c3..0303723 100644
--- a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js
+++ b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js
@@ -38,9 +38,6 @@
   /** @private {?welcome.Routes} */
   currentRoute_: null,
 
-  /** @private {?PromiseResolver} */
-  defaultCheckPromise_: null,
-
   /** @private {NuxOnboardingModules} */
   modules_: {
     'new-user': loadTimeData.getString('newUserModules').split(','),
@@ -60,30 +57,6 @@
     'default-browser-change': 'onDefaultBrowserChange_',
   },
 
-  /** @override */
-  ready: function() {
-    this.defaultCheckPromise_ = new PromiseResolver();
-
-    /** @param {!nux.DefaultBrowserInfo} status */
-    const defaultCheckCallback = status => {
-      if (status.isDefault || !status.canBeDefault) {
-        this.defaultCheckPromise_.resolve(false);
-      } else if (!status.isDisabledByPolicy && !status.isUnknownError) {
-        this.defaultCheckPromise_.resolve(true);
-      } else {  // Unknown error.
-        this.defaultCheckPromise_.resolve(false);
-      }
-
-      cr.removeWebUIListener(defaultCheckCallback);
-    };
-
-    cr.addWebUIListener('browser-default-state-changed', defaultCheckCallback);
-
-    // TODO(scottchen): convert the request to cr.sendWithPromise
-    // (see https://crbug.com/874520#c6).
-    nux.NuxSetAsDefaultProxyImpl.getInstance().requestDefaultBrowserState();
-  },
-
   /** @private */
   onDefaultBrowserChange_: function() {
     this.$$('cr-toast').show();
@@ -134,16 +107,28 @@
     let modules = this.modules_[route];
     assert(modules);  // Modules should be defined if on a valid route.
 
+    /** @type {!Promise} */
+    const defaultBrowserPromise =
+        nux.NuxSetAsDefaultProxyImpl.getInstance()
+            .requestDefaultBrowserState()
+            .then((status) => {
+              if (status.isDefault || !status.canBeDefault) {
+                return false;
+              } else if (!status.isDisabledByPolicy && !status.isUnknownError) {
+                return true;
+              } else {  // Unknown error.
+                return false;
+              }
+            });
+
     // Wait until the default-browser state and bookmark visibility are known
     // before anything initializes.
     return Promise
         .all([
-          this.defaultCheckPromise_.promise,
+          defaultBrowserPromise,
           nux.BookmarkBarManager.getInstance().initialized,
         ])
-        .then(args => {
-          const canSetDefault = args[0];
-
+        .then(([canSetDefault]) => {
           modules = modules.filter(module => {
             if (module == 'nux-set-as-default') {
               return canSetDefault;
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
index 6be6fef..0e65c846 100644
--- a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
+++ b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/features.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "google_apis/gaia/gaia_constants.h"
@@ -244,6 +245,28 @@
              ->is_under_advanced_protection();
 }
 
+// static
+bool AdvancedProtectionStatusManager::RequestsAdvancedProtectionVerdicts(
+    Profile* profile) {
+  Profile* original_profile =
+      profile->IsOffTheRecord() ? profile->GetOriginalProfile() : profile;
+
+  if (!original_profile)
+    return false;
+
+  bool is_under_advanced_protection =
+      AdvancedProtectionStatusManagerFactory::GetInstance()
+          ->GetForBrowserContext(
+              static_cast<content::BrowserContext*>(original_profile))
+          ->is_under_advanced_protection();
+
+  static bool force_enabled =
+      base::FeatureList::IsEnabled(kForceUseAPDownloadProtection);
+  static bool enabled = base::FeatureList::IsEnabled(kUseAPDownloadProtection);
+
+  return force_enabled || (is_under_advanced_protection && enabled);
+}
+
 bool AdvancedProtectionStatusManager::IsPrimaryAccount(
     const CoreAccountInfo& account_info) {
   return !account_info.account_id.empty() &&
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager.h b/chrome/browser/safe_browsing/advanced_protection_status_manager.h
index 91e16a0..fd6db9b 100644
--- a/chrome/browser/safe_browsing/advanced_protection_status_manager.h
+++ b/chrome/browser/safe_browsing/advanced_protection_status_manager.h
@@ -35,6 +35,10 @@
   // If the primary account of |profile| is under advanced protection.
   static bool IsUnderAdvancedProtection(Profile* profile);
 
+  // If the primary account of |profile| is requesting advanced protection
+  // verdicts.
+  static bool RequestsAdvancedProtectionVerdicts(Profile* profile);
+
   bool is_under_advanced_protection() const {
     return is_under_advanced_protection_;
   }
diff --git a/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc b/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc
index 5c4e26c..49b0db3d 100644
--- a/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc
+++ b/chrome/browser/safe_browsing/download_protection/check_client_download_request.cc
@@ -177,6 +177,7 @@
       is_extended_reporting_(false),
       is_incognito_(false),
       is_under_advanced_protection_(false),
+      requests_ap_verdicts_(false),
       weakptr_factory_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   item_->AddObserver(this);
@@ -209,6 +210,10 @@
     is_under_advanced_protection_ =
         profile &&
         AdvancedProtectionStatusManager::IsUnderAdvancedProtection(profile);
+    requests_ap_verdicts_ =
+        profile &&
+        AdvancedProtectionStatusManager::RequestsAdvancedProtectionVerdicts(
+            profile);
   }
 
   // If whitelist check passes, FinishRequest() will be called to avoid
@@ -704,8 +709,7 @@
     request->mutable_archived_binary()->Swap(&archived_binaries_);
   request->set_archive_file_count(file_count_);
   request->set_archive_directory_count(directory_count_);
-  request->set_request_ap_verdicts(
-      base::FeatureList::IsEnabled(kUseAPDownloadProtection));
+  request->set_request_ap_verdicts(requests_ap_verdicts_);
 
   if (!request->SerializeToString(&client_download_request_data_)) {
     FinishRequest(DownloadCheckResult::UNKNOWN, REASON_INVALID_REQUEST_PROTO);
diff --git a/chrome/browser/safe_browsing/download_protection/check_client_download_request.h b/chrome/browser/safe_browsing/download_protection/check_client_download_request.h
index 5571249..ae219730 100644
--- a/chrome/browser/safe_browsing/download_protection/check_client_download_request.h
+++ b/chrome/browser/safe_browsing/download_protection/check_client_download_request.h
@@ -134,6 +134,13 @@
   bool is_extended_reporting_;
   bool is_incognito_;
   bool is_under_advanced_protection_;
+
+  // Boolean indicating whether the user requests AP verdicts. Note that this is
+  // distinct from |is_under_advanced_protection_| while:
+  //  - The feature is still partially rolled out
+  //  - The feature has been force enabled from chrome://flags
+  bool requests_ap_verdicts_;
+
   int file_count_;
   int directory_count_;
 
diff --git a/chrome/browser/search/background/ntp_background_data.cc b/chrome/browser/search/background/ntp_background_data.cc
index 7b55e38..cbb3b61 100644
--- a/chrome/browser/search/background/ntp_background_data.cc
+++ b/chrome/browser/search/background/ntp_background_data.cc
@@ -82,7 +82,8 @@
       image.image_url() + ((image.image_url().find('=') == std::string::npos)
                                ? kThumbnailImageOptions
                                : std::string("")));
-  // TODO(ramyan): Request resolution from service, instead of setting it here.
+  // TODO(crbug.com/874339): Request resolution from service, instead of
+  // setting it here.
   collection_image.image_url = GURL(
       image.image_url() + ((image.image_url().find('=') == std::string::npos)
                                ? default_image_options
diff --git a/chrome/browser/search/background/ntp_background_service.cc b/chrome/browser/search/background/ntp_background_service.cc
index 602a8a83..6cefbba 100644
--- a/chrome/browser/search/background/ntp_background_service.cc
+++ b/chrome/browser/search/background/ntp_background_service.cc
@@ -32,7 +32,7 @@
 
 // The options to be added to an image URL, specifying resolution, cropping,
 // etc. Options appear on an image URL after the '=' character.
-// TODO(crbug.com/851990): Set options based on display resolution capability.
+// TODO(crbug.com/874339): Set options based on display resolution capability.
 constexpr char kImageOptions[] = "=w3840-h2160-p-k-no-nd-mv";
 
 }  // namespace
diff --git a/chrome/browser/search/iframe_source.h b/chrome/browser/search/iframe_source.h
index 78b60e8..9e7d802a 100644
--- a/chrome/browser/search/iframe_source.h
+++ b/chrome/browser/search/iframe_source.h
@@ -14,7 +14,7 @@
 #endif
 
 // Base class for URL data sources for chrome-search:// iframed content.
-// TODO(treib): This has only one subclass outside of tests,
+// TODO(crbug.com/947608): This has only one subclass outside of tests,
 // MostVisitedIframeSource. Merge the two classes?
 class IframeSource : public content::URLDataSource {
  public:
diff --git a/chrome/browser/search/instant_service.h b/chrome/browser/search/instant_service.h
index 24bb2b6..61931bf 100644
--- a/chrome/browser/search/instant_service.h
+++ b/chrome/browser/search/instant_service.h
@@ -104,10 +104,7 @@
   // using a non-Google search provider. Marked virtual for mocking in tests.
   virtual bool ResetCustomLinks();
 
-  // Invoked by the InstantController to update theme information for NTP.
-  //
-  // TODO(kmadhusu): Invoking this from InstantController shouldn't be
-  // necessary. Investigate more and remove this from here.
+  // Invoked to update theme information for the NTP.
   void UpdateThemeInfo();
 
   // Invoked when a background pref update is received via sync, triggering
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index e12d0f19b..028e4d2 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -838,8 +838,6 @@
       return;
     }
 
-    // TODO(crbug/909931): There's no need to fetch the promo on each load,
-    // we can sometimes use cached data.
     promo_requests_.emplace_back(base::TimeTicks::Now(), callback);
     promo_service_->Refresh();
 
@@ -855,13 +853,17 @@
     // Currently Vasco search suggestions are only available for en-US
     // users. If this restriction is expanded or removed in the future this
     // check must be changed.
-    if (one_google_bar_service_->language_code() == kEnUSLanguageCode) {
-      MaybeServeSearchSuggestions(callback);
-
-      search_suggest_requests_.emplace_back(base::TimeTicks::Now());
-      search_suggest_service_->Refresh();
+    if (one_google_bar_service_->language_code() != kEnUSLanguageCode) {
+      std::string no_suggestions =
+          "var search_suggestions = {suggestionsHtml: ''}";
+      callback.Run(base::RefCountedString::TakeString(&no_suggestions));
+      return;
     }
 
+    MaybeServeSearchSuggestions(callback);
+
+    search_suggest_requests_.emplace_back(base::TimeTicks::Now());
+    search_suggest_service_->Refresh();
     return;
   }
 
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.h b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.h
index f359cba..ac9babc 100644
--- a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.h
+++ b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.h
@@ -27,9 +27,6 @@
 
 struct OneGoogleBarData;
 
-// TODO(treib): This class uses cookies for authentication. After "Dice" account
-// consistency launches, we should switch to using OAuth2 instead.
-// See https://crbug.com/751534.
 class OneGoogleBarLoaderImpl : public OneGoogleBarLoader {
  public:
   OneGoogleBarLoaderImpl(
diff --git a/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc b/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc
index 5481b39..4b81c7af 100644
--- a/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc
+++ b/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc
@@ -57,7 +57,6 @@
     return base::nullopt;
   }
 
-  // TODO(crbug.com/919905): Investigate if SafeHtml should be used here.
   std::string suggestions_html = std::string();
   if (!query_suggestions->GetString("query_suggestions_with_html",
                                     &suggestions_html)) {
diff --git a/chrome/browser/search/suggestions/image_decoder_impl.h b/chrome/browser/search/suggestions/image_decoder_impl.h
index 497d709..6fba1f3 100644
--- a/chrome/browser/search/suggestions/image_decoder_impl.h
+++ b/chrome/browser/search/suggestions/image_decoder_impl.h
@@ -14,8 +14,8 @@
 namespace suggestions {
 
 // image_fetcher::ImageDecoder implementation.
-// TODO(treib,markusheintz): Move this to a better place - it really has
-// nothing to do with suggestions. crbug.com/624761
+// TODO(crbug.com/624761): Move this to a better place - it really has
+// nothing to do with suggestions.
 class ImageDecoderImpl : public image_fetcher::ImageDecoder {
  public:
   ImageDecoderImpl();
diff --git a/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.cc b/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.cc
index 9e012101..632178b 100644
--- a/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.cc
+++ b/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/send_tab_to_self/desktop_notification_handler.h"
@@ -61,4 +62,10 @@
   return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
 }
 
+void RecordSendTabToSelfClickResult(std::string context_menu,
+                                    SendTabToSelfClickResult state) {
+  base::UmaHistogramEnumeration(
+      "SendTabToSelf." + context_menu + ".ClickResult", state);
+}
+
 }  // namespace send_tab_to_self
diff --git a/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h b/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h
index 94d63c4..63f232e 100644
--- a/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h
+++ b/chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_DESKTOP_UTIL_H_
 #define CHROME_BROWSER_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_DESKTOP_UTIL_H_
 
+#include <string>
+
 class Profile;
 
 namespace content {
@@ -15,8 +17,22 @@
 class ImageSkia;
 }
 
+// State of the send tab to self option in the context menu.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class SendTabToSelfClickResult {
+  kShowItem = 0,
+  kClickItem = 1,
+  kMaxValue = kClickItem,
+};
+
 namespace send_tab_to_self {
 
+const char kContentMenu[] = "ContentMenu";
+const char kLinkMenu[] = "LinkMenu";
+const char kOmniboxMenu[] = "OmniboxMenu";
+const char kTabMenu[] = "TabMenu";
+
 // Add a new entry to SendTabToSelfModel when user click "Share to my devices"
 // option
 // TODO(crbug.com/945386): Flip parameter order.
@@ -25,6 +41,11 @@
 // Get the icon for send tab to self menu item.
 gfx::ImageSkia* GetImageSkia();
 
+// Record whether the user click to send a tab or link when send tab to self
+// entry point is shown in the context menu.
+void RecordSendTabToSelfClickResult(std::string context_menu,
+                                    SendTabToSelfClickResult state);
+
 }  // namespace send_tab_to_self
 
 #endif  // CHROME_BROWSER_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_DESKTOP_UTIL_H_
diff --git a/chrome/browser/speech/tts_message_filter.cc b/chrome/browser/speech/tts_message_filter.cc
index 4bcd4347..a7df91b 100644
--- a/chrome/browser/speech/tts_message_filter.cc
+++ b/chrome/browser/speech/tts_message_filter.cc
@@ -165,14 +165,10 @@
       Send(new TtsMsg_DidFinishSpeaking(utterance->GetSrcId()));
       break;
     case content::TTS_EVENT_WORD:
-      // We do not send the length here because the IPC message
-      // does not expect it. A SpeechSynthesisEvent does not currently
-      // take a length parameter in the TTS event.
-      // TODO(crbug.com/923556) Support length in the SpeechSynthesis API.
-      Send(new TtsMsg_WordBoundary(utterance->GetSrcId(), char_index));
+      Send(new TtsMsg_WordBoundary(utterance->GetSrcId(), char_index, length));
       break;
     case content::TTS_EVENT_SENTENCE:
-      Send(new TtsMsg_SentenceBoundary(utterance->GetSrcId(), char_index));
+      Send(new TtsMsg_SentenceBoundary(utterance->GetSrcId(), char_index, 0));
       break;
     case content::TTS_EVENT_MARKER:
       Send(new TtsMsg_MarkerEvent(utterance->GetSrcId(), char_index));
diff --git a/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc b/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc
index 809fd01..0832417a9 100644
--- a/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc
+++ b/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc
@@ -77,7 +77,7 @@
   }
 
   // Checks the user profile and sends a JSON-RPC request to the Spelling
-  // service if a user enables the "Ask Google for suggestions" option. When
+  // service if a user enables the "Use enhanced spell check" option. When
   // a response is received (including an error) from the remote Spelling
   // service, calls CallSpellingServiceDone.
   content::BrowserContext* context =
diff --git a/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc b/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc
index 5bad6f6d..d002a3d 100644
--- a/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc
@@ -284,14 +284,7 @@
   ASSERT_TRUE(IsAppEnabled(GetProfile(1), 0));
 }
 
-// TODO(crbug.com/721391) Flaky on CrOS.
-#if defined(OS_CHROMEOS)
-#define MAYBE_UpdateIncognitoEnableDisable DISABLED_UpdateIncognitoEnableDisable
-#else
-#define MAYBE_UpdateIncognitoEnableDisable UpdateIncognitoEnableDisable
-#endif
-IN_PROC_BROWSER_TEST_F(TwoClientAppListSyncTest,
-                       MAYBE_UpdateIncognitoEnableDisable) {
+IN_PROC_BROWSER_TEST_F(TwoClientAppListSyncTest, UpdateIncognitoEnableDisable) {
   ASSERT_TRUE(SetupSync());
   ASSERT_TRUE(AllProfilesHaveSameAppList());
 
diff --git a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
index 69b6dc2..31cbce9 100644
--- a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
@@ -3,13 +3,13 @@
 // found in the LICENSE file.
 
 #include <stddef.h>
+#include <memory>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/bookmark_app_helper.h"
-#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_sync_data.h"
 #include "chrome/browser/extensions/extension_sync_service.h"
 #include "chrome/browser/extensions/launch_util.h"
@@ -20,9 +20,12 @@
 #include "chrome/browser/sync/test/integration/sync_app_helper.h"
 #include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
+#include "chrome/browser/web_applications/components/install_manager.h"
+#include "chrome/browser/web_applications/components/web_app_provider_base.h"
 #include "chrome/browser/web_applications/extensions/bookmark_app_util.h"
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
 #include "chrome/common/extensions/manifest_handlers/app_theme_color_info.h"
+#include "chrome/common/web_application_info.h"
 #include "components/sync/driver/sync_driver_switches.h"
 #include "components/sync/model/string_ordinal.h"
 #include "content/public/browser/notification_service.h"
@@ -53,10 +56,6 @@
   return extensions::ExtensionRegistry::Get(profile);
 }
 
-extensions::ExtensionService* GetExtensionService(Profile* profile) {
-  return extensions::ExtensionSystem::Get(profile)->extension_service();
-}
-
 }  // namespace
 
 class TwoClientAppsSyncTest : public FeatureToggler, public SyncTest {
@@ -382,19 +381,23 @@
   size_t num_extensions =
       GetExtensionRegistry(GetProfile(0))->enabled_extensions().size();
 
-  WebApplicationInfo web_app_info;
-  web_app_info.app_url = GURL("http://www.chromium.org/path");
-  web_app_info.scope = GURL("http://www.chromium.org/");
-  web_app_info.title = base::UTF8ToUTF16("Test name");
-  web_app_info.description = base::UTF8ToUTF16("Test description");
+  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  web_app_info->app_url = GURL("http://www.chromium.org/path");
+  web_app_info->scope = GURL("http://www.chromium.org/");
+  web_app_info->title = base::UTF8ToUTF16("Test name");
+  web_app_info->description = base::UTF8ToUTF16("Test description");
   ++num_extensions;
   {
     content::WindowedNotificationObserver windowed_observer(
         extensions::NOTIFICATION_CRX_INSTALLER_DONE,
         content::NotificationService::AllSources());
-    extensions::CreateOrUpdateBookmarkApp(GetExtensionService(GetProfile(0)),
-                                          &web_app_info,
-                                          true /* is_locally_installed */);
+
+    auto* provider =
+        web_app::WebAppProviderBase::GetProviderBase(GetProfile(0));
+    DCHECK(provider);
+    provider->install_manager().InstallWebAppForTesting(std::move(web_app_info),
+                                                        base::DoNothing());
+
     windowed_observer.Wait();
     EXPECT_EQ(num_extensions,
               GetExtensionRegistry(GetProfile(0))->enabled_extensions().size());
@@ -415,17 +418,21 @@
   size_t num_extensions =
       GetExtensionRegistry(GetProfile(0))->enabled_extensions().size();
 
-  WebApplicationInfo web_app_info;
-  web_app_info.app_url = GURL("http://www.chromium.org/");
-  web_app_info.title = base::UTF8ToUTF16("Test name");
+  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  web_app_info->app_url = GURL("http://www.chromium.org/");
+  web_app_info->title = base::UTF8ToUTF16("Test name");
   ++num_extensions;
   {
     content::WindowedNotificationObserver windowed_observer(
         extensions::NOTIFICATION_CRX_INSTALLER_DONE,
         content::NotificationService::AllSources());
-    extensions::CreateOrUpdateBookmarkApp(GetExtensionService(GetProfile(0)),
-                                          &web_app_info,
-                                          true /* is_locally_installed */);
+
+    auto* provider =
+        web_app::WebAppProviderBase::GetProviderBase(GetProfile(0));
+    DCHECK(provider);
+    provider->install_manager().InstallWebAppForTesting(std::move(web_app_info),
+                                                        base::DoNothing());
+
     windowed_observer.Wait();
     EXPECT_EQ(num_extensions,
               GetExtensionRegistry(GetProfile(0))->enabled_extensions().size());
@@ -457,18 +464,23 @@
   size_t num_extensions =
       GetExtensionRegistry(GetProfile(0))->enabled_extensions().size();
 
-  WebApplicationInfo web_app_info;
-  web_app_info.app_url = GURL("http://www.chromium.org/");
-  web_app_info.title = base::UTF8ToUTF16("Test name");
-  web_app_info.theme_color = SK_ColorBLUE;
+  const GURL app_url("http://www.chromium.org/");
+  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  web_app_info->app_url = app_url;
+  web_app_info->title = base::UTF8ToUTF16("Test name");
+  web_app_info->theme_color = SK_ColorBLUE;
   ++num_extensions;
   {
     content::WindowedNotificationObserver windowed_observer(
         extensions::NOTIFICATION_CRX_INSTALLER_DONE,
         content::NotificationService::AllSources());
-    extensions::CreateOrUpdateBookmarkApp(GetExtensionService(GetProfile(0)),
-                                          &web_app_info,
-                                          true /* is_locally_installed */);
+
+    auto* provider =
+        web_app::WebAppProviderBase::GetProviderBase(GetProfile(0));
+    DCHECK(provider);
+    provider->install_manager().InstallWebAppForTesting(std::move(web_app_info),
+                                                        base::DoNothing());
+
     windowed_observer.Wait();
     EXPECT_EQ(num_extensions,
               GetExtensionRegistry(GetProfile(0))->enabled_extensions().size());
@@ -480,7 +492,7 @@
         base::BindRepeating(&AllProfilesHaveSameApps));
     windowed_observer.Wait();
   }
-  auto* extension = GetAppByLaunchURL(web_app_info.app_url, GetProfile(1));
+  auto* extension = GetAppByLaunchURL(app_url, GetProfile(1));
   base::Optional<SkColor> theme_color =
       extensions::AppThemeColorInfo::GetThemeColor(extension);
   EXPECT_EQ(SK_ColorBLUE, theme_color.value());
@@ -493,18 +505,23 @@
   size_t num_extensions =
       GetExtensionRegistry(GetProfile(0))->enabled_extensions().size();
 
-  WebApplicationInfo web_app_info;
-  web_app_info.app_url = GURL("http://www.chromium.org/");
-  web_app_info.title = base::UTF8ToUTF16("Test name");
-  web_app_info.theme_color = SK_ColorBLUE;
+  const GURL app_url("http://www.chromium.org/");
+  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  web_app_info->app_url = app_url;
+  web_app_info->title = base::UTF8ToUTF16("Test name");
+  web_app_info->theme_color = SK_ColorBLUE;
   ++num_extensions;
   {
     content::WindowedNotificationObserver windowed_observer(
         extensions::NOTIFICATION_CRX_INSTALLER_DONE,
         content::NotificationService::AllSources());
-    extensions::CreateOrUpdateBookmarkApp(GetExtensionService(GetProfile(0)),
-                                          &web_app_info,
-                                          true /* is_locally_installed */);
+
+    auto* provider =
+        web_app::WebAppProviderBase::GetProviderBase(GetProfile(0));
+    DCHECK(provider);
+    provider->install_manager().InstallWebAppForTesting(std::move(web_app_info),
+                                                        base::DoNothing());
+
     windowed_observer.Wait();
     EXPECT_EQ(num_extensions,
               GetExtensionRegistry(GetProfile(0))->enabled_extensions().size());
@@ -528,7 +545,7 @@
     // it would not wait for the sync stuff to happen.
     content::RunAllTasksUntilIdle();
   }
-  auto* extension = GetAppByLaunchURL(web_app_info.app_url, GetProfile(1));
+  auto* extension = GetAppByLaunchURL(app_url, GetProfile(1));
 #if defined(OS_CHROMEOS)
   EXPECT_TRUE(BookmarkAppIsLocallyInstalled(GetProfile(1), extension));
 #else
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc
index 32940b8..8529fa6 100644
--- a/chrome/browser/themes/theme_properties.cc
+++ b/chrome/browser/themes/theme_properties.cc
@@ -48,6 +48,10 @@
     case ThemeProperties::COLOR_TOOLBAR:
     case ThemeProperties::COLOR_NTP_BACKGROUND:
       return SkColorSetRGB(0x32, 0x36, 0x39);
+    case ThemeProperties::COLOR_HOVER_CARD_NO_PREVIEW_FOREGROUND:
+      return gfx::kGoogleGrey700;
+    case ThemeProperties::COLOR_HOVER_CARD_NO_PREVIEW_BACKGROUND:
+      return gfx::kGoogleGrey900;
     case ThemeProperties::COLOR_BOOKMARK_TEXT:
     case ThemeProperties::COLOR_TAB_TEXT:
     case ThemeProperties::COLOR_TAB_CLOSE_BUTTON_ACTIVE:
@@ -216,6 +220,10 @@
     case COLOR_TOOLBAR:
     case COLOR_STATUS_BUBBLE:
       return SK_ColorWHITE;
+    case COLOR_HOVER_CARD_NO_PREVIEW_FOREGROUND:
+      return gfx::kGoogleGrey300;
+    case COLOR_HOVER_CARD_NO_PREVIEW_BACKGROUND:
+      return gfx::kGoogleGrey050;
     case COLOR_BACKGROUND_TAB_TEXT:
     case COLOR_BACKGROUND_TAB_TEXT_INACTIVE:
     case COLOR_BOOKMARK_TEXT:
diff --git a/chrome/browser/themes/theme_properties.h b/chrome/browser/themes/theme_properties.h
index 66fd34e..dc432e8 100644
--- a/chrome/browser/themes/theme_properties.h
+++ b/chrome/browser/themes/theme_properties.h
@@ -113,6 +113,10 @@
     COLOR_INFOBAR,
     COLOR_STATUS_BUBBLE,
 
+    // Colors used when displaying hover cards.
+    COLOR_HOVER_CARD_NO_PREVIEW_FOREGROUND,
+    COLOR_HOVER_CARD_NO_PREVIEW_BACKGROUND,
+
     // The throbber colors for tabs or anything on a toolbar (currently, only
     // the download shelf). If you're adding a throbber elsewhere, such as in
     // a dialog or bubble, you likely want
diff --git a/chrome/browser/themes/theme_syncable_service.cc b/chrome/browser/themes/theme_syncable_service.cc
index dc7e3fdf..ea065fe 100644
--- a/chrome/browser/themes/theme_syncable_service.cc
+++ b/chrome/browser/themes/theme_syncable_service.cc
@@ -9,6 +9,7 @@
 #include <string>
 #include <utility>
 
+#include "base/one_shot_event.h"
 #include "base/strings/stringprintf.h"
 #include "base/version.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -22,7 +23,6 @@
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/manifest_url_handlers.h"
-#include "extensions/common/one_shot_event.h"
 
 using std::string;
 
diff --git a/chrome/browser/translate/translate_manager_browsertest.cc b/chrome/browser/translate/translate_manager_browsertest.cc
index b5aae4b..532a502f 100644
--- a/chrome/browser/translate/translate_manager_browsertest.cc
+++ b/chrome/browser/translate/translate_manager_browsertest.cc
@@ -407,6 +407,41 @@
   EXPECT_EQ(translate::TranslateErrors::NONE, GetPageTranslatedResult());
 }
 
+// Test that the translation was successful in an about:blank page.
+// This is a regression test for https://crbug.com/943685.
+IN_PROC_BROWSER_TEST_F(TranslateManagerBrowserTest, PageTranslationAboutBlank) {
+  SetTranslateScript(kTestValidScript);
+  ResetObserver();
+  AddTabAtIndex(0, GURL(embedded_test_server()->GetURL("/french_page.html")),
+                ui::PAGE_TRANSITION_TYPED);
+
+  // Open a pop-up window and leave it at the initial about:blank URL.
+  content::WebContentsAddedObserver popup_observer;
+  ASSERT_TRUE(
+      content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(),
+                      "window.open('about:blank', 'popup')"));
+  content::WebContents* popup = popup_observer.GetWebContents();
+
+  // A round-trip to the renderer process helps avoid a race where the
+  // browser-side translate structures are not yet ready for the translate call.
+  EXPECT_EQ("ping", content::EvalJs(popup, "'ping'"));
+
+  // Translate the about:blank page.
+  ChromeTranslateClient* chrome_translate_client =
+      ChromeTranslateClient::FromWebContents(popup);
+  translate::TranslateManager* manager =
+      chrome_translate_client->GetTranslateManager();
+  manager->TranslatePage("fr", "en", true);
+
+  // Verify that the crash from https://crbug.com/943685 didn't happen.
+  EXPECT_EQ("still alive", content::EvalJs(popup, "'still alive'"));
+
+  // Wait for translation to finish and verify it was successful.
+  WaitUntilPageTranslated();
+  EXPECT_FALSE(chrome_translate_client->GetLanguageState().translation_error());
+  EXPECT_EQ(translate::TranslateErrors::NONE, GetPageTranslatedResult());
+}
+
 // Test that hrefTranslate is propagating properly
 IN_PROC_BROWSER_TEST_F(TranslateManagerBrowserTest, HrefTranslateSuccess) {
   ChromeTranslateClient* chrome_translate_client = GetChromeTranslateClient();
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index ef2390d..3f9150d 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -510,6 +510,7 @@
     "//device/base",
     "//device/usb",
     "//extensions/buildflags",
+    "//gpu/config",
     "//media",
     "//net:net",
     "//ppapi/buildflags",
@@ -1286,6 +1287,7 @@
       "//chrome/browser/profile_resetter:profile_reset_report_proto",
       "//chrome/browser/resource_coordinator:tab_metrics_event_proto",
       "//chrome/browser/resource_coordinator/tab_ranker",
+      "//chrome/browser/safe_browsing:advanced_protection",
       "//chrome/browser/ui/webui/app_management:mojo_bindings",
       "//chrome/common:buildflags",
       "//chrome/common:search_mojom",
@@ -1314,6 +1316,10 @@
       deps += [ "//ui/ozone" ]
     }
 
+    if (is_linux && !is_chromeos) {
+      deps += [ "//ui/base/ime/linux" ]
+    }
+
     if (!toolkit_views) {
       sources += [ "media_router/cloud_services_dialog.cc" ]
     }
@@ -1786,6 +1792,7 @@
       "//chromeos/dbus",
       "//chromeos/dbus/cryptohome",
       "//chromeos/dbus/cryptohome:cryptohome_proto",
+      "//chromeos/dbus/session_manager",
       "//chromeos/dbus/system_clock",
       "//chromeos/login/auth",
       "//chromeos/login/login_state",
@@ -1815,7 +1822,7 @@
       "//services/device/public/mojom",
       "//services/ws/public/cpp",
       "//services/ws/public/mojom",
-      "//ui/base/ime",
+      "//ui/base/ime/chromeos",
       "//ui/chromeos",
       "//ui/chromeos/events",
       "//ui/compositor_extra",
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.cc b/chrome/browser/ui/app_list/app_list_syncable_service.cc
index 6af4d55..45d88b1 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -12,6 +12,7 @@
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/macros.h"
+#include "base/one_shot_event.h"
 #include "base/stl_util.h"
 #include "base/values.h"
 #include "build/build_config.h"
@@ -49,7 +50,6 @@
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/uninstall_reason.h"
 #include "extensions/common/constants.h"
-#include "extensions/common/one_shot_event.h"
 #include "ui/base/l10n/l10n_util.h"
 
 using syncer::SyncChange;
@@ -292,8 +292,8 @@
     BuildModel();
   } else {
     extension_system_->ready().Post(
-        FROM_HERE, base::Bind(&AppListSyncableService::BuildModel,
-                              weak_ptr_factory_.GetWeakPtr()));
+        FROM_HERE, base::BindOnce(&AppListSyncableService::BuildModel,
+                                  weak_ptr_factory_.GetWeakPtr()));
   }
 }
 
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc
index 42e9f10..1daaf9e 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.cc
@@ -37,26 +37,6 @@
 constexpr char kAppListImpressionsBeforeOpen[] =
     "Apps.AppListRecommendedImpResultCountAfterOpen";
 
-// Fields for working with pref syncable state.
-
-// Overall dictionary to use for all arc app reinstall states.
-constexpr char kAppState[] = "arc_app_reinstall_state";
-
-// field name for install start time, as milliseconds since epoch
-constexpr char kInstallStartTime[] = "install_start_time";
-
-// field name for install time, as milliseconds since epoch
-constexpr char kInstallTime[] = "install_time";
-// field name for install opened time, as milliseconds since epoch
-constexpr char kOpenTime[] = "open_time";
-// field name for uninstalltime, as milliseconds since epoch.
-constexpr char kUninstallTime[] = "uninstall_time";
-
-// field name for latest impressiontime, as milliseconds since epoch.
-constexpr char kImpressionTime[] = "impression_time";
-// Number of impressions.
-constexpr char kImpressionCount[] = "impression_count";
-
 // If uninstalled in this time, do not recommend.
 constexpr base::FeatureParam<int> kUninstallGrace(
     &app_list_features::kEnableAppReinstallZeroState,
@@ -100,7 +80,8 @@
                    const std::string& key,
                    const int64_t value) {
   const std::string int64_str = base::NumberToString(value);
-  DictionaryPrefUpdate update(profile->GetPrefs(), kAppState);
+  DictionaryPrefUpdate update(
+      profile->GetPrefs(), app_list::ArcAppReinstallSearchProvider::kAppState);
   base::DictionaryValue* const dictionary = update.Get();
   base::Value* package_item =
       dictionary->FindKeyOfType(package_name, base::Value::Type::DICTIONARY);
@@ -115,7 +96,8 @@
 void UpdateStateRemoveKey(Profile* profile,
                           const std::string& package_name,
                           const std::string& key) {
-  DictionaryPrefUpdate update(profile->GetPrefs(), kAppState);
+  DictionaryPrefUpdate update(
+      profile->GetPrefs(), app_list::ArcAppReinstallSearchProvider::kAppState);
   base::DictionaryValue* const dictionary = update.Get();
   base::Value* package_item =
       dictionary->FindKeyOfType(package_name, base::Value::Type::DICTIONARY);
@@ -137,8 +119,8 @@
                    const std::string& package_name,
                    const std::string& key,
                    int64_t* value) {
-  const base::DictionaryValue* dictionary =
-      profile->GetPrefs()->GetDictionary(kAppState);
+  const base::DictionaryValue* dictionary = profile->GetPrefs()->GetDictionary(
+      app_list::ArcAppReinstallSearchProvider::kAppState);
   if (!dictionary)
     return false;
   const base::Value* package_item =
@@ -171,8 +153,8 @@
 
 bool GetKnownPackageNames(Profile* profile,
                           std::unordered_set<std::string>* package_names) {
-  const base::DictionaryValue* dictionary =
-      profile->GetPrefs()->GetDictionary(kAppState);
+  const base::DictionaryValue* dictionary = profile->GetPrefs()->GetDictionary(
+      app_list::ArcAppReinstallSearchProvider::kAppState);
   for (const auto& it : dictionary->DictItems()) {
     if (it.second.is_dict()) {
       package_names->insert(it.first);
@@ -196,6 +178,27 @@
 
 namespace app_list {
 
+// static
+constexpr char ArcAppReinstallSearchProvider::kInstallTime[];
+
+// static
+constexpr char ArcAppReinstallSearchProvider::kAppState[];
+
+// static
+constexpr char ArcAppReinstallSearchProvider::kImpressionCount[];
+
+// static
+constexpr char ArcAppReinstallSearchProvider::kImpressionTime[];
+
+// static
+constexpr char ArcAppReinstallSearchProvider::kUninstallTime[];
+
+// static
+constexpr char ArcAppReinstallSearchProvider::kOpenTime[];
+
+// static
+constexpr char ArcAppReinstallSearchProvider::kInstallStartTime[];
+
 ArcAppReinstallSearchProvider::ArcAppReinstallSearchProvider(
     Profile* profile,
     unsigned int max_result_count)
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h
index 2534e7a..346f877 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h
@@ -26,9 +26,9 @@
                      TestResultsWithAppsChanged);
 FORWARD_DECLARE_TEST(ArcAppReinstallSearchProviderTest,
                      TestResultListComparison);
+FORWARD_DECLARE_TEST(ArcAppReinstallSearchProviderTest, TestShouldShowAnything);
 
 namespace app_list {
-
 // A search provider that returns app candidates that are reinstallation
 // candidates. The current provider of candidates for this provider is the Fast
 // App Reinstall API. This Provider returns a list of applications, in
@@ -43,6 +43,26 @@
       public ArcAppListPrefs::Observer,
       public ArcAppReinstallAppResult::Observer {
  public:
+  // Fields for working with pref syncable state.
+  // constants used for prefs.
+  static constexpr char kInstallTime[] = "install_time";
+
+  // Overall dictionary to use for all arc app reinstall states.
+  static constexpr char kAppState[] = "arc_app_reinstall_state";
+
+  // field name for install start time, as milliseconds since epoch
+  static constexpr char kInstallStartTime[] = "install_start_time";
+
+  // field name for install opened time, as milliseconds since epoch
+  static constexpr char kOpenTime[] = "open_time";
+  // field name for uninstalltime, as milliseconds since epoch.
+  static constexpr char kUninstallTime[] = "uninstall_time";
+
+  // field name for latest impressiontime, as milliseconds since epoch.
+  static constexpr char kImpressionTime[] = "impression_time";
+  // Number of impressions.
+  static constexpr char kImpressionCount[] = "impression_count";
+
   // Constructor receives the Profile in order to
   // instantiate App results. Ownership is not taken.
   //
@@ -65,7 +85,6 @@
   void OnVisibilityChanged(const std::string& id, bool visibility) override;
 
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
-
  private:
   FRIEND_TEST_ALL_PREFIXES(::ArcAppReinstallSearchProviderTest,
                            TestResultsWithSearchChanged);
@@ -73,6 +92,8 @@
                            TestResultsWithAppsChanged);
   FRIEND_TEST_ALL_PREFIXES(::ArcAppReinstallSearchProviderTest,
                            TestResultListComparison);
+  FRIEND_TEST_ALL_PREFIXES(::ArcAppReinstallSearchProviderTest,
+                           TestShouldShowAnything);
 
   // Called to start fetching from our server for this result set. Called when
   // the play store becomes available.
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc
index 89e6160..d9d1211c 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc
@@ -10,8 +10,8 @@
 
 #include "ash/public/cpp/app_list/app_list_features.h"
 #include "base/command_line.h"
-#include "base/metrics/field_trial_params.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/timer/mock_timer.h"
 #include "chrome/browser/ui/app_list/app_list_test_util.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
@@ -91,6 +91,15 @@
     package_item->SetKey(key, base::Value(int64_str));
   }
 
+  void SetStateTime(Profile* profile,
+                    const std::string& package_name,
+                    const std::string& key,
+                    const base::Time tstamp) {
+    const int64_t timestamp =
+        tstamp.ToDeltaSinceWindowsEpoch().InMilliseconds();
+    SetStateInt64(profile, package_name, key, timestamp);
+  }
+
   bool GetStateInt64(Profile* profile,
                      const std::string& package_name,
                      const std::string& key,
@@ -253,36 +262,43 @@
 
   // Check that impression counts are read and written appropriately.
   const std::string fake_package2 = "com.package.fakepackage2";
-  const std::string impression_count = "impression_count";
-  const std::string impression_time = "impression_time";
 
   // should update to 1.
   app_provider_->OnVisibilityChanged(fake_package2, true);
   int64_t loaded_impression_count = 0;
-  EXPECT_TRUE(GetStateInt64(profile_.get(), fake_package2, impression_count,
-                            &loaded_impression_count));
+  EXPECT_TRUE(
+      GetStateInt64(profile_.get(), fake_package2,
+                    app_list::ArcAppReinstallSearchProvider::kImpressionCount,
+                    &loaded_impression_count));
   EXPECT_EQ(1, loaded_impression_count);
   // An immediate re-show does nothing.
   app_provider_->OnVisibilityChanged(fake_package2, true);
   loaded_impression_count = 0;
-  EXPECT_TRUE(GetStateInt64(profile_.get(), fake_package2, impression_count,
-                            &loaded_impression_count));
+  EXPECT_TRUE(
+      GetStateInt64(profile_.get(), fake_package2,
+                    app_list::ArcAppReinstallSearchProvider::kImpressionCount,
+                    &loaded_impression_count));
   EXPECT_EQ(1, loaded_impression_count);
 
   // But, setting impression time back does.
   for (int i = 0; i < 4; ++i) {
-    SetStateInt64(profile_.get(), fake_package2, impression_time, 0);
+    SetStateInt64(profile_.get(), fake_package2,
+                  app_list::ArcAppReinstallSearchProvider::kImpressionTime, 0);
     app_provider_->OnVisibilityChanged(fake_package2, true);
   }
   loaded_impression_count = 0;
-  EXPECT_TRUE(GetStateInt64(profile_.get(), fake_package2, impression_count,
-                            &loaded_impression_count));
+  EXPECT_TRUE(
+      GetStateInt64(profile_.get(), fake_package2,
+                    app_list::ArcAppReinstallSearchProvider::kImpressionCount,
+                    &loaded_impression_count));
   EXPECT_EQ(5, loaded_impression_count);
 
-  SetStateInt64(profile_.get(), fake_package2, impression_count, 50);
+  SetStateInt64(profile_.get(), fake_package2,
+                app_list::ArcAppReinstallSearchProvider::kImpressionCount, 50);
   app_provider_->UpdateResults();
   EXPECT_EQ(0u, app_provider_->results().size());
-  SetStateInt64(profile_.get(), fake_package2, impression_count, 0);
+  SetStateInt64(profile_.get(), fake_package2,
+                app_list::ArcAppReinstallSearchProvider::kImpressionCount, 0);
   app_provider_->UpdateResults();
   app_provider_->OnIconLoaded("http://icon.com/icon1");
   EXPECT_EQ(1u, app_provider_->results().size());
@@ -295,6 +311,68 @@
   EXPECT_EQ(0u, app_provider_->results().size());
 }
 
+TEST_F(ArcAppReinstallSearchProviderTest, TestShouldShowAnything) {
+  EXPECT_TRUE(app_provider_->ShouldShowAnything());
+  std::map<std::string, std::string> feature_params;
+  feature_params["interaction_grace_hours"] = "72";
+  feature_params["impression_count_limit"] = "5";
+  const std::string fake_package2 = "com.package.fakepackage2";
+  const std::string fake_package3 = "com.package.fakepackage3";
+  const std::string fake_package4 = "com.package.fakepackage4";
+
+  base::test::ScopedFeatureList list;
+  list.InitWithFeaturesAndParameters(
+      {{app_list_features::kEnableAppReinstallZeroState, feature_params}}, {});
+  EXPECT_TRUE(app_provider_->ShouldShowAnything());
+  SetStateTime(profile_.get(), fake_package2,
+               app_list::ArcAppReinstallSearchProvider::kInstallTime,
+               base::Time::Now() - base::TimeDelta::FromSeconds(30));
+  // Expect this to now say we shouldn't show, since a package was installed
+  // well within an install grace.
+  EXPECT_FALSE(app_provider_->ShouldShowAnything());
+  SetStateTime(profile_.get(), fake_package2,
+               app_list::ArcAppReinstallSearchProvider::kInstallTime,
+               base::Time::Now() - base::TimeDelta::FromDays(30));
+  EXPECT_TRUE(app_provider_->ShouldShowAnything());
+
+  // Testing for opens: if an a recommendation is opened within the grace
+  // period, we won't show anything. That's 72 hours (per configuration here).
+  SetStateTime(profile_.get(), fake_package3,
+               app_list::ArcAppReinstallSearchProvider::kOpenTime,
+               base::Time::Now() - base::TimeDelta::FromSeconds(30));
+  EXPECT_FALSE(app_provider_->ShouldShowAnything());
+  SetStateTime(profile_.get(), fake_package3,
+               app_list::ArcAppReinstallSearchProvider::kOpenTime,
+               base::Time::Now() - base::TimeDelta::FromDays(30));
+  EXPECT_TRUE(app_provider_->ShouldShowAnything());
+
+  // Testing for impression counts: If we've shown a result more than the
+  // feature param "impression_count_limit", and the latest time we've shown it
+  // is within the grace period, do not show anything.
+  SetStateInt64(profile_.get(), fake_package4,
+                app_list::ArcAppReinstallSearchProvider::kImpressionCount, 10);
+  // no impression time is set, show.
+  EXPECT_TRUE(app_provider_->ShouldShowAnything());
+  // shown recently.
+  SetStateTime(profile_.get(), fake_package4,
+               app_list::ArcAppReinstallSearchProvider::kImpressionTime,
+               base::Time::Now() - base::TimeDelta::FromSeconds(30));
+  EXPECT_FALSE(app_provider_->ShouldShowAnything());
+  // shown long ago.
+  SetStateTime(profile_.get(), fake_package4,
+               app_list::ArcAppReinstallSearchProvider::kImpressionTime,
+               base::Time::Now() - base::TimeDelta::FromDays(30));
+  EXPECT_TRUE(app_provider_->ShouldShowAnything());
+
+  // Shown recently, but not frequently.
+  SetStateInt64(profile_.get(), fake_package4,
+                app_list::ArcAppReinstallSearchProvider::kImpressionCount, 3);
+  SetStateTime(profile_.get(), fake_package4,
+               app_list::ArcAppReinstallSearchProvider::kImpressionTime,
+               base::Time::Now() - base::TimeDelta::FromSeconds(30));
+  EXPECT_TRUE(app_provider_->ShouldShowAnything());
+}
+
 TEST_F(ArcAppReinstallSearchProviderTest, TestResultListComparison) {
   std::vector<std::unique_ptr<ChromeSearchResult>> a, b;
   EXPECT_TRUE(app_list::ArcAppReinstallSearchProvider::ResultsIdentical(a, b));
diff --git a/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc b/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc
index 580480a..c602ad5 100644
--- a/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc
+++ b/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc
@@ -75,6 +75,8 @@
 void FakeAccessibilityController::GetBatteryDescription(
     GetBatteryDescriptionCallback callback) {}
 
+void FakeAccessibilityController::SetVirtualKeyboardVisible(bool is_visible) {}
+
 void FakeAccessibilityController::Bind(mojo::ScopedMessagePipeHandle handle) {
   binding_.Bind(ash::mojom::AccessibilityControllerRequest(std::move(handle)));
 }
diff --git a/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.h b/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.h
index a97d43c..e94bbc2 100644
--- a/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.h
+++ b/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.h
@@ -46,6 +46,7 @@
       ash::mojom::DictationToggleSource source) override;
   void ForwardKeyEventsToSwitchAccess(bool should_forward) override;
   void GetBatteryDescription(GetBatteryDescriptionCallback callback) override;
+  void SetVirtualKeyboardVisible(bool is_visible) override;
 
  private:
   void Bind(mojo::ScopedMessagePipeHandle handle);
diff --git a/chrome/browser/ui/ash/drag_to_overview_interactive_uitest.cc b/chrome/browser/ui/ash/drag_to_overview_interactive_uitest.cc
deleted file mode 100644
index 6f8c507b..0000000
--- a/chrome/browser/ui/ash/drag_to_overview_interactive_uitest.cc
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2019 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 "ash/public/cpp/ash_switches.h"
-#include "ash/public/interfaces/constants.mojom.h"
-#include "ash/public/interfaces/shell_test_api.test-mojom-test-utils.h"
-#include "ash/public/interfaces/shell_test_api.test-mojom.h"
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/task/post_task.h"
-#include "base/test/bind_test_util.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/ui/ash/tablet_mode_client_test_util.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/views/tabs/tab_drag_controller.h"
-#include "chrome/browser/ui/views/tabs/tab_strip.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/interactive_test_utils.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/common/service_manager_connection.h"
-#include "content/public/test/test_utils.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "ui/aura/test/mus/change_completion_waiter.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_observer.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/test/ui_controls.h"
-#include "ui/compositor/compositor.h"
-#include "ui/display/display.h"
-#include "ui/display/screen.h"
-#include "ui/gfx/geometry/vector2d.h"
-#include "ui/views/widget/widget.h"
-#include "ui/views/widget/widget_observer.h"
-
-namespace {
-
-bool IsOverviewSelecting() {
-  ash::mojom::ShellTestApiPtr shell_test_api;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &shell_test_api);
-  ash::mojom::ShellTestApiAsyncWaiter waiter(shell_test_api.get());
-  bool is_selecting = false;
-  waiter.IsOverviewSelecting(&is_selecting);
-  return is_selecting;
-}
-
-int GetDetachY(TabStrip* tab_strip) {
-  return std::max(TabDragController::kTouchVerticalDetachMagnetism,
-                  TabDragController::kVerticalDetachMagnetism) +
-         tab_strip->height() + 1;
-}
-
-// Waits for the primary display to present a frame after the object is
-// constructed.
-class NextFrameWaiter {
- public:
-  NextFrameWaiter() {
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(ash::mojom::kServiceName, &shell_test_api_);
-    shell_test_api_->WaitForNextFrame(base::BindOnce(
-        &NextFrameWaiter::OnFramePresented, base::Unretained(this)));
-    // Flush to ensure the call has gone through.
-    shell_test_api_.FlushForTesting();
-  }
-  ~NextFrameWaiter() { EXPECT_TRUE(frame_presented_); }
-
-  void WaitForDisplay() {
-    if (!frame_presented_) {
-      run_loop_ = std::make_unique<base::RunLoop>(
-          base::RunLoop::Type::kNestableTasksAllowed);
-      run_loop_->Run();
-      EXPECT_TRUE(frame_presented_);
-    }
-  }
-
- private:
-  void OnFramePresented() {
-    frame_presented_ = true;
-    if (run_loop_)
-      run_loop_->Quit();
-  }
-
-  ash::mojom::ShellTestApiPtr shell_test_api_;
-  bool frame_presented_ = false;
-  std::unique_ptr<base::RunLoop> run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(NextFrameWaiter);
-};
-
-}  // namespace
-
-class DragToOverviewTest : public InProcessBrowserTest {
- public:
-  DragToOverviewTest() = default;
-  ~DragToOverviewTest() override = default;
-
-  // InProcessBrowserTest:
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitch(ash::switches::kAshEnableTabletMode);
-  }
-  void SetUpOnMainThread() override {
-    test::SetAndWaitForTabletMode(true);
-
-    if (base::SysInfo::IsRunningOnChromeOS()) {
-      base::RunLoop run_loop;
-      base::PostDelayedTask(FROM_HERE, run_loop.QuitClosure(),
-                            base::TimeDelta::FromSeconds(5));
-      run_loop.Run();
-    }
-  }
-
-  // Continue a drag by perform |count| steps mouse dragging with each step move
-  // |delta|, then moue up.
-  void ContinueDrag(const gfx::Point& start_position,
-                    const gfx::Vector2d& delta,
-                    int count) {
-    gfx::Point drag_position = start_position;
-    for (int i = 0; i < count; ++i) {
-      drag_position += delta;
-
-      NextFrameWaiter waiter;
-      ASSERT_TRUE(
-          ui_controls::SendMouseMove(drag_position.x(), drag_position.y()));
-      waiter.WaitForDisplay();
-    }
-
-    {
-      NextFrameWaiter waiter;
-      ASSERT_TRUE(
-          ui_controls::SendMouseEvents(ui_controls::LEFT, ui_controls::UP));
-      waiter.WaitForDisplay();
-    }
-  }
-
-  void VerifyTabDetachedAndContinueDrag(const gfx::Point& start_position,
-                                        const gfx::Vector2d delta,
-                                        int count) {
-    // Tab should be detached to create a new browser window.
-    EXPECT_EQ(2u, BrowserList::GetInstance()->size());
-    EXPECT_TRUE(TabDragController::IsActive());
-
-    ContinueDrag(start_position, delta, count);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(DragToOverviewTest);
-};
-
-IN_PROC_BROWSER_TEST_F(DragToOverviewTest, DragWindow) {
-  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
-  aura::Window* browser_window = browser_view->GetWidget()->GetNativeWindow();
-  gfx::Rect browser_screen_bounds = browser_window->GetBoundsInScreen();
-
-  const gfx::Point start_position(
-      browser_screen_bounds.CenterPoint().x(),
-      browser_screen_bounds.y() + browser_view->GetTabStripHeight() / 2);
-
-  ASSERT_TRUE(
-      ui_test_utils::SendMouseMoveSync(start_position) &&
-      ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, ui_controls::DOWN));
-
-  // One more mouse move to start drag.
-  ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(start_position));
-
-  // Drag 25% of the work area height.
-  const int drag_length = display::Screen::GetScreen()
-                              ->GetDisplayNearestWindow(browser_window)
-                              .work_area_size()
-                              .height() /
-                          4;
-  constexpr int kSteps = 20;
-  gfx::Vector2d delta(0, drag_length / kSteps);
-  ContinueDrag(start_position, delta, kSteps);
-  EXPECT_TRUE(IsOverviewSelecting());
-}
-
-IN_PROC_BROWSER_TEST_F(DragToOverviewTest, DragTab) {
-  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
-  aura::Window* browser_window = browser_view->GetWidget()->GetNativeWindow();
-
-  AddBlankTabAndShow(browser());
-  browser_view->tabstrip()->StopAnimating(true);
-  aura::test::WaitForAllChangesToComplete();
-
-  gfx::Point drag_position(ui_test_utils::GetCenterInScreenCoordinates(
-      browser_view->tabstrip()->tab_at(0)));
-
-  ASSERT_TRUE(
-      ui_test_utils::SendMouseMoveSync(drag_position) &&
-      ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, ui_controls::DOWN));
-
-  // Drag 25% of the work area height.
-  const int drag_length = display::Screen::GetScreen()
-                              ->GetDisplayNearestWindow(browser_window)
-                              .work_area_size()
-                              .height() /
-                          4;
-  constexpr int kSteps = 20;
-  gfx::Vector2d delta(0, drag_length / kSteps);
-
-  // Drag tab far enough to detach.
-  drag_position.Offset(0, GetDetachY(browser_view->tabstrip()));
-  ui_controls::SendMouseMoveNotifyWhenDone(
-      drag_position.x(), drag_position.y(),
-      base::BindOnce(&DragToOverviewTest::VerifyTabDetachedAndContinueDrag,
-                     base::Unretained(this), drag_position, delta, kSteps));
-
-  // Wait for the drag to finish.
-  content::WindowedNotificationObserver(
-      chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE,
-      content::NotificationService::AllSources())
-      .Wait();
-}
diff --git a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
index 40af67d5..757cdc5 100644
--- a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
@@ -21,8 +21,8 @@
 #include "ui/aura/test/mus/change_completion_waiter.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/ime/dummy_text_input_client.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_factory.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
diff --git a/chrome/browser/ui/ash/network/mobile_data_notifications_unittest.cc b/chrome/browser/ui/ash/network/mobile_data_notifications_unittest.cc
index 64dd96a7..499f02a 100644
--- a/chrome/browser/ui/ash/network/mobile_data_notifications_unittest.cc
+++ b/chrome/browser/ui/ash/network/mobile_data_notifications_unittest.cc
@@ -20,8 +20,8 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_connect.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ui/ash/network/network_state_notifier_unittest.cc b/chrome/browser/ui/ash/network/network_state_notifier_unittest.cc
index d2cedc7..165efcb 100644
--- a/chrome/browser/ui/ash/network/network_state_notifier_unittest.cc
+++ b/chrome/browser/ui/ash/network/network_state_notifier_unittest.cc
@@ -13,8 +13,8 @@
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/network_connect.h"
 #include "chromeos/network/network_handler.h"
diff --git a/chrome/browser/ui/ash/session_controller_client.cc b/chrome/browser/ui/ash/session_controller_client.cc
index 79d3b5be..f314c433 100644
--- a/chrome/browser/ui/ash/session_controller_client.cc
+++ b/chrome/browser/ui/ash/session_controller_client.cc
@@ -36,7 +36,6 @@
 #include "chrome/common/pref_names.h"
 #include "chromeos/assistant/buildflags.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
@@ -318,9 +317,7 @@
   // purely by emitting D-Bus signals, and thus has to be run whenever Ash is
   // started so Ash (DetachableBaseHandler in particular) gets the proper view
   // of the current detachable base state.
-  chromeos::DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->EmitAshInitialized();
+  chromeos::SessionManagerClient::Get()->EmitAshInitialized();
 }
 
 // static
@@ -407,9 +404,7 @@
     return;
 
   VLOG(1) << "Requesting screen lock from SessionControllerClient";
-  chromeos::DBusThreadManager::Get()
-      ->GetSessionManagerClient()
-      ->RequestLockScreen();
+  chromeos::SessionManagerClient::Get()->RequestLockScreen();
 }
 
 // static
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index dddd8de..fac29c30 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -1210,7 +1210,8 @@
   // Show various bits of UI
   command_updater_.UpdateCommandEnabled(IDC_DEVELOPER_MENU, show_main_ui);
 #if defined(GOOGLE_CHROME_BUILD)
-  command_updater_.UpdateCommandEnabled(IDC_FEEDBACK, show_main_ui);
+  command_updater_.UpdateCommandEnabled(
+      IDC_FEEDBACK, show_main_ui || browser_->is_devtools());
 #endif
   UpdateShowSyncState(show_main_ui);
 
diff --git a/chrome/browser/ui/libgtkui/BUILD.gn b/chrome/browser/ui/libgtkui/BUILD.gn
index 407f90ce..ced5ef6 100644
--- a/chrome/browser/ui/libgtkui/BUILD.gn
+++ b/chrome/browser/ui/libgtkui/BUILD.gn
@@ -106,6 +106,7 @@
     "//ui/aura",
     "//ui/base",
     "//ui/base/ime",
+    "//ui/base/ime/linux",
     "//ui/display",
     "//ui/events",
     "//ui/events:dom_keyboard_layout",
diff --git a/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.cc b/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.cc
index f9926db..c8b9604 100644
--- a/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.cc
+++ b/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.cc
@@ -13,7 +13,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/ime/composition_text.h"
-#include "ui/base/ime/composition_text_util_pango.h"
+#include "ui/base/ime/linux/composition_text_util_pango.h"
 #include "ui/base/ime/text_input_client.h"
 #include "ui/events/event.h"
 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
diff --git a/chrome/browser/ui/startup/bad_flags_prompt.cc b/chrome/browser/ui/startup/bad_flags_prompt.cc
index 182a3db6..5d597f93 100644
--- a/chrome/browser/ui/startup/bad_flags_prompt.cc
+++ b/chrome/browser/ui/startup/bad_flags_prompt.cc
@@ -35,6 +35,7 @@
 #include "content/public/common/content_switches.h"
 #include "extensions/common/switches.h"
 #include "google_apis/gaia/gaia_switches.h"
+#include "gpu/config/gpu_switches.h"
 #include "media/base/media_switches.h"
 #include "media/media_buildflags.h"
 #include "services/network/public/cpp/network_switches.h"
@@ -126,6 +127,10 @@
     // Enables save data feature which can cause user traffic to be proxied via
     // Google's data reduction proxy servers.
     data_reduction_proxy::switches::kEnableDataReductionProxy,
+
+    // GPU sanboxing isn't implemented for the Web GPU API yet meaning it would
+    // be possible to read GPU data for other Chromium processes.
+    switches::kEnableUnsafeWebGPU,
 };
 #endif  // OS_ANDROID
 
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 7a91403..0881e5ff 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -1258,7 +1258,7 @@
   // appear until second run.  However, if NuxOnboarding is enabled, the
   // standard welcome URL should still be used.
   bool is_navi_enabled = false;
-#if defined(GOOGLE_CHROME_BUILD)
+#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
   is_navi_enabled = nux::IsNuxOnboardingEnabled(profile1);
 #endif
   if (IsWindows10OrNewer() && !is_navi_enabled) {
diff --git a/chrome/browser/ui/tabs/tab_menu_model.cc b/chrome/browser/ui/tabs/tab_menu_model.cc
index f80cbc4..779d9d1 100644
--- a/chrome/browser/ui/tabs/tab_menu_model.cc
+++ b/chrome/browser/ui/tabs/tab_menu_model.cc
@@ -85,7 +85,8 @@
 
   if (send_tab_to_self::ShouldOfferFeature(
           tab_strip->profile(), tab_strip->GetWebContentsAt(index))) {
-    base::RecordAction(UserMetricsAction("TabContextMenu_SendTabToSelf_Shown"));
+    send_tab_to_self::RecordSendTabToSelfClickResult(
+        send_tab_to_self::kTabMenu, SendTabToSelfClickResult::kShowItem);
     AddSeparator(ui::NORMAL_SEPARATOR);
     AddItemWithStringIdAndIcon(TabStripModel::CommandSendTabToSelf,
                                IDS_CONTEXT_MENU_SEND_TAB_TO_SELF,
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc
index 170008c..b34ca79 100644
--- a/chrome/browser/ui/tabs/tab_strip_model.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/lifetime/browser_shutdown.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h"
+#include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
@@ -1214,8 +1215,8 @@
     }
 
     case CommandSendTabToSelf: {
-      base::RecordAction(
-          UserMetricsAction("TabContextMenu_SendTabToSelf_Clicked"));
+      send_tab_to_self::RecordSendTabToSelfClickResult(
+          send_tab_to_self::kTabMenu, SendTabToSelfClickResult::kClickItem);
       send_tab_to_self::CreateNewEntry(GetActiveWebContents(), profile_);
       break;
     }
diff --git a/chrome/browser/ui/tabs/tab_utils.cc b/chrome/browser/ui/tabs/tab_utils.cc
index da380e4..9deb09a 100644
--- a/chrome/browser/ui/tabs/tab_utils.cc
+++ b/chrome/browser/ui/tabs/tab_utils.cc
@@ -48,9 +48,6 @@
   if (usb_tab_helper && usb_tab_helper->IsDeviceConnected())
     return TabAlertState::USB_CONNECTED;
 
-  if (contents->IsConnectedToSerialPort())
-    return TabAlertState::SERIAL_CONNECTED;
-
   // Check if VR content is being presented in a headset.
   // NOTE: This icon must take priority over the audio alert ones
   // because most VR content has audio and its usage is implied by the VR icon.
@@ -88,7 +85,6 @@
     case TabAlertState::TAB_CAPTURING:
     case TabAlertState::BLUETOOTH_CONNECTED:
     case TabAlertState::USB_CONNECTED:
-    case TabAlertState::SERIAL_CONNECTED:
     case TabAlertState::DESKTOP_CAPTURING:
       // The new Audio Service implements muting separately from the tab audio
       // capture infrastructure; so the mute state can be toggled independently
diff --git a/chrome/browser/ui/tabs/tab_utils.h b/chrome/browser/ui/tabs/tab_utils.h
index e9ff577..8e4ca381 100644
--- a/chrome/browser/ui/tabs/tab_utils.h
+++ b/chrome/browser/ui/tabs/tab_utils.h
@@ -28,7 +28,6 @@
   AUDIO_MUTING,         // Tab audio is being muted.
   BLUETOOTH_CONNECTED,  // Tab is connected to a BT Device.
   USB_CONNECTED,        // Tab is connected to a USB device.
-  SERIAL_CONNECTED,     // Tab is connected to a serial device.
   PIP_PLAYING,          // Tab contains a video in Picture-in-Picture mode.
   DESKTOP_CAPTURING,    // Desktop contents being recorded, consumed by tab.
   VR_PRESENTING_IN_HEADSET,  // VR content is being presented in a headset.
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.cc b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
index 0128cd71..b2dff7aa 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_model.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
@@ -12,6 +12,7 @@
 #include "base/location.h"
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/one_shot_event.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -39,7 +40,6 @@
 #include "extensions/browser/pref_names.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/common/manifest_constants.h"
-#include "extensions/common/one_shot_event.h"
 
 ToolbarActionsModel::ToolbarActionsModel(
     Profile* profile,
@@ -59,8 +59,8 @@
       load_error_reporter_observer_(this),
       weak_ptr_factory_(this) {
   extensions::ExtensionSystem::Get(profile_)->ready().Post(
-      FROM_HERE, base::Bind(&ToolbarActionsModel::OnReady,
-                            weak_ptr_factory_.GetWeakPtr()));
+      FROM_HERE, base::BindOnce(&ToolbarActionsModel::OnReady,
+                                weak_ptr_factory_.GetWeakPtr()));
   visible_icon_count_ =
       prefs_->GetInteger(extensions::pref_names::kToolbarSize);
 
diff --git a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
index 10606aa..6dd7cd9 100644
--- a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
+++ b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
@@ -116,27 +116,25 @@
   SetBorder(views::CreateEmptyBorder(
       provider->GetInsetsMetric(views::INSETS_DIALOG)));
 
-  views::Label* header =
-      new views::Label(l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_HEADER),
-                       CONTEXT_BODY_TEXT_LARGE);
+  auto high_contrast = std::make_unique<views::Link>(
+      l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_EXT),
+      CONTEXT_BODY_TEXT_LARGE);
+  high_contrast->set_listener(this);
 
-  high_contrast_ =
-      new views::Link(l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_EXT),
-                      CONTEXT_BODY_TEXT_LARGE);
-  high_contrast_->set_listener(this);
-
-  dark_theme_ = new views::Link(l10n_util::GetStringUTF16(IDS_DARK_THEME),
-                                CONTEXT_BODY_TEXT_LARGE);
-  dark_theme_->set_listener(this);
+  auto dark_theme = std::make_unique<views::Link>(
+      l10n_util::GetStringUTF16(IDS_DARK_THEME), CONTEXT_BODY_TEXT_LARGE);
+  dark_theme->set_listener(this);
 
   views::BoxLayout* layout = SetLayoutManager(
       std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
   layout->set_cross_axis_alignment(
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
 
-  AddChildView(header);
-  AddChildView(high_contrast_);
-  AddChildView(dark_theme_);
+  AddChildView(std::make_unique<views::Label>(
+      l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_HEADER),
+      CONTEXT_BODY_TEXT_LARGE));
+  high_contrast_ = AddChildView(std::move(high_contrast));
+  dark_theme_ = AddChildView(std::move(dark_theme));
 
   // Switching to high-contrast mode has a nasty habit of causing Chrome
   // top-level windows to lose focus, so closing the bubble on deactivate
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
index 022697f2..ccc76971 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.h"
 
-#include <memory>
 #include <utility>
 
 #include "base/macros.h"
@@ -79,10 +78,10 @@
 // with an accelerator to close on escape.
 class BaseDialogContainer : public views::DialogDelegateView {
  public:
-  BaseDialogContainer(views::View* dialog_body,
+  BaseDialogContainer(std::unique_ptr<views::View> dialog_body,
                       const base::Closure& close_callback)
-      : dialog_body_(dialog_body), close_callback_(close_callback) {
-    AddChildView(dialog_body_);
+      : dialog_body_(AddChildView(std::move(dialog_body))),
+        close_callback_(close_callback) {
     // Since we are using a ClientView instead of a DialogClientView, we need to
     // manually bind the escape key to close the dialog.
     ui::Accelerator escape(ui::VKEY_ESCAPE, ui::EF_NONE);
@@ -134,12 +133,12 @@
 class AppListDialogContainer : public BaseDialogContainer,
                                public views::ButtonListener {
  public:
-  explicit AppListDialogContainer(views::View* dialog_body)
-      : BaseDialogContainer(dialog_body, base::RepeatingClosure()) {
+  explicit AppListDialogContainer(std::unique_ptr<views::View> dialog_body)
+      : BaseDialogContainer(std::move(dialog_body), base::RepeatingClosure()) {
     SetBackground(std::make_unique<AppListOverlayBackground>());
-    close_button_ = views::BubbleFrameView::CreateCloseButton(
-        this, GetNativeTheme()->SystemDarkModeEnabled());
-    AddChildView(close_button_);
+    close_button_ =
+        AddChildView(base::WrapUnique(views::BubbleFrameView::CreateCloseButton(
+            this, GetNativeTheme()->SystemDarkModeEnabled())));
   }
   ~AppListDialogContainer() override {}
 
@@ -216,10 +215,10 @@
 // A container view for a native dialog, which sizes to the given fixed |size|.
 class NativeDialogContainer : public BaseDialogContainer {
  public:
-  NativeDialogContainer(views::View* dialog_body,
+  NativeDialogContainer(std::unique_ptr<views::View> dialog_body,
                         const gfx::Size& size,
                         const base::Closure& close_callback)
-      : BaseDialogContainer(dialog_body, close_callback) {
+      : BaseDialogContainer(std::move(dialog_body), close_callback) {
     SetLayoutManager(std::make_unique<views::FillLayout>());
     chrome::RecordDialogCreation(chrome::DialogIdentifier::NATIVE_CONTAINER);
     SetPreferredSize(size);
@@ -231,8 +230,8 @@
   views::NonClientFrameView* CreateNonClientFrameView(
       views::Widget* widget) override {
     FullSizeBubbleFrameView* frame = new FullSizeBubbleFrameView();
-    std::unique_ptr<views::BubbleBorder> border(new views::BubbleBorder(
-        views::BubbleBorder::FLOAT, kShadowType, gfx::kPlaceholderColor));
+    auto border = std::make_unique<views::BubbleBorder>(
+        views::BubbleBorder::FLOAT, kShadowType, gfx::kPlaceholderColor);
     border->set_use_theme_background_color(true);
     frame->SetBubbleBorder(std::move(border));
     return frame;
@@ -244,14 +243,15 @@
 }  // namespace
 
 #if BUILDFLAG(ENABLE_APP_LIST)
-views::DialogDelegateView* CreateAppListContainerForView(views::View* view) {
-  return new AppListDialogContainer(view);
+views::DialogDelegateView* CreateAppListContainerForView(
+    std::unique_ptr<views::View> view) {
+  return new AppListDialogContainer(std::move(view));
 }
 #endif  // ENABLE_APP_LIST
 
 views::DialogDelegateView* CreateDialogContainerForView(
-    views::View* view,
+    std::unique_ptr<views::View> view,
     const gfx::Size& size,
     const base::Closure& close_callback) {
-  return new NativeDialogContainer(view, size, close_callback);
+  return new NativeDialogContainer(std::move(view), size, close_callback);
 }
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.h b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.h
index 1c7cc96..d9a17f5 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.h
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_APPS_APP_INFO_DIALOG_APP_INFO_DIALOG_CONTAINER_H_
 #define CHROME_BROWSER_UI_VIEWS_APPS_APP_INFO_DIALOG_APP_INFO_DIALOG_CONTAINER_H_
 
+#include <memory>
+
 #include "base/callback_forward.h"
 #include "chrome/common/buildflags.h"
 #include "ui/gfx/geometry/size.h"
@@ -17,16 +19,16 @@
 #if BUILDFLAG(ENABLE_APP_LIST)
 
 // Creates a new dialog containing |view| that can be displayed inside the app
-// list, covering the entire app list and adding a close button. Takes ownership
-// of |view|.
-views::DialogDelegateView* CreateAppListContainerForView(views::View* view);
+// list, covering the entire app list and adding a close button.
+views::DialogDelegateView* CreateAppListContainerForView(
+    std::unique_ptr<views::View> view);
 
 #endif  // ENABLE_APP_LIST
 
 // Creates a new native dialog of the given |size| containing |view| with a
-// close button and draggable titlebar. Takes ownership of |view|.
+// close button and draggable titlebar.
 views::DialogDelegateView* CreateDialogContainerForView(
-    views::View* view,
+    std::unique_ptr<views::View> view,
     const gfx::Size& size,
     const base::Closure& close_callback);
 
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc
index 0800a788..c69b4d1 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc
@@ -71,8 +71,8 @@
 void ShowAppInfoInAppList(const gfx::Rect& app_info_bounds,
                           Profile* profile,
                           const extensions::Extension* app) {
-  views::View* app_info_view = new AppInfoDialog(profile, app);
-  views::DialogDelegate* dialog = CreateAppListContainerForView(app_info_view);
+  views::DialogDelegate* dialog = CreateAppListContainerForView(
+      std::make_unique<AppInfoDialog>(profile, app));
   views::Widget* dialog_widget = new views::Widget();
   views::Widget::InitParams params =
       views::DialogDelegate::GetDialogWidgetInitParams(dialog, nullptr, nullptr,
@@ -90,10 +90,10 @@
                                Profile* profile,
                                const extensions::Extension* app,
                                const base::Closure& close_callback) {
-  views::View* app_info_view = new AppInfoDialog(profile, app);
   constexpr gfx::Size kDialogSize = gfx::Size(380, 490);
-  views::DialogDelegate* dialog =
-      CreateDialogContainerForView(app_info_view, kDialogSize, close_callback);
+  views::DialogDelegate* dialog = CreateDialogContainerForView(
+      std::make_unique<AppInfoDialog>(profile, app), kDialogSize,
+      close_callback);
   views::Widget* dialog_widget;
   if (dialog->GetModalType() == ui::MODAL_TYPE_CHILD) {
     dialog_widget =
@@ -112,19 +112,6 @@
       std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
 
   const int kHorizontalSeparatorHeight = 1;
-  dialog_header_ = new AppInfoHeaderPanel(profile, app);
-  dialog_header_->SetBorder(views::CreateSolidSidedBorder(
-      0, 0, kHorizontalSeparatorHeight, 0, kDialogSeparatorColor));
-
-  dialog_footer_ = new AppInfoFooterPanel(profile, app);
-  if (dialog_footer_->children().empty()) {
-    // If there are no controls in the footer, don't add it to the dialog.
-    delete dialog_footer_;
-    dialog_footer_ = NULL;
-  } else {
-    dialog_footer_->SetBorder(views::CreateSolidSidedBorder(
-        kHorizontalSeparatorHeight, 0, 0, 0, kDialogSeparatorColor));
-  }
 
   // Make a vertically stacked view of all the panels we want to display in the
   // dialog.
@@ -134,8 +121,10 @@
       views::BoxLayout::kVertical,
       provider->GetInsetsMetric(views::INSETS_DIALOG_SUBSECTION),
       provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL)));
-  dialog_body_contents->AddChildView(new AppInfoSummaryPanel(profile, app));
-  dialog_body_contents->AddChildView(new AppInfoPermissionsPanel(profile, app));
+  dialog_body_contents->AddChildView(
+      std::make_unique<AppInfoSummaryPanel>(profile, app));
+  dialog_body_contents->AddChildView(
+      std::make_unique<AppInfoPermissionsPanel>(profile, app));
 
 #if defined(OS_CHROMEOS)
   // When Google Play Store is enabled and the Settings app is available, show
@@ -145,8 +134,8 @@
     const ArcAppListPrefs* arc_app_list_prefs = ArcAppListPrefs::Get(profile);
     if (arc_app_list_prefs &&
         arc_app_list_prefs->IsRegistered(arc::kSettingsAppId)) {
-      arc_app_info_links_ = new ArcAppInfoLinksPanel(profile, app);
-      dialog_body_contents->AddChildView(arc_app_info_links_);
+      arc_app_info_links_ = dialog_body_contents->AddChildView(
+          std::make_unique<ArcAppInfoLinksPanel>(profile, app));
     }
   }
 #endif
@@ -157,17 +146,24 @@
   // TODO(sashab): Add ClipHeight() as a parameter-less method to
   // views::ScrollView() to mimic this behaviour.
   const int kMaxDialogHeight = 1000;
-  dialog_body_ = new views::ScrollView();
-  dialog_body_->ClipHeightTo(kMaxDialogHeight, kMaxDialogHeight);
-  dialog_body_->SetContents(std::move(dialog_body_contents));
+  auto dialog_body = std::make_unique<views::ScrollView>();
+  dialog_body->ClipHeightTo(kMaxDialogHeight, kMaxDialogHeight);
+  dialog_body->SetContents(std::move(dialog_body_contents));
 
-  AddChildView(dialog_header_);
+  auto dialog_header = std::make_unique<AppInfoHeaderPanel>(profile, app);
+  dialog_header->SetBorder(views::CreateSolidSidedBorder(
+      0, 0, kHorizontalSeparatorHeight, 0, kDialogSeparatorColor));
+  dialog_header_ = AddChildView(std::move(dialog_header));
 
-  AddChildView(dialog_body_);
+  dialog_body_ = AddChildView(std::move(dialog_body));
   layout->SetFlexForView(dialog_body_, 1);
 
-  if (dialog_footer_)
-    AddChildView(dialog_footer_);
+  auto dialog_footer = AppInfoFooterPanel::CreateFooterPanel(profile, app);
+  if (dialog_footer) {
+    dialog_footer->SetBorder(views::CreateSolidSidedBorder(
+        kHorizontalSeparatorHeight, 0, 0, 0, kDialogSeparatorColor));
+    dialog_footer_ = AddChildView(std::move(dialog_footer));
+  }
 
   // Close the dialog if the app is uninstalled, or if the profile is destroyed.
   StartObservingExtensionRegistry();
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
index a971cde..4e5e4ab 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
@@ -134,9 +134,8 @@
     widget_ = views::DialogDelegate::CreateDialogWidget(
         new views::DialogDelegateView(), GetContext(), nullptr);
     widget_->AddObserver(this);
-    dialog_ = new AppInfoDialog(profile, extension);
-
-    widget_->GetContentsView()->AddChildView(dialog_);
+    dialog_ = widget_->GetContentsView()->AddChildView(
+        std::make_unique<AppInfoDialog>(profile, extension));
     widget_->Show();
   }
 
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc
index 45a347db..be3817b 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.h"
 
+#include "base/memory/ptr_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
@@ -31,13 +32,7 @@
 AppInfoFooterPanel::AppInfoFooterPanel(Profile* profile,
                                        const extensions::Extension* app)
     : AppInfoPanel(profile, app),
-      create_shortcuts_button_(NULL),
-      pin_to_shelf_button_(NULL),
-      unpin_from_shelf_button_(NULL),
-      remove_button_(NULL),
       weak_ptr_factory_(this) {
-  CreateButtons();
-
   ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
 
   SetLayoutManager(std::make_unique<views::BoxLayout>(
@@ -45,51 +40,55 @@
       provider->GetInsetsMetric(views::INSETS_DIALOG_SUBSECTION),
       provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL)));
 
-  LayoutButtons();
+  CreateButtons();
 }
 
 AppInfoFooterPanel::~AppInfoFooterPanel() {
 }
 
+// static
+std::unique_ptr<AppInfoFooterPanel> AppInfoFooterPanel::CreateFooterPanel(
+    Profile* profile,
+    const extensions::Extension* app) {
+  if (CanCreateShortcuts(app) ||
+#if defined(OS_CHROMEOS)
+      CanSetPinnedToShelf(profile, app) ||
+#endif
+      CanUninstallApp(profile, app))
+    return std::make_unique<AppInfoFooterPanel>(profile, app);
+  return nullptr;
+}
+
 void AppInfoFooterPanel::CreateButtons() {
-  if (CanCreateShortcuts()) {
-    create_shortcuts_button_ = views::MdTextButton::CreateSecondaryUiButton(
-        this, l10n_util::GetStringUTF16(
-                  IDS_APPLICATION_INFO_CREATE_SHORTCUTS_BUTTON_TEXT));
+  if (CanCreateShortcuts(app_)) {
+    create_shortcuts_button_ = AddChildView(base::WrapUnique<views::View>(
+        views::MdTextButton::CreateSecondaryUiButton(
+            this, l10n_util::GetStringUTF16(
+                      IDS_APPLICATION_INFO_CREATE_SHORTCUTS_BUTTON_TEXT))));
   }
 
 #if defined(OS_CHROMEOS)
-  if (CanSetPinnedToShelf()) {
-    pin_to_shelf_button_ = views::MdTextButton::CreateSecondaryUiButton(
-        this, l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_PIN));
-    unpin_from_shelf_button_ = views::MdTextButton::CreateSecondaryUiButton(
-        this, l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_UNPIN));
+  if (CanSetPinnedToShelf(profile_, app_)) {
+    pin_to_shelf_button_ = AddChildView(base::WrapUnique<views::View>(
+        views::MdTextButton::CreateSecondaryUiButton(
+            this, l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_PIN))));
+    unpin_from_shelf_button_ = AddChildView(base::WrapUnique<views::View>(
+        views::MdTextButton::CreateSecondaryUiButton(
+            this, l10n_util::GetStringUTF16(IDS_APP_LIST_CONTEXT_MENU_UNPIN))));
+    UpdatePinButtons(false);
   }
 #endif
 
-  if (CanUninstallApp()) {
-    remove_button_ = views::MdTextButton::CreateSecondaryUiButton(
-        this,
-        l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_UNINSTALL_BUTTON_TEXT));
+  if (CanUninstallApp(profile_, app_)) {
+    remove_button_ = AddChildView(base::WrapUnique<views::View>(
+        views::MdTextButton::CreateSecondaryUiButton(
+            this, l10n_util::GetStringUTF16(
+                      IDS_APPLICATION_INFO_UNINSTALL_BUTTON_TEXT))));
   }
 }
 
-void AppInfoFooterPanel::LayoutButtons() {
-  if (create_shortcuts_button_)
-    AddChildView(create_shortcuts_button_);
-
-  if (pin_to_shelf_button_)
-    AddChildView(pin_to_shelf_button_);
-  if (unpin_from_shelf_button_)
-    AddChildView(unpin_from_shelf_button_);
-  UpdatePinButtons(false);
-
-  if (remove_button_)
-    AddChildView(remove_button_);
-}
-
-void AppInfoFooterPanel::UpdatePinButtons(bool focus_visible_button) {
 #if defined(OS_CHROMEOS)
+void AppInfoFooterPanel::UpdatePinButtons(bool focus_visible_button) {
   if (pin_to_shelf_button_ && unpin_from_shelf_button_) {
     const bool was_pinned =
         ChromeLauncherController::instance()->shelf_model()->IsAppPinned(
@@ -103,8 +102,8 @@
       button_to_focus->RequestFocus();
     }
   }
-#endif
 }
+#endif
 
 void AppInfoFooterPanel::ButtonPressed(views::Button* sender,
                                        const ui::Event& event) {
@@ -135,26 +134,27 @@
 }
 
 void AppInfoFooterPanel::CreateShortcuts() {
-  DCHECK(CanCreateShortcuts());
+  DCHECK(CanCreateShortcuts(app_));
   chrome::ShowCreateChromeAppShortcutsDialog(GetWidget()->GetNativeWindow(),
                                              profile_,
                                              app_,
                                              base::Callback<void(bool)>());
 }
 
-bool AppInfoFooterPanel::CanCreateShortcuts() const {
+// static
+bool AppInfoFooterPanel::CanCreateShortcuts(const extensions::Extension* app) {
 #if defined(OS_CHROMEOS)
   // Ash platforms can't create shortcuts.
   return false;
 #else
   // Extensions and the Chrome component app can't have shortcuts.
-  return app_->id() != extension_misc::kChromeAppId && !app_->is_extension();
+  return app->id() != extension_misc::kChromeAppId && !app->is_extension();
 #endif  // OS_CHROMEOS
 }
 
 #if defined(OS_CHROMEOS)
 void AppInfoFooterPanel::SetPinnedToShelf(bool value) {
-  DCHECK(CanSetPinnedToShelf());
+  DCHECK(CanSetPinnedToShelf(profile_, app_));
   ash::ShelfModel* shelf_model =
       ChromeLauncherController::instance()->shelf_model();
   DCHECK(shelf_model);
@@ -167,16 +167,18 @@
   Layout();
 }
 
-bool AppInfoFooterPanel::CanSetPinnedToShelf() const {
+// static
+bool AppInfoFooterPanel::CanSetPinnedToShelf(Profile* profile,
+                                             const extensions::Extension* app) {
   // The Chrome app can't be unpinned, and extensions can't be pinned.
-  return app_->id() != extension_misc::kChromeAppId && !app_->is_extension() &&
-         (GetPinnableForAppID(app_->id(), profile_) ==
+  return app->id() != extension_misc::kChromeAppId && !app->is_extension() &&
+         (GetPinnableForAppID(app->id(), profile) ==
           AppListControllerDelegate::PIN_EDITABLE);
 }
 #endif  // OS_CHROMEOS
 
 void AppInfoFooterPanel::UninstallApp() {
-  DCHECK(CanUninstallApp());
+  DCHECK(CanUninstallApp(profile_, app_));
   extension_uninstall_dialog_ = extensions::ExtensionUninstallDialog::Create(
       profile_, GetWidget()->GetNativeWindow(), this);
   extension_uninstall_dialog_->ConfirmUninstall(
@@ -184,9 +186,11 @@
       extensions::UNINSTALL_SOURCE_APP_INFO_DIALOG);
 }
 
-bool AppInfoFooterPanel::CanUninstallApp() const {
+// static
+bool AppInfoFooterPanel::CanUninstallApp(Profile* profile,
+                                         const extensions::Extension* app) {
   extensions::ManagementPolicy* policy =
-      extensions::ExtensionSystem::Get(profile_)->management_policy();
-  return policy->UserMayModifySettings(app_, nullptr) &&
-         !policy->MustRemainInstalled(app_, nullptr);
+      extensions::ExtensionSystem::Get(profile)->management_policy();
+  return policy->UserMayModifySettings(app, nullptr) &&
+         !policy->MustRemainInstalled(app, nullptr);
 }
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.h b/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.h
index dd758675..6802272 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.h
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.h
@@ -35,17 +35,24 @@
   AppInfoFooterPanel(Profile* profile, const extensions::Extension* app);
   ~AppInfoFooterPanel() override;
 
+  // This can return null if the footer panel contains no shortcuts, cannot be
+  // pinned to the shelf and the app cannot be uninstalled.
+  static std::unique_ptr<AppInfoFooterPanel> CreateFooterPanel(
+      Profile* profile,
+      const extensions::Extension* app);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(AppInfoDialogViewsTest,
                            PinButtonsAreFocusedAfterPinUnpin);
 
   void CreateButtons();
-  void LayoutButtons();
 
+#if defined(OS_CHROMEOS)
   // Updates the visibility of the pin/unpin buttons so that only one is visible
   // at a time. If |focus_button| is true, sets the focus to whichever button is
   // now visible.
   void UpdatePinButtons(bool focus_visible_button);
+#endif  // OS_CHROMEOS
 
   // Overridden from views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
@@ -54,27 +61,30 @@
   void OnExtensionUninstallDialogClosed(bool did_start_uninstall,
                                         const base::string16& error) override;
 
-  // Create Shortcuts for the app. Must only be called if CanCreateShortcuts()
-  // returns true.
+  // Create Shortcuts for the app.
   void CreateShortcuts();
-  bool CanCreateShortcuts() const;
+  static bool CanCreateShortcuts(const extensions::Extension* app);
 
 #if defined(OS_CHROMEOS)
   // Pins and unpins the app from the shelf. Must only be called if
   // CanSetPinnedToShelf() returns true.
   void SetPinnedToShelf(bool value);
-  bool CanSetPinnedToShelf() const;
-#endif
+  static bool CanSetPinnedToShelf(Profile* profile,
+                                  const extensions::Extension* app);
+#endif  // OS_CHROMEOS
 
   // Uninstall the app. Must only be called if CanUninstallApp() returns true.
   void UninstallApp();
-  bool CanUninstallApp() const;
+  static bool CanUninstallApp(Profile* profile,
+                              const extensions::Extension* app);
 
-  // UI elements on the dialog. Elements are NULL if they are not displayed.
-  views::View* create_shortcuts_button_;
-  views::View* pin_to_shelf_button_;
-  views::View* unpin_from_shelf_button_;
-  views::View* remove_button_;
+  // UI elements on the dialog. Elements are null if they are not displayed.
+  views::View* create_shortcuts_button_ = nullptr;
+#if defined(OS_CHROMEOS)
+  views::View* pin_to_shelf_button_ = nullptr;
+  views::View* unpin_from_shelf_button_ = nullptr;
+#endif  // OS_CHROMEOS
+  views::View* remove_button_ = nullptr;
 
   std::unique_ptr<extensions::ExtensionUninstallDialog>
       extension_uninstall_dialog_;
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc
index 88086c4e..d75d572 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc
@@ -64,38 +64,41 @@
 }
 
 void AppInfoHeaderPanel::CreateControls() {
-  app_icon_view_ = new views::ImageView();
-  app_icon_view_->SetImageSize(gfx::Size(kAppIconSize, kAppIconSize));
-  AddChildView(app_icon_view_);
+  auto app_icon_view = std::make_unique<views::ImageView>();
+  app_icon_view->SetImageSize(gfx::Size(kAppIconSize, kAppIconSize));
+  app_icon_view_ = AddChildView(std::move(app_icon_view));
 
   app_icon_ = extensions::ChromeAppIconService::Get(profile_)->CreateIcon(
       this, app_->id(), extension_misc::EXTENSION_ICON_LARGE);
 
   // Create a vertical container to store the app's name and link.
-  views::View* vertical_info_container = new views::View();
+  auto vertical_info_container = std::make_unique<views::View>();
   auto vertical_container_layout =
       std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical);
   vertical_container_layout->set_main_axis_alignment(
       views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
   vertical_info_container->SetLayoutManager(
       std::move(vertical_container_layout));
-  AddChildView(vertical_info_container);
+  auto* vertical_info_container_ptr =
+      AddChildView(std::move(vertical_info_container));
 
-  views::Label* app_name_label = new views::Label(
+  auto app_name_label = std::make_unique<views::Label>(
       base::UTF8ToUTF16(app_->name()), views::style::CONTEXT_DIALOG_TITLE);
   app_name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  vertical_info_container->AddChildView(app_name_label);
+  auto* app_name_label_ptr =
+      vertical_info_container_ptr->AddChildView(std::move(app_name_label));
 
   if (CanShowAppInWebStore()) {
-    view_in_store_link_ = new views::Link(
+    auto view_in_store_link = std::make_unique<views::Link>(
         l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_WEB_STORE_LINK));
-    view_in_store_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    view_in_store_link_->set_listener(this);
-    vertical_info_container->AddChildView(view_in_store_link_);
+    view_in_store_link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    view_in_store_link->set_listener(this);
+    view_in_store_link_ = vertical_info_container_ptr->AddChildView(
+        std::move(view_in_store_link));
   } else {
     // If there's no link, allow the app's name to take up multiple lines.
     // TODO(sashab): Limit the number of lines to 2.
-    app_name_label->SetMultiLine(true);
+    app_name_label_ptr->SetMultiLine(true);
   }
 }
 
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc
index 868bd7d..331a029 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.cc
@@ -37,38 +37,42 @@
   Navigate(&params);
 }
 
-views::Label* AppInfoPanel::CreateHeading(const base::string16& text) const {
-  views::Label* label = new views::Label(text);
+std::unique_ptr<views::Label> AppInfoPanel::CreateHeading(
+    const base::string16& text) const {
+  auto label = std::make_unique<views::Label>(text);
   label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
       ui::ResourceBundle::MediumFont));
   return label;
 }
 
-views::View* AppInfoPanel::CreateVerticalStack(int child_spacing) const {
-  views::View* vertically_stacked_view = new views::View();
+std::unique_ptr<views::View> AppInfoPanel::CreateVerticalStack(
+    int child_spacing) const {
+  auto vertically_stacked_view = std::make_unique<views::View>();
   vertically_stacked_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::kVertical, gfx::Insets(), child_spacing));
   return vertically_stacked_view;
 }
 
-views::View* AppInfoPanel::CreateVerticalStack() const {
+std::unique_ptr<views::View> AppInfoPanel::CreateVerticalStack() const {
   return CreateVerticalStack(ChromeLayoutProvider::Get()->GetDistanceMetric(
       views::DISTANCE_RELATED_CONTROL_VERTICAL));
 }
 
-views::View* AppInfoPanel::CreateHorizontalStack(int child_spacing) const {
-  views::View* vertically_stacked_view = new views::View();
+std::unique_ptr<views::View> AppInfoPanel::CreateHorizontalStack(
+    int child_spacing) const {
+  auto vertically_stacked_view = std::make_unique<views::View>();
   vertically_stacked_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::kHorizontal, gfx::Insets(), child_spacing));
   return vertically_stacked_view;
 }
 
-views::View* AppInfoPanel::CreateKeyValueField(views::View* key,
-                                               views::View* value) const {
-  views::View* horizontal_stack =
+std::unique_ptr<views::View> AppInfoPanel::CreateKeyValueField(
+    std::unique_ptr<views::View> key,
+    std::unique_ptr<views::View> value) const {
+  auto horizontal_stack =
       CreateHorizontalStack(kSpacingBetweenKeyAndStartOfValue);
-  horizontal_stack->AddChildView(key);
-  horizontal_stack->AddChildView(value);
+  horizontal_stack->AddChildView(std::move(key));
+  horizontal_stack->AddChildView(std::move(value));
   return horizontal_stack;
 }
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.h b/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.h
index b9d1208..bcb35b78 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.h
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_APPS_APP_INFO_DIALOG_APP_INFO_PANEL_H_
 #define CHROME_BROWSER_UI_VIEWS_APPS_APP_INFO_DIALOG_APP_INFO_PANEL_H_
 
+#include <memory>
+
 #include "base/macros.h"
 #include "ui/views/view.h"
 
@@ -33,21 +35,23 @@
   void OpenLink(const GURL& url);
 
   // Create a heading label with the given text.
-  views::Label* CreateHeading(const base::string16& text) const;
+  std::unique_ptr<views::Label> CreateHeading(const base::string16& text) const;
 
   // Create a view with a vertically-stacked box layout, which can have child
   // views appended to it. |child_spacing| defaults to
   // |views::kRelatedControlVerticalSpacing|.
-  views::View* CreateVerticalStack(int child_spacing) const;
-  views::View* CreateVerticalStack() const;
+  std::unique_ptr<views::View> CreateVerticalStack(int child_spacing) const;
+  std::unique_ptr<views::View> CreateVerticalStack() const;
 
   // Create a view with a horizontally-stacked box layout, which can have child
   // views appended to it.
-  views::View* CreateHorizontalStack(int child_spacing) const;
+  std::unique_ptr<views::View> CreateHorizontalStack(int child_spacing) const;
 
   // Given a key and a value, displays them side-by-side as a field and its
   // value.
-  views::View* CreateKeyValueField(views::View* key, views::View* value) const;
+  std::unique_ptr<views::View> CreateKeyValueField(
+      std::unique_ptr<views::View> key,
+      std::unique_ptr<views::View> value) const;
 
   Profile* profile_;
   const extensions::Extension* app_;
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc
index e024590..6e91367 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc
@@ -203,23 +203,23 @@
 }
 
 void AppInfoPermissionsPanel::CreatePermissionsList() {
-  views::View* permissions_heading = CreateHeading(
+  auto permissions_heading = CreateHeading(
       l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_APP_PERMISSIONS_TITLE));
-  AddChildView(permissions_heading);
+  AddChildView(std::move(permissions_heading));
 
   if (!HasActivePermissionMessages() && GetRetainedDeviceCount() == 0 &&
       GetRetainedFileCount() == 0) {
-    views::Label* no_permissions_text =
-        new views::Label(l10n_util::GetStringUTF16(
+    auto no_permissions_text =
+        std::make_unique<views::Label>(l10n_util::GetStringUTF16(
             app_->is_extension()
                 ? IDS_APPLICATION_INFO_EXTENSION_NO_PERMISSIONS_TEXT
                 : IDS_APPLICATION_INFO_APP_NO_PERMISSIONS_TEXT));
     no_permissions_text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    AddChildView(no_permissions_text);
+    AddChildView(std::move(no_permissions_text));
     return;
   }
 
-  BulletedPermissionsList* permissions_list = new BulletedPermissionsList();
+  auto permissions_list = std::make_unique<BulletedPermissionsList>();
 
   // Add regular and host permission messages.
   for (const auto& message : GetActivePermissionMessages()) {
@@ -248,7 +248,7 @@
                    base::Unretained(this)));
   }
 
-  AddChildView(permissions_list);
+  AddChildView(std::move(permissions_list));
 }
 
 bool AppInfoPermissionsPanel::HasActivePermissionMessages() const {
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
index 23782ab..97e3deb 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
@@ -154,7 +154,7 @@
 
 void AppInfoSummaryPanel::AddDescriptionAndLinksControl(
     views::View* vertical_stack) {
-  views::View* description_and_labels_stack = new views::View();
+  auto description_and_labels_stack = std::make_unique<views::View>();
   description_and_labels_stack->SetLayoutManager(
       std::make_unique<views::BoxLayout>(
           views::BoxLayout::kVertical, gfx::Insets(),
@@ -171,29 +171,31 @@
       text += base::ASCIIToUTF16(" ... ");
     }
 
-    views::Label* description_label = new views::Label(text);
+    auto description_label = std::make_unique<views::Label>(text);
     description_label->SetMultiLine(true);
     description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    description_and_labels_stack->AddChildView(description_label);
+    description_and_labels_stack->AddChildView(std::move(description_label));
   }
 
   if (CanShowAppHomePage()) {
-    homepage_link_ = new views::Link(
+    auto homepage_link = std::make_unique<views::Link>(
         l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_HOMEPAGE_LINK));
-    homepage_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    homepage_link_->set_listener(this);
-    description_and_labels_stack->AddChildView(homepage_link_);
+    homepage_link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    homepage_link->set_listener(this);
+    homepage_link_ =
+        description_and_labels_stack->AddChildView(std::move(homepage_link));
   }
 
   if (CanDisplayLicenses()) {
-    licenses_link_ = new views::Link(
+    auto licenses_link = std::make_unique<views::Link>(
         l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_LICENSES_BUTTON_TEXT));
-    licenses_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    licenses_link_->set_listener(this);
-    description_and_labels_stack->AddChildView(licenses_link_);
+    licenses_link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    licenses_link->set_listener(this);
+    licenses_link_ =
+        description_and_labels_stack->AddChildView(std::move(licenses_link));
   }
 
-  vertical_stack->AddChildView(description_and_labels_stack);
+  vertical_stack->AddChildView(std::move(description_and_labels_stack));
 }
 
 void AppInfoSummaryPanel::AddDetailsControl(views::View* vertical_stack) {
@@ -201,37 +203,39 @@
   if (app_->location() == extensions::Manifest::COMPONENT)
     return;
 
-  views::View* details_list =
+  std::unique_ptr<views::View> details_list =
       CreateVerticalStack(ChromeLayoutProvider::Get()->GetDistanceMetric(
           DISTANCE_RELATED_CONTROL_VERTICAL_SMALL));
 
   // Add the size.
-  views::Label* size_title = new views::Label(
+  auto size_title = std::make_unique<views::Label>(
       l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_SIZE_LABEL));
   size_title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
 
-  size_value_ = new views::Label(
+  auto size_value = std::make_unique<views::Label>(
       l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_SIZE_LOADING_LABEL));
-  size_value_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  size_value->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  size_value_ = size_value.get();
   StartCalculatingAppSize();
 
-  details_list->AddChildView(CreateKeyValueField(size_title, size_value_));
+  details_list->AddChildView(
+      CreateKeyValueField(std::move(size_title), std::move(size_value)));
 
   // The version doesn't make sense for bookmark apps.
   if (!app_->from_bookmark()) {
-    views::Label* version_title = new views::Label(
+    auto version_title = std::make_unique<views::Label>(
         l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_VERSION_LABEL));
     version_title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
 
-    views::Label* version_value =
-        new views::Label(base::UTF8ToUTF16(app_->GetVersionForDisplay()));
+    auto version_value = std::make_unique<views::Label>(
+        base::UTF8ToUTF16(app_->GetVersionForDisplay()));
     version_value->SetHorizontalAlignment(gfx::ALIGN_LEFT);
 
-    details_list->AddChildView(
-        CreateKeyValueField(version_title, version_value));
+    details_list->AddChildView(CreateKeyValueField(std::move(version_title),
+                                                   std::move(version_value)));
   }
 
-  vertical_stack->AddChildView(details_list);
+  vertical_stack->AddChildView(std::move(details_list));
 }
 
 void AppInfoSummaryPanel::AddLaunchOptionControl(views::View* vertical_stack) {
@@ -239,29 +243,31 @@
     return;
 
   launch_options_combobox_model_.reset(new LaunchOptionsComboboxModel());
-  launch_options_combobox_ =
-      new views::Combobox(launch_options_combobox_model_.get());
-  launch_options_combobox_->SetAccessibleName(
+  auto launch_options_combobox =
+      std::make_unique<views::Combobox>(launch_options_combobox_model_.get());
+  launch_options_combobox->SetAccessibleName(
       l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_LAUNCH_OPTIONS_ACCNAME));
-  launch_options_combobox_->set_listener(this);
-  launch_options_combobox_->SetSelectedIndex(
+  launch_options_combobox->set_listener(this);
+  launch_options_combobox->SetSelectedIndex(
       launch_options_combobox_model_->GetIndexForLaunchType(GetLaunchType()));
 
-  vertical_stack->AddChildView(launch_options_combobox_);
+  launch_options_combobox_ =
+      vertical_stack->AddChildView(std::move(launch_options_combobox));
 }
 
 void AppInfoSummaryPanel::AddSubviews() {
   AddChildView(CreateHeading(
       l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_APP_OVERVIEW_TITLE)));
 
-  views::View* vertical_stack =
+  auto vertical_stack =
       CreateVerticalStack(ChromeLayoutProvider::Get()->GetDistanceMetric(
           views::DISTANCE_UNRELATED_CONTROL_VERTICAL));
-  AddChildView(vertical_stack);
 
-  AddDescriptionAndLinksControl(vertical_stack);
-  AddDetailsControl(vertical_stack);
-  AddLaunchOptionControl(vertical_stack);
+  AddDescriptionAndLinksControl(vertical_stack.get());
+  AddDetailsControl(vertical_stack.get());
+  AddLaunchOptionControl(vertical_stack.get());
+
+  AddChildView(std::move(vertical_stack));
 }
 
 void AppInfoSummaryPanel::OnPerformAction(views::Combobox* combobox) {
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc
index 6651ddc..616d333 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/arc_app_info_links_panel.cc
@@ -30,11 +30,11 @@
       views::BoxLayout::kVertical, gfx::Insets(),
       ChromeLayoutProvider::Get()->GetDistanceMetric(
           views::DISTANCE_RELATED_CONTROL_VERTICAL)));
-  manage_link_ = new views::Link(
+  auto manage_link = std::make_unique<views::Link>(
       l10n_util::GetStringUTF16(IDS_ARC_APPLICATION_INFO_MANAGE_LINK));
-  manage_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  manage_link_->set_listener(this);
-  AddChildView(manage_link_);
+  manage_link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  manage_link->set_listener(this);
+  manage_link_ = AddChildView(std::move(manage_link));
 
   ArcAppListPrefs* const arc_prefs = ArcAppListPrefs::Get(profile_);
   DCHECK(arc_prefs);
diff --git a/chrome/browser/ui/views/arc_app_dialog_view.cc b/chrome/browser/ui/views/arc_app_dialog_view.cc
index 711eca4..f91946be 100644
--- a/chrome/browser/ui/views/arc_app_dialog_view.cc
+++ b/chrome/browser/ui/views/arc_app_dialog_view.cc
@@ -118,11 +118,11 @@
       provider->GetDialogInsetsForContentType(views::TEXT, views::TEXT),
       provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL)));
 
-  icon_view_ = new views::ImageView();
-  icon_view_->SetPreferredSize(gfx::Size(kArcAppIconSize, kArcAppIconSize));
-  AddChildView(icon_view_);
+  auto icon_view = std::make_unique<views::ImageView>();
+  icon_view->SetPreferredSize(gfx::Size(kArcAppIconSize, kArcAppIconSize));
+  icon_view_ = AddChildView(std::move(icon_view));
 
-  views::View* text_container = new views::View();
+  auto text_container = std::make_unique<views::View>();
   auto text_container_layout =
       std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical);
   text_container_layout->set_main_axis_alignment(
@@ -131,11 +131,11 @@
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
   text_container->SetLayoutManager(std::move(text_container_layout));
 
-  AddChildView(text_container);
+  auto* text_container_ptr = AddChildView(std::move(text_container));
   DCHECK(!heading_text.empty());
-  AddMultiLineLabel(text_container, heading_text);
+  AddMultiLineLabel(text_container_ptr, heading_text);
   if (!subheading_text.empty())
-    AddMultiLineLabel(text_container, subheading_text);
+    AddMultiLineLabel(text_container_ptr, subheading_text);
 
   icon_loader_ = std::make_unique<ArcAppIconLoader>(
       profile_, kIconSourceSize, this);
@@ -151,11 +151,11 @@
 
 void ArcAppDialogView::AddMultiLineLabel(views::View* parent,
                                          const base::string16& label_text) {
-  views::Label* label = new views::Label(label_text);
+  auto label = std::make_unique<views::Label>(label_text);
   label->SetMultiLine(true);
   label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   label->SetAllowCharacterBreak(true);
-  parent->AddChildView(label);
+  parent->AddChildView(std::move(label));
 }
 
 void ArcAppDialogView::ConfirmOrCancelForTest(bool confirm) {
diff --git a/chrome/browser/ui/views/arc_data_removal_dialog_view.cc b/chrome/browser/ui/views/arc_data_removal_dialog_view.cc
index ea21bcf..6b181ed8 100644
--- a/chrome/browser/ui/views/arc_data_removal_dialog_view.cc
+++ b/chrome/browser/ui/views/arc_data_removal_dialog_view.cc
@@ -93,17 +93,17 @@
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
   SetLayoutManager(std::move(layout));
 
-  icon_view_ = new views::ImageView();
-  icon_view_->SetPreferredSize(gfx::Size(kArcAppIconSize, kArcAppIconSize));
-  AddChildView(icon_view_);
+  auto icon_view = std::make_unique<views::ImageView>();
+  icon_view->SetPreferredSize(gfx::Size(kArcAppIconSize, kArcAppIconSize));
+  icon_view_ = AddChildView(std::move(icon_view));
 
   // UI hierarchy owned.
-  views::Label* label = new views::Label(
+  auto label = std::make_unique<views::Label>(
       l10n_util::GetStringUTF16(IDS_ARC_DATA_REMOVAL_CONFIRMATION_HEADING),
       views::style::CONTEXT_MESSAGE_BOX_BODY_TEXT);
   label->SetMultiLine(true);
   label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  AddChildView(label);
+  AddChildView(std::move(label));
 
   icon_loader_ =
       std::make_unique<ArcAppIconLoader>(profile_, kArcAppIconSize, this);
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
index e7d140c..0da810b 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -5,6 +5,8 @@
 #include "chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h"
 
 #include <algorithm>
+#include <memory>
+#include <utility>
 
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
@@ -88,7 +90,7 @@
 // specified maximum.
 class ConstrainedWidthView : public views::View {
  public:
-  ConstrainedWidthView(views::View* child, int max_width);
+  ConstrainedWidthView(std::unique_ptr<views::View> child, int max_width);
   ~ConstrainedWidthView() override = default;
 
  private:
@@ -100,10 +102,11 @@
   DISALLOW_COPY_AND_ASSIGN(ConstrainedWidthView);
 };
 
-ConstrainedWidthView::ConstrainedWidthView(views::View* child, int max_width)
+ConstrainedWidthView::ConstrainedWidthView(std::unique_ptr<views::View> child,
+                                           int max_width)
     : max_width_(max_width) {
   SetLayoutManager(std::make_unique<views::FillLayout>());
-  AddChildView(child);
+  AddChildView(std::move(child));
 }
 
 gfx::Size ConstrainedWidthView::CalculatePreferredSize() const {
@@ -145,18 +148,20 @@
   // content.
   virtual PopupItemLayoutType GetLayoutType() const = 0;
   virtual int GetPrimaryTextStyle() = 0;
-  virtual views::View* CreateValueLabel();
+  virtual std::unique_ptr<views::View> CreateValueLabel();
   // Creates an optional label below the value.
-  virtual views::View* CreateSubtextLabel();
+  virtual std::unique_ptr<views::View> CreateSubtextLabel();
   // The description view can be nullptr.
-  virtual views::View* CreateDescriptionLabel();
+  virtual std::unique_ptr<views::View> CreateDescriptionLabel();
 
   // Creates a label matching the style of the description label.
-  views::Label* CreateSecondaryLabel(const base::string16& text) const;
+  std::unique_ptr<views::Label> CreateSecondaryLabel(
+      const base::string16& text) const;
   // Creates a label with a specific context and style.
-  views::Label* CreateLabelWithStyleAndContext(const base::string16& text,
-                                               int text_context,
-                                               int text_style) const;
+  std::unique_ptr<views::Label> CreateLabelWithStyleAndContext(
+      const base::string16& text,
+      int text_context,
+      int text_style) const;
 
   // Returns the font weight to be applied to primary info.
   virtual gfx::Font::Weight GetPrimaryTextWeight() const = 0;
@@ -190,8 +195,8 @@
   PopupItemLayoutType GetLayoutType() const override;
   int GetPrimaryTextStyle() override;
   gfx::Font::Weight GetPrimaryTextWeight() const override;
-  views::View* CreateSubtextLabel() override;
-  views::View* CreateDescriptionLabel() override;
+  std::unique_ptr<views::View> CreateSubtextLabel() override;
+  std::unique_ptr<views::View> CreateDescriptionLabel() override;
 
   AutofillPopupSuggestionView(AutofillPopupViewNativeViews* popup_view,
                               int line_number,
@@ -212,9 +217,9 @@
 
  protected:
   // AutofillPopupItemView:
-  views::View* CreateValueLabel() override;
-  views::View* CreateSubtextLabel() override;
-  views::View* CreateDescriptionLabel() override;
+  std::unique_ptr<views::View> CreateValueLabel() override;
+  std::unique_ptr<views::View> CreateSubtextLabel() override;
+  std::unique_ptr<views::View> CreateDescriptionLabel() override;
   gfx::Font::Weight GetPrimaryTextWeight() const override;
 
  private:
@@ -396,18 +401,18 @@
                       /*resize=*/false, layout_manager);
   }
 
-  views::View* lower_value_label = CreateSubtextLabel();
-  views::View* value_label = CreateValueLabel();
+  auto lower_value_label = CreateSubtextLabel();
+  auto value_label = CreateValueLabel();
 
   const int kStandardRowHeight =
       views::MenuConfig::instance().touchable_menu_height + extra_height_;
   if (!lower_value_label) {
     layout_manager->set_minimum_cross_axis_size(kStandardRowHeight);
-    AddChildView(value_label);
+    AddChildView(std::move(value_label));
   } else {
     layout_manager->set_minimum_cross_axis_size(
         kStandardRowHeight + kAutofillPopupAdditionalDoubleRowHeight);
-    views::View* values_container = new views::View();
+    auto values_container = std::make_unique<views::View>();
     auto* vertical_layout =
         values_container->SetLayoutManager(std::make_unique<views::BoxLayout>(
             views::BoxLayout::kVertical, gfx::Insets(),
@@ -416,17 +421,17 @@
         views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
     vertical_layout->set_cross_axis_alignment(
         views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
-    values_container->AddChildView(value_label);
-    values_container->AddChildView(lower_value_label);
-    AddChildView(values_container);
+    values_container->AddChildView(std::move(value_label));
+    values_container->AddChildView(std::move(lower_value_label));
+    AddChildView(std::move(values_container));
   }
 
   AddSpacerWithSize(AutofillPopupBaseView::kValueLabelPadding,
                     /*resize=*/true, layout_manager);
 
-  views::View* description_label = CreateDescriptionLabel();
+  auto description_label = CreateDescriptionLabel();
   if (description_label)
-    AddChildView(description_label);
+    AddChildView(std::move(description_label));
 
   if (!icon.isNull() && GetLayoutType() == PopupItemLayoutType::kTrailingIcon) {
     AddSpacerWithSize(GetHorizontalMargin(),
@@ -440,7 +445,7 @@
   SchedulePaint();
 }
 
-views::View* AutofillPopupItemView::CreateValueLabel() {
+std::unique_ptr<views::View> AutofillPopupItemView::CreateValueLabel() {
   // TODO(crbug.com/831603): Remove elision responsibilities from controller.
   base::string16 text =
       popup_view_->controller()->GetElidedValueAt(line_number_);
@@ -450,7 +455,7 @@
     return CreateSecondaryLabel(text);
   }
 
-  views::Label* text_label = CreateLabelWithStyleAndContext(
+  auto text_label = CreateLabelWithStyleAndContext(
       popup_view_->controller()->GetElidedValueAt(line_number_),
       ChromeTextContext::CONTEXT_BODY_TEXT_LARGE, GetPrimaryTextStyle());
 
@@ -463,28 +468,29 @@
   return text_label;
 }
 
-views::View* AutofillPopupItemView::CreateSubtextLabel() {
+std::unique_ptr<views::View> AutofillPopupItemView::CreateSubtextLabel() {
   return nullptr;
 }
 
-views::View* AutofillPopupItemView::CreateDescriptionLabel() {
+std::unique_ptr<views::View> AutofillPopupItemView::CreateDescriptionLabel() {
   base::string16 text =
       popup_view_->controller()->GetElidedLabelAt(line_number_);
   return text.empty() ? nullptr : CreateSecondaryLabel(text);
 }
 
-views::Label* AutofillPopupItemView::CreateSecondaryLabel(
+std::unique_ptr<views::Label> AutofillPopupItemView::CreateSecondaryLabel(
     const base::string16& text) const {
   return CreateLabelWithStyleAndContext(
       text, ChromeTextContext::CONTEXT_BODY_TEXT_LARGE,
       ChromeTextStyle::STYLE_SECONDARY);
 }
 
-views::Label* AutofillPopupItemView::CreateLabelWithStyleAndContext(
+std::unique_ptr<views::Label>
+AutofillPopupItemView::CreateLabelWithStyleAndContext(
     const base::string16& text,
     int text_context,
     int text_style) const {
-  views::Label* label =
+  auto label =
       CreateLabelWithColorReadabilityDisabled(text, text_context, text_style);
   label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
 
@@ -492,18 +498,17 @@
 }
 
 void AutofillPopupItemView::AddIcon(gfx::ImageSkia icon) {
-  auto* image_view = new views::ImageView();
+  auto image_view = std::make_unique<views::ImageView>();
   image_view->SetImage(icon);
-  AddChildView(image_view);
+  AddChildView(std::move(image_view));
 }
 
 void AutofillPopupItemView::AddSpacerWithSize(int spacer_width,
                                               bool resize,
                                               views::BoxLayout* layout) {
-  auto* spacer = new views::View;
+  auto spacer = std::make_unique<views::View>();
   spacer->SetPreferredSize(gfx::Size(spacer_width, 1));
-  AddChildView(spacer);
-  layout->SetFlexForView(spacer,
+  layout->SetFlexForView(AddChildView(std::move(spacer)),
                          /*flex=*/resize ? 1 : 0,
                          /*use_min_size=*/true);
 }
@@ -568,14 +573,15 @@
   SetFocusBehavior(FocusBehavior::ALWAYS);
 }
 
-views::View* AutofillPopupSuggestionView::CreateDescriptionLabel() {
+std::unique_ptr<views::View>
+AutofillPopupSuggestionView::CreateDescriptionLabel() {
   // When two-line display is enabled, don't display the description.
   if (GetLayoutType() == PopupItemLayoutType::kTwoLinesLeadingIcon)
     return nullptr;
   return AutofillPopupItemView::CreateDescriptionLabel();
 }
 
-views::View* AutofillPopupSuggestionView::CreateSubtextLabel() {
+std::unique_ptr<views::View> AutofillPopupSuggestionView::CreateSubtextLabel() {
   // When two-line display is disabled, use the default behavior for the popup
   // item.
   if (GetLayoutType() != PopupItemLayoutType::kTwoLinesLeadingIcon)
@@ -586,7 +592,7 @@
   if (label_text.empty())
     return nullptr;
 
-  views::Label* label = CreateLabelWithStyleAndContext(
+  auto label = CreateLabelWithStyleAndContext(
       label_text, ChromeTextContext::CONTEXT_BODY_TEXT_SMALL,
       ChromeTextStyle::STYLE_SECONDARY);
   return label;
@@ -604,12 +610,13 @@
   return result;
 }
 
-views::View* PasswordPopupSuggestionView::CreateValueLabel() {
-  views::View* label = AutofillPopupSuggestionView::CreateValueLabel();
-  return new ConstrainedWidthView(label, kAutofillPopupUsernameMaxWidth);
+std::unique_ptr<views::View> PasswordPopupSuggestionView::CreateValueLabel() {
+  auto label = AutofillPopupSuggestionView::CreateValueLabel();
+  return std::make_unique<ConstrainedWidthView>(std::move(label),
+                                                kAutofillPopupUsernameMaxWidth);
 }
 
-views::View* PasswordPopupSuggestionView::CreateSubtextLabel() {
+std::unique_ptr<views::View> PasswordPopupSuggestionView::CreateSubtextLabel() {
   base::string16 text_to_use;
   if (!origin_.empty()) {
     // Always use the origin if it's available.
@@ -622,12 +629,14 @@
   if (text_to_use.empty())
     return nullptr;
 
-  views::Label* label = CreateSecondaryLabel(text_to_use);
+  auto label = CreateSecondaryLabel(text_to_use);
   label->SetElideBehavior(gfx::ELIDE_HEAD);
-  return new ConstrainedWidthView(label, kAutofillPopupUsernameMaxWidth);
+  return std::make_unique<ConstrainedWidthView>(std::move(label),
+                                                kAutofillPopupUsernameMaxWidth);
 }
 
-views::View* PasswordPopupSuggestionView::CreateDescriptionLabel() {
+std::unique_ptr<views::View>
+PasswordPopupSuggestionView::CreateDescriptionLabel() {
   // When no origin text is available, the two-line layout will use the masked
   // password in the subtext label, so it should not be reused here.
   if ((origin_.empty() &&
@@ -636,9 +645,10 @@
     return nullptr;
   }
 
-  views::Label* label = CreateSecondaryLabel(masked_password_);
+  auto label = CreateSecondaryLabel(masked_password_);
   label->SetElideBehavior(gfx::TRUNCATE);
-  return new ConstrainedWidthView(label, kAutofillPopupPasswordMaxWidth);
+  return std::make_unique<ConstrainedWidthView>(std::move(label),
+                                                kAutofillPopupPasswordMaxWidth);
 }
 
 gfx::Font::Weight PasswordPopupSuggestionView::GetPrimaryTextWeight() const {
@@ -797,7 +807,7 @@
   SetBorder(views::CreateEmptyBorder(
       gfx::Insets(vertical_margin, horizontal_margin)));
 
-  views::Label* text_label = CreateLabelWithColorReadabilityDisabled(
+  auto text_label = CreateLabelWithColorReadabilityDisabled(
       controller->GetElidedValueAt(line_number_),
       ChromeTextContext::CONTEXT_BODY_TEXT_LARGE, ChromeTextStyle::STYLE_RED);
   text_label->SetEnabledColor(popup_view_->GetWarningColor());
@@ -811,7 +821,7 @@
   text_label->SetMaximumWidth(max_width);
   text_label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
 
-  AddChildView(text_label);
+  AddChildView(std::move(text_label));
 }
 
 std::unique_ptr<views::Background>
diff --git a/chrome/browser/ui/views/autofill/view_util.cc b/chrome/browser/ui/views/autofill/view_util.cc
index 7cc1dfa..2e0a11a 100644
--- a/chrome/browser/ui/views/autofill/view_util.cc
+++ b/chrome/browser/ui/views/autofill/view_util.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ui/views/autofill/view_util.h"
 
-#include <memory>
+#include <utility>
 
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
@@ -120,11 +120,11 @@
   return textfield;
 }
 
-views::Label* CreateLabelWithColorReadabilityDisabled(
+std::unique_ptr<views::Label> CreateLabelWithColorReadabilityDisabled(
     const base::string16& text,
     int text_context,
     int text_style) {
-  views::Label* label = new views::Label(text, text_context, text_style);
+  auto label = std::make_unique<views::Label>(text, text_context, text_style);
   label->SetAutoColorReadabilityEnabled(false);
   // Forces the color for the required context and style to be applied. It may
   // have been overridden by the default theme's color before auto-color
diff --git a/chrome/browser/ui/views/autofill/view_util.h b/chrome/browser/ui/views/autofill/view_util.h
index ab5c8a6..8bca7e2 100644
--- a/chrome/browser/ui/views/autofill/view_util.h
+++ b/chrome/browser/ui/views/autofill/view_util.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_VIEW_UTIL_H_
 #define CHROME_BROWSER_UI_VIEWS_AUTOFILL_VIEW_UTIL_H_
 
+#include <memory>
+
 #include "base/strings/string16.h"
 #include "components/autofill/core/browser/payments/legal_message_line.h"
 #include "content/public/browser/web_contents.h"
@@ -41,7 +43,7 @@
 // Returns a new label with auto-color readability disabled to ensure consistent
 // colors in the title when a dark native theme is applied
 // (https://crbug.com/881514).
-views::Label* CreateLabelWithColorReadabilityDisabled(
+std::unique_ptr<views::Label> CreateLabelWithColorReadabilityDisabled(
     const base::string16& text,
     int text_context,
     int text_style);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index 4c5a0b4..f0bb928a 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -1328,7 +1328,7 @@
   return true;
 }
 
-void BookmarkBarView::OnMenuButtonClicked(views::MenuButton* view,
+void BookmarkBarView::OnMenuButtonClicked(views::Button* view,
                                           const gfx::Point& point,
                                           const ui::Event* event) {
   const BookmarkNode* node;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
index d3c4cd8..67c29d5 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
@@ -226,7 +226,7 @@
                            const gfx::Point& p) override;
 
   // views::MenuButtonListener:
-  void OnMenuButtonClicked(views::MenuButton* source,
+  void OnMenuButtonClicked(views::Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override;
 
diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc
index 79c24d7..c3511e3e 100644
--- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc
+++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc
@@ -18,7 +18,7 @@
 #include "components/prefs/pref_service.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
diff --git a/chrome/browser/ui/views/download/download_danger_prompt_views.cc b/chrome/browser/ui/views/download/download_danger_prompt_views.cc
index 702efdc..e9c7a17 100644
--- a/chrome/browser/ui/views/download/download_danger_prompt_views.cc
+++ b/chrome/browser/ui/views/download/download_danger_prompt_views.cc
@@ -6,6 +6,9 @@
 
 #include "base/compiler_specific.h"
 #include "chrome/browser/download/download_stats.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/safe_browsing/advanced_protection_status_manager.h"
+#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/grit/chromium_strings.h"
@@ -17,6 +20,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/download_item_utils.h"
+#include "content/public/browser/web_contents.h"
 #include "ui/base/buildflags.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -38,6 +42,7 @@
                                   public views::DialogDelegateView {
  public:
   DownloadDangerPromptViews(download::DownloadItem* item,
+                            Profile* profile,
                             bool show_context,
                             const OnDone& done);
   ~DownloadDangerPromptViews() override;
@@ -64,6 +69,7 @@
   void RunDone(Action action);
 
   download::DownloadItem* download_;
+  Profile* profile_;
   // If show_context_ is true, this is a download confirmation dialog by
   // download API, otherwise it is download recovery dialog from a regular
   // download.
@@ -73,9 +79,13 @@
 
 DownloadDangerPromptViews::DownloadDangerPromptViews(
     download::DownloadItem* item,
+    Profile* profile,
     bool show_context,
     const OnDone& done)
-    : download_(item), show_context_(show_context), done_(done) {
+    : download_(item),
+      profile_(profile),
+      show_context_(show_context),
+      done_(done) {
   download_->AddObserver(this);
 
   set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType(
@@ -220,19 +230,40 @@
       case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:  // Fall through
       case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
       case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
-        return l10n_util::GetStringFUTF16(
-            IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
-            download_->GetFileNameToReportUser().LossyDisplayName());
+        if (safe_browsing::AdvancedProtectionStatusManager::
+                RequestsAdvancedProtectionVerdicts(profile_)) {
+          return l10n_util::GetStringFUTF16(
+              IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION,
+              download_->GetFileNameToReportUser().LossyDisplayName());
+        } else {
+          return l10n_util::GetStringFUTF16(
+              IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
+              download_->GetFileNameToReportUser().LossyDisplayName());
+        }
       }
       case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
-        return l10n_util::GetStringFUTF16(
-            IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
-            download_->GetFileNameToReportUser().LossyDisplayName());
+        if (safe_browsing::AdvancedProtectionStatusManager::
+                RequestsAdvancedProtectionVerdicts(profile_)) {
+          return l10n_util::GetStringFUTF16(
+              IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT_IN_ADVANCED_PROTECTION,
+              download_->GetFileNameToReportUser().LossyDisplayName());
+        } else {
+          return l10n_util::GetStringFUTF16(
+              IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
+              download_->GetFileNameToReportUser().LossyDisplayName());
+        }
       }
       case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
-        return l10n_util::GetStringFUTF16(
-            IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS,
-            download_->GetFileNameToReportUser().LossyDisplayName());
+        if (safe_browsing::AdvancedProtectionStatusManager::
+                RequestsAdvancedProtectionVerdicts(profile_)) {
+          return l10n_util::GetStringFUTF16(
+              IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS_IN_ADVANCED_PROTECTION,
+              download_->GetFileNameToReportUser().LossyDisplayName());
+        } else {
+          return l10n_util::GetStringFUTF16(
+              IDS_PROMPT_DOWNLOAD_CHANGES_SETTINGS,
+              download_->GetFileNameToReportUser().LossyDisplayName());
+        }
       }
       case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
       case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
@@ -298,8 +329,10 @@
     content::WebContents* web_contents,
     bool show_context,
     const OnDone& done) {
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
   DownloadDangerPromptViews* download_danger_prompt =
-      new DownloadDangerPromptViews(item, show_context, done);
+      new DownloadDangerPromptViews(item, profile, show_context, done);
   constrained_window::ShowWebModalDialogViews(download_danger_prompt,
                                               web_contents);
   return download_danger_prompt;
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc
index 116ad93..948c8f8 100644
--- a/chrome/browser/ui/views/frame/browser_frame.cc
+++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window_state.h"
+#include "chrome/browser/ui/extensions/hosted_app_browser_controller.h"
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
 #include "chrome/browser/ui/views/frame/browser_root_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
@@ -170,16 +171,18 @@
 }
 
 bool BrowserFrame::ShouldUseTheme() const {
-  // Main browser windows are always themed.
-  if (browser_view_->IsBrowserTypeNormal())
+  // Browser windows are always themed (including popups).
+  if (!extensions::HostedAppBrowserController::
+          IsForExperimentalHostedAppBrowser(browser_view_->browser())) {
     return true;
+  }
 
   // The system GTK theme should always be respected if the user has opted to
   // use it.
   if (IsUsingGtkTheme(browser_view_->browser()->profile()))
     return true;
 
-  // Other window types (popups, hosted apps) on non-GTK use the default theme.
+  // Hosted apps on non-GTK use default colors.
   return false;
 }
 
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index b0fa27fd..a306c4c4 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1910,9 +1910,6 @@
     case TabAlertState::BLUETOOTH_CONNECTED:
       return l10n_util::GetStringFUTF16(
           IDS_TAB_AX_LABEL_BLUETOOTH_CONNECTED_FORMAT, title);
-    case TabAlertState::SERIAL_CONNECTED:
-      return l10n_util::GetStringFUTF16(
-          IDS_TAB_AX_LABEL_SERIAL_CONNECTED_FORMAT, title);
     case TabAlertState::MEDIA_RECORDING:
       return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_MEDIA_RECORDING_FORMAT,
                                         title);
@@ -1925,6 +1922,7 @@
     case TabAlertState::PIP_PLAYING:
       return l10n_util::GetStringFUTF16(IDS_TAB_AX_LABEL_PIP_PLAYING_FORMAT,
                                         title);
+
     case TabAlertState::DESKTOP_CAPTURING:
       return l10n_util::GetStringFUTF16(
           IDS_TAB_AX_LABEL_DESKTOP_CAPTURING_FORMAT, title);
diff --git a/chrome/browser/ui/views/frame/hosted_app_menu_button.cc b/chrome/browser/ui/views/frame/hosted_app_menu_button.cc
index 68b66e5..b1b3eb7 100644
--- a/chrome/browser/ui/views/frame/hosted_app_menu_button.cc
+++ b/chrome/browser/ui/views/frame/hosted_app_menu_button.cc
@@ -22,7 +22,7 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/border.h"
-#include "ui/views/controls/button/menu_button.h"
+#include "ui/views/controls/button/button.h"
 #include "ui/views/view_class_properties.h"
 #include "ui/views/window/hit_test_utils.h"
 
@@ -71,7 +71,7 @@
                              this, &HostedAppMenuButton::FadeHighlightOff);
 }
 
-void HostedAppMenuButton::OnMenuButtonClicked(views::MenuButton* source,
+void HostedAppMenuButton::OnMenuButtonClicked(views::Button* source,
                                               const gfx::Point& point,
                                               const ui::Event* event) {
   Browser* browser = browser_view_->browser();
diff --git a/chrome/browser/ui/views/frame/hosted_app_menu_button.h b/chrome/browser/ui/views/frame/hosted_app_menu_button.h
index 28aaec0..a8d79c9a 100644
--- a/chrome/browser/ui/views/frame/hosted_app_menu_button.h
+++ b/chrome/browser/ui/views/frame/hosted_app_menu_button.h
@@ -27,7 +27,7 @@
   void StartHighlightAnimation();
 
   // views::MenuButtonListener:
-  void OnMenuButtonClicked(views::MenuButton* source,
+  void OnMenuButtonClicked(views::Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override;
 
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index 43d9fa4..e89d0bf 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -349,7 +349,7 @@
   }
 }
 
-void OpaqueBrowserFrameView::OnMenuButtonClicked(views::MenuButton* source,
+void OpaqueBrowserFrameView::OnMenuButtonClicked(views::Button* source,
                                                  const gfx::Point& point,
                                                  const ui::Event* event) {
 #if defined(OS_LINUX)
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
index 999b1b9..9fa5c90 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
@@ -83,7 +83,7 @@
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
   // views::MenuButtonListener:
-  void OnMenuButtonClicked(views::MenuButton* source,
+  void OnMenuButtonClicked(views::Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override;
 
diff --git a/chrome/browser/ui/views/hover_button.cc b/chrome/browser/ui/views/hover_button.cc
index a996bb6..05a37ae 100644
--- a/chrome/browser/ui/views/hover_button.cc
+++ b/chrome/browser/ui/views/hover_button.cc
@@ -396,7 +396,7 @@
     subtitle_->SetEnabledColor(color);
 }
 
-void HoverButton::OnMenuButtonClicked(MenuButton* source,
+void HoverButton::OnMenuButtonClicked(Button* source,
                                       const gfx::Point& point,
                                       const ui::Event* event) {
   if (listener_)
diff --git a/chrome/browser/ui/views/hover_button.h b/chrome/browser/ui/views/hover_button.h
index 3c902f9..f51e983 100644
--- a/chrome/browser/ui/views/hover_button.h
+++ b/chrome/browser/ui/views/hover_button.h
@@ -95,7 +95,7 @@
 
  protected:
   // views::MenuButtonListener:
-  void OnMenuButtonClicked(MenuButton* source,
+  void OnMenuButtonClicked(Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override;
 
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
index a3047e0..7f0e4c6 100644
--- a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
+++ b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
@@ -9,8 +9,8 @@
 
 #include "chrome/browser/chromeos/accessibility/accessibility_input_method_observer.h"
 #include "chrome/browser/ui/views/ime_driver/remote_text_input_client.h"
+#include "ui/base/ime/chromeos/input_method_chromeos.h"
 #include "ui/base/ime/ime_bridge.h"
-#include "ui/base/ime/input_method_chromeos.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index a20a1a9..19093543 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -233,7 +233,6 @@
   params.browser = browser_;
   params.command_updater = command_updater();
   params.page_action_icon_delegate = this;
-  params.location_bar_delegate = delegate_;
   page_action_icon_container_view_ = new PageActionIconContainerView(params);
   AddChildView(page_action_icon_container_view_);
 
@@ -719,6 +718,10 @@
   return GetWebContents();
 }
 
+bool LocationBarView::IsLocationBarUserInputInProgress() const {
+  return omnibox_view() && omnibox_view()->model()->user_input_in_progress();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // LocationBarView, public static methods:
 
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index 1880f5e..074b6f0 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -345,6 +345,7 @@
   // PageActionIconView::Delegate:
   SkColor GetPageActionInkDropColor() const override;
   content::WebContents* GetWebContentsForPageActionIconView() override;
+  bool IsLocationBarUserInputInProgress() const override;
 
   // gfx::AnimationDelegate:
   void AnimationProgressed(const gfx::Animation* animation) override;
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.cc b/chrome/browser/ui/views/location_bar/location_icon_view.cc
index 112c095a..52b2d98 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.cc
@@ -25,6 +25,7 @@
 #include "ui/views/controls/label.h"
 
 using content::WebContents;
+using security_state::SecurityLevel;
 
 LocationIconView::LocationIconView(const gfx::FontList& font_list,
                                    Delegate* delegate)
@@ -58,8 +59,11 @@
 }
 
 SkColor LocationIconView::GetTextColor() const {
-  return delegate_->GetSecurityChipColor(
-      delegate_->GetLocationBarModel()->GetSecurityLevel(false));
+  SecurityLevel security_level = SecurityLevel::NONE;
+  if (!delegate_->IsEditingOrEmpty())
+    security_level = delegate_->GetLocationBarModel()->GetSecurityLevel(true);
+
+  return delegate_->GetSecurityChipColor(security_level);
 }
 
 bool LocationIconView::ShouldShowSeparator() const {
@@ -162,16 +166,18 @@
 }
 
 bool LocationIconView::ShouldAnimateTextVisibilityChange() const {
-  using SecurityLevel = security_state::SecurityLevel;
-  SecurityLevel level =
-      delegate_->GetLocationBarModel()->GetSecurityLevel(false);
+  if (delegate_->IsEditingOrEmpty())
+    return false;
+
+  SecurityLevel security_level =
+      delegate_->GetLocationBarModel()->GetSecurityLevel(true);
   // Do not animate transitions from HTTP_SHOW_WARNING to DANGEROUS, since the
   // transition can look confusing/messy.
-  if (level == SecurityLevel::DANGEROUS &&
+  if (security_level == SecurityLevel::DANGEROUS &&
       last_update_security_level_ == SecurityLevel::HTTP_SHOW_WARNING)
     return false;
-  return (level == SecurityLevel::DANGEROUS ||
-          level == SecurityLevel::HTTP_SHOW_WARNING);
+  return (security_level == SecurityLevel::DANGEROUS ||
+          security_level == SecurityLevel::HTTP_SHOW_WARNING);
 }
 
 void LocationIconView::UpdateTextVisibility(bool suppress_animations) {
@@ -236,8 +242,11 @@
     }
   }
 
-  last_update_security_level_ =
-      delegate_->GetLocationBarModel()->GetSecurityLevel(false);
+  last_update_security_level_ = SecurityLevel::NONE;
+  if (!is_editing_or_empty) {
+    last_update_security_level_ =
+        delegate_->GetLocationBarModel()->GetSecurityLevel(true);
+  }
   was_editing_or_empty_ = is_editing_or_empty;
 }
 
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
index 1b0fa59..261a7af 100644
--- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
@@ -10,6 +10,7 @@
 #include "base/i18n/number_formatting.h"
 #include "base/i18n/rtl.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/chrome_notification_types.h"
diff --git a/chrome/browser/ui/views/menu_model_adapter_test.cc b/chrome/browser/ui/views/menu_model_adapter_test.cc
index 78ea1d3..606b10e 100644
--- a/chrome/browser/ui/views/menu_model_adapter_test.cc
+++ b/chrome/browser/ui/views/menu_model_adapter_test.cc
@@ -188,7 +188,7 @@
   }
 
   // views::MenuButtonListener implementation.
-  void OnMenuButtonClicked(views::MenuButton* source,
+  void OnMenuButtonClicked(views::Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override {
     gfx::Point screen_location;
diff --git a/chrome/browser/ui/views/menu_test_base.cc b/chrome/browser/ui/views/menu_test_base.cc
index 3b38b1e..cc123dd 100644
--- a/chrome/browser/ui/views/menu_test_base.cc
+++ b/chrome/browser/ui/views/menu_test_base.cc
@@ -75,7 +75,7 @@
   return button_->GetPreferredSize();
 }
 
-void MenuTestBase::OnMenuButtonClicked(views::MenuButton* source,
+void MenuTestBase::OnMenuButtonClicked(views::Button* source,
                                        const gfx::Point& point,
                                        const ui::Event* event) {
   gfx::Point screen_location;
diff --git a/chrome/browser/ui/views/menu_test_base.h b/chrome/browser/ui/views/menu_test_base.h
index 61ed14cd..18bc3b27c 100644
--- a/chrome/browser/ui/views/menu_test_base.h
+++ b/chrome/browser/ui/views/menu_test_base.h
@@ -15,7 +15,7 @@
 #include "ui/views/controls/menu/menu_delegate.h"
 
 namespace views {
-class MenuButton;
+class Button;
 class MenuItemView;
 class MenuRunner;
 }
@@ -76,7 +76,7 @@
   gfx::Size GetPreferredSizeForContents() const override;
 
   // views::MenuButtonListener implementation
-  void OnMenuButtonClicked(views::MenuButton* source,
+  void OnMenuButtonClicked(views::Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override;
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index 3b308757..ccfdf29 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -38,6 +38,7 @@
 #include "components/omnibox/browser/omnibox_popup_model.h"
 #include "components/omnibox/common/omnibox_features.h"
 #include "components/search_engines/template_url_service.h"
+#include "components/security_state/core/security_state.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/elide_url.h"
 #include "content/public/browser/web_contents.h"
@@ -93,15 +94,6 @@
 constexpr base::Feature kOmniboxCanCopyHyperlinksToClipboard{
     "OmniboxCanCopyHyperlinksToClipboard", base::FEATURE_ENABLED_BY_DEFAULT};
 
-enum class UmaEnumOmniboxSendTabToSelf {
-  kShowItem = 0,
-  kClickItem = 1,
-  kMaxValue = kClickItem,
-};
-
-void RecordSendTabToSelf(UmaEnumOmniboxSendTabToSelf state) {
-  UMA_HISTOGRAM_ENUMERATION("OmniboxViewViews.SendTabToSelf", state);
-}
 // OmniboxState ---------------------------------------------------------------
 
 // Stores omnibox state for each tab.
@@ -198,7 +190,6 @@
                                    const gfx::FontList& font_list)
     : OmniboxView(controller, std::move(client)),
       popup_window_mode_(popup_window_mode),
-      security_level_(security_state::NONE),
       saved_selection_for_focus_change_(gfx::Range::InvalidRange()),
       ime_composing_before_change_(false),
       location_bar_view_(location_bar),
@@ -283,7 +274,6 @@
 }
 
 void OmniboxViewViews::OnTabChanged(const content::WebContents* web_contents) {
-  UpdateSecurityLevel();
   const OmniboxState* state = static_cast<OmniboxState*>(
       web_contents->GetUserData(&OmniboxState::kKey));
   model()->RestoreState(state ? &state->model_state : nullptr);
@@ -364,9 +354,6 @@
 }
 
 void OmniboxViewViews::Update() {
-  const security_state::SecurityLevel old_security_level = security_level_;
-  UpdateSecurityLevel();
-
   if (model()->ResetDisplayTexts()) {
     RevertAll();
 
@@ -377,7 +364,9 @@
       // URL updates result from a user gesture or navigation.
       SelectAllForUserGesture();
     }
-  } else if (old_security_level != security_level_) {
+  } else {
+    // If the text is unchanged, we still need to re-emphasize the text, as the
+    // security state may be different from before the Update.
     EmphasizeURLComponents();
   }
 }
@@ -491,7 +480,8 @@
       location_bar_view_->command_updater()->ExecuteCommand(command_id);
       return;
     case IDC_SEND_TAB_TO_SELF:
-      RecordSendTabToSelf(UmaEnumOmniboxSendTabToSelf::kClickItem);
+      send_tab_to_self::RecordSendTabToSelfClickResult(
+          send_tab_to_self::kOmniboxMenu, SendTabToSelfClickResult::kClickItem);
       send_tab_to_self::CreateNewEntry(location_bar_view_->GetWebContents(),
                                        location_bar_view_->profile());
       return;
@@ -641,11 +631,6 @@
   return true;
 }
 
-void OmniboxViewViews::UpdateSecurityLevel() {
-  security_level_ =
-      controller()->GetLocationBarModel()->GetSecurityLevel(false);
-}
-
 // The following 2 methods implement the following table, which attempts to
 // handle left and right arrow keys versus LTR/RTL text and UI (which can be
 // different) as expected.
@@ -962,15 +947,21 @@
 
 void OmniboxViewViews::UpdateSchemeStyle(const gfx::Range& range) {
   DCHECK(range.IsValid());
+  DCHECK(!model()->user_input_in_progress());
+
+  security_state::SecurityLevel security_level =
+      controller()->GetLocationBarModel()->GetSecurityLevel(
+          true /* ignore_editing */);
+
   // Only SECURE and DANGEROUS levels (pages served over HTTPS or flagged by
   // SafeBrowsing) get a special scheme color treatment. If the security level
   // is NONE or HTTP_SHOW_WARNING, we do not override the text style previously
   // applied to the scheme text range by SetEmphasis().
-  if (security_level_ == security_state::NONE ||
-      security_level_ == security_state::HTTP_SHOW_WARNING)
+  if (security_level == security_state::NONE ||
+      security_level == security_state::HTTP_SHOW_WARNING)
     return;
-  ApplyColor(location_bar_view_->GetSecurityChipColor(security_level_), range);
-  if (security_level_ == security_state::DANGEROUS)
+  ApplyColor(location_bar_view_->GetSecurityChipColor(security_level), range);
+  if (security_level == security_state::DANGEROUS)
     ApplyStyle(gfx::TEXT_STYLE_STRIKE, true, range);
 }
 
@@ -1718,7 +1709,8 @@
   if (send_tab_to_self::ShouldOfferFeature(
           location_bar_view_->profile(),
           location_bar_view_->GetWebContents())) {
-    RecordSendTabToSelf(UmaEnumOmniboxSendTabToSelf::kShowItem);
+    send_tab_to_self::RecordSendTabToSelfClickResult(
+        send_tab_to_self::kOmniboxMenu, SendTabToSelfClickResult::kShowItem);
     int index = menu_contents->GetIndexOfCommandId(IDS_APP_UNDO);
     // Add a separator if this is not the first item.
     if (index)
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
index 596b776e..9cba396 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -17,7 +17,6 @@
 #include "build/build_config.h"
 #include "components/omnibox/browser/omnibox_view.h"
 #include "components/search_engines/template_url_service_observer.h"
-#include "components/security_state/core/security_state.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/compositor_observer.h"
@@ -175,9 +174,6 @@
   // Handle keyword hint tab-to-search and tabbing through dropdown results.
   bool HandleEarlyTabActions(const ui::KeyEvent& event);
 
-  // Updates |security_level_| based on the location bar model's current value.
-  void UpdateSecurityLevel();
-
   void ClearAccessibilityLabel();
 
   void SetAccessibilityLabel(const base::string16& display_text,
@@ -297,8 +293,6 @@
   // Animation used to fade out the path under some elision settings.
   std::unique_ptr<PathFadeAnimation> path_fade_animation_;
 
-  security_state::SecurityLevel security_level_;
-
   // Selection persisted across temporary text changes, like popup suggestions.
   gfx::Range saved_temporary_selection_;
 
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc b/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
index 38d9b54..ae21b2f 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
+++ b/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
@@ -55,8 +55,7 @@
         page_action_icons_.push_back(translate_icon_);
         break;
       case PageActionIconType::kZoom:
-        zoom_view_ = new ZoomView(params.location_bar_delegate,
-                                  params.page_action_icon_delegate);
+        zoom_view_ = new ZoomView(params.page_action_icon_delegate);
         page_action_icons_.push_back(zoom_view_);
         break;
       case PageActionIconType::kLocalCardMigration:
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_container_view.h b/chrome/browser/ui/views/page_action/page_action_icon_container_view.h
index afcd0fd..a6b56b4 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_container_view.h
+++ b/chrome/browser/ui/views/page_action/page_action_icon_container_view.h
@@ -8,7 +8,7 @@
 #include "base/macros.h"
 #include "base/scoped_observer.h"
 #include "chrome/browser/ui/page_action/page_action_icon_container.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "components/zoom/zoom_event_manager.h"
 #include "components/zoom/zoom_event_manager_observer.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -38,7 +38,6 @@
     Browser* browser = nullptr;
     CommandUpdater* command_updater = nullptr;
     PageActionIconView::Delegate* page_action_icon_delegate = nullptr;
-    LocationBarView::Delegate* location_bar_delegate = nullptr;
 
    private:
     DISALLOW_COPY_AND_ASSIGN(Params);
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_view.cc b/chrome/browser/ui/views/page_action/page_action_icon_view.cc
index d554d2c..feacb87 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_view.cc
+++ b/chrome/browser/ui/views/page_action/page_action_icon_view.cc
@@ -32,6 +32,10 @@
 
 }  // namespace
 
+bool PageActionIconView::Delegate::IsLocationBarUserInputInProgress() const {
+  return false;
+}
+
 PageActionIconView::PageActionIconView(CommandUpdater* command_updater,
                                        int command_id,
                                        PageActionIconView::Delegate* delegate,
@@ -40,6 +44,8 @@
       command_updater_(command_updater),
       delegate_(delegate),
       command_id_(command_id) {
+  DCHECK(delegate_);
+
   image()->EnableCanvasFlippingForRTLUI(true);
   SetInkDropMode(InkDropMode::ON);
   set_ink_drop_visible_opacity(
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_view.h b/chrome/browser/ui/views/page_action/page_action_icon_view.h
index aefa154..9e25ec08 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_view.h
+++ b/chrome/browser/ui/views/page_action/page_action_icon_view.h
@@ -42,6 +42,10 @@
     virtual SkColor GetPageActionInkDropColor() const = 0;
 
     virtual content::WebContents* GetWebContentsForPageActionIconView() = 0;
+
+    // Delegate should override and return true when the user is editing the
+    // location bar contents.
+    virtual bool IsLocationBarUserInputInProgress() const;
   };
 
   // Updates the color of the icon, this must be set before the icon is drawn.
@@ -135,6 +139,9 @@
 
   bool active() const { return active_; }
 
+  // Delegate accessor for subclasses.
+  Delegate* delegate() const { return delegate_; }
+
  private:
   // The size of the icon image (excluding the ink drop).
   int icon_size_ = GetLayoutConstant(LOCATION_BAR_ICON_SIZE);
@@ -143,10 +150,10 @@
   SkColor icon_color_ = gfx::kPlaceholderColor;
 
   // The CommandUpdater for the Browser object that owns the location bar.
-  CommandUpdater* command_updater_;
+  CommandUpdater* const command_updater_;
 
   // Delegate for access to associated state.
-  Delegate* delegate_;
+  Delegate* const delegate_;
 
   // The command ID executed when the user clicks this icon.
   const int command_id_;
diff --git a/chrome/browser/ui/views/page_action/zoom_view.cc b/chrome/browser/ui/views/page_action/zoom_view.cc
index f0cfa29a..1e5d14e9 100644
--- a/chrome/browser/ui/views/page_action/zoom_view.cc
+++ b/chrome/browser/ui/views/page_action/zoom_view.cc
@@ -16,11 +16,8 @@
 #include "ui/events/event.h"
 #include "ui/gfx/geometry/size.h"
 
-ZoomView::ZoomView(LocationBarView::Delegate* location_bar_delegate,
-                   PageActionIconView::Delegate* delegate)
-    : PageActionIconView(nullptr, 0, delegate),
-      location_bar_delegate_(location_bar_delegate),
-      icon_(&kZoomMinusIcon) {
+ZoomView::ZoomView(PageActionIconView::Delegate* delegate)
+    : PageActionIconView(nullptr, 0, delegate), icon_(&kZoomMinusIcon) {
   SetVisible(false);
 }
 
@@ -33,10 +30,8 @@
 }
 
 bool ZoomView::ShouldBeVisible(bool can_show_bubble) const {
-  if (location_bar_delegate_ &&
-      location_bar_delegate_->GetLocationBarModel()->input_in_progress()) {
+  if (delegate()->IsLocationBarUserInputInProgress())
     return false;
-  }
 
   if (can_show_bubble)
     return true;
diff --git a/chrome/browser/ui/views/page_action/zoom_view.h b/chrome/browser/ui/views/page_action/zoom_view.h
index b007e15..24eab1e 100644
--- a/chrome/browser/ui/views/page_action/zoom_view.h
+++ b/chrome/browser/ui/views/page_action/zoom_view.h
@@ -6,7 +6,6 @@
 #define CHROME_BROWSER_UI_VIEWS_PAGE_ACTION_ZOOM_VIEW_H_
 
 #include "base/macros.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 
 // View for the zoom icon in the Omnibox.
@@ -16,8 +15,7 @@
   // WebContents. Because the current WebContents changes as the user switches
   // tabs, a LocationBarView::Delegate is supplied to queried for the current
   // WebContents when needed.
-  ZoomView(LocationBarView::Delegate* location_bar_delegate,
-           PageActionIconView::Delegate* delegate);
+  explicit ZoomView(PageActionIconView::Delegate* delegate);
   ~ZoomView() override;
 
   // Updates the image and its tooltip appropriately, hiding or showing the icon
@@ -36,9 +34,6 @@
   bool ShouldBeVisible(bool can_show_bubble) const;
   bool HasAssociatedBubble() const;
 
-  // The delegate used to get whether omnibox input is in progress.
-  LocationBarView::Delegate* location_bar_delegate_;
-
   const gfx::VectorIcon* icon_ = nullptr;
 
   int current_zoom_percent_ = 100;
diff --git a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
index 0c05ae41..3dfa12f 100644
--- a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
+++ b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
@@ -50,16 +50,19 @@
     BuildColumnSet(layout);
     layout->StartRow(views::GridLayout::kFixedSize, 0);
 
-    layout->AddView(autofill::CreateLabelWithColorReadabilityDisabled(
-        suggestion, ChromeTextContext::CONTEXT_BODY_TEXT_LARGE,
-        state == PasswordGenerationPopupController::kOfferGeneration
-            ? views::style::STYLE_PRIMARY
-            : STYLE_SECONDARY));
+    layout->AddView(
+        autofill::CreateLabelWithColorReadabilityDisabled(
+            suggestion, ChromeTextContext::CONTEXT_BODY_TEXT_LARGE,
+            state == PasswordGenerationPopupController::kOfferGeneration
+                ? views::style::STYLE_PRIMARY
+                : STYLE_SECONDARY)
+            .release());
 
     DCHECK(!password_label_);
     password_label_ = autofill::CreateLabelWithColorReadabilityDisabled(
-        password, ChromeTextContext::CONTEXT_BODY_TEXT_LARGE,
-        STYLE_SECONDARY_MONOSPACED);
+                          password, ChromeTextContext::CONTEXT_BODY_TEXT_LARGE,
+                          STYLE_SECONDARY_MONOSPACED)
+                          .release();
     layout->AddView(password_label_);
   }
 
diff --git a/chrome/browser/ui/views/tabs/DEPS b/chrome/browser/ui/views/tabs/DEPS
index 5c95fe2..fa42a14a 100644
--- a/chrome/browser/ui/views/tabs/DEPS
+++ b/chrome/browser/ui/views/tabs/DEPS
@@ -3,4 +3,9 @@
   "window_finder_chromeos\.cc": [
     "+ash/wm/window_finder.h",
   ],
+  # mash-ok
+  "tab_drag_controller_interactive_uitest\.cc": [
+    "+ash/shell.h",
+    "+ash/wm/splitview/split_view_controller.h",
+  ],
 }
diff --git a/chrome/browser/ui/views/tabs/alert_indicator.cc b/chrome/browser/ui/views/tabs/alert_indicator.cc
index a60dc693..b81e682 100644
--- a/chrome/browser/ui/views/tabs/alert_indicator.cc
+++ b/chrome/browser/ui/views/tabs/alert_indicator.cc
@@ -7,7 +7,6 @@
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/tabs/tab.h"
-#include "components/vector_icons/vector_icons.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/animation/multi_animation.h"
@@ -104,11 +103,6 @@
     case TabAlertState::USB_CONNECTED:
       icon = &kTabUsbConnectedIcon;
       break;
-    case TabAlertState::SERIAL_CONNECTED:
-      // TODO(https://crbug.com/917204): This icon is too large to fit properly
-      // as a tab indicator and should be replaced.
-      icon = &vector_icons::kSerialPortIcon;
-      break;
     case TabAlertState::PIP_PLAYING:
       icon = &kPictureInPictureAltIcon;
       break;
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index ccda17a..3a550d05 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -631,7 +631,6 @@
       return theme_provider->GetColor(ThemeProperties::COLOR_TAB_PIP_PLAYING);
     case TabAlertState::BLUETOOTH_CONNECTED:
     case TabAlertState::USB_CONNECTED:
-    case TabAlertState::SERIAL_CONNECTED:
     case TabAlertState::NONE:
     case TabAlertState::VR_PRESENTING_IN_HEADSET:
       return button_color_;
@@ -756,10 +755,6 @@
       result.append(
           l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_USB_CONNECTED));
       break;
-    case TabAlertState::SERIAL_CONNECTED:
-      result.append(l10n_util::GetStringUTF16(
-          IDS_TOOLTIP_TAB_ALERT_STATE_SERIAL_CONNECTED));
-      break;
     case TabAlertState::PIP_PLAYING:
       result.append(
           l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_ALERT_STATE_PIP_PLAYING));
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index a9ae4727..40f5628 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -119,7 +119,7 @@
 gfx::Rect GetDraggedBrowserBoundsInTabletMode(aura::Window* window) {
   const gfx::Rect work_area =
       display::Screen::GetScreen()->GetDisplayNearestWindow(window).work_area();
-  gfx::Rect bounds(window->bounds());
+  gfx::Rect bounds(window->GetBoundsInScreen());
   bounds.set_width(work_area.width() / 2);
   bounds.set_height(work_area.height() / 2);
   return bounds;
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index 4a0991a..95b7695c 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -73,16 +73,21 @@
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h"
 #include "ash/public/cpp/window_properties.h"
 #include "ash/public/interfaces/constants.mojom.h"
+#include "ash/public/interfaces/shell_test_api.test-mojom-test-utils.h"
 #include "ash/public/interfaces/shell_test_api.test-mojom.h"
+#include "ash/shell.h"
+#include "ash/wm/splitview/split_view_controller.h"
 #include "ash/wm/window_state.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "chrome/browser/ui/ash/tablet_mode_client_test_util.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h"
 #include "content/public/common/service_manager_connection.h"
+#include "content/public/common/service_names.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/mus/window_mus.h"
 #include "ui/aura/test/mus/change_completion_waiter.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/ui_base_features.h"
@@ -1771,6 +1776,32 @@
   ASSERT_FALSE(TabDragController::IsActive());
 }
 
+IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
+                       OffsetForDraggingRightSnappedWindowInTabletMode) {
+  test::SetAndWaitForTabletMode(true);
+
+  // Right snap the browser window.
+  aura::Window* window = browser()->window()->GetNativeWindow();
+  if (features::IsUsingWindowService()) {
+    ash::mojom::ShellTestApiPtr shell_test_api;
+    content::ServiceManagerConnection::GetForProcess()
+        ->GetConnector()
+        ->BindInterface(ash::mojom::kServiceName, &shell_test_api);
+    ash::mojom::ShellTestApiAsyncWaiter shell_waiter(shell_test_api.get());
+    shell_waiter.SnapWindowInSplitView(
+        content::mojom::kBrowserServiceName,
+        aura::WindowMus::Get(window->GetRootWindow())->server_id(), false);
+  } else {
+    ash::Shell* shell = ash::Shell::Get();
+    shell->split_view_controller()->SnapWindow(window,
+                                               ash::SplitViewController::RIGHT);
+  }
+  EXPECT_NE(gfx::Point(), window->GetBoundsInScreen().origin());
+
+  DragWindowAndVerifyOffset(this, GetTabStripForBrowser(browser()), 0);
+  ASSERT_FALSE(TabDragController::IsActive());
+}
+
 namespace {
 
 void DragToOverviewWindowStep2(DetachToBrowserTabDragControllerTest* test,
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
index fdea632..84edbb9f 100644
--- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
+++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -9,17 +9,24 @@
 
 #include "base/metrics/field_trial_params.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/browser_features.h"
+#include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/tabs/tab_style.h"
 #include "chrome/browser/ui/thumbnails/thumbnail_image.h"
 #include "chrome/browser/ui/views/chrome_typography.h"
 #include "chrome/browser/ui/views/tabs/tab.h"
 #include "chrome/browser/ui/views/tabs/tab_renderer_data.h"
 #include "components/url_formatter/url_formatter.h"
+#include "ui/base/theme_provider.h"
 #include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/animation/linear_animation.h"
 #include "ui/gfx/animation/tween.h"
 #include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/native_theme/native_theme.h"
+#include "ui/resources/grit/ui_resources.h"
+#include "ui/views/background.h"
 #include "ui/views/bubble/bubble_frame_view.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
@@ -201,8 +208,10 @@
   if (AreHoverCardImagesEnabled()) {
     preview_image_ = new views::ImageView();
     preview_image_->SetVisible(AreHoverCardImagesEnabled());
-    preview_image_->SetHorizontalAlignment(views::ImageViewBase::LEADING);
+    preview_image_->SetHorizontalAlignment(views::ImageViewBase::CENTER);
+    preview_image_->SetVerticalAlignment(views::ImageViewBase::CENTER);
     preview_image_->SetImageSize(GetTabHoverCardPreviewImageSize());
+    preview_image_->SetPreferredSize(GetTabHoverCardPreviewImageSize());
     AddChildView(preview_image_);
   }
 
@@ -322,13 +331,39 @@
     if (!data.thumbnail.AsImageSkiaAsync(
             base::BindOnce(&TabHoverCardBubbleView::UpdatePreviewImage,
                            weak_factory_.GetWeakPtr()))) {
-      preview_image_->SetImage(gfx::ImageSkia());
+      // Check the no-preview color and size to see if it needs to be
+      // regenerated. DPI or theme change can cause a regeneration.
+      const SkColor foreground_color = GetThemeProvider()->GetColor(
+          ThemeProperties::COLOR_HOVER_CARD_NO_PREVIEW_FOREGROUND);
+
+      // Set the no-preview placeholder image. All sizes are in DIPs.
+      // gfx::CreateVectorIcon() caches its result so there's no need to store
+      // images here; if a particular size/color combination has already been
+      // requested it will be low-cost to request it again.
+      constexpr gfx::Size kNoPreviewImageSize{64, 64};
+      const gfx::ImageSkia no_preview_image = gfx::CreateVectorIcon(
+          kGlobeIcon, kNoPreviewImageSize.width(), foreground_color);
+      preview_image_->SetImage(no_preview_image);
+      preview_image_->SetImageSize(kNoPreviewImageSize);
+      preview_image_->SetPreferredSize(GetTabHoverCardPreviewImageSize());
+
+      // Also possibly regenerate the background if it has changed.
+      const SkColor background_color = GetThemeProvider()->GetColor(
+          ThemeProperties::COLOR_HOVER_CARD_NO_PREVIEW_BACKGROUND);
+      if (!preview_image_->background() ||
+          preview_image_->background()->get_color() != background_color) {
+        preview_image_->SetBackground(
+            views::CreateSolidBackground(background_color));
+      }
     }
   }
 }
 
 void TabHoverCardBubbleView::UpdatePreviewImage(gfx::ImageSkia preview_image) {
   preview_image_->SetImage(preview_image);
+  preview_image_->SetImageSize(GetTabHoverCardPreviewImageSize());
+  preview_image_->SetPreferredSize(GetTabHoverCardPreviewImageSize());
+  preview_image_->SetBackground(nullptr);
 }
 
 gfx::Size TabHoverCardBubbleView::CalculatePreferredSize() const {
diff --git a/chrome/browser/ui/views/test/view_event_test_base.cc b/chrome/browser/ui/views/test/view_event_test_base.cc
index dda24a6..6c60e713 100644
--- a/chrome/browser/ui/views/test/view_event_test_base.cc
+++ b/chrome/browser/ui/views/test/view_event_test_base.cc
@@ -14,7 +14,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "mojo/core/embedder/embedder.h"
 #include "ui/base/clipboard/clipboard.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/compositor/test/context_factories_for_test.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
index 6553176..3da814af 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -175,7 +175,7 @@
   SchedulePaint();
 }
 
-void ToolbarActionView::OnMenuButtonClicked(views::MenuButton* sender,
+void ToolbarActionView::OnMenuButtonClicked(views::Button* sender,
                                             const gfx::Point& point,
                                             const ui::Event* event) {
   if (!view_controller_->IsEnabled(GetCurrentWebContents())) {
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.h b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
index a1388260..5cb76a6 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
@@ -80,7 +80,7 @@
   void UpdateState() override;
 
   // views::MenuButtonListener:
-  void OnMenuButtonClicked(views::MenuButton* source,
+  void OnMenuButtonClicked(views::Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override;
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 1754917e..6650e23a 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -407,7 +407,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ToolbarView, views::MenuButtonListener implementation:
 
-void ToolbarView::OnMenuButtonClicked(views::MenuButton* source,
+void ToolbarView::OnMenuButtonClicked(views::Button* source,
                                       const gfx::Point& point,
                                       const ui::Event* event) {
   TRACE_EVENT0("views", "ToolbarView::OnMenuButtonClicked");
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h
index dac4531..da4304f 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -144,7 +144,7 @@
   }
 
   // views::MenuButtonListener:
-  void OnMenuButtonClicked(views::MenuButton* source,
+  void OnMenuButtonClicked(views::Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override;
 
diff --git a/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc b/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc
index ca14aa8..239730a 100644
--- a/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc
@@ -14,10 +14,15 @@
 #include "base/files/file_util.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
+#include "base/linux_util.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/process/process_iterator.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_tokenizer.h"
 #include "base/strings/stringprintf.h"
 #include "base/task/post_task.h"
 #include "base/values.h"
+#include "chrome/browser/chromeos/arc/tracing/arc_cpu_model.h"
 #include "chrome/browser/chromeos/arc/tracing/arc_graphics_jank_detector.h"
 #include "chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h"
 #include "chrome/browser/chromeos/arc/tracing/arc_tracing_model.h"
@@ -74,6 +79,74 @@
   return std::make_pair(std::move(*model), "Loaded last tracing model");
 }
 
+class ProcessFilterPassAll : public base::ProcessFilter {
+ public:
+  ProcessFilterPassAll() = default;
+  ~ProcessFilterPassAll() override = default;
+
+  // base::ProcessFilter:
+  bool Includes(const base::ProcessEntry& process) const override {
+    return true;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ProcessFilterPassAll);
+};
+
+// Reads name of thread from /proc/pid/task/tid/status.
+bool ReadNameFromStatus(pid_t pid, pid_t tid, std::string* out_name) {
+  std::string status;
+  if (!base::ReadFileToString(base::FilePath(base::StringPrintf(
+                                  "/proc/%d/task/%d/status", pid, tid)),
+                              &status)) {
+    return false;
+  }
+  base::StringTokenizer tokenizer(status, "\n");
+  while (tokenizer.GetNext()) {
+    base::StringPiece value_str(tokenizer.token_piece());
+    if (!value_str.starts_with("Name:"))
+      continue;
+    std::vector<base::StringPiece> split_value_str = base::SplitStringPiece(
+        value_str, "\t", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+    DCHECK_EQ(2U, split_value_str.size());
+    *out_name = split_value_str[1].as_string();
+    return true;
+  }
+
+  return false;
+}
+
+// Helper that clarifies thread and process names. Tracing events may not have
+// enough data for this. Also it determines the process pid the thread belongs
+// to.
+void UpdateThreads(arc::ArcCpuModel::ThreadMap* threads) {
+  ProcessFilterPassAll filter_pass_all;
+  base::ProcessIterator process_iterator(&filter_pass_all);
+
+  std::vector<pid_t> tids;
+  std::string name;
+  for (const auto& process : process_iterator.Snapshot()) {
+    tids.clear();
+    base::GetThreadsForProcess(process.pid(), &tids);
+    bool process_in_use = threads->find(process.pid()) != threads->end();
+    for (pid_t tid : tids) {
+      if (threads->find(tid) != threads->end()) {
+        process_in_use = true;
+        (*threads)[tid].pid = process.pid();
+        if (!ReadNameFromStatus(process.pid(), tid, &(*threads)[tid].name))
+          LOG(WARNING) << "Failed to update thread name " << tid;
+      }
+    }
+    if (process_in_use) {
+      (*threads)[process.pid()].pid = process.pid();
+      if (!ReadNameFromStatus(process.pid(), process.pid(),
+                              &(*threads)[process.pid()].name)) {
+        LOG(WARNING) << "Failed to update process name " << process.pid();
+      }
+    }
+  }
+}
+
 std::pair<base::Value, std::string> BuildGraphicsModel(
     const std::string& data,
     base::DictionaryValue tasks_info,
@@ -94,6 +167,8 @@
   if (!graphics_model.Build(common_model))
     return std::make_pair(base::Value(), "Failed to build tracing model");
 
+  UpdateThreads(&graphics_model.cpu_model().thread_map());
+
   std::unique_ptr<base::DictionaryValue> model = graphics_model.Serialize();
   model->SetKey(kKeyTasks, std::move(tasks_info));
 
diff --git a/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h
index b6435e5..6a8fd69 100644
--- a/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h
@@ -54,7 +54,7 @@
   // OobeUI::Observer:
   void OnCurrentScreenChanged(OobeScreen current_screen,
                               OobeScreen new_screen) override;
-  void OnScreenInitialized(OobeScreen screen) override {}
+  void OnDestroyingOobeUI() override {}
 
   // system::TimezoneSettings::Observer:
   void TimezoneChanged(const icu::TimeZone& timezone) override;
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index fdf3b37..8e07ef3e 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -540,7 +540,10 @@
       &OobeUI::BindPrivilegedHostDeviceSetter, base::Unretained(this)));
 }
 
-OobeUI::~OobeUI() {}
+OobeUI::~OobeUI() {
+  for (Observer& observer : observer_list_)
+    observer.OnDestroyingOobeUI();
+}
 
 CoreOobeView* OobeUI::GetCoreOobeView() {
   return core_handler_;
@@ -733,7 +736,6 @@
   for (BaseScreenHandler* handler : screen_handlers_) {
     if (handler->async_assets_load_id().empty()) {
       handler->InitializeBase();
-      ScreenInitialized(handler->oobe_screen());
     }
   }
 }
@@ -746,11 +748,6 @@
     observer.OnCurrentScreenChanged(current_screen_, new_screen);
 }
 
-void OobeUI::ScreenInitialized(OobeScreen screen) {
-  for (Observer& observer : observer_list_)
-    observer.OnScreenInitialized(screen);
-}
-
 bool OobeUI::IsScreenInitialized(OobeScreen screen) {
   for (BaseScreenHandler* handler : screen_handlers_) {
     if (handler->oobe_screen() == screen) {
@@ -771,7 +768,6 @@
   for (BaseScreenHandler* handler : screen_handlers_) {
     if (handler->async_assets_load_id() == async_assets_load_id) {
       handler->InitializeBase();
-      ScreenInitialized(handler->oobe_screen());
     }
   }
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
index b208078..edd7137 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
@@ -94,7 +94,7 @@
     virtual void OnCurrentScreenChanged(OobeScreen current_screen,
                                         OobeScreen new_screen) = 0;
 
-    virtual void OnScreenInitialized(OobeScreen screen) = 0;
+    virtual void OnDestroyingOobeUI() = 0;
 
    protected:
     virtual ~Observer() {}
@@ -148,9 +148,6 @@
   // Called when the screen has changed.
   void CurrentScreenChanged(OobeScreen screen);
 
-  // Called when the screen was initialized.
-  void ScreenInitialized(OobeScreen screen);
-
   bool IsScreenInitialized(OobeScreen screen);
 
   // Invoked after the async assets load. The screen handler that has the same
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index 6cb3336..ea5ef06 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -224,7 +224,7 @@
   // OobeUI::Observer implementation:
   void OnCurrentScreenChanged(OobeScreen current_screen,
                               OobeScreen new_screen) override;
-  void OnScreenInitialized(OobeScreen screen) override {}
+  void OnDestroyingOobeUI() override {}
 
   // ash::mojom::WallpaperObserver implementation:
   void OnWallpaperChanged(uint32_t image_id) override;
diff --git a/chrome/browser/ui/webui/downloads/downloads_ui.cc b/chrome/browser/ui/webui/downloads/downloads_ui.cc
index 041c930..b1182623 100644
--- a/chrome/browser/ui/webui/downloads/downloads_ui.cc
+++ b/chrome/browser/ui/webui/downloads/downloads_ui.cc
@@ -15,6 +15,7 @@
 #include "base/values.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/safe_browsing/advanced_protection_status_manager.h"
 #include "chrome/browser/ui/webui/dark_mode_handler.h"
 #include "chrome/browser/ui/webui/downloads/downloads_dom_handler.h"
 #include "chrome/browser/ui/webui/managed_ui_handler.h"
@@ -75,12 +76,26 @@
   // Dangerous file.
   source->AddLocalizedString("dangerFileDesc",
                              IDS_BLOCK_REASON_GENERIC_DOWNLOAD);
-  source->AddLocalizedString("dangerDownloadDesc",
-                             IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD);
-  source->AddLocalizedString("dangerUncommonDesc",
-                             IDS_BLOCK_REASON_UNCOMMON_DOWNLOAD);
-  source->AddLocalizedString("dangerSettingsDesc",
-                             IDS_BLOCK_REASON_UNWANTED_DOWNLOAD);
+
+  bool requests_ap_verdicts = safe_browsing::AdvancedProtectionStatusManager::
+      RequestsAdvancedProtectionVerdicts(profile);
+
+  source->AddLocalizedString(
+      "dangerDownloadDesc",
+      requests_ap_verdicts
+          ? IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD_IN_ADVANCED_PROTECTION
+          : IDS_BLOCK_REASON_DANGEROUS_DOWNLOAD);
+  source->AddLocalizedString(
+      "dangerUncommonDesc",
+      requests_ap_verdicts
+          ? IDS_BLOCK_REASON_UNCOMMON_DOWNLOAD_IN_ADVANCED_PROTECTION
+          : IDS_BLOCK_REASON_UNCOMMON_DOWNLOAD);
+  source->AddLocalizedString(
+      "dangerSettingsDesc",
+      requests_ap_verdicts
+          ? IDS_BLOCK_REASON_UNWANTED_DOWNLOAD_IN_ADVANCED_PROTECTION
+          : IDS_BLOCK_REASON_UNWANTED_DOWNLOAD);
+
   source->AddLocalizedString("dangerSave", IDS_CONFIRM_DOWNLOAD);
   source->AddLocalizedString("dangerRestore", IDS_CONFIRM_DOWNLOAD_RESTORE);
   source->AddLocalizedString("dangerDiscard", IDS_DISCARD_DOWNLOAD);
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
index 4127290..a19b61e6 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_update_engine_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_handler.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 0ebb19b..d52d5c7 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -22,6 +22,7 @@
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/bookmark_app_extension_util.h"
 #include "chrome/browser/extensions/crx_installer.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_ui_util.h"
@@ -254,6 +255,10 @@
       base::BindRepeating(&AppLauncherHandler::HandleCreateAppShortcut,
                           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
+      "installAppLocally",
+      base::BindRepeating(&AppLauncherHandler::HandleInstallAppLocally,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
       "showAppInfo", base::BindRepeating(&AppLauncherHandler::HandleShowAppInfo,
                                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
@@ -618,6 +623,29 @@
       base::Callback<void(bool)>());
 }
 
+void AppLauncherHandler::HandleInstallAppLocally(const base::ListValue* args) {
+  std::string extension_id;
+  CHECK(args->GetString(0, &extension_id));
+
+  const Extension* extension =
+      extension_service_->GetExtensionById(extension_id, true);
+  if (!extension)
+    return;
+
+  auto* profile = Profile::FromBrowserContext(
+      web_ui()->GetWebContents()->GetBrowserContext());
+  SetBookmarkAppIsLocallyInstalled(profile, extension, true);
+  if (extensions::CanBookmarkAppCreateOsShortcuts()) {
+    extensions::BookmarkAppCreateOsShortcuts(
+        profile, extension, true /* add_to_desktop */, base::DoNothing());
+  }
+
+  // Use the appAdded to update the app icon's color to no longer be greyscale.
+  std::unique_ptr<base::DictionaryValue> app_info(GetAppInfo(extension));
+  if (app_info)
+    web_ui()->CallJavascriptFunctionUnsafe("ntp.appAdded", *app_info);
+}
+
 void AppLauncherHandler::HandleShowAppInfo(const base::ListValue* args) {
   std::string extension_id;
   CHECK(args->GetString(0, &extension_id));
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.h b/chrome/browser/ui/webui/ntp/app_launcher_handler.h
index 5e9bf46..c2a7659 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.h
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.h
@@ -112,6 +112,10 @@
   // [extension_id].
   void HandleCreateAppShortcut(const base::ListValue* args);
 
+  // Handles the "installAppLocally" message with |args| containing
+  // [extension_id].
+  void HandleInstallAppLocally(const base::ListValue* args);
+
   // Handles the "showAppInfo" message with |args| containing [extension_id].
   void HandleShowAppInfo(const base::ListValue* args);
 
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
index 090be9f..78c46d6 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -405,6 +405,8 @@
                            GetLocalizedString(IDS_APP_CONTEXT_MENU_SHOW_INFO));
   load_time_data.SetString("appcreateshortcut",
                            GetLocalizedString(IDS_NEW_TAB_APP_CREATE_SHORTCUT));
+  load_time_data.SetString("appinstalllocally",
+                           GetLocalizedString(IDS_NEW_TAB_APP_INSTALL_LOCALLY));
   load_time_data.SetString("appDefaultPageName",
                            GetLocalizedString(IDS_APP_DEFAULT_PAGE_NAME));
   load_time_data.SetString(
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
index 031c5ee2..f609d39 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -242,6 +242,8 @@
     {"printPagesLabel", IDS_PRINT_PREVIEW_PRINT_PAGES_LABEL},
     {"printPreviewPageLabelPlural", IDS_PRINT_PREVIEW_PAGE_LABEL_PLURAL},
     {"printPreviewPageLabelSingular", IDS_PRINT_PREVIEW_PAGE_LABEL_SINGULAR},
+    {"printPreviewNewSummaryFormatShort",
+     IDS_PRINT_PREVIEW_NEW_SUMMARY_FORMAT_SHORT},
     {"printPreviewSheetsLabelPlural", IDS_PRINT_PREVIEW_SHEETS_LABEL_PLURAL},
     {"printPreviewSheetsLabelSingular",
      IDS_PRINT_PREVIEW_SHEETS_LABEL_SINGULAR},
@@ -321,6 +323,10 @@
       base::FeatureList::IsEnabled(features::kCloudPrinterHandler);
   source->AddBoolean("cloudPrinterHandlerEnabled",
                      cloud_printer_handler_enabled);
+  bool new_print_preview_layout_enabled =
+      base::FeatureList::IsEnabled(features::kNewPrintPreviewLayout);
+  source->AddBoolean("newPrintPreviewLayoutEnabled",
+                     new_print_preview_layout_enabled);
 }
 
 std::vector<std::string> SetupPrintPreviewPlugin(
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index efc839dc..decd9f8 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -253,15 +253,42 @@
 
 }  // namespace
 
-CupsPrintersHandler::CupsPrintersHandler(content::WebUI* webui)
-    : profile_(Profile::FromWebUI(webui)),
-      ppd_provider_(CreatePpdProvider(profile_)),
-      printer_configurer_(PrinterConfigurer::Create(profile_)),
-      printers_manager_(
-          CupsPrintersManagerFactory::GetForBrowserContext(profile_)),
+CupsPrintersHandler::CupsPrintersHandler(
+    Profile* profile,
+    scoped_refptr<PpdProvider> ppd_provider,
+    std::unique_ptr<PrinterConfigurer> printer_configurer,
+    CupsPrintersManager* printers_manager)
+    : profile_(profile),
+      ppd_provider_(ppd_provider),
+      printer_configurer_(std::move(printer_configurer)),
+      printers_manager_(printers_manager),
       printers_manager_observer_(this),
       weak_factory_(this) {}
 
+// static
+std::unique_ptr<CupsPrintersHandler> CupsPrintersHandler::Create(
+    content::WebUI* webui) {
+  Profile* profile(Profile::FromWebUI(webui));
+  auto ppd_provider = CreatePpdProvider(profile);
+  auto printer_configurer = PrinterConfigurer::Create(profile);
+  CupsPrintersManager* printers_manager =
+      CupsPrintersManagerFactory::GetForBrowserContext(profile);
+  // Using 'new' to access non-public constructor.
+  return base::WrapUnique(new CupsPrintersHandler(
+      profile, ppd_provider, std::move(printer_configurer), printers_manager));
+}
+
+// static
+std::unique_ptr<CupsPrintersHandler> CupsPrintersHandler::CreateForTesting(
+    Profile* profile,
+    scoped_refptr<PpdProvider> ppd_provider,
+    std::unique_ptr<PrinterConfigurer> printer_configurer,
+    CupsPrintersManager* printers_manager) {
+  // Using 'new' to access non-public constructor.
+  return base::WrapUnique(new CupsPrintersHandler(
+      profile, ppd_provider, std::move(printer_configurer), printers_manager));
+}
+
 CupsPrintersHandler::~CupsPrintersHandler() = default;
 
 void CupsPrintersHandler::RegisterMessages() {
@@ -331,6 +358,10 @@
   printers_manager_observer_.RemoveAll();
 }
 
+void CupsPrintersHandler::SetWebUIForTest(content::WebUI* web_ui) {
+  set_web_ui(web_ui);
+}
+
 void CupsPrintersHandler::HandleGetCupsPrintersList(
     const base::ListValue* args) {
   AllowJavascript();
@@ -395,8 +426,9 @@
   printers_manager_->RemoveConfiguredPrinter(printer_id);
 
   DebugDaemonClient* client = DBusThreadManager::Get()->GetDebugDaemonClient();
-  client->CupsRemovePrinter(
-      printer_name, base::Bind(&OnRemovedPrinter, protocol), base::DoNothing());
+  client->CupsRemovePrinter(printer_id,
+                            base::BindOnce(&OnRemovedPrinter, protocol),
+                            base::DoNothing());
 }
 
 void CupsPrintersHandler::HandleGetPrinterInfo(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
index b1cc3107..d6a1a8c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
@@ -38,7 +38,14 @@
                             public ui::SelectFileDialog::Listener,
                             public CupsPrintersManager::Observer {
  public:
-  explicit CupsPrintersHandler(content::WebUI* webui);
+  static std::unique_ptr<CupsPrintersHandler> Create(content::WebUI* webui);
+
+  static std::unique_ptr<CupsPrintersHandler> CreateForTesting(
+      Profile* profile,
+      scoped_refptr<PpdProvider> ppd_provider,
+      std::unique_ptr<PrinterConfigurer> printer_configurer,
+      CupsPrintersManager* printers_manager);
+
   ~CupsPrintersHandler() override;
 
   // SettingsPageUIHandler overrides:
@@ -46,7 +53,14 @@
   void OnJavascriptAllowed() override;
   void OnJavascriptDisallowed() override;
 
+  void SetWebUIForTest(content::WebUI* web_ui);
+
  private:
+  CupsPrintersHandler(Profile* profile,
+                      scoped_refptr<PpdProvider> ppd_provider,
+                      std::unique_ptr<PrinterConfigurer> printer_configurer,
+                      CupsPrintersManager* printers_manager);
+
   // Gets all CUPS printers and return it to WebUI.
   void HandleGetCupsPrintersList(const base::ListValue* args);
   void HandleUpdateCupsPrinter(const base::ListValue* args);
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc
new file mode 100644
index 0000000..1ef4efc9
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc
@@ -0,0 +1,146 @@
+// Copyright 2019 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/cups_printers_handler.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/json/json_string_value_serializer.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/debug_daemon_client.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_web_ui.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace settings {
+
+class CupsPrintersHandlerTest;
+
+namespace {
+
+// Converts JSON string to base::ListValue object.
+// On failure, returns NULL and fills |*error| string.
+std::unique_ptr<base::ListValue> GetJSONAsListValue(const std::string& json,
+                                                    std::string* error) {
+  auto ret = base::ListValue::From(
+      JSONStringValueDeserializer(json).Deserialize(nullptr, error));
+  if (!ret)
+    *error = "Value is not a list.";
+  return ret;
+}
+
+}  // namespace
+
+// Callback used for testing CupsAddAutoConfiguredPrinter().
+void AddedPrinter(int32_t status) {
+  ASSERT_EQ(status, 0);
+}
+
+// Callback used for testing CupsRemovePrinter().
+void RemovedPrinter(bool* expected, bool result) {
+  EXPECT_EQ(*expected, result);
+}
+
+class FakePrinterConfigurer : public PrinterConfigurer {
+ public:
+  void SetUpPrinter(const Printer& printer,
+                    PrinterSetupCallback callback) override {}
+};
+
+class FakeCupsPrintersManager : public CupsPrintersManager {
+ public:
+  FakeCupsPrintersManager() = default;
+
+  std::vector<Printer> GetPrinters(PrinterClass printer_class) const override {
+    return {};
+  }
+
+  void RemoveUnavailablePrinters(std::vector<Printer>*) const override {}
+  void UpdateConfiguredPrinter(const Printer& printer) override {}
+  void RemoveConfiguredPrinter(const std::string& printer_id) override {}
+  void AddObserver(CupsPrintersManager::Observer* observer) override {}
+  void RemoveObserver(CupsPrintersManager::Observer* observer) override {}
+  void PrinterInstalled(const Printer& printer, bool is_automatic) override {}
+  void RecordSetupAbandoned(const Printer& printer) override {}
+
+  bool IsPrinterInstalled(const Printer& printer) const override {
+    return false;
+  }
+
+  std::unique_ptr<Printer> GetPrinter(const std::string& id) const override {
+    return std::make_unique<Printer>();
+  }
+};
+
+class FakePpdProvider : public PpdProvider {
+ public:
+  FakePpdProvider() = default;
+
+  void ResolveManufacturers(ResolveManufacturersCallback cb) override {}
+  void ResolvePrinters(const std::string& manufacturer,
+                       ResolvePrintersCallback cb) override {}
+  void ResolvePpdReference(const PrinterSearchData& search_data,
+                           ResolvePpdReferenceCallback cb) override {}
+  void ResolvePpd(const Printer::PpdReference& reference,
+                  ResolvePpdCallback cb) override {}
+  void ReverseLookup(const std::string& effective_make_and_model,
+                     ReverseLookupCallback cb) override {}
+
+ private:
+  ~FakePpdProvider() override {}
+};
+
+class CupsPrintersHandlerTest : public testing::Test {
+ public:
+  CupsPrintersHandlerTest() = default;
+  ~CupsPrintersHandlerTest() override = default;
+
+  void SetUp() override {
+    printers_handler_ = CupsPrintersHandler::CreateForTesting(
+        &profile_, base::MakeRefCounted<FakePpdProvider>(),
+        std::make_unique<FakePrinterConfigurer>(), &printers_manager_);
+    printers_handler_->SetWebUIForTest(&web_ui_);
+    printers_handler_->RegisterMessages();
+  }
+
+ protected:
+  // Must outlive |profile_|.
+  content::TestBrowserThreadBundle thread_bundle_;
+  TestingProfile profile_;
+  content::TestWebUI web_ui_;
+  std::unique_ptr<CupsPrintersHandler> printers_handler_;
+  FakeCupsPrintersManager printers_manager_;
+};
+
+TEST_F(CupsPrintersHandlerTest, RemoveCorrectPrinter) {
+  DBusThreadManager::Initialize();
+  DebugDaemonClient* client = DBusThreadManager::Get()->GetDebugDaemonClient();
+  client->CupsAddAutoConfiguredPrinter("testprinter1", "fakeuri",
+                                       base::BindOnce(&AddedPrinter));
+
+  const std::string remove_list = R"(
+    ["testprinter1", "Test Printer 1"]
+  )";
+  std::string error;
+  std::unique_ptr<base::ListValue> remove_printers(
+      GetJSONAsListValue(remove_list, &error));
+  ASSERT_TRUE(remove_printers) << "Error deserializing list: " << error;
+
+  web_ui_.HandleReceivedMessage("removeCupsPrinter", remove_printers.get());
+
+  // We expect this printer removal to fail since the printer should have
+  // already been removed by the previous call to 'removeCupsPrinter'.
+  bool expected = false;
+  client->CupsRemovePrinter("testprinter1",
+                            base::BindRepeating(&RemovedPrinter, &expected),
+                            base::DoNothing());
+  thread_bundle_.RunUntilIdle();
+}
+
+}  // 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 f610336c5..907b6e67 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
@@ -2811,10 +2811,6 @@
       {"securityKeysCurrentPIN", IDS_SETTINGS_SECURITY_KEYS_CURRENT_PIN},
       {"securityKeysCurrentPINIntro",
        IDS_SETTINGS_SECURITY_KEYS_CURRENT_PIN_INTRO},
-      {"securityKeysCurrentPINRetriesPl",
-       IDS_SETTINGS_SECURITY_KEYS_CURRENT_PIN_RETRIES_PL},
-      {"securityKeysCurrentPINRetriesSin",
-       IDS_SETTINGS_SECURITY_KEYS_CURRENT_PIN_RETRIES_SIN},
       {"securityKeysDesc", IDS_SETTINGS_SECURITY_KEYS_DESC},
       {"securityKeysNewPIN", IDS_SETTINGS_SECURITY_KEYS_NEW_PIN},
       {"securityKeysNoPIN", IDS_SETTINGS_SECURITY_KEYS_NO_PIN},
@@ -2823,6 +2819,10 @@
       {"securityKeysPINError", IDS_SETTINGS_SECURITY_KEYS_PIN_ERROR},
       {"securityKeysPINHardLock", IDS_SETTINGS_SECURITY_KEYS_PIN_HARD_LOCK},
       {"securityKeysPINIncorrect", IDS_SETTINGS_SECURITY_KEYS_PIN_INCORRECT},
+      {"securityKeysPINIncorrectRetriesSin",
+       IDS_SETTINGS_SECURITY_KEYS_PIN_INCORRECT_RETRIES_SIN},
+      {"securityKeysPINIncorrectRetriesPl",
+       IDS_SETTINGS_SECURITY_KEYS_PIN_INCORRECT_RETRIES_PL},
       {"securityKeysPINSoftLock", IDS_SETTINGS_SECURITY_KEYS_PIN_SOFT_LOCK},
       {"securityKeysPINSuccess", IDS_SETTINGS_SECURITY_KEYS_PIN_SUCCESS},
       {"securityKeysPINTouch", IDS_SETTINGS_SECURITY_KEYS_PIN_TOUCH},
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index d6569d12..d01eb0f7 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -228,7 +228,7 @@
         std::make_unique<chromeos::settings::CrostiniHandler>(profile));
   }
   AddSettingsPageUIHandler(
-      std::make_unique<chromeos::settings::CupsPrintersHandler>(web_ui));
+      chromeos::settings::CupsPrintersHandler::Create(web_ui));
   AddSettingsPageUIHandler(
       std::make_unique<chromeos::settings::FingerprintHandler>(profile));
   if (chromeos::switches::IsAssistantEnabled()) {
diff --git a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
index 8c34895..f46e5ef 100644
--- a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
@@ -64,9 +64,12 @@
 }
 
 void DefaultBrowserHandler::RequestDefaultBrowserState(
-    const base::ListValue* /*args*/) {
+    const base::ListValue* args) {
   AllowJavascript();
 
+  CHECK_EQ(args->GetSize(), 1U);
+  CHECK(args->GetString(0, &check_default_callback_id_));
+
   default_browser_worker_->StartCheckIsDefault();
 }
 
@@ -103,7 +106,12 @@
       state == shell_integration::UNKNOWN_DEFAULT);
   dict.SetBoolean("isDisabledByPolicy", DefaultBrowserIsDisabledByPolicy());
 
-  FireWebUIListener("browser-default-state-changed", dict);
+  if (!check_default_callback_id_.empty()) {
+    ResolveJavascriptCallback(base::Value(check_default_callback_id_), dict);
+    check_default_callback_id_.clear();
+  } else {
+    FireWebUIListener("browser-default-state-changed", dict);
+  }
 }
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/settings_default_browser_handler.h b/chrome/browser/ui/webui/settings/settings_default_browser_handler.h
index 81337dc..fe71f65 100644
--- a/chrome/browser/ui/webui/settings/settings_default_browser_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_default_browser_handler.h
@@ -40,6 +40,8 @@
   virtual void RecordSetAsDefaultUMA();
 
  private:
+  std::string check_default_callback_id_;
+
   // Called from WebUI to request the current state.
   void RequestDefaultBrowserState(const base::ListValue* args);
 
diff --git a/chrome/browser/ui/webui/welcome/nux/email_providers_list.cc b/chrome/browser/ui/webui/welcome/nux/email_providers_list.cc
index 329f878..62d6c1b 100644
--- a/chrome/browser/ui/webui/welcome/nux/email_providers_list.cc
+++ b/chrome/browser/ui/webui/welcome/nux/email_providers_list.cc
@@ -39,10 +39,11 @@
       };
     }
 
-      // TODO(scottchen): define all supported countries here.
+      // TODO(hcarmona/johntlee): define all supported countries here.
 
     default: {
-      // TODO(scottchen): examine if we want these US providers as default.
+      // TODO(hcarmona/johntlee): examine if we want these US providers as
+      // default.
       return {
           {static_cast<int>(EmailProviders::kGmail), "Gmail", "gmail",
            "https://accounts.google.com/b/0/AddMailService",
diff --git a/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc b/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc
index 0bd0c361..3d4f3387 100644
--- a/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc
+++ b/chrome/browser/ui/webui/welcome/nux/set_as_default_handler.cc
@@ -12,7 +12,7 @@
 SetAsDefaultHandler::~SetAsDefaultHandler() {}
 
 void SetAsDefaultHandler::RecordSetAsDefaultUMA() {
-  // TODO(scottchen): Add UMA tracking.
+  // TODO(hcarmona): Add UMA tracking.
 }
 
 }  // namespace nux
diff --git a/chrome/browser/vr/service/browser_xr_runtime.cc b/chrome/browser/vr/service/browser_xr_runtime.cc
index ad8ed86..d454f7db 100644
--- a/chrome/browser/vr/service/browser_xr_runtime.cc
+++ b/chrome/browser/vr/service/browser_xr_runtime.cc
@@ -4,21 +4,163 @@
 
 #include "chrome/browser/vr/service/browser_xr_runtime.h"
 
+#include <algorithm>
+
 #include "base/bind.h"
 #include "chrome/browser/vr/service/xr_device_impl.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "device/vr/vr_device.h"
+#include "ui/gfx/transform.h"
+#include "ui/gfx/transform_util.h"
 
 namespace vr {
 
+bool IsValidStandingTransform(std::vector<float> standingTransform) {
+  gfx::Transform transform = gfx::Transform(
+      standingTransform[0], standingTransform[1], standingTransform[2],
+      standingTransform[3], standingTransform[4], standingTransform[5],
+      standingTransform[6], standingTransform[7], standingTransform[8],
+      standingTransform[9], standingTransform[10], standingTransform[11],
+      standingTransform[12], standingTransform[13], standingTransform[14],
+      standingTransform[15]);
+  if (!transform.IsInvertible() || transform.HasPerspective())
+    return false;
+
+  gfx::DecomposedTransform decomp;
+  if (!DecomposeTransform(&decomp, transform))
+    return false;
+
+  float kEpsilon = 0.1f;
+  float kMaxTranslate = 1000000;  // Maximum 1000km translation.
+  if (abs(decomp.perspective[3] - 1) > kEpsilon) {
+    // If testing with unexpectedly high values, catch on debug builds rather
+    // than silently change data.  On release builds its better to be safe and
+    // validate.
+    DCHECK(false);
+    return false;
+  }
+  for (int i = 0; i < 3; ++i) {
+    if (abs(decomp.scale[i] - 1) > kEpsilon)
+      return false;
+    if (abs(decomp.skew[i]) > kEpsilon)
+      return false;
+    if (abs(decomp.perspective[i]) > kEpsilon)
+      return false;
+    if (abs(decomp.translate[i]) > kMaxTranslate)
+      return false;
+  }
+
+  // Only rotate and translate.
+  return true;
+}
+
+device::mojom::VREyeParametersPtr ValidateEyeParameters(
+    device::mojom::VREyeParametersPtr& eye) {
+  if (!eye)
+    return nullptr;
+  device::mojom::VREyeParametersPtr ret = device::mojom::VREyeParameters::New();
+  // FOV
+  float kDefaultFOV = 45;
+  ret->fieldOfView = device::mojom::VRFieldOfView::New();
+  if (eye->fieldOfView->upDegrees < 90 && eye->fieldOfView->upDegrees > -90 &&
+      eye->fieldOfView->upDegrees > -eye->fieldOfView->downDegrees &&
+      eye->fieldOfView->downDegrees < 90 &&
+      eye->fieldOfView->downDegrees > -90 &&
+      eye->fieldOfView->downDegrees > -eye->fieldOfView->upDegrees &&
+      eye->fieldOfView->leftDegrees < 90 &&
+      eye->fieldOfView->leftDegrees > -90 &&
+      eye->fieldOfView->leftDegrees > -eye->fieldOfView->rightDegrees &&
+      eye->fieldOfView->rightDegrees < 90 &&
+      eye->fieldOfView->rightDegrees > -90 &&
+      eye->fieldOfView->rightDegrees > -eye->fieldOfView->leftDegrees) {
+    ret->fieldOfView->upDegrees = eye->fieldOfView->upDegrees;
+    ret->fieldOfView->downDegrees = eye->fieldOfView->downDegrees;
+    ret->fieldOfView->leftDegrees = eye->fieldOfView->leftDegrees;
+    ret->fieldOfView->rightDegrees = eye->fieldOfView->rightDegrees;
+  } else {
+    ret->fieldOfView->upDegrees = kDefaultFOV;
+    ret->fieldOfView->downDegrees = kDefaultFOV;
+    ret->fieldOfView->leftDegrees = kDefaultFOV;
+    ret->fieldOfView->rightDegrees = kDefaultFOV;
+  }
+
+  // Offset
+  float kMaxOffset = 10;
+  if (eye->offset.size() == 3 && abs(eye->offset[0]) < kMaxOffset &&
+      abs(eye->offset[1]) < kMaxOffset && abs(eye->offset[2]) < kMaxOffset) {
+    ret->offset = eye->offset;
+  } else {
+    ret->offset = std::vector<float>({0, 0, 0});
+  }
+
+  // Renderwidth/height
+  uint32_t kMaxSize = 16384;
+  uint32_t kMinSize = 2;
+  // DCHECK on debug builds to catch legitimate large sizes, but clamp on
+  // release builds to ensure valid state.
+  DCHECK(eye->renderWidth < kMaxSize);
+  DCHECK(eye->renderHeight < kMaxSize);
+  ret->renderWidth = std::max(std::min(kMaxSize, eye->renderWidth), kMinSize);
+  ret->renderHeight = std::max(std::min(kMaxSize, eye->renderHeight), kMinSize);
+  return ret;
+}
+
+device::mojom::VRDisplayInfoPtr ValidateVRDisplayInfo(
+    device::mojom::VRDisplayInfoPtr& info,
+    device::mojom::XRDeviceId id) {
+  if (!info)
+    return nullptr;
+
+  device::mojom::VRDisplayInfoPtr ret = device::mojom::VRDisplayInfo::New();
+
+  // Rather than just cloning everything, we copy over each field and validate
+  // individually.  This ensures new fields don't bypass validation.
+  ret->id = id;
+  ret->displayName = info->displayName;
+  DCHECK(info->capabilities);  // Ensured by mojo.
+  ret->capabilities = device::mojom::VRDisplayCapabilities::New(
+      info->capabilities->hasPosition, info->capabilities->hasExternalDisplay,
+      info->capabilities->canPresent,
+      info->capabilities->canProvideEnvironmentIntegration);
+
+  if (info->stageParameters &&
+      IsValidStandingTransform(info->stageParameters->standingTransform)) {
+    ret->stageParameters = device::mojom::VRStageParameters::New(
+        info->stageParameters->standingTransform, info->stageParameters->sizeX,
+        info->stageParameters->sizeZ);
+  }
+
+  ret->leftEye = ValidateEyeParameters(info->leftEye);
+  ret->rightEye = ValidateEyeParameters(info->rightEye);
+
+  float kMinFramebufferScale = 0.1f;
+  float kMaxFramebufferScale = 1.0f;
+  if (info->webvr_default_framebuffer_scale <= kMaxFramebufferScale &&
+      info->webvr_default_framebuffer_scale >= kMinFramebufferScale) {
+    ret->webvr_default_framebuffer_scale =
+        info->webvr_default_framebuffer_scale;
+  } else {
+    ret->webvr_default_framebuffer_scale = 1;
+  }
+
+  if (info->webxr_default_framebuffer_scale <= kMaxFramebufferScale &&
+      info->webxr_default_framebuffer_scale >= kMinFramebufferScale) {
+    ret->webxr_default_framebuffer_scale =
+        info->webxr_default_framebuffer_scale;
+  } else {
+    ret->webxr_default_framebuffer_scale = 1;
+  }
+  return ret;
+}
+
 BrowserXRRuntime::BrowserXRRuntime(device::mojom::XRDeviceId id,
                                    device::mojom::XRRuntimePtr runtime,
                                    device::mojom::VRDisplayInfoPtr display_info)
     : id_(id),
       runtime_(std::move(runtime)),
-      display_info_(std::move(display_info)),
+      display_info_(ValidateVRDisplayInfo(display_info, id)),
       binding_(this),
       weak_ptr_factory_(this) {
   device::mojom::XRRuntimeEventListenerAssociatedPtr listener;
@@ -44,7 +186,7 @@
 void BrowserXRRuntime::OnDisplayInfoChanged(
     device::mojom::VRDisplayInfoPtr vr_device_info) {
   bool had_display_info = !!display_info_;
-  display_info_ = std::move(vr_device_info);
+  display_info_ = ValidateVRDisplayInfo(vr_device_info, id_);
   if (had_display_info) {
     for (XRDeviceImpl* device : renderer_device_connections_) {
       device->RuntimesChanged();
diff --git a/chrome/browser/vr/ui_host/vr_ui_host_impl.cc b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc
index 9086d5d0..b52a7530 100644
--- a/chrome/browser/vr/ui_host/vr_ui_host_impl.cc
+++ b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc
@@ -82,9 +82,25 @@
   return std::make_unique<VRUiHostImpl>(device_id, std::move(compositor));
 }
 
+bool IsValidInfo(device::mojom::VRDisplayInfoPtr& info) {
+  // Numeric properties are validated elsewhere, but we expect a stereo headset.
+  if (!info)
+    return false;
+  if (!info->leftEye)
+    return false;
+  if (!info->rightEye)
+    return false;
+  return true;
+}
+
 void VRUiHostImpl::SetWebXRWebContents(content::WebContents* contents) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
+  if (!IsValidInfo(info_)) {
+    XRRuntimeManager::ExitImmersivePresentation();
+    return;
+  }
+
   // Eventually the contents will be used to poll for permissions, or determine
   // what overlays should show.
 
@@ -165,6 +181,11 @@
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DVLOG(1) << __func__;
 
+  if (!IsValidInfo(display_info)) {
+    XRRuntimeManager::ExitImmersivePresentation();
+    return;
+  }
+
   info_ = std::move(display_info);
   if (ui_rendering_thread_) {
     ui_rendering_thread_->SetVRDisplayInfo(info_.Clone());
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc
index 58329c02c..fd69a8b 100644
--- a/chrome/browser/vr/ui_scene_creator.cc
+++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -1613,20 +1613,13 @@
                                  (model->web_vr.external_prompt_notification !=
                                   ExternalPromptNotificationType::kPromptNone));
 
-  scaler->AddBinding(std::make_unique<
-                     Binding<std::tuple<ExternalPromptNotificationType, GURL>>>(
+  scaler->AddBinding(std::make_unique<Binding<ExternalPromptNotificationType>>(
       VR_BIND_LAMBDA(
-          [](Model* m) {
-            return std::tuple<ExternalPromptNotificationType, GURL>(
-                m->web_vr.external_prompt_notification,
-                m->location_bar_state.gurl);
-          },
+          [](Model* m) { return m->web_vr.external_prompt_notification; },
           base::Unretained(model_)),
       VR_BIND_LAMBDA(
           [](Text* text_element, VectorIcon* icon_element,
-             const std::tuple<ExternalPromptNotificationType, GURL>&
-                 prompt_data) {
-            ExternalPromptNotificationType prompt = std::get<0>(prompt_data);
+             const ExternalPromptNotificationType& prompt) {
             if (prompt == ExternalPromptNotificationType::kPromptNone)
               return;
 
@@ -1641,14 +1634,7 @@
                 NOTREACHED();
             }
 
-            const GURL& gurl = std::get<1>(prompt_data);
-            base::string16 url_text =
-                url_formatter::FormatUrlForSecurityDisplay(
-                    gurl.GetOrigin(),
-                    url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
-
-            text_element->SetText(
-                l10n_util::GetStringFUTF16(message_id, url_text));
+            text_element->SetText(l10n_util::GetStringUTF16(message_id));
             icon_element->SetIcon(icon);
           },
           base::Unretained(line1_text), base::Unretained(vector_icon))));
diff --git a/chrome/browser/vr/win/vr_browser_renderer_thread_win.cc b/chrome/browser/vr/win/vr_browser_renderer_thread_win.cc
index 1501421e..fcd22738 100644
--- a/chrome/browser/vr/win/vr_browser_renderer_thread_win.cc
+++ b/chrome/browser/vr/win/vr_browser_renderer_thread_win.cc
@@ -331,12 +331,69 @@
   StopWebXrTimeout();
 }
 
+device::mojom::XRFrameDataPtr ValidateFrameData(
+    device::mojom::XRFrameDataPtr& data) {
+  device::mojom::XRFrameDataPtr ret = device::mojom::XRFrameData::New();
+  ret->pose = device::mojom::VRPose::New();
+
+  if (data->pose) {
+    if (data->pose->orientation && data->pose->orientation->size() == 4) {
+      float length = 0;
+      for (int i = 0; i < 4; ++i) {
+        length += (*data->pose->orientation)[i] * (*data->pose->orientation)[i];
+      }
+
+      float kEpsilson = 0.1f;
+      if (abs(length - 1) < kEpsilson) {
+        ret->pose->orientation = std::vector<float>{0, 0, 0, 1};
+        for (int i = 0; i < 4; ++i) {
+          (*ret->pose->orientation)[i] = (*data->pose->orientation)[i] / length;
+        }
+      }
+    }
+
+    if (data->pose->position && data->pose->position->size() == 3) {
+      ret->pose->position = data->pose->position;
+      // We'll never give position values outside this range.
+      float kMaxPosition = 1000000;
+      float kMinPosition = -kMaxPosition;
+      for (int i = 0; i < 3; ++i) {
+        if (!((*ret->pose->position)[i] < kMaxPosition) ||
+            !((*ret->pose->position)[i] > kMinPosition)) {
+          ret->pose->position = base::nullopt;
+          // If testing with unexpectedly high values, catch on debug builds
+          // rather than silently change data.  On release builds its better to
+          // be safe and validate.
+          DCHECK(false);
+          break;
+        }
+      }
+    }
+
+    if (!ret->pose->orientation) {
+      ret->pose->orientation = std::vector<float>{0, 0, 0, 1};
+    }
+
+    if (!ret->pose->position) {
+      ret->pose->position = std::vector<float>{0, 0, 0};
+    }
+
+    ret->frame_id = data->frame_id;
+
+    // Frame data has several other fields that we are ignoring.  If they are
+    // used, validate them before use.
+  }
+
+  return ret;
+}
+
 void VRBrowserRendererThreadWin::OnPose(int request_id,
                                         device::mojom::XRFrameDataPtr data) {
   if (request_id != current_request_id_) {
     // Old request. Do nothing.
     return;
   }
+
   if (!draw_state_.ShouldDrawUI()) {
     // We shouldn't be showing UI.
     overlay_->SetOverlayAndWebXRVisibility(draw_state_.ShouldDrawUI(),
@@ -346,13 +403,15 @@
     return;
   }
 
+  data = ValidateFrameData(data);
+
   // Deliver pose to input and scheduler.
-  std::vector<float> quat = {0, 0, 0, 1};
-  if (data && data->pose && data->pose->orientation)
-    quat = *data->pose->orientation;
-  std::vector<float> pos = {0, 0, 0};
-  if (data && data->pose && data->pose->position)
-    pos = *data->pose->position;
+  DCHECK(data);
+  DCHECK(data->pose);
+  DCHECK(data->pose->orientation);
+  DCHECK(data->pose->position);
+  const std::vector<float>& quat = *data->pose->orientation;
+  const std::vector<float>& pos = *data->pose->position;
 
   // The incoming pose represents where the headset is in "world space".  So
   // we'll need to invert to get the view transform.
diff --git a/chrome/browser/web_applications/bookmark_apps/BUILD.gn b/chrome/browser/web_applications/bookmark_apps/BUILD.gn
index 25842d9..10403c2 100644
--- a/chrome/browser/web_applications/bookmark_apps/BUILD.gn
+++ b/chrome/browser/web_applications/bookmark_apps/BUILD.gn
@@ -20,6 +20,7 @@
     "//chrome/common",
     "//components/favicon/content",
     "//components/pref_registry",
+    "//extensions/browser",
     "//skia",
   ]
 }
diff --git a/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.cc b/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.cc
index c51d98c..dcdf673 100644
--- a/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.cc
+++ b/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.cc
@@ -10,8 +10,10 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/scoped_observer.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/extensions/bookmark_app_helper.h"
+#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/tab_helper.h"
 #include "chrome/browser/installable/installable_metrics.h"
 #include "chrome/browser/profiles/profile.h"
@@ -23,6 +25,7 @@
 #include "chrome/common/web_application_info.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
 
 namespace extensions {
@@ -368,6 +371,50 @@
                      std::move(install_task), install_options));
 }
 
+void BookmarkAppInstallManager::InstallOrUpdateWebAppFromSync(
+    const web_app::AppId& app_id,
+    std::unique_ptr<WebApplicationInfo> web_application_info,
+    OnceInstallCallback callback) {
+  // |callback| is ignored here: the legacy system doesn't report completion.
+  ExtensionService* extension_service =
+      ExtensionSystem::Get(profile_)->extension_service();
+  DCHECK(extension_service);
+
+  const Extension* extension = extension_service->GetInstalledExtension(app_id);
+
+  // Return if there are no bookmark app details that need updating.
+  const std::string extension_sync_data_name =
+      base::UTF16ToUTF8(web_application_info->title);
+  const std::string bookmark_app_description =
+      base::UTF16ToUTF8(web_application_info->description);
+  if (extension &&
+      extension->non_localized_name() == extension_sync_data_name &&
+      extension->description() == bookmark_app_description) {
+    return;
+  }
+
+#if defined(OS_CHROMEOS)
+  const bool is_locally_installed = true;
+#else
+  const bool is_locally_installed = extension != nullptr;
+#endif
+
+  CreateOrUpdateBookmarkApp(extension_service, web_application_info.get(),
+                            is_locally_installed);
+}
+
+void BookmarkAppInstallManager::InstallWebAppForTesting(
+    std::unique_ptr<WebApplicationInfo> web_application_info,
+    OnceInstallCallback callback) {
+  // |callback| is ignored here: the legacy system doesn't report completion.
+  ExtensionService* extension_service =
+      ExtensionSystem::Get(profile_)->extension_service();
+  DCHECK(extension_service);
+
+  CreateOrUpdateBookmarkApp(extension_service, web_application_info.get(),
+                            true /*is_locally_installed*/);
+}
+
 void BookmarkAppInstallManager::SetBookmarkAppHelperFactoryForTesting(
     BookmarkAppHelperFactory bookmark_app_helper_factory) {
   bookmark_app_helper_factory_ = std::move(bookmark_app_helper_factory);
diff --git a/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.h b/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.h
index 518a5af..3f20e72 100644
--- a/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.h
+++ b/chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.h
@@ -53,6 +53,13 @@
   void InstallWebAppWithOptions(content::WebContents* web_contents,
                                 const web_app::InstallOptions& install_options,
                                 OnceInstallCallback callback) override;
+  void InstallOrUpdateWebAppFromSync(
+      const web_app::AppId& app_id,
+      std::unique_ptr<WebApplicationInfo> web_application_info,
+      OnceInstallCallback callback) override;
+  void InstallWebAppForTesting(
+      std::unique_ptr<WebApplicationInfo> web_application_info,
+      OnceInstallCallback callback) override;
 
   using BookmarkAppHelperFactory =
       base::RepeatingCallback<std::unique_ptr<BookmarkAppHelper>(
diff --git a/chrome/browser/web_applications/components/install_manager.h b/chrome/browser/web_applications/components/install_manager.h
index ba7bb18d..dfdd639d 100644
--- a/chrome/browser/web_applications/components/install_manager.h
+++ b/chrome/browser/web_applications/components/install_manager.h
@@ -82,6 +82,20 @@
                                         const InstallOptions& install_options,
                                         OnceInstallCallback callback) = 0;
 
+  // Starts background installation or an update of a web app from the sync
+  // system. |web_application_info| contains received sync data. Icons will be
+  // downloaded from the icon URLs provided in |web_application_info|.
+  virtual void InstallOrUpdateWebAppFromSync(
+      const AppId& app_id,
+      std::unique_ptr<WebApplicationInfo> web_application_info,
+      OnceInstallCallback callback) = 0;
+
+  // Starts background installation of a web app from the given
+  // |web_application_info|.
+  virtual void InstallWebAppForTesting(
+      std::unique_ptr<WebApplicationInfo> web_application_info,
+      OnceInstallCallback callback) = 0;
+
   InstallManager();
   virtual ~InstallManager();
 
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.cc b/chrome/browser/web_applications/components/web_app_install_utils.cc
index 39230d6..12ef100 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/components/web_app_install_utils.cc
@@ -53,15 +53,8 @@
   if (manifest.start_url.is_valid())
     web_app_info->app_url = manifest.start_url;
 
-  if (for_installable_site == ForInstallableSite::kYes) {
-    // If there is no scope present, use 'start_url' without the filename as the
-    // scope. This does not match the spec but it matches what we do on Android.
-    // See: https://github.com/w3c/manifest/issues/550
-    if (!manifest.scope.is_empty())
-      web_app_info->scope = manifest.scope;
-    else if (manifest.start_url.is_valid())
-      web_app_info->scope = manifest.start_url.Resolve(".");
-  }
+  if (for_installable_site == ForInstallableSite::kYes)
+    web_app_info->scope = manifest.scope;
 
   if (manifest.theme_color)
     web_app_info->theme_color = *manifest.theme_color;
diff --git a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
index 5b3af0b..bf68681 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
+++ b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
@@ -74,6 +74,7 @@
   {
     blink::Manifest manifest;
     manifest.start_url = GURL(kAppUrl);
+    manifest.scope = GURL(kAppUrl).GetWithoutFilename();
     WebApplicationInfo web_app_info;
     UpdateWebAppInfoFromManifest(manifest, &web_app_info,
                                  ForInstallableSite::kUnknown);
@@ -83,6 +84,7 @@
   {
     blink::Manifest manifest;
     manifest.start_url = GURL(kAppUrl);
+    manifest.scope = GURL(kAppUrl).GetWithoutFilename();
     WebApplicationInfo web_app_info;
     UpdateWebAppInfoFromManifest(manifest, &web_app_info,
                                  ForInstallableSite::kNo);
@@ -92,6 +94,7 @@
   {
     blink::Manifest manifest;
     manifest.start_url = GURL(kAppUrl);
+    manifest.scope = GURL(kAppUrl).GetWithoutFilename();
     WebApplicationInfo web_app_info;
     UpdateWebAppInfoFromManifest(manifest, &web_app_info,
                                  ForInstallableSite::kYes);
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc
index 5702d56c..cb9d770 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc
@@ -44,11 +44,11 @@
 
 BookmarkAppInstallationTask::BookmarkAppInstallationTask(
     Profile* profile,
-    std::unique_ptr<web_app::InstallFinalizer> install_finalizer,
+    web_app::InstallFinalizer* install_finalizer,
     web_app::InstallOptions install_options)
     : profile_(profile),
+      install_finalizer_(install_finalizer),
       extension_ids_map_(profile_->GetPrefs()),
-      install_finalizer_(std::move(install_finalizer)),
       install_options_(std::move(install_options)) {}
 
 BookmarkAppInstallationTask::~BookmarkAppInstallationTask() = default;
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.h b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.h
index 0afc9f1..b67fa476 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.h
+++ b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.h
@@ -57,7 +57,7 @@
   // policy, etc.
   explicit BookmarkAppInstallationTask(
       Profile* profile,
-      std::unique_ptr<web_app::InstallFinalizer> install_finalizer,
+      web_app::InstallFinalizer* install_finalizer,
       web_app::InstallOptions install_options);
 
   virtual ~BookmarkAppInstallationTask();
@@ -76,11 +76,10 @@
                          web_app::InstallResultCode code);
 
   Profile* profile_;
+  web_app::InstallFinalizer* install_finalizer_;
 
   web_app::ExtensionIdsMap extension_ids_map_;
 
-  std::unique_ptr<web_app::InstallFinalizer> install_finalizer_;
-
   const web_app::InstallOptions install_options_;
 
   base::WeakPtrFactory<BookmarkAppInstallationTask> weak_ptr_factory_{this};
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc
index dd2c164..95039b5f 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc
@@ -121,6 +121,8 @@
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
 
+    install_finalizer_ = std::make_unique<web_app::TestInstallFinalizer>();
+
     // CrxInstaller in BookmarkAppInstaller needs an ExtensionService, so
     // create one for the profile.
     TestExtensionSystem* test_system =
@@ -139,6 +141,10 @@
     return *test_helper_;
   }
 
+  web_app::TestInstallFinalizer* install_finalizer() {
+    return install_finalizer_.get();
+  }
+
  private:
   void SetUpTestingFactories() {
     auto* provider = web_app::WebAppProviderBase::GetProviderBase(profile());
@@ -170,6 +176,7 @@
         }));
   }
 
+  std::unique_ptr<web_app::TestInstallFinalizer> install_finalizer_;
   TestBookmarkAppHelper* test_helper_ = nullptr;
   GURL app_url_{kWebAppUrl};
 
@@ -179,7 +186,7 @@
 TEST_F(BookmarkAppInstallationTaskTest,
        WebAppOrShortcutFromContents_InstallationSucceeds) {
   auto task = std::make_unique<BookmarkAppInstallationTask>(
-      profile(), std::make_unique<web_app::TestInstallFinalizer>(),
+      profile(), install_finalizer(),
       web_app::InstallOptions(app_url(), web_app::LaunchContainer::kDefault,
                               web_app::InstallSource::kInternal));
 
@@ -222,7 +229,7 @@
 TEST_F(BookmarkAppInstallationTaskTest,
        WebAppOrShortcutFromContents_InstallationFails) {
   auto task = std::make_unique<BookmarkAppInstallationTask>(
-      profile(), std::make_unique<web_app::TestInstallFinalizer>(),
+      profile(), install_finalizer(),
       web_app::InstallOptions(app_url(), web_app::LaunchContainer::kWindow,
                               web_app::InstallSource::kInternal));
 
@@ -260,8 +267,7 @@
                                           web_app::InstallSource::kInternal);
   install_options.add_to_desktop = false;
   auto task = std::make_unique<BookmarkAppInstallationTask>(
-      profile(), std::make_unique<web_app::TestInstallFinalizer>(),
-      std::move(install_options));
+      profile(), install_finalizer(), std::move(install_options));
 
   bool callback_called = false;
   task->Install(web_contents(),
@@ -290,8 +296,7 @@
                                           web_app::InstallSource::kInternal);
   install_options.add_to_quick_launch_bar = false;
   auto task = std::make_unique<BookmarkAppInstallationTask>(
-      profile(), std::make_unique<web_app::TestInstallFinalizer>(),
-      std::move(install_options));
+      profile(), install_finalizer(), std::move(install_options));
 
   bool callback_called = false;
   task->Install(web_contents(),
@@ -323,8 +328,7 @@
   install_options.add_to_desktop = false;
   install_options.add_to_quick_launch_bar = false;
   auto task = std::make_unique<BookmarkAppInstallationTask>(
-      profile(), std::make_unique<web_app::TestInstallFinalizer>(),
-      std::move(install_options));
+      profile(), install_finalizer(), std::move(install_options));
 
   bool callback_called = false;
   task->Install(web_contents(),
@@ -353,8 +357,7 @@
       web_app::InstallOptions(app_url(), web_app::LaunchContainer::kWindow,
                               web_app::InstallSource::kInternal);
   auto task = std::make_unique<BookmarkAppInstallationTask>(
-      profile(), std::make_unique<web_app::TestInstallFinalizer>(),
-      std::move(install_options));
+      profile(), install_finalizer(), std::move(install_options));
 
   bool callback_called = false;
   task->Install(web_contents(),
@@ -381,8 +384,7 @@
       web_app::InstallOptions(app_url(), web_app::LaunchContainer::kTab,
                               web_app::InstallSource::kInternal);
   auto task = std::make_unique<BookmarkAppInstallationTask>(
-      profile(), std::make_unique<web_app::TestInstallFinalizer>(),
-      std::move(install_options));
+      profile(), install_finalizer(), std::move(install_options));
 
   bool callback_called = false;
   task->Install(web_contents(),
@@ -409,8 +411,7 @@
       web_app::InstallOptions(app_url(), web_app::LaunchContainer::kDefault,
                               web_app::InstallSource::kInternal);
   auto task = std::make_unique<BookmarkAppInstallationTask>(
-      profile(), std::make_unique<web_app::TestInstallFinalizer>(),
-      std::move(install_options));
+      profile(), install_finalizer(), std::move(install_options));
 
   bool callback_called = false;
   task->Install(web_contents(),
@@ -436,8 +437,7 @@
       web_app::InstallOptions(app_url(), web_app::LaunchContainer::kDefault,
                               web_app::InstallSource::kExternalPolicy);
   auto task = std::make_unique<BookmarkAppInstallationTask>(
-      profile(), std::make_unique<web_app::TestInstallFinalizer>(),
-      std::move(install_options));
+      profile(), install_finalizer(), std::move(install_options));
 
   bool callback_called = false;
   task->Install(web_contents(),
@@ -460,11 +460,8 @@
 TEST_F(BookmarkAppInstallationTaskTest, InstallPlaceholder) {
   web_app::InstallOptions options(app_url(), web_app::LaunchContainer::kWindow,
                                   web_app::InstallSource::kExternalPolicy);
-  auto finalizer = std::make_unique<web_app::TestInstallFinalizer>();
-  auto* finalizer_ptr = finalizer.get();
-
   auto task = std::make_unique<BookmarkAppInstallationTask>(
-      profile(), std::move(finalizer), std::move(options));
+      profile(), install_finalizer(), std::move(options));
 
   base::RunLoop run_loop;
   task->InstallPlaceholder(base::BindLambdaForTesting(
@@ -474,9 +471,9 @@
 
         EXPECT_TRUE(IsPlaceholderApp(profile(), app_url()));
 
-        EXPECT_TRUE(finalizer_ptr->finalized_policy_install());
+        EXPECT_TRUE(install_finalizer()->finalized_policy_install());
         std::unique_ptr<WebApplicationInfo> web_app_info =
-            finalizer_ptr->web_app_info();
+            install_finalizer()->web_app_info();
 
         EXPECT_EQ(base::UTF8ToUTF16(app_url().spec()), web_app_info->title);
         EXPECT_EQ(app_url(), web_app_info->app_url);
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc b/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc
index d8af4a37..33e73ce 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc
@@ -6,13 +6,13 @@
 
 #include <utility>
 
+#include "base/one_shot_event.h"
 #include "chrome/browser/extensions/convert_web_app.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/common/one_shot_event.h"
 
 namespace extensions {
 
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc
index 2e89b08..011f099 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc
@@ -23,10 +23,10 @@
 
 std::unique_ptr<BookmarkAppInstallationTask> InstallationTaskCreateWrapper(
     Profile* profile,
+    web_app::InstallFinalizer* install_finalizer,
     web_app::InstallOptions install_options) {
   return std::make_unique<BookmarkAppInstallationTask>(
-      profile, std::make_unique<BookmarkAppInstallFinalizer>(profile),
-      std::move(install_options));
+      profile, install_finalizer, std::move(install_options));
 }
 
 }  // namespace
@@ -43,9 +43,11 @@
 
 PendingBookmarkAppManager::PendingBookmarkAppManager(
     Profile* profile,
-    web_app::AppRegistrar* registrar)
+    web_app::AppRegistrar* registrar,
+    web_app::InstallFinalizer* install_finalizer)
     : profile_(profile),
       registrar_(registrar),
+      install_finalizer_(install_finalizer),
       uninstaller_(
           std::make_unique<BookmarkAppUninstaller>(profile_, registrar_)),
       extension_ids_map_(profile->GetPrefs()),
@@ -57,7 +59,8 @@
 void PendingBookmarkAppManager::Install(web_app::InstallOptions install_options,
                                         OnceInstallCallback callback) {
   pending_tasks_and_callbacks_.push_front(std::make_unique<TaskAndCallback>(
-      task_factory_.Run(profile_, std::move(install_options)),
+      task_factory_.Run(profile_, install_finalizer_,
+                        std::move(install_options)),
       std::move(callback)));
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -71,7 +74,9 @@
     const RepeatingInstallCallback& callback) {
   for (auto& install_options : install_options_list) {
     pending_tasks_and_callbacks_.push_back(std::make_unique<TaskAndCallback>(
-        task_factory_.Run(profile_, std::move(install_options)), callback));
+        task_factory_.Run(profile_, install_finalizer_,
+                          std::move(install_options)),
+        callback));
   }
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h
index 9fe29b2..614309fa 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h
@@ -30,6 +30,7 @@
 
 namespace web_app {
 class AppRegistrar;
+class InstallFinalizer;
 }  // namespace web_app
 
 namespace extensions {
@@ -43,11 +44,16 @@
  public:
   using WebContentsFactory =
       base::RepeatingCallback<std::unique_ptr<content::WebContents>(Profile*)>;
-  using TaskFactory = base::RepeatingCallback<std::unique_ptr<
-      BookmarkAppInstallationTask>(Profile*, web_app::InstallOptions)>;
+  using TaskFactory =
+      base::RepeatingCallback<std::unique_ptr<BookmarkAppInstallationTask>(
+          Profile*,
+          web_app::InstallFinalizer*,
+          web_app::InstallOptions)>;
 
-  explicit PendingBookmarkAppManager(Profile* profile,
-                                     web_app::AppRegistrar* registrar_);
+  explicit PendingBookmarkAppManager(
+      Profile* profile,
+      web_app::AppRegistrar* registrar,
+      web_app::InstallFinalizer* install_finalizer);
   ~PendingBookmarkAppManager() override;
 
   // web_app::PendingAppManager
@@ -84,6 +90,7 @@
 
   Profile* profile_;
   web_app::AppRegistrar* registrar_;
+  web_app::InstallFinalizer* install_finalizer_;
   std::unique_ptr<BookmarkAppUninstaller> uninstaller_;
   web_app::ExtensionIdsMap extension_ids_map_;
 
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
index 20beee4..cbaf4a1 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/test/bind_test_util.h"
 #include "base/timer/mock_timer.h"
 #include "chrome/browser/web_applications/components/app_registrar.h"
+#include "chrome/browser/web_applications/components/install_finalizer.h"
 #include "chrome/browser/web_applications/components/pending_app_manager.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/browser/web_applications/extensions/bookmark_app_installation_task.h"
@@ -77,12 +78,12 @@
  public:
   TestBookmarkAppInstallationTask(Profile* profile,
                                   web_app::TestAppRegistrar* registrar,
+                                  web_app::InstallFinalizer* install_finalizer,
                                   web_app::InstallOptions install_options,
                                   bool succeeds)
-      : BookmarkAppInstallationTask(
-            profile,
-            std::make_unique<web_app::TestInstallFinalizer>(),
-            std::move(install_options)),
+      : BookmarkAppInstallationTask(profile,
+                                    install_finalizer,
+                                    std::move(install_options)),
         profile_(profile),
         registrar_(registrar),
         succeeds_(succeeds),
@@ -198,6 +199,7 @@
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
     registrar_ = std::make_unique<web_app::TestAppRegistrar>();
+    install_finalizer_ = std::make_unique<web_app::TestInstallFinalizer>();
   }
 
   void TearDown() override {
@@ -207,10 +209,12 @@
 
   std::unique_ptr<BookmarkAppInstallationTask> CreateInstallationTask(
       Profile* profile,
+      web_app::InstallFinalizer* install_finalizer,
       web_app::InstallOptions install_options,
       bool succeeds) {
     auto task = std::make_unique<TestBookmarkAppInstallationTask>(
-        profile, registrar_.get(), std::move(install_options), succeeds);
+        profile, registrar_.get(), install_finalizer,
+        std::move(install_options), succeeds);
     auto* task_ptr = task.get();
     task->SetOnInstallCalled(base::BindLambdaForTesting([this, task_ptr]() {
       ++install_run_count_;
@@ -227,15 +231,19 @@
 
   std::unique_ptr<BookmarkAppInstallationTask> CreateSuccessfulInstallationTask(
       Profile* profile,
+      web_app::InstallFinalizer* install_finalizer,
       web_app::InstallOptions install_options) {
-    return CreateInstallationTask(profile, std::move(install_options),
+    return CreateInstallationTask(profile, install_finalizer,
+                                  std::move(install_options),
                                   true /* succeeds */);
   }
 
   std::unique_ptr<BookmarkAppInstallationTask> CreateFailingInstallationTask(
       Profile* profile,
+      web_app::InstallFinalizer* install_finalizer,
       web_app::InstallOptions install_options) {
-    return CreateInstallationTask(profile, std::move(install_options),
+    return CreateInstallationTask(profile, install_finalizer,
+                                  std::move(install_options),
                                   false /* succeeds */);
   }
 
@@ -314,7 +322,7 @@
   std::unique_ptr<PendingBookmarkAppManager>
   GetPendingBookmarkAppManagerWithTestFactories() {
     auto manager = std::make_unique<PendingBookmarkAppManager>(
-        profile(), registrar_.get());
+        profile(), registrar_.get(), install_finalizer_.get());
     manager->SetTaskFactoryForTesting(successful_installation_task_creator());
 
     // The test suite doesn't support multiple uninstallers.
@@ -375,6 +383,8 @@
   PendingBookmarkAppManager::TaskFactory failing_installation_task_creator_;
 
   std::unique_ptr<web_app::TestAppRegistrar> registrar_;
+  std::unique_ptr<web_app::TestInstallFinalizer> install_finalizer_;
+
   TestBookmarkAppUninstaller* uninstaller_ = nullptr;
   web_app::TestWebAppUrlLoader* url_loader_ = nullptr;
 
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc
index 6ecb9df..352b5a5 100644
--- a/chrome/browser/web_applications/web_app_install_manager.cc
+++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -23,11 +23,10 @@
 
 namespace web_app {
 
-WebAppInstallManager::WebAppInstallManager(
-    Profile* profile,
-    std::unique_ptr<InstallFinalizer> install_finalizer)
+WebAppInstallManager::WebAppInstallManager(Profile* profile,
+                                           InstallFinalizer* install_finalizer)
     : data_retriever_(std::make_unique<WebAppDataRetriever>()),
-      install_finalizer_(std::move(install_finalizer)),
+      install_finalizer_(install_finalizer),
       profile_(profile) {}
 
 WebAppInstallManager::~WebAppInstallManager() = default;
@@ -91,6 +90,21 @@
   NOTIMPLEMENTED();
 }
 
+void WebAppInstallManager::InstallOrUpdateWebAppFromSync(
+    const AppId& app_id,
+    std::unique_ptr<WebApplicationInfo> web_application_info,
+    OnceInstallCallback callback) {
+  // TODO(loyso): Implement it.
+  NOTIMPLEMENTED();
+}
+
+void WebAppInstallManager::InstallWebAppForTesting(
+    std::unique_ptr<WebApplicationInfo> web_application_info,
+    OnceInstallCallback callback) {
+  // TODO(loyso): Implement it.
+  NOTIMPLEMENTED();
+}
+
 void WebAppInstallManager::WebContentsDestroyed() {
   ReturnError(InstallResultCode::kWebContentsDestroyed);
 }
@@ -101,8 +115,8 @@
 }
 
 void WebAppInstallManager::SetInstallFinalizerForTesting(
-    std::unique_ptr<InstallFinalizer> install_finalizer) {
-  install_finalizer_ = std::move(install_finalizer);
+    InstallFinalizer* install_finalizer) {
+  install_finalizer_ = install_finalizer;
 }
 
 void WebAppInstallManager::CallInstallCallback(const AppId& app_id,
diff --git a/chrome/browser/web_applications/web_app_install_manager.h b/chrome/browser/web_applications/web_app_install_manager.h
index 99d084a2..67f7282d 100644
--- a/chrome/browser/web_applications/web_app_install_manager.h
+++ b/chrome/browser/web_applications/web_app_install_manager.h
@@ -33,8 +33,7 @@
 class WebAppInstallManager final : public InstallManager,
                                    content::WebContentsObserver {
  public:
-  WebAppInstallManager(Profile* profile,
-                       std::unique_ptr<InstallFinalizer> install_finalizer);
+  WebAppInstallManager(Profile* profile, InstallFinalizer* install_finalizer);
   ~WebAppInstallManager() override;
 
   // InstallManager:
@@ -56,14 +55,20 @@
   void InstallWebAppWithOptions(content::WebContents* web_contents,
                                 const InstallOptions& install_options,
                                 OnceInstallCallback callback) override;
+  void InstallOrUpdateWebAppFromSync(
+      const AppId& app_id,
+      std::unique_ptr<WebApplicationInfo> web_application_info,
+      OnceInstallCallback callback) override;
+  void InstallWebAppForTesting(
+      std::unique_ptr<WebApplicationInfo> web_application_info,
+      OnceInstallCallback callback) override;
 
   // WebContentsObserver:
   void WebContentsDestroyed() override;
 
   void SetDataRetrieverForTesting(
       std::unique_ptr<WebAppDataRetriever> data_retriever);
-  void SetInstallFinalizerForTesting(
-      std::unique_ptr<InstallFinalizer> install_finalizer);
+  void SetInstallFinalizerForTesting(InstallFinalizer* install_finalizer);
 
  private:
   void CallInstallCallback(const AppId& app_id, InstallResultCode code);
@@ -105,7 +110,7 @@
   WebappInstallSource install_source_ = kNoInstallSource;
 
   std::unique_ptr<WebAppDataRetriever> data_retriever_;
-  std::unique_ptr<InstallFinalizer> install_finalizer_;
+  InstallFinalizer* install_finalizer_;
   Profile* profile_;
 
   base::WeakPtrFactory<WebAppInstallManager> weak_ptr_factory_{this};
diff --git a/chrome/browser/web_applications/web_app_install_manager_unittest.cc b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
index 0308cef..fe4d4fa1 100644
--- a/chrome/browser/web_applications/web_app_install_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
@@ -112,11 +112,11 @@
     icon_manager_ =
         std::make_unique<WebAppIconManager>(profile(), std::move(file_utils));
 
-    auto install_finalizer = std::make_unique<WebAppInstallFinalizer>(
+    install_finalizer_ = std::make_unique<WebAppInstallFinalizer>(
         registrar_.get(), icon_manager_.get());
 
     install_manager_ = std::make_unique<WebAppInstallManager>(
-        profile(), std::move(install_finalizer));
+        profile(), install_finalizer_.get());
   }
 
   void CreateRendererAppInfo(const GURL& url,
@@ -157,10 +157,15 @@
   }
 
   void SetInstallFinalizerForTesting() {
-    auto install_finalizer = std::make_unique<TestInstallFinalizer>();
-    install_finalizer_ = install_finalizer.get();
-    install_manager_->SetInstallFinalizerForTesting(
-        std::move(install_finalizer));
+    auto test_install_finalizer = std::make_unique<TestInstallFinalizer>();
+    test_install_finalizer_ = test_install_finalizer.get();
+    install_finalizer_ = std::move(test_install_finalizer);
+    install_manager_->SetInstallFinalizerForTesting(test_install_finalizer_);
+  }
+
+  TestInstallFinalizer& test_install_finalizer() {
+    DCHECK(test_install_finalizer_);
+    return *test_install_finalizer_;
   }
 
   void SetIconsMapToRetrieve(IconsMap icons_map) {
@@ -213,11 +218,14 @@
   std::unique_ptr<WebAppRegistrar> registrar_;
   std::unique_ptr<WebAppIconManager> icon_manager_;
   std::unique_ptr<WebAppInstallManager> install_manager_;
+  std::unique_ptr<InstallFinalizer> install_finalizer_;
 
   // Owned by install_manager_:
   TestFileUtils* file_utils_ = nullptr;
   TestDataRetriever* data_retriever_ = nullptr;
-  TestInstallFinalizer* install_finalizer_ = nullptr;
+
+ private:
+  TestInstallFinalizer* test_install_finalizer_ = nullptr;
 };
 
 TEST_F(WebAppInstallManagerTest, InstallFromWebContents) {
@@ -426,7 +434,7 @@
   InstallWebApp();
 
   std::unique_ptr<WebApplicationInfo> web_app_info =
-      install_finalizer_->web_app_info();
+      test_install_finalizer().web_app_info();
 
   // Make sure that icons have been generated for all sub sizes.
   EXPECT_TRUE(ContainsOneIconOfEachSize(*web_app_info));
@@ -455,7 +463,7 @@
   InstallWebApp();
 
   std::unique_ptr<WebApplicationInfo> web_app_info =
-      install_finalizer_->web_app_info();
+      test_install_finalizer().web_app_info();
 
   // Make sure that icons have been generated for all sizes.
   EXPECT_TRUE(ContainsOneIconOfEachSize(*web_app_info));
@@ -613,15 +621,15 @@
 
   InstallWebApp();
 
-  EXPECT_EQ(1, install_finalizer_->num_create_os_shortcuts_calls());
-  EXPECT_EQ(1, install_finalizer_->num_reparent_tab_calls());
-  EXPECT_EQ(1, install_finalizer_->num_reveal_appshim_calls());
-  EXPECT_EQ(1, install_finalizer_->num_pin_app_to_shelf_calls());
+  EXPECT_EQ(1, test_install_finalizer().num_create_os_shortcuts_calls());
+  EXPECT_EQ(1, test_install_finalizer().num_reparent_tab_calls());
+  EXPECT_EQ(1, test_install_finalizer().num_reveal_appshim_calls());
+  EXPECT_EQ(1, test_install_finalizer().num_pin_app_to_shelf_calls());
 }
 
 TEST_F(WebAppInstallManagerTest, FinalizerMethodsNotCalled) {
   PrepareTestAppInstall();
-  install_finalizer_->SetNextFinalizeInstallResult(
+  test_install_finalizer().SetNextFinalizeInstallResult(
       AppId(), InstallResultCode::kFailedUnknownReason);
 
   InstallResult result = InstallWebAppAndGetResults();
@@ -629,10 +637,10 @@
   EXPECT_TRUE(result.app_id.empty());
   EXPECT_EQ(InstallResultCode::kFailedUnknownReason, result.code);
 
-  EXPECT_EQ(0, install_finalizer_->num_create_os_shortcuts_calls());
-  EXPECT_EQ(0, install_finalizer_->num_reparent_tab_calls());
-  EXPECT_EQ(0, install_finalizer_->num_reveal_appshim_calls());
-  EXPECT_EQ(0, install_finalizer_->num_pin_app_to_shelf_calls());
+  EXPECT_EQ(0, test_install_finalizer().num_create_os_shortcuts_calls());
+  EXPECT_EQ(0, test_install_finalizer().num_reparent_tab_calls());
+  EXPECT_EQ(0, test_install_finalizer().num_reveal_appshim_calls());
+  EXPECT_EQ(0, test_install_finalizer().num_pin_app_to_shelf_calls());
 }
 
 // TODO(loyso): Convert more tests from bookmark_app_helper_unittest.cc
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc
index c5c3baa..b18c7f59 100644
--- a/chrome/browser/web_applications/web_app_provider.cc
+++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/feature_list.h"
+#include "base/one_shot_event.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
@@ -17,6 +18,7 @@
 #include "chrome/browser/web_applications/components/web_app_audio_focus_id_map.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h"
 #include "chrome/browser/web_applications/extensions/bookmark_app_registrar.h"
 #include "chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h"
 #include "chrome/browser/web_applications/extensions/bookmark_app_util.h"
@@ -38,7 +40,6 @@
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/common/one_shot_event.h"
 
 namespace web_app {
 
@@ -105,10 +106,10 @@
   icon_manager_ = std::make_unique<WebAppIconManager>(
       profile, std::make_unique<FileUtilsWrapper>());
 
-  auto install_finalizer = std::make_unique<WebAppInstallFinalizer>(
+  install_finalizer_ = std::make_unique<WebAppInstallFinalizer>(
       web_app_registrar.get(), icon_manager_.get());
-  install_manager_ = std::make_unique<WebAppInstallManager>(
-      profile, std::move(install_finalizer));
+  install_manager_ =
+      std::make_unique<WebAppInstallManager>(profile, install_finalizer_.get());
 
   registrar_ = std::move(web_app_registrar);
 }
@@ -117,12 +118,14 @@
   auto bookmark_app_registrar =
       std::make_unique<extensions::BookmarkAppRegistrar>(profile);
 
+  install_finalizer_ =
+      std::make_unique<extensions::BookmarkAppInstallFinalizer>(profile_);
   install_manager_ =
       std::make_unique<extensions::BookmarkAppInstallManager>(profile);
 
   pending_app_manager_ =
       std::make_unique<extensions::PendingBookmarkAppManager>(
-          profile, bookmark_app_registrar.get());
+          profile, bookmark_app_registrar.get(), install_finalizer_.get());
 
   web_app_policy_manager_ = std::make_unique<WebAppPolicyManager>(
       profile, pending_app_manager_.get());
@@ -225,6 +228,7 @@
   pending_app_manager_.reset();
 
   install_manager_.reset();
+  install_finalizer_.reset();
   icon_manager_.reset();
   registrar_.reset();
   database_.reset();
diff --git a/chrome/browser/web_applications/web_app_provider.h b/chrome/browser/web_applications/web_app_provider.h
index a7a6bce..1d452d4 100644
--- a/chrome/browser/web_applications/web_app_provider.h
+++ b/chrome/browser/web_applications/web_app_provider.h
@@ -33,6 +33,7 @@
 // Forward declarations of generalized interfaces.
 class PendingAppManager;
 class InstallManager;
+class InstallFinalizer;
 class WebAppAudioFocusIdMap;
 class WebAppTabHelperBase;
 class SystemWebAppManager;
@@ -83,7 +84,7 @@
                const content::NotificationDetails& details) override;
 
   // Fires when app registry becomes ready.
-  // Consider to use base::ObserverList or extensions::OneShotEvent if many
+  // Consider to use base::ObserverList or base::OneShotEvent if many
   // subscribers needed.
   void SetRegistryReadyCallback(base::OnceClosure callback);
 
@@ -111,6 +112,7 @@
 
   // New generalized subsystems:
   std::unique_ptr<AppRegistrar> registrar_;
+  std::unique_ptr<InstallFinalizer> install_finalizer_;
   std::unique_ptr<InstallManager> install_manager_;
   std::unique_ptr<PendingAppManager> pending_app_manager_;
   std::unique_ptr<SystemWebAppManager> system_web_app_manager_;
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index bd7e16c..b439ca7 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -366,6 +366,12 @@
                                              base::FEATURE_DISABLED_BY_DEFAULT};
 #endif  // defined(OS_CHROMEOS)
 
+#if defined(OS_ANDROID)
+// Enables or disables the installable ambient badge infobar.
+const base::Feature kInstallableAmbientBadgeInfoBar{
+    "InstallableAmbientBadgeInfoBar", base::FEATURE_ENABLED_BY_DEFAULT};
+#endif
+
 #if !defined(OS_ANDROID)
 // Enables or disables intent picker.
 const base::Feature kIntentPicker {
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 28057d21..b2e2b17 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -232,6 +232,11 @@
 extern const base::Feature kInSessionPasswordChange;
 #endif
 
+#if defined(OS_ANDROID)
+COMPONENT_EXPORT(CHROME_FEATURES)
+extern const base::Feature kInstallableAmbientBadgeInfoBar;
+#endif  // defined(OS_ANDROID)
+
 #if !defined(OS_ANDROID)
 COMPONENT_EXPORT(CHROME_FEATURES)
 extern const base::Feature kIntentPicker;
diff --git a/chrome/common/extensions/api/accessibility_private.json b/chrome/common/extensions/api/accessibility_private.json
index 2c2af89..25f85a7 100644
--- a/chrome/common/extensions/api/accessibility_private.json
+++ b/chrome/common/extensions/api/accessibility_private.json
@@ -356,6 +356,18 @@
         "description": "Toggles dictation between active and inactive states.",
         "parameters": [],
         "platforms": ["chromeos"]
+      },
+      {
+        "name": "setVirtualKeyboardVisible",
+        "type": "function",
+        "description": "Shows or hides the virtual keyboard.",
+        "parameters": [
+          {
+            "name": "isVisible",
+            "type": "boolean"
+          }
+        ],
+        "platforms": ["chromeos"]
       }
     ],
     "events": [
diff --git a/chrome/common/page_load_metrics/page_load_metrics.mojom b/chrome/common/page_load_metrics/page_load_metrics.mojom
index 4b52793..28c63d4 100644
--- a/chrome/common/page_load_metrics/page_load_metrics.mojom
+++ b/chrome/common/page_load_metrics/page_load_metrics.mojom
@@ -231,6 +231,19 @@
   mojo_base.mojom.TimeDelta task_time;
 };
 
+// Metrics about the count of resources that were lazy loaded in the frame.
+struct DeferredResourceCounts {
+  // The count of frames that were deferred due to lazy load.
+  uint64 deferred_frames = 0;
+  // The count of frames that were loaded after being deferred due to lazy load.
+  uint64 frames_loaded_after_deferral = 0;
+
+  // The count of images that were deferred due to lazy load.
+  uint64 deferred_images = 0;
+  // The count of images that were loaded after being deferred due to lazy load.
+  uint64 images_loaded_after_deferral = 0;
+};
+
 // Sent from renderer to browser process when the PageLoadTiming for the
 // associated frame changed.
 interface PageLoadMetrics {
@@ -239,5 +252,6 @@
                PageLoadFeatures new_features,
                array<ResourceDataUpdate> resources,
                FrameRenderDataUpdate render_data,
-               CpuTiming cpu_load_timing);
+               CpuTiming cpu_load_timing,
+               DeferredResourceCounts new_deferred_resource_data);
 };
diff --git a/chrome/common/page_load_metrics/test/page_load_metrics_test_util.cc b/chrome/common/page_load_metrics/test/page_load_metrics_test_util.cc
index 7157d89..737a19fc 100644
--- a/chrome/common/page_load_metrics/test/page_load_metrics_test_util.cc
+++ b/chrome/common/page_load_metrics/test/page_load_metrics_test_util.cc
@@ -94,6 +94,7 @@
       page_load_metrics::mojom::ResourceDataUpdate::New();
   resource_data_update->was_fetched_via_cache = was_cached;
   resource_data_update->delta_bytes = delta_bytes;
+  resource_data_update->received_data_length = delta_bytes;
   resource_data_update->encoded_body_length = encoded_body_length;
   resource_data_update->is_complete = is_complete;
   return resource_data_update;
diff --git a/chrome/common/tts_messages.h b/chrome/common/tts_messages.h
index efb49f89f..5c53ebee 100644
--- a/chrome/common/tts_messages.h
+++ b/chrome/common/tts_messages.h
@@ -52,12 +52,14 @@
                      int /* utterance id */)
 IPC_MESSAGE_CONTROL1(TtsMsg_DidResumeSpeaking,
                      int /* utterance id */)
-IPC_MESSAGE_CONTROL2(TtsMsg_WordBoundary,
+IPC_MESSAGE_CONTROL3(TtsMsg_WordBoundary,
                      int /* utterance id */,
-                     int /* char index */)
-IPC_MESSAGE_CONTROL2(TtsMsg_SentenceBoundary,
+                     int /* char index */,
+                     int /* char length*/)
+IPC_MESSAGE_CONTROL3(TtsMsg_SentenceBoundary,
                      int /* utterance id */,
-                     int /* char index */)
+                     int /* char index */,
+                     int /* char length*/)
 IPC_MESSAGE_CONTROL2(TtsMsg_MarkerEvent,
                      int /* utterance id */,
                      int /* char index */)
diff --git a/chrome/credential_provider/gaiacp/auth_utils.cc b/chrome/credential_provider/gaiacp/auth_utils.cc
index eb40f26..0f450f7 100644
--- a/chrome/credential_provider/gaiacp/auth_utils.cc
+++ b/chrome/credential_provider/gaiacp/auth_utils.cc
@@ -15,6 +15,7 @@
 #include "base/stl_util.h"
 #include "chrome/credential_provider/gaiacp/gcp_utils.h"
 #include "chrome/credential_provider/gaiacp/logging.h"
+#include "chrome/credential_provider/gaiacp/os_user_manager.h"
 
 namespace credential_provider {
 
@@ -233,6 +234,74 @@
   return S_OK;
 }
 
+HRESULT UnpackUserInfoFromAuthenticationBuffer(
+    const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* cpcs,
+    base::string16* domain,
+    base::string16* username) {
+  DCHECK(cpcs);
+  DCHECK(domain);
+  DCHECK(username);
+  domain->clear();
+  username->clear();
+  KERB_INTERACTIVE_UNLOCK_LOGON* pkiul =
+      reinterpret_cast<KERB_INTERACTIVE_UNLOCK_LOGON*>(cpcs->rgbSerialization);
+  ULONG buffer_size = cpcs->cbSerialization;
+  KERB_INTERACTIVE_LOGON* pkil = &pkiul->Logon;
+
+  base::string16 serialization_domain;
+  base::string16 serialization_username;
+  // Check to see if the buffer is packed:
+  // 1. Ensure that the buffer can possibly contain the serialization.
+  // 2. Also if the range described by each (Buffer + MaximumSize) falls
+  // within the total bytecount, we can be pretty confident that the Buffers
+  // are actually offsets and that this is a packed credential.
+  if (sizeof(*pkiul) <= buffer_size &&
+      (reinterpret_cast<ptrdiff_t>(pkil->LogonDomainName.Buffer) +
+           pkil->LogonDomainName.MaximumLength <=
+       static_cast<ptrdiff_t>(buffer_size)) &&
+      (reinterpret_cast<ptrdiff_t>(pkil->UserName.Buffer) +
+           pkil->UserName.MaximumLength <=
+       static_cast<ptrdiff_t>(buffer_size)) &&
+      (reinterpret_cast<ptrdiff_t>(pkil->Password.Buffer) +
+           pkil->Password.MaximumLength <=
+       static_cast<ptrdiff_t>(buffer_size))) {
+    // When the authentication package is packed, then each buffer is not
+    // null terminated and the next buffer starts at the end of the previous
+    // one. Also the buffers are stored in the order that they are declared
+    // in the structure.
+
+    if (pkil->LogonDomainName.Buffer && pkil->UserName.Buffer) {
+      const wchar_t* domain_buffer_pos = reinterpret_cast<wchar_t*>(
+          (reinterpret_cast<ptrdiff_t>(pkiul) +
+           reinterpret_cast<ptrdiff_t>(pkil->LogonDomainName.Buffer)));
+
+      const wchar_t* username_buffer_pos = reinterpret_cast<wchar_t*>(
+          (reinterpret_cast<ptrdiff_t>(pkiul) +
+           reinterpret_cast<ptrdiff_t>(pkil->UserName.Buffer)));
+      serialization_domain = base::string16(
+          domain_buffer_pos,
+          pkil->LogonDomainName.MaximumLength / sizeof(domain_buffer_pos[0]));
+      serialization_username = base::string16(
+          username_buffer_pos,
+          pkil->UserName.MaximumLength / sizeof(username_buffer_pos[0]));
+    }
+  } else {
+    // If the authentication package is not packed, assume that the buffer
+    // points to a null terminated string.
+    serialization_domain = pkiul->Logon.LogonDomainName.Buffer;
+    serialization_username = pkiul->Logon.UserName.Buffer;
+  }
+
+  if (serialization_domain.length() && serialization_username.length()) {
+    *domain = serialization_domain;
+    *username = serialization_username;
+    return S_OK;
+  }
+  return E_FAIL;
+}
+
+}  // namespace
+
 // Gets the auth package id for NEGOSSP_NAME_A.
 HRESULT GetAuthenticationPackageId(ULONG* id) {
   DCHECK(id);
@@ -257,7 +326,45 @@
   return hr;
 }
 
-}  // namespace
+HRESULT DetermineUserSidFromAuthenticationBuffer(
+    const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* cpcs,
+    base::string16* sid) {
+  DCHECK(sid);
+
+  sid->clear();
+
+  base::string16 serialization_domain;
+  base::string16 serialization_username;
+  HRESULT hr = UnpackUserInfoFromAuthenticationBuffer(
+      cpcs, &serialization_domain, &serialization_username);
+
+  if (SUCCEEDED(hr)) {
+    hr = OSUserManager::Get()->GetUserSID(serialization_domain.c_str(),
+                                          serialization_username.c_str(), sid);
+    // The function GetUserSID strictly checks the domain that is passed in and
+    // determines if a user really exists in that domain. However the behavior
+    // of RDP connections is more lenient. You can enter any domain you want
+    // when connecting and if a user in that specific domain is not found, RDP
+    // will fall back to trying to sign in the local user with the same
+    // username. To emulate that behavior, we try to also check if there is a
+    // user on the local domain we could possibly signin and return the SID for
+    // that user if it exists.
+    if (FAILED(hr)) {
+      base::string16 local_domain = OSUserManager::GetLocalDomain();
+      if (!base::EqualsCaseInsensitiveASCII(local_domain,
+                                            serialization_domain)) {
+        hr = OSUserManager::Get()->GetUserSID(
+            local_domain.c_str(), serialization_username.c_str(), sid);
+
+        if (FAILED(hr)) {
+          LOGFN(ERROR) << "GetUserSID hr=" << putHR(hr);
+          return hr;
+        }
+      }
+    }
+  }
+  return S_OK;
+}
 
 HRESULT BuildCredPackAuthenticationBuffer(
     BSTR domain,
diff --git a/chrome/credential_provider/gaiacp/auth_utils.h b/chrome/credential_provider/gaiacp/auth_utils.h
index 24f8059..39d61c1 100644
--- a/chrome/credential_provider/gaiacp/auth_utils.h
+++ b/chrome/credential_provider/gaiacp/auth_utils.h
@@ -5,10 +5,19 @@
 #ifndef CHROME_CREDENTIAL_PROVIDER_GAIACP_AUTH_UTILS_H_
 #define CHROME_CREDENTIAL_PROVIDER_GAIACP_AUTH_UTILS_H_
 
+#include "base/strings/string16.h"
+
 #include "chrome/credential_provider/gaiacp/stdafx.h"
 
 namespace credential_provider {
 
+// Gets the auth package id for NEGOSSP_NAME_A.
+HRESULT GetAuthenticationPackageId(ULONG* id);
+
+HRESULT DetermineUserSidFromAuthenticationBuffer(
+    const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* cpcs,
+    base::string16* sid);
+
 HRESULT BuildCredPackAuthenticationBuffer(
     BSTR domain,
     BSTR username,
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_provider.cc b/chrome/credential_provider/gaiacp/gaia_credential_provider.cc
index 6337ab71..b49e4dbc 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_provider.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_provider.cc
@@ -17,6 +17,7 @@
 #include "chrome/common/chrome_version.h"
 #include "chrome/credential_provider/common/gcp_strings.h"
 #include "chrome/credential_provider/gaiacp/associated_user_validator.h"
+#include "chrome/credential_provider/gaiacp/auth_utils.h"
 #include "chrome/credential_provider/gaiacp/gaia_credential.h"
 #include "chrome/credential_provider/gaiacp/gaia_credential_other_user.h"
 #include "chrome/credential_provider/gaiacp/gaia_credential_provider_i.h"
@@ -66,8 +67,8 @@
   }
 
   // Get the user's email address.  If not found, proceed anyway.  The net
-  // effect is that the user will need to enter their email address
-  // manually instead of it being pre-filled.
+  // effect is that the user will need to enter their email address manually
+  // instead of it being pre-filled.
   wchar_t email[64];
   ULONG email_length = base::size(email);
   hr = GetUserProperty(sid.c_str(), kUserEmail, email, &email_length);
@@ -152,7 +153,7 @@
   if (SUCCEEDED(hr)) {
     hr = cred->Initialize(this);
     if (SUCCEEDED(hr)) {
-      users_.emplace_back(cred);
+      AddCredentialAndCheckAutoLogon(cred, base::string16());
     } else {
       LOG(ERROR) << "Could not create credential hr=" << putHR(hr);
     }
@@ -162,10 +163,7 @@
 }
 
 HRESULT CGaiaCredentialProvider::CreateReauthCredentials(
-    ICredentialProviderUserArray* users,
-    std::set<base::string16>* reauth_sids) {
-  DCHECK(reauth_sids);
-  reauth_sids->clear();
+    ICredentialProviderUserArray* users) {
   std::map<base::string16, std::pair<base::string16, base::string16>>
       sid_to_username;
 
@@ -240,13 +238,37 @@
       return hr;
     }
 
-    reauth_sids->insert(sid);
-    users_.emplace_back(cred);
+    AddCredentialAndCheckAutoLogon(cred, sid);
   }
 
   return S_OK;
 }
 
+void CGaiaCredentialProvider::AddCredentialAndCheckAutoLogon(
+    const CComPtr<IGaiaCredential>& cred,
+    const base::string16& sid) {
+  USES_CONVERSION;
+  users_.emplace_back(cred);
+
+  if (sid.empty())
+    return;
+
+  if (set_serialization_sid_.empty())
+    return;
+
+  // If serialization sid is set, then try to see if this credential is a reauth
+  // credential that needs to be auto signed in.
+  CComPtr<IReauthCredential> associated_user;
+  if (FAILED(cred.QueryInterface(&associated_user)))
+    return;
+
+  if (set_serialization_sid_ != sid)
+    return;
+
+  index_ = users_.size() - 1;
+  new_user_sid_ = W2COLE(sid.c_str());
+}
+
 // Static.
 bool CGaiaCredentialProvider::IsUsageScenarioSupported(
     CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus) {
@@ -308,8 +330,8 @@
   new_user_sid_ = sid;
 
   // Tell winlogon.exe that credential info has changed.  This provider will
-  // make the newly created user the default login credential with auto
-  // logon enabled.  See GetCredentialCount() for more details.
+  // make the newly created user the default login credential with auto logon
+  // enabled.  See GetCredentialCount() for more details.
   HRESULT hr = S_OK;
   if (events_ && fire_credentials_changed)
     hr = events_->CredentialsChanged(advise_context_);
@@ -341,8 +363,7 @@
   if (FAILED(hr))
     LOG(ERROR) << "Could not create anonymous credential hr=" << putHR(hr);
 
-  std::set<base::string16> reauth_sids;
-  hr = CreateReauthCredentials(users, &reauth_sids);
+  hr = CreateReauthCredentials(users);
   if (FAILED(hr))
     LOG(ERROR) << "CreateReauthCredentials hr=" << putHR(hr);
 
@@ -365,17 +386,28 @@
 
 HRESULT CGaiaCredentialProvider::SetSerialization(
     const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs) {
+  LOGFN(ERROR);
   DCHECK(pcpcs);
 
-  // NOTE: we only need to support this method if we want to support the
-  // CredUI or support remote login with gaia creds.  We are likely to want
-  // to support both, but not for prototype.
-  if (pcpcs->clsidCredentialProvider == CLSID_GaiaCredentialProvider) {
-    // Unmarshall the serialized buffer and fill in partial fields as needed.
-    // Examine cpusflags for things like admin-only, cred-in-only, etc.
-    LOGFN(INFO) << " authpkg=" << pcpcs->ulAuthenticationPackage
-                << " setsize=" << pcpcs->cbSerialization;
-  }
+  if (pcpcs->clsidCredentialProvider != CLSID_GaiaCredentialProvider)
+    return E_NOTIMPL;
+
+  ULONG auth_package_id;
+  HRESULT hr = GetAuthenticationPackageId(&auth_package_id);
+  if (FAILED(hr))
+    return E_NOTIMPL;
+
+  if (pcpcs->ulAuthenticationPackage != auth_package_id)
+    return E_NOTIMPL;
+
+  if (pcpcs->cbSerialization == 0)
+    return E_NOTIMPL;
+
+  // If serialziation data is set, try to extract the sid for the user
+  // referenced in the serialization data.
+  hr = DetermineUserSidFromAuthenticationBuffer(pcpcs, &set_serialization_sid_);
+  if (FAILED(hr))
+    LOGFN(ERROR) << "DetermineUserSidFromAuthenticationBuffer hr=" << putHR(hr);
 
   return S_OK;
 }
@@ -397,23 +429,22 @@
   HRESULT hr = DestroyCredentials();
   LOGFN(INFO) << "hr=" << putHR(hr);
 
-  // Delete the startup sentinel file if any still exists. It can still exist
-  // in 2 cases:
+  // Delete the startup sentinel file if any still exists. It can still exist in
+  // 2 cases:
 
-  // 1. The UnAdvise should only occur after the user has logged in, so if
-  // they never selected any gaia credential and just used normal credentials
-  // this function will be called in that situation and it is guaranteed that
-  // the user has at least been able provide some input to winlogon.
-  // 2. When no usage scenario is supported, none of the credentials will be
-  // selected and thus the gcpw startup sentinel file will not be deleted.
-  // So in the case where the user is asked for CPUS_CRED_UI enough times,
-  // the sentinel file size will keep growing without being deleted and
-  // eventually GCPW will be disabled completely. In the unsupported usage
-  // scenario, FinalRelease will be called shortly after SetUsageScenario
-  // if the function returns E_NOTIMPL so try to catch potential crashes
-  // of the destruction of the provider when it is not used because
-  // crashes in this case will prevent the cred ui from coming up and not
-  // allow the user to access their desired resource.
+  // 1. The UnAdvise should only occur after the user has logged in, so if they
+  // never selected any gaia credential and just used normal credentials this
+  // function will be called in that situation and it is guaranteed that the
+  // user has at least been able provide some input to winlogon. 2. When no
+  // usage scenario is supported, none of the credentials will be selected and
+  // thus the gcpw startup sentinel file will not be deleted. So in the case
+  // where the user is asked for CPUS_CRED_UI enough times, the sentinel file
+  // size will keep growing without being deleted and eventually GCPW will be
+  // disabled completely. In the unsupported usage scenario, FinalRelease will
+  // be called shortly after SetUsageScenario if the function returns E_NOTIMPL
+  // so try to catch potential crashes of the destruction of the provider when
+  // it is not used because crashes in this case will prevent the cred ui from
+  // coming up and not allow the user to access their desired resource.
   DeleteStartupSentinel();
 
   return S_OK;
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_provider.h b/chrome/credential_provider/gaiacp/gaia_credential_provider.h
index 0304d7f..5f33b2a 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_provider.h
+++ b/chrome/credential_provider/gaiacp/gaia_credential_provider.h
@@ -10,6 +10,9 @@
 #include <set>
 #include <vector>
 
+#include "base/strings/string16.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/win/scoped_handle.h"
 #include "chrome/credential_provider/gaiacp/gaia_credential.h"
 #include "chrome/credential_provider/gaiacp/gaia_credential_provider_i.h"
 #include "chrome/credential_provider/gaiacp/gaia_resources.h"
@@ -65,8 +68,13 @@
   // Creates all the reauth credentials from the users that is returned from
   // |users|. Fills |reauth_sids| with the list of user sids for which a reauth
   // credential was created.
-  HRESULT CreateReauthCredentials(ICredentialProviderUserArray* users,
-                                  std::set<base::string16>* reauth_sids);
+  HRESULT CreateReauthCredentials(ICredentialProviderUserArray* users);
+
+  // This function will always add |cred| to |users_| and will also try to
+  // check if the |sid| matches the one set in |set_serialization_sid_| to
+  // allow auto logon of remote connections.
+  void AddCredentialAndCheckAutoLogon(const CComPtr<IGaiaCredential>& cred,
+                                      const base::string16& sid);
 
   void ClearTransient();
   void CleanupOlderVersions();
@@ -115,6 +123,8 @@
   // Index in the |users_| array of the credential that performed the
   // authentication.
   size_t index_ = std::numeric_limits<size_t>::max();
+
+  base::string16 set_serialization_sid_;
 };
 
 // OBJECT_ENTRY_AUTO() contains an extra semicolon.
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_provider_filter.cc b/chrome/credential_provider/gaiacp/gaia_credential_provider_filter.cc
index 0516b585..486dd40 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_provider_filter.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_provider_filter.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/credential_provider/gaiacp/gaia_credential_provider_filter.h"
 
+#include "base/strings/string16.h"
 #include "chrome/credential_provider/gaiacp/associated_user_validator.h"
+#include "chrome/credential_provider/gaiacp/auth_utils.h"
 #include "chrome/credential_provider/gaiacp/logging.h"
 
 namespace credential_provider {
@@ -41,7 +43,46 @@
 HRESULT CGaiaCredentialProviderFilter::UpdateRemoteCredential(
     const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs_in,
     CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs_out) {
-  return E_NOTIMPL;
+  if (!pcpcs_out)
+    return E_NOTIMPL;
+
+  ULONG auth_package_id;
+  HRESULT hr = GetAuthenticationPackageId(&auth_package_id);
+  if (FAILED(hr))
+    return E_NOTIMPL;
+
+  if (pcpcs_in->ulAuthenticationPackage != auth_package_id)
+    return E_NOTIMPL;
+
+  if (pcpcs_in->cbSerialization == 0)
+    return E_NOTIMPL;
+
+  // If serialziation data is set, try to extract the sid for the user
+  // referenced in the serialization data.
+  base::string16 serialization_sid;
+  hr = DetermineUserSidFromAuthenticationBuffer(pcpcs_in, &serialization_sid);
+  if (FAILED(hr))
+    return E_NOTIMPL;
+
+  // Check if this user needs a reauth, if not, just pass the serialization
+  // to the default handler.
+  if (AssociatedUserValidator::Get()->IsTokenHandleValidForUser(
+          serialization_sid)) {
+    return E_NOTIMPL;
+  }
+
+  // Copy out the serialization data to pass it into the provider.
+  byte* serialization_buffer =
+      (BYTE*)::CoTaskMemAlloc(pcpcs_in->cbSerialization);
+  if (serialization_buffer == nullptr)
+    return E_NOTIMPL;
+
+  pcpcs_out->rgbSerialization = serialization_buffer;
+  memcpy(pcpcs_out->rgbSerialization, pcpcs_in->rgbSerialization,
+         pcpcs_in->cbSerialization);
+  pcpcs_out->cbSerialization = pcpcs_in->cbSerialization;
+  pcpcs_out->clsidCredentialProvider = CLSID_GaiaCredentialProvider;
+  return S_OK;
 }
 
 }  // namespace credential_provider
diff --git a/chrome/credential_provider/gaiacp/google_logo_small.bmp b/chrome/credential_provider/gaiacp/google_logo_small.bmp
index 85fe03d..7ce8956 100644
--- a/chrome/credential_provider/gaiacp/google_logo_small.bmp
+++ b/chrome/credential_provider/gaiacp/google_logo_small.bmp
Binary files differ
diff --git a/chrome/credential_provider/gaiacp/mdm_utils.cc b/chrome/credential_provider/gaiacp/mdm_utils.cc
index cef4abb..9b68eab 100644
--- a/chrome/credential_provider/gaiacp/mdm_utils.cc
+++ b/chrome/credential_provider/gaiacp/mdm_utils.cc
@@ -86,8 +86,23 @@
   auto get_device_registration_info_function =
       GET_MDM_FUNCTION_POINTER(library, GetDeviceRegistrationInfo);
   if (!get_device_registration_info_function) {
+    // On Windows < 1803 the function GetDeviceRegistrationInfo does not exist
+    // in MDMRegistration.dll so we have to fallback to the less accurate
+    // IsDeviceRegisteredWithManagement. This can return false positives if the
+    // machine is registered to MDM but to a different server.
     LOGFN(ERROR) << "GET_MDM_FUNCTION_POINTER(GetDeviceRegistrationInfo)";
-    return false;
+    auto is_device_registered_with_management_function =
+        GET_MDM_FUNCTION_POINTER(library, IsDeviceRegisteredWithManagement);
+    if (!is_device_registered_with_management_function) {
+      LOGFN(ERROR)
+          << "GET_MDM_FUNCTION_POINTER(IsDeviceRegisteredWithManagement)";
+      return false;
+    } else {
+      BOOL is_managed = FALSE;
+      HRESULT hr = is_device_registered_with_management_function(&is_managed, 0,
+                                                                 nullptr);
+      return SUCCEEDED(hr) && is_managed;
+    }
   }
 
   MANAGEMENT_REGISTRATION_INFO* info;
diff --git a/chrome/credential_provider/gaiacp/os_user_manager.cc b/chrome/credential_provider/gaiacp/os_user_manager.cc
index 14fcc65..c1904f2 100644
--- a/chrome/credential_provider/gaiacp/os_user_manager.cc
+++ b/chrome/credential_provider/gaiacp/os_user_manager.cc
@@ -414,6 +414,30 @@
 
 HRESULT OSUserManager::GetUserSID(const wchar_t* domain,
                                   const wchar_t* username,
+                                  base::string16* sid_string) {
+  DCHECK(sid_string);
+  sid_string->clear();
+
+  PSID sid;
+  HRESULT hr = GetUserSID(domain, username, &sid);
+
+  if (SUCCEEDED(hr)) {
+    wchar_t* sid_buffer;
+    if (::ConvertSidToStringSid(sid, &sid_buffer)) {
+      *sid_string = sid_buffer;
+      ::LocalFree(sid_buffer);
+    } else {
+      hr = HRESULT_FROM_WIN32(::GetLastError());
+      LOGFN(ERROR) << "ConvertStringSidToSid hr=" << putHR(hr);
+    }
+    ::LocalFree(sid);
+  }
+
+  return hr;
+}
+
+HRESULT OSUserManager::GetUserSID(const wchar_t* domain,
+                                  const wchar_t* username,
                                   PSID* sid) {
   DCHECK(username);
   DCHECK(sid);
diff --git a/chrome/credential_provider/gaiacp/os_user_manager.h b/chrome/credential_provider/gaiacp/os_user_manager.h
index 52f1463..1417c46d 100644
--- a/chrome/credential_provider/gaiacp/os_user_manager.h
+++ b/chrome/credential_provider/gaiacp/os_user_manager.h
@@ -58,6 +58,9 @@
   // should free it with a call to LocalFree().
   virtual HRESULT GetUserSID(const wchar_t* domain, const wchar_t* username,
                              PSID* sid);
+  // Gets the SID in string format of the given OS user.
+  HRESULT GetUserSID(const wchar_t* domain, const wchar_t* username,
+                     base::string16* sid_string);
 
   // Finds a user created from a gaia account by its SID.  Returns S_OK if a
   // user with the given SID exists, HRESULT_FROM_WIN32(ERROR_NONE_MAPPED)
diff --git a/chrome/credential_provider/gaiacp/strings/gaia_resources_iw.xtb b/chrome/credential_provider/gaiacp/strings/gaia_resources_iw.xtb
index a462d651..848255e 100644
--- a/chrome/credential_provider/gaiacp/strings/gaia_resources_iw.xtb
+++ b/chrome/credential_provider/gaiacp/strings/gaia_resources_iw.xtb
@@ -12,7 +12,7 @@
 <translation id="6292766200512304540">המשתמש נוצר באמצעות חשבון לצורכי עבודה</translation>
 <translation id="6312494990035843744">אין להיכנס לדומיין הזה באמצעות חשבון לצורכי עבודה. יש לנסות חשבון אחר.</translation>
 <translation id="6463752215771576050">לא ניתן לרשום את המחשב הזה לניהול ארגוני.  יש להיכנס באמצעות חשבון אחר לצורכי עבודה.</translation>
-<translation id="7135123390294776473">רק המשתמש שנעל את המחשב הזה רשאי להיכנס כעת.</translation>
+<translation id="7135123390294776473">רק המשתמש שנעל את המחשב הזה רשאי להיכנס עכשיו.</translation>
 <translation id="7357241217513796177">צריך לבדוק אם יש חיבור לרשת ואז אפשר לנסות שוב.</translation>
 <translation id="8440458902131551808">החשבון שלך ננעל. יש לפנות אל אחד ממנהלי המערכת.</translation>
 <translation id="8474372283141585908">‏ספק פרטי הכניסה של Google</translation>
diff --git a/chrome/credential_provider/gaiacp/strings/gaia_resources_ta.xtb b/chrome/credential_provider/gaiacp/strings/gaia_resources_ta.xtb
index 739b847..aec3299 100644
--- a/chrome/credential_provider/gaiacp/strings/gaia_resources_ta.xtb
+++ b/chrome/credential_provider/gaiacp/strings/gaia_resources_ta.xtb
@@ -2,11 +2,21 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="ta">
 <translation id="1383286653814676580">Google அனுமதிச் சான்று வழங்குநர் உள்நுழைவுப் பக்கத்தை இயக்கப் பயன்படுத்தப்படுகிறது.</translation>
+<translation id="1894475569413661128">உங்கள் பணிக் கணக்கில் உள்நுழையவும்.</translation>
+<translation id="2469311484561825731">உங்கள் பணிக் கணக்கில் உள்நுழைய முடியவில்லை. கம்ப்யூட்டரில் இணைய இணைப்பு உள்ளதா என்பதைச் சரிபார்த்து மீண்டும் முயலவும்.</translation>
 <translation id="2595469428674600431">உங்கள் Windows கடவுச்சொல்லைச் சரிபார்க்க முடியவில்லை. மீண்டும் முயலவும்.</translation>
+<translation id="3306357053520292004">இந்தக் கம்ப்யூட்டரில் உள்ள பயனர் இந்தக் கணக்கைப் பயன்படுத்தி ஏற்கனவே சேர்க்கப்பட்டுள்ளார். வேறொரு கணக்கில் உள்நுழையவும்.</translation>
 <translation id="4057329986137569701">அகப்பிழை ஏற்பட்டது.</translation>
+<translation id="4300229033992784001">உங்கள் கணக்கின் கடவுச்சொல் மாற்றப்பட்டது. உங்கள் Windows கணக்கை பணிக் கணக்குடன் ஒத்திசைக்க உங்களின் தற்போதைய Windows கடவுச்சொல்லை உள்ளிடவும்.</translation>
+<translation id="4706454071748629324">புதிய பயனரைச் சேர்க்க முடியவில்லை. இந்தக் கம்ப்யூட்டர் பணிக் கணக்கைப் பயன்படுத்தி ஒரு பயனரை உருவாக்குவதை மட்டுமே அனுமதிக்கும்.</translation>
+<translation id="6292766200512304540">பணிக் கணக்கிலிருந்து உருவாக்கப்பட்ட பயனர்</translation>
+<translation id="6312494990035843744">இந்த டொமைனில் பணிக் கணக்கில் உள்நுழைய அனுமதியில்லை. வேறொரு கணக்கைப் பயன்படுத்திப் பார்க்கவும்.</translation>
+<translation id="6463752215771576050">நிறுவன மேலாண்மைக்கு இந்தக் கம்ப்யூட்டரைப் பதிவுசெய்ய முடியவில்லை.  வேறொரு பணிக் கணக்கில் உள்நுழையவும்.</translation>
+<translation id="7135123390294776473">இந்தக் கம்ப்யூட்டரைப் பூட்டிய பயனர் மட்டுமே தற்போது உள்நுழைய அனுமதிக்கப்படுவார்.</translation>
 <translation id="7357241217513796177">இணைய இணைப்பு இருப்பதை உறுதிசெய்து மீண்டும் முயலவும்.</translation>
 <translation id="8440458902131551808">உங்கள் கணக்கு பூட்டப்பட்டுள்ளது. சாதன நிர்வாகியைத் தொடர்புகொள்ளவும்.</translation>
 <translation id="8474372283141585908">Google அனுமதிச் சான்று வழங்குநர்</translation>
 <translation id="866458870819756755">பயனரை உருவாக்க முடியவில்லை.</translation>
 <translation id="8860262547644202689">Google அனுமதிச் சான்று வழங்குநர் உதவி</translation>
+<translation id="9135619837062629367">இந்தக் கணக்கில் உள்நுழைய அனுமதியில்லை. வேறொரு கணக்கைப் பயன்படுத்திப் பார்க்கவும்.</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/chrome/installer/mac/BUILD.gn b/chrome/installer/mac/BUILD.gn
index cbc1562..35c3afe 100644
--- a/chrome/installer/mac/BUILD.gn
+++ b/chrome/installer/mac/BUILD.gn
@@ -2,10 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/util/branding.gni")
-import("//build/util/version.gni")
 import("//build/config/features.gni")
 import("//build/config/mac/base_rules.gni")
+import("//build/util/branding.gni")
+import("//build/util/version.gni")
 
 group("mac") {
   public_deps = [
@@ -76,7 +76,7 @@
   ]
 
   sources = [
-    "$root_gen_dir/chrome/entitlements.plist",
+    "$root_gen_dir/chrome/app-entitlements.plist",
     "$root_out_dir/goobsdiff",
     "$root_out_dir/goobspatch",
     "$root_out_dir/liblzma_decompress.dylib",
diff --git a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
index 8c30422d..a5435d2 100644
--- a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
+++ b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
@@ -6,6 +6,7 @@
 #include "chrome/common/extensions/chrome_extension_messages.h"
 #include "chrome/renderer/extensions/automation_internal_custom_bindings.h"
 #include "extensions/common/extension_messages.h"
+#include "ui/accessibility/ax_language_info.h"
 #include "ui/accessibility/ax_node.h"
 
 namespace extensions {
@@ -307,6 +308,21 @@
   for (const auto& targeted_event : event_generator_) {
     api::automation::EventType event_type =
         ToAutomationEvent(targeted_event.event_params.event);
+
+    // Perform language detection first thing if we see a load complete event.
+    // We have to run *before* we send the load complete event to javascript
+    // otherwise code which runs immediately on load complete will not be able
+    // to see the results of language detection.
+    //
+    // Currently language detection only runs once for initial load complete,
+    // any content loaded after this will not have language detection performed
+    // for it.
+    if (event_type == api::automation::EVENT_TYPE_LOADCOMPLETE) {
+      DetectLanguageForSubtree(tree_.root(), &tree_);
+      if (!LabelLanguageForSubtree(tree_.root(), &tree_))
+        LOG(FATAL) << "Language detection failed at step: Label";
+    }
+
     if (IsEventTypeHandledByAXEventGenerator(event_type)) {
       ui::AXEvent generated_event;
       generated_event.id = targeted_event.node->id();
diff --git a/chrome/renderer/page_load_metrics/fake_page_timing_sender.cc b/chrome/renderer/page_load_metrics/fake_page_timing_sender.cc
index 53e59169..bbe3909 100644
--- a/chrome/renderer/page_load_metrics/fake_page_timing_sender.cc
+++ b/chrome/renderer/page_load_metrics/fake_page_timing_sender.cc
@@ -20,9 +20,10 @@
     mojom::PageLoadFeaturesPtr new_features,
     std::vector<mojom::ResourceDataUpdatePtr> resources,
     const mojom::FrameRenderDataUpdate& render_data,
-    const mojom::CpuTimingPtr& cpu_timing) {
+    const mojom::CpuTimingPtr& cpu_timing,
+    mojom::DeferredResourceCountsPtr new_deferred_resource_data) {
   validator_->UpdateTiming(timing, metadata, new_features, resources,
-                           render_data, cpu_timing);
+                           render_data, cpu_timing, new_deferred_resource_data);
 }
 
 FakePageTimingSender::PageTimingValidator::PageTimingValidator() {}
@@ -123,7 +124,8 @@
     const mojom::PageLoadFeaturesPtr& new_features,
     const std::vector<mojom::ResourceDataUpdatePtr>& resources,
     const mojom::FrameRenderDataUpdate& render_data,
-    const mojom::CpuTimingPtr& cpu_timing) {
+    const mojom::CpuTimingPtr& cpu_timing,
+    const mojom::DeferredResourceCountsPtr& new_deferred_resource_data) {
   actual_timings_.push_back(timing.Clone());
   if (!cpu_timing->task_time.is_zero()) {
     actual_cpu_timings_.push_back(cpu_timing.Clone());
diff --git a/chrome/renderer/page_load_metrics/fake_page_timing_sender.h b/chrome/renderer/page_load_metrics/fake_page_timing_sender.h
index df511e7d..b71c184 100644
--- a/chrome/renderer/page_load_metrics/fake_page_timing_sender.h
+++ b/chrome/renderer/page_load_metrics/fake_page_timing_sender.h
@@ -88,7 +88,8 @@
         const mojom::PageLoadFeaturesPtr& new_features,
         const std::vector<mojom::ResourceDataUpdatePtr>& resources,
         const mojom::FrameRenderDataUpdate& render_data,
-        const mojom::CpuTimingPtr& cpu_timing);
+        const mojom::CpuTimingPtr& cpu_timing,
+        const mojom::DeferredResourceCountsPtr& new_deferred_resource_data);
 
    private:
     std::vector<mojom::PageLoadTimingPtr> expected_timings_;
@@ -106,12 +107,14 @@
 
   explicit FakePageTimingSender(PageTimingValidator* validator);
   ~FakePageTimingSender() override;
-  void SendTiming(const mojom::PageLoadTimingPtr& timing,
-                  const mojom::PageLoadMetadataPtr& metadata,
-                  mojom::PageLoadFeaturesPtr new_features,
-                  std::vector<mojom::ResourceDataUpdatePtr> resources,
-                  const mojom::FrameRenderDataUpdate& render_data,
-                  const mojom::CpuTimingPtr& cpu_timing) override;
+  void SendTiming(
+      const mojom::PageLoadTimingPtr& timing,
+      const mojom::PageLoadMetadataPtr& metadata,
+      mojom::PageLoadFeaturesPtr new_features,
+      std::vector<mojom::ResourceDataUpdatePtr> resources,
+      const mojom::FrameRenderDataUpdate& render_data,
+      const mojom::CpuTimingPtr& cpu_timing,
+      mojom::DeferredResourceCountsPtr new_deferred_resource_data) override;
 
  private:
   PageTimingValidator* const validator_;
diff --git a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
index beb401be..0dcb486 100644
--- a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
+++ b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.cc
@@ -38,16 +38,19 @@
         &page_load_metrics_);
   }
   ~MojoPageTimingSender() override {}
-  void SendTiming(const mojom::PageLoadTimingPtr& timing,
-                  const mojom::PageLoadMetadataPtr& metadata,
-                  mojom::PageLoadFeaturesPtr new_features,
-                  std::vector<mojom::ResourceDataUpdatePtr> resources,
-                  const mojom::FrameRenderDataUpdate& render_data,
-                  const mojom::CpuTimingPtr& cpu_timing) override {
+  void SendTiming(
+      const mojom::PageLoadTimingPtr& timing,
+      const mojom::PageLoadMetadataPtr& metadata,
+      mojom::PageLoadFeaturesPtr new_features,
+      std::vector<mojom::ResourceDataUpdatePtr> resources,
+      const mojom::FrameRenderDataUpdate& render_data,
+      const mojom::CpuTimingPtr& cpu_timing,
+      mojom::DeferredResourceCountsPtr new_deferred_resource_data) override {
     DCHECK(page_load_metrics_);
     page_load_metrics_->UpdateTiming(
         timing->Clone(), metadata->Clone(), std::move(new_features),
-        std::move(resources), render_data.Clone(), cpu_timing->Clone());
+        std::move(resources), render_data.Clone(), cpu_timing->Clone(),
+        std::move(new_deferred_resource_data));
   }
 
  private:
@@ -103,6 +106,11 @@
     page_timing_metrics_sender_->DidObserveLayoutJank(jank_fraction);
 }
 
+void MetricsRenderFrameObserver::DidObserveLazyLoadBehavior(
+    blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) {
+  page_timing_metrics_sender_->DidObserveLazyLoadBehavior(lazy_load_behavior);
+}
+
 void MetricsRenderFrameObserver::DidStartResponse(
     const GURL& response_url,
     int request_id,
diff --git a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.h b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.h
index 8291fd0..3496eaa 100644
--- a/chrome/renderer/page_load_metrics/metrics_render_frame_observer.h
+++ b/chrome/renderer/page_load_metrics/metrics_render_frame_observer.h
@@ -15,6 +15,7 @@
 #include "components/subresource_filter/content/renderer/ad_resource_tracker.h"
 #include "content/public/renderer/render_frame_observer.h"
 #include "third_party/blink/public/platform/web_loading_behavior_flag.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
 
 class GURL;
 
@@ -48,6 +49,8 @@
   void DidObserveNewCssPropertyUsage(int css_property,
                                      bool is_animated) override;
   void DidObserveLayoutJank(double jank_fraction) override;
+  void DidObserveLazyLoadBehavior(
+      blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) override;
   void DidStartResponse(const GURL& response_url,
                         int request_id,
                         const network::ResourceResponseHead& response_head,
diff --git a/chrome/renderer/page_load_metrics/page_timing_metrics_sender.cc b/chrome/renderer/page_load_metrics/page_timing_metrics_sender.cc
index 514a175..8f2fd70 100644
--- a/chrome/renderer/page_load_metrics/page_timing_metrics_sender.cc
+++ b/chrome/renderer/page_load_metrics/page_timing_metrics_sender.cc
@@ -38,6 +38,7 @@
       metadata_(mojom::PageLoadMetadata::New()),
       new_features_(mojom::PageLoadFeatures::New()),
       render_data_(),
+      new_deferred_resource_data_(mojom::DeferredResourceCounts::New()),
       buffer_timer_delay_ms_(kBufferTimerDelayMillis) {
   page_resource_data_use_.emplace(
       std::piecewise_construct,
@@ -99,6 +100,24 @@
   EnsureSendTimer();
 }
 
+void PageTimingMetricsSender::DidObserveLazyLoadBehavior(
+    blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) {
+  switch (lazy_load_behavior) {
+    case blink::WebLocalFrameClient::LazyLoadBehavior::kDeferredFrame:
+      ++new_deferred_resource_data_->deferred_frames;
+      break;
+    case blink::WebLocalFrameClient::LazyLoadBehavior::kDeferredImage:
+      ++new_deferred_resource_data_->deferred_images;
+      break;
+    case blink::WebLocalFrameClient::LazyLoadBehavior::kLazyLoadedFrame:
+      ++new_deferred_resource_data_->frames_loaded_after_deferral;
+      break;
+    case blink::WebLocalFrameClient::LazyLoadBehavior::kLazyLoadedImage:
+      ++new_deferred_resource_data_->images_loaded_after_deferral;
+      break;
+  }
+}
+
 void PageTimingMetricsSender::DidStartResponse(
     const GURL& response_url,
     int resource_id,
@@ -218,7 +237,9 @@
     }
   }
   sender_->SendTiming(last_timing_, metadata_, std::move(new_features_),
-                      std::move(resources), render_data_, last_cpu_timing_);
+                      std::move(resources), render_data_, last_cpu_timing_,
+                      std::move(new_deferred_resource_data_));
+  new_deferred_resource_data_ = mojom::DeferredResourceCounts::New();
   new_features_ = mojom::PageLoadFeatures::New();
   last_cpu_timing_->task_time = base::TimeDelta();
   modified_resources_.clear();
diff --git a/chrome/renderer/page_load_metrics/page_timing_metrics_sender.h b/chrome/renderer/page_load_metrics/page_timing_metrics_sender.h
index 946d337bb..9423c58 100644
--- a/chrome/renderer/page_load_metrics/page_timing_metrics_sender.h
+++ b/chrome/renderer/page_load_metrics/page_timing_metrics_sender.h
@@ -17,6 +17,7 @@
 #include "third_party/blink/public/mojom/use_counter/css_property_id.mojom.h"
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-shared.h"
 #include "third_party/blink/public/platform/web_loading_behavior_flag.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
 
 class GURL;
 
@@ -48,6 +49,9 @@
   void DidObserveNewFeatureUsage(blink::mojom::WebFeature feature);
   void DidObserveNewCssPropertyUsage(int css_property, bool is_animated);
   void DidObserveLayoutJank(double jank_fraction);
+  void DidObserveLazyLoadBehavior(
+      blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior);
+
   void DidStartResponse(const GURL& response_url,
                         int resource_id,
                         const network::ResourceResponseHead& response_head,
@@ -89,6 +93,7 @@
   // browser.
   mojom::PageLoadFeaturesPtr new_features_;
   mojom::FrameRenderDataUpdate render_data_;
+  mojom::DeferredResourceCountsPtr new_deferred_resource_data_;
 
   std::bitset<static_cast<size_t>(blink::mojom::WebFeature::kNumberOfFeatures)>
       features_sent_;
diff --git a/chrome/renderer/page_load_metrics/page_timing_sender.h b/chrome/renderer/page_load_metrics/page_timing_sender.h
index 12e4a84d..06e0ebe 100644
--- a/chrome/renderer/page_load_metrics/page_timing_sender.h
+++ b/chrome/renderer/page_load_metrics/page_timing_sender.h
@@ -14,12 +14,14 @@
 class PageTimingSender {
  public:
   virtual ~PageTimingSender() {}
-  virtual void SendTiming(const mojom::PageLoadTimingPtr& timing,
-                          const mojom::PageLoadMetadataPtr& metadata,
-                          mojom::PageLoadFeaturesPtr new_features,
-                          std::vector<mojom::ResourceDataUpdatePtr> resources,
-                          const mojom::FrameRenderDataUpdate& render_data,
-                          const mojom::CpuTimingPtr& cpu_timing) = 0;
+  virtual void SendTiming(
+      const mojom::PageLoadTimingPtr& timing,
+      const mojom::PageLoadMetadataPtr& metadata,
+      mojom::PageLoadFeaturesPtr new_features,
+      std::vector<mojom::ResourceDataUpdatePtr> resources,
+      const mojom::FrameRenderDataUpdate& render_data,
+      const mojom::CpuTimingPtr& cpu_timing,
+      mojom::DeferredResourceCountsPtr new_deferred_resource_data) = 0;
 };
 
 }  // namespace page_load_metrics
diff --git a/chrome/renderer/searchbox/search_bouncer.cc b/chrome/renderer/searchbox/search_bouncer.cc
index 0232807..73c4c33 100644
--- a/chrome/renderer/searchbox/search_bouncer.cc
+++ b/chrome/renderer/searchbox/search_bouncer.cc
@@ -12,6 +12,14 @@
 namespace {
 base::LazyInstance<SearchBouncer>::Leaky g_search_bouncer =
     LAZY_INSTANCE_INITIALIZER;
+
+GURL RemoveQueryAndRef(const GURL& url) {
+  url::Replacements<char> replacements;
+  replacements.ClearQuery();
+  replacements.ClearRef();
+  return url.ReplaceComponents(replacements);
+}
+
 }  // namespace
 
 SearchBouncer::SearchBouncer() : search_bouncer_binding_(this) {}
@@ -36,11 +44,9 @@
 }
 
 bool SearchBouncer::IsNewTabPage(const GURL& url) const {
-  // TODO(treib): Ignore query and ref. It's still an NTP even if those don't
-  // match.
-  // TODO(treib): Figure out if this should also handle the local NTP. Or are
-  // chrome-search:// URLs handled elsewhere?
-  return url.is_valid() && url == new_tab_page_url_;
+  GURL url_no_query_or_ref = RemoveQueryAndRef(url);
+  return url_no_query_or_ref.is_valid() &&
+         url_no_query_or_ref == new_tab_page_url_;
 }
 
 void SearchBouncer::SetNewTabPageURL(const GURL& new_tab_page_url) {
diff --git a/chrome/renderer/searchbox/search_bouncer_unittest.cc b/chrome/renderer/searchbox/search_bouncer_unittest.cc
index b2b1af0..c6b706b1 100644
--- a/chrome/renderer/searchbox/search_bouncer_unittest.cc
+++ b/chrome/renderer/searchbox/search_bouncer_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <vector>
 
+#include "chrome/common/url_constants.cc"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -24,9 +25,17 @@
   EXPECT_FALSE(bouncer_.ShouldFork(GURL("http://example.com/search?q=foo")));
   EXPECT_FALSE(bouncer_.ShouldFork(GURL("http://example.com/search2#q=foo")));
   EXPECT_TRUE(bouncer_.ShouldFork(GURL("http://example.com/newtab")));
+  EXPECT_TRUE(bouncer_.ShouldFork(GURL("http://example.com/newtab?q=foo")));
+  EXPECT_TRUE(bouncer_.ShouldFork(GURL("http://example.com/newtab#q=foo")));
+  EXPECT_TRUE(
+      bouncer_.ShouldFork(GURL("http://example.com/newtab#q=foo?q=foo")));
 }
 
 TEST_F(SearchBouncerTest, IsNewTabPage) {
   EXPECT_FALSE(bouncer_.IsNewTabPage(GURL("http://example.com/foo")));
   EXPECT_TRUE(bouncer_.IsNewTabPage(GURL("http://example.com/newtab")));
+  EXPECT_TRUE(bouncer_.IsNewTabPage(GURL("http://example.com/newtab?q=foo")));
+  EXPECT_TRUE(bouncer_.IsNewTabPage(GURL("http://example.com/newtab#q=foo")));
+  EXPECT_TRUE(
+      bouncer_.IsNewTabPage(GURL("http://example.com/newtab#q=foo?q=foo")));
 }
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc
index 4fc896b1..4da93d2f 100644
--- a/chrome/renderer/searchbox/searchbox_extension.cc
+++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -71,8 +71,6 @@
     "url(chrome-search://theme/IDR_THEME_NTP_BACKGROUND?%s) 1x, "
     "url(chrome-search://theme/IDR_THEME_NTP_BACKGROUND@2x?%s) 2x)";
 
-const char kCSSBackgroundColorFormat[] = "rgba(%d,%d,%d,%s)";
-
 const char kCSSBackgroundPositionCenter[] = "center";
 const char kCSSBackgroundPositionLeft[] = "left";
 const char kCSSBackgroundPositionTop[] = "top";
@@ -203,23 +201,6 @@
   // Value is always valid.
   builder.Set("usingDarkMode", theme_info.using_dark_mode);
 
-  // The theme background color is in RGBA format "rgba(R,G,B,A)" where R, G and
-  // B are between 0 and 255 inclusive, and A is a double between 0 and 1
-  // inclusive.
-  // This is the CSS "background-color" format.
-  // Value is always valid.
-  // TODO(jfweitz): Remove this field after GWS is modified to use the new
-  // backgroundColorRgba field.
-  builder.Set(
-      "colorRgba",
-      // Convert the alpha using NumberToString because StringPrintf will
-      // use locale specific formatters (e.g., use , instead of . in
-      // German).
-      base::StringPrintf(
-          kCSSBackgroundColorFormat, theme_info.background_color.r,
-          theme_info.background_color.g, theme_info.background_color.b,
-          base::NumberToString(theme_info.background_color.a / 255.0).c_str()));
-
   // Theme color for background as an array with the RGBA components in order.
   // Value is always valid.
   builder.Set("backgroundColorRgba",
diff --git a/chrome/renderer/tts_dispatcher.cc b/chrome/renderer/tts_dispatcher.cc
index 9dbfac3..c40d2b4 100644
--- a/chrome/renderer/tts_dispatcher.cc
+++ b/chrome/renderer/tts_dispatcher.cc
@@ -141,26 +141,38 @@
   synthesizer_client_->DidResumeSpeaking(utterance);
 }
 
-void TtsDispatcher::OnWordBoundary(int utterance_id, int char_index) {
+void TtsDispatcher::OnWordBoundary(int utterance_id,
+                                   int char_index,
+                                   int char_length) {
   CHECK(char_index >= 0);
 
   WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
   if (utterance.IsNull())
     return;
 
+  // charLength is unsigned in the web speech API, so -1 cannot be used as a
+  // sentinel value. Use 0 instead to match web standards.
+  char_length = (char_length < 0) ? 0 : char_length;
   synthesizer_client_->WordBoundaryEventOccurred(
-      utterance, static_cast<unsigned>(char_index));
+      utterance, static_cast<unsigned>(char_index),
+      static_cast<unsigned>(char_length));
 }
 
-void TtsDispatcher::OnSentenceBoundary(int utterance_id, int char_index) {
+void TtsDispatcher::OnSentenceBoundary(int utterance_id,
+                                       int char_index,
+                                       int char_length) {
   CHECK(char_index >= 0);
 
   WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
   if (utterance.IsNull())
     return;
 
+  // charLength is unsigned in the web speech API, so -1 cannot be used as a
+  // sentinel value. Use 0 instead to match web standards.
+  char_length = (char_length < 0) ? 0 : char_length;
   synthesizer_client_->SentenceBoundaryEventOccurred(
-      utterance, static_cast<unsigned>(char_index));
+      utterance, static_cast<unsigned>(char_index),
+      static_cast<unsigned>(char_length));
 }
 
 void TtsDispatcher::OnMarkerEvent(int utterance_id, int char_index) {
diff --git a/chrome/renderer/tts_dispatcher.h b/chrome/renderer/tts_dispatcher.h
index c7186b5..769795f 100644
--- a/chrome/renderer/tts_dispatcher.h
+++ b/chrome/renderer/tts_dispatcher.h
@@ -52,8 +52,8 @@
   void OnDidFinishSpeaking(int utterance_id);
   void OnDidPauseSpeaking(int utterance_id);
   void OnDidResumeSpeaking(int utterance_id);
-  void OnWordBoundary(int utterance_id, int char_index);
-  void OnSentenceBoundary(int utterance_id, int char_index);
+  void OnWordBoundary(int utterance_id, int char_index, int char_length);
+  void OnSentenceBoundary(int utterance_id, int char_index, int char_length);
   void OnMarkerEvent(int utterance_id, int char_index);
   void OnWasInterrupted(int utterance_id);
   void OnWasCancelled(int utterance_id);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 0d8144b..a128d94 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -281,7 +281,7 @@
       "//components/user_manager:test_support",
       "//ui/aura",
       "//ui/aura:test_support",
-      "//ui/base/ime",
+      "//ui/base/ime/init",
     ]
   }
 
@@ -547,6 +547,7 @@
       "//chromeos:test_support",
       "//chromeos/components/drivefs:test_support",
       "//chromeos/dbus:test_support",
+      "//chromeos/dbus/session_manager",
       "//components/arc:arc_test_support",
       "//components/exo:test_support",
       "//components/prefs",
@@ -2424,6 +2425,17 @@
   ]
 }
 
+group("ct_telemetry_perf_tests_without_chrome") {
+  testonly = true
+  deps = [
+    ":telemetry_perf_tests_without_chrome",
+  ]
+
+  data = [
+    "//tools/perf/contrib/cluster_telemetry/",
+  ]
+}
+
 # New target that will replace telemetry_perf_tests when testing
 # is done.
 group("performance_test_suite") {
@@ -2753,7 +2765,6 @@
     "../browser/page_load_metrics/observers/scheme_page_load_metrics_observer_unittest.cc",
     "../browser/page_load_metrics/observers/service_worker_page_load_metrics_observer_unittest.cc",
     "../browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer_unittest.cc",
-    "../browser/page_load_metrics/observers/stale_while_revalidate_page_load_metrics_observer_unittest.cc",
     "../browser/page_load_metrics/observers/tab_restore_page_load_metrics_observer_unittest.cc",
     "../browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc",
     "../browser/page_load_metrics/observers/use_counter_page_load_metrics_observer_unittest.cc",
@@ -2777,7 +2788,7 @@
     "../browser/performance_manager/graph/process_node_impl_unittest.cc",
     "../browser/performance_manager/graph/properties_unittest.cc",
     "../browser/performance_manager/graph/system_node_impl_unittest.cc",
-    "../browser/performance_manager/observers/coordination_unit_graph_observer_unittest.cc",
+    "../browser/performance_manager/observers/graph_observer_unittest.cc",
     "../browser/performance_manager/observers/metrics_collector_unittest.cc",
     "../browser/performance_manager/observers/page_signal_generator_impl_unittest.cc",
     "../browser/performance_manager/observers/working_set_trimmer_win_unittest.cc",
@@ -4338,7 +4349,10 @@
         "../service/service_process_prefs_unittest.cc",
       ]
     } else {
-      sources += [ "../browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc" ]
+      sources += [
+        "../browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc",
+        "../browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc",
+      ]
     }
   }
 
@@ -4811,6 +4825,8 @@
       "base/javascript_browser_test.h",
       "base/mojo_web_ui_browser_test.cc",
       "base/mojo_web_ui_browser_test.h",
+      "base/perf/performance_test.cc",
+      "base/perf/performance_test.h",
       "base/test_chrome_web_ui_controller_factory.cc",
       "base/test_chrome_web_ui_controller_factory.h",
       "base/ui_test_utils.cc",
@@ -5209,10 +5225,7 @@
         # Use only the _chromeos version on Ash / Chrome OS.
         "../browser/ui/views/test/view_event_test_platform_part_default.cc",
       ]
-      sources += [
-        "../browser/ui/ash/drag_to_overview_interactive_uitest.cc",
-        "../browser/ui/ash/split_view_interactive_uitest.cc",
-      ]
+      sources += [ "../browser/ui/ash/split_view_interactive_uitest.cc" ]
     } else {  # ! is_chromeos
       # Non-ChromeOS notifications tests.
       sources += [
@@ -5329,6 +5342,10 @@
       sources += [ "../browser/ui/views/accessibility/browser_accessibility_uitest_auralinux.cc" ]
       configs += [ "//build/config/linux/atk" ]
     }
+
+    if (is_linux && !is_chromeos) {
+      deps += [ "//ui/base/ime/linux" ]
+    }
   }
 }
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java
index bfe7500..d7494452 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java
@@ -4,14 +4,50 @@
 
 package org.chromium.chrome.test;
 
-import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
 
-/** Custom ActivityTestRule for test using ChromeTabbedActivity
- *
- * TODO(yolandyan): remove this TestRule
+import org.chromium.base.test.util.UrlUtils;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.chromium.chrome.browser.feed.FeedNewTabPage;
+import org.chromium.chrome.browser.feed.FeedProcessScopeFactory;
+import org.chromium.chrome.browser.feed.TestNetworkClient;
+
+/**
+ * Custom ActivityTestRule for test using ChromeTabbedActivity
  */
 public class ChromeTabbedActivityTestRule extends ChromeActivityTestRule<ChromeTabbedActivity> {
+    // Response file for Feed's network stub.
+    // TODO(crbug.com/943874): Make this configurable.
+    public static final String FEED_TEST_RESPONSE_FILE_PATH =
+            "/chrome/test/data/android/feed/feed_large.gcl.bin";
+
     public ChromeTabbedActivityTestRule() {
         super(ChromeTabbedActivity.class);
     }
+
+    @Override
+    public Statement apply(final Statement base, Description description) {
+        Statement tabbedActivityStatement = new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                // Setup Feed stubs if Feed is enabled.
+                boolean feedStubsInitialized = false;
+                if (!FeedNewTabPage.isDummy()) {
+                    feedStubsInitialized = true;
+                    TestNetworkClient client = new TestNetworkClient();
+                    client.setNetworkResponseFile(
+                            UrlUtils.getIsolatedTestFilePath(FEED_TEST_RESPONSE_FILE_PATH));
+                    FeedProcessScopeFactory.setTestNetworkClient(client);
+                }
+
+                base.evaluate();
+
+                // Teardown the network stubs for Feed if they've been setup.
+                if (feedStubsInitialized) FeedProcessScopeFactory.setTestNetworkClient(null);
+            }
+        };
+
+        return super.apply(tabbedActivityStatement, description);
+    }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/partnercustomizations/TestPartnerBrowserCustomizationsDelayedProvider.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/partnercustomizations/TestPartnerBrowserCustomizationsDelayedProvider.java
index cb7d750..f4a4750b 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/partnercustomizations/TestPartnerBrowserCustomizationsDelayedProvider.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/partnercustomizations/TestPartnerBrowserCustomizationsDelayedProvider.java
@@ -12,6 +12,7 @@
 import org.chromium.base.annotations.MainDex;
 
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
 
 /**
  * PartnerBrowserCustomizationsProvider example for testing. This adds one second latency for
@@ -22,14 +23,20 @@
 public class TestPartnerBrowserCustomizationsDelayedProvider
         extends TestPartnerBrowserCustomizationsProvider {
     private static String sUriPathToDelay;
+    private static CountDownLatch sLatch;
 
     public TestPartnerBrowserCustomizationsDelayedProvider() {
         super();
         mTag = TestPartnerBrowserCustomizationsDelayedProvider.class.getSimpleName();
     }
 
+    public static void unblockQuery() {
+        sLatch.countDown();
+    }
+
     private void setUriPathToDelay(String path) {
         sUriPathToDelay = path;
+        sLatch = new CountDownLatch(1);
     }
 
     @Override
@@ -48,7 +55,7 @@
             if (sUriPathToDelay == null
                     || (pathSegments != null && !pathSegments.isEmpty()
                             && TextUtils.equals(pathSegments.get(0), sUriPathToDelay))) {
-                Thread.sleep(1000);
+                sLatch.await();
             }
         } catch (InterruptedException e) {
             assert false;
diff --git a/chrome/test/android/test_trusted_web_activity/src/org/chromium/chrome/browser/browserservices/TestTrustedWebActivityService.java b/chrome/test/android/test_trusted_web_activity/src/org/chromium/chrome/browser/browserservices/TestTrustedWebActivityService.java
index c1662aa..7e5de5f 100644
--- a/chrome/test/android/test_trusted_web_activity/src/org/chromium/chrome/browser/browserservices/TestTrustedWebActivityService.java
+++ b/chrome/test/android/test_trusted_web_activity/src/org/chromium/chrome/browser/browserservices/TestTrustedWebActivityService.java
@@ -18,7 +18,7 @@
     @Override
     public void onCreate() {
         super.onCreate();
-        TrustedWebActivityService.setVerifiedProviderForTesting(this, "org.chromium.chrome.tests");
+        TrustedWebActivityService.setVerifiedProvider(this, "org.chromium.chrome.tests");
     }
 
     @Override
diff --git a/chrome/test/base/perf/performance_test.cc b/chrome/test/base/perf/performance_test.cc
new file mode 100644
index 0000000..fcdb011
--- /dev/null
+++ b/chrome/test/base/perf/performance_test.cc
@@ -0,0 +1,70 @@
+// Copyright 2019 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/test/base/perf/performance_test.h"
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/trace_event/trace_event.h"
+#include "content/public/browser/tracing_controller.h"
+#include "services/tracing/public/cpp/trace_event_agent.h"
+#include "ui/compositor/compositor_switches.h"
+#include "ui/gl/gl_switches.h"
+
+static const char kTraceDir[] = "trace-dir";
+
+PerformanceTest::PerformanceTest()
+    : should_start_trace_(
+          base::CommandLine::ForCurrentProcess()->HasSwitch(kTraceDir)) {
+  if (should_start_trace_) {
+    auto* cmd = base::CommandLine::ForCurrentProcess();
+    cmd->AppendSwitch(switches::kUseGpuInTests);
+    cmd->AppendSwitch(switches::kEnablePixelOutputInTests);
+  }
+}
+
+PerformanceTest::~PerformanceTest() = default;
+
+std::vector<std::string> PerformanceTest::GetUMAHistogramNames() const {
+  return {};
+}
+
+const std::string PerformanceTest::GetTracingCategories() const {
+  return std::string();
+}
+
+void PerformanceTest::SetUpOnMainThread() {
+  InProcessBrowserTest::SetUpOnMainThread();
+  if (!should_start_trace_)
+    return;
+
+  auto* controller = content::TracingController::GetInstance();
+  base::trace_event::TraceConfig config(GetTracingCategories(),
+                                        base::trace_event::RECORD_CONTINUOUSLY);
+  for (const auto& histogram : GetUMAHistogramNames())
+    config.EnableHistogram(histogram);
+
+  base::RunLoop runloop;
+  bool result = controller->StartTracing(config, runloop.QuitClosure());
+  runloop.Run();
+  CHECK(result);
+}
+
+void PerformanceTest::TearDownOnMainThread() {
+  if (should_start_trace_) {
+    auto* controller = content::TracingController::GetInstance();
+    base::RunLoop runloop;
+    base::FilePath dir =
+        base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(kTraceDir);
+    base::FilePath trace_file;
+    CHECK(base::CreateTemporaryFileInDir(dir, &trace_file));
+
+    auto trace_data_endpoint = content::TracingController::CreateFileEndpoint(
+        trace_file, runloop.QuitClosure());
+    bool result = controller->StopTracing(trace_data_endpoint);
+    runloop.Run();
+    CHECK(result);
+  }
+  InProcessBrowserTest::TearDownOnMainThread();
+}
diff --git a/chrome/test/base/perf/performance_test.h b/chrome/test/base/perf/performance_test.h
new file mode 100644
index 0000000..da4a35b
--- /dev/null
+++ b/chrome/test/base/perf/performance_test.h
@@ -0,0 +1,36 @@
+// Copyright 2019 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_TEST_BASE_PERF_PERFORMANCE_TEST_H_
+#define CHROME_TEST_BASE_PERF_PERFORMANCE_TEST_H_
+
+#include "chrome/test/base/in_process_browser_test.h"
+
+// PerformanceTest is an interactive-ui-test that can be used to collect traces.
+// The traces can then be post-processed, e.g. using catapult, to report
+// performance metrics. The GetUMAHistogramNames() and GetTracingCategories()
+// overrides can be used to specify which trace-events and which UMA histograms
+// should be collected in the trace files. The trace-file location must be set
+// using the --trace-dir=<path> command-line flag. If the flag is not given,
+// then the test will still run, but not produce any traces.
+class PerformanceTest : public InProcessBrowserTest {
+ public:
+  PerformanceTest();
+  ~PerformanceTest() override;
+
+  PerformanceTest(const PerformanceTest&) = delete;
+  PerformanceTest& operator=(const PerformanceTest&) = delete;
+
+  virtual std::vector<std::string> GetUMAHistogramNames() const;
+  virtual const std::string GetTracingCategories() const;
+
+  // InProcessBrowserTest:
+  void SetUpOnMainThread() override;
+  void TearDownOnMainThread() override;
+
+ private:
+  const bool should_start_trace_;
+};
+
+#endif  // CHROME_TEST_BASE_PERF_PERFORMANCE_TEST_H_
diff --git a/chrome/test/chromedriver/chrome/status.cc b/chrome/test/chromedriver/chrome/status.cc
index 67fc02f..f878cdc 100644
--- a/chrome/test/chromedriver/chrome/status.cc
+++ b/chrome/test/chromedriver/chrome/status.cc
@@ -7,10 +7,8 @@
 #include "base/debug/stack_trace.h"
 #include "base/strings/stringprintf.h"
 
-namespace {
-
 // Returns the string equivalent of the given |ErrorCode|.
-const char* DefaultMessageForStatusCode(StatusCode code) {
+const char* StatusCodeToString(StatusCode code) {
   switch (code) {
     case kOk:
       return "ok";
@@ -81,35 +79,30 @@
   }
 }
 
-}  // namespace
-
-Status::Status(StatusCode code)
-    : code_(code), msg_(DefaultMessageForStatusCode(code)) {
+Status::Status(StatusCode code) : code_(code), msg_(StatusCodeToString(code)) {
   if (code != kOk)
     stack_trace_ = base::debug::StackTrace().ToString();
 }
 
 Status::Status(StatusCode code, const std::string& details)
     : code_(code),
-      msg_(DefaultMessageForStatusCode(code) + std::string(": ") + details) {
+      msg_(StatusCodeToString(code) + std::string(": ") + details) {
   if (code != kOk)
         stack_trace_ = base::debug::StackTrace().ToString();
 }
 
 Status::Status(StatusCode code, const Status& cause)
     : code_(code),
-      msg_(DefaultMessageForStatusCode(code) + std::string("\nfrom ") +
+      msg_(StatusCodeToString(code) + std::string("\nfrom ") +
            cause.message()) {
   if (code != kOk)
     stack_trace_ = cause.stack_trace();
 }
 
-Status::Status(StatusCode code,
-               const std::string& details,
-               const Status& cause)
+Status::Status(StatusCode code, const std::string& details, const Status& cause)
     : code_(code),
-      msg_(DefaultMessageForStatusCode(code) + std::string(": ") + details +
-           "\nfrom " + cause.message()) {
+      msg_(StatusCodeToString(code) + std::string(": ") + details + "\nfrom " +
+           cause.message()) {
   if (code != kOk)
     stack_trace_ = cause.stack_trace();
 }
diff --git a/chrome/test/chromedriver/chrome/status.h b/chrome/test/chromedriver/chrome/status.h
index 44e9a832..1b745ef 100644
--- a/chrome/test/chromedriver/chrome/status.h
+++ b/chrome/test/chromedriver/chrome/status.h
@@ -70,4 +70,8 @@
   std::string stack_trace_;
 };
 
+// Returns the standard error code string associated with a StatusCode, as
+// defined by W3C (https://w3c.github.io/webdriver/#dfn-error-code).
+const char* StatusCodeToString(StatusCode code);
+
 #endif  // CHROME_TEST_CHROMEDRIVER_CHROME_STATUS_H_
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc
index f844136..bbbf66f 100644
--- a/chrome/test/chromedriver/server/http_handler.cc
+++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -1142,24 +1142,10 @@
 
   base::DictionaryValue body_params;
   if (status.IsError()){
-    // Separates status default message from additional details.
-    std::string error;
-    std::string message(status.message());
-    std::string::size_type separator = message.find_first_of(":\n");
-    if (separator == std::string::npos) {
-      error = message;
-      message.clear();
-    } else {
-      error = message.substr(0, separator);
-      separator++;
-      while (separator < message.length() && message[separator] == ' ')
-        separator++;
-      message = message.substr(separator);
-    }
     std::unique_ptr<base::DictionaryValue> inner_params(
         new base::DictionaryValue());
-    inner_params->SetString("error", error);
-    inner_params->SetString("message", message);
+    inner_params->SetString("error", StatusCodeToString(status.code()));
+    inner_params->SetString("message", status.message());
     inner_params->SetString("stacktrace", status.stack_trace());
     body_params.SetDictionary("value", std::move(inner_params));
   } else {
diff --git a/chrome/test/data/arc_graphics_tracing/gm_bad_no_view_buffers.json b/chrome/test/data/arc_graphics_tracing/gm_bad_no_view_buffers.json
index 7970848a..c22f730 100644
--- a/chrome/test/data/arc_graphics_tracing/gm_bad_no_view_buffers.json
+++ b/chrome/test/data/arc_graphics_tracing/gm_bad_no_view_buffers.json
@@ -4,6 +4,7 @@
                 "global_events": [ ] },
    "chrome": { "buffers": [ [ [ 500, 1667.0 ], [ 501, 1808.0 ] ] ],
                 "global_events": [ ]  },
+   "cpu": { "threads": {}, "events": []},
    "duration": 1053800.0,
    "views": [ {
       "activity": "com.android.vending/com.android.vending.AssetBrowserActivity",
diff --git a/chrome/test/data/arc_graphics_tracing/gm_bad_no_view_desc.json b/chrome/test/data/arc_graphics_tracing/gm_bad_no_view_desc.json
index ca3463d..f9006a0 100644
--- a/chrome/test/data/arc_graphics_tracing/gm_bad_no_view_desc.json
+++ b/chrome/test/data/arc_graphics_tracing/gm_bad_no_view_desc.json
@@ -5,6 +5,7 @@
    "chrome": { "buffers": [ [ [ 500, 1667.0 ], [ 501, 1808.0 ] ] ],
                 "global_events": [ ]  },
    "duration": 1053800.0,
+   "cpu": { "threads": {}, "events": []},
    "views": [ {
       "buffers": [ [ [ 200, 0.0 ], [ 201, 149.0 ] ], [ [ 300, 168.0 ], [ 202, 173.0 ] ] ],
       "global_events": [ ],
diff --git a/chrome/test/data/arc_graphics_tracing/gm_bad_wrong_timestamp.json b/chrome/test/data/arc_graphics_tracing/gm_bad_wrong_timestamp.json
index 3cdd40d6a..36ba418 100644
--- a/chrome/test/data/arc_graphics_tracing/gm_bad_wrong_timestamp.json
+++ b/chrome/test/data/arc_graphics_tracing/gm_bad_wrong_timestamp.json
@@ -4,6 +4,7 @@
                 "global_events": [ ] },
    "chrome": { "buffers": [ [ [ 500, 1667.0 ], [ 501, 1808.0 ] ] ],
                 "global_events": [ ]  },
+   "cpu": { "threads": {}, "events": []},
    "duration": 1053800.0,
    "views": [ {
       "activity": "com.android.vending/com.android.vending.AssetBrowserActivity",
diff --git a/chrome/test/data/arc_graphics_tracing/gm_good.json b/chrome/test/data/arc_graphics_tracing/gm_good.json
index 8f228600..93def21f 100644
--- a/chrome/test/data/arc_graphics_tracing/gm_good.json
+++ b/chrome/test/data/arc_graphics_tracing/gm_good.json
@@ -4,6 +4,7 @@
                 "global_events": [ ] },
    "chrome": { "buffers": [ [ [ 500, 1667.0 ], [ 501, 1808.0 ] ] ],
                 "global_events": [ ]  },
+   "cpu": { "threads": {}, "events": []},
    "duration": 1053800.0,
    "views": [ {
       "activity": "com.android.vending/com.android.vending.AssetBrowserActivity",
diff --git a/chrome/test/data/chromeos/login/saml_with_password_attributes.xml b/chrome/test/data/chromeos/login/saml_with_password_attributes.xml
index 06cd955..5246964 100644
--- a/chrome/test/data/chromeos/login/saml_with_password_attributes.xml
+++ b/chrome/test/data/chromeos/login/saml_with_password_attributes.xml
@@ -54,6 +54,9 @@
       <Attribute Name="http://schemas.google.com/saml/2019/passwordexpirationtimestamp">
         <AttributeValue>131963466584212478</AttributeValue>
       </Attribute>
+      <Attribute Name="http://schemas.google.com/saml/2019/passwordchangeurl">
+        <AttributeValue>https://example.com/adfs/portal/updatepassword/</AttributeValue>
+      </Attribute>
     </AttributeStatement>
     <AuthnStatement AuthnInstant="2019-02-22T11:51:03.358Z" SessionIndex="_573cbf2c-2f08-428c-8cbf-2f4d6307baaf">
       <AuthnContext>
diff --git a/chrome/test/data/extensions/api_test/automation/sites/detected_language.html b/chrome/test/data/extensions/api_test/automation/sites/detected_language.html
new file mode 100644
index 0000000..a9328012
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/automation/sites/detected_language.html
@@ -0,0 +1,16 @@
+<!--
+ * Copyright 2019 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.
+-->
+<html>
+<head>
+<title>Automation Tests - Language Detection</title>
+<meta charset="utf-8">
+</head>
+<body>
+  <div lang="fr" class="magritte">“The famous pipe. How people reproached me for it! And yet, could you stuff my pipe? No, it’s just a representation, is it not? So if I had written on my picture ‘This is a pipe,’ I’d have been lying!"</div>
+
+  <div lang="en" class="magritte">« La fameuse pipe, me l’a-t-on assez reprochée ! Et pourtant, pouvez-vous la bourrer ma pipe ? Non, n’est-ce pas, elle n’est qu’une représentation. Donc si j’avais écrit sous mon tableau « ceci est une pipe », j’aurais menti ! »</div>
+</body>
+</html>
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/detected_language.html b/chrome/test/data/extensions/api_test/automation/tests/tabs/detected_language.html
new file mode 100644
index 0000000..7e08c080
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/detected_language.html
@@ -0,0 +1,7 @@
+<!--
+ * Copyright 2019 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.
+-->
+<script src="common.js"></script>
+<script src="detected_language.js"></script>
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/detected_language.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/detected_language.js
new file mode 100644
index 0000000..166a8e9d
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/detected_language.js
@@ -0,0 +1,25 @@
+// Copyright 2019 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.
+
+var allTests = [
+  function detectedLanguageSetOnFirst() {
+    var first = rootNode.children[0].children[0];
+    assertEq('staticText', first.role);
+    assertEq('fr', first.language, 'document manually declares lang="fr"');
+    assertEq('en', first.detectedLanguage,
+      'detected language should be English');
+    chrome.test.succeed();
+  },
+
+  function detectedLanguageSetOnSecond() {
+    var second = rootNode.children[1].children[0];
+    assertEq('staticText', second.role);
+    assertEq('en', second.language, 'document manually declares lang="en"');
+    assertEq('fr', second.detectedLanguage,
+      'detected language should be French');
+    chrome.test.succeed();
+  }
+];
+
+setUpAndRunTests(allTests, 'detected_language.html');
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_blocking/manifest.json b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_blocking/manifest.json
new file mode 100644
index 0000000..2a7bc08
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_blocking/manifest.json
@@ -0,0 +1,8 @@
+{
+  "name": "Service Worker-based background script",
+  "version": "0.1",
+  "manifest_version": 2,
+  "description": "Test webRequest APIs for service worker-based background scripts.",
+  "permissions": ["webRequest", "webRequestBlocking", "<all_urls>"],
+  "background": {"service_worker": "service_worker_background.js"}
+}
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_blocking/service_worker_background.js b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_blocking/service_worker_background.js
new file mode 100644
index 0000000..7159b05
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/web_request_blocking/service_worker_background.js
@@ -0,0 +1,12 @@
+// Copyright 2019 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.
+
+// Register a listener with a callback that blocks all requests.
+chrome.webRequest.onBeforeRequest.addListener(function localListener(details) {
+  chrome.webRequest.onBeforeRequest.removeListener(localListener);
+  return {cancel: true};
+}, { urls: ['<all_urls>']}, ['blocking']);
+
+// Tell the C++ side of things to proceed with the test.
+chrome.test.sendMessage('ready');
diff --git a/chrome/test/data/extensions/theme/Cached Theme.pak b/chrome/test/data/extensions/theme/Cached Theme.pak
index c65f898..c55c07c 100644
--- a/chrome/test/data/extensions/theme/Cached Theme.pak
+++ b/chrome/test/data/extensions/theme/Cached Theme.pak
Binary files differ
diff --git a/chrome/test/data/local_ntp/custom_backgrounds_browsertest.js b/chrome/test/data/local_ntp/custom_backgrounds_browsertest.js
index bb13af95..a98f61b 100644
--- a/chrome/test/data/local_ntp/custom_backgrounds_browsertest.js
+++ b/chrome/test/data/local_ntp/custom_backgrounds_browsertest.js
@@ -237,7 +237,6 @@
 
 
 // TODO(crbug.com/857256): add tests for:
-//  * Image attributions.
 //  * Image upload flow.
 //  * Online/offline.
 
diff --git a/chrome/test/data/prerender/prerender_fragment_location_hash.html b/chrome/test/data/prerender/prerender_fragment_location_hash.html
deleted file mode 100644
index 6ba0a66..0000000
--- a/chrome/test/data/prerender/prerender_fragment_location_hash.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<html>
-<head>
-<title>Prerender fragment testing under location.hash change</title>
-
-<script>
-if (window.location.hash === "") {
-  window.location.hash = "fragment";
-}
-
-var pageWasPrerendered = false;
-
-function DidPrerenderPass() {
-  pageWasPrerendered = true;
-  return window.location.hash === "#fragment";
-}
-
-// Make sure DidPrerenderPass() was called first.  Otherwise, the page was
-// most likely reloaded instead of using the prerendered page.
-function DidDisplayPass() {
-  return pageWasPrerendered && window.location.hash === "#fragment";
-}
-
-</script>
-
-</head>
-<body>
-  <a name="fragment">Fragment</a>
-</body>
-</html>
-
diff --git a/chrome/test/data/prerender/prerender_html5_audio_jsplay.html b/chrome/test/data/prerender/prerender_html5_audio_jsplay.html
deleted file mode 100644
index 91aaab7..0000000
--- a/chrome/test/data/prerender/prerender_html5_audio_jsplay.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<html>
-  <!--
-  This test checks that:
-    - Audio tags are deferred during prerendering.
-    - The audio starts playing on page swap in when it has been played by js.
-  -->
-<head>
-<title>Prerender for HTML5 audio.</title>
-</head>
-
-<body>
-<audio id="mediaEl" src="bear.wav" controls>
-</audio>
-
-<script>
-  var willPlay = true;
-  var testNetworkEvents = false;
-</script>
-
-<script src="prerender_html5_common.js"></script>
-
-<script>
-  document.getElementById("mediaEl").play();
-</script>
-
-</body>
-</html>
diff --git a/chrome/test/data/prerender/prerender_html5_video_network.html b/chrome/test/data/prerender/prerender_html5_video_network.html
deleted file mode 100644
index 8918f54..0000000
--- a/chrome/test/data/prerender/prerender_html5_video_network.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<html>
-  <!--
-  This test checks that video tags created by javascript are are deferred
-  during prerendering and the autoplay is enabled during swap ins.
-  -->
-<head>
-<title>Prerender for HTML5 video.</title>
-</head>
-
-<body>
-<video id="mediaEl" controls>
-</video>
-
-<script>
-  var willPlay = true;
-  var testNetworkEvents = true;
-</script>
-
-<script src="prerender_html5_common.js"></script>
-
-<script>
-  mediaEl.src = 'bear.ogv'
-  mediaEl.play();
-</script>
-
-</body>
-</html>
diff --git a/chrome/test/data/prerender/prerender_location_replace.html b/chrome/test/data/prerender/prerender_location_replace.html
deleted file mode 100644
index 7944f3b..0000000
--- a/chrome/test/data/prerender/prerender_location_replace.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<html>
-  <!--
-  This test navigates to prerender_page.html via location.replace.
-  -->
-  <head>
-    <title>Prerender location.replace after load</title>
-    <script>
-      window.onload = function() {
-        setTimeout(function() {
-          // Wait until after load so webkitprerenderload counts aren't flaky.
-          var url = "prerender_page.html";
-          if (location.search)
-            url = decodeURIComponent(location.search.substring(1));
-          location.replace(url);
-        });
-      };
-    </script>
-  </head>
-  <body></body>
-</html>
diff --git a/chrome/test/data/prerender/prerender_page_pending.html b/chrome/test/data/prerender/prerender_page_pending.html
deleted file mode 100644
index e325399..0000000
--- a/chrome/test/data/prerender/prerender_page_pending.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<html>
-<!-- 
-This test checks to make sure that pending prerenders start at page launch,
-but not earlier.
--->
-<link id=thePrerender rel=prerender href="prerender_page.html" />
-<head>
-<title>Prerender Page</title>
-
-<script src="prerender_events_common.js"></script>
-
-<script>
-var pageWasPrerendered = false;
-
-function DidPrerenderPass() {
-  pageWasPrerendered = true;
-  return !GetPrerenderEventCount(0, 'webkitprerenderstart');
-}
-
-// Make sure DidPrerenderPass() was called first.  Otherwise, the page was
-// most likely reloaded instead of using the prerendered page.
-function DidDisplayPass() {
-  return pageWasPrerendered;
-}
-
-var link = document.getElementById('thePrerender');
-AddEventHandlersToLinkElement(link, 0);
-</script>
-
-</head>
-<body></body>
-</html>
diff --git a/chrome/test/data/prerender/prerender_plugin_nacl_disabled.html b/chrome/test/data/prerender/prerender_plugin_nacl_disabled.html
deleted file mode 100644
index 2d8a2da5..0000000
--- a/chrome/test/data/prerender/prerender_plugin_nacl_disabled.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<html>
-<!--
-Make sure prerendering doesn't load NaCl plugins when disabled.
--->
-<head>
-<title>Prerender NaCl Disabled</title>
-</head>
-<body>
-
-<script>
-var pluginLoadStarted = false;
-
-function eventListener(event) {
-  var targetElement = event.target;
-  if (event.target.id != 'naclPlugin')
-    return;
-  pluginLoadStarted = true;
-}
-
-document.body.addEventListener('loadstart', eventListener, true);
-
-function DidPrerenderPass() {
-  return !pluginLoadStarted;
-}
-
-function DidDisplayPass() {
-  return !pluginLoadStarted;
-}
-</script>
-
-<embed id="naclPlugin" type="application/x-nacl" src="dummy.nmf"></embed>
-</body>
-</html>
diff --git a/chrome/test/data/prerender/prerender_plugin_never_load.html b/chrome/test/data/prerender/prerender_plugin_never_load.html
deleted file mode 100644
index 84dc722..0000000
--- a/chrome/test/data/prerender/prerender_plugin_never_load.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<html>
-<!--
-This test checks to make sure plugins aren't loaded when a page is prerendered,
-and are also not loaded once the page is displayed. This is used to test certain
-content settings that do not allow plugin loading.
-
-This test relies on the Pepper plugin (but not the placeholder) implementing
-the postMessage() function on the plugin object.
--->
-<head>
-<title>Prerender Plugin Never Load</title>
-
-<script>
-// Make sure plugin was not loaded while prerendering.
-function DidPrerenderPass() {
-  // |plugin| should be the blocked plugin placeholder, rather than the
-  // test plugin.
-  var plugin = window.document['plugin'];
-  return plugin.postMessage == undefined;
-}
-
-// Make sure plugin still does not load once the page is displayed.
-function DidDisplayPass() {
-  var plugin = window.document['plugin'];
-  return plugin.postMessage == undefined;
-}
-</script>
-
-</head>
-<body>
-<embed name="plugin" type="application/x-ppapi-tests"></embed>
-</body>
-</html>
diff --git a/chrome/test/data/prerender/prerender_size.html b/chrome/test/data/prerender/prerender_size.html
deleted file mode 100644
index 025bb03..0000000
--- a/chrome/test/data/prerender/prerender_size.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<html>
-<!-- 
-Checks that a prerendered page gets the correct window size.
--->
-<head>
-<title>Prerender Window Size Test</title>
-
-<script>
-var width = window.innerWidth;
-var height = window.innerHeight;
-
-// Make sure width and height are positive.
-function DidPrerenderPass() {
-  return width > 0 && height > 0;
-}
-
-// Make sure width and height are the same as when prerendering.
-function DidDisplayPass() {
-  return width == window.innerWidth && height == window.innerHeight;
-}
-</script>
-
-</head>
-<body></body>
-</html>
diff --git a/chrome/test/data/prerender/prerender_xhr_get.html b/chrome/test/data/prerender/prerender_xhr_get.html
deleted file mode 100644
index 2ddaf4c..0000000
--- a/chrome/test/data/prerender/prerender_xhr_get.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<html>
-  <head>
-    <script>
-      var pageWasPrerendered = false;
-
-      // Make sure plugin was not loaded while prerendering.
-      function DidPrerenderPass() {
-        pageWasPrerendered = true;
-        return true;
-      }
-
-      // Make sure DidPrerenderPass() was called first.  Otherwise, the page was
-      // most likely reloaded instead of using the prerendered page.
-      function DidDisplayPass() {
-        return pageWasPrerendered;
-      }
-
-      function do_xhr() {
-        var xhr = new XMLHttpRequest();
-        xhr.onreadystatechange  = function() {
-          if(xhr.readyState == 4) {
-            if(xhr.status == 200) {
-              document.getElementById("dynamic").innerHTML =
-                  "Received:"  + xhr.responseText;
-            } else {
-              document.getElementById("dynamic").innerHTML =
-                  "Error code: " + xhr.status;
-            }
-          }
-        };
-
-        xhr.open("GET", "prerender_xhr_get.html", true);
-        xhr.send(null);
-      }
-
-      do_xhr();
-    </script>
-  </head>
-  <body>
-    <div id="dynamic">
-      Waiting for XHR response.
-    </div>
- </body>
-</html>
diff --git a/chrome/test/data/prerender/prerender_xhr_head.html b/chrome/test/data/prerender/prerender_xhr_head.html
deleted file mode 100644
index d78e921..0000000
--- a/chrome/test/data/prerender/prerender_xhr_head.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<html>
-  <head>
-    <script>
-      var pageWasPrerendered = false;
-
-      // Make sure plugin was not loaded while prerendering.
-      function DidPrerenderPass() {
-        pageWasPrerendered = true;
-        return true;
-      }
-
-      // Make sure DidPrerenderPass() was called first.  Otherwise, the page was
-      // most likely reloaded instead of using the prerendered page.
-      function DidDisplayPass() {
-        return pageWasPrerendered;
-      }
-
-      function do_xhr() {
-        var xhr = new XMLHttpRequest();
-        xhr.onreadystatechange  = function() {
-          if(xhr.readyState == 4) {
-            if(xhr.status == 200) {
-              document.getElementById("dynamic").innerHTML =
-                  "Received:"  + xhr.responseText;
-            } else {
-              document.getElementById("dynamic").innerHTML =
-                  "Error code: " + xhr.status;
-            }
-          }
-        };
-
-        xhr.open("HEAD", "prerender_xhr_head.html", true);
-        xhr.send(null);
-      }
-
-      do_xhr();
-    </script>
-  </head>
-  <body>
-    <div id="dynamic">
-      Waiting for XHR response.
-    </div>
- </body>
-</html>
diff --git a/chrome/test/data/prerender/prerender_xhr_options.html b/chrome/test/data/prerender/prerender_xhr_options.html
deleted file mode 100644
index c36ab4a..0000000
--- a/chrome/test/data/prerender/prerender_xhr_options.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<html>
-  <head>
-    <script>
-      var pageWasPrerendered = false;
-
-      // Make sure plugin was not loaded while prerendering.
-      function DidPrerenderPass() {
-        pageWasPrerendered = true;
-        return true;
-      }
-
-      // Make sure DidPrerenderPass() was called first.  Otherwise, the page was
-      // most likely reloaded instead of using the prerendered page.
-      function DidDisplayPass() {
-        return pageWasPrerendered;
-      }
-
-      function do_xhr() {
-        var xhr = new XMLHttpRequest();
-        xhr.onreadystatechange  = function() {
-          if(xhr.readyState == 4) {
-            if(xhr.status == 200) {
-              document.getElementById("dynamic").innerHTML =
-                  "Received:"  + xhr.responseText;
-            } else {
-              document.getElementById("dynamic").innerHTML =
-                  "Error code: " + xhr.status;
-            }
-          }
-        };
-
-        xhr.open("OPTIONS", "http://127.0.0.1/", true);
-        xhr.send(null);
-      }
-
-      do_xhr();
-    </script>
-  </head>
-  <body>
-    <div id="dynamic">
-      Waiting for XHR response.
-    </div>
- </body>
-</html>
diff --git a/chrome/test/data/prerender/prerender_xhr_post.html b/chrome/test/data/prerender/prerender_xhr_post.html
deleted file mode 100644
index f6b3240..0000000
--- a/chrome/test/data/prerender/prerender_xhr_post.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<html>
-  <head>
-    <script>
-      var pageWasPrerendered = false;
-
-      // Make sure plugin was not loaded while prerendering.
-      function DidPrerenderPass() {
-        pageWasPrerendered = true;
-        return true;
-      }
-
-      // Make sure DidPrerenderPass() was called first.  Otherwise, the page was
-      // most likely reloaded instead of using the prerendered page.
-      function DidDisplayPass() {
-        return pageWasPrerendered;
-      }
-
-      function do_xhr() {
-        var xhr = new XMLHttpRequest();
-        xhr.onreadystatechange  = function() {
-          if(xhr.readyState  == 4) {
-            if(xhr.status  == 200) {
-              document.getElementById("dynamic").innerHTML =
-                  "Received:"  + xhr.responseText;
-            } else {
-              document.getElementById("dynamic").innerHTML =
-                  "Error code: " + xhr.status;
-            }
-          }
-        };
-        xhr.open("POST", "prerender_xhr_post.html", true);
-        xhr.setRequestHeader("Content-Type", "text/plain");
-        xhr.send("test");
-      }
-
-      do_xhr();
-    </script>
-  </head>
-  <body>
-    <div id="dynamic">
-      Waiting for XHR response.
-    </div>
- </body>
-</html>
diff --git a/chrome/test/data/prerender/prerender_xhr_trace.html b/chrome/test/data/prerender/prerender_xhr_trace.html
deleted file mode 100644
index 3ea7ca32..0000000
--- a/chrome/test/data/prerender/prerender_xhr_trace.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<html>
-  <head>
-    <script>
-      var pageWasPrerendered = false;
-
-      // Make sure plugin was not loaded while prerendering.
-      function DidPrerenderPass() {
-        pageWasPrerendered = true;
-        return true;
-      }
-
-      // Make sure DidPrerenderPass() was called first.  Otherwise, the page was
-      // most likely reloaded instead of using the prerendered page.
-      function DidDisplayPass() {
-        return pageWasPrerendered;
-      }
-
-      function do_xhr() {
-        var xhr = new XMLHttpRequest();
-        xhr.onreadystatechange  = function() {
-          if(xhr.readyState == 4) {
-            if(xhr.status == 200) {
-              document.getElementById("dynamic").innerHTML =
-                  "Received:"  + xhr.responseText;
-            } else {
-              document.getElementById("dynamic").innerHTML =
-                  "Error code: " + xhr.status;
-            }
-          }
-        };
-
-        xhr.open("TRACE", "http://127.0.0.1/", true);
-        xhr.send(null);
-      }
-
-      do_xhr();
-    </script>
-  </head>
-  <body>
-    <div id="dynamic">
-      Waiting for XHR response.
-    </div>
- </body>
-</html>
diff --git a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
index 195c8c6..226487c 100644
--- a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
+++ b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
@@ -444,6 +444,10 @@
   this.runMochaTest(extension_manager_tests.TestNames.ItemOrder);
 });
 
+TEST_F('CrExtensionsManagerUnitTest', 'SetItemData', function() {
+  this.runMochaTest(extension_manager_tests.TestNames.SetItemData);
+});
+
 TEST_F('CrExtensionsManagerUnitTest', 'UpdateItemData', function() {
   this.runMochaTest(extension_manager_tests.TestNames.UpdateItemData);
 });
diff --git a/chrome/test/data/webui/extensions/manager_unit_test.js b/chrome/test/data/webui/extensions/manager_unit_test.js
index 7796bad..dc4f40e4 100644
--- a/chrome/test/data/webui/extensions/manager_unit_test.js
+++ b/chrome/test/data/webui/extensions/manager_unit_test.js
@@ -14,6 +14,7 @@
     ToggleIncognitoMode: 'toggle incognito mode',
     Uninstall: 'uninstall',
     UninstallFromDetails: 'uninstall while in details view',
+    SetItemData: 'set item data',
     UpdateItemData: 'update item data',
     UpdateFromActivityLog: 'update from activity log',
     KioskMode: 'kiosk mode',
@@ -114,6 +115,26 @@
       expectEquals(alphaFromStore.id, manager.extensions_[5].id);
     });
 
+    test(assert(TestNames.SetItemData), function() {
+      const description = 'description';
+
+      const extension =
+          extension_test_util.createExtensionInfo({description: description});
+      simulateExtensionInstall(extension);
+
+      // The detail view is not present until navigation.
+      expectFalse(!!manager.$$('extensions-detail-view'));
+      extensions.navigation.navigateTo(
+          {page: Page.DETAILS, extensionId: extension.id});
+      const detailsView = manager.$$('extensions-detail-view');
+      expectTrue(!!detailsView);  // View should now be present.
+      expectEquals(extension.id, detailsView.data.id);
+      expectEquals(description, detailsView.data.description);
+      expectEquals(
+          description,
+          detailsView.$$('.section .section-content').textContent.trim());
+    });
+
     test(assert(TestNames.UpdateItemData), function() {
       const oldDescription = 'old description';
       const newDescription = 'new description';
@@ -127,19 +148,9 @@
       });
       simulateExtensionInstall(secondExtension);
 
-      let data = manager.extensions_[0];
-      // The detail view is not present until navigation.
-      expectFalse(!!manager.$$('extensions-detail-view'));
-      // TODO(scottchen): maybe testing too many things in a single unit test.
       extensions.navigation.navigateTo(
           {page: Page.DETAILS, extensionId: extension.id});
       const detailsView = manager.$$('extensions-detail-view');
-      expectTrue(!!detailsView);  // View should now be present.
-      expectEquals(extension.id, detailsView.data.id);
-      expectEquals(oldDescription, detailsView.data.description);
-      expectEquals(
-          oldDescription,
-          detailsView.$$('.section .section-content').textContent.trim());
 
       let extensionCopy = Object.assign({}, extension);
       extensionCopy.description = newDescription;
@@ -147,11 +158,6 @@
         event_type: chrome.developerPrivate.EventType.PREFS_CHANGED,
         extensionInfo: extensionCopy,
       });
-      expectEquals(extension.id, detailsView.data.id);
-      expectEquals(newDescription, detailsView.data.description);
-      expectEquals(
-          newDescription,
-          detailsView.$$('.section .section-content').textContent.trim());
 
       // Updating a different extension shouldn't have any impact.
       let secondExtensionCopy = Object.assign({}, secondExtension);
diff --git a/chrome/test/data/webui/print_preview/button_strip_interactive_test.js b/chrome/test/data/webui/print_preview/button_strip_interactive_test.js
new file mode 100644
index 0000000..6f1fc4b
--- /dev/null
+++ b/chrome/test/data/webui/print_preview/button_strip_interactive_test.js
@@ -0,0 +1,50 @@
+// Copyright 2019 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.define('button_strip_interactive_test', function() {
+  /** @enum {string} */
+  const TestNames = {
+    FocusPrintOnReady: 'focus print on ready',
+  };
+
+  const suiteName = 'ButtonStripInteractiveTest';
+
+  suite(suiteName, function() {
+    /** @type {?PrintPreviewButtonStripElement} */
+    let buttonStrip = null;
+
+    /** @override */
+    setup(function() {
+      loadTimeData.overrideValues({
+        newPrintPreviewLayoutEnabled: true,
+      });
+      PolymerTest.clearBody();
+
+      buttonStrip = document.createElement('print-preview-button-strip');
+      buttonStrip.destination = new print_preview.Destination(
+          'FooDevice', print_preview.DestinationType.GOOGLE,
+          print_preview.DestinationOrigin.COOKIES, 'FooName',
+          print_preview.DestinationConnectionStatus.ONLINE);
+      buttonStrip.state = print_preview_new.State.NOT_READY;
+      document.body.appendChild(buttonStrip);
+    });
+
+    // Tests that the print button is automatically focused when the destination
+    // is ready.
+    test(assert(TestNames.FocusPrintOnReady), function() {
+      const printButton = buttonStrip.$$('.action-button');
+      assertTrue(!!printButton);
+      const whenFocusDone = test_util.eventToPromise('focus', printButton);
+
+      // Simulate initialization finishing.
+      buttonStrip.state = print_preview_new.State.READY;
+      return whenFocusDone;
+    });
+  });
+
+  return {
+    suiteName: suiteName,
+    TestNames: TestNames,
+  };
+});
diff --git a/chrome/test/data/webui/print_preview/button_strip_test.js b/chrome/test/data/webui/print_preview/button_strip_test.js
new file mode 100644
index 0000000..693f8b0
--- /dev/null
+++ b/chrome/test/data/webui/print_preview/button_strip_test.js
@@ -0,0 +1,97 @@
+// Copyright 2019 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.define('button_strip_test', function() {
+  /** @enum {string} */
+  const TestNames = {
+    ButtonStripChangesForState: 'button strip changes for state',
+    ButtonOrder: 'button order',
+    ButtonStripFiresEvents: 'button strip fires events',
+  };
+
+  const suiteName = 'ButtonStripTest';
+  suite(suiteName, function() {
+    /** @type {?PrintPreviewButtonStripElement} */
+    let buttonStrip = null;
+
+    /** @override */
+    setup(function() {
+      loadTimeData.overrideValues({
+        newPrintPreviewLayoutEnabled: true,
+      });
+      PolymerTest.clearBody();
+      buttonStrip = document.createElement('print-preview-button-strip');
+
+      buttonStrip.destination = new print_preview.Destination(
+          'FooDevice', print_preview.DestinationType.GOOGLE,
+          print_preview.DestinationOrigin.COOKIES, 'FooName',
+          print_preview.DestinationConnectionStatus.ONLINE);
+      buttonStrip.state = print_preview_new.State.READY;
+      document.body.appendChild(buttonStrip);
+    });
+
+    // Tests that the correct message is shown for non-READY states, and that
+    // the print button is disabled appropriately.
+    test(assert(TestNames.ButtonStripChangesForState), function() {
+      const printButton = buttonStrip.$$('.action-button');
+      assertFalse(printButton.disabled);
+
+      buttonStrip.state = print_preview_new.State.NOT_READY;
+      assertTrue(printButton.disabled);
+
+      buttonStrip.state = print_preview_new.State.PRINTING;
+      assertTrue(printButton.disabled);
+
+      buttonStrip.state = print_preview_new.State.ERROR;
+      assertTrue(printButton.disabled);
+
+      buttonStrip.state = print_preview_new.State.FATAL_ERROR;
+      assertTrue(printButton.disabled);
+    });
+
+    // Tests that the buttons are in the correct order for different platforms.
+    // See https://crbug.com/880562.
+    test(assert(TestNames.ButtonOrder), function() {
+      // Verify that there are only 2 buttons.
+      assertEquals(
+          2, buttonStrip.shadowRoot.querySelectorAll('paper-button').length);
+
+      const firstButton = buttonStrip.$$('paper-button:not(:last-child)');
+      const lastButton = buttonStrip.$$('paper-button:last-child');
+      const printButton = buttonStrip.$$('paper-button.action-button');
+      const cancelButton = buttonStrip.$$('paper-button.cancel-button');
+
+      if (cr.isWindows) {
+        // On Windows, the print button is on the left.
+        assertEquals(firstButton, printButton);
+        assertEquals(lastButton, cancelButton);
+      } else {
+        assertEquals(firstButton, cancelButton);
+        assertEquals(lastButton, printButton);
+      }
+    });
+
+    // Tests that the button strip fires print-requested and cancel-requested
+    // events.
+    test(assert(TestNames.ButtonStripFiresEvents), function() {
+      const printButton = buttonStrip.$$('paper-button.action-button');
+      const cancelButton = buttonStrip.$$('paper-button.cancel-button');
+
+      const whenPrintRequested =
+          test_util.eventToPromise('print-requested', buttonStrip);
+      printButton.click();
+      return whenPrintRequested.then(() => {
+        const whenCancelRequested =
+            test_util.eventToPromise('cancel-requested', buttonStrip);
+        cancelButton.click();
+        return whenCancelRequested;
+      });
+    });
+  });
+
+  return {
+    suiteName: suiteName,
+    TestNames: TestNames,
+  };
+});
diff --git a/chrome/test/data/webui/print_preview/header_new_test.js b/chrome/test/data/webui/print_preview/header_new_test.js
new file mode 100644
index 0000000..72cacbef
--- /dev/null
+++ b/chrome/test/data/webui/print_preview/header_new_test.js
@@ -0,0 +1,133 @@
+// Copyright 2019 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.define('header_new_test', function() {
+  /** @enum {string} */
+  const TestNames = {
+    HeaderPrinterTypes: 'header printer types',
+    HeaderWithDuplex: 'header with duplex',
+    HeaderWithCopies: 'header with copies',
+    HeaderWithNup: 'header with nup',
+    HeaderChangesForState: 'header changes for state',
+    EnterprisePolicy: 'enterprise policy',
+  };
+
+  const suiteName = 'HeaderNewTest';
+  suite(suiteName, function() {
+    /** @type {?PrintPreviewHeaderNewElement} */
+    let header = null;
+
+    /** @override */
+    setup(function() {
+      loadTimeData.overrideValues({
+        newPrintPreviewLayoutEnabled: true,
+      });
+      PolymerTest.clearBody();
+      const model = document.createElement('print-preview-model');
+      document.body.appendChild(model);
+
+      header = document.createElement('print-preview-header-new');
+      header.settings = model.settings;
+      model.set('settings.duplex.available', true);
+      model.set('settings.duplex.value', false);
+
+      header.destination = new print_preview.Destination(
+          'FooDevice', print_preview.DestinationType.GOOGLE,
+          print_preview.DestinationOrigin.COOKIES, 'FooName',
+          print_preview.DestinationConnectionStatus.ONLINE);
+      header.state = print_preview_new.State.READY;
+      header.managed = false;
+      test_util.fakeDataBind(model, header, 'settings');
+      document.body.appendChild(header);
+    });
+
+    function setPdfDestination() {
+      header.set(
+          'destination',
+          new print_preview.Destination(
+              print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
+              print_preview.DestinationType.LOCAL,
+              print_preview.DestinationOrigin.LOCAL,
+              loadTimeData.getString('printToPDF'),
+              print_preview.DestinationConnectionStatus.ONLINE));
+    }
+
+    // Tests that the 4 different messages (non-virtual printer singular and
+    // plural, virtual printer singular and plural) all show up as expected.
+    test(assert(TestNames.HeaderPrinterTypes), function() {
+      const summary = header.$$('.summary');
+      assertEquals('1 sheet of paper', summary.textContent.trim());
+      header.setSetting('pages', [1, 2, 3]);
+      assertEquals('3 sheets of paper', summary.textContent.trim());
+      setPdfDestination();
+      assertEquals('3 pages', summary.textContent.trim());
+      header.setSetting('pages', [1]);
+      assertEquals('1 page', summary.textContent.trim());
+    });
+
+    // Tests that the message is correctly adjusted with a duplex printer.
+    test(assert(TestNames.HeaderWithDuplex), function() {
+      const summary = header.$$('.summary');
+      assertEquals('1 sheet of paper', summary.textContent.trim());
+      header.setSetting('pages', [1, 2, 3]);
+      assertEquals('3 sheets of paper', summary.textContent.trim());
+      header.setSetting('duplex', true);
+      assertEquals('2 sheets of paper', summary.textContent.trim());
+      header.setSetting('pages', [1, 2]);
+      assertEquals('1 sheet of paper', summary.textContent.trim());
+    });
+
+    // Tests that the message is correctly adjusted with multiple copies.
+    test(assert(TestNames.HeaderWithCopies), function() {
+      const summary = header.$$('.summary');
+      assertEquals('1 sheet of paper', summary.textContent.trim());
+      header.setSetting('copies', 4);
+      assertEquals('4 sheets of paper', summary.textContent.trim());
+      header.setSetting('duplex', true);
+      assertEquals('4 sheets of paper', summary.textContent.trim());
+      header.setSetting('pages', [1, 2]);
+      assertEquals('4 sheets of paper', summary.textContent.trim());
+      header.setSetting('duplex', false);
+      assertEquals('8 sheets of paper', summary.textContent.trim());
+    });
+
+    // Tests that the correct message is shown for non-READY states, and that
+    // the print button is disabled appropriately.
+    test(assert(TestNames.HeaderChangesForState), function() {
+      const summary = header.$$('.summary');
+      assertEquals('1 sheet of paper', summary.textContent.trim());
+
+      header.state = print_preview_new.State.NOT_READY;
+      assertEquals('', summary.textContent.trim());
+
+      header.state = print_preview_new.State.PRINTING;
+      assertEquals(
+          loadTimeData.getString('printing'), summary.textContent.trim());
+      setPdfDestination();
+      assertEquals(
+          loadTimeData.getString('saving'), summary.textContent.trim());
+
+      header.state = print_preview_new.State.ERROR;
+      assertEquals('', summary.textContent.trim());
+
+      const testError = 'Error printing to cloud print';
+      header.cloudPrintErrorMessage = testError;
+      header.error = print_preview_new.Error.CLOUD_PRINT_ERROR;
+      header.state = print_preview_new.State.FATAL_ERROR;
+      assertEquals(testError, summary.textContent.trim());
+    });
+
+    // Tests that enterprise badge shows up if any setting is managed.
+    test(assert(TestNames.EnterprisePolicy), function() {
+      assertTrue(header.$$('iron-icon').hidden);
+      header.managed = true;
+      assertFalse(header.$$('iron-icon').hidden);
+    });
+  });
+
+  return {
+    suiteName: suiteName,
+    TestNames: TestNames,
+  };
+});
diff --git a/chrome/test/data/webui/print_preview/header_test.js b/chrome/test/data/webui/print_preview/header_test.js
index bde9c31..842d850 100644
--- a/chrome/test/data/webui/print_preview/header_test.js
+++ b/chrome/test/data/webui/print_preview/header_test.js
@@ -21,6 +21,9 @@
 
     /** @override */
     setup(function() {
+      loadTimeData.overrideValues({
+        newPrintPreviewLayoutEnabled: false,
+      });
       PolymerTest.clearBody();
       const model = document.createElement('print-preview-model');
       document.body.appendChild(model);
diff --git a/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js b/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js
index 310a38b6..16d42dc1 100644
--- a/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js
+++ b/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js
@@ -153,16 +153,23 @@
       const overlay = previewAreaEl.$$('.preview-area-overlay-layer');
       const messageEl = previewAreaEl.$$('.preview-area-message');
       const sidebar = page.$$('print-preview-sidebar');
-      const header = sidebar.$$('print-preview-header');
-      const printButton = header.$$('.action-button');
+      let printButton = null;
       const destinationSettings =
           sidebar.$$('print-preview-destination-settings');
 
-      return Promise
-          .all([
-            print_preview.Model.whenReady(),
-            nativeLayer.whenCalled('getInitialSettings'),
-          ])
+      return test_util.waitForRender(page)
+          .then(() => {
+            const parentElement =
+                loadTimeData.getBoolean('newPrintPreviewLayoutEnabled') ?
+                sidebar.$$('print-preview-button-strip') :
+                sidebar.$$('print-preview-header');
+            printButton = parentElement.$$('.action-button');
+
+            return Promise.all([
+              print_preview.Model.whenReady(),
+              nativeLayer.whenCalled('getInitialSettings'),
+            ]);
+          })
           .then(function() {
             destinationSettings.destinationStore_.startLoadAllDestinations();
             // Wait for the preview request.
@@ -208,8 +215,8 @@
           })
           .then(
               /**
-               * @param {string} printTicket The print ticket print() was called
-               *     for.
+               * @param {string} printTicket The print ticket print() was
+               *     called for.
                */
               function(printTicket) {
                 // Sanity check some printing argument values.
@@ -256,19 +263,25 @@
       const overlayEl = previewAreaEl.$$('.preview-area-overlay-layer');
       const messageEl = previewAreaEl.$$('.preview-area-message');
       const sidebar = page.$$('print-preview-sidebar');
-      const header = sidebar.$$('print-preview-header');
-      const printButton = header.$$('.action-button');
+      let printButton = null;
       const destinationSettings =
           sidebar.$$('print-preview-destination-settings');
       const scalingSettings = sidebar.$$('print-preview-scaling-settings')
                                   .$$('print-preview-number-settings-section');
       const layoutSettings = sidebar.$$('print-preview-layout-settings');
 
-      return Promise
-          .all([
-            print_preview.Model.whenReady(),
-            nativeLayer.whenCalled('getInitialSettings'),
-          ])
+      return test_util.waitForRender(page)
+          .then(() => {
+            const parentElement =
+                loadTimeData.getBoolean('newPrintPreviewLayoutEnabled') ?
+                sidebar.$$('print-preview-button-strip') :
+                sidebar.$$('print-preview-header');
+            printButton = parentElement.$$('.action-button');
+            return Promise.all([
+              print_preview.Model.whenReady(),
+              nativeLayer.whenCalled('getInitialSettings'),
+            ]);
+          })
           .then(function() {
             // Set this to enable the scaling input.
             page.setSetting('customScaling', true);
@@ -318,7 +331,8 @@
             // The destination select dropdown should still be enabled.
             assertFalse(destinationSettings.$.destinationSelect.disabled);
 
-            // Message text should have changed and overlay should be invisible.
+            // Message text should have changed and overlay should be
+            // invisible.
             assertFalse(messageEl.textContent.includes(expectedMessageStart));
             assertTrue(overlayEl.classList.contains('invisible'));
           });
@@ -344,16 +358,22 @@
           const overlayEl = previewAreaEl.$$('.preview-area-overlay-layer');
           const messageEl = previewAreaEl.$$('.preview-area-message');
           const sidebar = page.$$('print-preview-sidebar');
-          const header = sidebar.$$('print-preview-header');
-          const printButton = header.$$('.action-button');
+          let printButton = null;
           const destinationSettings =
               sidebar.$$('print-preview-destination-settings');
 
-          return Promise
-              .all([
-                print_preview.Model.whenReady(),
-                nativeLayer.whenCalled('getInitialSettings'),
-              ])
+          return test_util.waitForRender(page)
+              .then(() => {
+                const parentElement =
+                    loadTimeData.getBoolean('newPrintPreviewLayoutEnabled') ?
+                    sidebar.$$('print-preview-button-strip') :
+                    sidebar.$$('print-preview-header');
+                printButton = parentElement.$$('.action-button');
+                return Promise.all([
+                  print_preview.Model.whenReady(),
+                  nativeLayer.whenCalled('getInitialSettings'),
+                ]);
+              })
               .then(function() {
                 // Start loading cloud destinations so that the printer
                 // capabilities arrive.
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 2bb92d9..e0e841f 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
@@ -947,6 +947,78 @@
   this.runMochaTest(header_test.TestNames.EnterprisePolicy);
 });
 
+PrintPreviewHeaderNewTest = class extends NewPrintPreviewTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://print/new/header_new.html';
+  }
+
+  /** @override */
+  get extraLibraries() {
+    return super.extraLibraries.concat([
+      '../settings/test_util.js',
+      'header_new_test.js',
+    ]);
+  }
+
+  /** @override */
+  get suiteName() {
+    return header_new_test.suiteName;
+  }
+};
+
+TEST_F('PrintPreviewHeaderNewTest', 'HeaderPrinterTypes', function() {
+  this.runMochaTest(header_new_test.TestNames.HeaderPrinterTypes);
+});
+
+TEST_F('PrintPreviewHeaderNewTest', 'HeaderWithDuplex', function() {
+  this.runMochaTest(header_new_test.TestNames.HeaderWithDuplex);
+});
+
+TEST_F('PrintPreviewHeaderNewTest', 'HeaderWithCopies', function() {
+  this.runMochaTest(header_new_test.TestNames.HeaderWithCopies);
+});
+
+TEST_F('PrintPreviewHeaderNewTest', 'HeaderChangesForState', function() {
+  this.runMochaTest(header_new_test.TestNames.HeaderChangesForState);
+});
+
+TEST_F('PrintPreviewHeaderNewTest', 'EnterprisePolicy', function() {
+  this.runMochaTest(header_new_test.TestNames.EnterprisePolicy);
+});
+
+PrintPreviewButtonStripTest = class extends NewPrintPreviewTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://print/new/button_strip.html';
+  }
+
+  /** @override */
+  get extraLibraries() {
+    return super.extraLibraries.concat([
+      '../settings/test_util.js',
+      'button_strip_test.js',
+    ]);
+  }
+
+  /** @override */
+  get suiteName() {
+    return button_strip_test.suiteName;
+  }
+};
+
+TEST_F('PrintPreviewButtonStripTest', 'ButtonStripChangesForState', function() {
+  this.runMochaTest(button_strip_test.TestNames.ButtonStripChangesForState);
+});
+
+TEST_F('PrintPreviewButtonStripTest', 'ButtonOrder', function() {
+  this.runMochaTest(button_strip_test.TestNames.ButtonOrder);
+});
+
+TEST_F('PrintPreviewButtonStripTest', 'ButtonStripFiresEvents', function() {
+  this.runMochaTest(button_strip_test.TestNames.ButtonStripFiresEvents);
+});
+
 PrintPreviewDestinationItemTest = class extends NewPrintPreviewTest {
   /** @override */
   get browsePreload() {
diff --git a/chrome/test/data/webui/print_preview/print_button_test.js b/chrome/test/data/webui/print_preview/print_button_test.js
index 0e013f3..6b92945 100644
--- a/chrome/test/data/webui/print_preview/print_button_test.js
+++ b/chrome/test/data/webui/print_preview/print_button_test.js
@@ -56,8 +56,11 @@
         // preview is ready.
         if (printBeforePreviewReady) {
           const sidebar = page.$$('print-preview-sidebar');
-          const header = sidebar.$$('print-preview-header');
-          const printButton = header.$$('.action-button');
+          const parentElement =
+              loadTimeData.getBoolean('newPrintPreviewLayoutEnabled') ?
+              sidebar.$$('print-preview-button-strip') :
+              sidebar.$$('print-preview-header');
+          const printButton = parentElement.$$('.action-button');
           assertFalse(printButton.disabled);
           printButton.click();
         }
diff --git a/chrome/test/data/webui/print_preview/print_header_interactive_test.js b/chrome/test/data/webui/print_preview/print_header_interactive_test.js
index 1f101ce..e31bad25 100644
--- a/chrome/test/data/webui/print_preview/print_header_interactive_test.js
+++ b/chrome/test/data/webui/print_preview/print_header_interactive_test.js
@@ -16,6 +16,9 @@
 
     /** @override */
     setup(function() {
+      loadTimeData.overrideValues({
+        newPrintPreviewLayoutEnabled: false,
+      });
       PolymerTest.clearBody();
       const model = document.createElement('print-preview-model');
       document.body.appendChild(model);
diff --git a/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js b/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js
index 01bf101..04faf4e 100644
--- a/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js
+++ b/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js
@@ -69,6 +69,40 @@
           print_header_interactive_test.TestNames.FocusPrintOnReady);
     });
 
+PrintPreviewButtonStripInteractiveTest =
+    class extends PrintPreviewInteractiveUITest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://print/new/button_strip.html';
+  }
+
+  /** @override */
+  get extraLibraries() {
+    return super.extraLibraries.concat([
+      ROOT_PATH + 'chrome/test/data/webui/settings/test_util.js',
+      'button_strip_interactive_test.js',
+    ]);
+  }
+
+  /** @override */
+  get suiteName() {
+    return button_strip_interactive_test.suiteName;
+  }
+};
+
+// Web UI interactive tests are flaky on Win10, see https://crbug.com/711256
+GEN('#if defined(OS_WIN)');
+GEN('#define MAYBE_FocusPrintOnReady DISABLED_FocusPrintOnReady');
+GEN('#else');
+GEN('#define MAYBE_FocusPrintOnReady FocusPrintOnReady');
+GEN('#endif');
+TEST_F(
+    'PrintPreviewButtonStripInteractiveTest', 'MAYBE_FocusPrintOnReady',
+    function() {
+      this.runMochaTest(
+          button_strip_interactive_test.TestNames.FocusPrintOnReady);
+    });
+
 PrintPreviewDestinationDialogInteractiveTest =
     class extends PrintPreviewInteractiveUITest {
   /** @override */
@@ -211,3 +245,39 @@
       this.runMochaTest(number_settings_section_interactive_test.TestNames
                             .BlurResetsEmptyInput);
     });
+
+PrintPreviewScalingSettingsInteractiveTest =
+    class extends PrintPreviewInteractiveUITest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://print/new/scaling_settings.html';
+  }
+
+  /** @override */
+  get extraLibraries() {
+    return super.extraLibraries.concat([
+      ROOT_PATH + 'ui/webui/resources/js/util.js',
+      '../settings/test_util.js',
+      'print_preview_test_utils.js',
+      'scaling_settings_interactive_test.js',
+    ]);
+  }
+
+  /** @override */
+  get suiteName() {
+    return scaling_settings_interactive_test.suiteName;
+  }
+};
+
+// Web UI interactive tests are flaky on Win10, see https://crbug.com/711256
+GEN('#if defined(OS_WIN)');
+GEN('#define MAYBE_AutoFocusInput DISABLED_InputAutoFocus');
+GEN('#else');
+GEN('#define MAYBE_AutoFocusInput InputAutoFocus');
+GEN('#endif');
+TEST_F(
+    'PrintPreviewScalingSettingsInteractiveTest', 'MAYBE_AutoFocusInput',
+    function() {
+      this.runMochaTest(
+          scaling_settings_interactive_test.TestNames.AutoFocusInput);
+    });
diff --git a/chrome/test/data/webui/print_preview/scaling_settings_interactive_test.js b/chrome/test/data/webui/print_preview/scaling_settings_interactive_test.js
new file mode 100644
index 0000000..0f49158
--- /dev/null
+++ b/chrome/test/data/webui/print_preview/scaling_settings_interactive_test.js
@@ -0,0 +1,75 @@
+// Copyright 2019 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.define('scaling_settings_interactive_test', function() {
+  /** @enum {string} */
+  const TestNames = {
+    AutoFocusInput: 'auto focus input',
+  };
+
+  const suiteName = 'ScalingSettingsInteractiveTest';
+  suite(suiteName, function() {
+    /** @type {?PrintPreviewScalingSettingsElement} */
+    let scalingSection = null;
+
+    /** @type {?PrintPreviewModelElement} */
+    let model = null;
+
+    /** @override */
+    setup(function() {
+      PolymerTest.clearBody();
+      model = document.createElement('print-preview-model');
+      document.body.appendChild(model);
+      model.set('settings.fitToPage.available', false);
+
+      scalingSection = document.createElement('print-preview-scaling-settings');
+      scalingSection.settings = model.settings;
+      scalingSection.disabled = false;
+      test_util.fakeDataBind(model, scalingSection, 'settings');
+      document.body.appendChild(scalingSection);
+    });
+
+    test(assert(TestNames.AutoFocusInput), async () => {
+      const scalingInput =
+          scalingSection.$$('print-preview-number-settings-section')
+              .$.userValue.inputElement;
+      const scalingDropdown = scalingSection.$$('.md-select');
+      const collapse = scalingSection.$$('iron-collapse');
+
+      assertFalse(collapse.opened);
+      assertFalse(scalingSection.getSettingValue('customScaling'));
+
+      // Select custom with the dropdown. This should autofocus the input.
+      await Promise.all([
+        print_preview_test_utils.selectOption(
+            scalingSection, scalingSection.ScalingValue.CUSTOM.toString()),
+        test_util.eventToPromise('transitionend', collapse),
+      ]);
+      assertTrue(collapse.opened);
+      assertEquals(scalingInput, getDeepActiveElement());
+
+      // Blur and select default.
+      scalingInput.blur();
+      await Promise.all([
+        print_preview_test_utils.selectOption(
+            scalingSection, scalingSection.ScalingValue.DEFAULT.toString()),
+        test_util.eventToPromise('transitionend', collapse),
+      ]);
+      assertFalse(scalingSection.getSettingValue('customScaling'));
+      assertFalse(scalingSection.$$('iron-collapse').opened);
+
+      // Set custom in JS, which happens when we set the sticky settings. This
+      // should not autofocus the input.
+      scalingSection.setSetting('customScaling', true);
+      await test_util.eventToPromise('transitionend', collapse);
+      assertTrue(collapse.opened);
+      assertNotEquals(scalingInput, getDeepActiveElement());
+    });
+  });
+
+  return {
+    suiteName: suiteName,
+    TestNames: TestNames,
+  };
+});
diff --git a/chrome/test/data/webui/print_preview/system_dialog_browsertest.js b/chrome/test/data/webui/print_preview/system_dialog_browsertest.js
index d047e42d..7adbad5 100644
--- a/chrome/test/data/webui/print_preview/system_dialog_browsertest.js
+++ b/chrome/test/data/webui/print_preview/system_dialog_browsertest.js
@@ -84,34 +84,39 @@
       const scalingSettings = sidebar.$$('print-preview-scaling-settings');
       assertFalse(scalingSettings.hidden);
       nativeLayer.resetResolver('getPreview');
+      let previewCalls = 0;
 
       // Set scaling settings to custom.
-      scalingSettings.$$('.md-select').value =
-          scalingSettings.ScalingValue.CUSTOM;
-      scalingSettings.$$('.md-select').dispatchEvent(new CustomEvent('change'));
+      return print_preview_test_utils
+          .selectOption(
+              scalingSettings, scalingSettings.ScalingValue.CUSTOM.toString())
+          .then(() => {
+            previewCalls = nativeLayer.getCallCount('getPreview');
 
-      // Set an invalid input.
-      const scalingSettingsInput =
-          scalingSettings.$$('print-preview-number-settings-section')
-              .$.userValue.inputElement;
-      scalingSettingsInput.value = '0';
-      scalingSettingsInput.dispatchEvent(
-          new CustomEvent('input', {composed: true, bubbles: true}));
+            // Set an invalid input.
+            const scalingSettingsInput =
+                scalingSettings.$$('print-preview-number-settings-section')
+                    .$.userValue.inputElement;
+            scalingSettingsInput.value = '0';
+            scalingSettingsInput.dispatchEvent(
+                new CustomEvent('input', {composed: true, bubbles: true}));
 
-      // No new preview
-      nativeLayer.whenCalled('getPreview').then(function() {
-        assertTrue(false);
-      });
-
-      return test_util.eventToPromise('input-change', scalingSettings)
+            return test_util.eventToPromise('input-change', scalingSettings);
+          })
           .then(() => {
             // Expect disabled print button
-            const header = sidebar.$$('print-preview-header');
-            const printButton = header.$$('.action-button');
+            const parentElement =
+                loadTimeData.getBoolean('newPrintPreviewLayoutEnabled') ?
+                sidebar.$$('print-preview-button-strip') :
+                sidebar.$$('print-preview-header');
+            const printButton = parentElement.$$('.action-button');
             assertTrue(printButton.disabled);
             assertTrue(linkContainer.disabled);
             assertFalse(link.hidden);
             assertTrue(link.querySelector('button').disabled);
+
+            // No new preview
+            assertEquals(previewCalls, nativeLayer.getCallCount('getPreview'));
           });
     });
   });
diff --git a/chrome/test/data/webui/settings/default_browser_browsertest.js b/chrome/test/data/webui/settings/default_browser_browsertest.js
index 6a06de7f..23331ba 100644
--- a/chrome/test/data/webui/settings/default_browser_browsertest.js
+++ b/chrome/test/data/webui/settings/default_browser_browsertest.js
@@ -29,8 +29,7 @@
     /** @override */
     requestDefaultBrowserState() {
       this.methodCalled('requestDefaultBrowserState');
-      cr.webUIListenerCallback(
-          'browser-default-state-changed', this.defaultBrowserInfo_);
+      return Promise.resolve(this.defaultBrowserInfo_);
     }
 
     /** @override */
diff --git a/chrome/test/data/webui/welcome/test_bookmark_proxy.js b/chrome/test/data/webui/welcome/test_bookmark_proxy.js
index 9704019d..9ba70638 100644
--- a/chrome/test/data/webui/welcome/test_bookmark_proxy.js
+++ b/chrome/test/data/webui/welcome/test_bookmark_proxy.js
@@ -25,7 +25,7 @@
   isBookmarkBarShown() {
     this.methodCalled('isBookmarkBarShown');
 
-    // TODO(scottchen): make changable to test both true/false cases.
+    // TODO(hcarmona): make changeable to test both true/false cases.
     return Promise.resolve(true);
   }
 
diff --git a/chrome/test/data/webui/welcome/test_nux_set_as_default_proxy.js b/chrome/test/data/webui/welcome/test_nux_set_as_default_proxy.js
index 9014234..a91e168 100644
--- a/chrome/test/data/webui/welcome/test_nux_set_as_default_proxy.js
+++ b/chrome/test/data/webui/welcome/test_nux_set_as_default_proxy.js
@@ -21,9 +21,8 @@
 
   /** @override */
   requestDefaultBrowserState() {
-    cr.webUIListenerCallback(
-        'browser-default-state-changed', this.defaultStatus_);
     this.methodCalled('requestDefaultBrowserState');
+    return Promise.resolve(this.defaultStatus_);
   }
 
   /** @override */
diff --git a/chromecast/browser/cast_browser_process.cc b/chromecast/browser/cast_browser_process.cc
index 52fb1991..1f127f5 100644
--- a/chromecast/browser/cast_browser_process.cc
+++ b/chromecast/browser/cast_browser_process.cc
@@ -9,6 +9,8 @@
 #include "base/logging.h"
 #include "build/build_config.h"
 #include "chromecast/browser/cast_browser_context.h"
+#include "chromecast/browser/cast_content_browser_client.h"
+#include "chromecast/browser/cast_network_contexts.h"
 #include "chromecast/browser/devtools/remote_debugging_server.h"
 #include "chromecast/browser/metrics/cast_metrics_service_client.h"
 #include "chromecast/browser/tts/tts_controller.h"
@@ -48,6 +50,15 @@
 
 CastBrowserProcess::~CastBrowserProcess() {
   DCHECK_EQ(g_instance, this);
+
+  // TODO(halliwell): investigate having the state that's owned in
+  // CastContentBrowserClient (and its internal derived class) be owned in
+  // another class that's destructed by this point.
+  if (cast_content_browser_client_) {
+    cast_content_browser_client_->cast_network_contexts()
+        ->OnPrefServiceShutdown();
+  }
+
   if (pref_service_)
     pref_service_->CommitPendingWrite();
   g_instance = NULL;
diff --git a/chromecast/browser/cast_network_contexts.cc b/chromecast/browser/cast_network_contexts.cc
index 58653a5..9f4142a 100644
--- a/chromecast/browser/cast_network_contexts.cc
+++ b/chromecast/browser/cast_network_contexts.cc
@@ -126,9 +126,6 @@
 CastNetworkContexts::~CastNetworkContexts() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  if (proxy_config_service_)
-    proxy_config_service_->RemoveObserver(this);
-
   system_shared_url_loader_factory_->Shutdown();
 }
 
@@ -239,6 +236,14 @@
       ->SetAcceptLanguage(accept_language);
 }
 
+void CastNetworkContexts::OnPrefServiceShutdown() {
+  if (proxy_config_service_)
+    proxy_config_service_->RemoveObserver(this);
+
+  if (pref_proxy_config_tracker_impl_)
+    pref_proxy_config_tracker_impl_->DetachFromPrefService();
+}
+
 network::mojom::NetworkContextParamsPtr
 CastNetworkContexts::CreateDefaultNetworkContextParams() {
   network::mojom::NetworkContextParamsPtr network_context_params =
diff --git a/chromecast/browser/cast_network_contexts.h b/chromecast/browser/cast_network_contexts.h
index 6ac8883a..f993cea9 100644
--- a/chromecast/browser/cast_network_contexts.h
+++ b/chromecast/browser/cast_network_contexts.h
@@ -80,6 +80,9 @@
   // Called when the locale has changed.
   void OnLocaleUpdate();
 
+  // Called on shutdown of the PrefService.
+  void OnPrefServiceShutdown();
+
  private:
   class SystemNetworkContextOwner;
   class URLLoaderFactoryForSystem;
diff --git a/chromecast/browser/extensions/cast_extension_system.cc b/chromecast/browser/extensions/cast_extension_system.cc
index 6eec4c9..9c7ae096 100644
--- a/chromecast/browser/extensions/cast_extension_system.cc
+++ b/chromecast/browser/extensions/cast_extension_system.cc
@@ -262,7 +262,7 @@
     const std::string& extension_id,
     const UnloadedExtensionReason reason) {}
 
-const OneShotEvent& CastExtensionSystem::ready() const {
+const base::OneShotEvent& CastExtensionSystem::ready() const {
   return ready_;
 }
 
diff --git a/chromecast/browser/extensions/cast_extension_system.h b/chromecast/browser/extensions/cast_extension_system.h
index 1cbac8b6..975197a 100644
--- a/chromecast/browser/extensions/cast_extension_system.h
+++ b/chromecast/browser/extensions/cast_extension_system.h
@@ -10,9 +10,9 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/one_shot_event.h"
 #include "extensions/browser/extension_registrar.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/common/one_shot_event.h"
 
 namespace base {
 class FilePath;
@@ -80,7 +80,7 @@
   void UnregisterExtensionWithRequestContexts(
       const std::string& extension_id,
       const UnloadedExtensionReason reason) override;
-  const OneShotEvent& ready() const override;
+  const base::OneShotEvent& ready() const override;
   ContentVerifier* content_verifier() override;
   std::unique_ptr<ExtensionSet> GetDependentExtensions(
       const Extension* extension) override;
@@ -125,7 +125,7 @@
   scoped_refptr<ValueStoreFactory> store_factory_;
 
   // Signaled when the extension system has completed its startup tasks.
-  OneShotEvent ready_;
+  base::OneShotEvent ready_;
 
   base::WeakPtrFactory<CastExtensionSystem> weak_factory_;
 
diff --git a/chromecast/graphics/BUILD.gn b/chromecast/graphics/BUILD.gn
index a884b3ab..d77c071 100644
--- a/chromecast/graphics/BUILD.gn
+++ b/chromecast/graphics/BUILD.gn
@@ -62,7 +62,7 @@
     ]
 
     deps += [
-      "//ui/base/ime",
+      "//ui/base/ime/init",
       "//ui/events:gesture_detection",
       "//ui/views",
       "//ui/wm",
diff --git a/chromecast/graphics/cast_window_manager_aura.cc b/chromecast/graphics/cast_window_manager_aura.cc
index 8f82944..48129bac 100644
--- a/chromecast/graphics/cast_window_manager_aura.cc
+++ b/chromecast/graphics/cast_window_manager_aura.cc
@@ -19,8 +19,8 @@
 #include "ui/aura/null_window_targeter.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host_platform.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_factory.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 #include "ui/ozone/public/ozone_platform.h"
diff --git a/chromeos/components/proximity_auth/BUILD.gn b/chromeos/components/proximity_auth/BUILD.gn
index 963f465..fe71bb2 100644
--- a/chromeos/components/proximity_auth/BUILD.gn
+++ b/chromeos/components/proximity_auth/BUILD.gn
@@ -56,6 +56,7 @@
     "//chromeos/components/proximity_auth/public/interfaces",
     "//chromeos/constants",
     "//chromeos/dbus",
+    "//chromeos/dbus/session_manager",
     "//chromeos/services/multidevice_setup/public/cpp",
     "//chromeos/services/multidevice_setup/public/cpp:prefs",
     "//chromeos/services/secure_channel/public/cpp/client",
diff --git a/chromeos/components/proximity_auth/screenlock_bridge.cc b/chromeos/components/proximity_auth/screenlock_bridge.cc
index 8391263..9bbca434e 100644
--- a/chromeos/components/proximity_auth/screenlock_bridge.cc
+++ b/chromeos/components/proximity_auth/screenlock_bridge.cc
@@ -11,7 +11,6 @@
 #include "base/strings/string16.h"
 #include "build/build_config.h"
 #include "chromeos/components/multidevice/logging/logging.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 
 namespace proximity_auth {
@@ -149,9 +148,7 @@
 }
 
 void ScreenlockBridge::Lock() {
-  chromeos::SessionManagerClient* session_manager =
-      chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
-  session_manager->RequestLockScreen();
+  chromeos::SessionManagerClient::Get()->RequestLockScreen();
 }
 
 void ScreenlockBridge::Unlock(const AccountId& account_id) {
diff --git a/chromeos/components/proximity_auth/unlock_manager_impl_unittest.cc b/chromeos/components/proximity_auth/unlock_manager_impl_unittest.cc
index a23221d..313921b9 100644
--- a/chromeos/components/proximity_auth/unlock_manager_impl_unittest.cc
+++ b/chromeos/components/proximity_auth/unlock_manager_impl_unittest.cc
@@ -23,7 +23,6 @@
 #include "chromeos/components/proximity_auth/remote_device_life_cycle.h"
 #include "chromeos/components/proximity_auth/remote_status_update.h"
 #include "chromeos/constants/chromeos_features.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/services/secure_channel/public/cpp/client/fake_client_channel.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn
index 91842e1..fb7ab41 100644
--- a/chromeos/dbus/BUILD.gn
+++ b/chromeos/dbus/BUILD.gn
@@ -16,10 +16,8 @@
     "//dbus",
   ]
   deps = [
-    ":authpolicy_proto",
     ":cicerone_proto",
     ":concierge_proto",
-    ":login_manager_proto",
     ":metrics_event_proto",
     ":oobe_config_proto",
     ":plugin_vm_service_proto",
@@ -29,20 +27,8 @@
     ":smbprovider_proto",
     ":vm_applications_apps_proto",
     "//base",
-
-    # TODO(stevenjb): Remove these once auth_policy and session_manager are
-    # extracted. https://crbug.com/647367.
-    "//chromeos/dbus/cryptohome",
-    "//chromeos/dbus/cryptohome:cryptohome_proto",
-
-    # TODO(stevenjb): Remove these once upstart gets its own BUILD.gn file.
-    # https://crbug.com/647367.
-    "//chromeos/dbus/kerberos",
-    "//chromeos/dbus/media_analytics",
-    "//chromeos/dbus/media_analytics:media_perception_proto",
     "//components/account_id",
     "//components/device_event_log",
-    "//components/policy:cloud_policy_proto_generated_compile",
     "//components/policy/proto",
     "//net",
     "//url",
@@ -58,10 +44,6 @@
     "arc_oemcrypto_client.h",
     "audio_node.cc",
     "audio_node.h",
-    "auth_policy/auth_policy_client.cc",
-    "auth_policy/auth_policy_client.h",
-    "auth_policy/fake_auth_policy_client.cc",
-    "auth_policy/fake_auth_policy_client.h",
     "cec_service_client.cc",
     "cec_service_client.h",
     "cicerone_client.cc",
@@ -110,44 +92,24 @@
     "fake_diagnosticsd_client.h",
     "fake_easy_unlock_client.cc",
     "fake_easy_unlock_client.h",
-    "fake_gsm_sms_client.cc",
-    "fake_gsm_sms_client.h",
     "fake_image_burner_client.cc",
     "fake_image_burner_client.h",
     "fake_image_loader_client.cc",
     "fake_image_loader_client.h",
     "fake_lorgnette_manager_client.cc",
     "fake_lorgnette_manager_client.h",
-    "fake_modem_messaging_client.cc",
-    "fake_modem_messaging_client.h",
     "fake_oobe_configuration_client.cc",
     "fake_oobe_configuration_client.h",
     "fake_runtime_probe_client.cc",
     "fake_runtime_probe_client.h",
     "fake_seneschal_client.cc",
     "fake_seneschal_client.h",
-    "fake_shill_device_client.cc",
-    "fake_shill_device_client.h",
-    "fake_shill_ipconfig_client.cc",
-    "fake_shill_ipconfig_client.h",
-    "fake_shill_manager_client.cc",
-    "fake_shill_manager_client.h",
-    "fake_shill_profile_client.cc",
-    "fake_shill_profile_client.h",
-    "fake_shill_service_client.cc",
-    "fake_shill_service_client.h",
-    "fake_shill_third_party_vpn_driver_client.cc",
-    "fake_shill_third_party_vpn_driver_client.h",
     "fake_smb_provider_client.cc",
     "fake_smb_provider_client.h",
-    "fake_sms_client.cc",
-    "fake_sms_client.h",
     "fake_update_engine_client.cc",
     "fake_update_engine_client.h",
     "fake_virtual_file_provider_client.cc",
     "fake_virtual_file_provider_client.h",
-    "gsm_sms_client.cc",
-    "gsm_sms_client.h",
     "hammerd/fake_hammerd_client.cc",
     "hammerd/fake_hammerd_client.h",
     "hammerd/hammerd_client.cc",
@@ -158,8 +120,6 @@
     "image_loader_client.h",
     "lorgnette_manager_client.cc",
     "lorgnette_manager_client.h",
-    "modem_messaging_client.cc",
-    "modem_messaging_client.h",
     "oobe_configuration_client.cc",
     "oobe_configuration_client.h",
     "permission_broker/fake_permission_broker_client.cc",
@@ -178,34 +138,50 @@
     "runtime_probe_client.h",
     "seneschal_client.cc",
     "seneschal_client.h",
-    "session_manager/fake_session_manager_client.cc",
-    "session_manager/fake_session_manager_client.h",
-    "session_manager/session_manager_client.cc",
-    "session_manager/session_manager_client.h",
-    "shill_client_helper.cc",
-    "shill_client_helper.h",
-    "shill_device_client.cc",
-    "shill_device_client.h",
-    "shill_ipconfig_client.cc",
-    "shill_ipconfig_client.h",
-    "shill_manager_client.cc",
-    "shill_manager_client.h",
-    "shill_profile_client.cc",
-    "shill_profile_client.h",
-    "shill_service_client.cc",
-    "shill_service_client.h",
-    "shill_third_party_vpn_driver_client.cc",
-    "shill_third_party_vpn_driver_client.h",
+    "shill/fake_gsm_sms_client.cc",
+    "shill/fake_gsm_sms_client.h",
+    "shill/fake_modem_messaging_client.cc",
+    "shill/fake_modem_messaging_client.h",
+    "shill/fake_shill_device_client.cc",
+    "shill/fake_shill_device_client.h",
+    "shill/fake_shill_ipconfig_client.cc",
+    "shill/fake_shill_ipconfig_client.h",
+    "shill/fake_shill_manager_client.cc",
+    "shill/fake_shill_manager_client.h",
+    "shill/fake_shill_profile_client.cc",
+    "shill/fake_shill_profile_client.h",
+    "shill/fake_shill_service_client.cc",
+    "shill/fake_shill_service_client.h",
+    "shill/fake_shill_third_party_vpn_driver_client.cc",
+    "shill/fake_shill_third_party_vpn_driver_client.h",
+    "shill/fake_sms_client.cc",
+    "shill/fake_sms_client.h",
+    "shill/gsm_sms_client.cc",
+    "shill/gsm_sms_client.h",
+    "shill/modem_messaging_client.cc",
+    "shill/modem_messaging_client.h",
+    "shill/shill_client_helper.cc",
+    "shill/shill_client_helper.h",
+    "shill/shill_device_client.cc",
+    "shill/shill_device_client.h",
+    "shill/shill_ipconfig_client.cc",
+    "shill/shill_ipconfig_client.h",
+    "shill/shill_manager_client.cc",
+    "shill/shill_manager_client.h",
+    "shill/shill_profile_client.cc",
+    "shill/shill_profile_client.h",
+    "shill/shill_property_changed_observer.h",
+    "shill/shill_service_client.cc",
+    "shill/shill_service_client.h",
+    "shill/shill_third_party_vpn_driver_client.cc",
+    "shill/shill_third_party_vpn_driver_client.h",
+    "shill/shill_third_party_vpn_observer.h",
+    "shill/sms_client.cc",
+    "shill/sms_client.h",
     "smb_provider_client.cc",
     "smb_provider_client.h",
-    "sms_client.cc",
-    "sms_client.h",
     "update_engine_client.cc",
     "update_engine_client.h",
-    "upstart/fake_upstart_client.cc",
-    "upstart/fake_upstart_client.h",
-    "upstart/upstart_client.cc",
-    "upstart/upstart_client.h",
     "util/version_loader.cc",
     "util/version_loader.h",
     "virtual_file_provider_client.cc",
@@ -265,9 +241,11 @@
     ":test_support",
     "//base",
     "//base/test:test_support",
+    "//chromeos/dbus/auth_policy",
     "//chromeos/dbus/biod:test_support",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:attestation_proto",
+    "//chromeos/dbus/session_manager",
     "//components/account_id",
     "//dbus",
     "//dbus:test_support",
@@ -286,35 +264,27 @@
     "cryptohome/fake_cryptohome_client_unittest.cc",
     "dbus_thread_manager_unittest.cc",
     "fake_easy_unlock_client_unittest.cc",
-    "gsm_sms_client_unittest.cc",
-    "modem_messaging_client_unittest.cc",
     "native_timer_unittest.cc",
     "oobe_configuration_client_unittest.cc",
     "pipe_reader_unittest.cc",
     "power/fake_power_manager_client_unittest.cc",
     "power/power_manager_client_unittest.cc",
     "power/power_policy_controller_unittest.cc",
-    "shill_client_unittest_base.cc",
-    "shill_client_unittest_base.h",
-    "shill_device_client_unittest.cc",
-    "shill_ipconfig_client_unittest.cc",
-    "shill_manager_client_unittest.cc",
-    "shill_profile_client_unittest.cc",
-    "shill_service_client_unittest.cc",
-    "shill_third_party_vpn_driver_client_unittest.cc",
+    "shill/gsm_sms_client_unittest.cc",
+    "shill/modem_messaging_client_unittest.cc",
+    "shill/shill_client_unittest_base.cc",
+    "shill/shill_client_unittest_base.h",
+    "shill/shill_device_client_unittest.cc",
+    "shill/shill_ipconfig_client_unittest.cc",
+    "shill/shill_manager_client_unittest.cc",
+    "shill/shill_profile_client_unittest.cc",
+    "shill/shill_service_client_unittest.cc",
+    "shill/shill_third_party_vpn_driver_client_unittest.cc",
     "update_engine_client_unittest.cc",
     "util/version_loader_unittest.cc",
   ]
 }
 
-proto_library("authpolicy_proto") {
-  sources = [
-    "//third_party/cros_system_api/dbus/authpolicy/active_directory_info.proto",
-  ]
-
-  proto_out_dir = "chromeos/dbus/authpolicy"
-}
-
 proto_library("cicerone_proto") {
   sources = [
     "//third_party/cros_system_api/dbus/vm_cicerone/cicerone_service.proto",
@@ -331,15 +301,6 @@
   proto_out_dir = "chromeos/dbus/concierge"
 }
 
-proto_library("login_manager_proto") {
-  sources = [
-    "//third_party/cros_system_api/dbus/login_manager/arc.proto",
-    "//third_party/cros_system_api/dbus/login_manager/policy_descriptor.proto",
-  ]
-
-  proto_out_dir = "chromeos/dbus/login_manager"
-}
-
 proto_library("metrics_event_proto") {
   sources = [
     "//third_party/cros_system_api/dbus/metrics_event/metrics_event.proto",
diff --git a/chromeos/dbus/auth_policy/BUILD.gn b/chromeos/dbus/auth_policy/BUILD.gn
new file mode 100644
index 0000000..a5db8a2
--- /dev/null
+++ b/chromeos/dbus/auth_policy/BUILD.gn
@@ -0,0 +1,39 @@
+# Copyright 2019 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("//third_party/protobuf/proto_library.gni")
+
+assert(is_chromeos, "Non-Chrome-OS builds cannot depend on //chromeos")
+
+component("auth_policy") {
+  defines = [ "IS_AUTH_POLICY_IMPL" ]
+
+  deps = [
+    ":authpolicy_proto",
+    "//base",
+    "//chromeos/dbus:common",
+    "//chromeos/dbus/cryptohome",
+    "//chromeos/dbus/cryptohome:cryptohome_proto",
+    "//chromeos/dbus/session_manager",
+    "//components/account_id",
+    "//components/policy:cloud_policy_proto_generated_compile",
+    "//components/policy/proto",
+    "//dbus",
+  ]
+
+  sources = [
+    "auth_policy_client.cc",
+    "auth_policy_client.h",
+    "fake_auth_policy_client.cc",
+    "fake_auth_policy_client.h",
+  ]
+}
+
+proto_library("authpolicy_proto") {
+  sources = [
+    "//third_party/cros_system_api/dbus/authpolicy/active_directory_info.proto",
+  ]
+
+  proto_out_dir = "chromeos/dbus/auth_policy"
+}
diff --git a/chromeos/dbus/auth_policy/auth_policy_client.h b/chromeos/dbus/auth_policy/auth_policy_client.h
index 5b71b0b..f176546 100644
--- a/chromeos/dbus/auth_policy/auth_policy_client.h
+++ b/chromeos/dbus/auth_policy/auth_policy_client.h
@@ -9,7 +9,7 @@
 
 #include "base/callback.h"
 #include "base/component_export.h"
-#include "chromeos/dbus/authpolicy/active_directory_info.pb.h"
+#include "chromeos/dbus/auth_policy/active_directory_info.pb.h"
 #include "dbus/object_proxy.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
@@ -20,7 +20,7 @@
 // AuthPolicyClient is used to communicate with the org.chromium.AuthPolicy
 // sevice. All method should be called from the origin thread (UI thread) which
 // initializes the DBusThreadManager instance.
-class COMPONENT_EXPORT(CHROMEOS_DBUS) AuthPolicyClient {
+class COMPONENT_EXPORT(AUTH_POLICY) AuthPolicyClient {
  public:
   using AuthCallback = base::OnceCallback<void(
       authpolicy::ErrorType error,
diff --git a/chromeos/dbus/auth_policy/fake_auth_policy_client.cc b/chromeos/dbus/auth_policy/fake_auth_policy_client.cc
index 5caabaa6..5fb2a75 100644
--- a/chromeos/dbus/auth_policy/fake_auth_policy_client.cc
+++ b/chromeos/dbus/auth_policy/fake_auth_policy_client.cc
@@ -17,7 +17,6 @@
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/cryptohome/tpm_util.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/proto/cloud_policy.pb.h"
@@ -198,13 +197,10 @@
     return;
   }
 
-  SessionManagerClient* session_manager_client =
-      DBusThreadManager::Get()->GetSessionManagerClient();
-
   // On first refresh, we need to restore |machine_name| and |dm_token| from
   // the stored policy.
   if (machine_name_.empty() || dm_token_.empty()) {
-    session_manager_client->RetrieveDevicePolicy(
+    SessionManagerClient::Get()->RetrieveDevicePolicy(
         base::BindOnce(&FakeAuthPolicyClient::OnDevicePolicyRetrieved,
                        weak_factory_.GetWeakPtr(), std::move(callback)));
     return;
@@ -222,9 +218,6 @@
     return;
   }
 
-  SessionManagerClient* session_manager_client =
-      DBusThreadManager::Get()->GetSessionManagerClient();
-
   em::CloudPolicySettings policy;
   std::string payload;
   CHECK(policy.SerializeToString(&payload));
@@ -243,7 +236,7 @@
 
   cryptohome::AccountIdentifier account_identifier;
   account_identifier.set_account_id(account_id.GetAccountIdKey());
-  session_manager_client->StorePolicyForUser(
+  SessionManagerClient::Get()->StorePolicyForUser(
       account_identifier, response.SerializeAsString(),
       base::BindOnce(&OnStorePolicy, std::move(callback)));
 }
@@ -336,9 +329,7 @@
   em::PolicyFetchResponse response;
   response.set_policy_data(policy_data.SerializeAsString());
 
-  SessionManagerClient* session_manager_client =
-      DBusThreadManager::Get()->GetSessionManagerClient();
-  session_manager_client->StoreDevicePolicy(
+  SessionManagerClient::Get()->StoreDevicePolicy(
       response.SerializeAsString(),
       base::BindOnce(&OnStorePolicy, std::move(callback)));
 }
diff --git a/chromeos/dbus/auth_policy/fake_auth_policy_client.h b/chromeos/dbus/auth_policy/fake_auth_policy_client.h
index 57986ed..01d7a70d 100644
--- a/chromeos/dbus/auth_policy/fake_auth_policy_client.h
+++ b/chromeos/dbus/auth_policy/fake_auth_policy_client.h
@@ -9,10 +9,10 @@
 #include <string>
 #include <utility>
 
+#include "base/component_export.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
-
 #include "chromeos/dbus/auth_policy/auth_policy_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
@@ -22,7 +22,7 @@
 
 namespace chromeos {
 
-class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeAuthPolicyClient
+class COMPONENT_EXPORT(AUTH_POLICY) FakeAuthPolicyClient
     : public AuthPolicyClient {
  public:
   FakeAuthPolicyClient();
diff --git a/chromeos/dbus/auth_policy/fake_auth_policy_client_unittest.cc b/chromeos/dbus/auth_policy/fake_auth_policy_client_unittest.cc
index 0eab92a..534bab7a 100644
--- a/chromeos/dbus/auth_policy/fake_auth_policy_client_unittest.cc
+++ b/chromeos/dbus/auth_policy/fake_auth_policy_client_unittest.cc
@@ -7,10 +7,9 @@
 #include "base/bind.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
-#include "chromeos/dbus/cryptohome/fake_cryptohome_client.h"
+#include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/cryptohome/tpm_util.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/account_id/account_id.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -35,26 +34,19 @@
   FakeAuthPolicyClient* authpolicy_client() {
     return FakeAuthPolicyClient::Get();
   }
-  FakeSessionManagerClient* session_manager_client() {
-    return session_manager_client_ptr_;
-  }
 
   void SetUp() override {
     ::testing::Test::SetUp();
-    auto session_manager_client = std::make_unique<FakeSessionManagerClient>();
-    session_manager_client_ptr_ = session_manager_client.get();
-    // DBusThreadManager::GetSetterForTesting initializes DBusThreadManager.
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::move(session_manager_client));
     CryptohomeClient::InitializeFake();
+    SessionManagerClient::InitializeFakeInMemory();
     AuthPolicyClient::InitializeFake();
     authpolicy_client()->DisableOperationDelayForTesting();
   }
 
   void TearDown() override {
     AuthPolicyClient::Shutdown();
+    SessionManagerClient::Shutdown();
     CryptohomeClient::Shutdown();
-    DBusThreadManager::Shutdown();
   }
 
   void JoinAdDomain(const std::string& machine_name,
@@ -107,7 +99,6 @@
   int service_is_available_called_num_ = 0;
 
  private:
-  FakeSessionManagerClient* session_manager_client_ptr_;  // not owned.
   base::MessageLoop loop_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeAuthPolicyClientTest);
@@ -334,9 +325,9 @@
   {
     // Retrieve device policy from the session manager.
     std::string response_blob;
-    EXPECT_EQ(
-        SessionManagerClient::RetrievePolicyResponseType::SUCCESS,
-        session_manager_client()->BlockingRetrieveDevicePolicy(&response_blob));
+    EXPECT_EQ(SessionManagerClient::RetrievePolicyResponseType::SUCCESS,
+              SessionManagerClient::Get()->BlockingRetrieveDevicePolicy(
+                  &response_blob));
     em::PolicyFetchResponse response;
     EXPECT_TRUE(response.ParseFromString(response_blob));
     EXPECT_TRUE(response.has_policy_data());
diff --git a/chromeos/dbus/dbus_clients_common.cc b/chromeos/dbus/dbus_clients_common.cc
index d634f9fe..1a628086 100644
--- a/chromeos/dbus/dbus_clients_common.cc
+++ b/chromeos/dbus/dbus_clients_common.cc
@@ -10,33 +10,28 @@
 #include "chromeos/dbus/dbus_client_implementation_type.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_cras_audio_client.h"
-#include "chromeos/dbus/fake_gsm_sms_client.h"
-#include "chromeos/dbus/fake_modem_messaging_client.h"
-#include "chromeos/dbus/fake_shill_device_client.h"
-#include "chromeos/dbus/fake_shill_ipconfig_client.h"
-#include "chromeos/dbus/fake_shill_manager_client.h"
-#include "chromeos/dbus/fake_shill_profile_client.h"
-#include "chromeos/dbus/fake_shill_service_client.h"
-#include "chromeos/dbus/fake_shill_third_party_vpn_driver_client.h"
-#include "chromeos/dbus/fake_sms_client.h"
-#include "chromeos/dbus/gsm_sms_client.h"
-#include "chromeos/dbus/modem_messaging_client.h"
-#include "chromeos/dbus/session_manager/session_manager_client.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_ipconfig_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
-#include "chromeos/dbus/shill_third_party_vpn_driver_client.h"
-#include "chromeos/dbus/sms_client.h"
+#include "chromeos/dbus/shill/fake_gsm_sms_client.h"
+#include "chromeos/dbus/shill/fake_modem_messaging_client.h"
+#include "chromeos/dbus/shill/fake_shill_device_client.h"
+#include "chromeos/dbus/shill/fake_shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/fake_shill_manager_client.h"
+#include "chromeos/dbus/shill/fake_shill_profile_client.h"
+#include "chromeos/dbus/shill/fake_shill_service_client.h"
+#include "chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/fake_sms_client.h"
+#include "chromeos/dbus/shill/gsm_sms_client.h"
+#include "chromeos/dbus/shill/modem_messaging_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/sms_client.h"
 
 namespace chromeos {
 
 DBusClientsCommon::DBusClientsCommon(bool use_real_clients) {
-  const DBusClientImplementationType client_impl_type =
-      use_real_clients ? REAL_DBUS_CLIENT_IMPLEMENTATION
-                       : FAKE_DBUS_CLIENT_IMPLEMENTATION;
-
   if (use_real_clients)
     cras_audio_client_.reset(CrasAudioClient::Create());
   else
@@ -75,8 +70,6 @@
   else
     modem_messaging_client_.reset(new FakeModemMessagingClient);
 
-  session_manager_client_.reset(SessionManagerClient::Create(client_impl_type));
-
   if (use_real_clients)
     sms_client_.reset(SMSClient::Create());
   else
@@ -91,7 +84,6 @@
   cras_audio_client_->Init(system_bus);
   gsm_sms_client_->Init(system_bus);
   modem_messaging_client_->Init(system_bus);
-  session_manager_client_->Init(system_bus);
   shill_device_client_->Init(system_bus);
   shill_ipconfig_client_->Init(system_bus);
   shill_manager_client_->Init(system_bus);
diff --git a/chromeos/dbus/dbus_clients_common.h b/chromeos/dbus/dbus_clients_common.h
index 6a1e9015..bbbe6d1 100644
--- a/chromeos/dbus/dbus_clients_common.h
+++ b/chromeos/dbus/dbus_clients_common.h
@@ -19,7 +19,6 @@
 class CrasAudioClient;
 class GsmSMSClient;
 class ModemMessagingClient;
-class SessionManagerClient;
 class ShillDeviceClient;
 class ShillIPConfigClient;
 class ShillManagerClient;
@@ -54,7 +53,6 @@
   std::unique_ptr<ShillThirdPartyVpnDriverClient>
       shill_third_party_vpn_driver_client_;
   std::unique_ptr<SMSClient> sms_client_;
-  std::unique_ptr<SessionManagerClient> session_manager_client_;
 
   DISALLOW_COPY_AND_ASSIGN(DBusClientsCommon);
 };
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc
index 31102b3..15846c2 100644
--- a/chromeos/dbus/dbus_thread_manager.cc
+++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -25,22 +25,21 @@
 #include "chromeos/dbus/dbus_clients_common.h"
 #include "chromeos/dbus/debug_daemon_client.h"
 #include "chromeos/dbus/easy_unlock_client.h"
-#include "chromeos/dbus/gsm_sms_client.h"
 #include "chromeos/dbus/image_burner_client.h"
 #include "chromeos/dbus/image_loader_client.h"
 #include "chromeos/dbus/lorgnette_manager_client.h"
-#include "chromeos/dbus/modem_messaging_client.h"
 #include "chromeos/dbus/runtime_probe_client.h"
 #include "chromeos/dbus/seneschal_client.h"
-#include "chromeos/dbus/session_manager/session_manager_client.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_ipconfig_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
-#include "chromeos/dbus/shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/gsm_sms_client.h"
+#include "chromeos/dbus/shill/modem_messaging_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/sms_client.h"
 #include "chromeos/dbus/smb_provider_client.h"
-#include "chromeos/dbus/sms_client.h"
 #include "chromeos/dbus/update_engine_client.h"
 #include "dbus/bus.h"
 #include "dbus/dbus_statistics.h"
@@ -218,10 +217,6 @@
   return clients_browser_->oobe_configuration_client_.get();
 }
 
-SessionManagerClient* DBusThreadManager::GetSessionManagerClient() {
-  return clients_common_->session_manager_client_.get();
-}
-
 RuntimeProbeClient* DBusThreadManager::GetRuntimeProbeClient() {
   return clients_browser_ ? clients_browser_->runtime_probe_client_.get()
                           : nullptr;
@@ -423,12 +418,6 @@
       std::move(client);
 }
 
-void DBusThreadManagerSetter::SetSessionManagerClient(
-    std::unique_ptr<SessionManagerClient> client) {
-  DBusThreadManager::Get()->clients_common_->session_manager_client_ =
-      std::move(client);
-}
-
 void DBusThreadManagerSetter::SetSmbProviderClient(
     std::unique_ptr<SmbProviderClient> client) {
   DBusThreadManager::Get()->clients_browser_->smb_provider_client_ =
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h
index 288a8d0..63ff079e8 100644
--- a/chromeos/dbus/dbus_thread_manager.h
+++ b/chromeos/dbus/dbus_thread_manager.h
@@ -47,7 +47,6 @@
 class OobeConfigurationClient;
 class RuntimeProbeClient;
 class SeneschalClient;
-class SessionManagerClient;
 class ShillDeviceClient;
 class ShillIPConfigClient;
 class ShillManagerClient;
@@ -137,7 +136,6 @@
   OobeConfigurationClient* GetOobeConfigurationClient();
   RuntimeProbeClient* GetRuntimeProbeClient();
   SeneschalClient* GetSeneschalClient();
-  SessionManagerClient* GetSessionManagerClient();
   ShillDeviceClient* GetShillDeviceClient();
   ShillIPConfigClient* GetShillIPConfigClient();
   ShillManagerClient* GetShillManagerClient();
@@ -190,7 +188,6 @@
   void SetImageLoaderClient(std::unique_ptr<ImageLoaderClient> client);
   void SetSeneschalClient(std::unique_ptr<SeneschalClient> client);
   void SetRuntimeProbeClient(std::unique_ptr<RuntimeProbeClient> client);
-  void SetSessionManagerClient(std::unique_ptr<SessionManagerClient> client);
   void SetShillDeviceClient(std::unique_ptr<ShillDeviceClient> client);
   void SetShillIPConfigClient(std::unique_ptr<ShillIPConfigClient> client);
   void SetShillManagerClient(std::unique_ptr<ShillManagerClient> client);
diff --git a/chromeos/dbus/dbus_thread_manager_unittest.cc b/chromeos/dbus/dbus_thread_manager_unittest.cc
index 10e6ff4..4262eeaf 100644
--- a/chromeos/dbus/dbus_thread_manager_unittest.cc
+++ b/chromeos/dbus/dbus_thread_manager_unittest.cc
@@ -34,7 +34,6 @@
   EXPECT_TRUE(manager->GetLorgnetteManagerClient());
   EXPECT_TRUE(manager->GetModemMessagingClient());
   EXPECT_TRUE(manager->GetSeneschalClient());
-  EXPECT_TRUE(manager->GetSessionManagerClient());
   EXPECT_TRUE(manager->GetShillDeviceClient());
   EXPECT_TRUE(manager->GetShillIPConfigClient());
   EXPECT_TRUE(manager->GetShillManagerClient());
@@ -58,7 +57,6 @@
   EXPECT_TRUE(manager->GetCrasAudioClient());
   EXPECT_TRUE(manager->GetGsmSMSClient());
   EXPECT_TRUE(manager->GetModemMessagingClient());
-  EXPECT_TRUE(manager->GetSessionManagerClient());
   EXPECT_TRUE(manager->GetShillDeviceClient());
   EXPECT_TRUE(manager->GetShillIPConfigClient());
   EXPECT_TRUE(manager->GetShillManagerClient());
@@ -94,7 +92,6 @@
   EXPECT_TRUE(manager->GetCrasAudioClient());
   EXPECT_TRUE(manager->GetGsmSMSClient());
   EXPECT_TRUE(manager->GetModemMessagingClient());
-  EXPECT_TRUE(manager->GetSessionManagerClient());
   EXPECT_TRUE(manager->GetShillDeviceClient());
   EXPECT_TRUE(manager->GetShillIPConfigClient());
   EXPECT_TRUE(manager->GetShillManagerClient());
diff --git a/chromeos/dbus/debug_daemon_client.cc b/chromeos/dbus/debug_daemon_client.cc
index 39f75fe..548e492 100644
--- a/chromeos/dbus/debug_daemon_client.cc
+++ b/chromeos/dbus/debug_daemon_client.cc
@@ -502,10 +502,9 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  void CupsRemovePrinter(
-      const std::string& name,
-      const DebugDaemonClient::CupsRemovePrinterCallback& callback,
-      const base::Closure& error_callback) override {
+  void CupsRemovePrinter(const std::string& name,
+                         DebugDaemonClient::CupsRemovePrinterCallback callback,
+                         const base::Closure& error_callback) override {
     dbus::MethodCall method_call(debugd::kDebugdInterface,
                                  debugd::kCupsRemovePrinter);
     dbus::MessageWriter writer(&method_call);
@@ -514,7 +513,7 @@
     debugdaemon_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(&DebugDaemonClientImpl::OnPrinterRemoved,
-                       weak_ptr_factory_.GetWeakPtr(), callback,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback),
                        error_callback));
   }
 
@@ -790,12 +789,12 @@
     std::move(callback).Run(dbus_error);
   }
 
-  void OnPrinterRemoved(const CupsRemovePrinterCallback& callback,
+  void OnPrinterRemoved(CupsRemovePrinterCallback callback,
                         const base::Closure& error_callback,
                         dbus::Response* response) {
     bool result = false;
     if (response && dbus::MessageReader(response).PopBool(&result))
-      callback.Run(result);
+      std::move(callback).Run(result);
     else
       error_callback.Run();
   }
diff --git a/chromeos/dbus/debug_daemon_client.h b/chromeos/dbus/debug_daemon_client.h
index ddd3a59..6af26dfd 100644
--- a/chromeos/dbus/debug_daemon_client.h
+++ b/chromeos/dbus/debug_daemon_client.h
@@ -212,14 +212,14 @@
       CupsAddPrinterCallback callback) = 0;
 
   // A callback to handle the result of CupsRemovePrinter.
-  using CupsRemovePrinterCallback = base::Callback<void(bool success)>;
+  using CupsRemovePrinterCallback = base::OnceCallback<void(bool success)>;
 
   // Calls CupsRemovePrinter.  |name| is the printer name as registered in
   // CUPS.  |callback| is called with true if removing the printer from CUPS was
   // successful and false if there was an error.  |error_callback| will be
   // called if there was an error in communicating with debugd.
   virtual void CupsRemovePrinter(const std::string& name,
-                                 const CupsRemovePrinterCallback& callback,
+                                 CupsRemovePrinterCallback callback,
                                  const base::Closure& error_callback) = 0;
 
   // A callback to handle the result of StartConcierge/StopConcierge.
diff --git a/chromeos/dbus/fake_debug_daemon_client.cc b/chromeos/dbus/fake_debug_daemon_client.cc
index 146274bfe..f88b566 100644
--- a/chromeos/dbus/fake_debug_daemon_client.cc
+++ b/chromeos/dbus/fake_debug_daemon_client.cc
@@ -248,14 +248,14 @@
 
 void FakeDebugDaemonClient::CupsRemovePrinter(
     const std::string& name,
-    const DebugDaemonClient::CupsRemovePrinterCallback& callback,
+    DebugDaemonClient::CupsRemovePrinterCallback callback,
     const base::Closure& error_callback) {
   const bool has_printer = base::ContainsKey(printers_, name);
   if (has_printer)
     printers_.erase(name);
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, has_printer));
+      FROM_HERE, base::BindOnce(std::move(callback), has_printer));
 }
 
 void FakeDebugDaemonClient::StartConcierge(ConciergeCallback callback) {
diff --git a/chromeos/dbus/fake_debug_daemon_client.h b/chromeos/dbus/fake_debug_daemon_client.h
index dc9f235..a2c22f3 100644
--- a/chromeos/dbus/fake_debug_daemon_client.h
+++ b/chromeos/dbus/fake_debug_daemon_client.h
@@ -85,7 +85,7 @@
                                     const std::string& uri,
                                     CupsAddPrinterCallback callback) override;
   void CupsRemovePrinter(const std::string& name,
-                         const CupsRemovePrinterCallback& callback,
+                         CupsRemovePrinterCallback callback,
                          const base::Closure& error_callback) override;
   void StartConcierge(ConciergeCallback callback) override;
   void StopConcierge(ConciergeCallback callback) override;
diff --git a/chromeos/dbus/power/fake_power_manager_client.cc b/chromeos/dbus/power/fake_power_manager_client.cc
index fcc44fc8..8d8634d 100644
--- a/chromeos/dbus/power/fake_power_manager_client.cc
+++ b/chromeos/dbus/power/fake_power_manager_client.cc
@@ -254,11 +254,11 @@
       FROM_HERE, base::BindOnce(std::move(callback), inactivity_delays_));
 }
 
-base::Closure FakePowerManagerClient::GetSuspendReadinessCallback(
+base::OnceClosure FakePowerManagerClient::GetSuspendReadinessCallback(
     const base::Location& from_where) {
   ++num_pending_suspend_readiness_callbacks_;
-  return base::Bind(&FakePowerManagerClient::HandleSuspendReadiness,
-                    base::Unretained(this));
+  return base::BindOnce(&FakePowerManagerClient::HandleSuspendReadiness,
+                        base::Unretained(this));
 }
 
 void FakePowerManagerClient::CreateArcTimers(
diff --git a/chromeos/dbus/power/fake_power_manager_client.h b/chromeos/dbus/power/fake_power_manager_client.h
index 1faac2a..77ec74f 100644
--- a/chromeos/dbus/power/fake_power_manager_client.h
+++ b/chromeos/dbus/power/fake_power_manager_client.h
@@ -113,7 +113,7 @@
   void GetInactivityDelays(
       DBusMethodCallback<power_manager::PowerManagementPolicy::Delays> callback)
       override;
-  base::Closure GetSuspendReadinessCallback(
+  base::OnceClosure GetSuspendReadinessCallback(
       const base::Location& from_where) override;
   void CreateArcTimers(
       const std::string& tag,
diff --git a/chromeos/dbus/power/power_manager_client.cc b/chromeos/dbus/power/power_manager_client.cc
index 8d66107..ecbf593 100644
--- a/chromeos/dbus/power/power_manager_client.cc
+++ b/chromeos/dbus/power/power_manager_client.cc
@@ -451,16 +451,17 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
-  base::Closure GetSuspendReadinessCallback(
+  base::OnceClosure GetSuspendReadinessCallback(
       const base::Location& from_where) override {
     DCHECK(OnOriginThread());
     DCHECK(suspend_is_pending_);
 
     const int callback_id = next_suspend_readiness_callback_id_++;
     pending_suspend_readiness_callbacks_[callback_id] = from_where;
-    return base::Bind(&PowerManagerClientImpl::HandleObserverSuspendReadiness,
-                      weak_ptr_factory_.GetWeakPtr(), pending_suspend_id_,
-                      suspending_from_dark_resume_, callback_id);
+    return base::BindOnce(
+        &PowerManagerClientImpl::HandleObserverSuspendReadiness,
+        weak_ptr_factory_.GetWeakPtr(), pending_suspend_id_,
+        suspending_from_dark_resume_, callback_id);
   }
 
   void CreateArcTimers(
diff --git a/chromeos/dbus/power/power_manager_client.h b/chromeos/dbus/power/power_manager_client.h
index b6356af..5b6fbc0 100644
--- a/chromeos/dbus/power/power_manager_client.h
+++ b/chromeos/dbus/power/power_manager_client.h
@@ -276,7 +276,7 @@
 
   // Returns a callback that can be called by an observer to report readiness
   // for suspend. See Observer::SuspendImminent().
-  virtual base::Closure GetSuspendReadinessCallback(
+  virtual base::OnceClosure GetSuspendReadinessCallback(
       const base::Location& from_where) = 0;
 
   // Creates timers corresponding to clocks present in |arc_timer_requests|.
diff --git a/chromeos/dbus/power/power_manager_client_unittest.cc b/chromeos/dbus/power/power_manager_client_unittest.cc
index 255f167..a2c9d7c 100644
--- a/chromeos/dbus/power/power_manager_client_unittest.cc
+++ b/chromeos/dbus/power/power_manager_client_unittest.cc
@@ -92,8 +92,8 @@
   int num_suspend_imminent() const { return num_suspend_imminent_; }
   int num_suspend_done() const { return num_suspend_done_; }
   int num_dark_suspend_imminent() const { return num_dark_suspend_imminent_; }
-  base::Closure suspend_readiness_callback() const {
-    return suspend_readiness_callback_;
+  base::OnceClosure suspend_readiness_callback() {
+    return std::move(suspend_readiness_callback_);
   }
 
   void set_take_suspend_readiness_callback(bool take_callback) {
@@ -108,9 +108,7 @@
     if (suspend_readiness_callback_.is_null())
       return false;
 
-    auto cb = suspend_readiness_callback_;
-    suspend_readiness_callback_.Reset();
-    cb.Run();
+    std::move(suspend_readiness_callback_).Run();
     return true;
   }
 
@@ -156,7 +154,7 @@
   bool run_suspend_readiness_callback_immediately_ = false;
 
   // Callback returned by |client_|'s GetSuspendReadinessCallback() method.
-  base::Closure suspend_readiness_callback_;
+  base::OnceClosure suspend_readiness_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(TestObserver);
 };
@@ -531,20 +529,20 @@
   const int kSuspendId = 1;
   EmitSuspendImminentSignal(kSuspendImminent, kSuspendId);
   EXPECT_EQ(1, observer.num_suspend_imminent());
-  base::Closure regular_callback = observer.suspend_readiness_callback();
+  base::OnceClosure regular_callback = observer.suspend_readiness_callback();
 
   // Before readiness is reported, announce that dark suspend is imminent.
   const int kDarkSuspendId = 1;
   EmitSuspendImminentSignal(kDarkSuspendImminent, kDarkSuspendId);
   EXPECT_EQ(1, observer.num_dark_suspend_imminent());
-  base::Closure dark_callback = observer.suspend_readiness_callback();
+  base::OnceClosure dark_callback = observer.suspend_readiness_callback();
 
   // Complete the suspend attempt and run both of the earlier callbacks. Neither
   // should result in readiness being reported.
   EmitSuspendDoneSignal(kSuspendId);
   EXPECT_EQ(1, observer.num_suspend_done());
-  regular_callback.Run();
-  dark_callback.Run();
+  std::move(regular_callback).Run();
+  std::move(dark_callback).Run();
 }
 
 // Tests that PowerManagerClient handles a single observer that requests a
diff --git a/chromeos/dbus/power/power_policy_controller.cc b/chromeos/dbus/power/power_policy_controller.cc
index ae11e47..645a16e 100644
--- a/chromeos/dbus/power/power_policy_controller.cc
+++ b/chromeos/dbus/power/power_policy_controller.cc
@@ -6,6 +6,7 @@
 
 #include <stdint.h>
 
+#include <algorithm>
 #include <memory>
 #include <utility>
 
@@ -80,6 +81,32 @@
   return true;
 }
 
+// Adjusts |delays| appropriately for backlights having been forced off by
+// tapping the power button. The idle delay is shortened to (idle - screen off),
+// and the idle warning delay (if set) is shortened to (idle warning - screen
+// off). All other delays are cleared, as the display should already be off.
+void AdjustDelaysForBacklightsForcedOff(
+    power_manager::PowerManagementPolicy::Delays* delays) {
+  if (delays->screen_off_ms() <= 0 || delays->idle_ms() <= 0)
+    return;
+
+  // The screen-off delay should always be shorter than or equal to the idle
+  // delay, but we clamp the value just in case the prefs don't adhere to this.
+  // powerd only honors delays that are greater than 0, so use 1 ms as the min.
+  const int64_t idle_ms = std::max(delays->idle_ms() - delays->screen_off_ms(),
+                                   static_cast<int64_t>(1));
+  const int64_t warn_ms =
+      delays->idle_warning_ms() > 0
+          ? std::max(delays->idle_warning_ms() - delays->screen_off_ms(),
+                     static_cast<int64_t>(1))
+          : -1;
+
+  delays->Clear();
+  delays->set_idle_ms(idle_ms);
+  if (warn_ms > 0)
+    delays->set_idle_warning_ms(warn_ms);
+}
+
 power_manager::PowerManagementPolicy::PeakShiftDayConfig::WeekDay
 GetProtoWeekDay(PowerPolicyController::WeekDay week_day) {
   switch (week_day) {
@@ -113,44 +140,12 @@
 
 }  // namespace
 
+PowerPolicyController::PrefValues::PrefValues() = default;
+PowerPolicyController::PrefValues::~PrefValues() = default;
+
 const int PowerPolicyController::kScreenLockAfterOffDelayMs = 10000;  // 10 sec.
 const char PowerPolicyController::kPrefsReason[] = "Prefs";
 
-// -1 is interpreted as "unset" by powerd, resulting in powerd's default
-// delays being used instead.  There are no similarly-interpreted values
-// for the other fields, unfortunately (but the constructor-assigned values
-// will only reach powerd if Chrome messes up and forgets to override them
-// with the pref-assigned values).
-PowerPolicyController::PrefValues::PrefValues()
-    : ac_screen_dim_delay_ms(-1),
-      ac_screen_off_delay_ms(-1),
-      ac_screen_lock_delay_ms(-1),
-      ac_idle_warning_delay_ms(-1),
-      ac_idle_delay_ms(-1),
-      battery_screen_dim_delay_ms(-1),
-      battery_screen_off_delay_ms(-1),
-      battery_screen_lock_delay_ms(-1),
-      battery_idle_warning_delay_ms(-1),
-      battery_idle_delay_ms(-1),
-      ac_idle_action(ACTION_SUSPEND),
-      battery_idle_action(ACTION_SUSPEND),
-      lid_closed_action(ACTION_SUSPEND),
-      use_audio_activity(true),
-      use_video_activity(true),
-      ac_brightness_percent(-1.0),
-      battery_brightness_percent(-1.0),
-      allow_wake_locks(true),
-      allow_screen_wake_locks(true),
-      enable_auto_screen_lock(false),
-      presentation_screen_dim_delay_factor(1.0),
-      user_activity_screen_dim_delay_factor(1.0),
-      wait_for_initial_user_activity(false),
-      force_nonzero_brightness_for_user_activity(true),
-      peak_shift_enabled(false),
-      peak_shift_battery_threshold(-1) {}
-
-PowerPolicyController::PrefValues::~PrefValues() = default;
-
 // static
 std::string PowerPolicyController::GetPolicyDebugString(
     const power_manager::PowerManagementPolicy& policy) {
@@ -321,6 +316,9 @@
   honor_screen_wake_locks_ =
       honor_wake_locks_ && values.allow_screen_wake_locks;
 
+  fast_suspend_when_backlights_forced_off_ =
+      values.fast_suspend_when_backlights_forced_off;
+
   if (values.peak_shift_enabled) {
     prefs_policy_.set_peak_shift_battery_percent_threshold(
         values.peak_shift_battery_threshold);
@@ -395,6 +393,14 @@
   SendCurrentPolicy();
 }
 
+void PowerPolicyController::HandleBacklightsForcedOffForPowerButton(
+    bool forced_off) {
+  if (forced_off == backlights_forced_off_for_power_button_)
+    return;
+  backlights_forced_off_for_power_button_ = forced_off;
+  SendCurrentPolicy();
+}
+
 void PowerPolicyController::SetEncryptionMigrationActive(bool active) {
   if (encryption_migration_active_ == active)
     return;
@@ -436,6 +442,19 @@
   if (prefs_were_set_)
     causes = kPrefsReason;
 
+  // Shorten suspend delays if the backlight is forced off via the power button.
+  if (backlights_forced_off_for_power_button_ &&
+      fast_suspend_when_backlights_forced_off_) {
+    if (policy.ac_idle_action() ==
+        power_manager::PowerManagementPolicy_Action_SUSPEND) {
+      AdjustDelaysForBacklightsForcedOff(policy.mutable_ac_delays());
+    }
+    if (policy.battery_idle_action() ==
+        power_manager::PowerManagementPolicy_Action_SUSPEND) {
+      AdjustDelaysForBacklightsForcedOff(policy.mutable_battery_delays());
+    }
+  }
+
   if (honor_wake_locks_) {
     bool have_screen_wake_locks = false;
     bool have_dim_wake_locks = false;
diff --git a/chromeos/dbus/power/power_policy_controller.h b/chromeos/dbus/power/power_policy_controller.h
index c61e565..343e370 100644
--- a/chromeos/dbus/power/power_policy_controller.h
+++ b/chromeos/dbus/power/power_policy_controller.h
@@ -78,32 +78,39 @@
     PrefValues();
     ~PrefValues();
 
-    int ac_screen_dim_delay_ms;
-    int ac_screen_off_delay_ms;
-    int ac_screen_lock_delay_ms;
-    int ac_idle_warning_delay_ms;
-    int ac_idle_delay_ms;
-    int battery_screen_dim_delay_ms;
-    int battery_screen_off_delay_ms;
-    int battery_screen_lock_delay_ms;
-    int battery_idle_warning_delay_ms;
-    int battery_idle_delay_ms;
-    Action ac_idle_action;
-    Action battery_idle_action;
-    Action lid_closed_action;
-    bool use_audio_activity;
-    bool use_video_activity;
-    double ac_brightness_percent;
-    double battery_brightness_percent;
-    bool allow_wake_locks;
-    bool allow_screen_wake_locks;
-    bool enable_auto_screen_lock;
-    double presentation_screen_dim_delay_factor;
-    double user_activity_screen_dim_delay_factor;
-    bool wait_for_initial_user_activity;
-    bool force_nonzero_brightness_for_user_activity;
-    bool peak_shift_enabled;
-    int peak_shift_battery_threshold;
+    // -1 is interpreted as "unset" by powerd, resulting in powerd's default
+    // delays being used instead. There are no similarly-interpreted values for
+    // the other fields, unfortunately (but the default values would only reach
+    // powerd if Chrome failed to override them with the pref-assigned values).
+    int ac_screen_dim_delay_ms = -1;
+    int ac_screen_off_delay_ms = -1;
+    int ac_screen_lock_delay_ms = -1;
+    int ac_idle_warning_delay_ms = -1;
+    int ac_idle_delay_ms = -1;
+    int battery_screen_dim_delay_ms = -1;
+    int battery_screen_off_delay_ms = -1;
+    int battery_screen_lock_delay_ms = -1;
+    int battery_idle_warning_delay_ms = -1;
+    int battery_idle_delay_ms = -1;
+
+    Action ac_idle_action = ACTION_SUSPEND;
+    Action battery_idle_action = ACTION_SUSPEND;
+    Action lid_closed_action = ACTION_SUSPEND;
+
+    bool use_audio_activity = true;
+    bool use_video_activity = true;
+    double ac_brightness_percent = -1.0;
+    double battery_brightness_percent = -1.0;
+    bool allow_wake_locks = true;
+    bool allow_screen_wake_locks = true;
+    bool enable_auto_screen_lock = false;
+    double presentation_screen_dim_delay_factor = 1.0;
+    double user_activity_screen_dim_delay_factor = 1.0;
+    bool wait_for_initial_user_activity = false;
+    bool force_nonzero_brightness_for_user_activity = true;
+    bool fast_suspend_when_backlights_forced_off = true;
+    bool peak_shift_enabled = false;
+    int peak_shift_battery_threshold = -1;
     std::vector<PeakShiftDayConfiguration> peak_shift_day_configurations;
   };
 
@@ -152,6 +159,10 @@
   // down.
   void NotifyChromeIsExiting();
 
+  // Adjusts policy when the display is forced off in response to the
+  // user tapping the power button, or when it's no longer forced off.
+  void HandleBacklightsForcedOffForPowerButton(bool forced_off);
+
   // Adjusts policy when the migration of a user homedir to a new
   // encryption format starts or stops. While migration is active,
   // the lid-closed action is overridden to ensure the system
@@ -235,6 +246,14 @@
   // True if Chrome is in the process of exiting.
   bool chrome_is_exiting_ = false;
 
+  // True if the screen is currently forced off due to the user having tapped
+  // the power button.
+  bool backlights_forced_off_for_power_button_ = false;
+
+  // True if suspend delays should be shortened when
+  // |backlights_forced_off_for_power_button_| is true. Set from prefs.
+  bool fast_suspend_when_backlights_forced_off_ = true;
+
   // True if a user homedir is in the process of migrating encryption formats.
   bool encryption_migration_active_ = false;
 
diff --git a/chromeos/dbus/power/power_policy_controller_unittest.cc b/chromeos/dbus/power/power_policy_controller_unittest.cc
index 35d3d03..4c546ed3 100644
--- a/chromeos/dbus/power/power_policy_controller_unittest.cc
+++ b/chromeos/dbus/power/power_policy_controller_unittest.cc
@@ -443,4 +443,76 @@
       base::TimeDelta::FromMilliseconds(prefs.battery_screen_lock_delay_ms),
       policy_controller_->Get()->GetMaxPolicyAutoScreenLockDelay());
 }
+
+TEST_F(PowerPolicyControllerTest, FastSuspendWhenBacklightsForcedOff) {
+  const int kAcDimMs = 600000;            // 10m
+  const int kAcOffMs = 620000;            // 10m20s
+  const int kAcLockMs = 610000;           // 10m10s
+  const int kAcIdleWarnMs = 650000;       // 10m50s
+  const int kAcIdleMs = 660000;           // 11m
+  const int kBatteryDimMs = 300000;       // 5m
+  const int kBatteryOffMs = 310000;       // 5m10s
+  const int kBatteryLockMs = 320000;      // 5m20s
+  const int kBatteryIdleWarnMs = 355000;  // 5m55s
+  const int kBatteryIdleMs = 360000;      // 6m
+
+  PowerPolicyController::PrefValues prefs;
+  prefs.ac_screen_dim_delay_ms = kAcDimMs;
+  prefs.ac_screen_off_delay_ms = kAcOffMs;
+  prefs.ac_screen_lock_delay_ms = kAcLockMs;
+  prefs.ac_idle_warning_delay_ms = kAcIdleWarnMs;
+  prefs.ac_idle_delay_ms = kAcIdleMs;
+  prefs.battery_screen_dim_delay_ms = kBatteryDimMs;
+  prefs.battery_screen_off_delay_ms = kBatteryOffMs;
+  prefs.battery_screen_lock_delay_ms = kBatteryLockMs;
+  prefs.battery_idle_warning_delay_ms = kBatteryIdleWarnMs;
+  prefs.battery_idle_delay_ms = kBatteryIdleMs;
+  prefs.ac_idle_action = PowerPolicyController::ACTION_SUSPEND;
+  prefs.battery_idle_action = PowerPolicyController::ACTION_SUSPEND;
+  prefs.fast_suspend_when_backlights_forced_off = true;
+  policy_controller_->ApplyPrefs(prefs);
+
+  // We should start out with the delays specified by the prefs.
+  power_manager::PowerManagementPolicy policy = power_manager()->policy();
+  EXPECT_EQ(kAcDimMs, policy.ac_delays().screen_dim_ms());
+  EXPECT_EQ(kAcOffMs, policy.ac_delays().screen_off_ms());
+  EXPECT_EQ(kAcLockMs, policy.ac_delays().screen_lock_ms());
+  EXPECT_EQ(kAcIdleWarnMs, policy.ac_delays().idle_warning_ms());
+  EXPECT_EQ(kAcIdleMs, policy.ac_delays().idle_ms());
+  EXPECT_EQ(kBatteryDimMs, policy.battery_delays().screen_dim_ms());
+  EXPECT_EQ(kBatteryOffMs, policy.battery_delays().screen_off_ms());
+  EXPECT_EQ(kBatteryLockMs, policy.battery_delays().screen_lock_ms());
+  EXPECT_EQ(kBatteryIdleWarnMs, policy.battery_delays().idle_warning_ms());
+  EXPECT_EQ(kBatteryIdleMs, policy.battery_delays().idle_ms());
+
+  // After reporting that the backlights were forced off for a power button
+  // press, the idle and idle-warning delays should be shortened and other
+  // delays should be cleared.
+  policy_controller_->HandleBacklightsForcedOffForPowerButton(true);
+  policy = power_manager()->policy();
+  EXPECT_EQ(0, policy.ac_delays().screen_dim_ms());
+  EXPECT_EQ(0, policy.ac_delays().screen_off_ms());
+  EXPECT_EQ(0, policy.ac_delays().screen_lock_ms());
+  EXPECT_EQ(kAcIdleWarnMs - kAcOffMs, policy.ac_delays().idle_warning_ms());
+  EXPECT_EQ(kAcIdleMs - kAcOffMs, policy.ac_delays().idle_ms());
+  EXPECT_EQ(0, policy.battery_delays().screen_dim_ms());
+  EXPECT_EQ(0, policy.battery_delays().screen_off_ms());
+  EXPECT_EQ(0, policy.battery_delays().screen_lock_ms());
+  EXPECT_EQ(kBatteryIdleWarnMs - kBatteryOffMs,
+            policy.battery_delays().idle_warning_ms());
+  EXPECT_EQ(kBatteryIdleMs - kBatteryOffMs, policy.battery_delays().idle_ms());
+
+  // If the screen-off delay is equal to the idle delay and longer than the
+  // idle-warning delay, both the idle and idle-warning delays should be set to
+  // 1 (the minimum delay allowed by powerd).
+  prefs.ac_screen_off_delay_ms = kAcIdleMs;
+  policy_controller_->ApplyPrefs(prefs);
+  policy = power_manager()->policy();
+  EXPECT_EQ(0, policy.ac_delays().screen_dim_ms());
+  EXPECT_EQ(0, policy.ac_delays().screen_off_ms());
+  EXPECT_EQ(0, policy.ac_delays().screen_lock_ms());
+  EXPECT_EQ(1, policy.ac_delays().idle_warning_ms());
+  EXPECT_EQ(1, policy.ac_delays().idle_ms());
+}
+
 }  // namespace chromeos
diff --git a/chromeos/dbus/session_manager/BUILD.gn b/chromeos/dbus/session_manager/BUILD.gn
new file mode 100644
index 0000000..ca8831f
--- /dev/null
+++ b/chromeos/dbus/session_manager/BUILD.gn
@@ -0,0 +1,42 @@
+# Copyright 2019 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("//third_party/protobuf/proto_library.gni")
+
+assert(is_chromeos, "Non-Chrome-OS builds cannot depend on //chromeos")
+
+component("session_manager") {
+  defines = [ "IS_SESSION_MANAGER_IMPL" ]
+
+  public_deps = [
+    ":login_manager_proto",
+  ]
+
+  deps = [
+    "//base",
+    "//chromeos/dbus:common",
+    "//chromeos/dbus/constants",
+    "//chromeos/dbus/cryptohome",
+    "//chromeos/dbus/cryptohome:cryptohome_proto",
+    "//components/policy/proto",
+    "//crypto",
+    "//dbus",
+  ]
+
+  sources = [
+    "fake_session_manager_client.cc",
+    "fake_session_manager_client.h",
+    "session_manager_client.cc",
+    "session_manager_client.h",
+  ]
+}
+
+proto_library("login_manager_proto") {
+  sources = [
+    "//third_party/cros_system_api/dbus/login_manager/arc.proto",
+    "//third_party/cros_system_api/dbus/login_manager/policy_descriptor.proto",
+  ]
+
+  proto_out_dir = "chromeos/dbus/login_manager"
+}
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.cc b/chromeos/dbus/session_manager/fake_session_manager_client.cc
index 4189778..48504fb 100644
--- a/chromeos/dbus/session_manager/fake_session_manager_client.cc
+++ b/chromeos/dbus/session_manager/fake_session_manager_client.cc
@@ -44,6 +44,8 @@
 constexpr char kStubPerAccountPolicyKeyFileName[] = "policy.pub";
 constexpr char kEmptyAccountId[] = "";
 
+FakeSessionManagerClient* g_instance = nullptr;
+
 // Helper to asynchronously retrieve a file's content.
 std::string GetFileContent(const base::FilePath& path) {
   std::string result;
@@ -229,11 +231,20 @@
       screen_is_locked_(false),
       arc_available_(false),
       delegate_(nullptr),
-      weak_ptr_factory_(this) {}
+      weak_ptr_factory_(this) {
+  DCHECK(!g_instance);
+  g_instance = this;
+}
 
-FakeSessionManagerClient::~FakeSessionManagerClient() = default;
+FakeSessionManagerClient::~FakeSessionManagerClient() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
 
-void FakeSessionManagerClient::Init(dbus::Bus* bus) {}
+// static
+FakeSessionManagerClient* FakeSessionManagerClient::Get() {
+  return g_instance;
+}
 
 void FakeSessionManagerClient::SetStubDelegate(StubDelegate* delegate) {
   delegate_ = delegate;
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.h b/chromeos/dbus/session_manager/fake_session_manager_client.h
index 8c45ad7..b909932 100644
--- a/chromeos/dbus/session_manager/fake_session_manager_client.h
+++ b/chromeos/dbus/session_manager/fake_session_manager_client.h
@@ -22,7 +22,7 @@
 
 // A fake implementation of session_manager. Accepts policy blobs to be set and
 // returns them unmodified.
-class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeSessionManagerClient
+class COMPONENT_EXPORT(SESSION_MANAGER) FakeSessionManagerClient
     : public SessionManagerClient {
  public:
   enum class PolicyStorageType {
@@ -32,12 +32,20 @@
     kInMemory,  // Store policy in memory only. Usually used for tests.
   };
 
+  // Constructs a FakeSessionManagerClient with PolicyStorageType == kInMemory.
+  // NOTE: This is different from SessionManagerClient::InitializeFake which
+  // constructs an instance with PolicyStorageType == kOnDisk. Use
+  // SessionManagerClient::InitializeFakeInMemory when replacing this.
   FakeSessionManagerClient();
+
   explicit FakeSessionManagerClient(PolicyStorageType policy_storage);
+
   ~FakeSessionManagerClient() override;
 
+  // Returns the fake global instance if initialized. May return null.
+  static FakeSessionManagerClient* Get();
+
   // SessionManagerClient overrides
-  void Init(dbus::Bus* bus) override;
   void SetStubDelegate(StubDelegate* delegate) override;
   void AddObserver(Observer* observer) override;
   void RemoveObserver(Observer* observer) override;
diff --git a/chromeos/dbus/session_manager/session_manager_client.cc b/chromeos/dbus/session_manager/session_manager_client.cc
index efbe74b..ca500cc 100644
--- a/chromeos/dbus/session_manager/session_manager_client.cc
+++ b/chromeos/dbus/session_manager/session_manager_client.cc
@@ -39,6 +39,8 @@
 
 namespace {
 
+SessionManagerClient* g_instance = nullptr;
+
 using RetrievePolicyResponseType =
     SessionManagerClient::RetrievePolicyResponseType;
 
@@ -126,8 +128,7 @@
 // The SessionManagerClient implementation used in production.
 class SessionManagerClientImpl : public SessionManagerClient {
  public:
-  SessionManagerClientImpl() : weak_ptr_factory_(this) {}
-
+  SessionManagerClientImpl() = default;
   ~SessionManagerClientImpl() override = default;
 
   // SessionManagerClient overrides:
@@ -482,8 +483,7 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
- protected:
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus) {
     session_manager_proxy_ = bus->GetObjectProxy(
         login_manager::kSessionManagerServiceName,
         dbus::ObjectPath(login_manager::kSessionManagerServicePath));
@@ -841,22 +841,52 @@
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
-  base::WeakPtrFactory<SessionManagerClientImpl> weak_ptr_factory_;
+  base::WeakPtrFactory<SessionManagerClientImpl> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(SessionManagerClientImpl);
 };
 
-SessionManagerClient::SessionManagerClient() = default;
+SessionManagerClient::SessionManagerClient() {
+  DCHECK(!g_instance);
+  g_instance = this;
+}
 
-SessionManagerClient::~SessionManagerClient() = default;
+SessionManagerClient::~SessionManagerClient() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
 
-SessionManagerClient* SessionManagerClient::Create(
-    DBusClientImplementationType type) {
-  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
-    return new SessionManagerClientImpl();
-  DCHECK_EQ(FAKE_DBUS_CLIENT_IMPLEMENTATION, type);
-  return new FakeSessionManagerClient(
-      FakeSessionManagerClient::PolicyStorageType::kOnDisk);
+// static
+void SessionManagerClient::Initialize(dbus::Bus* bus) {
+  DCHECK(bus);
+  (new SessionManagerClientImpl)->Init(bus);
+}
+
+// static
+void SessionManagerClient::InitializeFake() {
+  // Do not create a new fake if it was initialized early in a browser test (for
+  // early setup calls dependent on SessionManagerClient).
+  if (!FakeSessionManagerClient::Get()) {
+    new FakeSessionManagerClient(
+        FakeSessionManagerClient::PolicyStorageType::kOnDisk);
+  }
+}
+
+// static
+void SessionManagerClient::InitializeFakeInMemory() {
+  new FakeSessionManagerClient(
+      FakeSessionManagerClient::PolicyStorageType::kInMemory);
+}
+
+// static
+void SessionManagerClient::Shutdown() {
+  DCHECK(g_instance);
+  delete g_instance;
+}
+
+// static
+SessionManagerClient* SessionManagerClient::Get() {
+  return g_instance;
 }
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/session_manager/session_manager_client.h b/chromeos/dbus/session_manager/session_manager_client.h
index ac4fe5d4..1492996c 100644
--- a/chromeos/dbus/session_manager/session_manager_client.h
+++ b/chromeos/dbus/session_manager/session_manager_client.h
@@ -14,8 +14,6 @@
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
-#include "chromeos/dbus/dbus_client.h"
-#include "chromeos/dbus/dbus_client_implementation_type.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
 #include "third_party/cros_system_api/dbus/login_manager/dbus-constants.h"
 
@@ -23,6 +21,10 @@
 class AccountIdentifier;
 }
 
+namespace dbus {
+class Bus;
+}
+
 namespace login_manager {
 class PolicyDescriptor;
 class StartArcMiniContainerRequest;
@@ -32,7 +34,7 @@
 namespace chromeos {
 
 // SessionManagerClient is used to communicate with the session manager.
-class COMPONENT_EXPORT(CHROMEOS_DBUS) SessionManagerClient : public DBusClient {
+class COMPONENT_EXPORT(SESSION_MANAGER) SessionManagerClient {
  public:
   // The result type received from session manager on request to retrieve the
   // policy. Used to define the buckets for an enumerated UMA histogram.
@@ -92,6 +94,21 @@
     virtual void LockScreenForStub() = 0;
   };
 
+  // Creates and initializes the global instance. |bus| must not be null.
+  static void Initialize(dbus::Bus* bus);
+
+  // Creates and initializes a fake global instance if not already created.
+  static void InitializeFake();
+
+  // Creates and initializes an InMemory fake global instance for testing.
+  static void InitializeFakeInMemory();
+
+  // Destroys the global instance which must have been initialized.
+  static void Shutdown();
+
+  // Returns the global instance if initialized. May return null.
+  static SessionManagerClient* Get();
+
   // Sets the delegate used by the stub implementation. Ownership of |delegate|
   // remains with the caller.
   virtual void SetStubDelegate(StubDelegate* delegate) = 0;
@@ -362,14 +379,10 @@
   virtual void GetArcStartTime(
       DBusMethodCallback<base::TimeTicks> callback) = 0;
 
-  // Creates the instance.
-  static SessionManagerClient* Create(DBusClientImplementationType type);
-
-  ~SessionManagerClient() override;
-
  protected:
-  // Create() should be used instead.
+  // Use Initialize/Shutdown instead.
   SessionManagerClient();
+  virtual ~SessionManagerClient();
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SessionManagerClient);
diff --git a/chromeos/dbus/fake_gsm_sms_client.cc b/chromeos/dbus/shill/fake_gsm_sms_client.cc
similarity index 94%
rename from chromeos/dbus/fake_gsm_sms_client.cc
rename to chromeos/dbus/shill/fake_gsm_sms_client.cc
index 6a72b78..5b3ad438 100644
--- a/chromeos/dbus/fake_gsm_sms_client.cc
+++ b/chromeos/dbus/shill/fake_gsm_sms_client.cc
@@ -11,7 +11,7 @@
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "chromeos/dbus/fake_gsm_sms_client.h"
+#include "chromeos/dbus/shill/fake_gsm_sms_client.h"
 
 namespace chromeos {
 
@@ -22,8 +22,9 @@
   test_messages_.push_back("Test Message 0");
   test_messages_.push_back("Test Message 1");
   test_messages_.push_back("Test a relatively long message 2");
-  test_messages_.push_back("Test a very, the quick brown fox jumped"
-                           " over the lazy dog, long message 3");
+  test_messages_.push_back(
+      "Test a very, the quick brown fox jumped"
+      " over the lazy dog, long message 3");
   test_messages_.push_back("Test Message 4");
   test_messages_.push_back("Test Message 5");
   test_messages_.push_back("Test Message 6");
@@ -31,8 +32,7 @@
 
 FakeGsmSMSClient::~FakeGsmSMSClient() = default;
 
-void FakeGsmSMSClient::Init(dbus::Bus* bus) {
-}
+void FakeGsmSMSClient::Init(dbus::Bus* bus) {}
 
 void FakeGsmSMSClient::SetSmsReceivedHandler(
     const std::string& service_name,
diff --git a/chromeos/dbus/fake_gsm_sms_client.h b/chromeos/dbus/shill/fake_gsm_sms_client.h
similarity index 91%
rename from chromeos/dbus/fake_gsm_sms_client.h
rename to chromeos/dbus/shill/fake_gsm_sms_client.h
index a3feff7..12d46a4 100644
--- a/chromeos/dbus/fake_gsm_sms_client.h
+++ b/chromeos/dbus/shill/fake_gsm_sms_client.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 CHROMEOS_DBUS_FAKE_GSM_SMS_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_GSM_SMS_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_FAKE_GSM_SMS_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_FAKE_GSM_SMS_CLIENT_H_
 
 #include <stdint.h>
 
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
-#include "chromeos/dbus/gsm_sms_client.h"
+#include "chromeos/dbus/shill/gsm_sms_client.h"
 #include "dbus/object_path.h"
 
 namespace chromeos {
@@ -70,4 +70,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_GSM_SMS_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_FAKE_GSM_SMS_CLIENT_H_
diff --git a/chromeos/dbus/fake_modem_messaging_client.cc b/chromeos/dbus/shill/fake_modem_messaging_client.cc
similarity index 96%
rename from chromeos/dbus/fake_modem_messaging_client.cc
rename to chromeos/dbus/shill/fake_modem_messaging_client.cc
index 0cd443a..c9d66e9 100644
--- a/chromeos/dbus/fake_modem_messaging_client.cc
+++ b/chromeos/dbus/shill/fake_modem_messaging_client.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 "chromeos/dbus/fake_modem_messaging_client.h"
+#include "chromeos/dbus/shill/fake_modem_messaging_client.h"
 
 #include <algorithm>
 #include <string>
diff --git a/chromeos/dbus/fake_modem_messaging_client.h b/chromeos/dbus/shill/fake_modem_messaging_client.h
similarity index 85%
rename from chromeos/dbus/fake_modem_messaging_client.h
rename to chromeos/dbus/shill/fake_modem_messaging_client.h
index 6469ed0..5dce655b 100644
--- a/chromeos/dbus/fake_modem_messaging_client.h
+++ b/chromeos/dbus/shill/fake_modem_messaging_client.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 CHROMEOS_DBUS_FAKE_MODEM_MESSAGING_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_MODEM_MESSAGING_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_FAKE_MODEM_MESSAGING_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_FAKE_MODEM_MESSAGING_CLIENT_H_
 
 #include <string>
 #include <vector>
@@ -11,7 +11,7 @@
 #include "base/compiler_specific.h"
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "chromeos/dbus/modem_messaging_client.h"
+#include "chromeos/dbus/shill/modem_messaging_client.h"
 
 namespace chromeos {
 
@@ -44,4 +44,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_MODEM_MESSAGING_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_FAKE_MODEM_MESSAGING_CLIENT_H_
diff --git a/chromeos/dbus/fake_shill_device_client.cc b/chromeos/dbus/shill/fake_shill_device_client.cc
similarity index 99%
rename from chromeos/dbus/fake_shill_device_client.cc
rename to chromeos/dbus/shill/fake_shill_device_client.cc
index 6cfcd586..a3ef2f4 100644
--- a/chromeos/dbus/fake_shill_device_client.cc
+++ b/chromeos/dbus/shill/fake_shill_device_client.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 "chromeos/dbus/fake_shill_device_client.h"
+#include "chromeos/dbus/shill/fake_shill_device_client.h"
 
 #include <algorithm>
 #include <memory>
@@ -17,8 +17,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
diff --git a/chromeos/dbus/fake_shill_device_client.h b/chromeos/dbus/shill/fake_shill_device_client.h
similarity index 97%
rename from chromeos/dbus/fake_shill_device_client.h
rename to chromeos/dbus/shill/fake_shill_device_client.h
index 3341e69..1e658f76 100644
--- a/chromeos/dbus/fake_shill_device_client.h
+++ b/chromeos/dbus/shill/fake_shill_device_client.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 CHROMEOS_DBUS_FAKE_SHILL_DEVICE_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_SHILL_DEVICE_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_FAKE_SHILL_DEVICE_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_FAKE_SHILL_DEVICE_CLIENT_H_
 
 #include <map>
 #include <memory>
@@ -13,7 +13,7 @@
 
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "chromeos/dbus/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
 
 namespace chromeos {
 
@@ -193,4 +193,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_SHILL_DEVICE_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_FAKE_SHILL_DEVICE_CLIENT_H_
diff --git a/chromeos/dbus/fake_shill_ipconfig_client.cc b/chromeos/dbus/shill/fake_shill_ipconfig_client.cc
similarity index 92%
rename from chromeos/dbus/fake_shill_ipconfig_client.cc
rename to chromeos/dbus/shill/fake_shill_ipconfig_client.cc
index 1c935db5..652f34015 100644
--- a/chromeos/dbus/fake_shill_ipconfig_client.cc
+++ b/chromeos/dbus/shill/fake_shill_ipconfig_client.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 "chromeos/dbus/fake_shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/fake_shill_ipconfig_client.h"
 
 #include <memory>
 #include <utility>
@@ -13,7 +13,7 @@
 #include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
@@ -23,23 +23,19 @@
 
 namespace chromeos {
 
-FakeShillIPConfigClient::FakeShillIPConfigClient() : weak_ptr_factory_(this) {
-}
+FakeShillIPConfigClient::FakeShillIPConfigClient() : weak_ptr_factory_(this) {}
 
 FakeShillIPConfigClient::~FakeShillIPConfigClient() = default;
 
-void FakeShillIPConfigClient::Init(dbus::Bus* bus) {
-}
+void FakeShillIPConfigClient::Init(dbus::Bus* bus) {}
 
 void FakeShillIPConfigClient::AddPropertyChangedObserver(
     const dbus::ObjectPath& ipconfig_path,
-    ShillPropertyChangedObserver* observer) {
-}
+    ShillPropertyChangedObserver* observer) {}
 
 void FakeShillIPConfigClient::RemovePropertyChangedObserver(
     const dbus::ObjectPath& ipconfig_path,
-    ShillPropertyChangedObserver* observer) {
-}
+    ShillPropertyChangedObserver* observer) {}
 
 void FakeShillIPConfigClient::Refresh(const dbus::ObjectPath& ipconfig_path,
                                       VoidDBusMethodCallback callback) {}
diff --git a/chromeos/dbus/fake_shill_ipconfig_client.h b/chromeos/dbus/shill/fake_shill_ipconfig_client.h
similarity index 91%
rename from chromeos/dbus/fake_shill_ipconfig_client.h
rename to chromeos/dbus/shill/fake_shill_ipconfig_client.h
index db44930..dd210429 100644
--- a/chromeos/dbus/fake_shill_ipconfig_client.h
+++ b/chromeos/dbus/shill/fake_shill_ipconfig_client.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_FAKE_SHILL_IPCONFIG_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_SHILL_IPCONFIG_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_FAKE_SHILL_IPCONFIG_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_FAKE_SHILL_IPCONFIG_CLIENT_H_
 
 #include <string>
 
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "chromeos/dbus/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
 
 namespace chromeos {
 
@@ -65,4 +65,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_SHILL_IPCONFIG_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_FAKE_SHILL_IPCONFIG_CLIENT_H_
diff --git a/chromeos/dbus/fake_shill_manager_client.cc b/chromeos/dbus/shill/fake_shill_manager_client.cc
similarity index 98%
rename from chromeos/dbus/fake_shill_manager_client.cc
rename to chromeos/dbus/shill/fake_shill_manager_client.cc
index 44c4a06..c25967f 100644
--- a/chromeos/dbus/fake_shill_manager_client.cc
+++ b/chromeos/dbus/shill/fake_shill_manager_client.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 "chromeos/dbus/fake_shill_manager_client.h"
+#include "chromeos/dbus/shill/fake_shill_manager_client.h"
 
 #include <stddef.h>
 
@@ -21,12 +21,12 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/dbus/constants/dbus_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_shill_device_client.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_ipconfig_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/fake_shill_device_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
diff --git a/chromeos/dbus/fake_shill_manager_client.h b/chromeos/dbus/shill/fake_shill_manager_client.h
similarity index 95%
rename from chromeos/dbus/fake_shill_manager_client.h
rename to chromeos/dbus/shill/fake_shill_manager_client.h
index b1e2189d..71c90b88 100644
--- a/chromeos/dbus/fake_shill_manager_client.h
+++ b/chromeos/dbus/shill/fake_shill_manager_client.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 CHROMEOS_DBUS_FAKE_SHILL_MANAGER_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_SHILL_MANAGER_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_FAKE_SHILL_MANAGER_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_FAKE_SHILL_MANAGER_CLIENT_H_
 
 #include <map>
 #include <memory>
@@ -13,7 +13,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 
 namespace chromeos {
 
@@ -121,8 +121,7 @@
   bool ParseOption(const std::string& arg0, const std::string& arg1);
   bool SetInitialNetworkState(std::string type_arg,
                               const std::string& state_arg);
-  std::string GetInitialStateForType(const std::string& type,
-                                     bool* enabled);
+  std::string GetInitialStateForType(const std::string& type, bool* enabled);
 
   // Dictionary of property name -> property value
   base::DictionaryValue stub_properties_;
@@ -172,4 +171,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_SHILL_MANAGER_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_FAKE_SHILL_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/fake_shill_profile_client.cc b/chromeos/dbus/shill/fake_shill_profile_client.cc
similarity index 86%
rename from chromeos/dbus/fake_shill_profile_client.cc
rename to chromeos/dbus/shill/fake_shill_profile_client.cc
index 760727899..3cd86cf9 100644
--- a/chromeos/dbus/fake_shill_profile_client.cc
+++ b/chromeos/dbus/shill/fake_shill_profile_client.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 "chromeos/dbus/fake_shill_profile_client.h"
+#include "chromeos/dbus/shill/fake_shill_profile_client.h"
 
 #include <memory>
 #include <utility>
@@ -15,8 +15,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
@@ -26,8 +26,8 @@
 namespace chromeos {
 
 struct FakeShillProfileClient::ProfileProperties {
-  std::string path;               // Profile path
-  base::DictionaryValue entries;  // Dictionary of Service Dictionaries
+  std::string path;                  // Profile path
+  base::DictionaryValue entries;     // Dictionary of Service Dictionaries
   base::DictionaryValue properties;  // Dictionary of Profile properties
 };
 
@@ -49,13 +49,11 @@
 
 void FakeShillProfileClient::AddPropertyChangedObserver(
     const dbus::ObjectPath& profile_path,
-    ShillPropertyChangedObserver* observer) {
-}
+    ShillPropertyChangedObserver* observer) {}
 
 void FakeShillProfileClient::RemovePropertyChangedObserver(
     const dbus::ObjectPath& profile_path,
-    ShillPropertyChangedObserver* observer) {
-}
+    ShillPropertyChangedObserver* observer) {}
 
 void FakeShillProfileClient::GetProperties(
     const dbus::ObjectPath& profile_path,
@@ -116,10 +114,11 @@
   }
 
   base::Value profile_path_value("");
-  DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()->
-      SetServiceProperty(entry_path,
-                         shill::kProfileProperty,
-                         profile_path_value);
+  DBusThreadManager::Get()
+      ->GetShillServiceClient()
+      ->GetTestInterface()
+      ->SetServiceProperty(entry_path, shill::kProfileProperty,
+                           profile_path_value);
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
 }
@@ -143,25 +142,29 @@
   profile->path = profile_path;
   profiles_.emplace_back(std::move(profile));
 
-  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
-      AddProfile(profile_path);
+  DBusThreadManager::Get()
+      ->GetShillManagerClient()
+      ->GetTestInterface()
+      ->AddProfile(profile_path);
 }
 
 void FakeShillProfileClient::AddEntry(const std::string& profile_path,
                                       const std::string& entry_path,
                                       const base::DictionaryValue& properties) {
-  ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path),
-                                          ErrorCallback());
+  ProfileProperties* profile =
+      GetProfile(dbus::ObjectPath(profile_path), ErrorCallback());
   DCHECK(profile);
   profile->entries.SetKey(entry_path, properties.Clone());
-  DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
-      AddManagerService(entry_path, true);
+  DBusThreadManager::Get()
+      ->GetShillManagerClient()
+      ->GetTestInterface()
+      ->AddManagerService(entry_path, true);
 }
 
 bool FakeShillProfileClient::AddService(const std::string& profile_path,
                                         const std::string& service_path) {
-  ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path),
-                                          ErrorCallback());
+  ProfileProperties* profile =
+      GetProfile(dbus::ObjectPath(profile_path), ErrorCallback());
   if (!profile) {
     LOG(ERROR) << "AddService: No matching profile: " << profile_path
                << " for: " << service_path;
@@ -174,8 +177,8 @@
 
 bool FakeShillProfileClient::UpdateService(const std::string& profile_path,
                                            const std::string& service_path) {
-  ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path),
-                                          ErrorCallback());
+  ProfileProperties* profile =
+      GetProfile(dbus::ObjectPath(profile_path), ErrorCallback());
   if (!profile) {
     LOG(ERROR) << "UpdateService: No matching profile: " << profile_path
                << " for: " << service_path;
@@ -206,8 +209,7 @@
                                                     &service_profile_path);
   if (service_profile_path.empty()) {
     base::Value profile_path_value(profile_path);
-    service_test->SetServiceProperty(service_path,
-                                     shill::kProfileProperty,
+    service_test->SetServiceProperty(service_path, shill::kProfileProperty,
                                      profile_path_value);
   } else if (service_profile_path != profile_path) {
     LOG(ERROR) << "Service has non matching profile path: "
diff --git a/chromeos/dbus/fake_shill_profile_client.h b/chromeos/dbus/shill/fake_shill_profile_client.h
similarity index 92%
rename from chromeos/dbus/fake_shill_profile_client.h
rename to chromeos/dbus/shill/fake_shill_profile_client.h
index ce8a87c..bd5b73f 100644
--- a/chromeos/dbus/fake_shill_profile_client.h
+++ b/chromeos/dbus/shill/fake_shill_profile_client.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 CHROMEOS_DBUS_FAKE_SHILL_PROFILE_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_SHILL_PROFILE_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_FAKE_SHILL_PROFILE_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_FAKE_SHILL_PROFILE_CLIENT_H_
 
 #include <memory>
 #include <string>
@@ -11,8 +11,8 @@
 
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
 
 namespace chromeos {
 
@@ -86,4 +86,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_SHILL_PROFILE_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_FAKE_SHILL_PROFILE_CLIENT_H_
diff --git a/chromeos/dbus/fake_shill_service_client.cc b/chromeos/dbus/shill/fake_shill_service_client.cc
similarity index 98%
rename from chromeos/dbus/fake_shill_service_client.cc
rename to chromeos/dbus/shill/fake_shill_service_client.cc
index 0ee7fbd..e8348bb 100644
--- a/chromeos/dbus/fake_shill_service_client.cc
+++ b/chromeos/dbus/shill/fake_shill_service_client.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 "chromeos/dbus/fake_shill_service_client.h"
+#include "chromeos/dbus/shill/fake_shill_service_client.h"
 
 #include <memory>
 #include <utility>
@@ -17,10 +17,10 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
diff --git a/chromeos/dbus/fake_shill_service_client.h b/chromeos/dbus/shill/fake_shill_service_client.h
similarity index 96%
rename from chromeos/dbus/fake_shill_service_client.h
rename to chromeos/dbus/shill/fake_shill_service_client.h
index d60fe11..5688a51f 100644
--- a/chromeos/dbus/fake_shill_service_client.h
+++ b/chromeos/dbus/shill/fake_shill_service_client.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 CHROMEOS_DBUS_FAKE_SHILL_SERVICE_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_SHILL_SERVICE_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_FAKE_SHILL_SERVICE_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_FAKE_SHILL_SERVICE_CLIENT_H_
 
 #include <map>
 #include <memory>
@@ -14,7 +14,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 
 namespace chromeos {
 
@@ -140,4 +140,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_SHILL_SERVICE_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_FAKE_SHILL_SERVICE_CLIENT_H_
diff --git a/chromeos/dbus/fake_shill_third_party_vpn_driver_client.cc b/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.cc
similarity index 93%
rename from chromeos/dbus/fake_shill_third_party_vpn_driver_client.cc
rename to chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.cc
index 453ed52..13aca81 100644
--- a/chromeos/dbus/fake_shill_third_party_vpn_driver_client.cc
+++ b/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.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 "chromeos/dbus/fake_shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h"
 
 #include <stdint.h>
 
@@ -10,7 +10,7 @@
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "chromeos/dbus/shill_third_party_vpn_observer.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_observer.h"
 #include "dbus/object_proxy.h"
 
 namespace chromeos {
@@ -21,8 +21,7 @@
 FakeShillThirdPartyVpnDriverClient::~FakeShillThirdPartyVpnDriverClient() =
     default;
 
-void FakeShillThirdPartyVpnDriverClient::Init(dbus::Bus* bus) {
-}
+void FakeShillThirdPartyVpnDriverClient::Init(dbus::Bus* bus) {}
 
 void FakeShillThirdPartyVpnDriverClient::AddShillThirdPartyVpnObserver(
     const std::string& object_path_value,
diff --git a/chromeos/dbus/fake_shill_third_party_vpn_driver_client.h b/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h
similarity index 89%
rename from chromeos/dbus/fake_shill_third_party_vpn_driver_client.h
rename to chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h
index 03aa764..a7290c8 100644
--- a/chromeos/dbus/fake_shill_third_party_vpn_driver_client.h
+++ b/chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.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 CHROMEOS_DBUS_FAKE_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_FAKE_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_FAKE_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
 
 #include <stdint.h>
 
@@ -13,7 +13,7 @@
 
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "chromeos/dbus/shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
 
 namespace chromeos {
 
@@ -68,4 +68,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_FAKE_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
diff --git a/chromeos/dbus/fake_sms_client.cc b/chromeos/dbus/shill/fake_sms_client.cc
similarity index 96%
rename from chromeos/dbus/fake_sms_client.cc
rename to chromeos/dbus/shill/fake_sms_client.cc
index 3fd69c1..e132965 100644
--- a/chromeos/dbus/fake_sms_client.cc
+++ b/chromeos/dbus/shill/fake_sms_client.cc
@@ -13,7 +13,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chromeos/dbus/constants/dbus_switches.h"
-#include "chromeos/dbus/fake_sms_client.h"
+#include "chromeos/dbus/shill/fake_sms_client.h"
 #include "dbus/object_path.h"
 
 namespace chromeos {
diff --git a/chromeos/dbus/fake_sms_client.h b/chromeos/dbus/shill/fake_sms_client.h
similarity index 76%
rename from chromeos/dbus/fake_sms_client.h
rename to chromeos/dbus/shill/fake_sms_client.h
index aa2f228..748dfd7 100644
--- a/chromeos/dbus/fake_sms_client.h
+++ b/chromeos/dbus/shill/fake_sms_client.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_DBUS_FAKE_SMS_CLIENT_H_
-#define CHROMEOS_DBUS_FAKE_SMS_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_FAKE_SMS_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_FAKE_SMS_CLIENT_H_
 
 #include <string>
 
 #include "base/macros.h"
-#include "chromeos/dbus/sms_client.h"
+#include "chromeos/dbus/shill/sms_client.h"
 
 namespace chromeos {
 
@@ -24,10 +24,9 @@
               GetAllCallback callback) override;
 
  private:
-
   DISALLOW_COPY_AND_ASSIGN(FakeSMSClient);
 };
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_FAKE_SMS_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_FAKE_SMS_CLIENT_H_
diff --git a/chromeos/dbus/gsm_sms_client.cc b/chromeos/dbus/shill/gsm_sms_client.cc
similarity index 96%
rename from chromeos/dbus/gsm_sms_client.cc
rename to chromeos/dbus/shill/gsm_sms_client.cc
index f6e0c8d..f4bc4c8 100644
--- a/chromeos/dbus/gsm_sms_client.cc
+++ b/chromeos/dbus/shill/gsm_sms_client.cc
@@ -1,7 +1,7 @@
 // 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 "chromeos/dbus/gsm_sms_client.h"
+#include "chromeos/dbus/shill/gsm_sms_client.h"
 
 #include <stdint.h>
 
@@ -51,9 +51,7 @@
   }
 
   // Resets SmsReceived signal handler.
-  void ResetSmsReceivedHandler() {
-    sms_received_handler_.Reset();
-  }
+  void ResetSmsReceivedHandler() { sms_received_handler_.Reset(); }
 
   // Calls Delete method.
   void Delete(uint32_t index, VoidDBusMethodCallback callback) {
@@ -95,8 +93,7 @@
     uint32_t index = 0;
     bool complete = false;
     dbus::MessageReader reader(signal);
-    if (!reader.PopUint32(&index) ||
-        !reader.PopBool(&complete)) {
+    if (!reader.PopUint32(&index) || !reader.PopBool(&complete)) {
       LOG(ERROR) << "Invalid signal: " << signal->ToString();
       return;
     }
@@ -108,8 +105,8 @@
   void OnSignalConnected(const std::string& interface,
                          const std::string& signal,
                          bool succeeded) {
-    LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " <<
-        signal << " failed.";
+    LOG_IF(ERROR, !succeeded)
+        << "Connect to " << interface << " " << signal << " failed.";
   }
 
   // Handles responses of Delete method calls.
diff --git a/chromeos/dbus/gsm_sms_client.h b/chromeos/dbus/shill/gsm_sms_client.h
similarity index 94%
rename from chromeos/dbus/gsm_sms_client.h
rename to chromeos/dbus/shill/gsm_sms_client.h
index 49436a5..a4a95f3 100644
--- a/chromeos/dbus/gsm_sms_client.h
+++ b/chromeos/dbus/shill/gsm_sms_client.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 CHROMEOS_DBUS_GSM_SMS_CLIENT_H_
-#define CHROMEOS_DBUS_GSM_SMS_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_GSM_SMS_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_GSM_SMS_CLIENT_H_
 
 #include <stdint.h>
 
@@ -18,7 +18,7 @@
 namespace base {
 class DictionaryValue;
 class ListValue;
-}
+}  // namespace base
 
 namespace dbus {
 class ObjectPath;
@@ -84,4 +84,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_GSM_SMS_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_GSM_SMS_CLIENT_H_
diff --git a/chromeos/dbus/gsm_sms_client_unittest.cc b/chromeos/dbus/shill/gsm_sms_client_unittest.cc
similarity index 98%
rename from chromeos/dbus/gsm_sms_client_unittest.cc
rename to chromeos/dbus/shill/gsm_sms_client_unittest.cc
index 0e0dee2..b8adc98 100644
--- a/chromeos/dbus/gsm_sms_client_unittest.cc
+++ b/chromeos/dbus/shill/gsm_sms_client_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/gsm_sms_client.h"
+#include "chromeos/dbus/shill/gsm_sms_client.h"
 
 #include <stdint.h>
 
@@ -58,8 +58,7 @@
     mock_bus_ = new dbus::MockBus(options);
 
     // Create a mock proxy.
-    mock_proxy_ = new dbus::MockObjectProxy(mock_bus_.get(),
-                                            kServiceName,
+    mock_proxy_ = new dbus::MockObjectProxy(mock_bus_.get(), kServiceName,
                                             dbus::ObjectPath(kObjectPath));
 
     // Set an expectation so mock_proxy's ConnectToSignal() will use
diff --git a/chromeos/dbus/modem_messaging_client.cc b/chromeos/dbus/shill/modem_messaging_client.cc
similarity index 93%
rename from chromeos/dbus/modem_messaging_client.cc
rename to chromeos/dbus/shill/modem_messaging_client.cc
index 18ab45198..61ef07e 100644
--- a/chromeos/dbus/modem_messaging_client.cc
+++ b/chromeos/dbus/shill/modem_messaging_client.cc
@@ -1,7 +1,7 @@
 // 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 "chromeos/dbus/modem_messaging_client.h"
+#include "chromeos/dbus/shill/modem_messaging_client.h"
 
 #include <map>
 #include <memory>
@@ -28,8 +28,8 @@
   using ListCallback = ModemMessagingClient::ListCallback;
 
   ModemMessagingProxy(dbus::Bus* bus,
-           const std::string& service_name,
-           const dbus::ObjectPath& object_path)
+                      const std::string& service_name,
+                      const dbus::ObjectPath& object_path)
       : proxy_(bus->GetObjectProxy(service_name, object_path)),
         service_name_(service_name),
         weak_ptr_factory_(this) {
@@ -50,9 +50,7 @@
   }
 
   // Resets SmsReceived signal handler.
-  void ResetSmsReceivedHandler() {
-    sms_received_handler_.Reset();
-  }
+  void ResetSmsReceivedHandler() { sms_received_handler_.Reset(); }
 
   // Calls Delete method.
   void Delete(const dbus::ObjectPath& message_path,
@@ -83,8 +81,7 @@
     dbus::ObjectPath message_path;
     bool complete = false;
     dbus::MessageReader reader(signal);
-    if (!reader.PopObjectPath(&message_path) ||
-        !reader.PopBool(&complete)) {
+    if (!reader.PopObjectPath(&message_path) || !reader.PopBool(&complete)) {
       LOG(ERROR) << "Invalid signal: " << signal->ToString();
       return;
     }
@@ -118,8 +115,8 @@
   void OnSignalConnected(const std::string& interface,
                          const std::string& signal,
                          bool succeeded) {
-    LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " "
-                              << signal << " failed.";
+    LOG_IF(ERROR, !succeeded)
+        << "Connect to " << interface << " " << signal << " failed.";
   }
 
   dbus::ObjectProxy* proxy_;
@@ -205,5 +202,4 @@
   return new ModemMessagingClientImpl();
 }
 
-
 }  // namespace chromeos
diff --git a/chromeos/dbus/modem_messaging_client.h b/chromeos/dbus/shill/modem_messaging_client.h
similarity index 90%
rename from chromeos/dbus/modem_messaging_client.h
rename to chromeos/dbus/shill/modem_messaging_client.h
index 97931d8..264f81ad 100644
--- a/chromeos/dbus/modem_messaging_client.h
+++ b/chromeos/dbus/shill/modem_messaging_client.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 CHROMEOS_DBUS_MODEM_MESSAGING_CLIENT_H_
-#define CHROMEOS_DBUS_MODEM_MESSAGING_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_MODEM_MESSAGING_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_MODEM_MESSAGING_CLIENT_H_
 
 #include <string>
 #include <vector>
@@ -27,7 +27,8 @@
 class COMPONENT_EXPORT(CHROMEOS_DBUS) ModemMessagingClient : public DBusClient {
  public:
   typedef base::Callback<void(const dbus::ObjectPath& message_path,
-                              bool complete)> SmsReceivedHandler;
+                              bool complete)>
+      SmsReceivedHandler;
 
   ~ModemMessagingClient() override;
 
@@ -68,4 +69,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_MODEM_MESSAGING_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_MODEM_MESSAGING_CLIENT_H_
diff --git a/chromeos/dbus/modem_messaging_client_unittest.cc b/chromeos/dbus/shill/modem_messaging_client_unittest.cc
similarity index 94%
rename from chromeos/dbus/modem_messaging_client_unittest.cc
rename to chromeos/dbus/shill/modem_messaging_client_unittest.cc
index e6977aa..9c0dace 100644
--- a/chromeos/dbus/modem_messaging_client_unittest.cc
+++ b/chromeos/dbus/shill/modem_messaging_client_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/modem_messaging_client.h"
+#include "chromeos/dbus/shill/modem_messaging_client.h"
 
 #include <memory>
 #include <utility>
@@ -34,7 +34,7 @@
 // A mock SmsReceivedHandler.
 class MockSmsReceivedHandler {
  public:
-  MOCK_METHOD2(Run, void(const dbus::ObjectPath &sms, bool complete));
+  MOCK_METHOD2(Run, void(const dbus::ObjectPath& sms, bool complete));
 };
 
 // D-Bus service name used by test.
@@ -55,8 +55,7 @@
     mock_bus_ = new dbus::MockBus(options);
 
     // Create a mock proxy.
-    mock_proxy_ = new dbus::MockObjectProxy(mock_bus_.get(),
-                                            kServiceName,
+    mock_proxy_ = new dbus::MockObjectProxy(mock_bus_.get(), kServiceName,
                                             dbus::ObjectPath(kObjectPath));
 
     // Set an expectation so mock_proxy's ConnectToSignal() will use
@@ -153,9 +152,9 @@
   MockSmsReceivedHandler handler;
   EXPECT_CALL(handler, Run(kSmsPath, kComplete)).Times(1);
   // Set handler.
-  client_->SetSmsReceivedHandler(kServiceName, dbus::ObjectPath(kObjectPath),
-                                 base::Bind(&MockSmsReceivedHandler::Run,
-                                            base::Unretained(&handler)));
+  client_->SetSmsReceivedHandler(
+      kServiceName, dbus::ObjectPath(kObjectPath),
+      base::Bind(&MockSmsReceivedHandler::Run, base::Unretained(&handler)));
 
   // Run the message loop to run the signal connection result callback.
   base::RunLoop().RunUntilIdle();
diff --git a/chromeos/dbus/shill_client_helper.cc b/chromeos/dbus/shill/shill_client_helper.cc
similarity index 97%
rename from chromeos/dbus/shill_client_helper.cc
rename to chromeos/dbus/shill/shill_client_helper.cc
index 96c82bd7..410496c 100644
--- a/chromeos/dbus/shill_client_helper.cc
+++ b/chromeos/dbus/shill/shill_client_helper.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 "chromeos/dbus/shill_client_helper.h"
+#include "chromeos/dbus/shill/shill_client_helper.h"
 
 #include <stddef.h>
 
@@ -140,10 +140,9 @@
 }
 
 // Handles responses for methods without results.
-void OnVoidMethodWithErrorCallback(
-    ShillClientHelper::RefHolder* ref_holder,
-    const base::Closure& callback,
-    dbus::Response* response) {
+void OnVoidMethodWithErrorCallback(ShillClientHelper::RefHolder* ref_holder,
+                                   const base::Closure& callback,
+                                   dbus::Response* response) {
   callback.Run();
 }
 
@@ -197,10 +196,7 @@
 }  // namespace
 
 ShillClientHelper::ShillClientHelper(dbus::ObjectProxy* proxy)
-    : proxy_(proxy),
-      active_refs_(0),
-      weak_ptr_factory_(this) {
-}
+    : proxy_(proxy), active_refs_(0), weak_ptr_factory_(this) {}
 
 ShillClientHelper::~ShillClientHelper() {
   if (observer_list_.might_have_observers())
diff --git a/chromeos/dbus/shill_client_helper.h b/chromeos/dbus/shill/shill_client_helper.h
similarity index 89%
rename from chromeos/dbus/shill_client_helper.h
rename to chromeos/dbus/shill/shill_client_helper.h
index 7a4260c..3b9f0ff 100644
--- a/chromeos/dbus/shill_client_helper.h
+++ b/chromeos/dbus/shill/shill_client_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 CHROMEOS_DBUS_SHILL_CLIENT_HELPER_H_
-#define CHROMEOS_DBUS_SHILL_CLIENT_HELPER_H_
+#ifndef CHROMEOS_DBUS_SHILL_SHILL_CLIENT_HELPER_H_
+#define CHROMEOS_DBUS_SHILL_SHILL_CLIENT_HELPER_H_
 
 #include <memory>
 #include <string>
@@ -15,7 +15,7 @@
 #include "base/observer_list.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 
 namespace base {
 
@@ -42,12 +42,13 @@
 
   // A callback to handle PropertyChanged signals.
   typedef base::Callback<void(const std::string& name,
-                              const base::Value& value)> PropertyChangedHandler;
+                              const base::Value& value)>
+      PropertyChangedHandler;
 
   // A callback to handle responses for methods with DictionaryValue results.
-  typedef base::Callback<void(
-      DBusMethodCallStatus call_status,
-      const base::DictionaryValue& result)> DictionaryValueCallback;
+  typedef base::Callback<void(DBusMethodCallStatus call_status,
+                              const base::DictionaryValue& result)>
+      DictionaryValueCallback;
 
   // A callback to handle responses for methods with DictionaryValue results.
   // This is used by CallDictionaryValueMethodWithErrorCallback.
@@ -59,7 +60,8 @@
 
   // A callback to handle errors for method call.
   typedef base::Callback<void(const std::string& error_name,
-                              const std::string& error_message)> ErrorCallback;
+                              const std::string& error_message)>
+      ErrorCallback;
 
   // A callback that handles responses for methods with string results.
   typedef base::Callback<void(const std::string& result)> StringCallback;
@@ -109,17 +111,15 @@
                                        const ErrorCallback& error_callback);
 
   // Calls a method with a boolean result with error callback.
-  void CallBooleanMethodWithErrorCallback(
-      dbus::MethodCall* method_call,
-      const BooleanCallback& callback,
-      const ErrorCallback& error_callback);
+  void CallBooleanMethodWithErrorCallback(dbus::MethodCall* method_call,
+                                          const BooleanCallback& callback,
+                                          const ErrorCallback& error_callback);
 
   // Calls a method with a string result with error callback.
   void CallStringMethodWithErrorCallback(dbus::MethodCall* method_call,
                                          const StringCallback& callback,
                                          const ErrorCallback& error_callback);
 
-
   // Calls a method with a dictionary value result with error callback.
   void CallDictionaryValueMethodWithErrorCallback(
       dbus::MethodCall* method_call,
@@ -181,4 +181,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SHILL_CLIENT_HELPER_H_
+#endif  // CHROMEOS_DBUS_SHILL_SHILL_CLIENT_HELPER_H_
diff --git a/chromeos/dbus/shill_client_unittest_base.cc b/chromeos/dbus/shill/shill_client_unittest_base.cc
similarity index 94%
rename from chromeos/dbus/shill_client_unittest_base.cc
rename to chromeos/dbus/shill/shill_client_unittest_base.cc
index ea3f88c..9b95990 100644
--- a/chromeos/dbus/shill_client_unittest_base.cc
+++ b/chromeos/dbus/shill/shill_client_unittest_base.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 "chromeos/dbus/shill_client_unittest_base.h"
+#include "chromeos/dbus/shill/shill_client_unittest_base.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -41,8 +41,7 @@
     std::string key;
     std::string value;
     if (!array_reader.PopDictEntry(&entry_reader) ||
-        !entry_reader.PopString(&key) ||
-        !entry_reader.PopString(&value))
+        !entry_reader.PopString(&key) || !entry_reader.PopString(&value))
       return NULL;
     result->SetKey(key, base::Value(value));
   }
@@ -52,10 +51,10 @@
 }  // namespace
 
 ValueMatcher::ValueMatcher(const base::Value& value)
-  : expected_value_(value.DeepCopy()) {}
+    : expected_value_(value.DeepCopy()) {}
 
 bool ValueMatcher::MatchAndExplain(const base::Value& value,
-                             MatchResultListener* listener) const {
+                                   MatchResultListener* listener) const {
   return expected_value_->Equals(&value);
 }
 
@@ -86,8 +85,7 @@
     const dbus::ObjectPath& object_path)
     : interface_name_(interface_name),
       object_path_(object_path),
-      response_(NULL) {
-}
+      response_(NULL) {}
 
 ShillClientUnittestBase::~ShillClientUnittestBase() = default;
 
@@ -99,9 +97,7 @@
 
   // Create a mock proxy.
   mock_proxy_ = new dbus::MockObjectProxy(
-      mock_bus_.get(),
-      shill::kFlimflamServiceName,
-      object_path_);
+      mock_bus_.get(), shill::kFlimflamServiceName, object_path_);
 
   // Set an expectation so mock_proxy's CallMethod() will use OnCallMethod()
   // to return responses.
@@ -162,20 +158,17 @@
   response_ = response;
 }
 
-void ShillClientUnittestBase::SendPlatformMessageSignal(
-    dbus::Signal* signal) {
+void ShillClientUnittestBase::SendPlatformMessageSignal(dbus::Signal* signal) {
   ASSERT_FALSE(platform_message_handler_.is_null());
   platform_message_handler_.Run(signal);
 }
 
-void ShillClientUnittestBase::SendPacketReceievedSignal(
-    dbus::Signal* signal) {
+void ShillClientUnittestBase::SendPacketReceievedSignal(dbus::Signal* signal) {
   ASSERT_FALSE(packet_receieved__handler_.is_null());
   packet_receieved__handler_.Run(signal);
 }
 
-void ShillClientUnittestBase::SendPropertyChangedSignal(
-    dbus::Signal* signal) {
+void ShillClientUnittestBase::SendPropertyChangedSignal(dbus::Signal* signal) {
   ASSERT_FALSE(property_changed_handler_.is_null());
   property_changed_handler_.Run(signal);
 }
@@ -303,8 +296,8 @@
     }
     ASSERT_TRUE(value.get());
     const base::Value* expected_value = NULL;
-    EXPECT_TRUE(expected_dictionary->GetWithoutPathExpansion(key,
-                                                             &expected_value));
+    EXPECT_TRUE(
+        expected_dictionary->GetWithoutPathExpansion(key, &expected_value));
     EXPECT_TRUE(value->Equals(expected_value));
   }
 }
@@ -325,7 +318,6 @@
   return properties;
 }
 
-
 // static
 void ShillClientUnittestBase::ExpectNoResultValue(bool result) {
   EXPECT_TRUE(result);
diff --git a/chromeos/dbus/shill_client_unittest_base.h b/chromeos/dbus/shill/shill_client_unittest_base.h
similarity index 89%
rename from chromeos/dbus/shill_client_unittest_base.h
rename to chromeos/dbus/shill/shill_client_unittest_base.h
index 3b316f6..23b9c4eb 100644
--- a/chromeos/dbus/shill_client_unittest_base.h
+++ b/chromeos/dbus/shill/shill_client_unittest_base.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 CHROMEOS_DBUS_SHILL_CLIENT_UNITTEST_BASE_H_
-#define CHROMEOS_DBUS_SHILL_CLIENT_UNITTEST_BASE_H_
+#ifndef CHROMEOS_DBUS_SHILL_SHILL_CLIENT_UNITTEST_BASE_H_
+#define CHROMEOS_DBUS_SHILL_SHILL_CLIENT_UNITTEST_BASE_H_
 
 #include <stdint.h>
 
@@ -14,18 +14,18 @@
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
-#include "chromeos/dbus/shill_client_helper.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
-#include "chromeos/dbus/shill_third_party_vpn_observer.h"
+#include "chromeos/dbus/shill/shill_client_helper.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_observer.h"
 #include "dbus/mock_bus.h"
 #include "dbus/mock_object_proxy.h"
 #include "dbus/object_proxy.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using ::testing::MakeMatcher;
+using ::testing::Matcher;
 using ::testing::MatcherInterface;
 using ::testing::MatchResultListener;
-using ::testing::Matcher;
-using ::testing::MakeMatcher;
 
 namespace base {
 
@@ -65,17 +65,16 @@
 class ShillClientUnittestBase : public testing::Test {
  public:
   // A mock PropertyChangedObserver that can be used to check expected values.
-  class MockPropertyChangeObserver
-      : public ShillPropertyChangedObserver {
+  class MockPropertyChangeObserver : public ShillPropertyChangedObserver {
    public:
     MockPropertyChangeObserver();
     ~MockPropertyChangeObserver();
-    MOCK_METHOD2(OnPropertyChanged, void(const std::string& name,
-                                         const base::Value& value));
+    MOCK_METHOD2(OnPropertyChanged,
+                 void(const std::string& name, const base::Value& value));
   };
 
   explicit ShillClientUnittestBase(const std::string& interface_name,
-                                      const dbus::ObjectPath& object_path);
+                                   const dbus::ObjectPath& object_path);
   ~ShillClientUnittestBase() override;
 
   void SetUp() override;
@@ -83,8 +82,8 @@
 
  protected:
   // A callback to intercept and check the method call arguments.
-  typedef base::Callback<void(
-      dbus::MessageReader* reader)> ArgumentCheckCallback;
+  typedef base::Callback<void(dbus::MessageReader* reader)>
+      ArgumentCheckCallback;
 
   // Sets expectations for called method name and arguments, and sets response.
   void PrepareForMethodCall(const std::string& method_name,
@@ -114,9 +113,8 @@
                                    dbus::MessageReader* reader);
 
   // Expects the reader to have an array of bytes
-  static void ExpectArrayOfBytesArgument(
-      const std::string& expected_bytes,
-      dbus::MessageReader* reader);
+  static void ExpectArrayOfBytesArgument(const std::string& expected_bytes,
+                                         dbus::MessageReader* reader);
 
   // Expects the reader to have a string.
   static void ExpectStringArgument(const std::string& expected_string,
@@ -157,9 +155,7 @@
       const dbus::ObjectPath& expected_result,
       const dbus::ObjectPath& result);
 
-  static void ExpectBoolResultWithoutStatus(
-      bool expected_result,
-      bool result);
+  static void ExpectBoolResultWithoutStatus(bool expected_result, bool result);
 
   static void ExpectStringResultWithoutStatus(
       const std::string& expected_result,
@@ -242,4 +238,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SHILL_CLIENT_UNITTEST_BASE_H_
+#endif  // CHROMEOS_DBUS_SHILL_SHILL_CLIENT_UNITTEST_BASE_H_
diff --git a/chromeos/dbus/shill_device_client.cc b/chromeos/dbus/shill/shill_device_client.cc
similarity index 98%
rename from chromeos/dbus/shill_device_client.cc
rename to chromeos/dbus/shill/shill_device_client.cc
index 0a97e7f..9688128 100644
--- a/chromeos/dbus/shill_device_client.cc
+++ b/chromeos/dbus/shill/shill_device_client.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 "chromeos/dbus/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
 
 #include <map>
 #include <utility>
@@ -11,7 +11,7 @@
 #include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
diff --git a/chromeos/dbus/shill_device_client.h b/chromeos/dbus/shill/shill_device_client.h
similarity index 97%
rename from chromeos/dbus/shill_device_client.h
rename to chromeos/dbus/shill/shill_device_client.h
index 8d46401..cd22975a 100644
--- a/chromeos/dbus/shill_device_client.h
+++ b/chromeos/dbus/shill/shill_device_client.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 CHROMEOS_DBUS_SHILL_DEVICE_CLIENT_H_
-#define CHROMEOS_DBUS_SHILL_DEVICE_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_SHILL_DEVICE_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_SHILL_DEVICE_CLIENT_H_
 
 #include <string>
 #include <vector>
@@ -12,7 +12,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "chromeos/dbus/dbus_client.h"
-#include "chromeos/dbus/shill_client_helper.h"
+#include "chromeos/dbus/shill/shill_client_helper.h"
 
 namespace base {
 
@@ -224,4 +224,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SHILL_DEVICE_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_SHILL_DEVICE_CLIENT_H_
diff --git a/chromeos/dbus/shill_device_client_unittest.cc b/chromeos/dbus/shill/shill_device_client_unittest.cc
similarity index 85%
rename from chromeos/dbus/shill_device_client_unittest.cc
rename to chromeos/dbus/shill/shill_device_client_unittest.cc
index 20f9eeb..58fd0e1 100644
--- a/chromeos/dbus/shill_device_client_unittest.cc
+++ b/chromeos/dbus/shill/shill_device_client_unittest.cc
@@ -8,8 +8,8 @@
 #include "base/run_loop.h"
 #include "base/test/mock_callback.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_client_unittest_base.h"
-#include "chromeos/dbus/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_client_unittest_base.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
 #include "dbus/values_util.h"
@@ -57,8 +57,7 @@
  public:
   ShillDeviceClientTest()
       : ShillClientUnittestBase(shill::kFlimflamDeviceInterface,
-                                   dbus::ObjectPath(kExampleDevicePath)) {
-  }
+                                dbus::ObjectPath(kExampleDevicePath)) {}
 
   void SetUp() override {
     ShillClientUnittestBase::SetUp();
@@ -85,26 +84,24 @@
   // Set expectations.
   const base::Value value(kValue);
   MockPropertyChangeObserver observer;
-  EXPECT_CALL(observer,
-              OnPropertyChanged(shill::kCellularAllowRoamingProperty,
-                                ValueEq(ByRef(value)))).Times(1);
+  EXPECT_CALL(observer, OnPropertyChanged(shill::kCellularAllowRoamingProperty,
+                                          ValueEq(ByRef(value))))
+      .Times(1);
 
   // Add the observer
-  client_->AddPropertyChangedObserver(
-      dbus::ObjectPath(kExampleDevicePath),
-      &observer);
+  client_->AddPropertyChangedObserver(dbus::ObjectPath(kExampleDevicePath),
+                                      &observer);
 
   // Run the signal callback.
   SendPropertyChangedSignal(&signal);
 
   // Remove the observer.
-  client_->RemovePropertyChangedObserver(
-      dbus::ObjectPath(kExampleDevicePath),
-      &observer);
+  client_->RemovePropertyChangedObserver(dbus::ObjectPath(kExampleDevicePath),
+                                         &observer);
 
-  EXPECT_CALL(observer,
-              OnPropertyChanged(shill::kCellularAllowRoamingProperty,
-                                ValueEq(ByRef(value)))).Times(0);
+  EXPECT_CALL(observer, OnPropertyChanged(shill::kCellularAllowRoamingProperty,
+                                          ValueEq(ByRef(value))))
+      .Times(0);
 
   // Run the signal callback again and make sure the observer isn't called.
   SendPropertyChangedSignal(&signal);
@@ -128,8 +125,7 @@
   base::DictionaryValue value;
   value.SetKey(shill::kCellularAllowRoamingProperty, base::Value(kValue));
   PrepareForMethodCall(shill::kGetPropertiesFunction,
-                       base::Bind(&ExpectNoArgument),
-                       response.get());
+                       base::Bind(&ExpectNoArgument), response.get());
   // Call method.
   client_->GetProperties(dbus::ObjectPath(kExampleDevicePath),
                          base::Bind(&ExpectDictionaryValueResult, &value));
@@ -146,8 +142,7 @@
   const base::Value value(kValue);
   PrepareForMethodCall(shill::kSetPropertyFunction,
                        base::Bind(&ExpectStringAndValueArguments,
-                                  shill::kCellularAllowRoamingProperty,
-                                  &value),
+                                  shill::kCellularAllowRoamingProperty, &value),
                        response.get());
   // Call method.
   base::MockCallback<base::Closure> mock_closure;
@@ -167,10 +162,10 @@
   std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
 
   // Set expectations.
-  PrepareForMethodCall(shill::kClearPropertyFunction,
-                       base::Bind(&ExpectStringArgument,
-                                  shill::kCellularAllowRoamingProperty),
-                       response.get());
+  PrepareForMethodCall(
+      shill::kClearPropertyFunction,
+      base::Bind(&ExpectStringArgument, shill::kCellularAllowRoamingProperty),
+      response.get());
   // Call method.
   client_->ClearProperty(dbus::ObjectPath(kExampleDevicePath),
                          shill::kCellularAllowRoamingProperty,
@@ -188,11 +183,10 @@
   // Set expectations.
   base::MockCallback<base::Closure> mock_closure;
   base::MockCallback<ShillDeviceClient::ErrorCallback> mock_error_callback;
-  PrepareForMethodCall(shill::kRequirePinFunction,
-                       base::Bind(&ExpectStringAndBoolArguments,
-                                  kPin,
-                                  kRequired),
-                       response.get());
+  PrepareForMethodCall(
+      shill::kRequirePinFunction,
+      base::Bind(&ExpectStringAndBoolArguments, kPin, kRequired),
+      response.get());
   EXPECT_CALL(mock_closure, Run()).Times(1);
   EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
   // Call method.
@@ -211,9 +205,7 @@
   base::MockCallback<base::Closure> mock_closure;
   base::MockCallback<ShillDeviceClient::ErrorCallback> mock_error_callback;
   PrepareForMethodCall(shill::kEnterPinFunction,
-                       base::Bind(&ExpectStringArgument,
-                                  kPin),
-                       response.get());
+                       base::Bind(&ExpectStringArgument, kPin), response.get());
   EXPECT_CALL(mock_closure, Run()).Times(1);
   EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
 
@@ -256,9 +248,7 @@
   base::MockCallback<base::Closure> mock_closure;
   base::MockCallback<ShillDeviceClient::ErrorCallback> mock_error_callback;
   PrepareForMethodCall(shill::kChangePinFunction,
-                       base::Bind(&ExpectTwoStringArguments,
-                                  kOldPin,
-                                  kNewPin),
+                       base::Bind(&ExpectTwoStringArguments, kOldPin, kNewPin),
                        response.get());
   EXPECT_CALL(mock_closure, Run()).Times(1);
   EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
@@ -317,8 +307,7 @@
   // Set expectations.
   base::MockCallback<base::Closure> mock_closure;
   base::MockCallback<ShillDeviceClient::ErrorCallback> mock_error_callback;
-  PrepareForMethodCall(shill::kResetFunction,
-                       base::Bind(&ExpectNoArgument),
+  PrepareForMethodCall(shill::kResetFunction, base::Bind(&ExpectNoArgument),
                        response.get());
   EXPECT_CALL(mock_closure, Run()).Times(1);
   // Call method.
diff --git a/chromeos/dbus/shill_ipconfig_client.cc b/chromeos/dbus/shill/shill_ipconfig_client.cc
similarity index 97%
rename from chromeos/dbus/shill_ipconfig_client.cc
rename to chromeos/dbus/shill/shill_ipconfig_client.cc
index c80b1c9b..a540a27 100644
--- a/chromeos/dbus/shill_ipconfig_client.cc
+++ b/chromeos/dbus/shill/shill_ipconfig_client.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 "chromeos/dbus/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
 
 #include <map>
 #include <memory>
@@ -11,7 +11,7 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
@@ -85,8 +85,7 @@
   DISALLOW_COPY_AND_ASSIGN(ShillIPConfigClientImpl);
 };
 
-ShillIPConfigClientImpl::ShillIPConfigClientImpl() : bus_(NULL) {
-}
+ShillIPConfigClientImpl::ShillIPConfigClientImpl() : bus_(NULL) {}
 
 void ShillIPConfigClientImpl::GetProperties(
     const dbus::ObjectPath& ipconfig_path,
@@ -121,8 +120,7 @@
       dbus::MessageWriter array_writer(NULL);
       variant_writer.OpenArray("s", &array_writer);
       for (base::ListValue::const_iterator it = list_value->begin();
-           it != list_value->end();
-           ++it) {
+           it != list_value->end(); ++it) {
         DLOG_IF(ERROR, !it->is_string()) << "Unexpected type " << it->type();
         std::string str;
         it->GetAsString(&str);
diff --git a/chromeos/dbus/shill_ipconfig_client.h b/chromeos/dbus/shill/shill_ipconfig_client.h
similarity index 93%
rename from chromeos/dbus/shill_ipconfig_client.h
rename to chromeos/dbus/shill/shill_ipconfig_client.h
index 4574b4f8..9d01d8f 100644
--- a/chromeos/dbus/shill_ipconfig_client.h
+++ b/chromeos/dbus/shill/shill_ipconfig_client.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 CHROMEOS_DBUS_SHILL_IPCONFIG_CLIENT_H_
-#define CHROMEOS_DBUS_SHILL_IPCONFIG_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_SHILL_IPCONFIG_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_SHILL_IPCONFIG_CLIENT_H_
 
 #include <string>
 
@@ -11,7 +11,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "chromeos/dbus/dbus_client.h"
-#include "chromeos/dbus/shill_client_helper.h"
+#include "chromeos/dbus/shill/shill_client_helper.h"
 
 namespace base {
 
@@ -107,4 +107,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SHILL_IPCONFIG_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_SHILL_IPCONFIG_CLIENT_H_
diff --git a/chromeos/dbus/shill_ipconfig_client_unittest.cc b/chromeos/dbus/shill/shill_ipconfig_client_unittest.cc
similarity index 83%
rename from chromeos/dbus/shill_ipconfig_client_unittest.cc
rename to chromeos/dbus/shill/shill_ipconfig_client_unittest.cc
index ceab6fa5e..05f1c37 100644
--- a/chromeos/dbus/shill_ipconfig_client_unittest.cc
+++ b/chromeos/dbus/shill/shill_ipconfig_client_unittest.cc
@@ -9,8 +9,8 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_client_unittest_base.h"
-#include "chromeos/dbus/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_client_unittest_base.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
 #include "dbus/message.h"
 #include "dbus/values_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -30,10 +30,8 @@
 class ShillIPConfigClientTest : public ShillClientUnittestBase {
  public:
   ShillIPConfigClientTest()
-      : ShillClientUnittestBase(
-          shill::kFlimflamIPConfigInterface,
-          dbus::ObjectPath(kExampleIPConfigPath)) {
-  }
+      : ShillClientUnittestBase(shill::kFlimflamIPConfigInterface,
+                                dbus::ObjectPath(kExampleIPConfigPath)) {}
 
   void SetUp() override {
     ShillClientUnittestBase::SetUp();
@@ -60,20 +58,19 @@
   // Set expectations.
   MockPropertyChangeObserver observer;
   EXPECT_CALL(observer, OnPropertyChanged(shill::kConnectedProperty,
-                                          ValueEq(ByRef(kConnected)))).Times(1);
+                                          ValueEq(ByRef(kConnected))))
+      .Times(1);
 
   // Add the observer
-  client_->AddPropertyChangedObserver(
-      dbus::ObjectPath(kExampleIPConfigPath),
-      &observer);
+  client_->AddPropertyChangedObserver(dbus::ObjectPath(kExampleIPConfigPath),
+                                      &observer);
 
   // Run the signal callback.
   SendPropertyChangedSignal(&signal);
 
   // Remove the observer.
-  client_->RemovePropertyChangedObserver(
-      dbus::ObjectPath(kExampleIPConfigPath),
-      &observer);
+  client_->RemovePropertyChangedObserver(dbus::ObjectPath(kExampleIPConfigPath),
+                                         &observer);
 
   EXPECT_CALL(observer, OnPropertyChanged(_, _)).Times(0);
 
@@ -110,8 +107,7 @@
 
   // Set expectations.
   PrepareForMethodCall(shill::kGetPropertiesFunction,
-                       base::Bind(&ExpectNoArgument),
-                       response.get());
+                       base::Bind(&ExpectNoArgument), response.get());
   // Call method.
   client_->GetProperties(dbus::ObjectPath(kExampleIPConfigPath),
                          base::Bind(&ExpectDictionaryValueResult, &value));
@@ -129,8 +125,7 @@
   base::Value value(kAddress);
   PrepareForMethodCall(shill::kSetPropertyFunction,
                        base::Bind(&ExpectStringAndValueArguments,
-                                  shill::kAddressProperty,
-                                  &value),
+                                  shill::kAddressProperty, &value),
                        response.get());
   // Call method.
   client_->SetProperty(dbus::ObjectPath(kExampleIPConfigPath),
@@ -145,10 +140,10 @@
   std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
 
   // Set expectations.
-  PrepareForMethodCall(shill::kClearPropertyFunction,
-                       base::Bind(&ExpectStringArgument,
-                                  shill::kAddressProperty),
-                       response.get());
+  PrepareForMethodCall(
+      shill::kClearPropertyFunction,
+      base::Bind(&ExpectStringArgument, shill::kAddressProperty),
+      response.get());
   // Call method.
   client_->ClearProperty(dbus::ObjectPath(kExampleIPConfigPath),
                          shill::kAddressProperty,
@@ -163,8 +158,7 @@
 
   // Set expectations.
   PrepareForMethodCall(shill::kRemoveConfigFunction,
-                       base::Bind(&ExpectNoArgument),
-                       response.get());
+                       base::Bind(&ExpectNoArgument), response.get());
   // Call method.
   client_->Remove(dbus::ObjectPath(kExampleIPConfigPath),
                   base::BindOnce(&ExpectNoResultValue));
diff --git a/chromeos/dbus/shill_manager_client.cc b/chromeos/dbus/shill/shill_manager_client.cc
similarity index 82%
rename from chromeos/dbus/shill_manager_client.cc
rename to chromeos/dbus/shill/shill_manager_client.cc
index 518bfc8..e2c8f14 100644
--- a/chromeos/dbus/shill_manager_client.cc
+++ b/chromeos/dbus/shill/shill_manager_client.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 "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 
 #include <memory>
 
@@ -10,7 +10,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
@@ -62,9 +62,8 @@
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(name);
     ShillClientHelper::AppendValueDataAsVariant(&writer, value);
-    helper_->CallVoidMethodWithErrorCallback(&method_call,
-                                            callback,
-                                            error_callback);
+    helper_->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                             error_callback);
   }
 
   void RequestScan(const std::string& type,
@@ -74,9 +73,8 @@
                                  shill::kRequestScanFunction);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(type);
-    helper_->CallVoidMethodWithErrorCallback(&method_call,
-                                            callback,
-                                            error_callback);
+    helper_->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                             error_callback);
   }
 
   void EnableTechnology(const std::string& type,
@@ -86,9 +84,8 @@
                                  shill::kEnableTechnologyFunction);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(type);
-    helper_->CallVoidMethodWithErrorCallback(&method_call,
-                                            callback,
-                                            error_callback);
+    helper_->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                             error_callback);
   }
 
   void SetNetworkThrottlingStatus(
@@ -112,9 +109,8 @@
                                  shill::kDisableTechnologyFunction);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(type);
-    helper_->CallVoidMethodWithErrorCallback(&method_call,
-                                            callback,
-                                            error_callback);
+    helper_->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                             error_callback);
   }
 
   void ConfigureService(const base::DictionaryValue& properties,
@@ -124,9 +120,8 @@
                                  shill::kConfigureServiceFunction);
     dbus::MessageWriter writer(&method_call);
     ShillClientHelper::AppendServicePropertiesDictionary(&writer, properties);
-    helper_->CallObjectPathMethodWithErrorCallback(&method_call,
-                                                  callback,
-                                                  error_callback);
+    helper_->CallObjectPathMethodWithErrorCallback(&method_call, callback,
+                                                   error_callback);
   }
 
   void ConfigureServiceForProfile(
@@ -139,9 +134,8 @@
     dbus::MessageWriter writer(&method_call);
     writer.AppendObjectPath(dbus::ObjectPath(profile_path));
     ShillClientHelper::AppendServicePropertiesDictionary(&writer, properties);
-    helper_->CallObjectPathMethodWithErrorCallback(&method_call,
-                                                  callback,
-                                                  error_callback);
+    helper_->CallObjectPathMethodWithErrorCallback(&method_call, callback,
+                                                   error_callback);
   }
 
   void GetService(const base::DictionaryValue& properties,
@@ -151,18 +145,16 @@
                                  shill::kGetServiceFunction);
     dbus::MessageWriter writer(&method_call);
     ShillClientHelper::AppendServicePropertiesDictionary(&writer, properties);
-    helper_->CallObjectPathMethodWithErrorCallback(&method_call,
-                                                  callback,
-                                                  error_callback);
+    helper_->CallObjectPathMethodWithErrorCallback(&method_call, callback,
+                                                   error_callback);
   }
 
   void ConnectToBestServices(const base::Closure& callback,
                              const ErrorCallback& error_callback) override {
     dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
                                  shill::kConnectToBestServicesFunction);
-    helper_->CallVoidMethodWithErrorCallback(&method_call,
-                                            callback,
-                                            error_callback);
+    helper_->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                             error_callback);
   }
 
   TestInterface* GetTestInterface() override { return NULL; }
diff --git a/chromeos/dbus/shill_manager_client.h b/chromeos/dbus/shill/shill_manager_client.h
similarity index 97%
rename from chromeos/dbus/shill_manager_client.h
rename to chromeos/dbus/shill/shill_manager_client.h
index 1cca0b3..2839ecf 100644
--- a/chromeos/dbus/shill_manager_client.h
+++ b/chromeos/dbus/shill/shill_manager_client.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 CHROMEOS_DBUS_SHILL_MANAGER_CLIENT_H_
-#define CHROMEOS_DBUS_SHILL_MANAGER_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_SHILL_MANAGER_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_SHILL_MANAGER_CLIENT_H_
 
 #include <string>
 
@@ -11,7 +11,7 @@
 #include "base/macros.h"
 #include "chromeos/dbus/dbus_client.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
-#include "chromeos/dbus/shill_client_helper.h"
+#include "chromeos/dbus/shill/shill_client_helper.h"
 
 namespace dbus {
 class ObjectPath;
@@ -202,4 +202,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SHILL_MANAGER_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_SHILL_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/shill_manager_client_unittest.cc b/chromeos/dbus/shill/shill_manager_client_unittest.cc
similarity index 94%
rename from chromeos/dbus/shill_manager_client_unittest.cc
rename to chromeos/dbus/shill/shill_manager_client_unittest.cc
index 4867622..ec0f8cb 100644
--- a/chromeos/dbus/shill_manager_client_unittest.cc
+++ b/chromeos/dbus/shill/shill_manager_client_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 
 #include <memory>
 #include <utility>
@@ -12,7 +12,7 @@
 #include "base/run_loop.h"
 #include "base/test/mock_callback.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_client_unittest_base.h"
+#include "chromeos/dbus/shill/shill_client_unittest_base.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
 #include "dbus/values_util.h"
@@ -75,9 +75,9 @@
 
   // Set expectations.
   MockPropertyChangeObserver observer;
-  EXPECT_CALL(observer,
-              OnPropertyChanged(shill::kOfflineModeProperty,
-                                ValueEq(ByRef(kOfflineMode)))).Times(1);
+  EXPECT_CALL(observer, OnPropertyChanged(shill::kOfflineModeProperty,
+                                          ValueEq(ByRef(kOfflineMode))))
+      .Times(1);
 
   // Add the observer
   client_->AddPropertyChangedObserver(&observer);
@@ -113,8 +113,7 @@
   value.SetKey(shill::kOfflineModeProperty, base::Value(true));
   // Set expectations.
   PrepareForMethodCall(shill::kGetPropertiesFunction,
-                       base::Bind(&ExpectNoArgument),
-                       response.get());
+                       base::Bind(&ExpectNoArgument), response.get());
   // Call method.
   client_->GetProperties(base::Bind(&ExpectDictionaryValueResult, &value));
   // Run the message loop.
@@ -148,7 +147,6 @@
   type_dict_writer.CloseContainer(&type_entry_writer);
   writer.CloseContainer(&type_dict_writer);
 
-
   // Create the expected value.
   auto property_dict_value = std::make_unique<base::DictionaryValue>();
   property_dict_value->SetKey(shill::kGeoMacAddressProperty,
@@ -160,11 +158,10 @@
 
   // Set expectations.
   PrepareForMethodCall(shill::kGetNetworksForGeolocation,
-                       base::Bind(&ExpectNoArgument),
-                       response.get());
+                       base::Bind(&ExpectNoArgument), response.get());
   // Call method.
-  client_->GetNetworksForGeolocation(base::Bind(&ExpectDictionaryValueResult,
-                                                &type_dict_value));
+  client_->GetNetworksForGeolocation(
+      base::Bind(&ExpectDictionaryValueResult, &type_dict_value));
 
   // Run the message loop.
   base::RunLoop().RunUntilIdle();
@@ -177,8 +174,7 @@
   base::Value value("portal list");
   PrepareForMethodCall(shill::kSetPropertyFunction,
                        base::Bind(ExpectStringAndValueArguments,
-                                  shill::kCheckPortalListProperty,
-                                  &value),
+                                  shill::kCheckPortalListProperty, &value),
                        response.get());
   // Call method.
   base::MockCallback<base::Closure> mock_closure;
diff --git a/chromeos/dbus/shill_profile_client.cc b/chromeos/dbus/shill/shill_profile_client.cc
similarity index 81%
rename from chromeos/dbus/shill_profile_client.cc
rename to chromeos/dbus/shill/shill_profile_client.cc
index e7b64c83..759dcda7 100644
--- a/chromeos/dbus/shill_profile_client.cc
+++ b/chromeos/dbus/shill/shill_profile_client.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 "chromeos/dbus/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
 
 #include <map>
 #include <memory>
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
@@ -70,8 +70,7 @@
   DISALLOW_COPY_AND_ASSIGN(ShillProfileClientImpl);
 };
 
-ShillProfileClientImpl::ShillProfileClientImpl() : bus_(NULL) {
-}
+ShillProfileClientImpl::ShillProfileClientImpl() : bus_(NULL) {}
 
 ShillClientHelper* ShillProfileClientImpl::GetHelper(
     const dbus::ObjectPath& profile_path) {
@@ -96,8 +95,9 @@
     const ErrorCallback& error_callback) {
   dbus::MethodCall method_call(shill::kFlimflamProfileInterface,
                                shill::kGetPropertiesFunction);
-  GetHelper(profile_path)->CallDictionaryValueMethodWithErrorCallback(
-      &method_call, callback, error_callback);
+  GetHelper(profile_path)
+      ->CallDictionaryValueMethodWithErrorCallback(&method_call, callback,
+                                                   error_callback);
 }
 
 void ShillProfileClientImpl::GetEntry(
@@ -109,21 +109,21 @@
                                shill::kGetEntryFunction);
   dbus::MessageWriter writer(&method_call);
   writer.AppendString(entry_path);
-  GetHelper(profile_path)->CallDictionaryValueMethodWithErrorCallback(
-      &method_call, callback, error_callback);
+  GetHelper(profile_path)
+      ->CallDictionaryValueMethodWithErrorCallback(&method_call, callback,
+                                                   error_callback);
 }
 
-void ShillProfileClientImpl::DeleteEntry(
-    const dbus::ObjectPath& profile_path,
-    const std::string& entry_path,
-    const base::Closure& callback,
-    const ErrorCallback& error_callback) {
+void ShillProfileClientImpl::DeleteEntry(const dbus::ObjectPath& profile_path,
+                                         const std::string& entry_path,
+                                         const base::Closure& callback,
+                                         const ErrorCallback& error_callback) {
   dbus::MethodCall method_call(shill::kFlimflamProfileInterface,
                                shill::kDeleteEntryFunction);
   dbus::MessageWriter writer(&method_call);
   writer.AppendString(entry_path);
-  GetHelper(profile_path)->CallVoidMethodWithErrorCallback(
-      &method_call, callback, error_callback);
+  GetHelper(profile_path)
+      ->CallVoidMethodWithErrorCallback(&method_call, callback, error_callback);
 }
 
 }  // namespace
diff --git a/chromeos/dbus/shill_profile_client.h b/chromeos/dbus/shill/shill_profile_client.h
similarity index 96%
rename from chromeos/dbus/shill_profile_client.h
rename to chromeos/dbus/shill/shill_profile_client.h
index 2866c93..d9a8a69 100644
--- a/chromeos/dbus/shill_profile_client.h
+++ b/chromeos/dbus/shill/shill_profile_client.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 CHROMEOS_DBUS_SHILL_PROFILE_CLIENT_H_
-#define CHROMEOS_DBUS_SHILL_PROFILE_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_SHILL_PROFILE_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_SHILL_PROFILE_CLIENT_H_
 
 #include <string>
 #include <vector>
@@ -12,7 +12,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "chromeos/dbus/dbus_client.h"
-#include "chromeos/dbus/shill_client_helper.h"
+#include "chromeos/dbus/shill/shill_client_helper.h"
 
 namespace base {
 
@@ -152,4 +152,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SHILL_PROFILE_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_SHILL_PROFILE_CLIENT_H_
diff --git a/chromeos/dbus/shill_profile_client_unittest.cc b/chromeos/dbus/shill/shill_profile_client_unittest.cc
similarity index 90%
rename from chromeos/dbus/shill_profile_client_unittest.cc
rename to chromeos/dbus/shill/shill_profile_client_unittest.cc
index 3af51541..30384b8 100644
--- a/chromeos/dbus/shill_profile_client_unittest.cc
+++ b/chromeos/dbus/shill/shill_profile_client_unittest.cc
@@ -9,8 +9,8 @@
 #include "base/run_loop.h"
 #include "base/test/mock_callback.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_client_unittest_base.h"
-#include "chromeos/dbus/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_client_unittest_base.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
 #include "dbus/values_util.h"
@@ -40,8 +40,7 @@
  public:
   ShillProfileClientTest()
       : ShillClientUnittestBase(shill::kFlimflamProfileInterface,
-                                   dbus::ObjectPath(kDefaultProfilePath)) {
-  }
+                                dbus::ObjectPath(kDefaultProfilePath)) {}
 
   void SetUp() override {
     ShillClientUnittestBase::SetUp();
@@ -70,22 +69,19 @@
   value.AppendString(kExampleEntryPath);
   MockPropertyChangeObserver observer;
   EXPECT_CALL(observer,
-              OnPropertyChanged(
-                  shill::kEntriesProperty,
-                  ValueEq(value))).Times(1);
+              OnPropertyChanged(shill::kEntriesProperty, ValueEq(value)))
+      .Times(1);
 
   // Add the observer
-  client_->AddPropertyChangedObserver(
-      dbus::ObjectPath(kDefaultProfilePath),
-      &observer);
+  client_->AddPropertyChangedObserver(dbus::ObjectPath(kDefaultProfilePath),
+                                      &observer);
 
   // Run the signal callback.
   SendPropertyChangedSignal(&signal);
 
   // Remove the observer.
-  client_->RemovePropertyChangedObserver(
-      dbus::ObjectPath(kDefaultProfilePath),
-      &observer);
+  client_->RemovePropertyChangedObserver(dbus::ObjectPath(kDefaultProfilePath),
+                                         &observer);
 
   EXPECT_CALL(observer, OnPropertyChanged(_, _)).Times(0);
 
@@ -114,8 +110,7 @@
   value.SetWithoutPathExpansion(shill::kEntriesProperty, std::move(entries));
   // Set expectations.
   PrepareForMethodCall(shill::kGetPropertiesFunction,
-                       base::Bind(&ExpectNoArgument),
-                       response.get());
+                       base::Bind(&ExpectNoArgument), response.get());
   // Call method.
   base::MockCallback<ShillProfileClient::ErrorCallback> error_callback;
   client_->GetProperties(
diff --git a/chromeos/dbus/shill_property_changed_observer.h b/chromeos/dbus/shill/shill_property_changed_observer.h
similarity index 75%
rename from chromeos/dbus/shill_property_changed_observer.h
rename to chromeos/dbus/shill/shill_property_changed_observer.h
index 7ee937328..a6a4b88 100644
--- a/chromeos/dbus/shill_property_changed_observer.h
+++ b/chromeos/dbus/shill/shill_property_changed_observer.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 CHROMEOS_DBUS_SHILL_PROPERTY_CHANGED_OBSERVER_H_
-#define CHROMEOS_DBUS_SHILL_PROPERTY_CHANGED_OBSERVER_H_
+#ifndef CHROMEOS_DBUS_SHILL_SHILL_PROPERTY_CHANGED_OBSERVER_H_
+#define CHROMEOS_DBUS_SHILL_SHILL_PROPERTY_CHANGED_OBSERVER_H_
 
 #include <string>
 
@@ -26,4 +26,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SHILL_PROPERTY_CHANGED_OBSERVER_H_
+#endif  // CHROMEOS_DBUS_SHILL_SHILL_PROPERTY_CHANGED_OBSERVER_H_
diff --git a/chromeos/dbus/shill_service_client.cc b/chromeos/dbus/shill/shill_service_client.cc
similarity index 77%
rename from chromeos/dbus/shill_service_client.cc
rename to chromeos/dbus/shill/shill_service_client.cc
index 54be594..1feb4f65 100644
--- a/chromeos/dbus/shill_service_client.cc
+++ b/chromeos/dbus/shill/shill_service_client.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 "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 
 #include <map>
 
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/stl_util.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 #include "components/device_event_log/device_event_log.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
@@ -36,10 +36,9 @@
     const ShillServiceClient::DictionaryValueCallback& callback,
     const std::string& error_name,
     const std::string& error_message) {
-  const std::string log_string =
-      "Failed to call org.chromium.shill.Service." + method_name +
-      " for: " + service_path.value() + ": " +
-      error_name + ": " + error_message;
+  const std::string log_string = "Failed to call org.chromium.shill.Service." +
+                                 method_name + " for: " + service_path.value() +
+                                 ": " + error_name + ": " + error_message;
 
   // Suppress ERROR messages for UnknownMethod/Object" since this can
   // happen under normal conditions. See crbug.com/130660 and crbug.com/222210.
@@ -59,8 +58,8 @@
   ShillServiceClientImpl() : bus_(NULL), weak_ptr_factory_(this) {}
 
   ~ShillServiceClientImpl() override {
-    for (HelperMap::iterator iter = helpers_.begin();
-         iter != helpers_.end(); ++iter) {
+    for (HelperMap::iterator iter = helpers_.begin(); iter != helpers_.end();
+         ++iter) {
       ShillClientHelper* helper = iter->second;
       bus_->RemoveObjectProxy(shill::kFlimflamServiceName,
                               helper->object_proxy()->object_path(),
@@ -85,11 +84,11 @@
                      const DictionaryValueCallback& callback) override {
     dbus::MethodCall method_call(shill::kFlimflamServiceInterface,
                                  shill::kGetPropertiesFunction);
-    GetHelper(service_path)->CallDictionaryValueMethodWithErrorCallback(
-        &method_call,
-        base::Bind(callback, DBUS_METHOD_CALL_SUCCESS),
-        base::Bind(&OnGetDictionaryError, "GetProperties",
-                   service_path, callback));
+    GetHelper(service_path)
+        ->CallDictionaryValueMethodWithErrorCallback(
+            &method_call, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS),
+            base::Bind(&OnGetDictionaryError, "GetProperties", service_path,
+                       callback));
   }
 
   void SetProperty(const dbus::ObjectPath& service_path,
@@ -102,9 +101,9 @@
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(name);
     ShillClientHelper::AppendValueDataAsVariant(&writer, value);
-    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
-                                                             callback,
-                                                             error_callback);
+    GetHelper(service_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void SetProperties(const dbus::ObjectPath& service_path,
@@ -115,9 +114,9 @@
                                  shill::kSetPropertiesFunction);
     dbus::MessageWriter writer(&method_call);
     ShillClientHelper::AppendServicePropertiesDictionary(&writer, properties);
-    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
-                                                             callback,
-                                                             error_callback);
+    GetHelper(service_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void ClearProperty(const dbus::ObjectPath& service_path,
@@ -128,9 +127,9 @@
                                  shill::kClearPropertyFunction);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(name);
-    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
-                                                             callback,
-                                                             error_callback);
+    GetHelper(service_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void ClearProperties(const dbus::ObjectPath& service_path,
@@ -141,10 +140,9 @@
                                  shill::kClearPropertiesFunction);
     dbus::MessageWriter writer(&method_call);
     writer.AppendArrayOfStrings(names);
-    GetHelper(service_path)->CallListValueMethodWithErrorCallback(
-        &method_call,
-        callback,
-        error_callback);
+    GetHelper(service_path)
+        ->CallListValueMethodWithErrorCallback(&method_call, callback,
+                                               error_callback);
   }
 
   void Connect(const dbus::ObjectPath& service_path,
@@ -152,8 +150,9 @@
                const ErrorCallback& error_callback) override {
     dbus::MethodCall method_call(shill::kFlimflamServiceInterface,
                                  shill::kConnectFunction);
-    GetHelper(service_path)->CallVoidMethodWithErrorCallback(
-        &method_call, callback, error_callback);
+    GetHelper(service_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void Disconnect(const dbus::ObjectPath& service_path,
@@ -161,9 +160,9 @@
                   const ErrorCallback& error_callback) override {
     dbus::MethodCall method_call(shill::kFlimflamServiceInterface,
                                  shill::kDisconnectFunction);
-    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
-                                                             callback,
-                                                             error_callback);
+    GetHelper(service_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void Remove(const dbus::ObjectPath& service_path,
@@ -171,9 +170,9 @@
               const ErrorCallback& error_callback) override {
     dbus::MethodCall method_call(shill::kFlimflamServiceInterface,
                                  shill::kRemoveServiceFunction);
-    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
-                                                             callback,
-                                                             error_callback);
+    GetHelper(service_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void ActivateCellularModem(const dbus::ObjectPath& service_path,
@@ -184,9 +183,9 @@
                                  shill::kActivateCellularModemFunction);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(carrier);
-    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
-                                                             callback,
-                                                             error_callback);
+    GetHelper(service_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void CompleteCellularActivation(
@@ -196,9 +195,9 @@
     dbus::MethodCall method_call(shill::kFlimflamServiceInterface,
                                  shill::kCompleteCellularActivationFunction);
     dbus::MessageWriter writer(&method_call);
-    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
-                                                             callback,
-                                                             error_callback);
+    GetHelper(service_path)
+        ->CallVoidMethodWithErrorCallback(&method_call, callback,
+                                          error_callback);
   }
 
   void GetLoadableProfileEntries(
@@ -206,11 +205,11 @@
       const DictionaryValueCallback& callback) override {
     dbus::MethodCall method_call(shill::kFlimflamServiceInterface,
                                  shill::kGetLoadableProfileEntriesFunction);
-    GetHelper(service_path)->CallDictionaryValueMethodWithErrorCallback(
-        &method_call,
-        base::Bind(callback, DBUS_METHOD_CALL_SUCCESS),
-        base::Bind(&OnGetDictionaryError, "GetLoadableProfileEntries",
-                   service_path, callback));
+    GetHelper(service_path)
+        ->CallDictionaryValueMethodWithErrorCallback(
+            &method_call, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS),
+            base::Bind(&OnGetDictionaryError, "GetLoadableProfileEntries",
+                       service_path, callback));
   }
 
   ShillServiceClient::TestInterface* GetTestInterface() override {
diff --git a/chromeos/dbus/shill_service_client.h b/chromeos/dbus/shill/shill_service_client.h
similarity index 93%
rename from chromeos/dbus/shill_service_client.h
rename to chromeos/dbus/shill/shill_service_client.h
index bb184e4f..c0d6ef7b 100644
--- a/chromeos/dbus/shill_service_client.h
+++ b/chromeos/dbus/shill/shill_service_client.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 CHROMEOS_DBUS_SHILL_SERVICE_CLIENT_H_
-#define CHROMEOS_DBUS_SHILL_SERVICE_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_SHILL_SERVICE_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_SHILL_SERVICE_CLIENT_H_
 
 #include <string>
 #include <vector>
@@ -12,7 +12,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "chromeos/dbus/dbus_client.h"
-#include "chromeos/dbus/shill_client_helper.h"
+#include "chromeos/dbus/shill/shill_client_helper.h"
 
 namespace base {
 
@@ -159,11 +159,10 @@
 
   // Calls ActivateCellularModem method.
   // |callback| is called after the method call succeeds.
-  virtual void ActivateCellularModem(
-      const dbus::ObjectPath& service_path,
-      const std::string& carrier,
-      const base::Closure& callback,
-      const ErrorCallback& error_callback) = 0;
+  virtual void ActivateCellularModem(const dbus::ObjectPath& service_path,
+                                     const std::string& carrier,
+                                     const base::Closure& callback,
+                                     const ErrorCallback& error_callback) = 0;
 
   // Calls the CompleteCellularActivation method.
   // |callback| is called after the method call succeeds.
@@ -193,4 +192,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SHILL_SERVICE_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_SHILL_SERVICE_CLIENT_H_
diff --git a/chromeos/dbus/shill_service_client_unittest.cc b/chromeos/dbus/shill/shill_service_client_unittest.cc
similarity index 88%
rename from chromeos/dbus/shill_service_client_unittest.cc
rename to chromeos/dbus/shill/shill_service_client_unittest.cc
index 9f7a4a41..d8c6f9e 100644
--- a/chromeos/dbus/shill_service_client_unittest.cc
+++ b/chromeos/dbus/shill/shill_service_client_unittest.cc
@@ -8,8 +8,8 @@
 #include "base/run_loop.h"
 #include "base/test/mock_callback.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_client_unittest_base.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_client_unittest_base.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "dbus/message.h"
 #include "dbus/object_path.h"
 #include "dbus/values_util.h"
@@ -31,8 +31,7 @@
  public:
   ShillServiceClientTest()
       : ShillClientUnittestBase(shill::kFlimflamServiceInterface,
-                                   dbus::ObjectPath(kExampleServicePath)) {
-  }
+                                dbus::ObjectPath(kExampleServicePath)) {}
 
   void SetUp() override {
     ShillClientUnittestBase::SetUp();
@@ -59,23 +58,20 @@
   // Set expectations.
   const base::Value value(kValue);
   MockPropertyChangeObserver observer;
-  EXPECT_CALL(observer,
-              OnPropertyChanged(
-                  shill::kSignalStrengthProperty,
-                  ValueEq(ByRef(value)))).Times(1);
+  EXPECT_CALL(observer, OnPropertyChanged(shill::kSignalStrengthProperty,
+                                          ValueEq(ByRef(value))))
+      .Times(1);
 
   // Add the observer
-  client_->AddPropertyChangedObserver(
-      dbus::ObjectPath(kExampleServicePath),
-      &observer);
+  client_->AddPropertyChangedObserver(dbus::ObjectPath(kExampleServicePath),
+                                      &observer);
 
   // Run the signal callback.
   SendPropertyChangedSignal(&signal);
 
   // Remove the observer.
-  client_->RemovePropertyChangedObserver(
-      dbus::ObjectPath(kExampleServicePath),
-      &observer);
+  client_->RemovePropertyChangedObserver(dbus::ObjectPath(kExampleServicePath),
+                                         &observer);
 
   EXPECT_CALL(observer, OnPropertyChanged(_, _)).Times(0);
 
@@ -101,8 +97,7 @@
   base::DictionaryValue value;
   value.SetKey(shill::kSignalStrengthProperty, base::Value(kValue));
   PrepareForMethodCall(shill::kGetPropertiesFunction,
-                       base::Bind(&ExpectNoArgument),
-                       response.get());
+                       base::Bind(&ExpectNoArgument), response.get());
   // Call method.
   client_->GetProperties(dbus::ObjectPath(kExampleServicePath),
                          base::Bind(&ExpectDictionaryValueResult, &value));
@@ -119,8 +114,7 @@
   const base::Value value(kValue);
   PrepareForMethodCall(shill::kSetPropertyFunction,
                        base::Bind(&ExpectStringAndValueArguments,
-                                  shill::kPassphraseProperty,
-                                  &value),
+                                  shill::kPassphraseProperty, &value),
                        response.get());
   // Call method.
   base::MockCallback<base::Closure> mock_closure;
@@ -165,10 +159,10 @@
   std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
 
   // Set expectations.
-  PrepareForMethodCall(shill::kClearPropertyFunction,
-                       base::Bind(&ExpectStringArgument,
-                                  shill::kPassphraseProperty),
-                       response.get());
+  PrepareForMethodCall(
+      shill::kClearPropertyFunction,
+      base::Bind(&ExpectStringArgument, shill::kPassphraseProperty),
+      response.get());
   // Call method.
   base::MockCallback<base::Closure> mock_closure;
   base::MockCallback<ShillServiceClient::ErrorCallback> mock_error_callback;
@@ -220,8 +214,7 @@
   // Set expectations.
   base::MockCallback<base::Closure> mock_closure;
   base::MockCallback<ShillServiceClient::ErrorCallback> mock_error_callback;
-  PrepareForMethodCall(shill::kConnectFunction,
-                       base::Bind(&ExpectNoArgument),
+  PrepareForMethodCall(shill::kConnectFunction, base::Bind(&ExpectNoArgument),
                        response.get());
   EXPECT_CALL(mock_closure, Run()).Times(1);
   // Call method.
@@ -238,8 +231,7 @@
 
   // Set expectations.
   PrepareForMethodCall(shill::kDisconnectFunction,
-                       base::Bind(&ExpectNoArgument),
-                       response.get());
+                       base::Bind(&ExpectNoArgument), response.get());
   // Call method.
   base::MockCallback<base::Closure> mock_closure;
   base::MockCallback<ShillServiceClient::ErrorCallback> mock_error_callback;
@@ -258,8 +250,7 @@
 
   // Set expectations.
   PrepareForMethodCall(shill::kRemoveServiceFunction,
-                       base::Bind(&ExpectNoArgument),
-                       response.get());
+                       base::Bind(&ExpectNoArgument), response.get());
   // Call method.
   base::MockCallback<base::Closure> mock_closure;
   base::MockCallback<ShillServiceClient::ErrorCallback> mock_error_callback;
diff --git a/chromeos/dbus/shill_third_party_vpn_driver_client.cc b/chromeos/dbus/shill/shill_third_party_vpn_driver_client.cc
similarity index 98%
rename from chromeos/dbus/shill_third_party_vpn_driver_client.cc
rename to chromeos/dbus/shill/shill_third_party_vpn_driver_client.cc
index 578719a..ebfc703 100644
--- a/chromeos/dbus/shill_third_party_vpn_driver_client.cc
+++ b/chromeos/dbus/shill/shill_third_party_vpn_driver_client.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 "chromeos/dbus/shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -13,7 +13,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/stl_util.h"
-#include "chromeos/dbus/shill_third_party_vpn_observer.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_observer.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_proxy.h"
@@ -130,8 +130,7 @@
 
 ShillThirdPartyVpnDriverClientImpl::HelperInfo::HelperInfo(
     dbus::ObjectProxy* object_proxy)
-    : helper_(object_proxy), observer_(nullptr), weak_ptr_factory_(this) {
-}
+    : helper_(object_proxy), observer_(nullptr), weak_ptr_factory_(this) {}
 
 ShillThirdPartyVpnDriverClientImpl::ShillThirdPartyVpnDriverClientImpl()
     : bus_(nullptr) {
diff --git a/chromeos/dbus/shill_third_party_vpn_driver_client.h b/chromeos/dbus/shill/shill_third_party_vpn_driver_client.h
similarity index 92%
rename from chromeos/dbus/shill_third_party_vpn_driver_client.h
rename to chromeos/dbus/shill/shill_third_party_vpn_driver_client.h
index 54af2bc..5d8af6d 100644
--- a/chromeos/dbus/shill_third_party_vpn_driver_client.h
+++ b/chromeos/dbus/shill/shill_third_party_vpn_driver_client.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 CHROMEOS_DBUS_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
-#define CHROMEOS_DBUS_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
 
 #include <stdint.h>
 #include <string>
@@ -13,7 +13,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "chromeos/dbus/dbus_client.h"
-#include "chromeos/dbus/shill_client_helper.h"
+#include "chromeos/dbus/shill/shill_client_helper.h"
 
 namespace chromeos {
 
@@ -92,4 +92,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_SHILL_THIRD_PARTY_VPN_DRIVER_CLIENT_H_
diff --git a/chromeos/dbus/shill_third_party_vpn_driver_client_unittest.cc b/chromeos/dbus/shill/shill_third_party_vpn_driver_client_unittest.cc
similarity index 96%
rename from chromeos/dbus/shill_third_party_vpn_driver_client_unittest.cc
rename to chromeos/dbus/shill/shill_third_party_vpn_driver_client_unittest.cc
index 8e9dc77..6e30887e 100644
--- a/chromeos/dbus/shill_third_party_vpn_driver_client_unittest.cc
+++ b/chromeos/dbus/shill/shill_third_party_vpn_driver_client_unittest.cc
@@ -10,9 +10,9 @@
 
 #include "base/bind.h"
 #include "base/run_loop.h"
-#include "chromeos/dbus/shill_client_unittest_base.h"
-#include "chromeos/dbus/shill_third_party_vpn_driver_client.h"
-#include "chromeos/dbus/shill_third_party_vpn_observer.h"
+#include "chromeos/dbus/shill/shill_client_unittest_base.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_observer.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 using testing::_;
diff --git a/chromeos/dbus/shill_third_party_vpn_observer.h b/chromeos/dbus/shill/shill_third_party_vpn_observer.h
similarity index 77%
rename from chromeos/dbus/shill_third_party_vpn_observer.h
rename to chromeos/dbus/shill/shill_third_party_vpn_observer.h
index 0a85eb8..1ae0e73f 100644
--- a/chromeos/dbus/shill_third_party_vpn_observer.h
+++ b/chromeos/dbus/shill/shill_third_party_vpn_observer.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 CHROMEOS_DBUS_SHILL_THIRD_PARTY_VPN_OBSERVER_H_
-#define CHROMEOS_DBUS_SHILL_THIRD_PARTY_VPN_OBSERVER_H_
+#ifndef CHROMEOS_DBUS_SHILL_SHILL_THIRD_PARTY_VPN_OBSERVER_H_
+#define CHROMEOS_DBUS_SHILL_SHILL_THIRD_PARTY_VPN_OBSERVER_H_
 
 #include <stdint.h>
 #include <vector>
@@ -26,4 +26,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SHILL_THIRD_PARTY_VPN_OBSERVER_H_
+#endif  // CHROMEOS_DBUS_SHILL_SHILL_THIRD_PARTY_VPN_OBSERVER_H_
diff --git a/chromeos/dbus/sms_client.cc b/chromeos/dbus/shill/sms_client.cc
similarity index 98%
rename from chromeos/dbus/sms_client.cc
rename to chromeos/dbus/shill/sms_client.cc
index 0fc6cf1..ff4d131 100644
--- a/chromeos/dbus/sms_client.cc
+++ b/chromeos/dbus/shill/sms_client.cc
@@ -1,7 +1,7 @@
 // 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 "chromeos/dbus/sms_client.h"
+#include "chromeos/dbus/shill/sms_client.h"
 
 #include <map>
 #include <memory>
diff --git a/chromeos/dbus/sms_client.h b/chromeos/dbus/shill/sms_client.h
similarity index 92%
rename from chromeos/dbus/sms_client.h
rename to chromeos/dbus/shill/sms_client.h
index c4ffaf0..478691fe 100644
--- a/chromeos/dbus/sms_client.h
+++ b/chromeos/dbus/shill/sms_client.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 CHROMEOS_DBUS_SMS_CLIENT_H_
-#define CHROMEOS_DBUS_SMS_CLIENT_H_
+#ifndef CHROMEOS_DBUS_SHILL_SMS_CLIENT_H_
+#define CHROMEOS_DBUS_SHILL_SMS_CLIENT_H_
 
 #include <string>
 
@@ -57,4 +57,4 @@
 
 }  // namespace chromeos
 
-#endif  // CHROMEOS_DBUS_SMS_CLIENT_H_
+#endif  // CHROMEOS_DBUS_SHILL_SMS_CLIENT_H_
diff --git a/chromeos/dbus/upstart/BUILD.gn b/chromeos/dbus/upstart/BUILD.gn
new file mode 100644
index 0000000..b6829e3
--- /dev/null
+++ b/chromeos/dbus/upstart/BUILD.gn
@@ -0,0 +1,26 @@
+# Copyright 2019 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_chromeos, "Non-Chrome-OS builds cannot depend on //chromeos")
+
+component("upstart") {
+  defines = [ "IS_UPSTART_CLIENT_IMPL" ]
+
+  deps = [
+    "//base",
+    "//chromeos/dbus:common",
+    "//chromeos/dbus/auth_policy",
+    "//chromeos/dbus/auth_policy:authpolicy_proto",
+    "//chromeos/dbus/kerberos",
+    "//chromeos/dbus/media_analytics",
+    "//dbus",
+  ]
+
+  sources = [
+    "fake_upstart_client.cc",
+    "fake_upstart_client.h",
+    "upstart_client.cc",
+    "upstart_client.h",
+  ]
+}
diff --git a/chromeos/dbus/upstart/fake_upstart_client.h b/chromeos/dbus/upstart/fake_upstart_client.h
index b2a14f3..3218df2 100644
--- a/chromeos/dbus/upstart/fake_upstart_client.h
+++ b/chromeos/dbus/upstart/fake_upstart_client.h
@@ -5,13 +5,14 @@
 #ifndef CHROMEOS_DBUS_UPSTART_FAKE_UPSTART_CLIENT_H_
 #define CHROMEOS_DBUS_UPSTART_FAKE_UPSTART_CLIENT_H_
 
+#include "base/component_export.h"
 #include "base/macros.h"
-
 #include "chromeos/dbus/upstart/upstart_client.h"
 
 namespace chromeos {
 
-class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeUpstartClient : public UpstartClient {
+class COMPONENT_EXPORT(UPSTART_CLIENT) FakeUpstartClient
+    : public UpstartClient {
  public:
   FakeUpstartClient();
   ~FakeUpstartClient() override;
diff --git a/chromeos/dbus/upstart/upstart_client.h b/chromeos/dbus/upstart/upstart_client.h
index f6b42fa..360c4c3b 100644
--- a/chromeos/dbus/upstart/upstart_client.h
+++ b/chromeos/dbus/upstart/upstart_client.h
@@ -22,7 +22,7 @@
 // UpstartClient is used to communicate with the com.ubuntu.Upstart
 // sevice. All methods should be called from the origin thread (UI thread) which
 // initializes the DBusThreadManager instance.
-class COMPONENT_EXPORT(CHROMEOS_DBUS) UpstartClient {
+class COMPONENT_EXPORT(UPSTART_CLIENT) UpstartClient {
  public:
   virtual ~UpstartClient();
 
diff --git a/chromeos/disks/suspend_unmount_manager.cc b/chromeos/disks/suspend_unmount_manager.cc
index 30cff943..f17cbf9 100644
--- a/chromeos/disks/suspend_unmount_manager.cc
+++ b/chromeos/disks/suspend_unmount_manager.cc
@@ -26,7 +26,7 @@
 SuspendUnmountManager::~SuspendUnmountManager() {
   PowerManagerClient::Get()->RemoveObserver(this);
   if (!suspend_readiness_callback_.is_null())
-    suspend_readiness_callback_.Run();
+    std::move(suspend_readiness_callback_).Run();
 }
 
 void SuspendUnmountManager::SuspendImminent(
@@ -69,10 +69,8 @@
   // This can happen when unmount completes after suspend done is called.
   if (unmounting_paths_.erase(mount_path) != 1)
     return;
-  if (unmounting_paths_.empty() && !suspend_readiness_callback_.is_null()) {
-    suspend_readiness_callback_.Run();
-    suspend_readiness_callback_.Reset();
-  }
+  if (unmounting_paths_.empty() && !suspend_readiness_callback_.is_null())
+    std::move(suspend_readiness_callback_).Run();
 }
 
 }  // namespace disks
diff --git a/chromeos/disks/suspend_unmount_manager.h b/chromeos/disks/suspend_unmount_manager.h
index 6a78b92..48714d9 100644
--- a/chromeos/disks/suspend_unmount_manager.h
+++ b/chromeos/disks/suspend_unmount_manager.h
@@ -40,7 +40,7 @@
   // The paths that the manager currently tries to unmount for suspend.
   std::set<std::string> unmounting_paths_;
 
-  base::Closure suspend_readiness_callback_;
+  base::OnceClosure suspend_readiness_callback_;
 
   base::WeakPtrFactory<SuspendUnmountManager> weak_ptr_factory_;
 
diff --git a/chromeos/geolocation/simple_geolocation_unittest.cc b/chromeos/geolocation/simple_geolocation_unittest.cc
index a7edebc6..7dc23e7 100644
--- a/chromeos/geolocation/simple_geolocation_unittest.cc
+++ b/chromeos/geolocation/simple_geolocation_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/geolocation/simple_geolocation_provider.h"
 #include "chromeos/geolocation/simple_geolocation_request_test_monitor.h"
 #include "chromeos/network/geolocation_handler.h"
diff --git a/chromeos/login/auth/BUILD.gn b/chromeos/login/auth/BUILD.gn
index 5809017c..b02ac08c 100644
--- a/chromeos/login/auth/BUILD.gn
+++ b/chromeos/login/auth/BUILD.gn
@@ -17,10 +17,11 @@
     "//base:i18n",
     "//chromeos/constants",
     "//chromeos/cryptohome",
-    "//chromeos/dbus",
-    "//chromeos/dbus:authpolicy_proto",
+    "//chromeos/dbus/auth_policy",
+    "//chromeos/dbus/auth_policy:authpolicy_proto",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:cryptohome_proto",
+    "//chromeos/dbus/session_manager",
     "//chromeos/login/login_state",
     "//chromeos/tpm",
     "//components/account_id",
@@ -110,7 +111,9 @@
     ":auth",
     "//base",
     "//base:i18n",
-    "//chromeos/dbus:authpolicy_proto",
+    "//chromeos/dbus/auth_policy",
+    "//chromeos/dbus/auth_policy:authpolicy_proto",
+    "//chromeos/dbus/cryptohome",
     "//chromeos/tpm:test_support",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/chromeos/login/auth/cryptohome_authenticator.cc b/chromeos/login/auth/cryptohome_authenticator.cc
index f5b563ae..12c5b67f9 100644
--- a/chromeos/login/auth/cryptohome_authenticator.cc
+++ b/chromeos/login/auth/cryptohome_authenticator.cc
@@ -21,7 +21,6 @@
 #include "chromeos/cryptohome/homedir_methods.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/login/auth/auth_status_consumer.h"
 #include "chromeos/login/auth/key.h"
 #include "chromeos/login/auth/login_event_recorder.h"
diff --git a/chromeos/login/auth/extended_authenticator_impl.cc b/chromeos/login/auth/extended_authenticator_impl.cc
index 89352b55..788bbb93 100644
--- a/chromeos/login/auth/extended_authenticator_impl.cc
+++ b/chromeos/login/auth/extended_authenticator_impl.cc
@@ -15,7 +15,6 @@
 #include "chromeos/cryptohome/homedir_methods.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/login/auth/auth_status_consumer.h"
 #include "chromeos/login/auth/key.h"
 #include "chromeos/login/auth/login_event_recorder.h"
diff --git a/chromeos/login/auth/login_performer.cc b/chromeos/login/auth/login_performer.cc
index b111581..25e9839 100644
--- a/chromeos/login/auth/login_performer.cc
+++ b/chromeos/login/auth/login_performer.cc
@@ -14,7 +14,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/login/auth/login_event_recorder.h"
 #include "components/account_id/account_id.h"
diff --git a/chromeos/network/auto_connect_handler.cc b/chromeos/network/auto_connect_handler.cc
index 889309c..e75109a 100644
--- a/chromeos/network/auto_connect_handler.cc
+++ b/chromeos/network/auto_connect_handler.cc
@@ -13,8 +13,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/device_state.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_connection_handler.h"
diff --git a/chromeos/network/client_cert_resolver.cc b/chromeos/network/client_cert_resolver.cc
index 768cce8a1..5a07452 100644
--- a/chromeos/network/client_cert_resolver.cc
+++ b/chromeos/network/client_cert_resolver.cc
@@ -21,7 +21,7 @@
 #include "base/task/post_task.h"
 #include "base/time/clock.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/certificate_helper.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_event_log.h"
diff --git a/chromeos/network/client_cert_resolver_unittest.cc b/chromeos/network/client_cert_resolver_unittest.cc
index a3f917c2..341d5bc 100644
--- a/chromeos/network/client_cert_resolver_unittest.cc
+++ b/chromeos/network/client_cert_resolver_unittest.cc
@@ -22,9 +22,9 @@
 #include "base/test/simple_test_clock.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/managed_network_configuration_handler_impl.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_configuration_handler.h"
diff --git a/chromeos/network/fast_transition_observer_unittest.cc b/chromeos/network/fast_transition_observer_unittest.cc
index b37f20f2..3ae70ea 100644
--- a/chromeos/network/fast_transition_observer_unittest.cc
+++ b/chromeos/network/fast_transition_observer_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/message_loop/message_loop.h"
 #include "chromeos/constants/chromeos_pref_names.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/fast_transition_observer.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/prefs/pref_registry_simple.h"
diff --git a/chromeos/network/geolocation_handler.cc b/chromeos/network/geolocation_handler.cc
index 79df504..c6e562ec 100644
--- a/chromeos/network/geolocation_handler.cc
+++ b/chromeos/network/geolocation_handler.cc
@@ -11,7 +11,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace chromeos {
diff --git a/chromeos/network/geolocation_handler.h b/chromeos/network/geolocation_handler.h
index 6d67a85..32b57c8 100644
--- a/chromeos/network/geolocation_handler.h
+++ b/chromeos/network/geolocation_handler.h
@@ -11,7 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_util.h"
 
diff --git a/chromeos/network/geolocation_handler_unittest.cc b/chromeos/network/geolocation_handler_unittest.cc
index 5b07c51..b0cc696 100644
--- a/chromeos/network/geolocation_handler_unittest.cc
+++ b/chromeos/network/geolocation_handler_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
diff --git a/chromeos/network/managed_network_configuration_handler_impl.cc b/chromeos/network/managed_network_configuration_handler_impl.cc
index a105a4e7..5eabaef 100644
--- a/chromeos/network/managed_network_configuration_handler_impl.cc
+++ b/chromeos/network/managed_network_configuration_handler_impl.cc
@@ -16,9 +16,9 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/device_state.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_device_handler.h"
diff --git a/chromeos/network/managed_network_configuration_handler_unittest.cc b/chromeos/network/managed_network_configuration_handler_unittest.cc
index a367164..395ee4e 100644
--- a/chromeos/network/managed_network_configuration_handler_unittest.cc
+++ b/chromeos/network/managed_network_configuration_handler_unittest.cc
@@ -14,8 +14,8 @@
 #include "base/run_loop.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_shill_profile_client.h"
-#include "chromeos/dbus/fake_shill_service_client.h"
+#include "chromeos/dbus/shill/fake_shill_profile_client.h"
+#include "chromeos/dbus/shill/fake_shill_service_client.h"
 #include "chromeos/network/managed_network_configuration_handler_impl.h"
 #include "chromeos/network/mock_network_state_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
diff --git a/chromeos/network/network_activation_handler.cc b/chromeos/network/network_activation_handler.cc
index a6845e3..2e53320 100644
--- a/chromeos/network/network_activation_handler.cc
+++ b/chromeos/network/network_activation_handler.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_event_log.h"
 #include "chromeos/network/network_handler.h"
 #include "dbus/object_proxy.h"
diff --git a/chromeos/network/network_cert_migrator.cc b/chromeos/network/network_cert_migrator.cc
index be3ea49..a0a199d 100644
--- a/chromeos/network/network_cert_migrator.cc
+++ b/chromeos/network/network_cert_migrator.cc
@@ -13,7 +13,7 @@
 #include "base/location.h"
 #include "base/metrics/histogram_macros.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/client_cert_util.h"
 #include "chromeos/network/network_handler_callbacks.h"
 #include "chromeos/network/network_state.h"
diff --git a/chromeos/network/network_cert_migrator_unittest.cc b/chromeos/network/network_cert_migrator_unittest.cc
index e433e0dd..324969fb 100644
--- a/chromeos/network/network_cert_migrator_unittest.cc
+++ b/chromeos/network/network_cert_migrator_unittest.cc
@@ -13,8 +13,8 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/test/scoped_task_environment.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_cert_loader.h"
 #include "chromeos/network/network_state_handler.h"
 #include "crypto/scoped_nss_types.h"
diff --git a/chromeos/network/network_configuration_handler.cc b/chromeos/network/network_configuration_handler.cc
index ff4788dd..b594fcb 100644
--- a/chromeos/network/network_configuration_handler.cc
+++ b/chromeos/network/network_configuration_handler.cc
@@ -19,9 +19,9 @@
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_device_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
diff --git a/chromeos/network/network_configuration_handler_unittest.cc b/chromeos/network/network_configuration_handler_unittest.cc
index 6578d9a..f32719b 100644
--- a/chromeos/network/network_configuration_handler_unittest.cc
+++ b/chromeos/network/network_configuration_handler_unittest.cc
@@ -19,8 +19,8 @@
 #include "base/strings/string_piece.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_shill_profile_client.h"
-#include "chromeos/dbus/fake_shill_service_client.h"
+#include "chromeos/dbus/shill/fake_shill_profile_client.h"
+#include "chromeos/dbus/shill/fake_shill_service_client.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_configuration_observer.h"
 #include "chromeos/network/network_profile_handler.h"
diff --git a/chromeos/network/network_connect_unittest.cc b/chromeos/network/network_connect_unittest.cc
index 285b4d3..fb4f2f7 100644
--- a/chromeos/network/network_connect_unittest.cc
+++ b/chromeos/network/network_connect_unittest.cc
@@ -11,8 +11,8 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/network_connect.h"
 #include "chromeos/network/network_connection_handler.h"
diff --git a/chromeos/network/network_connection_handler.cc b/chromeos/network/network_connection_handler.cc
index b5889cf6..4ee7ca1 100644
--- a/chromeos/network/network_connection_handler.cc
+++ b/chromeos/network/network_connection_handler.cc
@@ -12,8 +12,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/client_cert_resolver.h"
 #include "chromeos/network/client_cert_util.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
diff --git a/chromeos/network/network_connection_handler_impl.cc b/chromeos/network/network_connection_handler_impl.cc
index 9d3921e..6cc346eb 100644
--- a/chromeos/network/network_connection_handler_impl.cc
+++ b/chromeos/network/network_connection_handler_impl.cc
@@ -13,8 +13,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/client_cert_resolver.h"
 #include "chromeos/network/client_cert_util.h"
 #include "chromeos/network/device_state.h"
diff --git a/chromeos/network/network_device_handler_impl.cc b/chromeos/network/network_device_handler_impl.cc
index 63980bc6..84e8533d 100644
--- a/chromeos/network/network_device_handler_impl.cc
+++ b/chromeos/network/network_device_handler_impl.cc
@@ -22,8 +22,8 @@
 #include "base/time/time.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
 #include "chromeos/network/device_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "components/device_event_log/device_event_log.h"
diff --git a/chromeos/network/network_device_handler_unittest.cc b/chromeos/network/network_device_handler_unittest.cc
index b0935d8..aa7eafd 100644
--- a/chromeos/network/network_device_handler_unittest.cc
+++ b/chromeos/network/network_device_handler_unittest.cc
@@ -10,8 +10,8 @@
 #include "base/test/scoped_task_environment.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_shill_device_client.h"
-#include "chromeos/dbus/fake_shill_manager_client.h"
+#include "chromeos/dbus/shill/fake_shill_device_client.h"
+#include "chromeos/dbus/shill/fake_shill_manager_client.h"
 #include "chromeos/network/network_device_handler_impl.h"
 #include "chromeos/network/network_state_handler.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/network/network_profile_handler.cc b/chromeos/network/network_profile_handler.cc
index 8b4dc17..82713e72 100644
--- a/chromeos/network/network_profile_handler.cc
+++ b/chromeos/network/network_profile_handler.cc
@@ -12,8 +12,8 @@
 #include "base/strings/string_util.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
 #include "chromeos/network/network_profile_observer.h"
 #include "dbus/object_path.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/chromeos/network/network_profile_handler.h b/chromeos/network/network_profile_handler.h
index 46ba791..25c15335 100644
--- a/chromeos/network/network_profile_handler.h
+++ b/chromeos/network/network_profile_handler.h
@@ -15,7 +15,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_profile.h"
 
diff --git a/chromeos/network/network_sms_handler.cc b/chromeos/network/network_sms_handler.cc
index dfe7037..355e4b5 100644
--- a/chromeos/network/network_sms_handler.cc
+++ b/chromeos/network/network_sms_handler.cc
@@ -16,11 +16,11 @@
 #include "base/macros.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/gsm_sms_client.h"
-#include "chromeos/dbus/modem_messaging_client.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/sms_client.h"
+#include "chromeos/dbus/shill/gsm_sms_client.h"
+#include "chromeos/dbus/shill/modem_messaging_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/sms_client.h"
 #include "dbus/object_path.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
diff --git a/chromeos/network/network_sms_handler.h b/chromeos/network/network_sms_handler.h
index f47141bc..48203f5 100644
--- a/chromeos/network/network_sms_handler.h
+++ b/chromeos/network/network_sms_handler.h
@@ -14,7 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 
 namespace base {
 class DictionaryValue;
diff --git a/chromeos/network/network_sms_handler_unittest.cc b/chromeos/network/network_sms_handler_unittest.cc
index 883e915..d515c12e 100644
--- a/chromeos/network/network_sms_handler_unittest.cc
+++ b/chromeos/network/network_sms_handler_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
diff --git a/chromeos/network/network_state_handler_unittest.cc b/chromeos/network/network_state_handler_unittest.cc
index 2f09cdf..b816a33 100644
--- a/chromeos/network/network_state_handler_unittest.cc
+++ b/chromeos/network/network_state_handler_unittest.cc
@@ -22,11 +22,11 @@
 #include "base/values.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_ipconfig_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/device_state.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler_observer.h"
diff --git a/chromeos/network/network_state_test_helper.h b/chromeos/network/network_state_test_helper.h
index 068c42d0..0036865 100644
--- a/chromeos/network/network_state_test_helper.h
+++ b/chromeos/network/network_state_test_helper.h
@@ -9,10 +9,10 @@
 #include <string>
 
 #include "base/memory/weak_ptr.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_state_handler.h"
 
 namespace chromeos {
diff --git a/chromeos/network/policy_applicator.cc b/chromeos/network/policy_applicator.cc
index c9b4cf70..0f98682 100644
--- a/chromeos/network/policy_applicator.cc
+++ b/chromeos/network/policy_applicator.cc
@@ -13,7 +13,7 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
 #include "chromeos/network/network_type_pattern.h"
 #include "chromeos/network/network_ui_data.h"
 #include "chromeos/network/onc/onc_signature.h"
diff --git a/chromeos/network/proxy/proxy_config_handler.cc b/chromeos/network/proxy/proxy_config_handler.cc
index feb15214a..71b73545 100644
--- a/chromeos/network/proxy/proxy_config_handler.cc
+++ b/chromeos/network/proxy/proxy_config_handler.cc
@@ -12,7 +12,7 @@
 #include "base/logging.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_handler_callbacks.h"
 #include "chromeos/network/network_profile.h"
 #include "chromeos/network/network_profile_handler.h"
diff --git a/chromeos/network/proxy/ui_proxy_config_service_unittest.cc b/chromeos/network/proxy/ui_proxy_config_service_unittest.cc
index 836a01f..4339901 100644
--- a/chromeos/network/proxy/ui_proxy_config_service_unittest.cc
+++ b/chromeos/network/proxy/ui_proxy_config_service_unittest.cc
@@ -14,7 +14,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/onc/onc_utils.h"
 #include "components/onc/onc_pref_names.h"
diff --git a/chromeos/network/shill_property_handler.cc b/chromeos/network/shill_property_handler.cc
index 518686e2..4478a85 100644
--- a/chromeos/network/shill_property_handler.cc
+++ b/chromeos/network/shill_property_handler.cc
@@ -16,11 +16,11 @@
 #include "base/strings/string_util.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_ipconfig_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/network/network_state.h"
 #include "components/device_event_log/device_event_log.h"
 #include "dbus/object_path.h"
diff --git a/chromeos/network/shill_property_handler.h b/chromeos/network/shill_property_handler.h
index bdf6841e..057b756 100644
--- a/chromeos/network/shill_property_handler.h
+++ b/chromeos/network/shill_property_handler.h
@@ -14,7 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
-#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/dbus/shill/shill_property_changed_observer.h"
 #include "chromeos/network/managed_state.h"
 #include "chromeos/network/network_handler_callbacks.h"
 
diff --git a/chromeos/network/shill_property_handler_unittest.cc b/chromeos/network/shill_property_handler_unittest.cc
index a9f19bf..d4f77717 100644
--- a/chromeos/network/shill_property_handler_unittest.cc
+++ b/chromeos/network/shill_property_handler_unittest.cc
@@ -18,11 +18,11 @@
 #include "base/test/scoped_task_environment.h"
 #include "base/values.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_ipconfig_client.h"
-#include "chromeos/dbus/shill_manager_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_ipconfig_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "dbus/object_path.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/chromeos/tpm/BUILD.gn b/chromeos/tpm/BUILD.gn
index 6af9722..b83aea05 100644
--- a/chromeos/tpm/BUILD.gn
+++ b/chromeos/tpm/BUILD.gn
@@ -11,7 +11,6 @@
   deps = [
     "//base",
     "//chromeos/cryptohome",
-    "//chromeos/dbus",
     "//chromeos/dbus/constants",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:cryptohome_proto",
diff --git a/chromeos/tpm/install_attributes.cc b/chromeos/tpm/install_attributes.cc
index a12e575..26f629a 100644
--- a/chromeos/tpm/install_attributes.cc
+++ b/chromeos/tpm/install_attributes.cc
@@ -23,7 +23,6 @@
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "chromeos/dbus/cryptohome/tpm_util.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/policy/proto/install_attributes.pb.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
@@ -77,7 +76,6 @@
     return;
 
   DCHECK(!g_install_attributes);
-  DCHECK(DBusThreadManager::IsInitialized());
   g_install_attributes = new InstallAttributes(CryptohomeClient::Get());
   base::FilePath install_attrs_file;
   CHECK(base::PathService::Get(dbus_paths::FILE_INSTALL_ATTRIBUTES,
diff --git a/chromeos/tpm/tpm_password_fetcher.cc b/chromeos/tpm/tpm_password_fetcher.cc
index a6e5c30..1310a84 100644
--- a/chromeos/tpm/tpm_password_fetcher.cc
+++ b/chromeos/tpm/tpm_password_fetcher.cc
@@ -10,7 +10,6 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 
 namespace chromeos {
 
diff --git a/chromeos/tpm/tpm_token_loader.cc b/chromeos/tpm/tpm_token_loader.cc
index c4675e5..f932f0a0 100644
--- a/chromeos/tpm/tpm_token_loader.cc
+++ b/chromeos/tpm/tpm_token_loader.cc
@@ -13,7 +13,6 @@
 #include "base/system/sys_info.h"
 #include "base/task_runner_util.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/tpm/tpm_token_info_getter.h"
 #include "crypto/nss_util.h"
 
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index 7520b5a6..30f959cc 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -85,9 +85,10 @@
     "//chromeos/audio",
     "//chromeos/constants",
     "//chromeos/dbus",
-    "//chromeos/dbus:login_manager_proto",
     "//chromeos/dbus:power_manager_proto",
     "//chromeos/dbus/cryptohome",
+    "//chromeos/dbus/session_manager",
+    "//chromeos/dbus/session_manager:login_manager_proto",
     "//chromeos/disks",
     "//chromeos/login/login_state",
     "//chromeos/network",
@@ -167,7 +168,7 @@
     "//ash/public/cpp",
     "//base",
     "//chromeos/constants",
-    "//chromeos/dbus",
+    "//chromeos/dbus/session_manager",
     "//ui/aura",
   ]
 }
@@ -206,8 +207,10 @@
     "//base",
     "//chromeos/constants",
     "//chromeos/cryptohome",
-    "//chromeos/dbus",
-    "//chromeos/dbus:login_manager_proto",
+    "//chromeos/dbus:common",
+    "//chromeos/dbus/session_manager",
+    "//chromeos/dbus/session_manager:login_manager_proto",
+    "//chromeos/dbus/upstart",
     "//components/account_id",
     "//components/keyed_service/content",
     "//components/prefs",
@@ -350,6 +353,9 @@
     "//chromeos/cryptohome:test_support",
     "//chromeos/dbus:power_manager_proto",
     "//chromeos/dbus:test_support",
+    "//chromeos/dbus/session_manager",
+    "//chromeos/dbus/session_manager:login_manager_proto",
+    "//chromeos/dbus/upstart",
     "//chromeos/disks:test_support",
     "//chromeos/network:test_support",
     "//components/account_id",
diff --git a/components/arc/arc_prefs.cc b/components/arc/arc_prefs.cc
index cdf8e1c..c4ccb080 100644
--- a/components/arc/arc_prefs.cc
+++ b/components/arc/arc_prefs.cc
@@ -194,7 +194,7 @@
   registry->RegisterTimeDeltaPref(kEngagementTimeTotal, base::TimeDelta());
   registry->RegisterBooleanPref(kVoiceInteractionContextEnabled, false);
   registry->RegisterBooleanPref(kVoiceInteractionEnabled, false);
-  registry->RegisterBooleanPref(kVoiceInteractionHotwordAlwaysOn, true);
+  registry->RegisterBooleanPref(kVoiceInteractionHotwordAlwaysOn, false);
   registry->RegisterBooleanPref(kVoiceInteractionHotwordEnabled, false);
   registry->RegisterBooleanPref(kVoiceInteractionNotificationEnabled, true);
   registry->RegisterBooleanPref(kVoiceInteractionLaunchWithMicOpen, false);
diff --git a/components/arc/arc_util.cc b/components/arc/arc_util.cc
index cfc3107..62f9833 100644
--- a/components/arc/arc_util.cc
+++ b/components/arc/arc_util.cc
@@ -12,7 +12,6 @@
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/arc/arc_features.h"
 #include "components/user_manager/user_manager.h"
@@ -179,16 +178,14 @@
 }
 
 void SetArcCpuRestriction(bool do_restrict) {
-  chromeos::SessionManagerClient* session_manager_client =
-      chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
-  if (!session_manager_client) {
+  if (!chromeos::SessionManagerClient::Get()) {
     LOG(WARNING) << "SessionManagerClient is not available";
     return;
   }
   const login_manager::ContainerCpuRestrictionState state =
       do_restrict ? login_manager::CONTAINER_CPU_RESTRICTION_BACKGROUND
                   : login_manager::CONTAINER_CPU_RESTRICTION_FOREGROUND;
-  session_manager_client->SetArcCpuRestriction(
+  chromeos::SessionManagerClient::Get()->SetArcCpuRestriction(
       state, base::BindOnce(SetArcCpuRestrictionCallback, state));
 }
 
diff --git a/components/arc/common/file_system.mojom b/components/arc/common/file_system.mojom
index c667839..01651c6 100644
--- a/components/arc/common/file_system.mojom
+++ b/components/arc/common/file_system.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Next MinVersion: 13
+// Next MinVersion: 14
 
 module arc.mojom;
 
@@ -257,7 +257,7 @@
       (FileSelectorElements elements);
 };
 
-// Next method ID: 18
+// Next method ID: 19
 interface FileSystemInstance {
   // Notes about Android Documents Provider:
   //
@@ -370,6 +370,10 @@
   // URL.
   [MinVersion=1] OpenFileToRead@2(string url) => (handle? fd);
 
+  // Asks the ContentResolver to get a FD to write the file specified by the
+  // URL.
+  [MinVersion=13] OpenFileToWrite@18(string url) => (handle? fd);
+
   // Uninstalls a document watcher.
   //
   // After this method call returns, OnDocumentChanged() will never be called
diff --git a/components/arc/common/notifications.mojom b/components/arc/common/notifications.mojom
index 7d906321..85f6ee8 100644
--- a/components/arc/common/notifications.mojom
+++ b/components/arc/common/notifications.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Next MinVersion: 23
+// Next MinVersion: 24
 
 module arc.mojom;
 
@@ -158,6 +158,8 @@
   bool hidden_on_lock_screen;
   [MinVersion=21]
   ArcBitmap? snapshot_image_public;
+  [MinVersion=23]
+  bool is_media_notification;
 };
 
 [MinVersion=18]
diff --git a/components/arc/metrics/arc_metrics_service.cc b/components/arc/metrics/arc_metrics_service.cc
index b2b73b4..6c2c1c04 100644
--- a/components/arc/metrics/arc_metrics_service.cc
+++ b/components/arc/metrics/arc_metrics_service.cc
@@ -16,7 +16,6 @@
 #include "base/system/sys_info.h"
 #include "base/time/default_clock.h"
 #include "base/time/default_tick_clock.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
@@ -292,9 +291,7 @@
   }
 
   // Retrieve ARC full container's start time from session manager.
-  chromeos::SessionManagerClient* session_manager_client =
-      chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
-  session_manager_client->GetArcStartTime(base::BindOnce(
+  chromeos::SessionManagerClient::Get()->GetArcStartTime(base::BindOnce(
       &ArcMetricsService::OnArcStartTimeRetrieved,
       weak_ptr_factory_.GetWeakPtr(), std::move(events), boot_type));
 }
diff --git a/components/arc/metrics/arc_metrics_service_unittest.cc b/components/arc/metrics/arc_metrics_service_unittest.cc
index 5a4fc58d..dd91dfb 100644
--- a/components/arc/metrics/arc_metrics_service_unittest.cc
+++ b/components/arc/metrics/arc_metrics_service_unittest.cc
@@ -116,27 +116,17 @@
   DISALLOW_COPY_AND_ASSIGN(FakeTickClock);
 };
 
-// Helper class that initializes DBusThreadManager for testing, and ensures the
-// lifetime of DBusThreadManager.
+// Helper class that initializes and shuts down dbus clients for testing.
 class DBusThreadManagerLifetimeHelper {
  public:
   DBusThreadManagerLifetimeHelper() {
-    // Get DBusThreadManagerSetter for setting fake DBusThreadManager clients.
-    // This also initializes the global DBusThreadManager instance.
-    std::unique_ptr<chromeos::DBusThreadManagerSetter>
-        dbus_thread_manager_setter =
-            chromeos::DBusThreadManager::GetSetterForTesting();
-
-    // Set fake clients for testing.
-    dbus_thread_manager_setter->SetSessionManagerClient(
-        std::make_unique<chromeos::FakeSessionManagerClient>());
     chromeos::PowerManagerClient::InitializeFake();
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
   }
 
   ~DBusThreadManagerLifetimeHelper() {
+    chromeos::SessionManagerClient::Shutdown();
     chromeos::PowerManagerClient::Shutdown();
-    // Destroy the global DBusThreadManager instance.
-    chromeos::DBusThreadManager::Shutdown();
   }
 };
 
@@ -184,7 +174,7 @@
       : arc_service_manager_(std::make_unique<ArcServiceManager>()),
         context_(std::make_unique<TestBrowserContext>()),
         service_(CreateArcMetricsService(context_.get())) {
-    GetSessionManagerClient()->set_arc_available(true);
+    chromeos::FakeSessionManagerClient::Get()->set_arc_available(true);
 
     auto fake_arc_window_delegate = std::make_unique<FakeArcWindowDelegate>();
     fake_arc_window_delegate_ = fake_arc_window_delegate.get();
@@ -205,7 +195,8 @@
     const base::TimeTicks arc_start_time =
         base::TimeDelta::FromMilliseconds(arc_start_time_in_ms) +
         base::TimeTicks();
-    GetSessionManagerClient()->set_arc_start_time(arc_start_time);
+    chromeos::FakeSessionManagerClient::Get()->set_arc_start_time(
+        arc_start_time);
   }
 
   std::vector<mojom::BootProgressEventPtr> GetBootProgressEvents(
@@ -244,11 +235,6 @@
   FakeTickClock* fake_tick_clock() { return &fake_tick_clock_; }
 
  private:
-  chromeos::FakeSessionManagerClient* GetSessionManagerClient() {
-    return static_cast<chromeos::FakeSessionManagerClient*>(
-        chromeos::DBusThreadManager::Get()->GetSessionManagerClient());
-  }
-
   chromeos::FakePowerManagerClient* GetPowerManagerClient() {
     return static_cast<chromeos::FakePowerManagerClient*>(
         chromeos::PowerManagerClient::Get());
diff --git a/components/arc/net/always_on_vpn_manager_unittest.cc b/components/arc/net/always_on_vpn_manager_unittest.cc
index 3011903..d18bf1c 100644
--- a/components/arc/net/always_on_vpn_manager_unittest.cc
+++ b/components/arc/net/always_on_vpn_manager_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/values.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/network_handler.h"
 #include "components/arc/arc_prefs.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/components/arc/session/arc_container_client_adapter.cc b/components/arc/session/arc_container_client_adapter.cc
index a24f753d..2bed3ba 100644
--- a/components/arc/session/arc_container_client_adapter.cc
+++ b/components/arc/session/arc_container_client_adapter.cc
@@ -10,61 +10,43 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/login_manager/arc.pb.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 
 namespace arc {
 
-namespace {
-
-chromeos::SessionManagerClient* GetSessionManagerClient() {
-  // If the DBusThreadManager or the SessionManagerClient aren't available,
-  // there isn't much we can do. This should only happen when running tests.
-  if (!chromeos::DBusThreadManager::IsInitialized() ||
-      !chromeos::DBusThreadManager::Get() ||
-      !chromeos::DBusThreadManager::Get()->GetSessionManagerClient()) {
-    return nullptr;
-  }
-  return chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
-}
-
-}  // namespace
-
 class ArcContainerClientAdapter
     : public ArcClientAdapter,
       public chromeos::SessionManagerClient::Observer {
  public:
   ArcContainerClientAdapter() {
-    chromeos::SessionManagerClient* client = GetSessionManagerClient();
-    if (client)
-      client->AddObserver(this);
+    if (chromeos::SessionManagerClient::Get())
+      chromeos::SessionManagerClient::Get()->AddObserver(this);
   }
 
   ~ArcContainerClientAdapter() override {
-    chromeos::SessionManagerClient* client = GetSessionManagerClient();
-    if (client)
-      client->RemoveObserver(this);
+    if (chromeos::SessionManagerClient::Get())
+      chromeos::SessionManagerClient::Get()->RemoveObserver(this);
   }
 
   // ArcClientAdapter overrides:
   void StartMiniArc(const StartArcMiniContainerRequest& request,
                     StartMiniArcCallback callback) override {
-    GetSessionManagerClient()->StartArcMiniContainer(request,
-                                                     std::move(callback));
+    chromeos::SessionManagerClient::Get()->StartArcMiniContainer(
+        request, std::move(callback));
   }
 
   void UpgradeArc(const UpgradeArcContainerRequest& request,
                   base::OnceClosure success_callback,
                   UpgradeErrorCallback error_callback) override {
-    GetSessionManagerClient()->UpgradeArcContainer(
+    chromeos::SessionManagerClient::Get()->UpgradeArcContainer(
         request, std::move(success_callback), std::move(error_callback));
   }
 
   void StopArcInstance() override {
     // Since we have the ArcInstanceStopped() callback, we don't need to do
     // anything when StopArcInstance completes.
-    GetSessionManagerClient()->StopArcInstance(
+    chromeos::SessionManagerClient::Get()->StopArcInstance(
         chromeos::EmptyVoidDBusMethodCallback());
   }
 
diff --git a/components/arc/session/arc_session_impl_unittest.cc b/components/arc/session/arc_session_impl_unittest.cc
index c758a51..e3536d4 100644
--- a/components/arc/session/arc_session_impl_unittest.cc
+++ b/components/arc/session/arc_session_impl_unittest.cc
@@ -16,7 +16,6 @@
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
 #include "components/account_id/account_id.h"
 #include "components/arc/session/arc_session_impl.h"
@@ -168,10 +167,6 @@
 class ArcSessionImplTest : public testing::Test {
  public:
   ArcSessionImplTest() {
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::make_unique<chromeos::FakeSessionManagerClient>());
-    GetSessionManagerClient()->set_arc_available(true);
-
     // Create a user and set it as the primary user.
     const AccountId account_id =
         AccountId::FromUserEmailGaiaId(kFakeGmail, kFakeGmailGaiaId);
@@ -184,21 +179,22 @@
   ~ArcSessionImplTest() override {
     GetUserManager()->RemoveUserFromList(
         AccountId::FromUserEmailGaiaId(kFakeGmail, kFakeGmailGaiaId));
-    chromeos::DBusThreadManager::Shutdown();
   }
 
-  chromeos::FakeSessionManagerClient* GetSessionManagerClient() {
-    return static_cast<chromeos::FakeSessionManagerClient*>(
-        chromeos::DBusThreadManager::Get()->GetSessionManagerClient());
+  void SetUp() override {
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
+    chromeos::FakeSessionManagerClient::Get()->set_arc_available(true);
   }
 
+  void TearDown() override { chromeos::SessionManagerClient::Shutdown(); }
+
   user_manager::FakeUserManager* GetUserManager() {
     return static_cast<user_manager::FakeUserManager*>(
         user_manager::UserManager::Get());
   }
 
   void EmulateDBusFailure() {
-    GetSessionManagerClient()->set_arc_available(false);
+    chromeos::FakeSessionManagerClient::Get()->set_arc_available(false);
   }
 
   std::unique_ptr<ArcSessionImpl, ArcSessionDeleter> CreateArcSession(
@@ -261,7 +257,7 @@
 // causing the container upgrade to fail to start container with reason
 // LOW_DISK_SPACE.
 TEST_F(ArcSessionImplTest, Upgrade_LowDisk) {
-  GetSessionManagerClient()->set_low_disk(true);
+  chromeos::FakeSessionManagerClient::Get()->set_low_disk(true);
   // Set up. Start mini-container. The mini-container doesn't use the disk, so
   // there being low disk space won't cause it to start.
   auto arc_session = CreateArcSession();
@@ -551,10 +547,9 @@
             arc_session->GetStateForTesting());
 
   // Deliver the ArcInstanceStopped D-Bus signal.
-  auto* session_manager_client = GetSessionManagerClient();
-  session_manager_client->NotifyArcInstanceStopped(
+  chromeos::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped(
       login_manager::ArcContainerStopReason::CRASH,
-      session_manager_client->container_instance_id());
+      chromeos::FakeSessionManagerClient::Get()->container_instance_id());
 
   EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
   ASSERT_TRUE(observer.on_session_stopped_args().has_value());
@@ -575,8 +570,7 @@
             arc_session->GetStateForTesting());
 
   // Deliver the ArcInstanceStopped D-Bus signal.
-  auto* session_manager_client = GetSessionManagerClient();
-  session_manager_client->NotifyArcInstanceStopped(
+  chromeos::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped(
       login_manager::ArcContainerStopReason::CRASH, "dummy instance id");
 
   // The signal should be ignored.
@@ -627,9 +621,10 @@
   if (state.full_container)
     arc_session->RequestUpgrade(DefaultUpgradeParams());
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(state.expected_packages_cache_mode, GetSessionManagerClient()
-                                                    ->last_upgrade_arc_request()
-                                                    .packages_cache_mode());
+  EXPECT_EQ(state.expected_packages_cache_mode,
+            chromeos::FakeSessionManagerClient::Get()
+                ->last_upgrade_arc_request()
+                .packages_cache_mode());
 }
 
 INSTANTIATE_TEST_SUITE_P(,
@@ -649,9 +644,10 @@
   arc_session->RequestUpgrade(std::move(params));
 
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(
-      GetSessionManagerClient()->last_upgrade_arc_request().is_demo_session());
-  EXPECT_EQ(demo_apps_path, GetSessionManagerClient()
+  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
+                  ->last_upgrade_arc_request()
+                  .is_demo_session());
+  EXPECT_EQ(demo_apps_path, chromeos::FakeSessionManagerClient::Get()
                                 ->last_upgrade_arc_request()
                                 .demo_session_apps_path());
 }
@@ -666,9 +662,10 @@
   arc_session->RequestUpgrade(std::move(params));
 
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(
-      GetSessionManagerClient()->last_upgrade_arc_request().is_demo_session());
-  EXPECT_EQ(std::string(), GetSessionManagerClient()
+  EXPECT_TRUE(chromeos::FakeSessionManagerClient::Get()
+                  ->last_upgrade_arc_request()
+                  .is_demo_session());
+  EXPECT_EQ(std::string(), chromeos::FakeSessionManagerClient::Get()
                                ->last_upgrade_arc_request()
                                .demo_session_apps_path());
 }
@@ -686,10 +683,10 @@
   EXPECT_EQ(
       login_manager::
           UpgradeArcContainerRequest_SupervisionTransition_CHILD_TO_REGULAR,
-      GetSessionManagerClient()
+      chromeos::FakeSessionManagerClient::Get()
           ->last_upgrade_arc_request()
           .supervision_transition());
-  EXPECT_EQ(160, GetSessionManagerClient()
+  EXPECT_EQ(160, chromeos::FakeSessionManagerClient::Get()
                      ->last_start_arc_mini_container_request()
                      .lcd_density());
 }
@@ -701,7 +698,7 @@
 
   EXPECT_EQ(ArcSessionImpl::State::RUNNING_MINI_INSTANCE,
             arc_session->GetStateForTesting());
-  EXPECT_EQ(240, GetSessionManagerClient()
+  EXPECT_EQ(240, chromeos::FakeSessionManagerClient::Get()
                      ->last_start_arc_mini_container_request()
                      .lcd_density());
 }
@@ -718,7 +715,7 @@
             arc_session->GetStateForTesting());
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(240, GetSessionManagerClient()
+  EXPECT_EQ(240, chromeos::FakeSessionManagerClient::Get()
                      ->last_start_arc_mini_container_request()
                      .lcd_density());
 }
diff --git a/components/arc/session/arc_session_runner_unittest.cc b/components/arc/session/arc_session_runner_unittest.cc
index ae78698..dcea0d3 100644
--- a/components/arc/session/arc_session_runner_unittest.cc
+++ b/components/arc/session/arc_session_runner_unittest.cc
@@ -14,8 +14,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_task_environment.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/arc/arc_util.h"
 #include "components/arc/session/arc_session_runner.h"
 #include "components/arc/test/fake_arc_session.h"
@@ -61,9 +60,7 @@
             base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
 
   void SetUp() override {
-    chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::make_unique<chromeos::FakeSessionManagerClient>());
-    chromeos::DBusThreadManager::Initialize();
+    chromeos::SessionManagerClient::InitializeFakeInMemory();
 
     stop_reason_ = ArcStopReason::SHUTDOWN;
     restarting_ = false;
@@ -80,7 +77,7 @@
     arc_session_runner_->RemoveObserver(this);
     arc_session_runner_.reset();
 
-    chromeos::DBusThreadManager::Shutdown();
+    chromeos::SessionManagerClient::Shutdown();
   }
 
   ArcSessionRunner* arc_session_runner() { return arc_session_runner_.get(); }
diff --git a/components/arc/test/fake_file_system_instance.cc b/components/arc/test/fake_file_system_instance.cc
index ea3dad01..aaaf91e 100644
--- a/components/arc/test/fake_file_system_instance.cc
+++ b/components/arc/test/fake_file_system_instance.cc
@@ -7,6 +7,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <limits>
 #include <sstream>
 #include <utility>
 
@@ -26,30 +27,6 @@
 
 namespace {
 
-base::ScopedFD CreateRegularFileDescriptor(const std::string& content,
-                                           const base::FilePath& temp_dir) {
-  base::FilePath path;
-  bool create_success = base::CreateTemporaryFileInDir(temp_dir, &path);
-  DCHECK(create_success);
-  int written_size = base::WriteFile(path, content.data(), content.size());
-  DCHECK_EQ(static_cast<int>(content.size()), written_size);
-  base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
-  DCHECK(file.IsValid());
-  return base::ScopedFD(file.TakePlatformFile());
-}
-
-base::ScopedFD CreateStreamFileDescriptor(const std::string& content) {
-  int fds[2];
-  int ret = pipe(fds);
-  DCHECK_EQ(0, ret);
-  base::ScopedFD fd_read(fds[0]);
-  base::ScopedFD fd_write(fds[1]);
-  bool write_success =
-      base::WriteFileDescriptor(fd_write.get(), content.data(), content.size());
-  DCHECK(write_success);
-  return fd_read;
-}
-
 mojom::DocumentPtr MakeDocument(const FakeFileSystemInstance::Document& doc) {
   mojom::DocumentPtr document = mojom::Document::New();
   document->document_id = doc.document_id;
@@ -77,6 +54,9 @@
   return ss.str();
 }
 
+// Maximum size in bytes to read FD from PIPE.
+constexpr size_t kMaxBytesToReadFromPipe = 8 * 1024;  // 8KB;
+
 }  // namespace
 
 FakeFileSystemInstance::File::File(const std::string& url,
@@ -223,6 +203,39 @@
   return GetDocument(authority, document_id);
 }
 
+std::string FakeFileSystemInstance::GetFileContent(const std::string& url) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  return GetFileContent(url, std::numeric_limits<size_t>::max());
+}
+
+std::string FakeFileSystemInstance::GetFileContent(const std::string& url,
+                                                   size_t bytes) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  auto regular_file_paths_it = regular_file_paths_.find(url);
+  if (regular_file_paths_it != regular_file_paths_.end()) {
+    base::FilePath path = regular_file_paths_it->second;
+    std::string content;
+    if (base::ReadFileToStringWithMaxSize(path, &content, bytes))
+      return content;
+  } else {
+    auto pipe_read_ends_it = pipe_read_ends_.find(url);
+    if (pipe_read_ends_it != pipe_read_ends_.end()) {
+      if (bytes > kMaxBytesToReadFromPipe) {
+        LOG(ERROR) << "Trying to read too many bytes from pipe. " << url;
+        return std::string();
+      }
+      std::string result;
+      result.resize(bytes);
+      bool success =
+          base::ReadFromFD(pipe_read_ends_it->second.get(), &result[0], bytes);
+      DCHECK(success);
+      return result;
+    }
+  }
+  LOG(ERROR) << "A file to read content not found. " << url;
+  return std::string();
+}
+
 void FakeFileSystemInstance::AddWatcher(const std::string& authority,
                                         const std::string& document_id,
                                         AddWatcherCallback callback) {
@@ -281,8 +294,32 @@
   const File& file = iter->second;
   base::ScopedFD fd =
       file.seekable == File::Seekable::YES
-          ? CreateRegularFileDescriptor(file.content, temp_dir_.GetPath())
-          : CreateStreamFileDescriptor(file.content);
+          ? CreateRegularFileDescriptor(file, base::File::Flags::FLAG_OPEN |
+                                                  base::File::Flags::FLAG_READ)
+          : CreateStreamFileDescriptorToRead(file.content);
+  mojo::ScopedHandle wrapped_handle =
+      mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(fd)));
+  DCHECK(wrapped_handle.is_valid());
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(std::move(callback), std::move(wrapped_handle)));
+}
+
+void FakeFileSystemInstance::OpenFileToWrite(const std::string& url,
+                                             OpenFileToWriteCallback callback) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  auto iter = files_.find(url);
+  if (iter == files_.end()) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), mojo::ScopedHandle()));
+    return;
+  }
+  const File& file = iter->second;
+  base::ScopedFD fd =
+      file.seekable == File::Seekable::YES
+          ? CreateRegularFileDescriptor(file, base::File::Flags::FLAG_OPEN |
+                                                  base::File::Flags::FLAG_WRITE)
+          : CreateStreamFileDescriptorToWrite(file.url);
   mojo::ScopedHandle wrapped_handle =
       mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(fd)));
   DCHECK(wrapped_handle.is_valid());
@@ -515,4 +552,46 @@
   return std::string();
 }
 
+base::ScopedFD FakeFileSystemInstance::CreateRegularFileDescriptor(
+    const File& file,
+    uint32_t flags) {
+  if (regular_file_paths_.find(file.url) == regular_file_paths_.end()) {
+    base::FilePath path;
+    bool create_success =
+        base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &path);
+    DCHECK(create_success);
+    int written_size =
+        base::WriteFile(path, file.content.data(), file.content.size());
+    DCHECK_EQ(static_cast<int>(file.content.size()), written_size);
+    regular_file_paths_[file.url] = path;
+  }
+  base::File regular_file(regular_file_paths_[file.url], flags);
+  DCHECK(regular_file.IsValid());
+  return base::ScopedFD(regular_file.TakePlatformFile());
+}
+
+base::ScopedFD FakeFileSystemInstance::CreateStreamFileDescriptorToRead(
+    const std::string& content) {
+  int fds[2];
+  int ret = pipe(fds);
+  DCHECK_EQ(0, ret);
+  base::ScopedFD fd_read(fds[0]);
+  base::ScopedFD fd_write(fds[1]);
+  bool write_success =
+      base::WriteFileDescriptor(fd_write.get(), content.data(), content.size());
+  DCHECK(write_success);
+  return fd_read;
+}
+
+base::ScopedFD FakeFileSystemInstance::CreateStreamFileDescriptorToWrite(
+    const std::string& url) {
+  int fds[2];
+  int ret = pipe(fds);
+  DCHECK_EQ(0, ret);
+  base::ScopedFD fd_read(fds[0]);
+  base::ScopedFD fd_write(fds[1]);
+  pipe_read_ends_.emplace(url, std::move(fd_read));
+  return fd_write;
+}
+
 }  // namespace arc
diff --git a/components/arc/test/fake_file_system_instance.h b/components/arc/test/fake_file_system_instance.h
index 9991869..788156d 100644
--- a/components/arc/test/fake_file_system_instance.h
+++ b/components/arc/test/fake_file_system_instance.h
@@ -31,6 +31,7 @@
 // - GetFileSize()
 // - GetMimeType()
 // - OpenFileToRead()
+// - OpenFileToWrite()
 // Fake files for those functions can be set up by AddFile().
 //
 // Documents provider based functions are:
@@ -46,6 +47,8 @@
 //   added with AddDocument().
 // - GetRecentDocuments() returns recent documents in the same order as they
 //   were added with AddRecentDocument().
+// - OpenFileToRead() and OpenFileToWrite() will fail unless AddFile() for the
+//   file to open is called beforehand.
 // - Callbacks are never invoked synchronously.
 // - All member functions must be called on the same thread.
 class FakeFileSystemInstance : public mojom::FileSystemInstance {
@@ -60,7 +63,10 @@
     // Content URL of a file.
     std::string url;
 
-    // The content of a file.
+    // The content of a file, which can be read by OpenFileToRead().
+    // When Seekable.NO is specified and OpenFileToWrite() is called, this
+    // |content| will be ignored and bytes written to FD from OpenFileToWrite()
+    // will be read by OpenFileToRead().
     std::string content;
 
     // The MIME type of a file.
@@ -184,6 +190,13 @@
                        const std::string& document_id,
                        const base::FilePath& path);
 
+  // Returns the content written to the FD returned by OpenFileToWrite().
+  std::string GetFileContent(const std::string& url);
+
+  // Returns the content written to the FD returned by OpenFileToWrite(), up to
+  // |bytes| bytes.
+  std::string GetFileContent(const std::string& url, size_t bytes);
+
   // mojom::FileSystemInstance:
   void AddWatcher(const std::string& authority,
                   const std::string& document_id,
@@ -227,6 +240,8 @@
   void Init(mojom::FileSystemHostPtr host, InitCallback callback) override;
   void OpenFileToRead(const std::string& url,
                       OpenFileToReadCallback callback) override;
+  void OpenFileToWrite(const std::string& url,
+                       OpenFileToWriteCallback callback) override;
   void RemoveWatcher(int64_t watcher_id,
                      RemoveWatcherCallback callback) override;
   void RequestMediaScan(const std::vector<std::string>& paths) override;
@@ -248,6 +263,17 @@
                                   const std::string& parent_document_id,
                                   const std::vector<std::string>& components);
 
+  // Creates a regular file with the given flags and returns its fd.
+  base::ScopedFD CreateRegularFileDescriptor(const File& file, uint32_t flags);
+
+  // Returns a FD to non-seekable file to read. |content| content will be
+  // returned when reading the FD.
+  base::ScopedFD CreateStreamFileDescriptorToRead(const std::string& content);
+
+  // Returns a FD to non-seekable file to write. Bytes written to the FD can be
+  // read by calling GetFileContent() with the passed |url|.
+  base::ScopedFD CreateStreamFileDescriptorToWrite(const std::string& url);
+
   THREAD_CHECKER(thread_checker_);
 
   base::ScopedTempDir temp_dir_;
@@ -257,6 +283,14 @@
   // Mapping from a content URL to a file.
   std::map<std::string, File> files_;
 
+  // Mapping from a content URL to a file path of a created regular file.
+  std::map<std::string, base::FilePath> regular_file_paths_;
+
+  // Mapping from a content URL to a read end of a pipe.
+  // The corresponding write end should have been returned from
+  // OpenFileToWrite() on non-seekable file entry.
+  std::map<std::string, base::ScopedFD> pipe_read_ends_;
+
   // Mapping from a document key to a document.
   std::map<DocumentKey, Document> documents_;
 
diff --git a/components/autofill/core/browser/address_contact_form_label_formatter.cc b/components/autofill/core/browser/address_contact_form_label_formatter.cc
index b74e75a..13036f9 100644
--- a/components/autofill/core/browser/address_contact_form_label_formatter.cc
+++ b/components/autofill/core/browser/address_contact_form_label_formatter.cc
@@ -17,12 +17,12 @@
 
 AddressContactFormLabelFormatter::~AddressContactFormLabelFormatter() {}
 
-base::string16 AddressContactFormLabelFormatter::GetLabelForFocusedGroup(
+base::string16 AddressContactFormLabelFormatter::GetLabelForProfile(
     const AutofillProfile& profile,
-    FieldTypeGroup group) const {
-  return group == NAME || group == ADDRESS_HOME
-             ? GetLabelForProfileOnFocusedNameOrAddress(profile, group)
-             : GetLabelForProfileOnFocusedPhoneOrEmail(profile, group);
+    FieldTypeGroup focused_group) const {
+  return focused_group == NAME || focused_group == ADDRESS_HOME
+             ? GetLabelForProfileOnFocusedNameOrAddress(profile, focused_group)
+             : GetLabelForProfileOnFocusedPhoneOrEmail(profile, focused_group);
 }
 
 // Note that the order in which parts of the label are added--national address
diff --git a/components/autofill/core/browser/address_contact_form_label_formatter.h b/components/autofill/core/browser/address_contact_form_label_formatter.h
index 958eba3..d2fc7e3 100644
--- a/components/autofill/core/browser/address_contact_form_label_formatter.h
+++ b/components/autofill/core/browser/address_contact_form_label_formatter.h
@@ -26,8 +26,9 @@
 
   ~AddressContactFormLabelFormatter() override;
 
-  base::string16 GetLabelForFocusedGroup(const AutofillProfile& profile,
-                                         FieldTypeGroup group) const override;
+  base::string16 GetLabelForProfile(
+      const AutofillProfile& profile,
+      FieldTypeGroup focused_group) const override;
 
  private:
   // Returns a label to show the user when |focused_field_type_| belongs to the
diff --git a/components/autofill/core/browser/address_email_form_label_formatter.cc b/components/autofill/core/browser/address_email_form_label_formatter.cc
index ff02da3..9e831633 100644
--- a/components/autofill/core/browser/address_email_form_label_formatter.cc
+++ b/components/autofill/core/browser/address_email_form_label_formatter.cc
@@ -20,23 +20,23 @@
 // Note that the order--name, address, and email--in which parts of the label
 // are added ensures that the label is formatted correctly for |group| and for
 // this kind of formatter.
-base::string16 AddressEmailFormLabelFormatter::GetLabelForFocusedGroup(
+base::string16 AddressEmailFormLabelFormatter::GetLabelForProfile(
     const AutofillProfile& profile,
-    FieldTypeGroup group) const {
+    FieldTypeGroup focused_group) const {
   std::vector<base::string16> label_parts;
 
-  if (group != NAME) {
+  if (focused_group != NAME) {
     AddLabelPartIfNotEmpty(GetLabelName(profile, app_locale()), &label_parts);
   }
 
-  if (group != ADDRESS_HOME) {
+  if (focused_group != ADDRESS_HOME) {
     AddLabelPartIfNotEmpty(
         GetLabelAddress(form_has_street_address_, profile, app_locale(),
                         field_types_for_labels()),
         &label_parts);
   }
 
-  if (group != EMAIL) {
+  if (focused_group != EMAIL) {
     AddLabelPartIfNotEmpty(GetLabelEmail(profile, app_locale()), &label_parts);
   }
 
diff --git a/components/autofill/core/browser/address_email_form_label_formatter.h b/components/autofill/core/browser/address_email_form_label_formatter.h
index d025264..e6b3a50 100644
--- a/components/autofill/core/browser/address_email_form_label_formatter.h
+++ b/components/autofill/core/browser/address_email_form_label_formatter.h
@@ -26,8 +26,9 @@
 
   ~AddressEmailFormLabelFormatter() override;
 
-  base::string16 GetLabelForFocusedGroup(const AutofillProfile& profile,
-                                         FieldTypeGroup group) const override;
+  base::string16 GetLabelForProfile(
+      const AutofillProfile& profile,
+      FieldTypeGroup focused_group) const override;
 
  private:
   // True if this formatter's associated form has a street address field. A
diff --git a/components/autofill/core/browser/address_form_label_formatter.cc b/components/autofill/core/browser/address_form_label_formatter.cc
index f6a0a9f..a3b9786 100644
--- a/components/autofill/core/browser/address_form_label_formatter.cc
+++ b/components/autofill/core/browser/address_form_label_formatter.cc
@@ -17,10 +17,10 @@
 
 AddressFormLabelFormatter::~AddressFormLabelFormatter() {}
 
-base::string16 AddressFormLabelFormatter::GetLabelForFocusedGroup(
+base::string16 AddressFormLabelFormatter::GetLabelForProfile(
     const AutofillProfile& profile,
-    FieldTypeGroup group) const {
-  if (group != ADDRESS_HOME) {
+    FieldTypeGroup focused_group) const {
+  if (focused_group != ADDRESS_HOME) {
     return GetLabelNationalAddress(profile, app_locale(),
                                    field_types_for_labels());
   } else {
diff --git a/components/autofill/core/browser/address_form_label_formatter.h b/components/autofill/core/browser/address_form_label_formatter.h
index 35c6e28b..e477dfe 100644
--- a/components/autofill/core/browser/address_form_label_formatter.h
+++ b/components/autofill/core/browser/address_form_label_formatter.h
@@ -25,8 +25,9 @@
 
   ~AddressFormLabelFormatter() override;
 
-  base::string16 GetLabelForFocusedGroup(const AutofillProfile& profile,
-                                         FieldTypeGroup group) const override;
+  base::string16 GetLabelForProfile(
+      const AutofillProfile& profile,
+      FieldTypeGroup focused_group) const override;
 
  private:
   // True if this formatter's associated form has a street address field. A
diff --git a/components/autofill/core/browser/address_phone_form_label_formatter.cc b/components/autofill/core/browser/address_phone_form_label_formatter.cc
index 48baef2a..80438e40 100644
--- a/components/autofill/core/browser/address_phone_form_label_formatter.cc
+++ b/components/autofill/core/browser/address_phone_form_label_formatter.cc
@@ -20,20 +20,20 @@
 // Note that the order--phone, name, and address--in which parts of the label
 // are added ensures that the label is formatted correctly for the focused
 // group.
-base::string16 AddressPhoneFormLabelFormatter::GetLabelForFocusedGroup(
+base::string16 AddressPhoneFormLabelFormatter::GetLabelForProfile(
     const AutofillProfile& profile,
-    FieldTypeGroup group) const {
+    FieldTypeGroup focused_group) const {
   std::vector<base::string16> label_parts;
 
-  if (group != PHONE_HOME) {
+  if (focused_group != PHONE_HOME) {
     AddLabelPartIfNotEmpty(GetLabelPhone(profile, app_locale()), &label_parts);
   }
 
-  if (group != NAME) {
+  if (focused_group != NAME) {
     AddLabelPartIfNotEmpty(GetLabelName(profile, app_locale()), &label_parts);
   }
 
-  if (group != ADDRESS_HOME) {
+  if (focused_group != ADDRESS_HOME) {
     AddLabelPartIfNotEmpty(
         GetLabelAddress(form_has_street_address_, profile, app_locale(),
                         field_types_for_labels()),
diff --git a/components/autofill/core/browser/address_phone_form_label_formatter.h b/components/autofill/core/browser/address_phone_form_label_formatter.h
index 00d5163..0917f584 100644
--- a/components/autofill/core/browser/address_phone_form_label_formatter.h
+++ b/components/autofill/core/browser/address_phone_form_label_formatter.h
@@ -26,8 +26,9 @@
 
   ~AddressPhoneFormLabelFormatter() override;
 
-  base::string16 GetLabelForFocusedGroup(const AutofillProfile& profile,
-                                         FieldTypeGroup group) const override;
+  base::string16 GetLabelForProfile(
+      const AutofillProfile& profile,
+      FieldTypeGroup focused_group) const override;
 
  private:
   // True if this formatter's associated form has a street address field. A
diff --git a/components/autofill/core/browser/contact_form_label_formatter.cc b/components/autofill/core/browser/contact_form_label_formatter.cc
index e4949d9d..9c81ab0e 100644
--- a/components/autofill/core/browser/contact_form_label_formatter.cc
+++ b/components/autofill/core/browser/contact_form_label_formatter.cc
@@ -19,22 +19,21 @@
 ContactFormLabelFormatter::~ContactFormLabelFormatter() {}
 
 // Note that the order--phone, name, and email--in which parts of the label
-// are added ensures that the label is formatted correctly for the focused
-// group.
-base::string16 ContactFormLabelFormatter::GetLabelForFocusedGroup(
+// are added ensures that the label is formatted correctly for |focused_group|.
+base::string16 ContactFormLabelFormatter::GetLabelForProfile(
     const AutofillProfile& profile,
-    FieldTypeGroup group) const {
+    FieldTypeGroup focused_group) const {
   std::vector<base::string16> label_parts;
 
-  if (group != PHONE_HOME) {
+  if (focused_group != PHONE_HOME) {
     AddLabelPartIfNotEmpty(MaybeGetPhone(profile), &label_parts);
   }
 
-  if (group != NAME) {
+  if (focused_group != NAME) {
     AddLabelPartIfNotEmpty(GetLabelName(profile, app_locale()), &label_parts);
   }
 
-  if (group != EMAIL) {
+  if (focused_group != EMAIL) {
     AddLabelPartIfNotEmpty(MaybeGetEmail(profile), &label_parts);
   }
 
diff --git a/components/autofill/core/browser/contact_form_label_formatter.h b/components/autofill/core/browser/contact_form_label_formatter.h
index da5a442..ca23a7fe 100644
--- a/components/autofill/core/browser/contact_form_label_formatter.h
+++ b/components/autofill/core/browser/contact_form_label_formatter.h
@@ -26,8 +26,9 @@
 
   ~ContactFormLabelFormatter() override;
 
-  base::string16 GetLabelForFocusedGroup(const AutofillProfile& profile,
-                                         FieldTypeGroup group) const override;
+  base::string16 GetLabelForProfile(
+      const AutofillProfile& profile,
+      FieldTypeGroup focused_group) const override;
 
  private:
   // Returns |profile|'s email address if |profile| has a valid email address
diff --git a/components/autofill/core/browser/label_formatter.cc b/components/autofill/core/browser/label_formatter.cc
index 555094e..263df91b 100644
--- a/components/autofill/core/browser/label_formatter.cc
+++ b/components/autofill/core/browser/label_formatter.cc
@@ -26,15 +26,15 @@
                                ServerFieldType focused_field_type,
                                const std::vector<ServerFieldType>& field_types)
     : app_locale_(app_locale), focused_field_type_(focused_field_type) {
-  const FieldTypeGroup group = GetFocusedNonBillingGroup();
+  const FieldTypeGroup focused_group = GetFocusedNonBillingGroup();
   std::set<FieldTypeGroup> groups{NAME, ADDRESS_HOME, EMAIL, PHONE_HOME};
 
   // If a user is focused on an address field, then parts of the address may be
   // shown in the label. For example, if the user is focusing on a street
   // address field, then it may be helpful to show the city in the label.
   // Otherwise, the focused field should not appear in the label.
-  if (group != ADDRESS_HOME) {
-    groups.erase(group);
+  if (focused_group != ADDRESS_HOME) {
+    groups.erase(focused_group);
   }
 
   // Countries are excluded to prevent them from appearing in labels with
@@ -57,8 +57,7 @@
     const std::vector<AutofillProfile*>& profiles) const {
   std::vector<base::string16> labels;
   for (const AutofillProfile* profile : profiles) {
-    labels.push_back(
-        GetLabelForFocusedGroup(*profile, GetFocusedNonBillingGroup()));
+    labels.push_back(GetLabelForProfile(*profile, GetFocusedNonBillingGroup()));
   }
   return labels;
 }
diff --git a/components/autofill/core/browser/label_formatter.h b/components/autofill/core/browser/label_formatter.h
index 71cc68fa..5879599 100644
--- a/components/autofill/core/browser/label_formatter.h
+++ b/components/autofill/core/browser/label_formatter.h
@@ -39,14 +39,14 @@
  protected:
   // Returns a label to show the user. The elements of the label and their
   // ordering depend on the kind of LabelFormatter, the data in |profile|, and
-  // on the focused |group|.
+  // on |focused_group|.
   // Subclasses may return labels that span one or two lines. If a label is
   // intended to span two lines, then it contains a kMultilineLabelDelimiter.
-  virtual base::string16 GetLabelForFocusedGroup(
+  virtual base::string16 GetLabelForProfile(
       const AutofillProfile& profile,
-      FieldTypeGroup group) const = 0;
+      FieldTypeGroup focused_group) const = 0;
 
-  // Returns the FieldTypeGroup with which focused_field_type_ is associated.
+  // Returns the FieldTypeGroup with which |focused_field_type_| is associated.
   // Billing field types are mapped to their corresponding home address field
   // types. For example, if focused_field_type_ is ADDRESS_BILLING_ZIP, then
   // the resulting FieldTypeGroup is ADDRESS_HOME instead of ADDRESS_BILLING.
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn
index 432dff1..128949e 100644
--- a/components/autofill_assistant/browser/BUILD.gn
+++ b/components/autofill_assistant/browser/BUILD.gn
@@ -101,6 +101,8 @@
     "protocol_utils.h",
     "rectf.cc",
     "rectf.h",
+    "retry_timer.cc",
+    "retry_timer.h",
     "script.cc",
     "script.h",
     "script_executor.cc",
@@ -164,6 +166,7 @@
     "mock_web_controller.cc",
     "mock_web_controller.h",
     "protocol_utils_unittest.cc",
+    "retry_timer_unittest.cc",
     "script_executor_unittest.cc",
     "script_precondition_unittest.cc",
     "script_tracker_unittest.cc",
diff --git a/components/autofill_assistant/browser/actions/action_delegate.h b/components/autofill_assistant/browser/actions/action_delegate.h
index b6bde7b8..7a9a5fb 100644
--- a/components/autofill_assistant/browser/actions/action_delegate.h
+++ b/components/autofill_assistant/browser/actions/action_delegate.h
@@ -46,9 +46,9 @@
   // the action.
   virtual std::string GetStatusMessage() = 0;
 
-  // Create a helper for checking for multiple element existence or field
-  // values.
-  virtual std::unique_ptr<BatchElementChecker> CreateBatchElementChecker() = 0;
+  // Checks one or more elements.
+  virtual void RunElementChecks(BatchElementChecker* checker,
+                                base::OnceCallback<void()> all_done) = 0;
 
   // Wait for a short time for a given selector to appear.
   //
diff --git a/components/autofill_assistant/browser/actions/autofill_action.cc b/components/autofill_assistant/browser/actions/autofill_action.cc
index 1cafea7..1476c51 100644
--- a/components/autofill_assistant/browser/actions/autofill_action.cc
+++ b/components/autofill_assistant/browser/actions/autofill_action.cc
@@ -145,7 +145,7 @@
   }
 
   DCHECK(!batch_element_checker_);
-  batch_element_checker_ = delegate->CreateBatchElementChecker();
+  batch_element_checker_ = std::make_unique<BatchElementChecker>();
   for (int i = 0; i < proto_.use_address().required_fields_size(); i++) {
     auto& required_address_field = proto_.use_address().required_fields(i);
     DCHECK_GT(required_address_field.element().selectors_size(), 0);
@@ -154,10 +154,8 @@
         base::BindOnce(&AutofillAction::OnGetRequiredFieldValue,
                        weak_ptr_factory_.GetWeakPtr(), i));
   }
-  batch_element_checker_->Run(
-      base::TimeDelta::FromSeconds(0),
-      /* try_done= */ base::DoNothing(),
-      /* all_done= */
+  delegate->RunElementChecks(
+      batch_element_checker_.get(),
       base::BindOnce(&AutofillAction::OnCheckRequiredFieldsDone,
                      weak_ptr_factory_.GetWeakPtr(), base::Unretained(delegate),
                      allow_fallback));
diff --git a/components/autofill_assistant/browser/actions/autofill_action_unittest.cc b/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
index 57452d4e..ae14a9ef 100644
--- a/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
@@ -115,9 +115,10 @@
         .WillByDefault(Return(&client_memory_));
     ON_CALL(mock_action_delegate_, GetPersonalDataManager)
         .WillByDefault(Return(personal_data_manager_.get()));
-    ON_CALL(mock_action_delegate_, CreateBatchElementChecker)
-        .WillByDefault(Invoke([this]() {
-          return std::make_unique<BatchElementChecker>(&mock_web_controller_);
+    ON_CALL(mock_action_delegate_, RunElementChecks)
+        .WillByDefault(Invoke([this](BatchElementChecker* checker,
+                                     base::OnceCallback<void()> all_done) {
+          checker->Run(&mock_web_controller_, std::move(all_done));
         }));
     ON_CALL(mock_action_delegate_, OnShortWaitForElement(_, _, _))
         .WillByDefault(RunOnceCallback<2>(true));
diff --git a/components/autofill_assistant/browser/actions/mock_action_delegate.h b/components/autofill_assistant/browser/actions/mock_action_delegate.h
index 2567aaf4..4879dbc 100644
--- a/components/autofill_assistant/browser/actions/mock_action_delegate.h
+++ b/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -22,8 +22,8 @@
   MockActionDelegate();
   ~MockActionDelegate() override;
 
-  MOCK_METHOD0(CreateBatchElementChecker,
-               std::unique_ptr<BatchElementChecker>());
+  MOCK_METHOD2(RunElementChecks,
+               void(BatchElementChecker*, base::OnceCallback<void()>));
 
   void ShortWaitForElement(ElementCheckType check_type,
                            const Selector& selector,
diff --git a/components/autofill_assistant/browser/actions/prompt_action.cc b/components/autofill_assistant/browser/actions/prompt_action.cc
index 2a1f9bd..d94464f4 100644
--- a/components/autofill_assistant/browser/actions/prompt_action.cc
+++ b/components/autofill_assistant/browser/actions/prompt_action.cc
@@ -42,10 +42,21 @@
   callback_ = std::move(callback);
   delegate->SetStatusMessage(proto_.prompt().message());
 
-  SetupAutoSelect();
   SetupPreconditions();
-  CheckPreconditions();
   UpdateChips();
+
+  if (HasNonemptyPreconditions() || HasAutoSelect()) {
+    RunPeriodicChecks();
+    timer_ = std::make_unique<base::RepeatingTimer>();
+    timer_->Start(FROM_HERE, kPreconditionChipCheckInterval,
+                  base::BindRepeating(&PromptAction::RunPeriodicChecks,
+                                      weak_ptr_factory_.GetWeakPtr()));
+  }
+}
+
+void PromptAction::RunPeriodicChecks() {
+  CheckPreconditions();
+  CheckAutoSelect();
 }
 
 void PromptAction::SetupPreconditions() {
@@ -57,27 +68,27 @@
     preconditions_[i] = std::make_unique<ElementPrecondition>(
         choice_proto.show_only_if_element_exists(),
         choice_proto.show_only_if_form_value_matches());
-    precondition_results_[i] = false;
+    precondition_results_[i] = preconditions_[i]->empty();
   }
 }
 
-void PromptAction::CheckPreconditions() {
-  // This method might be called by PostDelayedTask, possibly after
-  // OnSuggestionChosen ran. The condition on callback_ makes sure that the
-  // caller is still waiting for a response.
-  if (!callback_)
-    return;
+bool PromptAction::HasNonemptyPreconditions() {
+  for (const auto& precondition : preconditions_) {
+    if (!precondition->empty())
+      return true;
+  }
+  return false;
+}
 
-  precondition_checker_ = delegate_->CreateBatchElementChecker();
+void PromptAction::CheckPreconditions() {
+  precondition_checker_ = std::make_unique<BatchElementChecker>();
   for (size_t i = 0; i < preconditions_.size(); i++) {
     preconditions_[i]->Check(precondition_checker_.get(),
                              base::BindOnce(&PromptAction::OnPreconditionResult,
                                             weak_ptr_factory_.GetWeakPtr(), i));
   }
-  precondition_checker_->Run(
-      // Try once; retries are handled by OnPreconditionChecksDone.
-      base::TimeDelta::FromSeconds(0),
-      /* try_done= */ base::DoNothing(),
+  delegate_->RunElementChecks(
+      precondition_checker_.get(),
       base::BindOnce(&PromptAction::OnPreconditionChecksDone,
                      weak_ptr_factory_.GetWeakPtr()));
 }
@@ -93,24 +104,6 @@
 void PromptAction::OnPreconditionChecksDone() {
   if (precondition_changed_)
     UpdateChips();
-
-  if (HasNonemptyPreconditions()) {
-    // If there are element preconditions, the result can change with time, so
-    // schedule another check later on.
-    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&PromptAction::CheckPreconditions,
-                       weak_ptr_factory_.GetWeakPtr()),
-        kPreconditionChipCheckInterval);
-  }
-}
-
-bool PromptAction::HasNonemptyPreconditions() {
-  for (const auto& precondition : preconditions_) {
-    if (!precondition->empty())
-      return true;
-  }
-  return false;
 }
 
 void PromptAction::UpdateChips() {
@@ -136,31 +129,35 @@
   precondition_changed_ = false;
 }
 
-void PromptAction::SetupAutoSelect() {
+bool PromptAction::HasAutoSelect() {
+  for (int i = 0; i < proto_.prompt().choices_size(); i++) {
+    Selector selector(
+        proto_.prompt().choices(i).auto_select_if_element_exists());
+    if (!selector.empty())
+      return true;
+  }
+  return false;
+}
+
+void PromptAction::CheckAutoSelect() {
+  auto_select_checker_ = std::make_unique<BatchElementChecker>();
+
   // Wait as long as necessary for one of the elements to show up. This is
-  // cancelled by CancelProto()
+  // cancelled by CancelPrompt()
   for (int i = 0; i < proto_.prompt().choices_size(); i++) {
     Selector selector(
         proto_.prompt().choices(i).auto_select_if_element_exists());
     if (selector.empty())
       continue;
 
-    if (!auto_select_checker_)
-      auto_select_checker_ = delegate_->CreateBatchElementChecker();
-
     auto_select_checker_->AddElementCheck(
         kExistenceCheck, selector,
         base::BindOnce(&PromptAction::OnAutoSelectElementExists,
                        weak_ptr_factory_.GetWeakPtr(), i));
   }
-  if (!auto_select_checker_)
-    return;
-
-  auto_select_checker_->Run(base::TimeDelta::Max(),
-                            /* try_done= */
-                            base::BindRepeating(&PromptAction::OnAutoSelectDone,
-                                                weak_ptr_factory_.GetWeakPtr()),
-                            /* all_done= */ base::DoNothing());
+  delegate_->RunElementChecks(auto_select_checker_.get(),
+                              base::BindOnce(&PromptAction::OnAutoSelectDone,
+                                             weak_ptr_factory_.GetWeakPtr()));
 }
 
 void PromptAction::OnAutoSelectElementExists(int choice_index, bool exists) {
@@ -186,7 +183,8 @@
   }
   DCHECK(choice_index >= 0 && choice_index <= proto_.prompt().choices_size());
 
-  // Interrupt checks.
+  // Interrupt checks and timer.
+  timer_.reset();
   precondition_checker_.reset();
   auto_select_checker_.reset();
 
diff --git a/components/autofill_assistant/browser/actions/prompt_action.h b/components/autofill_assistant/browser/actions/prompt_action.h
index 95465e77..e674b55 100644
--- a/components/autofill_assistant/browser/actions/prompt_action.h
+++ b/components/autofill_assistant/browser/actions/prompt_action.h
@@ -12,6 +12,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
 #include "components/autofill_assistant/browser/actions/action.h"
 #include "components/autofill_assistant/browser/batch_element_checker.h"
 #include "components/autofill_assistant/browser/chip.h"
@@ -30,13 +31,15 @@
   void InternalProcessAction(ActionDelegate* delegate,
                              ProcessActionCallback callback) override;
 
+  void RunPeriodicChecks();
   void SetupPreconditions();
+  bool HasNonemptyPreconditions();
   void CheckPreconditions();
   void OnPreconditionResult(size_t choice_index, bool result);
-  bool HasNonemptyPreconditions();
   void OnPreconditionChecksDone();
   void UpdateChips();
-  void SetupAutoSelect();
+  bool HasAutoSelect();
+  void CheckAutoSelect();
   void OnAutoSelectElementExists(int choice_index, bool exists);
   void OnAutoSelectDone();
   void OnSuggestionChosen(int choice_index);
@@ -66,6 +69,8 @@
   // Batch element checker for auto-selection, if any.
   std::unique_ptr<BatchElementChecker> auto_select_checker_;
 
+  std::unique_ptr<base::RepeatingTimer> timer_;
+
   base::WeakPtrFactory<PromptAction> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(PromptAction);
diff --git a/components/autofill_assistant/browser/actions/prompt_action_unittest.cc b/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
index e169e431..abe2649 100644
--- a/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
@@ -39,11 +39,11 @@
     ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
         .WillByDefault(RunOnceCallback<1>(false, ""));
 
-    ON_CALL(mock_action_delegate_, CreateBatchElementChecker)
-        .WillByDefault(Invoke([this]() {
-          return std::make_unique<BatchElementChecker>(&mock_web_controller_);
+    ON_CALL(mock_action_delegate_, RunElementChecks)
+        .WillByDefault(Invoke([this](BatchElementChecker* checker,
+                                     base::OnceCallback<void()> all_done) {
+          checker->Run(&mock_web_controller_, std::move(all_done));
         }));
-
     ON_CALL(mock_action_delegate_, Prompt(_, _))
         .WillByDefault(Invoke([this](std::unique_ptr<std::vector<Chip>> chips,
                                      base::OnceCallback<void()> on_terminate) {
diff --git a/components/autofill_assistant/browser/batch_element_checker.cc b/components/autofill_assistant/browser/batch_element_checker.cc
index b8f48b521..f3f0989 100644
--- a/components/autofill_assistant/browser/batch_element_checker.cc
+++ b/components/autofill_assistant/browser/batch_element_checker.cc
@@ -13,19 +13,8 @@
 #include "components/autofill_assistant/browser/web_controller.h"
 
 namespace autofill_assistant {
-namespace {
-// Waiting period between two checks.
-static constexpr base::TimeDelta kCheckPeriod = base::TimeDelta::FromSeconds(1);
-}  // namespace
 
-BatchElementChecker::BatchElementChecker(WebController* web_controller)
-    : web_controller_(web_controller),
-      pending_checks_count_(0),
-      all_found_(false),
-      started_(false),
-      weak_ptr_factory_(this) {
-  DCHECK(web_controller);
-}
+BatchElementChecker::BatchElementChecker() : weak_ptr_factory_(this) {}
 
 BatchElementChecker::~BatchElementChecker() {}
 
@@ -45,45 +34,23 @@
   get_field_value_callbacks_[selector].emplace_back(std::move(callback));
 }
 
-void BatchElementChecker::Run(const base::TimeDelta& duration,
-                              base::RepeatingCallback<void()> try_done,
+bool BatchElementChecker::empty() const {
+  return element_check_callbacks_.empty() && get_field_value_callbacks_.empty();
+}
+
+void BatchElementChecker::Run(WebController* web_controller,
                               base::OnceCallback<void()> all_done) {
+  DCHECK(web_controller);
+  DCHECK(!started_);
   started_ = true;
-  int64_t try_count = duration / kCheckPeriod;
-  if (try_count <= 0) {
-    try_count = 1;
-  }
 
-  Try(base::BindOnce(&BatchElementChecker::OnTryDone,
-                     weak_ptr_factory_.GetWeakPtr(), try_count, try_done,
-                     std::move(all_done)));
-}
-
-bool BatchElementChecker::all_found() {
-  if (!started_) {
-    return element_check_callbacks_.empty() &&
-           get_field_value_callbacks_.empty();
-  }
-  return all_found_;
-}
-
-void BatchElementChecker::Try(base::OnceCallback<void()> try_done_callback) {
-  DCHECK(!try_done_callback_);
-
-  try_done_callback_ = std::move(try_done_callback);
-
-  DCHECK_EQ(pending_checks_count_, 0);
+  all_done_ = std::move(all_done);
   pending_checks_count_ =
       element_check_callbacks_.size() + get_field_value_callbacks_.size() + 1;
 
   for (auto& entry : element_check_callbacks_) {
-    if (entry.second.empty()) {
-      pending_checks_count_--;
-      continue;
-    }
-
     const auto& call_arguments = entry.first;
-    web_controller_->ElementCheck(
+    web_controller->ElementCheck(
         call_arguments.first, call_arguments.second, /* strict= */ false,
         base::BindOnce(
             &BatchElementChecker::OnElementChecked,
@@ -94,12 +61,7 @@
   }
 
   for (auto& entry : get_field_value_callbacks_) {
-    if (entry.second.empty()) {
-      pending_checks_count_--;
-      continue;
-    }
-
-    web_controller_->GetFieldValue(
+    web_controller->GetFieldValue(
         entry.first,
         base::BindOnce(
             &BatchElementChecker::OnGetFieldValue,
@@ -117,111 +79,39 @@
   //
   // TODO(crbug.com/806868): make sure 'all_done' callback is called
   // asynchronously and fix unit tests accordingly.
-  pending_checks_count_--;
-  CheckTryDone();
-}
-
-void BatchElementChecker::OnTryDone(int64_t remaining_attempts,
-                                    base::RepeatingCallback<void()> try_done,
-                                    base::OnceCallback<void()> all_done) {
-  // Warning: try_done or all_done can indirectly delete this. this must not
-  // be used after calling either of these.
-  if (all_found_) {
-    try_done.Run();
-    std::move(all_done).Run();
-    return;
-  }
-
-  --remaining_attempts;
-  if (remaining_attempts <= 0) {
-    // GiveUp is run before calling try_done, so its effects are visible right
-    // away.
-    GiveUp();
-    try_done.Run();
-    std::move(all_done).Run();
-    return;
-  }
-
-  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE,
-      base::BindOnce(
-          &BatchElementChecker::Try, weak_ptr_factory_.GetWeakPtr(),
-          base::BindOnce(&BatchElementChecker::OnTryDone,
-                         weak_ptr_factory_.GetWeakPtr(), remaining_attempts,
-                         try_done, std::move(all_done))),
-      kCheckPeriod);
-
-  // try_done must be called after creating the delayed task, in case
-  // try_done.Run() deletes this.
-  try_done.Run();
-}
-
-void BatchElementChecker::GiveUp() {
-  for (auto& entry : element_check_callbacks_) {
-    RunCallbacks(&entry.second, false);
-  }
-  for (auto& entry : get_field_value_callbacks_) {
-    RunCallbacks(&entry.second, false, "");
-  }
+  CheckDone();
 }
 
 void BatchElementChecker::OnElementChecked(
     std::vector<ElementCheckCallback>* callbacks,
     bool exists) {
-  pending_checks_count_--;
-  if (exists)
-    RunCallbacks(callbacks, true);
-
-  CheckTryDone();
+  for (auto& callback : *callbacks) {
+    std::move(callback).Run(exists);
+  }
+  callbacks->clear();
+  CheckDone();
 }
 
 void BatchElementChecker::OnGetFieldValue(
     std::vector<GetFieldValueCallback>* callbacks,
     bool exists,
     const std::string& value) {
-  pending_checks_count_--;
-  if (exists)
-    RunCallbacks(callbacks, exists, value);
-
-  CheckTryDone();
-}
-
-void BatchElementChecker::CheckTryDone() {
-  DCHECK_GE(pending_checks_count_, 0);
-  if (pending_checks_count_ <= 0 && try_done_callback_) {
-    all_found_ = !HasMoreChecksToRun();
-    std::move(try_done_callback_).Run();
-  }
-}
-
-void BatchElementChecker::RunCallbacks(
-    std::vector<ElementCheckCallback>* callbacks,
-    bool result) {
-  for (auto& callback : *callbacks) {
-    std::move(callback).Run(result);
-  }
-  callbacks->clear();
-}
-
-void BatchElementChecker::RunCallbacks(
-    std::vector<GetFieldValueCallback>* callbacks,
-    bool exists,
-    const std::string& value) {
   for (auto& callback : *callbacks) {
     std::move(callback).Run(exists, value);
   }
   callbacks->clear();
+  CheckDone();
 }
 
-bool BatchElementChecker::HasMoreChecksToRun() {
-  for (const auto& entry : element_check_callbacks_) {
-    if (!entry.second.empty())
-      return true;
+void BatchElementChecker::CheckDone() {
+  pending_checks_count_--;
+  DCHECK_GE(pending_checks_count_, 0);
+  if (pending_checks_count_ <= 0) {
+    DCHECK(all_done_);
+    std::move(all_done_).Run();
+    // Don't do anything after calling all_done, since this could have been
+    // deleted.
   }
-  for (const auto& entry : get_field_value_callbacks_) {
-    if (!entry.second.empty())
-      return true;
-  }
-  return false;
 }
+
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/batch_element_checker.h b/components/autofill_assistant/browser/batch_element_checker.h
index aaa91ed..161c43c 100644
--- a/components/autofill_assistant/browser/batch_element_checker.h
+++ b/components/autofill_assistant/browser/batch_element_checker.h
@@ -24,30 +24,10 @@
 enum ElementCheckType { kExistenceCheck, kVisibilityCheck };
 
 // Helper for checking a set of elements at the same time. It avoids duplicate
-// checks and supports retries.
-//
-// Single check:
-//
-// The simplest way of using a BatchElementChecker is to:
-// - create an instance, using WebController::CreateBatchElementChecker or
-//   ActionDelegate::CreateBatchElementChecker
-// - call AddElementCheck() and AddFieldValueCheck()
-// - call Run() with duration set to 0.
-//
-// The result of the checks is reported to the callbacks passed to
-// AddElementCheck(kExistenceCheck, ) and AddFieldValueCheck(), then the
-// callback passed to Run() is called, to report the end of the a run.
-//
-// Check with retries:
-//
-// To check for existence more than once, call Run() with a duration that
-// specifies how long you're willing to wait. In that mode, elements that are
-// found are reported immediately. Elements that are not found are reported at
-// the end, once the specified deadline has passed, just before giving up and
-// calling the callback passed to Run().
+// checks.
 class BatchElementChecker {
  public:
-  explicit BatchElementChecker(WebController* web_controller);
+  explicit BatchElementChecker();
   virtual ~BatchElementChecker();
 
   // Callback for AddElementCheck. Argument is true if the check passed.
@@ -83,56 +63,19 @@
   void AddFieldValueCheck(const Selector& selector,
                           GetFieldValueCallback callback);
 
-  // Runs the checks until all elements exist or for |duration|, whichever one
-  // comes first. Elements found are reported as soon as they're founds.
-  // Elements not found are reported right before |all_done| is run.
-  //
-  // |duration| can be 0. In this case the checks are run once, without waiting.
-  // |try_done| is run at the end of each try.
-  //
-  // |try_done| or |all_done| can delete their calling BatchElementChecker to
-  // interrupt any future checks. If |try_done| deletes BatchElementChecker,
-  // |all_done| will never be called.
-  //
-  // Sync |try_done| and |all_done| can be called after the element checker has
-  // been deleted, they should always be called with callbacks that use a weak
-  // ptr instead of Unretained(this), even from objects that own the checker.
-  void Run(const base::TimeDelta& duration,
-           base::RepeatingCallback<void()> try_done,
-           base::OnceCallback<void()> all_done);
+  // Returns true if all there are no checks to run.
+  bool empty() const;
 
-  // Returns true if all element that were asked for have been found. Can be
-  // called while Run is progress or afterwards.
-  bool all_found();
+  // Runs the checks. Call |all_done| once all the results have been reported.
+  void Run(WebController* web_controller, base::OnceCallback<void()> all_done);
 
  private:
-  // Tries running the checks, reporting only successes.
-  //
-  // Calls |try_done_callback| at the end of the run.
-  void Try(base::OnceCallback<void()> try_done_callback);
-
-  void OnTryDone(int64_t remaining_attempts,
-                 base::RepeatingCallback<void()> try_done,
-                 base::OnceCallback<void()> all_done);
-
-  // If there are still callbacks not called by a previous call to Try, call
-  // them now. When this method returns, all callbacks are guaranteed to have
-  // been run.
-  void GiveUp();
-
   void OnElementChecked(std::vector<ElementCheckCallback>* callbacks,
                         bool exists);
   void OnGetFieldValue(std::vector<GetFieldValueCallback>* callbacks,
                        bool exists,
                        const std::string& value);
-  void CheckTryDone();
-  void RunCallbacks(std::vector<ElementCheckCallback>* callbacks, bool result);
-  void RunCallbacks(std::vector<GetFieldValueCallback>* callbacks,
-                    bool result,
-                    const std::string& value);
-  bool HasMoreChecksToRun();
-
-  WebController* const web_controller_;
+  void CheckDone();
 
   // A map of ElementCheck arguments (check_type, selector) to callbacks that
   // take the result of the check.
@@ -144,17 +87,12 @@
   // field value.
   std::map<Selector, std::vector<GetFieldValueCallback>>
       get_field_value_callbacks_;
-  int pending_checks_count_;
-  bool all_found_;
+  int pending_checks_count_ = 0;
 
   // Run() was called. Checking elements might or might not have finished yet.
-  bool started_;
+  bool started_ = false;
 
-  // The callback built for Try(). It is kept around while going through the
-  // maps and called once all selectors in that map have been looked up once,
-  // whether that lookup was successful or not. Also used to guarantee that only
-  // one Try runs at a time.
-  base::OnceCallback<void()> try_done_callback_;
+  base::OnceCallback<void()> all_done_;
 
   base::WeakPtrFactory<BatchElementChecker> weak_ptr_factory_;
 
diff --git a/components/autofill_assistant/browser/batch_element_checker_unittest.cc b/components/autofill_assistant/browser/batch_element_checker_unittest.cc
index de579347..d6e7d37e 100644
--- a/components/autofill_assistant/browser/batch_element_checker_unittest.cc
+++ b/components/autofill_assistant/browser/batch_element_checker_unittest.cc
@@ -27,14 +27,9 @@
 
 namespace {
 
-static constexpr base::TimeDelta kTimeUnit = base::TimeDelta::FromSeconds(1);
-
 class BatchElementCheckerTest : public testing::Test {
  protected:
-  BatchElementCheckerTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
-        checks_(&mock_web_controller_) {}
+  BatchElementCheckerTest() : checks_() {}
 
   void OnElementExistenceCheck(const std::string& name, bool result) {
     element_exists_results_[name] = result;
@@ -75,38 +70,23 @@
                           base::Unretained(this), name);
   }
 
-  void OnTry(const std::string& name) { ++try_done_[name]; }
-
-  base::RepeatingCallback<void()> TryCallback(const std::string& name) {
-    return base::BindRepeating(&BatchElementCheckerTest::OnTry,
-                               base::Unretained(this), name);
+  void Run(const std::string& callback_name) {
+    checks_.Run(&mock_web_controller_, DoneCallback(callback_name));
   }
 
-  void AdvanceTime() { scoped_task_environment_.FastForwardBy(kTimeUnit); }
-
-  void RunOnce(const std::string& callback_name) {
-    checks_.Run(base::TimeDelta::FromMilliseconds(0), base::DoNothing(),
-                DoneCallback(callback_name));
-  }
-
-  // scoped_task_environment_ must be first to guarantee other field
-  // creation run in that environment.
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
   MockWebController mock_web_controller_;
   BatchElementChecker checks_;
   std::map<std::string, bool> element_exists_results_;
   std::map<std::string, bool> element_visible_results_;
   std::map<std::string, std::string> get_field_value_results_;
   std::set<std::string> all_done_;
-  std::map<std::string, int> try_done_;
 };
 
-TEST_F(BatchElementCheckerTest, AllFoundIfEmpty) {
-  EXPECT_TRUE(checks_.all_found());
+TEST_F(BatchElementCheckerTest, Empty) {
+  EXPECT_TRUE(checks_.empty());
   checks_.AddElementCheck(kExistenceCheck, Selector({"exists"}),
                           ElementExistenceCallback("exists"));
-  EXPECT_FALSE(checks_.all_found());
+  EXPECT_FALSE(checks_.empty());
 }
 
 TEST_F(BatchElementCheckerTest, OneElementFound) {
@@ -115,11 +95,10 @@
       .WillOnce(RunOnceCallback<2>(true));
   checks_.AddElementCheck(kExistenceCheck, Selector({"exists"}),
                           ElementExistenceCallback("exists"));
-  RunOnce("run_once");
+  Run("was_run");
 
   EXPECT_THAT(element_exists_results_, Contains(Pair("exists", true)));
-  EXPECT_THAT(all_done_, Contains("run_once"));
-  EXPECT_TRUE(checks_.all_found());
+  EXPECT_THAT(all_done_, Contains("was_run"));
 }
 
 TEST_F(BatchElementCheckerTest, OneElementNotFound) {
@@ -129,44 +108,40 @@
       .WillOnce(RunOnceCallback<2>(false));
   checks_.AddElementCheck(kExistenceCheck, Selector({"does_not_exist"}),
                           ElementExistenceCallback("does_not_exist"));
-  RunOnce("run_once");
+  Run("was_run");
 
   EXPECT_THAT(element_exists_results_, Contains(Pair("does_not_exist", false)));
-  EXPECT_THAT(all_done_, Contains("run_once"));
-  EXPECT_FALSE(checks_.all_found());
+  EXPECT_THAT(all_done_, Contains("was_run"));
 }
 
 TEST_F(BatchElementCheckerTest, OneFieldValueFound) {
   EXPECT_CALL(mock_web_controller_, OnGetFieldValue(Eq(Selector({"field"})), _))
       .WillOnce(RunOnceCallback<1>(true, "some value"));
   checks_.AddFieldValueCheck(Selector({"field"}), FieldValueCallback("field"));
-  RunOnce("run_once");
+  Run("was_run");
 
   EXPECT_THAT(get_field_value_results_, Contains(Pair("field", "some value")));
-  EXPECT_THAT(all_done_, Contains("run_once"));
-  EXPECT_TRUE(checks_.all_found());
+  EXPECT_THAT(all_done_, Contains("was_run"));
 }
 
 TEST_F(BatchElementCheckerTest, OneFieldValueNotFound) {
   EXPECT_CALL(mock_web_controller_, OnGetFieldValue(Eq(Selector({"field"})), _))
       .WillOnce(RunOnceCallback<1>(false, ""));
   checks_.AddFieldValueCheck(Selector({"field"}), FieldValueCallback("field"));
-  RunOnce("run_once");
+  Run("was_run");
 
   EXPECT_THAT(get_field_value_results_, Contains(Pair("field", "")));
-  EXPECT_THAT(all_done_, Contains("run_once"));
-  EXPECT_FALSE(checks_.all_found());
+  EXPECT_THAT(all_done_, Contains("was_run"));
 }
 
 TEST_F(BatchElementCheckerTest, OneFieldValueEmpty) {
   EXPECT_CALL(mock_web_controller_, OnGetFieldValue(Eq(Selector({"field"})), _))
       .WillOnce(RunOnceCallback<1>(true, ""));
   checks_.AddFieldValueCheck(Selector({"field"}), FieldValueCallback("field"));
-  RunOnce("run_once");
+  Run("was_run");
 
   EXPECT_THAT(get_field_value_results_, Contains(Pair("field", "")));
-  EXPECT_THAT(all_done_, Contains("run_once"));
-  EXPECT_TRUE(checks_.all_found());
+  EXPECT_THAT(all_done_, Contains("was_run"));
 }
 
 TEST_F(BatchElementCheckerTest, MultipleElements) {
@@ -192,15 +167,14 @@
                           ElementExistenceCallback("3"));
   checks_.AddFieldValueCheck(Selector({"4"}), FieldValueCallback("4"));
   checks_.AddFieldValueCheck(Selector({"5"}), FieldValueCallback("5"));
-  RunOnce("run_once");
+  Run("was_run");
 
   EXPECT_THAT(element_exists_results_, Contains(Pair("1", true)));
   EXPECT_THAT(element_exists_results_, Contains(Pair("2", true)));
   EXPECT_THAT(element_exists_results_, Contains(Pair("3", false)));
   EXPECT_THAT(get_field_value_results_, Contains(Pair("4", "value")));
   EXPECT_THAT(get_field_value_results_, Contains(Pair("5", "")));
-  EXPECT_THAT(all_done_, Contains("run_once"));
-  EXPECT_FALSE(checks_.all_found());
+  EXPECT_THAT(all_done_, Contains("was_run"));
 }
 
 TEST_F(BatchElementCheckerTest, DeduplicateElementExists) {
@@ -218,12 +192,12 @@
   checks_.AddElementCheck(kExistenceCheck, Selector({"2"}),
                           ElementExistenceCallback("2"));
 
-  RunOnce("run_once");
+  Run("was_run");
 
   EXPECT_THAT(element_exists_results_, Contains(Pair("first 1", true)));
   EXPECT_THAT(element_exists_results_, Contains(Pair("second 1", true)));
   EXPECT_THAT(element_exists_results_, Contains(Pair("2", true)));
-  EXPECT_THAT(all_done_, Contains("run_once"));
+  EXPECT_THAT(all_done_, Contains("was_run"));
 }
 
 TEST_F(BatchElementCheckerTest, DeduplicateElementVisible) {
@@ -241,126 +215,15 @@
   checks_.AddElementCheck(kVisibilityCheck, Selector({"2"}),
                           ElementVisibilityCallback("2"));
 
-  RunOnce("run_once");
+  Run("was_run");
 
   EXPECT_THAT(element_visible_results_, Contains(Pair("first 1", true)));
   EXPECT_THAT(element_visible_results_, Contains(Pair("second 1", true)));
   EXPECT_THAT(element_visible_results_, Contains(Pair("2", true)));
-  EXPECT_THAT(all_done_, Contains("run_once"));
+  EXPECT_THAT(all_done_, Contains("was_run"));
 }
 
 // Deduplicate get field
 
-TEST_F(BatchElementCheckerTest, EventuallyFindAll) {
-  {
-    InSequence seq;
-
-    EXPECT_CALL(mock_web_controller_,
-                OnElementCheck(kExistenceCheck, Eq(Selector({"1"})), _))
-        .WillOnce(RunOnceCallback<2>(true));
-    EXPECT_CALL(mock_web_controller_,
-                OnElementCheck(kExistenceCheck, Eq(Selector({"2"})), _))
-        .WillOnce(RunOnceCallback<2>(false))
-        .WillOnce(RunOnceCallback<2>(true));
-  }
-  checks_.AddElementCheck(kExistenceCheck, Selector({"1"}),
-                          ElementExistenceCallback("1"));
-  checks_.AddElementCheck(kExistenceCheck, Selector({"2"}),
-                          ElementExistenceCallback("2"));
-  checks_.Run(base::TimeDelta::FromSeconds(10), base::DoNothing(),
-              DoneCallback("all_done"));
-
-  // The first try should have run, not fully successful, and should now be
-  // waiting for the second try.
-  EXPECT_TRUE(scoped_task_environment_.NextTaskIsDelayed());
-  EXPECT_THAT(element_exists_results_, Contains(Pair("1", true)));
-  EXPECT_THAT(element_exists_results_, Not(Contains(Key("2"))));
-  EXPECT_THAT(all_done_, Not(Contains("all_done")));
-  EXPECT_FALSE(checks_.all_found());
-
-  // The second try should have found 2 and finished.
-  AdvanceTime();
-  EXPECT_EQ(scoped_task_environment_.GetPendingMainThreadTaskCount(), 0u);
-  EXPECT_THAT(element_exists_results_, Contains(Pair("2", true)));
-  EXPECT_THAT(all_done_, Contains("all_done"));
-  EXPECT_TRUE(checks_.all_found());
-}
-
-TEST_F(BatchElementCheckerTest, EventuallyFindSome) {
-  {
-    InSequence seq;
-
-    EXPECT_CALL(mock_web_controller_,
-                OnElementCheck(kExistenceCheck, Eq(Selector({"1"})), _))
-        .WillOnce(RunOnceCallback<2>(true));
-    EXPECT_CALL(mock_web_controller_,
-                OnElementCheck(kExistenceCheck, Eq(Selector({"2"})), _))
-        .Times(3)
-        .WillRepeatedly(RunOnceCallback<2>(false));
-  }
-  checks_.AddElementCheck(kExistenceCheck, Selector({"1"}),
-                          ElementExistenceCallback("1"));
-  checks_.AddElementCheck(kExistenceCheck, Selector({"2"}),
-                          ElementExistenceCallback("2"));
-  checks_.Run(3 * kTimeUnit, base::DoNothing(), DoneCallback("all_done"));
-
-  // The first try should have run, not fully successful, and should now be
-  // waiting for the second try.
-  EXPECT_TRUE(scoped_task_environment_.NextTaskIsDelayed());
-  EXPECT_THAT(element_exists_results_, Contains(Pair("1", true)));
-  EXPECT_THAT(element_exists_results_, Not(Contains(Key("2"))));
-  EXPECT_THAT(all_done_, Not(Contains("all_done")));
-
-  // The second try still doesn't work'
-  AdvanceTime();
-  EXPECT_TRUE(scoped_task_environment_.NextTaskIsDelayed());
-  EXPECT_THAT(element_exists_results_, Not(Contains(Key("2"))));
-
-  // Give up after the third try
-  AdvanceTime();
-  EXPECT_EQ(scoped_task_environment_.GetPendingMainThreadTaskCount(), 0u);
-  EXPECT_THAT(element_exists_results_, Contains(Pair("2", false)));
-  EXPECT_THAT(all_done_, Contains("all_done"));
-  EXPECT_FALSE(checks_.all_found());
-}
-
-TEST_F(BatchElementCheckerTest, TryDoneCallback) {
-  EXPECT_CALL(mock_web_controller_,
-              OnElementCheck(kExistenceCheck, Eq(Selector({"element"})), _))
-      .WillOnce(RunOnceCallback<2>(false))
-      .WillOnce(RunOnceCallback<2>(true));
-
-  checks_.AddElementCheck(kExistenceCheck, Selector({"element"}),
-                          base::DoNothing());
-  checks_.Run(base::TimeDelta::FromSeconds(10), TryCallback("try"),
-              DoneCallback("all_done"));
-
-  // The first try does not fully succeed.
-  EXPECT_THAT(try_done_, Contains(Pair("try", 1)));
-  EXPECT_THAT(all_done_, Not(Contains("all_done")));
-
-  // The second try succeeds and ends the run.
-  AdvanceTime();
-  EXPECT_THAT(try_done_, Contains(Pair("try", 2)));
-  EXPECT_THAT(all_done_, Contains("all_done"));
-}
-
-TEST_F(BatchElementCheckerTest, TryOnceGivenSmallDuration) {
-  EXPECT_CALL(
-      mock_web_controller_,
-      OnElementCheck(kExistenceCheck, Eq(Selector({"does_not_exist"})), _))
-      .WillOnce(RunOnceCallback<2>(false));
-  checks_.AddElementCheck(kExistenceCheck, Selector({"does_not_exist"}),
-                          ElementExistenceCallback("does_not_exist"));
-
-  checks_.Run(base::TimeDelta::FromMilliseconds(10), base::DoNothing(),
-              DoneCallback("all_done"));
-
-  EXPECT_EQ(scoped_task_environment_.GetPendingMainThreadTaskCount(), 0u);
-  EXPECT_THAT(element_exists_results_, Contains(Pair("does_not_exist", false)));
-  EXPECT_THAT(all_done_, Contains("all_done"));
-  EXPECT_FALSE(checks_.all_found());
-}
-
 }  // namespace
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc
index 906b994..f47a33d 100644
--- a/components/autofill_assistant/browser/controller.cc
+++ b/components/autofill_assistant/browser/controller.cc
@@ -33,7 +33,7 @@
 
 // Time between two periodic script checks.
 static constexpr base::TimeDelta kPeriodicScriptCheckInterval =
-    base::TimeDelta::FromSeconds(2);
+    base::TimeDelta::FromSeconds(1);
 
 // Number of script checks to run after a call to StartPeriodicScriptChecks.
 // This limit does not apply when in autostart mode.
@@ -290,7 +290,7 @@
         url, parameters_,
         base::BindOnce(&Controller::OnGetScripts, base::Unretained(this), url));
   } else {
-    script_tracker()->CheckScripts(kPeriodicScriptCheckInterval);
+    script_tracker()->CheckScripts();
     StartPeriodicScriptChecks();
   }
 }
@@ -334,7 +334,7 @@
     return;
   }
 
-  script_tracker()->CheckScripts(kPeriodicScriptCheckInterval);
+  script_tracker()->CheckScripts();
   base::PostDelayedTaskWithTraits(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&Controller::OnPeriodicScriptCheck,
@@ -389,7 +389,7 @@
   DVLOG(2) << __func__ << " from " << script_domain_ << " returned "
            << scripts.size() << " scripts";
   script_tracker()->SetScripts(std::move(scripts));
-  script_tracker()->CheckScripts(kPeriodicScriptCheckInterval);
+  script_tracker()->CheckScripts();
   StartPeriodicScriptChecks();
 }
 
@@ -604,7 +604,7 @@
 }
 
 void Controller::OnUserInteractionInsideTouchableArea() {
-  script_tracker()->CheckScripts(kPeriodicScriptCheckInterval);
+  script_tracker()->CheckScripts();
   StartPeriodicScriptChecks();
 }
 
diff --git a/components/autofill_assistant/browser/element_precondition_unittest.cc b/components/autofill_assistant/browser/element_precondition_unittest.cc
index c98af57..5b0d6f5 100644
--- a/components/autofill_assistant/browser/element_precondition_unittest.cc
+++ b/components/autofill_assistant/browser/element_precondition_unittest.cc
@@ -50,11 +50,9 @@
   // Runs a precondition given |exists_| and |value_match_|.
   void Check(base::OnceCallback<void(bool)> callback) {
     ElementPrecondition precondition(exist_, value_match_);
-    BatchElementChecker batch_checks(&mock_web_controller_);
+    BatchElementChecker batch_checks;
     precondition.Check(&batch_checks, std::move(callback));
-    batch_checks.Run(base::TimeDelta::FromSeconds(0),
-                     /* try_done=*/base::DoNothing(),
-                     /* all_done=*/base::DoNothing());
+    batch_checks.Run(&mock_web_controller_, base::DoNothing());
   }
 
   MockWebController mock_web_controller_;
diff --git a/components/autofill_assistant/browser/retry_timer.cc b/components/autofill_assistant/browser/retry_timer.cc
new file mode 100644
index 0000000..047f77ea
--- /dev/null
+++ b/components/autofill_assistant/browser/retry_timer.cc
@@ -0,0 +1,70 @@
+// Copyright 2019 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/autofill_assistant/browser/retry_timer.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+
+namespace autofill_assistant {
+
+RetryTimer::RetryTimer(base::TimeDelta period)
+    : period_(period), weak_ptr_factory_(this) {}
+RetryTimer::~RetryTimer() = default;
+
+void RetryTimer::Start(
+    base::TimeDelta max_wait_time,
+    base::RepeatingCallback<void(base::OnceCallback<void(bool)>)> task,
+    base::OnceCallback<void(bool)> on_done) {
+  Reset();
+  task_ = std::move(task);
+  on_done_ = std::move(on_done);
+  if (max_wait_time <= base::TimeDelta::FromSeconds(0)) {
+    remaining_attempts_ = 1;
+  } else {
+    remaining_attempts_ = 1 + max_wait_time / period_;
+  }
+  DCHECK_GE(remaining_attempts_, 1);
+  RunTask();
+}
+
+void RetryTimer::Cancel() {
+  if (!on_done_)
+    return;
+
+  Reset();
+}
+
+void RetryTimer::Reset() {
+  timer_.reset();
+  task_id_++;  // cancels any pending OnTaskDone callbacks
+  task_.Reset();
+  on_done_.Reset();
+}
+
+void RetryTimer::RunTask() {
+  task_.Run(base::BindOnce(&RetryTimer::OnTaskDone,
+                           weak_ptr_factory_.GetWeakPtr(), task_id_));
+}
+
+void RetryTimer::OnTaskDone(int64_t task_id, bool success) {
+  if (task_id != task_id_)  // Ignore callbacks from cancelled tasks
+    return;
+
+  remaining_attempts_--;
+  if (success || remaining_attempts_ <= 0) {
+    CHECK_GE(remaining_attempts_, 0);
+    task_.Reset();  // release any resources held by the callback
+    std::move(on_done_).Run(success);
+    // Don't do anything after calling on_done_, as it could have deleted this.
+    return;
+  }
+  timer_ = std::make_unique<base::OneShotTimer>();
+  timer_->Start(FROM_HERE, period_,
+                base::BindOnce(&RetryTimer::RunTask,
+                               // Safe, since timer_ is owned by this instance
+                               base::Unretained(this)));
+}
+
+}  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/retry_timer.h b/components/autofill_assistant/browser/retry_timer.h
new file mode 100644
index 0000000..8b6b09672
--- /dev/null
+++ b/components/autofill_assistant/browser/retry_timer.h
@@ -0,0 +1,69 @@
+// Copyright 2019 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_AUTOFILL_ASSISTANT_BROWSER_RETRY_TIMER_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_RETRY_TIMER_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+
+namespace autofill_assistant {
+
+// Run an asynchronous task until either the task succeeds or time runs out.
+//
+// RetryTimer cancels the timer when it goes out of scope. This makes it easy to
+// guarantee that the callbacks are not called once the owning object has gone
+// out of scope.
+class RetryTimer {
+ public:
+  // A RetryTimer with the given retry period
+  RetryTimer(base::TimeDelta period);
+  ~RetryTimer();
+
+  // Tries to run |task| once immediately and then periodically until it
+  // either succeeds or times out. Reports the result to |on_done|.
+  //
+  // |task| must report the result to the callback passed to it. Retries are
+  // interrupted until that happens. If |task| never calls its callback, retries
+  // might never happen.
+  //
+  // Calling Start while an attempt is in progress cancels that attempt.
+  // |on_done| for the previous attempt will not be called in that case.
+  //
+  // If |max_wait_time| is 0 or lower than the retry period, the task is
+  // executed exactly once.
+  void Start(base::TimeDelta max_wait_time,
+             base::RepeatingCallback<void(base::OnceCallback<void(bool)>)> task,
+             base::OnceCallback<void(bool)> on_done);
+
+  // Cancels any pending tasks or timer. Any |on_done| callbacks passed to Start
+  // is released without being called.
+  //
+  // Does nothing if to tasks are in progress.
+  void Cancel();
+
+ private:
+  void Reset();
+  void RunTask();
+  void OnTaskDone(int64_t task_id_, bool success);
+
+  const base::TimeDelta period_;
+  int64_t remaining_attempts_ = 1;
+  int64_t task_id_ = 0;
+  base::RepeatingCallback<void(base::OnceCallback<void(bool)>)> task_;
+  base::OnceCallback<void(bool)> on_done_;
+  std::unique_ptr<base::OneShotTimer> timer_;
+
+  base::WeakPtrFactory<RetryTimer> weak_ptr_factory_;
+  DISALLOW_COPY_AND_ASSIGN(RetryTimer);
+};
+
+}  // namespace autofill_assistant
+
+#endif  // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_RETRY_TIMER_H_
diff --git a/components/autofill_assistant/browser/retry_timer_unittest.cc b/components/autofill_assistant/browser/retry_timer_unittest.cc
new file mode 100644
index 0000000..7c9e0b7
--- /dev/null
+++ b/components/autofill_assistant/browser/retry_timer_unittest.cc
@@ -0,0 +1,193 @@
+// Copyright 2019 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/autofill_assistant/browser/retry_timer.h"
+
+#include <map>
+#include <set>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using ::testing::_;
+
+namespace autofill_assistant {
+
+namespace {
+
+class RetryTimerTest : public testing::Test {
+ protected:
+  RetryTimerTest()
+      : scoped_task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+
+  void FastForwardOneSecond() {
+    scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  }
+
+  base::RepeatingCallback<void(base::OnceCallback<void(bool)>)>
+  AlwaysFailsCallback() {
+    return base::BindRepeating(&RetryTimerTest::AlwaysFails,
+                               base::Unretained(this));
+  }
+
+  void AlwaysFails(base::OnceCallback<void(bool)> callback) {
+    try_count_++;
+    std::move(callback).Run(false);
+  }
+
+  base::RepeatingCallback<void(base::OnceCallback<void(bool)>)>
+  SucceedsOnceCallback(int succeds_at) {
+    return base::BindRepeating(&RetryTimerTest::SucceedsOnce,
+                               base::Unretained(this), succeds_at);
+  }
+
+  void SucceedsOnce(int succeeds_at, base::OnceCallback<void(bool)> callback) {
+    EXPECT_GE(succeeds_at, try_count_);
+    bool success = succeeds_at == try_count_;
+    try_count_++;
+    std::move(callback).Run(success);
+  }
+
+  base::RepeatingCallback<void(base::OnceCallback<void(bool)>)>
+  CaptureCallback() {
+    return base::BindRepeating(&RetryTimerTest::Capture,
+                               base::Unretained(this));
+  }
+
+  void Capture(base::OnceCallback<void(bool)> callback) {
+    try_count_++;
+    captured_callback_ = std::move(callback);
+  }
+
+  // scoped_task_environment_ must be first to guarantee other field
+  // creation run in that environment.
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+  int try_count_ = 0;
+  base::OnceCallback<void(bool)> captured_callback_;
+  base::MockCallback<base::OnceCallback<void(bool)>> done_callback_;
+};
+
+TEST_F(RetryTimerTest, TryOnceAndSucceed) {
+  RetryTimer retry_timer(base::TimeDelta::FromSeconds(1));
+  EXPECT_CALL(done_callback_, Run(true));
+  retry_timer.Start(base::TimeDelta::FromSeconds(10), SucceedsOnceCallback(0),
+                    done_callback_.Get());
+  EXPECT_EQ(1, try_count_);
+}
+
+TEST_F(RetryTimerTest, TryOnceAndFail) {
+  RetryTimer retry_timer(base::TimeDelta::FromSeconds(1));
+  EXPECT_CALL(done_callback_, Run(false));
+  retry_timer.Start(base::TimeDelta::FromSeconds(0), AlwaysFailsCallback(),
+                    done_callback_.Get());
+  EXPECT_EQ(1, try_count_);
+}
+
+TEST_F(RetryTimerTest, TryMultipleTimesAndSucceed) {
+  RetryTimer retry_timer(base::TimeDelta::FromSeconds(1));
+  retry_timer.Start(base::TimeDelta::FromSeconds(10), SucceedsOnceCallback(2),
+                    done_callback_.Get());
+  EXPECT_EQ(1, try_count_);
+  FastForwardOneSecond();
+  EXPECT_EQ(2, try_count_);
+  EXPECT_CALL(done_callback_, Run(true));
+  FastForwardOneSecond();
+  EXPECT_EQ(3, try_count_);
+}
+
+TEST_F(RetryTimerTest, TryMultipleTimesAndFail) {
+  RetryTimer retry_timer(base::TimeDelta::FromSeconds(1));
+  retry_timer.Start(base::TimeDelta::FromSeconds(2), AlwaysFailsCallback(),
+                    done_callback_.Get());
+  EXPECT_EQ(1, try_count_);
+  FastForwardOneSecond();
+  EXPECT_EQ(2, try_count_);
+  EXPECT_CALL(done_callback_, Run(false));
+  FastForwardOneSecond();
+  EXPECT_EQ(3, try_count_);
+}
+
+TEST_F(RetryTimerTest, Cancel) {
+  EXPECT_CALL(done_callback_, Run(_)).Times(0);
+  RetryTimer retry_timer(base::TimeDelta::FromSeconds(1));
+  retry_timer.Start(base::TimeDelta::FromSeconds(10), AlwaysFailsCallback(),
+                    done_callback_.Get());
+  EXPECT_EQ(1, try_count_);
+  retry_timer.Cancel();
+  FastForwardOneSecond();  // nothing should happen
+}
+
+TEST_F(RetryTimerTest, CancelWithPendingCallbacks) {
+  EXPECT_CALL(done_callback_, Run(_)).Times(0);
+  RetryTimer retry_timer(base::TimeDelta::FromSeconds(1));
+  retry_timer.Start(base::TimeDelta::FromSeconds(10), CaptureCallback(),
+                    done_callback_.Get());
+  ASSERT_TRUE(captured_callback_);
+  retry_timer.Cancel();
+  std::move(captured_callback_).Run(true);  // Should do nothing
+}
+
+TEST_F(RetryTimerTest, GiveUpWhenLeavingScope) {
+  EXPECT_CALL(done_callback_, Run(_)).Times(0);
+  {
+    RetryTimer retry_timer(base::TimeDelta::FromSeconds(1));
+    retry_timer.Start(base::TimeDelta::FromSeconds(10), AlwaysFailsCallback(),
+                      done_callback_.Get());
+    EXPECT_EQ(1, try_count_);
+  }
+  FastForwardOneSecond();  // nothing should happen
+}
+
+TEST_F(RetryTimerTest, GiveUpWhenLeavingScopeWithPendingCallback) {
+  EXPECT_CALL(done_callback_, Run(_)).Times(0);
+  {
+    RetryTimer retry_timer(base::TimeDelta::FromSeconds(1));
+    retry_timer.Start(base::TimeDelta::FromSeconds(10), CaptureCallback(),
+                      done_callback_.Get());
+    ASSERT_TRUE(captured_callback_);
+  }
+  std::move(captured_callback_).Run(true);  // Should do nothing
+}
+
+TEST_F(RetryTimerTest, RestartOverridesFirstCall) {
+  EXPECT_CALL(done_callback_, Run(_)).Times(0);
+
+  RetryTimer retry_timer(base::TimeDelta::FromSeconds(1));
+  retry_timer.Start(base::TimeDelta::FromSeconds(1), AlwaysFailsCallback(),
+                    done_callback_.Get());
+  base::MockCallback<base::OnceCallback<void(bool)>> done_callback2;
+  retry_timer.Start(base::TimeDelta::FromSeconds(1), AlwaysFailsCallback(),
+                    done_callback2.Get());
+  EXPECT_EQ(2, try_count_);
+  EXPECT_CALL(done_callback2, Run(false));
+  FastForwardOneSecond();
+  EXPECT_EQ(3, try_count_);
+}
+
+TEST_F(RetryTimerTest, RestartOverridesFirstCallWithPendingTask) {
+  EXPECT_CALL(done_callback_, Run(_)).Times(0);
+
+  RetryTimer retry_timer(base::TimeDelta::FromSeconds(1));
+  retry_timer.Start(base::TimeDelta::FromSeconds(1), CaptureCallback(),
+                    done_callback_.Get());
+  ASSERT_TRUE(captured_callback_);
+
+  base::MockCallback<base::OnceCallback<void(bool)>> done_callback2;
+  retry_timer.Start(base::TimeDelta::FromSeconds(1), AlwaysFailsCallback(),
+                    done_callback2.Get());
+
+  std::move(captured_callback_).Run(true);  // Should do nothing
+
+  EXPECT_CALL(done_callback2, Run(false));
+  FastForwardOneSecond();
+  EXPECT_EQ(3, try_count_);
+}
+
+}  // namespace
+}  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index 84fa223..81ab9ce 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -35,6 +35,10 @@
 constexpr base::TimeDelta kShortWaitForElementDeadline =
     base::TimeDelta::FromSeconds(2);
 
+// Time between two element checks.
+static constexpr base::TimeDelta kPeriodicElementCheck =
+    base::TimeDelta::FromSeconds(1);
+
 std::ostream& operator<<(std::ostream& out,
                          const ScriptExecutor::AtEnd& at_end) {
 #ifdef NDEBUG
@@ -89,6 +93,7 @@
       previous_action_type_(ActionProto::ACTION_INFO_NOT_SET),
       scripts_state_(scripts_state),
       ordered_interrupts_(ordered_interrupts),
+      retry_timer_(kPeriodicElementCheck),
       weak_ptr_factory_(this) {
   DCHECK(delegate_);
   DCHECK(ordered_interrupts_);
@@ -113,9 +118,9 @@
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
-std::unique_ptr<BatchElementChecker>
-ScriptExecutor::CreateBatchElementChecker() {
-  return delegate_->GetWebController()->CreateBatchElementChecker();
+void ScriptExecutor::RunElementChecks(BatchElementChecker* checker,
+                                      base::OnceCallback<void()> all_done) {
+  return checker->Run(delegate_->GetWebController(), std::move(all_done));
 }
 
 void ScriptExecutor::ShortWaitForElement(
@@ -460,7 +465,6 @@
 }
 
 void ScriptExecutor::RunCallback(bool success) {
-  DCHECK(callback_);
   if (should_clean_contextual_ui_on_finish_ || !success) {
     SetDetails(nullptr);
     should_clean_contextual_ui_on_finish_ = false;
@@ -475,6 +479,7 @@
 }
 
 void ScriptExecutor::RunCallbackWithResult(const Result& result) {
+  DCHECK(callback_);
   (*scripts_state_)[script_path_] =
       result.success ? SCRIPT_STATUS_SUCCESS : SCRIPT_STATUS_FAILURE;
   std::move(callback_).Run(result);
@@ -544,20 +549,19 @@
                                     ElementCheckType check_type,
                                     const Selector& selector,
                                     base::OnceCallback<void(bool)> callback) {
-  DCHECK(!batch_element_checker_);
-  batch_element_checker_ = CreateBatchElementChecker();
-  batch_element_checker_->AddElementCheck(check_type, selector,
-                                          base::DoNothing());
-  batch_element_checker_->Run(
-      max_wait_time, /* try_done= */ base::DoNothing(), /* all_done= */
-      base::BindOnce(&ScriptExecutor::OnWaitForElement,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  retry_timer_.Start(
+      max_wait_time,
+      base::BindRepeating(&ScriptExecutor::CheckForElement,
+                          weak_ptr_factory_.GetWeakPtr(), check_type, selector),
+      std::move(callback));
 }
 
-void ScriptExecutor::OnWaitForElement(base::OnceCallback<void(bool)> callback) {
-  bool all_found = batch_element_checker_->all_found();
-  batch_element_checker_.reset();
-  std::move(callback).Run(all_found);
+void ScriptExecutor::CheckForElement(ElementCheckType check_type,
+                                     const Selector& selector,
+                                     base::OnceCallback<void(bool)> callback) {
+  delegate_->GetWebController()->ElementCheck(check_type, selector,
+                                              /* strict= */ false,
+                                              std::move(callback));
 }
 
 void ScriptExecutor::OnWaitForElementVisibleWithInterrupts(
@@ -599,17 +603,40 @@
       check_type_(check_type),
       selector_(selector),
       callback_(std::move(callback)),
+      retry_timer_(kPeriodicElementCheck),
       weak_ptr_factory_(this) {}
 
 ScriptExecutor::WaitWithInterrupts::~WaitWithInterrupts() = default;
 
 void ScriptExecutor::WaitWithInterrupts::Run() {
+  retry_timer_.Start(
+      max_wait_time_,
+      base::BindRepeating(&ScriptExecutor::WaitWithInterrupts::RunChecks,
+                          // safe since this instance owns retry_timer_
+                          base::Unretained(this)),
+      base::BindOnce(&ScriptExecutor::WaitWithInterrupts::RunCallback,
+                     base::Unretained(this)));
+}
+
+void ScriptExecutor::WaitWithInterrupts::OnServerPayloadChanged(
+    const std::string& global_payload,
+    const std::string& script_payload) {
+  // Interrupts and main scripts share global payloads, but not script payloads.
+  main_script_->last_global_payload_ = global_payload;
+  main_script_->ReportPayloadsToListener();
+}
+
+void ScriptExecutor::WaitWithInterrupts::OnScriptListChanged(
+    std::vector<std::unique_ptr<Script>> scripts) {
+  main_script_->ReportScriptsUpdateToListener(std::move(scripts));
+}
+
+void ScriptExecutor::WaitWithInterrupts::RunChecks(
+    base::OnceCallback<void(bool)> report_attempt_result) {
   // Reset state possibly left over from previous runs.
   element_found_ = false;
   runnable_interrupts_.clear();
-  batch_element_checker_ =
-      main_script_->delegate_->GetWebController()->CreateBatchElementChecker();
-
+  batch_element_checker_ = std::make_unique<BatchElementChecker>();
   batch_element_checker_->AddElementCheck(
       check_type_, selector_,
       base::BindOnce(&WaitWithInterrupts::OnElementCheckDone,
@@ -631,24 +658,9 @@
   // main script, which own this instance.
 
   batch_element_checker_->Run(
-      max_wait_time_,
-      base::BindRepeating(&WaitWithInterrupts::OnTryDone,
-                          weak_ptr_factory_.GetWeakPtr()),
-      base::BindOnce(&WaitWithInterrupts::OnAllDone,
-                     weak_ptr_factory_.GetWeakPtr()));
-}
-
-void ScriptExecutor::WaitWithInterrupts::OnServerPayloadChanged(
-    const std::string& global_payload,
-    const std::string& script_payload) {
-  // Interrupts and main scripts share global payloads, but not script payloads.
-  main_script_->last_global_payload_ = global_payload;
-  main_script_->ReportPayloadsToListener();
-}
-
-void ScriptExecutor::WaitWithInterrupts::OnScriptListChanged(
-    std::vector<std::unique_ptr<Script>> scripts) {
-  main_script_->ReportScriptsUpdateToListener(std::move(scripts));
+      main_script_->delegate_->GetWebController(),
+      base::BindOnce(&WaitWithInterrupts::OnAllChecksDone,
+                     base::Unretained(this), std::move(report_attempt_result)));
 }
 
 void ScriptExecutor::WaitWithInterrupts::OnPreconditionCheckDone(
@@ -664,7 +676,8 @@
   // the caller, so interrupts have a chance to run.
 }
 
-void ScriptExecutor::WaitWithInterrupts::OnTryDone() {
+void ScriptExecutor::WaitWithInterrupts::OnAllChecksDone(
+    base::OnceCallback<void(bool)> report_attempt_result) {
   if (!runnable_interrupts_.empty()) {
     // We must go through runnable_interrupts_ to make sure priority order is
     // respected in case more than one interrupt is ready to run.
@@ -675,16 +688,7 @@
       }
     }
   }
-
-  if (element_found_)
-    RunCallback(true, nullptr);
-}
-
-void ScriptExecutor::WaitWithInterrupts::OnAllDone() {
-  // This means that we've reached the end of the timeout. Report whether we
-  // found the element unless an interrupt has just been started by OnTryDone.
-  if (!interrupt_executor_)
-    RunCallback(element_found_, nullptr);
+  std::move(report_attempt_result).Run(element_found_);
 }
 
 void ScriptExecutor::WaitWithInterrupts::RunInterrupt(const Script* interrupt) {
@@ -706,7 +710,7 @@
     const ScriptExecutor::Result& result) {
   interrupt_executor_.reset();
   if (!result.success || result.at_end != ScriptExecutor::CONTINUE) {
-    RunCallback(false, &result);
+    RunCallbackWithResult(false, &result);
     return;
   }
   RestoreStatusMessage();
@@ -717,11 +721,16 @@
   Run();
 }
 
-void ScriptExecutor::WaitWithInterrupts::RunCallback(
+void ScriptExecutor::WaitWithInterrupts::RunCallback(bool found) {
+  RunCallbackWithResult(found, nullptr);
+}
+
+void ScriptExecutor::WaitWithInterrupts::RunCallbackWithResult(
     bool found,
     const ScriptExecutor::Result* result) {
   // stop element checking if one is still in progress
   batch_element_checker_.reset();
+  retry_timer_.Cancel();
   if (!callback_)
     return;
 
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h
index 1726b350..2eba69a 100644
--- a/components/autofill_assistant/browser/script_executor.h
+++ b/components/autofill_assistant/browser/script_executor.h
@@ -19,6 +19,7 @@
 #include "components/autofill_assistant/browser/actions/action_delegate.h"
 #include "components/autofill_assistant/browser/details.h"
 #include "components/autofill_assistant/browser/info_box.h"
+#include "components/autofill_assistant/browser/retry_timer.h"
 #include "components/autofill_assistant/browser/script.h"
 #include "components/autofill_assistant/browser/script_executor_delegate.h"
 #include "components/autofill_assistant/browser/service.pb.h"
@@ -101,7 +102,8 @@
   void Terminate();
 
   // Override ActionDelegate:
-  std::unique_ptr<BatchElementChecker> CreateBatchElementChecker() override;
+  void RunElementChecks(BatchElementChecker* checker,
+                        base::OnceCallback<void()> all_done) override;
   void ShortWaitForElement(ElementCheckType check_type,
                            const Selector& selector,
                            base::OnceCallback<void(bool)> callback) override;
@@ -208,14 +210,16 @@
     void OnScriptListChanged(
         std::vector<std::unique_ptr<Script>> scripts) override;
 
+    void RunChecks(base::OnceCallback<void(bool)> report_attempt_result);
     void OnPreconditionCheckDone(const Script* interrupt,
                                  bool precondition_match);
     void OnElementCheckDone(bool found);
-    void OnTryDone();
-    void OnAllDone();
+    void OnAllChecksDone(base::OnceCallback<void(bool)> report_attempt_result);
     void RunInterrupt(const Script* interrupt);
     void OnInterruptDone(const ScriptExecutor::Result& result);
-    void RunCallback(bool found, const ScriptExecutor::Result* result);
+    void RunCallback(bool found);
+    void RunCallbackWithResult(bool found,
+                               const ScriptExecutor::Result* result);
 
     // Saves the current state and sets save_pre_interrupt_state_.
     void SavePreInterruptState();
@@ -254,6 +258,8 @@
     // Paths of the interrupts that were run during the current action.
     std::set<std::string> ran_interrupts_;
 
+    RetryTimer retry_timer_;
+
     base::WeakPtrFactory<WaitWithInterrupts> weak_ptr_factory_;
 
     DISALLOW_COPY_AND_ASSIGN(WaitWithInterrupts);
@@ -275,7 +281,9 @@
                       ElementCheckType check_type,
                       const Selector& selectors,
                       base::OnceCallback<void(bool)> callback);
-  void OnWaitForElement(base::OnceCallback<void(bool)> callback);
+  void CheckForElement(ElementCheckType check_type,
+                       const Selector& selectors,
+                       base::OnceCallback<void(bool)> callback);
   void OnWaitForElementVisibleWithInterrupts(
       base::OnceCallback<void(ProcessedActionStatusProto)> callback,
       bool element_found,
@@ -326,6 +334,8 @@
   // without selecting any chips. nullptr unless showing a prompt.
   base::OnceCallback<void()> on_terminate_prompt_;
 
+  RetryTimer retry_timer_;
+
   base::WeakPtrFactory<ScriptExecutor> weak_ptr_factory_;
   DISALLOW_COPY_AND_ASSIGN(ScriptExecutor);
 };
diff --git a/components/autofill_assistant/browser/script_precondition_unittest.cc b/components/autofill_assistant/browser/script_precondition_unittest.cc
index fd7a02c..e4280cf 100644
--- a/components/autofill_assistant/browser/script_precondition_unittest.cc
+++ b/components/autofill_assistant/browser/script_precondition_unittest.cc
@@ -76,12 +76,10 @@
       return false;
 
     DirectCallback callback;
-    BatchElementChecker batch_checks(&mock_web_controller_);
+    BatchElementChecker batch_checks;
     precondition->Check(url_, &batch_checks, parameters_, executed_scripts_,
                         callback.Get());
-    batch_checks.Run(base::TimeDelta::FromSeconds(0),
-                     /* try_done=*/base::DoNothing(),
-                     /* all_done=*/base::DoNothing());
+    batch_checks.Run(&mock_web_controller_, /* all_done=*/base::DoNothing());
     return callback.GetResultOrDie();
   }
 
diff --git a/components/autofill_assistant/browser/script_tracker.cc b/components/autofill_assistant/browser/script_tracker.cc
index 104ec31..211729a 100644
--- a/components/autofill_assistant/browser/script_tracker.cc
+++ b/components/autofill_assistant/browser/script_tracker.cc
@@ -66,15 +66,14 @@
   SortScripts(&interrupts_);
 }
 
-void ScriptTracker::CheckScripts(const base::TimeDelta& max_duration) {
+void ScriptTracker::CheckScripts() {
   // In case checks are still running, terminate them.
   TerminatePendingChecks();
 
   DCHECK(pending_runnable_scripts_.empty());
 
   GURL url = delegate_->GetCurrentURL();
-  batch_element_checker_ =
-      delegate_->GetWebController()->CreateBatchElementChecker();
+  batch_element_checker_ = std::make_unique<BatchElementChecker>();
   for (const auto& entry : available_scripts_) {
     Script* script = entry.first;
     if (script->handle.name.empty() && !script->handle.autostart)
@@ -86,25 +85,20 @@
         base::BindOnce(&ScriptTracker::OnPreconditionCheck,
                        weak_ptr_factory_.GetWeakPtr(), script));
   }
-  if (batch_element_checker_->all_found() &&
-      pending_runnable_scripts_.empty() && !available_scripts_.empty()) {
+  if (batch_element_checker_->empty() && pending_runnable_scripts_.empty() &&
+      !available_scripts_.empty()) {
     DVLOG(1) << __func__ << ": No runnable scripts for " << url << " out of "
              << available_scripts_.size() << " available.";
     // There are no runnable scripts, even though we haven't checked the DOM
     // yet. Report it all immediately.
     UpdateRunnableScriptsIfNecessary();
     listener_->OnNoRunnableScripts();
-    OnCheckDone();
+    TerminatePendingChecks();
     return;
   }
-  batch_element_checker_->Run(
-      max_duration,
-      /* try_done= */
-      base::BindRepeating(&ScriptTracker::UpdateRunnableScriptsIfNecessary,
-                          weak_ptr_factory_.GetWeakPtr()),
-      /* all_done= */
-      base::BindOnce(&ScriptTracker::OnCheckDone,
-                     weak_ptr_factory_.GetWeakPtr()));
+  batch_element_checker_->Run(delegate_->GetWebController(),
+                              base::BindOnce(&ScriptTracker::OnCheckDone,
+                                             weak_ptr_factory_.GetWeakPtr()));
 }
 
 void ScriptTracker::ExecuteScript(const std::string& script_path,
@@ -196,6 +190,11 @@
   }
 }
 
+void ScriptTracker::OnCheckDone() {
+  UpdateRunnableScriptsIfNecessary();
+  TerminatePendingChecks();
+}
+
 void ScriptTracker::UpdateRunnableScriptsIfNecessary() {
   if (!RunnablesHaveChanged())
     return;
@@ -209,10 +208,6 @@
   listener_->OnRunnableScriptsChanged(runnable_scripts_);
 }
 
-void ScriptTracker::OnCheckDone() {
-  TerminatePendingChecks();
-}
-
 void ScriptTracker::TerminatePendingChecks() {
   batch_element_checker_.reset();
   pending_runnable_scripts_.clear();
diff --git a/components/autofill_assistant/browser/script_tracker.h b/components/autofill_assistant/browser/script_tracker.h
index fdec2a4c..fd436937 100644
--- a/components/autofill_assistant/browser/script_tracker.h
+++ b/components/autofill_assistant/browser/script_tracker.h
@@ -66,7 +66,7 @@
   //
   // Calling CheckScripts() while a check is in progress cancels the previously
   // running check and starts a new one right away.
-  void CheckScripts(const base::TimeDelta& max_duration);
+  void CheckScripts();
 
   // Runs a script and reports, when the script has ended, whether the run was
   // successful. Fails immediately if a script is already running.
@@ -110,18 +110,12 @@
   void OnScriptRun(const std::string& script_path,
                    ScriptExecutor::RunScriptCallback original_callback,
                    const ScriptExecutor::Result& result);
-  void UpdateRunnableScriptsIfNecessary();
-  void OnCheckDone();
 
   // Updates the list of available scripts if there is a pending update from
   // when a script was still being executed.
   void MaybeSwapInScripts();
-
-  // Overrides ScriptExecutor::Listener.
-  void OnServerPayloadChanged(const std::string& global_payload,
-                              const std::string& script_payload) override;
-  void OnScriptListChanged(
-      std::vector<std::unique_ptr<Script>> scripts) override;
+  void OnCheckDone();
+  void UpdateRunnableScriptsIfNecessary();
 
   // Stops running pending checks and cleans up any state used by pending
   // checks. This can safely be called at any time, including when no checks are
@@ -132,6 +126,12 @@
   bool RunnablesHaveChanged();
   void OnPreconditionCheck(Script* script, bool met_preconditions);
 
+  // Overrides ScriptExecutor::Listener.
+  void OnServerPayloadChanged(const std::string& global_payload,
+                              const std::string& script_payload) override;
+  void OnScriptListChanged(
+      std::vector<std::unique_ptr<Script>> scripts) override;
+
   ScriptExecutorDelegate* const delegate_;
   ScriptTracker::Listener* const listener_;
 
diff --git a/components/autofill_assistant/browser/script_tracker_unittest.cc b/components/autofill_assistant/browser/script_tracker_unittest.cc
index 9e4cbad..17ae136 100644
--- a/components/autofill_assistant/browser/script_tracker_unittest.cc
+++ b/components/autofill_assistant/browser/script_tracker_unittest.cc
@@ -73,7 +73,7 @@
       ProtocolUtils::AddScript(*script_proto, &scripts);
     }
     tracker_.SetScripts(std::move(scripts));
-    tracker_.CheckScripts(base::TimeDelta::FromSeconds(0));
+    tracker_.CheckScripts();
   }
 
   SupportedScriptProto* AddScript() {
@@ -138,7 +138,7 @@
 
 TEST_F(ScriptTrackerTest, NoScripts) {
   tracker_.SetScripts({});
-  tracker_.CheckScripts(base::TimeDelta::FromSeconds(0));
+  tracker_.CheckScripts();
   EXPECT_THAT(runnable_scripts(), IsEmpty());
   EXPECT_EQ(0, runnable_scripts_changed_);
   EXPECT_EQ(0, no_runnable_scripts_anymore_);
@@ -269,7 +269,7 @@
               Run(Field(&ScriptExecutor::Result::success, true)));
 
   tracker_.ExecuteScript("script1", execute_callback.Get());
-  tracker_.CheckScripts(base::TimeDelta::FromSeconds(0));
+  tracker_.CheckScripts();
 
   // The 2nd time the scripts are checked, automatically after the script runs,
   // 'script1' isn't runnable anymore, because it's already been run.
@@ -294,7 +294,7 @@
       mock_web_controller_,
       OnElementCheck(kExistenceCheck, Eq(Selector({"maybe_exists"})), _))
       .WillOnce(RunOnceCallback<2>(true));
-  tracker_.CheckScripts(base::TimeDelta::FromSeconds(0));
+  tracker_.CheckScripts();
 
   // The script can now run
   ASSERT_THAT(runnable_script_paths(), ElementsAre("script path"));
@@ -329,7 +329,7 @@
   EXPECT_CALL(execute_callback,
               Run(Field(&ScriptExecutor::Result::success, true)));
   tracker_.ExecuteScript("runnable name", execute_callback.Get());
-  tracker_.CheckScripts(base::TimeDelta::FromSeconds(0));
+  tracker_.CheckScripts();
 
   // 3. Verify that the runnable scripts have changed to the updated list.
   EXPECT_EQ(2, runnable_scripts_changed_);
@@ -371,7 +371,7 @@
   EXPECT_CALL(execute_callback,
               Run(Field(&ScriptExecutor::Result::success, true)));
   tracker_.ExecuteScript("runnable name", execute_callback.Get());
-  tracker_.CheckScripts(base::TimeDelta::FromSeconds(0));
+  tracker_.CheckScripts();
 
   // 3. Verify that the runnable scripts have changed to the updated list.
   EXPECT_EQ(2, runnable_scripts_changed_);
diff --git a/components/autofill_assistant/browser/web_controller.cc b/components/autofill_assistant/browser/web_controller.cc
index 3ecb899..d8f76aff 100644
--- a/components/autofill_assistant/browser/web_controller.cc
+++ b/components/autofill_assistant/browser/web_controller.cc
@@ -295,6 +295,7 @@
   object_id_ = element_object_id;
   callback_ = std::move(callback);
   remaining_rounds_ = kPeriodicCheckRounds;
+  // TODO(crbug/806868): Consider using autofill_assistant::RetryTimer
 
   // Wait for a roundtrips through the renderer and compositor pipeline,
   // otherwise touch event may be dropped because of missing handler.
@@ -1557,11 +1558,6 @@
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-std::unique_ptr<BatchElementChecker>
-WebController::CreateBatchElementChecker() {
-  return std::make_unique<BatchElementChecker>(this);
-}
-
 void WebController::GetElementPosition(
     const Selector& selector,
     base::OnceCallback<void(bool, const RectF&)> callback) {
diff --git a/components/autofill_assistant/browser/web_controller.h b/components/autofill_assistant/browser/web_controller.h
index a6cae588..934b577 100644
--- a/components/autofill_assistant/browser/web_controller.h
+++ b/components/autofill_assistant/browser/web_controller.h
@@ -135,9 +135,6 @@
       base::OnceCallback<void(const ClientStatus&, const std::string&)>
           callback);
 
-  // Create a helper for checking element existence and field value.
-  virtual std::unique_ptr<BatchElementChecker> CreateBatchElementChecker();
-
   // Gets the position of the element identified by the selector.
   //
   // If unsuccessful, the callback gets (false, 0, 0, 0, 0).
@@ -156,9 +153,6 @@
   virtual void HasCookie(base::OnceCallback<void(bool)> callback);
   virtual void ClearCookie();
 
- protected:
-  friend class BatchElementChecker;
-
   // Checks an element for:
   //
   // kExistenceCheck: Checks whether at least one element given by |selector|
@@ -169,7 +163,7 @@
   //
   // If strict, there must be exactly one element.
   //
-  // Normally done through BatchElementChecker.
+  // To check multiple elements, use a BatchElementChecker.
   virtual void ElementCheck(ElementCheckType type,
                             const Selector& selector,
                             bool strict,
@@ -179,7 +173,7 @@
   // returned value might be false, if the element cannot be found, true and the
   // empty string in case of error or empty value.
   //
-  // Normally done through BatchElementChecker.
+  // To get the value of multiple elements, use a BatchElementChecker.
   virtual void GetFieldValue(
       const Selector& selector,
       base::OnceCallback<void(bool, const std::string&)> callback);
diff --git a/components/browser_sync/BUILD.gn b/components/browser_sync/BUILD.gn
index afeab29..9ee54ee 100644
--- a/components/browser_sync/BUILD.gn
+++ b/components/browser_sync/BUILD.gn
@@ -26,21 +26,14 @@
     "//components/autofill/core/browser",
     "//components/autofill/core/common",
     "//components/history/core/browser",
-    "//components/invalidation/impl",
-    "//components/invalidation/public",
     "//components/password_manager/core/browser",
     "//components/prefs",
     "//components/reading_list/features:flags",
     "//components/send_tab_to_self",
-    "//components/signin/core/browser",
     "//components/sync_bookmarks",
     "//components/sync_sessions",
     "//components/version_info",
     "//components/version_info:generate_version_info",
-    "//google_apis",
-    "//net",
-    "//services/identity/public/cpp",
-    "//services/network/public/cpp",
   ]
 }
 
@@ -50,8 +43,6 @@
   sources = [
     "profile_sync_service_autofill_unittest.cc",
     "profile_sync_service_bookmark_unittest.cc",
-    "profile_sync_service_startup_unittest.cc",
-    "profile_sync_service_unittest.cc",
   ]
 
   deps = [
@@ -65,11 +56,7 @@
     "//components/bookmarks/managed",
     "//components/bookmarks/test",
     "//components/history/core/browser",
-    "//components/invalidation/impl",
-    "//components/invalidation/public",
     "//components/prefs",
-    "//components/signin/core/browser",
-    "//components/signin/core/browser:internals_test_support",
     "//components/sync",
     "//components/sync:test_support_driver",
     "//components/sync:test_support_engine",
@@ -83,11 +70,8 @@
     "//components/version_info:generate_version_info",
     "//components/webdata/common",
     "//components/webdata_services:test_support",
-    "//google_apis",
-    "//net",
     "//services/identity/public/cpp:test_support",
     "//services/network:test_support",
-    "//services/network/public/cpp",
     "//testing/gmock",
     "//testing/gtest",
   ]
@@ -98,8 +82,6 @@
   sources = [
     "abstract_profile_sync_service_test.cc",
     "abstract_profile_sync_service_test.h",
-    "profile_sync_test_util.cc",
-    "profile_sync_test_util.h",
     "test_http_bridge_factory.cc",
     "test_http_bridge_factory.h",
   ]
@@ -110,9 +92,6 @@
     "//base/test:test_support",
     "//components/bookmarks/browser",
     "//components/history/core/browser",
-    "//components/invalidation/impl",
-    "//components/invalidation/impl:test_support",
-    "//components/pref_registry",
     "//components/signin/core/browser",
     "//components/signin/core/browser:internals_test_support",
     "//components/sync",
@@ -121,12 +100,7 @@
     "//components/sync:test_support_model",
     "//components/sync_preferences:test_support",
     "//components/sync_sessions:test_support",
-    "//google_apis",
-    "//net:test_support",
-    "//services/identity/public/cpp",
     "//services/identity/public/cpp:test_support",
     "//services/network:test_support",
-    "//services/network/public/cpp",
-    "//testing/gmock",
   ]
 }
diff --git a/components/browser_sync/DEPS b/components/browser_sync/DEPS
index 83aedd9..179495cf 100644
--- a/components/browser_sync/DEPS
+++ b/components/browser_sync/DEPS
@@ -4,21 +4,11 @@
   "+components/bookmarks/managed",
   "+components/bookmarks/test",
   "+components/history/core/browser",
-  "+components/invalidation",
   "+components/keyed_service/core",
   "+components/password_manager/core/browser",
-  "+components/pref_registry",
   "+components/prefs",
   "+components/reading_list/features",
   "+components/send_tab_to_self",
-  "+components/signin/core/browser",
-  # Use identity_manager.h instead of the below files;
-  # see https://groups.google.com/a/chromium.org/d/msg/chromium-dev/dgFLuxqZt1o/iEqkyoQQBwAJ for help and info.
-  "-components/signin/core/browser/fake_profile_oauth2_token_service.h",
-  "-components/signin/core/browser/profile_oauth2_token_service.h",
-  "-components/signin/core/browser/fake_signin_manager.h",
-  "-components/signin/core/browser/signin_manager.h",
-  "-components/signin/core/browser/signin_manager_base.h",
   "+components/sync",
   "+components/sync_bookmarks",
   "+components/sync_preferences",
@@ -26,9 +16,6 @@
   "+components/version_info",
   "+components/webdata/common",
   "+components/webdata_services",
-  "+google_apis",
-  "+net",
   "+services/identity/public/cpp",
-  "+services/network/public/cpp",
   "+services/network/test",
 ]
diff --git a/components/browser_sync/abstract_profile_sync_service_test.cc b/components/browser_sync/abstract_profile_sync_service_test.cc
index b63af75..8b39f65 100644
--- a/components/browser_sync/abstract_profile_sync_service_test.cc
+++ b/components/browser_sync/abstract_profile_sync_service_test.cc
@@ -130,9 +130,9 @@
     std::unique_ptr<syncer::SyncClient> sync_client,
     base::OnceClosure initialization_success_callback) {
   ASSERT_TRUE(sync_client);
-  ProfileSyncService::InitParams init_params =
+  syncer::ProfileSyncService::InitParams init_params =
       profile_sync_service_bundle_.CreateBasicInitParams(
-          ProfileSyncService::AUTO_START, std::move(sync_client));
+          syncer::ProfileSyncService::AUTO_START, std::move(sync_client));
   sync_service_ =
       std::make_unique<syncer::TestProfileSyncService>(std::move(init_params));
 
diff --git a/components/browser_sync/abstract_profile_sync_service_test.h b/components/browser_sync/abstract_profile_sync_service_test.h
index 95d9d84..deb622f 100644
--- a/components/browser_sync/abstract_profile_sync_service_test.h
+++ b/components/browser_sync/abstract_profile_sync_service_test.h
@@ -11,8 +11,8 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/test/scoped_task_environment.h"
-#include "components/browser_sync/profile_sync_test_util.h"
 #include "components/sync/base/model_type.h"
+#include "components/sync/driver/profile_sync_service_bundle.h"
 #include "components/sync/syncable/change_record.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -42,7 +42,7 @@
 
   syncer::TestProfileSyncService* sync_service() { return sync_service_.get(); }
 
-  ProfileSyncServiceBundle* profile_sync_service_bundle() {
+  syncer::ProfileSyncServiceBundle* profile_sync_service_bundle() {
     return &profile_sync_service_bundle_;
   }
 
@@ -51,7 +51,7 @@
   base::Thread data_type_thread_;
 
   base::test::ScopedTaskEnvironment scoped_task_environment_;
-  ProfileSyncServiceBundle profile_sync_service_bundle_;
+  syncer::ProfileSyncServiceBundle profile_sync_service_bundle_;
   std::unique_ptr<syncer::TestProfileSyncService> sync_service_;
 
   base::ScopedTempDir temp_dir_;  // To pass to the backend host.
diff --git a/components/cast_channel/mojo_data_pump.cc b/components/cast_channel/mojo_data_pump.cc
index 8018a72..86a5b4e9 100644
--- a/components/cast_channel/mojo_data_pump.cc
+++ b/components/cast_channel/mojo_data_pump.cc
@@ -8,7 +8,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 
diff --git a/components/certificate_transparency/log_dns_client.h b/components/certificate_transparency/log_dns_client.h
index 1dd69f5..091e9873 100644
--- a/components/certificate_transparency/log_dns_client.h
+++ b/components/certificate_transparency/log_dns_client.h
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_piece.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/net_errors.h"
 #include "net/base/network_change_notifier.h"
 #include "net/log/net_log_with_source.h"
diff --git a/components/content_capture/android/content_capture_receiver_manager_android.cc b/components/content_capture/android/content_capture_receiver_manager_android.cc
index 522bfde..e3c6c3d 100644
--- a/components/content_capture/android/content_capture_receiver_manager_android.cc
+++ b/components/content_capture/android/content_capture_receiver_manager_android.cc
@@ -19,16 +19,22 @@
 using base::android::ScopedJavaLocalRef;
 using base::android::ToJavaLongArray;
 
-void JNI_ContentCaptureReceiverManager_Init(
+static ScopedJavaLocalRef<jobject>
+JNI_ContentCaptureReceiverManager_CreateOrGet(
     JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& jcaller,
-    const base::android::JavaParamRef<jobject>& jweb_contents) {
-  auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents);
+    const base::android::JavaParamRef<jobject>& jwebContents) {
+  auto* web_contents = content::WebContents::FromJavaWebContents(jwebContents);
   DCHECK(web_contents);
-  DCHECK(!content_capture::ContentCaptureReceiverManager::FromWebContents(
-      web_contents));
-  content_capture::ContentCaptureReceiverManagerAndroid::Create(web_contents,
-                                                                jcaller);
+  auto* manager =
+      content_capture::ContentCaptureReceiverManager::FromWebContents(
+          web_contents);
+  if (!manager) {
+    manager = content_capture::ContentCaptureReceiverManagerAndroid::Create(
+        env, web_contents);
+  }
+  return static_cast<content_capture::ContentCaptureReceiverManagerAndroid*>(
+             manager)
+      ->GetJavaObject();
 }
 
 namespace content_capture {
@@ -73,19 +79,22 @@
 }  // namespace
 
 ContentCaptureReceiverManagerAndroid::ContentCaptureReceiverManagerAndroid(
-    content::WebContents* web_contents,
-    const JavaRef<jobject>& jcaller)
-    : ContentCaptureReceiverManager(web_contents), java_ref_(jcaller) {}
+    JNIEnv* env,
+    content::WebContents* web_contents)
+    : ContentCaptureReceiverManager(web_contents),
+      java_ref_(Java_ContentCaptureReceiverManager_Constructor(env)) {}
 
 ContentCaptureReceiverManagerAndroid::~ContentCaptureReceiverManagerAndroid() =
     default;
 
-void ContentCaptureReceiverManagerAndroid::Create(
-    content::WebContents* web_contents,
-    const JavaRef<jobject>& jcaller) {
-  if (FromWebContents(web_contents))
-    return;
-  new ContentCaptureReceiverManagerAndroid(web_contents, jcaller);
+ContentCaptureReceiverManagerAndroid*
+ContentCaptureReceiverManagerAndroid::Create(
+    JNIEnv* env,
+    content::WebContents* web_contents) {
+  auto* manager = FromWebContents(web_contents);
+  if (manager)
+    return static_cast<ContentCaptureReceiverManagerAndroid*>(manager);
+  return new ContentCaptureReceiverManagerAndroid(env, web_contents);
 }
 
 void ContentCaptureReceiverManagerAndroid::DidCaptureContent(
@@ -121,4 +130,9 @@
       env, java_ref_, ToJavaArrayOfContentCaptureData(env, session));
 }
 
+ScopedJavaLocalRef<jobject>
+ContentCaptureReceiverManagerAndroid::GetJavaObject() {
+  return ScopedJavaLocalRef<jobject>(java_ref_);
+}
+
 }  // namespace content_capture
diff --git a/components/content_capture/android/content_capture_receiver_manager_android.h b/components/content_capture/android/content_capture_receiver_manager_android.h
index 46ec64df..14a2684d 100644
--- a/components/content_capture/android/content_capture_receiver_manager_android.h
+++ b/components/content_capture/android/content_capture_receiver_manager_android.h
@@ -18,8 +18,9 @@
     : public ContentCaptureReceiverManager {
  public:
   ~ContentCaptureReceiverManagerAndroid() override;
-  static void Create(content::WebContents* web_contents,
-                     const base::android::JavaRef<jobject>& jcaller);
+  static ContentCaptureReceiverManagerAndroid* Create(
+      JNIEnv* env,
+      content::WebContents* web_contents);
 
   void DidCaptureContent(const ContentCaptureSession& parent_session,
                          const ContentCaptureData& data) override;
@@ -27,10 +28,11 @@
                         const std::vector<int64_t>& data) override;
   void DidRemoveSession(const ContentCaptureSession& session) override;
 
+  base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
+
  private:
-  ContentCaptureReceiverManagerAndroid(
-      content::WebContents* web_contents,
-      const base::android::JavaRef<jobject>& jcaller);
+  ContentCaptureReceiverManagerAndroid(JNIEnv* env,
+                                       content::WebContents* web_contents);
 
   base::android::ScopedJavaGlobalRef<jobject> java_ref_;
 };
diff --git a/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureConsumer.java b/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureConsumer.java
index d9a458dbb..aacf65d 100644
--- a/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureConsumer.java
+++ b/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureConsumer.java
@@ -4,27 +4,52 @@
 
 package org.chromium.components.content_capture;
 
+import org.chromium.content_public.browser.WebContents;
+
 /**
- * This interface is for consumer to consume the captured content.
+ * This abstract class is for consumer to consume the captured content.
  */
-public interface ContentCaptureConsumer {
+public abstract class ContentCaptureConsumer {
+    private ContentCaptureReceiverManager mManager;
+    public ContentCaptureConsumer(WebContents webContents) {
+        onWebContentsChanged(webContents);
+    }
+
     /**
      * Invoked when the content is captured from a frame.
      * @param parentFrame is the parent of the frame from that the content captured.
      * @param contentCaptureData is the captured content tree, its root is the frame.
      */
-    void onContentCaptured(FrameSession parentFrame, ContentCaptureData contentCaptureData);
+    public abstract void onContentCaptured(
+            FrameSession parentFrame, ContentCaptureData contentCaptureData);
 
     /**
      * Invoked when the session is removed
      * @param session is the removed frame.
      */
-    void onSessionRemoved(FrameSession session);
+    public abstract void onSessionRemoved(FrameSession session);
 
     /**
      * Invoked when the content is removed from a frame
      * @param session defines the frame from that the content removed
      * @param removedIds are array of removed content id.
      */
-    void onContentRemoved(FrameSession session, long[] removedIds);
+    public abstract void onContentRemoved(FrameSession session, long[] removedIds);
+
+    public void onWebContentsChanged(WebContents current) {
+        if (!ContentCaptureFeatures.isEnabled()) return;
+        if (mManager != null) mManager.setContentCaptureConsumer(null);
+        if (current != null) {
+            mManager = ContentCaptureReceiverManager.createOrGet(current);
+            mManager.setContentCaptureConsumer(this);
+        } else {
+            mManager = null;
+        }
+    }
+
+    public void destroy() {
+        if (mManager == null) return;
+        mManager.setContentCaptureConsumer(null);
+        mManager = null;
+    }
 }
diff --git a/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureFeatures.java b/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureFeatures.java
index dc7ad56..7400008 100644
--- a/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureFeatures.java
+++ b/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureFeatures.java
@@ -3,12 +3,20 @@
 // found in the LICENSE file.
 package org.chromium.components.content_capture;
 
+import org.chromium.base.CommandLine;
+
 /**
  * The class to get if feature is enabled from native.
  */
 public class ContentCaptureFeatures {
+    private static final String FLAG = "dump-captured-content-to-logcat-for-testing";
+
     public static boolean isEnabled() {
         return nativeIsEnabled();
     }
+
+    public static boolean isDumpForTestingEnabled() {
+        return CommandLine.getInstance().hasSwitch(FLAG);
+    }
     private static native boolean nativeIsEnabled();
 }
diff --git a/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureReceiverManager.java b/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureReceiverManager.java
index c217f21..f6d7e8f 100644
--- a/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureReceiverManager.java
+++ b/components/content_capture/android/java/src/org/chromium/components/content_capture/ContentCaptureReceiverManager.java
@@ -4,9 +4,6 @@
 
 package org.chromium.components.content_capture;
 
-import android.view.ViewGroup;
-
-import org.chromium.base.CommandLine;
 import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.content_public.browser.WebContents;
@@ -18,25 +15,17 @@
  */
 public class ContentCaptureReceiverManager {
     private static final String TAG = "ContentCapture";
-    private static final String FLAG = "dump-captured-content-to-logcat-for-testing";
     private static Boolean sDump;
 
     private ContentCaptureConsumer mContentCaptureConsumer;
 
-    public static ContentCaptureReceiverManager create(WebContents webContents) {
-        ContentCaptureReceiverManager manager = new ContentCaptureReceiverManager();
-        manager.nativeInit(webContents);
-        return manager;
+    public static ContentCaptureReceiverManager createOrGet(WebContents webContents) {
+        return nativeCreateOrGet(webContents);
     }
 
-    public ContentCaptureReceiverManager() {
-        if (sDump == null) sDump = CommandLine.getInstance().hasSwitch(FLAG);
-    }
-
-    public void onContainerViewChanged(ViewGroup containerView) {
-        // Reset current consumer, the new consumer that associates with contanerView shall be set
-        // from setContentCaptureConsumer().
-        mContentCaptureConsumer = null;
+    @CalledByNative
+    private ContentCaptureReceiverManager() {
+        if (sDump == null) sDump = ContentCaptureFeatures.isDumpForTestingEnabled();
     }
 
     public void setContentCaptureConsumer(ContentCaptureConsumer consumer) {
@@ -74,5 +63,5 @@
         return frameSession;
     }
 
-    private native void nativeInit(WebContents webContents);
+    private static native ContentCaptureReceiverManager nativeCreateOrGet(WebContents webContents);
 }
diff --git a/components/country_codes/country_codes.cc b/components/country_codes/country_codes.cc
index 189e5c8..542c19d6 100644
--- a/components/country_codes/country_codes.cc
+++ b/components/country_codes/country_codes.cc
@@ -28,8 +28,8 @@
 
 namespace {
 
-// TODO(scottchen): remove this function after confirming if it only pertains
-// to obsolete OSes.
+// TODO(hcarmona/johntlee): remove this function after confirming if it only
+// pertains to obsolete OSes.
 int CountryCharsToCountryIDWithUpdate(char c1, char c2) {
   // SPECIAL CASE: In 2003, Yugoslavia renamed itself to Serbia and Montenegro.
   // Serbia and Montenegro dissolved their union in June 2006. Yugoslavia was
diff --git a/components/cronet/ios/BUILD.gn b/components/cronet/ios/BUILD.gn
index 3794f79e..17c6c8740 100644
--- a/components/cronet/ios/BUILD.gn
+++ b/components/cronet/ios/BUILD.gn
@@ -267,7 +267,6 @@
     bundle_contents_dir = bundle_root_dir
     bundle_executable_dir = bundle_contents_dir
     bundle_resources_dir = bundle_contents_dir
-    bundle_plugins_dir = bundle_contents_dir
     deps = [
       ":$_framework_binary_target",
       ":$_framework_headers_target",
diff --git a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
index e270678..5006226 100644
--- a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
+++ b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
@@ -23,7 +23,7 @@
 
 namespace {
 void RecordQuicProxyStatus(const net::ProxyServer& proxy_server) {
-  if (proxy_server.is_https()) {
+  if (proxy_server.is_https() || proxy_server.is_quic()) {
     RecordQuicProxyStatus(IsQuicProxy(proxy_server)
                               ? QUIC_PROXY_STATUS_AVAILABLE
                               : QUIC_PROXY_NOT_SUPPORTED);
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
index 3e091c7..4d216b80 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
@@ -29,7 +29,6 @@
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
-#include "net/base/completion_callback.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/load_flags.h"
 #include "net/base/network_change_notifier.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
index 47e6c6d..3c957d7 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
@@ -16,7 +16,6 @@
 #include "base/threading/thread_checker.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h"
 #include "components/data_use_measurement/core/data_use_user_data.h"
-#include "net/base/completion_callback.h"
 #include "net/base/layered_network_delegate.h"
 #include "net/proxy_resolution/proxy_retry_info.h"
 
diff --git a/components/data_use_measurement/core/data_use_network_delegate.h b/components/data_use_measurement/core/data_use_network_delegate.h
index adf9366..d66ee1b7 100644
--- a/components/data_use_measurement/core/data_use_network_delegate.h
+++ b/components/data_use_measurement/core/data_use_network_delegate.h
@@ -11,7 +11,6 @@
 
 #include "base/macros.h"
 #include "components/data_use_measurement/core/data_use_measurement.h"
-#include "net/base/completion_callback.h"
 #include "net/base/layered_network_delegate.h"
 
 namespace net {
diff --git a/components/download/quarantine/quarantine_win_unittest.cc b/components/download/quarantine/quarantine_win_unittest.cc
index a157683..f55a76a 100644
--- a/components/download/quarantine/quarantine_win_unittest.cc
+++ b/components/download/quarantine/quarantine_win_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/strings/stringprintf.h"
-#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_file_util.h"
 #include "base/win/win_util.h"
@@ -31,10 +30,6 @@
 const char kDummyClientGuid[] = "A1B69307-8FA2-4B6F-9181-EA06051A48A7";
 
 const char kMotwForInternetZone[] = "[ZoneTransfer]\r\nZoneId=3\r\n";
-const base::FilePath::CharType kMotwStreamSuffix[] =
-    FILE_PATH_LITERAL(":Zone.Identifier");
-
-const char kTestData[] = "Hello world!";
 
 const char* const kUntrustedURLs[] = {
     "http://example.com/foo",
@@ -46,15 +41,50 @@
     "about:internet",
     ""};
 
+// Creates a non-empty file at |file_path|.
+bool CreateFile(const base::FilePath& file_path) {
+  constexpr char kTestData[] = "Hello world!";
+
+  return base::WriteFile(file_path, kTestData, base::size(kTestData)) ==
+         static_cast<int>(base::size(kTestData));
+}
+
+// Reads the Zone.Identifier alternate data stream from |file_path| into
+// |contents|.
+bool GetZoneIdentifierStreamContents(const base::FilePath& file_path,
+                                     std::string* contents) {
+  DCHECK(contents);
+
+  const base::FilePath::CharType kMotwStreamSuffix[] =
+      FILE_PATH_LITERAL(":Zone.Identifier");
+
+  base::FilePath zone_identifier_stream_path(file_path.value() +
+                                             kMotwStreamSuffix);
+
+  return base::ReadFileToString(zone_identifier_stream_path, contents);
+}
+
 }  // namespace
 
-// If the file is missing, the QuarantineFile() call should return FILE_MISSING.
-TEST(QuarantineWinTest, MissingFile) {
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
+class QuarantineWinTest : public ::testing::Test {
+ public:
+  QuarantineWinTest() = default;
+  ~QuarantineWinTest() override = default;
 
+  void SetUp() override { ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); }
+
+  base::FilePath GetTempDir() { return scoped_temp_dir_.GetPath(); }
+
+ private:
+  base::ScopedTempDir scoped_temp_dir_;
+
+  DISALLOW_COPY_AND_ASSIGN(QuarantineWinTest);
+};
+
+// If the file is missing, the QuarantineFile() call should return FILE_MISSING.
+TEST_F(QuarantineWinTest, MissingFile) {
   EXPECT_EQ(QuarantineFileResult::FILE_MISSING,
-            QuarantineFile(test_dir.GetPath().AppendASCII("does-not-exist.exe"),
+            QuarantineFile(GetTempDir().AppendASCII("does-not-exist.exe"),
                            GURL(kDummySourceUrl), GURL(kDummyReferrerUrl),
                            kDummyClientGuid));
 }
@@ -64,38 +94,28 @@
 // verifies this behavior since the other tests in this suite would pass with a
 // false positive if local files are being annotated with the MOTW for the
 // internet zone.
-TEST(QuarantineWinTest, LocalFile_DependsOnLocalConfig) {
-  base::HistogramTester histogram_tester;
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
+TEST_F(QuarantineWinTest, LocalFile_DependsOnLocalConfig) {
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
 
   const char* const kLocalSourceURLs[] = {"http://localhost/foo",
                                           "file:///C:/some-local-dir/foo.exe"};
 
   for (const char* source_url : kLocalSourceURLs) {
     SCOPED_TRACE(::testing::Message() << "Trying URL " << source_url);
-    ASSERT_EQ(static_cast<int>(base::size(kTestData)),
-              base::WriteFile(test_file, kTestData, base::size(kTestData)));
+
+    ASSERT_TRUE(CreateFile(test_file));
 
     EXPECT_EQ(
         QuarantineFileResult::OK,
         QuarantineFile(test_file, GURL(source_url), GURL(), kDummyClientGuid));
 
-    std::string motw_contents;
-    base::ReadFileToString(
-        base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents);
+    std::string zone_identifier;
+    GetZoneIdentifierStreamContents(test_file, &zone_identifier);
 
-    // These warnings aren't displayed on successful test runs. They are there
-    // so that we can check for deviations in behavior during manual testing.
-    if (!motw_contents.empty()) {
-      LOG(WARNING) << "Unexpected zone marker for file " << test_file.value()
-                   << " Source URL:" << source_url;
-      if (motw_contents != kMotwForInternetZone)
-        LOG(WARNING) << "Zone marker contents: " << motw_contents;
-    }
+    // No zone identifier for local source.
+    EXPECT_TRUE(zone_identifier.empty());
 
-    base::DeleteFile(test_file, false);
+    ASSERT_TRUE(base::DeleteFile(test_file, false));
   }
 }
 
@@ -103,168 +123,146 @@
 // The specific zone assigned to our dummy source URL depends on the local
 // configuration. But no sane configuration should be treating the dummy URL as
 // a trusted source for anything.
-TEST(QuarantineWinTest, DownloadedFile_DependsOnLocalConfig) {
-  base::HistogramTester histogram_tester;
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
+TEST_F(QuarantineWinTest, DownloadedFile_DependsOnLocalConfig) {
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
 
   for (const char* source_url : kUntrustedURLs) {
     SCOPED_TRACE(::testing::Message() << "Trying URL " << source_url);
-    ASSERT_EQ(static_cast<int>(base::size(kTestData)),
-              base::WriteFile(test_file, kTestData, base::size(kTestData)));
+
+    ASSERT_TRUE(CreateFile(test_file));
     EXPECT_EQ(
         QuarantineFileResult::OK,
         QuarantineFile(test_file, GURL(source_url), GURL(), kDummyClientGuid));
-    std::string motw_contents;
-    ASSERT_TRUE(base::ReadFileToString(
-        base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
-    // The actual assigned zone could be anything. So only testing that there is
-    // a zone annotation.
-    EXPECT_FALSE(motw_contents.empty());
 
-    // These warnings aren't displayed on successful test runs. They are there
-    // so that we can check for deviations in behavior during manual testing.
-    if (motw_contents != kMotwForInternetZone)
-      LOG(WARNING) << "Unexpected zone marker: " << motw_contents;
-    base::DeleteFile(test_file, false);
+    std::string zone_identifier;
+    ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
+
+    // The actual assigned zone could be anything and the contents of the zone
+    // identifier depends on the version of Windows. So only testing that there
+    // is a zone annotation.
+    EXPECT_FALSE(zone_identifier.empty());
+
+    ASSERT_TRUE(base::DeleteFile(test_file, false));
   }
 }
 
-TEST(QuarantineWinTest, UnsafeReferrer_DependsOnLocalConfig) {
-  base::HistogramTester histogram_tester;
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
+TEST_F(QuarantineWinTest, UnsafeReferrer_DependsOnLocalConfig) {
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
 
   std::vector<std::string> unsafe_referrers(std::begin(kUntrustedURLs),
                                             std::end(kUntrustedURLs));
 
+  // Add one more test case.
   std::string huge_referrer = "http://example.com/";
   huge_referrer.append(INTERNET_MAX_URL_LENGTH * 2, 'a');
   unsafe_referrers.push_back(huge_referrer);
 
   for (const auto referrer_url : unsafe_referrers) {
     SCOPED_TRACE(::testing::Message() << "Trying URL " << referrer_url);
-    ASSERT_EQ(static_cast<int>(base::size(kTestData)),
-              base::WriteFile(test_file, kTestData, base::size(kTestData)));
+
+    ASSERT_TRUE(CreateFile(test_file));
     EXPECT_EQ(QuarantineFileResult::OK,
               QuarantineFile(test_file, GURL("http://example.com/good"),
                              GURL(referrer_url), kDummyClientGuid));
-    std::string motw_contents;
-    ASSERT_TRUE(base::ReadFileToString(
-        base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
-    // The actual assigned zone could be anything. So only testing that there is
-    // a zone annotation.
-    EXPECT_FALSE(motw_contents.empty());
 
-    // These warnings aren't displayed on successful test runs. They are there
-    // so that we can check for deviations in behavior during manual testing.
-    if (motw_contents != kMotwForInternetZone)
-      LOG(WARNING) << "Unexpected zone marker: " << motw_contents;
-    base::DeleteFile(test_file, false);
+    std::string zone_identifier;
+    ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
+
+    // The actual assigned zone could be anything and the contents of the zone
+    // identifier depends on the version of Windows. So only testing that there
+    // is a zone annotation.
+    EXPECT_FALSE(zone_identifier.empty());
+
+    ASSERT_TRUE(base::DeleteFile(test_file, false));
   }
 }
 
 // An empty source URL should result in a file that's treated the same as one
 // downloaded from the internet.
-TEST(QuarantineWinTest, EmptySource_DependsOnLocalConfig) {
-  base::HistogramTester histogram_tester;
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
-  ASSERT_EQ(static_cast<int>(base::size(kTestData)),
-            base::WriteFile(test_file, kTestData, base::size(kTestData)));
+TEST_F(QuarantineWinTest, EmptySource_DependsOnLocalConfig) {
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
+  ASSERT_TRUE(CreateFile(test_file));
 
   EXPECT_EQ(QuarantineFileResult::OK,
             QuarantineFile(test_file, GURL(), GURL(), kDummyClientGuid));
-  std::string motw_contents;
-  ASSERT_TRUE(base::ReadFileToString(
-      base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
-  // The actual assigned zone could be anything. So only testing that there is a
-  // zone annotation.
-  EXPECT_FALSE(motw_contents.empty());
+
+  std::string zone_identifier;
+  ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
+
+  // The actual assigned zone could be anything and the contents of the zone
+  // identifier depends on the version of Windows. So only testing that there is
+  // a zone annotation.
+  EXPECT_FALSE(zone_identifier.empty());
 }
 
 // Empty files aren't passed to AVScanFile. They are instead marked manually. If
 // the file is passed to AVScanFile, then there wouldn't be a MOTW attached to
 // it and the test would fail.
-TEST(QuarantineWinTest, EmptyFile) {
-  base::HistogramTester histogram_tester;
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
+TEST_F(QuarantineWinTest, EmptyFile) {
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
   ASSERT_EQ(0, base::WriteFile(test_file, "", 0u));
 
   EXPECT_EQ(QuarantineFileResult::OK,
             QuarantineFile(test_file, net::FilePathToFileURL(test_file), GURL(),
                            kDummyClientGuid));
-  std::string motw_contents;
-  ASSERT_TRUE(base::ReadFileToString(
-      base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
-  EXPECT_STREQ(kMotwForInternetZone, motw_contents.c_str());
+
+  std::string zone_identifier;
+  ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
+
+  EXPECT_STREQ(zone_identifier.c_str(), kMotwForInternetZone);
 }
 
 // If there is no client GUID supplied to the QuarantineFile() call, then rather
 // than invoking AVScanFile, the MOTW will be applied manually.  If the file is
 // passed to AVScanFile, then there wouldn't be a MOTW attached to it and the
 // test would fail.
-TEST(QuarantineWinTest, NoClientGuid) {
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
-  ASSERT_EQ(static_cast<int>(base::size(kTestData)),
-            base::WriteFile(test_file, kTestData, base::size(kTestData)));
+TEST_F(QuarantineWinTest, NoClientGuid) {
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
+  ASSERT_TRUE(CreateFile(test_file));
 
   EXPECT_EQ(QuarantineFileResult::OK,
             QuarantineFile(test_file, net::FilePathToFileURL(test_file), GURL(),
                            std::string()));
-  std::string motw_contents;
-  ASSERT_TRUE(base::ReadFileToString(
-      base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
-  EXPECT_STREQ(kMotwForInternetZone, motw_contents.c_str());
+
+  std::string zone_identifier;
+  ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
+
+  EXPECT_STREQ(zone_identifier.c_str(), kMotwForInternetZone);
 }
 
 // URLs longer than INTERNET_MAX_URL_LENGTH are known to break URLMon. Such a
 // URL, when used as a source URL shouldn't break QuarantineFile() which should
 // mark the file as being from the internet zone as a safe fallback.
-TEST(QuarantineWinTest, SuperLongURL) {
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
-  ASSERT_EQ(static_cast<int>(base::size(kTestData)),
-            base::WriteFile(test_file, kTestData, base::size(kTestData)));
+TEST_F(QuarantineWinTest, SuperLongURL) {
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
+  ASSERT_TRUE(CreateFile(test_file));
 
   std::string source_url("http://example.com/");
   source_url.append(INTERNET_MAX_URL_LENGTH * 2, 'a');
   EXPECT_EQ(QuarantineFileResult::OK,
             QuarantineFile(test_file, GURL(source_url), GURL(), std::string()));
 
-  std::string motw_contents;
-  ASSERT_TRUE(base::ReadFileToString(
-      base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
-  EXPECT_STREQ(kMotwForInternetZone, motw_contents.c_str());
+  std::string zone_identifier;
+  ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
+
+  EXPECT_STREQ(zone_identifier.c_str(), kMotwForInternetZone);
 }
 
 // On domain-joined machines, the IAttachmentExecute code path is taken, and the
 // output depends on the Windows version.
-TEST(QuarantineWinTest, EnterpriseUserZoneIdentifier) {
+TEST_F(QuarantineWinTest, EnterpriseUserZoneIdentifier) {
   base::win::ScopedDomainStateForTesting scoped_domain(true);
 
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
-  ASSERT_EQ(static_cast<int>(base::size(kTestData)),
-            base::WriteFile(test_file, kTestData, base::size(kTestData)));
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
+  ASSERT_TRUE(CreateFile(test_file));
 
   EXPECT_EQ(QuarantineFileResult::OK,
             QuarantineFile(test_file, GURL(kDummySourceUrl),
                            GURL(kDummyReferrerUrl), kDummyClientGuid));
 
-  // Read the zone identifier.
-  std::string motw_contents;
-  ASSERT_TRUE(base::ReadFileToString(
-      base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
+  std::string zone_identifier;
+  ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
+
   std::string expected = kMotwForInternetZone;
   // On Win10, the MotW now contains the HostUrl and ReferrerUrl values.
   if (base::win::GetVersion() >= base::win::VERSION_WIN10) {
@@ -272,13 +270,13 @@
                                        kDummyReferrerUrl, kDummySourceUrl));
   }
 
-  EXPECT_EQ(motw_contents, expected);
+  EXPECT_EQ(zone_identifier, expected);
 }
 
 // When the InvokeAttachmentServices is disabled, the fallback code path that
 // manually sets the MotW is always invoked. The original fallback code only
 // sets the ZoneId value.
-TEST(QuarantineWinTest, DisableInvokeAttachmentServices) {
+TEST_F(QuarantineWinTest, DisableInvokeAttachmentServices) {
   base::win::ScopedDomainStateForTesting scoped_domain(false);
 
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -288,29 +286,21 @@
       // Disabled features.
       {kInvokeAttachmentServices});
 
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
-  ASSERT_EQ(static_cast<int>(base::size(kTestData)),
-            base::WriteFile(test_file, kTestData, base::size(kTestData)));
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
+  ASSERT_TRUE(CreateFile(test_file));
 
   EXPECT_EQ(QuarantineFileResult::OK,
             QuarantineFile(test_file, GURL(kDummySourceUrl),
                            GURL(kDummyReferrerUrl), kDummyClientGuid));
 
-  // Read the zone identifier.
-  std::string motw_contents;
-  ASSERT_TRUE(base::ReadFileToString(
-      base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
+  std::string zone_identifier;
+  ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
 
-  // Only the ZoneId is set.
-  std::string expected = kMotwForInternetZone;
-
-  EXPECT_EQ(motw_contents, expected);
+  EXPECT_STREQ(zone_identifier.c_str(), kMotwForInternetZone);
 }
 
 // Tests the expected MotW when the AugmentedZoneIdentifier feature is enabled.
-TEST(QuarantineWinTest, AugmentedZoneIdentifier) {
+TEST_F(QuarantineWinTest, AugmentedZoneIdentifier) {
   base::win::ScopedDomainStateForTesting scoped_domain(false);
 
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -320,32 +310,25 @@
       // Disabled features.
       {kInvokeAttachmentServices});
 
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
-  ASSERT_EQ(static_cast<int>(base::size(kTestData)),
-            base::WriteFile(test_file, kTestData, base::size(kTestData)));
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
+  ASSERT_TRUE(CreateFile(test_file));
 
   EXPECT_EQ(QuarantineFileResult::OK,
             QuarantineFile(test_file, GURL(kDummySourceUrl),
                            GURL(kDummyReferrerUrl), kDummyClientGuid));
 
-  // Read the zone identifier.
-  std::string motw_contents;
-  ASSERT_TRUE(base::ReadFileToString(
-      base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
+  std::string zone_identifier;
+  ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
 
-  // Only the ZoneId is set.
   std::string expected = kMotwForInternetZone;
   expected.append(base::StringPrintf("ReferrerUrl=%s\r\nHostUrl=%s\r\n",
                                      kDummyReferrerUrl, kDummySourceUrl));
-
-  EXPECT_EQ(motw_contents, expected);
+  EXPECT_EQ(zone_identifier, expected);
 }
 
 // Tests the expected MotW when the AugmentedZoneIdentifier feature is enabled
 // and no referrer is provided to the QuarantineFile() function.
-TEST(QuarantineWinTest, AugmentedZoneIdentifierNoReferrer) {
+TEST_F(QuarantineWinTest, AugmentedZoneIdentifierNoReferrer) {
   base::win::ScopedDomainStateForTesting scoped_domain(false);
 
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -355,31 +338,25 @@
       // Disabled features.
       {kInvokeAttachmentServices});
 
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
-  ASSERT_EQ(static_cast<int>(base::size(kTestData)),
-            base::WriteFile(test_file, kTestData, base::size(kTestData)));
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
+  ASSERT_TRUE(CreateFile(test_file));
 
   EXPECT_EQ(QuarantineFileResult::OK,
             QuarantineFile(test_file, GURL(kDummySourceUrl), GURL(),
                            kDummyClientGuid));
 
-  // Read the zone identifier.
-  std::string motw_contents;
-  ASSERT_TRUE(base::ReadFileToString(
-      base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
+  std::string zone_identifier;
+  ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
 
-  // Only the ZoneId is set.
   std::string expected = kMotwForInternetZone;
   expected.append(base::StringPrintf("HostUrl=%s\r\n", kDummySourceUrl));
 
-  EXPECT_EQ(motw_contents, expected);
+  EXPECT_EQ(zone_identifier, expected);
 }
 
 // Tests the expected MotW when the AugmentedZoneIdentifier feature is enabled
 // and no source is provided to the QuarantineFile() function.
-TEST(QuarantineWinTest, AugmentedZoneIdentifierNoSource) {
+TEST_F(QuarantineWinTest, AugmentedZoneIdentifierNoSource) {
   base::win::ScopedDomainStateForTesting scoped_domain(false);
 
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -389,27 +366,21 @@
       // Disabled features.
       {kInvokeAttachmentServices});
 
-  base::ScopedTempDir test_dir;
-  ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-  base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.exe");
-  ASSERT_EQ(static_cast<int>(base::size(kTestData)),
-            base::WriteFile(test_file, kTestData, base::size(kTestData)));
+  base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
+  ASSERT_TRUE(CreateFile(test_file));
 
   EXPECT_EQ(QuarantineFileResult::OK,
             QuarantineFile(test_file, GURL(), GURL(kDummyReferrerUrl),
                            kDummyClientGuid));
 
-  // Read the zone identifier.
-  std::string motw_contents;
-  ASSERT_TRUE(base::ReadFileToString(
-      base::FilePath(test_file.value() + kMotwStreamSuffix), &motw_contents));
+  std::string zone_identifier;
+  ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
 
-  // Only the ZoneId is set.
   std::string expected = kMotwForInternetZone;
   expected.append(base::StringPrintf("ReferrerUrl=%s\r\nHostUrl=%s\r\n",
                                      kDummyReferrerUrl, "about:internet"));
 
-  EXPECT_EQ(motw_contents, expected);
+  EXPECT_EQ(zone_identifier, expected);
 }
 
 }  // namespace download
diff --git a/components/drive/local_file_reader.cc b/components/drive/local_file_reader.cc
index d1fb2f5..39858b79 100644
--- a/components/drive/local_file_reader.cc
+++ b/components/drive/local_file_reader.cc
@@ -9,7 +9,7 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/sequenced_task_runner.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index 731402f9..79e6af1 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -59,7 +59,7 @@
     "//device/gamepad",
     "//device/gamepad/public/cpp:shared_with_blink",
     "//gpu",
-    "//gpu/command_buffer/client:gles2_interface",
+    "//gpu/command_buffer/client:raster_interface",
     "//services/ws/public/mojom",
     "//skia",
     "//ui/aura",
@@ -145,6 +145,7 @@
     "//testing/gtest",
     "//ui/aura",
     "//ui/aura:test_support",
+    "//ui/base/ime/init",
     "//ui/compositor",
     "//ui/compositor:test_support",
     "//ui/display/manager",
@@ -184,7 +185,7 @@
     "//components/viz/service",
     "//components/viz/test:test_support",
     "//device/gamepad:test_helpers",
-    "//gpu/command_buffer/client:gles2_interface",
+    "//gpu/command_buffer/client:raster_interface",
     "//skia",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/components/exo/buffer.cc b/components/exo/buffer.cc
index c93ef73..1539f0a4 100644
--- a/components/exo/buffer.cc
+++ b/components/exo/buffer.cc
@@ -4,9 +4,6 @@
 
 #include "components/exo/buffer.h"
 
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <GLES2/gl2extchromium.h>
 #include <stdint.h>
 
 #include <algorithm>
@@ -27,9 +24,12 @@
 #include "components/viz/common/resources/resource_format.h"
 #include "components/viz/common/resources/resource_format_utils.h"
 #include "components/viz/common/resources/single_release_callback.h"
+#include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/context_support.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
+#include "gpu/command_buffer/client/shared_image_interface.h"
 #include "gpu/command_buffer/common/mailbox.h"
+#include "gpu/command_buffer/common/shared_image_usage.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "ui/aura/env.h"
 #include "ui/compositor/compositor.h"
@@ -44,56 +44,16 @@
 
 constexpr char kBufferInUse[] = "BufferInUse";
 
-GLenum GLInternalFormat(gfx::BufferFormat format) {
-  const GLenum kGLInternalFormats[] = {
-      GL_R8_EXT,                   // R_8
-      GL_R16_EXT,                  // R_16
-      GL_RG8_EXT,                  // RG_88
-      GL_RGB,                      // BGR_565
-      GL_RGBA,                     // RGBA_4444
-      GL_RGB,                      // RGBX_8888
-      GL_RGBA,                     // RGBA_8888
-      GL_RGB,                      // BGRX_8888
-      GL_RGB10_A2_EXT,             // BGRX_1010102
-      GL_RGB10_A2_EXT,             // RGBX_1010102
-      GL_BGRA_EXT,                 // BGRA_8888
-      GL_RGBA,                     // RGBA_F16
-      GL_RGB_YCRCB_420_CHROMIUM,   // YVU_420
-      GL_RGB_YCBCR_420V_CHROMIUM,  // YUV_420_BIPLANAR
-      GL_RGB_YCBCR_422_CHROMIUM,   // UYVY_422
-  };
-  static_assert(base::size(kGLInternalFormats) ==
-                    (static_cast<int>(gfx::BufferFormat::LAST) + 1),
-                "BufferFormat::LAST must be last value of kGLInternalFormats");
-
-  DCHECK(format <= gfx::BufferFormat::LAST);
-  return kGLInternalFormats[static_cast<int>(format)];
-}
-
-unsigned CreateGLTexture(gpu::gles2::GLES2Interface* gles2, GLenum target) {
-  unsigned texture_id = 0;
-  gles2->GenTextures(1, &texture_id);
-  gles2->ActiveTexture(GL_TEXTURE0);
-  gles2->BindTexture(target, texture_id);
-  gles2->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  gles2->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  gles2->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  gles2->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  return texture_id;
-}
-
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
 // Buffer::Texture
 
-// Encapsulates the state and logic needed to bind a buffer to a GLES2 texture.
+// Encapsulates the state and logic needed to bind a buffer to a SharedImage.
 class Buffer::Texture : public ui::ContextFactoryObserver {
  public:
+  Texture(ui::ContextFactory* context_factory, const gfx::Size& size);
   Texture(ui::ContextFactory* context_factory,
-          viz::ContextProvider* context_provider);
-  Texture(ui::ContextFactory* context_factory,
-          viz::ContextProvider* context_provider,
           gfx::GpuMemoryBuffer* gpu_memory_buffer,
           unsigned texture_target,
           unsigned query_type,
@@ -103,7 +63,7 @@
   // Overridden from ui::ContextFactoryObserver:
   void OnLostSharedContext() override;
 
-  // Returns true if GLES2 resources for texture have been lost.
+  // Returns true if the RasterInterface context has been lost.
   bool IsLost();
 
   // Allow texture to be reused after |sync_token| has passed and runs
@@ -112,16 +72,17 @@
                const gpu::SyncToken& sync_token,
                bool is_lost);
 
-  // Binds the contents referenced by |image_id_| to the texture returned by
-  // mailbox(). Returns a sync token that can be used when accessing texture
-  // from a different context.
-  gpu::SyncToken BindTexImage();
+  // Updates the contents referenced by |gpu_memory_buffer_| returned by
+  // mailbox().
+  // Returns a sync token that can be used when accessing the SharedImage from a
+  // different context.
+  gpu::SyncToken UpdateSharedImage();
 
-  // Releases the contents referenced by |image_id_| after |sync_token| has
+  // Releases the contents referenced by |mailbox_| after |sync_token| has
   // passed and runs |callback| when completed.
-  void ReleaseTexImage(base::OnceClosure callback,
-                       const gpu::SyncToken& sync_token,
-                       bool is_lost);
+  void ReleaseSharedImage(base::OnceClosure callback,
+                          const gpu::SyncToken& sync_token,
+                          bool is_lost);
 
   // Copy the contents of texture to |destination| and runs |callback| when
   // completed. Returns a sync token that can be used when accessing texture
@@ -139,14 +100,12 @@
   void WaitForRelease();
 
   gfx::GpuMemoryBuffer* const gpu_memory_buffer_;
+  const gfx::Size size_;
   ui::ContextFactory* context_factory_;
-  scoped_refptr<viz::ContextProvider> context_provider_;
+  scoped_refptr<viz::RasterContextProvider> context_provider_;
   const unsigned texture_target_;
   const unsigned query_type_;
-  const GLenum internalformat_;
-  unsigned image_id_ = 0;
   unsigned query_id_ = 0;
-  unsigned texture_id_ = 0;
   gpu::Mailbox mailbox_;
   base::OnceClosure release_callback_;
   const base::TimeDelta wait_for_release_delay_;
@@ -158,52 +117,63 @@
 };
 
 Buffer::Texture::Texture(ui::ContextFactory* context_factory,
-                         viz::ContextProvider* context_provider)
+                         const gfx::Size& size)
     : gpu_memory_buffer_(nullptr),
+      size_(size),
       context_factory_(context_factory),
-      context_provider_(context_provider),
+      context_provider_(
+          context_factory->SharedMainThreadRasterContextProvider()),
       texture_target_(GL_TEXTURE_2D),
       query_type_(GL_COMMANDS_COMPLETED_CHROMIUM),
-      internalformat_(GL_RGBA),
       weak_ptr_factory_(this) {
-  gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
-  texture_id_ = CreateGLTexture(gles2, texture_target_);
-  // Generate a crypto-secure random mailbox name.
-  gles2->ProduceTextureDirectCHROMIUM(texture_id_, mailbox_.name);
+  gpu::SharedImageInterface* sii = context_provider_->SharedImageInterface();
+  const uint32_t usage =
+      gpu::SHARED_IMAGE_USAGE_RASTER | gpu::SHARED_IMAGE_USAGE_DISPLAY;
+
+  mailbox_ = sii->CreateSharedImage(viz::ResourceFormat::RGBA_8888, size,
+                                    gfx::ColorSpace(), usage);
+  DCHECK(!mailbox_.IsZero());
+  gpu::raster::RasterInterface* ri = context_provider_->RasterInterface();
+  ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData());
+
   // Provides a notification when |context_provider_| is lost.
   context_factory_->AddObserver(this);
 }
 
 Buffer::Texture::Texture(ui::ContextFactory* context_factory,
-                         viz::ContextProvider* context_provider,
                          gfx::GpuMemoryBuffer* gpu_memory_buffer,
                          unsigned texture_target,
                          unsigned query_type,
                          base::TimeDelta wait_for_release_delay)
     : gpu_memory_buffer_(gpu_memory_buffer),
+      size_(gpu_memory_buffer->GetSize()),
       context_factory_(context_factory),
-      context_provider_(context_provider),
+      context_provider_(
+          context_factory->SharedMainThreadRasterContextProvider()),
       texture_target_(texture_target),
       query_type_(query_type),
-      internalformat_(GLInternalFormat(gpu_memory_buffer->GetFormat())),
       wait_for_release_delay_(wait_for_release_delay),
       weak_ptr_factory_(this) {
-  gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
-  gfx::Size size = gpu_memory_buffer->GetSize();
-  image_id_ =
-      gles2->CreateImageCHROMIUM(gpu_memory_buffer->AsClientBuffer(),
-                                 size.width(), size.height(), internalformat_);
-  DLOG_IF(WARNING, !image_id_) << "Failed to create GLImage";
+  gpu::SharedImageInterface* sii = context_provider_->SharedImageInterface();
+  const uint32_t usage = gpu::SHARED_IMAGE_USAGE_RASTER |
+                         gpu::SHARED_IMAGE_USAGE_DISPLAY |
+                         gpu::SHARED_IMAGE_USAGE_SCANOUT;
 
-  gles2->GenQueriesEXT(1, &query_id_);
-  texture_id_ = CreateGLTexture(gles2, texture_target_);
+  mailbox_ = sii->CreateSharedImage(
+      gpu_memory_buffer_, context_factory_->GetGpuMemoryBufferManager(),
+      gfx::ColorSpace(), usage);
+  DCHECK(!mailbox_.IsZero());
+  gpu::raster::RasterInterface* ri = context_provider_->RasterInterface();
+  ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData());
+  ri->GenQueriesEXT(1, &query_id_);
+
   // Provides a notification when |context_provider_| is lost.
   context_factory_->AddObserver(this);
 }
 
 Buffer::Texture::~Texture() {
   DestroyResources();
-  if (context_provider_)
+  if (context_factory_)
     context_factory_->RemoveObserver(this);
 }
 
@@ -217,8 +187,8 @@
 
 bool Buffer::Texture::IsLost() {
   if (context_provider_) {
-    gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
-    return gles2->GetGraphicsResetStatusKHR() != GL_NO_ERROR;
+    gpu::raster::RasterInterface* ri = context_provider_->RasterInterface();
+    return ri->GetGraphicsResetStatusKHR() != GL_NO_ERROR;
   }
   return true;
 }
@@ -227,9 +197,10 @@
                               const gpu::SyncToken& sync_token,
                               bool is_lost) {
   if (context_provider_) {
-    gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
-    if (sync_token.HasData())
-      gles2->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+    if (sync_token.HasData()) {
+      gpu::raster::RasterInterface* ri = context_provider_->RasterInterface();
+      ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+    }
   }
 
   // Run callback as texture can be reused immediately after waiting for sync
@@ -237,43 +208,36 @@
   std::move(callback).Run();
 }
 
-gpu::SyncToken Buffer::Texture::BindTexImage() {
+gpu::SyncToken Buffer::Texture::UpdateSharedImage() {
   gpu::SyncToken sync_token;
   if (context_provider_) {
-    gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
-    gles2->ActiveTexture(GL_TEXTURE0);
-    gles2->BindTexture(texture_target_, texture_id_);
-    DCHECK_NE(image_id_, 0u);
-    gles2->BindTexImage2DCHROMIUM(texture_target_, image_id_);
-    // Generate a crypto-secure random mailbox name if not already done.
-    if (mailbox_.IsZero())
-      gles2->ProduceTextureDirectCHROMIUM(texture_id_, mailbox_.name);
-    // Create and return a sync token that can be used to ensure that the
-    // BindTexImage2DCHROMIUM call is processed before issuing any commands
-    // that will read from the texture on a different context.
-    gles2->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+    gpu::SharedImageInterface* sii = context_provider_->SharedImageInterface();
+    DCHECK(!mailbox_.IsZero());
+    // UpdateSharedImage gets called only after |mailbox_| can be reused.
+    // A buffer can be reattached to a surface only after it has been returned
+    // to wayland clients. We return buffers to clients only after the query
+    // |query_type_| is available.
+    sii->UpdateSharedImage(gpu::SyncToken(), mailbox_);
+    sync_token = sii->GenUnverifiedSyncToken();
     TRACE_EVENT_ASYNC_STEP_INTO0("exo", kBufferInUse, gpu_memory_buffer_,
                                  "bound");
   }
   return sync_token;
 }
 
-void Buffer::Texture::ReleaseTexImage(base::OnceClosure callback,
-                                      const gpu::SyncToken& sync_token,
-                                      bool is_lost) {
+void Buffer::Texture::ReleaseSharedImage(base::OnceClosure callback,
+                                         const gpu::SyncToken& sync_token,
+                                         bool is_lost) {
   if (context_provider_) {
-    gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
+    gpu::raster::RasterInterface* ri = context_provider_->RasterInterface();
     if (sync_token.HasData())
-      gles2->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
-    gles2->ActiveTexture(GL_TEXTURE0);
-    gles2->BindTexture(texture_target_, texture_id_);
-    DCHECK_NE(query_id_, 0u);
-    gles2->BeginQueryEXT(query_type_, query_id_);
-    gles2->ReleaseTexImage2DCHROMIUM(texture_target_, image_id_);
-    gles2->EndQueryEXT(query_type_);
-    // Run callback when query result is available and ReleaseTexImage has been
-    // handled if sync token has data and buffer has been used. If buffer was
-    // never used then run the callback immediately.
+      ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+    ri->BeginQueryEXT(query_type_, query_id_);
+    ri->EndQueryEXT(query_type_);
+    // Run callback when query result is available (i.e., when all operations on
+    // the shared image have completed and it's ready to be reused) if sync
+    // token has data and buffer has been used. If buffer was never used then
+    // run the callback immediately.
     if (sync_token.HasData()) {
       ReleaseWhenQueryResultIsAvailable(std::move(callback));
       return;
@@ -286,37 +250,38 @@
                                              base::OnceClosure callback) {
   gpu::SyncToken sync_token;
   if (context_provider_) {
-    gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
-    gles2->ActiveTexture(GL_TEXTURE0);
-    gles2->BindTexture(texture_target_, texture_id_);
-    DCHECK_NE(image_id_, 0u);
-    gles2->BindTexImage2DCHROMIUM(texture_target_, image_id_);
-    gles2->CopyTextureCHROMIUM(texture_id_, 0, destination->texture_target_,
-                               destination->texture_id_, 0, internalformat_,
-                               GL_UNSIGNED_BYTE, false, false, false);
+    DCHECK(!mailbox_.IsZero());
+    gpu::SharedImageInterface* sii = context_provider_->SharedImageInterface();
+    sii->UpdateSharedImage(gpu::SyncToken(), mailbox_);
+    sync_token = sii->GenUnverifiedSyncToken();
+
+    gpu::raster::RasterInterface* ri = context_provider_->RasterInterface();
+    ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
     DCHECK_NE(query_id_, 0u);
-    gles2->BeginQueryEXT(query_type_, query_id_);
-    gles2->ReleaseTexImage2DCHROMIUM(texture_target_, image_id_);
-    gles2->EndQueryEXT(query_type_);
-    // Run callback when query result is available and ReleaseTexImage has been
-    // handled.
+    ri->BeginQueryEXT(query_type_, query_id_);
+    ri->CopySubTexture(mailbox_, destination->mailbox_,
+                       destination->texture_target_, 0, 0, 0, 0, size_.width(),
+                       size_.height());
+    ri->EndQueryEXT(query_type_);
+    // Run callback when query result is available.
     ReleaseWhenQueryResultIsAvailable(std::move(callback));
     // Create and return a sync token that can be used to ensure that the
-    // CopyTextureCHROMIUM call is processed before issuing any commands
+    // CopySubTexture call is processed before issuing any commands
     // that will read from the target texture on a different context.
-    gles2->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+    ri->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
   }
   return sync_token;
 }
 
 void Buffer::Texture::DestroyResources() {
   if (context_provider_) {
-    gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
-    gles2->DeleteTextures(1, &texture_id_);
-    if (query_id_)
-      gles2->DeleteQueriesEXT(1, &query_id_);
-    if (image_id_)
-      gles2->DestroyImageCHROMIUM(image_id_);
+    if (query_id_) {
+      gpu::raster::RasterInterface* ri = context_provider_->RasterInterface();
+      ri->DeleteQueriesEXT(1, &query_id_);
+      query_id_ = 0;
+    }
+    gpu::SharedImageInterface* sii = context_provider_->SharedImageInterface();
+    sii->DestroySharedImage(gpu::SyncToken(), mailbox_);
   }
 }
 
@@ -373,8 +338,8 @@
     // the query implies waiting for it to become available. The actual result
     // is unimportant and also not well defined.
     unsigned result = 0;
-    gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
-    gles2->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &result);
+    gpu::raster::RasterInterface* ri = context_provider_->RasterInterface();
+    ri->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &result);
   }
 
   std::move(callback).Run();
@@ -425,8 +390,8 @@
   ui::ContextFactory* context_factory =
       WMHelper::GetInstance()->env()->context_factory();
   // Note: This can fail if GPU acceleration has been disabled.
-  scoped_refptr<viz::ContextProvider> context_provider =
-      context_factory->SharedMainThreadContextProvider();
+  scoped_refptr<viz::RasterContextProvider> context_provider =
+      context_factory->SharedMainThreadRasterContextProvider();
   if (!context_provider) {
     DLOG(WARNING) << "Failed to acquire a context provider";
     resource->id = 0;
@@ -444,8 +409,8 @@
   // |texture| using a call to CopyTexImage.
   if (!contents_texture_) {
     contents_texture_ = std::make_unique<Texture>(
-        context_factory, context_provider.get(), gpu_memory_buffer_.get(),
-        texture_target_, query_type_, wait_for_release_delay_);
+        context_factory, gpu_memory_buffer_.get(), texture_target_, query_type_,
+        wait_for_release_delay_);
   }
   Texture* contents_texture = contents_texture_.get();
 
@@ -460,7 +425,7 @@
   // Zero-copy means using the contents texture directly.
   if (use_zero_copy_) {
     // This binds the latest contents of this buffer to |contents_texture|.
-    gpu::SyncToken sync_token = contents_texture->BindTexImage();
+    gpu::SyncToken sync_token = contents_texture->UpdateSharedImage();
     resource->mailbox_holder = gpu::MailboxHolder(contents_texture->mailbox(),
                                                   sync_token, texture_target_);
     resource->is_overlay_candidate = is_overlay_candidate_;
@@ -470,7 +435,7 @@
     // compositor.
     resource_manager->SetResourceReleaseCallback(
         resource->id,
-        base::BindOnce(&Buffer::Texture::ReleaseTexImage,
+        base::BindOnce(&Buffer::Texture::ReleaseSharedImage,
                        base::Unretained(contents_texture),
                        base::BindOnce(&Buffer::ReleaseContentsTexture,
                                       AsWeakPtr(), std::move(contents_texture_),
@@ -480,8 +445,8 @@
 
   // Create a mailbox texture that we copy the buffer contents to.
   if (!texture_) {
-    texture_ =
-        std::make_unique<Texture>(context_factory, context_provider.get());
+    texture_ = std::make_unique<Texture>(context_factory,
+                                         gpu_memory_buffer_->GetSize());
   }
   Texture* texture = texture_.get();
 
diff --git a/components/exo/buffer_unittest.cc b/components/exo/buffer_unittest.cc
index 3e8e934..f2d80e6 100644
--- a/components/exo/buffer_unittest.cc
+++ b/components/exo/buffer_unittest.cc
@@ -14,9 +14,8 @@
 #include "components/exo/test/exo_test_helper.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/resources/single_release_callback.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/raster_interface.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/khronos/GLES2/gl2.h"
 #include "ui/aura/env.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/test/in_process_context_factory.h"
@@ -39,11 +38,12 @@
   std::vector<GLbyte*> sync_tokens;
   for (auto& resource : frame->resource_list)
     sync_tokens.push_back(resource.mailbox_holder.sync_token.GetData());
-  gpu::gles2::GLES2Interface* gles2 = GetAuraEnv()
-                                          ->context_factory()
-                                          ->SharedMainThreadContextProvider()
-                                          ->ContextGL();
-  gles2->VerifySyncTokensCHROMIUM(sync_tokens.data(), sync_tokens.size());
+  gpu::raster::RasterInterface* ri =
+      GetAuraEnv()
+          ->context_factory()
+          ->SharedMainThreadRasterContextProvider()
+          ->RasterInterface();
+  ri->VerifySyncTokensCHROMIUM(sync_tokens.data(), sync_tokens.size());
 }
 
 TEST_F(BufferTest, ReleaseCallback) {
@@ -102,12 +102,12 @@
       frame_sink_holder->resource_manager(), false, &resource);
   ASSERT_TRUE(rv);
 
-  scoped_refptr<viz::ContextProvider> context_provider =
-      GetAuraEnv()->context_factory()->SharedMainThreadContextProvider();
+  scoped_refptr<viz::RasterContextProvider> context_provider =
+      GetAuraEnv()->context_factory()->SharedMainThreadRasterContextProvider();
   if (context_provider) {
-    gpu::gles2::GLES2Interface* gles2 = context_provider->ContextGL();
-    gles2->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
-                               GL_INNOCENT_CONTEXT_RESET_ARB);
+    gpu::raster::RasterInterface* ri = context_provider->RasterInterface();
+    ri->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
+                            GL_INNOCENT_CONTEXT_RESET_ARB);
   }
 
   // Release buffer.
diff --git a/components/exo/test/exo_test_base.cc b/components/exo/test/exo_test_base.cc
index 385cde74..92c3e49 100644
--- a/components/exo/test/exo_test_base.cc
+++ b/components/exo/test/exo_test_base.cc
@@ -10,7 +10,7 @@
 #include "components/exo/wm_helper.h"
 #include "components/exo/wm_helper_chromeos.h"
 #include "ui/aura/env.h"
-#include "ui/base/ime/input_method_factory.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/wm/core/wm_core_switches.h"
 
 namespace exo {
diff --git a/components/exo/test/exo_test_base_aura.cc b/components/exo/test/exo_test_base_aura.cc
index 6ceb5d30..473f0cc 100644
--- a/components/exo/test/exo_test_base_aura.cc
+++ b/components/exo/test/exo_test_base_aura.cc
@@ -5,7 +5,7 @@
 #include "components/exo/test/exo_test_base_aura.h"
 
 #include "components/exo/wm_helper.h"
-#include "ui/base/ime/input_method_factory.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/compositor/test/context_factories_for_test.h"
 #include "ui/display/manager/managed_display_info.h"
 #include "ui/wm/core/default_activation_client.h"
diff --git a/components/exo/wayland/zcr_remote_shell.cc b/components/exo/wayland/zcr_remote_shell.cc
index 713681f..8a6a5d2 100644
--- a/components/exo/wayland/zcr_remote_shell.cc
+++ b/components/exo/wayland/zcr_remote_shell.cc
@@ -551,8 +551,22 @@
   wl_resource_destroy(resource);
 }
 
+void input_method_surface_set_bounds(wl_client* client,
+                                     wl_resource* resource,
+                                     uint32_t display_id_hi,
+                                     uint32_t display_id_lo,
+                                     int32_t x,
+                                     int32_t y,
+                                     int32_t width,
+                                     int32_t height) {
+  GetUserDataAs<InputMethodSurface>(resource)->SetBounds(
+      static_cast<int64_t>(display_id_hi) << 32 | display_id_lo,
+      gfx::Rect(x, y, width, height));
+}
+
 const struct zcr_input_method_surface_v1_interface
-    input_method_surface_implementation = {input_method_surface_destroy};
+    input_method_surface_implementation = {input_method_surface_destroy,
+                                           input_method_surface_set_bounds};
 
 ////////////////////////////////////////////////////////////////////////////////
 // remote_shell_interface:
diff --git a/components/favicon/core/large_icon_service.h b/components/favicon/core/large_icon_service.h
index 0843935..f14555d 100644
--- a/components/favicon/core/large_icon_service.h
+++ b/components/favicon/core/large_icon_service.h
@@ -48,8 +48,8 @@
       const favicon_base::LargeIconCallback& callback,
       base::CancelableTaskTracker* tracker) = 0;
 
-  // Behaves the same as GetLargeIconOrFallbackStyleForPageUrl(), only returns
-  // the large icon (if available) decoded.
+  // Behaves the same as GetLargeIconRawBitmapOrFallbackStyleForPageUrl(), only
+  // returns the large icon (if available) decoded.
   virtual base::CancelableTaskTracker::TaskId
   GetLargeIconImageOrFallbackStyleForPageUrl(
       const GURL& page_url,
diff --git a/components/feedback/feedback_common.cc b/components/feedback/feedback_common.cc
index 1a356d6..5122185 100644
--- a/components/feedback/feedback_common.cc
+++ b/components/feedback/feedback_common.cc
@@ -55,11 +55,8 @@
 
 // Converts the system logs into a string that we can compress and send
 // with the report.
-// TODO(dcheng): This should probably just take advantage of string's move
-// constructor.
-std::unique_ptr<std::string> LogsToString(
-    const FeedbackCommon::SystemLogsMap& sys_info) {
-  std::unique_ptr<std::string> syslogs_string(new std::string);
+std::string LogsToString(const FeedbackCommon::SystemLogsMap& sys_info) {
+  std::string syslogs_string;
   for (const auto& iter : sys_info) {
     std::string key = iter.first;
     std::string value = iter.second;
@@ -73,11 +70,11 @@
       continue;
 
     if (value.find("\n") != std::string::npos) {
-      syslogs_string->append(key + "=" + kMultilineIndicatorString +
-                             kMultilineStartString + value + "\n" +
-                             kMultilineEndString);
+      syslogs_string.append(key + "=" + kMultilineIndicatorString +
+                            kMultilineStartString + value + "\n" +
+                            kMultilineEndString);
     } else {
-      syslogs_string->append(key + "=" + value + "\n");
+      syslogs_string.append(key + "=" + value + "\n");
     }
   }
   return syslogs_string;
@@ -118,7 +115,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 FeedbackCommon::AttachedFile::AttachedFile(const std::string& filename,
-                                           std::unique_ptr<std::string> data)
+                                           std::string data)
     : name(filename), data(std::move(data)) {}
 
 FeedbackCommon::AttachedFile::~AttachedFile() {}
@@ -129,23 +126,21 @@
 
 FeedbackCommon::FeedbackCommon() : product_id_(-1) {}
 
-void FeedbackCommon::AddFile(const std::string& filename,
-                             std::unique_ptr<std::string> data) {
+void FeedbackCommon::AddFile(const std::string& filename, std::string data) {
   base::AutoLock lock(attachments_lock_);
-  attachments_.emplace_back(new AttachedFile(filename, std::move(data)));
+  attachments_.emplace_back(filename, std::move(data));
 }
 
 void FeedbackCommon::AddLog(const std::string& name, const std::string& value) {
-  if (!logs_)
-    logs_ = base::WrapUnique(new SystemLogsMap);
-  (*logs_)[name] = value;
+  logs_[name] = value;
 }
 
-void FeedbackCommon::AddLogs(std::unique_ptr<SystemLogsMap> logs) {
-  if (logs_)
-    logs_->insert(logs->begin(), logs->end());
-  else
+void FeedbackCommon::AddLogs(SystemLogsMap logs) {
+  // The empty logs_ case is just an optimization.
+  if (logs_.empty())
     logs_ = std::move(logs);
+  else
+    logs.insert(logs.begin(), logs.end());
 }
 
 void FeedbackCommon::PrepareReport(
@@ -191,7 +186,7 @@
 
   AddFilesAndLogsToReport(feedback_data);
 
-  if (image() && image()->size()) {
+  if (image().size()) {
     userfeedback::PostedScreenshot screenshot;
     screenshot.set_mime_type(kPngMimeType);
 
@@ -202,7 +197,7 @@
     dimensions.set_height(0.0);
 
     *(screenshot.mutable_dimensions()) = dimensions;
-    screenshot.set_binary_content(*image());
+    screenshot.set_binary_content(image());
 
     *(feedback_data->mutable_screenshot()) = screenshot;
   }
@@ -213,13 +208,12 @@
 
 FeedbackCommon::~FeedbackCommon() {}
 
-void FeedbackCommon::CompressFile(
-    const base::FilePath& filename,
-    const std::string& zipname,
-    std::unique_ptr<std::string> data_to_be_compressed) {
-  std::unique_ptr<std::string> compressed_data(new std::string());
-  if (feedback_util::ZipString(filename, *data_to_be_compressed,
-                               compressed_data.get())) {
+void FeedbackCommon::CompressFile(const base::FilePath& filename,
+                                  const std::string& zipname,
+                                  std::string data_to_be_compressed) {
+  std::string compressed_data;
+  if (feedback_util::ZipString(filename, std::move(data_to_be_compressed),
+                               &compressed_data)) {
     std::string attachment_file_name = zipname;
     if (attachment_file_name.empty()) {
       // We need to use the UTF8Unsafe methods here to accommodate Windows,
@@ -232,10 +226,8 @@
 }
 
 void FeedbackCommon::CompressLogs() {
-  if (!logs_)
-    return;
-  std::unique_ptr<std::string> logs = LogsToString(*logs_);
-  if (!logs->empty()) {
+  std::string logs = LogsToString(logs_);
+  if (!logs.empty()) {
     CompressFile(base::FilePath(kLogsFilename), kLogsAttachmentName,
                  std::move(logs));
   }
@@ -245,13 +237,10 @@
     userfeedback::ExtensionSubmit* feedback_data) const {
   for (size_t i = 0; i < attachments(); ++i) {
     const AttachedFile* file = attachment(i);
-    AddAttachment(feedback_data, file->name.c_str(), *file->data);
+    AddAttachment(feedback_data, file->name.c_str(), file->data);
   }
 
-  if (!logs_)
-    return;
-
-  for (const auto& iter : *logs_) {
+  for (const auto& iter : logs_) {
     if (BelowCompressionThreshold(iter.second)) {
       // Small enough logs should end up in the report data itself. However,
       // they're still added as part of the system_logs.zip file.
diff --git a/components/feedback/feedback_common.h b/components/feedback/feedback_common.h
index 2f4016e..f7e382a8 100644
--- a/components/feedback/feedback_common.h
+++ b/components/feedback/feedback_common.h
@@ -29,20 +29,19 @@
   using SystemLogsMap = std::map<std::string, std::string>;
 
   struct AttachedFile {
-    explicit AttachedFile(const std::string& filename,
-                          std::unique_ptr<std::string> data);
+    explicit AttachedFile(const std::string& filename, std::string data);
     ~AttachedFile();
 
     std::string name;
-    std::unique_ptr<std::string> data;
+    std::string data;
   };
 
   FeedbackCommon();
 
-  void AddFile(const std::string& filename, std::unique_ptr<std::string> data);
+  void AddFile(const std::string& filename, std::string data);
 
   void AddLog(const std::string& name, const std::string& value);
-  void AddLogs(std::unique_ptr<SystemLogsMap> logs);
+  void AddLogs(SystemLogsMap logs);
 
   // Fill in |feedback_data| with all the data that we have collected.
   // CompressLogs() must have already been called.
@@ -53,15 +52,13 @@
   const std::string& page_url() const { return page_url_; }
   const std::string& description() const { return description_; }
   const std::string& user_email() const { return user_email_; }
-  const std::string* image() const { return image_.get(); }
-  const SystemLogsMap* sys_info() const { return logs_.get(); }
+  const std::string& image() const { return image_; }
+  const SystemLogsMap* sys_info() const { return &logs_; }
   int32_t product_id() const { return product_id_; }
   std::string user_agent() const { return user_agent_; }
   std::string locale() const { return locale_; }
 
-  const AttachedFile* attachment(size_t i) const {
-    return attachments_[i].get();
-  }
+  const AttachedFile* attachment(size_t i) const { return &attachments_[i]; }
   size_t attachments() const { return attachments_.size(); }
 
   // Setters
@@ -75,9 +72,7 @@
   void set_user_email(const std::string& user_email) {
     user_email_ = user_email;
   }
-  void set_image(std::unique_ptr<std::string> image) {
-    image_ = std::move(image);
-  }
+  void set_image(std::string image) { image_ = std::move(image); }
   void set_product_id(int32_t product_id) { product_id_ = product_id; }
   void set_user_agent(const std::string& user_agent) {
     user_agent_ = user_agent;
@@ -92,7 +87,7 @@
   // will be used and appended a ".zip" extension.
   void CompressFile(const base::FilePath& filename,
                     const std::string& zipname,
-                    std::unique_ptr<std::string> data_to_be_compressed);
+                    std::string data_to_be_compressed);
 
   void CompressLogs();
 
@@ -114,14 +109,14 @@
   std::string user_agent_;
   std::string locale_;
 
-  std::unique_ptr<std::string> image_;
+  std::string image_;
 
   // It is possible that multiple attachment add calls are running in
   // parallel, so synchronize access.
   base::Lock attachments_lock_;
-  std::vector<std::unique_ptr<AttachedFile>> attachments_;
+  std::vector<AttachedFile> attachments_;
 
-  std::unique_ptr<SystemLogsMap> logs_;
+  SystemLogsMap logs_;
 };
 
 #endif  // COMPONENTS_FEEDBACK_FEEDBACK_COMMON_H_
diff --git a/components/feedback/feedback_data.cc b/components/feedback/feedback_data.cc
index 38fab874a1..19818ba 100644
--- a/components/feedback/feedback_data.cc
+++ b/components/feedback/feedback_data.cc
@@ -71,7 +71,7 @@
 
   if (sys_info) {
     ++pending_op_count_;
-    AddLogs(std::move(sys_info));
+    AddLogs(std::move(*sys_info));
     base::PostTaskWithTraitsAndReply(
         FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
         base::BindOnce(&FeedbackData::CompressLogs, this),
@@ -79,12 +79,9 @@
   }
 }
 
-void FeedbackData::SetAndCompressHistograms(
-    std::unique_ptr<std::string> histograms) {
+void FeedbackData::SetAndCompressHistograms(std::string histograms) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  if (!histograms)
-    return;
   ++pending_op_count_;
   base::PostTaskWithTraitsAndReply(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
@@ -94,11 +91,10 @@
       base::BindOnce(&FeedbackData::OnCompressComplete, this));
 }
 
-void FeedbackData::AttachAndCompressFileData(
-    std::unique_ptr<std::string> attached_filedata) {
+void FeedbackData::AttachAndCompressFileData(std::string attached_filedata) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  if (!attached_filedata || attached_filedata->empty())
+  if (attached_filedata.empty())
     return;
   ++pending_op_count_;
   base::FilePath attached_file =
@@ -118,10 +114,7 @@
   if (manager)
     manager->DiscardTraceData(trace_id);
 
-  std::unique_ptr<std::string> data(new std::string);
-  data->swap(trace_data->data());
-
-  AddFile(kTraceFilename, std::move(data));
+  AddFile(kTraceFilename, std::move(trace_data->data()));
 
   set_category_tag(kPerformanceCategoryTag);
   --pending_op_count_;
diff --git a/components/feedback/feedback_data.h b/components/feedback/feedback_data.h
index 46bbc33..2c96b79 100644
--- a/components/feedback/feedback_data.h
+++ b/components/feedback/feedback_data.h
@@ -36,11 +36,10 @@
 
   // Sets the histograms for this instance and kicks off its
   // compression.
-  void SetAndCompressHistograms(std::unique_ptr<std::string> histograms);
+  void SetAndCompressHistograms(std::string histograms);
 
   // Sets the attached file data and kicks off its compression.
-  void AttachAndCompressFileData(
-      std::unique_ptr<std::string> attached_filedata);
+  void AttachAndCompressFileData(std::string attached_filedata);
 
   // Returns true if we've completed all the tasks needed before we can send
   // feedback - at this time this is includes getting the feedback page data
diff --git a/components/feedback/feedback_data_unittest.cc b/components/feedback/feedback_data_unittest.cc
index 1ca48b6..b93bc26 100644
--- a/components/feedback/feedback_data_unittest.cc
+++ b/components/feedback/feedback_data_unittest.cc
@@ -49,10 +49,6 @@
   DISALLOW_COPY_AND_ASSIGN(MockUploader);
 };
 
-std::unique_ptr<std::string> MakeScoped(const char* str) {
-  return std::make_unique<std::string>(str);
-}
-
 }  // namespace
 
 class FeedbackDataTest : public testing::Test {
@@ -98,9 +94,9 @@
 };
 
 TEST_F(FeedbackDataTest, ReportSending) {
-  data_->SetAndCompressHistograms(MakeScoped(kHistograms));
-  data_->set_image(MakeScoped(kImageData));
-  data_->AttachAndCompressFileData(MakeScoped(kFileData));
+  data_->SetAndCompressHistograms(kHistograms);
+  data_->set_image(kImageData);
+  data_->AttachAndCompressFileData(kFileData);
   Send();
   RunMessageLoop();
   EXPECT_TRUE(data_->IsDataComplete());
diff --git a/components/history/core/browser/history_backend_client.h b/components/history/core/browser/history_backend_client.h
index 29da78a9..343f722 100644
--- a/components/history/core/browser/history_backend_client.h
+++ b/components/history/core/browser/history_backend_client.h
@@ -39,9 +39,6 @@
   // Returns the set of pinned URLs with their titles.
   virtual std::vector<URLAndTitle> GetPinnedURLs() = 0;
 
-  // Returns whether database errors should be reported to the crash server.
-  virtual bool ShouldReportDatabaseError() = 0;
-
   // Returns whether |url| should be considered web-safe (see
   // content::ChildProcessSecurityPolicy).
   virtual bool IsWebSafe(const GURL& url) = 0;
diff --git a/components/history/core/browser/thumbnail_database.cc b/components/history/core/browser/thumbnail_database.cc
index 7748a79..e1f64e3 100644
--- a/components/history/core/browser/thumbnail_database.cc
+++ b/components/history/core/browser/thumbnail_database.cc
@@ -128,28 +128,6 @@
                             invalid_type, STRUCTURE_EVENT_MAX);
 }
 
-// TODO(shess): If this proves out, move it all into sql::Database to be
-// shared.
-void GenerateDiagnostics(sql::Database* db,
-                         int extended_error,
-                         sql::Statement* stmt) {
-  // Since some/most errors will not resolve themselves, only report
-  // once per Chrome run.
-  static bool reported = false;
-  if (reported)
-    return;
-  reported = true;
-
-  // Only pass 5% of new reports to prevent a thundering herd of dumps.
-  // TODO(shess): If this could be related to the time in the channel, then the
-  // rate could ramp up over time.  Perhaps could remember the timestamp the
-  // first time upload is considered, and ramp up 1% per day?
-  static const uint64_t kReportPercent = 5;
-  uint64_t rand = base::RandGenerator(100);
-  if (rand <= kReportPercent)
-    db->ReportDiagnosticInfo(extended_error, stmt);
-}
-
 // NOTE(shess): Schema modifications must consider initial creation in
 // |InitImpl()| and history pruning in |RetainDataForPageUrls()|.
 bool InitTables(sql::Database* db) {
@@ -230,10 +208,6 @@
   // AFAICT, should be the history thread, but at this level I can't
   // see how to reach that.
 
-  if (backend_client && backend_client->ShouldReportDatabaseError()) {
-    GenerateDiagnostics(db, extended_error, stmt);
-  }
-
   // Attempt to recover corrupt databases.
   if (sql::Recovery::ShouldRecover(extended_error)) {
     // NOTE(shess): This approach is valid as of version 8.  When bumping the
diff --git a/components/history/core/test/history_client_fake_bookmarks.cc b/components/history/core/test/history_client_fake_bookmarks.cc
index 4c55245..003b27db 100644
--- a/components/history/core/test/history_client_fake_bookmarks.cc
+++ b/components/history/core/test/history_client_fake_bookmarks.cc
@@ -82,7 +82,6 @@
   // HistoryBackendClient implementation.
   bool IsPinnedURL(const GURL& url) override;
   std::vector<URLAndTitle> GetPinnedURLs() override;
-  bool ShouldReportDatabaseError() override;
   bool IsWebSafe(const GURL& url) override;
 #if defined(OS_ANDROID)
   void OnHistoryBackendInitialized(HistoryBackend* history_backend,
@@ -115,10 +114,6 @@
   return bookmarks_->GetBookmarks();
 }
 
-bool HistoryBackendClientFakeBookmarks::ShouldReportDatabaseError() {
-  return false;
-}
-
 bool HistoryBackendClientFakeBookmarks::IsWebSafe(const GURL& url) {
   return true;
 }
diff --git a/components/image_fetcher/core/cached_image_fetcher.cc b/components/image_fetcher/core/cached_image_fetcher.cc
index baef95f..deaf389 100644
--- a/components/image_fetcher/core/cached_image_fetcher.cc
+++ b/components/image_fetcher/core/cached_image_fetcher.cc
@@ -109,13 +109,18 @@
   CachedImageFetcherMetricsReporter::ReportEvent(
       request.params.uma_client_name(), CachedImageFetcherEvent::kImageRequest);
 
-  // First, try to load the image from the cache, then try the network.
-  image_cache_->LoadImage(
-      read_only_, image_url.spec(),
-      base::BindOnce(&CachedImageFetcher::OnImageFetchedFromCache,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(request),
-                     std::move(image_data_callback),
-                     std::move(image_callback)));
+  if (params.skip_disk_cache_read()) {
+    EnqueueFetchImageFromNetwork(request, std::move(image_data_callback),
+                                 std::move(image_callback));
+  } else {
+    // First, try to load the image from the cache, then try the network.
+    image_cache_->LoadImage(
+        read_only_, image_url.spec(),
+        base::BindOnce(&CachedImageFetcher::OnImageFetchedFromCache,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(request),
+                       std::move(image_data_callback),
+                       std::move(image_callback)));
+  }
 }
 
 void CachedImageFetcher::OnImageFetchedFromCache(
diff --git a/components/image_fetcher/core/cached_image_fetcher_unittest.cc b/components/image_fetcher/core/cached_image_fetcher_unittest.cc
index 103a779..a4e8251 100644
--- a/components/image_fetcher/core/cached_image_fetcher_unittest.cc
+++ b/components/image_fetcher/core/cached_image_fetcher_unittest.cc
@@ -50,6 +50,7 @@
 
 constexpr char kUmaClientName[] = "TestUma";
 constexpr char kImageData[] = "data";
+constexpr char kImageDataOther[] = "other";
 
 const char kCachedImageFetcherEventHistogramName[] =
     "CachedImageFetcher.Events";
@@ -338,4 +339,24 @@
   }
 }
 
+TEST_F(CachedImageFetcherTest, FetchImageWithSkipDiskCache) {
+  // Save the image in the database.
+  image_cache()->SaveImage(kImageUrl.spec(), kImageDataOther);
+  RunUntilIdle();
+  test_url_loader_factory()->AddResponse(kImageUrl.spec(), kImageData);
+
+  base::MockCallback<ImageDataFetcherCallback> data_callback;
+  base::MockCallback<ImageFetcherCallback> image_callback;
+
+  ImageFetcherParams params(TRAFFIC_ANNOTATION_FOR_TESTS, kUmaClientName);
+  params.set_skip_disk_cache_read(true);
+
+  EXPECT_CALL(data_callback, Run(kImageData, _));
+  EXPECT_CALL(image_callback, Run(NonEmptyImage(), _));
+  cached_image_fetcher()->FetchImageAndData(kImageUrl, data_callback.Get(),
+                                            image_callback.Get(), params);
+
+  RunUntilIdle();
+}
+
 }  // namespace image_fetcher
diff --git a/components/image_fetcher/core/image_fetcher.cc b/components/image_fetcher/core/image_fetcher.cc
index 18f6dba7..949ccbb3 100644
--- a/components/image_fetcher/core/image_fetcher.cc
+++ b/components/image_fetcher/core/image_fetcher.cc
@@ -11,7 +11,8 @@
     std::string uma_client_name)
     : network_traffic_annotation_tag_(network_traffic_annotation_tag),
       uma_client_name_(uma_client_name),
-      skip_transcoding_(false) {}
+      skip_transcoding_(false),
+      skip_disk_cache_read_(false) {}
 
 ImageFetcherParams::ImageFetcherParams(const ImageFetcherParams& params) =
     default;
diff --git a/components/image_fetcher/core/image_fetcher.h b/components/image_fetcher/core/image_fetcher.h
index 3e7e56f..ec709522 100644
--- a/components/image_fetcher/core/image_fetcher.h
+++ b/components/image_fetcher/core/image_fetcher.h
@@ -74,6 +74,12 @@
     skip_transcoding_ = skip_transcoding;
   }
 
+  bool skip_disk_cache_read() { return skip_disk_cache_read_; }
+
+  void set_skip_disk_cache_read(bool skip_disk_cache_read) {
+    skip_disk_cache_read_ = skip_disk_cache_read;
+  }
+
  private:
   void set_skip_transcoding(bool skip_transcoding) {
     skip_transcoding_ = skip_transcoding;
@@ -89,6 +95,9 @@
   // some java clients we decode GIFs entirely in Java which is safe to do
   // in-process without transcoding.
   bool skip_transcoding_;
+  // True if the disk cache should be skipped because it was already checked in
+  // java.
+  bool skip_disk_cache_read_;
 };
 
 // A class used to fetch server images. It can be called from any thread and the
diff --git a/components/metrics/stability_metrics_helper.cc b/components/metrics/stability_metrics_helper.cc
index fae139b5..65da8bf 100644
--- a/components/metrics/stability_metrics_helper.cc
+++ b/components/metrics/stability_metrics_helper.cc
@@ -322,8 +322,7 @@
   local_state_->SetInt64(path, value + 1);
 }
 
-void StabilityMetricsHelper::LogRendererHang(RendererHangCause hang_cause) {
-  UMA_HISTOGRAM_ENUMERATION("ChildProcess.HungRendererCause", hang_cause);
+void StabilityMetricsHelper::LogRendererHang() {
   IncrementPrefValue(prefs::kStabilityRendererHangCount);
 }
 
diff --git a/components/metrics/stability_metrics_helper.h b/components/metrics/stability_metrics_helper.h
index 93c77b79..ec82e02 100644
--- a/components/metrics/stability_metrics_helper.h
+++ b/components/metrics/stability_metrics_helper.h
@@ -15,16 +15,6 @@
 
 namespace metrics {
 
-// The cause of the renderer hang.
-// This is for a temporary UMA value to aid in determining the cause of
-// renderer hangs described in crbug.com/938647.
-enum class RendererHangCause {
-  kCommitTimeout = 0,
-  kInputAckTimeout = 1,
-  // Special enumerator value used by histogram macros.
-  kMaxValue = kInputAckTimeout
-};
-
 class SystemProfileProto;
 
 // StabilityMetricsHelper is a class that providers functionality common to
@@ -63,7 +53,7 @@
   void LogRendererLaunched(bool was_extension_process);
 
   // Records a renderer process hang.
-  void LogRendererHang(RendererHangCause hang_cause);
+  void LogRendererHang();
 
   // Registers local state prefs used by this class.
   static void RegisterPrefs(PrefRegistrySimple* registry);
diff --git a/components/mirroring/mojom/mirroring_service.mojom b/components/mirroring/mojom/mirroring_service.mojom
index 8bd1317..09c6762 100644
--- a/components/mirroring/mojom/mirroring_service.mojom
+++ b/components/mirroring/mojom/mirroring_service.mojom
@@ -24,7 +24,4 @@
         ResourceProvider resource_provider,
         CastMessageChannel outbound_channel,
         CastMessageChannel& inbound_channel);
-
-  // TODO(xjz): Add interfaces to get the streaming events/stats and mirroring
-  // logs.
 };
diff --git a/components/mirroring/mojom/resource_provider.mojom b/components/mirroring/mojom/resource_provider.mojom
index 6b11637..7605585 100644
--- a/components/mirroring/mojom/resource_provider.mojom
+++ b/components/mirroring/mojom/resource_provider.mojom
@@ -32,7 +32,4 @@
                     uint32 shared_memory_count);
   ConnectToRemotingSource(media.mojom.Remoter remoter,
                           media.mojom.RemotingSource& request);
-
-  // TODO(xjz): Add interface for HW encoder profiles query and VEA create
-  // support.
 };
diff --git a/components/neterror/resources/neterror.css b/components/neterror/resources/neterror.css
index 8c56fad..8a0dc65 100644
--- a/components/neterror/resources/neterror.css
+++ b/components/neterror/resources/neterror.css
@@ -751,18 +751,33 @@
 
 /* Offline page */
 .offline {
-  transition: -webkit-filter 1.5s cubic-bezier(0.65, 0.05, 0.36, 1),
+  transition: filter 1.5s cubic-bezier(0.65, 0.05, 0.36, 1),
               background-color 1.5s cubic-bezier(0.65, 0.05, 0.36, 1);
-  will-change: -webkit-filter, background-color;
+  will-change: filter, background-color;
+}
+
+.offline body {
+  transition: background-color 1.5s cubic-bezier(0.65, 0.05, 0.36, 1);
 }
 
 .offline #main-message > p {
   display: none;
 }
 
+/* iOS WKWebView inverts the background color set at the HTML level
+whereas Blink does not. */
 .offline.inverted {
-  -webkit-filter: invert(100%);
+  filter: invert(1);
+<if expr="not is_ios">
   background-color: #000;
+</if>
+<if expr="is_ios">
+  background-color: #fff;
+</if>
+}
+
+.offline.inverted body {
+  background-color: #fff;
 }
 
 .offline .interstitial-wrapper {
diff --git a/components/neterror/resources/neterror.js b/components/neterror/resources/neterror.js
index 052916d..0d23dfa6 100644
--- a/components/neterror/resources/neterror.js
+++ b/components/neterror/resources/neterror.js
@@ -78,7 +78,7 @@
   classList['last_icon_class'] = newClass;
 
   if (newClass == 'icon-offline') {
-    document.body.classList.add('offline');
+    document.firstElementChild.classList.add('offline');
     new Runner('.interstitial-wrapper');
   } else {
     document.body.classList.add('neterror');
diff --git a/components/neterror/resources/offline.js b/components/neterror/resources/offline.js
index d19f0cc6..de4b80dd 100644
--- a/components/neterror/resources/offline.js
+++ b/components/neterror/resources/offline.js
@@ -118,7 +118,7 @@
   GRAVITY: 0.6,
   INITIAL_JUMP_VELOCITY: 12,
   INVERT_FADE_DURATION: 12000,
-  INVERT_DISTANCE: 700,
+  INVERT_DISTANCE: 100,
   MAX_BLINK_COUNT: 3,
   MAX_CLOUDS: 6,
   MAX_OBSTACLE_LENGTH: 3,
@@ -981,13 +981,16 @@
    * @param {boolean} Whether to reset colors.
    */
   invert: function(reset) {
+    let htmlEl = document.firstElementChild;
+
     if (reset) {
-      document.body.classList.toggle(Runner.classes.INVERTED, false);
+      htmlEl.classList.toggle(Runner.classes.INVERTED,
+          false);
       this.invertTimer = 0;
       this.inverted = false;
     } else {
-      this.inverted = document.body.classList.toggle(Runner.classes.INVERTED,
-          this.invertTrigger);
+      this.inverted = htmlEl.classList.toggle(
+          Runner.classes.INVERTED, this.invertTrigger);
     }
   }
 };
diff --git a/components/offline_pages/core/model/add_page_task.cc b/components/offline_pages/core/model/add_page_task.cc
index 0e3df54d6..4dff380 100644
--- a/components/offline_pages/core/model/add_page_task.cc
+++ b/components/offline_pages/core/model/add_page_task.cc
@@ -39,12 +39,12 @@
                                     sql::Database* db) {
   static const char kSql[] =
       "INSERT OR IGNORE INTO offlinepages_v1"
-      " (offline_id,online_url,client_namespace,client_id,file_path,file_size,"
-      "creation_time,last_access_time,access_count,title,original_url,"
-      "request_origin,system_download_id,file_missing_time,digest,"
-      "snippet,attribution)"
+      " (offline_id,online_url,client_namespace,client_id,file_path,"
+      "file_size,creation_time,last_access_time,access_count,"
+      "title,original_url,request_origin,system_download_id,"
+      "file_missing_time,digest)"
       " VALUES "
-      "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
+      "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
 
   sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
   statement.BindInt64(0, item.offline_id);
@@ -62,8 +62,6 @@
   statement.BindInt64(12, item.system_download_id);
   statement.BindInt64(13, store_utils::ToDatabaseTime(item.file_missing_time));
   statement.BindString(14, item.digest);
-  statement.BindString(15, item.snippet);
-  statement.BindString(16, item.attribution);
 
   if (!statement.Run())
     return ItemActionStatus::STORE_ERROR;
diff --git a/components/offline_pages/core/model/add_page_task_unittest.cc b/components/offline_pages/core/model/add_page_task_unittest.cc
index 903ea15..9f54ccc 100644
--- a/components/offline_pages/core/model/add_page_task_unittest.cc
+++ b/components/offline_pages/core/model/add_page_task_unittest.cc
@@ -37,8 +37,6 @@
 const base::string16 kTestTitle = base::UTF8ToUTF16("a title");
 const int64_t kTestDownloadId = 767574LL;
 const std::string kTestDigest("TesTIngDigEst==");
-const std::string kTestAttribution = "attribution";
-const std::string kTestSnippet = "snippet";
 
 }  // namespace
 
@@ -101,8 +99,6 @@
   page.system_download_id = kTestDownloadId;
   page.file_missing_time = base::Time::Now();
   page.digest = kTestDigest;
-  page.attribution = kTestAttribution;
-  page.snippet = kTestSnippet;
 
   AddPage(page);
 
diff --git a/components/offline_pages/core/model/offline_page_test_utils.cc b/components/offline_pages/core/model/offline_page_test_utils.cc
index c962a4b..3d36207 100644
--- a/components/offline_pages/core/model/offline_page_test_utils.cc
+++ b/components/offline_pages/core/model/offline_page_test_utils.cc
@@ -78,12 +78,6 @@
   if (!item.digest.empty()) {
     value.SetKey("digest", Value(item.digest));
   }
-  if (!item.snippet.empty()) {
-    value.SetKey("snippet", Value(item.snippet));
-  }
-  if (!item.attribution.empty()) {
-    value.SetKey("attribution", Value(item.attribution));
-  }
 
   std::string value_string;
   base::JSONWriter::Write(value, &value_string);
diff --git a/components/offline_pages/core/model/store_thumbnail_task.cc b/components/offline_pages/core/model/store_thumbnail_task.cc
index 7eaf2711..67e0fb57 100644
--- a/components/offline_pages/core/model/store_thumbnail_task.cc
+++ b/components/offline_pages/core/model/store_thumbnail_task.cc
@@ -18,13 +18,12 @@
 bool StoreThumbnailSync(const OfflinePageThumbnail& thumbnail,
                         sql::Database* db) {
   static const char kSql[] =
-      "INSERT OR REPLACE INTO page_thumbnails (offline_id,expiration,thumbnail,"
-      "favicon) VALUES (?,?,?,?)";
+      "INSERT OR REPLACE INTO page_thumbnails (offline_id, expiration, "
+      "thumbnail) VALUES (?, ?, ?)";
   sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
   statement.BindInt64(0, thumbnail.offline_id);
   statement.BindInt64(1, store_utils::ToDatabaseTime(thumbnail.expiration));
   statement.BindString(2, thumbnail.thumbnail);
-  statement.BindString(3, std::string());
   return statement.Run();
 }
 
diff --git a/components/offline_pages/core/offline_page_item.h b/components/offline_pages/core/offline_page_item.h
index 291475f..578fce40 100644
--- a/components/offline_pages/core/offline_page_item.h
+++ b/components/offline_pages/core/offline_page_item.h
@@ -92,10 +92,6 @@
   // page can be trusted. This field will always be an empty string for
   // temporary and shared pages.
   std::string digest;
-  // Snippet from the article.
-  std::string snippet;
-  // Text indicating the article's publisher.
-  std::string attribution;
 };
 
 // This operator is for testing only, see offline_page_test_utils.cc.
diff --git a/components/offline_pages/core/offline_page_metadata_store.cc b/components/offline_pages/core/offline_page_metadata_store.cc
index fa4dc87..75c36878 100644
--- a/components/offline_pages/core/offline_page_metadata_store.cc
+++ b/components/offline_pages/core/offline_page_metadata_store.cc
@@ -41,7 +41,7 @@
 }
 
 bool CreateOfflinePagesTable(sql::Database* db) {
-  static const char kCreateLatestOfflinePagesTableSql[] =
+  static const char kSql[] =
       "CREATE TABLE IF NOT EXISTS " OFFLINE_PAGES_TABLE_NAME
       "(offline_id INTEGER PRIMARY KEY NOT NULL,"
       " creation_time INTEGER NOT NULL,"
@@ -60,11 +60,9 @@
       " title VARCHAR NOT NULL DEFAULT '',"
       " original_url VARCHAR NOT NULL DEFAULT '',"
       " request_origin VARCHAR NOT NULL DEFAULT '',"
-      " digest VARCHAR NOT NULL DEFAULT '',"
-      " snippet VARCHAR NOT NULL DEFAULT '',"
-      " attribution VARCHAR NOT NULL DEFAULT ''"
+      " digest VARCHAR NOT NULL DEFAULT ''"
       ")";
-  return db->Execute(kCreateLatestOfflinePagesTableSql);
+  return db->Execute(kSql);
 }
 
 bool UpgradeWithQuery(sql::Database* db, const char* upgrade_sql) {
@@ -72,26 +70,7 @@
                    " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) {
     return false;
   }
-  static const char kCreateOfflinePagesTableVersion1Sql[] =
-      "CREATE TABLE IF NOT EXISTS " OFFLINE_PAGES_TABLE_NAME
-      "(offline_id INTEGER PRIMARY KEY NOT NULL,"
-      " creation_time INTEGER NOT NULL,"
-      " file_size INTEGER NOT NULL,"
-      " last_access_time INTEGER NOT NULL,"
-      " access_count INTEGER NOT NULL,"
-      " system_download_id INTEGER NOT NULL DEFAULT 0,"
-      " file_missing_time INTEGER NOT NULL DEFAULT 0,"
-      " upgrade_attempt INTEGER NOT NULL DEFAULT 0,"
-      " client_namespace VARCHAR NOT NULL,"
-      " client_id VARCHAR NOT NULL,"
-      " online_url VARCHAR NOT NULL,"
-      " file_path VARCHAR NOT NULL,"
-      " title VARCHAR NOT NULL DEFAULT '',"
-      " original_url VARCHAR NOT NULL DEFAULT '',"
-      " request_origin VARCHAR NOT NULL DEFAULT '',"
-      " digest VARCHAR NOT NULL DEFAULT ''"
-      ")";
-  if (!db->Execute(kCreateOfflinePagesTableVersion1Sql))
+  if (!CreateOfflinePagesTable(db))
     return false;
   if (!db->Execute(upgrade_sql))
     return false;
@@ -203,8 +182,7 @@
       "CREATE TABLE IF NOT EXISTS page_thumbnails"
       " (offline_id INTEGER PRIMARY KEY NOT NULL,"
       " expiration INTEGER NOT NULL,"
-      " thumbnail BLOB NOT NULL,"
-      " favicon BLOB NOT NULL"
+      " thumbnail BLOB NOT NULL"
       ")";
   return db->Execute(kSql);
 }
@@ -281,52 +259,10 @@
   if (!transaction.Begin())
     return false;
 
-  static const char kCreatePageThumbnailsSql[] =
-      "CREATE TABLE IF NOT EXISTS page_thumbnails"
-      " (offline_id INTEGER PRIMARY KEY NOT NULL,"
-      "expiration INTEGER NOT NULL,"
-      "thumbnail BLOB NOT NULL"
-      ")";
-  if (!db->Execute(kCreatePageThumbnailsSql))
-    return false;
-
-  meta_table->SetVersionNumber(3);
-  return transaction.Commit();
-}
-
-bool UpgradeFromVersion3ToVersion4(sql::Database* db,
-                                   sql::MetaTable* meta_table) {
-  sql::Transaction transaction(db);
-  if (!transaction.Begin())
-    return false;
-
-  const char kSql[] = "ALTER TABLE " OFFLINE_PAGES_TABLE_NAME
-                      " ADD COLUMN snippet VARCHAR NOT NULL DEFAULT ''; "
-                      "ALTER TABLE " OFFLINE_PAGES_TABLE_NAME
-                      " ADD COLUMN attribution VARCHAR NOT NULL DEFAULT '';";
-  if (!db->Execute(kSql))
-    return false;
-
-  // Upgrade page_thumbnails (rows must be copied into a new table since a
-  // column can't be modified in-place).
-  if (!db->Execute("ALTER TABLE page_thumbnails"
-                   " RENAME TO temp_page_thumbnails")) {
+  if (!CreatePageThumbnailsTable(db)) {
     return false;
   }
-  // Note: when the page_thumbnails schema changes, the old table creation query
-  // should be moved here.
-  if (!CreatePageThumbnailsTable(db))
-    return false;
-  static const char kUpgradeThumbnailsTableSql[] =
-      "INSERT INTO page_thumbnails"
-      " (offline_id,expiration,thumbnail)"
-      " SELECT offline_id,expiration,thumbnail FROM temp_page_thumbnails";
-  if (!db->Execute(kUpgradeThumbnailsTableSql))
-    return false;
-  if (!db->Execute("DROP TABLE IF EXISTS temp_page_thumbnails"))
-    return false;
-
-  meta_table->SetVersionNumber(4);
+  meta_table->SetVersionNumber(3);
   return transaction.Commit();
 }
 
@@ -356,10 +292,6 @@
         if (!UpgradeFromVersion2ToVersion3(db, &meta_table))
           return false;
         break;
-      case 3:
-        if (!UpgradeFromVersion3ToVersion4(db, &meta_table))
-          return false;
-        break;
       case OfflinePageMetadataStore::kCurrentVersion:
         return true;
       default:
diff --git a/components/offline_pages/core/offline_page_metadata_store.h b/components/offline_pages/core/offline_page_metadata_store.h
index e823c88..ebfb0d4f 100644
--- a/components/offline_pages/core/offline_page_metadata_store.h
+++ b/components/offline_pages/core/offline_page_metadata_store.h
@@ -35,29 +35,43 @@
 // OfflinePageMetadataStore keeps metadata for the offline pages in an SQLite
 // database.
 //
-// When updating the schema, be sure to do the following:
-// * Increment the version number kCurrentVersion (let's call its new value N).
-// * Write a function "UpgradeFromVersion<N-1>ToVersion<N>". This function
-//   should upgrade an existing database of the (previously) latest version and
-//   should call meta_table->SetVersionNumber(N). Add a case for version N-1 to
-//   the loop in CreateSchema.
-// * Update CreateLatestSchema() as necessary: this function creates a new empty
-//   DB. If there were changes to existing tables, their original "CREATE"
-//   queries should be copied into the new "UpgradeFromVersion..." function.
-// * Update `kCompatibleVersion` when a new schema becomes incompatible with
-//   old code (for instance, if a column is removed). Change it to the earliest
-//   version that is compatible with the new schema; that is very likely to be
-//   the version that broke compatibility.
-// * Add a test for upgrading to the latest database version to
-//   offline_page_metadata_store_unittest.cc. Good luck.
+// This store has a history of schema updates in pretty much every release.
+// Original schema was delivered in M52. Since then, the following changes
+// happened:
+// * In M53 expiration_time was added,
+// * In M54 title was added,
+// * In M55 we dropped the following fields (never used): version, status,
+//   offline_url, user_initiated.
+// * In M56 original_url was added.
+// * In M57 expiration_time was dropped. Existing expired pages would be
+//   removed when metadata consistency check happens.
+// * In M58-M60 there were no changes.
+// * In M61 request_origin was added.
+// * In M62 system_download_id, file_missing_time, upgrade_attempt and digest
+//   were added to support P2P sharing feature.
 //
+// Here is a procedure to update the schema for this store:
+// * Decide how to detect that the store is on a particular version, which
+//   typically means that a certain field exists or is missing. This happens in
+//   Upgrade section of |CreateSchema|
+// * Work out appropriate change and apply it to all existing upgrade paths. In
+//   the interest of performing a single update of the store, it upgrades from a
+//   detected version to the current one. This means that when making a change,
+//   more than a single query may have to be updated (in case of fields being
+//   removed or needed to be initialized to a specific, non-default value).
+//   Such approach is preferred to doing N updates for every changed version on
+//   a startup after browser update.
+// * New upgrade method should specify which version it is upgrading from, e.g.
+//   |UpgradeFrom54|.
+// * Upgrade should use |UpgradeWithQuery| and simply specify SQL command to
+//   move data from old table (prefixed by temp_) to the new one.
 class OfflinePageMetadataStore : public SqlStoreBase {
  public:
   // This is the first version saved in the meta table, which was introduced in
   // the store in M65. It is set once a legacy upgrade is run successfully for
   // the last time in |UpgradeFromLegacyVersion|.
   static const int kFirstPostLegacyVersion = 1;
-  static const int kCurrentVersion = 4;
+  static const int kCurrentVersion = 3;
   static const int kCompatibleVersion = kFirstPostLegacyVersion;
 
   // TODO(fgorski): Move to private and expose ForTest factory.
diff --git a/components/offline_pages/core/offline_page_metadata_store_unittest.cc b/components/offline_pages/core/offline_page_metadata_store_unittest.cc
index 46042ad9..3b696dd 100644
--- a/components/offline_pages/core/offline_page_metadata_store_unittest.cc
+++ b/components/offline_pages/core/offline_page_metadata_store_unittest.cc
@@ -51,8 +51,6 @@
 int64_t kTestSystemDownloadId = 42LL;
 const char kTestDigest[] = "test-digest";
 const base::Time kThumbnailExpiration = store_utils::FromDatabaseTime(42);
-const std::string kTestSnippet = "test snippet";
-const std::string kTestAttribution = "test attribution";
 
 // Build a store with outdated schema to simulate the upgrading process.
 void BuildTestStoreWithSchemaFromM52(const base::FilePath& file) {
@@ -472,18 +470,8 @@
   sql::Database db;
   ASSERT_TRUE(db.Open(file.Append(FILE_PATH_LITERAL("OfflinePages.db"))));
   sql::MetaTable meta_table;
-  ASSERT_TRUE(
-      meta_table.Init(&db, 2, OfflinePageMetadataStore::kCompatibleVersion));
-}
-
-void BuildTestStoreWithSchemaVersion3(const base::FilePath& file) {
-  BuildTestStoreWithSchemaVersion2(file);
-  sql::Database db;
-  ASSERT_TRUE(db.Open(file.Append(FILE_PATH_LITERAL("OfflinePages.db"))));
-  sql::MetaTable meta_table;
-  ASSERT_TRUE(
-      meta_table.Init(&db, 3, OfflinePageMetadataStore::kCompatibleVersion));
-
+  ASSERT_TRUE(meta_table.Init(&db, OfflinePageMetadataStore::kCurrentVersion,
+                              OfflinePageMetadataStore::kCompatibleVersion));
   static const char kSql[] =
       "CREATE TABLE page_thumbnails"
       " (offline_id INTEGER PRIMARY KEY NOT NULL,"
@@ -515,8 +503,6 @@
   GURL original_url(statement->ColumnString(13));
   std::string request_origin = statement->ColumnString(14);
   std::string digest = statement->ColumnString(15);
-  std::string snippet = statement->ColumnString(16);
-  std::string attribution = statement->ColumnString(17);
 
   OfflinePageItem item(url, id, client_id, path, file_size, creation_time);
   item.last_access_time = last_access_time;
@@ -527,8 +513,6 @@
   item.system_download_id = system_download_id;
   item.file_missing_time = file_missing_time;
   item.digest = digest;
-  item.snippet = snippet;
-  item.attribution = attribution;
   return item;
 }
 
@@ -594,8 +578,6 @@
     offline_page.original_url_if_different = GURL(kOriginalTestURL);
     offline_page.system_download_id = kTestSystemDownloadId;
     offline_page.digest = kTestDigest;
-    offline_page.snippet = kTestSnippet;
-    offline_page.attribution = kTestAttribution;
 
     EXPECT_EQ(ItemActionStatus::SUCCESS,
               AddOfflinePage(store.get(), offline_page));
@@ -707,9 +689,9 @@
           "file_path,"
           "file_size,creation_time,last_access_time,access_count,"
           "title,original_url,request_origin,system_download_id,"
-          "file_missing_time,digest,snippet,attribution)"
+          "file_missing_time,digest)"
           " VALUES "
-          "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
+          "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
 
       sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
       statement.BindInt64(0, item.offline_id);
@@ -729,8 +711,6 @@
       statement.BindInt64(13,
                           store_utils::ToDatabaseTime(item.file_missing_time));
       statement.BindString(14, item.digest);
-      statement.BindString(15, item.snippet);
-      statement.BindString(16, item.attribution);
 
       if (!statement.Run())
         return ItemActionStatus::STORE_ERROR;
@@ -771,13 +751,12 @@
     auto run_callback = base::BindLambdaForTesting([&](sql::Database* db) {
       static const char kSql[] =
           "INSERT INTO page_thumbnails"
-          " (offline_id, expiration, thumbnail, favicon) VALUES (?, ?, ?, ?)";
+          " (offline_id, expiration, thumbnail) VALUES (?, ?, ?)";
       sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
 
       statement.BindInt64(0, thumbnail.offline_id);
       statement.BindInt64(1, store_utils::ToDatabaseTime(thumbnail.expiration));
       statement.BindString(2, thumbnail.thumbnail);
-      statement.BindString(3, std::string());
       EXPECT_TRUE(statement.Run());
       return thumbnails;
     });
@@ -873,11 +852,6 @@
   LoadAndCheckStoreFromMetaVersion1AndUp();
 }
 
-TEST_F(OfflinePageMetadataStoreTest, LoadStoreWithMetaVersion3) {
-  BuildTestStoreWithSchemaVersion3(TempPath());
-  LoadAndCheckStoreFromMetaVersion1AndUp();
-}
-
 // Adds metadata of an offline page into a store and then opens the store
 // again to make sure that stored metadata survives store restarts.
 TEST_F(OfflinePageMetadataStoreTest, AddOfflinePage) {
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
index 02d0623d..28a65fd 100644
--- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
+++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
@@ -250,8 +250,7 @@
 
   std::unique_ptr<Task> generate_page_bundle_task =
       std::make_unique<GeneratePageBundleTask>(
-          this, service_->GetPrefetchStore(), service_->GetPrefetchGCMHandler(),
-          service_->GetCachedGCMToken(),
+          this, service_->GetPrefetchStore(), service_->GetCachedGCMToken(),
           service_->GetPrefetchNetworkRequestFactory(),
           base::BindOnce(
               &PrefetchDispatcherImpl::DidGenerateBundleOrGetOperationRequest,
diff --git a/components/offline_pages/core/prefetch/prefetch_importer_impl.cc b/components/offline_pages/core/prefetch/prefetch_importer_impl.cc
index d391183..ed0923b 100644
--- a/components/offline_pages/core/prefetch/prefetch_importer_impl.cc
+++ b/components/offline_pages/core/prefetch/prefetch_importer_impl.cc
@@ -104,8 +104,6 @@
                                dest_path, archive.file_size, base::Time::Now());
   offline_page.original_url_if_different = original_url;
   offline_page.title = archive.title;
-  offline_page.snippet = archive.snippet;
-  offline_page.attribution = archive.attribution;
 
   outstanding_import_offline_ids_.emplace(archive.offline_id);
 
diff --git a/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc b/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc
index d683cbe..80baf72c 100644
--- a/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc
+++ b/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc
@@ -23,18 +23,9 @@
 const GURL kTestURL("http://sample.org");
 const GURL kTestFinalURL("https://sample.org/foo");
 const ClientId kTestClientID("Foo", "C56A4180-65AA-42EC-A945-5FD21DEC0538");
-const base::string16 kTestTitle = base::UTF8ToUTF16("Hello");
+const base::string16 kTestTitle = base::ASCIIToUTF16("Hello");
 const base::FilePath kTestFilePath(FILE_PATH_LITERAL("foo"));
 const int64_t kTestFileSize = 88888;
-GURL TestFaviconURL() {
-  return GURL("http://sample.org/favicon.png");
-}
-std::string TestSnippet() {
-  return "test snippet";
-}
-std::string TestAttribution() {
-  return "sample.org";
-}
 
 class TestOfflinePageModel : public StubOfflinePageModel {
  public:
@@ -86,9 +77,6 @@
     archive.title = kTestTitle;
     archive.file_path = file_path;
     archive.file_size = kTestFileSize;
-    archive.favicon_url = TestFaviconURL();
-    archive.snippet = TestSnippet();
-    archive.attribution = TestAttribution();
     importer.ImportArchive(archive);
     task_runner_->RunUntilIdle();
   }
@@ -126,10 +114,6 @@
             offline_page_model()->last_added_page().original_url_if_different);
   EXPECT_EQ(kTestTitle, offline_page_model()->last_added_page().title);
   EXPECT_EQ(kTestFileSize, offline_page_model()->last_added_page().file_size);
-
-  EXPECT_EQ(TestSnippet(), offline_page_model()->last_added_page().snippet);
-  EXPECT_EQ(TestAttribution(),
-            offline_page_model()->last_added_page().attribution);
 }
 
 TEST_F(PrefetchImporterImplTest, MoveFileError) {
diff --git a/components/offline_pages/core/prefetch/prefetch_item.h b/components/offline_pages/core/prefetch/prefetch_item.h
index de3e54b..d0af6340 100644
--- a/components/offline_pages/core/prefetch/prefetch_item.h
+++ b/components/offline_pages/core/prefetch/prefetch_item.h
@@ -69,6 +69,12 @@
   // The URL to the favicon image of the article's hosting web site.
   GURL favicon_url;
 
+  // A snippet of the article's contents.
+  std::string snippet;
+
+  // The publisher name/web site the article is attributed to.
+  std::string attribution;
+
   // Number of attempts to request OPS to generate an archive for this item.
   int generate_bundle_attempts = 0;
 
@@ -118,12 +124,6 @@
   // The title of the page.
   base::string16 title;
 
-  // A snippet of the article's contents.
-  std::string snippet;
-
-  // The publisher name/web site the article is attributed to.
-  std::string attribution;
-
   // The file path to the archive of the page.
   base::FilePath file_path;
 
diff --git a/components/offline_pages/core/prefetch/prefetch_item_unittest.cc b/components/offline_pages/core/prefetch/prefetch_item_unittest.cc
index 23c926e..8e01d2d0 100644
--- a/components/offline_pages/core/prefetch/prefetch_item_unittest.cc
+++ b/components/offline_pages/core/prefetch/prefetch_item_unittest.cc
@@ -103,6 +103,12 @@
   item1.favicon_url = GURL("http://favicon");
   CheckFieldAndResetItem(item1, "favicon_url");
 
+  item1.snippet = "snippet";
+  CheckFieldAndResetItem(item1, "snippet");
+
+  item1.attribution = "attribution";
+  CheckFieldAndResetItem(item1, "attribution");
+
   item1.generate_bundle_attempts = 10;
   CheckFieldAndResetItem(item1, "generate_bundle_attempts");
 
@@ -139,12 +145,6 @@
   item1.file_size = 30;
   CheckFieldAndResetItem(item1, "file_size");
 
-  item1.snippet = "G";
-  CheckFieldAndResetItem(item1, "snippet");
-
-  item1.attribution = "H";
-  CheckFieldAndResetItem(item1, "attribution");
-
   CheckAllFieldsWereTested();
 }
 
diff --git a/components/offline_pages/core/prefetch/prefetch_service.h b/components/offline_pages/core/prefetch/prefetch_service.h
index 0348dc8..4a0cd58 100644
--- a/components/offline_pages/core/prefetch/prefetch_service.h
+++ b/components/offline_pages/core/prefetch/prefetch_service.h
@@ -82,6 +82,8 @@
   // suggestion from the Prefetching pipeline and/or the Offline Pages database.
   virtual void RemoveSuggestion(GURL url) = 0;
 
+  // Returns a pointer to the PrefetchGCMHandler. It is not available in reduced
+  // mode.
   virtual PrefetchGCMHandler* GetPrefetchGCMHandler() = 0;
 
   // Obtains the current GCM token from the PrefetchGCMHandler
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.cc b/components/offline_pages/core/prefetch/prefetch_service_impl.cc
index 4019ef5..8059ab2 100644
--- a/components/offline_pages/core/prefetch/prefetch_service_impl.cc
+++ b/components/offline_pages/core/prefetch/prefetch_service_impl.cc
@@ -7,10 +7,13 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "components/image_fetcher/core/image_fetcher.h"
 #include "components/offline_pages/core/client_id.h"
 #include "components/offline_pages/core/client_namespace_constants.h"
+#include "components/offline_pages/core/offline_page_feature.h"
 #include "components/offline_pages/core/prefetch/offline_metrics_collector.h"
 #include "components/offline_pages/core/prefetch/prefetch_background_task_handler.h"
 #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h"
@@ -28,7 +31,6 @@
 PrefetchServiceImpl::PrefetchServiceImpl(
     std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector,
     std::unique_ptr<PrefetchDispatcher> dispatcher,
-    std::unique_ptr<PrefetchGCMHandler> gcm_handler,
     std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory,
     OfflinePageModel* offline_page_model,
     std::unique_ptr<PrefetchStore> prefetch_store,
@@ -41,7 +43,6 @@
     image_fetcher::ImageFetcher* thumbnail_image_fetcher)
     : offline_metrics_collector_(std::move(offline_metrics_collector)),
       prefetch_dispatcher_(std::move(dispatcher)),
-      prefetch_gcm_handler_(std::move(gcm_handler)),
       network_request_factory_(std::move(network_request_factory)),
       offline_page_model_(offline_page_model),
       prefetch_store_(std::move(prefetch_store)),
@@ -55,7 +56,6 @@
       weak_ptr_factory_(this) {
   prefetch_dispatcher_->SetService(this);
   prefetch_downloader_->SetPrefetchService(this);
-  prefetch_gcm_handler_->SetService(this);
   if (suggested_articles_observer_)
     suggested_articles_observer_->SetPrefetchService(this);
 }
@@ -67,10 +67,18 @@
 }
 
 void PrefetchServiceImpl::SetCachedGCMToken(const std::string& gcm_token) {
-  gcm_token_ = gcm_token;
+  // This method is passed a cached token that was stored in the job scheduler,
+  // to be used until the PrefetchGCMHandler is created. In some cases, the
+  // PrefetchGCMHandler could have been already created and a fresher token
+  // requested before this function is called. Make sure to not override a
+  // fresher token with a stale one.
+  if (gcm_token_.empty())
+    gcm_token_ = gcm_token;
 }
 
 const std::string& PrefetchServiceImpl::GetCachedGCMToken() const {
+  DCHECK(!gcm_token_.empty()) << "No cached token is set, you should call "
+                                 "PrefetchService::GetGCMToken instead";
   return gcm_token_;
 }
 
@@ -85,7 +93,8 @@
     GCMTokenCallback callback,
     const std::string& gcm_token,
     instance_id::InstanceID::Result result) {
-  // Keep the token fresh
+  // TODO(dimich): Add UMA reporting on instance_id::InstanceID::Result.
+  // Keep the cached token fresh
   gcm_token_ = gcm_token;
   std::move(callback).Run(gcm_token);
 }
@@ -134,9 +143,27 @@
 }
 
 PrefetchGCMHandler* PrefetchServiceImpl::GetPrefetchGCMHandler() {
+  DCHECK(prefetch_gcm_handler_);
   return prefetch_gcm_handler_.get();
 }
 
+void PrefetchServiceImpl::SetPrefetchGCMHandler(
+    std::unique_ptr<PrefetchGCMHandler> handler) {
+  DCHECK(!prefetch_gcm_handler_);
+  prefetch_gcm_handler_ = std::move(handler);
+  prefetch_gcm_handler_->SetService(this);
+  if (IsPrefetchingOfflinePagesEnabled()) {
+    // Trigger an update of the cached GCM token. This needs to be post tasked
+    // because otherwise leads to circular dependency between
+    // PrefetchServiceFactory and GCMProfileServiceFactory. See
+    // https://crbug.com/944952
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(&PrefetchServiceImpl::GetGCMToken,
+                                  weak_ptr_factory_.GetWeakPtr(),
+                                  base::DoNothing::Once<const std::string&>()));
+  }
+}
+
 PrefetchNetworkRequestFactory*
 PrefetchServiceImpl::GetPrefetchNetworkRequestFactory() {
   return network_request_factory_.get();
@@ -181,6 +208,7 @@
 }
 
 void PrefetchServiceImpl::Shutdown() {
+  prefetch_gcm_handler_.reset();
   suggested_articles_observer_.reset();
   prefetch_downloader_.reset();
 }
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.h b/components/offline_pages/core/prefetch/prefetch_service_impl.h
index 28a5e144..5e0772e9 100644
--- a/components/offline_pages/core/prefetch/prefetch_service_impl.h
+++ b/components/offline_pages/core/prefetch/prefetch_service_impl.h
@@ -25,7 +25,6 @@
   PrefetchServiceImpl(
       std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector,
       std::unique_ptr<PrefetchDispatcher> dispatcher,
-      std::unique_ptr<PrefetchGCMHandler> gcm_handler,
       std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory,
       OfflinePageModel* offline_page_model,
       std::unique_ptr<PrefetchStore> prefetch_store,
@@ -62,6 +61,8 @@
   PrefetchImporter* GetPrefetchImporter() override;
   PrefetchBackgroundTaskHandler* GetPrefetchBackgroundTaskHandler() override;
 
+  void SetPrefetchGCMHandler(std::unique_ptr<PrefetchGCMHandler> handler);
+
   // Thumbnail fetchers. With Feed, GetThumbnailImageFetcher() is available
   // and GetThumbnailFetcher() is null.
   ThumbnailFetcher* GetThumbnailFetcher() override;
@@ -79,10 +80,10 @@
 
   OfflineEventLogger logger_;
   std::string gcm_token_;
+  std::unique_ptr<PrefetchGCMHandler> prefetch_gcm_handler_;
 
   std::unique_ptr<OfflineMetricsCollector> offline_metrics_collector_;
   std::unique_ptr<PrefetchDispatcher> prefetch_dispatcher_;
-  std::unique_ptr<PrefetchGCMHandler> prefetch_gcm_handler_;
   std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory_;
   OfflinePageModel* offline_page_model_;
   std::unique_ptr<PrefetchStore> prefetch_store_;
diff --git a/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc b/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc
index f19bafe6..f0eedd793 100644
--- a/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc
+++ b/components/offline_pages/core/prefetch/prefetch_service_test_taco.cc
@@ -194,14 +194,15 @@
 
 void PrefetchServiceTestTaco::CreatePrefetchService() {
   CHECK(!prefetch_service_);
-  prefetch_service_ = std::make_unique<PrefetchServiceImpl>(
+  auto service = std::make_unique<PrefetchServiceImpl>(
       std::move(metrics_collector_), std::move(dispatcher_),
-      std::move(gcm_handler_), std::move(network_request_factory_),
-      offline_page_model_.get(), std::move(prefetch_store_),
-      std::move(suggested_articles_observer_), std::move(prefetch_downloader_),
-      std::move(prefetch_importer_),
+      std::move(network_request_factory_), offline_page_model_.get(),
+      std::move(prefetch_store_), std::move(suggested_articles_observer_),
+      std::move(prefetch_downloader_), std::move(prefetch_importer_),
       std::move(prefetch_background_task_handler_),
       std::move(thumbnail_fetcher_), thumbnail_image_fetcher_.get());
+  service->SetPrefetchGCMHandler(std::move(gcm_handler_));
+  prefetch_service_ = std::move(service);
 }
 
 std::unique_ptr<PrefetchService>
diff --git a/components/offline_pages/core/prefetch/prefetch_types.cc b/components/offline_pages/core/prefetch/prefetch_types.cc
index 5820829f..e71c50ad 100644
--- a/components/offline_pages/core/prefetch/prefetch_types.cc
+++ b/components/offline_pages/core/prefetch/prefetch_types.cc
@@ -140,7 +140,13 @@
 PrefetchURL::PrefetchURL(const std::string& id,
                          const GURL& url,
                          const base::string16& title)
-    : id(id), url(url), title(title) {}
+    : id(id),
+      url(url),
+      title(title),
+      thumbnail_url(GURL()),
+      favicon_url(GURL()),
+      snippet(std::string()),
+      attribution(std::string()) {}
 
 PrefetchURL::PrefetchURL(const std::string& id,
                          const GURL& url,
diff --git a/components/offline_pages/core/prefetch/prefetch_types.h b/components/offline_pages/core/prefetch/prefetch_types.h
index 3c7988a..a4c425f2 100644
--- a/components/offline_pages/core/prefetch/prefetch_types.h
+++ b/components/offline_pages/core/prefetch/prefetch_types.h
@@ -286,9 +286,6 @@
   base::string16 title;
   base::FilePath file_path;
   int64_t file_size = 0;
-  GURL favicon_url;
-  std::string snippet;
-  std::string attribution;
 };
 
 // These operators are implemented for testing only, see test_util.cc.
diff --git a/components/offline_pages/core/prefetch/stub_prefetch_service.cc b/components/offline_pages/core/prefetch/stub_prefetch_service.cc
index f281bda..3463b59 100644
--- a/components/offline_pages/core/prefetch/stub_prefetch_service.cc
+++ b/components/offline_pages/core/prefetch/stub_prefetch_service.cc
@@ -19,6 +19,7 @@
 void StubPrefetchService::RemoveSuggestion(GURL url) {}
 
 void StubPrefetchService::SetCachedGCMToken(const std::string& gcm_token) {}
+
 void StubPrefetchService::GetGCMToken(GCMTokenCallback callback) {}
 
 const std::string& StubPrefetchService::GetCachedGCMToken() const {
diff --git a/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc b/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc
index c69810e8..28c4169 100644
--- a/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc
+++ b/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc
@@ -33,7 +33,7 @@
 PrefetchURL PrefetchURL1() {
   return {kClientId1,
           GURL("https://www.url1.com/"),
-          base::UTF8ToUTF16("Title 1"),
+          base::ASCIIToUTF16("Title 1"),
           GURL("https://www.url1.com/thumbnail.png"),
           GURL("https://www.url1.com/favicon.png"),
           "snippet 1",
@@ -42,7 +42,7 @@
 PrefetchURL PrefetchURL2() {
   return {kClientId2,
           GURL("https://www.url2.com/"),
-          base::UTF8ToUTF16("Title 2"),
+          base::ASCIIToUTF16("Title 2"),
           GURL("https://www.url2.com/thumbnail.png"),
           GURL("https://www.url2.com/favicon.png"),
           "snippet 2",
@@ -51,7 +51,7 @@
 PrefetchURL PrefetchURL3() {
   return {kClientId3,
           GURL("https://www.url3.com/"),
-          base::UTF8ToUTF16("Title 3"),
+          base::ASCIIToUTF16("Title 3"),
           GURL("https://www.url3.com/thumbnail.png"),
           GURL("https://www.url3.com/favicon.png"),
           "snippet 3",
diff --git a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.cc b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.cc
index 134e726..871c2ad 100644
--- a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.cc
+++ b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.cc
@@ -144,13 +144,11 @@
 GeneratePageBundleTask::GeneratePageBundleTask(
     PrefetchDispatcher* prefetch_dispatcher,
     PrefetchStore* prefetch_store,
-    PrefetchGCMHandler* gcm_handler,
     const std::string& gcm_token,
     PrefetchNetworkRequestFactory* request_factory,
     PrefetchRequestFinishedCallback callback)
     : prefetch_dispatcher_(prefetch_dispatcher),
       prefetch_store_(prefetch_store),
-      gcm_handler_(gcm_handler),
       gcm_token_(gcm_token),
       request_factory_(request_factory),
       callback_(std::move(callback)),
@@ -175,24 +173,7 @@
   DCHECK(!url_and_ids->urls.empty());
   DCHECK_EQ(url_and_ids->urls.size(), url_and_ids->ids.size());
 
-  if (gcm_handler_) {
-    gcm_handler_->GetGCMToken(base::AdaptCallbackForRepeating(
-        base::BindOnce(&GeneratePageBundleTask::GotRegistrationId,
-                       weak_factory_.GetWeakPtr(), std::move(url_and_ids))));
-  } else {
-    DCHECK(!gcm_token_.empty());
-    GotRegistrationId(std::move(url_and_ids), gcm_token_,
-                      instance_id::InstanceID::Result::SUCCESS);
-  }
-}
-
-void GeneratePageBundleTask::GotRegistrationId(
-    std::unique_ptr<UrlAndIds> url_and_ids,
-    const std::string& id,
-    instance_id::InstanceID::Result result) {
-  DCHECK(url_and_ids);
-  // TODO(dimich): Add UMA reporting on instance_id::InstanceID::Result.
-  request_factory_->MakeGeneratePageBundleRequest(url_and_ids->urls, id,
+  request_factory_->MakeGeneratePageBundleRequest(url_and_ids->urls, gcm_token_,
                                                   std::move(callback_));
   prefetch_dispatcher_->GeneratePageBundleRequested(
       std::make_unique<PrefetchDispatcher::IdsVector>(
diff --git a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h
index 224e487..1d2edff4 100644
--- a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h
+++ b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h
@@ -10,13 +10,11 @@
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
-#include "components/gcm_driver/instance_id/instance_id.h"
 #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h"
 #include "components/offline_pages/core/prefetch/prefetch_types.h"
 #include "components/offline_pages/task/task.h"
 
 namespace offline_pages {
-class PrefetchGCMHandler;
 class PrefetchNetworkRequestFactory;
 class PrefetchStore;
 
@@ -28,7 +26,6 @@
 
   GeneratePageBundleTask(PrefetchDispatcher* prefetch_dispatcher,
                          PrefetchStore* prefetch_store,
-                         PrefetchGCMHandler* gcm_handler,
                          const std::string& gcm_token,
                          PrefetchNetworkRequestFactory* request_factory,
                          PrefetchRequestFinishedCallback callback);
@@ -39,13 +36,9 @@
 
  private:
   void StartGeneratePageBundle(std::unique_ptr<UrlAndIds> url_and_ids);
-  void GotRegistrationId(std::unique_ptr<UrlAndIds> url_and_ids,
-                         const std::string& id,
-                         instance_id::InstanceID::Result result);
 
   PrefetchDispatcher* prefetch_dispatcher_;
   PrefetchStore* prefetch_store_;
-  PrefetchGCMHandler* gcm_handler_;
   std::string gcm_token_;
   PrefetchNetworkRequestFactory* request_factory_;
   PrefetchRequestFinishedCallback callback_;
diff --git a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task_unittest.cc b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task_unittest.cc
index 43546aa..5dc4496 100644
--- a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task_unittest.cc
+++ b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task_unittest.cc
@@ -16,7 +16,6 @@
 #include "components/offline_pages/core/prefetch/store/prefetch_store_utils.h"
 #include "components/offline_pages/core/prefetch/tasks/prefetch_task_test_base.h"
 #include "components/offline_pages/core/prefetch/test_prefetch_dispatcher.h"
-#include "components/offline_pages/core/prefetch/test_prefetch_gcm_handler.h"
 #include "components/offline_pages/core/test_scoped_offline_clock.h"
 #include "components/offline_pages/task/task.h"
 #include "services/network/test/test_utils.h"
@@ -37,13 +36,11 @@
   GeneratePageBundleTaskTest() = default;
   ~GeneratePageBundleTaskTest() override = default;
 
-  TestPrefetchGCMHandler* gcm_handler() { return &gcm_handler_; }
   std::string gcm_token() { return "dummy_gcm_token"; }
 
   TestPrefetchDispatcher* dispatcher() { return &dispatcher_; }
 
  private:
-  TestPrefetchGCMHandler gcm_handler_;
   TestPrefetchDispatcher dispatcher_;
 };
 
@@ -52,16 +49,16 @@
 
   base::MockCallback<PrefetchRequestFinishedCallback> callback;
   RunTask(std::make_unique<GeneratePageBundleTask>(
-      dispatcher(), store(), gcm_handler(), gcm_token(),
-      prefetch_request_factory(), callback.Get()));
+      dispatcher(), store(), gcm_token(), prefetch_request_factory(),
+      callback.Get()));
   EXPECT_EQ(0, dispatcher()->generate_page_bundle_requested);
 }
 
 TEST_F(GeneratePageBundleTaskTest, EmptyTask) {
   base::MockCallback<PrefetchRequestFinishedCallback> callback;
   RunTask(std::make_unique<GeneratePageBundleTask>(
-      dispatcher(), store(), gcm_handler(), gcm_token(),
-      prefetch_request_factory(), callback.Get()));
+      dispatcher(), store(), gcm_token(), prefetch_request_factory(),
+      callback.Get()));
 
   EXPECT_FALSE(prefetch_request_factory()->HasOutstandingRequests());
   auto requested_urls = prefetch_request_factory()->GetAllUrlsRequested();
@@ -104,7 +101,7 @@
 
   clock.Advance(base::TimeDelta::FromHours(1));
 
-  GeneratePageBundleTask task(dispatcher(), store(), gcm_handler(), gcm_token(),
+  GeneratePageBundleTask task(dispatcher(), store(), gcm_token(),
                               prefetch_request_factory(),
                               request_callback.Get());
   RunTask(&task);
diff --git a/components/offline_pages/core/prefetch/tasks/import_archives_task.cc b/components/offline_pages/core/prefetch/tasks/import_archives_task.cc
index f23498b2..84fa73c 100644
--- a/components/offline_pages/core/prefetch/tasks/import_archives_task.cc
+++ b/components/offline_pages/core/prefetch/tasks/import_archives_task.cc
@@ -24,11 +24,10 @@
 std::unique_ptr<std::vector<PrefetchArchiveInfo>> GetArchivesSync(
     sql::Database* db) {
   static const char kSql[] =
-      "SELECT offline_id,client_namespace,guid,requested_url,"
-      "final_archived_url,title,file_path,file_size,favicon_url,snippet,"
-      "attribution"
+      "SELECT offline_id, client_namespace, guid, requested_url,"
+      "  final_archived_url, title, file_path, file_size"
       " FROM prefetch_items"
-      " WHERE state=?";
+      " WHERE state = ?";
   sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
   statement.BindInt(0, static_cast<int>(PrefetchItemState::DOWNLOADED));
 
@@ -46,9 +45,6 @@
     archive.file_path =
         store_utils::FromDatabaseFilePath(statement.ColumnString(6));
     archive.file_size = statement.ColumnInt64(7);
-    archive.favicon_url = GURL(statement.ColumnString(8));
-    archive.snippet = statement.ColumnString(9);
-    archive.attribution = statement.ColumnString(10);
     if (!archives)
       archives = std::make_unique<std::vector<PrefetchArchiveInfo>>();
     archives->push_back(archive);
@@ -60,8 +56,8 @@
 bool UpdateToImportingStateSync(int64_t offline_id, sql::Database* db) {
   static const char kSql[] =
       "UPDATE prefetch_items"
-      " SET state=?"
-      " WHERE offline_id=?";
+      " SET state = ?"
+      " WHERE offline_id = ?";
 
   sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
   statement.BindInt(0, static_cast<int>(PrefetchItemState::IMPORTING));
diff --git a/components/offline_pages/core/prefetch/tasks/import_archives_task_unittest.cc b/components/offline_pages/core/prefetch/tasks/import_archives_task_unittest.cc
index d89b6f9..31e46fe 100644
--- a/components/offline_pages/core/prefetch/tasks/import_archives_task_unittest.cc
+++ b/components/offline_pages/core/prefetch/tasks/import_archives_task_unittest.cc
@@ -29,62 +29,20 @@
 const int64_t kTestOfflineID = 1111;
 const int64_t kTestOfflineID2 = 223344;
 const int64_t kTestOfflineID3 = 987;
-GURL TestURL() {
-  return GURL("http://sample.org");
-}
-GURL TestURL2() {
-  return GURL("http://sample.org");
-}
-GURL TestFinalURL() {
-  return GURL("https://sample.org/foo");
-}
-GURL TestFinalURL2() {
-  return GURL("https://sample.org/foo");
-}
-std::string TestGUID() {
-  return "C56A4180-65AA-42EC-A945-5FD21DEC0538";
-}
-ClientId TestClientID() {
-  return ClientId("Foo", TestGUID());
-}
-std::string TestGUID2() {
-  return "784f1b8b-6a32-4535-9751-ade05f947aa9";
-}
-ClientId TestClientID2() {
-  return ClientId("Foo2", TestGUID2());
-}
-base::string16 TestTitle() {
-  return base::UTF8ToUTF16("Hello");
-}
-base::string16 TestTitle2() {
-  return base::UTF8ToUTF16("Hello2");
-}
-base::FilePath TestFilePath() {
-  return base::FilePath(FILE_PATH_LITERAL("foo"));
-}
-base::FilePath TestFilePath2() {
-  return base::FilePath(FILE_PATH_LITERAL("foo2"));
-}
+const GURL kTestURL("http://sample.org");
+const GURL kTestURL2("http://sample.org");
+const GURL kTestFinalURL("https://sample.org/foo");
+const GURL kTestFinalURL2("https://sample.org/foo");
+const std::string kTestGUID("C56A4180-65AA-42EC-A945-5FD21DEC0538");
+const ClientId kTestClientID("Foo", kTestGUID);
+const std::string kTestGUID2("784f1b8b-6a32-4535-9751-ade05f947aa9");
+const ClientId kTestClientID2("Foo2", kTestGUID2);
+const base::string16 kTestTitle = base::ASCIIToUTF16("Hello");
+const base::string16 kTestTitle2 = base::ASCIIToUTF16("Hello2");
+const base::FilePath kTestFilePath(FILE_PATH_LITERAL("foo"));
+const base::FilePath kTestFilePath2(FILE_PATH_LITERAL("foo2"));
 const int64_t kTestFileSize = 88888;
 const int64_t kTestFileSize2 = 999;
-GURL TestFaviconURL() {
-  return GURL("http://sample.org/favicon.png");
-}
-GURL TestFaviconURL2() {
-  return GURL("http://sample.org/favicon2.png");
-}
-std::string TestSnippet() {
-  return "test snippet";
-}
-std::string TestSnippet2() {
-  return "test snippet 2";
-}
-std::string TestAttribution() {
-  return "test attribution";
-}
-std::string TestAttribution2() {
-  return "test attribution 2";
-}
 
 class TestPrefetchImporter : public PrefetchImporter {
  public:
@@ -124,35 +82,29 @@
   PrefetchItem item;
   item.offline_id = kTestOfflineID;
   item.state = PrefetchItemState::DOWNLOADED;
-  item.url = TestURL();
-  item.guid = TestGUID();
-  item.final_archived_url = TestFinalURL();
-  item.client_id = TestClientID();
-  item.title = TestTitle();
-  item.file_path = TestFilePath();
+  item.url = kTestURL;
+  item.guid = kTestGUID;
+  item.final_archived_url = kTestFinalURL;
+  item.client_id = kTestClientID;
+  item.title = kTestTitle;
+  item.file_path = kTestFilePath;
   item.file_size = kTestFileSize;
   item.creation_time = base::Time::Now();
   item.freshness_time = item.creation_time;
-  item.favicon_url = TestFaviconURL();
-  item.snippet = TestSnippet();
-  item.attribution = TestAttribution();
   EXPECT_TRUE(store_util()->InsertPrefetchItem(item));
 
   PrefetchItem item2;
   item2.offline_id = kTestOfflineID2;
   item2.state = PrefetchItemState::DOWNLOADED;
-  item2.url = TestURL2();
-  item2.guid = TestGUID2();
-  item2.final_archived_url = TestFinalURL2();
-  item2.client_id = TestClientID2();
-  item2.title = TestTitle2();
-  item2.file_path = TestFilePath2();
+  item2.url = kTestURL2;
+  item2.guid = kTestGUID2;
+  item2.final_archived_url = kTestFinalURL2;
+  item2.client_id = kTestClientID2;
+  item2.title = kTestTitle2;
+  item2.file_path = kTestFilePath2;
   item2.file_size = kTestFileSize2;
   item2.creation_time = base::Time::Now();
   item2.freshness_time = item.creation_time;
-  item2.favicon_url = TestFaviconURL2();
-  item2.snippet = TestSnippet2();
-  item2.attribution = TestAttribution2();
   EXPECT_TRUE(store_util()->InsertPrefetchItem(item2));
 
   PrefetchItem item3;
@@ -197,26 +149,20 @@
     archive2 = importer()->archives()[0];
   }
   EXPECT_EQ(kTestOfflineID, archive1.offline_id);
-  EXPECT_EQ(TestClientID(), archive1.client_id);
-  EXPECT_EQ(TestURL(), archive1.url);
-  EXPECT_EQ(TestFinalURL(), archive1.final_archived_url);
-  EXPECT_EQ(TestTitle(), archive1.title);
-  EXPECT_EQ(TestFilePath(), archive1.file_path);
+  EXPECT_EQ(kTestClientID, archive1.client_id);
+  EXPECT_EQ(kTestURL, archive1.url);
+  EXPECT_EQ(kTestFinalURL, archive1.final_archived_url);
+  EXPECT_EQ(kTestTitle, archive1.title);
+  EXPECT_EQ(kTestFilePath, archive1.file_path);
   EXPECT_EQ(kTestFileSize, archive1.file_size);
-  EXPECT_EQ(TestFaviconURL(), archive1.favicon_url);
-  EXPECT_EQ(TestSnippet(), archive1.snippet);
-  EXPECT_EQ(TestAttribution(), archive1.attribution);
 
   EXPECT_EQ(kTestOfflineID2, archive2.offline_id);
-  EXPECT_EQ(TestClientID2(), archive2.client_id);
-  EXPECT_EQ(TestURL2(), archive2.url);
-  EXPECT_EQ(TestFinalURL2(), archive2.final_archived_url);
-  EXPECT_EQ(TestTitle2(), archive2.title);
-  EXPECT_EQ(TestFilePath2(), archive2.file_path);
+  EXPECT_EQ(kTestClientID2, archive2.client_id);
+  EXPECT_EQ(kTestURL2, archive2.url);
+  EXPECT_EQ(kTestFinalURL2, archive2.final_archived_url);
+  EXPECT_EQ(kTestTitle2, archive2.title);
+  EXPECT_EQ(kTestFilePath2, archive2.file_path);
   EXPECT_EQ(kTestFileSize2, archive2.file_size);
-  EXPECT_EQ(TestFaviconURL2(), archive2.favicon_url);
-  EXPECT_EQ(TestSnippet2(), archive2.snippet);
-  EXPECT_EQ(TestAttribution2(), archive2.attribution);
 }
 
 }  // namespace offline_pages
diff --git a/components/omnibox/browser/omnibox_metrics_provider.cc b/components/omnibox/browser/omnibox_metrics_provider.cc
index b43cccc..279e4d4 100644
--- a/components/omnibox/browser/omnibox_metrics_provider.cc
+++ b/components/omnibox/browser/omnibox_metrics_provider.cc
@@ -91,9 +91,7 @@
 
 }  // namespace
 
-OmniboxMetricsProvider::OmniboxMetricsProvider(
-    const base::Callback<bool(void)>& is_off_the_record_callback)
-    : is_off_the_record_callback_(is_off_the_record_callback) {}
+OmniboxMetricsProvider::OmniboxMetricsProvider() {}
 
 OmniboxMetricsProvider::~OmniboxMetricsProvider() {
 }
@@ -115,10 +113,7 @@
 }
 
 void OmniboxMetricsProvider::OnURLOpenedFromOmnibox(OmniboxLog* log) {
-  // Do not log events to UMA if the embedder reports that the user is in an
-  // off-the-record context.
-  if (!is_off_the_record_callback_.Run())
-    RecordOmniboxOpenedURL(*log);
+  RecordOmniboxOpenedURL(*log);
 }
 
 void OmniboxMetricsProvider::RecordOmniboxOpenedURL(const OmniboxLog& log) {
diff --git a/components/omnibox/browser/omnibox_metrics_provider.h b/components/omnibox/browser/omnibox_metrics_provider.h
index f069171..505dfc8 100644
--- a/components/omnibox/browser/omnibox_metrics_provider.h
+++ b/components/omnibox/browser/omnibox_metrics_provider.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/callback_list.h"
 #include "base/macros.h"
 #include "components/metrics/metrics_provider.h"
 #include "components/omnibox/browser/omnibox_event_global_tracker.h"
@@ -18,8 +19,7 @@
 // section of the UMA proto.
 class OmniboxMetricsProvider : public metrics::MetricsProvider {
  public:
-  explicit OmniboxMetricsProvider(
-      const base::Callback<bool(void)>& is_off_the_record_callback);
+  OmniboxMetricsProvider();
   ~OmniboxMetricsProvider() override;
 
   // metrics::MetricsDataProvider:
@@ -44,10 +44,6 @@
   // proto when ProvideCurrentSessionData() is called.
   metrics::ChromeUserMetricsExtension omnibox_events_cache;
 
-  // Callback passed in from the embedder that returns whether the user is
-  // currently operating off-the-record.
-  const base::Callback<bool(void)> is_off_the_record_callback_;
-
   DISALLOW_COPY_AND_ASSIGN(OmniboxMetricsProvider);
 };
 
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 4183893..89b7f92 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -14129,7 +14129,7 @@
       'tags': [],
       'desc': '''Specifies a list of websites that are installed silently, without user interaction, and which cannot be uninstalled nor disabled by the user.
 
-      Each list item of the policy is an object with a mandatory member: "url" and two optional members: "default_launch_container" and "create_desktop_shortcut". "url" should be the URL of the web app to install, "launch_container" should be either "window" or "tab" to indicate how the Web App will be opened once installed, and "create_desktop_shortcut" should be true if a desktop shortcut should be created on Linux and Windows. If "default_launch_container" is omitted, the app will open in a tab by default. Regardless of the value of "default_launch_container", users are able to change which container the app will open in. If "create_desktop_shortcuts" is ommitted, no desktop shortcuts will be created.''',
+      Each list item of the policy is an object with a mandatory member: "url" and two optional members: "default_launch_container" and "create_desktop_shortcut". "url" should be the URL of the web app to install, "launch_container" should be either "window" or "tab" to indicate how the Web App will be opened once installed, and "create_desktop_shortcut" should be true if a desktop shortcut should be created on Linux and Windows. If "default_launch_container" is omitted, the app will open in a tab by default. Regardless of the value of "default_launch_container", users are able to change which container the app will open in. If "create_desktop_shortcuts" is omitted, no desktop shortcuts will be created.''',
       'label': '''URLs for Web Apps to be silently installed.''',
     },
     {
diff --git a/components/policy/resources/policy_templates_en-GB.xtb b/components/policy/resources/policy_templates_en-GB.xtb
index e6dd3d491..b0fb534 100644
--- a/components/policy/resources/policy_templates_en-GB.xtb
+++ b/components/policy/resources/policy_templates_en-GB.xtb
@@ -1765,11 +1765,11 @@
           If false or unset, then the content provider returns no information.</translation>
 <translation id="435461861920493948">Contains a list of patterns which are used to control the visiblity of accounts in <ph name="PRODUCT_NAME" />.
 
-      EachGoogle Accounton the device will be compared to patterns stored in this policy to determine the account visibility in <ph name="PRODUCT_NAME" />. The account will be visible if its name matches any pattern on the list. Otherwise, the account will be hidden.
+      Each Google Account on the device will be compared to patterns stored in this policy to determine the account visibility in <ph name="PRODUCT_NAME" />. The account will be visible if its name matches any pattern on the list. Otherwise, the account will be hidden.
 
       Use the wildcard character '*' to match zero or more arbitrary characters. The escape character is '\', so to match actual '*' or '\' characters, put a '\' in front of them.
 
-      If this policy is not set, allGoogle Accounts on the device will be visible in <ph name="PRODUCT_NAME" />.</translation>
+      If this policy is not set, all Google Accounts on the device will be visible in <ph name="PRODUCT_NAME" />.</translation>
 <translation id="4360826270668210664">If this policy is set, the remote access host will require authenticating clients to obtain an authentication token from this URL in order to connect. Must be used in conjunction with RemoteAccessHostTokenValidationUrl.
 
           This feature is currently disabled server-side.</translation>
@@ -3210,11 +3210,11 @@
           Automatic playback is only allowed for domains explicitly listed in the <ph name="PLUGINS_ALLOWED_FOR_URLS_POLICY_NAME" /> policy. If you want to enabled automatic playback for all sites, consider adding http://* and https://* to this list.
 
           If this policy is left not set, the user will be able to change this setting manually.</translation>
-<translation id="7229975860249300121">Contains a regular expression which is used to determine whichGoogle Accounts can be set as browser primary accounts in <ph name="PRODUCT_NAME" /> (i.e. the account that is chosen during the Sync opt-in flow).
+<translation id="7229975860249300121">Contains a regular expression which is used to determine which Google Accounts can be set as browser primary accounts in <ph name="PRODUCT_NAME" /> (i.e. the account that is chosen during the Sync opt-in flow).
 
       An appropriate error is displayed if a user tries to set a browser primary account with a username that does not match this pattern.
 
-      If this policy is left not set or blank, then the user can set anyGoogle Accountas a browser primary account in <ph name="PRODUCT_NAME" />.</translation>
+      If this policy is left not set or blank, then the user can set any Google Account as a browser primary account in <ph name="PRODUCT_NAME" />.</translation>
 <translation id="723103540848640830">Set the minimum length of the lock screen PIN</translation>
 <translation id="7232816984286843471">If the policy is set to false, unaffiliated users will not be allowed to use Crostini.
 
diff --git a/components/policy/resources/policy_templates_fil.xtb b/components/policy/resources/policy_templates_fil.xtb
index 04ebea7..9d01767 100644
--- a/components/policy/resources/policy_templates_fil.xtb
+++ b/components/policy/resources/policy_templates_fil.xtb
@@ -1,6 +1,9 @@
 <?xml version="1.0" ?>
 <!DOCTYPE translationbundle>
 <translationbundle lang="fil">
+<translation id="1002439864875515590">Kung nakatakda ang patakarang ito sa isang blangkong string o hindi naka-configure, hindi magpapakita ng opsyon sa pag-autocomplete ang <ph name="PRODUCT_OS_NAME" /> sa flow ng pag-sign in ng user.
+      Kung nakatakda ang patakarang ito sa isang string na kumakatawan sa isang domain name, magpapakita ang <ph name="PRODUCT_OS_NAME" /> ng opsyon sa pag-autocomplete sa pag-sign in ng user na nagbibigay-daan sa user na i-type lang ang kanyang user name nang walang extension ng domain name.  Mao-overwrite ng user ang extension ng domain name na ito.
+      Kung ang value ng patakaran ay hindi isang wastong domain, hindi ilalapat ang patakaran.</translation>
 <translation id="101438888985615157">I-rotate ang screen nang 180 degrees</translation>
 <translation id="1016912092715201525">Kino-configure ang mga default na pagsusuri ng browser sa <ph name="PRODUCT_NAME" /> at pinipigilan ang mga user na baguhin ang mga ito.
 
@@ -941,6 +944,16 @@
       Kung hindi pinagana ang setting na ito, hindi makakagamit ng JavaScript ang mga web page at hindi mababago ng user ang setting na iyon.
 
       Kung pinagana o hindi nakatakda ang setting na ito, makakagamit ng JavaScript ang mga web page ngunit mababago ng user ang setting na iyon.</translation>
+<translation id="2747157663401642394">Kino-configure ang mga setting ng pamamahala ng extension para sa <ph name="PRODUCT_NAME" />.
+
+          Kinokontrol ng patakarang ito ang maraming setting, kabilang ang mga setting na kinokontrol ng anumang kasalukuyang patakarang nauugnay sa extension. Io-override ng patakarang ito ang anumang patakaran ng legacy kung naitakda ang pareho.
+
+          Nagmamapa ang patakarang ito ng extension ID o ng isang URL ng update sa configuration nito. Gamit ang isang extension ID, ilalapat ang configuration sa tinukoy na extension lang. Maaaring itakda ang isang default na configuration para sa espesyal na ID <ph name="DEFAULT_SCOPE" /> na ilalapat sa lahat ng extension na walang nakatakdang custom na configuration sa patakarang ito. Gamit ang isang URL ng update, ilalapat ang configuration sa lahat ng extension na may eksaktong URL ng update na nakasaad sa manifest ng extension na ito, gaya ng nakasaad sa <ph name="LINK_TO_EXTENSION_DOC1" />.
+
+          Para sa mga instance ng Windows na hindi kasama sa isang domain ng <ph name="MS_AD_NAME" />, nililimitahan ang pwersahang pag-install sa mga app at extension na nakalista sa Chrome Web Store.
+
+          Para sa kumpletong paglalarawan ng mga posibleng setting at istruktura ng patakarang ito, mangyaring bumisita sa https://www.chromium.org/administrators/policy-list-3/extension-settings-full
+          </translation>
 <translation id="2753637905605932878">Paghigpitan ang hanay ng mga lokal na UDP port na ginagamit ng WebRTC</translation>
 <translation id="2755385841634849932">Kinokontrol ng patakarang ito ang availability ng pag-back up at pag-restore sa Android.
 
@@ -2079,6 +2092,7 @@
       Kapag nakatakda ang patakarang ito, itinuturing napanuntunan ang bawat item, kagaya ng patakarang <ph name="URL_LIST_POLICY_NAME" />. Gayunpaman, baliktad ang pagturing dito: hindi magbubukas ng alternatibong browser ang mga tutugmang panuntunan.
 
       Hindi gaya ng <ph name="URL_LIST_POLICY_NAME" />, nalalapat sa magkabilang direksyon ang mga panuntunan. Ibig sabihin, kapag mayroon ng Internet Explorer add-in at naka-enable ito, kinokontrol din nito kung dapat buksan ng <ph name="IE_PRODUCT_NAME" /> ang mga URL na ito sa <ph name="PRODUCT_NAME" />.</translation>
+<translation id="5124368997194894978">I-enable ang boot on AC (alternating current)</translation>
 <translation id="5130288486815037971">Kung naka-enable ang mga RC4 na cipher suite sa TLS o hindi</translation>
 <translation id="5141670636904227950">Itakda ang default na uri ng magnifier ng screen na naka-enable sa screen sa pag-login</translation>
 <translation id="5142301680741828703">Palaging i-render ang mga sumusunod na pattern ng URL sa <ph name="PRODUCT_FRAME_NAME" /></translation>
@@ -2879,6 +2893,17 @@
           Kung hinayaang hindi nakatakda ang patakarang ito, gagamitin ang '3,' at magagawa ng user na baguhin ito.</translation>
 <translation id="663685822663765995">Paghigpitan ang printing color mode</translation>
 <translation id="6641981670621198190">Huwag paganahin ang suporta para sa mga API ng mga 3D na graphic</translation>
+<translation id="6646056064606561298">I-enable ang patakaran sa pamamahala ng baterya na boot on AC.
+
+          Nagbibigay ang Boot on AC ng pagkakataon para sa system na awtomatikong mag-boot up mula sa NAKA-OFF/Naka-hibernate kapag ipinasok ang line power.
+
+          Kung nakatakda sa true ang patakarang ito, palaging naka-enable ang boot on AC kung sinusuportahan sa device.
+
+          Kung nakatakda sa false ang patakarang ito, palaging naka-disable ang boot on AC.
+
+          Kung itatakda mo ang patakarang ito, hindi ito mababago o mao-override ng mga user.
+
+          Kung hindi nakatakda ang patakarang ito, naka-disable ang boot on AC at hindi mae-enable ng user.</translation>
 <translation id="6647965994887675196">Kung nakatakda sa true, maaaring gumawa at gumamit ng mga pinapangasiwaang user.
 
           Kung nakatakda sa false o hindi naka-configure, idi-disable ang paggawa at pag-log in ng pinapangasiwaang user. Itatago ang lahat ng umiiral na pinapangasiwaang user.
diff --git a/components/policy/resources/policy_templates_iw.xtb b/components/policy/resources/policy_templates_iw.xtb
index 966619ba3..b6e02b2 100644
--- a/components/policy/resources/policy_templates_iw.xtb
+++ b/components/policy/resources/policy_templates_iw.xtb
@@ -193,7 +193,7 @@
 <translation id="1354424209129232709">מקסימום:</translation>
 <translation id="1354452738176731363">‏כאשר המדיניות הזו מקבלת את הערך False, פלט האודיו לא יהיה זמין במכשיר בזמן שהמשתמש מחובר.
 
-      המדיניות הזו משפיעה על כל הסוגים של פלט אודיו, לא רק על רמקולים מובנים. המדיניות הזו מגבילה גם תכונות נגישות של אודיו. אין להפעיל את המדיניות הזו אם המשתמש זקוק לקורא מסך.
+      המדיניות הזו משפיעה על פלט אודיו מכל הסוגים, ולא רק מהרמקולים המובנים. המדיניות הזו מגבילה גם תכונות נגישות של אודיו. אין להפעיל את המדיניות הזו אם המשתמש זקוק לקורא מסך.
 
       אם ההגדרה הזו מקבלת את הערך True או לא נקבעת, המשתמשים יכולים להשתמש בכל הסוגים הנתמכים של פלט אודיו במכשיר שלהם.</translation>
 <translation id="1359553908012294236">‏אם מדיניות זו מוגדרת כ-true או אינה מוגדרת, <ph name="PRODUCT_NAME" /> יאפשר התחברויות של אורחים. התחברויות של אורחים הן פרופילים של <ph name="PRODUCT_NAME" /> שבהם כל החלונות הם במצב גלישה בסתר.
@@ -259,17 +259,17 @@
 <translation id="1438739959477268107">הגדרת ברירת מחדל ליצירת מפתחות</translation>
 <translation id="1454846751303307294">‏מאפשר לך להגדיר רשימה של דפוסי כתובת אתר שמציינים אתרים שאינם מורשים להפעיל JavaScript. אם מדיניות זו אינה מוגדרת, המערכת תשתמש בערך ברירת המחדל הכללי עבור כל האתרים בין אם הם שייכים למדיניות 'DefaultJavaScriptSetting', אם היא מוגדרת, ובין אם הם שייכים לתצורה האישית של המשתמש.</translation>
 <translation id="1456822151187621582">‏Windows (לקוחות <ph name="PRODUCT_OS_NAME" />):</translation>
-<translation id="1458547592473993238">‏המדיניות הזו הוצאה משימוש. יש להשתמש במדיניות <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME" /> כדי לשלוט בזמינות של הפלאגין Flash ובמדיניות <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME" /> כדי לקבוע אם הכלי המשולב להצגת PDF משמש לפתיחת קובצי PDF.
+<translation id="1458547592473993238">‏המדיניות הזו הוצאה משימוש. יש להשתמש במדיניות <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME" /> כדי לשלוט בזמינות של הפלאגין Flash ובמדיניות <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME" /> כדי לקבוע אם הכלי המשולב להצגת PDF ישמש לפתיחת קובצי PDF.
 
       המדיניות מציינת רשימת יישומי פלאגין שמושבתים במסגרת <ph name="PRODUCT_NAME" /> ומונעת ממשתמשים לשנות את ההגדרה הזו.
 
-      ניתן להשתמש בתווים הכללים לחיפוש '*' ו-'?' כדי להתאים לרצפים של תווים שרירותיים. התו '*' תואם למספר שרירותי של תווים והתו '?' מציין תו אופציונלי יחיד, כלומר תואם לאפס תווים או לתו אחד. תו הבריחה הוא '\', כך שכדי להתאים בפועל לתווים '*', '?', או '\', ניתן להוסיף לפניהם '\'.
+      ניתן להשתמש בתווים הכלליים לחיפוש '*' ו-'?' כדי להתאים לרצפים של תווים שרירותיים. התו '*' תואם למספר שרירותי של תווים והתו '?' מציין תו אופציונלי יחיד, כלומר תואם לאפס תווים או לתו אחד. תו הבריחה הוא '\', כך שכדי להתאים בפועל לתווים '*', '?', או '\', ניתן להוסיף לפניהם '\'.
 
       אם ההגדרה הזו מופעלת, אף פעם לא נעשה שימוש ברשימת יישומי הפלאגין שצוינה במסגרת <ph name="PRODUCT_NAME" />. יישומי הפלאגין מסומנים כמושבתים ב-about:plugins והמשתמשים לא יכולים להפעיל אותם.
 
       חשוב לשים לב שכללי המדיניות EnabledPlugins ו-DisabledPluginsExceptions יכולים לבטל את המדיניות הזו.
 
-      אם המדיניות הזו לא מוגדרת, המשתמשים יכולים להשתמש בכל פלאגין שמותקן במערכת פרט ליישומי פלאגין בתוך הקוד שהם מיושנים, מסוכנים או לא תואמים.</translation>
+      ,אם המדיניות הזו לא מוגדרת, המשתמשים יכולים להשתמש בכל פלאגין שמותקן במערכת, פרט ליישומי פלאגין בתוך הקוד שהם מיושנים, מסוכנים או לא תואמים.</translation>
 <translation id="1464848559468748897">‏שולטת בהתנהגות המשתמשים בהפעלה מרובת-פרופילים במכשירי <ph name="PRODUCT_OS_NAME" />.
 
       אם המדיניות הזו מוגדרת כ-'MultiProfileUserBehaviorUnrestricted', המשתמש יכול להיות משתמש ראשי או משני בהפעלה מרובת-פרופילים.
@@ -343,7 +343,7 @@
 <translation id="1615221548356595305">‏התרת איחוד של חיבורי HTTP/2 במארחים האלה, גם כשנעשה שימוש באישורי לקוח</translation>
 <translation id="1615855314789673708">‏המדיניות הזו מספקת תצורת DTC (בקר אבחון וטלמטריה) של Wilco.
 
-      המדיניות הזו מאפשרת לספק תצורת DTC של Wilco שניתן להחיל אם DTC של Wilco זמין במכשיר הנקוב והשימוש בו מותר לפי מדיניות. גודל התצורה לא יכול לחרוג מ-1MB ‏(1,000,000 בתים) ועליה להיות מקודדת ב-JSON. ה-DTC של Wilco אחראי על הטיפול בה. הגיבוב הקריפטוגרפי משמש כדי לאמת את התקינות של ההורדה.
+      המדיניות הזו מאפשרת לספק תצורת DTC של Wilco שניתן להחיל אם DTC של Wilco זמין במכשיר הנקוב והשימוש בו מותר לפי מדיניות. הגודל המרבי המותר של התצורה הוא 1MB ‏(1,000,000 בתים), ועליה להיות מקודדת ב-JSON. ה-DTC של Wilco אחראי על הטיפול בה. הגיבוב הקריפטוגרפי משמש כדי לאמת את התקינות של ההורדה.
 
       המערכת מורידה את התצורה ושומרת אותה במטמון. אחרי כל שינוי של כתובת ה-URL או הגיבוב, תתבצע הורדה מחדש של התצורה.
 
@@ -494,7 +494,7 @@
       המדיניות הזו זמינה רק במופעים של Windows שמצורפים לדומיין <ph name="MS_AD_NAME" />, או במופעים של Windows 10 Pro או Enterprise שרשומים לניהול מכשירים.</translation>
 <translation id="1914840757300882918">‏אם המדיניות הזו מוגדרת, המארח ישתמש באישור לקוח עם ה-CN הנתון של המנפיק לצורך אימות עבור RemoteAccessHostTokenValidationUrl. אם המדיניות תקבל את הערך "*", ניתן יהיה להשתמש בכל אישור לקוח זמין.
 
-          בשלב זה התכונה הזו מושבתת בצד השרת.</translation>
+          בשלב זה, התכונה הזו מושבתת בצד השרת.</translation>
 <translation id="1919802376548418720">‏שימוש במדיניות KDC כדי להעניק גישה לפרטי כניסה.</translation>
 <translation id="1920046221095339924">התרת סשן מנוהל במכשיר</translation>
 <translation id="1929709556673267855">‏מספקת תצורה למדפסות ארגוניות המשויכות למכשירים.
@@ -618,14 +618,14 @@
 
       המדיניות הזו בתוקף רק אם מוגדר שרת proxy (למשל על ידי מדיניות, על ידי המשתמש ב-chrome://settings או על ידי תוספים).
 
-      אם ההגדרה הזו מופעלת, כל דפי האימות של פורטל שבוי (כלומר כל דפי האינטרט החל מדף הכניסה של הפורטל השבוי עד שמזוהה חיבור מוצלח לאינטרנט על ידי <ph name="PRODUCT_NAME" />) יוצגו בחלון נפרד, תוך התעלמות מכל ההגבלות והגדרות המדיניות של המשתמש הנוכחי.
+      אם ההגדרה הזו מופעלת, כל דפי האימות של פורטל שבוי (כלומר כל דפי האינטרנט החל מדף הכניסה של הפורטל השבוי עד שמזוהה חיבור מוצלח לאינטרנט על ידי <ph name="PRODUCT_NAME" />) יוצגו בחלון נפרד, תוך התעלמות מכל ההגבלות והגדרות המדיניות של המשתמש הנוכחי.
 
       אם ההגדרה הזו מושבתת או לא נקבעת, כל דפי האימות של פורטל שבוי יוצגו בכרטיסיית דפדפן חדשה (ורגילה), תוך שימוש בהגדרות שרת ה-proxy של המשתמש הנוכחי.</translation>
 <translation id="21394354835637379">‏המדיניות הזו מאפשרת לך לציין לאילו כתובות URL יש הרשאה להתקין תוספים, אפליקציות ועיצובים.
 
           החל מגרסה 21 של <ph name="PRODUCT_NAME" />, קשה יותר להתקין תוספים, אפליקציות וסקריפטים של משתמשים שאינם מחנות האינטרנט של Chrome. קודם לכן משתמשים יכלו ללחוץ על קישור לקובץ ‎*.crx ולקבל הצעה ממערכת <ph name="PRODUCT_NAME" /> להתקין את הקובץ לאחר כמה אזהרות. אחרי ‎<ph name="PRODUCT_NAME" /> 21 יש להוריד קבצים כאלה ולגרור אותם לדף ההגדרות של <ph name="PRODUCT_NAME" />. ההגדרה הזו מאפשרת לשייך לכתובות URL ספציפיות את תהליך ההתקנה הקודם והקל יותר.
 
-          כל פריט ברשימה הוא דפוס התאמה בסגנון תוסף (מידע נוסף זמין בכתובת https://developer.chrome.com/extensions/match_patterns). משתמשים יוכלו להתקין בקלות פריטים מכל כתובת URL שתואמת לפריט ברשימה הזו. הדפוסים האלה צריכים לקחת בחשבון את המיקום של קובץ ה-‎*.crx וגם את מיקום הדף שההורדה מתחילה ממנו (כלומר הגורם המפנה).
+          כל פריט ברשימה הוא דפוס התאמה בסגנון תוסף (מידע נוסף זמין בכתובת https://developer.chrome.com/extensions/match_patterns). משתמשים יוכלו להתקין בקלות פריטים מכל כתובת URL שתואמת לפריט ברשימה הזו. הדפוסים האלה צריכים לקחת בחשבון את המיקום של קובץ ה-‎*.crx וגם את מיקום הדף שההורדה מתחילה ממנו (כלומר: הגורם המפנה).
 
           המדיניות <ph name="EXTENSION_INSTALL_BLACKLIST_POLICY_NAME" /> מקבלת עדיפות על פני המדיניות הזו. המשמעות היא שאם תוסף נמצא ברשימה השחורה, הוא לא יותקן גם אם ההתקנה מתבצעת מאתר שנמצא ברשימה הזו.</translation>
 <translation id="214901426630414675">הגבלת הדפסה משני צידי הדף</translation>
@@ -674,7 +674,7 @@
       כאשר המדיניות הזו מושבתת, המערכת אף פעם לא מבקשת אישור מהמשתמש וצילום
       וידאו זמין רק לכתובות URL שהוגדרו ברשימה VideoCaptureAllowedUrls.
 
-      המדיניות הזו משפיעה על כל הסוגים של קלט הווידאו, לא רק על המצלמה המובנית.</translation>
+      המדיניות הזו משפיעה על קלט וידאו מכל הסוגים, ולא רק מהמצלמה המובנית.</translation>
 <translation id="2201555246697292490">הגדרה של רשימת היתרים עבור העברת הודעות מקומית</translation>
 <translation id="2204753382813641270">בקרת הסתרה אוטומטית של מדף</translation>
 <translation id="2208976000652006649">‏פרמטרים עבור כתובת אתר לחיפוש שמשתמשת ב-POST</translation>
@@ -687,7 +687,7 @@
 <translation id="2240879329269430151">‏מאפשר לך לקבוע אם מותר לאתרים להציג חלונות קופצים. ניתן להציג חלונות קופצים עבור כל האתרים או לבטל את הצגתם עבור כל האתרים. אם לא הגדרת מדיניות זו, המערכת תשתמש ב-'BlockPopups' והמשתמש יוכל לשנות זאת.</translation>
 <translation id="2255326053989409609">‏הפעלת ההגדרה הזו מונעת מדפי אינטרנט לגשת למעבד הגרפי (GPU). דפי אינטרנט לא יכולים לגשת ל-WebGL API ויישומי פלאגין לא יכולים להשתמש ב-Pepper 3D API.
 
-      אם ההגדרה הזו מושבתת או לא מוגדרת, הדבר עשוי לאפשר לדפי אינטרנט להשתמש ב-WebGL API וליישומי הפלאגין להשתמש ב-Pepper 3D API. ייתכן שהגדרות ברירת המחדל של הדפדפן עדיין ידרשו ארגומנטים של שורת פקודה שיש להעביר כדי להשתמש בממשקי API אלה.
+      אם ההגדרה הזו מושבתת, או אם לא קובעים אותה, הדבר עשוי לאפשר לדפי אינטרנט להשתמש ב-WebGL API וליישומי פלאגין להשתמש ב-Pepper 3D API. ייתכן שהגדרות ברירת המחדל של הדפדפן עדיין ידרשו ארגומנטים של שורת פקודה שיש להעביר כדי להשתמש בממשקי API אלה.
 
       אם המדיניות HardwareAccelerationModeEnabled מקבלת את הערך False, המערכת מתעלמת מהמדיניות Disable3DAPIs והדבר שווה ערך להגדרת Disable3DAPIs כ-True.</translation>
 <translation id="2258126710006312594">מדיניות זו קובעת אם לאפשר למשתמשים בגישה מרחוק להעביר קבצים אל המארח וממנו</translation>
@@ -844,7 +844,7 @@
 <translation id="257788512393330403">יש להזין סיסמה כל שש שעות</translation>
 <translation id="2587719089023392205">הגדר את <ph name="PRODUCT_NAME" /> כדפדפן ברירת המחדל</translation>
 <translation id="2592091433672667839">משך הזמן של חוסר פעילות לפני הופעת שומר המסך במסך הכניסה במצב קמעונאי</translation>
-<translation id="2592162121850992309">‏אם המדיניות הזו לא מוגדרת או מקבלת את הערך True, שיפור המהירות באמצעות החומרה מופעל אלא אם תכונה מסוימת של ה-GPU נוספת לרשימה השחורה.
+<translation id="2592162121850992309">‏אם המדיניות הזו לא מוגדרת, או אם היא מקבלת את הערך True, שיפור המהירות באמצעות החומרה מופעל אלא אם תכונה מסוימת של ה-GPU נוספת לרשימה השחורה.
 
       אם המדיניות הזו מקבלת את הערך False, שיפור המהירות באמצעות החומרה מושבת.</translation>
 <translation id="2596260130957832043">‏קובעת אם אימות NTLMv2 מופעל.
@@ -977,7 +977,7 @@
           אם המדיניות לא מוגדרת או מקבלת את הערך False, מדיניות ה-KDC לא נלקחת בחשבון בפלטפורמות נתמכות ורק המדיניות AuthNegotiateDelegateWhitelist נלקחת בחשבון.
 
           ב-Windows, מדיניות ה-KDC תמיד נלקחת בחשבון.</translation>
-<translation id="283695852388224413">אם המדיניות הזו מוגדרת, המערכת אוכפת את הגדרת האורך המקסימלי של קודי אימות. ערך של 0 ומטה משמעותו ללא אורך מקסימלי. במקרה כזה המשתמשים רשאים להגדיר קוד אימות בכל אורך. אם הערך של ההגדרה הזו גדול מאפס אבל קטן מ-<ph name="PIN_UNLOCK_MINIMUM_LENGTH_POLICY_NAME" />, האורך המקסימלי זהה לאורך המינימלי.
+<translation id="283695852388224413">אם המדיניות הזו מוגדרת, המערכת אוכפת את הגדרת האורך המקסימלי של קודי אימות. המשמעות של ערך של 0 ומטה היא שאין אורך מקסימלי. במקרה כזה, המשתמשים רשאים להגדיר קוד אימות בכל אורך. אם הערך של ההגדרה הזו גדול מאפס אבל קטן מ-<ph name="PIN_UNLOCK_MINIMUM_LENGTH_POLICY_NAME" />, האורך המקסימלי זהה לאורך המינימלי.
 
           אם ההגדרה לא נקבעת, המערכת לא אוכפת אורך מקסימלי כלשהו.</translation>
 <translation id="2838830882081735096">‏אל תאפשר העברת נתונים ו-ARC</translation>
@@ -1054,7 +1054,7 @@
 
       אם המדיניות הזו מופעלת, בדיקת האיות מופעלת לכל השפות שצוינו, בנוסף לשפות שהמשתמשים הפעילו עבורן את בדיקת האיות.
 
-      אם המדיניות הזו לא מוגדרת או מושבתת, העדפות בדיקת האיות של המשתמשים לא משתנות.
+      אם המדיניות הזו לא מוגדרת, או אם היא מושבתת, העדפות בדיקת האיות של המשתמשים לא משתנות.
 
       אם המדיניות SpellcheckEnabled מושבתת, למדיניות הזו אין השפעה.
 
@@ -1162,13 +1162,13 @@
 <translation id="3165808775394012744">כללי המדיניות האלה מפורטים כאן כדי שניתן יהיה להסיר אותם בקלות.</translation>
 <translation id="316778957754360075">‏מדיניות זו הופסקה החל מגרסה 29 של <ph name="PRODUCT_NAME" />. הדרך המומלצת להגדרת אוספים של תוספים/אפליקציות המתארחים בארגון היא לכלול את האתר המארח את חבילות ה-CRX ב-ExtensionInstallSources ולהציב קישורים להורדה ישירה של החבילות בדף אינטרנט. ניתן ליצור מרכז אפליקציות לדף אינטרנט זה באמצעות המדיניות ExtensionInstallForcelist.</translation>
 <translation id="3171369832001535378">תבנית שם המארח של רשת המכשיר</translation>
-<translation id="3172512016079904926">המדיניות הזו מאפשרת את ההתקנה של מארחי העברת הודעות מקומית ברמת המשתמש.
+<translation id="3172512016079904926">המדיניות הזו מאפשרת להתקין ברמת המשתמש מארחים מקומיים להעברת הודעות.
 
-          אם ההגדרה הזו מופעלת, <ph name="PRODUCT_NAME" /> מאפשר להשתמש במארחי העברת הודעות מקומית שמותקנים ברמת המשתמש.
+          אם ההגדרה הזו מופעלת, <ph name="PRODUCT_NAME" /> מאפשר להשתמש במארחים מקומיים להעברת הודעות שהותקנו ברמת המשתמש.
 
-          אם ההגדרה הזו מושבתת, <ph name="PRODUCT_NAME" /> משתמש רק במארחי העברת הודעות מקומית שמותקנים ברמת המערכת.
+          אם ההגדרה הזו מושבתת, <ph name="PRODUCT_NAME" /> משתמש רק במארחים מקומיים להעברת הודעות שהותקנו ברמת המערכת.
 
-          אם ההגדרה הזו לא נקבעת, <ph name="PRODUCT_NAME" /> מאפשר להשתמש במארחי העברת הודעות מקומית ברמת המשתמש.</translation>
+          אם ההגדרה הזו לא נקבעת, <ph name="PRODUCT_NAME" /> מאפשר להשתמש במארחים מקומיים להעברת הודעות ברמת המשתמש.</translation>
 <translation id="3185009703220253572">מאז גרסה <ph name="SINCE_VERSION" /></translation>
 <translation id="3187220842205194486">‏אפליקציות Android אינן יכולות לגשת אל מפתחות ארגוניים. אין למדיניות הזו השפעה עליהן.</translation>
 <translation id="3205825995289802549">הגדל למקסימום את חלון הדפדפן הראשון בהפעלה הראשונה</translation>
@@ -1297,9 +1297,9 @@
         אם המדיניות הזו מוגדרת, <ph name="PRODUCT_NAME" /> ינסה לרשום את עצמו ולהחיל מדיניות ענן משויכת על כל הפרופילים.
 
         ערך המדיניות הזו הוא אסימון הרשמה שאפשר לאחזר מהמסוף בממשק Google למנהלי מערכות.</translation>
-<translation id="3489247539215560634">אם ההגדרה הזו מופעלת, משתמשים יכולים לקבוע אם סיסמאות נשמרות בזיכרון על ידי <ph name="PRODUCT_NAME" /> ומוזנות באופן אוטומטי בפעם הבאה שהם נכנסים לאתר.
+<translation id="3489247539215560634">כשההגדרה הזו מופעלת, סיסמאות של המשתמשים יישמרו בזיכרון של <ph name="PRODUCT_NAME" /> ויוזנו באופן אוטומטי בפעם הבאה שהם ייכנסו לאתר.
 
-          אם ההגדרה הזו מושבתת, משתמשים לא יכולים לשמור סיסמאות חדשות אבל הם
+          כשההגדרה הזו מושבתת, משתמשים לא יכולים לשמור סיסמאות חדשות אבל הם
           עדיין יכולים להשתמש בסיסמאות שנשמרו קודם לכן.
 
           אם המדיניות הזו מופעלת או מושבתת, משתמשים לא יכולים לשנות או לבטל אותה ב-<ph name="PRODUCT_NAME" />. אם המדיניות לא מוגדרת, שמירת הסיסמאות מותרת (אבל המשתמשים רשאים להשבית אותה).</translation>
@@ -1327,7 +1327,7 @@
       כאשר המדיניות הזו מקבלת את הערך False, המכשיר לא ינסה
       ליצור קשר עם שרת ה-Quirks כדי להוריד קובצי תצורה.
 
-      אם המדיניות הזו לא מוגדרת או מקבלת את הערך True, מערכת ההפעלה <ph name="PRODUCT_OS_NAME" /> תנסה באופן אוטומטי ליצור קשר עם שרת ה-Quirks, להוריד קובצי תצורה אם הם זמינים ולשמור אותם במכשיר.  לדוגמה, קבצים מהסוג הזה משמשים כדי לשפר את איכות התצוגה של צגים מצורפים.</translation>
+      אם המדיניות הזו לא מוגדרת, או אם היא מקבלת את הערך True, מערכת ההפעלה <ph name="PRODUCT_OS_NAME" /> תנסה באופן אוטומטי ליצור קשר עם שרת ה-Quirks, להוריד קובצי תצורה אם הם זמינים ולשמור אותם במכשיר.  לדוגמה, קבצים מהסוג הזה משמשים כדי לשפר את איכות התצוגה של צגים מצורפים.</translation>
 <translation id="3524204464536655762">‏אתרים לא יכולים לבקש גישה אל התקני USB דרך ה-WebUSB API</translation>
 <translation id="3526752951628474302">הדפסה רק בשחור-לבן</translation>
 <translation id="3528000905991875314">הפעל דפי שגיאה חלופיים</translation>
@@ -1385,7 +1385,7 @@
 <translation id="3750220015372671395">חסימה של יצירת מפתחות באתרים אלה</translation>
 <translation id="375266612405883748">‏המדיניות הזו מגבילה את טווח יציאות ה-UDP שמארח הגישה מרחוק משתמש בהן במחשב הזה.
 
-          אם המדיניות לא מוגדרת או מוגדרת כמחרוזת ריקה, מארח הגישה מרחוק רשאי להשתמש בכל יציאה זמינה, אלא אם המדיניות <ph name="REMOTE_ACCESS_HOST_FIREWALL_TRAVERSAL_POLICY_NAME" /> מושבתת. אם היא מושבתת, מארח הגישה מרחוק משתמש ביציאות UDP בטווח של 12400-12409.</translation>
+          אם המדיניות לא מוגדרת, או אם היא מוגדרת כמחרוזת ריקה, מארח הגישה מרחוק רשאי להשתמש בכל יציאה זמינה, אלא אם המדיניות <ph name="REMOTE_ACCESS_HOST_FIREWALL_TRAVERSAL_POLICY_NAME" /> מושבתת. אם היא מושבתת, מארח הגישה מרחוק משתמש ביציאות UDP בטווח של 12400-12409.</translation>
 <translation id="3756011779061588474">חסימה של מצב מפתח</translation>
 <translation id="3758089716224084329">‏מאפשרת לך לציין את שרת ה-proxy שבו משתמש <ph name="PRODUCT_NAME" /> ומונעת ממשתמשים לשנות את הגדרות שרת ה-proxy. 
 
@@ -1608,7 +1608,7 @@
           ערך המדיניות צריך להיות באלפיות שנייה.</translation>
 <translation id="4105989332710272578">השבתת אכיפה של 'שקיפות אישורים' ברשימת כתובות אתרים</translation>
 <translation id="4121350739760194865">מנע הצגה של קידומי מכירות של יישומים בדף הכרטיסייה החדשה</translation>
-<translation id="4125606414556046117">‏המדיניות הזו מאפשרת לך להגדיר את תמונת הטפט שמוצגת בשולחן העבודה וברקע של המשתמש במסך הכניסה. כדי להגדיר את המדיניות הזו, יש לציין את כתובת ה-URL שמערכת ההפעלה <ph name="PRODUCT_OS_NAME" /> מורידה ממנה את תמונת הטפט. בנוסף, יש לציין גיבוב קריפטוגרפי שמשמש כדי לאמת את התקינות של ההורדה. התמונה צריכה להיות בפורמט JPEG וגודל הקובץ לא יכול לחרוג מ-16MB. כתובת ה-URL צריכה להיות נגישה ללא צורך באימות כלשהו.
+<translation id="4125606414556046117">‏המדיניות הזו מאפשרת להגדיר את תמונת הטפט שמוצגת בשולחן העבודה וברקע של המשתמש במסך הכניסה. כדי להגדיר את המדיניות הזו, יש לציין את כתובת ה-URL שמערכת ההפעלה <ph name="PRODUCT_OS_NAME" /> יכולה להוריד ממנה את תמונת הטפט. בנוסף, יש לציין גיבוב קריפטוגרפי שמשמש לאימות התקינות של ההורדה. התמונה צריכה להיות בפורמט JPEG והגודל המרבי המותר של הקובץ הוא 16MB. כתובת ה-URL צריכה להיות נגישה ללא צורך באימות כלשהו.
 
       המערכת מורידה את תמונת הטפט ושומרת אותה במטמון. אחרי כל שינוי של כתובת ה-URL או הגיבוב, תתבצע הורדה מחדש של התמונה.
 
@@ -1641,14 +1641,14 @@
 
           אם ההגדרה הזו מופעלת, רק לקוחות מאחד מהדומיינים שצוינו יכולים להתחבר למארח.
 
-          אם ההגדרה הזו מושבתת או לא נקבעת, המערכת מתבססת על מדיניות ברירת המחדל שמתאימה לסוג הקישור. אם מדובר בסיוע מרחוק, המדיניות מאפשרת ללקוחות מכל דומיין להתחבר למארח. כדי ליהנות מגישה מרחוק בכל עת, רק הבעלים של המארח יכול להתחבר.
+          אם ההגדרה הזו מושבתת או לא נקבעת, המערכת מתבססת על מדיניות ברירת המחדל שמתאימה לסוג הקישור. אם מדובר בסיוע מרחוק, המדיניות מאפשרת ללקוחות מכל דומיין להתחבר למארח. כדי ליהנות תמיד מגישה מרחוק, רק הבעלים של המארח יכול להתחבר.
 
           המדיניות הזו מבטלת את המדיניות RemoteAccessHostClientDomain, אם היא קיימת.
 
           מידע נוסף זמין במדיניות RemoteAccessHostDomainList.</translation>
 <translation id="4183229833636799228">הגדרת ברירת מחדל של <ph name="FLASH_PLUGIN_NAME" /></translation>
 <translation id="4192388905594723944">כתובת אתר לאימות אסימון אימות של לקוח גישה מרחוק</translation>
-<translation id="4197038214024763371">‏אם המדיניות הזו לא מוגדרת או מופעלת, המשתמשים רשאים להשתמש בבדיקת איות.
+<translation id="4197038214024763371">‏אם המדיניות הזו לא מוגדרת, או אם היא מופעלת, המשתמשים רשאים להשתמש בבדיקת איות.
 
       אם המדיניות הזו מושבתת, המשתמשים לא רשאים להשתמש בבדיקת איות. כאשר המדיניות הזו מושבתת, המערכת תתעלם גם מכללי המדיניות SpellcheckLanguage ו-SpellcheckLanguageBlacklist.
       </translation>
@@ -1675,7 +1675,7 @@
       אם מדיניות זו לא הוגדרה, המערכת תשתמש בערך ברירת המחדל הכללי עבור כל האתרים לפי המדיניות 'DefaultKeygenSetting' במקרה שהוגדרה, או לפי התצורה האישית שקבע המשתמש במקרה שלא הוגדרה.</translation>
 <translation id="4238997902172035160">‏המדיניות הזו מגדירה את הספרייה שתשמש את <ph name="PRODUCT_NAME" /> לצורך אחסון העותק הנודד של הפרופילים.
 
-      אם המדיניות הזו מוגדרת, הספריה שסופקה משמשת את <ph name="PRODUCT_NAME" /> כדי לאחסן את העותק הנודד של הפרופילים אם המדיניות <ph name="ROAMING_PROFILE_SUPPORT_ENABLED_POLICY_NAME" /> הופעלה. אם המדיניות <ph name="ROAMING_PROFILE_SUPPORT_ENABLED_POLICY_NAME" /> מושבתת או לא מוגדרת, המערכת לא משתמשת בערך שמאוחסן במדיניות הזו.
+      אם המדיניות הזו מוגדרת, הספריה שסופקה משמשת את <ph name="PRODUCT_NAME" /> כדי לאחסן את העותק הנודד של הפרופילים, אם המדיניות <ph name="ROAMING_PROFILE_SUPPORT_ENABLED_POLICY_NAME" /> הופעלה. אם המדיניות <ph name="ROAMING_PROFILE_SUPPORT_ENABLED_POLICY_NAME" /> מושבתת או לא מוגדרת, המערכת לא משתמשת בערך שמאוחסן במדיניות הזו.
 
       רשימת משתנים שניתן להשתמש בהם זמינה בכתובת https://www.chromium.org/administrators/policy-list-3/user-data-directory-variables.
 
@@ -1736,7 +1736,7 @@
       אם המדיניות הזו לא מוגדרת, כל חשבונות Google במכשירים יהיו גלויים במסגרת <ph name="PRODUCT_NAME" />.</translation>
 <translation id="4360826270668210664">‏אם המדיניות הזו מוגדרת, מארח הגישה מרחוק ידרוש מלקוחות המבצעים אימות לקבל אסימון אימות מכתובת URL זו כדי להתחבר. יש להשתמש במדיניות הזו ביחד עם RemoteAccessHostTokenValidationUrl.
 
-          בשלב זה התכונה הזו מושבתת בצד השרת.</translation>
+          בשלב זה, התכונה הזו מושבתת בצד השרת.</translation>
 <translation id="436581050240847513">דיווח על ממשקים של רשתות מכשירים</translation>
 <translation id="4372704773119750918">אל תאפשר למשתמש ארגוני להיות חלק מריבוי פרופילים (ראשי או משני)</translation>
 <translation id="4377599627073874279">אפשר לכל האתרים להציג את כל התמונות</translation>
@@ -1746,9 +1746,9 @@
 <translation id="4408428864159735559">רשימה של התקני רשת שהוגדרו מראש לשיתוף קבצים.</translation>
 <translation id="4410236409016356088">הפעלת ויסות רוחב הפס ברשת</translation>
 <translation id="441217499641439905">‏השבתת Google Drive דרך חיבורים סלולריים באפליקציה 'קבצים' של ‎<ph name="PRODUCT_OS_NAME" /></translation>
-<translation id="4415603335307944578">‏אם המדיניות הזו מקבלת את הערך True או לא מוגדרת, הדפדפן מציג מחדש את דף קבלת הפנים בפעם הראשונה שבה הוא מופעל אחרי עדכון מערכת ההפעלה.
+<translation id="4415603335307944578">‏אם המדיניות הזו מקבלת את הערך True או לא מוגדרת, הדפדפן מציג מחדש את דף קבלת הפנים בפעם הראשונה שבה הוא מופעל אחרי שדרוג מערכת ההפעלה.
 
-      אם המדיניות הזו מקבלת את הערך False, הדפדפן לא מציג מחדש את דף קבלת הפנים בפעם הראשונה שבה הוא מופעל אחרי עדכון מערכת ההפעלה.</translation>
+      אם המדיניות הזו מקבלת את הערך False, הדפדפן לא מציג מחדש את דף קבלת הפנים בפעם הראשונה שבה הוא מופעל אחרי שדרוג מערכת ההפעלה.</translation>
 <translation id="4418726081189202489">‏אם המדיניות תועבר למצב 'שקר', מערכת <ph name="PRODUCT_NAME" /> תפסיק לשלוח מדי פעם שאילתות לשרת Google כדי לאחזר חותמת זמן מדויקת. השאילתות יופעלו אם המדיניות תועבר למצב 'אמת' או תישאר ללא הגדרה.</translation>
 <translation id="4423597592074154136">‏ציין הגדרות Proxy באופן ידני</translation>
 <translation id="4429220551923452215">מפעילה או משבית את קיצור היישומים בשורת הסימניות.
@@ -1819,7 +1819,7 @@
 <translation id="4557134566541205630">כתובת האתר של דף הכרטיסייה החדשה של ספק החיפוש המוגדר כברירת מחדל</translation>
 <translation id="4567137030726189378">התרת שימוש ב'כלים למפתחים'</translation>
 <translation id="4578265298946081589">ללא הפעלה מחדש כשמשתמש יוצא.</translation>
-<translation id="4578912515887794133">‏אם ההגדרה הזו מופעלת, מארח הגישה מרחוק משווה בין השם של המשתמש המקומי (שהמארח משויך אליו) לשם של חשבון Google הרשום כבעלים של המארח (כלומר "johndoe" אם המארח בבעלות חשבון Google בשם "johndoe@example.com").  מארח הגישה מרחוק לא יפעל אם שם הבעלים של המארח שונה מהשם של המשתמש המקומי שהמארח משויך אליו.  בנוסף, כדי לאכוף שיוך בין חשבון Google של בעלי המארח לבין דומיין ספציפי (למשל "example.com"), יש להשתמש במדיניות RemoteAccessHostMatchUsername ביחד עם RemoteAccessHostDomain.
+<translation id="4578912515887794133">‏אם ההגדרה הזו מופעלת, מארח הגישה מרחוק משווה בין השם של המשתמש המקומי (שהמארח משויך אליו) לשם של חשבון Google הרשום כבעלים של המארח (למשל: "johndoe" אם המארח בבעלות חשבון Google בשם "johndoe@example.com").  מארח הגישה מרחוק לא יפעל אם שם הבעלים של המארח שונה מהשם של המשתמש המקומי שהמארח משויך אליו.  בנוסף, כדי לאכוף שיוך בין חשבון Google של בעלי המארח לבין דומיין ספציפי (למשל: "example.com"), יש להשתמש במדיניות RemoteAccessHostMatchUsername ביחד עם RemoteAccessHostDomain.
 
           אם ההגדרה הזו מושבתת או לא מוגדרת, מארח הגישה מרחוק יכול להיות משויך לכל משתמש מקומי.</translation>
 <translation id="4600786265870346112">הפעל סמן גדול</translation>
@@ -1833,7 +1833,7 @@
 
       אם המדיניות הזו מקבלת את הערך Migrate, ספריות בית המוגנות באמצעות הצפנת ecryptfs יועברו באופן אוטומטי להצפנת ext4 בזמן הכניסה, בלי לבקש את הסכמת המשתמש.
 
-      אם המדיניות מקבלת את הערך Wipe, ספריות בית שמוגנות באמצעות הצפנת ecryptfs יימחקו בזמן הכניסה ובמקומן יווצרו ספריות בית חדשות שמוגנות באמצעות הצפנת ext4. אזהרה: הפעולה הזו גורמת למחיקת הנתונים המקומיים של המשתמש.
+      אם המדיניות מקבלת את הערך Wipe, ספריות בית שמוגנות באמצעות הצפנת ecryptfs יימחקו בזמן הכניסה ובמקומן יווצרו ספריות בית חדשות שמוגנות באמצעות הצפנת ext4. אזהרה: הפעולה הזו גורמת להסרת הנתונים המקומיים של המשתמש.
 
       אם המדיניות מקבלת את הערך AskUser, משתמשים עם ספריות בית שמוגנות באמצעות הצפנת ecryptfs יקבלו הצעה לביצוע מעבר.
 
@@ -2057,9 +2057,9 @@
 
           אם בוחרים לא להשתמש אף פעם בשרת proxy ותמיד להתחבר ישירות, המערכת מתעלמת מכל שאר האפשרויות.
 
-          אם בוחרים להשתמש בהגדרות שרת ה-proxy של המערכת או לזהות באופן אוטומטי את שרת ה-proxy, המערכת מתעלמת מכל שאר האפשרויות.
+          אם בוחרים להשתמש בהגדרות שרת ה-proxy של המערכת, או לזהות באופן אוטומטי את שרת ה-proxy, המערכת מתעלמת מכל שאר האפשרויות.
 
-          אם בוחרים הגדרות שרת proxy ידניות, ניתן לציין אפשרויות נוספות ב'כתובת או כתובת אתר של שרת Proxy', 'כתובת אתר לקובץ ‎.pac של שרת Proxy' ו'רשימה מופרדת בפסיקים של כללי עקיפת Proxy'. רק שרת ה-proxy מסוג HTTP עם העדיפות הגבוהה ביותר זמין לאפליקציות ARC.
+          אם בוחרים הגדרות שרת proxy ידניות, ניתן לציין אפשרויות נוספות ב'כתובת או URL של שרת Proxy', 'כתובת URL לקובץ ‎.pac של שרת Proxy' ו'רשימה מופרדת בפסיקים של כללי עקיפת Proxy'. רק שרת ה-proxy מסוג HTTP עם העדיפות הגבוהה ביותר זמין לאפליקציות ARC.
 
           ניתן לעיין בדוגמאות מפורטות כאן:
           <ph name="PROXY_HELP_URL" />.
@@ -2106,11 +2106,11 @@
 <translation id="5236882091572996759">‏אם המדיניות הזו מקבלת את הערך True או לא מוגדרת, משתמשים אינם נחשבים כלא פעילים במהלך ההפעלה של תוכן אודיו. המדיניות מונעת מהמערכת להגיע לפרק זמן ההשהיה של חוסר הפעילות. בנוסף, היא מונעת מהמערכת לבצע את הפעולה המתאימה לחוסר פעילות. עם זאת, עמעום המסך, כיבוי המסך ונעילת המסך יתבצעו אחרי הזמנים הקצובים לתפוגה שהוגדרו, ללא קשר להפעלת תוכן אודיו.
 
           אם המדיניות הזו מקבלת את הערך False, הפעלת תוכן אודיו לא מונעת מהמשתמשים להיחשב כלא פעילים.</translation>
-<translation id="5246700266104954355">‏המדיניות הזו הוצאה משימוש. יש להשתמש במדיניות <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME" /> כדי לשלוט בזמינות של הפלאגין Flash ובמדיניות <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME" /> כדי לקבוע אם הכלי המשולב להצגת PDF משמש לפתיחת קובצי PDF.
+<translation id="5246700266104954355">‏המדיניות הזו הוצאה משימוש. יש להשתמש במדיניות <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME" /> כדי לשלוט בזמינות של הפלאגין Flash ובמדיניות <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME" /> כדי לקבוע אם הכלי המשולב להצגת PDF ישמש לפתיחת קובצי PDF.
 
       המדיניות מציינת רשימה של יישומי פלאגין שמופעלים ב-<ph name="PRODUCT_NAME" /> ומונעת ממשתמשים לשנות את ההגדרה הזו.
 
-      ניתן להשתמש בתווים הכללים לחיפוש '*' ו-'?' כדי להתאים לרצפים של תווים שרירותיים. התו '*' תואם למספר שרירותי של תווים והתו '?' מציין תו אופציונלי יחיד, כלומר תואם לאפס תווים או לתו אחד. תו הבריחה הוא '\', כך שכדי להתאים בפועל לתווים '*', '?', או '\', ניתן להוסיף לפניהם '\'.
+      ניתן להשתמש בתווים הכלליים לחיפוש '*' ו-'?' כדי להתאים לרצפים של תווים שרירותיים. התו '*' תואם למספר שרירותי של תווים והתו '?' מציין תו אופציונלי יחיד, כלומר תואם לאפס תווים או לתו אחד. תו הבריחה הוא '\', כך שכדי להתאים בפועל לתווים '*', '?', או '\', ניתן להוסיף לפניהם '\'.
 
       אם יישומי הפלאגין מהרשימה שצוינה מותקנים, הרשימה הזו תמיד נמצאת בשימוש ב-<ph name="PRODUCT_NAME" />. יישומי הפלאגין מסומנים כמופעלים ב-about:plugins והמשתמשים לא יכולים להשבית אותם.
 
@@ -2237,11 +2237,11 @@
       אם הכללים סותרים אחד את השני, <ph name="PRODUCT_NAME" /> משתמש בכלל הספציפי ביותר.</translation>
 <translation id="5475361623548884387">הפוך הדפסה לפעילה</translation>
 <translation id="547601067149622666">ללא מודעות באתרים עם מודעות שמפריעות</translation>
-<translation id="5483777239978559943">‏המדיניות הזו הוצאה משימוש. יש להשתמש במדיניות <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME" /> כדי לשלוט בזמינות של הפלאגין Flash ובמדיניות <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME" /> כדי לקבוע אם הכלי המשולב להצגת PDF משמש לפתיחת קובצי PDF.
+<translation id="5483777239978559943">‏המדיניות הזו הוצאה משימוש. יש להשתמש במדיניות <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME" /> כדי לשלוט בזמינות של הפלאגין Flash ובמדיניות <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME" /> כדי לקבוע אם הכלי המשולב להצגת PDF ישמש לפתיחת קובצי PDF.
 
       המדיניות הזו מציינת רשימת יישומי פלאגין שהמשתמשים יכולים להפעיל או להשבית ב-<ph name="PRODUCT_NAME" />.
 
-      ניתן להשתמש בתווים כלליים לחיפוש '*' ו-'?' כדי להתאים לרצפים של תווים שרירותיים. התו '*' תואם למספר שרירותי של תווים והתו '?' מציין תו אופציונלי יחיד, כלומר תואם לאפס תווים או לתו אחד. תו הבריחה הוא '\', כך שכדי להתאים בפועל לתווים '*', '?', או '\', ניתן להוסיף לפניהם '\'.
+      ניתן להשתמש בתווים הכלליים לחיפוש '*' ו-'?' כדי להתאים לרצפים של תווים שרירותיים. התו '*' תואם למספר שרירותי של תווים והתו '?' מציין תו אופציונלי יחיד, כלומר תואם לאפס תווים או לתו אחד. תו הבריחה הוא '\', כך שכדי להתאים בפועל לתווים '*', '?', או '\', ניתן להוסיף לפניהם '\'.
 
       אם ההגדרה הזו מופעלת, ניתן להשתמש ברשימת יישומי הפלאגין שצוינה ב-<ph name="PRODUCT_NAME" />. משתמשים יכולים להפעיל או להשבית את היישומים ב-about:plugins, גם אם הפלאגין תואם לדפוס ב-DisabledPlugins. משתמשים יכולים גם להפעיל ולהשבית יישומי פלאגין שלא תואמים לדפוסים כלשהם ב-DisabledPlugins, ב-DisabledPluginsExceptions וב-EnabledPlugins.
 
@@ -2338,12 +2338,12 @@
     הערה: המדיניות הזו חלה רק על Chrome ב-Android במכשירים עם זיכרון RAM גדול מ-1GB. כדי להחיל את המדיניות על פלטפורמות אחרות, ולא על Android, יש להשתמש ב-IsolateOrigins.
       </translation>
 <translation id="5599461642204007579">הגדרות ניהול של <ph name="MS_AD_NAME" /></translation>
-<translation id="5610104657949692379">כאשר המדיניות הזו מוגדרת, היא מציינת את הפעולה שמתבצעת על ידי <ph name="PRODUCT_OS_NAME" /> כאשר המשתמש אינו פעיל למשך פרק הזמן שמצוין על ידי השהיית חוסר הפעילות. ניתן להגדיר את ההשהיה הזו בנפרד.
+<translation id="5610104657949692379">כאשר המדיניות הזו מוגדרת, היא מציינת את הפעולה שמתבצעת על ידי <ph name="PRODUCT_OS_NAME" /> כאשר המשתמש אינו פעיל למשך פרק הזמן שנקבע להשהיית חוסר הפעילות. ניתן להגדיר את ההשהיה הזו בנפרד.
 
-          כשהמדיניות לא מוגדרת מתבצעת פעולת ברירת המחדל, השעיה.
+          כשהמדיניות לא מוגדרת, מתבצעת פעולת ברירת המחדל שהיא השעיה.
 
-          אם הפעולה מושעית, ניתן להגדיר בנפרד את <ph name="PRODUCT_OS_NAME" /> כדי לנעול או לא לנעול את המסך לפני ההשעיה.</translation>
-<translation id="5618398258385745432">‏ההגדרה המשויכת הייתה בשימוש לפני שנוספה האפשרות של אימות מחדש בעת הצגת סיסמאות. מאותו שלב ההגדרה לא משפיעה על ההתנהגות של Chrome. כתוצאה מכך, גם למדיניות אין השפעה על Chrome. ההתנהגות הנוכחית של Chrome זהה להתנהגות שהייתה מתקבלת אם הגדרת המדיניות הייתה להשבית הצגת סיסמאות בטקסט רגיל בדף ההגדרות של מנהל הסיסמאות. המשמעות היא שדף ההגדרות כולל רק placeholder ו-Chrome מציג את הסיסמה רק אחרי שהמשתמשים לוחצים על "הצגה" (ומבצעים אימות מחדש, אם זה רלוונטי). התיאור המקורי של המדיניות מצורף למטה.
+          אם הפעולה מושעית, ניתן לקבוע בנפרד ש-<ph name="PRODUCT_OS_NAME" /> ינעל את המסך, או לא ינעל אותו, לפני ההשעיה.</translation>
+<translation id="5618398258385745432">‏ההגדרה המשויכת הייתה בשימוש לפני שנוספה האפשרות של אימות מחדש בהצגת סיסמאות. מאותו שלב, ההגדרה לא משפיעה על ההתנהגות של Chrome. כתוצאה מכך, גם למדיניות אין השפעה על Chrome. ההתנהגות הנוכחית של Chrome זהה להתנהגות שהייתה מתקבלת אם הגדרת המדיניות הייתה להשבית הצגת סיסמאות בטקסט רגיל בדף ההגדרות של מנהל הסיסמאות. המשמעות היא שדף ההגדרות כולל רק placeholder ו-Chrome מציג את הסיסמה רק אחרי שהמשתמשים לוחצים על "הצגה" (ומבצעים אימות מחדש, אם זה רלוונטי). התיאור המקורי של המדיניות מצורף למטה.
 
           המדיניות הזו קובעת אם משתמשים רשאים להציג סיסמאות בטקסט רגיל במנהל הסיסמאות.
 
@@ -2385,9 +2385,9 @@
 <translation id="5732972008943405952">יבוא נתוני מילוי אוטומטי של טפסים מדפדפן ברירת המחדל בהפעלה הראשונה</translation>
 <translation id="5741810844420698449">כשהמדיניות הזו מוגדרת, היא מציינת את הפעולה שמתבצעת על ידי <ph name="PRODUCT_OS_NAME" /> כשהמשתמש סוגר את המכסה של המכשיר.
 
-          כשהמדיניות לא מוגדרת מתבצעת פעולת ברירת המחדל, השעיה.
+          כשהמדיניות לא מוגדרת, מתבצעת פעולת ברירת המחדל שהיא השעיה.
 
-          אם הפעולה מושעית, ניתן להגדיר בנפרד את <ph name="PRODUCT_OS_NAME" /> כדי לנעול או לא לנעול את המסך לפני ההשעיה.</translation>
+          אם הפעולה מושעית, ניתן לקבוע בנפרד ש-<ph name="PRODUCT_OS_NAME" /> ינעל את המסך, או לא ינעל אותו, לפני ההשעיה.</translation>
 <translation id="5765780083710877561">תיאור:</translation>
 <translation id="5770738360657678870">‏Dev channel (יכול להיות לא יציב)</translation>
 <translation id="5774856474228476867">כתובת אתר של ספק חיפוש המוגדר כברירת מחדל</translation>
@@ -2662,7 +2662,7 @@
 
       אם המדיניות הזו מושבתת, בדיקת האיות מושבתת לשפות שצוינו. המשתמשים יכולים עדיין להפעיל או להשבית את בדיקות האיות לשפות שלא מופיעות ברשימה.
 
-      אם המדיניות הזו לא מוגדרת או מושבתת, העדפות בדיקת האיות של המשתמשים לא משתנות.
+      אם המדיניות הזו לא מוגדרת, או אם היא מושבתת, העדפות בדיקת האיות של המשתמשים לא משתנות.
 
       אם המדיניות SpellcheckEnabled מושבתת, למדיניות הזו אין השפעה.
 
@@ -2718,7 +2718,7 @@
 <translation id="6449476513004303784">משתמשים לא יכולים לנהל אישורים</translation>
 <translation id="645425387487868471">הפעלת אכיפת הכניסה במסגרת <ph name="PRODUCT_NAME" /></translation>
 <translation id="6464074037294098618">הפעלת מילוי אוטומטי בשביל כתובות</translation>
-<translation id="6467613372414922590">מארחי העברת הודעות מקומית ברמת המשתמש (מותקנים ללא הרשאות מנהל מערכת) מותרים לשימוש.</translation>
+<translation id="6467613372414922590">מארחים מקומיים להעברת הודעות מותרים ברמת המשתמש (ואפשר להתקין אותם ללא צורך בהרשאות ממנהל המערכת).</translation>
 <translation id="6468980648680553776">‏המדיניות הזו הוצאה משימוש. במקומה, יש להשתמש במדיניות RemoteAccessHostClientDomainList.</translation>
 <translation id="6473623140202114570">הגדרת רשימת הדומיינים שבהם גלישה בטוחה לא תפעיל אזהרות.</translation>
 <translation id="6488627892044759800">‏המדיניות הזו מגדירה את סוג דף הבית שמוגדר כברירת מחדל ב-<ph name="PRODUCT_NAME" /> ומונעת ממשתמשים לשנות את העדפות דף הבית. ניתן להגדיר דף בית שהוא כתובת URL שמצוינת על ידך, או דף הכרטיסייה החדשה.
@@ -3057,7 +3057,7 @@
       אם מדיניות זו אינה מוגדרת כלל, 'מצב ברקע' מושבת כברירת מחדל, אך המשתמש יכול לשלוט בו מהגדרות הדפדפן.</translation>
 <translation id="7123160381479171745">מדיניות זו מגדירה את רשימת המשתמשים שרשאים להיכנס למכשיר. הרשומות הן מהטופס <ph name="USER_WHITELIST_ENTRY_FORMAT" />, כמו <ph name="USER_WHITELIST_ENTRY_EXAMPLE" />. כדי לאשר משתמשים שרירותיים בדומיין, יש להשתמש ברשומות מהטופס <ph name="USER_WHITELIST_ENTRY_WILDCARD" />.
 
-      אם המדיניות הזו לא מוגדרת, אין הגבלה על המשתמשים שרשאים להיכנס. חשוב לשים לב שכדי ליצור משתמשים חדשים, צריך עדיין להגדיר את המדיניות <ph name="DEVICE_ALLOW_NEW_USERS_POLICY_NAME" /> בהתאם.</translation>
+      אם המדיניות הזו לא מוגדרת, אין הגבלות לגבי זהות המשתמשים שרשאים להיכנס. חשוב לשים לב שכדי ליצור משתמשים חדשים, צריך עדיין להגדיר את המדיניות <ph name="DEVICE_ALLOW_NEW_USERS_POLICY_NAME" /> בהתאם.</translation>
 <translation id="7123266440503901785">‏<ph name="PRODUCT_NAME" /> מספק אבטחה בעדכונים ובהתקנות של תוספים. עם זאת, התוכן של חלק מהתוספים שמתארחים מחוץ לחנות האינטרנט של Chrome עשוי להיות מוגן רק על-ידי אלגוריתמים לא מאובטחים של חתימה או גיבוב (hashing), כמו SHA1. כשהמדיניות הזו מושבתת, התקנות חדשות ועדכונים של תוספים כאלה ייחסמו על-ידי Chrome (עד שמפתח התוסף יבנה אותו מחדש עם אלגוריתמים מאובטחים יותר). כשהמדיניות הזו מופעלת, ההתקנה והעדכונים של תוספים כאלה מותרת.
 
           אם היא לא מוגדרת, ברירת המחדל תהיה שימוש בהתנהגות המופעלת.
@@ -3163,7 +3163,7 @@
 
       אם ההגדרה הזו מושבתת, המשתמשים לא יהיו רשאים להשתמש ב-Smart Lock.
 
-      אם המדיניות הזו לא מוגדרת, ברירת המחדל היא לא לאפשר את השימוש בתכונה למשתמשים המנוהלים על ידי ארגון ולאפשר את השימוש בתכונה למשתמשים שאינם מנוהלים.</translation>
+      אם המדיניות הזו לא מוגדרת, ברירת המחדל היא לא לאפשר את השימוש בתכונה למשתמשים המנוהלים על ידי ארגון, ולאפשר את השימוש בתכונה למשתמשים שאינם מנוהלים.</translation>
 <translation id="7295019613773647480">הפעלת משתמשים בפיקוח</translation>
 <translation id="7301543427086558500">‏מדיניות זו מגדירה רשימה של כתובות אתרים חלופיות שיכולות לשמש לחילוץ מונחי חיפוש ממנוע החיפוש. כתובות האתרים יכילו את המחרוזת <ph name="SEARCH_TERM_MARKER" />, שתשמש לחילוץ מונחי החיפוש.
 
@@ -3235,7 +3235,7 @@
 <translation id="7485481791539008776">כללים לבחירת מדפסת ברירת מחדל</translation>
 <translation id="7485730741952775732">‏אם המדיניות הזו מוגדרת, מארח הגישה מרחוק ישתמש בכתובת ה-URL הזו כדי לאשר אסימוני אימות מלקוחות גישה מרחוק, במטרה לקבל חיבורים. יש להשתמש במדיניות הזו בשילוב עם RemoteAccessHostTokenUrl.
 
-          בשלב זה התכונה הזו מושבתת בצד השרת.</translation>
+          בשלב זה, התכונה הזו מושבתת בצד השרת.</translation>
 <translation id="749556411189861380">‏דיווח על גרסת הקושחה ומערכת ההפעלה של מכשירים רשומים.
 
       אם ההגדרה לא נקבעה או אם היא מוגדרת כ-True, מכשירים רשומים ידיווח את גרסת הקושחה ומערכת ההפעלה על בסיס תקופתי. אם ההגדרה הזו נקבעה כ-False, פרטי הגרסה לא ידיווחו.</translation>
@@ -3439,11 +3439,11 @@
 <translation id="793473937901685727">‏הגדר זמינות אישורים ליישומי ARC</translation>
 <translation id="7937766917976512374">התר או דחה הקלטת וידאו</translation>
 <translation id="7941975817681987555">אל תבצע חיזוי של פעולות רשת באף חיבור רשת</translation>
-<translation id="7952958573604504839">‏המדיניות הזו הוצאה משימוש ב-M48. היא הוחלפה במדיניות <ph name="NETWORK_PREDICTION_OPTIONS_POLICY_NAME" /> ולאחר מכן הוסרה ב-M54.
+<translation id="7952958573604504839">‏בגרסה M48, המדיניות הזו הוצאה משימוש והוחלפה במדיניות <ph name="NETWORK_PREDICTION_OPTIONS_POLICY_NAME" />. בגרסה M54, היא הוסרה.
 
       המדיניות הזו מאפשרת חיזוי ברשת ב-<ph name="PRODUCT_NAME" /> ומונעת ממשתמשים לשנות את ההגדרה הזו.
 
-      המדיניות שולטת לא רק בהבאת DNS מראש אלא גם בחיבור TCP ו-SSL מראש ובעיבוד מראש של דפי אינטרנט. שם המדיניות מתייחס להבאת DNS מראש משיקולים היסטוריים.
+      המדיניות שולטת לא רק בהבאת DNS מראש אלא גם בחיבור TCP ו-SSL מראש ובעיבוד מראש של דפי אינטרנט. שם המדיניות מתייחס להבאת DNS מראש מסיבות היסטוריות.
 
       אם ההגדרה הזו מופעלת או מושבתת, משתמשים לא יכולים לשנות או לבטל את ההגדרה הזו ב-<ph name="PRODUCT_NAME" />.
 
@@ -3491,12 +3491,12 @@
 
           אם המדיניות הזו מוגדרת על ידך, המשתמשים לא יכולים לשנות או לבטל אותה.
 
-          אם המדיניות הזו לא מוגדרת, אפשרויות הנגישות לא מופיעות בתפריט מגש המערכת אך המשתמשים יכולים לגרום להצגת אפשרויות הנגישות דרך דף ההגדרות.</translation>
+          אם המדיניות הזו לא מוגדרת, אפשרויות הנגישות לא מופיעות בתפריט מגש המערכת, אך המשתמשים יכולים לגרום להצגת אפשרויות הנגישות דרך דף ההגדרות.</translation>
 <translation id="806523868782250975">‏המדיניות הזו מגדירה רשימה של סימניות מנוהלות.
 
-      המדיניות כוללת רשימת סימניות שבה כל סימניה היא ספריה המכילה את המפתחות "<ph name="NAME" />" ו-"<ph name="URL_LABEL" />". המפתחות האלו מכילים את השם והיעד של הסימניה. ניתן להגדיר תיקיית משנה על ידי הגדרה סימניה ללא מפתח "<ph name="URL_LABEL" />" אך עם מפתח "<ph name="CHILDREN" />" נוסף, שבעצמו מכיל רשימת סימניות כפי שמתואר למעלה (גם חלק מהסימניות האלו יכולות להיות תיקיות). כתובת URL חסרות עוברות תיקון על ידי <ph name="PRODUCT_NAME" /> כאילו הן נשלחו דרך סרגל הכתובות. לדוגמה, הכתובת "<ph name="GOOGLE_COM" />" הופכת ל-"<ph name="HTTPS_GOOGLE_COM" />".
+      המדיניות כוללת רשימת סימניות שבה כל סימניה היא ספריה המכילה את המפתחות "<ph name="NAME" />" ו-"<ph name="URL_LABEL" />". המפתחות האלו מכילים את השם והיעד של הסימניה. ניתן להגדיר תיקיית משנה על ידי הגדרה של סימניה ללא מפתח "<ph name="URL_LABEL" />" אך עם מפתח "<ph name="CHILDREN" />" נוסף, שבעצמו מכיל רשימת סימניות כפי שמתואר למעלה (גם חלק מהסימניות האלו יכולות להיות תיקיות). כתובת URL שאינן מלאות עוברות השלמה על ידי <ph name="PRODUCT_NAME" /> כאילו הן נשלחו דרך סרגל הכתובות. לדוגמה, הכתובת "<ph name="GOOGLE_COM" />" הופכת ל-"<ph name="HTTPS_GOOGLE_COM" />".
 
-      הסימניות האלו ממוקמות בתיקייה שאינה ניתנת לשינוי על ידי המשתמשים (עם זאת, המשתמשים יכולים להסתיר אותה מסרגל הכתובות). כברירת מחדל, שם התיקייה הוא "סימניות מנוהלות". כדי להתאים אישית את השם, ניתן להוסיף לרשימת הסימניות ספרייה המכילה את המפתח "<ph name="TOPLEVEL_NAME" />" עם ערך שהוא השם הרצוי של התיקייה.
+      הסימניות האלו ממוקמות בתיקייה שהמשתמשים אינם יכולים לשנות (אבל המשתמשים יכולים לקבוע שהתיקייה הזו לא תופיע בסרגל הסימניות). כברירת מחדל, שם התיקייה הוא "סימניות מנוהלות". כדי להתאים אישית את השם, ניתן להוסיף לרשימת הסימניות ספרייה המכילה את המפתח "<ph name="TOPLEVEL_NAME" />" עם ערך שהוא השם הרצוי של התיקייה.
 
       סימניות מנוהלות לא מסתנכרנות עם חשבון המשתמש ותוספים לא יכולים לשנות אותן.</translation>
 <translation id="8078366200175825572">‏מאפשרת לך להגדיר רשימה של דפוסי כתובות אתרים המציינים אתרים שאינם מורשים להגדיר קובצי Cookie.
@@ -3601,7 +3601,7 @@
 
       הדרך המומלצת להגדיר מדיניות ב-Windows היא דרך GPO, למרות שניהול תצורת מדיניות
       דרך המרשם עדיין נתמך במופעים של Windows המשויכים לדומיין של <ph name="MS_AD_NAME" />.</translation>
-<translation id="8259592978873597235">‏אם המדיניות הזו מקבלת את הערך True או לא מוגדרת, משתמשים אינם נחשבים כלא פעילים במהלך ההפעלה של תוכן וידאו. המדיניות מונעת מהמערכת להגיע לפרקי זמן ההשהיה של חוסר הפעילות, עמעום המסך, כיבוי המסך ונעילת המסך. בנוסף, המדיניות מונעת מהמערכת לבצע את הפעולות התואמות.
+<translation id="8259592978873597235">‏אם המדיניות הזו מקבלת את הערך True או לא מוגדרת, משתמשים אינם נחשבים כלא פעילים במהלך הפעלה של תוכן וידאו. המדיניות מונעת מהמערכת להגיע לפרקי זמן ההשהיה של חוסר הפעילות, עמעום המסך, כיבוי המסך ונעילת המסך. בנוסף, המדיניות מונעת מהמערכת לבצע את הפעולות התואמות.
 
           אם המדיניות הזו מקבלת את הערך False, משתמשים יכולים להיחשב כלא פעילים גם במהלך הפעלה של תוכן וידאו.</translation>
 <translation id="8264653492961233132">‏המדיניות הזו מציינת רשימת אפליקציות ותוספים שמותקנים בצורה שקטה,
@@ -3667,7 +3667,7 @@
       אם המדיניות מוגדרת כ-true או אינה מוגדרת, הנתונים הסטטיסטיים ידווחו.</translation>
 <translation id="8380490658357556620">המדיניות הזו מאפשרת להשתמש בשרתי ממסר כאשר לקוחות מרוחקים מנסים להתחבר למחשב הזה.
 
-          אם ההגדרה הזו מופעלת, לקוחות מרוחקים יכולים להתחבר למחשב הזה באמצעות שרתי ממסר כאשר חיבור ישיר אינו זמין (למשל כתוצאה ממגבלות חומת האש).
+          אם ההגדרה הזו מופעלת, לקוחות מרוחקים יכולים להתחבר למחשב הזה באמצעות שרתי ממסר כאשר חיבור ישיר אינו זמין (למשל: בגלל מגבלות של חומת האש).
 
           חשוב לשים לב שאם המדיניות <ph name="REMOTE_ACCESS_HOST_FIREWALL_TRAVERSAL_POLICY_NAME" /> מושבתת, המערכת מתעלמת מהמדיניות הזו.
 
@@ -3962,7 +3962,7 @@
 <translation id="8992176907758534924">אל תאפשר לאף אתר להציג תמונות</translation>
 <translation id="9013875414788074110">‏במהלך הכניסה, מערכת ההפעלה <ph name="PRODUCT_OS_NAME" /> יכולה לבצע אימות מול שרת (באינטרנט) או באמצעות סיסמה שמורה במטמון (במצב לא מקוון).
 
-      כאשר המדיניות הזאת מקבלת ערך של ‎-1, המשתמשים יכולים לבצע אימות במצב לא מקוון ללא הגבלה. כאשר המדיניות מקבלת כל ערך אחר, הערך הזה הוא משך זמן שנמדד מהפעם האחרונה שבה התבצע אימות מקוון. אחרי משך הזמן הזה, משתמשים חייבים לבצע אימות מקוון מחדש.
+      כאשר המדיניות הזאת מקבלת ערך של ‎-1, המשתמשים יכולים לבצע אימות במצב לא מקוון ללא הגבלה. כאשר המדיניות מקבלת ערך אחר כלשהו, הערך הזה הוא הזמן שנמדד מהפעם האחרונה שבה התבצע אימות מקוון. אחרי פרק הזמן הזה, משתמשים חייבים לבצע אימות מקוון מחדש.
 
       אם המדיניות הזו לא מוגדרת, מערכת ההפעלה <ph name="PRODUCT_OS_NAME" /> משתמשת במגבלת זמן של 14 ימים שמוגדרת כברירת מחדל. אחרי 14 ימים המשתמשים צריכים לבצע אימות מקוון מחדש.
 
@@ -4097,13 +4097,13 @@
 <translation id="9217154963008402249">תדירות מנות הרשת לניטור</translation>
 <translation id="922540222991413931">הגדר את מקורות התקנת התוספים, היישומים והסקריפטים של משתמשים</translation>
 <translation id="924557436754151212">ייבא סיסמאות שנשמרו מדפדפן ברירת המחדל בהפעלה הראשונה</translation>
-<translation id="926146562923985266">‏המדיניות הזו שולטת בפקודה שבה יש להשתמש כדי לפתוח כתובות URL ב-<ph name="PRODUCT_NAME" /> בזמן המעבר מ-Internet Explorer.
+<translation id="926146562923985266">‏המדיניות הזו שולטת בפקודה שבה יש להשתמש כדי לפתוח כתובות URL ב-<ph name="PRODUCT_NAME" /> כשעוברים מ-Internet Explorer.
 
       אם התוסף 'תמיכה בדפדפן מדור קודם' ל-Internet Explorer לא מותקן, למדיניות אין השפעה.
 
-      כאשר המדיניות הזו לא מוגדרת, Internet Explorer מזהה באופן אוטומטי את נתיב קובץ ההפעלה של <ph name="PRODUCT_NAME" /> בעת הפעלת <ph name="PRODUCT_NAME" /> מ-Internet Explorer.
+      כאשר המדיניות הזו לא מוגדרת, Internet Explorer מזהה באופן אוטומטי את נתיב קובץ ההפעלה של <ph name="PRODUCT_NAME" /> כש-<ph name="PRODUCT_NAME" /> מופעל מ-Internet Explorer.
 
-      כאשר המדיניות הזו מוגדרת, היא משמשת לצורך הפעלת <ph name="PRODUCT_NAME" /> במהלך ההפעלה של <ph name="PRODUCT_NAME" /> מ-Internet Explorer.
+      כאשר המדיניות הזו מוגדרת, היא משמשת להפעלת <ph name="PRODUCT_NAME" /> כש-<ph name="PRODUCT_NAME" /> מופעל מ-Internet Explorer.
 
       אפשר להגדיר במדיניות הזו נתיב של קובץ הפעלה. לחלופין, אפשר להגדיר בה את הערך ${chrome} כדי לזהות באופן אוטומטי את מיקום ההתקנה של Chrome.</translation>
 <translation id="930930237275114205">הגדר את ספריית נתוני המשתמש של <ph name="PRODUCT_FRAME_NAME" /></translation>
diff --git a/components/policy/resources/policy_templates_ko.xtb b/components/policy/resources/policy_templates_ko.xtb
index 8423487..8b3ece2 100644
--- a/components/policy/resources/policy_templates_ko.xtb
+++ b/components/policy/resources/policy_templates_ko.xtb
@@ -1709,7 +1709,7 @@
 
       참고: 현재 로그인 화면이 표시되고 있거나 키오스크 앱 세션이 진행 중인 경우에 한해 자동 재부팅이 사용하도록 설정됩니다. 이후에는 이 내용이 변경되어 특정 유형의 세션이 진행 중인지 여부와 관계 없이 정책이 항상 적용됩니다.
 
-      정책 값은 초 단위로 지정되어야 하며 최소값은 3600(1시간)으로 고정되어 있습니다.</translation>
+      정책 값은 초 단위로 지정되어야 하며 최솟값은 3600(1시간)으로 고정되어 있습니다.</translation>
 <translation id="4203879074082863035">허용 목록에 있는 프린터만 사용자에게 표시됨</translation>
 <translation id="420512303455129789">호스트 이름을 호스트에 액세스를 허용(true) 또는 차단(false)할지 지정하는 부울 플래그에 매핑합니다.
 
@@ -1840,7 +1840,7 @@
 <translation id="449423975179525290"><ph name="PLUGIN_VM_NAME" /> 관련 정책을 설정합니다.</translation>
 <translation id="450537894712826981"><ph name="PRODUCT_NAME" />이(가) 캐시된 미디어 파일을 디스크에 저장할 때 사용하는 캐시 크기를 설정합니다.
 
-      이 정책을 설정하는 경우 <ph name="PRODUCT_NAME" />은(는) 사용자가 '--media-cache-size' 플래그를 지정했는지 여부에 관계없이 제공된 캐시 크기를 사용합니다. 이 정책에 지정된 값을 반드시 사용해야 하는 것은 아니며 캐싱 시스템에 추천되는 값입니다. 몇 MB 이하의 너무 작은 값은 적정한 최소값으로 반올림됩니다.
+      이 정책을 설정하는 경우 <ph name="PRODUCT_NAME" />은(는) 사용자가 '--media-cache-size' 플래그를 지정했는지 여부에 관계없이 제공된 캐시 크기를 사용합니다. 이 정책에 지정된 값을 반드시 사용해야 하는 것은 아니며 캐싱 시스템에 추천되는 값입니다. 몇 MB 이하의 너무 작은 값은 적정한 최솟값으로 반올림됩니다.
 
       이 정책 값이 0인 경우 기본 캐시 크기가 사용되지만 사용자가 변경할 수는 없습니다.
 
@@ -3399,7 +3399,7 @@
       이 정책을 숫자로 설정하면 Chrome에서 이 숫자만큼의 밀리초 동안 메시지가 표시된 후 대체 브라우저가 실행됩니다.</translation>
 <translation id="7593523670408385997"><ph name="PRODUCT_NAME" />이(가) 캐시된 미디어 파일을 디스크에 저장할 때 사용하는 캐시 크기를 설정합니다.
 
-      이 정책을 설정하는 경우 <ph name="PRODUCT_NAME" />은(는) 사용자가 '--disk-cache-size' 플래그를 지정했는지 여부에 관계없이 제공된 캐시 크기를 사용합니다. 이 정책에 지정된 값을 반드시 사용해야 하는 것은 아니지만 캐싱 시스템에 추천되는 값입니다. 몇 MB 이하의 너무 작은 값은 적정한 최소값으로 반올림됩니다.
+      이 정책을 설정하는 경우 <ph name="PRODUCT_NAME" />은(는) 사용자가 '--disk-cache-size' 플래그를 지정했는지 여부에 관계없이 제공된 캐시 크기를 사용합니다. 이 정책에 지정된 값을 반드시 사용해야 하는 것은 아니지만 캐싱 시스템에 추천되는 값입니다. 몇 MB 이하의 너무 작은 값은 적정한 최솟값으로 반올림됩니다.
 
       이 정책 값이 0인 경우 기본 캐시 크기가 사용되지만 사용자가 변경할 수는 없습니다.
 
diff --git a/components/policy/resources/policy_templates_no.xtb b/components/policy/resources/policy_templates_no.xtb
index 3c9a2e1..b6e662a4 100644
--- a/components/policy/resources/policy_templates_no.xtb
+++ b/components/policy/resources/policy_templates_no.xtb
@@ -1309,7 +1309,7 @@
           Hvis denne innstillingen er slått av, kan ikke brukerne lagre nye passord. De kan likevel bruke passord som er lagret tidligere.
 
           Hvis denne regelen er slått av eller på, kan ikke brukerne endre eller overstyre den i <ph name="PRODUCT_NAME" />. Hvis regelen ikke er angitt, er lagring av passord tillatt (men brukerne kan slå det av).</translation>
-<translation id="3496296378755072552">Passordbehandling</translation>
+<translation id="3496296378755072552">Passordlagring</translation>
 <translation id="3500732098526756068">Lar deg kontrollere utløsingen av advarsler for passordbeskyttelse. Med passordbeskyttelse varsles brukere ved gjenbruk av beskyttede passord på potensielt mistenkelige nettsteder.
 
       Du kan bruke reglene «PasswordProtectionLoginURLs» og «PasswordProtectionChangePasswordURL» til å konfigurere hvilke passord som skal beskyttes.
@@ -1782,7 +1782,7 @@
 <translation id="445270821089253489">Kontrollerer hva slags bruker- og enhetsinformasjon som rapporteres.</translation>
 <translation id="4454820008017317557">Vis verktøylinjeikonet for <ph name="PRODUCT_NAME" /></translation>
 <translation id="4467952432486360968">Blokkér tredjeparts informasjonskapsler</translation>
-<translation id="4474167089968829729">Slå på lagring av passord i passordbehandleren</translation>
+<translation id="4474167089968829729">Slå på lagring av passord i passordlagringsfunksjonen</translation>
 <translation id="4476769083125004742">Hvis denne regelen er angitt som <ph name="BLOCK_GEOLOCATION_SETTING" />, kan ikke Android-apper bruke posisjonsinformasjon. Hvis du angir en annen verdi for denne regelen, eller hvis du ikke angir noen ting, blir brukeren bedt om samtykke når Android-apper prøver å få tilgang til posisjonsinformasjon.</translation>
 <translation id="4480694116501920047">Tving Sikkert Søk</translation>
 <translation id="4482640907922304445">Viser Startside-knappen i verktøylinjen til <ph name="PRODUCT_NAME" />.
@@ -2049,7 +2049,7 @@
 Hvis denne regelen er angitt, blir hvert element behandlet som en regel – på samme måte som regelen <ph name="URL_LIST_POLICY_NAME" />. Men logikken er reversert: Samsvarende regler åpnes ikke i en alternativ nettleser.
 
 I motsetning til <ph name="URL_LIST_POLICY_NAME" /> gjelder denne regelen begge veier. Det betyr at når Internet Explorer-tilleggsprogrammet er installert og aktivert, kontrollerer det også om <ph name="IE_PRODUCT_NAME" /> skal åpne disse nettadressene i <ph name="PRODUCT_NAME" />.</translation>
-<translation id="5124368997194894978">Slå på oppstart ved strømtilkobling (vekselstrøm)</translation>
+<translation id="5124368997194894978">Slå på oppstart ved tilkobling til strømnettet</translation>
 <translation id="5130288486815037971">Definerer om RC4-chifferserier i TLS er slått på</translation>
 <translation id="5141670636904227950">Angi standard skjermforstørrelsestype som er aktivert på påloggingssiden</translation>
 <translation id="5142301680741828703">Alltid gjengi følgende nettadressemønstre i <ph name="PRODUCT_FRAME_NAME" /></translation>
@@ -2849,7 +2849,7 @@
 <translation id="6641981670621198190">Deaktiver støtte for programmeringsgrensesnitt for 3D-grafikk</translation>
 <translation id="6646056064606561298">Slå på regelen for administrering av oppstart ved strømtilkobling.
 
-          Med oppstart ved strømtilkobling får systemet muligheten til å starte opp automatisk fra AV/hvilemodus når enheten kobles til et strømuttak.
+          Med oppstart ved strømtilkobling får systemet muligheten til å starte opp automatisk fra AV/hvilemodus når enheten kobles til strømnettet.
 
           Hvis denne regelen er satt til «true» (sann), er oppstart ved strømtilkobling alltid slått på hvis enheten støtter det.
 
@@ -3139,7 +3139,7 @@
 
       Hvis denne regelen er angitt som en filbane, brukes den filen som en kjørbar
       fil.</translation>
-<translation id="7167436895080860385">Gi brukere tillatelse til å se passord i passordbehandlingen (avviklet)</translation>
+<translation id="7167436895080860385">Gi brukere tillatelse til å se passord i passordlagringsfunksjonen (avviklet)</translation>
 <translation id="7173856672248996428">Midlertidig profil</translation>
 <translation id="717630378807352957">Tillat alle skrivere fra konfigurasjonsfilen.</translation>
 <translation id="7176721759719212761">Angir om det er tillatt med oppvekkingslåser. Utvidelser kan be om skjermoppvekkingslåser via Power Management Extension API. ARC-apper kan også be om dem.
@@ -3635,7 +3635,7 @@
 
       Hvis denne retningslinjen ikke angis, er det ingen unntak fra retningslinjen URLBlacklist.</translation>
 <translation id="8176035528522326671">Tillat at bedriftsbrukeren bare er primær flerprofilbruker (standardatferd for bedriftsadministrerte brukere)</translation>
-<translation id="8214600119442850823">Konfigurerer passordbehandlingen.</translation>
+<translation id="8214600119442850823">Konfigurerer passordlagring.</translation>
 <translation id="8217516105848565518">Denne regelen er avviklet. Bruk RemoteAccessHostDomainList i stedet.</translation>
 <translation id="8244525275280476362">Maksimal innlastingsforsinkelse etter ugyldiggjøring av en innstilling</translation>
 <translation id="8256688113167012935">Kontrollerer hvilket kontonavn <ph name="PRODUCT_OS_NAME" /> viser på påloggingsskjermen for enhetens tilhørende lokale konto.
diff --git a/components/policy/resources/policy_templates_ta.xtb b/components/policy/resources/policy_templates_ta.xtb
index 92ad470e..294e305a 100644
--- a/components/policy/resources/policy_templates_ta.xtb
+++ b/components/policy/resources/policy_templates_ta.xtb
@@ -51,6 +51,7 @@
 <translation id="1062011392452772310">சாதனத்திற்கான தொலைநிலைச் சான்றொப்பத்தை இயக்கு</translation>
 <translation id="1062407476771304334">மாற்றியமை</translation>
 <translation id="1079801999187584280">டெவெலப்பர் கருவிகளின் பயன்பாட்டை அனுமதிக்காதே</translation>
+<translation id="1087437665304381368">இந்தக் கொள்கை <ph name="PRODUCT_OS_NAME" /> டெவலப்பர் பயன்முறையை மட்டும் கட்டுப்படுத்தும். Android டெவெலப்பர் விருப்பங்களுக்கான அணுகலைத் தடுக்க விரும்பினால் <ph name="DEVELOPER_TOOLS_DISABLED_POLICY_NAME" /> கொள்கையை அமைக்க வேண்டும்.</translation>
 <translation id="1093082332347834239">இந்த அமைப்பை இயக்கினால், தொலைநிலை உதவி ஹோஸ்ட்டானது <ph name="UIACCESS_PERMISSION_NAME" /> அனுமதிகளைக் கொண்ட செயல்முறையில் இயங்கும்.  இது பயனரின் டெஸ்க்டாப்பில் உயர்நிலைச் சாளரங்களை அணுக தொலைநிலைப் பயனர்களை அனுமதிக்கும்.
 
           இந்த அமைப்பு முடக்கப்பட்டாலோ உள்ளமைக்கப்படவில்லை என்றாலோ, தொலைநிலை உதவி ஹோஸ்ட்டானது பயனரின் சூழலிலேயே இயங்கும். தொலைநிலைப் பயனர்களால் டெஸ்க்டாப்பில் உயர்நிலைச் சாளரங்களை அணுக முடியாது.</translation>
@@ -75,6 +76,14 @@
       இந்தக் கொள்கையை அமைக்காமல் விட்டால், தற்காலிகமாகச் சேமிக்கப்பட்ட GPOகளை 25 மணிநேரம் வரை மீண்டும் பயன்படுத்தலாம்.
 
       இந்தக் கொள்கையின் மதிப்பை 0 என அமைத்தால், GPOவை தற்காலிக நினைவகத்தில் சேமிப்பது முடக்கப்படும். GPOகள் மாறவில்லை என்றாலும் கூட, ஒவ்வொரு முறை அவை மீண்டும் பதிவிறக்கப்படும் என்பதால் சேவையத்தின் பணியழுத்தம் அதிகரிக்கும் என்பதைக் கவனத்தில் கொள்ளவும்.</translation>
+<translation id="1117462881884985156">இங்கே கொடுக்கப்பட்டுள்ள ஹோஸ்ட்களின் பட்டியலுக்கு <ph name="PRODUCT_NAME" /> எந்தவொரு ப்ராக்ஸியையும் கடந்துசெல்லும்.
+
+          'ப்ராக்ஸி சேவையக அமைப்புகளை எவ்வாறு குறிப்பது எனத் தேர்வுசெய்க' என்பதில் கைமுறை ப்ராக்ஸி அமைப்புகளை நீங்கள் தேர்ந்தெடுத்திருந்தாலும் <ph name="PROXY_SETTINGS_POLICY_NAME" /> கொள்கை குறிப்பிடப்படவில்லை என்றாலும் மட்டுமே இந்தக் கொள்கை செயல்படுத்தப்படும்.
+
+          ப்ராக்ஸி கொள்கைகளை அமைப்பதற்கு வேறு ஏதேனும் பயன்முறையைத் தேர்ந்தெடுத்திருந்தால் இந்தக் கொள்கையை அமைக்க வேண்டாம்.
+
+          இன்னும் விரிவான எடுத்துக்காட்டுகளுக்கு இந்த URLலுக்குச் செல்லவும்:
+          <ph name="PROXY_HELP_URL" />.</translation>
 <translation id="1117535567637097036">Android இன்டென்ட்களைப் பயன்படுத்தும் போது, இந்தக் கொள்கை மூலம் அமைத்த நெறிமுறை ஹேண்ட்லர்கள் பயன்படுத்தப்படாது.</translation>
 <translation id="1118093128235245168">இணைக்கப்பட்டுள்ள USB சாதன அணுகலைக் கொடுக்குமாறு பயனரிடம் கேட்கத் தளங்களை அனுமதிக்கும்</translation>
 <translation id="1128903365609589950">தற்காலிகமாகச் சேமிக்கப்பட்ட கோப்புகளை டிஸ்க்கில் சேமிப்பதற்காக <ph name="PRODUCT_NAME" /> பயன்படுத்தும் கோப்பகத்தை உள்ளமைக்கும்.
@@ -115,6 +124,10 @@
           இந்தக் கொள்கையை அமைக்கவில்லை எனில், ஒட்டுமொத்த இயல்பு மதிப்பு எல்லாத் தளங்களுக்கும் பயன்படுத்தப்படும். அப்படி அமைக்கப்படும் மதிப்பு, 'DefaultImagesSetting' கொள்கையாகவோ (ஏற்கனவே அமைக்கப்பட்டிருந்தால்) அல்லது பயனரின் தனிப்பட்ட உள்ளமைவாகவோ இருக்கும்.
 
           குறிப்பு: இந்தக் கொள்கையானது முன்பு தவறுதலாக Android இல் இயக்கப்பட்டது. ஆனால், இந்தச் செயல்பாடு Android இல் எப்போதுமே முழுவதுமாக ஆதரிக்கப்படவில்லை.</translation>
+<translation id="1194005076170619046">இயக்கப்பட்டால், அமர்வு செயலில் இருக்கும்போதும் திரை பூட்டப்படாமல் இருக்கும்போதும், சிஸ்டம் ட்ரேயில் ஒரு பெரிய, சிவப்பு வண்ண 'வெளியேறு' பட்டன் தோன்றும்.
+
+      முடக்கப்பட்டாலோ குறிப்பிடப்படவில்லை என்றாலோ, சிஸ்டம் ட்ரேயில் எந்தவொரு பெரிய, சிவப்பு வண்ண 'வெளியேறு' பட்டனும் தோன்றாது.</translation>
+<translation id="1197437816436565375">ப்ராக்ஸியைப் பயன்படுத்தும்படி Android ஆப்ஸைக் கட்டாயப்படுத்த முடியாது. Android ஆப்ஸுக்கு ப்ராக்ஸி அமைப்புகளின் துணைத்தொகுப்பு கிடைக்கும்படி செய்யப்பட்டுள்ளது. இவை தானாகவே முக்கியத்துவம் அளிப்பதைத் தேர்வுசெய்து கொள்ளும். மேலும் விவரங்களுக்கு <ph name="PROXY_MODE_POLICY_NAME" /> கொள்கையைப் பார்க்கவும்.</translation>
 <translation id="1198465924256827162">சாதன நிலையின் பதிவேற்றங்கள் அனுப்பப்படும் கால இடைவெளி, மில்லிவினாடிகளில் குறிப்பிடப்படும்.
       
 இந்தக் கொள்கை அமைக்கப்படாவிட்டால், இயல்பான கால இடைவெளி 3 மணிநேரமாகும். குறைந்தபட்சமாக அனுமதிக்கப்பட்ட கால இடைவெளி 60 வினாடிகளாகும்.</translation>
@@ -155,6 +168,13 @@
 <translation id="1327466551276625742">ஆஃப்லைனில் இருக்கும்போது நெட்வொர்க் உள்ளமைவுத் தூண்டலை இயக்கு</translation>
 <translation id="1330145147221172764">ஸ்கிரீன் கீபோர்ட் இயக்கு</translation>
 <translation id="13356285923490863">கொள்கைப் பெயர்</translation>
+<translation id="1347198119056266798">இந்தக் கொள்கை தடுக்கப்பட்டிருப்பதால் இதற்குப் பதிலாக <ph name="FORCE_GOOGLE_SAFE_SEARCH_POLICY_NAME" />, <ph name="FORCE_YOUTUBE_RESTRICT_POLICY_NAME" /> ஆகிய கொள்கைகளைப் பயன்படுத்தவும். <ph name="FORCE_GOOGLE_SAFE_SEARCH_POLICY_NAME" />, <ph name="FORCE_YOUTUBE_RESTRICT_POLICY_NAME" /> அல்லது (தடுக்கப்பட்ட) <ph name="FORCE_YOUTUBE_SAFETY_MODE_POLICY_NAME" /> கொள்கைகள் அமைக்கப்பட்டால் இந்தக் கொள்கை புறக்கணிக்கப்படும்.
+
+      பாதுகாப்பான தேடலைச் செயலில் வைத்துச் செயலாக்கப்படும்படி Google இணையத் தேடலில் உள்ள வினவல்களைக் கட்டாயப்படுத்தும், பயனர்கள் இந்த அமைப்பை மாற்றுவதைத் தடுக்கும். இந்த அமைப்பு YouTubeல் சராசரிக் கட்டுப்பாட்டுப் பயன்முறையையும் கட்டாயப்படுத்தும் .
+
+      இந்த அமைப்பை இயக்கினால் Google தேடலில் 'பாதுகாப்பான தேடலும்' YouTubeல் 'சராசரிக் கட்டுப்பாட்டுப் பயன்முறையும்' எப்போதும் செயலில் இருக்கும்.
+
+      இந்த அமைப்பை முடக்கினாலோ மதிப்பை அமைக்கவில்லை என்றாலோ Google தேடலில் 'பாதுகாப்பான தேடலும்' YouTubeல் 'சராசரிக் கட்டுப்பாட்டுப் பயன்முறையும்' செயல்படுத்தப்படாது.</translation>
 <translation id="1352174694615491349">கிளையண்ட் சான்றிதழ்கள் பயன்பாட்டில் இருக்கும்போது, இந்தக் கொள்கையானது HTTP/2 இணைப்பு ஒன்றிணைதலை அனுமதிக்கும். ஒன்றிணைப்பதற்காக, சாத்தியமுள்ள புதிய இணைப்பின் ஹோஸ்ட்பெயர், தற்போதுள்ள இணைப்பின் ஹோஸ்ட்பெயர் ஆகிய இரண்டுமே இந்தக் கொள்கை விளக்கும் ஒன்று அல்லது பல பேட்டர்ன்களுடன் பொருந்த வேண்டும். இந்தக் கொள்கையானது URLBlacklist வடிப்பான் வடிவமைப்பைப் பயன்படுத்துகின்ற ஹோஸ்ட்டுகளின் ஒரு பட்டியலாகும்: "example.com" ஆனது "example.com" மற்றும் அனைத்து உள்களங்களுடன் பொருந்துகிறது (எ.கா. "sub.example.com"), அதே சமயத்தில் ".example.net" ஆனது "example.net" உடன் முழுதாகப் பொருந்துகிறது.
 
       சூழல் அங்கீகாரத்தைப் பயனர் வெளிப்படையாக அங்கீகரிக்காவிட்டால் கூட, அது அனைத்துக் கோரிக்கைகளுக்கும் அனுப்பப்படும் என்பதால், கிளையண்ட் சான்றிதழ்களைப் பயன்படுத்துகின்ற இணைப்புகள் வழியாக வெவ்வேறு ஹோஸ்ட்டுகளுக்கான கோரிக்கைகளை ஒன்றிணைப்பது பாதுகாப்பு மற்றும் தனியுரிமைச் சிக்கல்களை உருவாக்கலாம். இந்தக் கொள்கை தற்காலிகமானது, எதிர்கால வெளியீட்டில் அகற்றப்படும். https://crbug.com/855690ஐப் பார்க்கவும்.
@@ -162,6 +182,11 @@
       கொள்கையை அமைக்காமல் விட்டால், கிளையண்ட் சான்றிதழ்களைப் பயன்படுத்துகின்ற இணைப்புகளில் எந்தவொரு இணைப்பு ஒன்றிணைதலையும் அனுமதிக்காத இயல்பு நடத்தை பயன்படுத்தப்படும்.</translation>
 <translation id="1353966721814789986">தொடக்கப் பக்கங்கள்</translation>
 <translation id="1354424209129232709">அதிகபட்சம்:</translation>
+<translation id="1354452738176731363">இந்தக் கொள்கை 'தவறு' என அமைக்கப்பட்டால் பயனர் உள்நுழைந்திருக்கும் போது ஆடியோ வெளியீடு கிடைக்காது.
+
+      இந்தக் கொள்கை உள்ளமைந்த ஸ்பீக்கர்களை மட்டுமின்றி எல்லா வகையான ஆடியோ அவுட்புட்களிலும் மாற்றத்தை ஏற்படுத்தும். ஆடியோ அணுகல்தன்மை அம்சங்களும் இந்தக் கொள்கையால் தடுக்கப்படும். பயனருக்கு ஸ்கிரீன் ரீடர் தேவைப்படும்பட்சத்தில் இந்தக் கொள்கையை இயக்க வேண்டாம்.
+
+      இந்த அமைப்பு 'சரி' என அமைக்கப்பட்டாலோ உள்ளமைக்கப்படவில்லை என்றாலோ ஆதரிக்கப்படும் எல்லா ஆடியோ அவுட்புட்களையும் பயனர்கள் தங்களது சாதனத்தில் பயன்படுத்த முடியும்.</translation>
 <translation id="1359553908012294236">இந்தக் கொள்கை true என அமைக்கப்பட்டிருந்தாலோ அல்லது உள்ளமைக்கப்படாமல் இருந்தாலோ, விருந்தினர் உள்நுழைவுகளை <ph name="PRODUCT_NAME" /> இயக்கும். விருந்தினர் உள்நுழைவுகள் என்பவை அனைத்துச் சாளரங்களும் மறைநிலைப் பயன்முறையில் இருக்கும் <ph name="PRODUCT_NAME" /> சுயவிவரங்களாகும்.
 
       இந்தக் கொள்கை false என அமைக்கப்பட்டால், விருந்தினர் சுயவிவரங்களைத் தொடங்க <ph name="PRODUCT_NAME" /> அனுமதிக்காது.</translation>
@@ -206,10 +231,35 @@
       ’பாதுகாப்பு உலாவல்’ குறித்த மேலும் தகவலுக்கு, https://developers.google.com/safe-browsing என்னும் இணைப்பைப் பார்க்கவும்.
 
       <ph name="MS_AD_NAME" /> டொமைனுடன் இணைக்கப்பட்ட Windows நேர்வுகளின்போதும் சாதன நிர்வாகத்திற்காகப் பதிவுசெய்யப்பட்ட Windows 10 Pro அல்லது Enterprise நேர்வுகளின்போதும் மட்டுமே இந்தக் கொள்கை பயன்படுத்தப்படும்.</translation>
+<translation id="1432194160771348078">
+      உள்நுழைவுப் பக்கத்தில் சத்தமின்றி, பயனருக்கு அறிவிக்காமல் நிறுவப்படும் ஆப்ஸ் பட்டியல்களைக் குறிக்கும்.
+      இவற்றை நிறுவல் நீக்க முடியாது.
+      ஆப்ஸ் கோரிய அனைத்து அனுமதிகளும் பயனருக்கு அறிவிக்காமல்
+      ஆப்ஸின் எதிர்காலப் பதிப்புகள் கோரும் கூடுதல்
+      அனுமதிகளையும் சேர்த்து மறைமுகமாக வழங்கப்படும்.
+
+      பாதுகாப்பு மற்றும் தனியுரிமைக் காரணங்களுக்காக இந்தக் கொள்கையைப் பயன்படுத்தி நீட்டிப்புகளை நிறுவ அனுமதியில்லை என்பதை நினைவில் கொள்ளவும். அதுமட்டுமின்றி, நிலையான வழியில் உள்ள சாதனங்கள் <ph name="PRODUCT_NAME" />க்குள் தொகுக்கப்பட்ட ஏற்புப் பட்டியலுக்குரிய ஆப்ஸை மட்டுமே நிறுவும்.
+
+      இதற்கு முன் கட்டாயமாக நிறுவப்பட்ட ஆப்ஸ் இந்தப் பட்டியலில் இருந்து அகற்றப்பட்டால், அது <ph name="PRODUCT_NAME" /> மூலம் தானாகவே நிறுவல் நீக்கப்படும்.
+
+      கொள்கையின் பட்டியலில் உள்ள ஒவ்வொன்றும் அரைப்புள்ளியால் (<ph name="SEMICOLON" />) பிரிக்கப்பட்ட நீட்டிப்பு ஐடி, "புதுப்பிப்பு" URL ஆகியவற்றைக் கொண்ட வார்த்தையாகும். நீட்டிப்பு ஐடி என்பது டெவலப்பர் பயன்முறையில் <ph name="CHROME_EXTENSIONS_LINK" />ல் கிடைக்கும் 32 எழுத்துகளைக் கொண்ட வார்த்தையாகும். <ph name="LINK_TO_EXTENSION_DOC1" />ல் விவரிக்கப்பட்டுள்ளது போல "புதுப்பிப்பு" URL ஆனது புதுப்பிப்பு மெனிஃபெஸ்ட் XML ஆவணத்தைக் குறிக்க வேண்டும். கொள்கையில் அமைக்கப்படும் "புதுப்பிப்பு" URL தொடக்க நிறுவலுக்கு மட்டுமே பயன்படுத்தப்படும் என்பதை நினைவில் கொள்ளவும்; நீட்டிப்பின் அடுத்தடுத்த புதுப்பிப்புகள் நீட்டிப்பின் மெனிஃபெஸ்ட்டில் குறிப்பிடப்படும் புதுப்பிப்பு URLலைப் பயன்படுத்தும்.
+
+      எடுத்துக்காட்டாக, <ph name="EXTENSION_POLICY_EXAMPLE" /> <ph name="EXTENSION_POLICY_EXAMPLE_EXTENSION_NAME" /> ஆப்ஸை வழக்கமான Chrome இணைய அங்காடி "புதுப்பிப்பு" URLலிலிருந்து நிறுவும். ஹோஸ்ட் செய்யும் நீட்டிப்புகள் குறித்த கூடுதல் தகவலுக்கு இதைப் பார்க்கவும்: <ph name="LINK_TO_EXTENSION_DOC2" />.</translation>
 <translation id="1435659902881071157">சாதன-நிலை நெட்வொர்க் உள்ளமைவு</translation>
 <translation id="1438739959477268107">இயல்புநிலை விசை உருவாக்க அமைப்பு</translation>
 <translation id="1454846751303307294">JavaScript ஐ இயக்க அனுமதிக்காத, தளங்களைக் குறிப்பிடும் url முறைகளின் பட்டியலை அமைக்க உங்களை அனுமதிக்கிறது. இந்தக் கொள்கையை அமைக்காமல் விட்டால், ஒட்டுமொத்த இயல்புநிலை மதிப்பு, 'DefaultJavaScriptSetting' கொள்கை அமைக்கப்பட்டால், அதிலிருந்து அல்லது மற்றொரு வகையில் பயனரின் தனிப்பட்ட உள்ளமைவிலிருந்து எல்லா தளங்களுக்கும் பயன்படுத்தப்படும்.</translation>
 <translation id="1456822151187621582">Windows (<ph name="PRODUCT_OS_NAME" /> கிளையன்ட்டுகள்):</translation>
+<translation id="1458547592473993238">இந்தக் கொள்கை தடுக்கப்பட்டுள்ளது. ஃபிளாஷ் செருகுநிரலின் கிடைக்கும்தன்மையைக் கட்டுப்படுத்த <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME" />ஐப் பயன்படுத்தவும், மேலும் PDF கோப்புகளைத் திறப்பதற்கு ஒருங்கிணைந்த PDF வியூவர் பயன்படுத்தப்பட வேண்டுமா என்பதைக் கட்டுப்படுத்த <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME" />ஐப் பயன்படுத்தவும்.
+
+      <ph name="PRODUCT_NAME" />ல் முடக்கப்பட்டுள்ள செருகுநிரல்களின் பட்டியலைக் குறிக்கும், பயனர்கள் இந்த அமைப்பை மாற்றுவதிலிருந்து தடுக்கும்.
+
+      வைல்டுகார்டு எழுத்துகளான '*', '?' ஆகியவை தன்னிச்சையான எழுத்துகளின் வரிசைமுறைகளைப் பொருத்தப் பயன்படுத்தப்படலாம். '?' என்பது விருப்பத்திற்குரிய ஒற்றை எழுத்தைக் குறிக்கும் அதேநேரம் '*' என்பது தன்னிச்சையான எழுத்துகளின் எண்ணிக்கையைப் பொருத்தும். அதாவது பூஜ்ஜியம் அல்லது ஓர் எழுத்தைப் பொருத்தும். விடுபடு எழுத்து '\' என்பதால் உண்மையான '*', '?' அல்லது '\' எழுத்துகளைப் பொருத்த அவற்றுக்கு முன் '\' எழுத்தைச் சேர்க்கலாம்.
+
+      இந்த அமைப்பை இயக்கினால் குறிப்பிடப்படும் செருகுநிரல்களின் பட்டியல் <ph name="PRODUCT_NAME" />ல் பயன்படுத்தப்படாது. செருகுநிரல்கள் 'about:plugins' என்பதில் முடக்கப்படும், பயனர்கள் அவற்றை இயக்க முடியாது.
+
+      இந்தக் கொள்கையை EnabledPlugins, DisabledPluginsExceptions ஆகியவை மாற்றியமைக்கலாம் என்பதை நினைவில் கொள்ளவும்.
+
+      இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் ஹார்ட் கோடிங் செய்யப்பட்ட இணக்கமற்ற, காலாவதியான அல்லது ஆபத்தான செருகுநிரல்களைத் தவிர, சிஸ்டத்தில் நிறுவப்பட்டுள்ள எந்தச் செருகுநிரல்களையும் பயனர் பயன்படுத்தலாம்.</translation>
 <translation id="1464848559468748897"><ph name="PRODUCT_OS_NAME" /> சாதனங்களில், பல சுயவிவர அமர்வில் உள்ள பயனர் நடவடிக்கையைக் கட்டுப்படுத்துகிறது
 
       இந்தக் கொள்கை 'MultiProfileUserBehaviorUnrestricted' என அமைக்கப்பட்டால், பயனர் பலசுயவிவர அமர்வில் உள்ள முதன்மை அல்லது துணைப் பயனராக இருக்கலாம்.
@@ -279,6 +329,13 @@
 <translation id="1599424828227887013">Android சாதனங்களில், குறிப்பிட்ட தளங்களில் தளத்தைத் தனிப்படுத்தும் அம்சத்தை இயக்கு</translation>
 <translation id="1608755754295374538">அறிவுறுத்தல் இல்லாமல் ஆடியோ பிடிப்புச் சாதனங்களுக்கு அணுகல் உள்ள URLகள்</translation>
 <translation id="1615221548356595305">கிளையண்ட் சான்றிதழ்களைப் பயன்படுத்தும்போதும் இந்த ஹோஸ்ட்டுகளுக்கான HTTP/2 இணைப்புகளின் ஒன்றிணைதலை அனுமதிக்கவும்.</translation>
+<translation id="1615855314789673708">wilco DTC (கண்டறிதல் மற்றும் டெலிமெட்ரி கட்டுப்படுத்தி) உள்ளமைவை வழங்கும்.
+
+      இந்தக் கொள்கை wilco DTC உள்ளமைவை வழங்க அனுமதிக்கும். குறிப்பிட்ட சாதனத்தில் wilco DTC இருந்தால் மற்றும் கொள்கையால் அனுமதிக்கப்பட்டால் இதைப் பயன்படுத்த அனுமதிக்கப்படும். உள்ளமைவு 1 மெ.பை. (1000000 பைட்டுகள்) அளவைத் தாண்டக்கூடாது, மேலும் JSON வடிவத்தில் என்கோடிங் செய்யப்பட்டிருக்க வேண்டும். அதை நிர்வகிப்பது wilco DTCயின் பொறுப்பாகும். பதிவிறக்கத்தின் துல்லியத்தைச் சரிபார்க்க கிரிப்டோகிராஃபிக் ஹேஷ் பயன்படுத்தப்படும்.
+
+      உள்ளமைவு பதிவிறக்கப்பட்டு, தற்காலிகமாகச் சேமிக்கப்படும். URL அல்லது ஹேஷ் மாறும்போதெல்லாம் இது மீண்டும் பதிவிறக்கப்படும்.
+
+      இந்தக் கொள்கையை அமைத்தால் பயனரால் இதை மாற்றவோ மேலெழுதவோ முடியாது.</translation>
 <translation id="1617235075406854669">உலாவி மற்றும் பதிவிறக்க வரலாற்றின் நீக்கத்தை இயக்கு</translation>
 <translation id="163200210584085447">இந்தப் பட்டியலில் உள்ள வடிவங்கள்,
       கோரப்படும் URL இன் பாதுகாப்பு மூலத்துடன் ஒப்பிடப்படும்.  ஏதேனும் பொருத்தம் இருந்தால், வீடியோ
@@ -286,6 +343,11 @@
       எனில், தானாகவே அணுகல் நிராகரிக்கப்படும்.  சிறப்புக் குறி வடிவங்கள்
       அனுமதிக்கப்படாது.</translation>
 <translation id="1634989431648355062">இந்தத் தளங்களில் <ph name="FLASH_PLUGIN_NAME" /> செருகுநிரலை அனுமதி</translation>
+<translation id="1653229475925941921">இந்தக் கொள்கை அமைக்கப்பட்டால் இயக்கப்படும் 'திரைப் பெரிதாக்கி' வகையைக் கட்டுப்படுத்தும். கொள்கை 'எதுவுமில்லை' என அமைக்கப்பட்டால் 'திரைப் பெரிதாக்கி' முடக்கப்படும்.
+
+          இந்தக் கொள்கையை அமைத்தால் பயனரால் இதை மாற்றவோ மேலெழுதவோ முடியாது.
+
+          இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் தொடக்கத்தில் 'திரைப் பெரிதாக்கி' முடக்கப்படும், ஆனால் எந்த நேரத்திலும் பயனர்கள் அதை இயக்கலாம்.</translation>
 <translation id="1655229863189977773">வட்டு தற்காலிக சேமிப்பு அளவை பைட்களில் அமை</translation>
 <translation id="166427968280387991">ப்ராக்ஸி சேவையகம்</translation>
 <translation id="1668836044817793277"><ph name="PRODUCT_OS_NAME" /> பதிப்பைக் கட்டுப்படுத்துவதற்கு, தானாகவே உடனடியாகத் துவங்கும் கியோஸ்க் ஆப்ஸை அனுமதிப்பது தொடர்பான கொள்கை.
@@ -299,6 +361,23 @@
       எச்சரிக்கை: <ph name="PRODUCT_OS_NAME" /> பதிப்பின் கட்டுப்பாட்டை கியோஸ்க் ஆப்ஸுக்கு வழங்க வேண்டாம் எனப் பரிந்துரைக்கிறோம். இது மென்பொருள் புதுப்பிப்புகளையும் முக்கியமான பாதுகாப்புத் திருத்தங்களையும் பெறுவதிலிருந்து சாதனத்தைத் தடுக்கக்கூடும். <ph name="PRODUCT_OS_NAME" /> பதிப்பின் கட்டுப்பாட்டை வேறு ஆப்ஸிற்கு வழங்கினால், பயனர்களுக்கு சிக்கல்கள் ஏற்படலாம்.</translation>
 <translation id="1675002386741412210">இவற்றில் ஆதரிக்கப்படுகிறது:</translation>
 <translation id="1689963000958717134"><ph name="PRODUCT_OS_NAME" /> சாதனத்தைப் பயன்படுத்தும் அனைவருக்கும் நெட்வொர்க் உள்ளமைவைக் கொடுக்க அனுமதிக்கிறது. இந்த நெட்வொர்க் உள்ளமைவு <ph name="ONC_SPEC_URL" /> இல் விளக்கப்பட்டுள்ளபடி திறந்த நெட்வொர்க் உள்ளமைவு வடிவத்தால் வரையறுக்கப்பட்ட JSON-வடிவமைப்புத் தொடராகும்</translation>
+<translation id="1704516734140344991"><ph name="TPM_FIRMWARE_UPDATE_TPM" /> நிலைபொருள் புதுப்பிப்புச் செயல்பாட்டின் இருப்புநிலையையும் செயல்படும் விதத்தையும் உள்ளமைக்கும்.
+
+      தனிப்பட்ட அமைப்புகளை JSON பண்புகளில் குறிப்பிடலாம்:
+
+      <ph name="TPM_FIRMWARE_UPDATE_SETTINGS_ALLOW_USER_INITIATED_POWERWASH" />: <ph name="TPM_FIRMWARE_UPDATE_SETTINGS_ALLOW_USER_INITIATED_POWERWASH_TRUE" /> என அமைத்தால் <ph name="TPM_FIRMWARE_UPDATE_TPM" /> நிலைபொருள் புதுப்பிப்பை நிறுவும்பொருட்டு
+பயனர்களால் பவர்வாஷ் செயல்முறையைத் தொடங்க இயலும்.
+
+      <ph name="TPM_FIRMWARE_UPDATE_SETTINGS_ALLOW_USER_INITIATED_PRESERVE_DEVICE_STATE" />: <ph name="TPM_FIRMWARE_UPDATE_SETTINGS_ALLOW_USER_INITIATED_PRESERVE_DEVICE_STATE_TRUE" /> என அமைத்தால் <ph name="TPM_FIRMWARE_UPDATE_TPM" /> நிலைபொருள் புதுப்பிப்புச் செயல்முறையைப் பயனர்களால் இயக்க இயலும். இது சாதனத்தின் (நிறுவனப் பதிவு உட்பட) முழு நிலையையும் அப்படியே வைத்திருக்கும், எனினும் பயனரின் தரவை இழக்கச்செய்யும். 68ம் பதிப்பில் இருந்து இந்தப் புதுப்பிப்புச் செயல்முறை கிடைக்கிறது.
+
+      <ph name="TPM_FIRMWARE_UPDATE_SETTINGS_AUTO_UPDATE_MODE" />: பாதுகாப்பு குறைவான <ph name="TPM_FIRMWARE_UPDATE_TPM" /> நிலைபொருளுக்கான தானியங்கு <ph name="TPM_FIRMWARE_UPDATE_TPM" /> நிலைபொருள் புதுப்பிப்புகள் எவ்வாறு நிறுவப்படவேண்டும் என்பதைக் கட்டுப்படுத்தும். அனைத்துச் செயல்முறைகளும் உள்ளூர் சாதன நிலையைப் பாதுகாக்கும்.
+        1 என அமைத்தாலோ எதுவும் அமைக்கவில்லை என்றாலோ TPM நிலைபொருள் புதுப்பிப்புகள் நிறுவப்படாது.
+        2 என அமைத்தால் <ph name="TPM_FIRMWARE_UPDATE_TPM" /> சாதனத்தை மறுபடி தொடங்கும்போது பயனரின் அனுமதியின்பேரில் நிலைபொருள் புதுப்பிக்கப்படும்.
+        3 என அமைத்தால் <ph name="TPM_FIRMWARE_UPDATE_TPM" /> சாதனத்தை மறுபடி தொடங்கும்போது நிலைபொருள் புதுப்பிக்கப்படும்.
+        4 என அமைத்தால் பயனர் பதிவுசெய்ததற்கும் உள்நுழைவதற்கும் இடைப்பட்ட நேரத்தில் <ph name="TPM_FIRMWARE_UPDATE_TPM" /> நிலைபொருள் புதுப்பிக்கப்படும்.
+        74ம் பதிப்பில் இருந்து இந்த விருப்பத்தைப் பயன்படுத்த முடியும்.
+
+      இந்தக் கொள்கையை அமைக்காவிட்டால் <ph name="TPM_FIRMWARE_UPDATE_TPM" /> நிலைபொருள் புதுப்பிப்பு செயல்படாது.</translation>
 <translation id="1708496595873025510">மாறுபாடுகளின் ஸீடை பெறுவதில் கட்டுப்பாட்டை அமைக்கவும்</translation>
 <translation id="1717817358640580294">இது அமைக்கப்படாவிட்டால், ‘Chrome கிளீன்அப்' தேவைற்ற மென்பொருளைக் கண்டறியும்போது, SafeBrowsingExtendedReportingEnabled அமைத்த கொள்கையின்படி ஸ்கேனைப் பற்றிய தரவுத்தகவலை Googleளுக்கு அனுப்பக்கூடும். அதன் பின்னர், தேவையற்ற மென்பொருளை நீக்க விரும்புகிறீர்களா எனப் பயனரிடம் 'Chrome கிளீன்அப்’ கேட்கும். எதிர்காலத்தில் தேவையற்ற மென்பொருளைக் கண்டறிய உதவுவதற்காக, கிளீன்அப்பின் முடிவுகளை Googleளுக்கு பயனர் பகிரலாம். இந்த முடிவுகளில், Chrome தனியுரிமை அறிக்கையில் விவரிக்கப்பட்டுள்ளபடி கோப்பு தரவுத்தகவல், தானாக நிறுவப்பட்ட நீட்டிப்புகள், பதிவக விசைகள் ஆகியவை இருக்கும்.
 
@@ -403,6 +482,9 @@
       இந்த அமைப்பு இயக்கப்பட்டால், கடவுச்சொல் மீண்டும் பயன்படுத்தப்படுவதைக் கண்டறிவதற்காக இந்த URLகளில் கடவுச்சொல்லின் கைரேகையைக் கடவுச்சொல் பாதுகாப்புச் சேவை பதிவுசெய்யும்.
       இந்த அமைப்பு முடக்கப்பட்டிருந்தாலோ அமைக்கப்படவில்லை என்றாலோ, https://accounts.google.com பக்கத்தில் மட்டும் கடவுச்சொல் கைரேகையை கடவுச்சொல் பாதுகாப்புச் சேவை பதிவுசெய்யும்.
       <ph name="MS_AD_NAME" /> டொமைனுடன் இணைக்கப்பட்ட Windows நேர்வுகளின்போதும் சாதன நிர்வாகத்திற்காகப் பதிவுசெய்யப்பட்ட Windows 10 Pro அல்லது Enterprise நேர்வுகளின்போதும் மட்டுமே இந்தக் கொள்கை பயன்படுத்தப்படும்.</translation>
+<translation id="1914840757300882918">இந்தக் கொள்கை அமைக்கப்பட்டால் RemoteAccessHostTokenValidationUrlலை அங்கீகரிக்க, கொடுக்கப்பட்ட வழங்குநர் CN உடன் கிளையன்ட் சான்றிதழை ஹோஸ்ட் பயன்படுத்தும். கிடைக்கக்கூடிய எந்தவொரு கிளையன்ட் சான்றிதழையும் பயன்படுத்த அதை '*' என அமைக்கவும்.
+
+          இந்த அம்சம் தற்போது சேவையகத் தரப்பில் முடக்கப்பட்டுள்ளது.</translation>
 <translation id="1919802376548418720">அனுமதிச் சான்றுகளைப் பகிர்ந்தளிக்க KDC கொள்கையைப் பயன்படுத்தும்.</translation>
 <translation id="1920046221095339924">சாதனத்தில், நிர்வகிக்கப்பட்ட அமர்வை அனுமதிக்கும்</translation>
 <translation id="1929709556673267855">சாதனங்களில் இணைக்கப்பட்டிருக்கும் நிறுவனப் பிரிண்டர்களுக்கு உள்ளமைவுகளை வழங்கும்.
@@ -449,6 +531,13 @@
 
       இந்தக் கொள்கை சரி என்பதற்கு அமைக்கப்பட்டிருந்தால், HTTP வழியாகத் தானியங்கு புதுப்பிப்பு தரவுகளைப் பதிவிறக்க <ph name="PRODUCT_OS_NAME" /> முயற்சிக்கும். கொள்கை தவறு என்பதற்கு அமைக்கப்பட்டிருந்தால் அல்லது அமைக்கப்படாமல் இருந்தால், தானியங்கு புதுப்பிப்பு தரவுகளைப் பதிவிறக்க HTTPS பயன்படுத்தப்படும்.</translation>
 <translation id="199764499252435679"><ph name="PRODUCT_NAME" /> இல் கூறுகள் தொடர்பான புதுப்பிப்புகளை இயக்கும்</translation>
+<translation id="1997994951395619441">இந்த அமைப்பை இயக்கினால் புக்மார்க் பட்டியை <ph name="PRODUCT_NAME" /> காட்டும்.
+
+      இந்த அமைப்பை முடக்கினால் பயனர்கள் இனிமேல் புக்மார்க் பட்டியைப் பார்க்க மாட்டார்கள்.
+
+      இந்த அமைப்பை இயக்கினாலோ முடக்கினாலோ பயனர்களால் இதை <ph name="PRODUCT_NAME" />ல் மாற்றவோ மேலெழுதவோ முடியாது.
+
+      இந்த அமைப்பு அமைக்கப்படவில்லை எனில் பயனர் இந்தச் செயல்பாட்டைப் பயன்படுத்த வேண்டுமா இல்லையா என்பதைத் தீர்மானிக்கலாம்.</translation>
 <translation id="2006530844219044261">ஆற்றல் நிர்வாகம்</translation>
 <translation id="2014757022750736514">பயனர்கள் தங்கள் கணக்குகளில் உள்நுழையும் உள்நுழைவுத் திரையின் நடத்தையைக் கட்டுப்படுத்துகிறது. இந்த அமைப்புகளில் யாரெல்லாம் உள்நுழையலாம், எந்த வகையான கணக்குகள் உள்நுழைய அனுமதிக்கப்படும், எந்த அங்கீகார முறைகளைப் பயன்படுத்துவது, பொது அணுகல்தன்மை, உள்ளீட்டு முறை, உள்ளூர் அமைப்புகள் போன்றவை அடங்கும்.</translation>
 <translation id="201557587962247231">சாதனத்தின் நிலை அறிக்கை ஏற்றப்படும் கால இடைவெளி</translation>
@@ -468,6 +557,7 @@
 
           இந்த அமைப்பு முடக்கப்பட்டால் கோப்புப் பரிமாற்றம் அனுமதிக்கப்படாது. இந்த அமைப்பு இயக்கப்பட்டிருந்தாலோ அமைக்கப்படாமல் இருந்தாலோ கோப்புப் பரிமாற்றம் அனுமதிக்கப்படும்.</translation>
 <translation id="2057317273526988987">URLகளின் பட்டியலுக்கு அணுகலை அனுமதிக்கும்</translation>
+<translation id="2061810934846663491">தொலைநிலை அணுகல் ஹோஸ்ட்களுக்காக அவசியமான டொமைன் பெயர்களை உள்ளமைக்கும்</translation>
 <translation id="206623763829450685"><ph name="PRODUCT_NAME" /> ஆதரிக்கும் HTTP அடையாளத் திட்டங்களைக் குறிப்பிடும்.
 
           'basic', 'digest', 'ntlm' மற்றும் 'negotiate' ஆகியவை சாத்தியமுள்ள மதிப்புகள் ஆகும். பலவகை மதிப்புகளைக் காற்புள்ளியைக் கொண்டு பிரிக்கவும்.
@@ -515,6 +605,13 @@
       இந்த அமைப்பை இயக்கினால், கேப்டிவ் போர்டல் அங்கீகாரப் பக்கங்கள் ஏதேனும் இருந்தால் (அதாவது <ph name="PRODUCT_NAME" /> வெற்றிகரமான இணைய இணைப்பைக் கண்டறியும் வரை கேப்டிவ் போர்டல் உள்நுழைவுப் பக்கம் தொடங்கி அனைத்து இணையப் பக்கங்களும்), அவை தனிச் சாளரத்தில் காண்பிக்கப்படும், தற்போதைய பயனருக்கான அனைத்துக் கொள்கை அமைப்புகளும் கட்டுப்பாடுகளும் புறக்கணிக்கப்படும்.
 
       இந்த அமைப்பை முடக்கினால் அல்லது அமைக்காமல் விட்டால், கேப்டிவ் போர்டல் அங்கீகாரப் பக்கங்கள் ஏதேனும் இருந்தால், அவை தற்போதைய பயனரின் ப்ராக்ஸி அமைப்புகளைப் பயன்படுத்தி, (வழக்கமான) புதிய உலாவித் தாவலில் காண்பிக்கப்படும்.</translation>
+<translation id="21394354835637379">நீட்டிப்புகள், ஆப்ஸ் மற்றும் தீம்களை நிறுவ எந்த URLகளை அனுமதிக்கலாம் என்பதைக் குறிக்க உங்களை அனுமதிக்கும்.
+
+          <ph name="PRODUCT_NAME" /> 21ல் தொடங்கி, நீட்டிப்புகள், ஆப்ஸ் மற்றும் பயனர் ஸ்கிரிப்ட்டுகளை Chrome இணைய அங்காடிக்கு வெளியிலிருந்து நிறுவுவது இன்னும் கடினமாக இருக்கும். இதற்கு முன், *.crx கோப்பிற்கான இணைப்பைப் பயனரால் கிளிக் செய்ய முடிந்தது, மேலும் சில எச்சரிக்கைகளுக்குப் பிறகு கோப்பை நிறுவ <ph name="PRODUCT_NAME" /> அனுமதிக்கும். <ph name="PRODUCT_NAME" /> 21க்குப் பிறகு, இதுபோன்ற கோப்புகளைப் பதிவிறக்கி, <ph name="PRODUCT_NAME" /> அமைப்புகள் பக்கத்தில் இழுத்துவிட வேண்டும். இந்த அமைப்பு குறிப்பிட்ட URLகள் பழைய, எளிய நிறுவல் செயல்முறைகளைக் கொண்டிருக்க அனுமதிக்கும்.
+
+          இந்தப் பட்டியலில் உள்ள ஒவ்வொன்றும் நீட்டிப்புப் பாணியிலான பொருத்த பேட்டர்ன் ஆகும் (https://developer.chrome.com/extensions/match_patterns என்பதைப் பார்க்கவும்). இந்தப் பட்டியலில் உள்ளவற்றுடன் பொருந்தும் எந்தவொரு URLலில் உள்ளவற்றையும் பயனர்கள் எளிதாக நிறுவலாம். *.crx கோப்பின் இருப்பிடமும் பதிவிறக்கம் தொடங்கிய பக்கமும் (பரிந்துரைப்பவர்) இந்த பேட்டர்ன்களால் அனுமதிக்கப்பட வேண்டும்.
+
+          <ph name="EXTENSION_INSTALL_BLACKLIST_POLICY_NAME" /> இந்தக் கொள்கைக்கு முன்னுரிமையளிக்கும். இந்தப் பட்டியலில் உள்ள தளத்திலிருந்து நிகழ்ந்திருந்தாலும் கூட, தடைப்பட்டியலில் உள்ள நீட்டிப்பு நிறுவப்படாது.</translation>
 <translation id="214901426630414675">அச்சிடும் டூப்ளெக்ஸ் பயன்முறையைக் கட்டுப்படுத்தும்</translation>
 <translation id="2149330464730004005">வண்ண அச்சிடலை இயக்கு</translation>
 <translation id="2156132677421487971">தாவல்கள், தளங்கள் அல்லது டெஸ்க்டாப்பின் உள்ளடக்கத்தை, உலாவியிலிருந்து தொலைநிலையில் உள்ள திரைகள் மற்றும் ஆடியோ சாதனங்களுக்கு அனுப்ப பயனர்களை அனுமதிக்கும் <ph name="PRODUCT_NAME" /> அம்சத்திற்கான கொள்கைகளை உள்ளமைக்கும்.</translation>
@@ -554,6 +651,11 @@
 
       கியோஸ்க் பயன்பாடுகள் தானாக நகர்த்தப்படும் என்பதால், அவற்றுக்கு இந்தக் கொள்கை பொருந்தாது. இந்தக் கொள்கையை அமைக்கவில்லை எனில், 'DisallowArc' இன் அடிப்படையில் சாதனம் செயல்படும்.</translation>
 <translation id="2195032660890227692">இந்தக் கொள்கையானது <ph name="PRODUCT_NAME" /> 68டில் அகற்றப்பட்டு, <ph name="ARC_BR_POLICY_NAME" /> ஆல் மாற்றியமைக்கப்படும்.</translation>
+<translation id="219720814106081560">இயக்கப்பட்டாலோ உள்ளமைக்கப்படவில்லை என்றாலோ (இயல்புநிலை) எந்தவித அறிவுறுத்தலும் இன்றி அணுகல் வழங்கப்படும் VideoCaptureAllowedUrls  பட்டியலில் உள்ளமைக்கப்படும் URLகள் தவிர, வீடியோ எடுப்பதற்கான அணுகலுக்கு பயனர் அறிவுறுத்தப்படுவார்.
+
+      இந்தக் கொள்கை முடக்கப்பட்டால் பயனருக்கு எந்தவித அறிவுறுத்தலும் வழங்கப்படாது, மேலும் வீடியோ எடுப்பது VideoCaptureAllowedUrls பட்டியலில் உள்ளமைக்கப்படும் URLகளுக்கு மட்டுமே கிடைக்கும்.
+
+      இந்தக் கொள்கை உள்ளமைந்த கேமராவை மட்டுமின்றி எல்லா வகையான வீடியோ உள்ளீடுகளிலும் மாற்றத்தை ஏற்படுத்தும்.</translation>
 <translation id="2201555246697292490">நேட்டிவ் செய்தியிடல் ஏற்புப்பட்டியலை உள்ளமைத்தல்</translation>
 <translation id="2204753382813641270">அடுக்கு தானாக மறைக்கப்படுவதைக் கட்டுப்படுத்தவும்</translation>
 <translation id="2208976000652006649">POSTடைப் பயன்படுத்தும் தேடல் URLலுக்கான அளவுருக்கள்</translation>
@@ -564,6 +666,11 @@
 <translation id="2231817271680715693">முதல் இயக்கத்தின்போதே இயல்புநிலை உலாவலிருந்து உலாவல் வரலாற்றை இறக்குமதி செய்</translation>
 <translation id="2236488539271255289">அக தரவை அமைப்பதற்கு, எந்த தளத்தையும் அனுமதிக்க வேண்டாம்</translation>
 <translation id="2240879329269430151">பாப்-அப்களைக் காண்பிக்க வலைத் தளங்கள் அனுமதிக்கப்படுகின்றனவா என்பதை அமைக்க உங்களை அனுமதிக்கிறது. காண்பிக்கப்படும் பாப் அப்கள் எல்லா வலைத்தளங்களுக்கும் அனுமதிக்கப்படும் அல்லது எல்லா வலைத்தளங்களுக்கும் மறுக்கப்படும். இந்தக் கொள்கையை அமைக்காமல் விட்டால், 'BlockPopups' பயன்படுத்தப்படும், பயனர் அதை மாற்றலாம்.</translation>
+<translation id="2255326053989409609">இந்த அமைப்பை இயக்கினால், கிராஃபிக்ஸ் ப்ராஸஸிங் யூனிட்டை (GPU) அணுகுவதில் இருந்து இணையப் பக்கங்களைத் தடுக்கும். குறிப்பாக, இணையப் பக்கங்களால் WebGL APIயை அணுக முடியாது. செருகுநிரல்களால் Pepper 3D APIயைப் பயன்படுத்த முடியாது.
+
+      இந்த அமைப்பை முடக்கினாலோ அமைக்கவில்லை என்றாலோ, இணையப் பக்கங்கள் WebGL APIயைப் பயன்படுத்துவதையும் செருகுநிரல்கள் Pepper 3D APIயைப் பயன்படுத்துவதையும் அனுமதிக்கும். இந்த APIகளைப் பயன்படுத்துவதற்காக, கட்டளை வரி மதிப்புருக்களை வழங்குவது உலாவியின் இயல்புநிலைஅமைப்பிற்கு இப்போதும் தேவைப்படக்கூடும்.
+
+      HardwareAccelerationModeEnabled 'தவறு' என அமைக்கப்பட்டால், Disable3DAPIs புறக்கணிக்கப்படும். இது Disable3DAPIs 'சரி' என அமைக்கப்படுவதற்குச் சமமாகும்.</translation>
 <translation id="2258126710006312594">தொலைநிலை அணுகல் பயனர்களை, கோப்புகளை ஹோஸ்ட்டில் இருந்தோ, ஹோஸ்ட்டிற்கோ பரிமாற அனுமதிக்கும்.</translation>
 <translation id="2265214338421787313">ஒரு பக்கம் மூடப்படும்போது பாப் அப்களைக் காண்பிப்பதைக் குறிப்பிடுவதற்கு நிர்வாகிக்கு இந்தக் கொள்கை அனுமதியளிக்கிறது.
 
@@ -716,8 +823,12 @@
       இந்த அமைப்பை இயக்கினால் அல்லது முடக்கினால், பயனரால் இந்த அமைப்பை மாற்றவோ, மேலெழுதவொ முடியாது.
 
       இந்தக் கொள்கையை அமைக்கப்படாமல் விட்டால், பயனர் இதைப் பயன்படுத்த வேண்டுமா அல்லது வேண்டாமா என்பதைத் தேர்வுசெய்வதற்காக தரவு சுருக்க ப்ராக்ஸி அம்சம் கிடைக்கும்.</translation>
+<translation id="257788512393330403">ஒவ்வொரு 6 மணிநேரத்திற்கும் கடவுச்சொல்லை உள்ளிடுவது அவசியம்</translation>
 <translation id="2587719089023392205">எனது இயல்புநிலை உலாவியாக <ph name="PRODUCT_NAME" /> ஐ அமை</translation>
 <translation id="2592091433672667839">விற்பனை பயன்முறையில் உள்நுழைவு திரையில் ஸ்கிரீன் சேவர் காண்பிக்கும் முன்பான செயல்பாடற்ற கால நேரம்</translation>
+<translation id="2592162121850992309">இந்தக் கொள்கை 'சரி' என அமைக்கப்பட்டாலோ அமைக்கப்படவில்லை என்றாலோ, குறிப்பிட்ட GPU அம்சம் தடைப்பட்டியலில் சேர்க்கப்படும் வரை வன்பொருள் விரைவுப்படுத்தல் இயக்கப்படும்.
+
+      இந்தக் கொள்கை 'தவறு' என அமைக்கப்பட்டால் வன்பொருள் விரைவுப்படுத்தல் முடக்கப்படும்.</translation>
 <translation id="2596260130957832043">NTLMv2 இயக்கப்பட்டுள்ளதா என்பதைக் கட்டுப்படுத்தும்.
 
           Samba மற்றும் Windows சேவையகங்களின் எல்லாச் சமீபத்திய பதிப்புகளும் NTLMv2ஐ ஆதரிக்கின்றன. பின்னோக்கிய இணக்கத்தன்மைக்காக மட்டுமே இதனை முடக்க வேண்டும். மேலும் இது அங்கீகரிப்பின் பாதுகாப்பைக் குறைக்கும்.
@@ -743,6 +854,7 @@
 <translation id="2633084400146331575">பேச்சுவடிவ கருத்தைச் செயலாக்கு</translation>
 <translation id="2646290749315461919">பயனர்களின் இருப்பிடத்தை தடமறிய, வலைத்தளங்கள் அனுமதிக்கப்படுகின்றனவா என்பதை அமைக்க உங்களை அனுமதிக்கின்றன. பயனர்களின் இருப்பிடத்தைத்  தடமறிவது இயல்புநிலையால் அனுமதிக்கப்படலாம், இயல்புநிலையால் மறுக்கப்படலாம் அல்லது வலைத்தளம் கோரும் இருப்பிடத்தை ஒவ்வொரு முறையும் பயனரிடம் கேட்கப்படலாம். இந்தக் கொள்கையை அமைக்காமல் விட்டால், 'AskGeolocation' பயன்படுத்தப்படும், பயனர் அதை மாற்ற முடியும்.</translation>
 <translation id="2647069081229792812">புக்மார்க்கைத் திருத்துவதை இயக்கும் அல்லது முடக்கும்</translation>
+<translation id="2649896281375932517">பயனர்கள் தீர்மானிக்கட்டும்</translation>
 <translation id="2650049181907741121">உறையை பயனர் மூடும்போது எடுக்க வேண்டிய நடவடிக்கை</translation>
 <translation id="2655233147335439767">இயல்புநிலை தேடலைச் செய்யும்போது பயன்படுத்திய தேடல் இன்ஜினின் URLலைக் குறிப்பிடும். URLலில் '<ph name="SEARCH_TERM_MARKER" />' வார்த்தை இருக்க வேண்டும், இது வினவல் நேரத்தில் பயனர் தேடும் சொற்களினால் மாற்றப்படும்.
 
@@ -767,6 +879,7 @@
 <translation id="268577405881275241">தரவு சுருக்க ப்ராக்ஸி அம்சத்தை இயக்கு</translation>
 <translation id="2693108589792503178">கடவுச்சொல்லை மாற்றுவதற்கான URLஐ உள்ளமைக்கவும்.</translation>
 <translation id="2706708761587205154">’பின்’ மூலமாக மட்டும் அச்சிடலை அனுமதிக்கும்</translation>
+<translation id="2710534340210290498">இந்தக் கொள்கை 'தவறு' என அமைக்கப்பட்டால் பயனர்களால் திரையைப் பூட்ட முடியாது (பயனர் அமர்விலிருந்து வெளியேற மட்டுமே முடியும்). இந்தக் கொள்கை 'சரி' என அமைக்கப்பட்டால் கடவுச்சொல்லுடன் அங்கீகரிக்கப்படும் பயனர்களால் திரையைப் பூட்ட முடியும்.</translation>
 <translation id="2731627323327011390">ARC பயன்பாடுகளில் <ph name="PRODUCT_OS_NAME" /> சான்றிதழ்களின் உபயோகத்தை முடக்கு</translation>
 <translation id="2742843273354638707">புதிய தாவல் பக்கத்திலிருந்தும், <ph name="PRODUCT_OS_NAME" /> பயன்பாட்டுத் துவக்கியிலிருந்தும், Chrome இணைய அங்காடி பயன்பாடு மற்றும் அடிக்குறிப்பு இணைப்பை மறைக்கவும்.
 
@@ -836,6 +949,9 @@
           இந்தக் கொள்கை அமைக்கப்படவில்லை என்றாலோ ‘தவறு’ என அமைக்கப்பட்டிருந்தாலோ, ஆதரிக்கப்படும் பிளாட்ஃபார்ம்களில் KDC கொள்கை புறக்கணிக்கப்பட்டு, 'AuthNegotiateDelegateWhitelist' கொள்கை மட்டுமே மதிக்கப்படும்.
 
           Windowsஸில் KDC கொள்கை எப்போதும் மதிக்கப்படும்.</translation>
+<translation id="283695852388224413">இந்தக் கொள்கை அமைக்கப்பட்டால் உள்ளமைக்கப்படும் அதிகபட்ச பின் நீளம் செயல்படுத்தப்படும். 0 அல்லது அதற்குக் குறைவான மதிப்பு என்பது அதிகபட்ச நீளம் இல்லை என்பதைக் குறிக்கும்; அந்தச் சூழலில் பயனர் தாங்கள் விரும்பும் நீளத்தில் பின்னை அமைக்கலாம். இந்த அமைப்பு <ph name="PIN_UNLOCK_MINIMUM_LENGTH_POLICY_NAME" />க்குக் குறைவாகவும் 0 விட அதிகமாகவோ இருந்தால் அதிகபட்ச நீளமும் குறைந்தபட்ச நீளமும் ஒன்றாக இருக்கும்.
+
+          இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் அதிகபட்ச நீளம் செயல்படுத்தப்படாது.</translation>
 <translation id="2838830882081735096">தரவு நகர்த்துதலையும் ARCஐயும் அனுமதிக்காதே</translation>
 <translation id="2839294585867804686">’நெட்வொர்க் கோப்புப் பகிர்வு’ அமைப்புகள்</translation>
 <translation id="2840269525054388612">பயனர் பயன்படுத்தக்கூடிய பிரிண்டர்களைக் குறிப்பிடும்.
@@ -906,6 +1022,17 @@
       இந்தக் கொள்கை அமைக்கப்படவில்லை என்றால், <ph name="PRINTERS_ALLOW_ALL" /> பயன்படுத்தப்படும்.
       </translation>
 <translation id="2908277604670530363">ப்ராக்ஸி சேவையகத்திற்கான அதிகபட்ச உடன்நிகழ்வு இணைப்புகளின் எண்ணிக்கை</translation>
+<translation id="2948463916588961959">மொழிகளுக்கான எழுத்துப்பிழைச் சரிபார்ப்பைக் கட்டாயப்படுத்தி இயக்கும். அந்தப் பட்டியலில் இருக்கும் அங்கீகரிக்கப்படாத மொழிகள் புறக்கணிக்கப்படும்.
+
+      இந்தக் கொள்கையை இயக்கினால் பயனர் எழுத்துப்பிழைச் சரிபார்ப்பை இயக்கிய மொழிகளுக்கு மட்டுமின்றி குறிப்பிடப்படும் மொழிகளுக்கான எழுத்துப்பிழைச் சரிபார்ப்பும் இயக்கப்படும்.
+
+      இந்தக் கொள்கையை அமைக்கவில்லை என்றாலோ முடக்கினாலோ பயனரின் எழுத்துப்பிழைச் சரிபார்ப்பு விருப்பத்தேர்வுகளில் எந்தவித மாற்றமும் இருக்காது.
+
+      SpellcheckEnabled கொள்கையை முடக்கினால் இந்தக் கொள்கையில் எந்த மாற்றமும் இருக்காது.
+
+      இந்தக் கொள்கையிலும் SpellcheckLanguageBlacklist கொள்கையிலும் ஒரு மொழி சேர்க்கப்பட்டால் இந்தக் கொள்கைக்கு முன்னுரிமை அளிக்கப்பட்டு, மொழிக்கான எழுத்துப்பிழைச் சரிபார்ப்பு இயக்கப்படும்.
+
+      தற்போது ஆதரிக்கப்படும் மொழிகள்: af, bg, ca, cs, da, de, el, en-AU, en-CA, en-GB, en-US, es, es-419, es-AR, es-ES, es-MX, es-US, et, fa, fo, fr, he, hi, hr, hu, id, it, ko, lt, lv, nb, nl, pl, pt-BR, pt-PT, ro, ru, sh, sk, sl, sq, sr, sv, ta, tg, tr, uk, vi.</translation>
 <translation id="2952347049958405264">கட்டுப்பாடுகள்:</translation>
 <translation id="2956777931324644324">இந்தக் கொள்கை <ph name="PRODUCT_NAME" /> பதிப்பு 36 உடன் காலாவதியானது.
 
@@ -914,9 +1041,11 @@
       சோதனைக்கான TLS டொமைன்-சார்ந்த சான்றிதழ்களின் நீட்டிப்பை இயக்க, இந்த அமைப்பு பயன்படுத்தப்படுகிறது.  இந்தச் சோதனைக்குரிய அமைப்பு எதிர்காலத்தில் அகற்றப்படும்.</translation>
 <translation id="2957506574938329824">இணைய புளூடூத் API வழியாக புளூடூத் சாதனங்களுக்கான அணுகலைக் கோர எந்தத் தளத்தையும் அனுமதிக்க வேண்டாம்</translation>
 <translation id="2957513448235202597"><ph name="HTTP_NEGOTIATE" /> அங்கீகரிப்பிற்கான கணக்கு வகை</translation>
+<translation id="2959469725686993410">நேரமண்டலத்தைக் கண்டறியும் போது WiFi ஆக்சஸ் பாயின்ட்டுகளை எப்போதும் அனுப்பு</translation>
 <translation id="2959898425599642200">ப்ராக்ஸி கடந்துபோதல் விதிகள்</translation>
 <translation id="2960128438010718932">புதிய புதுப்பிப்பை நிறுவுவதற்கான படிப்படியான கால அட்டவணை</translation>
 <translation id="2960691910306063964">தொலைநிலை அணுகல் ஹோஸ்ட்களில் PIN-இல்லாத அங்கீகரிப்பை இயக்கும் அல்லது முடக்கும்</translation>
+<translation id="2972261849442778817">நகர்த்த விரும்புகிறார்களா அல்லது நகர்த்துவதைத் தவிர்த்து, ARCயைத் தடுக்க விரும்புகிறார்களா என்று பயனர்களிடம் கேள்.</translation>
 <translation id="2976002782221275500">பேட்டரி சக்தியில் இயங்கும்போது திரை மங்கலாகும் நேரத்தின் அளவைப் பயனரின் உள்ளீடு இல்லாமல் குறிப்பிடுகிறது.
 
           இந்தக் கொள்கை பூஜ்ஜியத்துக்கு அதிகமான மதிப்புக்கு அமைக்கப்பட்டால், திரையை <ph name="PRODUCT_OS_NAME" /> மங்கலாக்குவதற்கு முன்பாக பயனர் செயலற்ற நிலையில் இருக்க வேண்டிய நேரத்தின் அளவைக் குறிப்பிடும்.
@@ -926,12 +1055,25 @@
           இந்தக் கொள்கை அமைக்கப்படாமல் இருந்தால், இயல்பான நேரத்தின் அளவு பயன்படுத்தப்படும்.
 
           கொள்கை மதிப்பை மில்லிவினாடிகளில் மட்டுமே குறிப்பிட வேண்டும். மதிப்புகள் திரை முடக்கத்தின் தாமதம் (அமைக்கப்பட்டால்) மற்றும் செயலற்ற நிலைக்குக் குறைவாக அல்லது சமமாக இருக்குமாறு அமைக்கப்படும்.</translation>
+<translation id="2977997796833930843">இந்தக் கொள்கை தடுக்கப்பட்டிருப்பதால் எதிர்காலத்தில் அகற்றப்படும் என்பதை நினைவில் கொள்ளவும்.
+
+          இந்தக் கொள்கை மிகவும் குறிப்பிட்ட <ph name="IDLE_ACTION_AC_POLICY_NAME" /> மற்றும் <ph name="IDLE_ACTION_BATTERY_POLICY_NAME" /> கொள்கைகளுக்காக இயல்புநிலை மதிப்பை வழங்கும். இந்தக் கொள்கை அமைக்கப்பட்டால் தொடர்புடைய மிகவும் குறிப்பிட்ட கொள்கை அமைக்கப்படாமல் இருக்கும்பட்சத்தில் அதன் மதிப்புகள் பயன்படுத்தப்படும்.
+
+          இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் மிகவும் குறிப்பிட்ட கொள்கைகளின் நடத்தையில் எந்த மாற்றமும் இருக்காது.</translation>
 <translation id="2987155890997901449">ARCஐ இயக்கு</translation>
 <translation id="2987227569419001736">இணைய புளூடூத் API இன் பயன்பாட்டைக் கட்டுப்படுத்தும்</translation>
 <translation id="3016255526521614822"><ph name="PRODUCT_OS_NAME" /> லாக் ஸ்கிரீனில் அனுமதிக்க வேண்டிய குறிப்பெடுக்கும் பயன்பாடுகளை ஏற்புப்பட்டியலில் சேர்</translation>
 <translation id="3021562480854470924">பதிப்பு மீட்டமைப்பதற்கு அனுமதிக்கப்படும் மைல்ஸ்டோன்களின் எண்ணிக்கை</translation>
 <translation id="3023572080620427845">மாற்று உலாவியில் திறக்க வேண்டிய URLகளைக் கொண்ட ஒரு XML கோப்பின் URL.</translation>
 <translation id="3030000825273123558">மெட்ரிக்ஸ் அறிக்கைகளை இயக்கு</translation>
+<translation id="3033660238345063904">ப்ராக்ஸி சர்வரின் URLலை இங்கே நீங்கள் குறிப்பிடலாம்.
+
+          'ப்ராக்ஸி சேவையக அமைப்புகளை எவ்வாறு குறிப்பது எனத் தேர்வுசெய்க' என்பதில் கைமுறை ப்ராக்ஸி அமைப்புகளை நீங்கள் தேர்ந்தெடுத்திருந்தாலும் <ph name="PROXY_SETTINGS_POLICY_NAME" /> கொள்கை குறிப்பிடப்படவில்லை என்றாலும் மட்டுமே இந்தக் கொள்கை செயல்படுத்தப்படும்.
+
+          ப்ராக்ஸி கொள்கைகளை அமைப்பதற்கு வேறு ஏதேனும் பயன்முறையைத் தேர்ந்தெடுத்திருந்தால் இந்தக் கொள்கையை அமைக்க வேண்டாம்.
+
+          கூடுதல் விருப்பங்களையும் விரிவான எடுத்துக்காட்டுகளையும் பார்க்க இந்த URLலுக்குச் செல்லவும்:
+          <ph name="PROXY_HELP_URL" />.</translation>
 <translation id="3034580675120919256">JavaScript ஐ இயக்குவதற்கு வலைத்தளங்கள் அனுமதிக்கப்படுகின்றனவா என்பதை அமைக்க உங்களை அனுமதிக்கிறது. JavaScript ஐ இயக்குதல் அனைத்து வலைத்தளங்களுக்கும் அனுமதிக்கப்படலாம் அல்லது அனைத்து வலைத்தளங்களுக்கும் நிராகரிக்கப்படலாம். இந்தக் கொள்கையை அமைக்காமல் விட்டிருந்தால், 'AllowJavaScript' பயன்படுத்தப்படும். மேலும் பயனர் அதை மாற்ற இயலும்.</translation>
 <translation id="3038323923255997294"><ph name="PRODUCT_NAME" /> மூடப்படும்போது பின்புலப் பயன்பாடுகளைத் தொடர்ந்து இயக்கவும்</translation>
 <translation id="3046192273793919231">ஆன்லைன் நிலையைக் கண்காணிக்க, நெட்வொர்க் பாக்கெட்டுகளை மேலாண்மை சேவையகத்திற்கு அனுப்பு</translation>
@@ -986,10 +1128,18 @@
       இதை இயக்கினாலோ அமைக்காமலேயே விட்டாலோ, சிஸ்டத்திலுள்ள தேவையற்ற மென்பொருட்களைக் கண்டறிவதற்காக 'Chrome கிளீன்அப்’ அதை அவ்வப்போது ஸ்கேன் செய்யும், தேவையற்ற மென்பொருள் ஏதேனும் கண்டறியப்பட்டால், பயனரிடம் அதை அகற்றுவதற்கு அனுமதி கோரும். chrome://settings/cleanup இணைப்பிலிருந்து ‘Chrome கிளீன்அப்பை’ நேரடியாக இயக்கலாம்.
 
       <ph name="MS_AD_NAME" /> டொமைனுடன் இணைக்கப்பட்ட Windows நேர்வுகளின்போதும் சாதன நிர்வாகத்திற்காகப் பதிவுசெய்யப்பட்ட Windows 10 Pro அல்லது Enterprise நேர்வுகளின்போதும் மட்டுமே இந்தக் கொள்கை பயன்படுத்தப்படும்.</translation>
+<translation id="3152425128389603870">ஒருங்கிணைந்த டெஸ்க்டாப்பைக் கிடைக்கச் செய்து, இயல்பாகவே இயக்கத்தில் வைக்கும்</translation>
 <translation id="3159375329008977062">UI வழியாக Crostini கண்டெய்னர்களைப் பதிவேற்றவும், பதிவிறக்கவும் பயனருக்கு அனுமதி வழங்கப்பட்டுள்ளது</translation>
 <translation id="3165808775394012744">இந்தக் கொள்கைகளை அகற்றுவதை எளிதாக்குவதற்காக அவை இங்கே சேர்க்கப்பட்டுள்ளன.</translation>
 <translation id="316778957754360075">இந்த அமைப்பானது <ph name="PRODUCT_NAME" /> பதிப்பு 29க்கு பின்பு முடக்கப்பட்டுள்ளது. நிறுவனம் சார்ந்த நீட்டிப்பு/பயன்பாட்டு தொகுப்புகளை அமைக்க பரிந்துரைக்கப்படும் வழி, ExtensionInstallSources இல் உள்ள CRX தொகுப்புகளை வழங்கும் தளத்தைச் சேர்த்து, தொகுப்புகளுக்கான நேரடி பதிவிறக்க இணைப்புகளை இணையப்பக்கத்தில் வழங்குவதாகும். ExtensionInstallForcelist கொள்கையைப் பயன்படுத்தி அந்த இணையப்பக்கத்திற்கான துவக்கியை உருவாக்கலாம்.</translation>
 <translation id="3171369832001535378">சாதன நெட்வொர்க் ஹோஸ்ட்பெயர் டெம்ப்ளேட்</translation>
+<translation id="3172512016079904926">நேட்டிவ் மெசேஜிங் ஹோஸ்ட்களின் பயனர் அளவிலான நிறுவலை இயக்கும்.
+
+          இந்த அமைப்பு இயக்கப்பட்டால் பயனர் அளவில் நிறுவப்படும் நேட்டிவ் மெசேஜிங் ஹோஸ்ட்களின் உபயோகத்தை <ph name="PRODUCT_NAME" /> அனுமதிக்கும்.
+
+          இந்த அமைப்பு முடக்கப்பட்டால் சிஸ்டம் அளவில் நிறுவப்படும் நேட்டிவ் மெசேஜிங் ஹோஸ்ட்களை மட்டுமே <ph name="PRODUCT_NAME" /> பயன்படுத்தும்.
+
+          இந்த அமைப்பு அமைக்கப்படவில்லை எனில் பயனர் அளவிலான நேட்டிவ் மெசேஜிங் ஹோஸ்ட்களின் உபயோகத்தை <ph name="PRODUCT_NAME" /> அனுமதிக்கும்.</translation>
 <translation id="3185009703220253572">பதிப்பு <ph name="SINCE_VERSION" /> முதல்</translation>
 <translation id="3187220842205194486">Android பயன்பாடுகளால் நிறுவனக் குறியீடுகளை அணுக முடியாது. அவற்றில் இந்தக் கொள்கை எந்த மாற்றத்தையும் ஏற்படுத்தாது.</translation>
 <translation id="3205825995289802549">முதல் முறை இயக்கப்படும் போது முதல் உலாவிச் சாளரத்தைப் பெரிதாக்கும்</translation>
@@ -1057,6 +1207,17 @@
       இந்தக் கொள்கையைப் பரிந்துரைக்கப்படுவதாக மட்டுமே அமைக்க முடியும். இந்தக் கொள்கையைப் பயன்படுத்தி பரிந்துரைக்கப்பட்ட மொழிகளின் தொகுப்பை மேற்பகுதிக்கு நகர்த்தலாம், ஆனால் பயனர்கள் தங்கள் அமர்வுக்கு <ph name="PRODUCT_OS_NAME" /> ஆதரிக்கும் எந்த மொழியையும் தேர்வுசெய்ய எப்போதும் அனுமதிக்கப்படுவார்கள்.
       </translation>
 <translation id="3381968327636295719">இயல்புநிலையாக ஹோஸ்ட் உலாவியைப் பயன்படுத்து</translation>
+<translation id="3384115339826100753">Power peak shift ஆற்றல் நிர்வாகக் கொள்கையை இயக்கும்.
+
+          மின்சார உபயோகம் உச்சத்திலிருக்கும் பகல் நேரங்களில் மாறுதிசை மின்னோட்ட உபயோகத்தைக் குறைக்கும் மின்சாரச் சேமிப்புக் கொள்கையே Peak Shift ஆகும். ஒவ்வொரு வேலை நாட்களிலும் power Peak Shift பயன்முறையில் இயக்குவதற்கான தொடக்க நேரத்தையும் முடிவு நேரத்தையும் அமைக்கலாம். இந்த சமயங்களில் மாறுதிசை மின்னோட்டம் இணைக்கப்பட்டிருந்தாலும்கூட மேலே குறிப்பிட்டுள்ள ஆற்றல் வரம்பிற்குமேல் இருக்கும் பேட்டரி மூலமே சாதனம் இயங்கும். நிர்ணயித்த முடிவு நேரத்தைக் கடந்த பிறகு இணைக்கப்பட்டிருக்கும் பட்சத்தில் மாறுதிசை மின்னோட்டத்தில் சிஸ்டம் இயங்கும், எனினும் பேட்டரி சார்ஜ் ஆகாது. மாறுதிசை மின்னோட்டத்தைப் பயன்படுத்தியும், சார்ஜாவதற்கென அமைக்கப்பட்ட தொடக்க நேரத்திற்குப் பிறகு பேட்டரியை ரீசார்ஜ் செய்தும் வழக்கம்போல சிஸ்டம் இயங்கத் தொடங்கும்.
+
+          DevicePowerPeakShiftBatteryThreshold மற்றும் DevicePowerPeakShiftDayConfig அமைக்கப்பட்டுள்ளதோடு இந்தக் கொள்கை 'சரி' என அமைத்தால், சாதனம் ஆதரிக்கும்பட்சத்தில் power peak shift எப்போதும் இயக்கத்தில் இருக்கும்.
+
+          இந்தக் கொள்கை 'தவறு' என அமைத்தால் power peak shift எப்போதும் முடக்கத்தில் இருக்கும்.
+
+          நீங்கள் அமைத்த கொள்கையைப் பயனர்கள் மாற்றவோ மேலெழுதவோ இயலாது.
+
+          இந்தக் கொள்கையை அமைக்கவில்லை எனில் தொடக்கத்திலேயே power peak shift முடங்கிவிடும், அதன்பிறகு பயனரால் அதை இயக்க இயலாது.</translation>
 <translation id="3388153794103186066">குறிப்பிட்ட விற்பனையாளர் ஐடியையும் தயாரிப்பு ஐடிகளையும் கொண்ட ஒரு USB சாதனத்தை அணுகுவதற்குத் தானாக அனுமதி வழங்கப்படும் தளங்களைக் குறிப்பிடுகின்ற urlகளின் பட்டியலை அமைக்க உங்களை அனுமதிக்கும். கொள்கை செல்லுபடியாவதற்கு, இந்தப் பட்டியலில் உள்ள அனைத்திலும் சாதனங்களும் urlகளும் இருக்க வேண்டும். சாதனங்களிலுள்ள ஒவ்வொன்றிலும் ஒரு விற்பனையாளர் ஐடி புலமும் தயாரிப்பு ஐடி புலமும் இருக்கலாம். தவிர்க்கப்படும் எந்தவொரு ஐடியும் விதிவிலக்குள்ள ஒரு வைல்டுகார்டாகக் கருதப்படும், விற்பனையாளர் ஐடி இல்லாமல் தயாரிப்பு ஐடியைக் குறிப்பிட முடியாது என்பதே அந்த விதிவிலக்கு. அப்படி இல்லாவிட்டால், கொள்கை செல்லுபடியாகாது. செல்லுபடியாகாத கொள்கை மதிப்புகள் புறக்கணிக்கப்படும்.
 
         USB சாதனத்தை அணுகுவதற்குக் கோருகின்ற URLலுக்கு அனுமதியை வழங்க, கோருகின்ற தளத்தின் URLலையும் (”கோருகின்ற URL”) மேல் நிலை ஃபிரேம் தளத்தின் URLலையும் (”உட்பொதிக்கின்ற URL”) USB அனுமதி மாதிரி பயன்படுத்தும். கோருகின்ற தளத்தை iframeமில் ஏற்றும்போது, கோருகின்ற URLலும் உட்பொதிக்கின்ற URLலும் வெவ்வேறாக இருக்கலாம். அதனால், கோருகின்ற URLலையும் உட்பொதிக்கின்ற URLலையும் முறையே குறிப்பிடுவதற்காக, "urlகள்” புலத்தில் காற்புள்ளியால் பிரிக்கப்பட்ட இரண்டு URLகள் வரை இருக்கலாம். ஒரு URL மட்டும் குறிப்பிடப்பட்டிருந்தால், உட்பொதிக்கும் நிலை எதுவாக இருந்தாலும், கோருகின்ற தளத்தின் URLலும் இந்த URLலும் பொருந்தும்போது, தொடர்புடைய USB சாதனங்களுக்கான அணுகல் அளிக்கப்படும். "urlகளில்” உள்ள URLகள் செல்லுபடியாகும் URLகளாக இருக்க வேண்டும், இல்லாவிட்டால் அந்தக் கொள்கை புறக்கணிக்கப்படும்.
@@ -1082,6 +1243,13 @@
       இந்த அமைப்பு முடக்கத்தில் இருந்தால் அல்லது அமைக்கப்படாமல் இருந்தால், கட்டுப்பாட்டுப் பயன்முறையை YouTube இல் <ph name="PRODUCT_NAME" /> கட்டாயப்படுத்தாது. இருப்பினும், YouTube கொள்கைகள் போன்ற புறக் கொள்கைகளானவை கட்டுப்பாட்டுப் பயன்முறையைக் கட்டாயப்படுத்தக்கூடும்.</translation>
 <translation id="3428247105888806363">நெட்வொர்க் கணிப்பை இயக்கு</translation>
 <translation id="3432863169147125747">அச்சிடும் அமைப்புகளைக் கட்டுப்படுத்தும்.</translation>
+<translation id="3434932177006334880">Chrome 42க்கு முன்பாக இந்த அமைப்பு EnableWebBasedSignin எனப் பெயரிடப்பட்டிருந்தது. இதற்கான ஆதரவு Chrome 43ல் முழுமையாக அகற்றப்படும்.
+
+      புதிய இன்லைன் உள்நுழைவுச் செயல்முறையுடன் இன்னும் இணங்காத SSO தீர்வுகளைப் பயன்படுத்தும் என்டர்பிரைஸ் வாடிக்கையாளர்களுக்கு இந்த அமைப்பு பயனுள்ளதாகும்.
+      இந்த அமைப்பை இயக்கினால் பழைய இணையம் சார்ந்த உள்நுழைவுச் செயல்முறை பயன்படுத்தப்படும்.
+      இந்த அமைப்பை முடக்கினாலோ அமைக்கவில்லை என்றாலோ புதிய இன்லைன் உள்நுழைவுச் செயல்முறை இயல்பாகவே பயன்படுத்தப்படும். இருப்பினும், '--enable-web-based-signin' என்ற கட்டளை வரியின் மூலம் பயனர்கள் பழைய இணையம் சார்ந்த உள்நுழைவுச் செயல்முறையை இயக்கலாம்.
+
+      எல்லா SSO உள்நுழைவுச் செயல்முறைகளையும் இன்லைன் உள்நுழைவு ஆதரிக்கும் போது எதிர்காலத்தில் இந்தச் சோதனை அமைப்பு அகற்றப்படும்.</translation>
 <translation id="3437924696598384725">VPN இணைப்புகளை நிர்வகிக்கப் பயனரை அனுமதிக்கும்</translation>
 <translation id="3459509316159669723">அச்சிடல்</translation>
 <translation id="3460784402832014830">புதிய தாவல் பக்கத்தை வழங்குவதற்காக தேடல் இன்ஜின் பயன்படுத்தும் URLலைக் குறிப்பிடுகிறது.
@@ -1101,6 +1269,12 @@
         இந்தக் கொள்கை அமைக்கப்பட்டிருந்தால் <ph name="PRODUCT_NAME" /> தன்னைப் பதிவுசெய்வதற்கும் தொடர்புடைய கிளவுட் கொள்கையை அனைத்துக் கணக்குகளுக்கும் பயன்படுத்தவும் முயலும்.
 
         இந்தக் கொள்கையின் மதிப்பானது, Google Admin கன்சோலிலிருந்து பெறக்கூடிய பதிவுசெய்வதற்கான டோக்கன் ஆகும்.</translation>
+<translation id="3489247539215560634">இந்த அமைப்பு இயக்கப்பட்டால் கடவுச்சொற்களை <ph name="PRODUCT_NAME" /> நினைவில் கொண்டு, பயனர்கள் அடுத்த முறை தளத்தில் உள்நுழையும் போது தானாகவே அவற்றை வழங்கும்படி செய்யலாம்.
+
+          இந்த அமைப்பு முடக்கப்பட்டால் பயனர்களால் புதிய கடவுச்சொற்களைச் சேமிக்க முடியாது.
+          ஆனால் அதற்கு முன் சேமித்த கடவுச்சொற்களை அப்போதும் பயன்படுத்தலாம்.
+
+          இந்தக் கொள்கை இயக்கப்பட்டாலோ முடக்கப்பட்டாலோ <ph name="PRODUCT_NAME" />ல் பயனர்களால் இதை மாற்ற முடியாது. இந்தக் கொள்கை அமைக்கப்படவில்லை (ஆனால் பயனர் அதை முடக்கலாம்) எனில் கடவுச்சொல் சேமிப்பு அனுமதிக்கப்படும்.</translation>
 <translation id="3496296378755072552">கடவுச்சொல் நிர்வாகி</translation>
 <translation id="3500732098526756068">கடவுச்சொல் பாதுகாப்புச் சேவையின் எச்சரிக்கையை வழங்குவதற்கான தூண்டலைக் கட்டுப்படுத்த உங்களை அனுமதிக்கிறது. சந்தேகத்திற்குரிய தளங்களில் பயனர்கள் தங்கள் பாதுகாக்கப்பட்ட கடவுச்சொல்லை மீண்டும் பயன்படுத்தும்போது, கடவுச்சொல் பாதுகாப்புச் சேவை அவர்களை எச்சரிக்கும்.
 
@@ -1119,6 +1293,11 @@
           'DefaultSearchProviderEnabled' கொள்கை இயக்கப்பட்டிருந்தால் மட்டுமே இந்தக் கொள்கையானது ஆதரிக்கப்படும்.</translation>
 <translation id="350797926066071931">மொழியாக்கத்தை இயக்கு</translation>
 <translation id="3512226956150568738">ARCஐ இயக்குவதற்கு, ext4க்கு நகரத்துவதற்கு முன்னர் ARCஐ ஆதரித்த கிளையண்ட் சாதன மாடல் தேவைப்பட்டிருந்து, ArcEnabled கொள்கை "சரி" என அமைக்கப்பட்டால், இந்த விருப்பம் "AskUser (மதிப்பு 3)" என்ற மதிப்புக்கேற்ப செயல்படும். மற்ற எல்லாச் சூழல்களிலும் (சாதன மாடல் முன்னர் ARCஐ ஆதரிக்கவில்லை என்றாலோ அல்லது ArcEnabled கொள்கை "தவறு" என அமைக்கப்பட்டிருந்தாலோ), இந்த மதிப்பானது "DisallowArc (மதிப்பு 0)"க்குச் சமமானதாக இருக்கும்.</translation>
+<translation id="3513655665999652754">திரையின் அளவுத்திருத்தத்தைச் சரிசெய்வதற்கான ICC காட்சி சுயவிவரங்கள் போன்று வன்பொருள் சார்ந்த உள்ளமைவுக் கோப்புகளை Quirks சேவையகம் வழங்கும்.
+
+      இந்தக் கொள்கை 'தவறு' என அமைக்கப்பட்டால் சாதனம் உள்ளமைவுக் கோப்புகளைப் பதிவிறக்குவதற்கு Quirks சேவையகத்தைத் தொடர்பு கொள்ள முயலாது.
+
+      இந்தக் கொள்கை 'சரி' என அமைக்கப்பட்டாலோ உள்ளமைக்கப்படவில்லை என்றாலோ <ph name="PRODUCT_OS_NAME" /> Quirks சேவையகத்தைத் தானாகத் தொடர்பு கொண்டு உள்ளமைவுக் கோப்புகள் இருந்தால் அவற்றைப் பதிவிறக்கி, சாதனத்தில் சேமிக்கும்.  எடுத்துக்காட்டாக, இது போன்ற கோப்புகள் இணைக்கப்பட்ட திரைகளின் காட்சித் தரத்தை மேம்படுத்துவதற்காகப் பயன்படுத்தப்படலாம்.</translation>
 <translation id="3524204464536655762">WebUSB API மூலமாக USB சாதனங்களுக்கான அணுகலைக் கோர எந்தத் தளத்தையும் அனுமதிக்காது</translation>
 <translation id="3526752951628474302">மோனோகுரோம் அச்சிடல் மட்டும்</translation>
 <translation id="3528000905991875314">மாற்று பிழைப் பக்கங்களை இயக்கு</translation>
@@ -1129,6 +1308,7 @@
       இந்தக் கொள்கை 'DeveloperToolsDisallowed' (மதிப்பு 2) என்பதற்கு அமைக்கப்பட்டால், அதன் பின்னர் டெவெலப்பர் கருவிகளை அணுக முடியாது மற்றும் இணையதளக் கூறுகளை ஆய்வு செய்யமுடியாது. டெவெலப்பர் கருவிகள் அல்லது JavaScript கன்சோலைத் திறப்பதற்கான கீபோர்ட் ஷார்ட்கட்களும் மெனு அல்லது சூழல் மெனு உள்ளீடுகளும் முடக்கப்படும்.</translation>
 <translation id="3547954654003013442">ப்ராக்ஸி அமைப்புகள்</translation>
 <translation id="355118380775352753">இணையதளங்களை மாற்று உலாவியில் திறக்கும்</translation>
+<translation id="3554984410014457319">’குரல் மூலம் செயல்படுத்தும் சொற்றொடரை' Google அசிஸ்டண்ட் கேட்பதற்கு அனுமதிக்கும்</translation>
 <translation id="3577251398714997599">குறுக்கிடும் விளம்பரங்களுடன் கூடிய தளங்களுக்கான விளம்பர அமைப்புகள்</translation>
 <translation id="357917253161699596">பயனர் சான்றிதழ்களை நிர்வகிப்பதற்குப் பயனர்களை அனுமதிக்கும்</translation>
 <translation id="3583230441447348508">முன்னமைக்கப்பட்ட நெட்வொர்க் கோப்புப் பகிர்வுகளின் பட்டியலைக் குறிப்பிடும்.
@@ -1147,6 +1327,9 @@
       </translation>
 <translation id="3627678165642179114">எழுத்துப்பிழை சரிபார்க்கும் இணைய சேவையை இயக்கு/முடக்கு</translation>
 <translation id="3628480121685794414">சிம்ப்ளெக்ஸ் அச்சிடலை இயக்கு</translation>
+<translation id="3631099945620529777">இது 'தவறு' என அமைக்கப்பட்டால் செயல் நிர்வாகியில் 'செயலாக்கத்தை முடி' எனும் பட்டன் முடக்கப்படும்.
+
+      இது 'சரி' என அமைக்கப்பட்டாலோ உள்ளமைக்கப்படவில்லை என்றாலோ பயனர் 'செயல் நிர்வாகியில்' செயலாக்கங்களை முடிக்கலாம்.</translation>
 <translation id="3646859102161347133">திரை உருப்பெருக்கியின் வகையை அமை</translation>
 <translation id="3653237928288822292">இயல்புநிலை தேடல் வழங்குநர் ஐகான்</translation>
 <translation id="3660510274595679517">
@@ -1161,6 +1344,7 @@
 <translation id="3709266154059827597">நீட்டிப்பு நிறுவுதல் தடுப்புப்பட்டியலை உள்ளமை</translation>
 <translation id="3711895659073496551">இடைநிறுத்தப்பட்டது</translation>
 <translation id="3715569262675717862">கிளையண்ட் சான்றிதழ்களின் அடிப்படையில் அங்கீகரிப்பு</translation>
+<translation id="3734995764843493369">ஒவ்வொரு நாளும் (24 மணிநேரம்) கடவுச்சொல்லை உள்ளிட வேண்டும்</translation>
 <translation id="3736879847913515635">பயனர் நிர்வாகியில் பயனரைச் சேர்ப்பதை இயக்கு</translation>
 <translation id="3738723882663496016">இந்தக் கொள்கை இந்தச் சாதனத்திற்கான <ph name="PLUGIN_VM_NAME" /> உரிமக் குறியீட்டைக் குறிப்பிடுகிறது.</translation>
 <translation id="3748900290998155147">இயக்கநிலைப் பூட்டுகள் அனுமதிக்கப்படுமா என்பதைக் குறிப்பிடும். இயக்கநிலைப் பூட்டுகளை power management extension API வழியான நீட்டிப்புகள் மூலமும் ARC ஆப்ஸ் மூலமும் கோரலாம்.
@@ -1169,6 +1353,9 @@
 
           இந்தக் கொள்கையை 'தவறு' என அமைத்தால், இயக்கநிலைப் பூட்டுக் கோரிக்கைகள் புறக்கணிக்கப்படும்.</translation>
 <translation id="3750220015372671395">இந்தத் தளங்களில் விசை உருவாக்கத்தைத் தடு</translation>
+<translation id="375266612405883748">இந்த மெஷினில் தொலைநிலை அணுகல் ஹோஸ்ட்கள் பயன்படுத்தும் UDP போர்ட் வரம்பைக் கட்டுப்படுத்தும்.
+
+          இந்தக் கொள்கை அமைக்கப்படவில்லை என்றாலோ காலி வார்த்தையாக அமைக்கப்பட்டாலோ <ph name="REMOTE_ACCESS_HOST_FIREWALL_TRAVERSAL_POLICY_NAME" /> கொள்கை முடக்கப்படும் வரை கிடைக்கக்கூடிய எந்தப் போர்ட்டையும் பயன்படுத்த தொலைநிலை அணுகல் ஹோஸ்ட்டுக்கு அனுமதி வழங்கப்படும். அந்தக் கொள்கை முடக்கப்படும்பட்சத்தில் தொலைநிலை அணுகல் ஹோஸ்ட் UDP போர்ட்டுகளை 12400-12409 என்ற வரம்பில் பயன்படுத்தும்.</translation>
 <translation id="3756011779061588474">டெவலப்பர் பயன்முறையைத் தடு</translation>
 <translation id="3758089716224084329"><ph name="PRODUCT_NAME" /> பயன்படுத்தும் ப்ராக்ஸி சேவையகத்தைக் குறிப்பிட உங்களை அனுமதித்து, ப்ராக்ஸி அமைப்புகளை மாற்றுவதிலிருந்து பயனர்களைத் தடுக்கும்.
 
@@ -1245,6 +1432,8 @@
           தடுப்புப்பட்டியல் மதிப்பு * என்பது தடுப்புப்பட்டியலில் உள்ள எல்லா நேட்டிவ் ஹோஸ்ட்களும் தடுப்புப்பட்டியலில் அடங்குபவையாகும், மேலும் ஏற்புப்பட்டியலில் பட்டியலிடப்பட்ட நேட்டிவ் செய்தியிடல் ஹோஸ்ட்கள் மட்டும் ஏற்றப்படும் என்பதாகும்.
 
           இயல்பாகவே, எல்லா நேட்டிவ் செய்தியிடல் ஹோஸ்ட்களும் ஏற்புப்பட்டியலில் இருக்கும், ஆனால் எல்லா நேட்டிவ் செய்தியிடல் ஹோஸ்ட்களும் கொள்கையின்படி தடுக்கப்பட்டிருந்தால், கொள்கையை மேலெழுதும் வகையில் ஏற்புப்பட்டியல் பயன்படுத்தப்படும்.</translation>
+<translation id="3835692988507803626">மொழிகளுக்கான எழுத்துச்சரிபார்ப்பைக் கட்டாயப்படுத்தி முடக்கும்</translation>
+<translation id="3837424079837455272">இந்தக் கொள்கை <ph name="PRODUCT_OS_NAME" />ல் புதிய பயனர்களைச் சேர்க்கலாமா என்பதைக் கட்டுப்படுத்தும். Androidல் கூடுதல் Google கணக்குகளில் பயனர்கள் உள்நுழைவதைத் தடுக்காது. இதைத் தடுக்க விரும்பினால் Android சார்ந்த <ph name="ACCOUNT_TYPES_WITH_MANAGEMENT_DISABLED_CLOUDDPC_POLICY_NAME" /> கொள்கையை <ph name="ARC_POLICY_POLICY_NAME" /> கொள்கையின் ஒரு பகுதியாக உள்ளமைக்கவும்.</translation>
 <translation id="384743459174066962">பாப்அப்களைத் திறக்க அனுமதிக்காத தளங்களைக் குறிக்கும் url வகைகளின் பட்டியலை அமைக்க, உங்களை அனுமதிக்கிறது. ஒட்டுமொத்தமாக அமைக்காமல் இந்தப் பாலிசி விடப்பட்டிருந்தால் இயல்புநிலை மதிப்பானது, அமைக்கப்பட்டிருந்தால் 'DefaultPopupsSetting' கொள்கை அல்லது பயனரின் தனிப்பட்ட உள்ளமைவிலிருந்து அனைத்து தளங்களுக்கும் பயன்படுத்தப்படும்.</translation>
 <translation id="3851039766298741586">பயன்பாட்டு ஐடி, பதிப்பு போன்று செயலில் உள்ள கியோஸ்க் அமர்வைப்
       பற்றிய தகவலை அறிவிக்கும்.
@@ -1352,6 +1541,12 @@
       இந்த அமைப்பை உள்ளமைக்கவில்லை எனில் அல்லது ”தவறு” என அமைத்தால், <ph name="PRODUCT_OS_NAME" /> சாதனங்கள் தானாகவே புதுப்பிப்புகளைத் தேடும்.
 
       எச்சரிக்கை: தானியங்கு புதுப்பிப்புகளை இயக்கத்தில் வைக்கும்படி பரிந்துரைக்கிறோம். இதன் மூலம், பயனர்கள் மென்பொருள் புதுப்பிப்புகளையும் முக்கியமான பாதுகாப்புத் திருத்தங்களையும் பெறுவார்கள். தானியங்கு புதுப்பிப்புகளை முடக்கினால், பயனர்களுக்கு சிக்கல்கள் ஏற்படலாம்.</translation>
+<translation id="4018000735882846261">'குரல் மூலம் செயல்படுத்தும் சொற்றொடரை' Google அசிஸ்டண்ட் கேட்பதற்கு இந்தக் கொள்கை அனுமதிக்கும்.
+
+      இந்தக் கொள்கை இயக்கப்பட்டிருந்தால் 'குரல் மூலம் செயல்படுத்தும் சொற்றொடரை' Google அசிஸ்டண்ட் கேட்க இயலும்.
+      இந்தக் கொள்கை முடக்கப்பட்டிருந்தால் 'குரல் மூலம் செயல்படுத்தும் சொற்றொடரை' Google அசிஸ்டண்ட் கேட்க இயலாது.
+      இந்தக் கொள்கையை அமைக்கவில்லை எனில் 'குரல் மூலம் செயல்படுத்தும் சொற்றொடரை' Google அசிஸ்டண்ட் கேட்க இயலாது.
+      </translation>
 <translation id="4020682745012723568">பயனரின் சுயவிவரத்திற்குப் பரிமாற்றப்படும் குக்கீகளை, Android பயன்பாடுகளில் அணுக முடியாது.</translation>
 <translation id="402759845255257575">JavaScript ஐ இயக்குவதற்கு எந்த தளத்தையும் அனுமதிக்க வேண்டாம்</translation>
 <translation id="4027608872760987929">இயல்புநிலை தேடல் வழங்குநரை இயக்கு</translation>
@@ -1411,8 +1606,21 @@
 <translation id="4150201353443180367">டிஸ்பிளே</translation>
 <translation id="4157003184375321727">OS மற்றும் firmware பதிப்பைப் புகாரளி</translation>
 <translation id="4157594634940419685">இயல்பு CUPS பிரிண்டர்களுக்கான அணுகலை அனுமதிக்கும்</translation>
+<translation id="4163705126749612234">தொலைநிலை அணுகல் கிளையன்ட்களின் மீது பயன்படுத்தத் தேவையான கிளையன்ட் டொமைன் பெயர்களை உள்ளமைக்கும், பயனர்கள் அதை மாற்றுவதைத் தடுக்கும்.
+
+          இந்த அமைப்பு இயக்கப்பட்டால் குறிப்பிட்ட டொமைன்களில் ஒன்றின் கிளையன்ட்கள் மட்டுமே ஹோஸ்ட்டுடன் இணைய முடியும்.
+
+          இந்தக் கொள்கை முடக்கப்பட்டாலோ அமைக்கப்படவில்லை என்றாலோ இணைப்பு வகைக்கான இயல்புநிலைக் கொள்கை பயன்படுத்தப்படும். தொலைநிலை உதவிக்காக, இது எந்தவொரு டொமைனின் கிளையன்ட்களையும் ஹோஸ்ட்டுடன் இணைய அனுமதிக்கும்; எந்த நேரத்திலும் பெறக்கூடிய தொலைநிலை அணுகலுக்கு ஹோஸ்ட் உரிமையாளர் மட்டுமே இணைக்க முடியும்.
+
+          இந்த அமைப்பு RemoteAccessHostClientDomain கொள்கை இருக்கும்பட்சத்தில் அதை மேலெழுதும்.
+
+          RemoteAccessHostDomainList கொள்கையையும் பார்க்கவும்.</translation>
 <translation id="4183229833636799228">இயல்புநிலை <ph name="FLASH_PLUGIN_NAME" /> அமைப்பு</translation>
 <translation id="4192388905594723944">தொலைநிலை அணுகல் க்ளையண்ட் அங்கீகரிப்பு டோக்கனைச் சரிபார்ப்பதற்கான URL</translation>
+<translation id="4197038214024763371">இந்தக் கொள்கை அமைக்கப்படவில்லை என்றாலோ இயக்கப்பட்டாலோ பயனர் எழுத்துப்பிழைச் சரிபார்ப்பைப் பயன்படுத்த அனுமதிக்கப்படுவார்.
+
+      இந்தக் கொள்கை முடக்கப்பட்டால் பயனர் எழுத்துப்பிழைச் சரிபார்ப்பைப் பயன்படுத்த அனுமதிக்கப்படமாட்டார். இந்தக் கொள்கை முடக்கப்பட்டிருக்கும் போது SpellcheckLanguage, SpellcheckLanguageBlacklist ஆகிய கொள்கைகளும் புறக்கணிக்கப்படும்.
+      </translation>
 <translation id="4203389617541558220">தானியங்கு மறுதொடக்கங்களை திட்டமிட்டு சாதனத்தின் இயக்க நேரத்தை வரையறுக்கவும்.
 
       இந்தக் கொள்கை அமைக்கப்படும்போது, தானியங்கு மறுதொடக்கத்தைத் திட்டமிட்டப் பிறகான சாதனத்தின் இயக்க நேர நீளத்தைக் குறிப்பிடுகிறது.
@@ -1434,6 +1642,13 @@
 <translation id="423797045246308574">விசை உருவாக்கத்தைப் பயன்படுத்த அனுமதிக்காதத் தளங்களைக் குறிப்பிடும் url வடிவங்களின்  பட்டியலை அமைக்க உங்களை அனுமதிக்கும். url வடிவமானது 'KeygenAllowedForUrls' என்பதில் இருந்தால், இந்த விதிவிலக்குகளை அது மேலெழுதும்.
 
           இந்தக் கொள்கை அமைக்கப்படாமல் விடப்பட்டால், எல்லா தளங்களுக்குமான ஒட்டுமொத்த இயல்புநிலை மதிப்பானது 'DefaultKeygenSetting' கொள்கை அமைக்கப்பட்டிருந்தால் அதிலிருந்து பயன்படுத்தப்படும் அல்லது பயனரின் தனிப்பட்ட உள்ளமைவின்படி பயன்படுத்தப்படும்.</translation>
+<translation id="4238997902172035160">சுயவிவரங்களின் ரோமிங் நகலைச் சேமிப்பதற்காக <ph name="PRODUCT_NAME" /> பயன்படுத்தும் கோப்பகத்தை உள்ளமைக்கும்.
+
+      இந்தக் கொள்கையை அமைத்தால் <ph name="ROAMING_PROFILE_SUPPORT_ENABLED_POLICY_NAME" /> கொள்கை இயக்கப்படும்பட்சத்தில் சுயவிவரங்களின் ரோமிங் நகலைச் சேமிக்க வழங்கிய கோப்பகத்தை <ph name="PRODUCT_NAME" /> பயன்படுத்தும். <ph name="ROAMING_PROFILE_SUPPORT_ENABLED_POLICY_NAME" /> கொள்கை முடக்கப்பட்டாலோ அமைக்கப்படவில்லை என்றாலோ, இந்தக் கொள்கையில் சேமிக்கப்பட்டுள்ள மதிப்பு பயன்படுத்தப்படாது.
+
+      பயன்படுத்தக்கூடிய மாறிகளின் பட்டியலைப் பார்க்க, https://www.chromium.org/administrators/policy-list-3/user-data-directory-variables எனும் இணைப்பிற்குச் செல்லவும்.
+
+      இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் இயல்பு ரோமிங் சுயவிவரத் தடம் பயன்படுத்தப்படும்.</translation>
 <translation id="4239720644496144453">Android பயன்பாடுகளுக்குத் தற்காலிகச் சேமிப்பு பயன்படுத்தப்படாது. பல பயனர்கள் ஒரே Android பயன்பாட்டை நிறுவியிருந்தால், ஒவ்வொரு பயனருக்கும் அது புதியதாகப் பதிவிறக்கப்படும்.</translation>
 <translation id="4243336580717651045"><ph name="PRODUCT_NAME" /> இல், URLகளோடு சேகரிக்கப்படும் அடையாளமற்ற தரவுத் தொகுப்பை இயக்கும். மேலும் இந்த அமைப்பைப் பயனர்கள் மாற்றுவதைத் தடுக்கும்.
 
@@ -1500,6 +1715,9 @@
 <translation id="4408428864159735559">முன்னமைக்கப்பட்ட நெட்வொர்க் கோப்புப் பகிர்வுகளின் பட்டியல்.</translation>
 <translation id="4410236409016356088">நெட்வொர்க் இணைய வேகத்தை நெரித்துத் தடுக்கும் அம்சத்தை இயக்கும்</translation>
 <translation id="441217499641439905"><ph name="PRODUCT_OS_NAME" /> கோப்புகள் பயன்பாட்டில், செல்லுலார் இணைப்புகளின் மூலம் Google இயக்ககத்தை அணுகும் வசதியை முடக்கும்</translation>
+<translation id="4415603335307944578">இந்தக் கொள்கை 'சரி' என அமைக்கப்பட்டாலோ உள்ளமைக்கப்படவில்லை என்றாலோ OS மேம்பாட்டைத் தொடர்ந்து முதல்முறை துவங்கும் போது, உலாவியானது வரவேற்புப் பக்கத்தை மீண்டும் காட்டும்.
+
+      இந்தக் கொள்கை 'தவறு' என அமைக்கப்பட்டால் OS மேம்பாட்டைத் தொடர்ந்து முதல்முறை துவங்கும் போது, உலாவியானது வரவேற்புப் பக்கத்தை மீண்டும் காட்டாது.</translation>
 <translation id="4418726081189202489">இந்தக் கொள்கையைத் "தவறு" என அமைத்தால், துல்லியமான நேரமுத்திரையைப் பெறுவதற்காக Google சேவையகத்திற்கு <ph name="PRODUCT_NAME" /> அவ்வப்போது வினவல்களை அனுப்புவது நிறுத்தப்படும். இந்தக் கொள்கையைச் "சரி" என அமைத்தாலோ அல்லது அமைக்காமல் விட்டாலோ, இந்த வினவல்கள் இயக்கப்படும்.</translation>
 <translation id="4423597592074154136">ப்ராக்ஸி  அமைப்புகளைக் கைமுறையாகக் குறிப்பிடு</translation>
 <translation id="4429220551923452215">புத்தகக்குறிப் பட்டியில் பயன்பாடுகளின் ஷார்ட்கட்டை இயக்குகிறது அல்லது முடக்குகிறது.
@@ -1522,6 +1740,7 @@
       மேலே உள்ள இயங்குதளங்களில் கொள்கை ஆதரிக்கப்பட்டிருந்தால் கூட, கொள்கை இயக்கும் அம்சம் சில இயங்குதளங்களில் மட்டும் கிடைக்கலாம். எல்லா மறுக்கப்பட்ட இணைய இயங்குதள அம்சங்களும் மீண்டும் இயக்கப்படாது. ஒவ்வொரு அம்சத்திற்கும் மாறுபடக்கூடிய, கீழே வெளிப்படையாக பட்டியலிடப்பட்டவை மட்டுமே குறிப்பிட்ட நேரத்திற்கு கிடைக்கும். எழுத்துச்சரக் குறியின் பொதுவான வடிவம்:  [DeprecatedFeatureName]_EffectiveUntil[yyyymmdd]. மேற்கோளாக, இணைய இயங்குதள அம்ச மாற்றங்களின் பின்னணியில் உள்ள நோக்கத்தை  https://bit.ly/blinkintents என்ற இணைய தளத்தில் காணலாம்.
       </translation>
 <translation id="4442582539341804154">சாதனம் செயலற்றுப்போனாலோ இடைநிறுத்தப்பட்டாலோ பூட்டை இயக்கு</translation>
+<translation id="4449469846627734399">Power peak shift day config கொள்கையை அமைக்கும்</translation>
 <translation id="4449545651113180484">திரையைக் கடிகாரத் திசையில் 270 டிகிரிக்குச் சுழற்று</translation>
 <translation id="445270821089253489">எந்த வகையான பயனர் மற்றும் சாதனத் தகவல்கள் அறிக்கையளிக்கப்படும் என்பதைக் கட்டுப்படுத்தும்.</translation>
 <translation id="4454820008017317557"><ph name="PRODUCT_NAME" /> கருவிப்பட்டி ஐகானைக் காட்டும்</translation>
@@ -1569,11 +1788,25 @@
 <translation id="4557134566541205630">இயல்புநிலை தேடல் வழங்குநர் புதிய தாவல் பக்க URL</translation>
 <translation id="4567137030726189378">டெவெலப்பர் கருவிகளின் பயன்பாட்டை அனுமதி</translation>
 <translation id="4578265298946081589">பயனர் வெளியேறும்போது மறுபடி தொடங்காது.</translation>
+<translation id="4578912515887794133">இந்த அமைப்பு இயக்கப்பட்டால் (ஹோஸ்ட்டுடன் இணைக்கப்படும்) அகப் பயனரின் பெயரும் ஹோஸ்ட் உரிமையாளராகப் பதிவு செய்யப்பட்டுள்ள Google கணக்கின் பெயரும் (அதாவது ஹோஸ்ட் "johndoe@example.com" என்ற Google கணக்கிற்குச் சொந்தமானதாக இருந்தால் உரிமையாளரின் பெயர் "johndoe" ஆகும்) தொலைநிலை அணுகல் ஹோஸ்ட் மூலம் ஒப்பிடப்படும்.  ஹோஸ்ட் உரிமையாளர் பெயரும் அந்த ஹோஸ்ட்டன் இணைக்கப்படும் அகப் பயனரின் பெயரும் வெவ்வேறாக இருந்தால் தொலைநிலை அணுகல் ஹோஸ்ட் தொடங்கப்படாது.  குறிப்பிட்ட டொமைனுடன் (அதாவது "example.com") தொடர்புடைய ஹோஸ்ட் உரிமையாளரின் Google கணக்கையும் செயல்படுத்த, RemoteAccessHostMatchUsername கொள்கையை RemoteAccessHostDomain கொள்கையுடன் ஒன்றாகப் பயன்படுத்த வேண்டும்.
+
+          இந்த அமைப்பு முடக்கப்பட்டாலோ அமைக்கப்படவில்லை என்றாலோ தொலைநிலை அணுகல் ஹோஸ்ட் எந்தவொரு அகப் பயனருடனும் இணைக்கப்படலாம்.</translation>
 <translation id="4600786265870346112">பெரிய இடஞ்சுட்டியை இயக்கு</translation>
 <translation id="4604931264910482931">நேட்டிவ் செய்தியிடல் தடுப்புப்பட்டியலை உள்ளமைத்தல்</translation>
 <translation id="4613508646038788144">கொள்கையானது "வேண்டாம்" என அமைக்கப்பட்டால், Chrome செயல்முறைகளில் செயலாக்கத்தக்க குறியீட்டை உட்செலுத்துவதற்கு மூன்றாம் தரப்பு மென்பொருள் அனுமதிக்கப்படும். கொள்கை அமைக்கப்படாமல் விட்டாலோ அல்லது "சரி" என அமைத்தாலோ, Chrome செயல்முறைகளில் செயலாக்கத்தக்க குறியீட்டை உட்செலுத்துவதிலிருந்து மூன்றாம் தரப்பு மென்பொருள் தடுக்கப்படும்.</translation>
 <translation id="4617338332148204752"><ph name="PRODUCT_FRAME_NAME" /> இல் மீக்குறி பயன்படுத்துவதைத் தவிர்</translation>
 <translation id="4625915093043961294">நீட்டிப்பு நிறுவுதல் அனுமதிப் பட்டியலை உள்ளமைக்கவும்</translation>
+<translation id="463224920692183755">ecryptfs என்கிரிப்ஷன் மூலம் பயனரின் முகப்புக் கோப்பகம் உருவாக்கப்பட்ட போது மேற்கொள்ள வேண்டிய மற்றும் ext4 என்கிரிப்ஷனுக்கு மாற்ற வேண்டிய நடவடிக்கையைக் குறிக்கும்.
+
+      இந்தக் கொள்கையை 'DisallowArc' என அமைத்தால் பயனருக்கு Android ஆப்ஸ் முடக்கப்படும், மேலும் ecryptfsஸிலிருந்து ext4 என்கிரிப்ஷனுக்கு நகர்த்த முடியாது. முகப்புக் கோப்பகம் ஏற்கனவே ext4 என்கிரிப்ட் செய்யப்பட்டிருந்தால் Android ஆப்ஸ் இயங்குவது தடுக்கப்படாது.
+
+      இந்தக் கொள்கையை 'Migrate' என அமைத்தால் ecryptfs என்கிரிப்ட் செய்த முகப்புக் கோப்பகங்கள் பயனரின் ஒப்புதலைக் கேட்காமல் உள்நுழையும் போது தானாகவே ext4 என்கிரிப்ஷனுக்கு நகர்த்தப்படும்.
+
+      இந்தக் கொள்கையை 'Wipe' என அமைத்தால் உள்நுழையும் போது ecryptfs என்கிரிப்ட் செய்த முகப்புக் கோப்பகங்கள் நீக்கப்படும். அவற்றுக்குப் பதிலாக ext4 என்கிரிப்ட் செய்த புதிய முகப்புக் கோப்பகங்கள் உருவாக்கப்படும். எச்சரிக்கை: இது பயனரின் அகத் தரவை அகற்றும்.
+
+      இந்தக் கொள்கையை 'AskUser' என அமைத்தால் ecryptfs என்கிரிப்ட் செய்த முகப்புக் கோப்பகங்களைக் கொண்ட பயனர்கள் நகர்த்துவதற்கு அனுமதிக்கப்படுவார்கள்.
+
+      இந்தக் கொள்கை kiosk பயனர்களுக்குப் பொருந்தாது. இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் சாதனம் 'DisallowArc' தேர்வுசெய்யப்பட்டது போல செயல்படும்.</translation>
 <translation id="4632343302005518762">பின்வரும் பட்டியலிடப்பட்ட உள்ளடக்க வகைகளைக் கையாள <ph name="PRODUCT_FRAME_NAME" /> ஐ அனுமதி</translation>
 <translation id="4632566332417930481">நிறுவனக் கொள்கையால் நிறுவப்படும் நீட்டிப்புகளில் டெவெலப்பர் கருவிகளின் பயன்பாட்டை அனுமதிக்காமல், மற்றவற்றில் அவற்றின் பயன்பாட்டை அனுமதிக்கும்</translation>
 <translation id="4633786464238689684">மேல் வரிசையில் உள்ள விசைகளின் இயல்புநிலை செயலைச் செயல்பாட்டு விசைகளுக்கு மாற்றுகிறது.
@@ -1686,11 +1919,52 @@
 <translation id="4986560318567565414">மாற்று உலாவியிலிருந்து Chrome மாறுவதற்கான தடம்.</translation>
 <translation id="4988291787868618635">செயலற்ற நிலை தாமதத்தை அடைந்தவுடன் எடுக்க வேண்டிய நடவடிக்கை</translation>
 <translation id="4995548127349206948">NTLMv2 அங்கீகரிப்பு இயக்கப்பட்டுள்ளதா.</translation>
+<translation id="5030889661505907084">
+      கொள்கை 'சரி' என அமைக்கப்பட்டால் இயங்குதளக் கொள்கைக்கு முரணாக இருக்கும்பட்சத்தில் கிளவுட் கொள்கைக்கு முன்னுரிமை அளிக்கப்படும்.
+      கொள்கை 'தவறு' என அமைக்கப்பட்டாலோ உள்ளமைக்கப்படவில்லை என்றாலோ கிளவுட் கொள்கைக்கு முரணாக இருக்கும்பட்சத்தில் இயங்குதளக் கொள்கைக்கு முன்னுரிமை அளிக்கப்படும்.
+
+      இந்தக் கொள்கை இயங்குதளமாக மட்டுமே கிடைக்கும்.
+      </translation>
+<translation id="5034604678285451405">Power peak shift பேட்டரியின் ஆற்றல் வரம்பை சதவீதத்தில் அமைக்கவும்.
+
+          DevicePowerPeakShiftEnabled 'சரி' என அமைத்தால் மட்டுமே இந்தக் கொள்கையைப் பயன்படுத்த இயலும்.
+
+          இந்தக் கொள்கையை உள்ளமைக்கவில்லை என்றாலோ அமைக்கவில்லை என்றாலோ power peak shift முடக்கப்பட்ட நிலையிலேயே இருக்கும்.</translation>
 <translation id="5047604665028708335">உள்ளடக்கத் தொகுப்புகளுக்கு வெளியே உள்ள தளங்களுக்கான அணுகலை அனுமதி</translation>
 <translation id="5052081091120171147">இந்த கொள்கை செயலாக்கப்பட்டிருந்தால் தற்போதைய இயல்புநிலை உலாவியில் இருந்து, உலாவுதல் வரலாற்றை இறக்குமதி செய்ய வேண்டும் என்பதை வற்புறுத்தும். செயலாக்கப்பட்டிருந்தால், இறக்குமதி உரையாடலையும் இந்தக் கொள்கை பாதிக்கும். முடக்கப்பட்டிருந்தால், உலாவுதல் வரலாறு இறக்குமதியாகாது. இது அமைக்கப்படவில்லை எனில், இறக்குமதி செய்யலாமா என பயனரிடம் கேட்கப்படும் அல்லது தானாக இறக்குமதியாகும்</translation>
+<translation id="5055312535952606505"><ph name="PRODUCT_NAME" />க்கான ப்ராக்ஸி அமைப்புகளை உள்ளமைக்கும். இந்த ப்ராக்ஸி அமைப்புகள் ARC ஆப்ஸுக்கும் கிடைக்கும்.
+
+          இந்த அமைப்பை இயக்கினால் கட்டளை வரியில் குறிப்பிடப்படும் ப்ராக்ஸி தொடர்பான எல்லா விருப்பங்களையும் <ph name="PRODUCT_NAME" /> மற்றும் ARC ஆப்ஸ் புறக்கணிக்கும்.
+
+          இந்தக் கொள்கையை அமைக்கவில்லை என்றால் பயனர்கள் தாங்களே ப்ராக்ஸி அமைப்புகளைத் தேர்வுசெய்து கொள்ள அனுமதிக்கப்படுவார்கள்.
+
+          <ph name="PROXY_SETTINGS_POLICY_NAME" /> கொள்கை அமைக்கப்பட்டால் <ph name="PROXY_MODE_POLICY_NAME" />, <ph name="PROXY_PAC_URL_POLICY_NAME" />, <ph name="PROXY_SERVER_POLICY_NAME" />, <ph name="PROXY_BYPASS_POLICY_NAME" />, <ph name="PROXY_SERVER_MODE_POLICY_NAME" /> ஆகிய தனிப்பட்ட கொள்கைகளில் ஒன்றை மேலெழுதும்.
+
+          <ph name="PRODUCT_NAME" /> பயன்படுத்தும் ப்ராக்ஸி சர்வரைக் குறிக்க <ph name="PROXY_MODE_PROXY_SETTINGS_FIELD" /> புலம் உங்களை அனுமதிக்கும், பயனர்கள் ப்ராக்ஸி அமைப்புகளை மாற்றுவதைத் தடுக்கும்.
+
+          <ph name="PROXY_PAC_URL_PROXY_SETTINGS_FIELD" /> புலம் என்பது ப்ராக்ஸி .pac கோப்பிற்கான URL ஆகும்.
+
+          <ph name="PROXY_SERVER_PROXY_SETTINGS_FIELD" /> புலம் என்பது ப்ராக்ஸி சர்வரின் URL ஆகும்.
+
+          <ph name="PROXY_BYPASS_LIST_PROXY_SETTINGS_FIELD" /> புலம் என்பது <ph name="PRODUCT_NAME" /> கடந்துசெல்லும் ப்ராக்ஸி ஹோஸ்ட்களின் பட்டியலாகும்.
+
+          <ph name="PROXY_SERVER_MODE_PROXY_SETTINGS_FIELD" /> புலம் 'ProxyMode' புலத்திற்குச் சாதகமாகத் தடுக்கப்பட்டுள்ளது. இது <ph name="PRODUCT_NAME" /> பயன்படுத்தும் ப்ராக்ஸி சர்வரைக் குறிப்பிட உங்களை அனுமதித்து, பயனர்கள் ப்ராக்ஸி அமைப்புகளை மாற்றுவதைத் தடுக்கும்.
+
+          'நேரடி' என்ற மதிப்பை 'ProxyMode' ஆகத் தேர்வுசெய்தால் ப்ராக்ஸி பயன்படுத்தப்படாது, மேலும் மற்ற எல்லாப் புலங்களும் புறக்கணிக்கப்படும்.
+
+          'சிஸ்டம்' என்ற மதிப்பை 'ProxyMode' ஆகத் தேர்வுசெய்தால் சிஸ்டத்தின் ப்ராக்ஸி பயன்படுத்தப்பட்டு, மற்ற எல்லாப் புலங்களும் புறக்கணிக்கப்படும்.
+
+          'auto_detect' என்ற மதிப்பை 'ProxyMode' ஆகத் தேர்வுசெய்தால் மற்ற எல்லாப் புலங்களும் புறக்கணிக்கப்படும்.
+
+          'fixed_server' என்ற மதிப்பை 'ProxyMode' ஆகத் தேர்வுசெய்தால் 'ProxyServer' மற்றும் 'ProxyBypassList' புலங்கள் பயன்படுத்தப்படும்.
+
+          'pac_script' என்ற மதிப்பை 'ProxyMode' ஆகத் தேர்வுசெய்தால் 'ProxyPacUrl' மற்றும் 'ProxyBypassList' புலங்கள் பயன்படுத்தப்படும்.</translation>
 <translation id="5056708224511062314">திரை உருப்பெருக்கி முடக்கப்பட்டது</translation>
 <translation id="5058573563327660283">தானியங்கு சுத்தப்படுத்தலின்போது வட்டு இடத்தைக் காலியாக்குவதற்கான உத்தியைத் தேர்ந்தெடுக்கும் (தடுக்கப்பட்டது)</translation>
 <translation id="5067143124345820993">உள்நுழைவு பயனர் அனுமதிப் பட்டியல்</translation>
+<translation id="5075834892754086022">இந்தக் கொள்கை அமைக்கப்பட்டால் உள்ளமைக்கப்படும் குறைந்தபட்ச பின் நீளம் செயல்படுத்தப்படும். (பின்னின் முழுமையான குறைந்தபட்ச நீளம் 1; 1க்குக் குறைவான மதிப்புகள் 1 ஆகக் கருதப்படும்.)
+
+          கொள்கை அமைக்கப்படவில்லை எனில் பின்னின் குறைந்தபட்ச நீளமான 6 இலக்கங்கள் செயல்படுத்தப்படும். இதுவே பரிந்துரைக்கப்படும் குறைந்தபட்ச நீளமாகும்.</translation>
 <translation id="5076274878326940940">இயல்புத் தேடல் வழங்குநரைப் பயன்படுத்துவதை இயக்குகிறது.
 
           இந்த அமைப்பை இயக்கினால், பயனர் சர்வபுலத்தில் URL அல்லாத உரையை உள்ளிடும்போது ஓர் இயல்புத் தேடல் நிகழ்த்தப்படும்.
@@ -1743,6 +2017,24 @@
       கால இடைவெளி 30 வினாடிகளும், அதிகபட்சக் கால இடைவெளி 24 மணிநேரமும் ஆகும் - இந்த
       வரம்பில் இல்லாத மதிப்புகள், இந்த வரம்பிற்கு மாற்றியமைக்கப்படும்.</translation>
 <translation id="5163002264923337812">பழைய இணையம் சார்ந்த உள்நுழைவை இயக்கும்</translation>
+<translation id="5168529971295111207">இந்தக் கொள்கை தடுக்கப்பட்டுள்ளதால் இதற்குப் பதிலாக ProxyMode கொள்கையைப் பயன்படுத்தவும்.
+
+          <ph name="PRODUCT_NAME" /> பயன்படுத்தும் ப்ராக்ஸி சர்வரைக் குறிப்பிட உங்களை அனுமதிக்கும், பயனர்கள் ப்ராக்ஸி அமைப்புகளை மாற்றுவதைத் தடுக்கும்.
+
+          <ph name="PROXY_SETTINGS_POLICY_NAME" /> கொள்கை குறிப்பிடப்படவில்லை என்றால் மட்டுமே இந்தக் கொள்கை செயல்படுத்தப்படும்.
+
+          ப்ராக்ஸி சர்வரைப் பயன்படுத்த வேண்டாம் என்றும் எப்போதும் நேரடியாக இணைக்க வேண்டும் என்றும் தேர்வுசெய்தால் மற்ற எல்லா விருப்பங்களும் புறக்கணிக்கப்படும்.
+
+          சிஸ்டம் ப்ராக்ஸி அமைப்புகளைப் பயன்படுத்தும்படியோ ப்ராக்ஸி சர்வரைத் தானாகக் கண்டறியும்படியோ தேர்வுசெய்தால் மற்ற எல்லா விருப்பங்களும் புறக்கணிக்கப்படும்.
+
+          கைமுறை ப்ராக்ஸி அமைப்புகளைத் தேர்வுசெய்தால் 'ப்ராக்ஸி சர்வரின் முகவரி அல்லது URL', 'ப்ராக்ஸி .pac கோப்பிற்கான URL', 'காற்புள்ளியால் பிரிக்கப்பட்ட ப்ராக்ஸி கடந்துபோதல் விதிகளின் பட்டியல்' ஆகியவற்றில் கூடுதல் விருப்பங்களைக் குறிப்பிடலாம். அதிகப்படியான முன்னுரிமை கொண்ட HTTP ப்ராக்ஸி சர்வர் மட்டுமே ARC ஆப்ஸுக்குக் கிடைக்கும்.
+
+          விரிவான உதாரணங்களைப் பார்க்க இந்த URLலுக்குச் செல்லவும்:
+          <ph name="PROXY_HELP_URL" />.
+
+          இந்த அமைப்பை இயக்கினால் கட்டளை வரியில் குறிப்பிடப்படும் ப்ராக்ஸி தொடர்பான எல்லா விருப்பங்களையும் <ph name="PRODUCT_NAME" /> புறக்கணிக்கும்.
+
+          இந்தக் கொள்கையை அமைக்கவில்லை என்றால் பயனர்கள் தாங்களே ப்ராக்ஸி அமைப்புகளைத் தேர்வுசெய்து கொள்ள அனுமதிக்கப்படுவார்கள்.</translation>
 <translation id="5182055907976889880"><ph name="PRODUCT_OS_NAME" /> இல் Google இயக்ககத்தை உள்ளமைக்கவும்.</translation>
 <translation id="5183383917553127163">தடுப்பு பட்டியலுக்கு உட்படாத நீட்டிப்புகளைக் குறிப்பிட உங்களை அனுமதிக்கிறது.
 
@@ -1783,6 +2075,20 @@
 
       இந்தக் கொள்கையானது மில்லிவினாடிகளில் குறிப்பிடப்பட்டிருக்கும்.</translation>
 <translation id="523505283826916779">அணுகல்தன்மை அமைப்புகள்</translation>
+<translation id="5236882091572996759">இந்தக் கொள்கை 'சரி' என அமைக்கப்பட்டாலோ அமைக்கப்படவில்லை என்றாலோ ஆடியோ இயக்கத்தில் இருக்கும் போது பயனர் செயலற்று இருப்பதாகக் கருதப்படமாட்டார். இது செயலற்ற தாமதநிலை நிகழ்வதையும் அதற்காக மேற்கொள்ளப்படும் நடவடிக்கைகளையும் தடுக்கும். இருப்பினும், உள்ளமைக்கப்படும் நேர முடிவுகளுக்குப் பிறகு ஆடியோ செயல்பாட்டைப் பொருட்படுத்தாமல் திரையை மங்கலாக்குதல், திரை முடக்கப்படுதல் திரைப் பூட்டப்படுதல் ஆகியவை செயல்படுத்தப்படும்.
+
+          இந்தக் கொள்கை 'தவறு' என அமைக்கப்பட்டால் பயனர்கள் செயலற்று இருப்பதாகக் கருதப்படுவதை ஆடியோ இயக்கம் தடுக்காது.</translation>
+<translation id="5246700266104954355">இந்தக் கொள்கை தடுக்கப்பட்டுள்ளது. ஃபிளாஷ் செருகுநிரலின் கிடைக்கும்தன்மையைக் கட்டுப்படுத்த <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME" />ஐப் பயன்படுத்தவும், மேலும் PDF கோப்புகளைத் திறப்பதற்கு ஒருங்கிணைந்த PDF வியூவர் பயன்படுத்தப்பட வேண்டுமா என்பதைக் கட்டுப்படுத்த <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME" />ஐப் பயன்படுத்தவும்.
+
+      <ph name="PRODUCT_NAME" />ல் இயக்கப்பட்டுள்ள செருகுநிரல்களின் பட்டியலைக் குறிக்கும், பயனர்கள் இந்த அமைப்பை மாற்றுவதைத் தடுக்கும்.
+
+      வைல்டுகார்டு எழுத்துகளான '*', '?' ஆகியவை தன்னிச்சையான எழுத்துகளின் வரிசைமுறைகளைப் பொருத்தப் பயன்படுத்தப்படலாம். '?' என்பது விருப்பத்திற்குரிய ஒற்றை எழுத்தைக் குறிக்கும் அதேநேரம் '*' என்பது தன்னிச்சையான எழுத்துகளின் எண்ணிக்கையைப் பொருத்தும். அதாவது பூஜ்ஜியம் அல்லது ஓர் எழுத்தைப் பொருத்தும். விடுபடு எழுத்து '\' என்பதால் உண்மையான '*', '?' அல்லது '\' எழுத்துகளைப் பொருத்த அவற்றுக்கு முன் '\' எழுத்தைச் சேர்க்கலாம்.
+
+      குறிப்பிடப்படும் செருகுநிரல்களின் பட்டியல் நிறுவப்பட்டால் எப்போதும் <ph name="PRODUCT_NAME" />ல் பயன்படுத்தப்படும். செருகுநிரல்கள் 'about:plugins' என்பதில் இயக்கப்படும், பயனர்கள் அவற்றை முடக்க முடியாது.
+
+      இந்தக் கொள்கை DisabledPlugins, DisabledPluginsExceptions ஆகிய இரண்டையும் மேலெழுதும் என்பதை நினைவில் கொள்ளவும்.
+
+      இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் சிஸ்டத்தில் நிறுவப்பட்டிருக்கும் எந்தவொரு செருகுநிரலையும் பயனர் முடக்கலாம்.</translation>
 <translation id="5247006254130721952">ஆபத்துக்குரிய பதிவிறக்கங்களைத் தடு</translation>
 <translation id="5248863213023520115"><ph name="MS_AD_NAME" /> சேவையகத்தில் இருந்து Kerberos டிக்கெட்களைக் கோரும் போது, அனுமதிக்கப்படும் என்க்ரிப்ஷன் வகைகளை அமைக்கும்.
 
@@ -1824,6 +2130,7 @@
 
       இல்லையெனில், அது "tls1.2" அல்லது "tls1.3" ஆகிய மதிப்புகளில் ஏதேனும் ஒன்றுக்கு அமைக்கப்படலாம். அவ்வாறு அமைக்கப்பட்டால், குறிப்பிடப்பட்டுள்ள பதிப்பிற்கு மேற்பட்ட SSL/TLS பதிப்புகளை <ph name="PRODUCT_NAME" /> பயன்படுத்தாது. அங்கீகரிக்கப்படாத மதிப்பு புறக்கணிக்கப்படும்.</translation>
 <translation id="5330684698007383292">பின்வரும் உள்ளடக்க வகைகளைக் கையாள <ph name="PRODUCT_FRAME_NAME" /> ஐ அனுமதி</translation>
+<translation id="5331746669335642668"><ph name="PRODUCT_NAME" /> கிளவுட் கொள்கை இயங்குதளக் கொள்கையை மேலெழுதும்.</translation>
 <translation id="5365476955714838841">மாற்று உலாவிக்கான கட்டளை வரி அளவுருக்கள்.</translation>
 <translation id="5365946944967967336">கருவிப்பட்டியில் முகப்புப் பொத்தானைக் காண்பி</translation>
 <translation id="5366745336748853475">தளம் சான்றிதழைக் கோரினால், SAML செயல்பாட்டை ஹோஸ்ட் செய்யும் ஃப்ரேமில் உள்ள உள்நுழைவுத் திரையில், கிளையண்ட் சான்றிதழைத் தானாகத் தேர்ந்தெடுக்க வேண்டிய தளங்களைக் குறிப்பிடும் url வடிவங்களின் பட்டியலைக் குறிப்பிட உங்களை அனுமதிக்கும். SAML IdPக்கு வழங்குவதற்காக, சாதன அளவிலான சான்றிதழை உள்ளமைப்பதை இதற்கு உதாரணமாகக் குறிப்பிடலாம்.
@@ -1863,10 +2170,20 @@
 <translation id="5405289061476885481"><ph name="PRODUCT_OS_NAME" /> உள்நுழைவுத் திரையில் அனுமதிக்கப்படும் விசைப்பலகைத் தளவமைப்புகளை உள்ளமைக்கும்.
 
       இந்தக் கொள்கை, உள்ளீட்டு முறை அடையாளங்காட்டிகளின் பட்டியலாக அமைக்கப்பட்டால், வழங்கிய உள்ளீட்டுப் பயன்முறைகள் உள்நுழைவுத் திரையில் கிடைக்கும். முதலில் வழங்கிய உள்ளீட்டு முறையானது முன்கூட்டியே தேர்ந்தெடுக்கப்பட்டிருக்கும். உள்நுழைவுத் திரையில் பயனர் பாட் ஃபோகஸ் செய்துக் கொண்டிருக்கும் போது, இந்தக் கொள்கை வழங்கும் உள்ளீட்டு முறைகளுடன் சேர்த்து பயனர் கடைசியாகப் பயன்படுத்திய உள்ளீட்டு முறையும் கிடைக்கும். இந்தக் கொள்கை அமைக்கப்படவில்லை எனில், உள்நுழைவுத் திரை காட்டப்படும் மொழியிலிருந்து உள்நுழைவுத் திரையில் உள்ளீட்டு முறைகள் பெறப்படும். தவறான உள்ளீட்டு முறை அடையாளங்காட்டிகள் உள்ள மதிப்புகள் புறக்கணிக்கப்படும்.</translation>
+<translation id="5412057811596122582">இயக்கப்பட்டாலோ உள்ளமைக்கப்படவில்லை என்றாலோ (இயல்புநிலை) அறிவுறுத்தாமல் அணுகல் வழங்கப்படும் AudioCaptureAllowedUrls  பட்டியலில் உள்ளமைக்கப்படும் URLகள் தவிர, ஆடியோவைப் பதிவு செய்வதற்கான அணுகலுக்கு பயனர் அறிவுறுத்தப்படுவார்.
+
+      இந்தக் கொள்கை முடக்கப்பட்டால் பயனருக்கு அறிவுறுத்தப்படாது, மேலும் ஆடியோவைப் பதிவு செய்வது AudioCaptureAllowedUrls பட்டியலில் உள்ளமைக்கப்படும் URLகளுக்கு மட்டுமே கிடைக்கும்.
+
+      இந்தக் கொள்கை உள்ளமைந்த மைக்ரோஃபோனை மட்டுமின்றி எல்லா வகையான ஆடியோ உள்ளீடுகளிலும் மாற்றத்தை ஏற்படுத்தும்.</translation>
 <translation id="5422643441807528365"><ph name="PLUGIN_VM_NAME" /> உரிமக் குறியீடு</translation>
 <translation id="5423001109873148185">இந்தக் கொள்கை செயலாக்கப்பட்டிருந்தால் தற்போதைய இயல்புநிலை உலாவியில் இருந்து தேடல் இன்ஜின்கள் இறக்குமதி செய்யப்பட வேண்டும் என்பதை வற்புறுத்தும். செயலாக்கப்பட்டிருந்தால் இறக்குமதி உரையாடலையும் இந்தக் கொள்கை பாதிக்கும். முடக்கப்பட்டிருந்தால் இயல்புநிலையான தேடல் இன்ஜின் இறக்குமதியாகாது. இது அமைக்கப்படவில்லை எனில் இறக்குமதி செய்யலாமா என பயனரிடம் கேட்கப்படும் அல்லது தானாக இறக்குமதியாகும்.</translation>
 <translation id="5423197884968724595">Android WebView வரம்புப் பெயர்:</translation>
 <translation id="5424147596523390018">அனைத்து வண்ணப் பயன்முறைகளையும் அனுமதி</translation>
+<translation id="5437733496511628148">இந்த அமைப்பை இயக்கினால் உலாவியின் முகவரிப் பட்டியில் இல்லாத இணையப் பக்க உறுப்புகளால் அமைக்கப்படுவதில் இருந்து குக்கீகளைத் தடுக்கும்.
+
+      இந்த அமைப்பை முடக்கினால் உலாவியின் முகவரிப் பட்டியில் இல்லாத இணையப் பக்க உறுப்புகளால் அமைக்கப்படுவதற்கு குக்கீகளை அனுமதிக்கும், பயனர்கள் இந்த அமைப்பை மாற்றுவதைத் தடுக்கும்.
+
+      இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் மூன்றாம் தரப்பு குக்கீகள் இயக்கப்படும், ஆனால் பயனர்கள் அதை மாற்ற முடியும்.</translation>
 <translation id="5442026853063570579">Android டெவெலப்பர் விருப்பங்களுக்கான அணுகலையும் இந்தக் கொள்கை கட்டுப்படுத்தும். இந்தக் கொள்கையை 'DeveloperToolsDisallowed' (மதிப்பு 2) என அமைத்தால், பயனர்களால் டெவெலப்பர் விருப்பங்களை அணுக முடியாது. இந்தக் கொள்கையை வேறொரு மதிப்பில் அமைத்தாலோ அல்லது அமைக்காமல் விட்டாலோ, Android அமைப்புகள் பயன்பாட்டில் இருக்கும் பதிப்பு எண்ணை ஏழு முறை தட்டுவதன் மூலம், பயனர்களால் டெவெலப்பர் விருப்பங்களை அணுக முடியும்.</translation>
 <translation id="544342220587994947">தளம் சான்றிதழைக் கோரினால், <ph name="PRODUCT_NAME" /> தானாகவே கிளையண்ட் சான்றிதழைத் தேர்ந்தெடுக்க வேண்டிய தளங்களைக் குறிப்பிடும் url பேட்டர்ன்களின் பட்டியலைக் குறிப்பிட உங்களை அனுமதிக்கும்.
 
@@ -1877,6 +2194,7 @@
 <translation id="5457065417344056871">உலாவியில் விருந்தினர் பயன்முறையை இயக்கும்</translation>
 <translation id="5457924070961220141"><ph name="PRODUCT_FRAME_NAME" /> நிறுவியிருக்கும்போது, இயல்புநிலை HTML ரென்டரரை உள்ளமைக்க உங்களை அனுமதிக்கிறது. 
       இந்தக் கொள்கை அமைக்கப்படாமல் இருக்கும்போது இயல்புநிலையாக ஹோஸ்ட் உலாவியே ரென்டரிங் செய்ய அனுமதிக்கப்படுகிறது. ஆனால், நீங்கள் விரும்பினால் இதை மேலெழுதி இயல்புநிலையாக <ph name="PRODUCT_FRAME_NAME" /> மூலம் HTML பக்கங்களை ரென்டர் செய்ய வைக்கலாம்.</translation>
+<translation id="5458584148602890023">Power peak shiftடை இயக்கும்</translation>
 <translation id="5464816904705580310">நிர்வகிக்கப்படும் பயனர்களுக்கான அமைப்புகளை உள்ளமை.</translation>
 <translation id="546726650689747237">AC சக்தியில் இயங்கும்போது திரை மங்கல் தாமதமாகும்</translation>
 <translation id="5469143988693423708">Crostiniயை இயக்க, பயனர் அனுமதிக்கப்பட்டுள்ளார்</translation>
@@ -1894,6 +2212,19 @@
       விதிகள் முரண்பட்டால், <ph name="PRODUCT_NAME" /> மிகப் பொருத்தமான விதியைப் பயன்படுத்தும்.</translation>
 <translation id="5475361623548884387">அச்சிடலை இயக்கு</translation>
 <translation id="547601067149622666">குறுக்கிடும் விளம்பரங்களுடன்கூடிய தளங்களில் விளம்பரங்களை அனுமதிக்காதே</translation>
+<translation id="5483777239978559943">இந்தக் கொள்கை தடுக்கப்பட்டுள்ளது. ஃபிளாஷ் செருகுநிரலின் கிடைக்கும்தன்மையைக் கட்டுப்படுத்த <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME" />ஐப் பயன்படுத்தவும், மேலும் PDF கோப்புகளைத் திறப்பதற்கு ஒருங்கிணைந்த PDF வியூவர் பயன்படுத்தப்பட வேண்டுமா என்பதைக் கட்டுப்படுத்த <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME" />ஐப் பயன்படுத்தவும்.
+
+      <ph name="PRODUCT_NAME" />ல் பயனர் இயக்கக்கூடிய அல்லது முடக்கக்கூடிய செருகுநிரல்களின் பட்டியலைக் குறிக்கும்.
+
+      வைல்டுகார்டு எழுத்துகளான '*', '?' ஆகியவை தன்னிச்சையான எழுத்துகளின் வரிசைமுறைகளைப் பொருத்தப் பயன்படுத்தப்படலாம். '?' என்பது விருப்பத்திற்குரிய ஒற்றை எழுத்தைக் குறிக்கும் அதேநேரம் '*' என்பது தன்னிச்சையான எழுத்துகளின் எண்ணிக்கையைப் பொருத்தும். அதாவது பூஜ்ஜியம் அல்லது ஒரு எழுத்தைப் பொருத்தும். விடுபடு எழுத்து '\' என்பதால் உண்மையான '*', '?' அல்லது '\' எழுத்துகளைப் பொருத்த அவற்றுக்கு முன் '\' எழுத்தைச் சேர்க்கலாம்.
+
+      இந்த அமைப்பை இயக்கினால், குறிப்பிடப்படும் செருகுநிரல்களின் பட்டியல் <ph name="PRODUCT_NAME" />ல் பயன்படுத்தப்படும். செருகுநிரலானது DisabledPlugins ன் பேட்டர்னுடன் பொருந்தினாலும்கூட, பயனர்கள் அவற்றை 'about:plugins' என்பதில் இயக்கலாம் அல்லது முடக்கலாம். DisabledPlugins, DisabledPluginsExceptions, EnabledPlugins ஆகியவற்றின் பேட்டர்ன்களுடன் பொருந்தாத செருகுநிரல்களையும் பயனர்கள் இயக்கலாம், முடக்கலாம்.
+
+      இந்தக் கொள்கை செருகுநிரலை கண்டிப்பான முறையில் தடைசெய்ய அனுமதிக்கும், அதாவது 'DisabledPlugins' பட்டியலில் '*' (எல்லா செருகுநிரல்களையும் முடக்கும்) அல்லது '*Java*' (எல்லா Java செருகுநிரல்களையும் முடக்கும்) போன்ற வைல்டுகார்டு உள்ளீடுகள் இருக்கும். ஆனால் நிர்வாகி 'IcedTea Java 2.3' போன்ற சில குறிப்பிட்ட பதிப்பை இயக்க விரும்புகிறார். இந்தக் குறிப்பிட்ட பதிப்புகளை இந்தக் கொள்கையில் குறிப்பிடலாம்.
+
+      செருகுநிரல் பெயர் மற்றும் செருகுநிரலின் குழுப் பெயர் ஆகிய இரண்டிற்கும் விலக்களிக்கப்பட வேண்டும் என்பதை நினைவில் கொள்ளவும். ஒவ்வொரு செருகுநிரல் குழுவும் 'about:plugins'ஸின் தனிப்பட்ட பிரிவில் காட்டப்படுகின்றன; ஒவ்வொரு பிரிவிலும் ஒன்று அல்லது அதற்கும் அதிகமான செருகுநிரல்கள் இருக்கக்கூடும். எடுத்துக்காட்டாக, "Shockwave Flash" எனும் செருகுநிரல் "Adobe Flash Player" குழுவைச் சார்ந்ததாகும், மேலும் அந்தச் செருகுநிரலை தடுப்புப்பட்டியலில் இருந்து விலக்க வேண்டுமெனில், இரண்டு பெயர்களும் விதிவிலக்குகள் பட்டியலில் பொருந்த வேண்டும்.
+
+      இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் 'DisabledPlugins'ஸின் பேட்டர்ன்களுடன் பொருந்தும் எந்தச் செருகுநிரலும் பூட்டப்பட்டு, முடக்கப்படும். பயனர் அவற்றை இயக்க முடியாது.</translation>
 <translation id="5499375345075963939">இந்தக் கொள்கை விற்பனை பயன்முறையில் மட்டுமே செயலில் இருக்கும்.
 
       இந்தக் கொள்கையின் மதிப்பு அமைக்கப்பட்டு, அது 0 ஆக இருந்தால், குறிப்பிட்ட காலஅளவின் செயலற்ற நேரம் கழிந்தப் பிறகு உள்நுழைந்த டெமோ பயனர் தானாக வெளியேற்றப்படுவார்.
@@ -1929,6 +2260,13 @@
       குறிப்பிடப்படவில்லை எனில், மாறுபாடுகள் ஸீட் URL திருத்தப்படாது.</translation>
 <translation id="5561811616825571914">உள்நுழைவுத் திரையில் இந்தத் தளங்களின் கிளையண்ட் சான்றிதழ்களைத் தானாகத் தேர்ந்தெடுக்கவும்</translation>
 <translation id="5566210228171064229">’பின்’ உள்ளபோதும் இல்லாமல் இருக்கும்போதும் அச்சிடுதலை அனுமதிக்கும்</translation>
+<translation id="556865034069957245"><ph name="PRODUCT_NAME" /> UI அனைத்தும் மறைக்கப்பட்டு, இணைய உள்ளடக்கம் மட்டும் பார்க்கக்கூடியதாய் இருக்கும் 'முழுத்திரைப் பயன்முறையின்' கிடைக்கும்தன்மையை இந்தக் கொள்கை கட்டுப்படுத்தும்.
+
+      இந்தக் கொள்கை 'சரி' என அமைக்கப்பட்டாலோ உள்ளமைக்கப்படவில்லை என்றாலோ தேவையான அனுமதிகளைக் கொண்டிருக்கும் பயனர், ஆப்ஸ், நீட்டிப்புகள் ஆகியவை 'முழுத்திரைப் பயன்முறையில்' நுழையலாம்.
+
+      இந்தக் கொள்கை 'தவறு' என அமைக்கப்பட்டால் பயனர், ஆப்ஸ் அல்லது நீட்டிப்புகள் எதுவும் 'முழுத்திரைப் பயன்முறையில்' நுழைய முடியாது.
+
+      <ph name="PRODUCT_OS_NAME" /> தவிர அனைத்து இயங்குதளங்களிலும் 'முழுத்திரைப் பயன்முறை' முடக்கத்தில் இருக்கும் போது கியோஸ்க் பயன்முறை கிடைக்காது.</translation>
 <translation id="556941986578702361"><ph name="PRODUCT_OS_NAME" /> அடுக்கைத் தானாக மறைப்பதைக் கட்டுப்படுத்தலாம்.
 
       இந்தக் கொள்கையானது 'AlwaysAutoHideShelf' ஆக அமைக்கப்பட்டிருக்கும்போது, அடுக்கு எப்போதும் தானாக மறைக்கப்படும்.
@@ -1946,6 +2284,11 @@
 <translation id="5581292529942108810">Chrome அறிக்கையிடுதல் நீட்டிப்பு தொடர்பான கொள்கைகளை உள்ளமைக்கும்.
 
       <ph name="CHROME_REPORTING_EXTENSION_NAME" /> இயக்கப்பட்டு, <ph name="MACHINE_LEVEL_USER_CLOUD_POLICY_ENROLLMENT_TOKEN_POLICY_NAME" /> இல் சாதனம் பதிவு செய்யப்பட்டால் மட்டுமே, இந்தக் கொள்கை செயலில் இருக்கும்.</translation>
+<translation id="5583806683960333345">இந்த அமைப்பு இயக்கப்பட்டால் பயனர்கள் உடனடி இணைப்பு முறையைப் பயன்படுத்துவதற்கு அனுமதிக்கப்படுவார்கள். இதன் மூலம் அவர்களது Google மொபைல் அதன் மொபைல் டேட்டாவை அவர்களது சாதனத்துடன் பகிரலாம்.
+
+      இந்த அமைப்பு முடக்கப்பட்டால் பயனர்கள் உடனடி இணைப்பு முறையைப் பயன்படுத்த அனுமதிக்கப்பட மாட்டார்கள்.
+
+      இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் இயல்புநிலை அமைப்பானது என்டர்பிரைஸ் நிர்வகிக்கும் பயனர்களுக்கும் நிர்வகிக்கப்படாத பயனர்களுக்கும் அனுமதிக்கப்படாது.</translation>
 <translation id="5584132346604748282">Android Google இருப்பிடச் சேவைகளைக் கட்டுப்படுத்தும்</translation>
 <translation id="5586942249556966598">ஒன்றும் செய்ய வேண்டாம்</translation>
 <translation id="5590494712401018042">சாதனம் விளக்கக்காட்சிப் பயன்முறையில் இருக்கும்போது 'திரை மங்கல் தாமதம்' எந்தச் சதவீதத்தில் அளவிடப்படும் என்பதைக் குறிப்பிடும்.
@@ -1967,6 +2310,19 @@
       குறிப்பு: இந்தக் கொள்கை, கண்டிப்பாக 1ஜி.பை. RAMமுக்கு மேல் உள்ள Android சாதனங்களில் இயங்கும் Chromeமில் மட்டுமே பயன்படுத்தப்படும். Android அல்லாத இயங்குதளங்களில் இந்தக் கொள்கையைப் பயன்படுத்த, IsolateOrigins கொள்கையைப் பயன்படுத்தவும்.
       </translation>
 <translation id="5599461642204007579"><ph name="MS_AD_NAME" /> நிர்வாக அமைப்புகள்</translation>
+<translation id="5610104657949692379">இந்தக் கொள்கை அமைக்கப்பட்டால் செயலற்ற தாமதநிலை வழங்கும் நேரத்திற்கு பயனர் செயலற்று இருந்தால் <ph name="PRODUCT_OS_NAME" /> மேற்கொள்ளும் நடவடிக்கையை இது குறிக்கும். அந்த நேரத்தைத் தனியாக உள்ளமைக்கலாம்.
+
+          இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் இயல்பு நடவடிக்கையான இடைநிறுத்தத்தை மேற்கொள்ளும்.
+
+          நடவடிக்கை இடைநிறுத்தப்பட்டால், இடைநிறுத்தப்படுவதற்கு முன் திரையைப் பூட்டும்படியோ பூட்டாதபடியோ <ph name="PRODUCT_OS_NAME" />ஐத் தனித்தனியாக உள்ளமைக்கலாம்.</translation>
+<translation id="5618398258385745432">தொடர்புடைய அமைப்பானது கடவுச்சொற்களைக் காட்டுவது குறித்த மறுஅங்கீகரிப்பை அறிமுகப்படுத்துவதற்கு முன்பாகப் பயன்படுத்தப்பட்டுள்ளது. அதன் பிறகு அந்த அமைப்பும் இந்தக் கொள்கையும் Chromeமின் நடத்தையில் எந்தவித மாற்றத்தையும் ஏற்படுத்தவில்லை. 'கடவுச்சொல் நிர்வாகி அமைப்புகள்' பக்கத்தில் தெளிவான உரையில் கடவுச்சொற்கள் காட்டப்படுவதை முடக்கும்படி கொள்கையை அமைத்தால் இருக்கும் நடத்தையைப் போன்று Chromeமின் தற்போதைய நடத்தை உள்ளது. அதாவது அமைப்புகள் பக்கத்தில் வெறும் ஒதுக்கிடம் மட்டுமே உள்ளது, மேலும் 'காட்டு' என்பதைப் பயனர் கிளிக் செய்யும் போது (மற்றும் பொருந்தினால் மறுஅங்கீகாரம் வழங்கப்படும் போது) மட்டுமே கடவுச்சொற்களை Chrome காட்டும். கொள்கையில் அசல் விளக்கம் கீழே கொடுக்கப்பட்டுள்ளது.
+
+கடவுச்சொல் நிர்வாகியில் பயனர்களால் தங்கள் கடவுச்சொற்களை தெளிவான உரையில் பார்க்க முடியுமா என்பதைக் கட்டுப்படுத்தும்.
+
+இந்த அமைப்பை முடக்கினால் சேமிக்கப்படும் கடவுச்சொற்களை கடவுச்சொல் நிர்வாகிச் சாளரத்தில் காட்டுவதற்கு, கடவுச்சொல் நிர்வாகி அனுமதிக்காது.
+
+இந்தக் கொள்கையை இயக்கினாலோ அமைக்கவில்லை என்றாலோ கடவுச்சொல் நிர்வாகியில் பயனர்கள் தங்கள் கடவுச்சொற்களை தெளிவான உரையில் பார்க்கலாம்.</translation>
+<translation id="5620392548325769024">OS மேம்படுத்தலைத் தொடர்ந்து முதல் முறையாக உலாவியைத் துவங்கும் போது வரவேற்புப் பக்கத்தைக் காட்டுவதை இயக்கும்</translation>
 <translation id="5630352020869108293">கடைசி அமர்வை மீட்டமை</translation>
 <translation id="5645779841392247734">இந்த தளங்களில் குக்கீகளை அனுமதி</translation>
 <translation id="5689430183304951538">இயல்புநிலையில் அச்சிடும் பக்க அளவு</translation>
@@ -1990,6 +2346,7 @@
       இந்தக் கொள்கையை ‘சரி’ என அமைத்தாலோ அமைக்காமலேயே விட்டாலோ, நிர்வகிக்கப்பட்ட விருந்தினர் அமர்வானது “நிர்வகிக்கப்பட்ட அமர்வு” என்பதில் விவரிக்கப்பட்டுள்ளபடி செயல்படும், இது வழக்கமான “பொது அமர்வுகளுக்காக” நடைமுறையிலுள்ள பல கட்டுப்பாடுகளை நீக்கும்.
 
       இந்தக் கொள்கை அமைக்கப்பட்டிருந்தால், பயனரால் இதை மாற்றவோ மேலெழுதவோ முடியாது.</translation>
+<translation id="5708969689202733975">அனுமதிக்கப்படும் விரைவாகத் திறக்கும் பயன்முறைகளை உள்ளமைக்கும்</translation>
 <translation id="572155275267014074">Android அமைப்புகள்</translation>
 <translation id="5722934961007828462">இந்த அமைப்பு இயக்கப்படும்போது, வெற்றிகரமாகச் செல்லுபடியாக்கப்பட்ட, அக அமைவாக நிறுவப்பட்ட CA சான்றிதழ்களால் கையொப்பமிடப்பட்ட சேவையகச் சான்றிதழ்களுக்கு <ph name="PRODUCT_NAME" /> எப்போதுமே திரும்பப்பெறல் சரிபார்ப்பைச் செயல்படுத்தும்.
 
@@ -1998,6 +2355,11 @@
       இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் அல்லது தவறு என அமைக்கப்பட்டால், ஏற்கனவே உள்ள ஆன்லைன் திரும்பப்பெறல் சோதனை அமைப்புகளை <ph name="PRODUCT_NAME" /> பயன்படுத்தும்.</translation>
 <translation id="5728154254076636808"><ph name="PRODUCT_NAME" /> சுயவிவரத் தரவிற்கான ரோமிங் நகல்களை உருவாக்குவதை இயக்கு</translation>
 <translation id="5732972008943405952">முதல் இயக்கத்தின் போது இயல்புநிலை உலாவியிலிருந்து தன்னிரப்பிப் படிவத் தரவை இறக்குமதி செய்யும்</translation>
+<translation id="5741810844420698449">இந்தக் கொள்கை அமைக்கப்பட்டால் சாதனத்தின் மூடியை பயனர் மூடும் போது <ph name="PRODUCT_OS_NAME" /> மேற்கொள்ளும் நடவடிக்கையை இது குறிக்கும்.
+
+          இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் இயல்பு நடவடிக்கையான இடைநிறுத்தத்தை மேற்கொள்ளும்.
+
+          நடவடிக்கை இடைநிறுத்தப்பட்டால், இடைநிறுத்தப்படுவதற்கு முன் திரையைப் பூட்டும்படியோ பூட்டாதபடியோ <ph name="PRODUCT_OS_NAME" />ஐத் தனித்தனியாக உள்ளமைக்கலாம்.</translation>
 <translation id="5765780083710877561">விவரம்:</translation>
 <translation id="5770738360657678870">Dev சேனல் (நிலையற்றதாக இருக்கக்கூடும்)</translation>
 <translation id="5774856474228476867">இயல்புநிலை தேடல் வழங்குநர் தேடல் URL</translation>
@@ -2167,6 +2529,7 @@
 
 இந்தக் கொள்கை உள்ளமைக்கப்படவில்லை எனில், அகற்றத்தக்க USB சாதனங்களின் பட்டியல் காலியாக இருக்கும்.</translation>
 <translation id="6083631234867522991">Windows (Windows கிளையன்ட்டுகள்):</translation>
+<translation id="608788685013546076">Power peak shift பேட்டரியின் ஆற்றல் வரம்பைச் சதவீதத்தில் அமைக்கும்</translation>
 <translation id="6089679180657323464">wilco டயக்னாஸ்டிக்ஸ் &amp; டெலிமெட்ரி கண்ட்ரோலர் அமைப்புகளைக் கட்டுப்படுத்துகிறது.</translation>
 <translation id="6091233616732024397">உலாவியைப் பயன்படுத்த, உள்நுழையுமாறு பயனர்களை வலியுறுத்து</translation>
 <translation id="6093156968240188330">தொலைநிலை உதவி அமர்வுகளில், உயர்நிலைச் சாளரங்களை அணுக தொலைநிலைப் பயனர்களை அனுமதி</translation>
@@ -2187,6 +2550,7 @@
 <translation id="6111936128861357925">டைனோசர் ஈஸ்டர் எக் கேமை அனுமதிக்கும்</translation>
 <translation id="6114416803310251055">மறுக்கப்பட்டது</translation>
 <translation id="6133088669883929098">விசை உருவாக்கத்தை எல்லா தளங்களும் பயன்படுத்த அனுமதி</translation>
+<translation id="6141402445226505817">எப்போதும் தோராயமான நேரமண்டலக் கண்டறிதலைப் பயன்படுத்து</translation>
 <translation id="6145799962557135888">JavaScript ஐ இயக்க அனுமதிக்கும் தளங்களைக் குறிப்பிடுகின்ற url வகைகளின் பட்டியலை அமைக்க, உங்களை அனுமதிக்கிறது. இந்தக் கொள்கையை அமைக்காமல் விட்டால், ஒட்டுமொத்த இயல்புநிலை மதிப்பானது, அமைக்கப்பட்டிருந்தால் 'DefaultJavaScriptSetting' கொள்கை அல்லது பயனரின் தனிப்பட்ட உள்ளமைவில் இருந்து எல்லாத் தளங்களுக்கும் பயன்படுத்தப்படும்.</translation>
 <translation id="614662973812186053">இந்தக் கொள்கை Android உபயோகத்தையும் ஆய்வறிக்கைத் தரவுச் சேகரிப்பையும் கட்டுப்படுத்தும்.</translation>
 <translation id="6153048425064249648">Google நிர்வாகிக் கன்சோலுக்கு உலாவியின் செயல்பாடு பற்றிய தகவலைப் பதிவேற்றுகின்ற <ph name="PRODUCT_NAME" /> கிளவுடு அறிக்கையிடுதலை இந்தக் கொள்கை கட்டுப்படுத்தும்.
@@ -2218,6 +2582,15 @@
 <translation id="6155936611791017817">உள்நுழைவுத் திரையில் பெரிய இடஞ்சுட்டியின் இயல்புநிலையை அமை</translation>
 <translation id="6157537876488211233">ப்ராக்ஸி கடந்துபோதல் விதிகளின் கமாவால் பிரிக்கப்பட்ட பட்டியல்</translation>
 <translation id="6158324314836466367">நிறுவன இணைய அங்காடி பெயர் (தடுக்கப்பட்டது)</translation>
+<translation id="6158817306788002298">ப்ராக்ஸி .pac கோப்பிற்கான URLலை இங்கே குறிப்பிடலாம்.
+
+          'ப்ராக்ஸி சேவையக அமைப்புகளை எவ்வாறு குறிப்பது எனத் தேர்வுசெய்க' என்பதில் கைமுறை ப்ராக்ஸி அமைப்புகளை நீங்கள் தேர்ந்தெடுத்திருந்தாலும் <ph name="PROXY_SETTINGS_POLICY_NAME" /> கொள்கை குறிப்பிடப்படவில்லை என்றாலும் மட்டுமே இந்தக் கொள்கை செயல்படுத்தப்படும்.
+
+          ப்ராக்ஸி கொள்கைகளை அமைப்பதற்கு வேறு ஏதேனும் பயன்முறையைத் தேர்ந்தெடுத்திருந்தால் இந்தக் கொள்கையை அமைக்க வேண்டாம்.
+
+          விரிவான உதாரணங்களைப் பார்க்க இந்த URLலுக்குச் செல்லவும்:
+          <ph name="PROXY_HELP_URL" />.</translation>
+<translation id="6178075938488052838"><ph name="PRODUCT_OS_NAME" /> அமர்வை யார் தொடங்கக்கூடும் என்பதை இந்தக் கொள்கை கட்டுப்படுத்தும். இது Androidல் கூடுதல் Google கணக்குகளில் உள்நுழைவதில் இருந்து பயனர்களைத் தடுக்காது. இதைத் தடுக்க விரும்பினால் Android சார்ந்த <ph name="ACCOUNT_TYPES_WITH_MANAGEMENT_DISABLED_CLOUDDPC_POLICY_NAME" /> கொள்கையை <ph name="ARC_POLICY_POLICY_NAME" /> கொள்கையின் ஒரு பகுதியாக உள்ளமைக்கவும்.</translation>
 <translation id="6181608880636987460"><ph name="FLASH_PLUGIN_NAME" /> செருகுநிரலை இயங்க அனுமதிக்காத தளங்களைக் குறிப்பிடும் url பட்டியலை அமைக்க உங்களை அனுமதிக்கும்.
 
           இந்தக் கொள்கையை அமைக்கவில்லை எனில், இயல்புநிலை மதிப்பு எல்லாத் தளங்களுக்கும் பயன்படுத்தப்படும். அப்படி அமைக்கப்படும் மதிப்பு, 'DefaultPluginsSetting' கொள்கையாகவோ (ஏற்கனவே அமைக்கப்பட்டிருந்தால்) அல்லது பயனரின் தனிப்பட்ட உள்ளமைவாகவோ இருக்கும்.</translation>
@@ -2252,6 +2625,17 @@
 <translation id="6281043242780654992">நேட்டிவ் செய்தியிடலுக்கான கொள்கைகளை உள்ளமைக்கிறது. தடுப்புப்பட்டியலிடப்பட்ட நேட்டிவ் செய்தியிடல் ஹோஸ்ட்கள், ஏற்புப்பட்டியலிடப்படும்வரை அவை அனுமதிக்கப்படாது.</translation>
 <translation id="6282799760374509080">ஆடியோ பதிவை அனுமதி அல்லது தடு</translation>
 <translation id="6284362063448764300">TLS 1.1</translation>
+<translation id="6306608379445125648">மொழிகளுக்கான எழுத்துச்சரிபார்ப்பைக் கட்டாயப்படுத்தி முடக்கும். அந்தப் பட்டியலில் இருக்கும் அங்கீகரிக்கப்படாத மொழிகள் புறக்கணிக்கப்படும்.
+
+      இந்தக் கொள்கையை இயக்கினால் குறிப்பிடப்படும் மொழிகளுக்கான எழுத்துப்பிழைச் சரிபார்ப்பு முடக்கப்படும். இருப்பினும், பட்டியலில் இல்லாத மொழிகளுக்கான எழுத்துப்பிழைச் சரிபார்ப்பை பயனரால் இயக்கவோ முடக்கவோ முடியும்.
+
+      இந்தக் கொள்கையை அமைக்கவில்லை என்றாலோ முடக்கினாலோ பயனரின் எழுத்துப்பிழைச் சரிபார்ப்பு விருப்பத்தேர்வுகளில் எந்தவித மாற்றமும் இருக்காது.
+
+      SpellcheckEnabled கொள்கையை முடக்கினால் இந்தக் கொள்கையில் எந்த மாற்றமும் இருக்காது.
+
+      இந்தக் கொள்கையிலும் SpellcheckLanguage கொள்கையிலும் ஒரு மொழி சேர்க்கப்பட்டால் SpellcheckLanguage கொள்கைக்கு முன்னுரிமை அளிக்கப்பட்டு, மொழிக்கான எழுத்துப்பிழைச் சரிபார்ப்பு இயக்கப்படும்.
+
+      தற்போது ஆதரிக்கப்படும் மொழிகள்: af, bg, ca, cs, da, de, el, en-AU, en-CA, en-GB, en-US, es, es-419, es-AR, es-ES, es-MX, es-US, et, fa, fo, fr, he, hi, hr, hu, id, it, ko, lt, lv, nb, nl, pl, pt-BR, pt-PT, ro, ru, sh, sk, sl, sq, sr, sv, ta, tg, tr, uk, vi.</translation>
 <translation id="6310223829319187614">உள்நுழைவின் போது டொமைன் பெயர் தன்னிரப்பியை இயக்கும்</translation>
 <translation id="6315673513957120120">SSL பிழைகள் உள்ள தளங்களுக்குப் பயனர்கள் செல்லும் போது எச்சரிக்கைப் பக்கத்தை Chrome காட்டும். இயல்பாகவே அல்லது இந்தக் கொள்கை true என அமைக்கப்படும் போது, பயனர்கள் இந்த எச்சரிக்கைப் பக்கங்களில் கிளிக் செய்ய அனுமதிக்கப்படுவார்கள்.
       இந்தக் கொள்கையை false என அமைத்தால், எந்தவொரு எச்சரிக்கைப் பக்கத்திலும் பயனர்கள் கிளிக் செய்ய அனுமதிக்கப்படமாட்டார்கள்.</translation>
@@ -2301,6 +2685,8 @@
 <translation id="6449476513004303784">சான்றிதழ்களை நிர்வகிக்க, பயனர்களை அனுமதிக்காது</translation>
 <translation id="645425387487868471"><ph name="PRODUCT_NAME" />க்குக் கட்டாய உள்நுழைவை இயக்கும்</translation>
 <translation id="6464074037294098618">முகவரிகளுக்கு, தன்னிரப்பியை இயக்கும்</translation>
+<translation id="6467613372414922590">பயனர் அளவிலான நேட்டிவ் மெசேஜிங் (நிர்வாகியின் அனுமதிகளின்றி நிறுவப்படும்) ஹோஸ்ட்களை அனுமதிக்கும்</translation>
+<translation id="6468980648680553776">இந்தக் கொள்கை தடுக்கப்பட்டுள்ளது. அதற்குப் பதிலாக RemoteAccessHostClientDomainList கொள்கையைப் பயன்படுத்தவும்.</translation>
 <translation id="6473623140202114570">பாதுகாப்பான உலாவல் எச்சரிக்கைகளைத் தூண்டாத டொமைன்களின் பட்டியலை உள்ளமைக்கவும்.</translation>
 <translation id="6488627892044759800"><ph name="PRODUCT_NAME" /> இல் இயல்பு முகப்புப் பக்கத்தின் வகையை உள்ளமைத்து, முகப்புப் பக்க விருப்பத்தேர்வுகளைப் பயனர்கள் மாற்றுவதைத் தடுக்கும். முகப்புப் பக்கத்தை நீங்கள் குறிப்பிடும் URLலுக்கு அமைக்கலாம் அல்லது ‘புதிய தாவல் பக்கத்திற்கு’ அமைக்கலாம்.
 
@@ -2314,6 +2700,13 @@
 
           <ph name="MS_AD_NAME" /> டொமைனுடன் இணைக்கப்பட்ட Windows நேர்வுகளின்போதும் சாதன நிர்வாகத்திற்காகப் பதிவுசெய்யப்பட்ட Windows 10 Pro அல்லது Enterprise நேர்வுகளின்போதும் மட்டுமே இந்தக் கொள்கை பயன்படுத்தப்படும்.</translation>
 <translation id="6491139795995924304">சாதனத்தில் புளூடூத்தை அனுமதி</translation>
+<translation id="6491872498385040936">இந்தக் கொள்கை தடுக்கப்பட்டுள்ளது. இந்தக் கொள்கையை மேலெழுதி, மிகத் துல்லியமான சரிப்படுத்தலை அனுமதிக்கும் <ph name="FORCE_YOUTUBE_RESTRICT_POLICY_NAME" />ஐப் பயன்படுத்தவும்.
+
+      YouTube சராசரிக் கட்டுப்பாட்டுப் பயன்முறையைக் கட்டாயமாகச் செயல்படுத்தி, பயனர்கள் இந்த அமைப்பை மாற்றுவதைத் தடுக்கும்.
+
+      இந்த அமைப்பு இயக்கப்பட்டால் கட்டுப்பாட்டுப் பயன்முறையானது YouTubeல் எப்போதும் சராசரிக் கட்டுப்பாட்டில் இருப்பதற்குக் கட்டாயப்படுத்தப்படும்.
+
+      இந்த அமைப்பு முடக்கப்பட்டாலோ அமைக்கப்படாமல் இருந்தாலோ கட்டுப்பாட்டுப் பயன்முறையை YouTubeல் <ph name="PRODUCT_NAME" /> கட்டாயப்படுத்தாது. இருப்பினும், YouTube கொள்கைகள் போன்ற புறக் கொள்கைகள் கட்டுப்பாட்டுப் பயன்முறையைக் கட்டாயப்படுத்தக்கூடும்.</translation>
 <translation id="6495328383950074966">’பாதுகாப்பு உலாவல்’ நம்புகின்ற டொமைன்களின் பட்டியலை உள்ளமைக்கும். அதாவது:
       அவற்றின் URLகள் இந்த டொமைன்களின் URLகளுடன் பொருந்தினால், ஆபத்தான மூலங்களுக்கான (எ.கா. ஃபிஷிங், தீம்பொருள் அல்லது தேவையற்ற மென்பொருள்) சரிபார்ப்பை ‘பாதுகாப்பு உலாவல்’ மேற்கொள்ளாது.
       இந்த டொமைன்களில் ஹோஸ்ட் செய்யப்பட்டுள்ள பதிவிறக்கங்களை ‘பாதுகாப்பு உலாவல்’ செயல்பாட்டின் பதிவிறக்கப் பாதுகாப்புச் சேவை சரிபார்க்காது.
@@ -2584,6 +2977,7 @@
       அமர்வு ஐடி மூலமாக, Google சேவையால் சேகரிக்கப்பட்ட பிற பதிவுகளுடன் Google இந்தப் பதிவுகளைத் தொடர்புபடுத்தலாம்; இது பிழைதிருத்தத்தை எளிதாக்குவதற்காகச் செய்யப்படுகிறது.
       </translation>
 <translation id="706669471845501145">டெஸ்க்டாப் அறிவிக்கைகளை காண்பிக்க தளங்களை அனுமதி</translation>
+<translation id="7070525176564511548">ஒவ்வொரு வாரமும் கடவுச்சொல்லை உள்ளிடுவது அவசியம் (168 மணிநேரம்)</translation>
 <translation id="7072208053150563108">சாதனக் கடவுச்சொல் மாற்றத்தின் கால இடைவேளை</translation>
 <translation id="7079519252486108041">இந்த தளங்களில் பாப்அப்களைத் தடு</translation>
 <translation id="7085803328069945025">USB சாதனத்திற்கான அணுகலை வழங்குமாறு, பயனரைக் கேட்க அனுமதிக்கப்படும் தளங்களைக் குறிப்பிடும் url பேட்டர்ன்களின் பட்டியலை அமைக்க உதவுகிறது.
@@ -2616,6 +3010,9 @@
       இந்தக் கொள்கை False என அமைக்கப்பட்டால், பின்னணிப் பயன்முறை முடக்கப்படும், பயனரால் உலாவி அமைப்புகளில் கட்டுப்படுத்த முடியாது.
 
       இந்தக் கொள்கை அமைக்கப்படாமல் விடப்பட்டால், பின்னணிப் பயன்முறை முதலில் முடக்கப்பட்டிருக்கும், பயனரால் உலாவி அமைப்புகளில் அதனைக் கட்டுப்படுத்த முடியும்.</translation>
+<translation id="7123160381479171745">சாதனத்தில் உள்நுழைய அனுமதிக்கப்படும் பயனர்களின் பட்டியலை விளக்கும். உள்ளீடுகள் <ph name="USER_WHITELIST_ENTRY_EXAMPLE" /> போன்று <ph name="USER_WHITELIST_ENTRY_FORMAT" /> வடிவத்தில் இருக்கும். தன்னிச்சையான பயனர்களை டொமைனில் அனுமதிக்க <ph name="USER_WHITELIST_ENTRY_WILDCARD" /> வடிவத்தில் இருக்கும் உள்ளீடுகளைப் பயன்படுத்தவும்.
+
+      இந்தக் கொள்கை உள்ளமைக்கப்படவில்லை எனில் எல்லாப் பயனர்களும் உள்நுழையலாம். புதிய பயனர்களை உருவாக்குவதற்கு இப்போதும் <ph name="DEVICE_ALLOW_NEW_USERS_POLICY_NAME" /> கொள்கையை பொருந்துமாறு உள்ளமைப்பது அவசியம்.</translation>
 <translation id="7123266440503901785">பாதுகாப்பான புதுப்பிப்பு, நீட்டிப்புகளை நிறுவுதல் போன்றவற்றை <ph name="PRODUCT_NAME" /> வழங்குகிறது. எனினும், பாதுகாப்பற்ற கையொப்பம் அல்லது SHA1 போன்ற ஹேஷிங் அல்காரிதங்கள் மூலம் மட்டுமே Chrome இணைய அங்காடிக்கு வெளியே ஹோஸ்ட் செய்யப்பட்டுள்ள சில நீட்டிப்புகளின் உள்ளடக்கங்களைப் பாதுகாக்க முடியும். இந்தக் கொள்கை முடக்கப்படும்போது, Chrome அத்தகைய நீட்டிப்புகளைப் புதிதாக நிறுவவோ புதுப்பிக்கவோ அனுமதிக்காது (அதற்கு நீட்டிப்பு டெவெலப்பர்கள் அந்த நீட்டிப்பை வலுவான அல்காரிதங்களுடன் மீண்டும் உருவாக்க வேண்டும்). இந்தக் கொள்கை இயக்கப்பட்டிருக்கும்போது, அத்தகைய புதுப்பிப்புகளை நிறுவவும் புதுப்பிக்கவும் அனுமதிக்கப்படும்.
 
           இந்தக் கொள்கை அமைக்கப்படாவிட்டால் இயல்புநிலையாக இயக்கப்பட்டுள்ளது என்று கருதப்படும்.
@@ -2657,8 +3054,14 @@
 <translation id="7185078796915954712">TLS 1.3</translation>
 <translation id="718956142899066210">புதுப்பிப்புகளுக்கு அனுமதிக்கப்பட்ட இணைப்பு வகைகள்</translation>
 <translation id="7194407337890404814">இயல்புநிலை தேடல் வழங்குநர் பெயர்</translation>
+<translation id="7199304109870655950">Chrome தொலைநிலை டெஸ்க்டாப் ஹோஸ்ட்டில் தொலைநிலை அணுகல் விருப்பங்களை உள்ளமைக்கும்.
+
+      Chrome தொலைநிலை டெஸ்க்டாப் ஹோஸ்ட் என்பது Chrome தொலைநிலை டெஸ்க்டாப் ஆப்ஸைப் பயன்படுத்தி பயனர் இணையக்கூடிய இலக்கு மெஷினில் இயங்கும் நேட்டிவ் சேவையாகும்.  நேட்டிவ் சேவை <ph name="PRODUCT_NAME" /> உலாவியில் இருந்து தொகுக்கப்பட்டு தனித்தனியே செயல்படுத்தப்படும்.
+
+      Chrome தொலைநிலை டெஸ்க்டாப் ஹோஸ்ட் நிறுவப்படும் வரை இந்தக் கொள்கைகள் புறக்கணிக்கப்படும்.</translation>
 <translation id="7202925763179776247">பதிவிறக்கக் கட்டுப்பாடுகளை அனுமதி</translation>
 <translation id="7207095846245296855">Google பாதுகாப்பானத் தேடலைச் செயல்படுத்தும்</translation>
+<translation id="7211368186050418507">நேரமண்டலத்தைத் தானாகக் கண்டறியாதே</translation>
 <translation id="7216442368414164495">பாதுகாப்பான உலாவல் நீட்டிக்கப்பட்ட அறிவித்தலைப் பயனர்கள் தேர்வுசெய்ய அனுமதிக்கும்</translation>
 <translation id="7221822638060296742"><ph name="FLASH_PLUGIN_NAME" /> செருகுநிரலைத் தானாக இயக்குவதற்கு, இணையதளங்களுக்கு அனுமதி உள்ளதா என்பதை அமைக்க உங்களை அனுமதிக்கும். <ph name="FLASH_PLUGIN_NAME" /> செருகுநிரலைத் தானாக இயக்குவதற்கு எல்லா இணையதளங்களையும் அனுமதிக்கலாம் அல்லது எல்லா இணையதளங்களுக்கும் அனுமதி மறுக்கலாம்.
 
@@ -2712,6 +3115,11 @@
 
           இந்த அமைப்பு முடக்கப்பட்டிருந்தால், பிறகு இந்த அம்சம் கிடைக்காது.</translation>
 <translation id="7275334191706090484">நிர்வகிக்கப்படும் புக்மார்க்குகள்</translation>
+<translation id="7291084543582732020">இந்த அமைப்பை இயக்கினால் Smart Lock அம்சத்திற்கான தேவைகள் பூர்த்திசெயயப்படும்பட்சத்தில் பயனர்கள் அதைப் பயன்படுத்த அனுமதிக்கப்படுவார்கள்.
+
+      இந்த அமைப்பு முடக்கப்பட்டால் பயனர்கள் Smart Lock அம்சத்தைப் பயன்படுத்த அனுமதிக்கப்படமாட்டார்கள்.
+
+      இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் இயல்புநிலை அமைப்பானது என்டர்பிரைஸ் நிர்வகிக்கும் பயனர்களுக்கும் நிர்வகிக்கப்படாத பயனர்களுக்கும் அனுமதிக்கப்படாது.</translation>
 <translation id="7295019613773647480">மேற்பார்வையிடப்படும் பயனர்களை இயக்கு</translation>
 <translation id="7301543427086558500">தேடல் என்ஜினிலிருந்து தேடல் வார்த்தைகளைப் பிரிக்க பயன்படுத்தும் மாற்று URLகளின் பட்டியலைக் குறிப்பிடும். URLகளில் தேடல் வார்த்தைகளைப் பிரிக்க பயன்படுத்தும் <ph name="SEARCH_TERM_MARKER" /> வார்த்தை இருக்க வேண்டும்.
 
@@ -2764,6 +3172,9 @@
 
       <ph name="CHROME_REPORTING_EXTENSION_NAME" /> இயக்கப்பட்டு, <ph name="MACHINE_LEVEL_USER_CLOUD_POLICY_ENROLLMENT_TOKEN_POLICY_NAME" /> இல் சாதனம் பதிவு செய்யப்பட்டால் மட்டுமே, இந்தக் கொள்கை செயலில் இருக்கும்.</translation>
 <translation id="737655323154569539">அச்சிடும் பக்க அளவைக் கட்டுப்படுத்தும். கொள்கை அமைக்கப்படவில்லை என்றாலும் தொகுப்பு வெறுமையாக இருந்தாலும், கட்டுப்பாடு எதுவுமில்லை என்பதாகக் கருதப்படும்.</translation>
+<translation id="7389872682701720082">இந்த அமைப்பை இயக்கினால் காலாவதியாகாத செருகுநிரல்கள் எப்போதும் இயங்கும்.
+
+      இந்த அமைப்பு முடக்கப்பட்டாலோ அமைக்கப்படவில்லை என்றாலோ பயனர்களிடம் அங்கீகரிக்கப்பட வேண்டிய செருகுநிரல்களை இயக்குவதற்கான அனுமதி கேட்கப்படும். இந்தச் செருகுநிரல்கள் பாதுகாப்பைக் குறைக்கக்கூடியவை.</translation>
 <translation id="7417972229667085380">விளக்கக்காட்சி பயன்முறையில் செயலற்ற நிலை தாமதத்தை அளவிடுவதற்கான சதவீதம் (தடுக்கப்பட்டது)</translation>
 <translation id="7421483919690710988">மீடியா வட்டு தற்காலிக சேமிப்பு அளவை பைட்களில் அமை</translation>
 <translation id="7424751532654212117">முடக்கப்பட்ட செருகுநிரல்களின் பட்டியலின் விதிவிலக்குகளுக்கான பட்டியல்</translation>
@@ -2771,6 +3182,7 @@
 
       கொள்கை அமைக்கப்படாவிட்டால், அல்லது false என அமைக்கப்பட்டால், <ph name="TLS_FALSE_START" /> இயக்கப்படும். இது true என அமைக்கப்பட்டால், <ph name="TLS_FALSE_START" /> முடக்கப்படும்.</translation>
 <translation id="7433714841194914373">'உடனடி' அம்சத்தை இயக்கும்</translation>
+<translation id="7434202861148928348">தொலைநிலை அணுகல் கிளையன்ட்களுக்காக அவசியமான டொமைன் பெயர்களை உள்ளமைக்கும்</translation>
 <translation id="7443616896860707393">கிராஸ் ஒரிஜின் HTTP அடிப்படை அங்கீகரிப்பை குறிப்பிடுகிறது</translation>
 <translation id="7458437477941640506">OS பதிப்பு இலக்கை விடப் புதியதாக இருந்தால், இலக்குப் பதிப்புக்கு மீட்டமைக்க வேண்டாம். புதுப்பிப்புகளும் முடக்கப்பட்டுள்ளன.</translation>
 <translation id="7464991223784276288">நடப்பு அமர்வில் URLகளைப் பொருத்துவதிலிருந்து குக்கீகளை வரம்பிடும்</translation>
@@ -2872,6 +3284,8 @@
 
       பாதுகாப்பான உலாவல் குறித்த கூடுதல் தகவலுக்கு, https://developers.google.com/safe-browsing எனும் இணைப்பைப் பார்க்கவும்.</translation>
 <translation id="7643883929273267746"><ph name="PRODUCT_NAME" /> இல் தெரியும் கணக்குகளை வரம்பிடு</translation>
+<translation id="7644825865811580663">இந்தக் கொள்கை 'சரி' என அமைக்கப்பட்டால் <ph name="PRODUCT_NAME" /> முதல் இயக்கத்தில் காட்டப்படும் முதல் சாளரத்தை நிபந்தனையின்றிப் பெரிதுபடுத்தும்.
+      இந்தக் கொள்கை 'தவறு' என அமைக்கப்பட்டாலோ உள்ளமைக்கப்பட்டாலோ காட்டப்படும் முதல் சாளரத்தைப் பெரிதுபடுத்த வேண்டுமா என்பது திரை அளவைப் பொறுத்து அமையும்.</translation>
 <translation id="7651739109954974365">சாதனத்திற்கு தரவு ரோமிங்கை இயக்கலாமா என்பதை தீர்மானிக்கும்.  true என அமைக்கப்பட்டிருந்தால், தரவு ரோமிங் அனுமதிக்கப்படும். உள்ளமைக்கப்படாமல் விடுபட்டாலோ அல்லது false என அமைக்கப்பட்டாலோ, தரவு ரோமிங் கிடைக்காமல் போகலாம்.</translation>
 <translation id="7657261947024629645">செயல்திறனுக்காக மேம்படுத்துதல்.</translation>
 <translation id="7673194325208122247">கால அளவு (மில்லிவினாடிகள்)</translation>
@@ -2885,6 +3299,9 @@
 
           "RestoreOnStartup" கொள்கையானது முந்தைய அமர்வுகளிலிருந்து URLகளை மீட்டெடுக்கும்படி அமைக்கப்பட்டிருந்தால், இந்தக் கொள்கை கருத்தில்கொள்ளப்படாது. மேலும் அந்த தளங்களுக்கான குக்கீகள் நிரந்தரமாகச் சேமிக்கப்படும்.</translation>
 <translation id="7683777542468165012">டைனமிக் கொள்கை புதுப்பிப்பு</translation>
+<translation id="7687943045976362719">இந்தக் கொள்கை அமைக்கப்பட்டால் குறிப்பிடப்படும் உள்ளடக்க வகைகளை <ph name="PRODUCT_FRAME_NAME" /> நிர்வகிக்கும்.
+
+          இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் இயல்புநிலை ரெண்டரர் எல்லாத் தளங்களுக்கும் பயன்படுத்தப்படும். (இயல்புநிலை ரெண்டரரை உள்ளமைக்க <ph name="CHROME_FRAME_RENDERER_SETTINGS_POLICY_NAME" /> கொள்கை பயன்படுத்தப்படக்கூடும்.)</translation>
 <translation id="7694807474048279351"><ph name="PRODUCT_OS_NAME" /> புதுப்பிப்பு பயன்படுத்தப்பட்ட பிறகு தானியங்கு மறுதொடக்கத்தைத் திட்டமிடவும்.
 
       இந்தக் கொள்கை சரி என அமைக்கப்பட்டால், <ph name="PRODUCT_OS_NAME" /> புதுப்பிப்பு பயன்படுத்தப்பட்டவுடன் தானியங்கு மறுதொடக்கம் திட்டமிடப்படும், மேலும் புதுப்பிப்பு செயல்முறையை நிறைவுசெய்ய மறுதொடக்கம் அவசியமாகும். மறுதொடக்கம் உடனடியாக திட்டமிடப்படும், ஆனால் பயனர் தற்சமயம் சாதனத்தைப் பயன்படுத்தினால் 24 மணிநேரம் வரையில் சாதனத்தில் தாமதமாகலாம்.
@@ -2924,6 +3341,7 @@
 <translation id="7763614521440615342">புதிய தாவல் பக்கத்தில் உள்ளடக்கப் பரிந்துரைகளைக் காட்டு</translation>
 <translation id="7765879851993224640">Smart Lock உள்நுழைவைப் பயன்படுத்துவதை அனுமதிக்கும்.</translation>
 <translation id="7774768074957326919">கணினியின் ப்ராக்ஸி அமைப்புகளைப் பயன்படுத்து</translation>
+<translation id="7777535871204167559">வெளிப்புறச் சேமிப்பகச் சாதனங்களை, 'படிக்க மட்டுமேயான' சாதனங்களாகப் பயன்படுத்தும்</translation>
 <translation id="7781069478569868053">புதிய தாவல் பக்கம்</translation>
 <translation id="7788511847830146438">ஒவ்வொரு சுயவிவரத்திற்கும்</translation>
 <translation id="780603170519840350">subjectPublicKeyInfo ஹேஷ்களுக்கான சான்றிதழ் வெளிப்படைத்தன்மை தேவைகளைச் செயல்படுத்துவதை முடக்கும்.
@@ -2954,6 +3372,11 @@
       இந்தக் கொள்கையை அமைக்காமல் விடுவதால் <ph name="PRODUCT_NAME" />, இயல்புநிலை மதிப்பான 5000 மில்லி வினாடிகளைப் பயன்படுத்தும்படி செய்யும்.</translation>
 <translation id="7841880500990419427">மாற்றப்படக்கூடிய குறைந்தபட்ச TLS பதிப்பு</translation>
 <translation id="7842869978353666042">Google இயக்கக விருப்பங்களை உள்ளமைத்தல்</translation>
+<translation id="7858404742201086014">இந்த அமைப்பை இயக்கினால் காலாவதியான செருகுநிரல்கள் சாதாரணமான செருகுநிரல்களாகப் பயன்படுத்தப்படும்.
+
+      இந்த அமைப்பை முடக்கினால் காலாவதியான செருகுநிரல்கள் பயன்படுத்தப்படாது, மேலும் அவற்றை இயக்குவதற்கு பயனர்களிடம் அனுமதி கேட்கப்படாது.
+
+      இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் காலாவதியான செருகுநிரல்களை இயக்க, பயனர்களிடம் அனுமதி கேட்கப்படும்.</translation>
 <translation id="787125417158068494">SyncDisabled என அமைக்கப்பட்டாலோ உள்ளமைக்கப்படாமல் இருந்தாலோ, ARC பயன்பாடுகளுக்கு <ph name="PRODUCT_OS_NAME" /> சான்றிதழ்கள் கிடைக்காது.
 
       CopyCaCerts என அமைத்தால், ONC நிறுவிய, <ph name="WEB_TRUSTED_BIT" /> உடன் கூடிய எல்லா CA சான்றிதழ்களும் ARC பயன்பாடுகளுக்குக் கிடைக்கும்.</translation>
@@ -2972,12 +3395,25 @@
 <translation id="793473937901685727">ARC பயன்பாடுகளுக்குச் சான்றிதழ் கிடைக்கும்நிலையை அமை</translation>
 <translation id="7937766917976512374">வீடியோ பதிவை அனுமதி அல்லது தடு</translation>
 <translation id="7941975817681987555">எந்த நெட்வொர்க் இணைப்பிலும் நெட்வொர்க் செயல்பாடுகளை யூகிக்க வேண்டாம்</translation>
+<translation id="7952958573604504839">இந்தக் கொள்கை <ph name="NETWORK_PREDICTION_OPTIONS_POLICY_NAME" />க்குச் சாதகமாக M48ல் தடுக்கப்பட்டுள்ளது, M54ல் அகற்றப்பட்டுள்ளது.
+
+      <ph name="PRODUCT_NAME" />ல் நெட்வொர்க் கணிப்பை இயக்கி, பயனர்கள் இந்த அமைப்பை மாற்றுவதைத் தடுக்கும்.
+
+      இது 'DNS முன்பே பெறுதலை' மட்டுமின்றி இணையப் பக்கங்களின் 'TCP மற்றும் SSL முன்பே இணைத்தல், முன்பே ரெண்டர் செய்தல்' ஆகியவற்றையும் கட்டுப்படுத்தும். இந்தக் கொள்கையின் பெயரானது வரலாற்றுக் காரணங்களுக்காக 'DNS முன்பே பெறுதலைக்' குறிக்கும்.
+
+      இந்த அமைப்பை இயக்கினாலோ முடக்கினாலோ பயனர்கள் இதை <ph name="PRODUCT_NAME" />ல் மாற்றவோ மேலெழுதவோ முடியாது.
+
+      இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் இது இயக்கப்படும், ஆனால் பயனர்களால் இதை மாற்ற முடியும்.</translation>
 <translation id="7953256619080733119">நிர்வகித்த பயனர் கைமுறை விதிவிலக்கு ஹோஸ்ட்கள்</translation>
+<translation id="7958537754689366707">ஒவ்வொரு 12 மணிநேரத்திற்கும் கடவுச்சொல்லை உள்ளிடுவது அவசியம்</translation>
 <translation id="7961779417826583251">லெகஸி சான்றிதழ் அங்கீகரிப்பாளர்களின் பட்டியலுக்குச் சான்றிதழ் வெளிப்படைத்தன்மை செயலாக்கத்தை முடக்கு</translation>
 <translation id="7974114691960514888">இந்தக் கொள்கை இனி ஆதரவளிக்கப்படாது. தொலைநிலை கிளையண்டுடன் இணைக்கும்போது, STUN மற்றும் அதனுடன் தொடர்புடைய சேவையகங்களின் ஆப்ஸைச் செயலாக்குகிறது. இந்த அமைப்பு செயல்படுத்தப்பட்டால் ஃபயர்வாலால் தனிப்படுத்தப்பட்டிருந்தாலும் இந்த கம்ப்யூட்டரானது தொலைநிலை ஹோஸ்ட் கம்ப்யூட்டர்களைக் கண்டறிந்து அதனுடன் இணைய முடியும். இந்த அமைப்பு முடக்கப்பட்டு வெளிச்செல்லும் UDP இணைப்புகள் ஃபயர்வாலால் வடிகட்டப்பட்டால் அக நெட்வொர்க்கிற்குள் மட்டுமே ஹோஸ்ட் கம்ப்யூட்டர்களுடன் இணைக்கப்படும்.</translation>
 <translation id="7976157349247117979"><ph name="PRODUCT_NAME" /> இலக்கின் பெயர்</translation>
 <translation id="7980227303582973781">சிறப்புக் கட்டுப்பாடுகள் எதுவுமில்லை</translation>
 <translation id="7985242821674907985"><ph name="PRODUCT_NAME" /></translation>
+<translation id="798856998567564266">இந்த அமைப்பை இயக்கினால் புக்மார்க்குகளைச் சேர்க்கலாம், அகற்றலாம் அல்லது மாற்றியமைக்கலாம். இந்தக் கொள்கை அமைக்கப்படாத போது இதுவே இயல்புநிலையாகவும் இருக்கும்.
+
+      இந்த அமைப்பை முடக்கினால் புக்மார்க்குகளைச் சேர்க்கவோ அகற்றவோ மாற்றியமைக்கவோ முடியாது. ஏற்கனவே இருக்கும் புக்மார்க்குகள் அப்படியே இருக்கும்.</translation>
 <translation id="7992136759457836904">Chrome OSஸில் விர்ச்சுவல் சாதனங்களை இயக்க அனுமதிப்பதா என்பதைக் கட்டுப்படுத்த உங்களை அனுமதிக்கும்.
 
       கொள்கையைச் ‘சரி’ என அமைத்தால், விர்ச்சுவல் சாதனங்களை இயக்க இச்சாதனம் அனுமதிக்கப்படும்.
@@ -3004,6 +3440,20 @@
 <translation id="8050080920415773384">இயல்நிலை அச்சிடல்</translation>
 <translation id="8053580360728293758">இயல்புநிலையில் வண்ணப் பயன்முறையில் அச்சிடுவதை மேலெழுதும். பயன்முறை கிடைக்காவிட்டால், இந்தக் கொள்கை புறக்கணிக்கப்படும்.</translation>
 <translation id="8059164285174960932">தொலைநிலை அணுகல் க்ளையன்ட்கள் தங்கள் அங்கீகரிப்பு டோக்கனைப் பெற வேண்டிய URL</translation>
+<translation id="806280865577636339">இந்தக் கொள்கை 'சரி' என அமைக்கப்பட்டால் சிஸ்டம் ட்ரேயில் அணுகல்தன்மை விருப்பங்கள் எப்போதும் தோன்றும்.
+
+          இந்தக் கொள்கை 'தவறு' என அமைக்கப்பட்டால் சிஸ்டம் ட்ரேயில் அணுகல்தன்மை விருப்பங்கள் தோன்றாது.
+
+          இந்தக் கொள்கையை அமைத்தால் பயனரால் இதை மாற்றவோ மேலெழுதவோ முடியாது.
+
+          இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் சிஸ்டம் ட்ரேடு மெனுவில் அணுகல்தன்மை விருப்பங்கள் தோன்றாது, ஆனால் பயனர்கள் அமைப்புகள் பக்கத்திற்குச் சென்று அணுகல்தன்மை விருப்பங்கள் தோன்றும்படி செய்யலாம்.</translation>
+<translation id="806523868782250975">நிர்வகிக்கப்படும் புக்மார்க்குகளின் பட்டியலை உள்ளமைக்கும்.
+
+      இந்தக் கொள்கை புக்மார்க்குகளின் பட்டியலைக் கொண்டிருக்கும். இதில் உள்ள ஒவ்வொரு புக்மார்க்கும் "<ph name="NAME" />" (புக்மார்க் பெயர்), "<ph name="URL_LABEL" />" (இலக்கு) ஆகிய விசைகளைக் கொண்ட அகராதியாகும். "<ph name="URL_LABEL" />" விசையின்றி, ஆனால் கூடுதல் "<ph name="CHILDREN" />" விசையுடன் புக்மார்க்கை விளக்குவதன் மூலம் ஒரு துணைக் கோப்புறையை உள்ளமைக்கக்கூடும். மேலே (அவற்றில் சில, மீண்டும் கோப்புறைகளாக இருக்கக்கூடும்) விளக்கப்பட்டுள்ளது போல புக்மார்க்குகளின் பட்டியலை இந்த விசை கொண்டிருக்கும். முழுமையற்ற URLகளை Omnibox மூலம் அவை சமர்ப்பிக்கப்பட்டது போல <ph name="PRODUCT_NAME" /> மாற்றும். எடுத்துக்காட்டாக, "<ph name="GOOGLE_COM" />" என்பது "<ph name="HTTPS_GOOGLE_COM" />" என மாறும்.
+
+      இந்த புக்மார்க்குகள் பயனரால் மாற்றியமைக்க முடியாத கோப்புறையில் அமைக்கப்படும் (ஆனால் பயனர் அதை புக்மார்க் பட்டியில் இருந்து மறைக்கும்படி தேர்வுசெய்யலாம்). கோப்புறையின் பெயர் இயல்பாக 'நிர்வகிக்கப்படும் புக்மார்க்குகள்' என்றிருக்கும், ஆனால் விரும்பும் கோப்புறைப் பெயரை மதிப்பாகக் கொண்டு, '<ph name="TOPLEVEL_NAME" />' விசையைக் கொண்டிருக்கும் அகராதியான புக்மார்க்குகளின் பட்டியலில் சேர்ப்பதன் மூலம் அதைத் தனிப்பயனாக்கலாம்.
+
+      நிர்வகிக்கப்படும் புக்மார்க்குகள் பயனர் கணக்குடன் ஒத்திசைவில் இருக்காது, மேலும் நீட்டிப்புகளால் அதை மாற்றியமைக்க முடியாது.</translation>
 <translation id="8078366200175825572">குக்கீகளை அமைக்க அனுமதிக்காத தளங்களைக் குறிக்கும் url வகைகளின் பட்டியலை அமைக்க, உங்களை அனுமதிக்கிறது.
 
           இந்தக் கொள்கையை அமைக்கவில்லை எனில், ஒட்டுமொத்த இயல்பு மதிப்பு எல்லாத் தளங்களுக்கும் பயன்படுத்தப்படும். அப்படி அமைக்கப்படும் மதிப்பு, 'DefaultCookiesSetting' கொள்கையாகவோ (ஏற்கனவே அமைக்கப்பட்டிருந்தால்) அல்லது பயனரின் தனிப்பட்ட உள்ளமைவாகவோ இருக்கும்.
@@ -3066,6 +3516,9 @@
 
       கொள்கையை முடக்கினாலோ அமைக்காமல் விட்டாலோ, பயனர் உள்நுழையும்போது வழக்கமான கணக்குகள் உருவாக்கப்படும்.</translation>
 <translation id="8158758865057576716"><ph name="PRODUCT_NAME" /> சுயவிவரத் தரவிற்கான ரோமிங் நகல்களை உருவாக்குவதை இயக்கு.</translation>
+<translation id="8172676363520748127">இயக்கப்பட்டால் கீபோர்ட் ஷார்ட்கட்கள் அல்லது நீட்டிப்பு APIகளைப் பயன்படுத்தி ஸ்கிரீன்ஷாட்களை எடுக்க முடியாது.
+
+      இயக்கப்படவில்லை என்றாலோ குறிப்பிடப்படவில்லை என்றாலோ ஸ்கிரீன்ஷாட் எடுப்பது அனுமதிக்கப்படும்.</translation>
 <translation id="817455428376641507">URL தடுப்புப் பட்டியலுக்கான விதிவிலக்குகள் போன்று, பட்டியலிடப்பட்ட URLகளுக்கு அணுகலை அனுமதிக்கும்.
 
       இந்தப் பட்டியலின் உள்ளீடுகள் வடிவமைப்பிற்கு URL தடுப்புப் பட்டியல் கொள்கையின் விளக்கத்தைப் பார்க்கவும்.
@@ -3079,6 +3532,7 @@
       இந்தக் கொள்கையை அமைக்காமல் விட்டால், 'URLBlacklist' கொள்கையிலுள்ள தடுப்புப் பட்டியலில் எந்த விதிவிலக்குகளும் இருக்காது.</translation>
 <translation id="8176035528522326671">நிறுவன பயனரை, முதன்மை பலசுயவிவரப் பயனராவதற்கு மட்டும் அனுமதி (நிர்வகிக்கப்பட்ட நிறுவன பயனர்களுக்கான இயல்பு செயல்பாடு)</translation>
 <translation id="8214600119442850823">கடவுச்சொல் நிர்வாகியை உள்ளமைக்கும்.</translation>
+<translation id="8217516105848565518">இந்தக் கொள்கை தடுக்கப்பட்டுள்ளது. அதற்குப் பதிலாக RemoteAccessHostDomainList கொள்கையைப் பயன்படுத்தவும்.</translation>
 <translation id="8244525275280476362">கொள்கையைச் செல்லாததாக்கிய பின் பெறுவதில் ஏற்படும் அதிகபட்ச தாமதம்</translation>
 <translation id="8256688113167012935">தொடர்புடைய சாதன-அகக் கணக்கிற்கான உள்நுழைவுத் திரையில் காண்பிக்கப்படும் கணக்குப் பெயரை <ph name="PRODUCT_OS_NAME" /> கட்டுப்படுத்தலாம்.
 
@@ -3094,6 +3548,9 @@
 இந்த அமைப்புகளை கைமுறையாக உள்ளமைக்கத் தேவையில்லை! Windows, Mac, Linux ஆகியவற்றுக்கான எளிதாகப் பயன்படுத்தக்கூடிய டெம்ப்ளேட்கள், <ph name="POLICY_TEMPLATE_DOWNLOAD_URL" /> இல் பதிவிறக்கக் கிடைக்கின்றன.
 
 Windows இல் <ph name="MS_AD_NAME" /> டொமைனுடன் இணைக்கப்பட்டிருக்கும் Windows நேர்வுகளுக்கு, இன்னும் பதிவகத்தின் வழியாகக் கொள்கையை வழங்குவது ஆதரிக்கப்பட்டாலும், கொள்கையை GPO வழியாக உள்ளமைக்கும் வழியே பரிந்துரைக்கப்படுகிறது.</translation>
+<translation id="8259592978873597235">இந்தக் கொள்கை 'சரி' என அமைக்கப்பட்டாலோ அமைக்கப்படவில்லை என்றாலோ வீடியோ இயக்கத்தில் இருக்கும் போது பயனர் செயலற்று இருப்பதாகக் கருதப்படமாட்டார். இது செயலற்ற தாமதநிலை, திரை மங்கல் தாமதநிலை, திரை முடக்கப்படும் தாமதநிலை, திரை பூட்டப்படும் தாமதநிலை ஆகியவை நிகழ்வதையும் அதற்காக மேற்கொள்ளப்படும் நடவடிக்கைகளையும் தடுக்கும்.
+
+          இந்தக் கொள்கை 'தவறு' என அமைக்கப்பட்டால் பயனர்கள் செயலற்று இருப்பதாகக் கருதப்படுவதை வீடியோ இயக்கம் தடுக்காது.</translation>
 <translation id="8264653492961233132">பயனரின் பங்களிப்பு இல்லாமல் தானாக நிறுவப்படும், பயனரால் நிறுவல் நீக்க முடியாத மற்றும் முடக்க முடியாத ஆப்ஸ் மற்றும் நீட்டிப்புகளின் பட்டியலைக் குறிப்பிடும். ஆப்ஸ்/நீட்டிப்பின் இனிவரும் பதிப்புகள் கோரும் ஏதேனும் கூடுதல் அனுமதிகள் உட்பட, அவை கோரும் எல்லா அனுமதிகளும் பயனரின் பங்கு இல்லாமல் தானாகவே வழங்கப்படும். மேலும், enterprise.deviceAttributes மற்றும் enterprise.platformKeys நீட்டிப்பு APIகளுக்கு அனுமதிகள் வழங்கப்படும். (தானாக நிறுவப்படாத ஆப்ஸ்/நீட்டிப்புகளுக்கு இந்த இரண்டு APIகளும் இருக்காது.)
 
           <ph name="EXTENSION_INSTALL_BLACKLIST_POLICY_NAME" /> கொள்கையுடன் இந்தக் கொள்கை முரண்பட்டால், இந்தக் கொள்கையே மேலோங்கிச் செயல்படும். ஏற்கனவே தானாக நிறுவப்பட்ட ஒரு ஆப்ஸோ நீட்டிப்போ இந்தப் பட்டியலிலிருந்து அகற்றப்பட்டால், <ph name="PRODUCT_NAME" /> அதைத் தானாகவே நிறுவல்நீக்கும்.
@@ -3134,6 +3591,7 @@
 <translation id="8329984337216493753">இந்தக் கொள்கை விற்பனைப் பயன்முறையில் மட்டுமே செயலில் இருக்கும். DeviceIdleLogoutTimeout குறிப்பிட்டிருந்தால், இந்தக் கொள்கை கவுண்டவுன் நேரத்துடன் எச்சரிக்கைப் பெட்டியின் கால நேரத்தைக் குறிப்பிடும், பயனர் வெளியறுவதற்கு முன்பாக இது காண்பிக்கப்படும். இந்தக் கொள்கையின் மதிப்பு மில்லிவினாடிகளில் குறிப்பிடப்படும்.</translation>
 <translation id="8339420913453596618">இரண்டாம் படி முடக்கப்பட்டது</translation>
 <translation id="8344454543174932833">முதல் இயக்கத்தின்போதே இயல்புநிலை உலாவலிருந்து புக்மார்க்ஸை இறக்குமதி செய்</translation>
+<translation id="8357681633047935212">பயனர் அமர்வின் நீளத்தைக் கட்டுப்படுத்தும்</translation>
 <translation id="8359734107661430198">2008/09/02 வரை ExampleDeprecatedFeature API ஐ இயக்கு</translation>
 <translation id="8367209241899435947">Windowsஸில் Chrome கிளீன்அப்பை இயக்கும்</translation>
 <translation id="8369602308428138533">AC சக்தியில் இயங்கும்போது திரை முடக்கம் தாமதமாகும்</translation>
@@ -3142,6 +3600,13 @@
 
       இந்தக் கொள்கை ‘தவறு’ என அமைக்கப்பட்டிருந்தால், புள்ளிவிவரங்கள் அறிக்கையளிக்கப்படாது.
       இதை ‘சரி’ என அமைத்திருந்தாலோ அமைக்காமலேயே விட்டாலோ புள்ளிவிவரங்கள் அறிக்கையளிக்கப்படும்.</translation>
+<translation id="8380490658357556620">தொலைநிலை கிளையன்ட்கள் இந்த மெஷினுடன் இணைப்பை ஏற்படுத்த முயலும் போது இணைப்புச் சேவையகங்களின் உபயோகத்தை இயக்கும்.
+
+          இந்த அமைப்பு இயக்கப்பட்டால் நேரடி இணைப்பு இல்லாத போது (எ.கா. ஃபயர்வால் கட்டுப்பாடுகளின் காரணமாக) தொலைநிலை கிளையன்ட்கள் இணைப்புச் சேவையகங்களைப் பயன்படுத்தி இந்த மெஷினுடன் இணையலாம்.
+
+          <ph name="REMOTE_ACCESS_HOST_FIREWALL_TRAVERSAL_POLICY_NAME" /> கொள்கை முடக்கப்பட்டால் இந்தக் கொள்கை புறக்கணிக்கப்படும்.
+
+          இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் இந்த அமைப்பு இயக்கப்படும்.</translation>
 <translation id="8382184662529825177">சாதனத்தின் உள்ளடக்கப் பாதுகாப்பிற்கான தொலைநிலைச் சான்றொப்பப் பயன்பாட்டை இயக்கவும்</translation>
 <translation id="838870586332499308">தரவு ரோமிங்கை இயக்கு</translation>
 <translation id="8390049129576938611"><ph name="PRODUCT_NAME" /> இல் அக PDF வியூவரை முடக்கும். அதற்குப் பதிலாக, அதைப் பதிவிறக்கமாகக் கருதி, இயல்புப் பயன்பாட்டில் PDF கோப்புகளைத் திறக்க பயனரை அனுமதிக்கும்.
@@ -3220,6 +3685,9 @@
 <translation id="8548832052135586762">அச்சிடலை 'வண்ணம் மட்டும்', 'மோனோகுரோம் மட்டும்' அல்லது வண்ணப் பயன்முறைக் கட்டுப்பாடு இல்லை என்று அமைக்கும், கொள்கை அமைக்கப்படவில்லை என்றால், கட்டுப்பாடு இல்லை என்பதாகக் கருதப்படும்.</translation>
 <translation id="8549772397068118889">உள்ளடக்கத் தொகுப்புகளுக்கு வெளியே உள்ள தளங்களைப் பார்வையிடும்போது எச்சரிக்கை செய்</translation>
 <translation id="8566842294717252664">புதிய தாவல் பக்கம் மற்றும் பயன்பாட்டுத் துவக்கியில் இணைய அங்காடியை மறை</translation>
+<translation id="8569734380847633643">
+          இந்தக் கொள்கை 'தவறு' என அமைத்தால் பயனர்கள் வைஃபையை மீண்டும் இயக்க முடியாதவாறு <ph name="PRODUCT_OS_NAME" /> முடக்கும்.
+          இந்தக் கொள்கை ’சரி’ என அமைத்தாலோ எதையும் அமைக்கவில்லை என்றாலோ பயனர்கள் அவர்களது விருப்பத்திற்கேற்ப வைஃபையை இயக்கவோ முடக்கவோ இயலும்.</translation>
 <translation id="857369585509260201">இந்தக் கொள்கை தடுக்கப்பட்டுள்ளது, அதற்குப் பதில் BrowserSigninனைப் பயன்படுத்திப் பார்க்கவும்.
 
       இந்தக் கொள்கையை ‘சரி’ என அமைத்தால் உலாவியைப் பயன்படுத்தும் முன்பு, பயனர் தனது கணக்கின் மூலம் <ph name="PRODUCT_NAME" /> இல் உள்நுழைய வேண்டும். அத்துடன் BrowserGuestModeEnabledன் இயல்பு மதிப்பானது ‘தவறு’ என அமைக்கப்படும். இந்தக் கொள்கையை இயக்கிய பிறகு ஏற்கனவே இருக்கும் கையொப்பமிடாத கணக்குகள் முடக்கப்பட்டு, அவற்றை அணுக முடியாது என்பதை நினைவில் கொள்ளவும். மேலும் தகவலுக்கு உதவி மையக் கட்டுரையைப் பார்க்கவும்.
@@ -3260,6 +3728,7 @@
           பல சேவையகங்களின் பெயர்களைக் காற்புள்ளிகளால் பிரிக்கவும். சிறப்புக் குறிகள் (*) அனுமதிக்கப்படுகின்றன.
 
           இந்தக் கொள்கையை அமைக்கவில்லை எனில், சேவையகமானது அக இணையத்தில் உள்ளதா என்பதை <ph name="PRODUCT_NAME" /> கண்டறிய முயற்சிக்கும், அதன் பின்னரே IWA கோரிக்கைகளுக்கு பதிலளிக்கும். சேவையமானது இணையமாகக் கண்டறியப்பட்டால், அதிலிருந்து வரும் IWA கோரிக்கைகள், <ph name="PRODUCT_NAME" /> ஆல் தவிர்க்கப்படும்.</translation>
+<translation id="8661297125441579970">தரவு நகர்த்துதலையும் ARCயையும் அனுமதிக்காதே.</translation>
 <translation id="8672321184841719703">இலக்கு தானியங்கு புதுப்பித்தல் பதிப்பு</translation>
 <translation id="867410340948518937">U2F (யூனிவர்செல் செகண்ட் ஃபேக்டர்)</translation>
 <translation id="8682611302223077049">இது மில்லிவினாடிகளில் ஒரு காலகட்டத்தை அமைக்க அனுமதிக்கும், இந்தக் காலகட்டத்தில் <ph name="PRODUCT_NAME" />ஐ மீண்டும் தொடங்குவதற்கோ, நிலுவையிலுள்ள ஒரு புதுப்பிப்பைப் பயன்படுத்துவதற்கு <ph name="PRODUCT_OS_NAME" /> சாதனத்தை மீண்டும் தொடங்குவதற்கோ பயனருக்கு அறிவுறுத்தப்படும்.
@@ -3270,6 +3739,13 @@
 <translation id="8685024486845674965">கடவுச்சொல் பாதுகாப்புச் சேவையின் எச்சரிக்கையானது, கடவுச்சொல் மீண்டும் பயன்படுத்தப்பட்டால் தூண்டப்படும்</translation>
 <translation id="8693243869659262736">உள்ளிணைந்த DNS க்ளையன்ட்டைப் பயன்படுத்தவும்</translation>
 <translation id="8703488928438047864">போர்டின் நிலை குறித்து அறிக்கையளிக்கவும்</translation>
+<translation id="8703872185032220081">Power peak shift day config கொள்கையை அமைக்கும்.
+
+          DevicePowerPeakShiftEnabled 'சரி' என அமைத்தால் மட்டுமே இந்தக் கொள்கையைப் பயன்படுத்த இயலும்.
+
+          இந்தக் கொள்கையை உள்ளமைக்கவில்லை என்றாலோ அமைக்கவில்லை என்றாலோ power peak shift முடக்கப்பட்ட நிலையிலேயே இருக்கும்.
+
+          கவனத்திற்கு: <ph name="START_TIME_FIELD_NAME" />, <ph name="END_TIME_FIELD_NAME" /> மற்றும் <ph name="CHARGE_START_TIME_FIELD_NAME" /> புலங்களில் உள்ள <ph name="MINUTE_FIELD_NAME" /> புலத்தில் அனுமதிக்கப்படும் மதிப்புகள்: 0, 15, 30, 45.</translation>
 <translation id="8704831857353097849">முடக்கப்பட்ட செருகுநிரல்களின் பட்டியல்</translation>
 <translation id="8711086062295757690">இந்த வழங்குநரின் தேடலைத் தொடங்கும், சர்வபுலத்தில் பயன்படுத்தப்படும் ஷார்ட்கட் தேடல் குறிப்பைக் குறிப்பிடுகிறது. இது விருப்பத்தேர்வாக உள்ளது. அமைக்கவில்லையென்றால் தேடல் குறிப்பு தேடல் வழங்குநரை செயல்படுத்தாது. 'DefaultSearchProviderEnabled' கொள்கை இயக்கப்பட்டிருந்தால், இந்தக் கொள்கை பரிசீலனைக்கு மட்டுமே உள்ளது.</translation>
 <translation id="8731693562790917685">குறிப்பிட்ட வகையான உள்ளடக்கங்கள் (எடுத்துக்காட்டாக, குக்கீகள், படங்கள் அல்லது JavaScript போன்றவை) எவ்வாறு கையாளப்பட வேண்டும் என்று குறிப்பிட உள்ளடக்க அமைப்புகள் அனுமதிக்கிறது.</translation>
@@ -3294,9 +3770,11 @@
       இந்த அமைப்பு இயக்கப்பட்டிருந்தால் அல்லது அமைக்கப்படாமல் இருந்தால், உலாவல் மற்றும் பதிவிறக்க வரலாறு நீக்கப்படலாம்.
 
       இந்த அமைப்பு முடக்கப்பட்டிருந்தால், உலாவல் மற்றும் பதிவிறக்க வரலாற்றை நீக்க முடியாது.</translation>
+<translation id="8757552286070680084">Wilco DTC உள்ளமைவு</translation>
 <translation id="8758831693895931466">கட்டாயக் கிளவுட் நிர்வாகப் பதிவை இயக்கும்</translation>
 <translation id="8759829385824155666">அனுமதிக்கப்படும் Kerberos என்க்ரிப்ஷன் வகைகள்</translation>
 <translation id="8764119899999036911">உருவாக்கப்பட்ட Kerberos SPN, கனோனிக்கல் DNS பெயர் அல்லது உள்ளிட்ட உண்மையானப் பெயரின் அடிப்படையில் உள்ளதா என்பதைக் குறிப்பிடுகிறது. நீங்கள் இந்த அமைப்பை இயக்கினால், CNAME தேடல் தவிர்க்கப்படும் மேலும் நீங்கள் உள்ளிட்ட சேவையகத்தின் பெயர் பயன்படுத்தப்படும். நீங்கள் இந்த அமைப்பை முடக்கினால் அல்லது அமைக்கப்படாமல் இருந்தால், CNAME தேடல் வழியாக சேவையகத்தின் கனோனிக்கல் பெயர் அறியப்படும்.</translation>
+<translation id="8764477907716150749">இந்தக் கொள்கை <ph name="PRODUCT_NAME" />ன் அகப் பயன்பாட்டிற்கானது.</translation>
 <translation id="8765776988041674792">கடவுச்சொல்லை மாற்றும் URLலை உள்ளமைக்கும் (HTTP மற்றும் HTTPS திட்டங்கள் மட்டும்). கடவுச்சொல் பாதுகாப்புச் சேவை, பயனர்கள் உலாவியில் ஓர் எச்சரிக்கையைப் பார்த்த பின்னர் தங்கள் கடவுச்சொல்லை மாற்றுவதற்கு அவர்களை இந்த URLலுக்கு அனுப்பும்.
       இந்தக் கடவுச்சொல் மாற்றப் பக்கத்தில் புதிய கடவுச்சொல் கைரேகையை <ph name="PRODUCT_NAME" /> சரியாகப் பதிவுசெய்வதற்கு, https://www.chromium.org/developers/design-documents/create-amazing-password-forms என்னும் இணைப்பிலுள்ள வழிமுறைகளை உங்கள் கடவுச்சொல் மாற்றப் பக்கம் பின்பற்றுவதை உறுதிசெய்யவும்.
 
@@ -3317,6 +3795,26 @@
 <translation id="8833109046074170275">இயல்பு GAIA செயல்முறை வழியாக அங்கீகரித்தல்</translation>
 <translation id="8838303810937202360">ஒரு சாதனத்தின் பல பயனர்கள் நிறுவுவதற்கு உதவியாகப் பயன்பாடுகளையும் நீட்டிப்புகளையும் <ph name="PRODUCT_OS_NAME" /> தற்காலிகமாகச் சேமிக்கும், அதன் மூலம் ஒவ்வொரு பயனரும் மீண்டும் மீண்டும் பதிவிறக்குதல் தவிர்க்கப்படும்.
       இந்தக் கொள்கை உள்ளமைக்கப்படாவிட்டாலோ அல்லது அளவானது 1 மெ.பை.க்கும் குறைவான மதிப்பாக இருந்தாலோ, <ph name="PRODUCT_OS_NAME" /> இயல்பான தற்காலிகச் சேமிப்பைப் பயன்படுத்தும்.</translation>
+<translation id="8851325571441692315"><ph name="PRODUCT_NAME" /> பயன்படுத்தும் ப்ராக்ஸி சர்வரைக் குறிப்பிட உங்களை அனுமதிக்கும், பயனர்கள் ப்ராக்ஸி அமைப்புகளை மாற்றுவதைத் தடுக்கும்.
+
+          <ph name="PROXY_SETTINGS_POLICY_NAME" /> கொள்கை குறிப்பிடப்படவில்லை என்றால் மட்டுமே இந்தக் கொள்கை செயல்படுத்தப்படும்.
+
+          ப்ராக்ஸி சர்வரைப் பயன்படுத்த வேண்டாம் என்றும் எப்போதும் நேரடியாக இணைக்க வேண்டும் என்றும் தேர்வுசெய்தால் மற்ற எல்லா விருப்பங்களும் புறக்கணிக்கப்படும்.
+
+          சிஸ்டம் ப்ராக்ஸி அமைப்புகளைப் பயன்படுத்தும்படி தேர்வுசெய்தால் மற்ற எல்லா விருப்பங்களும் புறக்கணிக்கப்படும்.
+
+          ப்ராக்ஸி சர்வரைத் தானாகக் கண்டறியும்படி தேர்வுசெய்தால் மற்ற எல்லா விருப்பங்களும் புறக்கணிக்கப்படும்.
+
+          நிலையான சர்வர் ப்ராக்ஸி பயன்முறையைத் தேர்வுசெய்தால் 'ப்ராக்ஸி சர்வரின் முகவரி அல்லது URL', 'காற்புள்ளியால் பிரிக்கப்பட்ட ப்ராக்ஸி கடந்துபோதல் விதிகளின் பட்டியல்' ஆகியவற்றில் கூடுதல் விருப்பங்களைக் குறிப்பிடலாம். அதிகப்படியான முன்னுரிமை கொண்ட HTTP ப்ராக்ஸி சர்வர் மட்டுமே ARC ஆப்ஸுக்குக் கிடைக்கும்.
+
+          .pac ப்ராக்ஸி ஸ்கிரிப்ட்டைப் பயன்படுத்தும்படி தேர்வுசெய்தால் 'ப்ராக்ஸி .pac கோப்பிற்கான URL' என்பதில் அந்த ஸ்கிரிப்ட்டுக்கான URLலைக் குறிப்பிட வேண்டும்.
+
+          விரிவான உதாரணங்களைப் பார்க்க இந்த URLலுக்குச் செல்லவும்:
+          <ph name="PROXY_HELP_URL" />.
+
+          இந்த அமைப்பை இயக்கினால் கட்டளை வரியில் குறிப்பிடப்படும் ப்ராக்ஸி தொடர்பான எல்லா விருப்பங்களையும்<ph name="PRODUCT_NAME" /> மற்றும் ARC ஆப்ஸ் புறக்கணிக்கும்.
+
+          இந்தக் கொள்கையை அமைக்கவில்லை என்றால் பயனர்கள் தாங்களே ப்ராக்ஸி அமைப்புகளைத் தேர்வுசெய்து கொள்ள அனுமதிக்கப்படுவார்கள்.</translation>
 <translation id="8858642179038618439">YouTube பாதுகாப்புப் பயன்முறையைச் செயல்படுத்தும்</translation>
 <translation id="8860342862142842017">subjectPublicKeyInfo ஹேஷ்களின் பட்டியலுக்குச் சான்றிதழ் வெளிப்படைத்தன்மை செயலாக்கத்தை முடக்கு</translation>
 <translation id="8864975621965365890"><ph name="PRODUCT_FRAME_NAME" /> ஆல் தளம் வழங்கப்படும்போது தோன்றும் இயக்க அறிவுறுத்துதலை முடக்கும்</translation>
@@ -3427,6 +3925,14 @@
 
       கொள்கை அமைக்கப்படாமல் இருந்தால், உள்நுழைவுத் திரையில் பயனரைக் குறிப்பிடும் தோற்றப் படத்தைப் பயனர் தேர்வுசெய்யலாம்.</translation>
 <translation id="9035964157729712237">தடுப்புப் பட்டியலில் இருந்து, விலக்குவதற்கான நீட்டிப்பு IDகள்</translation>
+<translation id="9038839118379817310">வைஃபையை இயக்கும்</translation>
+<translation id="9039822628127365650">இந்தக் கொள்கை அமைக்கப்பட்டால் பயனர் தானாக வெளியேறிய பிறகு உள்ள நேரத்தைக் குறித்து, அமர்வை முடிக்கும். சிஸ்டம் ட்ரேயில் காட்டப்படும் நேரக் கணிப்பான் மூலம் மீதமிருக்கும் நேரம் பயனருக்குத் தெரிவிக்கப்படும்.
+
+      இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் அமர்வின் நீளம் வரம்பிடப்படாது.
+
+      இந்தக் கொள்கையை அமைத்தால் பயனரால் இதை மாற்றவோ மேலெழுதவோ முடியாது.
+
+      கொள்கையின் மதிப்பை மில்லி வினாடிகளில் குறிப்பிட வேண்டும். மதிப்புகள் 30 வினாடிகளில் இருந்து 24 மணிநேரம் வரையிலான வரம்பிற்கு மாற்றியமைக்கப்படும்.</translation>
 <translation id="9042911395677044526"><ph name="PRODUCT_OS_NAME" /> சாதனத்தில் பயன்படுத்துவதற்கு ஒவ்வொரு பயனருக்குமாக நெட்வொர்க் உள்ளமைவை வழங்க அனுமதிக்கிறது. நெட்வொர்க் உள்ளமைவு என்பது <ph name="ONC_SPEC_URL" /> இல் விளக்கப்பட்டுள்ளபடி திறந்த நெட்வொர்க் உள்ளமைவு வடிவத்தால் வரையறுக்கப்பட்ட JSON-வடிவமைப்புத் தொடர் ஆகும்.</translation>
 <translation id="906631898352326790">
       இந்தக் கொள்கை இயக்கப்பட்டிருந்தால், காற்புள்ளியால் பிரிக்கப்பட்ட பட்டியலில் குறிப்பிடப்பட்டுள்ள ஒவ்வொரு தளமும் அதற்குரிய செயல்முறையை இயக்கும். இது துணை டொமைன்களின்படியும் தளங்களைத் தனிப்படுத்தும். எ.கா. https://example.com/ எனக் குறிப்பிட்டால், https://example.com/ தளத்தின் ஒரு பகுதியாக https://foo.example.com/ எனும் தளமும் தனிப்படுத்தப்படும்.
@@ -3436,6 +3942,15 @@
 
       குறிப்பு: இந்தக் கொள்கை Androidல் பயன்படுத்தப்படாது. Androidல் IsolateOriginsஸை இயக்க, IsolateOriginsAndroid கொள்கை அமைப்பைப் பயன்படுத்தவும்.
       </translation>
+<translation id="9072600218500597787">தொலைநிலை அணுகல் ஹோஸ்ட்களின் மீது பயன்படுத்தத் தேவையான ஹோஸ்ட் டொமைன் பெயர்களை உள்ளமைக்கும், பயனர்கள் அதை மாற்றுவதைத் தடுக்கும்.
+
+          இந்த அமைப்பு இயக்கப்பட்டால் குறிப்பிடப்படும் டொமைன் பெயர்களில் ஒன்றில் பதிவு செய்த கணக்குகளைப் பயன்படுத்தி மட்டுமே ஹோஸ்ட்களைப் பகிர முடியும்.
+
+          இந்த அமைப்பு முடக்கப்பட்டாலோ அமைக்கப்படவில்லை என்றாலோ எந்தக் கணக்கையும் பயன்படுத்தி ஹோஸ்ட்களைப் பகிரலாம்.
+
+          RemoteAccessHostDomain இருந்தால் அதை இந்த அமைப்பு மேலெழுதும்.
+
+          RemoteAccessHostClientDomainList என்பதையும் பார்க்கவும்.</translation>
 <translation id="9077227880520270584">சாதன அகக் கணக்கு தானியங்கு உள்நுழைவு டைமர்</translation>
 <translation id="9084985621503260744">வீடியோ செயல்பாடு, சக்தி மேலாண்மையைப் பாதிக்குமா என்பதைக் குறிப்பிடவும்</translation>
 <translation id="9088433379343318874">மேற்பார்வையிடப்படும் பயனருக்கான உள்ளடக்க வழங்குநரை இயக்கு</translation>
@@ -3482,6 +3997,7 @@
 
           இந்தக் கொள்கை அமைக்கப்படவில்லை எனில், '3' பயன்படுத்தப்படும், மேலும் இதைப் பயனர் மாற்ற முடியும்.</translation>
 <translation id="9167719789236691545"><ph name="PRODUCT_OS_NAME" /> இன் கோப்புகள் பயன்பாட்டில் இயக்ககத்தை முடக்கும்</translation>
+<translation id="9185107612228451403">நீட்டிப்பு தொடர்பான கொள்கைகளை உள்ளமைக்கும். தடைப்பட்டியலில் உள்ள நீட்டிப்புகள் ஏற்புப் பட்டியலில் சேர்க்கப்படும் வரை அவற்றை நிறுவுவதற்கு பயனருக்கு அனுமதியில்லை. நீட்டிப்புகளை <ph name="EXTENSION_INSTALL_FORCELIST_POLICY_NAME" />ல் குறிப்பிடுவதன் மூலம் அவற்றைத் தானாகவே நிறுவ <ph name="PRODUCT_NAME" />ஐ நீங்கள் கட்டாயப்படுத்தவும் முடியும். அப்படிப்பட்ட நீட்டிப்புகள் தடைப்பட்டியலில் இருந்தாலும் இல்லாவிட்டாலும் நிறுவப்படும்.</translation>
 <translation id="9187743794267626640">வெளிப்புற சேமிப்பிடம் அமைப்பதை முடக்கு</translation>
 <translation id="9197740283131855199">மங்கலான பிறகு பயனர் செயலில் இருந்தால் திரையின் மங்கல் தாமதத்தை அளவிடுவதற்கான சதவீதம்</translation>
 <translation id="9200828125069750521">POST ஐப் பயன்படுத்தும் பட URL க்கான அளவுருக்கள்</translation>
@@ -3507,8 +4023,22 @@
 <translation id="9217154963008402249">கண்காணிக்கப்படும் நெட்வொர்க் பாக்கெட்டுகள் அனுப்பப்படும் கால இடைவெளி</translation>
 <translation id="922540222991413931">நீட்டிப்பு, பயன்பாடு, பயனர் ஸ்கிரிப்ட் நிறுவல் ஆதாரங்களை உள்ளமை</translation>
 <translation id="924557436754151212">முதல் இயக்கத்தின்போதே இயல்புநிலை உலாவலிருந்து சேமித்த கடவுச்சொற்களை இறக்குமதி செய்</translation>
+<translation id="926146562923985266">Internet Explorerரில் இருந்து மாறும் போது <ph name="PRODUCT_NAME" />ல் உள்ள URLகளைத் திறப்பதற்குப் பயன்படுத்தப்படும் கட்டளையை இந்தக் கொள்கை கட்டுப்படுத்தும்.
+
+      Internet Explorerருக்கான ‘லெகஸி உலாவி ஆதரவு’ செருகு நிரல் நிறுவப்படவில்லை எனில் இந்தக் கொள்கை எந்த மாற்றத்தையும் ஏற்படுத்தாது.
+
+      இந்தக் கொள்கை அமைக்கப்படவில்லை எனில் Internet Explorerரில் இருந்து <ph name="PRODUCT_NAME" />ஐ வெளியிடும் போது, <ph name="PRODUCT_NAME" />ன் செயல்படுத்தக்கூடிய சொந்தத் தடத்தை Internet Explorer தானாகவே கண்டறியும்.
+
+      இந்தக் கொள்கை அமைக்கப்பட்டால் Internet Explorerரில் இருந்து <ph name="PRODUCT_NAME" />ஐ வெளியிடும் போது, <ph name="PRODUCT_NAME" />ஐ வெளியிட இது பயன்படுத்தப்படும்.
+
+      செயல்படுத்தக்கூடிய கோப்புத் தடமாகவோ Chromeமின் நிறுவப்பட்ட இருப்பிடத்தைத் தானாகக் கண்டறிய ${chrome} ஆகவோ இந்தக் கொள்கையை அமைக்கலாம்.</translation>
 <translation id="930930237275114205"><ph name="PRODUCT_FRAME_NAME" /> பயனர் தரவு கோப்பகத்தை அமை</translation>
+<translation id="943865157632139008"><ph name="PRODUCT_FRAME_NAME" /> நிறுவப்பட்டுள்ள போது இயல்புநிலை HTML ரெண்டரை உள்ளமைக்க உங்களை அனுமதிக்கும்.
+ரெண்டரிங் செய்வதற்கு ஹோஸ்ட் உலாவியை அனுமதிப்பதே இயல்புநிலை அமைப்பாகும், ஆனால் உங்கள் விருப்பத்தின்படி இதை மேலெழுத முடியும். மேலும் இயல்புநிலையாக <ph name="PRODUCT_FRAME_NAME" /> HTML பக்கங்களை ரெண்டர் செய்ய அனுமதிக்கலாம்.</translation>
 <translation id="944817693306670849">வட்டு தேக்கக அளவை அமை</translation>
+<translation id="966854160628341653">புதிய பயனர் கணக்குகள் உருவாவதற்கு <ph name="PRODUCT_OS_NAME" /> அனுமதிப்பதைக் கட்டுப்படுத்தும். இந்தக் கொள்கை 'தவறு' என அமைக்கப்பட்டால் ஏற்கனவே கணக்கைக் கொண்டிராத பயனர்களால் உள்நுழைய முடியாது.
+
+      இந்தக் கொள்கை 'சரி' என அமைக்கப்பட்டாலோ உள்ளமைக்கப்படவில்லை என்றாலோ புதிய பயனர் கணக்குகள் உருவாவதற்கு அனுமதிக்கப்படும். பயனர் உள்நுழைவதை <ph name="DEVICE_USER_WHITELIST_POLICY_NAME" /> தடுக்காது.</translation>
 <translation id="981346395360763138">Google இருப்பிடச் சேவைகள் முடக்கப்பட்டன</translation>
 <translation id="982497069985795632">எழுத்துச்சரிபார்ப்பை இயக்கு</translation>
 <translation id="991560005425213776">பயனர்பெயரையும் கோப்புப்பெயரையும் சொந்தப் பிரிண்டர்களுக்கு அனுப்பவும்</translation>
diff --git a/components/safe_browsing/browser/threat_details.h b/components/safe_browsing/browser/threat_details.h
index ac3b3ec8..ca0c746 100644
--- a/components/safe_browsing/browser/threat_details.h
+++ b/components/safe_browsing/browser/threat_details.h
@@ -25,7 +25,6 @@
 #include "components/security_interstitials/content/unsafe_resource.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents_observer.h"
-#include "net/base/completion_callback.h"
 
 namespace history {
 class HistoryService;
diff --git a/components/safe_browsing/browser/threat_details_cache.h b/components/safe_browsing/browser/threat_details_cache.h
index 89508a23..81207096 100644
--- a/components/safe_browsing/browser/threat_details_cache.h
+++ b/components/safe_browsing/browser/threat_details_cache.h
@@ -14,7 +14,6 @@
 
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
-#include "net/base/completion_callback.h"
 
 namespace network {
 class SimpleURLLoader;
diff --git a/components/safe_browsing/browser/threat_details_history.h b/components/safe_browsing/browser/threat_details_history.h
index c294956..16bd25ff 100644
--- a/components/safe_browsing/browser/threat_details_history.h
+++ b/components/safe_browsing/browser/threat_details_history.h
@@ -18,7 +18,6 @@
 #include "base/task/cancelable_task_tracker.h"
 #include "components/history/core/browser/history_service_observer.h"
 #include "content/public/browser/browser_thread.h"
-#include "net/base/completion_callback.h"
 
 namespace safe_browsing {
 
diff --git a/components/safe_browsing/features.cc b/components/safe_browsing/features.cc
index a0b2f53b..29ce5fa 100644
--- a/components/safe_browsing/features.cc
+++ b/components/safe_browsing/features.cc
@@ -64,6 +64,9 @@
 const base::Feature kUseAPDownloadProtection{"UseAPDownloadProtection",
                                              base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kForceUseAPDownloadProtection{
+    "ForceUseAPDownloadProtection", base::FEATURE_DISABLED_BY_DEFAULT};
+
 namespace {
 // List of experimental features. Boolean value for each list member should be
 // set to true if the experiment is currently running at a probability other
@@ -84,6 +87,7 @@
     {&kTriggerThrottlerDailyQuotaFeature, false},
     {&kUseLocalBlacklistsV2, true},
     {&kUseAPDownloadProtection, false},
+    {&kForceUseAPDownloadProtection, false},
 };
 
 // Adds the name and the enabled/disabled status of a given feature.
diff --git a/components/safe_browsing/features.h b/components/safe_browsing/features.h
index 568bf0b6..87392b4 100644
--- a/components/safe_browsing/features.h
+++ b/components/safe_browsing/features.h
@@ -69,6 +69,9 @@
 // Controls whether we use AP download protection.
 extern const base::Feature kUseAPDownloadProtection;
 
+// Controls whether the user has forcible enabled AP download protection.
+extern const base::Feature kForceUseAPDownloadProtection;
+
 base::ListValue GetFeatureStatusList();
 
 }  // namespace safe_browsing
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc
index 4ab8b9b..abced09d 100644
--- a/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -238,8 +238,6 @@
 
   std::string PickAccountIdForAccount(const std::string& gaia_id,
                                       const std::string& username);
-  std::string SeedAccountInfo(const std::string& gaia_id,
-                              const std::string& username);
 
   void SimulateAddAccountToCookieCompleted(AccountReconcilor* reconcilor,
                                            const std::string& account_id,
@@ -366,16 +364,6 @@
       gaia_id, username);
 }
 
-std::string AccountReconcilorTest::SeedAccountInfo(
-    const std::string& gaia_id,
-    const std::string& username) {
-  AccountInfo account_info;
-  account_info.gaia = gaia_id;
-  account_info.email = username;
-  return identity_test_env()->identity_manager()->LegacySeedAccountInfo(
-      account_info);
-}
-
 void AccountReconcilorTest::SimulateAddAccountToCookieCompleted(
     AccountReconcilor* reconcilor,
     const std::string& account_id,
@@ -1159,8 +1147,7 @@
   ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1));
   ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_2));
 
-  // Add accounts 2 and 3 to the Gaia cookie.
-  const std::string account_id_3 = SeedAccountInfo("9999", "foo@gmail.com");
+  // Add account 2 to the Gaia cookie.
   signin::SetListAccountsResponseTwoAccounts(
       account_info_2.email, account_info_2.gaia, "foo@gmail.com", "9999",
       &test_url_loader_factory_);
@@ -2401,7 +2388,10 @@
   AccountInfo account_info2 =
       identity_test_env()->MakeAccountAvailable("other@gmail.com");
   const std::string account_id2 = account_info2.account_id;
-  const std::string account_id3 = SeedAccountInfo("34567", "third@gmail.com");
+
+  const std::string email3 = "third@gmail.com";
+  const std::string gaia_id3 = identity::GetTestGaiaIdForEmail(email3);
+  const std::string account_id3 = PickAccountIdForAccount(gaia_id3, email3);
 
   signin::SetListAccountsResponseOneAccount(
       account_info.email, account_info.gaia, &test_url_loader_factory_);
@@ -2448,7 +2438,7 @@
   identity_test_env()->SetFreshnessOfAccountsInGaiaCookie(false);
 
   // This will cause the reconcilor to fire.
-  identity_test_env()->SetRefreshTokenForAccount(account_id3);
+  identity_test_env()->MakeAccountAvailable(email3);
   if (IsMultiloginEnabled()) {
     std::vector<std::string> accounts_to_send = {account_id, account_id2,
                                                  account_id3};
diff --git a/components/strings/components_strings_cs.xtb b/components/strings/components_strings_cs.xtb
index 569b33f..69a05e0 100644
--- a/components/strings/components_strings_cs.xtb
+++ b/components/strings/components_strings_cs.xtb
@@ -1052,7 +1052,7 @@
 <translation id="6965978654500191972">Zařízení</translation>
 <translation id="6970216967273061347">Okres</translation>
 <translation id="6973656660372572881">Určeny jsou pevně dané servery proxy i adresa URL skriptu PAC.</translation>
-<translation id="6973932557599545801">Pardon, nedokážu vám pomoct. Pokračujte prosím sami.</translation>
+<translation id="6973932557599545801">Pardon, nedokážu vám pomoct. Je to na vás.</translation>
 <translation id="6979158407327259162">Disk Google</translation>
 <translation id="6979440798594660689">Ztlumit (výchozí)</translation>
 <translation id="6984479912851154518">Chystáte se opustit soukromý režim, abyste mohli zaplatit v externí aplikaci. Chcete pokračovat?</translation>
diff --git a/components/strings/components_strings_en-GB.xtb b/components/strings/components_strings_en-GB.xtb
index f7e740c..4ac7f7a 100644
--- a/components/strings/components_strings_en-GB.xtb
+++ b/components/strings/components_strings_en-GB.xtb
@@ -160,7 +160,7 @@
 <translation id="1734864079702812349">Amex</translation>
 <translation id="1734878702283171397">Try contacting the system admin.</translation>
 <translation id="1740951997222943430">Enter a valid expiry month</translation>
-<translation id="1743520634839655729">To pay faster next time, save your card, name and billing address to your Google Accountand to this device.</translation>
+<translation id="1743520634839655729">To pay faster next time, save your card, name and billing address to your Google Account and to this device.</translation>
 <translation id="1745880797583122200">Your browser is managed</translation>
 <translation id="17513872634828108">Open tabs</translation>
 <translation id="1753706481035618306">Page number</translation>
@@ -508,13 +508,13 @@
 <translation id="373042150751172459">B4 (Envelope)</translation>
 <translation id="3736520371357197498">If you understand the risks to your security, you may <ph name="BEGIN_LINK" />visit this unsafe site<ph name="END_LINK" /> before the dangerous programs have been removed.</translation>
 <translation id="3744899669254331632">You cannot visit <ph name="SITE" /> right now because the website sent scrambled credentials that Chromium cannot process. Network errors and attacks are usually temporary, so this page will probably work later.</translation>
-<translation id="3745099705178523657">Once you confirm, card details from your Google Accountwill be shared with this site.</translation>
+<translation id="3745099705178523657">Once you confirm, card details from your Google Account will be shared with this site.</translation>
 <translation id="3748148204939282805">Attackers on <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> may trick you into doing something dangerous like installing software or revealing your personal information (for example, passwords, phone numbers or credit cards). <ph name="BEGIN_LEARN_MORE_LINK" />Learn more<ph name="END_LEARN_MORE_LINK" /></translation>
 <translation id="375403751935624634">The translation failed because of a server error.</translation>
 <translation id="3759461132968374835">You have no recently reported crashes.  Crashes that occurred when crash reporting was disabled will not appear here.</translation>
 <translation id="3761718714832595332">Hide status</translation>
 <translation id="3765032636089507299">The Safe Browsing page is under construction.</translation>
-<translation id="3778403066972421603">Do you want to save this card to yourGoogle Accountand on this device?</translation>
+<translation id="3778403066972421603">Do you want to save this card to your Google Account and on this device?</translation>
 <translation id="3781428340399460090">Hot pink</translation>
 <translation id="3783418713923659662">Mastercard</translation>
 <translation id="3787705759683870569">Expires <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
@@ -687,7 +687,7 @@
 <translation id="4764776831041365478">The web page at <ph name="URL" /> might be temporarily down or it may have moved permanently to a new web address.</translation>
 <translation id="4771973620359291008">An unknown error has occurred.</translation>
 <translation id="4785689107224900852">Switch to this tab</translation>
-<translation id="4798078619018708837">Enter the expiry date and CVC for <ph name="CREDIT_CARD" /> to update your card details. Once you confirm, card details from your Google Accountwill be shared with this site.</translation>
+<translation id="4798078619018708837">Enter the expiry date and CVC for <ph name="CREDIT_CARD" /> to update your card details. Once you confirm, card details from your Google Account will be shared with this site.</translation>
 <translation id="4800132727771399293">Check your expiration date and CVC and try again</translation>
 <translation id="480334179571489655">Origin Policy Error</translation>
 <translation id="4803924862070940586"><ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
@@ -753,7 +753,7 @@
 <translation id="5145883236150621069">Error code present in the policy response</translation>
 <translation id="515292512908731282">C4 (Envelope)</translation>
 <translation id="5159010409087891077">Open page in a new Incognito window (⇧⌘N)</translation>
-<translation id="516920405563544094">Enter the CVC for <ph name="CREDIT_CARD" />. Once you confirm, card details from yourGoogle Accountwill be shared with this site.</translation>
+<translation id="516920405563544094">Enter the CVC for <ph name="CREDIT_CARD" />. Once you confirm, card details from your Google Account will be shared with this site.</translation>
 <translation id="5169827969064885044">You could lose access to your organisation's account or experience identity theft. Chrome recommends changing your password now.</translation>
 <translation id="5171045022955879922">Search or type URL</translation>
 <translation id="5171689220826475070">Fanfold-European</translation>
@@ -1013,7 +1013,7 @@
 <translation id="6710594484020273272">&lt;Type search term&gt;</translation>
 <translation id="671076103358959139">Enrolment Token:</translation>
 <translation id="6711464428925977395">There is something wrong with the proxy server or the address is incorrect.</translation>
-<translation id="6723740634201835758">In yourGoogle Account</translation>
+<translation id="6723740634201835758">In your Google Account</translation>
 <translation id="6738516213925468394">Your data was encrypted with your <ph name="BEGIN_LINK" />sync passphrase<ph name="END_LINK" /> on <ph name="TIME" />. Enter it to start sync.</translation>
 <translation id="674375294223700098">Unknown server certificate error.</translation>
 <translation id="6744009308914054259">While waiting for a connection, you can visit Downloads to read offline articles.</translation>
@@ -1042,7 +1042,7 @@
 <translation id="6897140037006041989">User Agent</translation>
 <translation id="6903319715792422884">Help improve Safe Browsing by sending some <ph name="BEGIN_WHITEPAPER_LINK" />system information and page content<ph name="END_WHITEPAPER_LINK" /> to Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
 <translation id="6915804003454593391">User:</translation>
-<translation id="6934672428414710184">This name is from yourGoogle Account</translation>
+<translation id="6934672428414710184">This name is from your Google Account</translation>
 <translation id="6939583532829045966">Your device is managed by <ph name="ENROLLMENT_DOMAIN" />. This means that your administrator may remotely configure your device.</translation>
 <translation id="6944692733090228304">You entered your password on a site that’s not managed by <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. To protect your account, don’t reuse your password on other apps and sites.</translation>
 <translation id="6945221475159498467">Select</translation>
@@ -1289,7 +1289,7 @@
 <translation id="8131740175452115882">Confirm</translation>
 <translation id="8149426793427495338">Your computer went to sleep.</translation>
 <translation id="8150722005171944719">The file at <ph name="URL" /> is not readable.  It may have been removed, moved or file permissions may be preventing access.</translation>
-<translation id="8175796834047840627">Chrome is offering to save your cards in your Google Accountbecause you are signed in. You can change this behaviour in settings.</translation>
+<translation id="8175796834047840627">Chrome is offering to save your cards in your Google Account because you are signed in. You can change this behaviour in settings.</translation>
 <translation id="8184538546369750125">Use global default (Allow)</translation>
 <translation id="8194797478851900357">&amp;Undo Move</translation>
 <translation id="8197543752516192074">Translate page</translation>
diff --git a/components/strings/components_strings_fil.xtb b/components/strings/components_strings_fil.xtb
index 26d0035..47837ea 100644
--- a/components/strings/components_strings_fil.xtb
+++ b/components/strings/components_strings_fil.xtb
@@ -8,6 +8,7 @@
 <translation id="1032854598605920125">I-rotate pakanan</translation>
 <translation id="1035334672863811645">mag-sign in sa Chrome</translation>
 <translation id="1038842779957582377">Hindi kilalang pangalan</translation>
+<translation id="1039626062703039346">Matutulungan ka ng Chrome na protektahan ang iyong Google Account at palitan ang password mo. Aabisuhan nito ang Google tungkol sa site na ito.</translation>
 <translation id="1050038467049342496">Isara ang iba pang app</translation>
 <translation id="1055184225775184556">&amp;I-undo ang Pagdagdag</translation>
 <translation id="1056898198331236512">Babala</translation>
@@ -296,13 +297,16 @@
 <translation id="2495083838625180221">Pang-parse ng JSON</translation>
 <translation id="2495093607237746763">Kung may check, mag-iimbak ang Chromium ng kopya ng iyong card sa device na ito para sa mas mabilis na pagsagot sa form.</translation>
 <translation id="2498091847651709837">Mag-scan ng bagong card</translation>
+<translation id="249825481377667906">Makakatulong sa iyo ang Chromium na protektahan ang iyong Google Account at palitan ang password mo. Aabisuhan nito ang Google tungkol sa site na ito.</translation>
 <translation id="2501278716633472235">Bumalik</translation>
 <translation id="2503184589641749290">Mga tinatanggap na debit at prepaid card</translation>
+<translation id="2505268675989099013">Protektahan ang Account</translation>
 <translation id="2515629240566999685">Suriin ang signal sa iyong lugar</translation>
 <translation id="2523886232349826891">Ise-save sa device lang na ito</translation>
 <translation id="2524461107774643265">Magdagdag ng Higit Pang Impormasyon</translation>
 <translation id="2536110899380797252">Magdagdag ng Address</translation>
 <translation id="2539524384386349900">Tukuyin</translation>
+<translation id="254947805923345898">Di-wasto ang value ng patakaran.</translation>
 <translation id="255002559098805027">Nagpadala ng di-wastong tugon ang <ph name="HOST_NAME" />.</translation>
 <translation id="2556876185419854533">&amp;I-undo ang Pag-e-edit</translation>
 <translation id="2586657967955657006">Clipboard</translation>
@@ -435,6 +439,7 @@
           <ph name="LIST_ITEM" />Cookies at data ng site
           <ph name="LIST_ITEM" />Impormasyong nilagay sa mga form
         <ph name="END_LIST" /></translation>
+<translation id="3362968246557010467">Awtomatikong kinopya ang patakarang ito mula sa hindi na ginagamit na patakarang <ph name="OLD_POLICY" />. Dapat mong gamitin ang patakarang ito sa halip.</translation>
 <translation id="3366477098757335611">Tingnan ang mga card</translation>
 <translation id="3369192424181595722">Error sa orasan</translation>
 <translation id="337363190475750230">Naalis sa pagkakaprobisyon</translation>
@@ -558,6 +563,7 @@
 <translation id="4072486802667267160">Nagkaroon ng error sa pagproseso ng iyong order. Pakisubukang muli.</translation>
 <translation id="4075732493274867456">Hindi sinusuportahan ng client at server ang isang karaniwang bersyon o cipher suite ng SSL protocol.</translation>
 <translation id="4079302484614802869">Nakatakda ang configuration ng proxy upang gumamit ng isang .pac script URL, hindi ng mga hindi nababagong proxy server.</translation>
+<translation id="4092411512356034591">Magpatuloy sa <ph name="DOMAIN" />?</translation>
 <translation id="4098354747657067197">Mapupunta sa nakakapanlinlang na site</translation>
 <translation id="4103249731201008433">Di-wasto ang serial number ng device</translation>
 <translation id="410351446219883937">I-autoplay</translation>
@@ -829,6 +835,7 @@
 <translation id="5556459405103347317">I-reload</translation>
 <translation id="5560088892362098740">Petsa ng Pag-expire</translation>
 <translation id="5565735124758917034">Aktibo</translation>
+<translation id="5570825185877910964">Protektahan ang account</translation>
 <translation id="5571083550517324815">Hindi maaaring mag-pick up mula sa address na ito. Pumili ng ibang address.</translation>
 <translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 ang ginagamit}one{# ang ginagamit}other{# ang ginagamit}})</translation>
 <translation id="5572851009514199876">Magsimula at mag-sign in sa Chrome upang masuri ng Chrome kung pinapayagan kang i-access ang site na ito.</translation>
@@ -965,10 +972,12 @@
 <translation id="6386120369904791316">{COUNT,plural, =1{1 pang suhestyon}one{# pang suhestyon}other{# pang suhestyon}}</translation>
 <translation id="6387754724289022810">Para mas mabilis na makapagbayad sa susunod, i-save ang iyong card at billing address sa Google Account mo at sa device na ito.</translation>
 <translation id="6390662030813198813">Engineering-E</translation>
+<translation id="6401136357288658127">Hindi na ginagamit ang patakarang ito. Dapat mong gamitin ang patakarang <ph name="NEW_POLICY" /> sa halip.</translation>
 <translation id="6404511346730675251">I-edit ang bookmark</translation>
 <translation id="6406765186087300643">C0 (Envelope)</translation>
 <translation id="6410264514553301377">Ilagay ang petsa ng pag-expire at CVC para sa <ph name="CREDIT_CARD" /></translation>
 <translation id="6414888972213066896">Tinanong mo ang iyong magulang kung maaari mong bisitahin ang site na ito</translation>
+<translation id="6415778972515849510">Makakatulong sa iyo ang Chromium na protektahan ang iyong Google Account at palitan ang password mo.</translation>
 <translation id="6417515091412812850">Hindi nagawang masuri kung nabawi na ang certificate.</translation>
 <translation id="6433490469411711332">I-edit ang impormasyon sa pakikipag-ugnayan</translation>
 <translation id="6433595998831338502">Tumangging kumonekta ang <ph name="HOST_NAME" />.</translation>
@@ -1034,6 +1043,7 @@
 <translation id="6868206169573555318">Muling Ilunsad para I-update</translation>
 <translation id="6874604403660855544">&amp;Gawing muli ang pagdagdag</translation>
 <translation id="6884662655240309489">Laki 1</translation>
+<translation id="6884796835813057577">Magpatuloy sa &lt;a href="#" id="dont-proceed-link"&gt;<ph name="DOMAIN" />&lt;/a&gt;?</translation>
 <translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
 <translation id="6891596781022320156">Hindi sinusuportahan ang antas ng patakaran.</translation>
 <translation id="6895330447102777224">Nakumpirma na ang iyong card</translation>
@@ -1055,7 +1065,7 @@
 <translation id="6965978654500191972">Device</translation>
 <translation id="6970216967273061347">Distrito</translation>
 <translation id="6973656660372572881">Tinukoy ang parehong mga hindi nababagong proxy server at isang .pac script URL.</translation>
-<translation id="6973932557599545801">Paumanhin, hindi ako makatulong, mangyaring magpatuloy nang mag-isa.</translation>
+<translation id="6973932557599545801">Paumanhin, hindi ako makatulong. Magpatuloy nang mag-isa.</translation>
 <translation id="6979158407327259162">Google Drive</translation>
 <translation id="6979440798594660689">I-mute (default)</translation>
 <translation id="6984479912851154518">Aalis sa pribadong mode para magbayad sa pamamagitan ng external na application. Magpatuloy?</translation>
@@ -1352,6 +1362,7 @@
 <translation id="8503559462189395349">Mga Password sa Chrome</translation>
 <translation id="8503813439785031346">Username</translation>
 <translation id="8508648098325802031">Icon ng paghahanap</translation>
+<translation id="8522552481199248698">Matutulungan ka ng Chrome na protektahan ang iyong Google Account at palitan ang password mo.</translation>
 <translation id="8543181531796978784">Maaari kang <ph name="BEGIN_ERROR_LINK" />mag-ulat ng problema sa pagtukoy<ph name="END_ERROR_LINK" /> o, kung nauunawaan mo ang mga panganib sa iyong seguridad, <ph name="BEGIN_LINK" />bisitahin ang hindi ligtas na site na ito<ph name="END_LINK" />.</translation>
 <translation id="8543556556237226809">May mga tanong? Makipag-ugnayan sa taong nangangasiwa sa iyong profile.</translation>
 <translation id="8553075262323480129">Nabigo ang pag-translate dahil hindi matukoy ang wika ng pahina.</translation>
@@ -1438,6 +1449,7 @@
 <translation id="9076630408993835509">Hindi pinapamahalaan ng kumpanya o iba pang organisasyon ang browser na ito. Maaaring pinapamahalaan sa labas ng Chrome ang aktibidad sa device na ito. <ph name="BEGIN_LINK" />Matuto Pa<ph name="END_LINK" /></translation>
 <translation id="9078964945751709336">Nangangailangan ng higit pang impormasyon</translation>
 <translation id="9080712759204168376">Buod ng Order</translation>
+<translation id="9095388113577226029">Higit pang wika...</translation>
 <translation id="9103872766612412690">Karaniwang gumagamit ang <ph name="SITE" /> ng pag-encrypt upang protektahan ang iyong impormasyon. Noong sinubukang kumonekta ng Chromium sa <ph name="SITE" /> sa pagkakataong ito, nagbalik ang website ng mga hindi pangkaraniwan at maling kredensyal. Maaari itong mangyari kapag sinusubukan ng isang attacker na magpanggap bilang <ph name="SITE" />, o naputol ang koneksyon dahil sa isang screen ng pag-sign in sa Wi-Fi. Secure pa rin ang iyong impormasyon dahil inihinto ng Chromium ang koneksyon bago magkaroon ng palitan ng anumang data.</translation>
 <translation id="9106062320799175032">Magdagdag ng Billing Address</translation>
 <translation id="9114524666733003316">Kinukumpirma ang card...</translation>
diff --git a/components/strings/components_strings_iw.xtb b/components/strings/components_strings_iw.xtb
index e4c064a..5c3852d8 100644
--- a/components/strings/components_strings_iw.xtb
+++ b/components/strings/components_strings_iw.xtb
@@ -480,7 +480,7 @@
 <translation id="3592413004129370115">Italian (Envelope)‎</translation>
 <translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
 <translation id="3614103345592970299">גודל 2</translation>
-<translation id="361438452008624280">רשומה ברשימה "<ph name="LANGUAGE_ID" />": לא ידוע או שפה לא נתמכת.</translation>
+<translation id="361438452008624280">רשומה ברשימה "<ph name="LANGUAGE_ID" />": שפה לא מוכרת או לא נתמכת.</translation>
 <translation id="3615877443314183785">עליך להזין תאריך תפוגה חוקי</translation>
 <translation id="36224234498066874">ניקוי נתוני גלישה…</translation>
 <translation id="362276910939193118">כל ההיסטוריה</translation>
@@ -1062,7 +1062,7 @@
 <translation id="6965978654500191972">התקן</translation>
 <translation id="6970216967273061347">מחוז</translation>
 <translation id="6973656660372572881">‏צוינו שרתי Proxy קבועים וכתובת אתר של הסקריפט מסוג ‎.Pac</translation>
-<translation id="6973932557599545801">אין לי אפשרות לעזור. עליך להמשיך בעצמך.</translation>
+<translation id="6973932557599545801">לצערי אין לי אפשרות לעזור. עליך להמשיך בעצמך.</translation>
 <translation id="6979158407327259162">Google Drive</translation>
 <translation id="6979440798594660689">השתקה (ברירת מחדל)</translation>
 <translation id="6984479912851154518">בחרת לצאת ממצב פרטי כדי לשלם באמצעות אפליקציה חיצונית. להמשיך?</translation>
diff --git a/components/strings/components_strings_ja.xtb b/components/strings/components_strings_ja.xtb
index 08a2c7f..e59830d 100644
--- a/components/strings/components_strings_ja.xtb
+++ b/components/strings/components_strings_ja.xtb
@@ -126,7 +126,7 @@
       &lt;p&gt;&lt;strong&gt;設定&lt;/strong&gt;アプリの [&lt;strong&gt;全般&lt;/strong&gt;] セクションで日時を調整してください。&lt;/p&gt;</translation>
 <translation id="1569487616857761740">有効期限の入力</translation>
 <translation id="1581080074034554886">CVC</translation>
-<translation id="1583429793053364125">このウェブページを表示中に問題が発生しました。</translation>
+<translation id="1583429793053364125">このウェブページの表示中に問題が発生しました。</translation>
 <translation id="1592005682883173041">ローカルデータへのアクセス</translation>
 <translation id="1594030484168838125">選択</translation>
 <translation id="161042844686301425">シアン</translation>
@@ -235,7 +235,7 @@
 <translation id="2202020181578195191">有効期限(年)を正しい形式で入力してください</translation>
 <translation id="2212735316055980242">ポリシーが見つかりません</translation>
 <translation id="2213606439339815911">エントリを取得しています...</translation>
-<translation id="2218879909401188352"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> では現在、悪意のあるユーザーによって危険なアプリ(端末に問題を生じたり、モバイル利用料に不明瞭な請求を加えたり、個人情報を抜き取ったりするアプリ)がインストールされる可能性があります。<ph name="BEGIN_LEARN_MORE_LINK" />詳細<ph name="END_LEARN_MORE_LINK" /></translation>
+<translation id="2218879909401188352"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> では現在、悪意のあるユーザーによって危険なアプリ(端末に問題を生じさせたり、モバイル利用料に不明瞭な請求を加えたり、個人情報を抜き取ったりするアプリ)がインストールされる可能性があります。<ph name="BEGIN_LEARN_MORE_LINK" />詳細<ph name="END_LEARN_MORE_LINK" /></translation>
 <translation id="2224337661447660594">インターネットに接続されていません</translation>
 <translation id="2230458221926704099"><ph name="BEGIN_LINK" />診断アプリ<ph name="END_LINK" />を使用して接続を修正してください</translation>
 <translation id="2239100178324503013">送信</translation>
@@ -482,7 +482,7 @@
 <translation id="3614103345592970299">サイズ 2</translation>
 <translation id="361438452008624280">リスト項目「<ph name="LANGUAGE_ID" />」: 不明またはサポートされていない言語です。</translation>
 <translation id="3615877443314183785">有効期限(日)を入力してください</translation>
-<translation id="36224234498066874">閲覧履歴を消去...</translation>
+<translation id="36224234498066874">閲覧履歴データを削除...</translation>
 <translation id="362276910939193118">全履歴を表示</translation>
 <translation id="3630155396527302611">ネットワークへのアクセスを許可されたプログラムとして既に表示されている場合は、
       いったんリストから削除し、もう一度追加してみてください。</translation>
@@ -798,7 +798,7 @@
 <translation id="5386426401304769735">このサイトの証明書チェーンには SHA-1 を使って署名された証明書が含まれています。</translation>
 <translation id="538659543871111977">A4-Tab</translation>
 <translation id="540969355065856584">このサーバーが <ph name="DOMAIN" /> であることを確認できませんでした。このサーバーのセキュリティ証明書は現在有効ではありません。設定が不適切か、悪意のあるユーザーによって接続が妨害されている可能性があります。</translation>
-<translation id="5421136146218899937">閲覧履歴データの消去...</translation>
+<translation id="5421136146218899937">閲覧履歴データを削除...</translation>
 <translation id="5430298929874300616">ブックマークを削除</translation>
 <translation id="5431657950005405462">ファイルが見つかりませんでした</translation>
 <translation id="5439770059721715174">「<ph name="ERROR_PATH" />」でスキーマ確認エラー: <ph name="ERROR" /></translation>
@@ -853,7 +853,7 @@
 <translation id="5684874026226664614">このページを翻訳できませんでした。</translation>
 <translation id="5685654322157854305">配送先住所を追加</translation>
 <translation id="5689199277474810259">JSON にエクスポート</translation>
-<translation id="5689516760719285838">現在地</translation>
+<translation id="5689516760719285838">位置情報</translation>
 <translation id="570530837424789914">管理...</translation>
 <translation id="57094364128775171">安全なパスワードを自動生成…</translation>
 <translation id="5710435578057952990">このウェブサイトの ID は確認されていません。</translation>
@@ -927,7 +927,7 @@
 <translation id="6144381551823904650">{COUNT,plural, =0{なし}=1{1 個のパスワード(同期済み)}other{# 個のパスワード(同期済み)}}</translation>
 <translation id="6146055958333702838">ケーブルを確認し、使用しているネットワーク デバイス(ルーター、モデムなど)を
     再起動してください。</translation>
-<translation id="614940544461990577">次をお試しください:</translation>
+<translation id="614940544461990577">次をお試しください</translation>
 <translation id="6151417162996330722">サーバー証明書の有効期限が長すぎます。</translation>
 <translation id="6157877588268064908">配送方法と要件を確認するには、住所を選択してください</translation>
 <translation id="6165508094623778733">詳しく見る</translation>
@@ -1065,7 +1065,7 @@
 <translation id="6993898126790112050">6x9(封筒)</translation>
 <translation id="6996312675313362352"><ph name="ORIGINAL_LANGUAGE" />を常に翻訳</translation>
 <translation id="7012363358306927923">中国銀聯</translation>
-<translation id="7016992613359344582">料金の請求は 1 回限りの場合も毎月行われる場合もあり、課金されたかどうかわからないこともあります。</translation>
+<translation id="7016992613359344582">料金の請求は 1 回限りの場合も繰り返し行われる場合もあり、課金されたかどうかわからないこともあります。</translation>
 <translation id="7029809446516969842">パスワード</translation>
 <translation id="7050187094878475250"><ph name="DOMAIN" /> にアクセスしようとしましたが、サーバーに提示された証明書の有効期限が長すぎて信頼性を確認できませんでした。</translation>
 <translation id="705310974202322020">{NUM_CARDS,plural, =1{現在、このカードは保存できません}other{現在、これらのカードは保存できません}}</translation>
@@ -1330,7 +1330,7 @@
 <translation id="8368476060205742148">Google Play 開発者サービス</translation>
 <translation id="8371889962595521444">カスタムルート証明書</translation>
 <translation id="8380941800586852976">危険</translation>
-<translation id="8381674639488873545">料金の請求は 1 回限りの場合も毎月行われる場合もあり、課金されたかどうかわからないこともあります。<ph name="BEGIN_LINK" />理解したうえで表示する<ph name="END_LINK" /></translation>
+<translation id="8381674639488873545">料金の請求は 1 回限りの場合も繰り返し行われる場合もあり、課金されたかどうかわからないこともあります。<ph name="BEGIN_LINK" />理解したうえで表示する<ph name="END_LINK" /></translation>
 <translation id="8398259832188219207">クラッシュ レポートが <ph name="UPLOAD_TIME" /> にアップロードされました</translation>
 <translation id="8412145213513410671">障害数(<ph name="CRASH_COUNT" />)</translation>
 <translation id="8412392972487953978">同じパスフレーズを 2 回入力する必要があります。</translation>
@@ -1451,7 +1451,7 @@
 <translation id="9154194610265714752">更新完了</translation>
 <translation id="9157595877708044936">セットアップ中...</translation>
 <translation id="9158625974267017556">C6(封筒)</translation>
-<translation id="9168814207360376865">お支払い方法を保存しているかどうかの確認をサイトに許可する</translation>
+<translation id="9168814207360376865">お支払い方法を保存しているかどうかの確認をサイトに許可します</translation>
 <translation id="9169664750068251925">このサイトでは常にブロック</translation>
 <translation id="9170848237812810038">取消(&amp;U)</translation>
 <translation id="9171296965991013597">アプリを終了しますか?</translation>
diff --git a/components/strings/components_strings_no.xtb b/components/strings/components_strings_no.xtb
index daf8622..fa3c714 100644
--- a/components/strings/components_strings_no.xtb
+++ b/components/strings/components_strings_no.xtb
@@ -972,7 +972,7 @@
 <translation id="6386120369904791316">{COUNT,plural, =1{1 annet forslag}other{# andre forslag}}</translation>
 <translation id="6387754724289022810">For å betale raskere neste gang, lagre kortet ditt og faktureringsadressen i Google-kontoen din og på denne enheten.</translation>
 <translation id="6390662030813198813">Engineering-E</translation>
-<translation id="6401136357288658127">Denne regelen er avviklet. Du bør bruke den nye <ph name="NEW_POLICY" />-regelen i stedet.</translation>
+<translation id="6401136357288658127">Denne regelen er avviklet. Du bør bruke den nye regelen <ph name="NEW_POLICY" /> i stedet.</translation>
 <translation id="6404511346730675251">Rediger bokmerket</translation>
 <translation id="6406765186087300643">C0 (konvolutt)</translation>
 <translation id="6410264514553301377">Skriv inn utløpsdatoen og verifiseringskoden for <ph name="CREDIT_CARD" /></translation>
diff --git a/components/strings/components_strings_ta.xtb b/components/strings/components_strings_ta.xtb
index e8d36c43..1a6a975 100644
--- a/components/strings/components_strings_ta.xtb
+++ b/components/strings/components_strings_ta.xtb
@@ -480,6 +480,7 @@
 <translation id="3592413004129370115">Italian (என்வலப்)</translation>
 <translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
 <translation id="3614103345592970299">அளவு: 2</translation>
+<translation id="361438452008624280">பட்டியல் உள்ளீடு '<ph name="LANGUAGE_ID" />': தெரியாத அல்லது ஆதரிக்கப்படாத மொழி.</translation>
 <translation id="3615877443314183785">சரியான காலாவதித் தேதியை உள்ளிடவும்</translation>
 <translation id="36224234498066874">உலாவல் தரவை அழி...</translation>
 <translation id="362276910939193118">முழு வரலாற்றையும் காண்பி</translation>
@@ -547,6 +548,7 @@
 <translation id="40103911065039147">{URL_count,plural, =1{அருகில் ஒரு இணையப் பக்கம் உள்ளது}other{அருகில் # இணையப் பக்கங்கள் உள்ளன}}</translation>
 <translation id="4030383055268325496">&amp;சேர்த்தலைச் செயல்தவிர்</translation>
 <translation id="4032320456957708163">உங்கள் உலாவியை <ph name="ENROLLMENT_DOMAIN" /> நிர்வகிக்கிறது</translation>
+<translation id="4034375457890803692">நீங்கள் வழக்கமாகப் பார்க்காத இணையதளத்திற்கு இந்த இணைப்பு செல்கிறது. இது உங்களைக் குழப்புவதற்காக இருக்கலாம்.</translation>
 <translation id="4058922952496707368">விசை "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
 <translation id="4067263367174615723">C1 (என்வலப்)</translation>
 <translation id="4067947977115446013">சரியான முகவரியைச் சேர்க்கவும்</translation>
@@ -1045,6 +1047,7 @@
 <translation id="6957887021205513506">சேவையகத்தின் சான்றிதழ் போலியானது போல் தெரிகிறது.</translation>
 <translation id="6964255747740675745">நெட்வொர்க் உள்ளமைவைப் பாகுபடுத்த முடியவில்லை (தவறான JSON).</translation>
 <translation id="6965382102122355670">சரி</translation>
+<translation id="6965456981923010628"><ph name="LEFT_PART" /> • <ph name="RIGHT_PART" /></translation>
 <translation id="6965978654500191972">சாதனம்</translation>
 <translation id="6970216967273061347">மாவட்டம்</translation>
 <translation id="6973656660372572881">நிலையான ப்ராக்ஸி சேவையகங்களும் .pac ஸ்கிரிப்ட் URL ஆகிய இரண்டும் குறிப்பிடப்பட்டுள்ளது.</translation>
@@ -1379,6 +1382,7 @@
 <translation id="8790007591277257123">&amp;நீக்குதலை மீண்டும் செய்</translation>
 <translation id="8792621596287649091"><ph name="ORG_NAME" /> கணக்கிற்கான அணுகலை நீங்கள் இழக்கக்கூடும் அல்லது அடையாளத் திருட்டை எதிர்கொள்ளக்கூடும். இப்போதே உங்கள் கடவுச்சொல்லை மாற்றும்படி Chromium பரிந்துரைக்கிறது.</translation>
 <translation id="8800988563907321413">உங்கள் அருகிலுள்ளவற்றுக்கான பரிந்துரைகள் இங்கே தோன்றும்</translation>
+<translation id="8805819170075074995">பட்டியல் உள்ளீடு "<ph name="LANGUAGE_ID" />": உள்ளீடானது SpellcheckLanguage கொள்கையிலும் சேர்க்கப்பட்டிருப்பதால் புறக்கணிக்கப்பட்டது.</translation>
 <translation id="8820817407110198400">புக்மார்க்குகள்</translation>
 <translation id="883848425547221593">மற்ற புக்மார்க்குகள்</translation>
 <translation id="884264119367021077">ஷிப்பிங் முகவரி</translation>
@@ -1402,6 +1406,7 @@
 <translation id="8968766641738584599">கார்டைச் சேமி</translation>
 <translation id="8971063699422889582">சேவையகச் சான்றிதழ் காலாவதியானது.</translation>
 <translation id="8975012916872825179">இதில் ஃபோன் எண்கள், மின்னஞ்சல் முகவரிகள், ஷிப்பிங் முகவரிகள் போன்ற தகவல்கள் உள்ளடங்கும்</translation>
+<translation id="8975263830901772334">நீங்கள் அச்சிடும் கோப்புகளின் பெயர்கள்</translation>
 <translation id="8978053250194585037">சமீபத்தில் Google பாதுகாப்பான உலாவலானது <ph name="SITE" /> தளத்தில் <ph name="BEGIN_LINK" />ஃபிஷிங்கைக் கண்டறிந்தது<ph name="END_LINK" />. ஃபிஷிங் தளங்கள் பிற இணையதளங்களைப் போல் காண்பித்து, உங்களை ஏமாற்ற முயற்சிக்கக்கூடும்.</translation>
 <translation id="8983003182662520383">Google Payவைப் பயன்படுத்தும் கட்டண முறைகளும் முகவரிகளும்</translation>
 <translation id="8987927404178983737">மாதம்</translation>
diff --git a/components/strings/components_strings_vi.xtb b/components/strings/components_strings_vi.xtb
index 5e471a372..e482c49 100644
--- a/components/strings/components_strings_vi.xtb
+++ b/components/strings/components_strings_vi.xtb
@@ -1065,7 +1065,7 @@
 <translation id="6965978654500191972">Thiết bị</translation>
 <translation id="6970216967273061347">Quận</translation>
 <translation id="6973656660372572881">Cả hai máy chủ proxy cố định và URL tập lệnh .pac đều được chỉ định.</translation>
-<translation id="6973932557599545801">Rất tiếc, tôi không thể trợ giúp được nữa. Bạn vui lòng tự thực hiện hành động này.</translation>
+<translation id="6973932557599545801">Rất tiếc, tôi không thể trợ giúp được nữa. Bạn vui lòng tự thực hiện việc này.</translation>
 <translation id="6979158407327259162">Google Drive</translation>
 <translation id="6979440798594660689">Tắt tiếng (mặc định)</translation>
 <translation id="6984479912851154518">Đang rời khỏi chế độ riêng tư để thanh toán qua một ứng dụng bên ngoài. Bạn có muốn tiếp tục không?</translation>
diff --git a/components/strings/components_strings_zh-TW.xtb b/components/strings/components_strings_zh-TW.xtb
index 91a8f1e..46ca2c0 100644
--- a/components/strings/components_strings_zh-TW.xtb
+++ b/components/strings/components_strings_zh-TW.xtb
@@ -1065,7 +1065,7 @@
 <translation id="6965978654500191972">裝置</translation>
 <translation id="6970216967273061347">District</translation>
 <translation id="6973656660372572881">已指定固定的 Proxy 伺服器和 .pac 指令碼網址。</translation>
-<translation id="6973932557599545801">抱歉,目前無法提供協助,請您自行填入資料。</translation>
+<translation id="6973932557599545801">抱歉,目前無法提供協助,請自行填入資料。</translation>
 <translation id="6979158407327259162">Google 雲端硬碟</translation>
 <translation id="6979440798594660689">靜音 (預設)</translation>
 <translation id="6984479912851154518">即將離開私密模式,改為使用外部應用程式付款,要繼續嗎?</translation>
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index 93a224e..5fdf913c 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -574,6 +574,7 @@
 
   public_deps = [
     "//base",
+    "//components/invalidation/public",
     "//components/sync/protocol",
     "//net",
     "//third_party/leveldatabase",
@@ -583,7 +584,6 @@
     "//base:i18n",
     "//components/data_use_measurement/core",
     "//components/invalidation/impl:feature_list",
-    "//components/invalidation/public",
     "//components/keyed_service/core",
     "//components/metrics",
     "//components/os_crypt",
@@ -812,6 +812,8 @@
     "driver/mock_sync_service.h",
     "driver/model_associator_mock.cc",
     "driver/model_associator_mock.h",
+    "driver/profile_sync_service_bundle.cc",
+    "driver/profile_sync_service_bundle.h",
     "driver/sync_api_component_factory_mock.cc",
     "driver/sync_api_component_factory_mock.h",
     "driver/sync_client_mock.cc",
@@ -839,10 +841,15 @@
   deps = [
     ":sync",
     ":test_support_engine",
+    ":test_support_model",
+    "//components/invalidation/impl:test_support",
+    "//components/pref_registry",
     "//components/signin/core/browser:shared",
     "//components/sync_preferences:test_support",
     "//components/version_info",
+    "//components/version_info:generate_version_info",
     "//google_apis",
+    "//services/identity/public/cpp:test_support",
   ]
 }
 
@@ -880,6 +887,8 @@
     "driver/glue/sync_engine_impl_unittest.cc",
     "driver/model_association_manager_unittest.cc",
     "driver/model_type_controller_unittest.cc",
+    "driver/profile_sync_service_startup_unittest.cc",
+    "driver/profile_sync_service_unittest.cc",
     "driver/shared_change_processor_unittest.cc",
     "driver/startup_controller_unittest.cc",
     "driver/sync_auth_manager_unittest.cc",
@@ -981,6 +990,7 @@
     "//components/sync_preferences:test_support",
     "//components/variations",
     "//components/version_info",
+    "//components/version_info:generate_version_info",
     "//components/version_info:version_string",
     "//google_apis",
     "//google_apis:test_support",
diff --git a/components/sync/DEPS b/components/sync/DEPS
index 74b71ff4..39b70c7 100644
--- a/components/sync/DEPS
+++ b/components/sync/DEPS
@@ -1,15 +1,11 @@
 include_rules = [
-  # Repeat these from the top-level DEPS file so one can just run
+  # Run
   #
-  #   checkdeps.py sync
+  #   buildtools/checkdeps/checkdeps.py components/sync
   #
   # to test.
-  "+base",
-  "+build",
   "+components/version_info",
   "+google_apis",
-  "+testing",
-  "+ui/base",
 
   # Force subdirectories to explicitly define DEPS.
   "-components/sync",
diff --git a/components/sync/driver/DEPS b/components/sync/driver/DEPS
index cd4639a2..e6a74b5 100644
--- a/components/sync/driver/DEPS
+++ b/components/sync/driver/DEPS
@@ -4,6 +4,7 @@
   "+components/keyed_service/core",
   "+components/os_crypt",
   "+components/policy",
+  "+components/pref_registry",
   "+components/prefs",
   "+components/signin/core/browser",
   # Use identity_manager.h instead of the below files;
@@ -18,7 +19,6 @@
   "+components/sync/engine",
   "+components/sync/js",
   "+components/sync/model",
-  # TODO(crbug.com/855010): Remove this dependency when tests get simplified.
   "+components/sync/model_impl",
   "+components/sync/protocol",
   "+components/sync/syncable",
diff --git a/components/browser_sync/profile_sync_test_util.cc b/components/sync/driver/profile_sync_service_bundle.cc
similarity index 79%
rename from components/browser_sync/profile_sync_test_util.cc
rename to components/sync/driver/profile_sync_service_bundle.cc
index ec37273..b6c6f05 100644
--- a/components/browser_sync/profile_sync_test_util.cc
+++ b/components/sync/driver/profile_sync_service_bundle.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/browser_sync/profile_sync_test_util.h"
+#include "components/sync/driver/profile_sync_service_bundle.h"
 
 #include <string>
 #include <utility>
@@ -12,21 +12,20 @@
 #include "components/sync/base/sync_prefs.h"
 #include "components/sync/device_info/local_device_info_provider_impl.h"
 #include "components/sync/engine/passive_model_worker.h"
-#include "components/sync/model/model_type_store_test_util.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
 #include "services/network/test/test_network_connection_tracker.h"
 #include "services/network/test/test_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
-namespace browser_sync {
+namespace syncer {
 
 using testing::Return;
 
 ProfileSyncServiceBundle::ProfileSyncServiceBundle()
     : device_info_sync_service_(
           model_type_store_service_.GetStoreFactory(),
-          std::make_unique<syncer::LocalDeviceInfoProviderImpl>(
+          std::make_unique<LocalDeviceInfoProviderImpl>(
               version_info::Channel::UNKNOWN,
               "someversion",
               /*is_tablet=*/false,
@@ -34,7 +33,7 @@
                 return std::string();
               }))),
       identity_test_env_(&test_url_loader_factory_, &pref_service_) {
-  syncer::SyncPrefs::RegisterProfilePrefs(pref_service_.registry());
+  SyncPrefs::RegisterProfilePrefs(pref_service_.registry());
   identity_test_env_.SetAutomaticIssueOfAccessTokens(true);
   identity_provider_ = std::make_unique<invalidation::ProfileIdentityProvider>(
       identity_manager());
@@ -42,25 +41,23 @@
 
 ProfileSyncServiceBundle::~ProfileSyncServiceBundle() {}
 
-std::unique_ptr<syncer::SyncClientMock>
+std::unique_ptr<SyncClientMock>
 ProfileSyncServiceBundle::CreateSyncClientMock() {
-  auto sync_client =
-      std::make_unique<testing::NiceMock<syncer::SyncClientMock>>();
+  auto sync_client = std::make_unique<testing::NiceMock<SyncClientMock>>();
   ON_CALL(*sync_client, GetPrefService()).WillByDefault(Return(&pref_service_));
   ON_CALL(*sync_client, GetDeviceInfoSyncService())
       .WillByDefault(Return(&device_info_sync_service_));
   ON_CALL(*sync_client, GetSyncApiComponentFactory())
       .WillByDefault(Return(&component_factory_));
   // Used by control types.
-  ON_CALL(*sync_client, CreateModelWorkerForGroup(syncer::GROUP_PASSIVE))
-      .WillByDefault(
-          Return(base::MakeRefCounted<syncer::PassiveModelWorker>()));
+  ON_CALL(*sync_client, CreateModelWorkerForGroup(GROUP_PASSIVE))
+      .WillByDefault(Return(base::MakeRefCounted<PassiveModelWorker>()));
   return std::move(sync_client);
 }
 
 ProfileSyncService::InitParams ProfileSyncServiceBundle::CreateBasicInitParams(
     ProfileSyncService::StartBehavior start_behavior,
-    std::unique_ptr<syncer::SyncClient> sync_client) {
+    std::unique_ptr<SyncClient> sync_client) {
   ProfileSyncService::InitParams init_params;
 
   init_params.start_behavior = start_behavior;
@@ -79,4 +76,4 @@
   return init_params;
 }
 
-}  // namespace browser_sync
+}  // namespace syncer
diff --git a/components/browser_sync/profile_sync_test_util.h b/components/sync/driver/profile_sync_service_bundle.h
similarity index 77%
rename from components/browser_sync/profile_sync_test_util.h
rename to components/sync/driver/profile_sync_service_bundle.h
index 364c262..dd6f50a4 100644
--- a/components/browser_sync/profile_sync_test_util.h
+++ b/components/sync/driver/profile_sync_service_bundle.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_BROWSER_SYNC_PROFILE_SYNC_TEST_UTIL_H_
-#define COMPONENTS_BROWSER_SYNC_PROFILE_SYNC_TEST_UTIL_H_
+#ifndef COMPONENTS_SYNC_DRIVER_PROFILE_SYNC_SERVICE_BUNDLE_H_
+#define COMPONENTS_SYNC_DRIVER_PROFILE_SYNC_SERVICE_BUNDLE_H_
 
 #include <memory>
 
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "components/browser_sync/profile_sync_service.h"
 #include "components/invalidation/impl/fake_invalidation_service.h"
 #include "components/invalidation/impl/profile_identity_provider.h"
 #include "components/sync/device_info/device_info_sync_service_impl.h"
+#include "components/sync/driver/profile_sync_service.h"
 #include "components/sync/driver/sync_api_component_factory_mock.h"
 #include "components/sync/driver/sync_client_mock.h"
 #include "components/sync/model/test_model_type_store_service.h"
@@ -21,7 +21,7 @@
 #include "services/identity/public/cpp/identity_test_environment.h"
 #include "services/network/test/test_url_loader_factory.h"
 
-namespace browser_sync {
+namespace syncer {
 
 // Aggregate this class to get all necessary support for creating a
 // ProfileSyncService in tests. The test still needs to have its own
@@ -33,14 +33,14 @@
   ~ProfileSyncServiceBundle();
 
   // Creates a mock sync client that leverages the dependencies in this bundle.
-  std::unique_ptr<syncer::SyncClientMock> CreateSyncClientMock();
+  std::unique_ptr<SyncClientMock> CreateSyncClientMock();
 
   // Creates an InitParams instance with the specified |start_behavior| and
   // |sync_client|, and fills the rest with dummy values and objects owned by
   // the bundle.
   ProfileSyncService::InitParams CreateBasicInitParams(
       ProfileSyncService::StartBehavior start_behavior,
-      std::unique_ptr<syncer::SyncClient> sync_client);
+      std::unique_ptr<SyncClient> sync_client);
 
   // Accessors
 
@@ -60,7 +60,7 @@
     return identity_test_env_.identity_manager();
   }
 
-  syncer::SyncApiComponentFactoryMock* component_factory() {
+  SyncApiComponentFactoryMock* component_factory() {
     return &component_factory_;
   }
 
@@ -72,16 +72,16 @@
     return &fake_invalidation_service_;
   }
 
-  syncer::DeviceInfoSyncService* device_info_sync_service() {
+  DeviceInfoSyncService* device_info_sync_service() {
     return &device_info_sync_service_;
   }
 
  private:
   sync_preferences::TestingPrefServiceSyncable pref_service_;
-  syncer::TestModelTypeStoreService model_type_store_service_;
-  syncer::DeviceInfoSyncServiceImpl device_info_sync_service_;
+  TestModelTypeStoreService model_type_store_service_;
+  DeviceInfoSyncServiceImpl device_info_sync_service_;
   identity::IdentityTestEnvironment identity_test_env_;
-  testing::NiceMock<syncer::SyncApiComponentFactoryMock> component_factory_;
+  testing::NiceMock<SyncApiComponentFactoryMock> component_factory_;
   std::unique_ptr<invalidation::ProfileIdentityProvider> identity_provider_;
   invalidation::FakeInvalidationService fake_invalidation_service_;
   network::TestURLLoaderFactory test_url_loader_factory_;
@@ -89,6 +89,6 @@
   DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceBundle);
 };
 
-}  // namespace browser_sync
+}  // namespace syncer
 
-#endif  // COMPONENTS_BROWSER_SYNC_PROFILE_SYNC_TEST_UTIL_H_
+#endif  // COMPONENTS_SYNC_DRIVER_PROFILE_SYNC_SERVICE_BUNDLE_H_
diff --git a/components/browser_sync/profile_sync_service_startup_unittest.cc b/components/sync/driver/profile_sync_service_startup_unittest.cc
similarity index 82%
rename from components/browser_sync/profile_sync_service_startup_unittest.cc
rename to components/sync/driver/profile_sync_service_startup_unittest.cc
index bf77ca8..c03af92 100644
--- a/components/browser_sync/profile_sync_service_startup_unittest.cc
+++ b/components/sync/driver/profile_sync_service_startup_unittest.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/browser_sync/profile_sync_service.h"
+#include "components/sync/driver/profile_sync_service.h"
 
 #include "base/bind.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
-#include "components/browser_sync/profile_sync_test_util.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync/base/pref_names.h"
 #include "components/sync/driver/data_type_manager_mock.h"
 #include "components/sync/driver/fake_data_type_controller.h"
+#include "components/sync/driver/profile_sync_service_bundle.h"
 #include "components/sync/driver/sync_api_component_factory_mock.h"
 #include "components/sync/driver/sync_client_mock.h"
 #include "components/sync/driver/sync_driver_switches.h"
@@ -21,10 +21,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using syncer::DataTypeManager;
-using syncer::DataTypeManagerMock;
-using syncer::FakeSyncEngine;
-using syncer::MockSyncEngine;
 using testing::_;
 using testing::ByMove;
 using testing::DoAll;
@@ -33,17 +29,16 @@
 using testing::NiceMock;
 using testing::Return;
 
-namespace browser_sync {
+namespace syncer {
 
 namespace {
 
 const char kEmail[] = "test_user@gmail.com";
 
 void SetError(DataTypeManager::ConfigureResult* result) {
-  syncer::DataTypeStatusTable::TypeErrorMap errors;
-  errors[syncer::BOOKMARKS] =
-      syncer::SyncError(FROM_HERE, syncer::SyncError::UNRECOVERABLE_ERROR,
-                        "Error", syncer::BOOKMARKS);
+  DataTypeStatusTable::TypeErrorMap errors;
+  errors[BOOKMARKS] =
+      SyncError(FROM_HERE, SyncError::UNRECOVERABLE_ERROR, "Error", BOOKMARKS);
   result->data_type_status_table.UpdateFailedDataTypes(errors);
 }
 
@@ -56,7 +51,7 @@
 ACTION_P3(InvokeOnConfigureDone, sync_service, error_callback, result) {
   DataTypeManager::ConfigureResult configure_result =
       static_cast<DataTypeManager::ConfigureResult>(result);
-  if (result.status == syncer::DataTypeManager::ABORTED)
+  if (result.status == DataTypeManager::ABORTED)
     error_callback.Run(&configure_result);
   sync_service->OnConfigureDone(configure_result);
 }
@@ -71,20 +66,17 @@
         ->SetAutomaticIssueOfAccessTokens(true);
   }
 
-  ~ProfileSyncServiceStartupTest() override {
-    sync_service_->Shutdown();
-  }
+  ~ProfileSyncServiceStartupTest() override { sync_service_->Shutdown(); }
 
-  void CreateSyncService(ProfileSyncService::StartBehavior start_behavior,
-                         syncer::ModelTypeSet registered_types =
-                             syncer::ModelTypeSet(syncer::BOOKMARKS)) {
-    syncer::DataTypeController::TypeVector controllers;
-    for (syncer::ModelType type : registered_types) {
-      controllers.push_back(
-          std::make_unique<syncer::FakeDataTypeController>(type));
+  void CreateSyncService(
+      ProfileSyncService::StartBehavior start_behavior,
+      ModelTypeSet registered_types = ModelTypeSet(BOOKMARKS)) {
+    DataTypeController::TypeVector controllers;
+    for (ModelType type : registered_types) {
+      controllers.push_back(std::make_unique<FakeDataTypeController>(type));
     }
 
-    std::unique_ptr<syncer::SyncClientMock> sync_client =
+    std::unique_ptr<SyncClientMock> sync_client =
         profile_sync_service_bundle_.CreateSyncClientMock();
     ON_CALL(*sync_client, CreateDataTypeControllers(_))
         .WillByDefault(Return(ByMove(std::move(controllers))));
@@ -133,7 +125,7 @@
     return sync_engine_raw;
   }
 
-  syncer::SyncPrefs* sync_prefs() { return &sync_prefs_; }
+  SyncPrefs* sync_prefs() { return &sync_prefs_; }
 
   ProfileSyncService* sync_service() { return sync_service_.get(); }
 
@@ -141,7 +133,7 @@
     return profile_sync_service_bundle_.pref_service();
   }
 
-  syncer::SyncApiComponentFactoryMock* component_factory() {
+  SyncApiComponentFactoryMock* component_factory() {
     return profile_sync_service_bundle_.component_factory();
   }
 
@@ -152,7 +144,7 @@
  private:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
   ProfileSyncServiceBundle profile_sync_service_bundle_;
-  syncer::SyncPrefs sync_prefs_;
+  SyncPrefs sync_prefs_;
   std::unique_ptr<ProfileSyncService> sync_service_;
 };
 
@@ -173,10 +165,10 @@
   // Should not actually start, rather just clean things up and wait
   // to be enabled.
   sync_service()->Initialize();
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN |
-                syncer::SyncService::DISABLE_REASON_USER_CHOICE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NOT_SIGNED_IN |
+                SyncService::DISABLE_REASON_USER_CHOICE,
             sync_service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             sync_service()->GetTransportState());
 
   // Preferences should be back to defaults.
@@ -189,9 +181,9 @@
   sync_service()->GetUserSettings()->SetSyncRequested(true);
   auto sync_blocker = sync_service()->GetSetupInProgressHandle();
   EXPECT_FALSE(sync_service()->IsEngineInitialized());
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NOT_SIGNED_IN,
             sync_service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             sync_service()->GetTransportState());
 
   SimulateTestUserSignin();
@@ -199,9 +191,9 @@
   // Now we're signed in, so the engine can start. Engine initialization is
   // immediate in this test, so we bypass the INITIALIZING state.
   EXPECT_TRUE(sync_service()->IsEngineInitialized());
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NONE,
             sync_service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
+  EXPECT_EQ(SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
             sync_service()->GetTransportState());
 
   // Simulate the UI telling sync it has finished setting up. Note that this is
@@ -215,7 +207,7 @@
       .WillByDefault(Return(DataTypeManager::CONFIGURED));
   sync_blocker.reset();
   ASSERT_FALSE(sync_service()->IsSetupInProgress());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             sync_service()->GetTransportState());
   // Sync-the-feature is still not active, but rather pending confirmation.
   EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
@@ -231,10 +223,10 @@
   // This should have fully enabled sync.
   EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
   EXPECT_TRUE(sync_service()->IsSyncFeatureActive());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             sync_service()->GetTransportState());
 
-  EXPECT_CALL(*data_type_manager, Stop(syncer::BROWSER_SHUTDOWN));
+  EXPECT_CALL(*data_type_manager, Stop(BROWSER_SHUTDOWN));
 }
 #endif  // OS_CHROMEOS
 
@@ -255,7 +247,7 @@
 
   // ProfileSyncService should now be active, but of course not have an access
   // token.
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             sync_service()->GetTransportState());
   EXPECT_TRUE(sync_service()->GetAccessTokenForTest().empty());
   // Note that ProfileSyncService is not in an auth error state - no auth was
@@ -282,9 +274,9 @@
   // state. It'll take either a browser restart or a full sign-out+sign-in to
   // get out of this.
   EXPECT_TRUE(sync_service()->HasUnrecoverableError());
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR,
+  EXPECT_EQ(SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR,
             sync_service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             sync_service()->GetTransportState());
 }
 
@@ -309,7 +301,7 @@
       .WillByDefault(Return(DataTypeManager::CONFIGURED));
 
   // Sync should be considered active, even though there is no refresh token.
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             sync_service()->GetTransportState());
   // Since we're in AUTO_START mode, FirstSetupComplete gets set automatically.
   EXPECT_TRUE(sync_service()->GetUserSettings()->IsFirstSetupComplete());
@@ -333,9 +325,9 @@
   // a refresh token.
   UpdateCredentials();
   sync_service()->Initialize();
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             sync_service()->GetTransportState());
-  EXPECT_CALL(*data_type_manager, Stop(syncer::BROWSER_SHUTDOWN));
+  EXPECT_CALL(*data_type_manager, Stop(BROWSER_SHUTDOWN));
 }
 
 TEST_F(ProfileSyncServiceStartupTest, StartNormal) {
@@ -358,10 +350,10 @@
   ON_CALL(*data_type_manager, state())
       .WillByDefault(Return(DataTypeManager::CONFIGURED));
 
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             sync_service()->GetTransportState());
 
-  EXPECT_CALL(*data_type_manager, Stop(syncer::BROWSER_SHUTDOWN));
+  EXPECT_CALL(*data_type_manager, Stop(BROWSER_SHUTDOWN));
 }
 
 TEST_F(ProfileSyncServiceStartupTest, StopSync) {
@@ -376,7 +368,7 @@
 
   sync_service()->Initialize();
 
-  EXPECT_CALL(*data_type_manager, Stop(syncer::STOP_SYNC));
+  EXPECT_CALL(*data_type_manager, Stop(STOP_SYNC));
   // On SetSyncRequested(false), the sync service will immediately start up
   // again in transport mode.
   SetUpFakeSyncEngine();
@@ -420,9 +412,9 @@
 // therefore being left unset.
 TEST_F(ProfileSyncServiceStartupTest, StartRecoverDatatypePrefs) {
   // Clear the datatype preference fields (simulating bug 154940).
-  pref_service()->ClearPref(syncer::prefs::kSyncKeepEverythingSynced);
-  for (syncer::ModelType type : syncer::UserSelectableTypes()) {
-    pref_service()->ClearPref(syncer::SyncPrefs::GetPrefNameForDataType(type));
+  pref_service()->ClearPref(prefs::kSyncKeepEverythingSynced);
+  for (ModelType type : UserSelectableTypes()) {
+    pref_service()->ClearPref(SyncPrefs::GetPrefNameForDataType(type));
   }
 
   sync_prefs()->SetFirstSetupComplete();
@@ -446,8 +438,7 @@
   // Explicitly set Keep Everything Synced to false and have only bookmarks
   // enabled.
   sync_prefs()->SetDataTypesConfiguration(/*keep_everything_synced=*/false,
-                                          syncer::UserTypes(),
-                                          {syncer::BOOKMARKS});
+                                          UserTypes(), {BOOKMARKS});
 
   sync_prefs()->SetFirstSetupComplete();
   CreateSyncService(ProfileSyncService::MANUAL_START);
@@ -478,7 +469,7 @@
   EXPECT_CALL(*component_factory(), CreateDataTypeManager(_, _, _, _, _, _))
       .Times(0);
   sync_service()->Initialize();
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
+  EXPECT_EQ(SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
             sync_service()->GetDisableReasons());
 }
 
@@ -499,9 +490,9 @@
   // this test).
   sync_service()->Initialize();
   EXPECT_TRUE(sync_service()->IsEngineInitialized());
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NONE,
             sync_service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             sync_service()->GetTransportState());
   EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
   EXPECT_TRUE(sync_service()->IsSyncFeatureActive());
@@ -510,13 +501,13 @@
   Mock::VerifyAndClearExpectations(data_type_manager);
   EXPECT_CALL(*data_type_manager, state())
       .WillOnce(Return(DataTypeManager::CONFIGURED));
-  EXPECT_CALL(*data_type_manager, Stop(syncer::DISABLE_SYNC));
+  EXPECT_CALL(*data_type_manager, Stop(DISABLE_SYNC));
 
   sync_prefs()->SetManagedForTest(true);
-  ASSERT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
+  ASSERT_EQ(SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
             sync_service()->GetDisableReasons());
   EXPECT_FALSE(sync_service()->IsEngineInitialized());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             sync_service()->GetTransportState());
   EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
   EXPECT_FALSE(sync_service()->IsSyncFeatureActive());
@@ -534,11 +525,11 @@
 
   sync_prefs()->SetManagedForTest(false);
 
-  ASSERT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
+  ASSERT_EQ(SyncService::DISABLE_REASON_NONE,
             sync_service()->GetDisableReasons());
 
   EXPECT_TRUE(sync_service()->IsEngineInitialized());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             sync_service()->GetTransportState());
   // Sync-the-feature is still considered off because disabling Sync through
   // policy also reset the first-setup-complete flag.
@@ -555,7 +546,7 @@
   SetUpFakeSyncEngine();
   DataTypeManagerMock* data_type_manager = SetUpDataTypeManagerMock();
   DataTypeManager::ConfigureStatus status = DataTypeManager::ABORTED;
-  DataTypeManager::ConfigureResult result(status, syncer::ModelTypeSet());
+  DataTypeManager::ConfigureResult result(status, ModelTypeSet());
   EXPECT_CALL(*data_type_manager, Configure(_, _))
       .WillRepeatedly(
           DoAll(InvokeOnConfigureStart(sync_service()),
@@ -566,7 +557,7 @@
   ON_CALL(*data_type_manager, IsNigoriEnabled()).WillByDefault(Return(true));
   sync_service()->Initialize();
   EXPECT_TRUE(sync_service()->HasUnrecoverableError());
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR,
+  EXPECT_EQ(SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR,
             sync_service()->GetDisableReasons());
 }
 
@@ -583,9 +574,9 @@
 
   auto sync_blocker = sync_service()->GetSetupInProgressHandle();
   sync_blocker.reset();
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR,
+  EXPECT_EQ(SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR,
             sync_service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             sync_service()->GetTransportState());
 }
 
@@ -606,24 +597,23 @@
 
   // Note: Deferred startup is only enabled if SESSIONS is among the preferred
   // data types.
-  CreateSyncService(ProfileSyncService::MANUAL_START,
-                    syncer::ModelTypeSet(syncer::SESSIONS));
+  CreateSyncService(ProfileSyncService::MANUAL_START, ModelTypeSet(SESSIONS));
   sync_service()->Initialize();
 
   // There is no signed-in user, so also nobody has decided that Sync should be
   // started.
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN |
-                syncer::SyncService::DISABLE_REASON_USER_CHOICE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NOT_SIGNED_IN |
+                SyncService::DISABLE_REASON_USER_CHOICE,
             sync_service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             sync_service()->GetTransportState());
 
   // Sign in. Now Sync-the-transport could start, but gets deferred by default.
   // Sync-the-feature still doesn't start until the user says they want it.
   SimulateTestUserSignin();
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_USER_CHOICE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_USER_CHOICE,
             sync_service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::START_DEFERRED,
+  EXPECT_EQ(SyncService::TransportState::START_DEFERRED,
             sync_service()->GetTransportState());
   EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
 
@@ -633,19 +623,19 @@
   EXPECT_CALL(*sync_engine, Initialize(_));
   sync_service()->GetUserSettings()->SetSyncRequested(true);
   auto setup_in_progress_handle = sync_service()->GetSetupInProgressHandle();
-  EXPECT_EQ(syncer::SyncService::TransportState::INITIALIZING,
+  EXPECT_EQ(SyncService::TransportState::INITIALIZING,
             sync_service()->GetTransportState());
 
   // Once the engine calls back and says it's initialized, we're just waiting
   // for the user to finish the initial configuration (choosing data types etc.)
   // before actually syncing data.
-  sync_service()->OnEngineInitialized(
-      syncer::ModelTypeSet(), syncer::WeakHandle<syncer::JsBackend>(),
-      syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(), "test-guid",
-      "test-session-name", "test-birthday", "test-bag-of-chips",
-      /*success=*/true);
+  sync_service()->OnEngineInitialized(ModelTypeSet(), WeakHandle<JsBackend>(),
+                                      WeakHandle<DataTypeDebugInfoListener>(),
+                                      "test-guid", "test-session-name",
+                                      "test-birthday", "test-bag-of-chips",
+                                      /*success=*/true);
   ASSERT_TRUE(sync_service()->IsEngineInitialized());
-  EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
+  EXPECT_EQ(SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
             sync_service()->GetTransportState());
   EXPECT_FALSE(sync_service()->IsSyncFeatureEnabled());
 
@@ -654,7 +644,7 @@
   // isn't enough though, because setup is still considered in progress (we
   // haven't released the setup-in-progress handle).
   sync_service()->GetUserSettings()->SetFirstSetupComplete();
-  EXPECT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
+  EXPECT_EQ(SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
             sync_service()->GetTransportState());
   EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
 
@@ -668,18 +658,18 @@
   setup_in_progress_handle.reset();
   // While DataTypeManager configuration is ongoing, the overall state is still
   // CONFIGURING.
-  EXPECT_EQ(syncer::SyncService::TransportState::CONFIGURING,
+  EXPECT_EQ(SyncService::TransportState::CONFIGURING,
             sync_service()->GetTransportState());
   EXPECT_TRUE(sync_service()->IsSyncFeatureActive());
 
   // Finally, once the DataTypeManager says it's done with configuration, Sync
   // is actually fully up and running.
-  DataTypeManager::ConfigureResult configure_result(
-      DataTypeManager::OK, syncer::ModelTypeSet(syncer::SESSIONS));
+  DataTypeManager::ConfigureResult configure_result(DataTypeManager::OK,
+                                                    ModelTypeSet(SESSIONS));
   ON_CALL(*data_type_manager, state())
       .WillByDefault(Return(DataTypeManager::CONFIGURED));
   sync_service()->OnConfigureDone(configure_result);
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             sync_service()->GetTransportState());
   EXPECT_TRUE(sync_service()->IsSyncFeatureActive());
 }
@@ -700,44 +690,43 @@
 
   // Note: Deferred startup is only enabled if SESSIONS is among the preferred
   // data types.
-  CreateSyncService(ProfileSyncService::MANUAL_START,
-                    syncer::ModelTypeSet(syncer::SESSIONS));
+  CreateSyncService(ProfileSyncService::MANUAL_START, ModelTypeSet(SESSIONS));
   sync_service()->Initialize();
 
   // Nothing is preventing Sync from starting, but it should be deferred so as
   // to now slow down browser startup.
-  EXPECT_EQ(syncer::SyncService::TransportState::START_DEFERRED,
+  EXPECT_EQ(SyncService::TransportState::START_DEFERRED,
             sync_service()->GetTransportState());
 
   // Wait for the deferred startup timer to expire. The Sync service will start
   // and initialize the engine.
   EXPECT_CALL(*sync_engine, Initialize(_));
   FastForwardUntilNoTasksRemain();
-  EXPECT_EQ(syncer::SyncService::TransportState::INITIALIZING,
+  EXPECT_EQ(SyncService::TransportState::INITIALIZING,
             sync_service()->GetTransportState());
 
   // Once the engine calls back and says it's initialized, the DataTypeManager
   // will get configured, since initial setup is already done.
   EXPECT_CALL(*data_type_manager, Configure(_, _));
-  sync_service()->OnEngineInitialized(
-      syncer::ModelTypeSet(), syncer::WeakHandle<syncer::JsBackend>(),
-      syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(), "test-guid",
-      "test-session-name", "test-birthday", "test-bag-of-chips",
-      /*success=*/true);
+  sync_service()->OnEngineInitialized(ModelTypeSet(), WeakHandle<JsBackend>(),
+                                      WeakHandle<DataTypeDebugInfoListener>(),
+                                      "test-guid", "test-session-name",
+                                      "test-birthday", "test-bag-of-chips",
+                                      /*success=*/true);
   ON_CALL(*data_type_manager, state())
       .WillByDefault(Return(DataTypeManager::CONFIGURING));
-  EXPECT_EQ(syncer::SyncService::TransportState::CONFIGURING,
+  EXPECT_EQ(SyncService::TransportState::CONFIGURING,
             sync_service()->GetTransportState());
 
   // Finally, once the DataTypeManager says it's done with configuration, Sync
   // is actually fully up and running.
-  DataTypeManager::ConfigureResult configure_result(
-      DataTypeManager::OK, syncer::ModelTypeSet(syncer::SESSIONS));
+  DataTypeManager::ConfigureResult configure_result(DataTypeManager::OK,
+                                                    ModelTypeSet(SESSIONS));
   ON_CALL(*data_type_manager, state())
       .WillByDefault(Return(DataTypeManager::CONFIGURED));
   sync_service()->OnConfigureDone(configure_result);
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             sync_service()->GetTransportState());
 }
 
-}  // namespace browser_sync
+}  // namespace syncer
diff --git a/components/browser_sync/profile_sync_service_unittest.cc b/components/sync/driver/profile_sync_service_unittest.cc
similarity index 79%
rename from components/browser_sync/profile_sync_service_unittest.cc
rename to components/sync/driver/profile_sync_service_unittest.cc
index 8557938d..f6511b6 100644
--- a/components/browser_sync/profile_sync_service_unittest.cc
+++ b/components/sync/driver/profile_sync_service_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/browser_sync/profile_sync_service.h"
+#include "components/sync/driver/profile_sync_service.h"
 
 #include <memory>
 #include <string>
@@ -16,12 +16,12 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/values.h"
-#include "components/browser_sync/profile_sync_test_util.h"
 #include "components/signin/core/browser/account_info.h"
 #include "components/sync/base/pref_names.h"
 #include "components/sync/device_info/local_device_info_provider.h"
 #include "components/sync/driver/configure_context.h"
 #include "components/sync/driver/fake_data_type_controller.h"
+#include "components/sync/driver/profile_sync_service_bundle.h"
 #include "components/sync/driver/sync_api_component_factory_mock.h"
 #include "components/sync/driver/sync_client_mock.h"
 #include "components/sync/driver/sync_driver_switches.h"
@@ -40,35 +40,32 @@
 using testing::ByMove;
 using testing::Return;
 
-namespace browser_sync {
+namespace syncer {
 
 namespace {
 
-class FakeDataTypeManager : public syncer::DataTypeManager {
+class FakeDataTypeManager : public DataTypeManager {
  public:
-  using ConfigureCalled =
-      base::RepeatingCallback<void(syncer::ConfigureReason)>;
+  using ConfigureCalled = base::RepeatingCallback<void(ConfigureReason)>;
 
   explicit FakeDataTypeManager(const ConfigureCalled& configure_called)
       : configure_called_(configure_called), state_(STOPPED) {}
 
   ~FakeDataTypeManager() override {}
 
-  void Configure(syncer::ModelTypeSet desired_types,
-                 const syncer::ConfigureContext& context) override {
+  void Configure(ModelTypeSet desired_types,
+                 const ConfigureContext& context) override {
     state_ = CONFIGURED;
     DCHECK(!configure_called_.is_null());
     configure_called_.Run(context.reason);
   }
 
-  void ReenableType(syncer::ModelType type) override {}
-  void ReadyForStartChanged(syncer::ModelType type) override {}
+  void ReenableType(ModelType type) override {}
+  void ReadyForStartChanged(ModelType type) override {}
   void ResetDataTypeErrors() override {}
-  void PurgeForMigration(syncer::ModelTypeSet undesired_types) override {}
-  void Stop(syncer::ShutdownReason reason) override {}
-  syncer::ModelTypeSet GetActiveDataTypes() const override {
-    return syncer::ModelTypeSet();
-  }
+  void PurgeForMigration(ModelTypeSet undesired_types) override {}
+  void Stop(ShutdownReason reason) override {}
+  ModelTypeSet GetActiveDataTypes() const override { return ModelTypeSet(); }
   bool IsNigoriEnabled() const override { return true; }
   State state() const override { return state_; }
 
@@ -81,12 +78,12 @@
   return std::make_unique<FakeDataTypeManager>(configure_called);
 }
 
-class TestSyncServiceObserver : public syncer::SyncServiceObserver {
+class TestSyncServiceObserver : public SyncServiceObserver {
  public:
   TestSyncServiceObserver()
       : setup_in_progress_(false), auth_error_(GoogleServiceAuthError()) {}
 
-  void OnStateChanged(syncer::SyncService* sync) override {
+  void OnStateChanged(SyncService* sync) override {
     setup_in_progress_ = sync->IsSetupInProgress();
     auth_error_ = sync->GetAuthError();
   }
@@ -102,39 +99,39 @@
 // A variant of the FakeSyncEngine that won't automatically call back when asked
 // to initialize. Allows us to test things that could happen while backend init
 // is in progress.
-class FakeSyncEngineNoReturn : public syncer::FakeSyncEngine {
+class FakeSyncEngineNoReturn : public FakeSyncEngine {
   void Initialize(InitParams params) override {}
 };
 
 // FakeSyncEngine that stores the SyncCredentials passed into Initialize(), and
 // optionally also whether InvalidateCredentials was called.
-class FakeSyncEngineCollectCredentials : public syncer::FakeSyncEngine {
+class FakeSyncEngineCollectCredentials : public FakeSyncEngine {
  public:
   explicit FakeSyncEngineCollectCredentials(
-      syncer::SyncCredentials* init_credentials,
+      SyncCredentials* init_credentials,
       const base::RepeatingClosure& invalidate_credentials_callback)
       : init_credentials_(init_credentials),
         invalidate_credentials_callback_(invalidate_credentials_callback) {}
 
   void Initialize(InitParams params) override {
     *init_credentials_ = params.credentials;
-    syncer::FakeSyncEngine::Initialize(std::move(params));
+    FakeSyncEngine::Initialize(std::move(params));
   }
 
   void InvalidateCredentials() override {
     if (invalidate_credentials_callback_) {
       invalidate_credentials_callback_.Run();
     }
-    syncer::FakeSyncEngine::InvalidateCredentials();
+    FakeSyncEngine::InvalidateCredentials();
   }
 
  private:
-  syncer::SyncCredentials* init_credentials_;
+  SyncCredentials* init_credentials_;
   base::RepeatingClosure invalidate_credentials_callback_;
 };
 
 ACTION(ReturnNewFakeSyncEngine) {
-  return std::make_unique<syncer::FakeSyncEngine>();
+  return std::make_unique<FakeSyncEngine>();
 }
 
 ACTION(ReturnNewFakeSyncEngineNoReturn) {
@@ -168,11 +165,10 @@
   void CreateService(ProfileSyncService::StartBehavior behavior) {
     DCHECK(!service_);
 
-    syncer::DataTypeController::TypeVector controllers;
-    controllers.push_back(
-        std::make_unique<syncer::FakeDataTypeController>(syncer::BOOKMARKS));
+    DataTypeController::TypeVector controllers;
+    controllers.push_back(std::make_unique<FakeDataTypeController>(BOOKMARKS));
 
-    std::unique_ptr<syncer::SyncClientMock> sync_client =
+    std::unique_ptr<SyncClientMock> sync_client =
         profile_sync_service_bundle_.CreateSyncClientMock();
     ON_CALL(*sync_client, CreateDataTypeControllers(_))
         .WillByDefault(Return(ByMove(std::move(controllers))));
@@ -191,11 +187,10 @@
   void CreateServiceWithLocalSyncBackend() {
     DCHECK(!service_);
 
-    syncer::DataTypeController::TypeVector controllers;
-    controllers.push_back(
-        std::make_unique<syncer::FakeDataTypeController>(syncer::BOOKMARKS));
+    DataTypeController::TypeVector controllers;
+    controllers.push_back(std::make_unique<FakeDataTypeController>(BOOKMARKS));
 
-    std::unique_ptr<syncer::SyncClientMock> sync_client =
+    std::unique_ptr<SyncClientMock> sync_client =
         profile_sync_service_bundle_.CreateSyncClientMock();
     ON_CALL(*sync_client, CreateDataTypeControllers(_))
         .WillByDefault(Return(ByMove(std::move(controllers))));
@@ -204,7 +199,7 @@
         profile_sync_service_bundle_.CreateBasicInitParams(
             ProfileSyncService::AUTO_START, std::move(sync_client));
 
-    prefs()->SetBoolean(syncer::prefs::kEnableLocalSyncBackend, true);
+    prefs()->SetBoolean(prefs::kEnableLocalSyncBackend, true);
     init_params.identity_manager = nullptr;
 
     service_ = std::make_unique<ProfileSyncService>(std::move(init_params));
@@ -224,12 +219,11 @@
 
   void InitializeForNthSync() {
     // Set first sync time before initialize to simulate a complete sync setup.
-    syncer::SyncPrefs sync_prefs(prefs());
+    SyncPrefs sync_prefs(prefs());
     sync_prefs.SetLastSyncedTime(base::Time::Now());
     sync_prefs.SetSyncRequested(true);
     sync_prefs.SetDataTypesConfiguration(/*keep_everything_synced=*/true,
-                                         syncer::UserTypes(),
-                                         syncer::UserSelectableTypes());
+                                         UserTypes(), UserSelectableTypes());
     sync_prefs.SetFirstSetupComplete();
     service_->Initialize();
   }
@@ -238,18 +232,17 @@
 
   void TriggerPassphraseRequired() {
     service_->GetEncryptionObserverForTest()->OnPassphraseRequired(
-        syncer::REASON_DECRYPTION,
-        syncer::KeyDerivationParams::CreateForPbkdf2(),
+        REASON_DECRYPTION, KeyDerivationParams::CreateForPbkdf2(),
         sync_pb::EncryptedData());
   }
 
   void TriggerDataTypeStartRequest() {
-    service_->OnDataTypeRequestsSyncStartup(syncer::BOOKMARKS);
+    service_->OnDataTypeRequestsSyncStartup(BOOKMARKS);
   }
 
-  void OnConfigureCalled(syncer::ConfigureReason configure_reason) {
-    syncer::DataTypeManager::ConfigureResult result;
-    result.status = syncer::DataTypeManager::OK;
+  void OnConfigureCalled(ConfigureReason configure_reason) {
+    DataTypeManager::ConfigureResult result;
+    result.status = DataTypeManager::OK;
     service()->OnConfigureDone(result);
   }
 
@@ -259,11 +252,9 @@
   }
 
   FakeDataTypeManager::ConfigureCalled GetRecordingConfigureCalledCallback(
-      syncer::ConfigureReason* reason_dest) {
+      ConfigureReason* reason_dest) {
     return base::BindLambdaForTesting(
-        [reason_dest](syncer::ConfigureReason reason) {
-          *reason_dest = reason;
-        });
+        [reason_dest](ConfigureReason reason) { *reason_dest = reason; });
   }
 
   invalidation::ProfileIdentityProvider* identity_provider() {
@@ -284,11 +275,11 @@
     return profile_sync_service_bundle_.pref_service();
   }
 
-  syncer::SyncApiComponentFactoryMock* component_factory() {
+  SyncApiComponentFactoryMock* component_factory() {
     return profile_sync_service_bundle_.component_factory();
   }
 
-  const syncer::LocalDeviceInfoProvider* local_device_info_provider() {
+  const LocalDeviceInfoProvider* local_device_info_provider() {
     return profile_sync_service_bundle_.device_info_sync_service()
         ->GetLocalDeviceInfoProvider();
   }
@@ -304,8 +295,8 @@
   CreateService(ProfileSyncService::AUTO_START);
   InitializeForNthSync();
   const std::string& url = service()->sync_service_url().spec();
-  EXPECT_TRUE(url == syncer::internal::kSyncServerUrl ||
-              url == syncer::internal::kSyncDevServerUrl);
+  EXPECT_TRUE(url == internal::kSyncServerUrl ||
+              url == internal::kSyncDevServerUrl);
 }
 
 TEST_F(ProfileSyncServiceTest, SuccessfulInitialization) {
@@ -317,9 +308,8 @@
       .WillOnce(
           ReturnNewFakeDataTypeManager(GetDefaultConfigureCalledCallback()));
   InitializeForNthSync();
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
-            service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NONE, service()->GetDisableReasons());
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 }
 
@@ -331,9 +321,8 @@
       .WillOnce(
           ReturnNewFakeDataTypeManager(GetDefaultConfigureCalledCallback()));
   InitializeForNthSync();
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
-            service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NONE, service()->GetDisableReasons());
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 }
 
@@ -343,20 +332,18 @@
   SignIn();
   CreateService(ProfileSyncService::MANUAL_START);
 
-  syncer::SyncPrefs sync_prefs(prefs());
+  SyncPrefs sync_prefs(prefs());
   base::Time now = base::Time::Now();
   sync_prefs.SetLastSyncedTime(now);
   sync_prefs.SetSyncRequested(true);
   sync_prefs.SetDataTypesConfiguration(/*keep_everything_synced=*/true,
-                                       syncer::UserTypes(),
-                                       syncer::UserSelectableTypes());
+                                       UserTypes(), UserSelectableTypes());
   service()->Initialize();
 
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
-            service()->GetDisableReasons());
+  EXPECT_EQ(SyncService::DISABLE_REASON_NONE, service()->GetDisableReasons());
 
   // Sync should immediately start up in transport mode.
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   EXPECT_FALSE(service()->IsSyncFeatureActive());
   EXPECT_FALSE(service()->IsSyncFeatureEnabled());
@@ -386,43 +373,43 @@
 
 // Verify that disable by enterprise policy works.
 TEST_F(ProfileSyncServiceTest, DisabledByPolicyBeforeInit) {
-  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
+  prefs()->SetManagedPref(prefs::kSyncManaged,
                           std::make_unique<base::Value>(true));
   SignIn();
   CreateService(ProfileSyncService::AUTO_START);
   InitializeForNthSync();
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
+  EXPECT_EQ(SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
             service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             service()->GetTransportState());
 }
 
 // This test exercises sign-in after startup, which isn't supported on ChromeOS.
 #if !defined(OS_CHROMEOS)
 TEST_F(ProfileSyncServiceTest, DisabledByPolicyBeforeInitThenPolicyRemoved) {
-  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
+  prefs()->SetManagedPref(prefs::kSyncManaged,
                           std::make_unique<base::Value>(true));
   CreateService(ProfileSyncService::AUTO_START);
   InitializeForNthSync();
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY |
-                syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
+  EXPECT_EQ(SyncService::DISABLE_REASON_ENTERPRISE_POLICY |
+                SyncService::DISABLE_REASON_NOT_SIGNED_IN,
             service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             service()->GetTransportState());
 
   // Remove the policy. Now only missing sign-in is preventing startup.
-  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
+  prefs()->SetManagedPref(prefs::kSyncManaged,
                           std::make_unique<base::Value>(false));
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NOT_SIGNED_IN,
             service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             service()->GetTransportState());
 
   // Once we mark first setup complete again (it was cleared by the policy) and
   // sign in, sync starts up.
   service()->GetUserSettings()->SetFirstSetupComplete();
   SignIn();
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 }
 #endif  // !defined(OS_CHROMEOS)
@@ -434,17 +421,16 @@
   CreateService(ProfileSyncService::AUTO_START);
   InitializeForNthSync();
 
-  ASSERT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
-            service()->GetDisableReasons());
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::DISABLE_REASON_NONE, service()->GetDisableReasons());
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
-  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
+  prefs()->SetManagedPref(prefs::kSyncManaged,
                           std::make_unique<base::Value>(true));
 
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
+  EXPECT_EQ(SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
             service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             service()->GetTransportState());
 }
 
@@ -457,7 +443,7 @@
 
   SignIn();
   InitializeForNthSync();
-  ASSERT_EQ(syncer::SyncService::TransportState::INITIALIZING,
+  ASSERT_EQ(SyncService::TransportState::INITIALIZING,
             service()->GetTransportState());
 
   ShutdownAndDeleteService();
@@ -472,7 +458,7 @@
   SignIn();
   InitializeForNthSync();
 
-  ASSERT_EQ(syncer::SyncService::TransportState::INITIALIZING,
+  ASSERT_EQ(SyncService::TransportState::INITIALIZING,
             service()->GetTransportState());
 
   // Request stop. This should immediately restart the service in standalone
@@ -480,18 +466,17 @@
   EXPECT_CALL(*component_factory(), CreateSyncEngine(_, _, _))
       .WillOnce(ReturnNewFakeSyncEngine());
   service()->GetUserSettings()->SetSyncRequested(false);
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_USER_CHOICE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_USER_CHOICE,
             service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   EXPECT_FALSE(service()->IsSyncFeatureActive());
   EXPECT_FALSE(service()->IsSyncFeatureEnabled());
 
   // Request start. Now Sync-the-feature should start again.
   service()->GetUserSettings()->SetSyncRequested(true);
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
-            service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NONE, service()->GetDisableReasons());
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   EXPECT_TRUE(service()->IsSyncFeatureActive());
   EXPECT_TRUE(service()->IsSyncFeatureEnabled());
@@ -503,10 +488,9 @@
   SignIn();
   InitializeForNthSync();
 
-  ASSERT_FALSE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart));
-  ASSERT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
-            service()->GetDisableReasons());
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_FALSE(prefs()->GetBoolean(prefs::kSyncSuppressStart));
+  ASSERT_EQ(SyncService::DISABLE_REASON_NONE, service()->GetDisableReasons());
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   ASSERT_TRUE(service()->IsSyncFeatureActive());
   ASSERT_TRUE(service()->IsSyncFeatureEnabled());
@@ -514,19 +498,18 @@
   testing::Mock::VerifyAndClearExpectations(component_factory());
 
   service()->GetUserSettings()->SetSyncRequested(false);
-  EXPECT_TRUE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart));
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_USER_CHOICE,
+  EXPECT_TRUE(prefs()->GetBoolean(prefs::kSyncSuppressStart));
+  EXPECT_EQ(SyncService::DISABLE_REASON_USER_CHOICE,
             service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   EXPECT_FALSE(service()->IsSyncFeatureActive());
   EXPECT_FALSE(service()->IsSyncFeatureEnabled());
 
   service()->GetUserSettings()->SetSyncRequested(true);
-  EXPECT_FALSE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart));
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
-            service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_FALSE(prefs()->GetBoolean(prefs::kSyncSuppressStart));
+  EXPECT_EQ(SyncService::DISABLE_REASON_NONE, service()->GetDisableReasons());
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   EXPECT_TRUE(service()->IsSyncFeatureActive());
   EXPECT_TRUE(service()->IsSyncFeatureEnabled());
@@ -540,10 +523,9 @@
   SignIn();
   InitializeForNthSync();
 
-  EXPECT_FALSE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart));
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
-            service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_FALSE(prefs()->GetBoolean(prefs::kSyncSuppressStart));
+  EXPECT_EQ(SyncService::DISABLE_REASON_NONE, service()->GetDisableReasons());
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   EXPECT_EQ(identity_manager()->GetPrimaryAccountId(),
             identity_provider()->GetActiveAccountId());
@@ -558,9 +540,9 @@
       signin_metrics::SignoutDelete::IGNORE_METRIC);
   // Wait for PSS to be notified that the primary account has gone away.
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NOT_SIGNED_IN,
             service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             service()->GetTransportState());
   EXPECT_EQ("", identity_provider()->GetActiveAccountId());
 
@@ -577,20 +559,20 @@
   InitializeForNthSync();
 
   // Initial status.
-  syncer::SyncTokenStatus token_status = service()->GetSyncTokenStatus();
-  ASSERT_EQ(syncer::CONNECTION_NOT_ATTEMPTED, token_status.connection_status);
+  SyncTokenStatus token_status = service()->GetSyncTokenStatus();
+  ASSERT_EQ(CONNECTION_NOT_ATTEMPTED, token_status.connection_status);
   ASSERT_TRUE(token_status.connection_status_update_time.is_null());
   ASSERT_TRUE(token_status.token_request_time.is_null());
   ASSERT_TRUE(token_status.token_receive_time.is_null());
 
   // Simulate an auth error.
-  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);
+  service()->OnConnectionStatusChange(CONNECTION_AUTH_ERROR);
 
   // The token request will take the form of a posted task.  Run it.
   base::RunLoop().RunUntilIdle();
 
   token_status = service()->GetSyncTokenStatus();
-  EXPECT_EQ(syncer::CONNECTION_AUTH_ERROR, token_status.connection_status);
+  EXPECT_EQ(CONNECTION_AUTH_ERROR, token_status.connection_status);
   EXPECT_FALSE(token_status.connection_status_update_time.is_null());
   EXPECT_FALSE(token_status.token_request_time.is_null());
   EXPECT_FALSE(token_status.token_receive_time.is_null());
@@ -599,13 +581,13 @@
   EXPECT_TRUE(token_status.next_token_request_time.is_null());
 
   // Simulate successful connection.
-  service()->OnConnectionStatusChange(syncer::CONNECTION_OK);
+  service()->OnConnectionStatusChange(CONNECTION_OK);
   token_status = service()->GetSyncTokenStatus();
-  EXPECT_EQ(syncer::CONNECTION_OK, token_status.connection_status);
+  EXPECT_EQ(CONNECTION_OK, token_status.connection_status);
 }
 
 TEST_F(ProfileSyncServiceTest, RevokeAccessTokenFromTokenService) {
-  syncer::SyncCredentials init_credentials;
+  SyncCredentials init_credentials;
 
   CreateService(ProfileSyncService::AUTO_START);
   SignIn();
@@ -614,7 +596,7 @@
           Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
               &init_credentials, base::RepeatingClosure()))));
   InitializeForNthSync();
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
   const std::string primary_account_id =
@@ -629,7 +611,7 @@
   // (because it has no access token), and eventually call
   // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
   // doesn't do any of this, call that explicitly here.
-  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);
+  service()->OnConnectionStatusChange(CONNECTION_AUTH_ERROR);
 
   base::RunLoop().RunUntilIdle();
   ASSERT_FALSE(service()->GetAccessTokenForTest().empty());
@@ -650,7 +632,7 @@
   base::test::ScopedFeatureList feature;
   feature.InitAndEnableFeature(switches::kStopSyncInPausedState);
 
-  syncer::SyncCredentials init_credentials;
+  SyncCredentials init_credentials;
 
   CreateService(ProfileSyncService::AUTO_START);
   SignIn();
@@ -659,7 +641,7 @@
           Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
               &init_credentials, base::RepeatingClosure()))));
   InitializeForNthSync();
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
   TestSyncServiceObserver observer;
@@ -677,7 +659,7 @@
   // (because it has no access token), and eventually call
   // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
   // doesn't do any of this, call that explicitly here.
-  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);
+  service()->OnConnectionStatusChange(CONNECTION_AUTH_ERROR);
 
   base::RunLoop().RunUntilIdle();
   ASSERT_FALSE(service()->GetAccessTokenForTest().empty());
@@ -700,10 +682,9 @@
   // The observer should have been notified of the auth error state.
   EXPECT_EQ(rejected_by_client, observer.auth_error());
   // The Sync engine should have been shut down.
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             service()->GetTransportState());
-  EXPECT_TRUE(
-      service()->HasDisableReason(syncer::SyncService::DISABLE_REASON_PAUSED));
+  EXPECT_TRUE(service()->HasDisableReason(SyncService::DISABLE_REASON_PAUSED));
 
   service()->RemoveObserver(&observer);
 }
@@ -712,7 +693,7 @@
   base::test::ScopedFeatureList feature;
   feature.InitAndDisableFeature(switches::kStopSyncInPausedState);
 
-  syncer::SyncCredentials init_credentials;
+  SyncCredentials init_credentials;
 
   bool invalidate_credentials_called = false;
   base::RepeatingClosure invalidate_credentials_callback =
@@ -726,7 +707,7 @@
           Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
               &init_credentials, invalidate_credentials_callback))));
   InitializeForNthSync();
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
   TestSyncServiceObserver observer;
@@ -744,7 +725,7 @@
   // (because it has no access token), and eventually call
   // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
   // doesn't do any of this, call that explicitly here.
-  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);
+  service()->OnConnectionStatusChange(CONNECTION_AUTH_ERROR);
 
   base::RunLoop().RunUntilIdle();
   ASSERT_FALSE(service()->GetAccessTokenForTest().empty());
@@ -768,7 +749,7 @@
   // The observer should have been notified of the auth error state.
   EXPECT_EQ(rejected_by_client, observer.auth_error());
   // The Sync engine should still be running.
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
   service()->RemoveObserver(&observer);
@@ -777,7 +758,7 @@
 // CrOS does not support signout.
 #if !defined(OS_CHROMEOS)
 TEST_F(ProfileSyncServiceTest, SignOutRevokeAccessToken) {
-  syncer::SyncCredentials init_credentials;
+  SyncCredentials init_credentials;
 
   CreateService(ProfileSyncService::AUTO_START);
   SignIn();
@@ -786,7 +767,7 @@
           Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
               &init_credentials, base::RepeatingClosure()))));
   InitializeForNthSync();
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
   const std::string primary_account_id =
@@ -801,7 +782,7 @@
   // (because it has no access token), and eventually call
   // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
   // doesn't do any of this, call that explicitly here.
-  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);
+  service()->OnConnectionStatusChange(CONNECTION_AUTH_ERROR);
 
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(service()->GetAccessTokenForTest().empty());
@@ -824,7 +805,7 @@
   SignIn();
   CreateService(ProfileSyncService::AUTO_START);
   InitializeForNthSync();
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   base::Time last_synced_time = service()->GetLastSyncedTime();
   ASSERT_LT(base::Time::Now() - last_synced_time,
@@ -836,7 +817,7 @@
 
   // Even though Sync-the-feature is disabled, Sync-the-transport should still
   // be running, and should have updated the last synced time.
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   EXPECT_FALSE(service()->IsSyncFeatureEnabled());
 
@@ -848,7 +829,7 @@
   SignIn();
   CreateService(ProfileSyncService::AUTO_START);
   InitializeForNthSync();
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   base::Time last_synced_time = service()->GetLastSyncedTime();
   ASSERT_LT(base::Time::Now() - last_synced_time,
@@ -872,7 +853,7 @@
   // automatic replies to access token requests.
   identity_test_env()->SetAutomaticIssueOfAccessTokens(false);
 
-  syncer::SyncCredentials init_credentials;
+  SyncCredentials init_credentials;
 
   CreateService(ProfileSyncService::AUTO_START);
   SignIn();
@@ -881,7 +862,7 @@
           Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
               &init_credentials, base::RepeatingClosure()))));
   InitializeForNthSync();
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
   const std::string primary_account_id =
@@ -899,7 +880,7 @@
   // (because it has no access token), and eventually call
   // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
   // doesn't do any of this, call that explicitly here.
-  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);
+  service()->OnConnectionStatusChange(CONNECTION_AUTH_ERROR);
 
   // Wait for ProfileSyncService to send an access token request.
   base::RunLoop().RunUntilIdle();
@@ -922,7 +903,7 @@
   EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
             observer.auth_error().state());
   // The overall state should remain ACTIVE.
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
   service()->RemoveObserver(&observer);
@@ -935,7 +916,7 @@
   // automatic replies to access token requests.
   identity_test_env()->SetAutomaticIssueOfAccessTokens(false);
 
-  syncer::SyncCredentials init_credentials;
+  SyncCredentials init_credentials;
 
   CreateService(ProfileSyncService::AUTO_START);
   SignIn();
@@ -944,7 +925,7 @@
           Return(ByMove(std::make_unique<FakeSyncEngineCollectCredentials>(
               &init_credentials, base::RepeatingClosure()))));
   InitializeForNthSync();
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
   const std::string primary_account_id =
@@ -962,7 +943,7 @@
   // (because it has no access token), and eventually call
   // OnConnectionStatusChange(CONNECTION_AUTH_ERROR). Since our fake SyncEngine
   // doesn't do any of this, call that explicitly here.
-  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);
+  service()->OnConnectionStatusChange(CONNECTION_AUTH_ERROR);
 
   // Wait for ProfileSyncService to send an access token request.
   base::RunLoop().RunUntilIdle();
@@ -984,7 +965,7 @@
   ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
             service()->GetAuthError().state());
   // The overall state should remain ACTIVE.
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
   // Now emulate Chrome receiving a new, valid LST.
@@ -997,7 +978,7 @@
   // Check that sync auth error state cleared.
   EXPECT_EQ(GoogleServiceAuthError::NONE, service()->GetAuthError().state());
   EXPECT_EQ(GoogleServiceAuthError::NONE, observer.auth_error().state());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
   service()->RemoveObserver(&observer);
@@ -1020,16 +1001,15 @@
   SignIn();
   InitializeForNthSync();
 
-  ASSERT_FALSE(prefs()->GetBoolean(syncer::prefs::kSyncSuppressStart));
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_FALSE(prefs()->GetBoolean(prefs::kSyncSuppressStart));
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
   testing::Mock::VerifyAndClearExpectations(component_factory());
 
-  syncer::SyncPrefs sync_prefs(prefs());
+  SyncPrefs sync_prefs(prefs());
 
-  ASSERT_EQ(prefs()->GetInteger(syncer::prefs::kSyncMemoryPressureWarningCount),
-            0);
+  ASSERT_EQ(prefs()->GetInteger(prefs::kSyncMemoryPressureWarningCount), 0);
   ASSERT_FALSE(sync_prefs.DidSyncShutdownCleanly());
 
   // Simulate memory pressure notification.
@@ -1038,8 +1018,7 @@
   base::RunLoop().RunUntilIdle();
 
   // Verify memory pressure recorded.
-  EXPECT_EQ(prefs()->GetInteger(syncer::prefs::kSyncMemoryPressureWarningCount),
-            1);
+  EXPECT_EQ(prefs()->GetInteger(prefs::kSyncMemoryPressureWarningCount), 1);
   EXPECT_FALSE(sync_prefs.DidSyncShutdownCleanly());
 
   // Simulate memory pressure notification.
@@ -1049,8 +1028,7 @@
   ShutdownAndDeleteService();
 
   // Verify memory pressure and shutdown recorded.
-  EXPECT_EQ(prefs()->GetInteger(syncer::prefs::kSyncMemoryPressureWarningCount),
-            2);
+  EXPECT_EQ(prefs()->GetInteger(prefs::kSyncMemoryPressureWarningCount), 2);
   EXPECT_TRUE(sync_prefs.DidSyncShutdownCleanly());
 }
 
@@ -1061,7 +1039,7 @@
   CreateService(ProfileSyncService::AUTO_START);
   InitializeForNthSync();
 
-  syncer::SyncPrefs sync_prefs(prefs());
+  SyncPrefs sync_prefs(prefs());
   ASSERT_EQ(PRODUCT_VERSION, sync_prefs.GetLastRunVersion());
 
   sync_prefs.SetPassphrasePrompted(true);
@@ -1101,8 +1079,8 @@
 
   InitializeForNthSync();
 
-  syncer::SyncProtocolError client_cmd;
-  client_cmd.action = syncer::RESET_LOCAL_SYNC_DATA;
+  SyncProtocolError client_cmd;
+  client_cmd.action = RESET_LOCAL_SYNC_DATA;
   service()->OnActionableError(client_cmd);
 }
 
@@ -1113,31 +1091,31 @@
   CreateService(ProfileSyncService::AUTO_START);
   InitializeForNthSync();
 
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   ASSERT_LT(base::Time::Now() - service()->GetLastSyncedTime(),
             base::TimeDelta::FromMinutes(1));
   ASSERT_TRUE(local_device_info_provider()->GetLocalDeviceInfo());
 
-  syncer::SyncProtocolError client_cmd;
-  client_cmd.action = syncer::DISABLE_SYNC_ON_CLIENT;
+  SyncProtocolError client_cmd;
+  client_cmd.action = DISABLE_SYNC_ON_CLIENT;
   service()->OnActionableError(client_cmd);
 
 #if defined(OS_CHROMEOS)
   // ChromeOS does not support signout.
   EXPECT_TRUE(identity_manager()->HasPrimaryAccount());
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_USER_CHOICE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_USER_CHOICE,
             service()->GetDisableReasons());
   // Since ChromeOS doesn't support signout and so the account is still there
   // and available, Sync will restart in standalone transport mode.
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 #else
   EXPECT_FALSE(identity_manager()->HasPrimaryAccount());
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN |
-                syncer::SyncService::DISABLE_REASON_USER_CHOICE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NOT_SIGNED_IN |
+                SyncService::DISABLE_REASON_USER_CHOICE,
             service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             service()->GetTransportState());
   EXPECT_TRUE(service()->GetLastSyncedTime().is_null());
   EXPECT_FALSE(local_device_info_provider()->GetLocalDeviceInfo());
@@ -1149,41 +1127,39 @@
 
 // Verify a that local sync mode resumes after the policy is lifted.
 TEST_F(ProfileSyncServiceTest, LocalBackendDisabledByPolicy) {
-  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
+  prefs()->SetManagedPref(prefs::kSyncManaged,
                           std::make_unique<base::Value>(false));
   CreateServiceWithLocalSyncBackend();
   InitializeForNthSync();
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
-            service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NONE, service()->GetDisableReasons());
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 
-  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
+  prefs()->SetManagedPref(prefs::kSyncManaged,
                           std::make_unique<base::Value>(true));
 
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
+  EXPECT_EQ(SyncService::DISABLE_REASON_ENTERPRISE_POLICY,
             service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::DISABLED,
+  EXPECT_EQ(SyncService::TransportState::DISABLED,
             service()->GetTransportState());
 
   // Note: If standalone transport is enabled, then setting kSyncManaged to
   // false will immediately start up the engine. Otherwise, the RequestStart
   // call below will trigger it.
-  prefs()->SetManagedPref(syncer::prefs::kSyncManaged,
+  prefs()->SetManagedPref(prefs::kSyncManaged,
                           std::make_unique<base::Value>(false));
 
   service()->GetUserSettings()->SetSyncRequested(true);
-  EXPECT_EQ(syncer::SyncService::DISABLE_REASON_NONE,
-            service()->GetDisableReasons());
-  EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  EXPECT_EQ(SyncService::DISABLE_REASON_NONE, service()->GetDisableReasons());
+  EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
 }
 
 // Test ConfigureDataTypeManagerReason on First and Nth start.
 TEST_F(ProfileSyncServiceTest, ConfigureDataTypeManagerReason) {
-  const syncer::DataTypeManager::ConfigureResult configure_result(
-      syncer::DataTypeManager::OK, syncer::ModelTypeSet());
-  syncer::ConfigureReason configure_reason = syncer::CONFIGURE_REASON_UNKNOWN;
+  const DataTypeManager::ConfigureResult configure_result(DataTypeManager::OK,
+                                                          ModelTypeSet());
+  ConfigureReason configure_reason = CONFIGURE_REASON_UNKNOWN;
 
   SignIn();
 
@@ -1193,17 +1169,17 @@
       .WillOnce(ReturnNewFakeDataTypeManager(
           GetRecordingConfigureCalledCallback(&configure_reason)));
   InitializeForFirstSync();
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(component_factory()));
-  EXPECT_EQ(syncer::CONFIGURE_REASON_NEW_CLIENT, configure_reason);
+  EXPECT_EQ(CONFIGURE_REASON_NEW_CLIENT, configure_reason);
   service()->OnConfigureDone(configure_result);
 
   // Reconfiguration.
   // Trigger a reconfig by grabbing a SyncSetupInProgressHandle and immediately
   // releasing it again (via the temporary unique_ptr going away).
   service()->GetSetupInProgressHandle();
-  EXPECT_EQ(syncer::CONFIGURE_REASON_RECONFIGURATION, configure_reason);
+  EXPECT_EQ(CONFIGURE_REASON_RECONFIGURATION, configure_reason);
   service()->OnConfigureDone(configure_result);
   ShutdownAndDeleteService();
 
@@ -1213,20 +1189,20 @@
       .WillOnce(ReturnNewFakeDataTypeManager(
           GetRecordingConfigureCalledCallback(&configure_reason)));
   InitializeForNthSync();
-  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+  ASSERT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
   ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(component_factory()));
-  EXPECT_EQ(syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE, configure_reason);
+  EXPECT_EQ(CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE, configure_reason);
   service()->OnConfigureDone(configure_result);
 
   // Reconfiguration.
   // Trigger a reconfig by grabbing a SyncSetupInProgressHandle and immediately
   // releasing it again (via the temporary unique_ptr going away).
   service()->GetSetupInProgressHandle();
-  EXPECT_EQ(syncer::CONFIGURE_REASON_RECONFIGURATION, configure_reason);
+  EXPECT_EQ(CONFIGURE_REASON_RECONFIGURATION, configure_reason);
   service()->OnConfigureDone(configure_result);
   ShutdownAndDeleteService();
 }
 
 }  // namespace
-}  // namespace browser_sync
+}  // namespace syncer
diff --git a/components/sync/engine/sync_engine_switches.cc b/components/sync/engine/sync_engine_switches.cc
index e05efd0..c0d6921 100644
--- a/components/sync/engine/sync_engine_switches.cc
+++ b/components/sync/engine/sync_engine_switches.cc
@@ -23,7 +23,7 @@
 // via scrypt when we receive a remote Nigori node that specifies it as the key
 // derivation method.
 const base::Feature kSyncUseScryptForNewCustomPassphrases{
-    "SyncUseScryptForNewCustomPassphrases", base::FEATURE_ENABLED_BY_DEFAULT};
+    "SyncUseScryptForNewCustomPassphrases", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enable USS implementation of Nigori datatype.
 const base::Feature kSyncUSSNigori{"SyncUSSNigori",
diff --git a/components/sync/engine_impl/sync_encryption_handler_impl_unittest.cc b/components/sync/engine_impl/sync_encryption_handler_impl_unittest.cc
index baa6fdd..a3bfcd66 100644
--- a/components/sync/engine_impl/sync_encryption_handler_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_encryption_handler_impl_unittest.cc
@@ -1752,9 +1752,9 @@
   VerifyPassphraseType(PassphraseType::CUSTOM_PASSPHRASE);
   EXPECT_TRUE(encryption_handler()->IsEncryptEverythingEnabled());
   EXPECT_FALSE(encryption_handler()->custom_passphrase_time().is_null());
-  VerifyMigratedNigoriWithTimestamp(
-      migration_time, PassphraseType::CUSTOM_PASSPHRASE, kNewKey,
-      {KeyDerivationParams::CreateForScrypt(kScryptSalt)});
+  VerifyMigratedNigoriWithTimestamp(migration_time,
+                                    PassphraseType::CUSTOM_PASSPHRASE, kNewKey,
+                                    {KeyDerivationParams::CreateForPbkdf2()});
 
   // Check that the cryptographer can decrypt the old key.
   sync_pb::EncryptedData old_encrypted;
@@ -1770,9 +1770,8 @@
   keystore_cryptographer.EncryptString("string", &keystore_encrypted);
   EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted));
 
-  // Check that the cryptographer is encrypting with the new key.
-  KeyParams new_key = {KeyDerivationParams::CreateForScrypt(kScryptSalt),
-                       kNewKey};
+  // Check the the cryptographer is encrypting with the new key.
+  KeyParams new_key = {KeyDerivationParams::CreateForPbkdf2(), kNewKey};
   Cryptographer new_cryptographer(GetCryptographer()->encryptor());
   new_cryptographer.AddKey(new_key);
   sync_pb::EncryptedData new_encrypted;
@@ -1784,7 +1783,7 @@
   VerifyRestoreAfterExplicitPaspshrase(
       migration_time, kNewKey, captured_bootstrap_token, captured_nigori_state,
       PassphraseType::CUSTOM_PASSPHRASE,
-      {KeyDerivationParams::CreateForScrypt(kScryptSalt)});
+      {KeyDerivationParams::CreateForPbkdf2()});
 }
 
 // Test that if a client without a keystore key (e.g. one without keystore
@@ -1865,9 +1864,9 @@
   VerifyPassphraseType(PassphraseType::CUSTOM_PASSPHRASE);
   EXPECT_TRUE(encryption_handler()->IsEncryptEverythingEnabled());
   EXPECT_FALSE(encryption_handler()->custom_passphrase_time().is_null());
-  VerifyMigratedNigoriWithTimestamp(
-      migration_time, PassphraseType::CUSTOM_PASSPHRASE, kNewKey,
-      {KeyDerivationParams::CreateForScrypt(kScryptSalt)});
+  VerifyMigratedNigoriWithTimestamp(migration_time,
+                                    PassphraseType::CUSTOM_PASSPHRASE, kNewKey,
+                                    {KeyDerivationParams::CreateForPbkdf2()});
 
   // Check that the cryptographer can decrypt the old key.
   sync_pb::EncryptedData old_encrypted;
@@ -1882,9 +1881,8 @@
   keystore_cryptographer.EncryptString("string", &keystore_encrypted);
   EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted));
 
-  // Check that the cryptographer is encrypting with the new key.
-  KeyParams new_key = {KeyDerivationParams::CreateForScrypt(kScryptSalt),
-                       kNewKey};
+  // Check the the cryptographer is encrypting with the new key.
+  KeyParams new_key = {KeyDerivationParams::CreateForPbkdf2(), kNewKey};
   Cryptographer new_cryptographer(GetCryptographer()->encryptor());
   new_cryptographer.AddKey(new_key);
   sync_pb::EncryptedData new_encrypted;
@@ -1896,7 +1894,7 @@
   VerifyRestoreAfterExplicitPaspshrase(
       migration_time, kNewKey, captured_bootstrap_token, captured_nigori_state,
       PassphraseType::CUSTOM_PASSPHRASE,
-      {KeyDerivationParams::CreateForScrypt(kScryptSalt)});
+      {KeyDerivationParams::CreateForPbkdf2()});
 }
 
 // Test that if a client without a keystore key (e.g. one without keystore
diff --git a/components/sync/test/fake_server/fake_server_http_post_provider.cc b/components/sync/test/fake_server/fake_server_http_post_provider.cc
index 7b1ea99f..2b2173b 100644
--- a/components/sync/test/fake_server/fake_server_http_post_provider.cc
+++ b/components/sync/test/fake_server/fake_server_http_post_provider.cc
@@ -15,7 +15,7 @@
 namespace fake_server {
 
 // static
-bool FakeServerHttpPostProvider::network_enabled_ = true;
+std::atomic_bool FakeServerHttpPostProvider::network_enabled_(true);
 
 FakeServerHttpPostProviderFactory::FakeServerHttpPostProviderFactory(
     const base::WeakPtr<FakeServer>& fake_server,
@@ -150,18 +150,15 @@
   synchronous_post_completion_.Signal();
 }
 
+// static
 void FakeServerHttpPostProvider::DisableNetwork() {
-  // TODO(crbug.com/947691,crbug.com/947692): This causes flakiness on TSan
-  // because this variable is set on the main thread (a.k.a.
-  // |fake_server_task_runner_|), but read on the Sync thread (corresponding to
-  // |sequence_checker_|).
+  // Note: This may be called on any thread.
   network_enabled_ = false;
 }
 
+// static
 void FakeServerHttpPostProvider::EnableNetwork() {
-  // TODO(crbug.com/947691,crbug.com/947692): This causes flakiness on TSan
-  // because this variable is set on the main thread, but read on the Sync
-  // thread.
+  // Note: This may be called on any thread.
   network_enabled_ = true;
 }
 
diff --git a/components/sync/test/fake_server/fake_server_http_post_provider.h b/components/sync/test/fake_server/fake_server_http_post_provider.h
index 74ca30b11..9514fcb 100644
--- a/components/sync/test/fake_server/fake_server_http_post_provider.h
+++ b/components/sync/test/fake_server/fake_server_http_post_provider.h
@@ -59,7 +59,7 @@
   void HandleCommandOnFakeServerThread(int* http_status_code,
                                        std::string* response);
 
-  static bool network_enabled_;
+  static std::atomic_bool network_enabled_;
 
   // |fake_server_| should only be dereferenced on the same thread as
   // |fake_server_task_runner_| runs on.
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/README.md b/components/test/data/autofill/automated_integration/action_recorder_extension/README.md
deleted file mode 100644
index 26dc3f9..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# Action Recorder Extension
-
-> An extension that generates Python scripts which automate integration testing
-> through Chrome. It was primarily designed for testing Autofill but is easily
-> portable to other uses.
-
-## Usage
-
-1.  Install the extension into Chrome as an unpacked extension on
-    chrome://extensions (don't forget to turn on "Developer mode" on this page).
-2.  Navigate to the desired start page or use the extension's dropdown menu
-    (next to the omnibox) to go to the next "top 100" site.
-3.  Use the dropdown menu or right-click context menu to start action recording.
-4.  Proceed to click on page elements to navigate through the desired sequence
-    of pages.
-5.  To validate the input field types simply right-click on the inputs and
-    select the appropriate 'Input Field Type'. Before performing any other
-    actions, right click on the page and select 'Validate Field Types'.
-6.  Select 'Stop & Copy', at which point the test code will be in your
-    clipboard.
-7.  Paste the generated code into the autofill_top_100.py file
-    (components/test/data/password_manager/form_classification_tests).
-8.  Clean up as necessary.
-
-You might also visit arbitrary sites. Just go to a site and start recording
-there.
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/background/background.js b/components/test/data/autofill/automated_integration/action_recorder_extension/background/background.js
deleted file mode 100644
index 1b5b899..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/background/background.js
+++ /dev/null
@@ -1,854 +0,0 @@
-// Copyright 2018 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.
-
-'use strict';
-
-(function() {
-
-function displayUserErrorMessage(message) {
-  chrome.notifications.create(
-      'no_current_tab', {
-        type: 'basic',
-        title: 'Error!',
-        message: message,
-        iconUrl: '../icons/ic_error_outline_black_2x_web_24dp.png'
-      },
-      null);
-}
-
-// IndexedDB implementation of the recipe object.
-// We use IndexedDB to implement the recipe object because:
-//    * IndexedDB is persistent.
-//    * IndexedDB access are atomic and synchronized.
-//
-// The Action Recorder Extension uses non-persistent background scripts.
-// The Extension loads the background scripts to respond to events, and
-// unload the background scripts when event handler functions finish.
-// JavaScript variables do not persist between background script sessions,
-// so the extension cannot store the recipe object as a local variable.
-//
-// The background scripts must synchronize access to the recipe object
-// to ensure that the extension records user actions in chronological
-// order. Often, the extension catches multiple user events in a short
-// period of time. If the extension does not synchronize access to the
-// recipe object, event handlers in the background script will run
-// into race conditions that break the recipe.
-
-function openRecipeIndexedDB() {
-  return new Promise((resolve, reject) => {
-           const request = window.indexedDB.open(
-               Indexed_DB_Vars.RECIPE_DB, Indexed_DB_Vars.VERSION);
-           request.onerror = (event) => {
-             console.warn('Unable to load the indexedDB Recipe database!');
-             reject(request.error);
-           };
-           request.onsuccess = (event) => {
-             const db = request.result;
-             resolve(db);
-           };
-           request.onupgradeneeded = (event) => {
-             const db = request.result;
-             db.onerror = (event) => {
-               console.warn('Unable to load the indexedDB Recipe database!');
-               reject(event);
-             };
-             db.createObjectStore(
-                 Indexed_DB_Vars.ATTRIBUTES, {autoIncrement: true});
-             db.createObjectStore(
-                 Indexed_DB_Vars.ACTIONS,
-                 {keyPath: 'action_index', autoIncrement: true});
-             db.createObjectStore(
-                 Indexed_DB_Vars.SAVED_ACTION_PARAMS, {autoIncrement: true});
-             db.createObjectStore(
-                 Indexed_DB_Vars.AUTOFILL_PROFILE, {keyPath: 'type'});
-             db.createObjectStore(
-                 Indexed_DB_Vars.PASSWORD_MANAGER_PROFILE,
-                 {keyPath: ['website', 'username']});
-             event.target.transaction.oncomplete = (event) => {
-               resolve(db);
-             };
-           };
-         })
-      .catch((error) => {
-        console.error('Unable to open the indexedDB Recipe database!', error);
-      });
-}
-
-function clearRecipeIndexedDB() {
-  return new Promise((resolve, reject) => {
-    const request = window.indexedDB.deleteDatabase(Indexed_DB_Vars.RECIPE_DB);
-    request.onerror = (event) => {
-      console.warn('Error deleting indexedDB database.');
-      reject(request.error);
-    };
-    request.onsuccess = (event) => {
-      console.log('IndexedDB database deleted successfully.');
-      resolve();
-    };
-  });
-}
-
-async function performTransactionOnRecipeIndexedDB(transactionToPerform) {
-  const db = await openRecipeIndexedDB();
-  return await new Promise((resolve, reject) => {
-           const transaction = db.transaction(
-               [
-                 Indexed_DB_Vars.ATTRIBUTES, Indexed_DB_Vars.ACTIONS,
-                 Indexed_DB_Vars.SAVED_ACTION_PARAMS,
-                 Indexed_DB_Vars.AUTOFILL_PROFILE,
-                 Indexed_DB_Vars.PASSWORD_MANAGER_PROFILE
-               ],
-               'readwrite');
-           transaction.oncomplete = (event) => {
-             resolve(event);
-           };
-           transaction.onerror = (event) => {
-             console.warn('Unable to complete indexedDB transaction.');
-             reject(transaction.error);
-           };
-           transactionToPerform(transaction);
-         })
-      .catch((error) => {
-        console.error(
-            'Unable to perform transaction in the indexedDB ' +
-                'Recipe database!',
-            error);
-      })
-      .finally(() => {
-        db.close();
-      });
-}
-
-function initializeRecipe(url) {
-  return performTransactionOnRecipeIndexedDB((transaction) => {
-    const attributeStore = transaction.objectStore(Indexed_DB_Vars.ATTRIBUTES);
-    attributeStore.put(url, Indexed_DB_Vars.URL);
-  });
-}
-
-async function addActionToRecipe(action, tabId, skipUpdatingUi) {
-  const db = await openRecipeIndexedDB();
-  const key =
-      await new Promise((resolve, reject) => {
-        const transaction =
-            db.transaction([Indexed_DB_Vars.ACTIONS], 'readwrite');
-        const request =
-            transaction.objectStore(Indexed_DB_Vars.ACTIONS).add(action);
-        let completed = false;
-        let key;
-        request.onsuccess = (event) => {
-          key = event.target.result;
-          if (completed) {
-            resolve(key);
-          }
-        };
-        transaction.oncomplete = (event) => {
-          completed = true;
-          if (key) {
-            resolve(key);
-          }
-        };
-        transaction.onerror = (event) => {
-          console.warn('Unable to add action to the recipe!');
-          reject(event.target.error);
-        };
-      }).finally(() => {
-        db.close();
-      });
-
-  if (!skipUpdatingUi) {
-    // Update the recording UI with the new action.
-    const frameId = await getRecorderUiFrameId();
-    action.action_index = key;
-    await sendMessageToTab(
-        tabId, {type: RecorderUiMsgEnum.ADD_ACTION, action: action},
-        {frameId: frameId});
-  }
-}
-
-function removeActionFromRecipe(index) {
-  return performTransactionOnRecipeIndexedDB((transaction) => {
-    transaction.objectStore(Indexed_DB_Vars.ACTIONS).delete(index);
-  });
-}
-
-function insertChromeAutofillProfileEntry(entry) {
-  return performTransactionOnRecipeIndexedDB((transaction) => {
-    const autofillProfileStore =
-        transaction.objectStore(Indexed_DB_Vars.AUTOFILL_PROFILE);
-    autofillProfileStore.add(entry);
-  });
-}
-
-function insertChromePasswordManagerProfileEntry(entry) {
-  return performTransactionOnRecipeIndexedDB((transaction) => {
-    const passwordManagerProfileStore =
-        transaction.objectStore(Indexed_DB_Vars.PASSWORD_MANAGER_PROFILE);
-    passwordManagerProfileStore.add(entry);
-  });
-}
-
-async function getRecipe() {
-  const db = await openRecipeIndexedDB();
-  let recipe = {};
-  return await new Promise((resolve, reject) => {
-           const transaction = db.transaction(
-               [
-                 Indexed_DB_Vars.ATTRIBUTES, Indexed_DB_Vars.ACTIONS,
-                 Indexed_DB_Vars.AUTOFILL_PROFILE,
-                 Indexed_DB_Vars.PASSWORD_MANAGER_PROFILE
-               ],
-               'readonly');
-           transaction.oncomplete = (event) => {
-             resolve(recipe);
-           };
-           transaction.onerror = (event) => {
-             console.error('Unable to read from indexedDB.');
-             throw (transaction.error);
-           };
-
-           const attributeStore =
-               transaction.objectStore(Indexed_DB_Vars.ATTRIBUTES);
-           const urlReq = attributeStore.get(Indexed_DB_Vars.URL);
-           urlReq.onsuccess = (event) => {
-             recipe.startingURL = urlReq.result;
-           };
-
-           const autofillProfileStore =
-               transaction.objectStore(Indexed_DB_Vars.AUTOFILL_PROFILE);
-           const autofillProfileReq = autofillProfileStore.getAll();
-           autofillProfileReq.onsuccess = (event) => {
-             recipe.autofillProfile =
-                 autofillProfileReq.result ? autofillProfileReq.result : [];
-           };
-
-           const passwordManagerProfileStore = transaction.objectStore(
-               Indexed_DB_Vars.PASSWORD_MANAGER_PROFILE);
-           const passwordManagerProfileReq =
-               passwordManagerProfileStore.getAll();
-           passwordManagerProfileReq.onsuccess = (event) => {
-             recipe.passwordManagerProfiles = [];
-             // Filter out passwords submitted by the user during the course of
-             // recording.
-             if (passwordManagerProfileReq.result) {
-               for (const entry of passwordManagerProfileReq.result) {
-                 if (entry.submittedByUser === undefined) {
-                   recipe.passwordManagerProfiles.push(entry);
-                 }
-               }
-             }
-           };
-
-           const actionsStore =
-               transaction.objectStore(Indexed_DB_Vars.ACTIONS);
-           const actionsReq = actionsStore.getAll();
-           actionsReq.onsuccess = (event) => {
-             recipe.actions = actionsReq.result ? actionsReq.result : [];
-           };
-         })
-      .finally(() => {
-        db.close();
-      });
-}
-
-async function getSavedEventParameters() {
-  const db = await openRecipeIndexedDB();
-  let params = {};
-  return await new Promise((resolve, reject) => {
-           const transaction = db.transaction(
-               [Indexed_DB_Vars.SAVED_ACTION_PARAMS], 'readonly');
-           transaction.oncomplete = (event) => {
-             resolve(params);
-           };
-           transaction.onerror = (event) => {
-             console.error('Unable to read from indexedDB.');
-             throw (transaction.error);
-           };
-
-           const actionParamsStore =
-               transaction.objectStore(Indexed_DB_Vars.SAVED_ACTION_PARAMS);
-           const passwordManagerParamsReq =
-               actionParamsStore.get(Indexed_DB_Vars.PASSWORD_MANAGER_PARAMS);
-           passwordManagerParamsReq.onsuccess = (event) => {
-             if (passwordManagerParamsReq.result) {
-               params.passwordManagerParams = passwordManagerParamsReq.result;
-             }
-           };
-         })
-      .finally(() => {
-        db.close();
-      });
-}
-
-function savePasswordEventParams(username, password, website) {
-  return performTransactionOnRecipeIndexedDB((transaction) => {
-    const attributeStore =
-        transaction.objectStore(Indexed_DB_Vars.SAVED_ACTION_PARAMS);
-    attributeStore.put(
-        {username: username, password: password, website: website},
-        Indexed_DB_Vars.PASSWORD_MANAGER_PARAMS);
-  });
-}
-
-function setBrowserActionUi(state, targetTabId) {
-  switch (state) {
-    case RecorderStateEnum.SHOWN:
-      chrome.browserAction.setTitle(
-          {title: `Action Recorder (Recording on tab ${targetTabId})`});
-      chrome.browserAction.setBadgeText({text: 'HIDE'});
-      chrome.browserAction.setBadgeBackgroundColor({color: [255, 0, 0, 255]});
-      break;
-    case RecorderStateEnum.HIDDEN:
-      chrome.browserAction.setTitle({
-        title: `Action Recorder (Recording on tab ${targetTabId}),` +
-            ' UI is hidden'
-      });
-      chrome.browserAction.setBadgeText({text: 'SHOW'});
-      chrome.browserAction.setBadgeBackgroundColor({color: [0, 255, 0, 255]});
-      break;
-    default:
-      chrome.browserAction.setTitle({title: 'Action Recorder (Idle)'});
-      chrome.browserAction.setBadgeText({text: 'START'});
-      chrome.browserAction.setBadgeBackgroundColor({color: [0, 255, 255, 255]});
-      break;
-  }
-}
-
-async function getRecordingTabId() {
-  const items = await getChromeLocalStorageVariables(
-      [Local_Storage_Vars.RECORDING_TAB_ID]);
-  return items[Local_Storage_Vars.RECORDING_TAB_ID];
-}
-
-async function getRecordingState() {
-  const items = await getChromeLocalStorageVariables(
-      [Local_Storage_Vars.RECORDING_STATE]);
-  return items[Local_Storage_Vars.RECORDING_STATE];
-}
-
-async function getRecorderUiFrameId() {
-  const items = await getChromeLocalStorageVariables(
-      [Local_Storage_Vars.RECORDING_UI_FRAME_ID]);
-  return items[Local_Storage_Vars.RECORDING_UI_FRAME_ID];
-}
-
-async function setRecorderUiFrameId(frameId) {
-  let items = {};
-  items[Local_Storage_Vars.RECORDING_UI_FRAME_ID] = frameId;
-  await setChromeLocalStorageVariables(items);
-}
-
-function sendMessageToTab(tabId, message, options) {
-  return new Promise((resolve, reject) => {
-    chrome.tabs.sendMessage(tabId, message, options, (response) => {
-      resolve(response);
-    });
-  });
-}
-
-function getAllFramesInTab(tabId) {
-  return new Promise((resolve, reject) => {
-    chrome.webNavigation.getAllFrames({tabId: tabId}, (details) => {
-      resolve(details);
-    });
-  });
-}
-
-function clearBrowserCache() {
-  return new Promise(
-      (resolve, reject) => { chrome.browsingData.removeCache({}, () => {
-        if (chrome.runtime.lastError) {
-          reject(chrome.runtime.lastError);
-        } else {
-          resolve();
-        }
-      }); });
-}
-
-async function getIframeContext(tabId, frameId) {
-  if (frameId === 0) {
-    return {isIframe: false};
-  }
-
-  let context = {isIframe: true};
-
-  const allFrames = await getAllFramesInTab(tabId);
-  let targetFrame;
-  for (const frame of allFrames) {
-    if (frame.frameId === frameId) {
-      targetFrame = frame;
-      break;
-    }
-  }
-
-  // Send a message to the parent frame and see if the iframe has a
-  // 'name' attribute.
-  const frameName = await sendMessageToTab(
-      tabId, {type: RecorderMsgEnum.GET_IFRAME_NAME, url: targetFrame.url},
-      {frameId: targetFrame.parentFrameId});
-  if (frameName) {
-    context.browserTest = {name: frameName};
-    return context;
-  }
-
-  const targetFrameUrl = new URL(targetFrame.url);
-  // The frame does not have a 'name' attribute. Check if the frame has
-  // a unique origin.
-  //
-  // The Captured Site automation framework can identify an iframe by its
-  // origin, provided the origin is unique.
-  //
-  // Identifying an iframe through its origin is more preferable than
-  // identifying an iframe through its URL. An URL will frequently
-  // contain parameters, and many websites use random number generator or
-  // date generator to create these parameters. For example, in the
-  // following URL
-  //
-  // https://payment.bhphotovideo.com/static/desktop/v2.0/
-  // index.html
-  // #paypageId=aLGNuLSTJVwgEiCn&cartID=333334444
-  // &receiverID=77777777-7777-4777-b777-777777888888
-  // &uuid=77777777-7777-4777-b777-778888888888
-  //
-  // The site created the parameters cartID, receiverID and uuid using
-  // random number generators. These parameters will have different
-  // values every time the browser loads the page. Therefore automation
-  // will not be able to identify an iframe that loads this URL.
-  let originIsUnique = true;
-  for (const frame of allFrames) {
-    const url = new URL(frame.url);
-    if (frame.frameId !== targetFrame.frameId &&
-        url.origin === targetFrameUrl.origin) {
-      originIsUnique = false;
-      break;
-    }
-  }
-
-  if (originIsUnique) {
-    context.browserTest = {
-      origin: `${targetFrameUrl.protocol}//${targetFrameUrl.host}`
-    };
-    return context;
-  }
-
-  context.browserTest = {url: targetFrame.url};
-  return context;
-}
-
-async function stopRecordingOnTab(tabId) {
-  const allFrames = await getAllFramesInTab(tabId);
-  let stopRecordingOnMainFrameResponse;
-
-  for (const frame of allFrames) {
-    try {
-      const response = await sendMessageToTab(
-          tabId, {type: RecorderMsgEnum.STOP}, {frameId: frame.frameId});
-      if (frame.frameId === 0) {
-        stopRecordingOnMainFrameResponse = response;
-      }
-    } catch (error) {
-      console.warn(`Unable to stop recording on '${frame.url}'`, error);
-    }
-  }
-
-  if (!stopRecordingOnMainFrameResponse) {
-    return Promise.reject(
-        new Error('Unable to stop recording on the root frame!'));
-  }
-
-  const destroyRecordingUiResponse = await sendMessageToTab(
-      tabId, {type: RecorderUiMsgEnum.DESTROY_UI}, {frameId: 0});
-  if (!destroyRecordingUiResponse) {
-    return Promise.reject(new Error('Unable to destroy the recorder UI!'));
-  }
-  setBrowserActionUi(RecorderStateEnum.STOPPED);
-}
-
-async function startRecording(tab) {
-  // By default, start recording on the current active tab.
-  await clearRecorderVariables();
-  await initializeRecorderVariables(tab);
-  const allFrames = await getAllFramesInTab(tab.id);
-  for (const frame of allFrames) {
-    // The extension has no need and no permission to inject script
-    // into 'about:' pages, such as the 'about:blank' page.
-    if (!frame.url.startsWith('about:')) {
-      try {
-        await startRecordingOnTabAndFrame(tab.id, frame.frameId);
-      } catch (error) {
-        console.warn(
-            `Unable to start recording for url ${tab.url}!\r\n`, error);
-      }
-    }
-  }
-  console.log(`Started recording for tab ${tab.id}`);
-}
-
-async function startRecordingOnTabAndFrame(tabId, frameId) {
-  const context = await getIframeContext(tabId, frameId);
-  const response = await sendMessageToTab(
-      tabId, {type: RecorderMsgEnum.START, frameContext: context},
-      {frameId: frameId});
-  if (!response) {
-    return Promise.reject(
-        new Error(`Unable to start recording on ${tabId}, ${frameId}`));
-  }
-
-  // If starting recording on the root frame, tell the root frame to
-  // create the recorder UI.
-  if (frameId === 0) {
-    await sendMessageToTab(
-        tabId, {type: RecorderUiMsgEnum.CREATE_UI}, {frameId: 0});
-    if (!response) {
-      return Promise.reject(new Error('Unable to create the recorder UI!'));
-    }
-    let items = {};
-    items[Local_Storage_Vars.RECORDING_STATE] = RecorderStateEnum.SHOWN;
-    await setChromeLocalStorageVariables(items);
-    setBrowserActionUi(RecorderStateEnum.SHOWN, tabId);
-  }
-}
-
-async function initializeRecorderVariables(tab) {
-  let items = {};
-  // Initialize the target tab id in the local storage area. The
-  // background script will use this id to communicate with the content
-  // script on the actively recording tab.
-  items[Local_Storage_Vars.RECORDING_TAB_ID] = tab.id;
-  await setChromeLocalStorageVariables(items);
-  await initializeRecipe(tab.url);
-}
-
-// Clean up local storage variables used for recording.
-function clearRecorderVariables() {
-  return new Promise((resolve, reject) => {
-    chrome.storage.local.clear(() => {
-      if (chrome.runtime.lastError) {
-        reject(chrome.runtime.lastError);
-      } else {
-        clearRecipeIndexedDB().then(() => resolve());
-      }
-    });
-  });
-}
-
-async function stopRecording() {
-  const tabId = await getRecordingTabId();
-  await stopRecordingOnTab(tabId);
-  await clearRecorderVariables();
-  await clearBrowserCache();
-  console.log('Stopped Recording.');
-}
-
-async function downloadRecipe() {
-  const recipe = await getRecipe();
-
-  // Download the JSON-serialized recipe as a text file.
-  const recipeJsonString = JSON.stringify(recipe, null, 2);
-  const blob = new Blob([recipeJsonString], {type: 'text/plain'});
-  return new Promise((resolve, reject) => {
-    chrome.downloads.download(
-        {
-          filename: '_web_site_name.test',
-          saveAs: true,
-          url: window.URL.createObjectURL(blob)
-        },
-        (downloadId) => {
-          if (downloadId) {
-            resolve();
-          } else {
-            reject('Download failed! Recording isn\'t stopped.');
-          }
-        });
-  });
-}
-
-async function downloadRecipeAndStopRecording() {
-  await downloadRecipe();
-  await stopRecording();
-}
-
-async function showContentScriptUi() {
-  const tabId = await getRecordingTabId();
-  await sendMessageToTab(
-      tabId, {type: RecorderUiMsgEnum.SHOW_UI}, {frameId: 0});
-  let items = {};
-  items[Local_Storage_Vars.RECORDING_STATE] = RecorderStateEnum.SHOWN;
-  await setChromeLocalStorageVariables(items);
-  setBrowserActionUi(RecorderStateEnum.SHOWN, tabId);
-}
-
-async function hideContentScriptUi() {
-  const tabId = await getRecordingTabId();
-  await sendMessageToTab(
-      tabId, {type: RecorderUiMsgEnum.HIDE_UI}, {frameId: 0});
-  let items = {};
-  items[Local_Storage_Vars.RECORDING_STATE] = RecorderStateEnum.HIDDEN;
-  await setChromeLocalStorageVariables(items);
-  setBrowserActionUi(RecorderStateEnum.HIDDEN, tabId);
-}
-
-async function setPasswordEventParams(params, mainFrameIsReady) {
-  // Add an empty entry to the Password Manager Profile Table.
-  //
-  // The Password Manager Profile Table stores the saved passwords a user
-  // has at the start of recording.
-  //
-  // An empty entry is an entry consisting of an origin and a user name,
-  // but not a password.
-  //
-  // The background script adds Password Manager Profile table entries by
-  // insertion - in other words, the background script cannot override an
-  // existing entry. The background script creates an empty entry to denote
-  // that at the start of recording, Chrome did not have a saved password for
-  // the specified username on the specified origin. If a user saves a new
-  // password during the course of recording, the empty entry prevents the
-  // background from erroneously recording the new entry as present at the
-  // start of recording.
-  await insertChromePasswordManagerProfileEntry({
-    submittedByUser: true,
-    username: params.username,
-    website: params.website
-  });
-
-  await savePasswordEventParams(
-      params.username, params.password, params.website);
-
-  if (!mainFrameIsReady) {
-    return true;
-  }
-
-  return await sendPasswordEventParamsToUi(params.username, params.password);
-}
-
-async function sendPasswordEventParamsToUi(username, password, website) {
-  const tabId = await getRecordingTabId();
-  const frameId = await getRecorderUiFrameId();
-  const response = await sendMessageToTab(
-      tabId, {
-        type: RecorderUiMsgEnum.SET_PASSWORD_MANAGER_ACTION_PARAMS,
-        username: username,
-        password: password,
-        website: website
-      },
-      {frameId: frameId});
-  return response;
-}
-
-// Reset the action recorder state to a clean slate every time the background
-// script is loaded.
-// Used to reset the recorder state in the scenario that the user previously
-// closed a session without stopping the recorder. Since the recorder uses
-// indexedDB and local storage, the recording state would persist. The
-// browser action icon state also persists.
-clearRecorderVariables()
-    .then(() => setBrowserActionUi(RecorderStateEnum.STOPPED))
-    .catch((error) => {
-      console.error('Unable to clean up the recorder!\r\n', error);
-      displayUserErrorMessage('Unable to clean up the recorder!');
-    });
-
-// Reset the action recorder state to a clean slate every time the extension
-// is installed or reinstalled.
-// Used to reset the recorder state when reloading the extension after a code
-// change.
-chrome.runtime.onInstalled.addListener(() => {
-  clearRecorderVariables()
-      .then(() => setBrowserActionUi(RecorderStateEnum.STOPPED))
-      .catch((error) => {
-        console.error('Unable to clean up the recorder!\r\n', error);
-        displayUserErrorMessage('Unable to clean up the recorder!');
-      });
-});
-
-async function browserActionOnClickedHander(tab) {
-  const state = await getRecordingState();
-  switch (state) {
-    case RecorderStateEnum.SHOWN:
-      try {
-        await hideContentScriptUi();
-      } catch (error) {
-        console.error('Unable to hide the recorder UI!\r\n', error);
-        displayUserErrorMessage('Unable to hide the recording UI!');
-      }
-      break;
-    case RecorderStateEnum.HIDDEN:
-      try {
-        showContentScriptUi();
-      } catch (error) {
-        console.error('Unable to show the recorder UI!\r\n', error);
-        displayUserErrorMessage('Unable to show the recording UI!');
-      }
-      break;
-    default:
-      // By default, start recording on the current active tab.
-      try {
-        await startRecording(tab);
-      } catch (startRecordingError) {
-        console.error('Unable to start recording!\r\n', startRecordingError);
-        displayUserErrorMessage('Unable to start recording!');
-        try {
-          await stopRecording();
-        } catch (stopRecordingError) {
-          console.warn('Unable to clean up recording!', stopRecordingError);
-          displayUserErrorMessage('Unable to clean up recording!');
-        }
-      }
-  }
-}
-
-chrome.browserAction.onClicked.addListener((tab) => {
-  browserActionOnClickedHander(tab);
-});
-
-async function tabsOnRemovedHandler(tabId) {
-  const recordingTabId = await getRecordingTabId();
-  if (recordingTabId == tabId) {
-    try {
-      await downloadRecipe();
-      await clearRecorderVariables();
-    } catch (error) {
-      console.error(
-          `Unable to stop recording on the closing tab ${tabId}!\r\n`, error);
-    } finally {
-      setBrowserActionUi(RecorderStateEnum.STOPPED);
-    }
-  }
-}
-
-chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
-  tabsOnRemovedHandler(tabId);
-});
-
-async function webNavigationOnCompletedHander(details) {
-  const tabId = await getRecordingTabId();
-  if (details.tabId === tabId &&
-      // Skip recording on 'about:' pages. No meaningful user interaction
-      // occur on 'about:'' pages such as the blank page. Plus, this
-      // extension has no permission to access 'about:' pages.
-      !details.url.startsWith('about:')) {
-    try {
-      await startRecordingOnTabAndFrame(tabId, details.frameId);
-      console.log(`Resumed recording on tab ${tabId}`);
-
-      if (details.frameId !== 0) {
-        return;
-      }
-
-      // If the tab's root frame loaded a new page, log the page's url.
-      // An engineer can truncate a test recipe generated for captured sites
-      // using the 'loadPage' actions. If the Web Page Replay (WPR) tool can
-      // serve a 'loadPage' action url, then the engineer can delete all the
-      // actions that precedes the 'loadPage' action.
-      addActionToRecipe(
-          {
-            url: details.url,
-            context: {'isIframe': false},
-            type: ActionTypeEnum.LOAD_PAGE
-          },
-          tabId, true);
-
-      const state = await getRecordingState();
-      if (state === RecorderStateEnum.HIDDEN) {
-        setBrowserActionUi(RecorderStateEnum.SHOWN, tabId);
-      }
-    } catch (error) {
-      if (details.frameId === 0) {
-        console.error('Unable to resume recording!', error);
-        await stopRecordingOnTab(tabId);
-      } else {
-        console.warn(
-            'Unable to resume recording on the recording ' +
-                `tab ${tabId}, frame ${details.frameId}, ` +
-                `url '${details.url}'!`,
-            error);
-      }
-    }
-  }
-}
-
-chrome.webNavigation.onCompleted.addListener((details) => {
-  webNavigationOnCompletedHander(details);
-});
-
-chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
-  if (!request) return false;
-  switch (request.type) {
-    case RecorderMsgEnum.SAVE:
-      downloadRecipe().then(() => sendResponse(true));
-      return true;
-    case RecorderMsgEnum.STOP:
-      downloadRecipeAndStopRecording().catch((error) => {
-        console.error('Unable to stop recording!\r\n', error);
-        displayUserErrorMessage('Unable to stop recording!');
-      });
-      sendResponse(true);
-      break;
-    case RecorderMsgEnum.CANCEL:
-      stopRecording().catch((error) => {
-        console.error('Unable to stop recording!\r\n', error);
-        displayUserErrorMessage('Unable to stop recording!');
-      });
-      sendResponse(true);
-      break;
-    case RecorderMsgEnum.ADD_ACTION:
-      addActionToRecipe(request.action, sender.tab.id)
-          .then(() => {
-            return sendResponse(true);
-          })
-          .catch((error) => {
-            console.error(
-                `Unable to add the ${request.action.type} action for ` +
-                    `${request.action.selector}!\r\n`,
-                error);
-            displayUserErrorMessage('Unable to record the action!');
-            sendResponse(false);
-          });
-      return true;
-    case RecorderUiMsgEnum.REMOVE_ACTION:
-      removeActionFromRecipe(request.action_index)
-          .then(() => {
-            sendResponse(true);
-          })
-          .catch((error) => {
-            sendResponse(false);
-            console.error(
-                'Unable to remove the action indexed at ' +
-                    `${request.action_index}!\r\n`,
-                error);
-            displayUserErrorMessage('Unable to remove action!');
-          });
-      return true;
-    case RecorderUiMsgEnum.GET_RECIPE:
-      setRecorderUiFrameId(sender.frameId)
-          .then(() => getRecipe())
-          .then((recipe) => sendResponse(recipe));
-      return true;
-    case RecorderUiMsgEnum.GET_SAVED_ACTION_PARAMS:
-      getSavedEventParameters().then((params) => sendResponse(params));
-      return true;
-    case RecorderMsgEnum.SET_PASSWORD_MANAGER_ACTION_PARAMS:
-      setPasswordEventParams(
-          request.params,
-          // A page content scripts sends out a 'Set Password Event
-          // Parameters' message to the background script before submitting a
-          // page form.
-          // Submitting page form triggers a reload. Therefore the main frame
-          // is ready if the message originates from an iframe, but not if the
-          // message originates from the main frame.
-          sender.frameId != 0);
-      return false;
-    case RecorderMsgEnum.SET_AUTOFILL_PROFILE_ENTRY:
-      insertChromeAutofillProfileEntry(request.entry);
-      sendResponse(true);
-      return false;
-    case RecorderMsgEnum.SET_PASSWORD_MANAGER_PROFILE_ENTRY:
-      insertChromePasswordManagerProfileEntry(request.entry);
-      sendResponse(true);
-      return false;
-    default:
-  }
-  return false;
-});
-})();
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/common_lib.js b/components/test/data/autofill/automated_integration/action_recorder_extension/common_lib.js
deleted file mode 100644
index d0356dd..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/common_lib.js
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2018 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.
-
-'use strict';
-
-/**
- * Retrieve a set of variables in Chrome local storage.
- * @param {string|!Array<string>} keys a single key or a list of keys
- *     specifying the variables
- * @returns {!Promise<!Object>} Promise object with the variables in key-value
- *     mappings.
- */
-function getChromeLocalStorageVariables(keys) {
-  return new Promise((resolve, reject) => {
-    chrome.storage.local.get(keys, (items) => {
-      if (chrome.runtime.lastError) {
-        reject(`Unable to get variables from local storage!`);
-      } else {
-        resolve(items);
-      }
-    });
-  });
-}
-
-/**
- * Store a set of variables in Chrome local storage.
- * @param {!Object} items an objecy containing key/value pairs of variable
- *     names/ variable values to store in local storage.
- * @returns {!Promise<!Object>} Promise object denoting whether the operation
- * succeeded.
- */
-function setChromeLocalStorageVariables(items) {
-  return new Promise((resolve, reject) => {
-    chrome.storage.local.set(items, () => {
-      if (chrome.runtime.lastError) {
-        reject(`Unable to set variables in local storage!`);
-      } else {
-        resolve();
-      }
-    });
-  });
-}
-
-/**
- * Send a single message to the background script.
- * @param {!Object} message the message to send to the background script. This
- *     message should be a JSON-ifiable object.
- * @returns {!Promise<!Object>} Promise object containing the background
- * script's response.
- */
-function sendRuntimeMessageToBackgroundScript(message) {
-  return new Promise((resolve, reject) => {
-    chrome.runtime.sendMessage(chrome.runtime.id, message, null,
-                               (response) => {
-      if (chrome.runtime.lastError) {
-        reject(chrome.runtime.lastError);
-      } else {
-        resolve(response);
-      }
-    });
-  });
-}
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/constants.js b/components/test/data/autofill/automated_integration/action_recorder_extension/constants.js
deleted file mode 100644
index b9285ee..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/constants.js
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2018 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.
-
-const Buttons = {
-  LEFT_BUTTON: 0,
-  RIGHT_BUTTON: 2
-};
-
-const RecorderStateEnum = {
-  // Not recording.
-  STOPPED: 'stopped',
-  // Recording, extension is showing the recorder UI on the page.
-  SHOWN: 'shown',
-  // Recording, extension is hiding the recorder UI on the page.
-  HIDDEN: 'hidden'
-};
-
-const ActionTypeEnum = {
-  CLICK: 'click',
-  HOVER: 'hover',
-  LOAD_PAGE: 'loadPage',
-  PRESS_ENTER: 'pressEnter',
-  SELECT: 'select',
-  TYPE: 'type',
-  TYPE_PASSWORD: 'typePassword',
-  VALIDATE_FIELD: 'validateField',
-  // Autofill actions
-  AUTOFILL: 'autofill',
-  // Password manager actions
-  SAVE_PASSWORD: 'savePassword',
-  REJECT_SAVE_PASSWORD: 'rejectSavePassword',
-  UPDATE_PASSWORD: 'updatePassword',
-  REJECT_UPDATE_PASSWORD: 'rejectUpdatePassword'
-};
-
-const RecorderUiMsgEnum = {
-  CREATE_UI: 'add-ui',
-  DESTROY_UI: 'remove-ui',
-  HIDE_UI: 'hide-ui',
-  SHOW_UI: 'show-ui',
-  ADD_ACTION: 'add-action',
-  REMOVE_ACTION: 'remove-action',
-  GET_RECIPE: 'get-recipe',
-  GET_SAVED_ACTION_PARAMS: 'get-saved-action-params',
-  SET_PASSWORD_MANAGER_ACTION_PARAMS: 'set-password-manager-action-params'
-};
-
-const RecorderMsgEnum = {
-  SAVE: 'save-recording',
-  START: 'start-recording',
-  STOP: 'stop-recording',
-  CANCEL: 'cancel-recording',
-  GET_IFRAME_NAME: 'get-iframe-name',
-  ADD_ACTION: 'record-action',
-  SET_PASSWORD_MANAGER_ACTION_PARAMS: 'set-password-manager-action-params',
-  SET_AUTOFILL_PROFILE_ENTRY: 'set-autofill-profile-entry',
-  SET_PASSWORD_MANAGER_PROFILE_ENTRY: 'set-password-manager-profile-entry'
-};
-
-const Local_Storage_Vars = {
-  RECORDING_STATE: 'state',
-  RECORDING_TAB_ID: 'target_tab_id',
-  RECORDING_UI_FRAME_ID: 'ui_frame_id'
-};
-
-const Indexed_DB_Vars = {
-  RECIPE_DB: 'Action_Recorder_Extension_Recipe',
-  VERSION: 1,
-  ACTIONS: 'Actions',
-  // The 'Attributes' table stores properties of the current recipe.
-  ATTRIBUTES: 'Attributes',
-  NAME: 'name',
-  URL: 'url',
-  // The 'Saved Action Params' table stores parameters of potential Chrome
-  // actions.
-  SAVED_ACTION_PARAMS: 'Saved_Action_Params',
-  PASSWORD_MANAGER_PARAMS: 'password_manager_params',
-  // The 'Profile' tables stores the user's Chrome autofill profile and Chrome
-  // password manager profile.
-  AUTOFILL_PROFILE: 'autofill_profile',
-  PASSWORD_MANAGER_PROFILE: 'password_manager_profile'
-};
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/content/action_handler.js b/components/test/data/autofill/automated_integration/action_recorder_extension/content/action_handler.js
deleted file mode 100644
index 57a6653..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/content/action_handler.js
+++ /dev/null
@@ -1,764 +0,0 @@
-// Copyright 2018 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.
-
-'use strict';
-
-(function() {
-function buildXPathForElement(target) {
-  function build(target) {
-    let node = target;
-    let descendentXPath = '';
-
-    while (node !== null) {
-      if (node.nodeType === Node.DOCUMENT_NODE) {
-        return descendentXPath;
-      }
-
-      let result = prependParentNodeToXPath(node, descendentXPath);
-      if (result.isUnique) {
-        return result.xPath;
-      }
-
-      descendentXPath = result.xPath;
-      node = node.parentNode;
-    }
-
-    throw (
-        'Failed to build a unique XPath! The target node isn\'t ' +
-        'attached to the document!');
-  }
-
-  function prependParentNodeToXPath(node, xPath) {
-    // First, test if simply constructing an XPath using the element's
-    // local name results in a unique XPath.
-    let nodeXPath = buildXPathForSingleNode(node);
-    let testXPath = `//${nodeXPath}${xPath}`;
-    let numMatches = countNumberOfMatches(testXPath);
-    if (numMatches === 1) {
-      return {isUnique: true, xPath: testXPath};
-    }
-
-    // Build a list of potential classifiers using
-    // * The element's explicit attributes.
-    // * The element's text content, if the element contains text.
-    let classifiers = [];
-    let attributes = [];
-    let attrRawValues = [];
-    // Populate the attribute list with the element's explicit attributes.
-    for (let index = 0; index < node.attributes.length; index++) {
-      const attr = node.attributes[index].name;
-      if (attr === 'style') {
-        // Skip styles. 'style' is mutable.
-        continue;
-      } else if (attr === 'class') {
-        // Disabled. Class list is simply too mutable, especially in the
-        // case where an element changes class on hover or on focus.
-        continue;
-      } else if (
-          attr === 'autofill-prediction' || attr === 'field_signature' ||
-          attr === 'pm_parser_annotation' || attr === 'title') {
-        // These attributes are inserted by Chrome.
-        // Since Chrome sets these attributes, these attributes may change
-        // from build to build. Skip these attributes.
-        continue;
-      } else {
-        attributes.push(`@${attr}`);
-        attrRawValues.push(node.attributes[index].value);
-      }
-    }
-    // Add the element's text content to the attribute list.
-    switch (node.localName) {
-      case 'a':
-      case 'span':
-      case 'button':
-        attributes.push('text()');
-        attrRawValues.push(node.textContent);
-        break;
-      default:
-    }
-
-    // Iterate through each attribute.
-    for (let index = 0; index < attributes.length; index++) {
-      let classifier =
-          buildClassifier(node, attributes[index], attrRawValues[index]);
-      // Add the classifier and see if adding it generates a unique XPath.
-      let numMatchesBefore = numMatches;
-      classifiers.push(classifier);
-      nodeXPath = buildXPathForSingleNode(node, classifiers);
-      testXPath = `//${nodeXPath}${xPath}`;
-      numMatches = countNumberOfMatches(testXPath);
-
-      if (numMatches === 0) {
-        // The classifier is faulty, log an error and remove the classifier.
-        console.warn('Encountered faulty classifier: ' + classifiers.pop());
-      } else if (numMatches === 1) {
-        // The current XPath is unique, exit.
-        return {isUnique: true, xPath: testXPath};
-      } else if (numMatches === numMatchesBefore) {
-        // Adding this classifier to the XPath does not narrow down the
-        // number of elements this XPath matches. Therefore the XPath does not
-        // need this classifier. Remove the classifier.
-        classifiers.pop();
-      }
-    }
-
-    // A XPath with the current node as the root is not unique.
-    // Check if the node has siblings with the same XPath. If so,
-    // add a child node index to the current node's XPath.
-    const queryResult = document.evaluate(
-        nodeXPath, node.parentNode, null,
-        XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
-
-    if (queryResult.snapshotLength === 1) {
-      return {isUnique: false, xPath: `/${nodeXPath}${xPath}`};
-    } else {
-      // The current node has siblings with the same XPath. Add an index
-      // to the current node's XPath.
-      for (let index = 0; index < queryResult.snapshotLength; index++) {
-        if (queryResult.snapshotItem(index) === node) {
-          let testXPath = `/${nodeXPath}[${(index + 1)}]${xPath}`;
-          return {isUnique: false, xPath: testXPath};
-        }
-      }
-
-      throw ('Assert: unable to find the target node!');
-    }
-  }
-
-  function buildClassifier(element, attributeXPathToken, attributeValue) {
-    if (!attributeValue ||
-        // Skip values that has the " character. There is just no good way to
-        // wrap this character in xslt, and the best way to handle it
-        // involves doing gynmnastics with string concatenation, as in
-        // "concat('Single', "'", 'quote. Double', '"', 'quote.')]";
-        // It is easier to just skip attributes containing the '"' character.
-        // Furthermore, attributes containing the '"' character are very rare.
-        attributeValue.indexOf('"') >= 0 ||
-        // Skip values that have the \ character. JavaScript does not
-        // serialize this character correctly.
-        attributeValue.indexOf('\\') >= 0) {
-      return attributeXPathToken;
-    }
-
-    // Sometimes, the attribute is a piece of code containing spaces,
-    // carriage returns or tabs. A XPath constructed using the raw value
-    // will not work. Normalize the value instead.
-    const queryResult = document.evaluate(
-        `normalize-space(${attributeXPathToken})`, element, null,
-        XPathResult.STRING_TYPE, null);
-    if (queryResult.stringValue === attributeValue) {
-      // There is no difference between the raw value and the normalized
-      // value, return a shorter XPath with the raw value.
-      return `${attributeXPathToken}="${attributeValue}"`;
-    } else {
-      return `normalize-space(${attributeXPathToken})=` +
-          `"${queryResult.stringValue}"`;
-    }
-  }
-
-  function buildXPathForSingleNode(element, classifiers = []) {
-    let xPathSelector = element.localName;
-    // Add the classifiers
-    if (classifiers.length > 0) {
-      xPathSelector += `[${classifiers[0]}`;
-      for (let index = 1; index < classifiers.length; index++) {
-        xPathSelector += ` and ${classifiers[index]}`;
-      }
-      xPathSelector += ']';
-    }
-    return xPathSelector;
-  }
-
-  function countNumberOfMatches(xPath) {
-    const queryResult = document.evaluate(
-        `count(${xPath})`, document, null, XPathResult.NUMBER_TYPE, null);
-    return queryResult.numberValue;
-  }
-
-  return build(target);
-}
-
-let autofillTriggerElementInfo = null;
-let lastTypingEventInfo = null;
-let frameContext;
-let mutationObserver = null;
-let started = false;
-
-function resetAutofillTriggerElement() {
-  autofillTriggerElementInfo = null;
-}
-
-function isEditableInputElement(element) {
-  return (element.localName === 'select') ||
-      (element.localName === 'textarea') || canTriggerAutofill(element);
-}
-
-function isPasswordInputElement(element) {
-  return element.getAttribute('type') === 'password';
-}
-
-function isChromeRecognizedPasswordField(element) {
-  const passwordManagerParserAnnotation =
-      element.getAttribute('pm_parser_annotation');
-  return passwordManagerParserAnnotation === 'password_element' ||
-      passwordManagerParserAnnotation === 'new_password_element' ||
-      passwordManagerParserAnnotation === 'confirmation_password_element';
-}
-
-function isChromeRecognizedUserNameField(element) {
-  return element.getAttribute('pm_parser_annotation') === 'username_element';
-}
-
-function canTriggerAutofill(element) {
-  return (element.localName === 'input' && [
-    'checkbox', 'radio', 'button', 'submit', 'hidden', 'reset'
-  ].indexOf(element.getAttribute('type')) === -1);
-}
-
-async function extractAndSendChromePasswordManagerProfile(passwordField) {
-  // Extract the user name field.
-  const form = passwordField.form;
-  const usernameField = form.querySelector(
-      `*[form_signature][pm_parser_annotation='username_element']`);
-  if (!usernameField) {
-    console.warn('Failed to detect the user name field!');
-    return;
-  }
-
-  const autofilledPasswordManagerProfile = {
-    username: usernameField.value,
-    password: passwordField.value,
-    website: window.location.origin
-  };
-  return await sendRuntimeMessageToBackgroundScript({
-    type: RecorderMsgEnum.SET_PASSWORD_MANAGER_PROFILE_ENTRY,
-    entry: autofilledPasswordManagerProfile
-  });
-}
-
-async function sendChromeAutofillProfileEntry(field) {
-  const entry = {
-    type: field.getAttribute('autofill-prediction'),
-    value: field.value
-  };
-  return await sendRuntimeMessageToBackgroundScript(
-      {type: RecorderMsgEnum.SET_AUTOFILL_PROFILE_ENTRY, entry: entry});
-}
-
-async function addActionToRecipe(action) {
-  return await sendRuntimeMessageToBackgroundScript(
-      {type: RecorderMsgEnum.ADD_ACTION, action: action});
-}
-
-async function onUserMakingSelectionChange(element) {
-  const selector = buildXPathForElement(element);
-  const elementReadyState = automation_helper.getElementState(element);
-  const index = element.options.selectedIndex;
-
-  console.log(`Select detected on: ${selector} with '${index}'`);
-  const action = {
-    context: frameContext,
-    index: index,
-    selector: selector,
-    type: ActionTypeEnum.SELECT,
-    visibility: elementReadyState
-  };
-  await addActionToRecipe(action);
-}
-
-async function onUserFinishingTypingInput(element) {
-  const selector = buildXPathForElement(element);
-  const elementReadyState = automation_helper.getElementState(element);
-
-  console.log(`Typing detected on: ${selector}`);
-  // Distinguish between typing inside password input fields and
-  // other type of text input fields.
-  //
-  // This extension generates test recipes to be consumed by the Captured
-  // Sites Automation Framework. The automation framework replays a typing
-  // action by using JavaScript to set the value of a text input field.
-  //
-  // However, to trigger the Chrome Password Manager, the automation
-  // framework must simulate user typing inside the password field by
-  // sending individual character keyboard input - because Chrome Password
-  // Manager deliberately ignores forms filled by JavaScript.
-  //
-  // Simulating keyboard input is a less reliable and therefore the less
-  // preferred way for filling text inputs. The Automation Framework uses
-  // keyboard input only when necessary. So this extension separates
-  // typing password actions from other typing actions.
-  const isPasswordField = isPasswordInputElement(event.target);
-
-  const action = {
-    context: frameContext,
-    selector: selector,
-    type: isPasswordField ? ActionTypeEnum.TYPE_PASSWORD : ActionTypeEnum.TYPE,
-    value: element.value,
-    visibility: elementReadyState
-  };
-
-  await addActionToRecipe(action);
-}
-
-async function onUserInvokingAutofill() {
-  console.log(`Triggered autofill on ${autofillTriggerElementInfo.selector}`);
-  const autofillAction = {
-    selector: autofillTriggerElementInfo.selector,
-    context: frameContext,
-    type: ActionTypeEnum.AUTOFILL,
-    visibility: autofillTriggerElementInfo.visibility
-  };
-  resetAutofillTriggerElement();
-  await addActionToRecipe(autofillAction);
-}
-
-async function onChromeAutofillingNonPasswordInput(element) {
-  const selector = buildXPathForElement(element);
-  const elementReadyState = automation_helper.getElementState(element);
-  const value = element.value;
-  const autofillType = element.getAttribute('autofill-prediction');
-
-  console.log(`Autofill detected on: ${selector} with value '${value}'`);
-  let action = {
-    context: frameContext,
-    expectedValue: value,
-    selector: selector,
-    type: ActionTypeEnum.VALIDATE_FIELD,
-    visibility: elementReadyState
-  };
-
-  if (autofillType) {
-    action.expectedAutofillType = autofillType;
-  }
-  await addActionToRecipe(action);
-
-  if (autofillType) {
-    await sendChromeAutofillProfileEntry(element);
-  }
-}
-
-async function onChromeAutofillingPasswordInput(element) {
-  const elementReadyState = automation_helper.getElementState(element);
-  const selector = buildXPathForElement(element);
-  const value = element.value;
-
-  console.log(`Autofill detected on: ${selector} with value '${value}'`);
-  let validateAction = {
-    selector: selector,
-    context: frameContext,
-    expectedValue: value,
-    type: ActionTypeEnum.VALIDATE_FIELD,
-    visibility: elementReadyState
-  };
-  await addActionToRecipe(validateAction);
-
-  await extractAndSendChromePasswordManagerProfile(element);
-}
-
-async function onInputChangeActionHandler(event) {
-  if (event.target.autofilledByChrome &&
-      isChromeRecognizedPasswordField(event.target)) {
-    await onChromeAutofillingPasswordInput(event.target);
-  } else if (event.target.autofilledByChrome) {
-    // If the user has previously clicked on a field that can trigger
-    // autofill, add a trigger autofill action.
-    if (autofillTriggerElementInfo !== null) {
-      await onUserInvokingAutofill();
-    }
-    await onChromeAutofillingNonPasswordInput(event.target);
-  } else if (event.target.localName === 'select') {
-    await onUserMakingSelectionChange(event.target);
-  } else if (
-      lastTypingEventInfo && lastTypingEventInfo.target === event.target &&
-      lastTypingEventInfo.value === event.target.value) {
-    await onUserFinishingTypingInput(event.target);
-  }
-}
-
-function registerOnInputChangeActionListener(root) {
-  const inputElements = root.querySelectorAll('input, select, textarea');
-  inputElements.forEach((element) => {
-    if (isEditableInputElement(element)) {
-      element.addEventListener('change', onInputChangeActionHandler, true);
-      element.addEventListener('animationstart', onAnimationStartHandler, true);
-    }
-  });
-}
-
-function unRegisterOnInputChangeActionListener(root) {
-  const inputElements = root.querySelectorAll('input, select, textarea');
-  inputElements.forEach((element) => {
-    if (isEditableInputElement(element)) {
-      element.removeEventListener('change', onInputChangeActionHandler, true);
-      element.removeEventListener(
-          'animationstart', onAnimationStartHandler, true);
-    }
-  });
-}
-
-// If the user clicks on an element that can trigger autofill, save the
-// element's xpath. If the extension detects Chrome autofill events later,
-// the extension will designate this element as the autofill trigger
-// element.
-function onClickingAutofillableElement(element) {
-  const selector = buildXPathForElement(event.target);
-  const elementReadyState = automation_helper.getElementState(event.target);
-  autofillTriggerElementInfo = {
-    selector: selector,
-    visibility: elementReadyState
-  };
-}
-
-async function onLeftMouseClickingPageElement(element) {
-  // Reset the autofill trigger element.
-  resetAutofillTriggerElement();
-
-  // Do not record left mouse clicks on editable inputs.
-  // These clicks should always precede either a typing action, or an
-  // autofill action. The extension will record typing actions and
-  // autofill actions separately.
-  if (isEditableInputElement(element)) {
-    if (canTriggerAutofill(element)) {
-      onClickingAutofillableElement(element);
-    }
-    return;
-  }
-
-  // Ignore left mouse clicks on the html element. A page fires an event
-  // with the entire html element as the target when the user clicks on
-  // Chrome's side scroll bar.
-  if (event.target.localName === 'html') return;
-
-  const elementReadyState = automation_helper.getElementState(element);
-  const selector = buildXPathForElement(element);
-
-  console.log(`Left-click detected on: ${selector}`);
-  await addActionToRecipe({
-    selector: selector,
-    visibility: elementReadyState,
-    context: frameContext,
-    type: ActionTypeEnum.CLICK
-  });
-}
-
-async function onRightMouseClickingPageElement(element) {
-  const selector = buildXPathForElement(element);
-  const elementReadyState = automation_helper.getElementState(element);
-
-  console.log(`Right-click detected on: ${selector}`);
-  await addActionToRecipe({
-    selector: selector,
-    visibility: elementReadyState,
-    context: frameContext,
-    type: ActionTypeEnum.HOVER
-  });
-}
-
-async function onClickActionHander(event) {
-  if (event.button === Buttons.LEFT_BUTTON) {
-    await onLeftMouseClickingPageElement(event.target);
-  } else if (event.button === Buttons.RIGHT_BUTTON) {
-    await onRightMouseClickingPageElement(event.target);
-  }
-}
-
-async function onEnterKeyUp(element) {
-  const elementReadyState = automation_helper.getElementState(element);
-  const selector = buildXPathForElement(element);
-
-  console.log(`Enter detected on: ${selector}'`);
-  await addActionToRecipe({
-    selector: selector,
-    visibility: elementReadyState,
-    context: frameContext,
-    type: ActionTypeEnum.PRESS_ENTER
-  });
-}
-
-async function onKeyUpActionHandler(event) {
-  if (event.key === 'Enter') {
-    return await onEnterKeyUp(event.target);
-  }
-
-  if (isEditableInputElement(event.target)) {
-    lastTypingEventInfo = { target: event.target, value: event.target.value };
-  } else {
-    lastTypingEventInfo = null;
-  }
-}
-
-async function onPasswordFormSubmitHandler(event) {
-  const form = event.target;
-
-  // Extract the form signature value from the form.
-  const fields =
-      form.querySelectorAll(`*[form_signature][pm_parser_annotation]`);
-  let username = null;
-  let password = null;
-  for (const field of fields) {
-    const passwordManagerAnnotation =
-        field.getAttribute('pm_parser_annotation');
-    switch (passwordManagerAnnotation) {
-      case 'password_element':
-      case 'new_password_element':
-      case 'confirmation_password_element':
-        password = field.value;
-        break;
-      case 'username_element':
-        username = field.value;
-        break;
-      default:
-    }
-  }
-
-  if (!username || !password) {
-    // The form is missing a user name field or a password field.
-    // The content script should not forward an incomplete password form to
-    // the recorder extension. Exit.
-    return;
-  }
-
-  await sendRuntimeMessageToBackgroundScript({
-    type: RecorderMsgEnum.SET_PASSWORD_MANAGER_ACTION_PARAMS,
-    params: {
-      username: username,
-      password: password,
-      website: window.location.origin
-    }
-  });
-}
-
-function registerOnPasswordFormSubmitHandler(root) {
-  const formElements = root.querySelectorAll('form');
-  formElements.forEach((form) => {
-    form.addEventListener('submit', onPasswordFormSubmitHandler, true);
-  });
-}
-
-function unRegisterOnPasswordFormSubmitHandler(root) {
-  const formElements = root.querySelectorAll('form');
-  formElements.forEach((form) => {
-    form.removeEventListener('submit', onPasswordFormSubmitHandler, true);
-  });
-}
-
-function addCssStyleToTriggerAutofillEvents() {
-  let style = document.createElement('style');
-  style.type = 'text/css';
-  const css = `@keyframes onAutoFillStart {
-                   from {/**/}  to {/**/}
-                 }
-                 @keyframes onAutoFillCancel {
-                   from {/**/}  to {/**/}
-                 }
-
-                 input:-webkit-autofill,
-                 select:-webkit-autofill,
-                 textarea:-webkit-autofill {
-                   animation-name: onAutoFillStart;
-                 }
-
-                 input:not(:-webkit-autofill),
-                 select:not(:-webkit-autofill),
-                 textarea:not(:-webkit-autofill) {
-                   animation-name: onAutoFillCancel;
-                 }`;
-  style.appendChild(document.createTextNode(css));
-  document.getElementsByTagName('head')[0].appendChild(style);
-}
-
-function onAnimationStartHandler(event) {
-  switch (event.animationName) {
-    case 'onAutoFillStart':
-      event.target.autofilledByChrome = true;
-      break;
-    case 'onAutoFillCancel':
-      event.target.autofilledByChrome = false;
-      break;
-    default:
-  }
-}
-
-function startRecording(context) {
-  frameContext = context;
-  // Add a css rule to allow the extension to detect when Chrome
-  // autofills password input fields.
-  addCssStyleToTriggerAutofillEvents();
-  // Register on change listeners on all the input elements.
-  registerOnInputChangeActionListener(document);
-  registerOnPasswordFormSubmitHandler(document);
-  // Register a mouse up listener on the entire document.
-  //
-  // The content script registers a 'Mouse Up' listener rather than a
-  // 'Mouse Down' to correctly handle the following scenario:
-  //
-  // A user types inside a search box, then clicks the search button.
-  //
-  // The following events will fire in quick chronological succession:
-  // * Mouse down on the search button.
-  // * Change on the search input box.
-  // * Mouse up on the search button.
-  //
-  // To capture the correct sequence of actions, the content script
-  // should tie left mouse click actions to the mouseup event.
-  document.addEventListener('mouseup', onClickActionHander);
-  // Register a key press listener on the entire document.
-  document.addEventListener('keyup', onKeyUpActionHandler);
-  // Setup mutation observer to listen for event on nodes added after
-  // recording starts.
-  mutationObserver = new MutationObserver((mutations) => {
-    mutations.forEach(mutation => {
-      mutation.addedNodes.forEach(node => {
-        if (node.nodeType === Node.ELEMENT_NODE) {
-          // Add the onchange listener on any new input elements. This
-          // way the recorder can record user interactions with new
-          // elements.
-          registerOnInputChangeActionListener(node);
-          // Add the on password form submission listener on any new
-          // form elements.
-          registerOnPasswordFormSubmitHandler(node);
-        }
-      });
-    });
-  });
-  mutationObserver.observe(document, {childList: true, subtree: true});
-  started = true;
-  return Promise.resolve();
-}
-
-function stopRecording() {
-  if (started) {
-    mutationObserver.disconnect();
-    document.removeEventListener('mousedown', onClickActionHander);
-    document.removeEventListener('keyup', onKeyUpActionHandler);
-    unRegisterOnInputChangeActionListener(document);
-    unRegisterOnPasswordFormSubmitHandler(document);
-  }
-}
-
-function queryIframeName(iframeUrl) {
-  let iframe = null;
-  const frameLocation = new URL(iframeUrl);
-  const iframes = document.querySelectorAll('iframe');
-  // Find the target iframe.
-  for (let index = 0; index < iframes.length; index++) {
-    const url = new URL(iframes[index].src, location.origin);
-    // Try to identify the iframe using the entire URL.
-    if (frameLocation.href === url.href) {
-      iframe = iframes[index];
-    }
-    // On rare occasions, the hash in an iframe's URL may not match with the
-    // hash in the iframe element's src attribute. For example, the iframe
-    // document reports that the iframe url is 'http://foobar.com/index#bar',
-    // whereas in the parent document, the iframe element's src attribute is
-    // '/index'
-    // To handle the scenario described above, this code optionally ignores
-    // the iframe url's hash.
-    if (iframes === null && frameLocation.origin === url.origin &&
-        frameLocation.pathname === url.pathname &&
-        frameLocation.search === url.search) {
-      iframe = iframes[index];
-    }
-  }
-
-  if (iframe === null) {
-    return Promise.reject(
-        new Error(`Unable to find iframe with url '${iframeUrl}'!`));
-  }
-
-  if (iframe.name) {
-    return Promise.resolve(iframe.name);
-  } else {
-    return Promise.resolve(false);
-  }
-}
-
-chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
-  if (!request) return;
-  switch (request.type) {
-    case RecorderMsgEnum.START:
-      startRecording(request.frameContext)
-          .then(() => sendResponse(true))
-          .catch((error) => {
-            sendResponse(false);
-            console.error(
-                `Unable to start recording on ${window.location.href}!\r\n`,
-                error);
-          });
-      return true;
-    case RecorderMsgEnum.STOP:
-      stopRecording();
-      sendResponse(true);
-      break;
-    case RecorderMsgEnum.GET_IFRAME_NAME:
-      console.log(`Cross: ${request.url}`);
-      queryIframeName(request.url)
-          .then((context) => {
-            sendResponse(context);
-          })
-          .catch((error) => {
-            sendResponse(false);
-            console.error(`Unable to query for iframe!\r\n`, error);
-          });
-      return true;
-    default:
-  }
-  // Return false to close the message channel. Lingering message
-  // channels will prevent background scripts from unloading, causing it
-  // to persist.
-  return false;
-});
-
-if (typeof automation_helper === 'undefined') {
-  var automation_helper = {
-    // An enum specifying the state of an element on the page.
-    DomElementReadyState: Object.freeze({
-      'present': 0,
-      'visible': 1 << 0,
-      'enabled': 1 << 1,
-      'on_top': 1 << 2,
-    }),
-  };
-
-  automation_helper.getElementState =
-      function(element) {
-    let state_flags = this.DomElementReadyState.present;
-    // Check if the element is disabled.
-    if (!element.disabled) {
-      state_flags |= this.DomElementReadyState.enabled;
-    }
-    // Check if the element is visible.
-    if (element.offsetParent !== null && element.offsetWidth > 0 &&
-        element.offsetHeight > 0) {
-      state_flags |= this.DomElementReadyState.visible;
-
-      // Check if the element is also on top.
-      const rect = element.getBoundingClientRect();
-      const topElement = document.elementFromPoint(
-          // As coordinates, use the center of the element, minus
-          // the window offset in case the element is outside the
-          // view.
-          rect.left + rect.width / 2 - window.pageXOffset,
-          rect.top + rect.height / 2 - window.pageYOffset);
-      if (isSelfOrDescendant(element, topElement)) {
-        state_flags |= this.DomElementReadyState.on_top;
-      }
-    }
-    return state_flags;
-  };
-
-  function isSelfOrDescendant(parent, child) {
-    var node = child;
-    while (node != null) {
-      if (node == parent) {
-        return true;
-      }
-      node = node.parentNode;
-    }
-    return false;
-  }
-
-  return automation_helper;
-}
-})();
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/content/foreground.js b/components/test/data/autofill/automated_integration/action_recorder_extension/content/foreground.js
deleted file mode 100644
index 620ef4a..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/content/foreground.js
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2018 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.
-
-'use strict';
-
-(function() {
-  let panelUi;
-
-  function createRecordingUi() {
-    panelUi = document.createElement('iframe');
-    panelUi.src = chrome.runtime.getURL('content/panel.html');
-    panelUi.style.border = 'none';
-    panelUi.style.height = '613px';
-    panelUi.style.padding = '0';
-    panelUi.style.position = 'fixed';
-    panelUi.style.right = 0;
-    panelUi.style.top = '100px';
-    panelUi.style.width = '365px';
-
-    // 2147483647 should be the maximum possible z index value.
-    panelUi.style.zIndex = 2147483647;
-
-    // The 'clip' and the 'overflow' properties are set to prevent css rules
-    // on the main page from disabling interaction with iframes.
-    // Please read the following bug for more details:
-    // https://crbug.com/850700
-    panelUi.style.clip = 'auto';
-    panelUi.style.overflow = 'visible';
-
-    document.body.appendChild(panelUi);
-  }
-
-  function hideUi() {
-    panelUi.style.display = 'none';
-  }
-
-  function showUi() {
-    panelUi.style.display = 'block';
-  }
-
-  function removeUi() {
-    if (panelUi) {
-      panelUi.remove();
-    }
-  }
-
-  chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
-    if (!request) return;
-    switch (request.type) {
-      case RecorderUiMsgEnum.CREATE_UI:
-        createRecordingUi();
-        sendResponse(true);
-        break;
-      case RecorderUiMsgEnum.DESTROY_UI:
-        removeUi();
-        sendResponse(true);
-        break;
-      case RecorderUiMsgEnum.HIDE_UI:
-        hideUi();
-        sendResponse(true);
-        break;
-      case RecorderUiMsgEnum.SHOW_UI:
-        showUi();
-        sendResponse(true);
-        break;
-      default:
-    }
-    // Return false to close the message channel. Lingering message
-    // channels will prevent background scripts from unloading, causing it
-    // to persist.
-    return false;
-  });
-})();
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/content/panel.css b/components/test/data/autofill/automated_integration/action_recorder_extension/content/panel.css
deleted file mode 100644
index f2aee89..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/content/panel.css
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Copyright 2018 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 url('https://fonts.googleapis.com/css?family=Roboto');
-
-:root {
-  --primary-background-color: #FFFFFF;
-  --secondary-background-color: #4285F4;
-}
-
-.hidden {
-  display: none !important;
-}
-
-#panel {
-  background-color: var(--primary-background-color);
-  display: block;
-  font-family: 'Roboto', sans-serif;
-  height: 100%;
-  opacity: 0.8;
-  position: fixed;
-  right: 0;
-  width: 360px;
-}
-
-#panel .section {
-  background-color: var(--primary-background-color);
-  box-shadow: 0 0 2px 0 rgba(0,0,0,0.12), 0 0 2px 0 rgba(0,0,0,0.24);
-  margin-bottom: 8px;
-  padding: 8px 16px 8px 16px;
-}
-
-#panel .h-flex-container {
-  display: flex;
-}
-
-#panel .v-flex-container {
-  display: flex;
-}
-
-#panel #header {
-  background-color: var(--secondary-background-color);
-  color: var(--primary-background-color);
-}
-
-#panel #headingText {
-  flex: 8;
-  margin: 8px 4px 4px 0px;
-}
-
-#panel #actions {
-  background-color: var(--primary-background-color);
-  box-shadow: 0 0 2px 0 rgba(0,0,0,0.12), 0 0 2px 0 rgba(0,0,0,0.24);
-  height: calc(100% - 220px);
-  overflow-y: scroll;
-}
-
-#panel #actions .action {
-  margin: 2px 0 2px 0;
-  position:relative;
-}
-
-#panel .tooltip-body {
-  background-color: var(--secondary-background-color);
-  color: var(--primary-background-color);
-  opacity: 0;
-  position: absolute;
-  transition: opacity 0.5s;
-  visibility: hidden;
-}
-
-#panel #actions .action .tooltip-body {
-  overflow: -webkit-paged-x;
-  top: 16px;
-  width: 100%;
-}
-
-#panel .tooltip-trigger:hover .tooltip-body {
-  opacity: 1;
-  visibility: visible;
-  z-index: 1;
-}
-
-#panel #forms::-webkit-scrollbar {
-  background-color: #F1F1F1;
-  width: 10px;
-}
-
-#panel #forms::-webkit-scrollbar-thumb {
-  background-color: var(--secondary-background-color);
-}
-
-#panel h1 {
-  display: block;
-  line-height: 20px;
-  font-size: 20px;
-  margin: 2px 4px 2px 8px;
-  width: 200px;
-}
-
-#panel h2 {
-  display: block;
-  font-size: 16px;
-  line-height: 16px;
-  margin: 2px 4px 2px 8px;
-  width: 160px;
-}
-
-#panel h3 {
-  display: block;
-  font-size: 12px;
-  font-weight: 800;
-  line-height: 12px;
-  margin: 2px 4px 2px 8px;
-  width: 120px;
-}
-
-#panel h4 {
-  display: block;
-  font-size: 12px;
-  font-weight: 200;
-  line-height: 12px;
-  margin: 2px 4px 2px 8px;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  width: 165px;
-}
-
-#panel label {
-  display: block;
-  flex: 1;
-  font-size: 12px;
-  line-height: 18px;
-  margin: 2px 4px 0px 8px;
-}
-
-#panel input {
-  border: thin #BDBDBD dashed;
-  display: block;
-  font-size: 12px;
-  height: 16px;
-  line-height: 12px;
-  margin: 4px 0 0 0;
-  padding: 0;
-}
-
-#panel input.input1Box {
-  flex: 4;
-}
-
-#panel input.input2Box {
-  flex: 2;
-}
-
-#panel select {
-  background-color: #F7F7F7;
-  border: 0;
-  display: block;
-  flex: 3;
-  font-size: 12px;
-  height: 12px;
-  line-height: 12px;
-  margin: 4px 0 0 0;
-  padding: 0;
-}
-
-#panel .field {
-  padding: 0 0 0 0;
-}
-
-#panel #nextStep {
-  display: flex;
-  padding: 8px 16px;
-}
-
-#panel .nextBtnClass {
-  background-color: var(--secondary-background-color);
-  border-style: outset;
-  border-width: 1px;
-  color: var(--primary-background-color);
-  cursor: pointer;
-  flex: 2;
-  font-size: 12px;
-  line-height: 12px;
-  margin: 0 1px;
-  padding: 4px;
-  text-align: center;
-}
-
-#panel .iconBox {
-  cursor: pointer;
-  height: 12px;
-  margin: 4px 0 0 0;
-  width: 12px;
-}
-
-#panel .imgBox {
-  background-color: #F7F7F7;
-  flex: 1;
-  height: 40px;
-  margin: 4px 0 0 0;
-}
-
-/* Tooltip container */
-.tooltip-trigger {
-  position: relative;
-  display: inline-block;
-}
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/content/panel.html b/components/test/data/autofill/automated_integration/action_recorder_extension/content/panel.html
deleted file mode 100644
index 9cca922..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/content/panel.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<html>
-<head>
-  <link rel="stylesheet" type="text/css" href="panel.css">
-</head>
-<body>
-  <div id="panel">
-    <div id="header" class="section">
-      <div id="headingText" class="h-flex-container">
-        <h1>Action Recorder</h1>
-      </div>
-      <div class="h-flex-container">
-        <a class="nextBtnClass" id="saveBtn">Save Recipe</a>
-        <a class="nextBtnClass" id="stopBtn">Stop Recording</a>
-        <a class="nextBtnClass" id="cancelBtn">Cancel Recording</a>
-      </div>
-    </div>
-    <div class="section">
-      <div class="field h-flex-container">
-        <label>Start URL</label>
-        <input type="text" class="input1Box" id="startingURL" disabled/>
-      </div>
-    </div>
-    <div class="section">
-      <div>
-        <div class="field h-flex-container">
-          <a class="nextBtnClass" id="addChromeAction">Add Chrome Action</a>
-          <select id="newActionType">
-          </select>
-        </div>
-        <div id="passwordActionParamsDiv">
-          <div class="field h-flex-container">
-            <label>User Name</label>
-            <input type="text" class="input1Box" id="pmUser"/>
-          </div>
-          <div class="field h-flex-container">
-            <label>Password</label>
-            <input type="text" class="input1Box" id="pmPassword"/>
-          </div>
-        </div>
-      </div>
-    </div>
-    <div id="actions">
-    </div>
-  </div>
-  <script src="../common_lib.js"></script>
-  <script src="../constants.js"></script>
-  <script src="panel.js"></script>
-</body>
-</html>
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/content/panel.js b/components/test/data/autofill/automated_integration/action_recorder_extension/content/panel.js
deleted file mode 100644
index d4c608a..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/content/panel.js
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright 2018 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.
-
-document.addEventListener('DOMContentLoaded', () => {
-  const startingURLField = document.getElementById('startingURL');
-  const saveBtn = document.getElementById('saveBtn');
-  const stopBtn = document.getElementById('stopBtn');
-  const cancelBtn = document.getElementById('cancelBtn');
-  const actionsListDiv = document.getElementById('actions');
-
-  // Sets up the 'Add Chrome Action' panel.
-  const newActionTypeSelect = document.getElementById('newActionType');
-  const passwordActionUserParam = document.getElementById('pmUser');
-  const passwordActionPasswordParam = document.getElementById('pmPassword');
-  createNewActionTypeOption('Save Password', 'savePassword');
-  createNewActionTypeOption('Don\'t Save Password', 'rejectSavePassword');
-  createNewActionTypeOption('Update Password', 'updatePassword');
-  createNewActionTypeOption('Don\'t Update Password', 'rejectUpdatePassword');
-  const addChromeAction = document.getElementById('addChromeAction');
-  addChromeAction.addEventListener('click', (event) => {
-    let action = {type: newActionTypeSelect.value};
-
-    switch (newActionTypeSelect.value) {
-      case ActionTypeEnum.SAVE_PASSWORD:
-      case ActionTypeEnum.REJECT_SAVE_PASSWORD:
-      case ActionTypeEnum.UPDATE_PASSWORD:
-      case ActionTypeEnum.REJECT_UPDATE_PASSWORD:
-        action.userName = passwordActionUserParam.value;
-        action.password = passwordActionPasswordParam.value;
-        break;
-      default:
-    }
-
-    return sendRuntimeMessageToBackgroundScript(
-        {type: RecorderMsgEnum.ADD_ACTION, action: action});
-  });
-
-  function createNewActionTypeOption(text, value) {
-    const option = document.createElement('option');
-    option.value = value;
-    option.textContent = text;
-    newActionTypeSelect.appendChild(option);
-  }
-
-  function createActionElement(action) {
-    const actionDiv = document.createElement('div');
-    actionDiv.classList.add('action');
-
-    // The action row.
-    const flexContainerDiv = document.createElement('div');
-    flexContainerDiv.classList.add('h-flex-container');
-    flexContainerDiv.classList.add('tooltip-trigger');
-    const selectorLabel = document.createElement('h4');
-    const actionLabel = document.createElement('h4');
-    const iconBoxDiv = document.createElement('div');
-    iconBoxDiv.classList.add('iconBox');
-    iconBoxDiv.textContent = 'X';
-    iconBoxDiv.addEventListener('click', (event) => {
-      sendRuntimeMessageToBackgroundScript({
-        type: RecorderUiMsgEnum.REMOVE_ACTION,
-        action_index: action.action_index
-      })
-          .then((response) => {
-            if (response) {
-              actionDiv.remove();
-            }
-          })
-          .catch((error) => {
-            console.error('Unable to remove the recorded action!', error);
-          });
-    });
-    flexContainerDiv.appendChild(selectorLabel);
-    flexContainerDiv.appendChild(actionLabel);
-    flexContainerDiv.appendChild(iconBoxDiv);
-
-    // The action detail row.
-    const detailsDiv = document.createElement('div');
-    detailsDiv.classList.add('tooltip-body');
-    const selectorDetailLabel = document.createElement('label');
-    const actionDetailLabel = document.createElement('label');
-    detailsDiv.appendChild(selectorDetailLabel);
-    detailsDiv.appendChild(actionDetailLabel);
-
-    selectorLabel.textContent = action.selector;
-    selectorDetailLabel.textContent = action.selector;
-
-    switch (action.type) {
-      case ActionTypeEnum.AUTOFILL:
-        actionLabel.textContent = 'trigger autofill';
-        actionDetailLabel.textContent = `trigger autofill`;
-        break;
-      case ActionTypeEnum.CLICK:
-        actionLabel.textContent = 'left-click';
-        actionDetailLabel.textContent = `left click element`;
-        break;
-      case ActionTypeEnum.HOVER:
-        actionLabel.textContent = 'hover';
-        actionDetailLabel.textContent = `hover over element`;
-        break;
-      case ActionTypeEnum.LOAD_PAGE:
-        actionLabel.textContent = 'loaded page';
-        actionDetailLabel.textContent = 'loaded a new page';
-        selectorLabel.textContent = action.url;
-        selectorDetailLabel.textContent = action.url;
-        break;
-      case ActionTypeEnum.PRESS_ENTER:
-        actionLabel.textContent = 'enter';
-        actionDetailLabel.textContent = `press enter`;
-        break;
-      case ActionTypeEnum.SELECT:
-        actionLabel.textContent = 'select dropdown option';
-        actionDetailLabel.textContent = `select option ${action.index}`;
-        break;
-      case ActionTypeEnum.TYPE:
-        actionLabel.textContent = 'type';
-        actionDetailLabel.textContent = `type '${action.value}'`;
-        break;
-      case ActionTypeEnum.TYPE_PASSWORD:
-        actionLabel.textContent = 'type password';
-        actionDetailLabel.textContent = `type '${action.value}'`;
-        break;
-      case ActionTypeEnum.VALIDATE_FIELD:
-        actionLabel.textContent = 'validate field';
-        if (action.expectedAutofillType) {
-          actionDetailLabel.textContent = `check that field
-              (${action.expectedAutofillType}) has the value
-              '${action.expectedValue}'`;
-        } else {
-          actionDetailLabel.textContent = `check that field
-              has the value '${action.expectedValue}'`;
-        }
-        break;
-      case ActionTypeEnum.SAVE_PASSWORD:
-        actionLabel.textContent = 'save password';
-        actionDetailLabel.textContent = `save password
-            '${action.password}' for
-            '${action.userName}'`;
-        break;
-      case ActionTypeEnum.REJECT_SAVE_PASSWORD:
-        actionLabel.textContent = 'reject saving password';
-        actionDetailLabel.textContent = `reject saving password
-            '${action.password}' for
-            '${action.userName}'`;
-        break;
-      case ActionTypeEnum.UPDATE_PASSWORD:
-        actionLabel.textContent = 'update password';
-        actionDetailLabel.textContent = `update password
-            '${action.password}' for
-            '${action.userName}'`;
-        break;
-      case ActionTypeEnum.REJECT_UPDATE_PASSWORD:
-        actionLabel.textContent = 'reject updating password';
-        actionDetailLabel.textContent = `reject updating password
-            '${action.password}' for
-            '${action.userName}'`;
-        break;
-      default:
-        actionLabel.textContent = 'unknown';
-        actionDetailLabel.textContent = `unknown action: ${action.type}`;
-    }
-
-    flexContainerDiv.appendChild(detailsDiv);
-    actionDiv.appendChild(flexContainerDiv);
-    return actionDiv;
-  }
-
-  function addAction(action) {
-    actionsListDiv.appendChild(createActionElement(action));
-    // Scroll to the action that the panel just appended.
-    actionsListDiv.scrollTop = actionsListDiv.scrollHeight;
-  }
-
-  function setPasswordEventParams(userName, password) {
-    passwordActionUserParam.value = userName;
-    passwordActionPasswordParam.value = password;
-  }
-
-  saveBtn.addEventListener('click', (event) => {
-    sendRuntimeMessageToBackgroundScript({type: RecorderMsgEnum.SAVE});
-  });
-  stopBtn.addEventListener('click', (event) => {
-    sendRuntimeMessageToBackgroundScript({type: RecorderMsgEnum.STOP});
-  });
-  cancelBtn.addEventListener('click', (event) => {
-    sendRuntimeMessageToBackgroundScript({type: RecorderMsgEnum.CANCEL});
-  });
-
-  chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
-    if (!request) return;
-    switch (request.type) {
-      case RecorderUiMsgEnum.ADD_ACTION:
-        addAction(request.action);
-        sendResponse(true);
-        break;
-      case RecorderUiMsgEnum.SET_PASSWORD_MANAGER_ACTION_PARAMS:
-        setPasswordEventParams(request.userName, request.password);
-        sendResponse(true);
-      default:
-    }
-    return false;
-  });
-
-  // Get the recipe from the background script and render it.
-  sendRuntimeMessageToBackgroundScript({
-    type: RecorderUiMsgEnum.GET_RECIPE
-  }).then((recipe) => {
-    while (actionsListDiv.hasChildNodes()) {
-      actionsListDiv.removeChild(actionsListDiv.lastChild);
-    }
-
-    startingURLField.value = recipe.startingURL;
-
-    for (let index = 0; index < recipe.actions.length; index++) {
-      const action = recipe.actions[index];
-      actionsListDiv.appendChild(createActionElement(action));
-    }
-  });
-
-  // Get the saved event parameters from the background script and
-  // set parameters on the UI.
-  sendRuntimeMessageToBackgroundScript(
-      {type: RecorderUiMsgEnum.GET_SAVED_ACTION_PARAMS})
-      .then((params) => {
-        if (params.passwordManagerParams) {
-          passwordActionUserParam.value = params.passwordManagerParams.userName;
-          passwordActionPasswordParam.value =
-              params.passwordManagerParams.password;
-        }
-      })
-      .catch((error) => {
-        console.error('Unable to obtain saved action parameters!\r\n', error);
-      });
-});
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/ic_error_outline_black_2x_web_24dp.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/ic_error_outline_black_2x_web_24dp.png
deleted file mode 100644
index 63244526..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/ic_error_outline_black_2x_web_24dp.png
+++ /dev/null
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle.svg b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle.svg
deleted file mode 100644
index b232058..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle.svg
+++ /dev/null
@@ -1,338 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   id="svg3039"
-   height="256"
-   width="256"
-   version="1.1">
-  <metadata
-     id="metadata3045">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs3043">
-    <linearGradient
-       id="linearGradient3803">
-      <stop
-         id="stop3805"
-         offset="0"
-         style="stop-color:#d7def0;stop-opacity:1;" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1"
-         offset="0.5"
-         id="stop3811" />
-      <stop
-         id="stop3807"
-         offset="1"
-         style="stop-color:#d5def0;stop-opacity:1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3750">
-      <stop
-         style="stop-color:#d0e2f1;stop-opacity:1"
-         offset="0"
-         id="stop3752" />
-      <stop
-         id="stop3756"
-         offset="0.85580856"
-         style="stop-color:#cadef0;stop-opacity:1" />
-      <stop
-         style="stop-color:#95bee3;stop-opacity:1"
-         offset="1"
-         id="stop3754" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3708">
-      <stop
-         id="stop3710"
-         offset="0"
-         style="stop-color:#658db6;stop-opacity:1" />
-      <stop
-         style="stop-color:#527fab;stop-opacity:1;"
-         offset="0.76777935"
-         id="stop3716" />
-      <stop
-         id="stop3712"
-         offset="1"
-         style="stop-color:#4071a0;stop-opacity:1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3698">
-      <stop
-         id="stop3700"
-         offset="0"
-         style="stop-color:#96d0e1;stop-opacity:1" />
-      <stop
-         style="stop-color:#89b7e1;stop-opacity:1"
-         offset="0.67819428"
-         id="stop3706" />
-      <stop
-         id="stop3702"
-         offset="1"
-         style="stop-color:#699dd3;stop-opacity:1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3588">
-      <stop
-         id="stop3590"
-         offset="0"
-         style="stop-color:#ffffff;stop-opacity:1" />
-      <stop
-         id="stop3592"
-         offset="1"
-         style="stop-color:#000000;stop-opacity:0;" />
-    </linearGradient>
-    <radialGradient
-       gradientTransform="matrix(0.02177942,-0.95743591,0.97872327,0.02221687,-235.0993,5.0684454)"
-       gradientUnits="userSpaceOnUse"
-       r="25.491526"
-       fy="121.49152"
-       fx="-118.77966"
-       cy="121.49152"
-       cx="-118.77966"
-       id="radialGradient3594"
-       xlink:href="#linearGradient3588" />
-    <filter
-       id="filter3374"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3376"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3414"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3416" />
-    </filter>
-    <filter
-       id="filter3378"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3380"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3418"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3420" />
-    </filter>
-    <filter
-       id="filter3382"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3384"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3422"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3424" />
-    </filter>
-    <filter
-       id="filter3386"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3388"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3426"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3428" />
-    </filter>
-    <filter
-       id="filter3390"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3392"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3430"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3432" />
-    </filter>
-    <filter
-       id="filter3394"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3396"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3434"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3436" />
-    </filter>
-    <filter
-       id="filter3398"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3400"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3438"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3440" />
-    </filter>
-    <filter
-       id="filter3402"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3404"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3442"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3444" />
-    </filter>
-    <filter
-       id="filter3406"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3408"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3446"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3448" />
-    </filter>
-    <filter
-       id="filter3410"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3412"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3450"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3452" />
-    </filter>
-    <filter
-       id="filter3402-5"
-       style="color-interpolation-filters:sRGB">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3404-5"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3442-4"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3444-8" />
-    </filter>
-  </defs>
-  <ellipse
-     d="m -92.745764,122.57627 a 25.491526,25.491526 0 1 1 -50.983056,0 25.491526,25.491526 0 1 1 50.983056,0 z"
-     transform="matrix(4.680851,0,0,4.7978723,685.10478,-449.69946)"
-     id="path2814"
-     style="fill:url(#radialGradient3594);fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3374)" />
-  <path
-     id="path3655"
-     d="m 232.17258,88.120422 c 0,15.673918 -19.79135,34.931518 -45.84395,34.931518 -26.0526,0 -59.92241,-16.08123 -59.92241,-31.755152 0,-15.673924 21.11981,-28.38015 47.17241,-28.38015 19.90254,0 46.36122,18.293224 56.45971,20.3521 0.79179,1.710571 1.36862,2.925087 2.13424,4.851684 z"
-     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3378)" />
-  <path
-     id="path3655-4-8"
-     d="m 38.822019,65.971523 c 12.38148,-9.610993 35.314514,-1.245318 51.289554,19.334679 15.975027,20.579998 17.694937,51.065068 5.31349,60.676058 -12.38147,9.61099 -34.17571,-5.29155 -50.15074,-25.87156 -12.20392,-15.72181 -4.05062,-41.19089 -8.61646,-50.430553 0.61589,-1.122052 1.381696,-2.456607 2.164156,-3.708624 z"
-     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3382)" />
-  <path
-     id="path3596"
-     d="m 230.04347,83.261765 c -7.0081,-0.03265 -61.07025,0.289575 -107.66568,0.0654 -17.371,5.108098 -31.704627,13.258827 -39.181777,29.154945 -5.33639,-4.54237 -40.74576,-42.215609 -44.40678,-46.440684 31.38983,-41.648805 74.528017,-45.559321 82.915257,-45.559321 8.38724,0 70.64407,-8.631855 108.33898,62.77966 z"
-     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3386)" />
-  <path
-     id="path3655-4"
-     d="m 117.12454,243.96815 c -12.49835,-9.45851 -14.5752,-36.93927 1.14635,-57.71356 15.72155,-20.77428 41.03582,-34.94753 53.53417,-25.48904 12.49834,9.4585 7.44792,38.96701 -8.27364,59.74129 -12.01027,15.87024 -35.4911,16.88498 -43.22681,23.69505 -1.23894,-0.0455 -1.95523,-0.0605 -3.18007,-0.23374 z"
-     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3390)" />
-  <path
-     id="path3596-1"
-     d="m 120.3032,244.20103 c 3.58354,-6.02268 28.85859,-52.8991 52.69131,-92.9389 4.41104,-17.56095 5.34663,-33.64185 -4.5584,-48.14993 6.62173,-2.29412 58.23852,-13.976353 63.73684,-14.987686 19.9656,48.180076 1.44992,87.338276 -2.80522,94.565966 -4.25515,7.22768 -28.40179,65.25666 -109.06453,61.51055 z"
-     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3394)" />
-  <path
-     id="path3596-1-7"
-     d="m 36.696853,69.642524 c 3.46858,6.089612 30.72312,52.780196 53.77852,93.272576 13.094367,12.50527 27.684997,19.48512 45.191737,18.03328 -1.2738,6.89113 -16.62898,57.75037 -18.4638,63.03126 -51.756237,-6.42158 -76.669777,-41.85476 -80.854757,-49.1233 -4.18497,-7.26855 -42.7297502,-56.91452 0.3483,-125.213816 z"
-     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3398)" />
-  <path
-     id="path3645"
-     d="m -338.44068,101.42373 c 0,32.65032 -26.46832,59.11864 -59.11865,59.11864 -32.65032,0 -59.11864,-26.46832 -59.11864,-59.11864 0,-32.650327 26.46832,-59.118646 59.11864,-59.118646 32.65033,0 59.11865,26.468319 59.11865,59.118646 z"
-     style="fill:#f3f3f3;fill-opacity:1;stroke:#ffffff;stroke-width:10.07013607;stroke-miterlimit:4;stroke-opacity:1;filter:url(#filter3402)"
-     transform="matrix(0.77294737,0,0,0.77619098,435.90647,53.275706)" />
-  <path
-     id="rect3782"
-     d="m 163.54619,108.89582 c 18.52979,17.09836 16.03302,29.55794 10.0625,44 -3.10892,-22.25001 -2.34478,-32.42697 -10.0625,-44 z"
-     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3406)" />
-  <path
-     id="rect3782-4"
-     d="m 101.42092,173.63924 c -22.645593,-14.47335 -29.809884,-45.71983 -8.813354,-62.99032 -10.847561,19.77514 -6.225429,32.39863 8.813354,62.99032 z"
-     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3410)" />
-</svg>
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle128.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle128.png
deleted file mode 100644
index dfbf8ab..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle128.png
+++ /dev/null
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle16.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle16.png
deleted file mode 100644
index 4f8cc06..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle16.png
+++ /dev/null
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle32.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle32.png
deleted file mode 100644
index 09177112..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle32.png
+++ /dev/null
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle48.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle48.png
deleted file mode 100644
index 8ea7d383..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_idle48.png
+++ /dev/null
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording.svg b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording.svg
deleted file mode 100644
index 18c112c..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording.svg
+++ /dev/null
@@ -1,338 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   id="svg3039"
-   height="256"
-   width="256"
-   version="1.1">
-  <metadata
-     id="metadata3045">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs3043">
-    <linearGradient
-       id="linearGradient3803">
-      <stop
-         id="stop3805"
-         offset="0"
-         style="stop-color:#d7def0;stop-opacity:1;" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1"
-         offset="0.5"
-         id="stop3811" />
-      <stop
-         id="stop3807"
-         offset="1"
-         style="stop-color:#d5def0;stop-opacity:1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3750">
-      <stop
-         style="stop-color:#d0e2f1;stop-opacity:1"
-         offset="0"
-         id="stop3752" />
-      <stop
-         id="stop3756"
-         offset="0.85580856"
-         style="stop-color:#cadef0;stop-opacity:1" />
-      <stop
-         style="stop-color:#95bee3;stop-opacity:1"
-         offset="1"
-         id="stop3754" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3708">
-      <stop
-         id="stop3710"
-         offset="0"
-         style="stop-color:#658db6;stop-opacity:1" />
-      <stop
-         style="stop-color:#527fab;stop-opacity:1;"
-         offset="0.76777935"
-         id="stop3716" />
-      <stop
-         id="stop3712"
-         offset="1"
-         style="stop-color:#4071a0;stop-opacity:1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3698">
-      <stop
-         id="stop3700"
-         offset="0"
-         style="stop-color:#96d0e1;stop-opacity:1" />
-      <stop
-         style="stop-color:#89b7e1;stop-opacity:1"
-         offset="0.67819428"
-         id="stop3706" />
-      <stop
-         id="stop3702"
-         offset="1"
-         style="stop-color:#699dd3;stop-opacity:1" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient3588">
-      <stop
-         id="stop3590"
-         offset="0"
-         style="stop-color:#ffffff;stop-opacity:1" />
-      <stop
-         id="stop3592"
-         offset="1"
-         style="stop-color:#000000;stop-opacity:0;" />
-    </linearGradient>
-    <radialGradient
-       gradientTransform="matrix(0.02177942,-0.95743591,0.97872327,0.02221687,-235.0993,5.0684454)"
-       gradientUnits="userSpaceOnUse"
-       r="25.491526"
-       fy="121.49152"
-       fx="-118.77966"
-       cy="121.49152"
-       cx="-118.77966"
-       id="radialGradient3594"
-       xlink:href="#linearGradient3588" />
-    <filter
-       id="filter3374"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3376"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3414"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3416" />
-    </filter>
-    <filter
-       id="filter3378"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3380"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3418"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3420" />
-    </filter>
-    <filter
-       id="filter3382"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3384"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3422"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3424" />
-    </filter>
-    <filter
-       id="filter3386"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3388"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3426"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3428" />
-    </filter>
-    <filter
-       id="filter3390"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3392"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3430"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3432" />
-    </filter>
-    <filter
-       id="filter3394"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3396"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3434"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3436" />
-    </filter>
-    <filter
-       id="filter3398"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3400"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3438"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3440" />
-    </filter>
-    <filter
-       id="filter3402"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3404"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3442"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3444" />
-    </filter>
-    <filter
-       id="filter3406"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3408"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3446"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3448" />
-    </filter>
-    <filter
-       id="filter3410"
-       style="color-interpolation-filters:sRGB;">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3412"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3450"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3452" />
-    </filter>
-    <filter
-       id="filter3402-5"
-       style="color-interpolation-filters:sRGB">
-      <feColorMatrix
-         result="fbSourceGraphic"
-         id="feColorMatrix3404-5"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 " />
-      <feColorMatrix
-         id="feColorMatrix3442-4"
-         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
-         in="fbSourceGraphic"
-         result="fbSourceGraphicAlpha" />
-      <feColorMatrix
-         in="fbSourceGraphic"
-         values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "
-         id="feColorMatrix3444-8" />
-    </filter>
-  </defs>
-  <circle
-     d="m -92.745764,122.57627 a 25.491526,25.491526 0 1 1 -50.983056,0 25.491526,25.491526 0 1 1 50.983056,0 z"
-     transform="matrix(4.680851,0,0,4.7978723,685.10478,-449.69946)"
-     id="path2814"
-     style="fill:url(#radialGradient3594);fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3374)" />
-  <path
-     id="path3655"
-     d="m 232.17258,88.120422 c 0,15.673918 -19.79135,34.931518 -45.84395,34.931518 -26.0526,0 -59.92241,-16.08123 -59.92241,-31.755152 0,-15.673924 21.11981,-28.38015 47.17241,-28.38015 19.90254,0 46.36122,18.293224 56.45971,20.3521 0.79179,1.710571 1.36862,2.925087 2.13424,4.851684 z"
-     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3378)" />
-  <path
-     id="path3655-4-8"
-     d="m 38.822019,65.971523 c 12.38148,-9.610993 35.314514,-1.245318 51.289554,19.334679 15.975027,20.579998 17.694937,51.065068 5.31349,60.676058 -12.38147,9.61099 -34.17571,-5.29155 -50.15074,-25.87156 -12.20392,-15.72181 -4.05062,-41.19089 -8.61646,-50.430553 0.61589,-1.122052 1.381696,-2.456607 2.164156,-3.708624 z"
-     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3382)" />
-  <path
-     id="path3596"
-     d="m 230.04347,83.261765 c -7.0081,-0.03265 -61.07025,0.289575 -107.66568,0.0654 -17.371,5.108098 -31.704627,13.258827 -39.181777,29.154945 -5.33639,-4.54237 -40.74576,-42.215609 -44.40678,-46.440684 31.38983,-41.648805 74.528017,-45.559321 82.915257,-45.559321 8.38724,0 70.64407,-8.631855 108.33898,62.77966 z"
-     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3386)" />
-  <path
-     id="path3655-4"
-     d="m 117.12454,243.96815 c -12.49835,-9.45851 -14.5752,-36.93927 1.14635,-57.71356 15.72155,-20.77428 41.03582,-34.94753 53.53417,-25.48904 12.49834,9.4585 7.44792,38.96701 -8.27364,59.74129 -12.01027,15.87024 -35.4911,16.88498 -43.22681,23.69505 -1.23894,-0.0455 -1.95523,-0.0605 -3.18007,-0.23374 z"
-     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3390)" />
-  <path
-     id="path3596-1"
-     d="m 120.3032,244.20103 c 3.58354,-6.02268 28.85859,-52.8991 52.69131,-92.9389 4.41104,-17.56095 5.34663,-33.64185 -4.5584,-48.14993 6.62173,-2.29412 58.23852,-13.976353 63.73684,-14.987686 19.9656,48.180076 1.44992,87.338276 -2.80522,94.565966 -4.25515,7.22768 -28.40179,65.25666 -109.06453,61.51055 z"
-     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3394)" />
-  <path
-     id="path3596-1-7"
-     d="m 36.696853,69.642524 c 3.46858,6.089612 30.72312,52.780196 53.77852,93.272576 13.094367,12.50527 27.684997,19.48512 45.191737,18.03328 -1.2738,6.89113 -16.62898,57.75037 -18.4638,63.03126 -51.756237,-6.42158 -76.669777,-41.85476 -80.854757,-49.1233 -4.18497,-7.26855 -42.7297502,-56.91452 0.3483,-125.213816 z"
-     style="fill:#b9b9b9;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3398)" />
-  <path
-     id="path3645"
-     d="m -338.44068,101.42373 c 0,32.65032 -26.46832,59.11864 -59.11865,59.11864 -32.65032,0 -59.11864,-26.46832 -59.11864,-59.11864 0,-32.650327 26.46832,-59.118646 59.11864,-59.118646 32.65033,0 59.11865,26.468319 59.11865,59.118646 z"
-     style="fill:#fa4e4e;fill-opacity:0.98431373;stroke:#ffffff;stroke-width:10.07013607;stroke-miterlimit:4;stroke-opacity:1"
-     transform="matrix(0.77294737,0,0,0.77619098,435.90647,53.275706)" />
-  <path
-     id="rect3782"
-     d="m 163.54619,108.89582 c 18.52979,17.09836 16.03302,29.55794 10.0625,44 -3.10892,-22.25001 -2.34478,-32.42697 -10.0625,-44 z"
-     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3406)" />
-  <path
-     id="rect3782-4"
-     d="m 101.42092,173.63924 c -22.645593,-14.47335 -29.809884,-45.71983 -8.813354,-62.99032 -10.847561,19.77514 -6.225429,32.39863 8.813354,62.99032 z"
-     style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3410)" />
-</svg>
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording128.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording128.png
deleted file mode 100644
index cdf17c6..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording128.png
+++ /dev/null
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording16.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording16.png
deleted file mode 100644
index 7b6d52d0..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording16.png
+++ /dev/null
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording32.png b/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording32.png
deleted file mode 100644
index 7450fe02..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/icons/icon_recording32.png
+++ /dev/null
Binary files differ
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/manifest.json b/components/test/data/autofill/automated_integration/action_recorder_extension/manifest.json
deleted file mode 100644
index 19360405..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/manifest.json
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2018 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.
-
-{
-  "manifest_version": 2,
-
-  "name": "Action Recorder Extension",
-  "description": "Extension to record user actions and generate automated test recipes.",
-  "version": "2.0.0",
-  "minimum_chrome_version": "66",
-
-  "icons": {
-    "16": "icons/icon_idle16.png",
-    "48": "icons/icon_idle48.png",
-    "128": "icons/icon_idle128.png"
-  },
-
-  "browser_action": {
-    "default_icon": {
-      "16": "icons/icon_idle16.png",
-      "32": "icons/icon_idle32.png"
-    },
-    "default_title": "Action Recorder (Idle)"
-  },
-  "background": {
-    "scripts": [
-      "background/background.js",
-      "common_lib.js",
-      "constants.js"
-    ]
-  },
-  "content_scripts":
-    [{
-      "js": [
-        "common_lib.js",
-        "constants.js",
-        "content/action_handler.js"
-      ],
-      "matches": ["<all_urls>"],
-      // The extension should inject the action recorder script into all
-      // frames, so that the extension can record user actions on any frame,
-      // be it the main document or its iframes.
-      "all_frames": true
-    }, {
-      "js": [
-        "content/foreground.js"
-      ],
-      "matches": ["<all_urls>"]
-    }],
-  "web_accessible_resources": [
-    // panel.html contains the extension's action recorder UI.
-    "content/panel.html"
-  ],
-  "permissions": [
-    // The "browsingData" permission allows the extension to clear the browser
-    // cache at the start and the end of a web page capture session. The action
-    // recorder extension will be integrated with web page capture at a future
-    // date. To capture a webpage, the browser must download all of the page's
-    // resources from the web. In other words, the browser cannot reach out
-    // to the browser's local cache for resources. Therefore the extension must
-    // clear the browser cache before starting a web page capture.
-    "browsingData",
-    // The "downloads" permission allows the extension to download the recorded
-    // action recipe as a file.
-    "downloads",
-    // The "notifications" permission allows the extension to alert the user
-    // when the extension malfunctions.
-    "notifications",
-    // The "storage" permission allows the extension to access local storage.
-    // The extension uses non-persistent background scripts, meaning that the
-    // extension executes the background scripts only in response to user
-    // actions. When there is no user action, the extension unloads the
-    // background scripts. Non-persistent background scripts cannot persist
-    // local JavaScript variables between two different user actions. Instead,
-    // the extension persists any variables the background script needs inside
-    // local storage.
-    "storage",
-    // The "tabs" permission allows the extension to query for tab information.
-    // When the user starts an action recording session, the extension needs
-    // to access the current active tab, and obtain the following information:
-    // * The extension records the active tab's URL as the start point of the
-    //   recorded action recipe.
-    // * The extension records the active tab's title as the title of the
-    //   recorded action recipe.
-    "tabs",
-    // The "webNavigation" permission allows the extension to perform the
-    // following tasks:
-    // * Query for a list of all the frames in a web page. When the user starts
-    //   a recording session, the extension needs to send a 'start-recording'
-    //   message to each frame inside the target tab.
-    // * Query for a frame's url and parent frame Id. When the user interacts
-    //   with an element inside an iframe, the extension needs to record a
-    //   path from the tab's root frame to the iframe that the user is
-    //   interacting with. The extension derives this path by traversing a
-    //   frames's ancestors.
-    // * Receive notifications when a frame completed navigation. During a
-    //   recording session, the user can trigger a new page load in the
-    //   target tab, or an iframe inside the target tab. Once the tab or iframe
-    //   finishes loading, the extension needs to send a message to the tab or
-    //   iframe to resume recording.
-    "webNavigation"
-  ]
-}
\ No newline at end of file
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.html b/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.html
deleted file mode 100644
index bba14a49..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!doctype html>
-<html>
-  <head>
-    <title>Action Recorder Extension</title>
-    <style>
-    body {
-      overflow: hidden;
-      margin: 0px;
-      padding: 0px;
-      background: white;
-    }
-    div:first-child {
-      margin-top: 0px;
-    }
-    div {
-      cursor: pointer;
-      text-align: center;
-      padding: 5px;
-      font-family: sans-serif;
-      font-size: 1em;
-      width: 100px;
-      margin-top: 1px;
-      background: #f5f5f5;
-      border: #c8c8c8 1px solid;
-    }
-    div:hover {
-      background: #e8e8e8;
-    }
-    .hidden {
-      display: none;
-    }
-    </style>
-  </head>
-  <body>
-    <div id="start" class="hidden">Start</div>
-    <div id="next-site" class="hidden">Next Site</div>
-    <div id="stop" class="hidden">Stop &amp; Copy</div>
-    <div id="cancel" class="hidden">Cancel</div>
-    <script src="popup.js"></script>
-  </body>
-</html>
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.js b/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.js
deleted file mode 100644
index 3f4fb71..0000000
--- a/components/test/data/autofill/automated_integration/action_recorder_extension/popup/popup.js
+++ /dev/null
@@ -1,136 +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.
-
-'use strict';
-
-class PopupController {
-  constructor() {
-    this._startButton = document.getElementById('start');
-    this._nextSiteButton = document.getElementById('next-site');
-    this._stopButton = document.getElementById('stop');
-    this._cancelButton = document.getElementById('cancel');
-
-    this._startListeners();
-    this._getRecordingState();
-  }
-
-  startRecording() {
-    chrome.runtime.sendMessage({
-        type: 'start-recording'
-      },
-      (response) => this._handleRecordingResponse(response));
-  }
-
-  stopRecording() {
-    chrome.runtime.sendMessage({
-        type: 'stop-recording'
-      },
-      (response) => this._handleRecordingResponse(response));
-  }
-
-  cancelRecording() {
-    chrome.runtime.sendMessage({
-        type: 'cancel-recording'
-      },
-      (response) => this._handleRecordingResponse(response));
-  }
-
-  nextSite() {
-    chrome.runtime.sendMessage({
-      type: 'next-site'
-    });
-  }
-
-  _getRecordingState() {
-    chrome.runtime.sendMessage({
-        type: 'recording-state-request'
-      },
-      (response) => this._handleRecordingResponse(response));
-  }
-
-  _handleRecordingResponse(response) {
-    if (!response) {
-      return;
-    }
-
-    this._setRecordingState(!!response.isRecording);
-  }
-
-  _startListeners() {
-    this._startButton.addEventListener(
-      'click', (event) => {
-        this.startRecording();
-      });
-
-    this._stopButton.addEventListener(
-      'click', (event) => {
-        this.stopRecording();
-      });
-
-    this._cancelButton.addEventListener(
-      'click', (event) => {
-        this.cancelRecording();
-      });
-
-    this._nextSiteButton.addEventListener(
-      'click', (event) => {
-        this.nextSite();
-      });
-  }
-
-  _setRecordingState(isRecording) {
-    this._isRecording = isRecording;
-    this._updateStyling();
-  }
-
-  _updateStyling() {
-    let shownButton1, shownButton2, hiddenButton1, hiddenButton2;
-
-    if (this._isRecording) {
-      shownButton1 = this._stopButton;
-      shownButton2 = this._cancelButton;
-      hiddenButton1 = this._startButton;
-      hiddenButton2 = this._nextSiteButton;
-    } else {
-      shownButton1 = this._startButton;
-      shownButton2 = this._nextSiteButton;
-      hiddenButton1 = this._stopButton;
-      hiddenButton2 = this._cancelButton;
-    }
-
-    this._removeClass(shownButton1, 'hidden');
-    this._removeClass(shownButton2, 'hidden');
-    this._applyClass(hiddenButton1, 'hidden');
-    this._applyClass(hiddenButton2, 'hidden');
-
-    chrome.browserAction.setIcon({
-      path: this._getIconUrl()
-    });
-  }
-
-
-  _removeClass(element, className) {
-    if (element.classList.contains(className)) {
-      element.classList.remove(className);
-    }
-  }
-
-  _applyClass(element, className) {
-    element.classList.add(className);
-  }
-
-  _getIconUrl() {
-    const iconUrlPrefix = '../icons/icon_' +
-      (this._isRecording ? 'recording' : 'idle');
-
-    return {
-      '16': iconUrlPrefix + '16.png',
-      '32': iconUrlPrefix + '32.png'
-    };
-  }
-}
-
-document.addEventListener('DOMContentLoaded', function() {
-  const popupController = new PopupController();
-});
diff --git a/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_bad_cert_popup.Pixel_XL-25.png.sha1 b/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_bad_cert_popup.Pixel_XL-25.png.sha1
index d69ac12..6f889f2d 100644
--- a/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_bad_cert_popup.Pixel_XL-25.png.sha1
+++ b/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_bad_cert_popup.Pixel_XL-25.png.sha1
@@ -1 +1 @@
-43ee9975eb933c684d4608c2a6852e69c433d45c
\ No newline at end of file
+1cb9e7b549ee40a26d20bc8b9e28f5a7a9248440
\ No newline at end of file
diff --git a/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_bad_cert_popup.Pixel_XL-26.png.sha1 b/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_bad_cert_popup.Pixel_XL-26.png.sha1
index 9b6da7f..1657c26f 100644
--- a/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_bad_cert_popup.Pixel_XL-26.png.sha1
+++ b/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_bad_cert_popup.Pixel_XL-26.png.sha1
@@ -1 +1 @@
-15c6c3a2524a6ff05f9361bc8c7c4c267f913098
\ No newline at end of file
+b02278e520c41cdd3ccf52d66c13d8eb1a90ca56
\ No newline at end of file
diff --git a/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_popup.Pixel_XL-25.png.sha1 b/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_popup.Pixel_XL-25.png.sha1
index 870d216..92207877 100644
--- a/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_popup.Pixel_XL-25.png.sha1
+++ b/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_popup.Pixel_XL-25.png.sha1
@@ -1 +1 @@
-c14ee554d3f0afd15b1e3bb33730fd26347e7062
\ No newline at end of file
+cb341266df169a673ea23f202a2ef4051b08994d
\ No newline at end of file
diff --git a/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_popup.Pixel_XL-26.png.sha1 b/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_popup.Pixel_XL-26.png.sha1
index 89c15bee..e070c14d 100644
--- a/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_popup.Pixel_XL-26.png.sha1
+++ b/components/test/data/vr_browser_ui/render_tests/VrBrowserNativeUiTest.security_token_https_popup.Pixel_XL-26.png.sha1
@@ -1 +1 @@
-971c391fabde3702fe093d5d4b874dda06b2c693
\ No newline at end of file
+f8946d5df09e9bb9c7344427f21965deeba9451a
\ No newline at end of file
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 90ac8741..89d1184 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -202,6 +202,8 @@
     "traced_value.cc",
     "traced_value.h",
     "viz_common_export.h",
+    "viz_utils.cc",
+    "viz_utils.h",
   ]
 
   deps = [
diff --git a/components/viz/common/viz_utils.cc b/components/viz/common/viz_utils.cc
new file mode 100644
index 0000000..cf216d60
--- /dev/null
+++ b/components/viz/common/viz_utils.cc
@@ -0,0 +1,19 @@
+// Copyright 2019 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/common/viz_utils.h"
+
+#include "base/system/sys_info.h"
+#include "build/build_config.h"
+
+namespace viz {
+
+bool PreferRGB565ResourcesForDisplay() {
+#if defined(OS_ANDROID)
+  return base::SysInfo::AmountOfPhysicalMemoryMB() <= 512;
+#endif
+  return false;
+}
+
+}  // namespace viz
diff --git a/components/viz/common/viz_utils.h b/components/viz/common/viz_utils.h
new file mode 100644
index 0000000..f8406511
--- /dev/null
+++ b/components/viz/common/viz_utils.h
@@ -0,0 +1,16 @@
+// Copyright 2019 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_COMMON_VIZ_UTILS_H_
+#define COMPONENTS_VIZ_COMMON_VIZ_UTILS_H_
+
+#include "components/viz/common/viz_common_export.h"
+
+namespace viz {
+
+VIZ_COMMON_EXPORT bool PreferRGB565ResourcesForDisplay();
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_COMMON_VIZ_UTILS_H_
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index 3d9e2f5d..7675a94 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -818,7 +818,7 @@
     default:
       // If we've reached here, the quad's type hasn't been updated to be
       // batch aware yet.
-      DoSingleDrawQuad(quad, draw_region);
+      DoSingleDrawQuad(quad, draw_region, params);
       break;
   }
 }
@@ -1329,7 +1329,8 @@
 }
 
 void SkiaRenderer::DoSingleDrawQuad(const DrawQuad* quad,
-                                    const gfx::QuadF* draw_region) {
+                                    const gfx::QuadF* draw_region,
+                                    const DrawQuadParams& params) {
   base::Optional<SkAutoCanvasRestore> auto_canvas_restore;
   const gfx::Rect* scissor_rect =
       is_scissor_enabled_ ? &scissor_rect_ : nullptr;
@@ -1341,23 +1342,7 @@
                             draw_region, scissor_rect, rounded_corner_bounds,
                             &auto_canvas_restore);
 
-  SkPaint paint;
-  if (settings_->force_antialiasing ||
-      !IsScaleAndIntegerTranslate(current_canvas_->getTotalMatrix())) {
-    // TODO(danakj): Until we can enable AA only on exterior edges of the
-    // layer, disable AA if any interior edges are present. crbug.com/248175
-    bool all_four_edges_are_exterior =
-        quad->IsTopEdge() && quad->IsLeftEdge() && quad->IsBottomEdge() &&
-        quad->IsRightEdge();
-    if (settings_->allow_antialiasing &&
-        (settings_->force_antialiasing || all_four_edges_are_exterior))
-      paint.setAntiAlias(true);
-    paint.setFilterQuality(kLow_SkFilterQuality);
-  }
-
-  paint.setAlpha(quad->shared_quad_state->opacity * 255);
-  paint.setBlendMode(
-      static_cast<SkBlendMode>(quad->shared_quad_state->blend_mode));
+  SkPaint paint = params.paint();
 
   switch (quad->material) {
     case DrawQuad::DEBUG_BORDER:
@@ -1557,14 +1542,6 @@
 void SkiaRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad,
                                       SkPaint* paint) {
   DCHECK(paint);
-  // The flag |force_anti_aliasing_off| is also expected to disable alpha
-  // blending, so switch from kSrcOver blending to kSrc.
-  if (quad->force_anti_aliasing_off) {
-    paint->setAntiAlias(false);
-    if (paint->isSrcOver()) {
-      paint->setBlendMode(SkBlendMode::kSrc);
-    }
-  }
   auto bypass = render_pass_bypass_quads_.find(quad->render_pass_id);
   // When Render Pass has a single quad inside we would draw that directly.
   if (bypass != render_pass_bypass_quads_.end()) {
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h
index 0f0c529..465e515 100644
--- a/components/viz/service/display/skia_renderer.h
+++ b/components/viz/service/display/skia_renderer.h
@@ -103,7 +103,9 @@
   // old implementation of DoDrawQuad and types will be migrated individually
   // to the new system and handled directly in the new DoDrawQuad definition,
   // after which this function can be removed.
-  void DoSingleDrawQuad(const DrawQuad* quad, const gfx::QuadF* draw_region);
+  void DoSingleDrawQuad(const DrawQuad* quad,
+                        const gfx::QuadF* draw_region,
+                        const DrawQuadParams& params);
 
   void PrepareCanvasForDrawQuads(
       gfx::Transform quad_to_target_transform,
diff --git a/components/viz/service/display_embedder/skia_output_device.cc b/components/viz/service/display_embedder/skia_output_device.cc
index 2a3c81ee..f32281d3 100644
--- a/components/viz/service/display_embedder/skia_output_device.cc
+++ b/components/viz/service/display_embedder/skia_output_device.cc
@@ -17,10 +17,6 @@
 
 SkiaOutputDevice::~SkiaOutputDevice() = default;
 
-bool SkiaOutputDevice::SupportPostSubBuffer() {
-  return false;
-}
-
 gfx::SwapResponse SkiaOutputDevice::PostSubBuffer(
     const gfx::Rect& rect,
     BufferPresentedCallback feedback) {
@@ -62,4 +58,7 @@
   return response;
 }
 
+void SkiaOutputDevice::EnsureBackbuffer() {}
+void SkiaOutputDevice::DiscardBackbuffer() {}
+
 }  // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device.h b/components/viz/service/display_embedder/skia_output_device.h
index 0f5620c..1165856da 100644
--- a/components/viz/service/display_embedder/skia_output_device.h
+++ b/components/viz/service/display_embedder/skia_output_device.h
@@ -8,6 +8,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/optional.h"
+#include "components/viz/service/display/output_surface.h"
 #include "gpu/command_buffer/common/swap_buffers_complete_params.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 #include "ui/gfx/swap_result.h"
@@ -45,17 +46,24 @@
 
   // Presents DrawSurface.
   virtual gfx::SwapResponse SwapBuffers(BufferPresentedCallback feedback) = 0;
-
-  virtual bool SupportPostSubBuffer();
-
   virtual gfx::SwapResponse PostSubBuffer(const gfx::Rect& rect,
                                           BufferPresentedCallback feedback);
+  const OutputSurface::Capabilities& capabilities() const {
+    return capabilities_;
+  }
+
+  // EnsureBackbuffer called when output surface is visible and may be drawn to.
+  // DiscardBackbuffer called when output surface is hidden and will not be
+  // drawn to. Default no-op.
+  virtual void EnsureBackbuffer();
+  virtual void DiscardBackbuffer();
 
  protected:
   void StartSwapBuffers(base::Optional<BufferPresentedCallback> feedback);
   gfx::SwapResponse FinishSwapBuffers(gfx::SwapResult result);
 
   sk_sp<SkSurface> draw_surface_;
+  OutputSurface::Capabilities capabilities_;
 
  private:
   uint64_t swap_id_ = 0;
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.cc b/components/viz/service/display_embedder/skia_output_device_gl.cc
index 17e151c..b3d28283 100644
--- a/components/viz/service/display_embedder/skia_output_device_gl.cc
+++ b/components/viz/service/display_embedder/skia_output_device_gl.cc
@@ -43,31 +43,26 @@
   gl::CurrentGL* current_gl = gl_context->GetCurrentGL();
   DCHECK(current_gl);
 
-  // Get alpha and stencil bits from the default frame buffer.
+  // Get alpha bits from the default frame buffer.
   glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
   gr_context_->resetContext(kRenderTarget_GrGLBackendState);
   const auto* version = current_gl->Version;
-  GLint stencil_bits = 0;
   GLint alpha_bits = 0;
   if (version->is_desktop_core_profile) {
     glGetFramebufferAttachmentParameterivEXT(
-        GL_FRAMEBUFFER, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
-        &stencil_bits);
-    glGetFramebufferAttachmentParameterivEXT(
         GL_FRAMEBUFFER, GL_BACK_LEFT, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
         &alpha_bits);
   } else {
-    glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
     glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
   }
   CHECK_GL_ERROR();
-  supports_stencil_ = stencil_bits > 0;
   supports_alpha_ = alpha_bits > 0;
 
-  supports_post_sub_buffer_ = gl_surface_->SupportsPostSubBuffer();
+  capabilities_.flipped_output_surface = gl_surface_->FlipsVertically();
+  capabilities_.supports_post_sub_buffer = gl_surface_->SupportsPostSubBuffer();
   if (feature_info_->workarounds()
           .disable_post_sub_buffers_for_onscreen_surfaces)
-    supports_post_sub_buffer_ = false;
+    capabilities_.supports_post_sub_buffer = false;
 }
 
 SkiaOutputDeviceGL::~SkiaOutputDeviceGL() {}
@@ -115,10 +110,6 @@
   return FinishSwapBuffers(gl_surface_->SwapBuffers(std::move(feedback)));
 }
 
-bool SkiaOutputDeviceGL::SupportPostSubBuffer() {
-  return supports_post_sub_buffer_;
-}
-
 gfx::SwapResponse SkiaOutputDeviceGL::PostSubBuffer(
     const gfx::Rect& rect,
     BufferPresentedCallback feedback) {
@@ -128,4 +119,12 @@
       rect.x(), rect.y(), rect.width(), rect.height(), std::move(feedback)));
 }
 
+void SkiaOutputDeviceGL::EnsureBackbuffer() {
+  gl_surface_->SetBackbufferAllocation(true);
+}
+
+void SkiaOutputDeviceGL::DiscardBackbuffer() {
+  gl_surface_->SetBackbufferAllocation(false);
+}
+
 }  // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.h b/components/viz/service/display_embedder/skia_output_device_gl.h
index 7740f31..9d5f9941d 100644
--- a/components/viz/service/display_embedder/skia_output_device_gl.h
+++ b/components/viz/service/display_embedder/skia_output_device_gl.h
@@ -42,10 +42,6 @@
     DCHECK(gr_context_);
     return supports_alpha_;
   }
-  bool supports_stencil() {
-    DCHECK(gr_context_);
-    return supports_stencil_;
-  }
 
   // SkiaOutputDevice implementation:
   void Reshape(const gfx::Size& size,
@@ -53,9 +49,10 @@
                const gfx::ColorSpace& color_space,
                bool has_alpha) override;
   gfx::SwapResponse SwapBuffers(BufferPresentedCallback feedback) override;
-  bool SupportPostSubBuffer() override;
   gfx::SwapResponse PostSubBuffer(const gfx::Rect& rect,
                                   BufferPresentedCallback feedback) override;
+  void EnsureBackbuffer() override;
+  void DiscardBackbuffer() override;
 
  private:
   const gpu::SurfaceHandle surface_handle_;
@@ -64,11 +61,8 @@
 
   GrContext* gr_context_ = nullptr;
   scoped_refptr<gl::GLSurface> gl_surface_;
-  sk_sp<SkSurface> sk_surface_;
 
   bool supports_alpha_ = false;
-  bool supports_stencil_ = false;
-  bool supports_post_sub_buffer_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(SkiaOutputDeviceGL);
 };
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.cc b/components/viz/service/display_embedder/skia_output_device_offscreen.cc
index db50ec3..e976bb2 100644
--- a/components/viz/service/display_embedder/skia_output_device_offscreen.cc
+++ b/components/viz/service/display_embedder/skia_output_device_offscreen.cc
@@ -17,8 +17,10 @@
     DidSwapBufferCompleteCallback did_swap_buffer_complete_callback)
     : SkiaOutputDevice(did_swap_buffer_complete_callback),
       gr_context_(gr_context),
-      flipped_(flipped),
-      has_alpha_(has_alpha) {}
+      has_alpha_(has_alpha) {
+  capabilities_.flipped_output_surface = flipped;
+  capabilities_.supports_post_sub_buffer = true;
+}
 
 SkiaOutputDeviceOffscreen::~SkiaOutputDeviceOffscreen() = default;
 
@@ -26,16 +28,23 @@
                                         float device_scale_factor,
                                         const gfx::ColorSpace& color_space,
                                         bool has_alpha) {
-  auto image_info = SkImageInfo::Make(
+  image_info_ = SkImageInfo::Make(
       size.width(), size.height(),
       has_alpha_ ? kRGBA_8888_SkColorType : kRGB_888x_SkColorType,
       has_alpha_ ? kPremul_SkAlphaType : kOpaque_SkAlphaType);
   draw_surface_ = SkSurface::MakeRenderTarget(
-      gr_context_, SkBudgeted::kNo, image_info, 0 /* sampleCount */,
-      flipped_ ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin,
+      gr_context_, SkBudgeted::kNo, image_info_, 0 /* sampleCount */,
+      capabilities_.flipped_output_surface ? kTopLeft_GrSurfaceOrigin
+                                           : kBottomLeft_GrSurfaceOrigin,
       nullptr /* surfaceProps */);
 }
 
+gfx::SwapResponse SkiaOutputDeviceOffscreen::PostSubBuffer(
+    const gfx::Rect& rect,
+    BufferPresentedCallback feedback) {
+  return SwapBuffers(std::move(feedback));
+}
+
 gfx::SwapResponse SkiaOutputDeviceOffscreen::SwapBuffers(
     BufferPresentedCallback feedback) {
   // Reshape should have been called first.
@@ -45,4 +54,18 @@
   return FinishSwapBuffers(gfx::SwapResult::SWAP_ACK);
 }
 
+void SkiaOutputDeviceOffscreen::EnsureBackbuffer() {
+  if (!image_info_.isEmpty() && !draw_surface_) {
+    draw_surface_ = SkSurface::MakeRenderTarget(
+        gr_context_, SkBudgeted::kNo, image_info_, 0 /* sampleCount */,
+        capabilities_.flipped_output_surface ? kTopLeft_GrSurfaceOrigin
+                                             : kBottomLeft_GrSurfaceOrigin,
+        nullptr /* surfaceProps */);
+  }
+}
+
+void SkiaOutputDeviceOffscreen::DiscardBackbuffer() {
+  draw_surface_.reset();
+}
+
 }  // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.h b/components/viz/service/display_embedder/skia_output_device_offscreen.h
index e3e77671..fbec9fbb9 100644
--- a/components/viz/service/display_embedder/skia_output_device_offscreen.h
+++ b/components/viz/service/display_embedder/skia_output_device_offscreen.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "components/viz/service/display_embedder/skia_output_device.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
 
 class GrContext;
 
@@ -27,13 +28,18 @@
                const gfx::ColorSpace& color_space,
                bool has_alpha) override;
   gfx::SwapResponse SwapBuffers(BufferPresentedCallback feedback) override;
+  gfx::SwapResponse PostSubBuffer(const gfx::Rect& rect,
+                                  BufferPresentedCallback feedback) override;
+  void EnsureBackbuffer() override;
+  void DiscardBackbuffer() override;
 
  protected:
   GrContext* const gr_context_;
-  const bool flipped_;
   const bool has_alpha_;
 
  private:
+  SkImageInfo image_info_;
+
   DISALLOW_COPY_AND_ASSIGN(SkiaOutputDeviceOffscreen);
 };
 
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.cc b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
index bbb8be8..6dbf7a0 100644
--- a/components/viz/service/display_embedder/skia_output_device_vulkan.cc
+++ b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
@@ -23,7 +23,10 @@
     DidSwapBufferCompleteCallback did_swap_buffer_complete_callback)
     : SkiaOutputDevice(did_swap_buffer_complete_callback),
       context_provider_(context_provider),
-      surface_handle_(surface_handle) {}
+      surface_handle_(surface_handle) {
+  capabilities_.flipped_output_surface = true;
+  capabilities_.supports_post_sub_buffer = false;
+}
 
 SkiaOutputDeviceVulkan::~SkiaOutputDeviceVulkan() {
   if (vulkan_surface_)
diff --git a/components/viz/service/display_embedder/skia_output_device_x11.cc b/components/viz/service/display_embedder/skia_output_device_x11.cc
index f5ef89b..76ed3d9 100644
--- a/components/viz/service/display_embedder/skia_output_device_x11.cc
+++ b/components/viz/service/display_embedder/skia_output_device_x11.cc
@@ -31,6 +31,9 @@
                          << widget_;
   bpp_ = gfx::BitsPerPixelForPixmapDepth(display_, attributes_.depth);
   support_rendr_ = ui::QueryRenderSupport(display_);
+
+  capabilities_.flipped_output_surface = false;
+  capabilities_.supports_post_sub_buffer = true;
 }
 
 SkiaOutputDeviceX11::~SkiaOutputDeviceX11() {
@@ -55,10 +58,6 @@
       std::move(feedback));
 }
 
-bool SkiaOutputDeviceX11::SupportPostSubBuffer() {
-  return true;
-}
-
 gfx::SwapResponse SkiaOutputDeviceX11::PostSubBuffer(
     const gfx::Rect& rect,
     BufferPresentedCallback feedback) {
diff --git a/components/viz/service/display_embedder/skia_output_device_x11.h b/components/viz/service/display_embedder/skia_output_device_x11.h
index 8642d58..a82d72e7 100644
--- a/components/viz/service/display_embedder/skia_output_device_x11.h
+++ b/components/viz/service/display_embedder/skia_output_device_x11.h
@@ -28,7 +28,6 @@
                const gfx::ColorSpace& color_space,
                bool has_alpha) override;
   gfx::SwapResponse SwapBuffers(BufferPresentedCallback feedback) override;
-  bool SupportPostSubBuffer() override;
   gfx::SwapResponse PostSubBuffer(const gfx::Rect& rect,
                                   BufferPresentedCallback feedback) override;
 
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc
index 2fd56233..59c3c89 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -320,12 +320,20 @@
 
 void SkiaOutputSurfaceImpl::EnsureBackbuffer() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  NOTIMPLEMENTED();
+  // impl_on_gpu_ is released on the GPU thread by a posted task from
+  // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
+  auto callback = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::EnsureBackbuffer,
+                                 base::Unretained(impl_on_gpu_.get()));
+  ScheduleGpuTask(std::move(callback), std::vector<gpu::SyncToken>());
 }
 
 void SkiaOutputSurfaceImpl::DiscardBackbuffer() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  NOTIMPLEMENTED();
+  // impl_on_gpu_ is released on the GPU thread by a posted task from
+  // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
+  auto callback = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::DiscardBackbuffer,
+                                 base::Unretained(impl_on_gpu_.get()));
+  ScheduleGpuTask(std::move(callback), std::vector<gpu::SyncToken>());
 }
 
 void SkiaOutputSurfaceImpl::BindFramebuffer() {
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc b/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc
index 097075d..6b3c548 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc
@@ -347,8 +347,11 @@
       sync_point_client_state_->command_buffer_id(), ++sync_fence_release_);
   sync_token.SetVerifyFlush();
   sync_point_client_state_->ReleaseFenceSync(sync_fence_release_);
-  DCHECK(mailbox_manager_->UsesSync());
-  mailbox_manager_->PushTextureUpdates(sync_token);
+  const bool is_using_vulkan = shared_context_state_->use_vulkan_gr_context();
+  if (!is_using_vulkan) {
+    DCHECK(mailbox_manager_->UsesSync());
+    mailbox_manager_->PushTextureUpdates(sync_token);
+  }
   sync_point_order_data_->FinishProcessingOrderNumber(order_num_);
   order_num_ = 0u;
   return sync_token;
@@ -497,9 +500,17 @@
                    "with display usage.";
     return nullptr;
   }
-  // TODO(penghuang): make SharedImageBacking be aware the target context.
-  auto promise_texture =
-      representation->BeginReadAccess(nullptr /* read_surface */);
+  if (!sk_surface_) {
+    // Create a dummy sk surface to make SharedImage happy.
+    // TODO(penghuang): remove the dummy sk surface when BeginReadAccess()
+    // doesn't need pass in a sk surface.
+    auto image_info =
+        SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+    sk_surface_ = SkSurface::MakeRenderTarget(
+        gr_context(), SkBudgeted::kNo, image_info, 0 /* sampleCount */,
+        kBottomLeft_GrSurfaceOrigin, nullptr /* surfaceProps */);
+  }
+  auto promise_texture = representation->BeginReadAccess(sk_surface_.get());
   if (!promise_texture) {
     DLOG(ERROR)
         << "Failed to begin read access for SharedImageRepresentationSkia";
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 8bf4c2c07d..eae8a86 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -428,10 +428,10 @@
 
   DCHECK(output_device_);
   gfx::SwapResponse response;
-  if (capabilities_.supports_post_sub_buffer) {
+  if (capabilities().supports_post_sub_buffer) {
     DCHECK(frame.sub_buffer_rect);
     DCHECK(!frame.sub_buffer_rect->IsEmpty());
-    if (!capabilities_.flipped_output_surface)
+    if (!capabilities().flipped_output_surface)
       frame.sub_buffer_rect->set_y(size_.height() - frame.sub_buffer_rect->y() -
                                    frame.sub_buffer_rect->height());
     response = output_device_->PostSubBuffer(*frame.sub_buffer_rect,
@@ -534,7 +534,7 @@
 
     GLuint gl_id = 0;
     GLenum internal_format = supports_alpha_ ? GL_RGBA : GL_RGB;
-    bool flipped = from_fbo0 ? !capabilities_.flipped_output_surface : false;
+    bool flipped = from_fbo0 ? !capabilities().flipped_output_surface : false;
 
     base::Optional<ScopedSurfaceToTexture> texture_mapper;
     if (!from_fbo0 || surface_handle_ == gpu::kNullSurfaceHandle) {
@@ -744,10 +744,9 @@
     const OutputSurface::Capabilities& capabilities) {
   MakeCurrent(false /* need_fbo0 */);
   // Check that we're using an offscreen surface.
-  DCHECK(output_device_);
-  capabilities_ = capabilities;
+  DCHECK(!surface_handle_);
   output_device_ = std::make_unique<SkiaOutputDeviceOffscreen>(
-      gr_context(), capabilities_.flipped_output_surface,
+      gr_context(), capabilities.flipped_output_surface,
       renderer_settings_.requires_alpha_channel,
       did_swap_buffer_complete_callback_);
 }
@@ -781,8 +780,6 @@
       return;
     }
     onscreen_device->Initialize(gr_context(), context);
-    capabilities_.flipped_output_surface = gl_surface_->FlipsVertically();
-    capabilities_.supports_stencil = onscreen_device->supports_stencil();
     supports_alpha_ = onscreen_device->supports_alpha();
     output_device_ = std::move(onscreen_device);
   } else {
@@ -790,19 +787,14 @@
         gr_context(), true /* flipped */,
         renderer_settings_.requires_alpha_channel,
         did_swap_buffer_complete_callback_);
-    capabilities_.flipped_output_surface = true;
-    capabilities_.supports_stencil = false;
     supports_alpha_ = renderer_settings_.requires_alpha_channel;
   }
-  capabilities_.supports_post_sub_buffer =
-      output_device_->SupportPostSubBuffer();
 }
 
 void SkiaOutputSurfaceImplOnGpu::InitializeForVulkan(
     GpuServiceImpl* gpu_service) {
   context_state_ = gpu_service->GetContextState();
   DCHECK(context_state_);
-  capabilities_.flipped_output_surface = true;
 #if BUILDFLAG(ENABLE_VULKAN)
   if (surface_handle_ == gpu::kNullSurfaceHandle) {
     output_device_ = std::make_unique<SkiaOutputDeviceOffscreen>(
@@ -827,8 +819,6 @@
         did_swap_buffer_complete_callback_);
 #endif
   }
-  capabilities_.supports_post_sub_buffer =
-      output_device_->SupportPostSubBuffer();
 #endif
 }
 
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
index 03ab63d..01a910e 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -104,7 +104,7 @@
     return sync_point_client_state_->command_buffer_id();
   }
   const OutputSurface::Capabilities capabilities() const {
-    return capabilities_;
+    return output_device_->capabilities();
   }
   const base::WeakPtr<SkiaOutputSurfaceImplOnGpu>& weak_ptr() const {
     return weak_ptr_;
@@ -123,6 +123,8 @@
       std::vector<gpu::SyncToken> sync_tokens,
       uint64_t sync_fence_release);
   void SwapBuffers(OutputSurfaceFrame frame);
+  void EnsureBackbuffer() { output_device_->EnsureBackbuffer(); }
+  void DiscardBackbuffer() { output_device_->DiscardBackbuffer(); }
   void FinishPaintRenderPass(RenderPassId id,
                              std::unique_ptr<SkDeferredDisplayList> ddl,
                              std::vector<gpu::SyncToken> sync_tokens,
@@ -209,7 +211,6 @@
   scoped_refptr<gl::GLSurface> gl_surface_;
   scoped_refptr<gpu::SharedContextState> context_state_;
   const gl::GLVersionInfo* gl_version_info_ = nullptr;
-  OutputSurface::Capabilities capabilities_;
 
   std::unique_ptr<SkiaOutputDevice> output_device_;
 
diff --git a/components/viz/service/display_embedder/viz_process_context_provider.cc b/components/viz/service/display_embedder/viz_process_context_provider.cc
index 36b2c4d..28cb6705 100644
--- a/components/viz/service/display_embedder/viz_process_context_provider.cc
+++ b/components/viz/service/display_embedder/viz_process_context_provider.cc
@@ -20,6 +20,7 @@
 #include "components/viz/common/gpu/context_lost_observer.h"
 #include "components/viz/common/gpu/context_lost_reason.h"
 #include "components/viz/common/resources/platform_color.h"
+#include "components/viz/common/viz_utils.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
@@ -73,8 +74,7 @@
     NOTREACHED();
   }
 
-  if (!requires_alpha_channel &&
-      base::SysInfo::AmountOfPhysicalMemoryMB() <= 512) {
+  if (!requires_alpha_channel && PreferRGB565ResourcesForDisplay()) {
     // See compositor_impl_android.cc for more information about this.
     // It is inside GetCompositorContextAttributes().
     attributes.alpha_size = 0;
diff --git a/content/app/strings/translations/content_strings_sk.xtb b/content/app/strings/translations/content_strings_sk.xtb
index 194672c..8997042 100644
--- a/content/app/strings/translations/content_strings_sk.xtb
+++ b/content/app/strings/translations/content_strings_sk.xtb
@@ -144,7 +144,7 @@
 <translation id="5987525920412732405">tlačidlo otáčania</translation>
 <translation id="6011459053400940133">posúvač hlasitosti</translation>
 <translation id="6015796118275082299">Rok</translation>
-<translation id="6023896073578205740">pole s ponukou</translation>
+<translation id="6023896073578205740">zoznamové pole</translation>
 <translation id="6150588977291308318">bibliografia</translation>
 <translation id="6164829606128959761">meter</translation>
 <translation id="6166809985690652833">doslov</translation>
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index e9d1ce6..f02b9965 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -202,7 +202,7 @@
     "//ui/base:buildflags",
     "//ui/base/clipboard",
     "//ui/base/idle",
-    "//ui/base/ime",
+    "//ui/base/ime/init",
     "//ui/base/mpris/buildflags",
     "//ui/display",
     "//ui/display/types",
@@ -1359,8 +1359,10 @@
     "renderer_host/cursor_manager.h",
     "renderer_host/dip_util.cc",
     "renderer_host/dip_util.h",
-    "renderer_host/direct_manipulation_win.cc",
-    "renderer_host/direct_manipulation_win.h",
+    "renderer_host/direct_manipulation_event_handler_win.cc",
+    "renderer_host/direct_manipulation_event_handler_win.h",
+    "renderer_host/direct_manipulation_helper_win.cc",
+    "renderer_host/direct_manipulation_helper_win.h",
     "renderer_host/display_util.cc",
     "renderer_host/display_util.h",
     "renderer_host/dwrite_font_file_util_win.cc",
@@ -1719,8 +1721,6 @@
     "service_worker/service_worker_provider_host.h",
     "service_worker/service_worker_quota_client.cc",
     "service_worker/service_worker_quota_client.h",
-    "service_worker/service_worker_read_from_cache_job.cc",
-    "service_worker/service_worker_read_from_cache_job.h",
     "service_worker/service_worker_register_job.cc",
     "service_worker/service_worker_register_job.h",
     "service_worker/service_worker_register_job_base.h",
@@ -2523,6 +2523,10 @@
       "renderer_host/render_widget_host_view_event_handler.cc",
       "renderer_host/render_widget_host_view_event_handler.h",
     ]
+
+    if (is_linux && !is_chromeos) {
+      deps += [ "//ui/base/ime/linux" ]
+    }
   } else {  # Not aura.
     sources -= [
       "media/desktop_media_window_registry_aura.cc",
diff --git a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
index 1542435..3583821 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -321,22 +321,25 @@
       &line);
 
   const base::ListValue* states_value;
-  node.GetList("states", &states_value);
-  for (auto it = states_value->begin(); it != states_value->end(); ++it) {
-    std::string state_value;
-    if (it->GetAsString(&state_value))
-      WriteAttribute(false, state_value, &line);
+  if (node.GetList("states", &states_value)) {
+    for (auto it = states_value->begin(); it != states_value->end(); ++it) {
+      std::string state_value;
+      if (it->GetAsString(&state_value))
+        WriteAttribute(false, state_value, &line);
+    }
   }
 
   const base::ListValue* relations_value;
-  node.GetList("relations", &relations_value);
-  for (auto it = relations_value->begin(); it != relations_value->end(); ++it) {
-    std::string relation_value;
-    if (it->GetAsString(&relation_value)) {
-      // By default, exclude embedded-by because that should appear on every
-      // top-level document object. The other relation types are less common
-      // and thus almost always of interest when testing.
-      WriteAttribute(relation_value != "embedded-by", relation_value, &line);
+  if (node.GetList("relations", &relations_value)) {
+    for (auto it = relations_value->begin(); it != relations_value->end();
+         ++it) {
+      std::string relation_value;
+      if (it->GetAsString(&relation_value)) {
+        // By default, exclude embedded-by because that should appear on every
+        // top-level document object. The other relation types are less common
+        // and thus almost always of interest when testing.
+        WriteAttribute(relation_value != "embedded-by", relation_value, &line);
+      }
     }
   }
 
@@ -351,27 +354,30 @@
   }
 
   const base::ListValue* value_info;
-  node.GetList("value", &value_info);
-  for (auto it = value_info->begin(); it != value_info->end(); ++it) {
-    std::string value_property;
-    if (it->GetAsString(&value_property))
-      WriteAttribute(true, value_property, &line);
+  if (node.GetList("value", &value_info)) {
+    for (auto it = value_info->begin(); it != value_info->end(); ++it) {
+      std::string value_property;
+      if (it->GetAsString(&value_property))
+        WriteAttribute(true, value_property, &line);
+    }
   }
 
   const base::ListValue* table_info;
-  node.GetList("table", &table_info);
-  for (auto it = table_info->begin(); it != table_info->end(); ++it) {
-    std::string table_property;
-    if (it->GetAsString(&table_property))
-      WriteAttribute(true, table_property, &line);
+  if (node.GetList("table", &table_info)) {
+    for (auto it = table_info->begin(); it != table_info->end(); ++it) {
+      std::string table_property;
+      if (it->GetAsString(&table_property))
+        WriteAttribute(true, table_property, &line);
+    }
   }
 
   const base::ListValue* cell_info;
-  node.GetList("cell", &cell_info);
-  for (auto it = cell_info->begin(); it != cell_info->end(); ++it) {
-    std::string cell_property;
-    if (it->GetAsString(&cell_property))
-      WriteAttribute(true, cell_property, &line);
+  if (node.GetList("cell", &cell_info)) {
+    for (auto it = cell_info->begin(); it != cell_info->end(); ++it) {
+      std::string cell_property;
+      if (it->GetAsString(&cell_property))
+        WriteAttribute(true, cell_property, &line);
+    }
   }
 
   return line;
diff --git a/content/browser/browser_main_runner_impl.cc b/content/browser/browser_main_runner_impl.cc
index 5e6c0fff..2d7f4eb 100644
--- a/content/browser/browser_main_runner_impl.cc
+++ b/content/browser/browser_main_runner_impl.cc
@@ -29,7 +29,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
 #include "third_party/skia/include/core/SkGraphics.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 
 #if defined(OS_ANDROID)
 #include "content/browser/android/tracing_controller_android.h"
diff --git a/content/browser/browsing_data/storage_partition_http_cache_data_remover.h b/content/browser/browsing_data/storage_partition_http_cache_data_remover.h
index 6d64417..53e10d4c 100644
--- a/content/browser/browsing_data/storage_partition_http_cache_data_remover.h
+++ b/content/browser/browsing_data/storage_partition_http_cache_data_remover.h
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "base/sequenced_task_runner_helpers.h"
 #include "base/time/time.h"
-#include "net/base/completion_callback.h"
 #include "url/gurl.h"
 
 namespace disk_cache {
diff --git a/content/browser/code_cache/generated_code_cache.cc b/content/browser/code_cache/generated_code_cache.cc
index 733bf67..bef010a 100644
--- a/content/browser/code_cache/generated_code_cache.cc
+++ b/content/browser/code_cache/generated_code_cache.cc
@@ -7,7 +7,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "content/public/common/url_constants.h"
-#include "net/base/completion_callback.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/url_util.h"
 #include "url/gurl.h"
diff --git a/content/browser/code_cache/generated_code_cache.h b/content/browser/code_cache/generated_code_cache.h
index a91e888a..986bf03 100644
--- a/content/browser/code_cache/generated_code_cache.h
+++ b/content/browser/code_cache/generated_code_cache.h
@@ -12,7 +12,6 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "content/common/content_export.h"
-#include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/disk_cache/disk_cache.h"
 #include "url/origin.h"
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index 7950acf5..519ea20 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -877,7 +877,7 @@
   bool need_alpha_channel = false;
   bool support_locking = false;
   bool support_gles2_interface = true;
-  bool support_raster_interface = false;
+  bool support_raster_interface = true;
   bool support_grcontext = false;
   shared_main_thread_contexts_ = CreateContextCommon(
       std::move(gpu_channel_host), gpu::kNullSurfaceHandle, need_alpha_channel,
@@ -894,6 +894,14 @@
 }
 
 scoped_refptr<viz::RasterContextProvider>
+GpuProcessTransportFactory::SharedMainThreadRasterContextProvider() {
+  SharedMainThreadContextProvider();
+  DCHECK(!shared_main_thread_contexts_ ||
+         shared_main_thread_contexts_->RasterInterface());
+  return shared_main_thread_contexts_;
+}
+
+scoped_refptr<viz::RasterContextProvider>
 GpuProcessTransportFactory::shared_worker_context_provider() {
   return shared_worker_context_provider_factory_.provider();
 }
diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h
index dd97989..525fa0c 100644
--- a/content/browser/compositor/gpu_process_transport_factory.h
+++ b/content/browser/compositor/gpu_process_transport_factory.h
@@ -70,6 +70,9 @@
       base::WeakPtr<ui::Compositor> compositor) override;
   scoped_refptr<viz::ContextProvider> SharedMainThreadContextProvider()
       override;
+  scoped_refptr<viz::RasterContextProvider>
+  SharedMainThreadRasterContextProvider() override;
+
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
   void AddObserver(ui::ContextFactoryObserver* observer) override;
diff --git a/content/browser/compositor/test/test_image_transport_factory.cc b/content/browser/compositor/test/test_image_transport_factory.cc
index f4ec67e..c7956a2b 100644
--- a/content/browser/compositor/test/test_image_transport_factory.cc
+++ b/content/browser/compositor/test/test_image_transport_factory.cc
@@ -95,6 +95,12 @@
   return shared_main_context_provider_;
 }
 
+scoped_refptr<viz::RasterContextProvider>
+TestImageTransportFactory::SharedMainThreadRasterContextProvider() {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
 gpu::GpuMemoryBufferManager*
 TestImageTransportFactory::GetGpuMemoryBufferManager() {
   return &gpu_memory_buffer_manager_;
diff --git a/content/browser/compositor/test/test_image_transport_factory.h b/content/browser/compositor/test/test_image_transport_factory.h
index eb7d2d5f..4cbfcc0 100644
--- a/content/browser/compositor/test/test_image_transport_factory.h
+++ b/content/browser/compositor/test/test_image_transport_factory.h
@@ -47,6 +47,9 @@
       base::WeakPtr<ui::Compositor> compositor) override;
   scoped_refptr<viz::ContextProvider> SharedMainThreadContextProvider()
       override;
+  scoped_refptr<viz::RasterContextProvider>
+  SharedMainThreadRasterContextProvider() override;
+
   void RemoveCompositor(ui::Compositor* compositor) override {}
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc
index dd21166..0c91d65 100644
--- a/content/browser/compositor/viz_process_transport_factory.cc
+++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -248,6 +248,13 @@
   return main_context_provider_;
 }
 
+scoped_refptr<viz::RasterContextProvider>
+VizProcessTransportFactory::SharedMainThreadRasterContextProvider() {
+  SharedMainThreadContextProvider();
+  DCHECK(!main_context_provider_ || main_context_provider_->RasterInterface());
+  return main_context_provider_;
+}
+
 void VizProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
   context_factory_private_.UnconfigureCompositor(compositor);
 }
@@ -448,7 +455,7 @@
   if (!main_context_provider_) {
     constexpr bool kCompositorContextSupportsLocking = false;
     constexpr bool kCompositorContextSupportsGLES2 = true;
-    constexpr bool kCompositorContextSupportsRaster = false;
+    constexpr bool kCompositorContextSupportsRaster = true;
     constexpr bool kCompositorContextSupportsGrContext = false;
     constexpr bool kCompositorContextSupportsOOPR = false;
 
diff --git a/content/browser/compositor/viz_process_transport_factory.h b/content/browser/compositor/viz_process_transport_factory.h
index af01023..4447840 100644
--- a/content/browser/compositor/viz_process_transport_factory.h
+++ b/content/browser/compositor/viz_process_transport_factory.h
@@ -64,6 +64,9 @@
       base::WeakPtr<ui::Compositor> compositor) override;
   scoped_refptr<viz::ContextProvider> SharedMainThreadContextProvider()
       override;
+  scoped_refptr<viz::RasterContextProvider>
+  SharedMainThreadRasterContextProvider() override;
+
   void RemoveCompositor(ui::Compositor* compositor) override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index a77abfb..5821060f 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -3784,10 +3784,13 @@
             std::string("header_value"));
 }
 
+// Verify WebUI download will success with an associated renderer process.
 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadFromWebUI) {
   GURL webui_url("chrome://resources/images/apps/blue_button.png");
   NavigateToURL(shell(), webui_url);
   SetupEnsureNoPendingDownloads();
+
+  // Creates download parameters with renderer process information.
   std::unique_ptr<download::DownloadUrlParameters> download_parameters(
       DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
           shell()->web_contents(), webui_url, TRAFFIC_ANNOTATION_FOR_TESTS));
@@ -3803,6 +3806,32 @@
   ASSERT_EQ(download::DownloadItem::COMPLETE, downloads[0]->GetState());
 }
 
+// Verify WebUI download will gracefully fail without an associated renderer
+// process.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadFromWebUIWithoutRenderer) {
+  GURL webui_url("chrome://resources/images/apps/blue_button.png");
+  NavigateToURL(shell(), webui_url);
+  SetupEnsureNoPendingDownloads();
+
+  // Creates download parameters without any renderer process information.
+  auto download_parameters = std::make_unique<download::DownloadUrlParameters>(
+      webui_url, TRAFFIC_ANNOTATION_FOR_TESTS);
+  std::unique_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
+  DownloadManagerForShell(shell())->DownloadUrl(std::move(download_parameters));
+  observer->WaitForFinished();
+
+  EXPECT_TRUE(EnsureNoPendingDownloads());
+
+  std::vector<download::DownloadItem*> downloads;
+  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
+  ASSERT_EQ(1u, downloads.size());
+
+  // WebUI or other UrlLoaderFacotry will not handle request without a valid
+  // render frame host, download should gracefully fail without triggering
+  // crash.
+  ASSERT_EQ(download::DownloadItem::INTERRUPTED, downloads[0]->GetState());
+}
+
 // Test fixture for forcing MHTML download.
 class MhtmlDownloadTest : public DownloadContentTest {
  protected:
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index c35fc830..21e888a1 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -1304,7 +1304,7 @@
         base::MakeRefCounted<FileDownloadURLLoaderFactoryGetter>(
             params->url(), browser_context_->GetPath(),
             browser_context_->GetSharedCorsOriginAccessList());
-  } else if (params->url().SchemeIs(content::kChromeUIScheme)) {
+  } else if (rfh && params->url().SchemeIs(content::kChromeUIScheme)) {
     url_loader_factory_getter =
         base::MakeRefCounted<WebUIDownloadURLLoaderFactoryGetter>(
             rfh, params->url());
@@ -1326,7 +1326,7 @@
         base::MakeRefCounted<FileSystemDownloadURLLoaderFactoryGetter>(
             params->url(), rfh, /*is_navigation=*/false,
             storage_partition->GetFileSystemContext(), storage_domain);
-  } else if (!IsURLHandledByNetworkService(params->url())) {
+  } else if (rfh && !IsURLHandledByNetworkService(params->url())) {
     ContentBrowserClient::NonNetworkURLLoaderFactoryMap
         non_network_url_loader_factories;
     GetContentClient()
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index 29eaa3b..c53bf6ad 100644
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -8340,15 +8340,6 @@
   }
 }
 
-class NavigationControllerControllableResponseBrowserTest
-    : public ContentBrowserTest {
- protected:
-  void SetUpOnMainThread() override {
-    host_resolver()->AddRule("*", "127.0.0.1");
-    content::SetupCrossSiteRedirector(embedded_test_server());
-  }
-};
-
 // Data URLs can have a reference fragment like any other URLs. In this test,
 // there are two navigations with the same data URL, but with a different
 // reference. The second navigation must be classified as "same-document".
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 981d354..889191d 100644
--- a/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -1455,17 +1455,13 @@
   // The value of "should replace entry" will be tested, but it's an error to
   // specify it when there are no entries. Create a simple entry to be replaced.
   const GURL url0("http://foo/0");
-  controller.LoadURL(
-      url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller.GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  main_test_rfh()->SendNavigate(entry_id, true, url0);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url0);
 
   // Set up the pending entry.
   const GURL url1("http://foo/1");
-  controller.LoadURL(
-      url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  entry_id = controller.GetPendingEntry()->GetUniqueID();
+  auto navigation =
+      NavigationSimulatorImpl::CreateBrowserInitiated(url1, contents());
+  navigation->Start();
 
   // Set up some sample values.
   const char* raw_data = "post\n\n\0data";
@@ -1484,8 +1480,7 @@
   EXPECT_TRUE(pending_entry->should_clear_history_list());
 
   // Fake a commit response.
-  main_test_rfh()->PrepareForCommit();
-  main_test_rfh()->SendNavigateWithReplacement(entry_id, true, url1);
+  navigation->set_should_replace_current_entry(true);
 
   // Certain values that are only used for pending entries get reset after
   // commit.
@@ -3084,8 +3079,9 @@
 
   // We create pending entries for renderer-initiated navigations so that we
   // can show them in new tabs when it is safe.
-  main_test_rfh()->SendRendererInitiatedNavigationRequest(url1, false);
-  main_test_rfh()->PrepareForCommit();
+  auto navigation1 =
+      NavigationSimulator::CreateRendererInitiated(url1, main_test_rfh());
+  navigation1->ReadyToCommit();
 
   // Simulate what happens if a BrowserURLHandler rewrites the URL, causing
   // the virtual URL to differ from the URL.
@@ -3097,22 +3093,23 @@
   EXPECT_TRUE(controller.GetPendingEntry()->is_renderer_initiated());
 
   // If the user clicks another link, we should replace the pending entry.
-  main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, false);
-  TestRenderFrameHost* navigating_rfh = GetNavigatingRenderFrameHost();
-  navigating_rfh->PrepareForCommit();
+  auto navigation2 =
+      NavigationSimulator::CreateRendererInitiated(url2, main_test_rfh());
+  navigation2->ReadyToCommit();
   EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL());
   EXPECT_EQ(url2, controller.GetPendingEntry()->GetVirtualURL());
 
   // Once it commits, the URL and virtual URL should reflect the actual page.
-  navigating_rfh->SendNavigate(0, true, url2);
+  navigation2->Commit();
   EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
   EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetVirtualURL());
 
   // We should remember if the pending entry will replace the current one.
   // http://crbug.com/308444.
-  main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, false);
-  main_test_rfh()->PrepareForCommit();
-  main_test_rfh()->SendNavigateWithReplacement(0, false, url2);
+  auto navigation3 =
+      NavigationSimulatorImpl::CreateRendererInitiated(url2, main_test_rfh());
+  navigation3->set_should_replace_current_entry(true);
+  navigation3->Commit();
   EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
 }
 
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc
index f454a8a..acd158e 100644
--- a/content/browser/frame_host/navigation_handle_impl.cc
+++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -1009,8 +1009,7 @@
   render_process_blocked_state_changed_subscription_.reset();
   GetRenderFrameHost()->GetRenderWidgetHost()->RendererIsUnresponsive(
       base::BindRepeating(&NavigationHandleImpl::RestartCommitTimeout,
-                          weak_factory_.GetWeakPtr()),
-      metrics::RendererHangCause::kCommitTimeout);
+                          weak_factory_.GetWeakPtr()));
 }
 
 // static
diff --git a/content/browser/manifest/manifest_browsertest.cc b/content/browser/manifest/manifest_browsertest.cc
index 0ad52df4..1d136dc 100644
--- a/content/browser/manifest/manifest_browsertest.cc
+++ b/content/browser/manifest/manifest_browsertest.cc
@@ -204,7 +204,7 @@
 }
 
 // If a page has an empty manifest, requesting the manifest should return the
-// empty manifest. The manifest URL should be non-empty.
+// manifest with default values. The manifest URL should be non-empty.
 IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, EmptyManifest) {
   GURL test_url =
       embedded_test_server()->GetURL("/manifest/empty-manifest.html");
@@ -212,8 +212,9 @@
   ASSERT_TRUE(NavigateToURL(shell(), test_url));
 
   GetManifestAndWait();
-  EXPECT_TRUE(manifest().IsEmpty());
+  EXPECT_FALSE(manifest().IsEmpty());
   EXPECT_FALSE(manifest_url().is_empty());
+  ASSERT_EQ(test_url.GetWithoutFilename(), manifest().scope);
   EXPECT_EQ(0, GetConsoleErrorCount());
   ASSERT_EQ(1u, reported_manifest_urls().size());
   EXPECT_EQ(manifest_url(), reported_manifest_urls()[0]);
@@ -294,7 +295,7 @@
         ExecuteScript(shell(), "setManifestTo('" + manifest_link + "')"));
 
     GetManifestAndWait();
-    EXPECT_TRUE(manifest().IsEmpty());
+    EXPECT_FALSE(manifest().IsEmpty());
     EXPECT_FALSE(manifest_url().is_empty());
     expected_manifest_urls.push_back(manifest_url());
     EXPECT_EQ(expected_manifest_urls, reported_manifest_urls());
@@ -421,9 +422,10 @@
   ASSERT_TRUE(NavigateToURL(shell(), test_url));
 
   GetManifestAndWait();
-  EXPECT_TRUE(manifest().IsEmpty());
+  EXPECT_FALSE(manifest().IsEmpty());
   EXPECT_FALSE(manifest_url().is_empty());
-  EXPECT_EQ(6, GetConsoleErrorCount());
+  ASSERT_EQ(test_url.GetWithoutFilename(), manifest().scope);
+  EXPECT_EQ(7, GetConsoleErrorCount());
   ASSERT_EQ(1u, reported_manifest_urls().size());
   EXPECT_EQ(manifest_url(), reported_manifest_urls()[0]);
   ASSERT_EQ(1u, manifests_reported_when_favicon_url_updated().size());
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 2ecee561..6755d606 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -49,6 +49,7 @@
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/surfaces/frame_sink_id_allocator.h"
 #include "components/viz/common/surfaces/local_surface_id_allocation.h"
+#include "components/viz/common/viz_utils.h"
 #include "components/viz/host/host_display_client.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/display/display.h"
@@ -367,7 +368,7 @@
 
   if (requires_alpha_channel) {
     attributes.alpha_size = 8;
-  } else if (base::SysInfo::AmountOfPhysicalMemoryMB() <= 512) {
+  } else if (viz::PreferRGB565ResourcesForDisplay()) {
     // In this case we prefer to use RGB565 format instead of RGBA8888 if
     // possible.
     // TODO(danakj): CommandBufferStub constructor checks for alpha == 0
diff --git a/content/browser/renderer_host/direct_manipulation_event_handler_win.cc b/content/browser/renderer_host/direct_manipulation_event_handler_win.cc
new file mode 100644
index 0000000..967467f
--- /dev/null
+++ b/content/browser/renderer_host/direct_manipulation_event_handler_win.cc
@@ -0,0 +1,314 @@
+// Copyright 2019 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/direct_manipulation_event_handler_win.h"
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/browser/renderer_host/direct_manipulation_helper_win.h"
+#include "ui/base/ui_base_features.h"
+#include "ui/base/win/window_event_target.h"
+
+namespace content {
+
+namespace {
+
+bool LoggingEnabled() {
+  static bool logging_enabled =
+      base::FeatureList::IsEnabled(features::kPrecisionTouchpadLogging);
+
+  return logging_enabled;
+}
+
+// TODO(crbug.com/914914) This is added for help us getting debug log on
+// machine with scrolling issue on Windows Precision Touchpad. We will remove it
+// after Windows Precision Touchpad scrolling issue fixed.
+void DebugLogging(const std::string& s, HRESULT hr) {
+  if (!LoggingEnabled())
+    return;
+
+  LOG(ERROR) << "Windows PTP: " << s << " " << hr;
+}
+
+bool FloatEquals(float f1, float f2) {
+  // The idea behind this is to use this fraction of the larger of the
+  // two numbers as the limit of the difference.  This breaks down near
+  // zero, so we reuse this as the minimum absolute size we will use
+  // for the base of the scale too.
+  static const float epsilon_scale = 0.00001f;
+  return fabs(f1 - f2) <
+         epsilon_scale *
+             std::fmax(std::fmax(std::fabs(f1), std::fabs(f2)), epsilon_scale);
+}
+
+}  // namespace
+
+DirectManipulationEventHandler::DirectManipulationEventHandler(
+    DirectManipulationHelper* helper)
+    : helper_(helper) {}
+
+void DirectManipulationEventHandler::SetWindowEventTarget(
+    ui::WindowEventTarget* event_target) {
+  if (!event_target && LoggingEnabled()) {
+    DebugLogging("Event target is null.", S_OK);
+    if (event_target_)
+      DebugLogging("Previous event target is not null", S_OK);
+    else
+      DebugLogging("Previous event target is null", S_OK);
+  }
+  event_target_ = event_target;
+}
+
+void DirectManipulationEventHandler::SetDeviceScaleFactor(
+    float device_scale_factor) {
+  device_scale_factor_ = device_scale_factor;
+}
+
+DirectManipulationEventHandler::~DirectManipulationEventHandler() {}
+
+void DirectManipulationEventHandler::TransitionToState(
+    GestureState new_gesture_state) {
+  if (gesture_state_ == new_gesture_state)
+    return;
+
+  if (LoggingEnabled()) {
+    std::string s = "TransitionToState " +
+                    base::NumberToString(static_cast<int>(gesture_state_)) +
+                    " -> " +
+                    base::NumberToString(static_cast<int>(new_gesture_state));
+    DebugLogging(s, S_OK);
+  }
+
+  GestureState previous_gesture_state = gesture_state_;
+  gesture_state_ = new_gesture_state;
+
+  // End the previous sequence.
+  switch (previous_gesture_state) {
+    case GestureState::kScroll: {
+      // kScroll -> kNone, kPinch, ScrollEnd.
+      // kScroll -> kFling, we don't want to end the current scroll sequence.
+      if (new_gesture_state != GestureState::kFling)
+        event_target_->ApplyPanGestureScrollEnd();
+      break;
+    }
+    case GestureState::kFling: {
+      // kFling -> *, FlingEnd.
+      event_target_->ApplyPanGestureFlingEnd();
+      break;
+    }
+    case GestureState::kPinch: {
+      DCHECK_EQ(new_gesture_state, GestureState::kNone);
+      // kPinch -> kNone, PinchEnd. kPinch should only transition to kNone.
+      event_target_->ApplyPinchZoomEnd();
+      break;
+    }
+    case GestureState::kNone: {
+      // kNone -> *, no cleanup is needed.
+      break;
+    }
+    default:
+      NOTREACHED();
+  }
+
+  // Start the new sequence.
+  switch (new_gesture_state) {
+    case GestureState::kScroll: {
+      // kFling, kNone -> kScroll, ScrollBegin.
+      // ScrollBegin is different phase event with others. It must send within
+      // the first scroll event.
+      should_send_scroll_begin_ = true;
+      break;
+    }
+    case GestureState::kFling: {
+      // Only kScroll can transition to kFling.
+      DCHECK_EQ(previous_gesture_state, GestureState::kScroll);
+      event_target_->ApplyPanGestureFlingBegin();
+      break;
+    }
+    case GestureState::kPinch: {
+      // * -> kPinch, PinchBegin.
+      // Pinch gesture may begin with some scroll events.
+      event_target_->ApplyPinchZoomBegin();
+      break;
+    }
+    case GestureState::kNone: {
+      // * -> kNone, only cleanup is needed.
+      break;
+    }
+    default:
+      NOTREACHED();
+  }
+}
+
+HRESULT DirectManipulationEventHandler::OnViewportStatusChanged(
+    IDirectManipulationViewport* viewport,
+    DIRECTMANIPULATION_STATUS current,
+    DIRECTMANIPULATION_STATUS previous) {
+  // MSDN never mention |viewport| are nullable and we never saw it is null when
+  // testing.
+  DCHECK(viewport);
+
+  if (LoggingEnabled()) {
+    std::string s = "ViewportStatusChanged " + base::NumberToString(previous) +
+                    " -> " + base::NumberToString(current);
+    DebugLogging(s, S_OK);
+  }
+
+  // The state of our viewport has changed! We'l be in one of three states:
+  // - ENABLED: initial state
+  // - READY: the previous gesture has been completed
+  // - RUNNING: gesture updating
+  // - INERTIA: finger leave touchpad content still updating by inertia
+
+  // Windows should not call this when event_target_ is null since we do not
+  // pass the DM_POINTERHITTEST to DirectManipulation.
+  if (!event_target_)
+    return S_OK;
+
+  if (current == previous)
+    return S_OK;
+
+  if (current == DIRECTMANIPULATION_INERTIA) {
+    // Fling must lead by Scroll. We can actually hit here when user pinch then
+    // quickly pan gesture and leave touchpad. In this case, we don't want to
+    // start a new sequence until the gesture end. The rest events in sequence
+    // will be ignore since sequence still in pinch and only scale factor
+    // changes will be applied.
+    if (previous != DIRECTMANIPULATION_RUNNING ||
+        gesture_state_ != GestureState::kScroll) {
+      return S_OK;
+    }
+
+    TransitionToState(GestureState::kFling);
+  }
+
+  if (current == DIRECTMANIPULATION_RUNNING) {
+    // INERTIA -> RUNNING, should start a new sequence.
+    if (previous == DIRECTMANIPULATION_INERTIA)
+      TransitionToState(GestureState::kNone);
+  }
+
+  if (current != DIRECTMANIPULATION_READY)
+    return S_OK;
+
+  // Reset the viewport when we're idle, so the content transforms always start
+  // at identity.
+  // Every animation will receive 2 ready message, we should stop request
+  // compositor animation at the second ready.
+  first_ready_ = !first_ready_;
+  HRESULT hr = helper_->Reset(first_ready_);
+  last_scale_ = 1.0f;
+  last_x_offset_ = 0.0f;
+  last_y_offset_ = 0.0f;
+
+  TransitionToState(GestureState::kNone);
+
+  return hr;
+}
+
+HRESULT DirectManipulationEventHandler::OnViewportUpdated(
+    IDirectManipulationViewport* viewport) {
+  if (LoggingEnabled())
+    DebugLogging("OnViewportUpdated", S_OK);
+  // Nothing to do here.
+  return S_OK;
+}
+
+HRESULT DirectManipulationEventHandler::OnContentUpdated(
+    IDirectManipulationViewport* viewport,
+    IDirectManipulationContent* content) {
+  // MSDN never mention these params are nullable and we never saw they are null
+  // when testing.
+  DCHECK(viewport);
+  DCHECK(content);
+
+  if (LoggingEnabled())
+    DebugLogging("OnContentUpdated", S_OK);
+
+  // Windows should not call this when event_target_ is null since we do not
+  // pass the DM_POINTERHITTEST to DirectManipulation.
+  if (!event_target_) {
+    DebugLogging("OnContentUpdated event_target_ is null.", S_OK);
+    return S_OK;
+  }
+
+  float xform[6];
+  HRESULT hr = content->GetContentTransform(xform, ARRAYSIZE(xform));
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("DirectManipulationContent get transform failed.", hr);
+    return hr;
+  }
+
+  float scale = xform[0];
+  int x_offset = xform[4] / device_scale_factor_;
+  int y_offset = xform[5] / device_scale_factor_;
+
+  // Ignore if Windows pass scale=0 to us.
+  if (scale == 0.0f) {
+    LOG(ERROR) << "Windows DirectManipulation API pass scale = 0.";
+    return hr;
+  }
+
+  // Ignore the scale factor change less than float point rounding error and
+  // scroll offset change less than 1.
+  // TODO(456622) Because we don't fully support fractional scroll, pass float
+  // scroll offset feels steppy. eg.
+  // first x_offset is 0.1 ignored, but last_x_offset_ set to 0.1
+  // second x_offset is 1 but x_offset - last_x_offset_ is 0.9 ignored.
+  if (FloatEquals(scale, last_scale_) && x_offset == last_x_offset_ &&
+      y_offset == last_y_offset_) {
+    if (LoggingEnabled()) {
+      std::string s =
+          "OnContentUpdated ignored. scale=" + base::NumberToString(scale) +
+          ", last_scale=" + base::NumberToString(last_scale_) +
+          ", x_offset=" + base::NumberToString(x_offset) +
+          ", last_x_offset=" + base::NumberToString(last_x_offset_) +
+          ", y_offset=" + base::NumberToString(y_offset) +
+          ", last_y_offset=" + base::NumberToString(last_y_offset_);
+      DebugLogging(s, S_OK);
+    }
+    return hr;
+  }
+
+  DCHECK_NE(last_scale_, 0.0f);
+
+  // DirectManipulation will send xy transform move to down-right which is noise
+  // when pinch zoom. We should consider the gesture either Scroll or Pinch at
+  // one sequence. But Pinch gesture may begin with some scroll transform since
+  // DirectManipulation recognition maybe wrong at start if the user pinch with
+  // slow motion. So we allow kScroll -> kPinch.
+
+  // Consider this is a Scroll when scale factor equals 1.0.
+  if (FloatEquals(scale, 1.0f)) {
+    if (gesture_state_ == GestureState::kNone)
+      TransitionToState(GestureState::kScroll);
+  } else {
+    // Pinch gesture may begin with some scroll events.
+    TransitionToState(GestureState::kPinch);
+  }
+
+  if (gesture_state_ == GestureState::kScroll) {
+    if (should_send_scroll_begin_) {
+      event_target_->ApplyPanGestureScrollBegin(x_offset - last_x_offset_,
+                                                y_offset - last_y_offset_);
+      should_send_scroll_begin_ = false;
+    } else {
+      event_target_->ApplyPanGestureScroll(x_offset - last_x_offset_,
+                                           y_offset - last_y_offset_);
+    }
+  } else if (gesture_state_ == GestureState::kFling) {
+    event_target_->ApplyPanGestureFling(x_offset - last_x_offset_,
+                                        y_offset - last_y_offset_);
+  } else {
+    event_target_->ApplyPinchZoomScale(scale / last_scale_);
+  }
+
+  last_scale_ = scale;
+  last_x_offset_ = x_offset;
+  last_y_offset_ = y_offset;
+
+  return hr;
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/direct_manipulation_event_handler_win.h b/content/browser/renderer_host/direct_manipulation_event_handler_win.h
new file mode 100644
index 0000000..270e85a
--- /dev/null
+++ b/content/browser/renderer_host/direct_manipulation_event_handler_win.h
@@ -0,0 +1,85 @@
+// Copyright 2019 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_RENDERER_HOST_DIRECT_MANIPULATION_EVENT_HANDLER_WIN_H_
+#define CONTENT_BROWSER_RENDERER_HOST_DIRECT_MANIPULATION_EVENT_HANDLER_WIN_H_
+
+#include <windows.h>
+
+#include <directmanipulation.h>
+#include <wrl.h>
+
+#include "base/macros.h"
+
+namespace ui {
+
+class WindowEventTarget;
+
+}  // namespace ui
+
+namespace content {
+
+class DirectManipulationHelper;
+class DirectManipulationUnitTest;
+
+// DirectManipulationEventHandler receives status update and gesture events from
+// Direct Manipulation API.
+class DirectManipulationEventHandler
+    : public Microsoft::WRL::RuntimeClass<
+          Microsoft::WRL::RuntimeClassFlags<
+              Microsoft::WRL::RuntimeClassType::ClassicCom>,
+          Microsoft::WRL::Implements<
+              Microsoft::WRL::RuntimeClassFlags<
+                  Microsoft::WRL::RuntimeClassType::ClassicCom>,
+              Microsoft::WRL::FtmBase,
+              IDirectManipulationViewportEventHandler>> {
+ public:
+  explicit DirectManipulationEventHandler(DirectManipulationHelper* helper);
+
+  // WindowEventTarget updates for every DM_POINTERHITTEST in case window
+  // hierarchy changed.
+  void SetWindowEventTarget(ui::WindowEventTarget* event_target);
+
+  void SetDeviceScaleFactor(float device_scale_factor);
+
+ private:
+  friend DirectManipulationUnitTest;
+
+  // DirectManipulationEventHandler();
+  ~DirectManipulationEventHandler() override;
+
+  enum class GestureState { kNone, kScroll, kFling, kPinch };
+
+  void TransitionToState(GestureState gesture);
+
+  HRESULT STDMETHODCALLTYPE
+  OnViewportStatusChanged(_In_ IDirectManipulationViewport* viewport,
+                          _In_ DIRECTMANIPULATION_STATUS current,
+                          _In_ DIRECTMANIPULATION_STATUS previous) override;
+
+  HRESULT STDMETHODCALLTYPE
+  OnViewportUpdated(_In_ IDirectManipulationViewport* viewport) override;
+
+  HRESULT STDMETHODCALLTYPE
+  OnContentUpdated(_In_ IDirectManipulationViewport* viewport,
+                   _In_ IDirectManipulationContent* content) override;
+
+  DirectManipulationHelper* helper_ = nullptr;
+  ui::WindowEventTarget* event_target_ = nullptr;
+  float device_scale_factor_ = 1.0f;
+  float last_scale_ = 1.0f;
+  int last_x_offset_ = 0;
+  int last_y_offset_ = 0;
+  bool first_ready_ = false;
+  bool should_send_scroll_begin_ = false;
+
+  // Current recognized gesture from Direct Manipulation.
+  GestureState gesture_state_ = GestureState::kNone;
+
+  DISALLOW_COPY_AND_ASSIGN(DirectManipulationEventHandler);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_DIRECT_MANIPULATION_EVENT_HANDLER_WIN_H_
diff --git a/content/browser/renderer_host/direct_manipulation_helper_win.cc b/content/browser/renderer_host/direct_manipulation_helper_win.cc
new file mode 100644
index 0000000..3548205e
--- /dev/null
+++ b/content/browser/renderer_host/direct_manipulation_helper_win.cc
@@ -0,0 +1,295 @@
+// 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/renderer_host/direct_manipulation_helper_win.h"
+
+#include <objbase.h>
+#include <cmath>
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/win/windows_version.h"
+#include "ui/base/ui_base_features.h"
+#include "ui/base/win/window_event_target.h"
+#include "ui/display/win/screen_win.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace content {
+
+namespace {
+
+bool LoggingEnabled() {
+  static bool logging_enabled =
+      base::FeatureList::IsEnabled(features::kPrecisionTouchpadLogging);
+
+  return logging_enabled;
+}
+
+// TODO(crbug.com/914914) This is added for help us getting debug log on
+// machine with scrolling issue on Windows Precision Touchpad. We will remove it
+// after Windows Precision Touchpad scrolling issue fixed.
+void DebugLogging(const std::string& s, HRESULT hr) {
+  if (!LoggingEnabled())
+    return;
+
+  LOG(ERROR) << "Windows PTP: " << s << " " << hr;
+}
+
+}  // namespace
+
+// static
+std::unique_ptr<DirectManipulationHelper>
+DirectManipulationHelper::CreateInstance(HWND window,
+                                         ui::WindowEventTarget* event_target) {
+  if (!::IsWindow(window))
+    return nullptr;
+
+  if (!base::FeatureList::IsEnabled(features::kPrecisionTouchpad))
+    return nullptr;
+
+  // DM_POINTERHITTEST supported since Win10.
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return nullptr;
+
+  std::unique_ptr<DirectManipulationHelper> instance =
+      base::WrapUnique(new DirectManipulationHelper());
+  instance->window_ = window;
+
+  if (instance->Initialize(event_target))
+    return instance;
+
+  return nullptr;
+}
+
+// static
+std::unique_ptr<DirectManipulationHelper>
+DirectManipulationHelper::CreateInstanceForTesting(
+    ui::WindowEventTarget* event_target,
+    Microsoft::WRL::ComPtr<IDirectManipulationViewport> viewport) {
+  if (!base::FeatureList::IsEnabled(features::kPrecisionTouchpad))
+    return nullptr;
+
+  // DM_POINTERHITTEST supported since Win10.
+  if (base::win::GetVersion() < base::win::VERSION_WIN10)
+    return nullptr;
+
+  std::unique_ptr<DirectManipulationHelper> instance =
+      base::WrapUnique(new DirectManipulationHelper());
+
+  instance->event_handler_ =
+      Microsoft::WRL::Make<DirectManipulationEventHandler>(instance.get());
+  instance->event_handler_->SetWindowEventTarget(event_target);
+
+  instance->viewport_ = viewport;
+
+  return instance;
+}
+
+DirectManipulationHelper::~DirectManipulationHelper() {
+  if (viewport_)
+    viewport_->Abandon();
+}
+
+DirectManipulationHelper::DirectManipulationHelper() {}
+
+bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) {
+  // IDirectManipulationUpdateManager is the first COM object created by the
+  // application to retrieve other objects in the Direct Manipulation API.
+  // It also serves to activate and deactivate Direct Manipulation functionality
+  // on a per-HWND basis.
+  HRESULT hr =
+      ::CoCreateInstance(CLSID_DirectManipulationManager, nullptr,
+                         CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&manager_));
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("DirectManipulationManager create failed.", hr);
+    return false;
+  }
+
+  // Since we want to use fake viewport, we need UpdateManager to tell a fake
+  // fake render frame.
+  hr = manager_->GetUpdateManager(IID_PPV_ARGS(&update_manager_));
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("Get UpdateManager failed.", hr);
+    return false;
+  }
+
+  hr = manager_->CreateViewport(nullptr, window_, IID_PPV_ARGS(&viewport_));
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("Viewport create failed.", hr);
+    return false;
+  }
+
+  DIRECTMANIPULATION_CONFIGURATION configuration =
+      DIRECTMANIPULATION_CONFIGURATION_INTERACTION |
+      DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X |
+      DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y |
+      DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_INERTIA |
+      DIRECTMANIPULATION_CONFIGURATION_RAILS_X |
+      DIRECTMANIPULATION_CONFIGURATION_RAILS_Y |
+      DIRECTMANIPULATION_CONFIGURATION_SCALING;
+
+  hr = viewport_->ActivateConfiguration(configuration);
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("Viewport set ActivateConfiguration failed.", hr);
+    return false;
+  }
+
+  // Since we are using fake viewport and only want to use Direct Manipulation
+  // for touchpad, we need to use MANUALUPDATE option.
+  hr = viewport_->SetViewportOptions(
+      DIRECTMANIPULATION_VIEWPORT_OPTIONS_MANUALUPDATE);
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("Viewport set ViewportOptions failed.", hr);
+    return false;
+  }
+
+  event_handler_ = Microsoft::WRL::Make<DirectManipulationEventHandler>(this);
+  event_handler_->SetWindowEventTarget(event_target);
+
+  // We got Direct Manipulation transform from
+  // IDirectManipulationViewportEventHandler.
+  hr = viewport_->AddEventHandler(window_, event_handler_.Get(),
+                                  &view_port_handler_cookie_);
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("Viewport add EventHandler failed.", hr);
+    return false;
+  }
+
+  // Set default rect for viewport before activate.
+  viewport_size_in_pixels_ = {1000, 1000};
+  RECT rect = gfx::Rect(viewport_size_in_pixels_).ToRECT();
+  hr = viewport_->SetViewportRect(&rect);
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("Viewport set rect failed.", hr);
+    return false;
+  }
+
+  hr = manager_->Activate(window_);
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("DirectManipulationManager activate failed.", hr);
+    return false;
+  }
+
+  hr = viewport_->Enable();
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("Viewport enable failed.", hr);
+    return false;
+  }
+
+  hr = update_manager_->Update(nullptr);
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("UpdateManager update failed.", hr);
+    return false;
+  }
+
+  DebugLogging("DirectManipulation initialization complete", S_OK);
+  return true;
+}
+
+void DirectManipulationHelper::Activate() {
+  HRESULT hr = viewport_->Stop();
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("Viewport stop failed.", hr);
+    return;
+  }
+
+  hr = manager_->Activate(window_);
+  if (!SUCCEEDED(hr))
+    DebugLogging("DirectManipulationManager activate failed.", hr);
+}
+
+void DirectManipulationHelper::Deactivate() {
+  HRESULT hr = viewport_->Stop();
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("Viewport stop failed.", hr);
+    return;
+  }
+
+  hr = manager_->Deactivate(window_);
+  if (!SUCCEEDED(hr))
+    DebugLogging("DirectManipulationManager deactivate failed.", hr);
+}
+
+void DirectManipulationHelper::SetSizeInPixels(
+    const gfx::Size& size_in_pixels) {
+  if (viewport_size_in_pixels_ == size_in_pixels)
+    return;
+
+  HRESULT hr = viewport_->Stop();
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("Viewport stop failed.", hr);
+    return;
+  }
+
+  viewport_size_in_pixels_ = size_in_pixels;
+  RECT rect = gfx::Rect(viewport_size_in_pixels_).ToRECT();
+  hr = viewport_->SetViewportRect(&rect);
+  if (!SUCCEEDED(hr))
+    DebugLogging("Viewport set rect failed.", hr);
+}
+
+bool DirectManipulationHelper::OnPointerHitTest(
+    WPARAM w_param,
+    ui::WindowEventTarget* event_target) {
+  // Update the device scale factor.
+  event_handler_->SetDeviceScaleFactor(
+      display::win::ScreenWin::GetScaleFactorForHWND(window_));
+
+  // Only DM_POINTERHITTEST can be the first message of input sequence of
+  // touchpad input.
+  // TODO(chaopeng) Check if Windows API changes:
+  // For WM_POINTER, the pointer type will show the event from mouse.
+  // For WM_POINTERACTIVATE, the pointer id will be different with the following
+  // message.
+  event_handler_->SetWindowEventTarget(event_target);
+
+  using GetPointerTypeFn = BOOL(WINAPI*)(UINT32, POINTER_INPUT_TYPE*);
+  UINT32 pointer_id = GET_POINTERID_WPARAM(w_param);
+  POINTER_INPUT_TYPE pointer_type;
+  static GetPointerTypeFn get_pointer_type = reinterpret_cast<GetPointerTypeFn>(
+      GetProcAddress(GetModuleHandleA("user32.dll"), "GetPointerType"));
+  if (get_pointer_type && get_pointer_type(pointer_id, &pointer_type) &&
+      pointer_type == PT_TOUCHPAD && event_target) {
+    HRESULT hr = viewport_->SetContact(pointer_id);
+    if (!SUCCEEDED(hr)) {
+      DebugLogging("Viewport set contact failed.", hr);
+      return false;
+    }
+
+    // Request begin frame for fake viewport.
+    need_poll_events_ = true;
+  }
+  return need_poll_events_;
+}
+
+HRESULT DirectManipulationHelper::Reset(bool need_poll_events) {
+  // By zooming the primary content to a rect that match the viewport rect, we
+  // reset the content's transform to identity.
+  HRESULT hr = viewport_->ZoomToRect(
+      static_cast<float>(0), static_cast<float>(0),
+      static_cast<float>(viewport_size_in_pixels_.width()),
+      static_cast<float>(viewport_size_in_pixels_.height()), FALSE);
+  if (!SUCCEEDED(hr)) {
+    DebugLogging("Viewport zoom to rect failed.", hr);
+    return hr;
+  }
+
+  need_poll_events_ = need_poll_events;
+  return S_OK;
+}
+
+bool DirectManipulationHelper::PollForNextEvent() {
+  // Simulate 1 frame in update_manager_.
+  HRESULT hr = update_manager_->Update(nullptr);
+  if (!SUCCEEDED(hr))
+    DebugLogging("UpdateManager update failed.", hr);
+  return need_poll_events_;
+}
+
+void DirectManipulationHelper::SetDeviceScaleFactorForTesting(float factor) {
+  event_handler_->SetDeviceScaleFactor(factor);
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/direct_manipulation_helper_win.h b/content/browser/renderer_host/direct_manipulation_helper_win.h
new file mode 100644
index 0000000..7f79818
--- /dev/null
+++ b/content/browser/renderer_host/direct_manipulation_helper_win.h
@@ -0,0 +1,103 @@
+// 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_BROWSER_RENDERER_HOST_DIRECT_MANIPULATION_HELPER_WIN_H_
+#define CONTENT_BROWSER_RENDERER_HOST_DIRECT_MANIPULATION_HELPER_WIN_H_
+
+#include <windows.h>
+
+#include <directmanipulation.h>
+#include <wrl.h>
+#include <memory>
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "content/browser/renderer_host/direct_manipulation_event_handler_win.h"
+#include "content/common/content_export.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace ui {
+
+class WindowEventTarget;
+
+}  // namespace ui
+
+namespace content {
+
+class DirectManipulationBrowserTest;
+class DirectManipulationUnitTest;
+
+// Windows 10 provides a new API called Direct Manipulation which generates
+// smooth scroll and scale factor via IDirectManipulationViewportEventHandler
+// on precision touchpad.
+// 1. The foreground window is checked to see if it is a Direct Manipulation
+//    consumer.
+// 2. Call SetContact in Direct Manipulation takes over the following scrolling
+//    when DM_POINTERHITTEST.
+// 3. OnViewportStatusChanged will be called when the gesture phase change.
+//    OnContentUpdated will be called when the gesture update.
+class CONTENT_EXPORT DirectManipulationHelper {
+ public:
+  // Creates and initializes an instance of this class if Direct Manipulation is
+  // enabled on the platform. Returns nullptr if it disabled or failed on
+  // initialization.
+  static std::unique_ptr<DirectManipulationHelper> CreateInstance(
+      HWND window,
+      ui::WindowEventTarget* event_target);
+
+  // Creates and initializes an instance for testing.
+  static std::unique_ptr<DirectManipulationHelper> CreateInstanceForTesting(
+      ui::WindowEventTarget* event_target,
+      Microsoft::WRL::ComPtr<IDirectManipulationViewport> viewport);
+
+  ~DirectManipulationHelper();
+
+  // Actives Direct Manipulation, call when window show.
+  void Activate();
+
+  // Deactivates Direct Manipulation, call when window show.
+  void Deactivate();
+
+  // Updates viewport size. Call it when window bounds updated.
+  void SetSizeInPixels(const gfx::Size& size_in_pixels);
+
+  // Reset for gesture end.
+  HRESULT Reset(bool need_animtation);
+
+  // Pass the pointer hit test to Direct Manipulation. Return true indicated we
+  // need poll for new events every frame from here.
+  bool OnPointerHitTest(WPARAM w_param, ui::WindowEventTarget* event_target);
+
+  // On each frame poll new Direct Manipulation events. Return true if we still
+  // need poll for new events on next frame, otherwise stop request need begin
+  // frame.
+  bool PollForNextEvent();
+
+ private:
+  friend class content::DirectManipulationBrowserTest;
+  friend class DirectManipulationUnitTest;
+
+  DirectManipulationHelper();
+
+  // This function instantiates Direct Manipulation and creates a viewport for
+  // the passed in |window|. Return false if initialize failed.
+  bool Initialize(ui::WindowEventTarget* event_target);
+
+  void SetDeviceScaleFactorForTesting(float factor);
+
+  Microsoft::WRL::ComPtr<IDirectManipulationManager> manager_;
+  Microsoft::WRL::ComPtr<IDirectManipulationUpdateManager> update_manager_;
+  Microsoft::WRL::ComPtr<IDirectManipulationViewport> viewport_;
+  Microsoft::WRL::ComPtr<DirectManipulationEventHandler> event_handler_;
+  HWND window_;
+  DWORD view_port_handler_cookie_;
+  bool need_poll_events_ = false;
+  gfx::Size viewport_size_in_pixels_;
+
+  DISALLOW_COPY_AND_ASSIGN(DirectManipulationHelper);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_DIRECT_MANIPULATION_HELPER_WIN_H_
diff --git a/content/browser/renderer_host/direct_manipulation_win.cc b/content/browser/renderer_host/direct_manipulation_win.cc
deleted file mode 100644
index fca09cb6..0000000
--- a/content/browser/renderer_host/direct_manipulation_win.cc
+++ /dev/null
@@ -1,584 +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/renderer_host/direct_manipulation_win.h"
-
-#include <objbase.h>
-#include <cmath>
-
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/win/windows_version.h"
-#include "ui/base/ui_base_features.h"
-#include "ui/display/win/screen_win.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace content {
-
-namespace {
-
-bool LoggingEnabled() {
-  static bool logging_enabled =
-      base::FeatureList::IsEnabled(features::kPrecisionTouchpadLogging);
-
-  return logging_enabled;
-}
-
-// TODO(crbug.com/914914) This is added for help us getting debug log on
-// machine with scrolling issue on Windows Precision Touchpad. We will remove it
-// after Windows Precision Touchpad scrolling issue fixed.
-void DebugLogging(const std::string& s, HRESULT hr) {
-  if (!LoggingEnabled())
-    return;
-
-  LOG(ERROR) << "Windows PTP: " << s << " " << hr;
-}
-
-}  // namespace
-
-// static
-std::unique_ptr<DirectManipulationHelper>
-DirectManipulationHelper::CreateInstance(HWND window,
-                                         ui::WindowEventTarget* event_target) {
-  if (!::IsWindow(window))
-    return nullptr;
-
-  if (!base::FeatureList::IsEnabled(features::kPrecisionTouchpad))
-    return nullptr;
-
-  // DM_POINTERHITTEST supported since Win10.
-  if (base::win::GetVersion() < base::win::VERSION_WIN10)
-    return nullptr;
-
-  std::unique_ptr<DirectManipulationHelper> instance =
-      base::WrapUnique(new DirectManipulationHelper());
-  instance->window_ = window;
-
-  if (instance->Initialize(event_target))
-    return instance;
-
-  return nullptr;
-}
-
-// static
-std::unique_ptr<DirectManipulationHelper>
-DirectManipulationHelper::CreateInstanceForTesting(
-    ui::WindowEventTarget* event_target,
-    Microsoft::WRL::ComPtr<IDirectManipulationViewport> viewport) {
-  if (!base::FeatureList::IsEnabled(features::kPrecisionTouchpad))
-    return nullptr;
-
-  // DM_POINTERHITTEST supported since Win10.
-  if (base::win::GetVersion() < base::win::VERSION_WIN10)
-    return nullptr;
-
-  std::unique_ptr<DirectManipulationHelper> instance =
-      base::WrapUnique(new DirectManipulationHelper());
-
-  instance->event_handler_ =
-      Microsoft::WRL::Make<DirectManipulationHandler>(instance.get());
-  instance->event_handler_->SetWindowEventTarget(event_target);
-
-  instance->viewport_ = viewport;
-
-  return instance;
-}
-
-DirectManipulationHelper::~DirectManipulationHelper() {
-  if (viewport_)
-    viewport_->Abandon();
-}
-
-DirectManipulationHelper::DirectManipulationHelper() {}
-
-bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) {
-  // IDirectManipulationUpdateManager is the first COM object created by the
-  // application to retrieve other objects in the Direct Manipulation API.
-  // It also serves to activate and deactivate Direct Manipulation functionality
-  // on a per-HWND basis.
-  HRESULT hr =
-      ::CoCreateInstance(CLSID_DirectManipulationManager, nullptr,
-                         CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&manager_));
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("DirectManipulationManager create failed.", hr);
-    return false;
-  }
-
-  // Since we want to use fake viewport, we need UpdateManager to tell a fake
-  // fake render frame.
-  hr = manager_->GetUpdateManager(IID_PPV_ARGS(&update_manager_));
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("Get UpdateManager failed.", hr);
-    return false;
-  }
-
-  hr = manager_->CreateViewport(nullptr, window_, IID_PPV_ARGS(&viewport_));
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("Viewport create failed.", hr);
-    return false;
-  }
-
-  DIRECTMANIPULATION_CONFIGURATION configuration =
-      DIRECTMANIPULATION_CONFIGURATION_INTERACTION |
-      DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X |
-      DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y |
-      DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_INERTIA |
-      DIRECTMANIPULATION_CONFIGURATION_RAILS_X |
-      DIRECTMANIPULATION_CONFIGURATION_RAILS_Y |
-      DIRECTMANIPULATION_CONFIGURATION_SCALING;
-
-  hr = viewport_->ActivateConfiguration(configuration);
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("Viewport set ActivateConfiguration failed.", hr);
-    return false;
-  }
-
-  // Since we are using fake viewport and only want to use Direct Manipulation
-  // for touchpad, we need to use MANUALUPDATE option.
-  hr = viewport_->SetViewportOptions(
-      DIRECTMANIPULATION_VIEWPORT_OPTIONS_MANUALUPDATE);
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("Viewport set ViewportOptions failed.", hr);
-    return false;
-  }
-
-  event_handler_ = Microsoft::WRL::Make<DirectManipulationHandler>(this);
-  event_handler_->SetWindowEventTarget(event_target);
-
-  // We got Direct Manipulation transform from
-  // IDirectManipulationViewportEventHandler.
-  hr = viewport_->AddEventHandler(window_, event_handler_.Get(),
-                                  &view_port_handler_cookie_);
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("Viewport add EventHandler failed.", hr);
-    return false;
-  }
-
-  // Set default rect for viewport before activate.
-  viewport_size_ = {1000, 1000};
-  RECT rect = gfx::Rect(viewport_size_).ToRECT();
-  hr = viewport_->SetViewportRect(&rect);
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("Viewport set rect failed.", hr);
-    return false;
-  }
-
-  hr = manager_->Activate(window_);
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("DirectManipulationManager activate failed.", hr);
-    return false;
-  }
-
-  hr = viewport_->Enable();
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("Viewport enable failed.", hr);
-    return false;
-  }
-
-  hr = update_manager_->Update(nullptr);
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("UpdateManager update failed.", hr);
-    return false;
-  }
-
-  DebugLogging("DirectManipulation initialization complete", S_OK);
-  return true;
-}
-
-void DirectManipulationHelper::Activate() {
-  HRESULT hr = viewport_->Stop();
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("Viewport stop failed.", hr);
-    return;
-  }
-
-  hr = manager_->Activate(window_);
-  if (!SUCCEEDED(hr))
-    DebugLogging("DirectManipulationManager activate failed.", hr);
-}
-
-void DirectManipulationHelper::Deactivate() {
-  HRESULT hr = viewport_->Stop();
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("Viewport stop failed.", hr);
-    return;
-  }
-
-  hr = manager_->Deactivate(window_);
-  if (!SUCCEEDED(hr))
-    DebugLogging("DirectManipulationManager deactivate failed.", hr);
-}
-
-void DirectManipulationHelper::SetSize(const gfx::Size& size) {
-  if (viewport_size_ == size)
-    return;
-
-  HRESULT hr = viewport_->Stop();
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("Viewport stop failed.", hr);
-    return;
-  }
-
-  viewport_size_ = size;
-  RECT rect = gfx::Rect(viewport_size_).ToRECT();
-  hr = viewport_->SetViewportRect(&rect);
-  if (!SUCCEEDED(hr))
-    DebugLogging("Viewport set rect failed.", hr);
-}
-
-bool DirectManipulationHelper::OnPointerHitTest(
-    WPARAM w_param,
-    ui::WindowEventTarget* event_target) {
-  // Update the device scale factor.
-  event_handler_->SetDeviceScaleFactor(
-      display::win::ScreenWin::GetScaleFactorForHWND(window_));
-
-  // Only DM_POINTERHITTEST can be the first message of input sequence of
-  // touchpad input.
-  // TODO(chaopeng) Check if Windows API changes:
-  // For WM_POINTER, the pointer type will show the event from mouse.
-  // For WM_POINTERACTIVATE, the pointer id will be different with the following
-  // message.
-  event_handler_->SetWindowEventTarget(event_target);
-
-  using GetPointerTypeFn = BOOL(WINAPI*)(UINT32, POINTER_INPUT_TYPE*);
-  UINT32 pointer_id = GET_POINTERID_WPARAM(w_param);
-  POINTER_INPUT_TYPE pointer_type;
-  static GetPointerTypeFn get_pointer_type = reinterpret_cast<GetPointerTypeFn>(
-      GetProcAddress(GetModuleHandleA("user32.dll"), "GetPointerType"));
-  if (get_pointer_type && get_pointer_type(pointer_id, &pointer_type) &&
-      pointer_type == PT_TOUCHPAD && event_target) {
-    HRESULT hr = viewport_->SetContact(pointer_id);
-    if (!SUCCEEDED(hr)) {
-      DebugLogging("Viewport set contact failed.", hr);
-      return false;
-    }
-
-    // Request begin frame for fake viewport.
-    need_poll_events_ = true;
-  }
-  return need_poll_events_;
-}
-
-HRESULT DirectManipulationHelper::ResetViewport(bool need_poll_events) {
-  // By zooming the primary content to a rect that match the viewport rect, we
-  // reset the content's transform to identity.
-  HRESULT hr =
-      viewport_->ZoomToRect(static_cast<float>(0), static_cast<float>(0),
-                            static_cast<float>(viewport_size_.width()),
-                            static_cast<float>(viewport_size_.height()), FALSE);
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("Viewport zoom to rect failed.", hr);
-    return hr;
-  }
-
-  need_poll_events_ = need_poll_events;
-  return S_OK;
-}
-
-bool DirectManipulationHelper::PollForNextEvent() {
-  // Simulate 1 frame in update_manager_.
-  HRESULT hr = update_manager_->Update(nullptr);
-  if (!SUCCEEDED(hr))
-    DebugLogging("UpdateManager update failed.", hr);
-  return need_poll_events_;
-}
-
-void DirectManipulationHelper::SetDeviceScaleFactorForTesting(float factor) {
-  event_handler_->SetDeviceScaleFactor(factor);
-}
-
-// DirectManipulationHandler
-DirectManipulationHandler::DirectManipulationHandler() {
-  NOTREACHED();
-}
-
-DirectManipulationHandler::DirectManipulationHandler(
-    DirectManipulationHelper* helper)
-    : helper_(helper) {}
-
-DirectManipulationHandler::~DirectManipulationHandler() {}
-
-void DirectManipulationHandler::TransitionToState(Gesture new_gesture_state) {
-  if (gesture_state_ == new_gesture_state)
-    return;
-
-  if (LoggingEnabled()) {
-    std::string s = "TransitionToState " +
-                    std::to_string(static_cast<int>(gesture_state_)) + " -> " +
-                    std::to_string(static_cast<int>(new_gesture_state));
-    DebugLogging(s, S_OK);
-  }
-
-  Gesture previous_gesture_state = gesture_state_;
-  gesture_state_ = new_gesture_state;
-
-  // End the previous sequence.
-  switch (previous_gesture_state) {
-    case Gesture::kScroll: {
-      // kScroll -> kNone, kPinch, ScrollEnd.
-      // kScroll -> kFling, we don't want to end the current scroll sequence.
-      if (new_gesture_state != Gesture::kFling)
-        event_target_->ApplyPanGestureScrollEnd();
-      break;
-    }
-    case Gesture::kFling: {
-      // kFling -> *, FlingEnd.
-      event_target_->ApplyPanGestureFlingEnd();
-      break;
-    }
-    case Gesture::kPinch: {
-      DCHECK_EQ(new_gesture_state, Gesture::kNone);
-      // kPinch -> kNone, PinchEnd. kPinch should only transition to kNone.
-      event_target_->ApplyPinchZoomEnd();
-      break;
-    }
-    case Gesture::kNone: {
-      // kNone -> *, no cleanup is needed.
-      break;
-    }
-    default:
-      NOTREACHED();
-  }
-
-  // Start the new sequence.
-  switch (new_gesture_state) {
-    case Gesture::kScroll: {
-      // kFling, kNone -> kScroll, ScrollBegin.
-      // ScrollBegin is different phase event with others. It must send within
-      // the first scroll event.
-      should_send_scroll_begin_ = true;
-      break;
-    }
-    case Gesture::kFling: {
-      // Only kScroll can transition to kFling.
-      DCHECK_EQ(previous_gesture_state, Gesture::kScroll);
-      event_target_->ApplyPanGestureFlingBegin();
-      break;
-    }
-    case Gesture::kPinch: {
-      // * -> kPinch, PinchBegin.
-      // Pinch gesture may begin with some scroll events.
-      event_target_->ApplyPinchZoomBegin();
-      break;
-    }
-    case Gesture::kNone: {
-      // * -> kNone, only cleanup is needed.
-      break;
-    }
-    default:
-      NOTREACHED();
-  }
-}
-
-HRESULT DirectManipulationHandler::OnViewportStatusChanged(
-    IDirectManipulationViewport* viewport,
-    DIRECTMANIPULATION_STATUS current,
-    DIRECTMANIPULATION_STATUS previous) {
-  // MSDN never mention |viewport| are nullable and we never saw it is null when
-  // testing.
-  DCHECK(viewport);
-
-  if (LoggingEnabled()) {
-    std::string s = "ViewportStatusChanged " + std::to_string(previous) +
-                    " -> " + std::to_string(current);
-    DebugLogging(s, S_OK);
-  }
-
-  // The state of our viewport has changed! We'l be in one of three states:
-  // - ENABLED: initial state
-  // - READY: the previous gesture has been completed
-  // - RUNNING: gesture updating
-  // - INERTIA: finger leave touchpad content still updating by inertia
-  HRESULT hr = S_OK;
-
-  // Windows should not call this when event_target_ is null since we do not
-  // pass the DM_POINTERHITTEST to DirectManipulation.
-  if (!event_target_)
-    return hr;
-
-  if (current == previous)
-    return hr;
-
-  if (current == DIRECTMANIPULATION_INERTIA) {
-    // Fling must lead by Scroll. We can actually hit here when user pinch then
-    // quickly pan gesture and leave touchpad. In this case, we don't want to
-    // start a new sequence until the gesture end. The rest events in sequence
-    // will be ignore since sequence still in pinch and only scale factor
-    // changes will be applied.
-    if (previous != DIRECTMANIPULATION_RUNNING ||
-        gesture_state_ != Gesture::kScroll) {
-      return hr;
-    }
-
-    TransitionToState(Gesture::kFling);
-  }
-
-  if (current == DIRECTMANIPULATION_RUNNING) {
-    // INERTIA -> RUNNING, should start a new sequence.
-    if (previous == DIRECTMANIPULATION_INERTIA)
-      TransitionToState(Gesture::kNone);
-  }
-
-  // Reset the viewport when we're idle, so the content transforms always start
-  // at identity.
-  if (current == DIRECTMANIPULATION_READY) {
-    // Every animation will receive 2 ready message, we should stop request
-    // compositor animation at the second ready.
-    first_ready_ = !first_ready_;
-    hr = helper_->ResetViewport(first_ready_);
-    last_scale_ = 1.0f;
-    last_x_offset_ = 0.0f;
-    last_y_offset_ = 0.0f;
-
-    TransitionToState(Gesture::kNone);
-  }
-
-  return hr;
-}
-
-HRESULT DirectManipulationHandler::OnViewportUpdated(
-    IDirectManipulationViewport* viewport) {
-  if (LoggingEnabled())
-    DebugLogging("OnViewportUpdated", S_OK);
-  // Nothing to do here.
-  return S_OK;
-}
-
-namespace {
-
-bool FloatEquals(float f1, float f2) {
-  // The idea behind this is to use this fraction of the larger of the
-  // two numbers as the limit of the difference.  This breaks down near
-  // zero, so we reuse this as the minimum absolute size we will use
-  // for the base of the scale too.
-  static const float epsilon_scale = 0.00001f;
-  return fabs(f1 - f2) <
-         epsilon_scale *
-             std::fmax(std::fmax(std::fabs(f1), std::fabs(f2)), epsilon_scale);
-}
-
-bool DifferentLessThanOne(int f1, int f2) {
-  return abs(f1 - f2) < 1;
-}
-
-}  // namespace
-
-HRESULT DirectManipulationHandler::OnContentUpdated(
-    IDirectManipulationViewport* viewport,
-    IDirectManipulationContent* content) {
-  // MSDN never mention these params are nullable and we never saw they are null
-  // when testing.
-  DCHECK(viewport);
-  DCHECK(content);
-
-  if (LoggingEnabled())
-    DebugLogging("OnContentUpdated", S_OK);
-
-  // Windows should not call this when event_target_ is null since we do not
-  // pass the DM_POINTERHITTEST to DirectManipulation.
-  if (!event_target_) {
-    DebugLogging("OnContentUpdated event_target_ is null.", S_OK);
-    return S_OK;
-  }
-
-  float xform[6];
-  HRESULT hr = content->GetContentTransform(xform, ARRAYSIZE(xform));
-  if (!SUCCEEDED(hr)) {
-    DebugLogging("DirectManipulationContent get transform failed.", hr);
-    return hr;
-  }
-
-  float scale = xform[0];
-  int x_offset = xform[4] / device_scale_factor_;
-  int y_offset = xform[5] / device_scale_factor_;
-
-  // Ignore if Windows pass scale=0 to us.
-  if (scale == 0.0f) {
-    LOG(ERROR) << "Windows DirectManipulation API pass scale = 0.";
-    return hr;
-  }
-
-  // Ignore the scale factor change less than float point rounding error and
-  // scroll offset change less than 1.
-  // TODO(456622) Because we don't fully support fractional scroll, pass float
-  // scroll offset feels steppy. eg.
-  // first x_offset is 0.1 ignored, but last_x_offset_ set to 0.1
-  // second x_offset is 1 but x_offset - last_x_offset_ is 0.9 ignored.
-  if (FloatEquals(scale, last_scale_) &&
-      DifferentLessThanOne(x_offset, last_x_offset_) &&
-      DifferentLessThanOne(y_offset, last_y_offset_)) {
-    if (LoggingEnabled()) {
-      std::string s =
-          "OnContentUpdated ignored. scale=" + std::to_string(scale) +
-          ", last_scale=" + std::to_string(last_scale_) +
-          ", x_offset=" + std::to_string(x_offset) +
-          ", last_x_offset=" + std::to_string(last_x_offset_) +
-          ", y_offset=" + std::to_string(y_offset) +
-          ", last_y_offset=" + std::to_string(last_y_offset_);
-      DebugLogging(s, S_OK);
-    }
-    return hr;
-  }
-
-  DCHECK_NE(last_scale_, 0.0f);
-
-  // DirectManipulation will send xy transform move to down-right which is noise
-  // when pinch zoom. We should consider the gesture either Scroll or Pinch at
-  // one sequence. But Pinch gesture may begin with some scroll transform since
-  // DirectManipulation recognition maybe wrong at start if the user pinch with
-  // slow motion. So we allow kScroll -> kPinch.
-
-  // Consider this is a Scroll when scale factor equals 1.0.
-  if (FloatEquals(scale, 1.0f)) {
-    if (gesture_state_ == Gesture::kNone)
-      TransitionToState(Gesture::kScroll);
-  } else {
-    // Pinch gesture may begin with some scroll events.
-    TransitionToState(Gesture::kPinch);
-  }
-
-  if (gesture_state_ == Gesture::kScroll) {
-    if (should_send_scroll_begin_) {
-      event_target_->ApplyPanGestureScrollBegin(x_offset - last_x_offset_,
-                                                y_offset - last_y_offset_);
-      should_send_scroll_begin_ = false;
-    } else {
-      event_target_->ApplyPanGestureScroll(x_offset - last_x_offset_,
-                                           y_offset - last_y_offset_);
-    }
-  } else if (gesture_state_ == Gesture::kFling) {
-    event_target_->ApplyPanGestureFling(x_offset - last_x_offset_,
-                                        y_offset - last_y_offset_);
-  } else {
-    event_target_->ApplyPinchZoomScale(scale / last_scale_);
-  }
-
-  last_scale_ = scale;
-  last_x_offset_ = x_offset;
-  last_y_offset_ = y_offset;
-
-  return hr;
-}
-
-void DirectManipulationHandler::SetWindowEventTarget(
-    ui::WindowEventTarget* event_target) {
-  if (!event_target && LoggingEnabled()) {
-    DebugLogging("Event target is null.", S_OK);
-    if (event_target_) {
-      DebugLogging("Previous event target is not null", S_OK);
-    } else {
-      DebugLogging("Previous event target is null", S_OK);
-    }
-  }
-  event_target_ = event_target;
-}
-
-void DirectManipulationHandler::SetDeviceScaleFactor(
-    float device_scale_factor) {
-  device_scale_factor_ = device_scale_factor;
-}
-
-}  // namespace content
diff --git a/content/browser/renderer_host/direct_manipulation_win.h b/content/browser/renderer_host/direct_manipulation_win.h
deleted file mode 100644
index 1f759a8..0000000
--- a/content/browser/renderer_host/direct_manipulation_win.h
+++ /dev/null
@@ -1,156 +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_BROWSER_RENDERER_HOST_DIRECT_MANIPULATION_WIN_H_
-#define CONTENT_BROWSER_RENDERER_HOST_DIRECT_MANIPULATION_WIN_H_
-
-#include <windows.h>
-
-#include <directmanipulation.h>
-#include <wrl.h>
-#include <memory>
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "ui/base/win/window_event_target.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace content {
-
-class DirectManipulationBrowserTest;
-class DirectManipulationHelper;
-class DirectManipulationUnitTest;
-
-// DirectManipulationHandler receives status update and gesture events from
-// Direct Manipulation API.
-class DirectManipulationHandler
-    : public Microsoft::WRL::RuntimeClass<
-          Microsoft::WRL::RuntimeClassFlags<
-              Microsoft::WRL::RuntimeClassType::ClassicCom>,
-          Microsoft::WRL::Implements<
-              Microsoft::WRL::RuntimeClassFlags<
-                  Microsoft::WRL::RuntimeClassType::ClassicCom>,
-              Microsoft::WRL::FtmBase,
-              IDirectManipulationViewportEventHandler>> {
- public:
-  explicit DirectManipulationHandler(DirectManipulationHelper* helper);
-
-  // WindowEventTarget updates for every DM_POINTERHITTEST in case window
-  // hierarchy changed.
-  void SetWindowEventTarget(ui::WindowEventTarget* event_target);
-
-  void SetDeviceScaleFactor(float device_scale_factor);
-
- private:
-  friend DirectManipulationUnitTest;
-
-  DirectManipulationHandler();
-  ~DirectManipulationHandler() override;
-
-  enum class Gesture { kNone, kScroll, kFling, kPinch };
-
-  void TransitionToState(Gesture gesture);
-
-  HRESULT STDMETHODCALLTYPE
-  OnViewportStatusChanged(_In_ IDirectManipulationViewport* viewport,
-                          _In_ DIRECTMANIPULATION_STATUS current,
-                          _In_ DIRECTMANIPULATION_STATUS previous) override;
-
-  HRESULT STDMETHODCALLTYPE
-  OnViewportUpdated(_In_ IDirectManipulationViewport* viewport) override;
-
-  HRESULT STDMETHODCALLTYPE
-  OnContentUpdated(_In_ IDirectManipulationViewport* viewport,
-                   _In_ IDirectManipulationContent* content) override;
-
-  DirectManipulationHelper* helper_ = nullptr;
-  ui::WindowEventTarget* event_target_ = nullptr;
-  float device_scale_factor_ = 1.0f;
-  float last_scale_ = 1.0f;
-  int last_x_offset_ = 0;
-  int last_y_offset_ = 0;
-  bool first_ready_ = false;
-  bool should_send_scroll_begin_ = false;
-
-  // Current recognized gesture from Direct Manipulation.
-  Gesture gesture_state_ = Gesture::kNone;
-
-  DISALLOW_COPY_AND_ASSIGN(DirectManipulationHandler);
-};
-
-// Windows 10 provides a new API called Direct Manipulation which generates
-// smooth scroll and scale factor via IDirectManipulationViewportEventHandler
-// on precision touchpad.
-// 1. The foreground window is checked to see if it is a Direct Manipulation
-//    consumer.
-// 2. Call SetContact in Direct Manipulation takes over the following scrolling
-//    when DM_POINTERHITTEST.
-// 3. OnViewportStatusChanged will be called when the gesture phase change.
-//    OnContentUpdated will be called when the gesture update.
-class CONTENT_EXPORT DirectManipulationHelper {
- public:
-  // Creates and initializes an instance of this class if Direct Manipulation is
-  // enabled on the platform. Returns nullptr if it disabled or failed on
-  // initialization.
-  static std::unique_ptr<DirectManipulationHelper> CreateInstance(
-      HWND window,
-      ui::WindowEventTarget* event_target);
-
-  // Creates and initializes an instance for testing.
-  static std::unique_ptr<DirectManipulationHelper> CreateInstanceForTesting(
-      ui::WindowEventTarget* event_target,
-      Microsoft::WRL::ComPtr<IDirectManipulationViewport> viewport);
-
-  ~DirectManipulationHelper();
-
-  // Registers and activates the passed in |window| as a Direct Manipulation
-  // consumer.
-  void Activate();
-
-  // Deactivates Direct Manipulation processing on the passed in |window|.
-  void Deactivate();
-
-  // Updates viewport size. Call it when window bounds updated.
-  void SetSize(const gfx::Size& size_in_pixels);
-
-  // Reset the fake viewport for gesture end.
-  HRESULT ResetViewport(bool need_animtation);
-
-  // Pass the pointer hit test to Direct Manipulation. Return true indicated we
-  // need poll for new events every frame from here.
-  bool OnPointerHitTest(WPARAM w_param, ui::WindowEventTarget* event_target);
-
-  // On each frame poll new Direct Manipulation events. Return true if we still
-  // need poll for new events on next frame, otherwise stop request need begin
-  // frame.
-  bool PollForNextEvent();
-
- private:
-  friend class content::DirectManipulationBrowserTest;
-  friend class DirectManipulationUnitTest;
-
-  DirectManipulationHelper();
-
-  // This function instantiates Direct Manipulation and creates a viewport for
-  // the passed in |window|. Return false if initialize failed.
-  bool Initialize(ui::WindowEventTarget* event_target);
-
-  void SetDeviceScaleFactorForTesting(float factor);
-
-  Microsoft::WRL::ComPtr<IDirectManipulationManager> manager_;
-  Microsoft::WRL::ComPtr<IDirectManipulationUpdateManager> update_manager_;
-  Microsoft::WRL::ComPtr<IDirectManipulationViewport> viewport_;
-  Microsoft::WRL::ComPtr<DirectManipulationHandler> event_handler_;
-  HWND window_;
-  DWORD view_port_handler_cookie_;
-  bool need_poll_events_ = false;
-  gfx::Size viewport_size_;
-
-  DISALLOW_COPY_AND_ASSIGN(DirectManipulationHelper);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_RENDERER_HOST_DIRECT_MANIPULATION_WIN_H_
diff --git a/content/browser/renderer_host/direct_manipulation_win_browsertest.cc b/content/browser/renderer_host/direct_manipulation_win_browsertest.cc
index b6855d4..6690f4ef 100644
--- a/content/browser/renderer_host/direct_manipulation_win_browsertest.cc
+++ b/content/browser/renderer_host/direct_manipulation_win_browsertest.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 "content/browser/renderer_host/direct_manipulation_win.h"
+#include "content/browser/renderer_host/direct_manipulation_helper_win.h"
 
 #include <windows.h>
 
diff --git a/content/browser/renderer_host/direct_manipulation_win_unittest.cc b/content/browser/renderer_host/direct_manipulation_win_unittest.cc
index 5483889..3c85312 100644
--- a/content/browser/renderer_host/direct_manipulation_win_unittest.cc
+++ b/content/browser/renderer_host/direct_manipulation_win_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/renderer_host/direct_manipulation_win.h"
+#include "content/browser/renderer_host/direct_manipulation_helper_win.h"
 
 #include <objbase.h>
 
@@ -11,6 +11,7 @@
 #include "base/win/windows_version.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/ui_base_features.h"
+#include "ui/base/win/window_event_target.h"
 
 namespace content {
 
diff --git a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc
index 041c6d2..b5d20ad2 100644
--- a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc
+++ b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc
@@ -307,6 +307,10 @@
   return IsFontUniqueNameTableValid();
 }
 
+bool DWriteFontLookupTableBuilder::FontUniqueNameTableReady() {
+  return font_table_built_.IsSignaled() && IsFontUniqueNameTableValid();
+}
+
 void DWriteFontLookupTableBuilder::SchedulePrepareFontUniqueNameTable() {
   DCHECK(base::FeatureList::IsEnabled(features::kFontSrcLocalMatching));
 
diff --git a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h
index 0f59849..77e851c 100644
--- a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h
+++ b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h
@@ -52,10 +52,14 @@
   // constructed. Call only after ScheduleBuildFontUniqueNameTable().
   bool EnsureFontUniqueNameTable();
 
+  // Returns whether the indexing has completed and the shared memory region is
+  // immediately ready without any sync operations.
+  bool FontUniqueNameTableReady();
+
   // Posts a task to load from cache or build (if cache not available) the
   // unique name table index, should only be called once at browser startup,
-  // after that, use EnsureFontUniqueNameTable() and DuplicatedMemoryRegion() to
-  // retrieve the lookup structure buffer.
+  // after that, use EnsureFontUniqueNameTable() and
+  // DuplicatedMemoryRegion() to retrieve the lookup structure buffer.
   void SchedulePrepareFontUniqueNameTable();
 
   enum class SlowDownMode { kDelayEachTask, kHangOneTask, kNoSlowdown };
diff --git a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc
index 4473d3b..c0400fd0 100644
--- a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc
+++ b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc
@@ -117,6 +117,16 @@
         DWriteFontLookupTableBuilder::SlowDownMode::kDelayEachTask,
         DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask));
 
+TEST_F(DWriteFontLookupTableBuilderTest, TestReadyEarly) {
+  font_lookup_table_builder_->SetSlowDownIndexingForTesting(
+      DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask);
+  font_lookup_table_builder_->SchedulePrepareFontUniqueNameTable();
+  ASSERT_FALSE(font_lookup_table_builder_->FontUniqueNameTableReady());
+  font_lookup_table_builder_->ResumeFromHangForTesting();
+  font_lookup_table_builder_->EnsureFontUniqueNameTable();
+  ASSERT_TRUE(font_lookup_table_builder_->FontUniqueNameTableReady());
+}
+
 TEST_F(DWriteFontLookupTableBuilderTest, RepeatedScheduling) {
   for (unsigned i = 0; i < 3; ++i) {
     font_lookup_table_builder_->ResetLookupTableForTesting();
diff --git a/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc b/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
index f1460e2..ab6ba863 100644
--- a/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
+++ b/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
@@ -392,10 +392,26 @@
   DCHECK_GT(result->mapped_length, 0u);
 }
 
+void DWriteFontProxyImpl::GetUniqueNameLookupTableIfAvailable(
+    GetUniqueNameLookupTableIfAvailableCallback callback) {
+  DCHECK(base::FeatureList::IsEnabled(features::kFontSrcLocalMatching));
+  base::ReadOnlySharedMemoryRegion invalid_region;
+  callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+      std::move(callback), false, std::move(invalid_region));
+
+  if (!DWriteFontLookupTableBuilder::GetInstance()
+           ->FontUniqueNameTableReady()) {
+    return;
+  }
+
+  std::move(callback).Run(
+      true,
+      DWriteFontLookupTableBuilder::GetInstance()->DuplicateMemoryRegion());
+}
+
 void DWriteFontProxyImpl::GetUniqueNameLookupTable(
     GetUniqueNameLookupTableCallback callback) {
   DCHECK(base::FeatureList::IsEnabled(features::kFontSrcLocalMatching));
-  InitializeDirectWrite();
   callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun(
       std::move(callback), base::ReadOnlySharedMemoryRegion());
 
diff --git a/content/browser/renderer_host/dwrite_font_proxy_impl_win.h b/content/browser/renderer_host/dwrite_font_proxy_impl_win.h
index db77d04..b0af5db 100644
--- a/content/browser/renderer_host/dwrite_font_proxy_impl_win.h
+++ b/content/browser/renderer_host/dwrite_font_proxy_impl_win.h
@@ -59,6 +59,9 @@
                      const base::string16& base_family_name,
                      MapCharactersCallback callback) override;
 
+  void GetUniqueNameLookupTableIfAvailable(
+      GetUniqueNameLookupTableIfAvailableCallback callback) override;
+
   void GetUniqueNameLookupTable(
       GetUniqueNameLookupTableCallback callback) override;
 
diff --git a/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc b/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc
index a39f90a..4ca5740 100644
--- a/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc
+++ b/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -217,24 +218,34 @@
   }
 }
 
-TEST_F(DWriteFontProxyUniqueNameMatchingTest, TestFindUniqueFont) {
-  base::ReadOnlySharedMemoryRegion font_table_memory;
-  dwrite_font_proxy().GetUniqueNameLookupTable(&font_table_memory);
+namespace {
+void TestWhenLookupTableReady(
+    bool* did_test_fonts,
+    base::ReadOnlySharedMemoryRegion font_table_memory) {
   blink::FontTableMatcher font_table_matcher(font_table_memory.Map());
-
   for (auto& test_font_name_index : kExpectedTestFonts) {
     base::Optional<blink::FontTableMatcher::MatchResult> match_result =
         font_table_matcher.MatchName(test_font_name_index.font_name);
-    CHECK(match_result) << "No font matched for font name: "
-                        << test_font_name_index.font_name;
+    ASSERT_TRUE(match_result)
+        << "No font matched for font name: " << test_font_name_index.font_name;
     base::File unique_font_file(
         base::FilePath::FromUTF8Unsafe(match_result->font_path),
         base::File::FLAG_OPEN | base::File::FLAG_READ);
-    CHECK(unique_font_file.IsValid());
-    CHECK_GT(unique_font_file.GetLength(), 0);
-    CHECK_EQ(test_font_name_index.ttc_index, match_result->ttc_index);
+    ASSERT_TRUE(unique_font_file.IsValid());
+    ASSERT_GT(unique_font_file.GetLength(), 0);
+    ASSERT_EQ(test_font_name_index.ttc_index, match_result->ttc_index);
+    *did_test_fonts = true;
   }
 }
+}  // namespace
+
+TEST_F(DWriteFontProxyUniqueNameMatchingTest, TestFindUniqueFont) {
+  bool lookup_table_results_were_tested = false;
+  dwrite_font_proxy().GetUniqueNameLookupTable(base::BindOnce(
+      &TestWhenLookupTableReady, &lookup_table_results_were_tested));
+  scoped_task_environment_.RunUntilIdle();
+  ASSERT_TRUE(lookup_table_results_were_tested);
+}
 
 }  // namespace
 
diff --git a/content/browser/renderer_host/input/mock_input_router.cc b/content/browser/renderer_host/input/mock_input_router.cc
new file mode 100644
index 0000000..7be9f1db
--- /dev/null
+++ b/content/browser/renderer_host/input/mock_input_router.cc
@@ -0,0 +1,52 @@
+// Copyright 2019 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/input/mock_input_router.h"
+
+#include "content/browser/renderer_host/input/input_router_client.h"
+
+namespace content {
+
+void MockInputRouter::SendMouseEvent(
+    const MouseEventWithLatencyInfo& mouse_event,
+    MouseEventCallback event_result_callback) {
+  sent_mouse_event_ = true;
+}
+void MockInputRouter::SendWheelEvent(
+    const MouseWheelEventWithLatencyInfo& wheel_event) {
+  sent_wheel_event_ = true;
+}
+void MockInputRouter::SendKeyboardEvent(
+    const NativeWebKeyboardEventWithLatencyInfo& key_event,
+    KeyboardEventCallback event_result_callback) {
+  sent_keyboard_event_ = true;
+}
+void MockInputRouter::SendGestureEvent(
+    const GestureEventWithLatencyInfo& gesture_event) {
+  sent_gesture_event_ = true;
+}
+void MockInputRouter::SendTouchEvent(
+    const TouchEventWithLatencyInfo& touch_event) {
+  send_touch_event_not_cancelled_ =
+      client_->FilterInputEvent(touch_event.event, touch_event.latency) ==
+      INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
+}
+
+bool MockInputRouter::HasPendingEvents() const {
+  return false;
+}
+
+base::Optional<cc::TouchAction> MockInputRouter::AllowedTouchAction() {
+  return cc::kTouchActionAuto;
+}
+
+bool MockInputRouter::FlingCancellationIsDeferred() {
+  return false;
+}
+
+void MockInputRouter::OnHasTouchEventHandlers(bool has_handlers) {
+  has_handlers_ = has_handlers;
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/input/mock_input_router.h b/content/browser/renderer_host/input/mock_input_router.h
new file mode 100644
index 0000000..19aef7f
--- /dev/null
+++ b/content/browser/renderer_host/input/mock_input_router.h
@@ -0,0 +1,70 @@
+// Copyright 2019 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_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_H_
+
+#include "content/browser/renderer_host/input/input_router.h"
+
+#include "base/optional.h"
+#include "cc/input/touch_action.h"
+#include "content/browser/renderer_host/event_with_latency_info.h"
+#include "content/common/input/event_with_latency_info.h"
+
+namespace content {
+class InputRouterClient;
+
+class MockInputRouter : public InputRouter {
+ public:
+  explicit MockInputRouter(InputRouterClient* client)
+      : sent_mouse_event_(false),
+        sent_wheel_event_(false),
+        sent_keyboard_event_(false),
+        sent_gesture_event_(false),
+        send_touch_event_not_cancelled_(false),
+        has_handlers_(false),
+        client_(client) {}
+  ~MockInputRouter() override {}
+
+  // InputRouter:
+  void SendMouseEvent(const MouseEventWithLatencyInfo& mouse_event,
+                      MouseEventCallback event_result_callback) override;
+  void SendWheelEvent(
+      const MouseWheelEventWithLatencyInfo& wheel_event) override;
+  void SendKeyboardEvent(const NativeWebKeyboardEventWithLatencyInfo& key_event,
+                         KeyboardEventCallback event_result_callback) override;
+  void SendGestureEvent(
+      const GestureEventWithLatencyInfo& gesture_event) override;
+  void SendTouchEvent(const TouchEventWithLatencyInfo& touch_event) override;
+  void NotifySiteIsMobileOptimized(bool is_mobile_optimized) override {}
+  bool HasPendingEvents() const override;
+  void SetDeviceScaleFactor(float device_scale_factor) override {}
+  void SetFrameTreeNodeId(int frameTreeNodeId) override {}
+  base::Optional<cc::TouchAction> AllowedTouchAction() override;
+  void SetForceEnableZoom(bool enabled) override {}
+  void BindHost(mojom::WidgetInputHandlerHostRequest request,
+                bool frame_handler) override {}
+  void StopFling() override {}
+  bool FlingCancellationIsDeferred() override;
+  void OnSetTouchAction(cc::TouchAction touch_action) override {}
+  void ForceSetTouchActionAuto() override {}
+  void OnHasTouchEventHandlers(bool has_handlers) override;
+  void WaitForInputProcessed(base::OnceClosure callback) override {}
+
+  bool sent_mouse_event_;
+  bool sent_wheel_event_;
+  bool sent_keyboard_event_;
+  bool sent_gesture_event_;
+  bool send_touch_event_not_cancelled_;
+  bool has_handlers_;
+
+ private:
+  InputRouterClient* client_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockInputRouter);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_H_
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.cc b/content/browser/renderer_host/legacy_render_widget_host_win.cc
index ff46c6bf..f417c5e5 100644
--- a/content/browser/renderer_host/legacy_render_widget_host_win.cc
+++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc
@@ -14,7 +14,7 @@
 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
 #include "content/browser/accessibility/browser_accessibility_win.h"
-#include "content/browser/renderer_host/direct_manipulation_win.h"
+#include "content/browser/renderer_host/direct_manipulation_helper_win.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
 #include "content/public/common/content_switches.h"
@@ -163,7 +163,7 @@
                  bounds_in_pixel.width(), bounds_in_pixel.height(),
                  SWP_NOREDRAW);
   if (direct_manipulation_helper_)
-    direct_manipulation_helper_->SetSize(bounds_in_pixel.size());
+    direct_manipulation_helper_->SetSizeInPixels(bounds_in_pixel.size());
 }
 
 void LegacyRenderWidgetHostHWND::OnFinalMessage(HWND hwnd) {
diff --git a/content/browser/renderer_host/mock_render_widget_host.cc b/content/browser/renderer_host/mock_render_widget_host.cc
new file mode 100644
index 0000000..3cfdc06
--- /dev/null
+++ b/content/browser/renderer_host/mock_render_widget_host.cc
@@ -0,0 +1,118 @@
+// Copyright 2019 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/mock_render_widget_host.h"
+
+#include "components/viz/test/mock_compositor_frame_sink_client.h"
+#include "content/browser/renderer_host/frame_token_message_queue.h"
+
+namespace {
+class TestFrameTokenMessageQueue : public content::FrameTokenMessageQueue {
+ public:
+  explicit TestFrameTokenMessageQueue(FrameTokenMessageQueue::Client* client)
+      : FrameTokenMessageQueue(client) {}
+  ~TestFrameTokenMessageQueue() override {}
+
+  uint32_t processed_frame_messages_count() {
+    return processed_frame_messages_count_;
+  }
+
+ protected:
+  void ProcessSwapMessages(std::vector<IPC::Message> messages) override {
+    processed_frame_messages_count_++;
+  }
+
+ private:
+  uint32_t processed_frame_messages_count_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(TestFrameTokenMessageQueue);
+};
+}  // namespace
+
+namespace content {
+
+MockRenderWidgetHost::~MockRenderWidgetHost() {}
+
+void MockRenderWidgetHost::OnTouchEventAck(
+    const TouchEventWithLatencyInfo& event,
+    InputEventAckSource ack_source,
+    InputEventAckState ack_result) {
+  // Sniff touch acks.
+  acked_touch_event_type_ = event.event.GetType();
+  RenderWidgetHostImpl::OnTouchEventAck(event, ack_source, ack_result);
+}
+
+void MockRenderWidgetHost::DisableGestureDebounce() {
+  input_router_.reset(new InputRouterImpl(this, this, fling_scheduler_.get(),
+                                          InputRouter::Config()));
+}
+
+void MockRenderWidgetHost::ExpectForceEnableZoom(bool enable) {
+  EXPECT_EQ(enable, force_enable_zoom_);
+
+  InputRouterImpl* input_router =
+      static_cast<InputRouterImpl*>(input_router_.get());
+  EXPECT_EQ(enable, input_router->touch_action_filter_.force_enable_zoom_);
+}
+
+// Mocks out |renderer_compositor_frame_sink_| with a
+// CompositorFrameSinkClientPtr bound to
+// |mock_renderer_compositor_frame_sink|.
+void MockRenderWidgetHost::SetMockRendererCompositorFrameSink(
+    viz::MockCompositorFrameSinkClient* mock_renderer_compositor_frame_sink) {
+  renderer_compositor_frame_sink_ =
+      mock_renderer_compositor_frame_sink->BindInterfacePtr();
+}
+
+void MockRenderWidgetHost::SetupForInputRouterTest() {
+  input_router_.reset(new MockInputRouter(this));
+}
+
+uint32_t MockRenderWidgetHost::processed_frame_messages_count() {
+  CHECK(frame_token_message_queue_);
+  return static_cast<TestFrameTokenMessageQueue*>(
+             frame_token_message_queue_.get())
+      ->processed_frame_messages_count();
+}
+
+// static
+MockRenderWidgetHost* MockRenderWidgetHost::Create(
+    RenderWidgetHostDelegate* delegate,
+    RenderProcessHost* process,
+    int32_t routing_id) {
+  mojom::WidgetPtr widget;
+  std::unique_ptr<MockWidgetImpl> widget_impl =
+      std::make_unique<MockWidgetImpl>(mojo::MakeRequest(&widget));
+
+  return new MockRenderWidgetHost(delegate, process, routing_id,
+                                  std::move(widget_impl), std::move(widget));
+}
+
+mojom::WidgetInputHandler* MockRenderWidgetHost::GetWidgetInputHandler() {
+  return &mock_widget_input_handler_;
+}
+
+void MockRenderWidgetHost::NotifyNewContentRenderingTimeoutForTesting() {
+  new_content_rendering_timeout_fired_ = true;
+}
+
+MockRenderWidgetHost::MockRenderWidgetHost(
+    RenderWidgetHostDelegate* delegate,
+    RenderProcessHost* process,
+    int routing_id,
+    std::unique_ptr<MockWidgetImpl> widget_impl,
+    mojom::WidgetPtr widget)
+    : RenderWidgetHostImpl(delegate,
+                           process,
+                           routing_id,
+                           std::move(widget),
+                           false),
+      new_content_rendering_timeout_fired_(false),
+      widget_impl_(std::move(widget_impl)),
+      fling_scheduler_(std::make_unique<FlingScheduler>(this)) {
+  acked_touch_event_type_ = blink::WebInputEvent::kUndefined;
+  frame_token_message_queue_.reset(new TestFrameTokenMessageQueue(this));
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/mock_render_widget_host.h b/content/browser/renderer_host/mock_render_widget_host.h
new file mode 100644
index 0000000..8e82f2e5
--- /dev/null
+++ b/content/browser/renderer_host/mock_render_widget_host.h
@@ -0,0 +1,102 @@
+// Copyright 2019 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_RENDERER_HOST_MOCK_RENDER_WIDGET_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MOCK_RENDER_WIDGET_HOST_H_
+
+#include "content/browser/renderer_host/render_view_host_impl.h"
+
+#include "content/browser/renderer_host/input/mock_input_router.h"
+#include "content/common/input/event_with_latency_info.h"
+#include "content/common/input/input_handler.mojom.h"
+#include "content/public/common/input_event_ack_source.h"
+#include "content/public/common/input_event_ack_state.h"
+#include "content/test/mock_widget_impl.h"
+#include "content/test/mock_widget_input_handler.h"
+#include "third_party/blink/public/platform/web_input_event.h"
+
+namespace viz {
+class MockCompositorFrameSinkClient;
+}  // namespace viz
+
+namespace content {
+
+class MockRenderWidgetHost : public RenderWidgetHostImpl {
+ public:
+  // Allow poking at a few private members.
+  using RenderWidgetHostImpl::frame_token_message_queue_;
+  using RenderWidgetHostImpl::GetVisualProperties;
+  using RenderWidgetHostImpl::input_router_;
+  using RenderWidgetHostImpl::is_hidden_;
+  using RenderWidgetHostImpl::old_visual_properties_;
+  using RenderWidgetHostImpl::RendererExited;
+  using RenderWidgetHostImpl::SetInitialVisualProperties;
+  using RenderWidgetHostImpl::visual_properties_ack_pending_;
+
+  ~MockRenderWidgetHost() override;
+
+  void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+                       InputEventAckSource ack_source,
+                       InputEventAckState ack_result) override;
+
+  void reset_new_content_rendering_timeout_fired() {
+    new_content_rendering_timeout_fired_ = false;
+  }
+
+  bool new_content_rendering_timeout_fired() const {
+    return new_content_rendering_timeout_fired_;
+  }
+
+  void DisableGestureDebounce();
+  void ExpectForceEnableZoom(bool enable);
+
+  blink::WebInputEvent::Type acked_touch_event_type() const {
+    return acked_touch_event_type_;
+  }
+
+  // Mocks out |renderer_compositor_frame_sink_| with a
+  // CompositorFrameSinkClientPtr bound to
+  // |mock_renderer_compositor_frame_sink|.
+  void SetMockRendererCompositorFrameSink(
+      viz::MockCompositorFrameSinkClient* mock_renderer_compositor_frame_sink);
+
+  void SetupForInputRouterTest();
+
+  MockInputRouter* mock_input_router() {
+    return static_cast<MockInputRouter*>(input_router_.get());
+  }
+
+  InputRouter* input_router() { return input_router_.get(); }
+
+  uint32_t processed_frame_messages_count();
+
+  static MockRenderWidgetHost* Create(RenderWidgetHostDelegate* delegate,
+                                      RenderProcessHost* process,
+                                      int32_t routing_id);
+
+  mojom::WidgetInputHandler* GetWidgetInputHandler() override;
+
+  MockWidgetInputHandler mock_widget_input_handler_;
+
+ protected:
+  void NotifyNewContentRenderingTimeoutForTesting() override;
+
+  bool new_content_rendering_timeout_fired_;
+  blink::WebInputEvent::Type acked_touch_event_type_;
+
+ private:
+  MockRenderWidgetHost(RenderWidgetHostDelegate* delegate,
+                       RenderProcessHost* process,
+                       int routing_id,
+                       std::unique_ptr<MockWidgetImpl> widget_impl,
+                       mojom::WidgetPtr widget);
+
+  std::unique_ptr<MockWidgetImpl> widget_impl_;
+
+  std::unique_ptr<FlingScheduler> fling_scheduler_;
+  DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHost);
+};
+
+}  // namespace content
+#endif  // CONTENT_BROWSER_RENDERER_HOST_MOCK_RENDER_WIDGET_HOST_H_
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 8b154b7c..e465d41 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -215,6 +215,7 @@
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
 #include "third_party/blink/public/public_buildflags.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/accessibility/accessibility_switches.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/base/ui_base_switches_util.h"
@@ -2974,6 +2975,7 @@
     switches::kDomAutomationController,
     switches::kEnableAccessibilityObjectModel,
     switches::kEnableAutomation,
+    switches::kEnableExperimentalAccessibilityLanguageDetection,
     switches::kEnableExperimentalWebPlatformFeatures,
     switches::kEnableGPUClientLogging,
     switches::kEnableGpuClientTracing,
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 00df801a..0fcea8c 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1024,7 +1024,8 @@
   // request, before subsequently merging ids to send.
   if (visual_properties_ack_pending_ || !process_->IsInitializedAndNotDead() ||
       !view_ || !view_->HasSize() || !renderer_initialized_ || !delegate_ ||
-      surface_id_allocation_suppressed_) {
+      surface_id_allocation_suppressed_ ||
+      !view_->CanSynchronizeVisualProperties()) {
     return false;
   }
 
@@ -2218,19 +2219,17 @@
 }
 
 void RenderWidgetHostImpl::OnInputEventAckTimeout() {
-  RendererIsUnresponsive(
-      base::BindRepeating(
-          &RenderWidgetHostImpl::RestartInputEventAckTimeoutIfNecessary,
-          weak_factory_.GetWeakPtr()),
-      metrics::RendererHangCause::kInputAckTimeout);
+  RendererIsUnresponsive(base::BindRepeating(
+      &RenderWidgetHostImpl::RestartInputEventAckTimeoutIfNecessary,
+      weak_factory_.GetWeakPtr()));
 }
 
 void RenderWidgetHostImpl::RendererIsUnresponsive(
-    base::RepeatingClosure restart_hang_monitor_timeout,
-    metrics::RendererHangCause hang_cause) {
+    base::RepeatingClosure restart_hang_monitor_timeout) {
   NotificationService::current()->Notify(
-      NOTIFICATION_RENDER_WIDGET_HOST_HANG, Source<RenderWidgetHost>(this),
-      Details<metrics::RendererHangCause>(&hang_cause));
+      NOTIFICATION_RENDER_WIDGET_HOST_HANG,
+      Source<RenderWidgetHost>(this),
+      NotificationService::NoDetails());
   is_unresponsive_ = true;
 
   if (delegate_) {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 8ffadf09..4e57f0e 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -31,7 +31,6 @@
 #include "base/time/time.h"
 #include "base/timer/elapsed_timer.h"
 #include "build/build_config.h"
-#include "components/metrics/stability_metrics_helper.h"
 #include "components/viz/common/resources/shared_bitmap.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "content/browser/renderer_host/event_with_latency_info.h"
@@ -730,8 +729,7 @@
   // 1) |hang_monitor_timeout_| (slow to ack input events) or
   // 2) NavigationHandle::OnCommitTimeout (slow to commit).
   void RendererIsUnresponsive(
-      base::RepeatingClosure restart_hang_monitor_timeout,
-      metrics::RendererHangCause hang_cause);
+      base::RepeatingClosure restart_hang_monitor_timeout);
 
   // Called if we know the renderer is responsive. When we currently think the
   // renderer is unresponsive, this will clear that state and call
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 78ae46d6c..1e1cd88 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -30,7 +30,9 @@
 #include "components/viz/test/mock_compositor_frame_sink_client.h"
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/renderer_host/frame_token_message_queue.h"
+#include "content/browser/renderer_host/input/mock_input_router.h"
 #include "content/browser/renderer_host/input/touch_emulator.h"
+#include "content/browser/renderer_host/mock_render_widget_host.h"
 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
@@ -91,220 +93,6 @@
 using testing::_;
 
 namespace content {
-
-// MockInputRouter -------------------------------------------------------------
-
-class MockInputRouter : public InputRouter {
- public:
-  explicit MockInputRouter(InputRouterClient* client)
-      : sent_mouse_event_(false),
-        sent_wheel_event_(false),
-        sent_keyboard_event_(false),
-        sent_gesture_event_(false),
-        send_touch_event_not_cancelled_(false),
-        has_handlers_(false),
-        client_(client) {}
-  ~MockInputRouter() override {}
-
-  // InputRouter
-  void SendMouseEvent(const MouseEventWithLatencyInfo& mouse_event,
-                      MouseEventCallback event_result_callback) override {
-    sent_mouse_event_ = true;
-  }
-  void SendWheelEvent(
-      const MouseWheelEventWithLatencyInfo& wheel_event) override {
-    sent_wheel_event_ = true;
-  }
-  void SendKeyboardEvent(const NativeWebKeyboardEventWithLatencyInfo& key_event,
-                         KeyboardEventCallback event_result_callback) override {
-    sent_keyboard_event_ = true;
-  }
-  void SendGestureEvent(
-      const GestureEventWithLatencyInfo& gesture_event) override {
-    sent_gesture_event_ = true;
-  }
-  void SendTouchEvent(const TouchEventWithLatencyInfo& touch_event) override {
-    send_touch_event_not_cancelled_ =
-        client_->FilterInputEvent(touch_event.event, touch_event.latency) ==
-        INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
-  }
-  void NotifySiteIsMobileOptimized(bool is_mobile_optimized) override {}
-  bool HasPendingEvents() const override { return false; }
-  void SetDeviceScaleFactor(float device_scale_factor) override {}
-  void SetFrameTreeNodeId(int frameTreeNodeId) override {}
-  base::Optional<cc::TouchAction> AllowedTouchAction() override {
-    return cc::kTouchActionAuto;
-  }
-  void SetForceEnableZoom(bool enabled) override {}
-  void BindHost(mojom::WidgetInputHandlerHostRequest request,
-                bool frame_handler) override {}
-  void StopFling() override {}
-  bool FlingCancellationIsDeferred() override { return false; }
-  void OnSetTouchAction(cc::TouchAction touch_action) override {}
-  void ForceSetTouchActionAuto() override {}
-  void OnHasTouchEventHandlers(bool has_handlers) override {
-    has_handlers_ = has_handlers;
-  }
-  void WaitForInputProcessed(base::OnceClosure callback) override {}
-
-  bool sent_mouse_event_;
-  bool sent_wheel_event_;
-  bool sent_keyboard_event_;
-  bool sent_gesture_event_;
-  bool send_touch_event_not_cancelled_;
-  bool has_handlers_;
-
- private:
-  InputRouterClient* client_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockInputRouter);
-};
-
-// TestFrameTokenMessageQueue ----------------------------------------------
-
-class TestFrameTokenMessageQueue : public FrameTokenMessageQueue {
- public:
-  explicit TestFrameTokenMessageQueue(FrameTokenMessageQueue::Client* client)
-      : FrameTokenMessageQueue(client) {}
-  ~TestFrameTokenMessageQueue() override {}
-
-  uint32_t processed_frame_messages_count() {
-    return processed_frame_messages_count_;
-  }
-
- protected:
-  void ProcessSwapMessages(std::vector<IPC::Message> messages) override {
-    processed_frame_messages_count_++;
-  }
-
- private:
-  uint32_t processed_frame_messages_count_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(TestFrameTokenMessageQueue);
-};
-
-// MockRenderWidgetHost ----------------------------------------------------
-
-class MockRenderWidgetHost : public RenderWidgetHostImpl {
- public:
-  // Allow poking at a few private members.
-  using RenderWidgetHostImpl::GetVisualProperties;
-  using RenderWidgetHostImpl::RendererExited;
-  using RenderWidgetHostImpl::SetInitialVisualProperties;
-  using RenderWidgetHostImpl::old_visual_properties_;
-  using RenderWidgetHostImpl::is_hidden_;
-  using RenderWidgetHostImpl::visual_properties_ack_pending_;
-  using RenderWidgetHostImpl::input_router_;
-  using RenderWidgetHostImpl::frame_token_message_queue_;
-
-  void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
-                       InputEventAckSource ack_source,
-                       InputEventAckState ack_result) override {
-    // Sniff touch acks.
-    acked_touch_event_type_ = event.event.GetType();
-    RenderWidgetHostImpl::OnTouchEventAck(event, ack_source, ack_result);
-  }
-
-  void reset_new_content_rendering_timeout_fired() {
-    new_content_rendering_timeout_fired_ = false;
-  }
-
-  bool new_content_rendering_timeout_fired() const {
-    return new_content_rendering_timeout_fired_;
-  }
-
-  void DisableGestureDebounce() {
-    input_router_.reset(new InputRouterImpl(this, this, fling_scheduler_.get(),
-                                            InputRouter::Config()));
-  }
-
-  void ExpectForceEnableZoom(bool enable) {
-    EXPECT_EQ(enable, force_enable_zoom_);
-
-    InputRouterImpl* input_router =
-        static_cast<InputRouterImpl*>(input_router_.get());
-    EXPECT_EQ(enable, input_router->touch_action_filter_.force_enable_zoom_);
-  }
-
-  WebInputEvent::Type acked_touch_event_type() const {
-    return acked_touch_event_type_;
-  }
-
-  // Mocks out |renderer_compositor_frame_sink_| with a
-  // CompositorFrameSinkClientPtr bound to
-  // |mock_renderer_compositor_frame_sink|.
-  void SetMockRendererCompositorFrameSink(
-      viz::MockCompositorFrameSinkClient* mock_renderer_compositor_frame_sink) {
-    renderer_compositor_frame_sink_ =
-        mock_renderer_compositor_frame_sink->BindInterfacePtr();
-  }
-
-  void SetupForInputRouterTest() {
-    input_router_.reset(new MockInputRouter(this));
-  }
-
-  MockInputRouter* mock_input_router() {
-    return static_cast<MockInputRouter*>(input_router_.get());
-  }
-
-  InputRouter* input_router() { return input_router_.get(); }
-
-  uint32_t processed_frame_messages_count() {
-    CHECK(frame_token_message_queue_);
-    return static_cast<TestFrameTokenMessageQueue*>(
-               frame_token_message_queue_.get())
-        ->processed_frame_messages_count();
-  }
-
-  static MockRenderWidgetHost* Create(RenderWidgetHostDelegate* delegate,
-                                      RenderProcessHost* process,
-                                      int32_t routing_id) {
-    mojom::WidgetPtr widget;
-    std::unique_ptr<MockWidgetImpl> widget_impl =
-        std::make_unique<MockWidgetImpl>(mojo::MakeRequest(&widget));
-
-    return new MockRenderWidgetHost(delegate, process, routing_id,
-                                    std::move(widget_impl), std::move(widget));
-  }
-
-  mojom::WidgetInputHandler* GetWidgetInputHandler() override {
-    return &mock_widget_input_handler_;
-  }
-
-  MockWidgetInputHandler mock_widget_input_handler_;
-
- protected:
-  void NotifyNewContentRenderingTimeoutForTesting() override {
-    new_content_rendering_timeout_fired_ = true;
-  }
-
-  bool new_content_rendering_timeout_fired_;
-  WebInputEvent::Type acked_touch_event_type_;
-
- private:
-  MockRenderWidgetHost(RenderWidgetHostDelegate* delegate,
-                       RenderProcessHost* process,
-                       int routing_id,
-                       std::unique_ptr<MockWidgetImpl> widget_impl,
-                       mojom::WidgetPtr widget)
-      : RenderWidgetHostImpl(delegate,
-                             process,
-                             routing_id,
-                             std::move(widget),
-                             false),
-        new_content_rendering_timeout_fired_(false),
-        widget_impl_(std::move(widget_impl)),
-        fling_scheduler_(std::make_unique<FlingScheduler>(this)) {
-    acked_touch_event_type_ = blink::WebInputEvent::kUndefined;
-    frame_token_message_queue_.reset(new TestFrameTokenMessageQueue(this));
-  }
-
-  std::unique_ptr<MockWidgetImpl> widget_impl_;
-
-  std::unique_ptr<FlingScheduler> fling_scheduler_;
-  DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHost);
-};
-
 namespace  {
 
 // RenderWidgetHostProcess -----------------------------------------------------
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 2a1b59e..1af97d0e 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -194,7 +194,6 @@
   // layer is managed by the DelegatedFrameHost.
   view_.SetLayer(cc::Layer::Create());
   view_.set_event_handler(this);
-
   if (using_browser_compositor_) {
     delegated_frame_host_client_ =
         std::make_unique<DelegatedFrameHostClientAndroid>(this);
@@ -278,6 +277,15 @@
   } else {
     local_surface_id_allocator_.GenerateId();
   }
+
+  // If we still have an invalid viz::LocalSurfaceId, then we are hidden and
+  // evicted. This will have been triggered by a child acknowledging a previous
+  // synchronization message via DidUpdateVisualProperties. The child has not
+  // prompted any further property changes, so we do not need to continue
+  // syncrhonization. Nor do we want to embed an invalid surface.
+  if (!local_surface_id_allocator_.HasValidLocalSurfaceIdAllocation())
+    return false;
+
   if (delegated_frame_host_) {
     delegated_frame_host_->EmbedSurface(
         local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index c3cf148..b7cfad4 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -354,6 +354,8 @@
   bool HasFallbackSurface() const override;
 
  private:
+  friend class RenderWidgetHostViewAndroidTest;
+
   MouseWheelPhaseHandler* GetMouseWheelPhaseHandler() override;
 
   void EvictDelegatedFrame();
diff --git a/content/browser/renderer_host/render_widget_host_view_android_unittest.cc b/content/browser/renderer_host/render_widget_host_view_android_unittest.cc
new file mode 100644
index 0000000..8f2478e
--- /dev/null
+++ b/content/browser/renderer_host/render_widget_host_view_android_unittest.cc
@@ -0,0 +1,126 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/render_widget_host_view_android.h"
+
+#include <memory>
+
+#include "cc/layers/deadline_policy.h"
+#include "cc/layers/layer.h"
+#include "components/viz/common/surfaces/local_surface_id_allocation.h"
+#include "content/browser/renderer_host/mock_render_widget_host.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/mock_render_widget_host_delegate.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/android/view_android.h"
+
+namespace content {
+
+class RenderWidgetHostViewAndroidTest : public testing::Test {
+ public:
+  RenderWidgetHostViewAndroidTest();
+  ~RenderWidgetHostViewAndroidTest() override {}
+
+  RenderWidgetHostViewAndroid* render_widget_host_view_android() {
+    return render_widget_host_view_android_;
+  }
+
+  // Directly map to RenderWidgetHostViewAndroid methods.
+  bool SynchronizeVisualProperties(
+      const cc::DeadlinePolicy& deadline_policy,
+      const base::Optional<viz::LocalSurfaceIdAllocation>&
+          child_local_surface_id_allocation);
+  void WasEvicted();
+
+ protected:
+  // testing::Test:
+  void SetUp() override;
+  void TearDown() override;
+
+ private:
+  std::unique_ptr<TestBrowserContext> browser_context_;
+  MockRenderProcessHost* process_;  // Deleted automatically by the widget.
+  std::unique_ptr<MockRenderWidgetHostDelegate> delegate_;
+  scoped_refptr<cc::Layer> parent_layer_;
+  scoped_refptr<cc::Layer> layer_;
+  ui::ViewAndroid parent_view_;
+  ui::ViewAndroid native_view_;
+  std::unique_ptr<MockRenderWidgetHost> host_;
+  RenderWidgetHostViewAndroid* render_widget_host_view_android_;
+
+  TestBrowserThreadBundle thread_bundle_;
+
+  DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroidTest);
+};
+
+RenderWidgetHostViewAndroidTest::RenderWidgetHostViewAndroidTest()
+    : parent_view_(ui::ViewAndroid::LayoutType::NORMAL),
+      native_view_(ui::ViewAndroid::LayoutType::NORMAL) {}
+
+bool RenderWidgetHostViewAndroidTest::SynchronizeVisualProperties(
+    const cc::DeadlinePolicy& deadline_policy,
+    const base::Optional<viz::LocalSurfaceIdAllocation>&
+        child_local_surface_id_allocation) {
+  return render_widget_host_view_android_->SynchronizeVisualProperties(
+      deadline_policy, child_local_surface_id_allocation);
+}
+
+void RenderWidgetHostViewAndroidTest::WasEvicted() {
+  render_widget_host_view_android_->WasEvicted();
+}
+
+void RenderWidgetHostViewAndroidTest::SetUp() {
+  browser_context_.reset(new TestBrowserContext());
+  delegate_.reset(new MockRenderWidgetHostDelegate());
+  process_ = new MockRenderProcessHost(browser_context_.get());
+  host_.reset(MockRenderWidgetHost::Create(delegate_.get(), process_,
+                                           process_->GetNextRoutingID()));
+  parent_layer_ = cc::Layer::Create();
+  parent_view_.SetLayer(parent_layer_);
+  layer_ = cc::Layer::Create();
+  native_view_.SetLayer(layer_);
+  parent_view_.AddChild(&native_view_);
+  EXPECT_EQ(&parent_view_, native_view_.parent());
+  render_widget_host_view_android_ =
+      new RenderWidgetHostViewAndroid(host_.get(), &native_view_);
+}
+
+void RenderWidgetHostViewAndroidTest::TearDown() {
+  render_widget_host_view_android_->Destroy();
+  host_.reset();
+  delegate_.reset();
+  process_ = nullptr;
+  browser_context_.reset();
+}
+
+// Tests that when a child responds to a Surface Synchronization message, while
+// we are evicted, that we do not attempt to embed an invalid
+// viz::LocalSurfaceId. This test should not crash.
+TEST_F(RenderWidgetHostViewAndroidTest, NoSurfaceSynchronizationWhileEvicted) {
+  // Android default host and views initialize as visible.
+  RenderWidgetHostViewAndroid* rwhva = render_widget_host_view_android();
+  EXPECT_TRUE(rwhva->IsShowing());
+  const viz::LocalSurfaceIdAllocation initial_allocation =
+      rwhva->GetLocalSurfaceIdAllocation();
+  EXPECT_TRUE(initial_allocation.local_surface_id().is_valid());
+
+  // Evicting while hidden should invalidate the current viz::LocalSurfaceId.
+  rwhva->Hide();
+  EXPECT_FALSE(rwhva->IsShowing());
+  WasEvicted();
+  EXPECT_FALSE(
+      rwhva->GetLocalSurfaceIdAllocation().local_surface_id().is_valid());
+
+  // When a child acknowledges a Surface Synchronization message, and has no new
+  // properties to change, it responds with the original viz::LocalSurfaceId.
+  // If we are evicted, we should not attempt to embed our invalid id. Nor
+  // should we continue the synchronization process. This should not cause a
+  // crash in DelegatedFrameHostAndroid.
+  EXPECT_FALSE(SynchronizeVisualProperties(
+      cc::DeadlinePolicy::UseDefaultDeadline(), initial_allocation));
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 45c4dfa..a232ab0 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1596,13 +1596,20 @@
 void RenderWidgetHostViewAura::OnDisplayMetricsChanged(
     const display::Display& display,
     uint32_t metrics) {
-  // The screen info should be updated regardless of the metric change.
   display::Screen* screen = display::Screen::GetScreen();
-  if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
-    UpdateScreenInfo(window_);
-    current_cursor_.SetDisplayInfo(display);
-    UpdateCursorIfOverSelf();
+  if (display.id() != screen->GetDisplayNearestWindow(window_).id())
+    return;
+
+  if (window_->GetHost() && window_->GetHost()->device_scale_factor() !=
+                                display.device_scale_factor()) {
+    // The DisplayMetrics changed, but the Compositor hasn't been updated yet.
+    // Delay updating until the Compositor is updated as well, otherwise we
+    // are likely to hit surface invariants (LocalSurfaceId generated with a
+    // size/scale-factor that differs from scale-factor used by Compositor).
+    needs_to_update_display_metrics_ = true;
+    return;
   }
+  ProcessDisplayMetricsChanged();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1665,6 +1672,9 @@
   if (!window_->GetRootWindow())
     return;
 
+  if (needs_to_update_display_metrics_)
+    ProcessDisplayMetricsChanged();
+
   SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
                               window_->GetLocalSurfaceIdAllocation());
 
@@ -2683,8 +2693,20 @@
   host()->GetContentRenderingTimeoutFrom(view_aura->host());
 }
 
+bool RenderWidgetHostViewAura::CanSynchronizeVisualProperties() {
+  return !needs_to_update_display_metrics_;
+}
+
 void RenderWidgetHostViewAura::InvalidateLocalSurfaceIdOnEviction() {
   window_->InvalidateLocalSurfaceId();
 }
 
+void RenderWidgetHostViewAura::ProcessDisplayMetricsChanged() {
+  needs_to_update_display_metrics_ = false;
+  UpdateScreenInfo(window_);
+  current_cursor_.SetDisplayInfo(
+      display::Screen::GetScreen()->GetDisplayNearestWindow(window_));
+  UpdateCursorIfOverSelf();
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index c78259d5..23740d7 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -204,9 +204,9 @@
   void OnSynchronizedDisplayPropertiesChanged() override;
   viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
       const cc::RenderFrameMetadata& metadata) override;
-
   void DidNavigate() override;
   void TakeFallbackContentFrom(RenderWidgetHostView* view) override;
+  bool CanSynchronizeVisualProperties() override;
 
   // Overridden from ui::TextInputClient:
   void SetCompositionText(const ui::CompositionText& composition) override;
@@ -578,6 +578,9 @@
 
   void InvalidateLocalSurfaceIdOnEviction();
 
+  // Called to process a display metrics change.
+  void ProcessDisplayMetricsChanged();
+
   const bool is_mus_browser_plugin_guest_;
 
   // NOTE: this is null if |is_mus_browser_plugin_guest_| is true.
@@ -713,6 +716,9 @@
   bool is_first_navigation_ = true;
   viz::LocalSurfaceIdAllocation inset_surface_id_allocation_;
 
+  // See OnDisplayMetricsChanged() for details.
+  bool needs_to_update_display_metrics_ = false;
+
   base::WeakPtrFactory<RenderWidgetHostViewAura> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura);
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 71d20f15..067e2c7 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
@@ -97,8 +97,8 @@
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_observer.h"
 #include "ui/base/clipboard/clipboard.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_factory.h"
 #include "ui/base/ime/input_method_keyboard_controller.h"
 #include "ui/base/ime/mock_input_method.h"
 #include "ui/base/ui_base_features.h"
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index e43c594..3e24a03 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -761,6 +761,10 @@
   }
 }
 
+bool RenderWidgetHostViewBase::CanSynchronizeVisualProperties() {
+  return true;
+}
+
 void RenderWidgetHostViewBase::TextInputStateChanged(
     const TextInputState& text_input_state) {
   if (GetTextInputManager())
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 4535431a..2d0fb4ae 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -450,6 +450,11 @@
   // should be called before the WebContents is fully destroyed.
   virtual void OnInterstitialPageGoingAway() {}
 
+  // Returns true if the visual properties should be sent to the renderer at
+  // this time. This function is intended for subclasses to suppress
+  // synchronization, the default implementation returns true.
+  virtual bool CanSynchronizeVisualProperties();
+
   //----------------------------------------------------------------------------
   // The following methods are related to IME.
   // TODO(ekaramad): Most of the IME methods should not stay virtual after IME
diff --git a/content/browser/serial/serial_browsertest.cc b/content/browser/serial/serial_browsertest.cc
index 2428037..361bd9d7 100644
--- a/content/browser/serial/serial_browsertest.cc
+++ b/content/browser/serial/serial_browsertest.cc
@@ -14,7 +14,6 @@
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -26,55 +25,6 @@
 
 namespace {
 
-class FakeSerialPort : public device::mojom::SerialPort {
- public:
-  FakeSerialPort(device::mojom::SerialPortConnectionWatcherPtr watcher)
-      : watcher_(std::move(watcher)) {}
-  ~FakeSerialPort() override = default;
-
-  // device::mojom::SerialPort
-  void Open(device::mojom::SerialConnectionOptionsPtr options,
-            mojo::ScopedDataPipeConsumerHandle in_stream,
-            mojo::ScopedDataPipeProducerHandle out_stream,
-            device::mojom::SerialPortClientAssociatedPtrInfo client,
-            OpenCallback callback) override {
-    in_stream_ = std::move(in_stream);
-    out_stream_ = std::move(out_stream);
-    client_ = std::move(client);
-    std::move(callback).Run(true);
-  }
-  void ClearSendError(mojo::ScopedDataPipeConsumerHandle consumer) override {
-    NOTREACHED();
-  }
-  void ClearReadError(mojo::ScopedDataPipeProducerHandle producer) override {
-    NOTREACHED();
-  }
-  void Flush(FlushCallback callback) override { NOTREACHED(); }
-  void GetControlSignals(GetControlSignalsCallback callback) override {
-    NOTREACHED();
-  }
-  void SetControlSignals(device::mojom::SerialHostControlSignalsPtr signals,
-                         SetControlSignalsCallback callback) override {
-    NOTREACHED();
-  }
-  void ConfigurePort(device::mojom::SerialConnectionOptionsPtr options,
-                     ConfigurePortCallback callback) override {
-    NOTREACHED();
-  }
-  void GetPortInfo(GetPortInfoCallback callback) override { NOTREACHED(); }
-  void SetBreak(SetBreakCallback callback) override { NOTREACHED(); }
-  void ClearBreak(ClearBreakCallback callback) override { NOTREACHED(); }
-
- private:
-  // Mojo handles to keep open in order to simulate an active connection.
-  device::mojom::SerialPortConnectionWatcherPtr watcher_;
-  mojo::ScopedDataPipeConsumerHandle in_stream_;
-  mojo::ScopedDataPipeProducerHandle out_stream_;
-  device::mojom::SerialPortClientAssociatedPtrInfo client_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeSerialPort);
-};
-
 class FakeSerialPortManager : public device::mojom::SerialPortManager {
  public:
   FakeSerialPortManager() = default;
@@ -94,12 +44,7 @@
   }
 
   void GetPort(const base::UnguessableToken& token,
-               device::mojom::SerialPortRequest request,
-               device::mojom::SerialPortConnectionWatcherPtr watcher) override {
-    mojo::MakeStrongBinding(
-        std::make_unique<FakeSerialPort>(std::move(watcher)),
-        std::move(request));
-  }
+               device::mojom::SerialPortRequest request) override {}
 
  private:
   std::map<base::UnguessableToken, device::mojom::SerialPortInfoPtr> ports_;
@@ -195,9 +140,15 @@
       .WillOnce(Return(false))
       .WillOnce(Return(true));
 
-  EXPECT_EQ(
-      2, EvalJs(shell(),
-                R"(navigator.serial.getPorts().then(ports => ports.length))"));
+  int result;
+  EXPECT_TRUE(ExecuteScriptAndExtractInt(
+      shell(),
+      "navigator.serial.getPorts()"
+      "    .then(ports => {"
+      "        domAutomationController.send(ports.length);"
+      "    });",
+      &result));
+  EXPECT_EQ(2, result);
 }
 
 IN_PROC_BROWSER_TEST_F(SerialTest, RequestPort) {
@@ -208,53 +159,17 @@
   EXPECT_CALL(delegate(), RunChooserInternal)
       .WillOnce(Return(ByMove(std::move(port))));
 
-  EXPECT_EQ(true, EvalJs(shell(),
-                         R"((async () => {
-                           let port = await navigator.serial.requestPort({});
-                           return port instanceof SerialPort;
-                         })())"));
-}
-
-IN_PROC_BROWSER_TEST_F(SerialTest, OpenAndClosePort) {
-  NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html"));
-
-  auto port = device::mojom::SerialPortInfo::New();
-  port->token = base::UnguessableToken::Create();
-  port_manager()->AddPort(std::move(port));
-
-  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(true));
-
-  EXPECT_FALSE(shell()->web_contents()->IsConnectedToSerialPort());
-  EXPECT_EQ(nullptr, EvalJs(shell(),
-                            R"((async () => {
-                              let ports = await navigator.serial.getPorts();
-                              window.port = ports[0];
-                              await window.port.open({});
-                            })())"));
-  EXPECT_TRUE(shell()->web_contents()->IsConnectedToSerialPort());
-  EXPECT_EQ(nullptr, EvalJs(shell(), "window.port.close()"));
-  EXPECT_FALSE(shell()->web_contents()->IsConnectedToSerialPort());
-}
-
-IN_PROC_BROWSER_TEST_F(SerialTest, OpenAndNavigate) {
-  NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html"));
-
-  auto port = device::mojom::SerialPortInfo::New();
-  port->token = base::UnguessableToken::Create();
-  port_manager()->AddPort(std::move(port));
-
-  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(true));
-
-  EXPECT_FALSE(shell()->web_contents()->IsConnectedToSerialPort());
-  EXPECT_EQ(nullptr, EvalJs(shell(),
-                            R"((async () => {
-                              let ports = await navigator.serial.getPorts();
-                              await ports[0].open({});
-                            })())"));
-  EXPECT_TRUE(shell()->web_contents()->IsConnectedToSerialPort());
-
-  NavigateToURL(shell(), GetTestUrl(nullptr, "simple_page.html"));
-  EXPECT_FALSE(shell()->web_contents()->IsConnectedToSerialPort());
+  bool result;
+  EXPECT_TRUE(
+      ExecuteScriptAndExtractBool(shell(),
+                                  "navigator.serial.requestPort({})"
+                                  "    .then(port => {"
+                                  "        domAutomationController.send(true);"
+                                  "    }, error => {"
+                                  "        domAutomationController.send(false);"
+                                  "    });",
+                                  &result));
+  EXPECT_TRUE(result);
 }
 
 }  // namespace content
diff --git a/content/browser/serial/serial_service.cc b/content/browser/serial/serial_service.cc
index e4b7c9d0..d62e9ece 100644
--- a/content/browser/serial/serial_service.cc
+++ b/content/browser/serial/serial_service.cc
@@ -6,15 +6,11 @@
 
 #include <utility>
 
-#include "base/bind.h"
 #include "base/callback.h"
-#include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/serial_chooser.h"
 #include "content/public/browser/serial_delegate.h"
-#include "content/public/browser/web_contents.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"
 
 namespace content {
@@ -40,15 +36,9 @@
     : render_frame_host_(render_frame_host) {
   DCHECK(render_frame_host_->IsFeatureEnabled(
       blink::mojom::FeaturePolicyFeature::kSerial));
-  watchers_.set_connection_error_handler(base::BindRepeating(
-      &SerialService::OnWatcherConnectionError, base::Unretained(this)));
 }
 
-SerialService::~SerialService() {
-  // The remaining watchers will be closed from this end.
-  if (!watchers_.empty())
-    DecrementActiveFrameCount();
-}
+SerialService::~SerialService() = default;
 
 void SerialService::Bind(blink::mojom::SerialServiceRequest request) {
   bindings_.AddBinding(this, std::move(request));
@@ -82,24 +72,6 @@
                      weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void SerialService::GetPort(const base::UnguessableToken& token,
-                            device::mojom::SerialPortRequest request) {
-  SerialDelegate* delegate = GetContentClient()->browser()->GetSerialDelegate();
-  if (!delegate)
-    return;
-
-  if (watchers_.empty()) {
-    auto* web_contents_impl = static_cast<WebContentsImpl*>(
-        WebContents::FromRenderFrameHost(render_frame_host_));
-    web_contents_impl->IncrementSerialActiveFrameCount();
-  }
-
-  device::mojom::SerialPortConnectionWatcherPtr watcher;
-  watchers_.AddBinding(this, mojo::MakeRequest(&watcher));
-  delegate->GetPortManager(render_frame_host_)
-      ->GetPort(token, std::move(request), std::move(watcher));
-}
-
 void SerialService::FinishGetPorts(
     GetPortsCallback callback,
     std::vector<device::mojom::SerialPortInfoPtr> ports) {
@@ -129,15 +101,4 @@
   std::move(callback).Run(ToBlinkType(*port));
 }
 
-void SerialService::OnWatcherConnectionError() {
-  if (watchers_.empty())
-    DecrementActiveFrameCount();
-}
-
-void SerialService::DecrementActiveFrameCount() {
-  auto* web_contents_impl = static_cast<WebContentsImpl*>(
-      WebContents::FromRenderFrameHost(render_frame_host_));
-  web_contents_impl->DecrementSerialActiveFrameCount();
-}
-
 }  // namespace content
diff --git a/content/browser/serial/serial_service.h b/content/browser/serial/serial_service.h
index 12378db..81c8048 100644
--- a/content/browser/serial/serial_service.h
+++ b/content/browser/serial/serial_service.h
@@ -19,8 +19,7 @@
 class RenderFrameHost;
 class SerialChooser;
 
-class SerialService : public blink::mojom::SerialService,
-                      public device::mojom::SerialPortConnectionWatcher {
+class SerialService : public blink::mojom::SerialService {
  public:
   explicit SerialService(RenderFrameHost* render_frame_host);
   ~SerialService() override;
@@ -31,16 +30,12 @@
   void GetPorts(GetPortsCallback callback) override;
   void RequestPort(std::vector<blink::mojom::SerialPortFilterPtr> filters,
                    RequestPortCallback callback) override;
-  void GetPort(const base::UnguessableToken& token,
-               device::mojom::SerialPortRequest request) override;
 
  private:
   void FinishGetPorts(GetPortsCallback callback,
                       std::vector<device::mojom::SerialPortInfoPtr> ports);
   void FinishRequestPort(RequestPortCallback callback,
                          device::mojom::SerialPortInfoPtr port);
-  void OnWatcherConnectionError();
-  void DecrementActiveFrameCount();
 
   RenderFrameHost* const render_frame_host_;
   mojo::BindingSet<blink::mojom::SerialService> bindings_;
@@ -48,10 +43,6 @@
   // The last shown serial port chooser UI.
   std::unique_ptr<SerialChooser> chooser_;
 
-  // Each pipe here watches a connection created by GetPort() in order to notify
-  // the WebContentsImpl when an active connection indicator should be shown.
-  mojo::BindingSet<device::mojom::SerialPortConnectionWatcher> watchers_;
-
   base::WeakPtrFactory<SerialService> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(SerialService);
diff --git a/content/browser/service_worker/service_worker_navigation_loader.cc b/content/browser/service_worker/service_worker_navigation_loader.cc
index 1ba0cc47..580f7bb 100644
--- a/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -43,16 +43,6 @@
   return stream.str();
 }
 
-bool BodyHasNoDataPipeGetters(const network::ResourceRequestBody* body) {
-  if (!body)
-    return true;
-  for (const auto& elem : *body->elements()) {
-    if (elem.type() == network::mojom::DataElementType::kDataPipe)
-      return false;
-  }
-  return true;
-}
-
 }  // namespace
 
 // This class waits for completion of a stream response from the service worker.
@@ -208,16 +198,6 @@
     return;
   }
 
-  // Passing the request body over Mojo moves out the DataPipeGetter elements,
-  // which would mean we should clone the body like
-  // ServiceWorkerSubresourceLoader does. But we don't expect DataPipeGetters
-  // here yet: they are only created by the renderer when converting from a
-  // Blob, which doesn't happen for navigations. In interest of speed, just
-  // don't clone until proven necessary.
-  DCHECK(BodyHasNoDataPipeGetters(resource_request_.request_body.get()))
-      << "We assumed there would be no data pipe getter elements here, but "
-         "there are. Add code here to clone the body before proceeding.";
-
   if (!provider_host_) {
     // We lost |provider_host_| (for the client) somehow before dispatching
     // FetchEvent.
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job.cc b/content/browser/service_worker/service_worker_read_from_cache_job.cc
deleted file mode 100644
index a6e95ff..0000000
--- a/content/browser/service_worker/service_worker_read_from_cache_job.cc
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/service_worker/service_worker_read_from_cache_job.h"
-
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
-#include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/browser/service_worker/service_worker_metrics.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_status.h"
-
-namespace content {
-
-ServiceWorkerReadFromCacheJob::ServiceWorkerReadFromCacheJob(
-    net::URLRequest* request,
-    net::NetworkDelegate* network_delegate,
-    ResourceType resource_type,
-    base::WeakPtr<ServiceWorkerContextCore> context,
-    const scoped_refptr<ServiceWorkerVersion>& version,
-    int64_t resource_id)
-    : net::URLRequestJob(request, network_delegate),
-      resource_type_(resource_type),
-      resource_id_(resource_id),
-      context_(context),
-      version_(version),
-      weak_factory_(this) {
-  DCHECK(version_);
-#if DCHECK_IS_ON()
-  switch (version_->script_type()) {
-    case blink::mojom::ScriptType::kClassic:
-      // For classic scripts, the main service worker script should have the
-      // "service worker" resource type and imported scripts should have the
-      // "script" resource type.
-      DCHECK(resource_type_ == RESOURCE_TYPE_SCRIPT ||
-             (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER &&
-              version_->script_url() == request_->url()));
-      break;
-    case blink::mojom::ScriptType::kModule:
-      // For module scripts, both the main service worker script and
-      // static-imported scripts should have the "service worker" resource type
-      // because static import inherits the resource type of the top-level
-      // module script.
-      DCHECK_EQ(RESOURCE_TYPE_SERVICE_WORKER, resource_type_);
-      break;
-  }
-#endif  // DCHECK_IS_ON()
-  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("ServiceWorker",
-                                    "ServiceWorkerReadFromCacheJob", this,
-                                    "URL", request_->url().spec());
-}
-
-ServiceWorkerReadFromCacheJob::~ServiceWorkerReadFromCacheJob() {
-  TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker",
-                                  "ServiceWorkerReadFromCacheJob", this);
-}
-
-void ServiceWorkerReadFromCacheJob::Start() {
-  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "ReadInfo", this);
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&ServiceWorkerReadFromCacheJob::StartAsync,
-                                weak_factory_.GetWeakPtr()));
-}
-
-void ServiceWorkerReadFromCacheJob::Kill() {
-  TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("ServiceWorker", "Kill", this);
-  if (has_been_killed_)
-    return;
-  weak_factory_.InvalidateWeakPtrs();
-  has_been_killed_ = true;
-  reader_.reset();
-  context_.reset();
-  http_info_io_buffer_ = nullptr;
-  http_info_.reset();
-  range_response_info_.reset();
-  net::URLRequestJob::Kill();
-}
-
-net::LoadState ServiceWorkerReadFromCacheJob::GetLoadState() const {
-  if (reader_.get() && reader_->IsReadPending())
-    return net::LOAD_STATE_READING_RESPONSE;
-  return net::LOAD_STATE_IDLE;
-}
-
-bool ServiceWorkerReadFromCacheJob::GetCharset(std::string* charset) {
-  if (!http_info())
-    return false;
-  return http_info()->headers->GetCharset(charset);
-}
-
-bool ServiceWorkerReadFromCacheJob::GetMimeType(std::string* mime_type) const {
-  if (!http_info())
-    return false;
-  return http_info()->headers->GetMimeType(mime_type);
-}
-
-void ServiceWorkerReadFromCacheJob::GetResponseInfo(
-    net::HttpResponseInfo* info) {
-  if (!http_info())
-    return;
-  *info = *http_info();
-}
-
-void ServiceWorkerReadFromCacheJob::SetExtraRequestHeaders(
-      const net::HttpRequestHeaders& headers) {
-  std::string value;
-  std::vector<net::HttpByteRange> ranges;
-  if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &value) ||
-      !net::HttpUtil::ParseRangeHeader(value, &ranges)) {
-    return;
-  }
-
-  // If multiple ranges are requested, we play dumb and
-  // return the entire response with 200 OK.
-  if (ranges.size() == 1U)
-    range_requested_ = ranges[0];
-}
-
-int ServiceWorkerReadFromCacheJob::ReadRawData(net::IOBuffer* buf,
-                                               int buf_size) {
-  DCHECK_NE(buf_size, 0);
-  DCHECK(!reader_->IsReadPending());
-  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("ServiceWorker", "ReadRawData", this,
-                                    "buf_size", buf_size);
-  reader_->ReadData(
-      buf, buf_size,
-      base::BindOnce(&ServiceWorkerReadFromCacheJob::OnReadComplete,
-                     weak_factory_.GetWeakPtr()));
-  return net::ERR_IO_PENDING;
-}
-
-void ServiceWorkerReadFromCacheJob::StartAsync() {
-  TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("ServiceWorker", "StartAsync", this);
-  if (!context_) {
-    // NotifyStartError is not safe to call synchronously in Start.
-    NotifyStartError(
-        net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED));
-    return;
-  }
-
-  // Create a response reader and start reading the headers,
-  // we'll continue when thats done.
-  if (is_main_script())
-    version_->embedded_worker()->OnScriptReadStarted();
-  reader_ = context_->storage()->CreateResponseReader(resource_id_);
-  http_info_io_buffer_ = new HttpResponseInfoIOBuffer;
-  reader_->ReadInfo(
-      http_info_io_buffer_.get(),
-      base::BindOnce(&ServiceWorkerReadFromCacheJob::OnReadInfoComplete,
-                     weak_factory_.GetWeakPtr()));
-}
-
-const net::HttpResponseInfo* ServiceWorkerReadFromCacheJob::http_info() const {
-  if (!http_info_)
-    return nullptr;
-  if (range_response_info_)
-    return range_response_info_.get();
-  return http_info_.get();
-}
-
-void ServiceWorkerReadFromCacheJob::OnReadInfoComplete(int result) {
-  if (!http_info_io_buffer_->http_info) {
-    DCHECK_LT(result, 0);
-    ServiceWorkerMetrics::CountReadResponseResult(
-        ServiceWorkerMetrics::READ_HEADERS_ERROR);
-    Done(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
-    NotifyStartError(
-        net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
-    return;
-  }
-  DCHECK_GE(result, 0);
-  http_info_.reset(http_info_io_buffer_->http_info.release());
-  if (is_range_request())
-    SetupRangeResponse(http_info_io_buffer_->response_data_size);
-  http_info_io_buffer_ = nullptr;
-  if (is_main_script())
-    version_->SetMainScriptHttpResponseInfo(*http_info_);
-  TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "ReadInfo", this, "Result",
-                                  result);
-  NotifyHeadersComplete();
-}
-
-void ServiceWorkerReadFromCacheJob::SetupRangeResponse(int resource_size) {
-  DCHECK(is_range_request() && http_info_.get() && reader_.get());
-  if (resource_size < 0 || !range_requested_.ComputeBounds(resource_size)) {
-    range_requested_ = net::HttpByteRange();
-    return;
-  }
-
-  DCHECK(range_requested_.IsValid());
-  int offset = static_cast<int>(range_requested_.first_byte_position());
-  int length = static_cast<int>(range_requested_.last_byte_position() -
-                                range_requested_.first_byte_position() + 1);
-
-  // Tell the reader about the range to read.
-  reader_->SetReadRange(offset, length);
-
-  // Make a copy of the full response headers and fix them up
-  // for the range we'll be returning.
-  range_response_info_.reset(new net::HttpResponseInfo(*http_info_));
-  net::HttpResponseHeaders* headers = range_response_info_->headers.get();
-  headers->UpdateWithNewRange(
-      range_requested_, resource_size, true /* replace status line */);
-}
-
-void ServiceWorkerReadFromCacheJob::Done(const net::URLRequestStatus& status) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (!status.is_success()) {
-    version_->SetStartWorkerStatusCode(
-        blink::ServiceWorkerStatusCode::kErrorDiskCache);
-    // TODO(falken): Retry before evicting.
-    if (context_) {
-      ServiceWorkerRegistration* registration =
-          context_->GetLiveRegistration(version_->registration_id());
-      registration->DeleteVersion(version_);
-    }
-  }
-  if (is_main_script())
-    version_->embedded_worker()->OnScriptReadFinished();
-}
-
-void ServiceWorkerReadFromCacheJob::OnReadComplete(int result) {
-  ServiceWorkerMetrics::ReadResponseResult check_result;
-
-  if (result >= 0) {
-    check_result = ServiceWorkerMetrics::READ_OK;
-    if (result == 0)
-      Done(net::URLRequestStatus());
-  } else {
-    check_result = ServiceWorkerMetrics::READ_DATA_ERROR;
-    Done(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
-  }
-
-  TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "ReadRawData", this,
-                                  "Result", result);
-  ServiceWorkerMetrics::CountReadResponseResult(check_result);
-  ReadRawDataComplete(result);
-}
-
-}  // namespace content
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job.h b/content/browser/service_worker/service_worker_read_from_cache_job.h
deleted file mode 100644
index c2aa051..0000000
--- a/content/browser/service_worker/service_worker_read_from_cache_job.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_READ_FROM_CACHE_JOB_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_READ_FROM_CACHE_JOB_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/common/content_export.h"
-#include "content/public/common/resource_type.h"
-#include "net/http/http_byte_range.h"
-#include "net/url_request/url_request_job.h"
-
-namespace content {
-
-class ServiceWorkerContextCore;
-class ServiceWorkerResponseReader;
-class ServiceWorkerVersion;
-
-// A URLRequestJob derivative used to retrieve script resources
-// from the service workers script cache. It uses a response reader
-// and pipes the response to the consumer of this url request job.
-class CONTENT_EXPORT ServiceWorkerReadFromCacheJob
-    : public net::URLRequestJob {
- public:
-  ServiceWorkerReadFromCacheJob(
-      net::URLRequest* request,
-      net::NetworkDelegate* network_delegate,
-      ResourceType resource_type,
-      base::WeakPtr<ServiceWorkerContextCore> context,
-      const scoped_refptr<ServiceWorkerVersion>& version,
-      int64_t resource_id);
-  ~ServiceWorkerReadFromCacheJob() override;
-
- private:
-  friend class ServiceWorkerReadFromCacheJobTest;
-
-  bool is_main_script() const {
-    return resource_type_ == RESOURCE_TYPE_SERVICE_WORKER;
-  }
-
-  // net::URLRequestJob overrides
-  void Start() override;
-  void Kill() override;
-  net::LoadState GetLoadState() const override;
-  bool GetCharset(std::string* charset) override;
-  bool GetMimeType(std::string* mime_type) const override;
-  void GetResponseInfo(net::HttpResponseInfo* info) override;
-  void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
-  int ReadRawData(net::IOBuffer* buf, int buf_size) override;
-
-  // Reader completion callbacks.
-  void OnReadInfoComplete(int result);
-  void OnReadComplete(int result);
-
-  // Helpers
-  void StartAsync();
-  const net::HttpResponseInfo* http_info() const;
-  bool is_range_request() const { return range_requested_.IsValid(); }
-  void SetupRangeResponse(int response_data_size);
-  void Done(const net::URLRequestStatus& status);
-
-  const ResourceType resource_type_;
-  const int64_t resource_id_;
-
-  base::WeakPtr<ServiceWorkerContextCore> context_;
-  scoped_refptr<ServiceWorkerVersion> version_;
-  std::unique_ptr<ServiceWorkerResponseReader> reader_;
-  scoped_refptr<HttpResponseInfoIOBuffer> http_info_io_buffer_;
-  std::unique_ptr<net::HttpResponseInfo> http_info_;
-  net::HttpByteRange range_requested_;
-  std::unique_ptr<net::HttpResponseInfo> range_response_info_;
-  bool has_been_killed_ = false;
-
-  base::WeakPtrFactory<ServiceWorkerReadFromCacheJob> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerReadFromCacheJob);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_READ_FROM_CACHE_JOB_H_
diff --git a/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc b/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
deleted file mode 100644
index 5417d3cf..0000000
--- a/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
+++ /dev/null
@@ -1,278 +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/service_worker/service_worker_read_from_cache_job.h"
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/run_loop.h"
-#include "base/stl_util.h"
-#include "content/browser/service_worker/embedded_worker_test_helper.h"
-#include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_registration.h"
-#include "content/browser/service_worker/service_worker_test_utils.h"
-#include "content/browser/service_worker/service_worker_version.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/base/io_buffer.h"
-#include "net/base/test_completion_callback.h"
-#include "net/http/http_response_headers.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_job_factory_impl.h"
-#include "net/url_request/url_request_status.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
-
-namespace content {
-
-namespace {
-
-const int64_t kRegistrationId = 1;
-const int64_t kVersionId = 2;
-const int64_t kMainScriptResourceId = 10;
-const int64_t kImportedScriptResourceId = 11;
-const int64_t kNonExistentResourceId = 12;
-const int64_t kResourceSize = 100;
-
-void DidStoreRegistration(blink::ServiceWorkerStatusCode* status_out,
-                          base::OnceClosure quit_closure,
-                          blink::ServiceWorkerStatusCode status) {
-  *status_out = status;
-  std::move(quit_closure).Run();
-}
-
-void DidFindRegistration(
-    blink::ServiceWorkerStatusCode* status_out,
-    base::OnceClosure quit_closure,
-    blink::ServiceWorkerStatusCode status,
-    scoped_refptr<ServiceWorkerRegistration> registration) {
-  *status_out = status;
-  std::move(quit_closure).Run();
-}
-
-}  // namespace
-
-class ServiceWorkerReadFromCacheJobTest : public testing::Test {
- public:
-  ServiceWorkerReadFromCacheJobTest()
-      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
-        main_script_(kMainScriptResourceId,
-                     GURL("http://example.com/main.js"),
-                     kResourceSize),
-        imported_script_(kImportedScriptResourceId,
-                         GURL("http://example.com/imported.js"),
-                         kResourceSize),
-        test_job_interceptor_(nullptr) {}
-  ~ServiceWorkerReadFromCacheJobTest() override {}
-
-  void SetUp() override {
-    helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
-    InitializeStorage();
-
-    url_request_context_.reset(new net::TestURLRequestContext(true));
-
-    // The |test_job_factory_| takes ownership of the interceptor.
-    test_job_interceptor_ = new net::TestJobInterceptor();
-    EXPECT_TRUE(test_job_factory_.SetProtocolHandler(
-        url::kHttpScheme, base::WrapUnique(test_job_interceptor_)));
-    url_request_context_->set_job_factory(&test_job_factory_);
-
-    url_request_context_->Init();
-  }
-
-  void InitializeStorage() {
-    base::RunLoop run_loop;
-    context()->storage()->LazyInitializeForTest(run_loop.QuitClosure());
-    run_loop.Run();
-
-    // Populate a registration in the storage.
-    blink::mojom::ServiceWorkerRegistrationOptions options;
-    options.scope = GURL("http://example.com/scope");
-    registration_ = new ServiceWorkerRegistration(options, kRegistrationId,
-                                                  context()->AsWeakPtr());
-    version_ = new ServiceWorkerVersion(registration_.get(), main_script_.url,
-                                        blink::mojom::ScriptType::kClassic,
-                                        kVersionId, context()->AsWeakPtr());
-    std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
-    resources.push_back(main_script_);
-    resources.push_back(imported_script_);
-    version_->script_cache_map()->SetResources(resources);
-    version_->set_fetch_handler_existence(
-        ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
-    ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, StoreRegistration());
-    ASSERT_TRUE(WriteResource(main_script_.resource_id));
-    ASSERT_TRUE(WriteResource(imported_script_.resource_id));
-  }
-
-  bool WriteResource(int64_t resource_id) {
-    const char kHttpHeaders[] = "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
-    const char kHttpBody[] = "Hello";
-    const int length = base::size(kHttpBody);
-    std::string headers(kHttpHeaders, base::size(kHttpHeaders));
-    scoped_refptr<net::IOBuffer> body =
-        base::MakeRefCounted<net::WrappedIOBuffer>(kHttpBody);
-
-    std::unique_ptr<ServiceWorkerResponseWriter> writer =
-        context()->storage()->CreateResponseWriter(resource_id);
-
-    std::unique_ptr<net::HttpResponseInfo> info =
-        std::make_unique<net::HttpResponseInfo>();
-    info->request_time = base::Time::Now();
-    info->response_time = base::Time::Now();
-    info->was_cached = false;
-    info->headers = new net::HttpResponseHeaders(headers);
-    scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
-        base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(info));
-    {
-      net::TestCompletionCallback cb;
-      writer->WriteInfo(info_buffer.get(), cb.callback());
-      int rv = cb.WaitForResult();
-      if (rv < 0)
-        return false;
-    }
-    {
-      net::TestCompletionCallback cb;
-      writer->WriteData(body.get(), length, cb.callback());
-      int rv = cb.WaitForResult();
-      if (rv < 0)
-        return false;
-    }
-    return true;
-  }
-
-  blink::ServiceWorkerStatusCode StoreRegistration() {
-    base::RunLoop run_loop;
-    blink::ServiceWorkerStatusCode status =
-        blink::ServiceWorkerStatusCode::kErrorFailed;
-    context()->storage()->StoreRegistration(
-        registration_.get(), version_.get(),
-        base::BindOnce(&DidStoreRegistration, &status, run_loop.QuitClosure()));
-    run_loop.Run();
-    return status;
-  }
-
-  blink::ServiceWorkerStatusCode FindRegistration() {
-    base::RunLoop run_loop;
-    blink::ServiceWorkerStatusCode status =
-        blink::ServiceWorkerStatusCode::kErrorFailed;
-    context()->storage()->FindRegistrationForId(
-        registration_->id(), registration_->scope().GetOrigin(),
-        base::BindOnce(&DidFindRegistration, &status, run_loop.QuitClosure()));
-    run_loop.Run();
-    return status;
-  }
-
-  void StartAndWaitForRequest(net::URLRequest* request) {
-    request->Start();
-    // net::TestDelegate quits the loop when the request is completed.
-    base::RunLoop().RunUntilIdle();
-  }
-
-  blink::ServiceWorkerStatusCode DeduceStartWorkerFailureReason(
-      blink::ServiceWorkerStatusCode default_code) {
-    return version_->DeduceStartWorkerFailureReason(default_code);
-  }
-
-  ServiceWorkerContextCore* context() const { return helper_->context(); }
-
- protected:
-  TestBrowserThreadBundle thread_bundle_;
-  std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
-
-  scoped_refptr<ServiceWorkerRegistration> registration_;
-  scoped_refptr<ServiceWorkerVersion> version_;
-  ServiceWorkerDatabase::ResourceRecord main_script_;
-  ServiceWorkerDatabase::ResourceRecord imported_script_;
-
-  // |test_job_interceptor_| is owned by |test_job_factory_|.
-  net::TestJobInterceptor* test_job_interceptor_;
-  net::URLRequestJobFactoryImpl test_job_factory_;
-
-  std::unique_ptr<net::TestURLRequestContext> url_request_context_;
-  net::TestDelegate delegate_;
-};
-
-TEST_F(ServiceWorkerReadFromCacheJobTest, ReadMainScript) {
-  // Read the main script from the diskcache.
-  std::unique_ptr<net::URLRequest> request =
-      url_request_context_->CreateRequest(main_script_.url,
-                                          net::DEFAULT_PRIORITY, &delegate_,
-                                          TRAFFIC_ANNOTATION_FOR_TESTS);
-  test_job_interceptor_->set_main_intercept_job(
-      std::make_unique<ServiceWorkerReadFromCacheJob>(
-          request.get(), nullptr /* NetworkDelegate */,
-          RESOURCE_TYPE_SERVICE_WORKER, context()->AsWeakPtr(), version_,
-          main_script_.resource_id));
-  StartAndWaitForRequest(request.get());
-
-  EXPECT_EQ(net::URLRequestStatus::SUCCESS, request->status().status());
-  EXPECT_EQ(0, request->status().error());
-  EXPECT_EQ(
-      blink::ServiceWorkerStatusCode::kOk,
-      DeduceStartWorkerFailureReason(blink::ServiceWorkerStatusCode::kOk));
-}
-
-TEST_F(ServiceWorkerReadFromCacheJobTest, ReadImportedScript) {
-  // Read the imported script from the diskcache.
-  std::unique_ptr<net::URLRequest> request =
-      url_request_context_->CreateRequest(imported_script_.url,
-                                          net::DEFAULT_PRIORITY, &delegate_,
-                                          TRAFFIC_ANNOTATION_FOR_TESTS);
-  test_job_interceptor_->set_main_intercept_job(
-      std::make_unique<ServiceWorkerReadFromCacheJob>(
-          request.get(), nullptr /* NetworkDelegate */, RESOURCE_TYPE_SCRIPT,
-          context()->AsWeakPtr(), version_, imported_script_.resource_id));
-  StartAndWaitForRequest(request.get());
-
-  EXPECT_EQ(net::URLRequestStatus::SUCCESS, request->status().status());
-  EXPECT_EQ(0, request->status().error());
-  EXPECT_EQ(
-      blink::ServiceWorkerStatusCode::kOk,
-      DeduceStartWorkerFailureReason(blink::ServiceWorkerStatusCode::kOk));
-}
-
-TEST_F(ServiceWorkerReadFromCacheJobTest, ResourceNotFound) {
-  ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, FindRegistration());
-
-  // Populate the script cache map with a nonexistent resource.
-  ServiceWorkerScriptCacheMap* script_cache_map = version_->script_cache_map();
-  script_cache_map->resource_map_.clear();
-  using Record = ServiceWorkerDatabase::ResourceRecord;
-  std::vector<Record> resources = {
-      Record(kNonExistentResourceId, main_script_.url, main_script_.size_bytes),
-      Record(imported_script_.resource_id, imported_script_.url,
-             imported_script_.size_bytes)};
-  script_cache_map->SetResources(resources);
-
-  // Attempt to read it from the disk cache.
-  std::unique_ptr<net::URLRequest> request =
-      url_request_context_->CreateRequest(main_script_.url,
-                                          net::DEFAULT_PRIORITY, &delegate_,
-                                          TRAFFIC_ANNOTATION_FOR_TESTS);
-  const int64_t kNonexistentResourceId = 100;
-  test_job_interceptor_->set_main_intercept_job(
-      std::make_unique<ServiceWorkerReadFromCacheJob>(
-          request.get(), nullptr /* NetworkDelegate */,
-          RESOURCE_TYPE_SERVICE_WORKER, context()->AsWeakPtr(), version_,
-          kNonexistentResourceId));
-  StartAndWaitForRequest(request.get());
-
-  EXPECT_EQ(net::URLRequestStatus::FAILED, request->status().status());
-  EXPECT_EQ(net::ERR_CACHE_MISS, request->status().error());
-  EXPECT_EQ(
-      blink::ServiceWorkerStatusCode::kErrorDiskCache,
-      DeduceStartWorkerFailureReason(blink::ServiceWorkerStatusCode::kOk));
-
-  // The version should be doomed by the job.
-  EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
-  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound, FindRegistration());
-}
-
-}  // namespace content
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 8940566..e870f17 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -140,6 +140,8 @@
 
 #if defined(USE_AURA)
 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
 #endif
 
 #if defined(OS_MACOSX)
@@ -999,6 +1001,11 @@
   test_screen->CreateHostForPrimaryDisplay();
   test_screen->SetDeviceScaleFactor(expected_dip_scale);
 
+  // This forces |expected_dip_scale| to be applied to the aura::WindowTreeHost
+  // and aura::Window.
+  aura::WindowTreeHost* window_tree_host = shell()->window()->GetHost();
+  window_tree_host->SetBoundsInPixels(window_tree_host->GetBoundsInPixels());
+
   double device_scale_factor = 0;
   // Wait until dppx becomes 2 if the frame's dpr hasn't beeen updated
   // to 2 yet.
diff --git a/content/browser/speech/tts_mac.mm b/content/browser/speech/tts_mac.mm
index 90bd14f..02f87148 100644
--- a/content/browser/speech/tts_mac.mm
+++ b/content/browser/speech/tts_mac.mm
@@ -73,6 +73,7 @@
   void OnSpeechEvent(NSSpeechSynthesizer* sender,
                      content::TtsEventType event_type,
                      int char_index,
+                     int char_length,
                      const std::string& error_message);
 
   // Get the single instance of this class.
@@ -255,6 +256,7 @@
 void TtsPlatformImplMac::OnSpeechEvent(NSSpeechSynthesizer* sender,
                                        content::TtsEventType event_type,
                                        int char_index,
+                                       int char_length,
                                        const std::string& error_message) {
   // Don't send events from an utterance that's already completed.
   // This depends on the fact that we construct a new NSSpeechSynthesizer
@@ -265,9 +267,8 @@
   if (event_type == content::TTS_EVENT_END)
     char_index = utterance_.size();
 
-  // TODO: Use mac's word length here.
   content::TtsController::GetInstance()->OnTtsEvent(
-      utterance_id_, event_type, char_index, -1, error_message);
+      utterance_id_, event_type, char_index, char_length, error_message);
   last_char_index_ = char_index;
 }
 
@@ -296,7 +297,7 @@
 
 - (void)speechSynthesizer:(NSSpeechSynthesizer*)sender
         didFinishSpeaking:(BOOL)finished_speaking {
-  ttsImplMac_->OnSpeechEvent(sender, content::TTS_EVENT_END, 0, "");
+  ttsImplMac_->OnSpeechEvent(sender, content::TTS_EVENT_END, 0, -1, "");
 }
 
 - (void)speechSynthesizer:(NSSpeechSynthesizer*)sender
@@ -308,7 +309,7 @@
     return;
 
   ttsImplMac_->OnSpeechEvent(sender, content::TTS_EVENT_WORD,
-                             word_range.location, "");
+                             word_range.location, word_range.length, "");
 }
 
 - (void)speechSynthesizer:(NSSpeechSynthesizer*)sender
@@ -322,7 +323,7 @@
 
   std::string message_utf8 = base::SysNSStringToUTF8(message);
   ttsImplMac_->OnSpeechEvent(sender, content::TTS_EVENT_ERROR, character_index,
-                             message_utf8);
+                             -1, message_utf8);
 }
 
 @end
diff --git a/content/browser/speech/tts_win.cc b/content/browser/speech/tts_win.cc
index e4eb7748..6a7e8fd 100644
--- a/content/browser/speech/tts_win.cc
+++ b/content/browser/speech/tts_win.cc
@@ -70,6 +70,7 @@
   int prefix_len_;
   ULONG stream_number_;
   int char_position_;
+  int char_length_;
   bool paused_;
   std::string last_voice_name_;
 
@@ -124,6 +125,7 @@
   utterance_ = base::UTF8ToWide(src_utterance);
   utterance_id_ = utterance_id;
   char_position_ = 0;
+  char_length_ = 0;
   std::wstring merged_utterance = prefix + utterance_ + suffix;
   prefix_len_ = prefix.size();
 
@@ -253,9 +255,9 @@
         break;
       case SPEI_WORD_BOUNDARY:
         char_position_ = static_cast<ULONG>(event.lParam) - prefix_len_;
-        // TODO: Get length of win word from win specific tts things.
+        char_length_ = static_cast<ULONG>(event.wParam);
         controller->OnTtsEvent(utterance_id_, TTS_EVENT_WORD, char_position_,
-                               -1, std::string());
+                               char_length_, std::string());
         break;
       case SPEI_SENTENCE_BOUNDARY:
         char_position_ = static_cast<ULONG>(event.lParam) - prefix_len_;
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index adaa2a713..a0eae6e 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -53,7 +53,6 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "net/base/completion_callback.h"
 #include "net/base/features.h"
 #include "net/base/net_errors.h"
 #include "net/cookies/canonical_cookie.h"
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 19426d69..8d3bd79 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -583,6 +583,7 @@
           GetContentClient()->browser()->GetAXModeForBrowserContext(
               browser_context)),
       audio_stream_monitor_(this),
+      bluetooth_connected_device_count_(0),
       media_web_contents_observer_(
           std::make_unique<MediaWebContentsObserver>(this)),
       media_device_group_id_salt_base_(
@@ -1541,10 +1542,6 @@
   return bluetooth_connected_device_count_ > 0;
 }
 
-bool WebContentsImpl::IsConnectedToSerialPort() const {
-  return serial_active_frame_count_ > 0;
-}
-
 bool WebContentsImpl::HasPictureInPictureVideo() {
   return has_picture_in_picture_video_;
 }
@@ -6716,31 +6713,6 @@
   }
 }
 
-void WebContentsImpl::IncrementSerialActiveFrameCount() {
-  // Trying to invalidate the tab state while being destroyed could result in a
-  // use after free.
-  if (IsBeingDestroyed())
-    return;
-
-  // Notify for UI updates if the state changes.
-  serial_active_frame_count_++;
-  if (serial_active_frame_count_ == 1)
-    NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
-}
-
-void WebContentsImpl::DecrementSerialActiveFrameCount() {
-  // Trying to invalidate the tab state while being destroyed could result in a
-  // use after free.
-  if (IsBeingDestroyed())
-    return;
-
-  // Notify for UI updates if the state changes.
-  DCHECK_NE(0u, serial_active_frame_count_);
-  serial_active_frame_count_--;
-  if (serial_active_frame_count_ == 0)
-    NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
-}
-
 void WebContentsImpl::SetHasPersistentVideo(bool has_persistent_video) {
   if (has_persistent_video_ == has_persistent_video)
     return;
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 1c255230..3fb7ee650 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -344,7 +344,6 @@
   void SetAudioMuted(bool mute) override;
   bool IsCurrentlyAudible() override;
   bool IsConnectedToBluetoothDevice() override;
-  bool IsConnectedToSerialPort() const override;
   bool HasPictureInPictureVideo() override;
   bool IsCrashed() override;
   void SetIsCrashed(base::TerminationStatus status, int error_code) override;
@@ -938,11 +937,6 @@
   void IncrementBluetoothConnectedDeviceCount();
   void DecrementBluetoothConnectedDeviceCount();
 
-  // Modify the counter of frames in this WebContents actively using serial
-  // ports.
-  void IncrementSerialActiveFrameCount();
-  void DecrementSerialActiveFrameCount();
-
   // Called when the WebContents gains or loses a persistent video.
   void SetHasPersistentVideo(bool has_persistent_video);
 
@@ -1762,8 +1756,7 @@
   // Created on-demand to mute all audio output from this WebContents.
   std::unique_ptr<WebContentsAudioMuter> audio_muter_;
 
-  size_t bluetooth_connected_device_count_ = 0;
-  size_t serial_active_frame_count_ = 0;
+  size_t bluetooth_connected_device_count_;
 
   bool has_picture_in_picture_video_ = false;
 
diff --git a/content/browser/web_package/signed_exchange_handler.h b/content/browser/web_package/signed_exchange_handler.h
index 5f61b93..93a2fb94 100644
--- a/content/browser/web_package/signed_exchange_handler.h
+++ b/content/browser/web_package/signed_exchange_handler.h
@@ -16,7 +16,6 @@
 #include "content/browser/web_package/signed_exchange_prologue.h"
 #include "content/common/content_export.h"
 #include "mojo/public/cpp/system/data_pipe.h"
-#include "net/base/completion_callback.h"
 #include "net/cert/cert_verifier.h"
 #include "net/cert/cert_verify_result.h"
 #include "net/log/net_log_with_source.h"
diff --git a/content/browser/webui/web_ui_url_loader_factory.cc b/content/browser/webui/web_ui_url_loader_factory.cc
index 63fe012..d6462a4 100644
--- a/content/browser/webui/web_ui_url_loader_factory.cc
+++ b/content/browser/webui/web_ui_url_loader_factory.cc
@@ -226,7 +226,9 @@
       : WebContentsObserver(WebContents::FromRenderFrameHost(rfh)),
         render_frame_host_(rfh),
         scheme_(scheme),
-        allowed_hosts_(std::move(allowed_hosts)) {}
+        allowed_hosts_(std::move(allowed_hosts)) {
+    DCHECK(render_frame_host_);
+  }
 
   ~WebUIURLLoaderFactory() override {}
 
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc
index 68cff2ae0..2b2882c 100644
--- a/content/child/blink_platform_impl.cc
+++ b/content/child/blink_platform_impl.cc
@@ -452,6 +452,8 @@
      ui::SCALE_FACTOR_NONE, true},
     {"inspect_tool_common.js", IDR_INSPECT_TOOL_COMMON_JS,
      ui::SCALE_FACTOR_NONE, true},
+    {"inspect_tool_distances.html", IDR_INSPECT_TOOL_DISTANCES_HTML,
+     ui::SCALE_FACTOR_NONE, true},
     {"inspect_tool_highlight.html", IDR_INSPECT_TOOL_HIGHLIGHT_HTML,
      ui::SCALE_FACTOR_NONE, true},
     {"inspect_tool_paused.html", IDR_INSPECT_TOOL_PAUSED_HTML,
diff --git a/content/public/browser/gpu_utils.cc b/content/public/browser/gpu_utils.cc
index 29197660..c4b61f9 100644
--- a/content/public/browser/gpu_utils.cc
+++ b/content/public/browser/gpu_utils.cc
@@ -13,6 +13,7 @@
 #include "build/build_config.h"
 #include "cc/base/switches.h"
 #include "components/viz/common/features.h"
+#include "components/viz/common/viz_utils.h"
 #include "content/browser/browser_main_loop.h"
 #include "content/browser/gpu/gpu_process_host.h"
 #include "content/public/common/content_features.h"
@@ -56,6 +57,8 @@
 #if !defined(OS_ANDROID)
   return false;
 #else
+  if (viz::PreferRGB565ResourcesForDisplay())
+    return false;
   return features::IsAndroidSurfaceControlEnabled();
 #endif
 }
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 6cf2ca2..b33d118 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -474,10 +474,6 @@
   // Device.
   virtual bool IsConnectedToBluetoothDevice() = 0;
 
-  // Indicates whether any frame in the WebContents is connected to a serial
-  // port.
-  virtual bool IsConnectedToSerialPort() const = 0;
-
   // Indicates whether a video is in Picture-in-Picture for |this|.
   virtual bool HasPictureInPictureVideo() = 0;
 
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h
index f16b90c..89356971 100644
--- a/content/public/renderer/render_frame_observer.h
+++ b/content/public/renderer/render_frame_observer.h
@@ -22,6 +22,7 @@
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
 #include "third_party/blink/public/platform/web_loading_behavior_flag.h"
 #include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/public/web/web_meaningful_layout.h"
 #include "third_party/blink/public/web/web_navigation_type.h"
 #include "ui/base/page_transition_types.h"
@@ -171,6 +172,13 @@
   // summing the jank fractions.
   virtual void DidObserveLayoutJank(double jank_fraction) {}
 
+  // Reports lazy loaded behavior when the frame or image is fully deferred or
+  // if the frame or image is loaded after being deferred by lazy load.
+  // Called every time the behavior occurs. This does not apply to image
+  // requests for placeholder images.
+  virtual void DidObserveLazyLoadBehavior(
+      blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) {}
+
   // Notification when the renderer a response started, completed or canceled.
   // Complete or Cancel is guaranteed to be called for a response that started.
   // |request_id| uniquely identifies the request within this render frame.
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/TestThreadUtils.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/TestThreadUtils.java
index 01dc2ce..d38a13e 100644
--- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/TestThreadUtils.java
+++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/TestThreadUtils.java
@@ -6,6 +6,8 @@
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.task.PostTask;
+import org.chromium.base.task.SingleThreadTaskRunner;
+import org.chromium.base.task.TaskTraits;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 
 import java.util.concurrent.Callable;
@@ -23,11 +25,23 @@
      * @param r The Runnable to run.
      */
     public static void runOnUiThreadBlocking(final Runnable r) {
-        if (ThreadUtils.runningOnUiThread()) {
+        runBlockingWithTraits(UiThreadTaskTraits.DEFAULT, r);
+    }
+
+    /**
+     * Run the supplied Runnable with the provided traits. The method will block until the Runnable
+     * completes.
+     *
+     * @param traits The Traits to run.
+     * @param r The Runnable to run.
+     */
+    public static void runBlockingWithTraits(final TaskTraits traits, final Runnable r) {
+        SingleThreadTaskRunner taskRunner = PostTask.createSingleThreadTaskRunner(traits);
+        if (taskRunner.belongsToCurrentThread()) {
             r.run();
         } else {
             FutureTask<Void> task = new FutureTask<Void>(r, null);
-            PostTask.postTask(UiThreadTaskTraits.DEFAULT, task);
+            taskRunner.postTask(task);
             try {
                 task.get();
             } catch (Exception e) {
@@ -60,8 +74,22 @@
      * @throws ExecutionException c's exception
      */
     public static <T> T runOnUiThreadBlocking(Callable<T> c) throws ExecutionException {
+        return runBlockingWithTraits(UiThreadTaskTraits.DEFAULT, c);
+    }
+
+    /**
+     * Run the supplied Callable with the given task traits, The method will block until the
+     * Callable completes.
+     *
+     * @param traits The Traits to run
+     * @param c The Callable to run
+     * @return The result of the callable
+     * @throws ExecutionException c's exception
+     */
+    public static <T> T runBlockingWithTraits(final TaskTraits traits, Callable<T> c)
+            throws ExecutionException {
         FutureTask<T> task = new FutureTask<T>(c);
-        PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, task);
+        PostTask.runOrPostTask(traits, task);
         try {
             return task.get();
         } catch (InterruptedException e) {
diff --git a/content/public/test/content_browser_test.cc b/content/public/test/content_browser_test.cc
index a19fc29..a61629a 100644
--- a/content/public/test/content_browser_test.cc
+++ b/content/public/test/content_browser_test.cc
@@ -31,7 +31,7 @@
 #endif
 
 #if !defined(OS_CHROMEOS) && defined(OS_LINUX)
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #endif
 
 #if defined(OS_CHROMEOS)
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.cc b/content/renderer/loader/web_worker_fetch_context_impl.cc
index 8e2748f2..704ae6c8 100644
--- a/content/renderer/loader/web_worker_fetch_context_impl.cc
+++ b/content/renderer/loader/web_worker_fetch_context_impl.cc
@@ -399,7 +399,7 @@
     request.SetURL(g_rewrite_url(request.Url().GetString().Utf8(), false));
 
   if (!renderer_preferences_.enable_referrers) {
-    request.SetHTTPReferrer(blink::WebString(),
+    request.SetHttpReferrer(blink::WebString(),
                             network::mojom::ReferrerPolicy::kDefault);
   }
 }
diff --git a/content/renderer/media/webrtc/rtc_certificate_generator.cc b/content/renderer/media/webrtc/rtc_certificate_generator.cc
index 63da8da..a57e278 100644
--- a/content/renderer/media/webrtc/rtc_certificate_generator.cc
+++ b/content/renderer/media/webrtc/rtc_certificate_generator.cc
@@ -44,10 +44,6 @@
 // request alive independently of the |RTCCertificateGenerator| that spawned it.
 class RTCCertificateGeneratorRequest
     : public base::RefCountedThreadSafe<RTCCertificateGeneratorRequest> {
- private:
-  using CertificateCallbackPtr = std::unique_ptr<
-     blink::WebRTCCertificateCallback,
-     base::OnTaskRunnerDeleter>;
  public:
   RTCCertificateGeneratorRequest(
       const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
@@ -61,17 +57,15 @@
   void GenerateCertificateAsync(
       const blink::WebRTCKeyParams& key_params,
       const absl::optional<uint64_t>& expires_ms,
-      std::unique_ptr<blink::WebRTCCertificateCallback> observer) {
+      blink::WebRTCCertificateCallback completion_callback) {
     DCHECK(main_thread_->BelongsToCurrentThread());
-    DCHECK(observer);
+    DCHECK(completion_callback);
 
-    CertificateCallbackPtr transition(observer.release(),
-                                      base::OnTaskRunnerDeleter(main_thread_));
     worker_thread_->PostTask(
         FROM_HERE,
         base::BindOnce(
             &RTCCertificateGeneratorRequest::GenerateCertificateOnWorkerThread,
-            this, key_params, expires_ms, std::move(transition)));
+            this, key_params, expires_ms, std::move(completion_callback)));
   }
 
  private:
@@ -81,7 +75,7 @@
   void GenerateCertificateOnWorkerThread(
       const blink::WebRTCKeyParams key_params,
       const absl::optional<uint64_t> expires_ms,
-      CertificateCallbackPtr observer) {
+      blink::WebRTCCertificateCallback completion_callback) {
     DCHECK(worker_thread_->BelongsToCurrentThread());
 
     rtc::scoped_refptr<rtc::RTCCertificate> certificate =
@@ -91,18 +85,15 @@
     main_thread_->PostTask(
         FROM_HERE,
         base::BindOnce(&RTCCertificateGeneratorRequest::DoCallbackOnMainThread,
-                       this, std::move(observer), certificate));
+                       this, std::move(completion_callback), certificate));
   }
 
   void DoCallbackOnMainThread(
-      CertificateCallbackPtr observer,
+      blink::WebRTCCertificateCallback completion_callback,
       rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
     DCHECK(main_thread_->BelongsToCurrentThread());
-    DCHECK(observer);
-    if (certificate)
-      observer->OnSuccess(std::move(certificate));
-    else
-      observer->OnError();
+    DCHECK(completion_callback);
+    std::move(completion_callback).Run(std::move(certificate));
   }
 
   // The main thread is the renderer thread.
@@ -114,7 +105,7 @@
 void GenerateCertificateWithOptionalExpiration(
     const blink::WebRTCKeyParams& key_params,
     const absl::optional<uint64_t>& expires_ms,
-    std::unique_ptr<blink::WebRTCCertificateCallback> observer,
+    blink::WebRTCCertificateCallback completion_callback,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   DCHECK(WebRTCKeyParamsToKeyParams(key_params).IsValid());
   PeerConnectionDependencyFactory* pc_dependency_factory =
@@ -125,26 +116,26 @@
       new RTCCertificateGeneratorRequest(
           task_runner, pc_dependency_factory->GetWebRtcWorkerThread());
   request->GenerateCertificateAsync(key_params, expires_ms,
-                                    std::move(observer));
+                                    std::move(completion_callback));
 }
 
 }  // namespace
 
 void RTCCertificateGenerator::GenerateCertificate(
     const blink::WebRTCKeyParams& key_params,
-    std::unique_ptr<blink::WebRTCCertificateCallback> observer,
+    blink::WebRTCCertificateCallback completion_callback,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
-  GenerateCertificateWithOptionalExpiration(key_params, absl::nullopt,
-                                            std::move(observer), task_runner);
+  GenerateCertificateWithOptionalExpiration(
+      key_params, absl::nullopt, std::move(completion_callback), task_runner);
 }
 
 void RTCCertificateGenerator::GenerateCertificateWithExpiration(
     const blink::WebRTCKeyParams& key_params,
     uint64_t expires_ms,
-    std::unique_ptr<blink::WebRTCCertificateCallback> observer,
+    blink::WebRTCCertificateCallback completion_callback,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
-  GenerateCertificateWithOptionalExpiration(key_params, expires_ms,
-                                            std::move(observer), task_runner);
+  GenerateCertificateWithOptionalExpiration(
+      key_params, expires_ms, std::move(completion_callback), task_runner);
 }
 
 bool RTCCertificateGenerator::IsSupportedKeyParams(
diff --git a/content/renderer/media/webrtc/rtc_certificate_generator.h b/content/renderer/media/webrtc/rtc_certificate_generator.h
index 9d520f7..76ce08f8 100644
--- a/content/renderer/media/webrtc/rtc_certificate_generator.h
+++ b/content/renderer/media/webrtc/rtc_certificate_generator.h
@@ -24,12 +24,12 @@
   // blink::WebRTCCertificateGenerator implementation.
   void GenerateCertificate(
       const blink::WebRTCKeyParams& key_params,
-      std::unique_ptr<blink::WebRTCCertificateCallback> observer,
+      blink::WebRTCCertificateCallback completion_callback,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
   void GenerateCertificateWithExpiration(
       const blink::WebRTCKeyParams& key_params,
       uint64_t expires_ms,
-      std::unique_ptr<blink::WebRTCCertificateCallback> observer,
+      blink::WebRTCCertificateCallback completion_callback,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
   bool IsSupportedKeyParams(const blink::WebRTCKeyParams& key_params) override;
   rtc::scoped_refptr<rtc::RTCCertificate> FromPEM(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index d7ba5e2c..2b4d968 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -3847,10 +3847,28 @@
     std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
         subresource_loader_factories) {
   DCHECK(loader_factories_);
-  // TODO(crbug/916625): CHECKing for crbug.com/916625.
-  CHECK(loader_factories_->IsHostChildURLLoaderFactoryBundle());
-  static_cast<HostChildURLLoaderFactoryBundle*>(loader_factories_.get())
-      ->UpdateThisAndAllClones(std::move(subresource_loader_factories));
+  if (loader_factories_->IsHostChildURLLoaderFactoryBundle()) {
+    static_cast<HostChildURLLoaderFactoryBundle*>(loader_factories_.get())
+        ->UpdateThisAndAllClones(std::move(subresource_loader_factories));
+  } else {
+#if DCHECK_IS_ON()
+    // In presence of the NetworkService, this situation should happen only if
+    // the frame hosts a document that isn't related to a real navigation (i.e.
+    // if the frame should "inherit" the factories from its opener/parent - for
+    // example for about:blank or about:srcdoc or about:blank#someHref frames,
+    // or for frames with no URL - like the initial frame opened by window('',
+    // 'popup')).
+    if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+      WebURL url = GetWebFrame()->GetDocument().Url();
+      if (url.IsValid() && !url.IsEmpty())
+        DCHECK(url.ProtocolIs(url::kAboutScheme));
+    }
+#endif
+    auto partial_bundle = base::MakeRefCounted<ChildURLLoaderFactoryBundle>();
+    static_cast<blink::URLLoaderFactoryBundle*>(partial_bundle.get())
+        ->Update(std::move(subresource_loader_factories));
+    loader_factories_->Update(partial_bundle->PassInterface());
+  }
 }
 
 void RenderFrameImpl::MarkInitiatorAsRequiringSeparateURLLoaderFactory(
@@ -5262,7 +5280,7 @@
 
   // Set an empty HTTP origin header for non GET methods if none is currently
   // present.
-  request.SetHTTPOriginIfNeeded(WebSecurityOrigin::CreateUnique());
+  request.SetHttpOriginIfNeeded(WebSecurityOrigin::CreateUnique());
 
   WebDocument frame_document = frame_->GetDocument();
   if (!request.GetExtraData())
@@ -5325,7 +5343,7 @@
       WebUserGestureIndicator::IsProcessingUserGesture(frame_));
 
   if (!render_view_->renderer_preferences_.enable_referrers)
-    request.SetHTTPReferrer(WebString(),
+    request.SetHttpReferrer(WebString(),
                             network::mojom::ReferrerPolicy::kDefault);
 }
 
@@ -5490,6 +5508,12 @@
     observer.DidObserveLayoutJank(jank_fraction);
 }
 
+void RenderFrameImpl::DidObserveLazyLoadBehavior(
+    WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) {
+  for (auto& observer : observers_)
+    observer.DidObserveLazyLoadBehavior(lazy_load_behavior);
+}
+
 bool RenderFrameImpl::ShouldTrackUseCounter(const blink::WebURL& url) {
   return GetContentClient()->renderer()->ShouldTrackUseCounter(url);
 }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index d252198..8c1b740 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -817,6 +817,8 @@
   void DidObserveNewCssPropertyUsage(int css_property,
                                      bool is_animated) override;
   void DidObserveLayoutJank(double jank_fraction) override;
+  void DidObserveLazyLoadBehavior(
+      blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) override;
   bool ShouldTrackUseCounter(const blink::WebURL& url) override;
   void DidCreateScriptContext(v8::Local<v8::Context> context,
                               int world_id) override;
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 e989d73..7ea9dd31 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -111,7 +111,7 @@
   request.SetExtraData(std::move(extra_data));
 
   if (!renderer_preferences_.enable_referrers) {
-    request.SetHTTPReferrer(blink::WebString(),
+    request.SetHttpReferrer(blink::WebString(),
                             network::mojom::ReferrerPolicy::kDefault);
   }
 }
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index 54191a7d..bf3ec5e6 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -339,7 +339,7 @@
     "//third_party/icu",
     "//ui/base",
     "//ui/base/clipboard",
-    "//ui/base/ime",
+    "//ui/base/ime/init",
     "//ui/display",
     "//ui/events:events_base",
     "//ui/gfx",
diff --git a/content/shell/browser/shell_browser_main_parts.cc b/content/shell/browser/shell_browser_main_parts.cc
index 10f1b0c..da56c7036 100644
--- a/content/shell/browser/shell_browser_main_parts.cc
+++ b/content/shell/browser/shell_browser_main_parts.cc
@@ -49,7 +49,7 @@
 #include "ui/events/devices/x11/touch_factory_x11.h"  // nogncheck
 #endif
 #if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(OS_LINUX)
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #endif
 #if defined(OS_CHROMEOS)
 #include "chromeos/dbus/dbus_thread_manager.h"
diff --git a/content/shell/browser/shell_platform_data_aura.cc b/content/shell/browser/shell_platform_data_aura.cc
index d89c2f3..860a1a8 100644
--- a/content/shell/browser/shell_platform_data_aura.cc
+++ b/content/shell/browser/shell_platform_data_aura.cc
@@ -15,9 +15,9 @@
 #include "ui/aura/test/test_window_parenting_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/input_method.h"
 #include "ui/base/ime/input_method_delegate.h"
-#include "ui/base/ime/input_method_factory.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 #include "ui/wm/core/default_activation_client.h"
diff --git a/content/shell/browser/web_test/web_test_browser_main_parts.cc b/content/shell/browser/web_test/web_test_browser_main_parts.cc
index 2f959ccd..27a3d388 100644
--- a/content/shell/browser/web_test/web_test_browser_main_parts.cc
+++ b/content/shell/browser/web_test/web_test_browser_main_parts.cc
@@ -43,7 +43,7 @@
 #include "ui/events/devices/x11/touch_factory_x11.h"  // nogncheck
 #endif
 #if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(OS_LINUX)
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #endif
 
 namespace content {
diff --git a/content/shell/test_runner/test_plugin.cc b/content/shell/test_runner/test_plugin.cc
index 46811de..10a91c9b 100644
--- a/content/shell/test_runner/test_plugin.cc
+++ b/content/shell/test_runner/test_plugin.cc
@@ -315,6 +315,7 @@
         base::BindOnce(&ReleaseSharedMemory, std::move(shared_bitmap_),
                        std::move(registration)));
   }
+  resource->size = gfx::Size(rect_.width, rect_.height);
   content_changed_ = false;
   return true;
 }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 07463cf..6adf3c7 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -53,6 +53,10 @@
     "../browser/media/session/mock_media_session_player_observer.h",
     "../browser/media/session/mock_media_session_service_impl.cc",
     "../browser/media/session/mock_media_session_service_impl.h",
+    "../browser/renderer_host/input/mock_input_router.cc",
+    "../browser/renderer_host/input/mock_input_router.h",
+    "../browser/renderer_host/mock_render_widget_host.cc",
+    "../browser/renderer_host/mock_render_widget_host.h",
     "../browser/service_worker/embedded_worker_test_helper.cc",
     "../browser/service_worker/embedded_worker_test_helper.h",
     "../browser/service_worker/fake_embedded_worker_instance_client.cc",
@@ -579,7 +583,7 @@
     "//testing/gtest",
     "//ui/accessibility:ax_enums_mojo",
     "//ui/base",
-    "//ui/base/ime",
+    "//ui/base/ime/init",
   ]
 
   if (is_android) {
@@ -1677,7 +1681,6 @@
     "../browser/service_worker/service_worker_object_host_unittest.cc",
     "../browser/service_worker/service_worker_process_manager_unittest.cc",
     "../browser/service_worker/service_worker_provider_host_unittest.cc",
-    "../browser/service_worker/service_worker_read_from_cache_job_unittest.cc",
     "../browser/service_worker/service_worker_registration_unittest.cc",
     "../browser/service_worker/service_worker_request_handler_unittest.cc",
     "../browser/service_worker/service_worker_script_loader_factory_unittest.cc",
@@ -2036,7 +2039,7 @@
     "//ui/accessibility:test_support",
     "//ui/base:test_support",
     "//ui/base/clipboard:clipboard_test_support",
-    "//ui/base/ime",
+    "//ui/base/ime/init",
     "//ui/compositor:test_support",
     "//ui/display",
     "//ui/display:test_support",
@@ -2163,6 +2166,7 @@
       "../browser/android/url_request_content_job_unittest.cc",
       "../browser/font_unique_name_lookup/font_unique_name_lookup_unittest.cc",
       "../browser/media/capture/screen_capture_device_android_unittest.cc",
+      "../browser/renderer_host/render_widget_host_view_android_unittest.cc",
       "../renderer/java/gin_java_bridge_value_converter_unittest.cc",
       "../renderer/media/android/stream_texture_wrapper_impl_unittest.cc",
     ]
diff --git a/content/test/data/manifest/parsing-errors-manifest.json b/content/test/data/manifest/parsing-errors-manifest.json
index 92403728..b53ee36d 100644
--- a/content/test/data/manifest/parsing-errors-manifest.json
+++ b/content/test/data/manifest/parsing-errors-manifest.json
@@ -4,5 +4,6 @@
   "start_url": [],
   "orientation": "foobar",
   "display": "tulip",
-  "icons": {}
+  "icons": {},
+  "scope": []
 }
diff --git a/content/test/dwrite_font_fake_sender_win.cc b/content/test/dwrite_font_fake_sender_win.cc
index 2e2db962..7897e50 100644
--- a/content/test/dwrite_font_fake_sender_win.cc
+++ b/content/test/dwrite_font_fake_sender_win.cc
@@ -131,6 +131,9 @@
 void FakeFontCollection::GetUniqueNameLookupTable(
     GetUniqueNameLookupTableCallback callback) {}
 
+void FakeFontCollection::GetUniqueNameLookupTableIfAvailable(
+    GetUniqueNameLookupTableIfAvailableCallback callback) {}
+
 FakeFontCollection::~FakeFontCollection() = default;
 
 }  // namespace content
diff --git a/content/test/dwrite_font_fake_sender_win.h b/content/test/dwrite_font_fake_sender_win.h
index 4ee2c79..f46b250 100644
--- a/content/test/dwrite_font_fake_sender_win.h
+++ b/content/test/dwrite_font_fake_sender_win.h
@@ -119,6 +119,8 @@
                      uint32_t reading_direction,
                      const base::string16& base_family_name,
                      MapCharactersCallback callback) override;
+  void GetUniqueNameLookupTableIfAvailable(
+      GetUniqueNameLookupTableIfAvailableCallback callback) override;
   void GetUniqueNameLookupTable(
       GetUniqueNameLookupTableCallback callback) override;
 
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn
index e91ab33..ea096511 100644
--- a/content/test/fuzzer/BUILD.gn
+++ b/content/test/fuzzer/BUILD.gn
@@ -46,6 +46,8 @@
     "origin_policy_parser_fuzzer.cc",
   ]
   deps = [
+    "//base",
+    "//base:i18n",
     "//content/test:test_support",
   ]
   dict =
diff --git a/content/test/fuzzer/origin_policy_parser_fuzzer.cc b/content/test/fuzzer/origin_policy_parser_fuzzer.cc
index bf9c5f4..875e9ae 100644
--- a/content/test/fuzzer/origin_policy_parser_fuzzer.cc
+++ b/content/test/fuzzer/origin_policy_parser_fuzzer.cc
@@ -4,11 +4,21 @@
 
 #include "third_party/blink/public/common/origin_policy/origin_policy.h"  // nogncheck
 
+#include "base/at_exit.h"
+#include "base/i18n/icu_util.h"
 #include "base/strings/string_piece.h"
 
 #include <stddef.h>
 #include <stdint.h>
 
+struct IcuEnvironment {
+  IcuEnvironment() { CHECK(base::i18n::InitializeICU()); }
+  base::AtExitManager at_exit_manager;
+};
+
+// Initialize ICU, which is required by the URL parser.
+IcuEnvironment* env = new IcuEnvironment();
+
 namespace content {
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
diff --git a/content/test/gpu/gather_swarming_json_results.py b/content/test/gpu/gather_swarming_json_results.py
index 963f8557..d74040c8 100755
--- a/content/test/gpu/gather_swarming_json_results.py
+++ b/content/test/gpu/gather_swarming_json_results.py
@@ -18,35 +18,59 @@
 import urllib2
 
 
-def GetJsonForBuildSteps(bot, build):
+def GetBuildData(method, request):
   # Explorable via RPC explorer:
   # https://cr-buildbucket.appspot.com/rpcexplorer/services/
-  #   buildbucket.v2.Builds/GetBuild
+  #   buildbucket.v2.Builds/{GetBuild|SearchBuilds}
+  assert method in ['GetBuild', 'SearchBuilds']
 
   # The Python docs are wrong. It's fine for this payload to be just
   # a JSON string.
-  call_arg = json.dumps({ 'builder': { 'project': 'chromium',
-                                       'bucket': 'ci',
-                                       'builder': bot },
-                          'buildNumber': build,
-                          'fields': 'steps.*.name,steps.*.logs' })
   headers = {
     'content-type': 'application/json',
     'accept': 'application/json'
   }
-  request = urllib2.Request(
-    'https://cr-buildbucket.appspot.com/prpc/buildbucket.v2.Builds/GetBuild',
-    call_arg,
+  url = urllib2.Request(
+    'https://cr-buildbucket.appspot.com/prpc/buildbucket.v2.Builds/' + method,
+    request,
     headers)
-  conn = urllib2.urlopen(request)
+  conn = urllib2.urlopen(url)
   result = conn.read()
   conn.close()
-
   # Result is a multi-line string the first line of which is
   # deliberate garbage and the rest of which is a JSON payload.
   return json.loads(''.join(result.splitlines()[1:]))
 
 
+def GetJsonForBuildSteps(bot, build):
+  request = json.dumps({ 'builder': { 'project': 'chromium',
+                                      'bucket': 'ci',
+                                      'builder': bot },
+                         'buildNumber': build,
+                         'fields': 'steps.*.name,steps.*.logs' })
+  return GetBuildData('GetBuild', request)
+
+
+def GetJsonForLatestGreenBuildSteps(bot):
+  fields = [
+    'builds.*.number',
+    'builds.*.steps.*.name',
+    'builds.*.steps.*.logs',
+  ]
+  request = json.dumps({ 'predicate': { 'builder': { 'project': 'chromium',
+                                                     'bucket': 'ci',
+                                                     'builder': bot },
+                                        'status': 'SUCCESS' },
+                         'fields': ','.join(fields),
+                         'pageSize': 1 })
+  builds_json = GetBuildData('SearchBuilds', request)
+  if 'builds' not in builds_json:
+    raise ValueError('Returned json data does not have "builds"')
+  builds = builds_json['builds']
+  assert len(builds) == 1
+  return builds[0]
+
+
 def JsonLoadStrippingUnicode(url):
   def StripUnicode(obj):
     if isinstance(obj, unicode):
@@ -109,7 +133,8 @@
   parser.add_argument('--bot', default='Linux FYI Release (NVIDIA)',
                       help='Which bot to examine')
   parser.add_argument('--build', type=int,
-                      help='Which build to fetch (must be specified)')
+                      help='Which build to fetch. If not specified, use '
+                      'the latest successful build.')
   parser.add_argument('--step', default='webgl2_conformance_tests',
                       help='Which step to fetch (treated as a prefix)')
   parser.add_argument('--output', metavar='FILE', default='output.json',
@@ -121,23 +146,23 @@
   if options.verbose:
     logging.basicConfig(level=logging.DEBUG)
 
-  if options.build is None:
-    logging.error('Build number must be specified; check the bot\'s page')
-    return 1
+  build = options.build
+  if build is None:
+    build_json = GetJsonForLatestGreenBuildSteps(options.bot)
+    build = build_json.get('number')
+  else:
+    build_json = GetJsonForBuildSteps(options.bot, build)
 
-  build_json = GetJsonForBuildSteps(options.bot, options.build)
+  logging.debug('Fetched information from bot %s, build %s',
+                options.bot, build)
+
   if 'steps' not in build_json:
-    logging.error('Returned Json data does not have "steps"')
-    return 1
-
-  logging.debug('Fetching information from bot %s, build %s',
-                options.bot, options.build)
+    raise ValueError('Returned Json data do not have "steps"')
 
   json_output = FindStepLogURL(build_json['steps'], options.step, 'json.output')
   if not json_output:
-    logging.error('Unable to find json.output from step starting with %s',
-                  options.step)
-    return 1
+    raise ValueError('Unable to find json.output from step starting with %s' %
+                     options.step)
   logging.debug('json.output for step starting with %s: %s',
                 options.step, json_output)
 
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index d25deec3..d696564d 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -17,7 +17,9 @@
 [ android ] Pixel_OffscreenCanvasWebGLSoftwareCompositing [ Skip ]
 [ android ] Pixel_OffscreenCanvasWebGLSoftwareCompositingWorker [ Skip ]
 [ android ] Pixel_CanvasDisplayLinearRGBUnaccelerated2D [ Skip ]
+[ android ] Pixel_CanvasDisplaySRGBUnaccelerated2D [ Skip ]
 [ android ] Pixel_CanvasDisplayLinearRGBUnaccelerated2DGPUCompositing [ Skip ]
+[ android ] Pixel_CanvasDisplaySRGBUnaccelerated2DGPUCompositing [ Skip ]
 [ android ] Pixel_CanvasDisplaySRGBUnaccelerated2D [ Skip ]
 [ android ] Pixel_CanvasUnacceleratedLowLatency2D [ Skip ]
 [ android ] Pixel_RepeatedWebGLTo2D_SoftwareCompositing [ Skip ]
@@ -119,27 +121,9 @@
 
 crbug.com/868596 [ android nvidia ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ Failure ]
 
-# New tests, mark as failing
-[ win ] Pixel_CanvasDisplaySRGBUnaccelerated2D [ Failure ]
-[ mac ] Pixel_CanvasDisplaySRGBUnaccelerated2D [ Failure ]
-[ linux ] Pixel_CanvasDisplaySRGBUnaccelerated2D [ Failure ]
-[ chromeos ] Pixel_CanvasDisplaySRGBUnaccelerated2D [ Failure ]
-Pixel_CanvasDisplaySRGBUnaccelerated2DGPUCompositing [ Failure ]
-
 # float16 is not yet supported for accelerated canvases
 crbug.com/948141 Pixel_CanvasDisplaySRGBAccelerated2D [ Failure ]
 
-# Color space has changed here so we need to rebaseline
-[ win ] Pixel_CanvasDisplayLinearRGBUnaccelerated2D [ Failure ]
-[ mac ] Pixel_CanvasDisplayLinearRGBUnaccelerated2D [ Failure ]
-[ linux ] Pixel_CanvasDisplayLinearRGBUnaccelerated2D [ Failure ]
-[ chromeos ] Pixel_CanvasDisplayLinearRGBUnaccelerated2D [ Failure ]
-[ win ] Pixel_CanvasDisplayLinearRGBUnaccelerated2DGPUCompositing [ Failure ]
-[ mac ] Pixel_CanvasDisplayLinearRGBUnaccelerated2DGPUCompositing [ Failure ]
-[ linux ] Pixel_CanvasDisplayLinearRGBUnaccelerated2DGPUCompositing [ Failure ]
-[ chromeos ] Pixel_CanvasDisplayLinearRGBUnaccelerated2DGPUCompositing [ Failure ]
-Pixel_CanvasDisplayLinearRGBAccelerated2D [ Failure ]
-
 # Fails on Nexus 5, 6 and 6P
 crbug.com/883500 [ android qualcomm-adreno-(tm)-330 ] Pixel_BackgroundImage [ Failure ]
 crbug.com/883500 [ android qualcomm-adreno-(tm)-420 ] Pixel_BackgroundImage [ Failure ]
@@ -184,36 +168,3 @@
 
 # Complex overlays test is flaky on Nvidia probably due to its small size.
 crbug.com/929425 [ win nvidia ] Pixel_DirectComposition_ComplexOverlays [ RetryOnFailure ]
-
-# Mark as fail all pixel tests on Android WebView before refimgs are
-# generated
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_Canvas2DUntagged [ Failure ]
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_GpuRasterization_BlueBox [ Failure ]
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_GpuRasterization_ConcavePaths [ Failure ]
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_OffscreenCanvasTransferToImageBitmap [ Failure ]
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_OffscreenCanvasTransferToImageBitmapWorker [ Failure ]
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_RepeatedWebGLTo2D [ Failure ]
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_WebGL_PremultipliedAlpha_False [ Failure ]
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_2DCanvasWebGL [ Failure ]
-
-# Uncomment this when crbug.com/927107 is fixed and conflicting expectation
-# above is removed.
-# crbug.com/907935 [ android-webview-instrumentation ] Pixel_CSS3DBlueBox [ Failure ]
-
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_Canvas2DRedBox [ Failure ]
-
-# crbug.com/907935 [ android-webview-instrumentation ] Pixel_CanvasDisplayLinearRGBAccelerated2D [ Failure ]
-
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_CanvasLowLatency2D [ Failure ]
-
-# crbug.com/907935 [ android-webview-instrumentation ] Pixel_CanvasDisplayLinearRGBUnaccelerated2DGPUCompositing [ Failure ]
-
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_WebGLGreenTriangle_AA_Alpha [ Failure ]
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_WebGLGreenTriangle_AA_NoAlpha [ Failure ]
-
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_WebGLGreenTriangle_NoAA_Alpha [ Failure ]
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_WebGLGreenTriangle_NoAA_NoAlpha [ Failure ]
-
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_WebGLTransparentGreenTriangle_NoAlpha_ImplicitClear [ Failure ]
-
-crbug.com/907935 [ android-webview-instrumentation ] Pixel_BackgroundImage [ Failure ]
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index 7cba0a2..5674a3d 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -507,6 +507,8 @@
     self.Fail('conformance/textures/' +
         'image_bitmap_from_canvas/tex-2d-rgb*.html',
         ['win', 'passthrough', 'vulkan', 'amd'], bug=931016)
+    self.Fail('conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html',
+        ['win', 'passthrough', 'vulkan', 'amd'], bug=3343) # ANGLE bug ID
 
     # Mac failures
     self.Fail('conformance/glsl/misc/fragcolor-fragdata-invariant.html',
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc
index 44f0322d..ed2d3fe 100644
--- a/content/test/navigation_simulator_impl.cc
+++ b/content/test/navigation_simulator_impl.cc
@@ -1203,6 +1203,7 @@
       has_user_gesture_ ? NavigationGestureUser : NavigationGestureAuto;
   params->history_list_was_cleared = history_list_was_cleared_;
   params->did_create_new_entry = DidCreateNewEntry();
+  params->should_replace_current_entry = should_replace_current_entry_;
 
   if (failed_navigation) {
     // Note: Error pages must commit in a unique origin. So it is left unset.
diff --git a/content/test/navigation_simulator_impl.h b/content/test/navigation_simulator_impl.h
index 23dfd31c..54ee6b94 100644
--- a/content/test/navigation_simulator_impl.h
+++ b/content/test/navigation_simulator_impl.h
@@ -110,10 +110,16 @@
   // Set DidCommit*Params history_list_was_cleared flag to |history_cleared|.
   void set_history_list_was_cleared(bool history_cleared);
 
-  // Manually force the value of did_create_new__entry flag in DidCommit*Params
+  // Manually force the value of did_create_new_entry flag in DidCommit*Params
   // to |did_create_new_entry|.
   void set_did_create_new_entry(bool did_create_new_entry);
 
+  // Manually force the value of should_replace_current_entry flag in
+  // DidCommit*Params to |should_replace_current_entry|.
+  void set_should_replace_current_entry(bool should_replace_current_entry) {
+    should_replace_current_entry_ = should_replace_current_entry;
+  }
+
   void set_http_connection_info(net::HttpResponseInfo::ConnectionInfo info) {
     http_connection_info_ = info;
   }
@@ -259,6 +265,7 @@
 
   bool history_list_was_cleared_ = false;
   base::Optional<bool> did_create_new_entry_;
+  bool should_replace_current_entry_ = false;
 
   // These are used to sanity check the content/public/ API calls emitted as
   // part of the navigation.
diff --git a/content/test/test_blink_web_unit_test_support.cc b/content/test/test_blink_web_unit_test_support.cc
index 8fc2e274..22a1a27 100644
--- a/content/test/test_blink_web_unit_test_support.cc
+++ b/content/test/test_blink_web_unit_test_support.cc
@@ -320,14 +320,14 @@
     : public blink::WebRTCCertificateGenerator {
   void GenerateCertificate(
       const blink::WebRTCKeyParams& key_params,
-      std::unique_ptr<blink::WebRTCCertificateCallback> callback,
+      blink::WebRTCCertificateCallback completion_callback,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
     NOTIMPLEMENTED();
   }
   void GenerateCertificateWithExpiration(
       const blink::WebRTCKeyParams& key_params,
       uint64_t expires_ms,
-      std::unique_ptr<blink::WebRTCCertificateCallback> callback,
+      blink::WebRTCCertificateCallback completion_callback,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override {
     NOTIMPLEMENTED();
   }
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 38b3e188a..c37656d 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -230,8 +230,8 @@
 void TestRenderFrameHost::SendNavigate(int nav_entry_id,
                                        bool did_create_new_entry,
                                        const GURL& url) {
-  SendNavigateWithParameters(nav_entry_id, did_create_new_entry, false,
-                             url, ui::PAGE_TRANSITION_LINK, 200,
+  SendNavigateWithParameters(nav_entry_id, did_create_new_entry, url,
+                             ui::PAGE_TRANSITION_LINK, 200,
                              ModificationCallback());
 }
 
@@ -240,16 +240,8 @@
     bool did_create_new_entry,
     const GURL& url,
     ui::PageTransition transition) {
-  SendNavigateWithParameters(nav_entry_id, did_create_new_entry, false,
-                             url, transition, 200, ModificationCallback());
-}
-
-void TestRenderFrameHost::SendNavigateWithReplacement(int nav_entry_id,
-                                                      bool did_create_new_entry,
-                                                      const GURL& url) {
-  SendNavigateWithParameters(nav_entry_id, did_create_new_entry, true,
-                             url, ui::PAGE_TRANSITION_LINK, 200,
-                             ModificationCallback());
+  SendNavigateWithParameters(nav_entry_id, did_create_new_entry, url,
+                             transition, 200, ModificationCallback());
 }
 
 void TestRenderFrameHost::SendNavigateWithModificationCallback(
@@ -257,14 +249,13 @@
     bool did_create_new_entry,
     const GURL& url,
     const ModificationCallback& callback) {
-  SendNavigateWithParameters(nav_entry_id, did_create_new_entry, false,
-                             url, ui::PAGE_TRANSITION_LINK, 200, callback);
+  SendNavigateWithParameters(nav_entry_id, did_create_new_entry, url,
+                             ui::PAGE_TRANSITION_LINK, 200, callback);
 }
 
 void TestRenderFrameHost::SendNavigateWithParameters(
     int nav_entry_id,
     bool did_create_new_entry,
-    bool should_replace_entry,
     const GURL& url,
     ui::PageTransition transition,
     int response_code,
@@ -281,9 +272,8 @@
        url.ReplaceComponents(replacements) ==
            GetLastCommittedURL().ReplaceComponents(replacements));
 
-  auto params = BuildDidCommitParams(nav_entry_id, did_create_new_entry,
-                                     should_replace_entry, url, transition,
-                                     response_code);
+  auto params = BuildDidCommitParams(nav_entry_id, did_create_new_entry, url,
+                                     transition, response_code);
 
   if (!callback.is_null())
     callback.Run(params.get());
@@ -581,7 +571,6 @@
 std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
 TestRenderFrameHost::BuildDidCommitParams(int nav_entry_id,
                                           bool did_create_new_entry,
-                                          bool should_replace_entry,
                                           const GURL& url,
                                           ui::PageTransition transition,
                                           int response_code) {
@@ -592,7 +581,7 @@
   params->transition = transition;
   params->should_update_history = true;
   params->did_create_new_entry = did_create_new_entry;
-  params->should_replace_current_entry = should_replace_entry;
+  params->should_replace_current_entry = false;
   params->gesture = NavigationGestureUser;
   params->contents_mime_type = "text/html";
   params->method = "GET";
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h
index 9fd2c619..7d464d6f 100644
--- a/content/test/test_render_frame_host.h
+++ b/content/test/test_render_frame_host.h
@@ -82,10 +82,6 @@
       const std::vector<url::Origin>& whitelist) override;
   const std::vector<std::string>& GetConsoleMessages() override;
 
-  void SendNavigateWithReplacement(int nav_entry_id,
-                                   bool did_create_new_entry,
-                                   const GURL& url);
-
   using ModificationCallback =
       base::Callback<void(FrameHostMsg_DidCommitProvisionalLoad_Params*)>;
 
@@ -244,7 +240,6 @@
  private:
   void SendNavigateWithParameters(int nav_entry_id,
                                   bool did_create_new_entry,
-                                  bool should_replace_entry,
                                   const GURL& url,
                                   ui::PageTransition transition,
                                   int response_code,
@@ -263,7 +258,6 @@
   std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
   BuildDidCommitParams(int nav_entry_id,
                        bool did_create_new_entry,
-                       bool should_replace_entry,
                        const GURL& url,
                        ui::PageTransition transition,
                        int response_code);
diff --git a/courgette/disassembler_win32.cc b/courgette/disassembler_win32.cc
index b89db450..1592c21 100644
--- a/courgette/disassembler_win32.cc
+++ b/courgette/disassembler_win32.cc
@@ -67,7 +67,7 @@
 // structure.
 //
 bool DisassemblerWin32::ParseHeader() {
-  if (length() < kOffsetOfFileAddressOfNewExeHeader + 4 /*size*/)
+  if (!IsRangeInBounds(kOffsetOfFileAddressOfNewExeHeader, 4))
     return Bad("Too small");
 
   // Have 'MZ' magic for a DOS header?
@@ -75,100 +75,98 @@
     return Bad("Not MZ");
 
   // offset from DOS header to PE header is stored in DOS header.
-  FileOffset file_offset = static_cast<FileOffset>(
+  FileOffset pe_header_offset = static_cast<FileOffset>(
       ReadU32(start(), kOffsetOfFileAddressOfNewExeHeader));
-
-  if (file_offset >= length())
-    return Bad("Bad offset to PE header");
-
-  const uint8_t* const pe_header = FileOffsetToPointer(file_offset);
-  const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader;
-  if (pe_header <= start() || pe_header >= end() - kMinPEHeaderSize)
-    return Bad("Bad file offset to PE header");
-
-  if (file_offset % 8 != 0)
+  if (pe_header_offset % 8 != 0)
     return Bad("Misaligned PE header");
+  if (pe_header_offset < kOffsetOfFileAddressOfNewExeHeader + 4)
+    return Bad("PE header pathological overlap");
+  if (!IsRangeInBounds(pe_header_offset, kMinPeHeaderSize))
+    return Bad("PE header past end of file");
+
+  const uint8_t* const pe_header = FileOffsetToPointer(pe_header_offset);
 
   // The 'PE' header is an IMAGE_NT_HEADERS structure as defined in WINNT.H.
   // See http://msdn.microsoft.com/en-us/library/ms680336(VS.85).aspx
   //
   // The first field of the IMAGE_NT_HEADERS is the signature.
   if (!(pe_header[0] == 'P' && pe_header[1] == 'E' && pe_header[2] == 0 &&
-        pe_header[3] == 0))
+        pe_header[3] == 0)) {
     return Bad("No PE signature");
+  }
 
   // The second field of the IMAGE_NT_HEADERS is the COFF header.
   // The COFF header is also called an IMAGE_FILE_HEADER
   //   http://msdn.microsoft.com/en-us/library/ms680313(VS.85).aspx
-  const uint8_t* const coff_header = pe_header + 4;
+  FileOffset coff_header_offset = pe_header_offset + 4;
+  if (!IsRangeInBounds(coff_header_offset, kSizeOfCoffHeader))
+    return Bad("COFF header past end of file");
+  const uint8_t* const coff_header = start() + coff_header_offset;
   machine_type_ = ReadU16(coff_header, 0);
   number_of_sections_ = ReadU16(coff_header, 2);
   size_of_optional_header_ = ReadU16(coff_header, 16);
-
-  // The rest of the IMAGE_NT_HEADERS is the IMAGE_OPTIONAL_HEADER(32|64)
-  const uint8_t* const optional_header = coff_header + kSizeOfCoffHeader;
-  optional_header_ = optional_header;
-
-  if (optional_header + size_of_optional_header_ >= end())
-    return Bad("Optional header past end of file");
-
   // Check we can read the magic.
   if (size_of_optional_header_ < 2)
     return Bad("Optional header no magic");
+  // Check that we can read the rest of the the fixed fields. Data directories
+  // directly follow the fixed fields of the IMAGE_OPTIONAL_HEADER.
+  if (size_of_optional_header_ < RelativeOffsetOfDataDirectories())
+    return Bad("Optional header too short");
 
-  uint16_t magic = ReadU16(optional_header, 0);
+  // The rest of the IMAGE_NT_HEADERS is the IMAGE_OPTIONAL_HEADER(32|64)
+  FileOffset optional_header_offset = pe_header_offset + kMinPeHeaderSize;
+  if (!IsRangeInBounds(optional_header_offset, size_of_optional_header_))
+    return Bad("Optional header past end of file");
+  optional_header_ = start() + optional_header_offset;
 
+  uint16_t magic = ReadU16(optional_header_, 0);
   switch (kind()) {
     case EXE_WIN_32_X86:
-      if (magic != kImageNtOptionalHdr32Magic) {
+      if (magic != kImageNtOptionalHdr32Magic)
         return Bad("64 bit executables are not supported by this disassembler");
-      }
       break;
 
     case EXE_WIN_32_X64:
-      if (magic != kImageNtOptionalHdr64Magic) {
+      if (magic != kImageNtOptionalHdr64Magic)
         return Bad("32 bit executables are not supported by this disassembler");
-      }
       break;
 
     default:
       return Bad("Unrecognized magic");
   }
 
-  // Check that we can read the rest of the the fixed fields.  Data directories
-  // directly follow the fixed fields of the IMAGE_OPTIONAL_HEADER.
-  if (size_of_optional_header_ < OffsetOfDataDirectories())
-    return Bad("Optional header too short");
-
   // The optional header is either an IMAGE_OPTIONAL_HEADER32 or
   // IMAGE_OPTIONAL_HEADER64
   // http://msdn.microsoft.com/en-us/library/ms680339(VS.85).aspx
   //
   // Copy the fields we care about.
-  size_of_code_ = ReadU32(optional_header, 4);
-  size_of_initialized_data_ = ReadU32(optional_header, 8);
-  size_of_uninitialized_data_ = ReadU32(optional_header, 12);
-  base_of_code_ = ReadU32(optional_header, 20);
+  size_of_code_ = ReadU32(optional_header_, 4);
+  size_of_initialized_data_ = ReadU32(optional_header_, 8);
+  size_of_uninitialized_data_ = ReadU32(optional_header_, 12);
+  base_of_code_ = ReadU32(optional_header_, 20);
 
   switch (kind()) {
     case EXE_WIN_32_X86:
-      base_of_data_ = ReadU32(optional_header, 24);
-      image_base_ = ReadU32(optional_header, 28);
-      size_of_image_ = ReadU32(optional_header, 56);
-      number_of_data_directories_ = ReadU32(optional_header, 92);
+      base_of_data_ = ReadU32(optional_header_, 24);
+      image_base_ = ReadU32(optional_header_, 28);
+      size_of_image_ = ReadU32(optional_header_, 56);
+      number_of_data_directories_ = ReadU32(optional_header_, 92);
       break;
 
     case EXE_WIN_32_X64:
       base_of_data_ = 0;
-      image_base_ = ReadU64(optional_header, 24);
-      size_of_image_ = ReadU32(optional_header, 56);
-      number_of_data_directories_ = ReadU32(optional_header, 108);
+      image_base_ = ReadU64(optional_header_, 24);
+      size_of_image_ = ReadU32(optional_header_, 56);
+      number_of_data_directories_ = ReadU32(optional_header_, 108);
       break;
 
     default:
       NOTREACHED();
   }
 
+  if (size_of_image_ >= 0x80000000U)
+    return Bad("Invalid SizeOfImage");
+
   if (size_of_code_ >= length() || size_of_initialized_data_ >= length() ||
       size_of_code_ + size_of_initialized_data_ >= length()) {
     // This validation fires on some perfectly fine executables.
@@ -188,15 +186,19 @@
   b &= ReadDataDirectory(12, &import_address_table_);
   b &= ReadDataDirectory(13, &delay_import_descriptor_);
   b &= ReadDataDirectory(14, &clr_runtime_header_);
-  if (!b) {
+  if (!b)
     return Bad("Malformed data directory");
-  }
 
   // Sections follow the optional header.
-  sections_ = reinterpret_cast<const Section*>(optional_header +
-                                               size_of_optional_header_);
-  size_t detected_length = 0;
+  FileOffset sections_offset =
+      optional_header_offset + size_of_optional_header_;
+  if (!IsArrayInBounds(sections_offset, number_of_sections_, sizeof(Section)))
+    return Bad("Sections past end of file");
+  sections_ = reinterpret_cast<const Section*>(start() + sections_offset);
+  if (!CheckSectionRanges())
+    return Bad("Out of bound section");
 
+  size_t detected_length = 0;
   for (int i = 0; i < number_of_sections_; ++i) {
     const Section* section = &sections_[i];
 
@@ -318,29 +320,47 @@
 bool DisassemblerWin32::QuickDetect(const uint8_t* start,
                                     size_t length,
                                     uint16_t magic) {
-  if (length < kOffsetOfFileAddressOfNewExeHeader + 4 /* size */)
+  if (length < kOffsetOfFileAddressOfNewExeHeader + 4)
     return false;
 
   // Have 'MZ' magic for a DOS header?
   if (start[0] != 'M' || start[1] != 'Z')
     return false;
 
-  FileOffset file_offset = static_cast<FileOffset>(
+  FileOffset pe_header_offset = static_cast<FileOffset>(
       ReadU32(start, kOffsetOfFileAddressOfNewExeHeader));
-  if (file_offset >= length || file_offset % 8 != 0)
+  if (pe_header_offset % 8 != 0 ||
+      pe_header_offset < kOffsetOfFileAddressOfNewExeHeader + 4 ||
+      pe_header_offset >= length ||
+      length - pe_header_offset < kMinPeHeaderSize) {
     return false;
-  const uint8_t* const pe_header = start + file_offset;
-  const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader;
-  if (pe_header <= start || pe_header + kMinPEHeaderSize >= start + length)
+  }
+  const uint8_t* pe_header = start + pe_header_offset;
+  if (!(pe_header[0] == 'P' && pe_header[1] == 'E' && pe_header[2] == 0 &&
+        pe_header[3] == 0)) {
     return false;
+  }
 
-  const uint8_t* optional_header = pe_header + 4 + kSizeOfCoffHeader;
-  // Check we can read the magic.
-  if (optional_header + 2 >= start + length)
+  FileOffset optional_header_offset = pe_header_offset + kMinPeHeaderSize;
+  if (optional_header_offset >= length || length - optional_header_offset < 2)
     return false;
-  if (magic != ReadU16(optional_header, 0))
-    return false;
+  const uint8_t* optional_header = start + optional_header_offset;
+  return magic == ReadU16(optional_header, 0);
+}
 
+bool DisassemblerWin32::IsRvaRangeInBounds(size_t start, size_t length) {
+  return start < size_of_image_ && length <= size_of_image_ - start;
+}
+
+bool DisassemblerWin32::CheckSectionRanges() {
+  for (int i = 0; i < number_of_sections_; ++i) {
+    const Section* section = &sections_[i];
+    if (!IsRangeInBounds(section->file_offset_of_raw_data,
+                         section->size_of_raw_data) ||
+        !IsRvaRangeInBounds(section->virtual_address, section->virtual_size)) {
+      return false;
+    }
+  }
   return true;
 }
 
@@ -647,7 +667,7 @@
 bool DisassemblerWin32::ReadDataDirectory(int index,
                                           ImageDataDirectory* directory) {
   if (index < number_of_data_directories_) {
-    FileOffset file_offset = index * 8 + OffsetOfDataDirectories();
+    FileOffset file_offset = index * 8 + RelativeOffsetOfDataDirectories();
     if (file_offset >= size_of_optional_header_)
       return Bad("Number of data directories inconsistent");
     const uint8_t* data_directory = optional_header_ + file_offset;
diff --git a/courgette/disassembler_win32.h b/courgette/disassembler_win32.h
index d2df58c..da6a16d 100644
--- a/courgette/disassembler_win32.h
+++ b/courgette/disassembler_win32.h
@@ -55,8 +55,11 @@
   // which will be checked against the detected one.
   static bool QuickDetect(const uint8_t* start, size_t length, uint16_t magic);
 
-  bool ParseAbs32Relocs();
-  void ParseRel32RelocsFromSections();
+  // Returns true if the given RVA range lies within [0, |size_of_image_|).
+  bool IsRvaRangeInBounds(size_t start, size_t length);
+
+  // Returns whether all sections lie within image.
+  bool CheckSectionRanges();
 
   // Disassembler interfaces.
   bool ExtractAbs32Locations() override;
@@ -91,7 +94,7 @@
                             InstructionReceptor* receptor) const = 0;
   // Returns true if type is recognized.
   virtual bool SupportsRelTableType(int type) const = 0;
-  virtual uint16_t OffsetOfDataDirectories() const = 0;
+  virtual uint16_t RelativeOffsetOfDataDirectories() const = 0;
 
 #if COURGETTE_HISTOGRAM_TARGETS
   void HistogramTargets(const char* kind, const std::map<RVA, int>& map) const;
@@ -132,6 +135,7 @@
   RVA base_of_data_ = 0;
 
   uint64_t image_base_ = 0;  // Range limited to 32 bits for 32 bit executable.
+  // Specifies size of loaded PE in memory, and provides bound on RVA.
   uint32_t size_of_image_ = 0;
   int number_of_data_directories_ = 0;
 
diff --git a/courgette/disassembler_win32_x64.h b/courgette/disassembler_win32_x64.h
index a5e8317..837c745 100644
--- a/courgette/disassembler_win32_x64.h
+++ b/courgette/disassembler_win32_x64.h
@@ -44,7 +44,7 @@
   bool SupportsRelTableType(int type) const override {
     return type == 10;  // IMAGE_REL_BASED_DIR64
   }
-  uint16_t OffsetOfDataDirectories() const override {
+  uint16_t RelativeOffsetOfDataDirectories() const override {
     return kOffsetOfDataDirectoryFromImageOptionalHeader64;
   }
 
diff --git a/courgette/disassembler_win32_x86.h b/courgette/disassembler_win32_x86.h
index f747ef5..84813e6 100644
--- a/courgette/disassembler_win32_x86.h
+++ b/courgette/disassembler_win32_x86.h
@@ -44,7 +44,7 @@
   bool SupportsRelTableType(int type) const override {
     return type == 3;  // IMAGE_REL_BASED_HIGHLOW
   }
-  uint16_t OffsetOfDataDirectories() const override {
+  uint16_t RelativeOffsetOfDataDirectories() const override {
     return kOffsetOfDataDirectoryFromImageOptionalHeader32;
   }
 
diff --git a/courgette/types_win_pe.h b/courgette/types_win_pe.h
index f926b5f..23aecf8 100644
--- a/courgette/types_win_pe.h
+++ b/courgette/types_win_pe.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 TYPES_WIN_PE_H_
-#define TYPES_WIN_PE_H_
+#ifndef COURGETTE_TYPES_WIN_PE_H_
+#define COURGETTE_TYPES_WIN_PE_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -58,8 +58,10 @@
 const uint16_t kImageNtOptionalHdr64Magic = 0x20b;
 
 const size_t kSizeOfCoffHeader = 20;
+const size_t kMinPeHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader;
 const size_t kOffsetOfDataDirectoryFromImageOptionalHeader32 = 96;
 const size_t kOffsetOfDataDirectoryFromImageOptionalHeader64 = 112;
 
-}  // namespace
-#endif  // TYPES_WIN_PE_H_
+}  // namespace courgette
+
+#endif  // COURGETTE_TYPES_WIN_PE_H_
diff --git a/device/fido/ble/fido_ble_device.cc b/device/fido/ble/fido_ble_device.cc
index fa0013c..29076031 100644
--- a/device/fido/ble/fido_ble_device.cc
+++ b/device/fido/ble/fido_ble_device.cc
@@ -53,11 +53,6 @@
   return std::string("ble:").append(address.begin(), address.end());
 }
 
-void FidoBleDevice::TryWink(WinkCallback callback) {
-  // U2F over BLE does not support winking.
-  std::move(callback).Run();
-}
-
 void FidoBleDevice::Cancel() {
   if (state_ != State::kReady && state_ != State::kBusy)
     return;
@@ -156,13 +151,6 @@
     case State::kInit:
       Connect();
       break;
-    case State::kConnected:
-      StartTimeout();
-      state_ = State::kBusy;
-      connection_->ReadControlPointLength(
-          base::BindOnce(&FidoBleDevice::OnReadControlPointLength,
-                         weak_factory_.GetWeakPtr()));
-      break;
     case State::kReady:
       if (!pending_frames_.empty()) {
         FidoBleFrame frame;
@@ -201,8 +189,16 @@
 
 void FidoBleDevice::OnConnected(bool success) {
   StopTimeout();
-  state_ = success ? State::kConnected : State::kDeviceError;
-  Transition();
+  if (!success) {
+    state_ = State::kDeviceError;
+    Transition();
+    return;
+  }
+
+  state_ = State::kBusy;
+  StartTimeout();
+  connection_->ReadControlPointLength(base::BindOnce(
+      &FidoBleDevice::OnReadControlPointLength, weak_factory_.GetWeakPtr()));
 }
 
 void FidoBleDevice::OnReadControlPointLength(base::Optional<uint16_t> length) {
diff --git a/device/fido/ble/fido_ble_device.h b/device/fido/ble/fido_ble_device.h
index 26a3710..4ec6294 100644
--- a/device/fido/ble/fido_ble_device.h
+++ b/device/fido/ble/fido_ble_device.h
@@ -40,7 +40,6 @@
   static std::string GetId(base::StringPiece address);
 
   // FidoDevice:
-  void TryWink(WinkCallback callback) override;
   void Cancel() override;
   std::string GetId() const override;
   base::string16 GetDisplayName() const override;
diff --git a/device/fido/ble/fido_ble_device_unittest.cc b/device/fido/ble/fido_ble_device_unittest.cc
index 4838066e..4f657ed 100644
--- a/device/fido/ble/fido_ble_device_unittest.cc
+++ b/device/fido/ble/fido_ble_device_unittest.cc
@@ -211,12 +211,6 @@
   EXPECT_EQ("ble:" + address, FidoBleDevice::GetId(address));
 }
 
-TEST_F(FidoBleDeviceTest, TryWinkTest) {
-  test::TestCallbackReceiver<> closure_receiver;
-  device()->TryWink(closure_receiver.callback());
-  closure_receiver.WaitForCallback();
-}
-
 TEST_F(FidoBleDeviceTest, GetIdTest) {
   EXPECT_EQ(std::string("ble:") + BluetoothTestBase::kTestDeviceAddress1,
             device()->GetId());
diff --git a/device/fido/fido_constants.cc b/device/fido/fido_constants.cc
index 91f8e34..360622c 100644
--- a/device/fido/fido_constants.cc
+++ b/device/fido/fido_constants.cc
@@ -30,8 +30,6 @@
 
 const base::TimeDelta kDeviceTimeout = base::TimeDelta::FromSeconds(3);
 const base::TimeDelta kU2fRetryDelay = base::TimeDelta::FromMilliseconds(200);
-const base::TimeDelta kHidKeepAliveDelay =
-    base::TimeDelta::FromMilliseconds(100);
 
 const char kFormatKey[] = "fmt";
 const char kAttestationStatementKey[] = "attStmt";
diff --git a/device/fido/fido_constants.h b/device/fido/fido_constants.h
index 96f710f99..868ca59 100644
--- a/device/fido/fido_constants.h
+++ b/device/fido/fido_constants.h
@@ -352,11 +352,6 @@
 // device times out waiting for user presence.
 COMPONENT_EXPORT(DEVICE_FIDO) extern const base::TimeDelta kU2fRetryDelay;
 
-// Interval wait time before retrying reading on HID connection when
-// CTAPHID_KEEPALIVE message has been received.
-// https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#ctaphid_keepalive-0x3b
-COMPONENT_EXPORT(DEVICE_FIDO) extern const base::TimeDelta kHidKeepAliveDelay;
-
 // String key values for attestation object as a response to MakeCredential
 // request.
 COMPONENT_EXPORT(DEVICE_FIDO) extern const char kFormatKey[];
diff --git a/device/fido/fido_device.h b/device/fido/fido_device.h
index 3b7d54ad..e15bde4 100644
--- a/device/fido/fido_device.h
+++ b/device/fido/fido_device.h
@@ -30,14 +30,12 @@
 // |FidoDeviceDiscovery| are not fully initialized.
 class COMPONENT_EXPORT(DEVICE_FIDO) FidoDevice {
  public:
-  using WinkCallback = base::OnceClosure;
   using DeviceCallback =
       base::OnceCallback<void(base::Optional<std::vector<uint8_t>>)>;
 
   // Internal state machine states.
   enum class State {
     kInit,
-    kConnected,
     kBusy,
     kReady,
     // kMsgError occurs when the the device responds with an error indicating an
@@ -57,7 +55,6 @@
   // call (i.e. hairpin) |callback|.
   virtual void DeviceTransact(std::vector<uint8_t> command,
                               DeviceCallback callback) = 0;
-  virtual void TryWink(WinkCallback callback) = 0;
   virtual void Cancel() = 0;
   virtual std::string GetId() const = 0;
   virtual base::string16 GetDisplayName() const;
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc
index b1a2beb..3f28120 100644
--- a/device/fido/get_assertion_request_handler.cc
+++ b/device/fido/get_assertion_request_handler.cc
@@ -536,7 +536,9 @@
   CtapGetAssertionRequest request(request_);
   request.SetPinAuth(response->PinAuth(request.client_data_hash()));
   request.SetPinProtocol(pin::kProtocolVersion);
-  request.SetUserVerification(UserVerificationRequirement::kRequired);
+  // If doing a PIN operation then we don't ask the authenticator to also do
+  // internal UV.
+  request.SetUserVerification(UserVerificationRequirement::kDiscouraged);
 
   authenticator_->GetAssertion(
       std::move(request),
diff --git a/device/fido/hid/fido_hid_device.cc b/device/fido/hid/fido_hid_device.cc
index 3703c19..481cb33a 100644
--- a/device/fido/hid/fido_hid_device.cc
+++ b/device/fido/hid/fido_hid_device.cc
@@ -43,7 +43,8 @@
 
 void FidoHidDevice::DeviceTransact(std::vector<uint8_t> command,
                                    DeviceCallback callback) {
-  Transition(std::move(command), std::move(callback));
+  pending_transactions_.emplace_back(std::move(command), std::move(callback));
+  Transition();
 }
 
 void FidoHidDevice::Cancel() {
@@ -51,8 +52,14 @@
   if (state_ != State::kBusy && state_ != State::kReady)
     return;
 
+  // TODO(agl): this is problematic:
+  //   1) sends a cancel message, whether the transaction to be canceled is the
+  //      active one or not.
+  //   2) there's no way to indicate in the API which transaction should be
+  //      canceled.
+  //   3) the cancel is sent immediately, but that may corrupt a message that
+  //      is in the process of being transmitted.
   state_ = State::kReady;
-  pending_transactions_ = {};
   timeout_callback_.Cancel();
 
   WriteMessage(
@@ -64,106 +71,98 @@
       false /* response_expected */, base::DoNothing());
 }
 
-void FidoHidDevice::Transition(std::vector<uint8_t> command,
-                               DeviceCallback callback) {
-  // This adapter is needed to support the calls to ArmTimeout(). However, it is
-  // still guaranteed that |callback| will only be invoked once.
-  auto repeating_callback =
-      base::AdaptCallbackForRepeating(std::move(callback));
+// TODO(agl): maybe Transition should take the next step to move to?
+void FidoHidDevice::Transition() {
   switch (state_) {
     case State::kInit:
       state_ = State::kBusy;
-      ArmTimeout(repeating_callback);
+      ArmTimeout();
       Connect(base::BindOnce(&FidoHidDevice::OnConnect,
-                             weak_factory_.GetWeakPtr(), std::move(command),
-                             repeating_callback));
-      break;
-    case State::kConnected:
-      state_ = State::kBusy;
-      ArmTimeout(repeating_callback);
-      AllocateChannel(std::move(command), repeating_callback);
+                             weak_factory_.GetWeakPtr()));
       break;
     case State::kReady: {
       state_ = State::kBusy;
-      ArmTimeout(repeating_callback);
+      DCHECK(!pending_transactions_.empty());
+      ArmTimeout();
 
       // Write message to the device.
       const auto command_type = supported_protocol() == ProtocolVersion::kCtap
                                     ? FidoHidDeviceCommand::kCbor
                                     : FidoHidDeviceCommand::kMsg;
-      WriteMessage(
-          FidoHidMessage::Create(channel_id_, command_type, output_report_size_,
-                                 std::move(command)),
-          true,
-          base::BindOnce(&FidoHidDevice::MessageReceived,
-                         weak_factory_.GetWeakPtr(), repeating_callback));
+      WriteMessage(FidoHidMessage::Create(
+                       channel_id_, command_type, output_report_size_,
+                       std::move(pending_transactions_.front().command)),
+                   true,
+                   base::BindOnce(&FidoHidDevice::MessageReceived,
+                                  weak_factory_.GetWeakPtr()));
       break;
     }
     case State::kBusy:
-      pending_transactions_.emplace(std::move(command), repeating_callback);
       break;
     case State::kDeviceError:
     case State::kMsgError:
       base::WeakPtr<FidoHidDevice> self = weak_factory_.GetWeakPtr();
-      repeating_callback.Run(base::nullopt);
       // Executing callbacks may free |this|. Check |self| first.
       while (self && !pending_transactions_.empty()) {
         // Respond to any pending requests.
         DeviceCallback pending_cb =
-            std::move(pending_transactions_.front().second);
-        pending_transactions_.pop();
+            std::move(pending_transactions_.front().callback);
+        pending_transactions_.pop_front();
         std::move(pending_cb).Run(base::nullopt);
       }
       break;
   }
 }
 
+FidoHidDevice::PendingTransaction::PendingTransaction(
+    std::vector<uint8_t> in_command,
+    DeviceCallback in_callback)
+    : command(std::move(in_command)), callback(std::move(in_callback)) {}
+
+FidoHidDevice::PendingTransaction::~PendingTransaction() = default;
+
 void FidoHidDevice::Connect(ConnectCallback callback) {
   DCHECK(hid_manager_);
   hid_manager_->Connect(device_info_->guid, std::move(callback));
 }
 
-void FidoHidDevice::OnConnect(std::vector<uint8_t> command,
-                              DeviceCallback callback,
-                              device::mojom::HidConnectionPtr connection) {
+void FidoHidDevice::OnConnect(device::mojom::HidConnectionPtr connection) {
   if (state_ == State::kDeviceError)
     return;
   timeout_callback_.Cancel();
 
-  if (connection) {
-    connection_ = std::move(connection);
-    state_ = State::kConnected;
-  } else {
+  if (!connection) {
     state_ = State::kDeviceError;
+    Transition();
+    return;
   }
-  Transition(std::move(command), std::move(callback));
-}
 
-void FidoHidDevice::AllocateChannel(std::vector<uint8_t> command,
-                                    DeviceCallback callback) {
+  connection_ = std::move(connection);
   // Send random nonce to device to verify received message.
   std::vector<uint8_t> nonce(8);
   crypto::RandBytes(nonce.data(), nonce.size());
+
+  state_ = State::kBusy;
+  ArmTimeout();
   WriteMessage(FidoHidMessage::Create(channel_id_, FidoHidDeviceCommand::kInit,
                                       output_report_size_, nonce),
                true,
                base::BindOnce(&FidoHidDevice::OnAllocateChannel,
-                              weak_factory_.GetWeakPtr(), nonce,
-                              std::move(command), std::move(callback)));
+                              weak_factory_.GetWeakPtr(), nonce));
 }
 
 void FidoHidDevice::OnAllocateChannel(std::vector<uint8_t> nonce,
-                                      std::vector<uint8_t> command,
-                                      DeviceCallback callback,
                                       base::Optional<FidoHidMessage> message) {
   if (state_ == State::kDeviceError)
     return;
 
-  timeout_callback_.Cancel();
-
+  // TODO(agl): is this correct? it's entirely possible to see a response to a
+  // command from another client on the machine. Going to kDeviceError seems
+  // questionable.
   if (!message || message->cmd() != FidoHidDeviceCommand::kInit) {
+    timeout_callback_.Cancel();
     state_ = State::kDeviceError;
-    Transition(std::vector<uint8_t>(), std::move(callback));
+    Transition();
     return;
   }
 
@@ -177,8 +176,9 @@
   // 16: Capabilities
   std::vector<uint8_t> payload = message->GetMessagePayload();
   if (payload.size() != 17) {
+    timeout_callback_.Cancel();
     state_ = State::kDeviceError;
-    Transition(std::vector<uint8_t>(), std::move(callback));
+    Transition();
     return;
   }
 
@@ -187,15 +187,13 @@
   // reading.
   if (!std::equal(nonce.begin(), nonce.end(), received_nonce.begin(),
                   received_nonce.end())) {
-    auto repeating_callback =
-        base::AdaptCallbackForRepeating(std::move(callback));
-    ArmTimeout(repeating_callback);
     ReadMessage(base::BindOnce(&FidoHidDevice::OnAllocateChannel,
-                               weak_factory_.GetWeakPtr(), nonce,
-                               std::move(command), repeating_callback));
+                               weak_factory_.GetWeakPtr(), std::move(nonce)));
+
     return;
   }
 
+  timeout_callback_.Cancel();
   size_t index = 8;
   channel_id_ = payload[index++] << 24;
   channel_id_ |= payload[index++] << 16;
@@ -203,7 +201,7 @@
   channel_id_ |= payload[index++];
   capabilities_ = payload[16];
   state_ = State::kReady;
-  Transition(std::move(command), std::move(callback));
+  Transition();
 }
 
 void FidoHidDevice::WriteMessage(base::Optional<FidoHidMessage> message,
@@ -306,95 +304,62 @@
                                    std::move(message), std::move(callback)));
 }
 
-void FidoHidDevice::MessageReceived(DeviceCallback callback,
-                                    base::Optional<FidoHidMessage> message) {
+void FidoHidDevice::MessageReceived(base::Optional<FidoHidMessage> message) {
   if (state_ == State::kDeviceError)
     return;
 
   timeout_callback_.Cancel();
   if (!message) {
     state_ = State::kDeviceError;
-    Transition(std::vector<uint8_t>(), std::move(callback));
+    Transition();
     return;
   }
 
   const auto cmd = message->cmd();
-  // If received HID packet has keep_alive as command type, re-read after delay.
+  // If received HID packet is a keep-alive message then reset the timeout and
+  // read again.
   if (supported_protocol() == ProtocolVersion::kCtap &&
       cmd == FidoHidDeviceCommand::kKeepAlive) {
-    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&FidoHidDevice::OnKeepAlive, weak_factory_.GetWeakPtr(),
-                       std::move(callback)),
-        kHidKeepAliveDelay);
-    return;
-  }
-
-  if (cmd != FidoHidDeviceCommand::kMsg && cmd != FidoHidDeviceCommand::kCbor) {
-    ProcessHidError(cmd, message->GetMessagePayload());
-    Transition(std::vector<uint8_t>(), std::move(callback));
+    ArmTimeout();
+    ReadMessage(base::BindOnce(&FidoHidDevice::MessageReceived,
+                               weak_factory_.GetWeakPtr()));
     return;
   }
 
   auto response = message->GetMessagePayload();
-  state_ = State::kReady;
-  base::WeakPtr<FidoHidDevice> self = weak_factory_.GetWeakPtr();
-  std::move(callback).Run(
-      message ? base::make_optional(message->GetMessagePayload())
-              : base::nullopt);
-
-  // Executing |callback| may have freed |this|. Check |self| first.
-  if (self && !pending_transactions_.empty()) {
-    // If any transactions were queued, process the first one.
-    auto pending_cmd = std::move(pending_transactions_.front().first);
-    auto pending_cb = std::move(pending_transactions_.front().second);
-    pending_transactions_.pop();
-    Transition(std::move(pending_cmd), std::move(pending_cb));
-  }
-}
-
-void FidoHidDevice::TryWink(WinkCallback callback) {
-  // Only try to wink if device claims support.
-  if (!(capabilities_ & kWinkCapability) || state_ != State::kReady) {
-    std::move(callback).Run();
+  if (cmd != FidoHidDeviceCommand::kMsg && cmd != FidoHidDeviceCommand::kCbor) {
+    // TODO(agl): inline |ProcessHidError|, or maybe have it call |Transition|.
+    ProcessHidError(cmd, response);
+    Transition();
     return;
   }
 
-  WriteMessage(
-      FidoHidMessage::Create(channel_id_, FidoHidDeviceCommand::kWink,
-                             output_report_size_, std::vector<uint8_t>()),
-      true,
-      base::BindOnce(&FidoHidDevice::OnWink, weak_factory_.GetWeakPtr(),
-                     std::move(callback)));
+  state_ = State::kReady;
+  DCHECK(!pending_transactions_.empty());
+  auto callback = std::move(pending_transactions_.front().callback);
+  pending_transactions_.pop_front();
+
+  base::WeakPtr<FidoHidDevice> self = weak_factory_.GetWeakPtr();
+  std::move(callback).Run(std::move(response));
+
+  // Executing |callback| may have freed |this|. Check |self| first.
+  if (self && !pending_transactions_.empty()) {
+    Transition();
+  }
 }
 
-void FidoHidDevice::OnKeepAlive(DeviceCallback callback) {
-  auto repeating_callback =
-      base::AdaptCallbackForRepeating(std::move(callback));
-  ArmTimeout(repeating_callback);
-  ReadMessage(base::BindOnce(&FidoHidDevice::MessageReceived,
-                             weak_factory_.GetWeakPtr(),
-                             std::move(repeating_callback)));
-}
-
-void FidoHidDevice::OnWink(WinkCallback callback,
-                           base::Optional<FidoHidMessage> response) {
-  std::move(callback).Run();
-}
-
-void FidoHidDevice::ArmTimeout(DeviceCallback callback) {
+void FidoHidDevice::ArmTimeout() {
   DCHECK(timeout_callback_.IsCancelled());
-  timeout_callback_.Reset(base::BindOnce(&FidoHidDevice::OnTimeout,
-                                         weak_factory_.GetWeakPtr(),
-                                         std::move(callback)));
+  timeout_callback_.Reset(
+      base::BindOnce(&FidoHidDevice::OnTimeout, weak_factory_.GetWeakPtr()));
   // Setup timeout task for 3 seconds.
   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
       FROM_HERE, timeout_callback_.callback(), kDeviceTimeout);
 }
 
-void FidoHidDevice::OnTimeout(DeviceCallback callback) {
+void FidoHidDevice::OnTimeout() {
   state_ = State::kDeviceError;
-  Transition(std::vector<uint8_t>(), std::move(callback));
+  Transition();
 }
 
 void FidoHidDevice::ProcessHidError(FidoHidDeviceCommand cmd,
diff --git a/device/fido/hid/fido_hid_device.h b/device/fido/hid/fido_hid_device.h
index 1a296c18..70dd99b 100644
--- a/device/fido/hid/fido_hid_device.h
+++ b/device/fido/hid/fido_hid_device.h
@@ -5,6 +5,7 @@
 #ifndef DEVICE_FIDO_HID_FIDO_HID_DEVICE_H_
 #define DEVICE_FIDO_HID_FIDO_HID_DEVICE_H_
 
+#include <list>
 #include <string>
 #include <utility>
 #include <vector>
@@ -50,8 +51,6 @@
                       DeviceCallback callback) final;
 
   // FidoDevice:
-  // Send a wink command if supported.
-  void TryWink(WinkCallback callback) final;
   // Send command to cancel any outstanding requests on this device.
   void Cancel() final;
   // Use a string identifier to compare to other devices.
@@ -69,7 +68,14 @@
   FRIEND_TEST_ALL_PREFIXES(FidoHidDeviceTest, TestRetryChannelAllocation);
   FRIEND_TEST_ALL_PREFIXES(FidoHidDeviceTest, TestCancel);
 
-  static constexpr uint8_t kWinkCapability = 0x01;
+  struct COMPONENT_EXPORT(DEVICE_FIDO) PendingTransaction {
+    PendingTransaction(std::vector<uint8_t> command, DeviceCallback callback);
+    ~PendingTransaction();
+
+    std::vector<uint8_t> command;
+    DeviceCallback callback;
+  };
+
   static constexpr uint8_t kLockCapability = 0x02;
   static constexpr uint32_t kBroadcastChannel = 0xffffffff;
 
@@ -79,16 +85,11 @@
 
   // Open a connection to this device.
   void Connect(ConnectCallback callback);
-  void OnConnect(std::vector<uint8_t> command,
-                 DeviceCallback callback,
-                 device::mojom::HidConnectionPtr connection);
+  void OnConnect(device::mojom::HidConnectionPtr connection);
   // Ask device to allocate a unique channel id for this connection.
-  void AllocateChannel(std::vector<uint8_t> command, DeviceCallback callback);
   void OnAllocateChannel(std::vector<uint8_t> nonce,
-                         std::vector<uint8_t> command,
-                         DeviceCallback callback,
                          base::Optional<FidoHidMessage> message);
-  void Transition(std::vector<uint8_t> command, DeviceCallback callback);
+  void Transition();
   // Write all message packets to device, and read response if expected.
   void WriteMessage(base::Optional<FidoHidMessage> message,
                     bool response_expected,
@@ -99,8 +100,7 @@
                      bool success);
   // Read all response message packets from device.
   void ReadMessage(HidMessageCallback callback);
-  void MessageReceived(DeviceCallback callback,
-                       base::Optional<FidoHidMessage> message);
+  void MessageReceived(base::Optional<FidoHidMessage> message);
   void OnRead(HidMessageCallback callback,
               bool success,
               uint8_t report_id,
@@ -110,10 +110,8 @@
                           bool success,
                           uint8_t report_id,
                           const base::Optional<std::vector<uint8_t>>& buf);
-  void OnKeepAlive(DeviceCallback callback);
-  void OnWink(WinkCallback callback, base::Optional<FidoHidMessage> response);
-  void ArmTimeout(DeviceCallback callback);
-  void OnTimeout(DeviceCallback callback);
+  void ArmTimeout();
+  void OnTimeout();
   void ProcessHidError(FidoHidDeviceCommand cmd,
                        base::span<const uint8_t> payload);
 
@@ -126,8 +124,9 @@
   const uint8_t output_report_size_;
 
   base::CancelableOnceClosure timeout_callback_;
-  base::queue<std::pair<std::vector<uint8_t>, DeviceCallback>>
-      pending_transactions_;
+  // pending_transactions_ includes both the current transaction, and
+  // transactions that have not yet been sent.
+  std::list<PendingTransaction> pending_transactions_;
 
   // All the FidoHidDevice instances are owned by U2fRequest. So it is safe to
   // let the FidoHidDevice share the device::mojo::HidManager raw pointer from
diff --git a/device/fido/hid/fido_hid_device_unittest.cc b/device/fido/hid/fido_hid_device_unittest.cc
index 88325ea..472fcdbe 100644
--- a/device/fido/hid/fido_hid_device_unittest.cc
+++ b/device/fido/hid/fido_hid_device_unittest.cc
@@ -209,11 +209,11 @@
 
   // Add pending transactions manually and ensure they are processed.
   TestDeviceCallbackReceiver receiver_1;
-  device->pending_transactions_.emplace(GetMockDeviceRequest(),
-                                        receiver_1.callback());
+  device->pending_transactions_.emplace_back(GetMockDeviceRequest(),
+                                             receiver_1.callback());
   TestDeviceCallbackReceiver receiver_2;
-  device->pending_transactions_.emplace(GetMockDeviceRequest(),
-                                        receiver_2.callback());
+  device->pending_transactions_.emplace_back(GetMockDeviceRequest(),
+                                             receiver_2.callback());
   TestDeviceCallbackReceiver receiver_3;
   device->DeviceTransact(GetMockDeviceRequest(), receiver_3.callback());
 
@@ -250,11 +250,11 @@
 
   // Add pending transactions manually and ensure they are processed.
   TestDeviceCallbackReceiver receiver_1;
-  device->pending_transactions_.emplace(GetMockDeviceRequest(),
-                                        receiver_1.callback());
+  device->pending_transactions_.emplace_back(GetMockDeviceRequest(),
+                                             receiver_1.callback());
   TestDeviceCallbackReceiver receiver_2;
-  device->pending_transactions_.emplace(GetMockDeviceRequest(),
-                                        receiver_2.callback());
+  device->pending_transactions_.emplace_back(GetMockDeviceRequest(),
+                                             receiver_2.callback());
   TestDeviceCallbackReceiver receiver_3;
   device->DeviceTransact(GetMockDeviceRequest(), receiver_3.callback());
   FakeHidConnection::mock_connection_error_ = false;
diff --git a/device/fido/make_credential_request_handler.cc b/device/fido/make_credential_request_handler.cc
index e61a0ee..2f11cf9a 100644
--- a/device/fido/make_credential_request_handler.cc
+++ b/device/fido/make_credential_request_handler.cc
@@ -472,7 +472,9 @@
   CtapMakeCredentialRequest request(request_);
   request.SetPinAuth(response->PinAuth(request.client_data_hash()));
   request.SetPinProtocol(pin::kProtocolVersion);
-  request.SetUserVerification(UserVerificationRequirement::kRequired);
+  // If doing a PIN operation then we don't ask the authenticator to also do
+  // internal UV.
+  request.SetUserVerification(UserVerificationRequirement::kDiscouraged);
 
   authenticator_->MakeCredential(
       std::move(request),
diff --git a/device/fido/make_credential_task.cc b/device/fido/make_credential_task.cc
index 4cb18f7..d1e901e 100644
--- a/device/fido/make_credential_task.cc
+++ b/device/fido/make_credential_task.cc
@@ -16,20 +16,20 @@
 
 namespace {
 
-// Checks whether the incoming MakeCredential request has ClientPin option that
-// is compatible with the Chrome's CTAP2 implementation. According to the CTAP
-// spec, CTAP2 authenticators that have client pin set will always error out on
-// MakeCredential request when "pinAuth" parameter in the request is not set. As
-// ClientPin is not supported on Chrome yet, this check allows Chrome to avoid
-// such failures if possible by defaulting to U2F request when user verification
-// is not required and the device supports U2F protocol.
-// TODO(hongjunchoi): Remove this once ClientPin command is implemented.
-// See: https://crbug.com/870892
+// CTAP 2.0 specifies[1] that once a PIN has been set on an authenticator, the
+// PIN is required in order to make a credential. In some cases we don't want to
+// prompt for a PIN and so use U2F to make the credential instead.
+//
+// [1]
+// https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#authenticatorMakeCredential,
+// step 6
 bool ShouldUseU2fBecauseCtapRequiresClientPin(
     const FidoDevice* device,
     const CtapMakeCredentialRequest& request) {
-  if (request.user_verification() == UserVerificationRequirement::kRequired)
+  if (request.user_verification() == UserVerificationRequirement::kRequired ||
+      (request.pin_auth() && !request.pin_auth()->empty())) {
     return false;
+  }
 
   DCHECK(device && device->device_info());
   bool client_pin_set =
diff --git a/device/fido/mock_fido_device.cc b/device/fido/mock_fido_device.cc
index 02282bf..40d0a18f 100644
--- a/device/fido/mock_fido_device.cc
+++ b/device/fido/mock_fido_device.cc
@@ -82,10 +82,6 @@
 }
 MockFidoDevice::~MockFidoDevice() = default;
 
-void MockFidoDevice::TryWink(WinkCallback cb) {
-  TryWinkRef(cb);
-}
-
 void MockFidoDevice::DeviceTransact(std::vector<uint8_t> command,
                                     DeviceCallback cb) {
   DeviceTransactPtr(command, cb);
@@ -99,10 +95,6 @@
   return weak_factory_.GetWeakPtr();
 }
 
-void MockFidoDevice::ExpectWinkedAtLeastOnce() {
-  EXPECT_CALL(*this, TryWinkRef(::testing::_)).Times(::testing::AtLeast(1));
-}
-
 void MockFidoDevice::StubGetId() {
   // Use a counter to keep the device ID unique.
   static size_t i = 0;
diff --git a/device/fido/mock_fido_device.h b/device/fido/mock_fido_device.h
index 83dfaca..1c3070983 100644
--- a/device/fido/mock_fido_device.h
+++ b/device/fido/mock_fido_device.h
@@ -52,11 +52,6 @@
                  base::Optional<AuthenticatorGetInfoResponse> device_info);
   ~MockFidoDevice() override;
 
-  // TODO(crbug.com/729950): Remove these workarounds once support for move-only
-  // types is added to GMock.
-  MOCK_METHOD1(TryWinkRef, void(WinkCallback& cb));
-  void TryWink(WinkCallback cb) override;
-
   MOCK_METHOD0(Cancel, void(void));
 
   MOCK_CONST_METHOD0(GetId, std::string(void));
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc
index 4c4710d..162b79a 100644
--- a/device/fido/virtual_ctap2_device.cc
+++ b/device/fido/virtual_ctap2_device.cc
@@ -140,15 +140,19 @@
   // Step 4.
   bool uv = false;
   if (can_do_uv) {
-    if (options.user_verification_availability ==
-            AuthenticatorSupportedOptions::UserVerificationAvailability::
-                kSupportedAndConfigured &&
-        user_verification == UserVerificationRequirement::kRequired) {
-      // Internal UV is assumed to always succeed.
-      if (simulate_press_callback) {
-        simulate_press_callback.Run();
+    if (user_verification == UserVerificationRequirement::kRequired) {
+      if (options.user_verification_availability ==
+          AuthenticatorSupportedOptions::UserVerificationAvailability::
+              kSupportedAndConfigured) {
+        // Internal UV is assumed to always succeed.
+        if (simulate_press_callback) {
+          simulate_press_callback.Run();
+        }
+        uv = true;
+      } else {
+        // UV was requested, but either not supported or not configured.
+        return CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid;
       }
-      uv = true;
     }
 
     if (pin_auth && options.client_pin_availability ==
diff --git a/device/fido/virtual_fido_device.cc b/device/fido/virtual_fido_device.cc
index 6d95884..e0e07bb 100644
--- a/device/fido/virtual_fido_device.cc
+++ b/device/fido/virtual_fido_device.cc
@@ -201,10 +201,6 @@
   return &it->second;
 }
 
-void VirtualFidoDevice::TryWink(WinkCallback cb) {
-  std::move(cb).Run();
-}
-
 std::string VirtualFidoDevice::GetId() const {
   // Use our heap address to get a unique-ish number. (0xffe1 is a prime).
   return "VirtualFidoDevice-" + std::to_string((size_t)this % 0xffe1);
diff --git a/device/fido/virtual_fido_device.h b/device/fido/virtual_fido_device.h
index 9875634b..f43bd0be 100644
--- a/device/fido/virtual_fido_device.h
+++ b/device/fido/virtual_fido_device.h
@@ -184,7 +184,6 @@
       base::span<const uint8_t, kRpIdHashLength> application_parameter);
 
   // FidoDevice:
-  void TryWink(WinkCallback cb) override;
   std::string GetId() const override;
   FidoTransportProtocol DeviceTransport() const override;
 
diff --git a/device/udev_linux/udev_watcher.cc b/device/udev_linux/udev_watcher.cc
index dbccf04..318883ec 100644
--- a/device/udev_linux/udev_watcher.cc
+++ b/device/udev_linux/udev_watcher.cc
@@ -31,10 +31,6 @@
 
 UdevWatcher::Observer::~Observer() = default;
 
-void UdevWatcher::Observer::OnDeviceAdded(ScopedUdevDevicePtr device) {}
-
-void UdevWatcher::Observer::OnDeviceRemoved(ScopedUdevDevicePtr device) {}
-
 std::unique_ptr<UdevWatcher> UdevWatcher::StartWatching(
     Observer* observer,
     const std::vector<Filter>& filters) {
diff --git a/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc b/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc
index fd3d9a1..feae38c 100644
--- a/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc
+++ b/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc
@@ -41,6 +41,7 @@
 namespace WFN = ABI::Windows::Foundation::Numerics;
 namespace WInput = ABI::Windows::UI::Input::Spatial;
 
+using ABI::Windows::Foundation::IEventHandler;
 using ABI::Windows::Foundation::IReference;
 using ABI::Windows::Foundation::Numerics::Matrix4x4;
 
@@ -136,7 +137,10 @@
     base::RepeatingCallback<void(mojom::VRDisplayInfoPtr)>
         on_display_info_changed)
     : XRCompositorCommon(),
-      on_display_info_changed_(std::move(on_display_info_changed)) {}
+      on_display_info_changed_(std::move(on_display_info_changed)),
+      weak_ptr_factory_(this) {
+  stage_changed_token_.value = 0;
+}
 
 MixedRealityRenderLoop::~MixedRealityRenderLoop() {
   Stop();
@@ -271,6 +275,7 @@
   holographic_space_ = nullptr;
   origin_ = nullptr;
   stage_origin_ = nullptr;
+  ClearStageStatics();
   last_origin_from_attached_ = base::nullopt;
   attached_ = nullptr;
 
@@ -335,21 +340,14 @@
 
 void MixedRealityRenderLoop::InitializeStageOrigin() {
   TRACE_EVENT0("xr", "InitializeStageOrigin");
+  if (!EnsureStageStatics())
+    return;
   stage_transform_needs_updating_ = true;
 
   // Try to get a SpatialStageFrameOfReference.  We'll use this to calculate
   // the transform between the poses we're handing out and where the floor is.
-  ComPtr<ISpatialStageFrameOfReferenceStatics> spatial_stage_statics;
-  base::win::ScopedHString spatial_stage_string =
-      base::win::ScopedHString::Create(
-          RuntimeClass_Windows_Perception_Spatial_SpatialStageFrameOfReference);
-  HRESULT hr = base::win::RoGetActivationFactory(
-      spatial_stage_string.get(), IID_PPV_ARGS(&spatial_stage_statics));
-  if (FAILED(hr))
-    return;
-
   ComPtr<ISpatialStageFrameOfReference> spatial_stage;
-  hr = spatial_stage_statics->get_Current(&spatial_stage);
+  HRESULT hr = stage_statics_->get_Current(&spatial_stage);
   if (FAILED(hr) || !spatial_stage) {
     TraceError(ErrorLocation::kAcquireCurrentStage, hr);
     return;
@@ -358,6 +356,57 @@
   spatial_stage->get_CoordinateSystem(&stage_origin_);
 }
 
+bool MixedRealityRenderLoop::EnsureStageStatics() {
+  if (stage_statics_)
+    return true;
+
+  base::win::ScopedHString spatial_stage_string =
+      base::win::ScopedHString::Create(
+          RuntimeClass_Windows_Perception_Spatial_SpatialStageFrameOfReference);
+  HRESULT hr = base::win::RoGetActivationFactory(spatial_stage_string.get(),
+                                                 IID_PPV_ARGS(&stage_statics_));
+  if (FAILED(hr))
+    return false;
+
+  auto weak_this = weak_ptr_factory_.GetWeakPtr();
+  scoped_refptr<base::SingleThreadTaskRunner> thread_runner = task_runner();
+
+  auto callback = Microsoft::WRL::Callback<IEventHandler<IInspectable*>>(
+      [weak_this, thread_runner](IInspectable*, IInspectable*) {
+        thread_runner->PostTask(
+            FROM_HERE,
+            base::BindOnce(&MixedRealityRenderLoop::OnCurrentStageChanged,
+                           weak_this));
+        return S_OK;
+      });
+
+  DCHECK(stage_changed_token_.value == 0);
+  hr =
+      stage_statics_->add_CurrentChanged(callback.Get(), &stage_changed_token_);
+  DCHECK(SUCCEEDED(hr));
+
+  return true;
+}
+
+void MixedRealityRenderLoop::ClearStageStatics() {
+  if (!stage_statics_)
+    return;
+
+  HRESULT hr = S_OK;
+  if (stage_changed_token_.value != 0) {
+    hr = stage_statics_->remove_CurrentChanged(stage_changed_token_);
+    stage_changed_token_.value = 0;
+    DCHECK(SUCCEEDED(hr));
+  }
+
+  stage_statics_ = nullptr;
+}
+
+void MixedRealityRenderLoop::OnCurrentStageChanged() {
+  stage_origin_ = nullptr;
+  InitializeStageOrigin();
+}
+
 void MixedRealityRenderLoop::OnSessionStart() {
   // Each session should start with new origins.
   origin_ = nullptr;
diff --git a/device/vr/windows_mixed_reality/mixed_reality_renderloop.h b/device/vr/windows_mixed_reality/mixed_reality_renderloop.h
index 9eb8dd5..f3c332f 100644
--- a/device/vr/windows_mixed_reality/mixed_reality_renderloop.h
+++ b/device/vr/windows_mixed_reality/mixed_reality_renderloop.h
@@ -57,7 +57,6 @@
   // Helpers to implement XRDeviceAbstraction.
   bool EnsureSpatialInteractionManager();
   void InitializeOrigin();
-  void InitializeStageOrigin();
   void InitializeSpace();
   void StartPresenting();
   void UpdateWMRDataForNextFrame();
@@ -67,6 +66,11 @@
   // Returns true if stage parameters have changed.
   bool UpdateStageParameters();
 
+  void InitializeStageOrigin();
+  bool EnsureStageStatics();
+  void ClearStageStatics();
+  void OnCurrentStageChanged();
+
   std::unique_ptr<base::win::ScopedWinrtInitializer> initializer_;
 
   Microsoft::WRL::ComPtr<ABI::Windows::Graphics::Holographic::IHolographicSpace>
@@ -112,9 +116,15 @@
       ABI::Windows::Graphics::Holographic::IHolographicCamera>
       camera_;
 
-  // Input Data
   std::unique_ptr<MixedRealityInputHelper> input_helper_;
 
+  Microsoft::WRL::ComPtr<
+      ABI::Windows::Perception::Spatial::ISpatialStageFrameOfReferenceStatics>
+      stage_statics_;
+  EventRegistrationToken stage_changed_token_;
+
+  base::WeakPtrFactory<MixedRealityRenderLoop> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(MixedRealityRenderLoop);
 };
 
diff --git a/docs/gpu/sync_token_internals.md b/docs/gpu/sync_token_internals.md
index 4ba2caac..bc272f88 100644
--- a/docs/gpu/sync_token_internals.md
+++ b/docs/gpu/sync_token_internals.md
@@ -37,8 +37,7 @@
 Fences are typically generated or inserted on the client using a sequential
 counter. The corresponding GL API is `GenSyncTokenCHROMIUM` which generates the
 fence using `CommandBufferProxyImpl::GenerateFenceSyncRelease()`, and also adds
-the fence to the command buffer using the internal `InsertFenceSyncCHROMIUM`
-command.
+the fence to the command buffer using the internal `InsertFenceSync` command.
 
 ## Verification
 
@@ -100,8 +99,8 @@
 
 Sync tokens are completed when the fence is released in the GPU process by
 calling `SyncPointClientState::ReleaseFenceSync()`. For GL command buffers, the
-`InsertFenceSyncCHROMIUM` command, which contains the release count generated in
-the client, calls this when executed in the service. This issues callbacks and
+`InsertFenceSync` command, which contains the release count generated in the
+client, calls this when executed in the service. This issues callbacks and
 allows waiting command buffers to resume their work.
 
 ## Correctness
diff --git a/docs/security/rule-of-2.md b/docs/security/rule-of-2.md
index 3a7dc22e..13bcb62 100644
--- a/docs/security/rule-of-2.md
+++ b/docs/security/rule-of-2.md
@@ -161,15 +161,19 @@
 The trick of this technique lies in finding a sufficiently-trivial grammar, and
 committing to its limitations.
 
-Another good approach is to define a Mojo message type for the information you
-want, extract that information from a complex input object in a sandboxed
-process, and then send the information to a higher-privileged process in a Mojo
-message using the message type. That way, the higher-privileged process need
-only process objects adhering to a well-defined, generally low-complexity
-grammar. This is a big part of why [we like for Mojo messages to use structured
-types](mojo.md#Use-structured-types).
+Another good approach is to
 
-For example, it would be safe enough to convert a PNG to an `SkBitmap` in a
+  1. define a new Mojo message type for the information you want;
+  2. extract that information from a complex input object in a sandboxed
+     process; and then
+  3. send the result to a higher-privileged process in a Mojo message using the
+     new message type.
+
+That way, the higher-privileged process need only process objects adhering to a
+well-defined, generally low-complexity grammar. This is a big part of why [we
+like for Mojo messages to use structured types](mojo.md#Use-structured-types).
+
+For example, it should be safe enough to convert a PNG to an `SkBitmap` in a
 sandboxed process, and then send the `SkBitmap` to a higher-privileged process
 via IPC. Although there may be bugs in the IPC message deserialization code
 and/or in Skia's `SkBitmap` handling code, we consider this safe enough for a
@@ -177,10 +181,12 @@
 
   * we must accept the risk of bugs in Mojo deserialization; but thankfully
   * Mojo deserialization is very amenable to fuzzing; and
-  * it's a big improvement to scope bugs to smaller areas, like deserialization
-    functions and very simple classes like `SkBitmap` and `SkPixmap`; and
-  * ultimately this process results in parsing significantly simpler grammars
-    (PNG → Mojo + `SkBitmap` in this case).
+  * it's a big improvement to scope bugs to smaller areas, like IPC
+    deserialization functions and very simple classes like `SkBitmap` and
+    `SkPixmap`.
+
+Ultimately this process results in parsing significantly simpler grammars. (PNG
+→ Mojo + `SkBitmap` in this case.)
 
 > (We have to accept the risk of memory safety bugs in Mojo deserialization
 > because C++'s high performance is crucial in such a throughput- and
diff --git a/docs/threading_and_tasks.md b/docs/threading_and_tasks.md
index 4cb346a..3dd0c0e 100644
--- a/docs/threading_and_tasks.md
+++ b/docs/threading_and_tasks.md
@@ -273,8 +273,7 @@
 computation or through disk access, then that slow work should be done without
 holding on to the lock.  Only when the result is available should the lock be
 used to swap in the new data.  An example of this is in PluginList::LoadPlugins
-([`content/common/plugin_list.cc`](https://cs.chromium.org/chromium/src/content/
-common/plugin_list.cc). If you must use locks,
+([`content/browser/plugin_list.cc`](https://cs.chromium.org/chromium/src/content/browser/plugin_list.cc)). If you must use locks,
 [here](https://www.chromium.org/developers/lock-and-condition-variable) are some
 best practices and pitfalls to avoid.
 
diff --git a/docs/ui/android/mvc_architecture_tutorial.md b/docs/ui/android/mvc_architecture_tutorial.md
new file mode 100644
index 0000000..f05183de
--- /dev/null
+++ b/docs/ui/android/mvc_architecture_tutorial.md
@@ -0,0 +1,120 @@
+# So, you want to do MVC...
+
+### Overview
+A full explanation of the MVC framework can be found [here](https://docs.google.com/document/d/1nP9NjTvsSMZvkR_aWRZPdy67wRINomgQ7AfEtbsIwzg). This document is intended to go over the logistics of the most basic implementation of the framework in Chrome’s codebase.
+
+For this example, we’ll be implementing a simple progress bar; a rectangle that changes length based on the loading state of the underlying webpage.
+
+#### Additional Resources
+[Testing MVC primer doc](https://docs.google.com/document/d/1Mel7f4lE_osFjnttkxu1wcUf_k9CmIzPv6oxwCw9tx4/edit#)
+
+#### File Structure
+The file structure of our component will be the following:
+* ./org/chromium/chrome/browser/simple_progress/
+  * [`SimpleProgressCoordinator.java`](#SimpleProgressCoordinator)
+  * [`SimpleProgressMediator.java`](#SimpleProgressMediator)
+  * [`SimpleProgressViewBinder.java`](#SimpleProgressViewBinder)
+  * [`SimpleProgressProperties.java`](#SimpleProgressProperties)
+  * `SimpleProgressView.java` (assuming it requires interesting logic)
+
+#### SimpleProgressCoordinator
+The class responsible for setting up the component. This should be the only public class in the component's package and is the only class with direct access to the mediator.
+
+```java
+public class SimpleProgressCoordinator {
+
+   private SimpleProgressMediator mMediator;
+
+   public SimpleProgressCoordinator (Tab tabProgressBarIsFor) {
+
+       PropertyModel model = new PropertyModel.Builder(SimpleProgressProperties.ALL_KEYS)
+               .with(SimpleProgressProperties.PROGRESS_FRACTION, 0f)
+               .with(SimpleProgressProperties.FOREGROUND_COLOR, Color.RED)
+               .build();
+
+       // This view can come from multiple places, in this case we find it in the existing
+       // view hierarchy.
+       View view = tabProgressBarIsFor.getActivity().findViewById(
+               R.id.my_simple_progress_bar);
+
+       PropertyModelChangeProcessor.create(model, view, SimpleProgressViewBinder::bind);
+
+       mMediator = new SimpleProgressMediator(model, tabProgressBarIsFor);
+   }
+
+   public void destroy() {
+       mMediator.destroy();
+   }
+}
+```
+
+#### SimpleProgressMediator
+The class that handles all of the signals coming from the outside world. External classes should never interact with this class directly.
+
+```java
+class SimpleProgressMediator extends EmptyTabObserver {
+
+   private PropertyModel mModel;
+
+   private Tab mObservedTab;
+
+   public SimpleProgressMediator(PropertyModel model, Tab tabProgressBarIsFor) {
+       mModel = model;
+       mObservedTab = tabProgressBarIsFor;
+       mObservedTab.addObserver(this);
+   }
+
+   @Override
+   public void onLoadProgressChanged(Tab tab, int progress) {
+       mModel.set(SimpleProgressProperties.PROGRESS_FRACTION, progress / 100f);
+   }
+
+   @Override
+   public void onDidChangeThemeColor(Tab tab, int color) {
+       mModel.set(SimpleProgressProperties.FOREGROUND_COLOR, color);
+   }
+
+   void destroy() {
+       // Be sure to clean up anything that needs to be (in this case, detach the tab
+       // observer).
+       mObservedTab.removeObserver(this);
+   }
+}
+```
+
+#### SimpleProgressViewBinder
+The class responsible for applying a model to a specific view. In general there is a 1:1 relationship between a type of view and its binder. Multiple binders can know how to take a single type of model and apply it to a view. The binder's method should be stateless; this is implied by the 'static' identifier.
+
+```java
+class SimpleProgressViewBinder {
+
+    public static void bind(PropertyModel model, View view, PropertyKey propertyKey) {
+        if (SimpleProgressProperties.PROGRESS_FRACTION == propertyKey) {
+
+            // Apply width modification to 'view' here.
+
+        } else if (SimpleProgressProperties.FOREGROUND_COLOR == propertyKey) {
+
+            // Apply color modification to 'view' here.
+
+        }
+    }
+}
+```
+
+#### SimpleProgressProperties
+These are properties associated with the view the model will be applied to.
+
+```java
+class SimpleProgressProperties {
+
+    public static final WritableFloatPropertyKey PROGRESS_FRACTION =
+            new WritableFloatPropertyKey();
+
+    public static final WritableIntPropertyKey FOREGROUND_COLOR =
+            new WritableIntPropertyKey();
+
+    public static final PropertyKey[] ALL_KEYS = {PROGRESS_FRACTION, FOREGROUND_COLOR};
+}
+```
+
diff --git a/docs/vscode.md b/docs/vscode.md
index 9b40e113..b9d8ead2 100644
--- a/docs/vscode.md
+++ b/docs/vscode.md
@@ -150,6 +150,28 @@
     format-on-save (see `C_Cpp.clang_format_formatOnSave` setting). This
     extension adds the ability to format a document or the current selection on
     demand.
+*   ***vscode-clangd*** -
+    If you do not plan to use VSCode for debugging, vscode-clangd is a great
+    alternative to C/C++ IntelliSense. It knows about how to compile Chromium,
+    enabling it to provide smarter autocomplete than C/C++ IntelliSense as well
+    as allowing you to jump from functions to their definitions. To set it up:
+
+    1. Install vscode-clangd
+    2. Disable C/C++ IntelliSense
+    3. Generate compilation database, from chromium/src:
+
+        ```
+        $ ninja -C out/Default -t compdb cc cxx objc objcxx > compile_commands.json
+        ```
+
+    4. Re-run the above command each time you gclient sync to stay updated.
+
+    If you need to debug, disable the vscode-clangd plugin, enable C/C++
+    Intellisense, and restart VSCode.
+
+    Read more about [clangd with VSCode](https://clang.llvm.org/extra/clangd/Installation.html#editor-plugins).
+    If you are a Googler, also see [go/clangd-chromium](go/clangd-chromium).
+
 
 Also be sure to take a look at the
 [VS Code marketplace](https://marketplace.visualstudio.com/VSCode) to check out other
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index 1611a43..c6e82a45 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -518,6 +518,7 @@
       "//chromeos/dbus:test_support",
       "//chromeos/dbus/media_analytics",
       "//chromeos/dbus/media_analytics:media_perception_proto",
+      "//chromeos/dbus/upstart",
       "//chromeos/login/login_state",
       "//chromeos/network",
     ]
@@ -724,6 +725,7 @@
       "//chromeos/dbus:test_support",
       "//chromeos/dbus/media_analytics",
       "//chromeos/dbus/media_analytics:media_perception_proto",
+      "//chromeos/dbus/upstart",
       "//chromeos/login/login_state",
       "//chromeos/network:test_support",
       "//components/feedback",
diff --git a/extensions/browser/api/BUILD.gn b/extensions/browser/api/BUILD.gn
index b6b5c2d0..3e1d917a 100644
--- a/extensions/browser/api/BUILD.gn
+++ b/extensions/browser/api/BUILD.gn
@@ -146,6 +146,7 @@
       "//chromeos/dbus",
       "//chromeos/dbus/media_analytics",
       "//chromeos/dbus/media_analytics:media_perception_proto",
+      "//chromeos/dbus/upstart",
       "//chromeos/login/login_state",
       "//chromeos/services/media_perception/public/mojom",
       "//chromeos/services/media_perception/public/mojom:mojom_js_data_deps",
diff --git a/extensions/browser/api/declarative/rules_cache_delegate.cc b/extensions/browser/api/declarative/rules_cache_delegate.cc
index 12b538b2..83fb408 100644
--- a/extensions/browser/api/declarative/rules_cache_delegate.cc
+++ b/extensions/browser/api/declarative/rules_cache_delegate.cc
@@ -95,8 +95,8 @@
   }
 
   system.ready().Post(FROM_HERE,
-                      base::BindRepeating(&RulesCacheDelegate::CheckIfReady,
-                                          weak_ptr_factory_.GetWeakPtr()));
+                      base::BindOnce(&RulesCacheDelegate::CheckIfReady,
+                                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 void RulesCacheDelegate::UpdateRules(const std::string& extension_id,
@@ -188,9 +188,10 @@
     storage_init_time_ = base::Time::Now();
 
   if (!GetDeclarativeRulesStored(extension_id)) {
-    ExtensionSystem::Get(browser_context_)->ready().Post(
-        FROM_HERE, base::Bind(&RulesCacheDelegate::CheckIfReady,
-                              weak_ptr_factory_.GetWeakPtr()));
+    ExtensionSystem::Get(browser_context_)
+        ->ready()
+        .Post(FROM_HERE, base::BindOnce(&RulesCacheDelegate::CheckIfReady,
+                                        weak_ptr_factory_.GetWeakPtr()));
     return;
   }
 
@@ -219,9 +220,10 @@
   waiting_for_extensions_.erase(extension_id);
 
   if (waiting_for_extensions_.empty())
-    ExtensionSystem::Get(browser_context_)->ready().Post(
-        FROM_HERE, base::Bind(&RulesCacheDelegate::CheckIfReady,
-                              weak_ptr_factory_.GetWeakPtr()));
+    ExtensionSystem::Get(browser_context_)
+        ->ready()
+        .Post(FROM_HERE, base::BindOnce(&RulesCacheDelegate::CheckIfReady,
+                                        weak_ptr_factory_.GetWeakPtr()));
 }
 
 bool RulesCacheDelegate::GetDeclarativeRulesStored(
diff --git a/extensions/browser/api/declarative/rules_registry.cc b/extensions/browser/api/declarative/rules_registry.cc
index 1159bed9..8b8367b 100644
--- a/extensions/browser/api/declarative/rules_registry.cc
+++ b/extensions/browser/api/declarative/rules_registry.cc
@@ -368,9 +368,8 @@
 
   process_changed_rules_requested_[extension_id] = SCHEDULED_FOR_PROCESSING;
   ready_.Post(FROM_HERE,
-              base::Bind(&RulesRegistry::ProcessChangedRules,
-                         weak_ptr_factory_.GetWeakPtr(),
-                         extension_id));
+              base::BindOnce(&RulesRegistry::ProcessChangedRules,
+                             weak_ptr_factory_.GetWeakPtr(), extension_id));
 }
 
 bool RulesRegistry::IsUniqueId(const std::string& extension_id,
diff --git a/extensions/browser/api/declarative/rules_registry.h b/extensions/browser/api/declarative/rules_registry.h
index 7479a2a..e32424d 100644
--- a/extensions/browser/api/declarative/rules_registry.h
+++ b/extensions/browser/api/declarative/rules_registry.h
@@ -17,12 +17,12 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/one_shot_event.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "extensions/common/api/events.h"
 #include "extensions/common/extension_id.h"
-#include "extensions/common/one_shot_event.h"
 
 namespace content {
 class BrowserContext;
@@ -55,9 +55,7 @@
                 RulesCacheDelegate* cache_delegate,
                 int id);
 
-  const OneShotEvent& ready() const {
-    return ready_;
-  }
+  const base::OneShotEvent& ready() const { return ready_; }
 
   // RulesRegistry implementation:
 
@@ -258,7 +256,7 @@
 
   // Signaled when we have finished reading from storage for all extensions that
   // are loaded on startup.
-  OneShotEvent ready_;
+  base::OneShotEvent ready_;
 
   ProcessStateMap process_changed_rules_requested_;
 
diff --git a/extensions/browser/api/feedback_private/feedback_private_api.cc b/extensions/browser/api/feedback_private/feedback_private_api.cc
index 8499932..b0f7700 100644
--- a/extensions/browser/api/feedback_private/feedback_private_api.cc
+++ b/extensions/browser/api/feedback_private/feedback_private_api.cc
@@ -357,18 +357,15 @@
   feedback_data->SetAndCompressSystemInfo(std::move(sys_logs));
 
   if (send_histograms) {
-    auto histograms = std::make_unique<std::string>();
-    *histograms =
+    std::string histograms =
         base::StatisticsRecorder::ToJSON(base::JSON_VERBOSITY_LEVEL_FULL);
-    if (!histograms->empty())
-      feedback_data->SetAndCompressHistograms(std::move(histograms));
+    feedback_data->SetAndCompressHistograms(std::move(histograms));
   }
 
   if (send_bluetooth_logs) {
-    std::unique_ptr<std::string> bluetooth_logs =
-        std::make_unique<std::string>();
+    std::string bluetooth_logs;
     if (base::ReadFileToString(base::FilePath(kBluetoothLogsFilePath),
-                               bluetooth_logs.get())) {
+                               &bluetooth_logs)) {
       feedback_data->AddFile(kBluetoothLogsAttachmentName,
                              std::move(bluetooth_logs));
     }
diff --git a/extensions/browser/api/feedback_private/feedback_service.cc b/extensions/browser/api/feedback_private/feedback_service.cc
index 1912141e..8775dfc 100644
--- a/extensions/browser/api/feedback_private/feedback_service.cc
+++ b/extensions/browser/api/feedback_private/feedback_service.cc
@@ -69,7 +69,7 @@
     int64_t /* total_blob_length */) {
   feedback_data->set_attached_file_uuid(std::string());
   if (data)
-    feedback_data->AttachAndCompressFileData(std::move(data));
+    feedback_data->AttachAndCompressFileData(std::move(*data));
 
   CompleteSendFeedback(feedback_data, callback);
 }
@@ -81,7 +81,7 @@
     int64_t /* total_blob_length */) {
   feedback_data->set_screenshot_uuid(std::string());
   if (data)
-    feedback_data->set_image(std::move(data));
+    feedback_data->set_image(std::move(*data));
 
   CompleteSendFeedback(feedback_data, callback);
 }
@@ -110,9 +110,7 @@
           ->BindInterface(ash::mojom::kServiceName, &assistant_controller);
       assistant_controller->SendAssistantFeedback(
           feedback_data->assistant_debug_info_allowed(),
-          feedback_data->description(),
-          (feedback_data->image() != nullptr) ? *(feedback_data->image())
-                                              : std::string());
+          feedback_data->description(), feedback_data->image());
     }
 #endif
 
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos.cc b/extensions/browser/api/networking_private/networking_private_chromeos.cc
index 2532dfa..61fe801 100644
--- a/extensions/browser/api/networking_private/networking_private_chromeos.cc
+++ b/extensions/browser/api/networking_private/networking_private_chromeos.cc
@@ -11,8 +11,6 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/values.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/device_state.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
@@ -45,7 +43,6 @@
 using chromeos::NetworkHandler;
 using chromeos::NetworkStateHandler;
 using chromeos::NetworkTypePattern;
-using chromeos::ShillManagerClient;
 using extensions::NetworkingPrivateDelegate;
 
 namespace private_api = extensions::api::networking_private;
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc b/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
index 98cacbd2..daa98f20 100644
--- a/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
+++ b/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
@@ -13,9 +13,9 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_device_client.h"
-#include "chromeos/dbus/shill_profile_client.h"
-#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/dbus/shill/shill_device_client.h"
+#include "chromeos/dbus/shill/shill_profile_client.h"
+#include "chromeos/dbus/shill/shill_service_client.h"
 #include "chromeos/login/login_state/login_state.h"
 #include "chromeos/network/managed_network_configuration_handler.h"
 #include "chromeos/network/network_configuration_handler.h"
diff --git a/extensions/browser/api/runtime/runtime_api.cc b/extensions/browser/api/runtime/runtime_api.cc
index 50da868..968e2d9 100644
--- a/extensions/browser/api/runtime/runtime_api.cc
+++ b/extensions/browser/api/runtime/runtime_api.cc
@@ -12,6 +12,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
+#include "base/one_shot_event.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -40,7 +41,6 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest_handlers/background_info.h"
 #include "extensions/common/manifest_handlers/shared_module_info.h"
-#include "extensions/common/one_shot_event.h"
 #include "storage/browser/fileapi/isolated_context.h"
 #include "url/gurl.h"
 
diff --git a/extensions/browser/api/serial/serial_apitest.cc b/extensions/browser/api/serial/serial_apitest.cc
index ddd32895..79240759 100644
--- a/extensions/browser/api/serial/serial_apitest.cc
+++ b/extensions/browser/api/serial/serial_apitest.cc
@@ -285,9 +285,7 @@
   }
 
   void GetPort(const base::UnguessableToken& token,
-               device::mojom::SerialPortRequest request,
-               device::mojom::SerialPortConnectionWatcherPtr watcher) override {
-    DCHECK(!watcher);
+               device::mojom::SerialPortRequest request) override {
     auto it = token_path_map_.find(token);
     DCHECK(it != token_path_map_.end());
     mojo::MakeStrongBinding(std::make_unique<FakeSerialPort>(it->second),
diff --git a/extensions/browser/api/serial/serial_port_manager.cc b/extensions/browser/api/serial/serial_port_manager.cc
index f47311b..44ea9b1 100644
--- a/extensions/browser/api/serial/serial_port_manager.cc
+++ b/extensions/browser/api/serial/serial_port_manager.cc
@@ -194,8 +194,7 @@
 
   for (auto& device : devices) {
     if (device->path.AsUTF8Unsafe() == path) {
-      port_manager_->GetPort(device->token, std::move(request),
-                             /*watcher=*/nullptr);
+      port_manager_->GetPort(device->token, std::move(request));
       return;
     }
   }
diff --git a/extensions/browser/api/vpn_provider/vpn_service.cc b/extensions/browser/api/vpn_provider/vpn_service.cc
index beb7781..722dfd40 100644
--- a/extensions/browser/api/vpn_provider/vpn_service.cc
+++ b/extensions/browser/api/vpn_provider/vpn_service.cc
@@ -20,8 +20,8 @@
 #include "base/strings/string_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
-#include "chromeos/dbus/shill_third_party_vpn_driver_client.h"
-#include "chromeos/dbus/shill_third_party_vpn_observer.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_driver_client.h"
+#include "chromeos/dbus/shill/shill_third_party_vpn_observer.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_profile.h"
 #include "chromeos/network/network_profile_handler.h"
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc
index 53898d39..fbb8c365 100644
--- a/extensions/browser/api/web_request/web_request_api.cc
+++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -2380,9 +2380,9 @@
     // singleton is leaked.
     rules_registry->ready().Post(
         FROM_HERE,
-        base::Bind(&ExtensionWebRequestEventRouter::OnRulesRegistryReady,
-                   base::Unretained(this), browser_context, event_name,
-                   request->id, request_stage));
+        base::BindOnce(&ExtensionWebRequestEventRouter::OnRulesRegistryReady,
+                       base::Unretained(this), browser_context, event_name,
+                       request->id, request_stage));
     BlockedRequest& blocked_request = blocked_requests_[request->id];
     blocked_request.num_handlers_blocking++;
     blocked_request.request = request;
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 464ef416..28cb568 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1388,6 +1388,7 @@
   AUTOTESTPRIVATE_SETSHELFAUTOHIDEBEHAVIOR = 1325,
   AUTOTESTPRIVATE_EXPORTCROSTINI = 1326,
   AUTOTESTPRIVATE_IMPORTCROSTINI = 1327,
+  ACCESSIBILITY_PRIVATE_SETVIRTUALKEYBOARDVISIBLE = 1328,
   // Last entry: Add new entries above, then run:
   // python tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/extensions/browser/extension_system.h b/extensions/browser/extension_system.h
index 5177822..2bfdd21 100644
--- a/extensions/browser/extension_system.h
+++ b/extensions/browser/extension_system.h
@@ -20,6 +20,10 @@
 #error "Extensions must be enabled"
 #endif
 
+namespace base {
+class OneShotEvent;
+}
+
 namespace content {
 class BrowserContext;
 }
@@ -33,7 +37,6 @@
 class ExtensionSet;
 class InfoMap;
 class ManagementPolicy;
-class OneShotEvent;
 class QuotaService;
 class RuntimeData;
 class ServiceWorkerManager;
@@ -122,7 +125,7 @@
       const UnloadedExtensionReason reason) {}
 
   // Signaled when the extension system has completed its startup tasks.
-  virtual const OneShotEvent& ready() const = 0;
+  virtual const base::OneShotEvent& ready() const = 0;
 
   // Returns the content verifier, if any.
   virtual ContentVerifier* content_verifier() = 0;
diff --git a/extensions/browser/extension_user_script_loader.cc b/extensions/browser/extension_user_script_loader.cc
index a0b8bc89..205c3fc 100644
--- a/extensions/browser/extension_user_script_loader.cc
+++ b/extensions/browser/extension_user_script_loader.cc
@@ -16,6 +16,7 @@
 #include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/one_shot_event.h"
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
 #include "base/version.h"
@@ -33,7 +34,6 @@
 #include "extensions/common/file_util.h"
 #include "extensions/common/manifest_handlers/default_locale_handler.h"
 #include "extensions/common/message_bundle.h"
-#include "extensions/common/one_shot_event.h"
 #include "ui/base/resource/resource_bundle.h"
 
 using content::BrowserContext;
@@ -217,8 +217,8 @@
     ExtensionSystem::Get(browser_context)
         ->ready()
         .Post(FROM_HERE,
-              base::Bind(&ExtensionUserScriptLoader::OnExtensionSystemReady,
-                         weak_factory_.GetWeakPtr()));
+              base::BindOnce(&ExtensionUserScriptLoader::OnExtensionSystemReady,
+                             weak_factory_.GetWeakPtr()));
   } else {
     SetReady(true);
   }
diff --git a/extensions/browser/mock_extension_system.cc b/extensions/browser/mock_extension_system.cc
index 55a6c454..13eeaa1 100644
--- a/extensions/browser/mock_extension_system.cc
+++ b/extensions/browser/mock_extension_system.cc
@@ -64,7 +64,7 @@
   return nullptr;
 }
 
-const OneShotEvent& MockExtensionSystem::ready() const {
+const base::OneShotEvent& MockExtensionSystem::ready() const {
   return ready_;
 }
 
diff --git a/extensions/browser/mock_extension_system.h b/extensions/browser/mock_extension_system.h
index 6a51491..6d5b7c7 100644
--- a/extensions/browser/mock_extension_system.h
+++ b/extensions/browser/mock_extension_system.h
@@ -6,11 +6,11 @@
 #define EXTENSIONS_BROWSER_MOCK_EXTENSION_SYSTEM_H_
 
 #include "base/macros.h"
+#include "base/one_shot_event.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "extensions/browser/extension_registry_factory.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/extension_system_provider.h"
-#include "extensions/common/one_shot_event.h"
 
 namespace extensions {
 
@@ -42,7 +42,7 @@
   InfoMap* info_map() override;
   QuotaService* quota_service() override;
   AppSorting* app_sorting() override;
-  const OneShotEvent& ready() const override;
+  const base::OneShotEvent& ready() const override;
   ContentVerifier* content_verifier() override;
   std::unique_ptr<ExtensionSet> GetDependentExtensions(
       const Extension* extension) override;
@@ -56,7 +56,7 @@
 
  private:
   content::BrowserContext* browser_context_;
-  OneShotEvent ready_;
+  base::OneShotEvent ready_;
 
   DISALLOW_COPY_AND_ASSIGN(MockExtensionSystem);
 };
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
index 14fa00f..b203c13 100644
--- a/extensions/browser/process_manager.cc
+++ b/extensions/browser/process_manager.cc
@@ -14,6 +14,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/one_shot_event.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task/post_task.h"
@@ -49,7 +50,6 @@
 #include "extensions/common/extension_messages.h"
 #include "extensions/common/manifest_handlers/background_info.h"
 #include "extensions/common/manifest_handlers/incognito_info.h"
-#include "extensions/common/one_shot_event.h"
 
 using content::BrowserContext;
 
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn
index 641ca4e..1c2643d 100644
--- a/extensions/common/BUILD.gn
+++ b/extensions/common/BUILD.gn
@@ -241,8 +241,6 @@
       "manifest_url_handlers.h",
       "message_bundle.cc",
       "message_bundle.h",
-      "one_shot_event.cc",
-      "one_shot_event.h",
       "permissions/api_permission.cc",
       "permissions/api_permission.h",
       "permissions/api_permission_set.cc",
@@ -429,7 +427,6 @@
       "manifest_handlers/oauth2_manifest_unittest.cc",
       "manifest_handlers/shared_module_manifest_unittest.cc",
       "message_bundle_unittest.cc",
-      "one_shot_event_unittest.cc",
       "permissions/api_permission_set_unittest.cc",
       "permissions/api_permission_unittest.cc",
       "permissions/base_set_operators_unittest.cc",
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc
index ae13bf6..fbe97b24 100644
--- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc
+++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.cc
@@ -91,7 +91,7 @@
 void MimeHandlerViewContainerManager::RetryCreatingMimeHandlerViewGuest(
     int32_t element_instance_id) {
   if (auto* frame_container = GetFrameContainer(element_instance_id))
-    frame_container->DestroyFrameContainer();
+    frame_container->RetryCreatingMimeHandlerViewGuest();
 }
 
 void MimeHandlerViewContainerManager::DidLoad(int32_t element_instance_id) {
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn
index de406cea..4f0d95f 100644
--- a/extensions/shell/BUILD.gn
+++ b/extensions/shell/BUILD.gn
@@ -70,7 +70,7 @@
     "//google_apis",
     "//third_party/blink/public:blink",
     "//ui/base",
-    "//ui/base/ime",
+    "//ui/base/ime/init",
   ]
 
   # TODO(michaelpg): remove Mac support and always use aura.
@@ -346,6 +346,7 @@
     deps += [
       "//ui/aura:test_support",
       "//ui/base:test_support",
+      "//ui/base/ime/init",
       "//ui/compositor:test_support",
     ]
   }
diff --git a/extensions/shell/browser/shell_browser_main_parts.cc b/extensions/shell/browser/shell_browser_main_parts.cc
index ef09855..2604e90 100644
--- a/extensions/shell/browser/shell_browser_main_parts.cc
+++ b/extensions/shell/browser/shell_browser_main_parts.cc
@@ -42,7 +42,7 @@
 #include "extensions/shell/browser/shell_update_query_params_delegate.h"
 #include "extensions/shell/common/shell_extensions_client.h"
 #include "extensions/shell/common/switches.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/resource/resource_bundle.h"
 
 #if defined(USE_AURA)
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.cc b/extensions/shell/browser/shell_desktop_controller_aura.cc
index 73abaf0..8fa05d0 100644
--- a/extensions/shell/browser/shell_desktop_controller_aura.cc
+++ b/extensions/shell/browser/shell_desktop_controller_aura.cc
@@ -18,8 +18,8 @@
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/image_cursors.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_factory.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
diff --git a/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc b/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc
index 7667aeb..b6cd5f3 100644
--- a/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc
+++ b/extensions/shell/browser/shell_desktop_controller_aura_unittest.cc
@@ -24,8 +24,8 @@
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/ime/dummy_text_input_client.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_factory.h"
 #include "ui/base/ime/input_method_minimal.h"
 #include "ui/display/display.h"
 #include "ui/display/screen_base.h"
diff --git a/extensions/shell/browser/shell_extension_system.cc b/extensions/shell/browser/shell_extension_system.cc
index a3bffdb..e778a0c 100644
--- a/extensions/shell/browser/shell_extension_system.cc
+++ b/extensions/shell/browser/shell_extension_system.cc
@@ -154,7 +154,7 @@
     const std::string& extension_id,
     const UnloadedExtensionReason reason) {}
 
-const OneShotEvent& ShellExtensionSystem::ready() const {
+const base::OneShotEvent& ShellExtensionSystem::ready() const {
   return ready_;
 }
 
diff --git a/extensions/shell/browser/shell_extension_system.h b/extensions/shell/browser/shell_extension_system.h
index 7e6075a93..a782471f 100644
--- a/extensions/shell/browser/shell_extension_system.h
+++ b/extensions/shell/browser/shell_extension_system.h
@@ -12,8 +12,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/one_shot_event.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/common/one_shot_event.h"
 
 namespace base {
 class FilePath;
@@ -78,7 +78,7 @@
   void UnregisterExtensionWithRequestContexts(
       const std::string& extension_id,
       const UnloadedExtensionReason reason) override;
-  const OneShotEvent& ready() const override;
+  const base::OneShotEvent& ready() const override;
   ContentVerifier* content_verifier() override;
   std::unique_ptr<ExtensionSet> GetDependentExtensions(
       const Extension* extension) override;
@@ -108,7 +108,7 @@
   scoped_refptr<ValueStoreFactory> store_factory_;
 
   // Signaled when the extension system has completed its startup tasks.
-  OneShotEvent ready_;
+  base::OneShotEvent ready_;
 
   base::WeakPtrFactory<ShellExtensionSystem> weak_factory_;
 
diff --git a/fuchsia/engine/web_engine_main_delegate.cc b/fuchsia/engine/web_engine_main_delegate.cc
index a9044e3b1..a19fc9d 100644
--- a/fuchsia/engine/web_engine_main_delegate.cc
+++ b/fuchsia/engine/web_engine_main_delegate.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/base_paths.h"
+#include "base/base_paths_fuchsia.h"
 #include "base/command_line.h"
 #include "base/path_service.h"
 #include "content/public/common/content_switches.h"
@@ -25,8 +26,8 @@
   base::FilePath log_filename;
   std::string filename = command_line.GetSwitchValueASCII(switches::kLogFile);
   if (filename.empty()) {
-    base::PathService::Get(base::DIR_EXE, &log_filename);
-    log_filename = log_filename.AppendASCII("webrunner.log");
+    base::PathService::Get(base::DIR_APP_DATA, &log_filename);
+    log_filename = log_filename.AppendASCII("web_engine.log");
   } else {
     log_filename = base::FilePath::FromUTF8Unsafe(filename);
   }
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 7c637d3..4210e8a 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -3887,14 +3887,6 @@
     'extension': 'CHROMIUM_lose_context',
     'trace_level': 1,
   },
-  'InsertFenceSyncCHROMIUM': {
-    'type': 'Custom',
-    'internal': True,
-    'impl_func': False,
-    'cmd_args': 'GLuint64 release_count',
-    'extension': "CHROMIUM_sync_point",
-    'trace_level': 1,
-  },
   'GenSyncTokenCHROMIUM': {
     'type': 'NoCommand',
     'extension': "CHROMIUM_sync_point",
diff --git a/gpu/command_buffer/build_raster_cmd_buffer.py b/gpu/command_buffer/build_raster_cmd_buffer.py
index bd59f96..dfd29c7 100755
--- a/gpu/command_buffer/build_raster_cmd_buffer.py
+++ b/gpu/command_buffer/build_raster_cmd_buffer.py
@@ -271,13 +271,6 @@
     'client_test': False,
     'cmd_args': 'GLuint url_bucket_id',
   },
-  'InsertFenceSyncCHROMIUM': {
-    'type': 'Custom',
-    'internal': True,
-    'impl_func': False,
-    'cmd_args': 'GLuint64 release_count',
-    'trace_level': 1,
-  },
   'LoseContextCHROMIUM': {
     'decoder_func': 'DoLoseContextCHROMIUM',
     'unit_test': False,
diff --git a/gpu/command_buffer/client/client_test_helper.cc b/gpu/command_buffer/client/client_test_helper.cc
index 89570ea..df2c7c24 100644
--- a/gpu/command_buffer/client/client_test_helper.cc
+++ b/gpu/command_buffer/client/client_test_helper.cc
@@ -177,4 +177,15 @@
 
 MockClientGpuControl::~MockClientGpuControl() = default;
 
+FakeDecoderClient::~FakeDecoderClient() = default;
+void FakeDecoderClient::OnConsoleMessage(int32_t, const std::string&) {}
+void FakeDecoderClient::CacheShader(const std::string&, const std::string&) {}
+void FakeDecoderClient::OnFenceSyncRelease(uint64_t) {}
+void FakeDecoderClient::OnDescheduleUntilFinished() {}
+void FakeDecoderClient::OnRescheduleAfterFinished() {}
+void FakeDecoderClient::OnSwapBuffers(uint64_t, uint32_t) {}
+void FakeDecoderClient::ScheduleGrContextCleanup() {}
+void FakeDecoderClient::SetActiveURL(GURL) {}
+void FakeDecoderClient::HandleReturnData(base::span<const uint8_t>) {}
+
 }  // namespace gpu
diff --git a/gpu/command_buffer/client/client_test_helper.h b/gpu/command_buffer/client/client_test_helper.h
index a293fe6..75ccd661 100644
--- a/gpu/command_buffer/client/client_test_helper.h
+++ b/gpu/command_buffer/client/client_test_helper.h
@@ -19,6 +19,7 @@
 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/command_buffer/service/decoder_client.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -147,6 +148,20 @@
   DISALLOW_COPY_AND_ASSIGN(MockClientGpuControl);
 };
 
+class FakeDecoderClient : public DecoderClient {
+ public:
+  ~FakeDecoderClient() override;
+  void OnConsoleMessage(int32_t id, const std::string& message) override;
+  void CacheShader(const std::string& key, const std::string& shader) override;
+  void OnFenceSyncRelease(uint64_t release) override;
+  void OnDescheduleUntilFinished() override;
+  void OnRescheduleAfterFinished() override;
+  void OnSwapBuffers(uint64_t swap_id, uint32_t flags) override;
+  void ScheduleGrContextCleanup() override;
+  void SetActiveURL(GURL url) override;
+  void HandleReturnData(base::span<const uint8_t> data) override;
+};
+
 }  // namespace gpu
 
 #endif  // GPU_COMMAND_BUFFER_CLIENT_CLIENT_TEST_HELPER_H_
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h
index d6ff4d05..c8bbb11 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper.h
+++ b/gpu/command_buffer/client/cmd_buffer_helper.h
@@ -250,6 +250,13 @@
     }
   }
 
+  void InsertFenceSync(uint64_t release_count) {
+    cmd::InsertFenceSync* c = GetCmdSpace<cmd::InsertFenceSync>();
+    if (c) {
+      c->Init(release_count);
+    }
+  }
+
   CommandBuffer* command_buffer() const { return command_buffer_; }
 
   scoped_refptr<Buffer> get_ring_buffer() const { return ring_buffer_; }
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index e2ac0195..dc77c30b 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -2886,14 +2886,6 @@
   }
 }
 
-void InsertFenceSyncCHROMIUM(GLuint64 release_count) {
-  gles2::cmds::InsertFenceSyncCHROMIUM* c =
-      GetCmdSpace<gles2::cmds::InsertFenceSyncCHROMIUM>();
-  if (c) {
-    c->Init(release_count);
-  }
-}
-
 void UnpremultiplyAndDitherCopyCHROMIUM(GLuint source_id,
                                         GLuint dest_id,
                                         GLint x,
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index e748a48..6cf2b48 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -6670,7 +6670,7 @@
   }
 
   uint64_t fence_sync = gpu_control_->GenerateFenceSyncRelease();
-  helper_->InsertFenceSyncCHROMIUM(fence_sync);
+  helper_->InsertFenceSync(fence_sync);
   helper_->CommandBufferHelper::OrderingBarrier();
   gpu_control_->EnsureWorkVisible();
 
@@ -6689,7 +6689,7 @@
   }
 
   uint64_t fence_sync = gpu_control_->GenerateFenceSyncRelease();
-  helper_->InsertFenceSyncCHROMIUM(fence_sync);
+  helper_->InsertFenceSync(fence_sync);
   helper_->CommandBufferHelper::OrderingBarrier();
 
   // Copy the data over after setting the data to ensure alignment.
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index 717abb1..77861ecf 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -3851,7 +3851,7 @@
   EXPECT_EQ(GL_INVALID_VALUE, CheckError());
 
   const void* commands = GetPut();
-  cmds::InsertFenceSyncCHROMIUM insert_fence_sync;
+  cmd::InsertFenceSync insert_fence_sync;
   insert_fence_sync.Init(kFenceSync);
 
   EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
@@ -3884,7 +3884,7 @@
   EXPECT_EQ(GL_INVALID_VALUE, CheckError());
 
   const void* commands = GetPut();
-  cmds::InsertFenceSyncCHROMIUM insert_fence_sync;
+  cmd::InsertFenceSync insert_fence_sync;
   insert_fence_sync.Init(kFenceSync);
 
   EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
@@ -4034,7 +4034,7 @@
   GLbyte* sync_token_data = sync_token.GetData();
 
   struct Cmds {
-    cmds::InsertFenceSyncCHROMIUM insert_fence_sync;
+    cmd::InsertFenceSync insert_fence_sync;
   };
   Cmds expected;
   expected.insert_fence_sync.Init(kFenceSync);
diff --git a/gpu/command_buffer/client/raster_cmd_helper_autogen.h b/gpu/command_buffer/client/raster_cmd_helper_autogen.h
index 1ea6b2d..0bbe47f5 100644
--- a/gpu/command_buffer/client/raster_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/raster_cmd_helper_autogen.h
@@ -76,14 +76,6 @@
   }
 }
 
-void InsertFenceSyncCHROMIUM(GLuint64 release_count) {
-  raster::cmds::InsertFenceSyncCHROMIUM* c =
-      GetCmdSpace<raster::cmds::InsertFenceSyncCHROMIUM>();
-  if (c) {
-    c->Init(release_count);
-  }
-}
-
 void BeginRasterCHROMIUMImmediate(GLuint sk_color,
                                   GLuint msaa_sample_count,
                                   GLboolean can_use_lcd_text,
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc
index 6ae0f513..b27e74a 100644
--- a/gpu/command_buffer/client/raster_implementation.cc
+++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -913,7 +913,7 @@
   }
 
   uint64_t fence_sync = gpu_control_->GenerateFenceSyncRelease();
-  helper_->InsertFenceSyncCHROMIUM(fence_sync);
+  helper_->InsertFenceSync(fence_sync);
   helper_->CommandBufferHelper::OrderingBarrier();
 
   // Copy the data over after setting the data to ensure alignment.
diff --git a/gpu/command_buffer/client/raster_implementation_unittest.cc b/gpu/command_buffer/client/raster_implementation_unittest.cc
index 3e34ef9..f59d22b 100644
--- a/gpu/command_buffer/client/raster_implementation_unittest.cc
+++ b/gpu/command_buffer/client/raster_implementation_unittest.cc
@@ -523,7 +523,7 @@
   EXPECT_EQ(GL_INVALID_VALUE, CheckError());
 
   const void* commands = GetPut();
-  cmds::InsertFenceSyncCHROMIUM insert_fence_sync;
+  cmd::InsertFenceSync insert_fence_sync;
   insert_fence_sync.Init(kFenceSync);
 
   EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
@@ -673,7 +673,7 @@
   GLbyte* sync_token_data = sync_token.GetData();
 
   struct Cmds {
-    cmds::InsertFenceSyncCHROMIUM insert_fence_sync;
+    cmd::InsertFenceSync insert_fence_sync;
   };
   Cmds expected;
   expected.insert_fence_sync.Init(kFenceSync);
diff --git a/gpu/command_buffer/common/cmd_buffer_common.h b/gpu/command_buffer/common/cmd_buffer_common.h
index 0ae8bec..ae83e190 100644
--- a/gpu/command_buffer/common/cmd_buffer_common.h
+++ b/gpu/command_buffer/common/cmd_buffer_common.h
@@ -171,13 +171,14 @@
 //
 // NOTE: THE ORDER OF THESE MUST NOT CHANGE (their id is derived by order)
 #define COMMON_COMMAND_BUFFER_CMDS(OP) \
-  OP(Noop)                          /*  0 */ \
-  OP(SetToken)                      /*  1 */ \
-  OP(SetBucketSize)                 /*  2 */ \
-  OP(SetBucketData)                 /*  3 */ \
-  OP(SetBucketDataImmediate)        /*  4 */ \
-  OP(GetBucketStart)                /*  5 */ \
-  OP(GetBucketData)                 /*  6 */ \
+  OP(Noop)                   /*  0 */  \
+  OP(SetToken)               /*  1 */  \
+  OP(SetBucketSize)          /*  2 */  \
+  OP(SetBucketData)          /*  3 */  \
+  OP(SetBucketDataImmediate) /*  4 */  \
+  OP(GetBucketStart)         /*  5 */  \
+  OP(GetBucketData)          /*  6 */  \
+  OP(InsertFenceSync)        /*  7 */
 
 // Common commands.
 enum CommandId {
@@ -552,6 +553,45 @@
 static_assert(offsetof(GetBucketData, shared_memory_offset) == 20,
               "offset of GetBucketData.shared_memory_offset should be 20");
 
+struct InsertFenceSync {
+  typedef InsertFenceSync ValueType;
+  static const CommandId kCmdId = kInsertFenceSync;
+  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+  static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1);
+
+  void SetHeader() { header.SetCmd<ValueType>(); }
+
+  void Init(uint64_t _release_count) {
+    SetHeader();
+    release_count_0 = static_cast<uint32_t>(_release_count & 0xFFFFFFFF);
+    release_count_1 =
+        static_cast<uint32_t>((_release_count >> 32) & 0xFFFFFFFF);
+  }
+
+  void* Set(void* cmd, uint64_t _release_count) {
+    static_cast<ValueType*>(cmd)->Init(_release_count);
+    return NextCmdAddress<ValueType>(cmd);
+  }
+
+  uint64_t release_count() const volatile {
+    return (static_cast<uint64_t>(release_count_1) << 32) +
+           static_cast<uint64_t>(release_count_0);
+  }
+
+  gpu::CommandHeader header;
+  uint32_t release_count_0;
+  uint32_t release_count_1;
+};
+
+static_assert(sizeof(InsertFenceSync) == 12,
+              "size of InsertFenceSync should be 12");
+static_assert(offsetof(InsertFenceSync, header) == 0,
+              "offset of InsertFenceSync header should be 0");
+static_assert(offsetof(InsertFenceSync, release_count_0) == 4,
+              "offset of InsertFenceSync release_count_0 should be 4");
+static_assert(offsetof(InsertFenceSync, release_count_1) == 8,
+              "offset of InsertFenceSync release_count_1 should be 8");
+
 }  // namespace cmd
 
 #pragma pack(pop)
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 2a59e11..ebc1f78 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -14280,48 +14280,6 @@
 static_assert(offsetof(LoseContextCHROMIUM, other) == 8,
               "offset of LoseContextCHROMIUM other should be 8");
 
-struct InsertFenceSyncCHROMIUM {
-  typedef InsertFenceSyncCHROMIUM ValueType;
-  static const CommandId kCmdId = kInsertFenceSyncCHROMIUM;
-  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
-  static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1);
-
-  static uint32_t ComputeSize() {
-    return static_cast<uint32_t>(sizeof(ValueType));  // NOLINT
-  }
-
-  void SetHeader() { header.SetCmd<ValueType>(); }
-
-  void Init(GLuint64 _release_count) {
-    SetHeader();
-    GLES2Util::MapUint64ToTwoUint32(static_cast<uint64_t>(_release_count),
-                                    &release_count_0, &release_count_1);
-  }
-
-  void* Set(void* cmd, GLuint64 _release_count) {
-    static_cast<ValueType*>(cmd)->Init(_release_count);
-    return NextCmdAddress<ValueType>(cmd);
-  }
-
-  GLuint64 release_count() const volatile {
-    return static_cast<GLuint64>(
-        GLES2Util::MapTwoUint32ToUint64(release_count_0, release_count_1));
-  }
-
-  gpu::CommandHeader header;
-  uint32_t release_count_0;
-  uint32_t release_count_1;
-};
-
-static_assert(sizeof(InsertFenceSyncCHROMIUM) == 12,
-              "size of InsertFenceSyncCHROMIUM should be 12");
-static_assert(offsetof(InsertFenceSyncCHROMIUM, header) == 0,
-              "offset of InsertFenceSyncCHROMIUM header should be 0");
-static_assert(offsetof(InsertFenceSyncCHROMIUM, release_count_0) == 4,
-              "offset of InsertFenceSyncCHROMIUM release_count_0 should be 4");
-static_assert(offsetof(InsertFenceSyncCHROMIUM, release_count_1) == 8,
-              "offset of InsertFenceSyncCHROMIUM release_count_1 should be 8");
-
 struct UnpremultiplyAndDitherCopyCHROMIUM {
   typedef UnpremultiplyAndDitherCopyCHROMIUM ValueType;
   static const CommandId kCmdId = kUnpremultiplyAndDitherCopyCHROMIUM;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index 1284733..fd913f8 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -4758,17 +4758,6 @@
   CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
 }
 
-TEST_F(GLES2FormatTest, InsertFenceSyncCHROMIUM) {
-  cmds::InsertFenceSyncCHROMIUM& cmd =
-      *GetBufferAs<cmds::InsertFenceSyncCHROMIUM>();
-  void* next_cmd = cmd.Set(&cmd, static_cast<GLuint64>(11));
-  EXPECT_EQ(static_cast<uint32_t>(cmds::InsertFenceSyncCHROMIUM::kCmdId),
-            cmd.header.command);
-  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
-  EXPECT_EQ(static_cast<GLuint64>(11), cmd.release_count());
-  CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
-}
-
 TEST_F(GLES2FormatTest, UnpremultiplyAndDitherCopyCHROMIUM) {
   cmds::UnpremultiplyAndDitherCopyCHROMIUM& cmd =
       *GetBufferAs<cmds::UnpremultiplyAndDitherCopyCHROMIUM>();
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index b3dd9b3..5fab1e6 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -301,67 +301,66 @@
   OP(TraceEndCHROMIUM)                                     /* 542 */ \
   OP(DiscardFramebufferEXTImmediate)                       /* 543 */ \
   OP(LoseContextCHROMIUM)                                  /* 544 */ \
-  OP(InsertFenceSyncCHROMIUM)                              /* 545 */ \
-  OP(UnpremultiplyAndDitherCopyCHROMIUM)                   /* 546 */ \
-  OP(DrawBuffersEXTImmediate)                              /* 547 */ \
-  OP(DiscardBackbufferCHROMIUM)                            /* 548 */ \
-  OP(ScheduleOverlayPlaneCHROMIUM)                         /* 549 */ \
-  OP(ScheduleCALayerSharedStateCHROMIUM)                   /* 550 */ \
-  OP(ScheduleCALayerCHROMIUM)                              /* 551 */ \
-  OP(ScheduleCALayerInUseQueryCHROMIUMImmediate)           /* 552 */ \
-  OP(CommitOverlayPlanesCHROMIUM)                          /* 553 */ \
-  OP(FlushDriverCachesCHROMIUM)                            /* 554 */ \
-  OP(ScheduleDCLayerCHROMIUM)                              /* 555 */ \
-  OP(SetActiveURLCHROMIUM)                                 /* 556 */ \
-  OP(MatrixLoadfCHROMIUMImmediate)                         /* 557 */ \
-  OP(MatrixLoadIdentityCHROMIUM)                           /* 558 */ \
-  OP(GenPathsCHROMIUM)                                     /* 559 */ \
-  OP(DeletePathsCHROMIUM)                                  /* 560 */ \
-  OP(IsPathCHROMIUM)                                       /* 561 */ \
-  OP(PathCommandsCHROMIUM)                                 /* 562 */ \
-  OP(PathParameterfCHROMIUM)                               /* 563 */ \
-  OP(PathParameteriCHROMIUM)                               /* 564 */ \
-  OP(PathStencilFuncCHROMIUM)                              /* 565 */ \
-  OP(StencilFillPathCHROMIUM)                              /* 566 */ \
-  OP(StencilStrokePathCHROMIUM)                            /* 567 */ \
-  OP(CoverFillPathCHROMIUM)                                /* 568 */ \
-  OP(CoverStrokePathCHROMIUM)                              /* 569 */ \
-  OP(StencilThenCoverFillPathCHROMIUM)                     /* 570 */ \
-  OP(StencilThenCoverStrokePathCHROMIUM)                   /* 571 */ \
-  OP(StencilFillPathInstancedCHROMIUM)                     /* 572 */ \
-  OP(StencilStrokePathInstancedCHROMIUM)                   /* 573 */ \
-  OP(CoverFillPathInstancedCHROMIUM)                       /* 574 */ \
-  OP(CoverStrokePathInstancedCHROMIUM)                     /* 575 */ \
-  OP(StencilThenCoverFillPathInstancedCHROMIUM)            /* 576 */ \
-  OP(StencilThenCoverStrokePathInstancedCHROMIUM)          /* 577 */ \
-  OP(BindFragmentInputLocationCHROMIUMBucket)              /* 578 */ \
-  OP(ProgramPathFragmentInputGenCHROMIUM)                  /* 579 */ \
-  OP(CoverageModulationCHROMIUM)                           /* 580 */ \
-  OP(BlendBarrierKHR)                                      /* 581 */ \
-  OP(ApplyScreenSpaceAntialiasingCHROMIUM)                 /* 582 */ \
-  OP(BindFragDataLocationIndexedEXTBucket)                 /* 583 */ \
-  OP(BindFragDataLocationEXTBucket)                        /* 584 */ \
-  OP(GetFragDataIndexEXT)                                  /* 585 */ \
-  OP(UniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate) /* 586 */ \
-  OP(OverlayPromotionHintCHROMIUM)                         /* 587 */ \
-  OP(SwapBuffersWithBoundsCHROMIUMImmediate)               /* 588 */ \
-  OP(SetDrawRectangleCHROMIUM)                             /* 589 */ \
-  OP(SetEnableDCLayersCHROMIUM)                            /* 590 */ \
-  OP(InitializeDiscardableTextureCHROMIUM)                 /* 591 */ \
-  OP(UnlockDiscardableTextureCHROMIUM)                     /* 592 */ \
-  OP(LockDiscardableTextureCHROMIUM)                       /* 593 */ \
-  OP(TexStorage2DImageCHROMIUM)                            /* 594 */ \
-  OP(SetColorSpaceMetadataCHROMIUM)                        /* 595 */ \
-  OP(WindowRectanglesEXTImmediate)                         /* 596 */ \
-  OP(CreateGpuFenceINTERNAL)                               /* 597 */ \
-  OP(WaitGpuFenceCHROMIUM)                                 /* 598 */ \
-  OP(DestroyGpuFenceCHROMIUM)                              /* 599 */ \
-  OP(SetReadbackBufferShadowAllocationINTERNAL)            /* 600 */ \
-  OP(FramebufferTextureMultiviewLayeredANGLE)              /* 601 */ \
-  OP(MaxShaderCompilerThreadsKHR)                          /* 602 */ \
-  OP(CreateAndTexStorage2DSharedImageINTERNALImmediate)    /* 603 */ \
-  OP(BeginSharedImageAccessDirectCHROMIUM)                 /* 604 */ \
-  OP(EndSharedImageAccessDirectCHROMIUM)                   /* 605 */
+  OP(UnpremultiplyAndDitherCopyCHROMIUM)                   /* 545 */ \
+  OP(DrawBuffersEXTImmediate)                              /* 546 */ \
+  OP(DiscardBackbufferCHROMIUM)                            /* 547 */ \
+  OP(ScheduleOverlayPlaneCHROMIUM)                         /* 548 */ \
+  OP(ScheduleCALayerSharedStateCHROMIUM)                   /* 549 */ \
+  OP(ScheduleCALayerCHROMIUM)                              /* 550 */ \
+  OP(ScheduleCALayerInUseQueryCHROMIUMImmediate)           /* 551 */ \
+  OP(CommitOverlayPlanesCHROMIUM)                          /* 552 */ \
+  OP(FlushDriverCachesCHROMIUM)                            /* 553 */ \
+  OP(ScheduleDCLayerCHROMIUM)                              /* 554 */ \
+  OP(SetActiveURLCHROMIUM)                                 /* 555 */ \
+  OP(MatrixLoadfCHROMIUMImmediate)                         /* 556 */ \
+  OP(MatrixLoadIdentityCHROMIUM)                           /* 557 */ \
+  OP(GenPathsCHROMIUM)                                     /* 558 */ \
+  OP(DeletePathsCHROMIUM)                                  /* 559 */ \
+  OP(IsPathCHROMIUM)                                       /* 560 */ \
+  OP(PathCommandsCHROMIUM)                                 /* 561 */ \
+  OP(PathParameterfCHROMIUM)                               /* 562 */ \
+  OP(PathParameteriCHROMIUM)                               /* 563 */ \
+  OP(PathStencilFuncCHROMIUM)                              /* 564 */ \
+  OP(StencilFillPathCHROMIUM)                              /* 565 */ \
+  OP(StencilStrokePathCHROMIUM)                            /* 566 */ \
+  OP(CoverFillPathCHROMIUM)                                /* 567 */ \
+  OP(CoverStrokePathCHROMIUM)                              /* 568 */ \
+  OP(StencilThenCoverFillPathCHROMIUM)                     /* 569 */ \
+  OP(StencilThenCoverStrokePathCHROMIUM)                   /* 570 */ \
+  OP(StencilFillPathInstancedCHROMIUM)                     /* 571 */ \
+  OP(StencilStrokePathInstancedCHROMIUM)                   /* 572 */ \
+  OP(CoverFillPathInstancedCHROMIUM)                       /* 573 */ \
+  OP(CoverStrokePathInstancedCHROMIUM)                     /* 574 */ \
+  OP(StencilThenCoverFillPathInstancedCHROMIUM)            /* 575 */ \
+  OP(StencilThenCoverStrokePathInstancedCHROMIUM)          /* 576 */ \
+  OP(BindFragmentInputLocationCHROMIUMBucket)              /* 577 */ \
+  OP(ProgramPathFragmentInputGenCHROMIUM)                  /* 578 */ \
+  OP(CoverageModulationCHROMIUM)                           /* 579 */ \
+  OP(BlendBarrierKHR)                                      /* 580 */ \
+  OP(ApplyScreenSpaceAntialiasingCHROMIUM)                 /* 581 */ \
+  OP(BindFragDataLocationIndexedEXTBucket)                 /* 582 */ \
+  OP(BindFragDataLocationEXTBucket)                        /* 583 */ \
+  OP(GetFragDataIndexEXT)                                  /* 584 */ \
+  OP(UniformMatrix4fvStreamTextureMatrixCHROMIUMImmediate) /* 585 */ \
+  OP(OverlayPromotionHintCHROMIUM)                         /* 586 */ \
+  OP(SwapBuffersWithBoundsCHROMIUMImmediate)               /* 587 */ \
+  OP(SetDrawRectangleCHROMIUM)                             /* 588 */ \
+  OP(SetEnableDCLayersCHROMIUM)                            /* 589 */ \
+  OP(InitializeDiscardableTextureCHROMIUM)                 /* 590 */ \
+  OP(UnlockDiscardableTextureCHROMIUM)                     /* 591 */ \
+  OP(LockDiscardableTextureCHROMIUM)                       /* 592 */ \
+  OP(TexStorage2DImageCHROMIUM)                            /* 593 */ \
+  OP(SetColorSpaceMetadataCHROMIUM)                        /* 594 */ \
+  OP(WindowRectanglesEXTImmediate)                         /* 595 */ \
+  OP(CreateGpuFenceINTERNAL)                               /* 596 */ \
+  OP(WaitGpuFenceCHROMIUM)                                 /* 597 */ \
+  OP(DestroyGpuFenceCHROMIUM)                              /* 598 */ \
+  OP(SetReadbackBufferShadowAllocationINTERNAL)            /* 599 */ \
+  OP(FramebufferTextureMultiviewLayeredANGLE)              /* 600 */ \
+  OP(MaxShaderCompilerThreadsKHR)                          /* 601 */ \
+  OP(CreateAndTexStorage2DSharedImageINTERNALImmediate)    /* 602 */ \
+  OP(BeginSharedImageAccessDirectCHROMIUM)                 /* 603 */ \
+  OP(EndSharedImageAccessDirectCHROMIUM)                   /* 604 */
 
 enum CommandId {
   kOneBeforeStartPoint =
diff --git a/gpu/command_buffer/common/raster_cmd_format_autogen.h b/gpu/command_buffer/common/raster_cmd_format_autogen.h
index 9c5c570..a628b27 100644
--- a/gpu/command_buffer/common/raster_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/raster_cmd_format_autogen.h
@@ -313,49 +313,6 @@
 static_assert(offsetof(LoseContextCHROMIUM, other) == 8,
               "offset of LoseContextCHROMIUM other should be 8");
 
-struct InsertFenceSyncCHROMIUM {
-  typedef InsertFenceSyncCHROMIUM ValueType;
-  static const CommandId kCmdId = kInsertFenceSyncCHROMIUM;
-  static const cmd::ArgFlags kArgFlags = cmd::kFixed;
-  static const uint8_t cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(1);
-
-  static uint32_t ComputeSize() {
-    return static_cast<uint32_t>(sizeof(ValueType));  // NOLINT
-  }
-
-  void SetHeader() { header.SetCmd<ValueType>(); }
-
-  void Init(GLuint64 _release_count) {
-    SetHeader();
-    gles2::GLES2Util::MapUint64ToTwoUint32(
-        static_cast<uint64_t>(_release_count), &release_count_0,
-        &release_count_1);
-  }
-
-  void* Set(void* cmd, GLuint64 _release_count) {
-    static_cast<ValueType*>(cmd)->Init(_release_count);
-    return NextCmdAddress<ValueType>(cmd);
-  }
-
-  GLuint64 release_count() const volatile {
-    return static_cast<GLuint64>(gles2::GLES2Util::MapTwoUint32ToUint64(
-        release_count_0, release_count_1));
-  }
-
-  gpu::CommandHeader header;
-  uint32_t release_count_0;
-  uint32_t release_count_1;
-};
-
-static_assert(sizeof(InsertFenceSyncCHROMIUM) == 12,
-              "size of InsertFenceSyncCHROMIUM should be 12");
-static_assert(offsetof(InsertFenceSyncCHROMIUM, header) == 0,
-              "offset of InsertFenceSyncCHROMIUM header should be 0");
-static_assert(offsetof(InsertFenceSyncCHROMIUM, release_count_0) == 4,
-              "offset of InsertFenceSyncCHROMIUM release_count_0 should be 4");
-static_assert(offsetof(InsertFenceSyncCHROMIUM, release_count_1) == 8,
-              "offset of InsertFenceSyncCHROMIUM release_count_1 should be 8");
-
 struct BeginRasterCHROMIUMImmediate {
   typedef BeginRasterCHROMIUMImmediate ValueType;
   static const CommandId kCmdId = kBeginRasterCHROMIUMImmediate;
diff --git a/gpu/command_buffer/common/raster_cmd_format_test_autogen.h b/gpu/command_buffer/common/raster_cmd_format_test_autogen.h
index 15145cc..d8a94e7 100644
--- a/gpu/command_buffer/common/raster_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/raster_cmd_format_test_autogen.h
@@ -120,17 +120,6 @@
   CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
 }
 
-TEST_F(RasterFormatTest, InsertFenceSyncCHROMIUM) {
-  cmds::InsertFenceSyncCHROMIUM& cmd =
-      *GetBufferAs<cmds::InsertFenceSyncCHROMIUM>();
-  void* next_cmd = cmd.Set(&cmd, static_cast<GLuint64>(11));
-  EXPECT_EQ(static_cast<uint32_t>(cmds::InsertFenceSyncCHROMIUM::kCmdId),
-            cmd.header.command);
-  EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
-  EXPECT_EQ(static_cast<GLuint64>(11), cmd.release_count());
-  CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
-}
-
 TEST_F(RasterFormatTest, BeginRasterCHROMIUMImmediate) {
   const int kSomeBaseValueToTestWith = 51;
   static GLbyte data[] = {
diff --git a/gpu/command_buffer/common/raster_cmd_ids_autogen.h b/gpu/command_buffer/common/raster_cmd_ids_autogen.h
index 0c879b9..27c763e2 100644
--- a/gpu/command_buffer/common/raster_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/raster_cmd_ids_autogen.h
@@ -20,20 +20,19 @@
   OP(BeginQueryEXT)                              /* 261 */ \
   OP(EndQueryEXT)                                /* 262 */ \
   OP(LoseContextCHROMIUM)                        /* 263 */ \
-  OP(InsertFenceSyncCHROMIUM)                    /* 264 */ \
-  OP(BeginRasterCHROMIUMImmediate)               /* 265 */ \
-  OP(RasterCHROMIUM)                             /* 266 */ \
-  OP(EndRasterCHROMIUM)                          /* 267 */ \
-  OP(CreateTransferCacheEntryINTERNAL)           /* 268 */ \
-  OP(DeleteTransferCacheEntryINTERNAL)           /* 269 */ \
-  OP(UnlockTransferCacheEntryINTERNAL)           /* 270 */ \
-  OP(DeletePaintCacheTextBlobsINTERNALImmediate) /* 271 */ \
-  OP(DeletePaintCachePathsINTERNALImmediate)     /* 272 */ \
-  OP(ClearPaintCacheINTERNAL)                    /* 273 */ \
-  OP(CopySubTextureINTERNALImmediate)            /* 274 */ \
-  OP(TraceBeginCHROMIUM)                         /* 275 */ \
-  OP(TraceEndCHROMIUM)                           /* 276 */ \
-  OP(SetActiveURLCHROMIUM)                       /* 277 */
+  OP(BeginRasterCHROMIUMImmediate)               /* 264 */ \
+  OP(RasterCHROMIUM)                             /* 265 */ \
+  OP(EndRasterCHROMIUM)                          /* 266 */ \
+  OP(CreateTransferCacheEntryINTERNAL)           /* 267 */ \
+  OP(DeleteTransferCacheEntryINTERNAL)           /* 268 */ \
+  OP(UnlockTransferCacheEntryINTERNAL)           /* 269 */ \
+  OP(DeletePaintCacheTextBlobsINTERNALImmediate) /* 270 */ \
+  OP(DeletePaintCachePathsINTERNALImmediate)     /* 271 */ \
+  OP(ClearPaintCacheINTERNAL)                    /* 272 */ \
+  OP(CopySubTextureINTERNALImmediate)            /* 273 */ \
+  OP(TraceBeginCHROMIUM)                         /* 274 */ \
+  OP(TraceEndCHROMIUM)                           /* 275 */ \
+  OP(SetActiveURLCHROMIUM)                       /* 276 */
 
 enum CommandId {
   kOneBeforeStartPoint =
diff --git a/gpu/command_buffer/gles2_cmd_buffer_functions.txt b/gpu/command_buffer/gles2_cmd_buffer_functions.txt
index 2f9b93fd..195bcb0 100644
--- a/gpu/command_buffer/gles2_cmd_buffer_functions.txt
+++ b/gpu/command_buffer/gles2_cmd_buffer_functions.txt
@@ -323,7 +323,6 @@
 GL_APICALL void         GL_APIENTRY glTraceEndCHROMIUM (void);
 GL_APICALL void         GL_APIENTRY glDiscardFramebufferEXT (GLenumFramebufferTarget target, GLsizei count, const GLenum* attachments);
 GL_APICALL void         GL_APIENTRY glLoseContextCHROMIUM (GLenumResetStatus current, GLenumResetStatus other);
-GL_APICALL GLuint64     GL_APIENTRY glInsertFenceSyncCHROMIUM (void);
 GL_APICALL void         GL_APIENTRY glGenSyncTokenCHROMIUM (GLbyte* sync_token);
 GL_APICALL void         GL_APIENTRY glGenUnverifiedSyncTokenCHROMIUM (GLbyte* sync_token);
 GL_APICALL void         GL_APIENTRY glVerifySyncTokensCHROMIUM (GLbyte** sync_tokens, GLsizei count);
diff --git a/gpu/command_buffer/raster_cmd_buffer_functions.txt b/gpu/command_buffer/raster_cmd_buffer_functions.txt
index bc9938e1..3a0002a 100644
--- a/gpu/command_buffer/raster_cmd_buffer_functions.txt
+++ b/gpu/command_buffer/raster_cmd_buffer_functions.txt
@@ -17,7 +17,6 @@
 
 // Non-GL commands.
 GL_APICALL void         GL_APIENTRY glLoseContextCHROMIUM (GLenumResetStatus current, GLenumResetStatus other);
-GL_APICALL GLuint64     GL_APIENTRY glInsertFenceSyncCHROMIUM (void);
 GL_APICALL void         GL_APIENTRY glGenUnverifiedSyncTokenCHROMIUM (GLbyte* sync_token);
 GL_APICALL void         GL_APIENTRY glVerifySyncTokensCHROMIUM (GLbyte** sync_tokens, GLsizei count);
 GL_APICALL void         GL_APIENTRY glWaitSyncTokenCHROMIUM (const GLbyte* sync_token);
diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc
index 0a02d3f..909d973 100644
--- a/gpu/command_buffer/service/common_decoder.cc
+++ b/gpu/command_buffer/service/common_decoder.cc
@@ -12,6 +12,7 @@
 #include "base/numerics/safe_math.h"
 #include "base/stl_util.h"
 #include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/command_buffer/service/decoder_client.h"
 
 namespace gpu {
 namespace {
@@ -127,8 +128,10 @@
   return true;
 }
 
-CommonDecoder::CommonDecoder(CommandBufferServiceBase* command_buffer_service)
+CommonDecoder::CommonDecoder(DecoderClient* client,
+                             CommandBufferServiceBase* command_buffer_service)
     : command_buffer_service_(command_buffer_service),
+      client_(client),
       max_bucket_size_(kDefaultMaxBucketSize) {
   DCHECK(command_buffer_service_);
 }
@@ -363,4 +366,19 @@
   return error::kNoError;
 }
 
+error::Error CommonDecoder::HandleInsertFenceSync(
+    uint32_t immediate_data_size,
+    const volatile void* cmd_data) {
+  const volatile cmd::InsertFenceSync& c =
+      *static_cast<const volatile cmd::InsertFenceSync*>(cmd_data);
+
+  const uint64_t release_count = c.release_count();
+  client_->OnFenceSyncRelease(release_count);
+  // Exit inner command processing loop so that we check the scheduling state
+  // and yield if necessary as we may have unblocked a higher priority
+  // context.
+  ExitCommandProcessingEarly();
+  return error::kNoError;
+}
+
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/common_decoder.h b/gpu/command_buffer/service/common_decoder.h
index 76df1a5..b635baa 100644
--- a/gpu/command_buffer/service/common_decoder.h
+++ b/gpu/command_buffer/service/common_decoder.h
@@ -25,6 +25,7 @@
 namespace gpu {
 
 class CommandBufferServiceBase;
+class DecoderClient;
 
 // This class is a helper base class for implementing the common parts of the
 // o3d/gl2 command buffer decoder.
@@ -111,13 +112,16 @@
     DISALLOW_COPY_AND_ASSIGN(Bucket);
   };
 
-  explicit CommonDecoder(CommandBufferServiceBase* command_buffer_service);
+  explicit CommonDecoder(DecoderClient* client,
+                         CommandBufferServiceBase* command_buffer_service);
   ~CommonDecoder();
 
   CommandBufferServiceBase* command_buffer_service() const {
     return command_buffer_service_;
   }
 
+  DecoderClient* client() const { return client_; }
+
   // Sets the maximum size for buckets.
   void set_max_bucket_size(size_t max_bucket_size) {
     max_bucket_size_ = max_bucket_size;
@@ -185,6 +189,10 @@
   // Gets an name for a common command.
   const char* GetCommonCommandName(cmd::CommandId command_id) const;
 
+  // Exit the command processing loop to allow context preemption and GPU
+  // watchdog checks in CommandExecutor().
+  virtual void ExitCommandProcessingEarly() {}
+
  private:
   // Generate a member function prototype for each command in an automated and
   // typesafe way.
@@ -197,6 +205,7 @@
   #undef COMMON_COMMAND_BUFFER_CMD_OP
 
   CommandBufferServiceBase* command_buffer_service_;
+  DecoderClient* client_;
   size_t max_bucket_size_;
 
   typedef std::map<uint32_t, std::unique_ptr<Bucket>> BucketMap;
diff --git a/gpu/command_buffer/service/common_decoder_unittest.cc b/gpu/command_buffer/service/common_decoder_unittest.cc
index e3d5d05..51ecede 100644
--- a/gpu/command_buffer/service/common_decoder_unittest.cc
+++ b/gpu/command_buffer/service/common_decoder_unittest.cc
@@ -56,8 +56,9 @@
 
 class TestCommonDecoder : public CommonDecoder {
  public:
-  explicit TestCommonDecoder(CommandBufferServiceBase* command_buffer_service)
-      : CommonDecoder(command_buffer_service) {}
+  explicit TestCommonDecoder(DecoderClient* client,
+                             CommandBufferServiceBase* command_buffer_service)
+      : CommonDecoder(client, command_buffer_service) {}
   error::Error DoCommand(unsigned int command,
                          unsigned int arg_count,
                          const volatile void* cmd_data) {
@@ -73,7 +74,7 @@
  protected:
   static const size_t kBufferSize = 1024;
   static const uint32_t kInvalidShmId = UINT32_MAX;
-  CommonDecoderTest() : decoder_(&command_buffer_service_) {}
+  CommonDecoderTest() : decoder_(&client_, &command_buffer_service_) {}
 
   void SetUp() override {
     command_buffer_service_.CreateTransferBufferHelper(kBufferSize,
@@ -104,6 +105,7 @@
   }
 
   FakeCommandBufferServiceBase command_buffer_service_;
+  FakeDecoderClient client_;
   TestCommonDecoder decoder_;
   int32_t valid_shm_id_ = 0;
 };
diff --git a/gpu/command_buffer/service/context_group_unittest.cc b/gpu/command_buffer/service/context_group_unittest.cc
index 870cc3ae..5ed2ee7 100644
--- a/gpu/command_buffer/service/context_group_unittest.cc
+++ b/gpu/command_buffer/service/context_group_unittest.cc
@@ -45,7 +45,8 @@
  protected:
   void SetUp() override {
     GpuServiceTest::SetUp();
-    decoder_.reset(new MockGLES2Decoder(&command_buffer_service_, &outputter_));
+    decoder_.reset(
+        new MockGLES2Decoder(&client_, &command_buffer_service_, &outputter_));
     scoped_refptr<FeatureInfo> feature_info = new FeatureInfo;
     group_ = scoped_refptr<ContextGroup>(new ContextGroup(
         gpu_preferences_, false, &mailbox_manager_,
@@ -62,6 +63,7 @@
   ServiceDiscardableManager discardable_manager_;
   SharedImageManager shared_image_manager_;
   FakeCommandBufferServiceBase command_buffer_service_;
+  FakeDecoderClient client_;
   MailboxManagerImpl mailbox_manager_;
   TraceOutputter outputter_;
   std::unique_ptr<MockGLES2Decoder> decoder_;
@@ -121,9 +123,10 @@
 
 TEST_F(ContextGroupTest, MultipleContexts) {
   FakeCommandBufferServiceBase command_buffer_service2;
+  FakeDecoderClient client2;
   TraceOutputter outputter;
   std::unique_ptr<MockGLES2Decoder> decoder2_(
-      new MockGLES2Decoder(&command_buffer_service2, &outputter));
+      new MockGLES2Decoder(&client2, &command_buffer_service2, &outputter));
   TestHelper::SetupContextGroupInitExpectations(
       gl_.get(), DisallowedFeatures(), "", "",
       CONTEXT_TYPE_OPENGLES2, kBindGeneratesResource);
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index 13c7c84..787123b0 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -154,7 +154,8 @@
     TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(gl_.get(),
         extensions, "", gl_version, context_type_);
     feature_info_->InitializeForTesting(context_type_);
-    decoder_.reset(new MockGLES2Decoder(&command_buffer_service_, &outputter_));
+    decoder_.reset(
+        new MockGLES2Decoder(&client_, &command_buffer_service_, &outputter_));
     manager_.CreateFramebuffer(kClient1Id, kService1Id);
     error_state_.reset(new ::testing::StrictMock<gles2::MockErrorState>());
     framebuffer_ = manager_.GetFramebuffer(kClient1Id);
@@ -171,6 +172,7 @@
   std::unique_ptr<RenderbufferManager> renderbuffer_manager_;
   std::unique_ptr<MockErrorState> error_state_;
   FakeCommandBufferServiceBase command_buffer_service_;
+  FakeDecoderClient client_;
   TraceOutputter outputter_;
   std::unique_ptr<MockGLES2Decoder> decoder_;
 };
diff --git a/gpu/command_buffer/service/gl_context_virtual_unittest.cc b/gpu/command_buffer/service/gl_context_virtual_unittest.cc
index fb9ab6c2..b9c6bcd 100644
--- a/gpu/command_buffer/service/gl_context_virtual_unittest.cc
+++ b/gpu/command_buffer/service/gl_context_virtual_unittest.cc
@@ -22,11 +22,14 @@
 class GLContextVirtualTest : public GpuServiceTest {
  public:
   GLContextVirtualTest()
-      : decoder_(new MockGLES2Decoder(&command_buffer_service_, &outputter_)) {}
+      : decoder_(new MockGLES2Decoder(&client_,
+                                      &command_buffer_service_,
+                                      &outputter_)) {}
   ~GLContextVirtualTest() override = default;
 
  protected:
   FakeCommandBufferServiceBase command_buffer_service_;
+  FakeDecoderClient client_;
   TraceOutputter outputter_;
   std::unique_ptr<MockGLES2Decoder> decoder_;
 };
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index c52f9f4..0d85a6f 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -563,9 +563,10 @@
   return 0;
 }
 
-GLES2Decoder::GLES2Decoder(CommandBufferServiceBase* command_buffer_service,
+GLES2Decoder::GLES2Decoder(DecoderClient* client,
+                           CommandBufferServiceBase* command_buffer_service,
                            Outputter* outputter)
-    : CommonDecoder(command_buffer_service), outputter_(outputter) {
+    : CommonDecoder(client, command_buffer_service), outputter_(outputter) {
   DCHECK(outputter_);
 }
 
@@ -2422,7 +2423,7 @@
 
   // Set remaining commands to process to 0 to force DoCommands to return
   // and allow context preemption and GPU watchdog checks in CommandExecutor().
-  void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
+  void ExitCommandProcessingEarly() override;
 
   void ProcessPendingReadPixels(bool did_finish);
   void FinishReadPixels(GLsizei width,
@@ -2524,8 +2525,6 @@
 
   #undef GLES2_CMD_OP
 
-  DecoderClient* client_;
-
   // The GL context this decoder renders to on behalf of the client.
   scoped_refptr<gl::GLSurface> surface_;
   scoped_refptr<gl::GLContext> context_;
@@ -3425,12 +3424,11 @@
     CommandBufferServiceBase* command_buffer_service,
     Outputter* outputter,
     ContextGroup* group)
-    : GLES2Decoder(command_buffer_service, outputter),
-      client_(client),
+    : GLES2Decoder(client, command_buffer_service, outputter),
       group_(group),
       logger_(&debug_marker_manager_,
               base::BindRepeating(&DecoderClient::OnConsoleMessage,
-                                  base::Unretained(client_),
+                                  base::Unretained(client),
                                   0),
               group->gpu_preferences().disable_gl_error_limit),
       error_state_(ErrorState::Create(this, &logger_)),
@@ -5991,6 +5989,10 @@
   }
 }
 
+void GLES2DecoderImpl::ExitCommandProcessingEarly() {
+  commands_to_process_ = 0;
+}
+
 void GLES2DecoderImpl::DoFinish() {
   api()->glFinishFn();
   ProcessPendingReadPixels(true);
@@ -9692,7 +9694,7 @@
                     workarounds().count_all_in_varyings_packing
                         ? Program::kCountAll
                         : Program::kCountOnlyStaticallyUsed,
-                    client_)) {
+                    client())) {
     if (program == state_.current_program.get()) {
       if (workarounds().clear_uniforms_before_first_program_use)
         program_manager()->ClearUniforms(program);
@@ -13332,7 +13334,7 @@
     bounds[i] = gfx::Rect(rects[i * 4 + 0], rects[i * 4 + 1], rects[i * 4 + 2],
                           rects[i * 4 + 3]);
   }
-  client_->OnSwapBuffers(swap_id, flags);
+  client()->OnSwapBuffers(swap_id, flags);
   FinishSwapBuffers(surface_->SwapBuffersWithBounds(bounds, base::DoNothing()));
 }
 
@@ -13364,14 +13366,14 @@
   if (supports_async_swap_) {
     TRACE_EVENT_ASYNC_BEGIN0("gpu", "AsyncSwapBuffers", c.swap_id());
 
-    client_->OnSwapBuffers(c.swap_id(), c.flags);
+    client()->OnSwapBuffers(c.swap_id(), c.flags);
     surface_->PostSubBufferAsync(
         c.x, c.y, c.width, c.height,
         base::BindOnce(&GLES2DecoderImpl::FinishAsyncSwapBuffers,
                        weak_ptr_factory_.GetWeakPtr(), c.swap_id()),
         base::DoNothing());
   } else {
-    client_->OnSwapBuffers(c.swap_id(), c.flags);
+    client()->OnSwapBuffers(c.swap_id(), c.flags);
     FinishSwapBuffers(surface_->PostSubBuffer(c.x, c.y, c.width, c.height,
                                               base::DoNothing()));
   }
@@ -16585,13 +16587,13 @@
   } else if (supports_async_swap_) {
     TRACE_EVENT_ASYNC_BEGIN0("gpu", "AsyncSwapBuffers", swap_id);
 
-    client_->OnSwapBuffers(swap_id, flags);
+    client()->OnSwapBuffers(swap_id, flags);
     surface_->SwapBuffersAsync(
         base::BindOnce(&GLES2DecoderImpl::FinishAsyncSwapBuffers,
                        weak_ptr_factory_.GetWeakPtr(), swap_id),
         base::DoNothing());
   } else {
-    client_->OnSwapBuffers(swap_id, flags);
+    client()->OnSwapBuffers(swap_id, flags);
     FinishSwapBuffers(surface_->SwapBuffers(base::DoNothing()));
   }
 
@@ -16638,13 +16640,13 @@
   }
   ClearScheduleCALayerState();
   if (supports_async_swap_) {
-    client_->OnSwapBuffers(swap_id, flags);
+    client()->OnSwapBuffers(swap_id, flags);
     surface_->CommitOverlayPlanesAsync(
         base::BindOnce(&GLES2DecoderImpl::FinishAsyncSwapBuffers,
                        weak_ptr_factory_.GetWeakPtr(), swap_id),
         base::DoNothing());
   } else {
-    client_->OnSwapBuffers(swap_id, flags);
+    client()->OnSwapBuffers(swap_id, flags);
     FinishSwapBuffers(surface_->CommitOverlayPlanes(base::DoNothing()));
   }
 }
@@ -17031,25 +17033,10 @@
 
   TRACE_EVENT_ASYNC_BEGIN0("cc", "GLES2DecoderImpl::DescheduleUntilFinished",
                            this);
-  client_->OnDescheduleUntilFinished();
+  client()->OnDescheduleUntilFinished();
   return error::kDeferLaterCommands;
 }
 
-error::Error GLES2DecoderImpl::HandleInsertFenceSyncCHROMIUM(
-    uint32_t immediate_data_size,
-    const volatile void* cmd_data) {
-  const volatile gles2::cmds::InsertFenceSyncCHROMIUM& c =
-      *static_cast<const volatile gles2::cmds::InsertFenceSyncCHROMIUM*>(
-          cmd_data);
-
-  const uint64_t release_count = c.release_count();
-  client_->OnFenceSyncRelease(release_count);
-  // Exit inner command processing loop so that we check the scheduling state
-  // and yield if necessary as we may have unblocked a higher priority context.
-  ExitCommandProcessingEarly();
-  return error::kNoError;
-}
-
 error::Error GLES2DecoderImpl::HandleDiscardBackbufferCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
@@ -17143,7 +17130,7 @@
                          this);
   deschedule_until_finished_fences_.erase(
       deschedule_until_finished_fences_.begin());
-  client_->OnRescheduleAfterFinished();
+  client()->OnRescheduleAfterFinished();
 }
 
 bool GLES2DecoderImpl::HasMoreIdleWork() const {
@@ -20921,7 +20908,7 @@
     return error::kInvalidArguments;
 
   GURL url(base::StringPiece(url_str, size));
-  client_->SetActiveURL(std::move(url));
+  client()->SetActiveURL(std::move(url));
   return error::kNoError;
 }
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 6cdf5a3..8c0e5d1 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -195,7 +195,8 @@
       CopyTexImageResourceManager* copy_tex_image_blit) = 0;
 
  protected:
-  GLES2Decoder(CommandBufferServiceBase* command_buffer_service,
+  GLES2Decoder(DecoderClient* client,
+               CommandBufferServiceBase* command_buffer_service,
                Outputter* outputter);
 
  private:
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc b/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc
index 8d5a3b2..7797ac41 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc
@@ -10,9 +10,11 @@
 namespace gles2 {
 
 MockGLES2Decoder::MockGLES2Decoder(
+    DecoderClient* client,
     CommandBufferServiceBase* command_buffer_service,
     Outputter* outputter)
-    : GLES2Decoder(command_buffer_service, outputter), weak_ptr_factory_(this) {
+    : GLES2Decoder(client, command_buffer_service, outputter),
+      weak_ptr_factory_(this) {
   ON_CALL(*this, MakeCurrent())
       .WillByDefault(testing::Return(true));
 }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index 334ee91..7142310 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -37,7 +37,8 @@
 
 class MockGLES2Decoder : public GLES2Decoder {
  public:
-  MockGLES2Decoder(CommandBufferServiceBase* command_buffer_service,
+  MockGLES2Decoder(DecoderClient* client,
+                   CommandBufferServiceBase* command_buffer_service,
                    Outputter* outputter);
   ~MockGLES2Decoder() override;
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
index 2766bcb..6b9c176 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -543,13 +543,12 @@
     CommandBufferServiceBase* command_buffer_service,
     Outputter* outputter,
     ContextGroup* group)
-    : GLES2Decoder(command_buffer_service, outputter),
-      client_(client),
+    : GLES2Decoder(client, command_buffer_service, outputter),
       commands_to_process_(0),
       debug_marker_manager_(),
       logger_(&debug_marker_manager_,
               base::BindRepeating(&DecoderClient::OnConsoleMessage,
-                                  base::Unretained(client_),
+                                  base::Unretained(client),
                                   0),
               group->gpu_preferences().disable_gl_error_limit),
       surface_(),
@@ -683,6 +682,10 @@
   return result;
 }
 
+void GLES2DecoderPassthroughImpl::ExitCommandProcessingEarly() {
+  commands_to_process_ = 0;
+}
+
 base::WeakPtr<DecoderContext> GLES2DecoderPassthroughImpl::AsWeakPtr() {
   return weak_ptr_factory_.GetWeakPtr();
 }
@@ -2314,7 +2317,7 @@
       "cc", "GLES2DecoderPassthroughImpl::DescheduleUntilFinished", this);
   deschedule_until_finished_fences_.erase(
       deschedule_until_finished_fences_.begin());
-  client_->OnRescheduleAfterFinished();
+  client()->OnRescheduleAfterFinished();
 }
 
 void GLES2DecoderPassthroughImpl::UpdateTextureBinding(
@@ -2423,7 +2426,7 @@
     return error::kInvalidArguments;
 
   GURL url(base::StringPiece(url_str, size));
-  client_->SetActiveURL(std::move(url));
+  client()->SetActiveURL(std::move(url));
   return error::kNoError;
 }
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
index ed68201..7470c03b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -464,7 +464,7 @@
     return feature_info_->feature_flags();
   }
 
-  void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
+  void ExitCommandProcessingEarly() override;
 
   error::Error CheckSwapBuffersResult(gfx::SwapResult result,
                                       const char* function_name);
@@ -511,8 +511,6 @@
     }
   }
 
-  DecoderClient* client_ = nullptr;
-
   // A set of raw pointers to currently living PassthroughAbstractTextures
   // which allow us to properly signal to them when we are destroyed.
   base::flat_set<PassthroughAbstractTextureImpl*> abstract_textures_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
index 2f29c64..6605a36 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doer_prototypes.h
@@ -877,7 +877,6 @@
                                      const volatile GLenum* attachments);
 error::Error DoLoseContextCHROMIUM(GLenum current, GLenum other);
 error::Error DoDescheduleUntilFinishedCHROMIUM();
-error::Error DoInsertFenceSyncCHROMIUM(GLuint64 release_count);
 error::Error DoWaitSyncTokenCHROMIUM(CommandBufferNamespace namespace_id,
                                      CommandBufferId command_buffer_id,
                                      GLuint64 release_count);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
index 95f7162d..3f1d15f 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -3576,7 +3576,7 @@
     return error::kNoError;
   }
 
-  client_->OnSwapBuffers(swap_id, flags);
+  client()->OnSwapBuffers(swap_id, flags);
   return CheckSwapBuffersResult(surface_->SwapBuffers(base::DoNothing()),
                                 "SwapBuffers");
 }
@@ -4158,7 +4158,7 @@
                           rects[i * 4 + 3]);
   }
 
-  client_->OnSwapBuffers(swap_id, flags);
+  client()->OnSwapBuffers(swap_id, flags);
   return CheckSwapBuffersResult(
       surface_->SwapBuffersWithBounds(bounds, base::DoNothing()),
       "SwapBuffersWithBounds");
@@ -4177,7 +4177,7 @@
     return error::kNoError;
   }
 
-  client_->OnSwapBuffers(swap_id, flags);
+  client()->OnSwapBuffers(swap_id, flags);
   return CheckSwapBuffersResult(
       surface_->PostSubBuffer(x, y, width, height, base::DoNothing()),
       "PostSubBuffer");
@@ -4434,16 +4434,10 @@
 
   TRACE_EVENT_ASYNC_BEGIN0(
       "cc", "GLES2DecoderPassthroughImpl::DescheduleUntilFinished", this);
-  client_->OnDescheduleUntilFinished();
+  client()->OnDescheduleUntilFinished();
   return error::kDeferLaterCommands;
 }
 
-error::Error GLES2DecoderPassthroughImpl::DoInsertFenceSyncCHROMIUM(
-    GLuint64 release_count) {
-  client_->OnFenceSyncRelease(release_count);
-  return error::kNoError;
-}
-
 error::Error GLES2DecoderPassthroughImpl::DoDrawBuffersEXT(
     GLsizei count,
     const volatile GLenum* bufs) {
@@ -4591,7 +4585,7 @@
     return error::kNoError;
   }
 
-  client_->OnSwapBuffers(swap_id, flags);
+  client()->OnSwapBuffers(swap_id, flags);
   return CheckSwapBuffersResult(
       surface_->CommitOverlayPlanes(base::DoNothing()), "CommitOverlayPlanes");
 }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
index 07aafbdf..5a3c402 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_handlers.cc
@@ -2018,17 +2018,6 @@
   return DoDescheduleUntilFinishedCHROMIUM();
 }
 
-error::Error GLES2DecoderPassthroughImpl::HandleInsertFenceSyncCHROMIUM(
-    uint32_t immediate_data_size,
-    const volatile void* cmd_data) {
-  const volatile gles2::cmds::InsertFenceSyncCHROMIUM& c =
-      *static_cast<const volatile gles2::cmds::InsertFenceSyncCHROMIUM*>(
-          cmd_data);
-  GLuint64 release_count = c.release_count();
-
-  return DoInsertFenceSyncCHROMIUM(release_count);
-}
-
 error::Error GLES2DecoderPassthroughImpl::HandleDiscardBackbufferCHROMIUM(
     uint32_t immediate_data_size,
     const volatile void* cmd_data) {
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 ad7830a..34bfa245 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -247,7 +247,7 @@
   // will initialize itself.
   command_buffer_service_.reset(new FakeCommandBufferServiceBase());
   mock_decoder_.reset(
-      new MockGLES2Decoder(command_buffer_service_.get(), &outputter_));
+      new MockGLES2Decoder(this, command_buffer_service_.get(), &outputter_));
 
   EXPECT_EQ(group_->Initialize(mock_decoder_.get(), init.context_type,
                                DisallowedFeatures()),
diff --git a/gpu/command_buffer/service/gpu_tracer_unittest.cc b/gpu/command_buffer/service/gpu_tracer_unittest.cc
index 0381d17..8d6248c 100644
--- a/gpu/command_buffer/service/gpu_tracer_unittest.cc
+++ b/gpu/command_buffer/service/gpu_tracer_unittest.cc
@@ -316,8 +316,9 @@
     ExpectTracerOffsetQueryMocks();
 
     FakeCommandBufferServiceBase command_buffer_service;
+    FakeDecoderClient client;
     MockOutputter outputter;
-    MockGLES2Decoder decoder(&command_buffer_service, &outputter);
+    MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
     EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
     GPUTracerTester tracer(&decoder);
     tracer.SetTracingEnabled(true);
@@ -332,8 +333,9 @@
     const GpuTracerSource source = static_cast<GpuTracerSource>(0);
 
     FakeCommandBufferServiceBase command_buffer_service;
+    FakeDecoderClient client;
     MockOutputter outputter;
-    MockGLES2Decoder decoder(&command_buffer_service, &outputter);
+    MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
     EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
     GPUTracerTester tracer(&decoder);
     tracer.SetTracingEnabled(false);
@@ -360,8 +362,9 @@
         (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
 
     FakeCommandBufferServiceBase command_buffer_service;
+    FakeDecoderClient client;
     MockOutputter outputter;
-    MockGLES2Decoder decoder(&command_buffer_service, &outputter);
+    MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
     EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
     GPUTracerTester tracer(&decoder);
     tracer.SetTracingEnabled(true);
@@ -433,8 +436,9 @@
     const bool valid_timer = gpu_timing_client_->IsAvailable();
 
     FakeCommandBufferServiceBase command_buffer_service;
+    FakeDecoderClient client;
     MockOutputter outputter;
-    MockGLES2Decoder decoder(&command_buffer_service, &outputter);
+    MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
     EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
     GPUTracerTester tracer(&decoder);
 
@@ -512,8 +516,9 @@
         (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
 
     FakeCommandBufferServiceBase command_buffer_service;
+    FakeDecoderClient client;
     MockOutputter outputter;
-    MockGLES2Decoder decoder(&command_buffer_service, &outputter);
+    MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
     EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
     GPUTracerTester tracer(&decoder);
     tracer.SetTracingEnabled(true);
@@ -569,8 +574,9 @@
         (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
 
     FakeCommandBufferServiceBase command_buffer_service;
+    FakeDecoderClient client;
     MockOutputter outputter;
-    MockGLES2Decoder decoder(&command_buffer_service, &outputter);
+    MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
     EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
     EXPECT_CALL(decoder, MakeCurrent()).WillRepeatedly(Return(true));
     GPUTracerTester tracer(&decoder);
@@ -706,7 +712,8 @@
   void SetUp() override {
     g_fakeCPUTime = 0;
     GpuServiceTest::SetUpWithGLVersion("3.2", "");
-    decoder_.reset(new MockGLES2Decoder(&command_buffer_service_, &outputter_));
+    decoder_.reset(
+        new MockGLES2Decoder(&client_, &command_buffer_service_, &outputter_));
     EXPECT_CALL(*decoder_, GetGLContext())
         .Times(AtMost(1))
         .WillRepeatedly(Return(GetGLContext()));
@@ -720,6 +727,7 @@
   }
 
   FakeCommandBufferServiceBase command_buffer_service_;
+  FakeDecoderClient client_;
   MockOutputter outputter_;
   std::unique_ptr<MockGLES2Decoder> decoder_;
   std::unique_ptr<GPUTracerTester> tracer_tester_;
diff --git a/gpu/command_buffer/service/query_manager_unittest.cc b/gpu/command_buffer/service/query_manager_unittest.cc
index e415682..5fdd7f3c 100644
--- a/gpu/command_buffer/service/query_manager_unittest.cc
+++ b/gpu/command_buffer/service/query_manager_unittest.cc
@@ -70,8 +70,8 @@
     buffer = command_buffer_service_->CreateTransferBufferHelper(
         kSharedBufferSize, &shared_memory2_id_);
     memset(buffer->memory(), kInitialMemoryValue, kSharedBufferSize);
-    decoder_.reset(
-        new MockGLES2Decoder(command_buffer_service_.get(), &outputter_));
+    decoder_.reset(new MockGLES2Decoder(&client_, command_buffer_service_.get(),
+                                        &outputter_));
     TestHelper::SetupFeatureInfoInitExpectations(
         gl_.get(), extension_expectations);
     EXPECT_CALL(*decoder_.get(), GetGLContext())
@@ -126,6 +126,7 @@
 
   TraceOutputter outputter_;
   std::unique_ptr<FakeCommandBufferServiceBase> command_buffer_service_;
+  FakeDecoderClient client_;
   std::unique_ptr<MockGLES2Decoder> decoder_;
   std::unique_ptr<GLES2QueryManager> manager_;
 
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 3f37ecd9..ce01577 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -398,7 +398,7 @@
   // Set remaining commands to process to 0 to force DoCommands to return
   // and allow context preemption and GPU watchdog checks in
   // CommandExecutor().
-  void ExitCommandProcessingEarly() { commands_to_process_ = 0; }
+  void ExitCommandProcessingEarly() override;
 
   template <bool DebugImpl>
   error::Error DoCommandsImpl(unsigned int num_commands,
@@ -522,8 +522,6 @@
 
   scoped_refptr<gl::GLContext> context_;
 
-  DecoderClient* client_;
-
   GpuPreferences gpu_preferences_;
 
   gles2::DebugMarkerManager debug_marker_manager_;
@@ -606,9 +604,10 @@
                                std::move(shared_context_state));
 }
 
-RasterDecoder::RasterDecoder(CommandBufferServiceBase* command_buffer_service,
+RasterDecoder::RasterDecoder(DecoderClient* client,
+                             CommandBufferServiceBase* command_buffer_service,
                              gles2::Outputter* outputter)
-    : CommonDecoder(command_buffer_service), outputter_(outputter) {}
+    : CommonDecoder(client, command_buffer_service), outputter_(outputter) {}
 
 RasterDecoder::~RasterDecoder() {}
 
@@ -655,18 +654,17 @@
     MemoryTracker* memory_tracker,
     SharedImageManager* shared_image_manager,
     scoped_refptr<SharedContextState> shared_context_state)
-    : RasterDecoder(command_buffer_service, outputter),
+    : RasterDecoder(client, command_buffer_service, outputter),
       raster_decoder_id_(g_raster_decoder_id.GetNext() + 1),
       supports_gpu_raster_(
           gpu_feature_info.status_values[GPU_FEATURE_TYPE_GPU_RASTERIZATION] ==
           kGpuFeatureStatusEnabled),
       use_passthrough_(gles2::PassthroughCommandDecoderSupported() &&
                        gpu_preferences.use_passthrough_cmd_decoder),
-      client_(client),
       gpu_preferences_(gpu_preferences),
       logger_(&debug_marker_manager_,
               base::BindRepeating(&DecoderClient::OnConsoleMessage,
-                                  base::Unretained(client_),
+                                  base::Unretained(client),
                                   0),
               gpu_preferences_.disable_gl_error_limit),
       error_state_(gles2::ErrorState::Create(this, &logger_)),
@@ -1206,7 +1204,7 @@
   }
 
   if (supports_oop_raster_)
-    client_->ScheduleGrContextCleanup();
+    client()->ScheduleGrContextCleanup();
 
   return result;
 }
@@ -1224,6 +1222,10 @@
   }
 }
 
+void RasterDecoderImpl::ExitCommandProcessingEarly() {
+  commands_to_process_ = 0;
+}
+
 base::StringPiece RasterDecoderImpl::GetLogPrefix() {
   return logger_.GetLogPrefix();
 }
@@ -1480,22 +1482,6 @@
   return error::kNoError;
 }
 
-error::Error RasterDecoderImpl::HandleInsertFenceSyncCHROMIUM(
-    uint32_t immediate_data_size,
-    const volatile void* cmd_data) {
-  const volatile gles2::cmds::InsertFenceSyncCHROMIUM& c =
-      *static_cast<const volatile gles2::cmds::InsertFenceSyncCHROMIUM*>(
-          cmd_data);
-
-  const uint64_t release_count = c.release_count();
-  client_->OnFenceSyncRelease(release_count);
-  // Exit inner command processing loop so that we check the scheduling state
-  // and yield if necessary as we may have unblocked a higher priority
-  // context.
-  ExitCommandProcessingEarly();
-  return error::kNoError;
-}
-
 void RasterDecoderImpl::DoFinish() {
   if (!shared_context_state_->use_vulkan_gr_context())
     api()->glFinishFn();
@@ -1585,7 +1571,7 @@
     return error::kInvalidArguments;
 
   GURL url(base::StringPiece(url_str, size));
-  client_->SetActiveURL(std::move(url));
+  client()->SetActiveURL(std::move(url));
   return error::kNoError;
 }
 
diff --git a/gpu/command_buffer/service/raster_decoder.h b/gpu/command_buffer/service/raster_decoder.h
index 0c0575f..64c90a8 100644
--- a/gpu/command_buffer/service/raster_decoder.h
+++ b/gpu/command_buffer/service/raster_decoder.h
@@ -93,7 +93,8 @@
   virtual void DisableFlushWorkaroundForTest() = 0;
 
  protected:
-  RasterDecoder(CommandBufferServiceBase* command_buffer_service,
+  RasterDecoder(DecoderClient* client,
+                CommandBufferServiceBase* command_buffer_service,
                 gles2::Outputter* outputter);
 
  private:
diff --git a/gpu/command_buffer/service/service_discardable_manager_unittest.cc b/gpu/command_buffer/service/service_discardable_manager_unittest.cc
index 9fd5658..1a50b05a 100644
--- a/gpu/command_buffer/service/service_discardable_manager_unittest.cc
+++ b/gpu/command_buffer/service/service_discardable_manager_unittest.cc
@@ -71,7 +71,8 @@
  protected:
   void SetUp() override {
     GpuServiceTest::SetUp();
-    decoder_.reset(new MockGLES2Decoder(&command_buffer_service_, &outputter_));
+    decoder_.reset(
+        new MockGLES2Decoder(&client_, &command_buffer_service_, &outputter_));
     feature_info_ = new FeatureInfo();
     context_group_ = scoped_refptr<ContextGroup>(new ContextGroup(
         gpu_preferences_, false, &mailbox_manager_, nullptr, nullptr, nullptr,
@@ -128,6 +129,7 @@
   MockDestructionObserver destruction_observer_;
   TextureManager* texture_manager_;
   FakeCommandBufferServiceBase command_buffer_service_;
+  FakeDecoderClient client_;
   std::unique_ptr<MockGLES2Decoder> decoder_;
   scoped_refptr<gles2::ContextGroup> context_group_;
 };
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc
index f98c223..b60e67a 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc
@@ -45,6 +45,7 @@
 #include "ui/gl/gl_fence_android_native_fence_sync.h"
 #include "ui/gl/gl_gl_api_implementation.h"
 #include "ui/gl/gl_image_ahardwarebuffer.h"
+#include "ui/gl/gl_utils.h"
 #include "ui/gl/gl_version_info.h"
 
 namespace gpu {
@@ -56,25 +57,22 @@
   kWrite,
 };
 
-void DestroyAllSemaphores(VkDevice vk_device,
-                          VkQueue vk_queue,
-                          std::vector<VkSemaphore> semaphores,
-                          bool wait_for_idle) {
+void DestroySemaphore(VkDevice vk_device,
+                      VkQueue vk_queue,
+                      VkSemaphore semaphore) {
+  if (semaphore == VK_NULL_HANDLE)
+    return;
+
   // TODO(vikassoni): Need to do better semaphore cleanup management. Waiting
   // on device to be idle to delete the semaphore is costly. Instead use a
   // fence to get signal when semaphore submission is done.
-  if (!semaphores.empty() && wait_for_idle) {
-    VkResult result = vkQueueWaitIdle(vk_queue);
-    if (result != VK_SUCCESS) {
-      LOG(ERROR) << "vkQueueWaitIdle failed: " << result;
-      return;
-    }
+  VkResult result = vkQueueWaitIdle(vk_queue);
+  if (result != VK_SUCCESS) {
+    LOG(ERROR) << "vkQueueWaitIdle failed: " << result;
+    return;
   }
 
-  for (VkSemaphore& semaphore : semaphores) {
-    if (semaphore != VK_NULL_HANDLE)
-      vkDestroySemaphore(vk_device, semaphore, nullptr);
-  }
+  vkDestroySemaphore(vk_device, semaphore, nullptr);
 }
 
 sk_sp<SkPromiseImageTexture> BeginVulkanAccess(
@@ -85,7 +83,7 @@
     base::android::ScopedHardwareBufferHandle ahb_handle,
     gfx::Size size,
     viz::ResourceFormat format,
-    std::vector<VkSemaphore> semaphores_to_clean) {
+    VkSemaphore semaphore_to_clean) {
   // Create a VkImage and import AHB.
   VkImage vk_image;
   VkImageCreateInfo vk_image_info;
@@ -115,8 +113,7 @@
     return nullptr;
   }
 
-  DestroyAllSemaphores(vk_device, vk_queue, semaphores_to_clean,
-                       true /* wait_for_idle*/);
+  DestroySemaphore(vk_device, vk_queue, semaphore_to_clean);
 
   return promise_texture;
 }
@@ -203,7 +200,7 @@
   void Destroy() override;
   base::android::ScopedHardwareBufferHandle GetAhbHandle() const;
 
-  bool BeginWrite(std::vector<base::ScopedFD>* fds_to_wait_on);
+  bool BeginWrite(base::ScopedFD* fd_to_wait_on);
   void EndWrite(base::ScopedFD end_write_fd);
   bool BeginRead(const SharedImageRepresentation* reader,
                  base::ScopedFD* fd_to_wait_on);
@@ -233,7 +230,7 @@
   bool is_writing_ = false;
 
   // All writes must wait for existing reads to complete.
-  std::vector<base::ScopedFD> read_sync_fds_;
+  base::ScopedFD read_sync_fd_;
   base::flat_set<const SharedImageRepresentation*> active_readers_;
 
   DISALLOW_COPY_AND_ASSIGN(SharedImageBackingAHB);
@@ -267,14 +264,12 @@
       if (!InsertEglFenceAndWait(std::move(write_sync_fd)))
         return false;
     } else if (mode == GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM) {
-      std::vector<base::ScopedFD> sync_fds;
-      if (!ahb_backing()->BeginWrite(&sync_fds))
+      base::ScopedFD sync_fd;
+      if (!ahb_backing()->BeginWrite(&sync_fd))
         return false;
 
-      for (auto& sync_fd : sync_fds) {
-        if (!InsertEglFenceAndWait(std::move(sync_fd)))
-          return false;
-      }
+      if (!InsertEglFenceAndWait(std::move(sync_fd)))
+        return false;
     }
 
     if (mode == GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM) {
@@ -356,14 +351,12 @@
     if (surface_)
       return nullptr;
 
-    std::vector<base::ScopedFD> sync_fds;
-    if (!ahb_backing()->BeginWrite(&sync_fds))
+    base::ScopedFD sync_fd;
+    if (!ahb_backing()->BeginWrite(&sync_fd))
       return nullptr;
 
-    for (auto& sync_fd : sync_fds) {
-      if (!InsertEglFenceAndWait(std::move(sync_fd)))
-        return nullptr;
-    }
+    if (!InsertEglFenceAndWait(std::move(sync_fd)))
+      return nullptr;
 
     if (!promise_texture_) {
       return nullptr;
@@ -483,49 +476,29 @@
     if (surface_)
       return nullptr;
 
-    std::vector<base::ScopedFD> sync_fds;
-    if (!ahb_backing()->BeginWrite(&sync_fds))
+    base::ScopedFD sync_fd;
+    if (!ahb_backing()->BeginWrite(&sync_fd))
       return nullptr;
+    DCHECK(sync_fd.is_valid());
 
-    bool failed_to_insert_semaphores = false;
-    std::vector<VkSemaphore> semaphores(sync_fds.size(), VK_NULL_HANDLE);
-    for (size_t i = 0; i < sync_fds.size(); ++i) {
-      DCHECK(sync_fds[i].is_valid());
-
-      semaphores[i] = vk_implementation()->ImportSemaphoreHandle(
-          vk_device(),
-          SemaphoreHandle(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
-                          std::move(sync_fds[i])));
-      if (semaphores[i] == VK_NULL_HANDLE) {
-        failed_to_insert_semaphores = true;
-        break;
-      }
-    }
-
-    if (failed_to_insert_semaphores) {
-      DestroyAllSemaphores(vk_device(), vk_queue(), std::move(semaphores),
-                           false /* wait_for_idle */);
+    VkSemaphore semaphore = vk_implementation()->ImportSemaphoreHandle(
+        vk_device(),
+        SemaphoreHandle(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
+                        std::move(sync_fd)));
+    if (semaphore == VK_NULL_HANDLE) {
       return nullptr;
     }
 
-    for (size_t i = 0; i < sync_fds.size(); ++i) {
-      // Submit wait semaphore to the queue. Note that Skia uses the same queue
-      // exposed by vk_queue(), so this will work due to Vulkan queue ordering.
-      if (!SubmitWaitVkSemaphore(vk_queue(), semaphores[i])) {
-        failed_to_insert_semaphores = true;
-        break;
-      }
-    }
-
-    if (failed_to_insert_semaphores) {
-      DestroyAllSemaphores(vk_device(), vk_queue(), std::move(semaphores),
-                           true /* wait_for_idle */);
+    // Submit wait semaphore to the queue. Note that Skia uses the same queue
+    // exposed by vk_queue(), so this will work due to Vulkan queue ordering.
+    if (!SubmitWaitVkSemaphore(vk_queue(), semaphore)) {
+      DestroySemaphore(vk_device(), vk_queue(), semaphore);
       return nullptr;
     }
 
     promise_texture_ = BeginVulkanAccess(
         vk_implementation(), vk_device(), vk_phy_device(), vk_queue(),
-        ahb_backing()->GetAhbHandle(), size(), format(), std::move(semaphores));
+        ahb_backing()->GetAhbHandle(), size(), format(), semaphore);
     if (!promise_texture_)
       return nullptr;
 
@@ -582,13 +555,9 @@
       }
     }
 
-    std::vector<VkSemaphore> semaphores_to_clean(1);
-    semaphores_to_clean.emplace_back(std::move(semaphore));
-
-    auto promise_texture =
-        BeginVulkanAccess(vk_implementation(), vk_device(), vk_phy_device(),
-                          vk_queue(), ahb_backing()->GetAhbHandle(), size(),
-                          format(), std::move(semaphores_to_clean));
+    auto promise_texture = BeginVulkanAccess(
+        vk_implementation(), vk_device(), vk_phy_device(), vk_queue(),
+        ahb_backing()->GetAhbHandle(), size(), format(), std::move(semaphore));
 
     // Cache the sk surface in the representation so that it can be used in the
     // EndReadAccess. Also make sure previous surface_ have been consumed by
@@ -775,8 +744,7 @@
       manager, this, promise_texture, tracker, std::move(texture));
 }
 
-bool SharedImageBackingAHB::BeginWrite(
-    std::vector<base::ScopedFD>* fds_to_wait_on) {
+bool SharedImageBackingAHB::BeginWrite(base::ScopedFD* fd_to_wait_on) {
   AutoLock auto_lock(this);
 
   if (is_writing_ || !active_readers_.empty()) {
@@ -786,11 +754,8 @@
   }
 
   is_writing_ = true;
-
-  (*fds_to_wait_on) = std::move(read_sync_fds_);
-  // Assign a known state back to the moved-from read_sync_fds
-  read_sync_fds_ = std::vector<base::ScopedFD>{};
-  fds_to_wait_on->emplace_back(std::move(write_sync_fd_));
+  (*fd_to_wait_on) =
+      gl::MergeFDs(std::move(read_sync_fd_), std::move(write_sync_fd_));
 
   return true;
 }
@@ -846,8 +811,8 @@
 
   active_readers_.erase(reader);
 
-  if (end_read_fd.is_valid())
-    read_sync_fds_.emplace_back(std::move(end_read_fd));
+  read_sync_fd_ =
+      gl::MergeFDs(std::move(read_sync_fd_), std::move(end_read_fd));
 }
 
 gles2::Texture* SharedImageBackingAHB::GenGLTexture() {
diff --git a/gpu/command_buffer/service/shared_image_factory.h b/gpu/command_buffer/service/shared_image_factory.h
index 261454a..824f2c9a1 100644
--- a/gpu/command_buffer/service/shared_image_factory.h
+++ b/gpu/command_buffer/service/shared_image_factory.h
@@ -75,6 +75,7 @@
                     base::trace_event::ProcessMemoryDump* pmd,
                     int client_id,
                     uint64_t client_tracing_id);
+  MemoryTypeTracker* memory_tracker() const { return memory_tracker_.get(); }
 
  private:
   bool IsSharedBetweenThreads(uint32_t usage);
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index bb62ffddf..5cd4704c 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -32,6 +32,10 @@
 class ProgressReporter;
 }
 
+namespace media {
+class SharedImageVideo;
+}
+
 namespace gpu {
 class DecoderContext;
 class ExternalVkImageBacking;
@@ -375,6 +379,7 @@
   friend class MailboxManagerTest;
   friend class gpu::ExternalVkImageBacking;
   friend class gpu::ExternalVkImageGlRepresentation;
+  friend class media::SharedImageVideo;
   friend class gpu::SharedImageBackingGLTexture;
   friend class gpu::SharedImageBackingFactoryGLTexture;
   friend class gpu::SharedImageBackingAHB;
diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc
index 032b734..70084fa 100644
--- a/gpu/command_buffer/service/texture_manager_unittest.cc
+++ b/gpu/command_buffer/service/texture_manager_unittest.cc
@@ -655,7 +655,7 @@
         kMaxArrayTextureLayers, kUseDefaultTextures, nullptr,
         &discardable_manager_));
     decoder_.reset(new ::testing::StrictMock<MockGLES2Decoder>(
-        &command_buffer_service_, &outputter_));
+        &client_, &command_buffer_service_, &outputter_));
     error_state_.reset(new ::testing::StrictMock<MockErrorState>());
     manager_->CreateTexture(kClient1Id, kService1Id);
     texture_ref_ = manager_->GetTexture(kClient1Id);
@@ -689,6 +689,7 @@
   }
 
   FakeCommandBufferServiceBase command_buffer_service_;
+  FakeDecoderClient client_;
   TraceOutputter outputter_;
   std::unique_ptr<MockGLES2Decoder> decoder_;
   std::unique_ptr<MockErrorState> error_state_;
diff --git a/gpu/command_buffer/service/webgpu_decoder.cc b/gpu/command_buffer/service/webgpu_decoder.cc
index 7758aa9..f22232b 100644
--- a/gpu/command_buffer/service/webgpu_decoder.cc
+++ b/gpu/command_buffer/service/webgpu_decoder.cc
@@ -29,7 +29,7 @@
 WebGPUDecoder::WebGPUDecoder(DecoderClient* client,
                              CommandBufferServiceBase* command_buffer_service,
                              gles2::Outputter* outputter)
-    : CommonDecoder(command_buffer_service) {}
+    : CommonDecoder(client, command_buffer_service) {}
 
 WebGPUDecoder::~WebGPUDecoder() {}
 
diff --git a/gpu/ipc/client/raster_in_process_context_tests.cc b/gpu/ipc/client/raster_in_process_context_tests.cc
index 520066d..fd66316 100644
--- a/gpu/ipc/client/raster_in_process_context_tests.cc
+++ b/gpu/ipc/client/raster_in_process_context_tests.cc
@@ -111,8 +111,8 @@
 
   // Should flag an error this command is not allowed between a Begin and
   // EndRasterCHROMIUM.
-  SyncToken sync_token;
-  ri_->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+  GLuint id;
+  ri_->GenQueriesEXT(1, &id);
   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), ri_->GetError());
 
   // Confirm that we skip over without error.
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc
index db4fb5e..c4a7a6c 100644
--- a/gpu/ipc/service/direct_composition_surface_win.cc
+++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -483,6 +483,18 @@
     kMaxValue = kBindAndVideoProcessorBlit,
   };
 
+  // Mapped to DecodeSwapChainNotUsedReason UMA enum.  Do not remove or remap
+  // existing entries.
+  enum class DecodeSwapChainNotUsedReason {
+    kSoftwareFrame = 0,
+    kNv12NotSupported = 1,
+    kFailedToPresent = 2,
+    kNonDecoderTexture = 3,
+    kSharedTexture = 4,
+    kIncompatibleTransform = 5,
+    kMaxValue = kIncompatibleTransform,
+  };
+
   // Upload given YUV buffers to NV12 |staging_texture_|.  Returns true on
   // success.
   bool UploadVideoImages(gl::GLImageMemory* y_image_memory,
@@ -1154,54 +1166,72 @@
   if (UpdateVisuals(params, swap_chain_size))
     *needs_commit = true;
 
-  bool use_decode_swap_chain =
-      base::FeatureList::IsEnabled(
-          features::kDirectCompositionUseNV12DecodeSwapChain) &&
-      g_overlay_format_used == OverlayFormat::kNV12 &&
-      !failed_to_present_decode_swapchain_;
-  // TODO(sunnyps): Try using decode swap chain for uploaded video images.
-  if (image_dxgi && use_decode_swap_chain) {
-    D3D11_TEXTURE2D_DESC texture_desc = {};
-    image_dxgi->texture()->GetDesc(&texture_desc);
+  if (base::FeatureList::IsEnabled(
+          features::kDirectCompositionUseNV12DecodeSwapChain)) {
+    auto not_used_reason = DecodeSwapChainNotUsedReason::kFailedToPresent;
 
-    bool is_decoder_texture = texture_desc.BindFlags & D3D11_BIND_DECODER;
+    bool nv12_supported = g_overlay_format_used == OverlayFormat::kNV12;
+    // TODO(sunnyps): Try using decode swap chain for uploaded video images.
+    if (image_dxgi && nv12_supported && !failed_to_present_decode_swapchain_) {
+      D3D11_TEXTURE2D_DESC texture_desc = {};
+      image_dxgi->texture()->GetDesc(&texture_desc);
 
-    // Decode swap chains do not support shared resources.
-    // TODO(sunnyps): Find a workaround for when the decoder moves to its own
-    // thread and D3D device.  See https://crbug.com/911847
-    bool is_shared_texture =
-        texture_desc.MiscFlags &
-        (D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX |
-         D3D11_RESOURCE_MISC_SHARED_NTHANDLE);
+      bool is_decoder_texture = texture_desc.BindFlags & D3D11_BIND_DECODER;
 
-    // Rotated videos are not promoted to overlays.  We plan to implement
-    // rotation using video processor instead of via direct composition.  Also
-    // check for skew and any downscaling specified to direct composition.
-    bool is_overlay_supported_transform =
-        visual_info_.transform.IsPositiveScaleOrTranslation();
+      // Decode swap chains do not support shared resources.
+      // TODO(sunnyps): Find a workaround for when the decoder moves to its own
+      // thread and D3D device.  See https://crbug.com/911847
+      bool is_shared_texture =
+          texture_desc.MiscFlags &
+          (D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX |
+           D3D11_RESOURCE_MISC_SHARED_NTHANDLE);
 
-    // Downscaled video isn't promoted to hardware overlays.  We prefer to blit
-    // into the smaller size so that it can be promoted to a hardware overlay.
-    float swap_chain_scale_x =
-        swap_chain_size.width() * 1.0f / params.content_rect.width();
-    float swap_chain_scale_y =
-        swap_chain_size.height() * 1.0f / params.content_rect.height();
+      // Rotated videos are not promoted to overlays.  We plan to implement
+      // rotation using video processor instead of via direct composition.  Also
+      // check for skew and any downscaling specified to direct composition.
+      bool is_overlay_supported_transform =
+          visual_info_.transform.IsPositiveScaleOrTranslation();
 
-    is_overlay_supported_transform = is_overlay_supported_transform &&
-                                     (swap_chain_scale_x >= 1.0f) &&
-                                     (swap_chain_scale_y >= 1.0f);
+      // Downscaled video isn't promoted to hardware overlays.  We prefer to
+      // blit into the smaller size so that it can be promoted to a hardware
+      // overlay.
+      float swap_chain_scale_x =
+          swap_chain_size.width() * 1.0f / params.content_rect.width();
+      float swap_chain_scale_y =
+          swap_chain_size.height() * 1.0f / params.content_rect.height();
 
-    if (is_decoder_texture && !is_shared_texture &&
-        is_overlay_supported_transform) {
-      if (PresentToDecodeSwapChain(image_dxgi, params.content_rect,
-                                   swap_chain_size, needs_commit)) {
-        return true;
+      is_overlay_supported_transform = is_overlay_supported_transform &&
+                                       (swap_chain_scale_x >= 1.0f) &&
+                                       (swap_chain_scale_y >= 1.0f);
+
+      if (is_decoder_texture && !is_shared_texture &&
+          is_overlay_supported_transform) {
+        if (PresentToDecodeSwapChain(image_dxgi, params.content_rect,
+                                     swap_chain_size, needs_commit)) {
+          return true;
+        }
+        ReleaseSwapChainResources();
+        failed_to_present_decode_swapchain_ = true;
+        not_used_reason = DecodeSwapChainNotUsedReason::kFailedToPresent;
+        DLOG(ERROR)
+            << "Present to decode swap chain failed - falling back to blit";
+      } else if (!is_decoder_texture) {
+        not_used_reason = DecodeSwapChainNotUsedReason::kNonDecoderTexture;
+      } else if (is_shared_texture) {
+        not_used_reason = DecodeSwapChainNotUsedReason::kSharedTexture;
+      } else if (!is_overlay_supported_transform) {
+        not_used_reason = DecodeSwapChainNotUsedReason::kIncompatibleTransform;
       }
-      ReleaseSwapChainResources();
-      failed_to_present_decode_swapchain_ = true;
-      DLOG(ERROR)
-          << "Present to decode swap chain failed - falling back to blit";
+    } else if (!image_dxgi) {
+      not_used_reason = DecodeSwapChainNotUsedReason::kSoftwareFrame;
+    } else if (!nv12_supported) {
+      not_used_reason = DecodeSwapChainNotUsedReason::kNv12NotSupported;
+    } else if (failed_to_present_decode_swapchain_) {
+      not_used_reason = DecodeSwapChainNotUsedReason::kFailedToPresent;
     }
+
+    UMA_HISTOGRAM_ENUMERATION(
+        "GPU.DirectComposition.DecodeSwapChainNotUsedReason", not_used_reason);
   }
 
   bool swap_chain_resized = swap_chain_size_ != swap_chain_size;
@@ -1215,6 +1245,7 @@
       toggle_protected_video) {
     if (!ReallocateSwapChain(swap_chain_size, use_yuv_swap_chain,
                              params.protected_video_type)) {
+      ReleaseSwapChainResources();
       return false;
     }
     content_visual_->SetContent(swap_chain_.Get());
diff --git a/gpu/ipc/service/gpu_channel.h b/gpu/ipc/service/gpu_channel.h
index eafab1a..1cfe978 100644
--- a/gpu/ipc/service/gpu_channel.h
+++ b/gpu/ipc/service/gpu_channel.h
@@ -158,6 +158,10 @@
   const CommandBufferStub* GetOneStub() const;
 #endif
 
+  SharedImageStub* shared_image_stub() const {
+    return shared_image_stub_.get();
+  }
+
  private:
   // Takes ownership of the renderer process handle.
   GpuChannel(GpuChannelManager* gpu_channel_manager,
diff --git a/gpu/ipc/service/shared_image_stub.h b/gpu/ipc/service/shared_image_stub.h
index 9094304b..8e832fa 100644
--- a/gpu/ipc/service/shared_image_stub.h
+++ b/gpu/ipc/service/shared_image_stub.h
@@ -42,6 +42,7 @@
                     base::trace_event::ProcessMemoryDump* pmd) override;
 
   SequenceId sequence() const { return sequence_; }
+  SharedImageFactory* factory() const { return factory_.get(); }
 
  private:
   SharedImageStub(GpuChannel* channel, int32_t route_id);
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg
index 842337c..d679c2c 100644
--- a/infra/config/cr-buildbucket.cfg
+++ b/infra/config/cr-buildbucket.cfg
@@ -699,11 +699,6 @@
     }
 
     builders {
-      name: "Android FYI 32 dEQP Vk Release (Nexus 5X)"
-      mixins: "android-gpu-fyi-ci"
-    }
-
-    builders {
       name: "Android FYI 32 dEQP Vk Release (Pixel 2)"
       mixins: "android-gpu-fyi-ci"
     }
@@ -714,11 +709,6 @@
     }
 
     builders {
-      name: "Android FYI 32 Vk Release (Nexus 5X)"
-      mixins: "android-gpu-fyi-ci"
-    }
-
-    builders {
       name: "Android FYI 32 Vk Release (Pixel 2)"
       mixins: "android-gpu-fyi-ci"
     }
@@ -729,11 +719,6 @@
     }
 
     builders {
-      name: "Android FYI 64 dEQP Vk Release (Nexus 5X)"
-      mixins: "android-gpu-fyi-ci"
-    }
-
-    builders {
       name: "Android FYI 64 dEQP Vk Release (Pixel 2)"
       mixins: "android-gpu-fyi-ci"
     }
@@ -744,11 +729,6 @@
     }
 
     builders {
-      name: "Android FYI 64 Vk Release (Nexus 5X)"
-      mixins: "android-gpu-fyi-ci"
-    }
-
-    builders {
       name: "Android FYI 64 Vk Release (Pixel 2)"
       mixins: "android-gpu-fyi-ci"
     }
diff --git a/infra/config/luci-milo.cfg b/infra/config/luci-milo.cfg
index 4033c844..7a40bc8 100644
--- a/infra/config/luci-milo.cfg
+++ b/infra/config/luci-milo.cfg
@@ -3294,20 +3294,10 @@
   }
   builders {
     name: "buildbucket/luci.chromium.ci/Android FYI Release (Pixel 2)"
-    category: "Android|P64|QCOM"
+    category: "Android|P32|QCOM"
     short_name: "P2"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/Android FYI 32 Vk Release (Nexus 5X)"
-    category: "Android|vk|O32"
-    short_name: "N5X"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.ci/Android FYI 64 Vk Release (Nexus 5X)"
-    category: "Android|vk|O64"
-    short_name: "N5X"
-  }
-  builders {
     name: "buildbucket/luci.chromium.ci/Android FYI 32 Vk Release (Pixel XL)"
     category: "Android|vk|P32"
     short_name: "PXL"
@@ -3333,16 +3323,6 @@
     short_name: "N5X"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/Android FYI 32 dEQP Vk Release (Nexus 5X)"
-    category: "Android|dqp|vk|O32"
-    short_name: "N5X"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.ci/Android FYI 64 dEQP Vk Release (Nexus 5X)"
-    category: "Android|dqp|vk|O64"
-    short_name: "N5X"
-  }
-  builders {
     name: "buildbucket/luci.chromium.ci/Android FYI 32 dEQP Vk Release (Pixel XL)"
     category: "Android|dqp|vk|P32"
     short_name: "PXL"
diff --git a/infra/config/luci-scheduler.cfg b/infra/config/luci-scheduler.cfg
index 087c9e56..c070b74 100644
--- a/infra/config/luci-scheduler.cfg
+++ b/infra/config/luci-scheduler.cfg
@@ -73,16 +73,12 @@
   triggers: "Android Builder (dbg)"
   triggers: "Android CFI"
   triggers: "Android Cronet Builder"
-  triggers: "Android FYI 32 Vk Release (Nexus 5X)"
   triggers: "Android FYI 32 Vk Release (Pixel 2)"
   triggers: "Android FYI 32 Vk Release (Pixel XL)"
-  triggers: "Android FYI 32 dEQP Vk Release (Nexus 5X)"
   triggers: "Android FYI 32 dEQP Vk Release (Pixel 2)"
   triggers: "Android FYI 32 dEQP Vk Release (Pixel XL)"
-  triggers: "Android FYI 64 Vk Release (Nexus 5X)"
   triggers: "Android FYI 64 Vk Release (Pixel 2)"
   triggers: "Android FYI 64 Vk Release (Pixel XL)"
-  triggers: "Android FYI 64 dEQP Vk Release (Nexus 5X)"
   triggers: "Android FYI 64 dEQP Vk Release (Pixel 2)"
   triggers: "Android FYI 64 dEQP Vk Release (Pixel XL)"
   triggers: "Android FYI Release (NVIDIA Shield TV)"
@@ -454,16 +450,6 @@
 }
 
 job {
-  id: "Android FYI 32 dEQP Vk Release (Nexus 5X)"
-  acl_sets: "default"
-  buildbucket: {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.chromium.ci"
-    builder: "Android FYI 32 dEQP Vk Release (Nexus 5X)"
-  }
-}
-
-job {
   id: "Android FYI 32 dEQP Vk Release (Pixel 2)"
   acl_sets: "default"
   buildbucket: {
@@ -484,16 +470,6 @@
 }
 
 job {
-  id: "Android FYI 32 Vk Release (Nexus 5X)"
-  acl_sets: "default"
-  buildbucket: {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.chromium.ci"
-    builder: "Android FYI 32 Vk Release (Nexus 5X)"
-  }
-}
-
-job {
   id: "Android FYI 32 Vk Release (Pixel 2)"
   acl_sets: "default"
   buildbucket: {
@@ -514,16 +490,6 @@
 }
 
 job {
-  id: "Android FYI 64 dEQP Vk Release (Nexus 5X)"
-  acl_sets: "default"
-  buildbucket: {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.chromium.ci"
-    builder: "Android FYI 64 dEQP Vk Release (Nexus 5X)"
-  }
-}
-
-job {
   id: "Android FYI 64 dEQP Vk Release (Pixel 2)"
   acl_sets: "default"
   buildbucket: {
@@ -544,16 +510,6 @@
 }
 
 job {
-  id: "Android FYI 64 Vk Release (Nexus 5X)"
-  acl_sets: "default"
-  buildbucket: {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.chromium.ci"
-    builder: "Android FYI 64 Vk Release (Nexus 5X)"
-  }
-}
-
-job {
   id: "Android FYI 64 Vk Release (Pixel 2)"
   acl_sets: "default"
   buildbucket: {
@@ -1057,19 +1013,6 @@
 }
 
 job {
-  id: "Nougat Phone Tester"
-  # triggered by "Android arm64 Builder (dbg)"
-  acl_sets: "triggered-by-parent-builders"
-  # TODO(bpastene): s/noop/buildbucket.
-  noop: {}
-  # buildbucket: {
-  #   server: "cr-buildbucket.appspot.com"
-  #   bucket: "luci.chromium.ci"
-  #   builder: "Nougat Phone Tester"
-  # }
-}
-
-job {
   id: "Optional Android Release (Nexus 5X)"
   acl_sets: "default"
   # This bot doesn't actually exist, so it's noop'ed out. crbug.com/819899
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn
index 4b00738a..bdfcc01 100644
--- a/ios/chrome/app/BUILD.gn
+++ b/ios/chrome/app/BUILD.gn
@@ -368,7 +368,7 @@
         "$root_out_dir/content_widget_extension.appex",
       ]
       outputs = [
-        "{{bundle_plugins_dir}}/{{source_file_part}}",
+        "{{bundle_contents_dir}}/PlugIns/{{source_file_part}}",
       ]
     }
   }
@@ -382,7 +382,7 @@
         "$root_out_dir/search_widget_extension.appex",
       ]
       outputs = [
-        "{{bundle_plugins_dir}}/{{source_file_part}}",
+        "{{bundle_contents_dir}}/PlugIns/{{source_file_part}}",
       ]
     }
   }
@@ -396,7 +396,7 @@
         "$root_out_dir/share_extension.appex",
       ]
       outputs = [
-        "{{bundle_plugins_dir}}/{{source_file_part}}",
+        "{{bundle_contents_dir}}/PlugIns/{{source_file_part}}",
       ]
     }
   }
diff --git a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ja.xtb b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ja.xtb
index 061c029..fad9dff 100644
--- a/ios/chrome/app/strings/resources/ios_google_chrome_strings_ja.xtb
+++ b/ios/chrome/app/strings/resources/ios_google_chrome_strings_ja.xtb
@@ -9,7 +9,7 @@
 <translation id="2147651015520127414">このウェブサイトの証明書が <ph name="ISSUER" /> 発行のものであると確認されました。</translation>
 <translation id="2199719347983604670">Chrome 同期のデータ</translation>
 <translation id="2334084861041072223">Copyright <ph name="YEAR" /> Google Inc. All rights reserved.</translation>
-<translation id="2342981853652716282">Chrome にログインすれば、ブックマーク、パスワード、その他の設定をどの端末からでもご利用いただけます。</translation>
+<translation id="2342981853652716282">Chrome にログインすると、ブックマーク、パスワード、その他の設定をどの端末からでもご利用いただけます。</translation>
 <translation id="2347208864470321755">この機能を有効にすると、外国語のページで翻訳ツールが表示されます。<ph name="BEGIN_LINK" />詳細<ph name="END_LINK" /></translation>
 <translation id="2441696206556358796">画像を保存するには、[設定] をタップして写真の使用を Chrome に許可してください</translation>
 <translation id="2576431527583832481">Chrome のアップデートが見つかりました。新しいバージョンが利用可能です。</translation>
@@ -48,7 +48,7 @@
 <translation id="7265369419224458312">パソコンで開いたタブにこちらからアクセスできます。パソコンでChromeを開き、メニューから[Chromeにログイン]を選択してください。</translation>
 <translation id="728488472449859922">Google Chrome の QR スキャナをオンにする</translation>
 <translation id="7400722733683201933">Google Chrome について</translation>
-<translation id="7437998757836447326">Chromeからログアウト</translation>
+<translation id="7437998757836447326">Chrome からログアウト</translation>
 <translation id="756809126120519699">Chrome データの消去完了</translation>
 <translation id="7626032353295482388">Chrome へようこそ</translation>
 <translation id="840168496893712993">アドオンが原因でChromeがクラッシュしました。アドオンをアンインストールしてみてください。</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb b/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb
index 76fb203..68827349 100644
--- a/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_en-GB.xtb
@@ -513,7 +513,7 @@
 <translation id="9188680907066685419">Sign out of managed account</translation>
 <translation id="9203116392574189331">Handoff</translation>
 <translation id="9223358826628549784">Crash report sent.</translation>
-<translation id="935490618240037774">Your bookmarks, history, passwords and other settings will be synced to yourGoogle Accountso that you can use them on all of your devices.</translation>
+<translation id="935490618240037774">Your bookmarks, history, passwords and other settings will be synced to your Google Account so that you can use them on all of your devices.</translation>
 <translation id="976982866697960176">Manage Synced Data…</translation>
 <translation id="988141524645182168">Other devices</translation>
 <translation id="989988560359834682">Edit Address</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_fil.xtb b/ios/chrome/app/strings/resources/ios_strings_fil.xtb
index a622cb14..2fe0bcc 100644
--- a/ios/chrome/app/strings/resources/ios_strings_fil.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_fil.xtb
@@ -364,6 +364,7 @@
 <translation id="6643016212128521049">I-clear</translation>
 <translation id="6656103420185847513">I-edit ang Folder</translation>
 <translation id="6657585470893396449">Password</translation>
+<translation id="6668619169535738264">I-edit ang Bookmark</translation>
 <translation id="667999046851023355">Dokumento</translation>
 <translation id="6691331417640343772">Pamahalaan ang naka-sync na data sa Google Dashboard</translation>
 <translation id="6713747756340119864">Google Apps</translation>
@@ -406,6 +407,7 @@
 <translation id="7291368939935408496">Inihahanda ang Mga Password...</translation>
 <translation id="7336264872878993241"><ph name="PERCENT" /> (na) porsyento ang na-download na</translation>
 <translation id="7346909386216857016">Ok, nakuha ko</translation>
+<translation id="7348502496356775519">Bookmark</translation>
 <translation id="7383797227493018512">Listahan ng Babasahin</translation>
 <translation id="7400418766976504921">URL</translation>
 <translation id="7425346204213733349">Hindi na masi-sync sa Google Account mo ang mga pagbabago sa iyong mga bookmark, history, password, at iba pang setting. Gayunpaman, mananatiling naka-store sa Google account mo ang iyong kasalukuyang data.</translation>
diff --git a/ios/chrome/app/strings/resources/ios_strings_ja.xtb b/ios/chrome/app/strings/resources/ios_strings_ja.xtb
index 58f2ef8..369721e 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ja.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ja.xtb
@@ -63,7 +63,7 @@
 <translation id="1752547299766512813">パスワードの保存</translation>
 <translation id="1753905327828125965">よくアクセスするページ</translation>
 <translation id="1809939268435598390">フォルダーを削除</translation>
-<translation id="1813414402673211292">閲覧履歴の消去</translation>
+<translation id="1813414402673211292">閲覧履歴データの削除</translation>
 <translation id="1820259098641718022">リーディング リストに追加しました</translation>
 <translation id="1828824471510190776">パスワードを自動生成...</translation>
 <translation id="1876721852596493031">使用状況データ送信</translation>
@@ -371,7 +371,7 @@
 <translation id="6730682669179532099">パスワードをエクスポートできません</translation>
 <translation id="6780034285637185932">郵便番号</translation>
 <translation id="6785453220513215166">クラッシュレポートを送信しています...</translation>
-<translation id="679325081238418596">ブックマーク、履歴、パスワードなどの設定がどの端末でも利用できるようになります</translation>
+<translation id="679325081238418596">ブックマーク、履歴、パスワードなどの設定をどの端末でも利用できるようにします</translation>
 <translation id="6797885426782475225">音声検索</translation>
 <translation id="6807889908376551050">すべて表示...</translation>
 <translation id="681368974849482173">作成済みのアイテム</translation>
@@ -396,7 +396,7 @@
 <translation id="7133798577887235672">氏名</translation>
 <translation id="7136892417564438900">カメラを使用できません</translation>
 <translation id="7159472599653637159">モバイルサイトをリクエスト</translation>
-<translation id="7167621057293532233">データ タイプ</translation>
+<translation id="7167621057293532233">データの種類</translation>
 <translation id="7189598951263744875">共有...</translation>
 <translation id="7192050974311852563">ログ記録を開始</translation>
 <translation id="7203585745079012652">回答を音声で聞く</translation>
@@ -497,7 +497,7 @@
 <translation id="8971089644512329999">OK</translation>
 <translation id="8976382372951310360">ヘルプ</translation>
 <translation id="8981454092730389528">Google アクティビティ管理</translation>
-<translation id="8985320356172329008">次のユーザーとして Google にログインしています:</translation>
+<translation id="8985320356172329008">次のユーザーとして Google にログインしています</translation>
 <translation id="902659348151742535">検索、広告、その他の Google サービスをカスタマイズする目的で、Google が閲覧履歴を使用することがあります。</translation>
 <translation id="9034759925968272072">Google アカウントへのログイン状態は維持されます。Google アカウントでの他の形式の閲覧履歴が <ph name="BEGIN_LINK" />history.google.com<ph name="END_LINK" /> に残ることがあります。</translation>
 <translation id="9039373489628511875">帯域幅</translation>
@@ -515,7 +515,7 @@
 <translation id="9223358826628549784">クラッシュレポートを送信しました。</translation>
 <translation id="935490618240037774">ブックマーク、履歴、パスワード、その他の設定が Google アカウントに同期され、どの端末でも利用できるようになります。</translation>
 <translation id="976982866697960176">同期データを管理...</translation>
-<translation id="988141524645182168">その他のデバイス</translation>
+<translation id="988141524645182168">他のデバイス</translation>
 <translation id="989988560359834682">住所の編集</translation>
 <translation id="994757059139821576">記事の候補表示</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/ios/chrome/app/strings/resources/ios_strings_ta.xtb b/ios/chrome/app/strings/resources/ios_strings_ta.xtb
index a1fb66af..404b6d4 100644
--- a/ios/chrome/app/strings/resources/ios_strings_ta.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_ta.xtb
@@ -42,6 +42,7 @@
 <translation id="152234381334907219">எப்போதும் சேமிக்காதவை</translation>
 <translation id="1540800554400757039">முகவரி 1</translation>
 <translation id="1545749641540134597">QR குறியீட்டை ஸ்கேன் செய்க</translation>
+<translation id="1552525382687785070">உங்கள் நிர்வாகி ஒத்திசைவை முடக்கியுள்ளார்</translation>
 <translation id="1558704936695638228">மேலும் தாவல் விருப்பத்தேர்வுகளைப் பார்க்க, அழுத்திப் பிடித்திருக்கவும்</translation>
 <translation id="1580783302095112590">மின்னஞ்சல் அனுப்பப்பட்டது.</translation>
 <translation id="1582732959743469162">இவ்வாறு செய்தால் உங்களின் தற்போதைய பதிவிறக்கத்திற்கான அனைத்துச் செயல்பாடும் நிறுத்தப்படும்.</translation>
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm
index 5a62687..9560828 100644
--- a/ios/chrome/browser/about_flags.mm
+++ b/ios/chrome/browser/about_flags.mm
@@ -347,11 +347,6 @@
      flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(
          autofill::features::kAutofillEnforceMinRequiredFieldsForUpload)},
-    {"browser-container-fullscreen",
-     flag_descriptions::kBrowserContainerFullscreenName,
-     flag_descriptions::kBrowserContainerFullscreenDescription,
-     flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(web::features::kBrowserContainerFullscreen)},
     {"autofill-cache-query-responses",
      flag_descriptions::kAutofillCacheQueryResponsesName,
      flag_descriptions::kAutofillCacheQueryResponsesDescription,
@@ -380,9 +375,6 @@
      flag_descriptions::kSyncSupportSecondaryAccountDescription,
      flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(switches::kSyncSupportSecondaryAccount)},
-    {"out-of-web-fullscreen", flag_descriptions::kOutOfWebFullscreenName,
-     flag_descriptions::kOutOfWebFullscreenDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(web::features::kOutOfWebFullscreen)},
     {"autofill-manual-fallback-phase-two",
      flag_descriptions::kAutofillManualFallbackPhaseTwoName,
      flag_descriptions::kAutofillManualFallbackPhaseTwoDescription,
diff --git a/ios/chrome/browser/autofill/automation/automation_egtest.mm b/ios/chrome/browser/autofill/automation/automation_egtest.mm
index 268ed80a..bd85c3ce 100644
--- a/ios/chrome/browser/autofill/automation/automation_egtest.mm
+++ b/ios/chrome/browser/autofill/automation/automation_egtest.mm
@@ -194,6 +194,7 @@
   autofill::PersonalDataManager* personal_data_manager =
       autofill_manager->client()->GetPersonalDataManager();
 
+  personal_data_manager->ClearAllLocalData();
   personal_data_manager->AddCreditCard(credit_card);
   personal_data_manager->SaveImportedProfile(profile);
 }
diff --git a/ios/chrome/browser/autofill/form_input_accessory_consumer.h b/ios/chrome/browser/autofill/form_input_accessory_consumer.h
index c3b3d37..ae85277 100644
--- a/ios/chrome/browser/autofill/form_input_accessory_consumer.h
+++ b/ios/chrome/browser/autofill/form_input_accessory_consumer.h
@@ -50,6 +50,11 @@
 // reset.
 - (void)continueCustomKeyboardView;
 
+// Tells the consumer that suggestions are being fetched. The fetching is
+// asynchronous, so this call gives the opportunity to do any view preparation
+// that doesn't need the suggestions.
+- (void)prepareToShowSuggestions;
+
 // Replace the keyboard accessory view with one showing the passed suggestions.
 // And form navigation buttons if not an iPad (which already includes those).
 // |isHardwareKeyboard| is true if a hardware keyboard is in use.
diff --git a/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm b/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm
index b539b04..7db7b1163 100644
--- a/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm
+++ b/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm
@@ -114,10 +114,21 @@
   return self;
 }
 
+// Returns YES if the keyboard constraint view is present. This view is the one
+// used to constraint any presented view.
+- (BOOL)canPresentView {
+  if (IsIPadIdiom()) {
+    // iPad always presents in a separate popover.
+    return YES;
+  }
+  UIView* keyboardView = [self getKeyboardView];
+  return [self recursiveGetKeyboardConstraintView:keyboardView];
+}
+
 #pragma mark - Public
 
 - (void)presentView:(UIView*)view {
-  if (self.paused) {
+  if (self.paused || ![self canPresentView]) {
     return;
   }
   DCHECK(view);
@@ -127,7 +138,6 @@
   [keyboardView.superview addSubview:view];
   UIView* constrainingView =
       [self recursiveGetKeyboardConstraintView:keyboardView];
-  DCHECK(constrainingView);
   view.translatesAutoresizingMaskIntoConstraints = NO;
   AddSameConstraints(view, constrainingView);
   self.keyboardReplacementView = view;
@@ -148,6 +158,12 @@
 
 #pragma mark - FormInputAccessoryConsumer
 
+- (void)prepareToShowSuggestions {
+  // Hides the Manual Fallback icons when there is no proper keyboard to present
+  // those views. And shows them if there is a keyboard present.
+  self.manualFillAccessoryViewController.view.hidden = ![self canPresentView];
+}
+
 - (void)showAccessorySuggestions:(NSArray<FormSuggestion*>*)suggestions
                 suggestionClient:(id<FormSuggestionClient>)suggestionClient
               isHardwareKeyboard:(BOOL)hardwareKeyboard {
@@ -310,7 +326,8 @@
 
 - (UIView*)getKeyboardView {
   NSArray* windows = [UIApplication sharedApplication].windows;
-  if (windows.count < 2)
+  NSUInteger expectedMinWindows = IsIPadIdiom() ? 2 : 3;
+  if (windows.count < expectedMinWindows)
     return nil;
 
   UIWindow* window;
@@ -374,6 +391,7 @@
   if (CGRectContainsRect(windowRect, keyboardFrame)) {
     _keyboardFrame = keyboardFrame;
     // Make sure the input accessory is there if needed.
+    [self prepareToShowSuggestions];
     [self addInputAccessoryViewIfNeeded];
     [self addCustomKeyboardViewIfNeeded];
   } else {
diff --git a/ios/chrome/browser/browsing_data/cache_counter.cc b/ios/chrome/browser/browsing_data/cache_counter.cc
index 7c0d8c42..05ef844 100644
--- a/ios/chrome/browser/browsing_data/cache_counter.cc
+++ b/ios/chrome/browser/browsing_data/cache_counter.cc
@@ -10,7 +10,7 @@
 #include "ios/web/public/browser_state.h"
 #include "ios/web/public/web_task_traits.h"
 #include "ios/web/public/web_thread.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_repeating_callback.h"
 #include "net/base/net_errors.h"
 #include "net/disk_cache/disk_cache.h"
 #include "net/http/http_cache.h"
@@ -24,7 +24,7 @@
  public:
   IOThreadCacheCounter(
       const scoped_refptr<net::URLRequestContextGetter>& context_getter,
-      const net::Int64CompletionCallback& result_callback)
+      const net::Int64CompletionRepeatingCallback& result_callback)
       : next_step_(STEP_GET_BACKEND),
         context_getter_(context_getter),
         result_callback_(result_callback),
@@ -109,7 +109,7 @@
 
   Step next_step_;
   scoped_refptr<net::URLRequestContextGetter> context_getter_;
-  net::Int64CompletionCallback result_callback_;
+  net::Int64CompletionRepeatingCallback result_callback_;
   int64_t result_;
   disk_cache::Backend* backend_;
 };
diff --git a/ios/chrome/browser/favicon/favicon_loader.h b/ios/chrome/browser/favicon/favicon_loader.h
index 87772b9..676330c 100644
--- a/ios/chrome/browser/favicon/favicon_loader.h
+++ b/ios/chrome/browser/favicon/favicon_loader.h
@@ -28,19 +28,32 @@
   explicit FaviconLoader(favicon::LargeIconService* large_icon_service);
   ~FaviconLoader() override;
 
-  // Returns the FaviconAttributes for the favicon retrieved from |url|.
-  // If no icon is in favicon_cache_, will start an asynchronous load with the
-  // favicon service and return the default favicon.
-  // |fallback_to_google_server|, if set to YES, will make a call to a Google
-  // Server if no valid favicon was retrieved from LargeIconService. Calls
-  // |block| when the load completes with a valid image/attributes. Note: If no
-  // successful favicon was retrieved by LargeIconService, it returns the
-  // default favicon.
-  FaviconAttributes* FaviconForUrl(const GURL& url,
-                                   float size_in_points,
-                                   float min_size_in_points,
-                                   bool fallback_to_google_server,
-                                   FaviconAttributesCompletionBlock block);
+  // Tries to find a FaviconAttributes in |favicon_cache_| with |page_url|:
+  // If found, returns it.
+  // If not found, returns a default favicon, and invokes |block| asynchronously
+  // with the favicon fetched by trying following methods:
+  //   1. Use |large_icon_service_| to fetch from local DB managed by
+  //      HistoryService;
+  //   2. Use |large_icon_service_| to fetch from Google Favicon server if
+  //      |fallback_to_google_server|=YES;
+  //   3. Create a favicon base on the fallback style from |large_icon_service|.
+  FaviconAttributes* FaviconForPageUrl(const GURL& page_url,
+                                       float size_in_points,
+                                       float min_size_in_points,
+                                       bool fallback_to_google_server,
+                                       FaviconAttributesCompletionBlock block);
+
+  // Tries to find a FaviconAttributes in |favicon_cache_| with |icon_url|:
+  // If found, returns it.
+  // If not found, returns a default favicon, and invokes |block| asynchronously
+  // with the favicon fetched by trying following methods:
+  //   1. Use |large_icon_service_| to fetch from local DB managed by
+  //      HistoryService;
+  //   2. Create a favicon base on the fallback style from |large_icon_service|.
+  FaviconAttributes* FaviconForIconUrl(const GURL& icon_url,
+                                       float size_in_points,
+                                       float min_size_in_points,
+                                       FaviconAttributesCompletionBlock block);
 
   // Cancel all incomplete requests.
   void CancellAllRequests();
@@ -52,9 +65,9 @@
   // Tracks tasks sent to FaviconService.
   base::CancelableTaskTracker cancelable_task_tracker_;
   // Holds cached favicons. This NSCache is populated as favicons or fallback
-  // attributes are retrieved from the FaviconService. Contents will be removed
-  // during low-memory conditions based on its inherent LRU removal algorithm.
-  // Keyed by NSString of URL spec.
+  // attributes are retrieved from |large_icon_service_|. Contents will be
+  // removed during low-memory conditions based on its inherent LRU removal
+  // algorithm. Keyed by NSString of URL (page URL or icon URL) spec.
   NSCache<NSString*, FaviconAttributes*>* favicon_cache_;
 
   DISALLOW_COPY_AND_ASSIGN(FaviconLoader);
diff --git a/ios/chrome/browser/favicon/favicon_loader.mm b/ios/chrome/browser/favicon/favicon_loader.mm
index 7bc656d..0b08dd1 100644
--- a/ios/chrome/browser/favicon/favicon_loader.mm
+++ b/ios/chrome/browser/favicon/favicon_loader.mm
@@ -25,7 +25,7 @@
 #endif
 
 namespace {
-extern const CGFloat kFallbackIconDefaultTextColor = 0xAAAAAA;
+const CGFloat kFallbackIconDefaultTextColor = 0xAAAAAA;
 
 // NetworkTrafficAnnotationTag for fetching favicon from a Google server.
 const net::NetworkTrafficAnnotationTag kTrafficAnnotation =
@@ -55,15 +55,15 @@
 // TODO(pinkerton): How do we update the favicon if it's changed on the web?
 // We can possibly just rely on this class being purged or the app being killed
 // to reset it, but then how do we ensure the FaviconService is updated?
-FaviconAttributes* FaviconLoader::FaviconForUrl(
-    const GURL& url,
+FaviconAttributes* FaviconLoader::FaviconForPageUrl(
+    const GURL& page_url,
     float size_in_points,
     float min_size_in_points,
     bool fallback_to_google_server,  // retrieve favicon from Google Server if
                                      // GetLargeIconOrFallbackStyle() doesn't
                                      // return valid favicon.
     FaviconAttributesCompletionBlock block) {
-  NSString* key = base::SysUTF8ToNSString(url.spec());
+  NSString* key = base::SysUTF8ToNSString(page_url.spec());
   FaviconAttributes* value = [favicon_cache_ objectForKey:key];
   if (value) {
     return value;
@@ -73,7 +73,7 @@
       [UIScreen mainScreen].scale * size_in_points;
   const CGFloat min_favicon_size_in_pixels =
       [UIScreen mainScreen].scale * min_size_in_points;
-  GURL block_url(url);
+  GURL block_page_url(page_url);
   auto favicon_block = ^(const favicon_base::LargeIconResult& result) {
     // GetLargeIconOrFallbackStyle() either returns a valid favicon (which can
     // be the default favicon) or fallback attributes.
@@ -97,20 +97,20 @@
           ^(const favicon_base::GoogleFaviconServerRequestStatus status) {
             // Update the time when the icon was last requested - postpone thus
             // the automatic eviction of the favicon from the favicon database.
-            large_icon_service_->TouchIconFromGoogleServer(block_url);
+            large_icon_service_->TouchIconFromGoogleServer(block_page_url);
 
             // Favicon should be loaded to the db that backs LargeIconService
             // now.  Fetch it again. Even if the request was not successful, the
             // fallback style will be used.
-            FaviconForUrl(block_url, size_in_points, min_size_in_points,
-                          /*continueToGoogleServer=*/false, block);
-
+            FaviconForPageUrl(block_page_url, size_in_points,
+                              min_size_in_points,
+                              /*continueToGoogleServer=*/false, block);
           };
 
       large_icon_service_
           ->GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
               favicon::FaviconServerFetcherParams::CreateForMobile(
-                  block_url, min_favicon_size_in_pixels,
+                  block_page_url, min_favicon_size_in_pixels,
                   favicon_size_in_pixels),
               /*may_page_url_be_private=*/true, kTrafficAnnotation,
               base::BindRepeating(favicon_loaded_from_server_block));
@@ -118,21 +118,13 @@
     }
 
     // Did not get valid favicon back and are not attempting to retrieve one
-    // from a Google Server
+    // from a Google Server.
     DCHECK(result.fallback_icon_style);
-    UIColor* textColor =
-        skia::UIColorFromSkColor(result.fallback_icon_style->text_color);
-    UIColor* backgroundColor =
-        skia::UIColorFromSkColor(result.fallback_icon_style->background_color);
-    if (IsUIRefreshPhase1Enabled()) {
-      textColor = UIColorFromRGB(kFallbackIconDefaultTextColor);
-      backgroundColor = [UIColor clearColor];
-    }
     FaviconAttributes* attributes = [FaviconAttributes
         attributesWithMonogram:base::SysUTF16ToNSString(
-                                   favicon::GetFallbackIconText(block_url))
-                     textColor:textColor
-               backgroundColor:backgroundColor
+                                   favicon::GetFallbackIconText(block_page_url))
+                     textColor:UIColorFromRGB(kFallbackIconDefaultTextColor)
+               backgroundColor:UIColor.clearColor
         defaultBackgroundColor:result.fallback_icon_style->
                                is_default_background_color];
 
@@ -144,15 +136,71 @@
 
   DCHECK(large_icon_service_);
   large_icon_service_->GetLargeIconRawBitmapOrFallbackStyleForPageUrl(
-      block_url, min_favicon_size_in_pixels, favicon_size_in_pixels,
+      page_url, min_favicon_size_in_pixels, favicon_size_in_pixels,
       base::BindRepeating(favicon_block), &cancelable_task_tracker_);
 
-  if (IsUIRefreshPhase1Enabled()) {
-    return [FaviconAttributes
-        attributesWithImage:[UIImage imageNamed:@"default_world_favicon"]];
-  }
   return [FaviconAttributes
-      attributesWithImage:[UIImage imageNamed:@"default_favicon"]];
+      attributesWithImage:[UIImage imageNamed:@"default_world_favicon"]];
+}
+
+FaviconAttributes* FaviconLoader::FaviconForIconUrl(
+    const GURL& icon_url,
+    float size_in_points,
+    float min_size_in_points,
+    FaviconAttributesCompletionBlock block) {
+  NSString* key = base::SysUTF8ToNSString(icon_url.spec());
+  FaviconAttributes* value = [favicon_cache_ objectForKey:key];
+  if (value) {
+    return value;
+  }
+
+  const CGFloat favicon_size_in_pixels =
+      [UIScreen mainScreen].scale * size_in_points;
+  const CGFloat min_favicon_size_in_pixels =
+      [UIScreen mainScreen].scale * min_size_in_points;
+  GURL block_icon_url(icon_url);
+  auto favicon_block = ^(const favicon_base::LargeIconResult& result) {
+    // GetLargeIconOrFallbackStyle() either returns a valid favicon (which can
+    // be the default favicon) or fallback attributes.
+    if (result.bitmap.is_valid()) {
+      scoped_refptr<base::RefCountedMemory> data =
+          result.bitmap.bitmap_data.get();
+      // The favicon code assumes favicons are PNG-encoded.
+      UIImage* favicon =
+          [UIImage imageWithData:[NSData dataWithBytes:data->front()
+                                                length:data->size()]];
+      FaviconAttributes* attributes =
+          [FaviconAttributes attributesWithImage:favicon];
+      [favicon_cache_ setObject:attributes forKey:key];
+      if (block) {
+        block(attributes);
+      }
+      return;
+    }
+    // Did not get valid favicon back and are not attempting to retrieve one
+    // from a Google Server
+    DCHECK(result.fallback_icon_style);
+    FaviconAttributes* attributes = [FaviconAttributes
+        attributesWithMonogram:base::SysUTF16ToNSString(
+                                   favicon::GetFallbackIconText(block_icon_url))
+                     textColor:UIColorFromRGB(kFallbackIconDefaultTextColor)
+               backgroundColor:UIColor.clearColor
+        defaultBackgroundColor:result.fallback_icon_style->
+                               is_default_background_color];
+
+    [favicon_cache_ setObject:attributes forKey:key];
+    if (block) {
+      block(attributes);
+    }
+  };
+
+  DCHECK(large_icon_service_);
+  large_icon_service_->GetLargeIconRawBitmapOrFallbackStyleForIconUrl(
+      icon_url, min_favicon_size_in_pixels, favicon_size_in_pixels,
+      base::BindRepeating(favicon_block), &cancelable_task_tracker_);
+
+  return [FaviconAttributes
+      attributesWithImage:[UIImage imageNamed:@"default_world_favicon"]];
 }
 
 void FaviconLoader::CancellAllRequests() {
diff --git a/ios/chrome/browser/favicon/favicon_loader_unittest.mm b/ios/chrome/browser/favicon/favicon_loader_unittest.mm
index 11b882e..df3b375 100644
--- a/ios/chrome/browser/favicon/favicon_loader_unittest.mm
+++ b/ios/chrome/browser/favicon/favicon_loader_unittest.mm
@@ -28,6 +28,10 @@
 // Size of dummy favicon image.
 const CGFloat kTestFaviconSize = 57;
 
+// FaviconLoaderTest is parameterized on this enum to test both
+// FaviconLoader::FaviconForPageUrl and FaviconLoader::FaviconForIconUrl.
+enum FaviconUrlType { TEST_PAGE_URL, TEST_ICON_URL };
+
 // FakeLargeIconService mimics a LargeIconService that returns a LargeIconResult
 // with a test favicon image for kTestFaviconURL and a LargeIconResult
 // initialized with FallbackIconStyle.
@@ -36,6 +40,9 @@
   FakeLargeIconService()
       : favicon::LargeIconServiceImpl(/*favicon_service=*/nullptr,
                                       /*image_fetcher=*/nullptr) {}
+
+  // Returns LargeIconResult with valid bitmap if |page_url| is
+  // |kTestFaviconURL|, or LargeIconResult with fallback style.
   base::CancelableTaskTracker::TaskId
   GetLargeIconRawBitmapOrFallbackStyleForPageUrl(
       const GURL& page_url,
@@ -66,36 +73,63 @@
 
     return 1;
   }
+
+  // Returns the same as |GetLargeIconRawBitmapOrFallbackStyleForPageUrl|.
+  base::CancelableTaskTracker::TaskId
+  GetLargeIconRawBitmapOrFallbackStyleForIconUrl(
+      const GURL& icon_url,
+      int min_source_size_in_pixel,
+      int desired_size_in_pixel,
+      const favicon_base::LargeIconCallback& callback,
+      base::CancelableTaskTracker* tracker) override {
+    return GetLargeIconRawBitmapOrFallbackStyleForPageUrl(
+        icon_url, min_source_size_in_pixel, desired_size_in_pixel, callback,
+        tracker);
+  }
 };
 
-class FaviconLoaderTest : public PlatformTest {
+class FaviconLoaderTest : public PlatformTest,
+                          public ::testing::WithParamInterface<FaviconUrlType> {
  protected:
   FaviconLoaderTest() : favicon_loader_(&large_icon_service_) {}
 
   FakeLargeIconService large_icon_service_;
   FaviconLoader favicon_loader_;
 
+  // Returns FaviconLoader::FaviconForPageUrl or
+  // FaviconLoader::FaviconForIconUrl depending on the TEST_P param.
+  FaviconAttributes* FaviconForUrl(
+      const GURL& url,
+      FaviconLoader::FaviconAttributesCompletionBlock callback) {
+    if (GetParam() == TEST_PAGE_URL) {
+      return favicon_loader_.FaviconForPageUrl(
+          url, kTestFaviconSize, kTestFaviconSize,
+          /*fallback_to_google_server=*/false, callback);
+    } else {
+      return favicon_loader_.FaviconForIconUrl(url, kTestFaviconSize,
+                                               kTestFaviconSize, callback);
+    }
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(FaviconLoaderTest);
 };
 
 // Tests that image is returned when a favicon is retrieved from
 // LargeIconService.
-TEST_F(FaviconLoaderTest, Favicon) {
+TEST_P(FaviconLoaderTest, FaviconForPageUrl) {
   __block bool callback_executed = false;
   auto confirmation_block = ^(FaviconAttributes* favicon_attributes) {
     callback_executed = true;
     EXPECT_TRUE(favicon_attributes.faviconImage);
   };
-  favicon_loader_.FaviconForUrl(
-      GURL(kTestFaviconURL), kTestFaviconSize, kTestFaviconSize,
-      /*fallback_to_google_server=*/false, confirmation_block);
+  FaviconForUrl(GURL(kTestFaviconURL), confirmation_block);
   EXPECT_TRUE(callback_executed);
 }
 
 // Tests that fallback data is provided when no favicon is retrieved from
 // LargeIconService.
-TEST_F(FaviconLoaderTest, FallbackIcon) {
+TEST_P(FaviconLoaderTest, FallbackIcon) {
   __block bool callback_executed = false;
   auto confirmation_block = ^(FaviconAttributes* favicon_attributes) {
     callback_executed = true;
@@ -104,29 +138,29 @@
     EXPECT_TRUE(favicon_attributes.textColor);
     EXPECT_TRUE(favicon_attributes.backgroundColor);
   };
-  favicon_loader_.FaviconForUrl(
-      GURL(kTestFallbackURL), kTestFaviconSize, kTestFaviconSize,
-      /*fallback_to_google_server=*/false, confirmation_block);
+  FaviconForUrl(GURL(kTestFallbackURL), confirmation_block);
   EXPECT_TRUE(callback_executed);
 }
 
 // Tests that when favicon is in cache, it is returned immediately. The callback
 // should never be executed.
-TEST_F(FaviconLoaderTest, Cache) {
+TEST_P(FaviconLoaderTest, Cache) {
   // Favicon retrieval that should put it in the cache.
-  favicon_loader_.FaviconForUrl(GURL(kTestFaviconURL), kTestFaviconSize,
-                                kTestFaviconSize,
-                                /*fallback_to_google_server=*/false, nil);
+  FaviconForUrl(GURL(kTestFaviconURL), nil);
   __block bool callback_executed = false;
   auto confirmation_block = ^(FaviconAttributes* faviconAttributes) {
     callback_executed = true;
   };
-  FaviconAttributes* attributes_result = favicon_loader_.FaviconForUrl(
-      GURL(kTestFaviconURL), kTestFaviconSize, kTestFaviconSize,
-      /*fallback_to_google_server=*/false, confirmation_block);
+  FaviconAttributes* attributes_result =
+      FaviconForUrl(GURL(kTestFaviconURL), confirmation_block);
   EXPECT_TRUE(attributes_result.faviconImage);
   // Favicon should be returned by cache, so callback should never exectue.
   EXPECT_FALSE(callback_executed);
 }
 
+INSTANTIATE_TEST_SUITE_P(ProgrammaticFaviconLoaderTest,
+                         FaviconLoaderTest,
+                         ::testing::Values(FaviconUrlType::TEST_PAGE_URL,
+                                           FaviconUrlType::TEST_ICON_URL));
+
 }  // namespace
diff --git a/ios/chrome/browser/history/history_backend_client_impl.cc b/ios/chrome/browser/history/history_backend_client_impl.cc
index dc5aaa43..b80906b 100644
--- a/ios/chrome/browser/history/history_backend_client_impl.cc
+++ b/ios/chrome/browser/history/history_backend_client_impl.cc
@@ -47,10 +47,6 @@
   return result;
 }
 
-bool HistoryBackendClientImpl::ShouldReportDatabaseError() {
-  return false;
-}
-
 bool HistoryBackendClientImpl::IsWebSafe(const GURL& url) {
   return url.SchemeIsHTTPOrHTTPS();
 }
diff --git a/ios/chrome/browser/history/history_backend_client_impl.h b/ios/chrome/browser/history/history_backend_client_impl.h
index 001ea74..6295c93 100644
--- a/ios/chrome/browser/history/history_backend_client_impl.h
+++ b/ios/chrome/browser/history/history_backend_client_impl.h
@@ -26,7 +26,6 @@
   // history::HistoryBackendClient implementation.
   bool IsPinnedURL(const GURL& url) override;
   std::vector<history::URLAndTitle> GetPinnedURLs() override;
-  bool ShouldReportDatabaseError() override;
   bool IsWebSafe(const GURL& url) override;
 
   // ModelLoader is used to access bookmarks. May be null during testing.
diff --git a/ios/chrome/browser/infobars/BUILD.gn b/ios/chrome/browser/infobars/BUILD.gn
index abaea0f5..e7cdd228 100644
--- a/ios/chrome/browser/infobars/BUILD.gn
+++ b/ios/chrome/browser/infobars/BUILD.gn
@@ -55,3 +55,24 @@
     "infobar_controller_delegate.h",
   ]
 }
+
+source_set("unit_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  testonly = true
+  sources = [
+    "infobar_badge_tab_helper_unittest.mm",
+  ]
+  deps = [
+    ":badge",
+    ":infobars",
+    "//base/test:test_support",
+    "//ios/chrome/browser/browser_state:test_support",
+    "//ios/chrome/browser/ui/infobars:feature_flags",
+    "//ios/chrome/browser/ui/infobars:infobars_ui",
+    "//ios/chrome/browser/ui/infobars:test_support",
+    "//ios/chrome/browser/ui/infobars/coordinators",
+    "//ios/chrome/test:test_support",
+    "//ios/web/public/test/fakes",
+    "//testing/gtest",
+  ]
+}
diff --git a/ios/chrome/browser/infobars/infobar_badge_tab_helper_delegate.h b/ios/chrome/browser/infobars/infobar_badge_tab_helper_delegate.h
index a1f501e..4ede888 100644
--- a/ios/chrome/browser/infobars/infobar_badge_tab_helper_delegate.h
+++ b/ios/chrome/browser/infobars/infobar_badge_tab_helper_delegate.h
@@ -5,6 +5,8 @@
 #ifndef IOS_CHROME_BROWSER_INFOBARS_INFOBAR_BADGE_TAB_HELPER_DELEGATE_H_
 #define IOS_CHROME_BROWSER_INFOBARS_INFOBAR_BADGE_TAB_HELPER_DELEGATE_H_
 
+#import <Foundation/Foundation.h>
+
 // States for the InfobarBadge.
 typedef NS_OPTIONS(NSUInteger, InfobarBadgeState) {
   // Default state. e.g. The InfobarBanner is being presented, or the Banner has
diff --git a/ios/chrome/browser/infobars/infobar_badge_tab_helper_unittest.mm b/ios/chrome/browser/infobars/infobar_badge_tab_helper_unittest.mm
new file mode 100644
index 0000000..836c553b
--- /dev/null
+++ b/ios/chrome/browser/infobars/infobar_badge_tab_helper_unittest.mm
@@ -0,0 +1,288 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/infobars/infobar_badge_tab_helper.h"
+
+#import "base/test/ios/wait_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#include "ios/chrome/browser/infobars/infobar.h"
+#include "ios/chrome/browser/infobars/infobar_badge_tab_helper_delegate.h"
+#include "ios/chrome/browser/infobars/infobar_container_ios.h"
+#include "ios/chrome/browser/infobars/infobar_manager_impl.h"
+#import "ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.h"
+#import "ios/chrome/browser/ui/infobars/infobar_badge_ui_delegate.h"
+#import "ios/chrome/browser/ui/infobars/infobar_container_consumer.h"
+#import "ios/chrome/browser/ui/infobars/infobar_feature.h"
+#import "ios/chrome/browser/ui/infobars/test_infobar_delegate.h"
+#import "ios/chrome/test/scoped_key_window.h"
+#import "ios/web/public/test/fakes/test_navigation_manager.h"
+#import "ios/web/public/test/fakes/test_web_state.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// InfobarTabHelperDelegate for testing.
+@interface InfobarBadgeTabHelperTestDelegate
+    : NSObject <InfobarBadgeTabHelperDelegate>
+@property(nonatomic, assign) BOOL displayingBadge;
+@end
+
+@implementation InfobarBadgeTabHelperTestDelegate
+@synthesize badgeState = _badgeState;
+- (void)displayBadge:(BOOL)display {
+  self.displayingBadge = display;
+}
+@end
+
+// InfobarBadgeUIDelegate for testing.
+// TODO(crbug.com/892376): Once InfobarContainerMediator stops using TabModel we
+// should be able to use it instead of this fake.
+@interface InfobarBadgeUITestDelegate : NSObject <InfobarBadgeUIDelegate>
+@property(nonatomic, assign) InfobarBadgeTabHelper* infobarBadgeTabHelper;
+@end
+
+@implementation InfobarBadgeUITestDelegate
+- (void)infobarBannerWasDismissed {
+  self.infobarBadgeTabHelper->UpdateBadgeForInfobarBannerDismissed();
+}
+- (void)infobarModalWasPresented {
+  self.infobarBadgeTabHelper->UpdateBadgeForInfobarModalPresented();
+}
+- (void)infobarModalWasDismissed {
+  self.infobarBadgeTabHelper->UpdateBadgeForInfobarModalDismissed();
+}
+- (void)infobarWasAccepted {
+  self.infobarBadgeTabHelper->UpdateBadgeForInfobarAccepted();
+}
+@end
+
+// Fake Infobar Container.
+@interface FakeInfobarContainerCoordinator : NSObject <InfobarContainerConsumer>
+@property(nonatomic, strong) UIViewController* baseViewController;
+@property(nonatomic, strong) InfobarCoordinator* infobarCoordinator;
+@property(nonatomic, assign) BOOL bannerWasDismissed;
+- (void)presentModal;
+- (void)destroyInfobar;
+- (void)removeInfobarView;
+@end
+
+@implementation FakeInfobarContainerCoordinator
+- (void)addInfoBarWithDelegate:(id<InfobarUIDelegate>)infoBarDelegate
+                      position:(NSInteger)position {
+  self.infobarCoordinator = static_cast<InfobarCoordinator*>(infoBarDelegate);
+  self.infobarCoordinator.baseViewController = self.baseViewController;
+  [self.infobarCoordinator start];
+  [self.infobarCoordinator presentInfobarBannerAnimated:NO completion:nil];
+}
+
+- (void)setUserInteractionEnabled:(BOOL)enabled {
+}
+- (void)updateLayoutAnimated:(BOOL)animated {
+}
+- (void)presentModal {
+  [self.infobarCoordinator presentInfobarModal];
+}
+- (void)dismissBanner {
+  [self.infobarCoordinator dismissInfobarBanner:self
+                                       animated:NO
+                                     completion:^{
+                                       self.bannerWasDismissed = YES;
+                                     }];
+}
+- (void)destroyInfobar {
+  [self.infobarCoordinator detachView];
+}
+- (void)removeInfobarView {
+  [self.infobarCoordinator removeView];
+}
+@end
+
+// Test fixture for testing InfobarBadgeTabHelper.
+class InfobarBadgeTabHelperTest : public PlatformTest {
+ protected:
+  InfobarBadgeTabHelperTest()
+      : infobar_badge_tab_delegate_(
+            [[InfobarBadgeTabHelperTestDelegate alloc] init]),
+        browser_state_(TestChromeBrowserState::Builder().Build()),
+        infobar_container_coordinator_(
+            [[FakeInfobarContainerCoordinator alloc] init]),
+        infobar_badge_ui_delegate_([[InfobarBadgeUITestDelegate alloc] init]) {
+    // Enable kInfobarUIReboot flag.
+    feature_list_.InitAndEnableFeature(kInfobarUIReboot);
+
+    // Setup navigation manager. Needed for InfobarManager.
+    std::unique_ptr<web::TestNavigationManager> navigation_manager =
+        std::make_unique<web::TestNavigationManager>();
+    navigation_manager->SetBrowserState(browser_state_.get());
+    navigation_manager_ = navigation_manager.get();
+    web_state_.SetNavigationManager(std::move(navigation_manager));
+    web_state_.SetBrowserState(browser_state_.get());
+
+    // Create the InfobarManager for web_state_.
+    InfoBarManagerImpl::CreateForWebState(&web_state_);
+
+    // Create the InfobarBadgeTabHelper for web_state_ and set its delegate.
+    InfobarBadgeTabHelper::CreateForWebState(&web_state_);
+    tab_helper()->SetDelegate(infobar_badge_tab_delegate_);
+
+    // Configure the fake InfobarContainerCoordinator, and set its baseVC as
+    // rootVC.
+    infobar_container_coordinator_.baseViewController =
+        [[UIViewController alloc] init];
+    [scoped_key_window_.Get()
+        setRootViewController:infobar_container_coordinator_
+                                  .baseViewController];
+
+    // Configure the fake InfobarBadgeUIDelegate.
+    infobar_badge_ui_delegate_.infobarBadgeTabHelper = tab_helper();
+
+    // Create InfobarContainerIOS.
+    infobar_container_model_.reset(
+        new InfoBarContainerIOS(infobar_container_coordinator_, nil));
+    infobar_container_model_->ChangeInfoBarManager(GetInfobarManager());
+
+    // Create and configure the InfobarCoordinator.
+    TestInfoBarDelegate* test_infobar_delegate =
+        new TestInfoBarDelegate(@"Title");
+    InfobarConfirmCoordinator* coordinator = [[InfobarConfirmCoordinator alloc]
+        initWithInfoBarDelegate:test_infobar_delegate];
+    coordinator.browserState = browser_state_.get();
+    coordinator.badgeDelegate = infobar_badge_ui_delegate_;
+
+    // Create the InfobarIOS using the InfobarCoordinator and add it to the
+    // InfobarManager, this will trigger the Infobar presentation.
+    std::unique_ptr<ConfirmInfoBarDelegate> infobar_delegate =
+        std::unique_ptr<ConfirmInfoBarDelegate>(test_infobar_delegate);
+    GetInfobarManager()->AddInfoBar(
+        std::make_unique<InfoBarIOS>(coordinator, std::move(infobar_delegate)));
+  }
+
+  // Returns InfobarBadgeTabHelper attached to web_state_.
+  InfobarBadgeTabHelper* tab_helper() {
+    return InfobarBadgeTabHelper::FromWebState(&web_state_);
+  }
+
+  // Returns InfoBarManager attached to web_state_.
+  infobars::InfoBarManager* GetInfobarManager() {
+    return InfoBarManagerImpl::FromWebState(&web_state_);
+  }
+
+  base::test::ScopedTaskEnvironment environment_;
+  InfobarBadgeTabHelperTestDelegate* infobar_badge_tab_delegate_;
+  std::unique_ptr<ios::ChromeBrowserState> browser_state_;
+  FakeInfobarContainerCoordinator* infobar_container_coordinator_;
+  InfobarBadgeUITestDelegate* infobar_badge_ui_delegate_;
+  base::test::ScopedFeatureList feature_list_;
+  web::TestWebState web_state_;
+  web::TestNavigationManager* navigation_manager_;
+  std::unique_ptr<InfoBarContainerIOS> infobar_container_model_;
+  ScopedKeyWindow scoped_key_window_;
+};
+
+// Test each UpdateBadge public method individually.
+TEST_F(InfobarBadgeTabHelperTest, TestInfobarBadgeStates) {
+  // Test that dismissing the Banner unselects the badge.
+  tab_helper()->UpdateBadgeForInfobarBannerDismissed();
+  EXPECT_FALSE(infobar_badge_tab_delegate_.badgeState &
+               InfobarBadgeStateSelected);
+  // Test that dismissing the Modal unselects the badge.
+  tab_helper()->UpdateBadgeForInfobarModalDismissed();
+  EXPECT_FALSE(infobar_badge_tab_delegate_.badgeState &
+               InfobarBadgeStateSelected);
+  // Test that presenting the Modal selects the badge.
+  tab_helper()->UpdateBadgeForInfobarModalPresented();
+  EXPECT_TRUE(infobar_badge_tab_delegate_.badgeState &
+              InfobarBadgeStateSelected);
+  // Test that accepting the Infobar sets the badge to accepted state.
+  tab_helper()->UpdateBadgeForInfobarAccepted();
+  EXPECT_TRUE(infobar_badge_tab_delegate_.badgeState &
+              InfobarBadgeStateAccepted);
+}
+
+// Tests that dismissing or presenting the Modal doesn't change the previously
+// accepted state.
+TEST_F(InfobarBadgeTabHelperTest, TestInfobarBadgeAcceptedState) {
+  // Accept the Infobar.
+  tab_helper()->UpdateBadgeForInfobarAccepted();
+  EXPECT_TRUE(infobar_badge_tab_delegate_.badgeState &
+              InfobarBadgeStateAccepted);
+  // Test badge is still "accepted" after Modal presentation.
+  tab_helper()->UpdateBadgeForInfobarModalPresented();
+  EXPECT_TRUE(infobar_badge_tab_delegate_.badgeState &
+              InfobarBadgeStateAccepted);
+  EXPECT_TRUE(infobar_badge_tab_delegate_.badgeState &
+              InfobarBadgeStateSelected);
+  // Test badge is still "accepted" after Modal dismissal.
+  tab_helper()->UpdateBadgeForInfobarModalDismissed();
+  EXPECT_TRUE(infobar_badge_tab_delegate_.badgeState &
+              InfobarBadgeStateAccepted);
+  EXPECT_FALSE(infobar_badge_tab_delegate_.badgeState &
+               InfobarBadgeStateSelected);
+}
+
+// Test the initial badge state once the banner has been presented.
+TEST_F(InfobarBadgeTabHelperTest, TestInfobarBadgeStateOnBannerPresentation) {
+  EXPECT_TRUE(infobar_badge_tab_delegate_.displayingBadge);
+  EXPECT_TRUE(infobar_badge_tab_delegate_.badgeState &
+              InfobarBadgeStateSelected);
+}
+
+// Tests that once the Modal is presented the default state is
+// InfobarBadgeStateSelected.
+TEST_F(InfobarBadgeTabHelperTest, TestInfobarBadgeStateOnModalPresentation) {
+  [infobar_container_coordinator_ dismissBanner];
+  EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+      base::test::ios::kWaitForUIElementTimeout, ^bool {
+        return infobar_container_coordinator_.bannerWasDismissed;
+      }));
+  [infobar_container_coordinator_ presentModal];
+  EXPECT_TRUE(infobar_badge_tab_delegate_.badgeState &
+              InfobarBadgeStateSelected);
+  EXPECT_TRUE(infobar_badge_tab_delegate_.displayingBadge);
+}
+
+// Tests that the InfobarBadge is still being displayed after dismissing the
+// InfobarBanner.
+TEST_F(InfobarBadgeTabHelperTest, TestInfobarBadgeOnBannerDismissal) {
+  [infobar_container_coordinator_ dismissBanner];
+  EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+      base::test::ios::kWaitForUIElementTimeout, ^bool {
+        return infobar_container_coordinator_.bannerWasDismissed;
+      }));
+  EXPECT_TRUE(infobar_badge_tab_delegate_.displayingBadge);
+  EXPECT_FALSE(infobar_badge_tab_delegate_.badgeState &
+               InfobarBadgeStateSelected);
+}
+
+// Test that the Accepted badge state remains after dismissing the
+// InfobarBanner.
+TEST_F(InfobarBadgeTabHelperTest, TestInfobarBadgeOnBannerAccepted) {
+  EXPECT_FALSE(infobar_badge_tab_delegate_.badgeState &
+               InfobarBadgeStateAccepted);
+  tab_helper()->UpdateBadgeForInfobarAccepted();
+  [infobar_container_coordinator_ dismissBanner];
+  EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+      base::test::ios::kWaitForUIElementTimeout, ^bool {
+        return infobar_container_coordinator_.bannerWasDismissed;
+      }));
+  EXPECT_TRUE(infobar_badge_tab_delegate_.badgeState &
+              InfobarBadgeStateAccepted);
+}
+
+// Test that removing the InfobarView doesn't stop displaying the badge.
+TEST_F(InfobarBadgeTabHelperTest, TestInfobarBadgeOnInfobarViewRemoval) {
+  [infobar_container_coordinator_ removeInfobarView];
+  EXPECT_TRUE(infobar_badge_tab_delegate_.displayingBadge);
+}
+
+// Test that destroying the InfobarView stops displaying the badge.
+TEST_F(InfobarBadgeTabHelperTest, TestInfobarBadgeOnInfobarDestroyal) {
+  [infobar_container_coordinator_ destroyInfobar];
+  EXPECT_FALSE(infobar_badge_tab_delegate_.displayingBadge);
+}
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
index a2ab6c1..e4c4bba 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -201,11 +201,6 @@
     "Transmit rich form/field metadata when querying the autofill server. "
     "This feature only works on the Canary and Dev channels.";
 
-const char kBrowserContainerFullscreenName[] = "Browser Container Fullscreen";
-const char kBrowserContainerFullscreenDescription[] =
-    "When enabled, the BrowserContainer is fullscreen. No UI change should be "
-    "visible.";
-
 const char kBrowserContainerContainsNTPName[] = "Browser Container NTP";
 const char kBrowserContainerContainsNTPDescription[] =
     "When enabled, the BrowserContainer contains the NTP directly, rather than"
@@ -356,11 +351,6 @@
 const char kOnlyNewPasswordFormParsingDescription[] =
     "The old password form parsing is disabled";
 
-const char kOutOfWebFullscreenName[] = "Fullscreen implementation out of web";
-const char kOutOfWebFullscreenDescription[] =
-    "Use the fullscreen implementation living outside of web. Disable the one "
-    "in web.";
-
 const char kPasswordGenerationName[] = "Password generation suggestion";
 const char kPasswordGenerationDescription[] =
     "Add 'Suggest Password' in suggestion list for form completion.";
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h
index 3e10148c..f96fc53 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -152,10 +152,6 @@
 extern const char kAutofillRichMetadataQueriesName[];
 extern const char kAutofillRichMetadataQueriesDescription[];
 
-// Title and description for the flag to make browser container fullscreen.
-extern const char kBrowserContainerFullscreenName[];
-extern const char kBrowserContainerFullscreenDescription[];
-
 // Title and description for the flag to make browser container contain the NTP
 // directly.
 extern const char kBrowserContainerContainsNTPName[];
@@ -287,11 +283,6 @@
 extern const char kOnlyNewPasswordFormParsingName[];
 extern const char kOnlyNewPasswordFormParsingDescription[];
 
-// Title and description for the flag to control the out of web implementation
-// of fullscreen.
-extern const char kOutOfWebFullscreenName[];
-extern const char kOutOfWebFullscreenDescription[];
-
 // Title and description for the flag to enable password generation.
 extern const char kPasswordGenerationName[];
 extern const char kPasswordGenerationDescription[];
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm
index 7593199..d2760d4 100644
--- a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm
+++ b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm
@@ -58,7 +58,6 @@
 #include "ios/chrome/browser/sync/device_info_sync_service_factory.h"
 #include "ios/chrome/browser/sync/profile_sync_service_factory.h"
 #include "ios/chrome/browser/tab_parenting_global_observer.h"
-#import "ios/chrome/browser/tabs/tab_model_list.h"
 #include "ios/chrome/browser/translate/translate_ranker_metrics_provider.h"
 #include "ios/chrome/common/channel_info.h"
 #include "ios/web/public/web_thread.h"
@@ -204,12 +203,8 @@
       std::make_unique<metrics::NetworkMetricsProvider>(
           base::BindRepeating(&GetNetworkConnectionTrackerAsync)));
 
-  // Currently, we configure OmniboxMetricsProvider to not log events to UMA
-  // if there is a single incognito session visible. In the future, it may
-  // be worth revisiting this to still log events from non-incognito sessions.
   metrics_service_->RegisterMetricsProvider(
-      std::make_unique<OmniboxMetricsProvider>(
-          base::Bind(&TabModelList::IsOffTheRecordSessionActive)));
+      std::make_unique<OmniboxMetricsProvider>());
 
   {
     auto stability_metrics_provider =
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm b/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm
index 51a0f4f4..2b395c2 100644
--- a/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm
+++ b/ios/chrome/browser/ui/autofill/form_input_accessory_mediator.mm
@@ -304,6 +304,7 @@
   }
   _lastSeenParams = params;
   _hasLastSeenParams = YES;
+  [self.consumer prepareToShowSuggestions];
   [self retrieveSuggestionsForForm:params webState:webState];
 }
 
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.mm b/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.mm
index b80db987..38a6f1b 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/password_mediator.mm
@@ -262,7 +262,7 @@
 - (FaviconAttributes*)faviconForURL:(const GURL&)URL
                          completion:(void (^)(FaviconAttributes*))completion {
   DCHECK(completion);
-  FaviconAttributes* cachedAttributes = self.faviconLoader->FaviconForUrl(
+  FaviconAttributes* cachedAttributes = self.faviconLoader->FaviconForPageUrl(
       URL, gfx::kFaviconSize, kMinFaviconSizePt,
       /*fallback_to_google_server=*/false, completion);
   DCHECK(cachedAttributes);
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
index 2ec8515..98b6464 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -560,7 +560,7 @@
       [BookmarkHomeSharedState desiredFaviconSizePt];
   CGFloat minFaviconSizeInPoints = [BookmarkHomeSharedState minFaviconSizePt];
 
-  FaviconAttributes* cachedAttributes = self.faviconLoader->FaviconForUrl(
+  FaviconAttributes* cachedAttributes = self.faviconLoader->FaviconForPageUrl(
       blockURL, desiredFaviconSizeInPoints, minFaviconSizeInPoints,
       /*fallback_to_google_server=*/fallbackToGoogleServer, faviconLoadedBlock);
   DCHECK(cachedAttributes);
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index f7a7925..3afa8b8 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -615,8 +615,6 @@
 // The webState of the active tab.
 @property(nonatomic, readonly) web::WebState* currentWebState;
 
-// Whether the browser container should be the full bounds of self.view.
-@property(nonatomic, readonly) BOOL usesFullscreenContainer;
 // Whether the safe area insets should be used to adjust the viewport.
 @property(nonatomic, readonly) BOOL usesSafeInsetsForViewportAdjustments;
 
@@ -1078,9 +1076,6 @@
   }
 
   CGFloat statusBarOffset = 0;
-  if (!self.usesFullscreenContainer) {
-    statusBarOffset = StatusBarHeight();
-  }
   return height - statusBarOffset;
 }
 
@@ -1088,12 +1083,6 @@
   return self.tabModel.currentTab.webState;
 }
 
-- (BOOL)usesFullscreenContainer {
-  return base::FeatureList::IsEnabled(
-             web::features::kBrowserContainerFullscreen) ||
-         self.usesSafeInsetsForViewportAdjustments;
-}
-
 - (BOOL)usesSafeInsetsForViewportAdjustments {
   fullscreen::features::ViewportAdjustmentExperiment viewportExperiment =
       fullscreen::features::GetActiveViewportExperiment();
@@ -1414,6 +1403,11 @@
       urlLoadingNotifier->RemoveObserver(_URLLoadingObserverBridge.get());
   }
 
+  // Uninstall delegates so that any delegate callbacks triggered by subsequent
+  // WebStateDestroyed() signals are not handled.
+  for (NSUInteger index = 0; index < self.tabModel.count; ++index)
+    [self uninstallDelegatesForTab:[self.tabModel tabAtIndex:index]];
+
   // Disconnect child coordinators.
   [_activityServiceCoordinator disconnect];
   [self.popupMenuCoordinator stop];
@@ -1501,10 +1495,6 @@
 
 - (void)viewDidLoad {
   CGRect initialViewsRect = self.view.bounds;
-  if (!self.usesFullscreenContainer) {
-    initialViewsRect.origin.y += StatusBarHeight();
-    initialViewsRect.size.height -= StatusBarHeight();
-  }
   UIViewAutoresizing initialViewAutoresizing =
       UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
 
@@ -2386,11 +2376,6 @@
   // Adjust the content area to be under the toolbar, for fullscreen or below
   // the toolbar is not fullscreen.
   CGRect contentFrame = self.contentArea.frame;
-  if (!self.usesFullscreenContainer) {
-    CGFloat marginWithHeader = StatusBarHeight();
-    contentFrame.size.height = CGRectGetMaxY(contentFrame) - marginWithHeader;
-    contentFrame.origin.y = marginWithHeader;
-  }
   self.contentArea.frame = contentFrame;
 
   // Attach the typing shield to the content area but have it hidden.
@@ -2415,10 +2400,7 @@
     // Make new content visible, resizing it first as the orientation may
     // have changed from the last time it was displayed.
     [self viewForTab:tab].frame = self.contentArea.bounds;
-    if (base::FeatureList::IsEnabled(
-            web::features::kBrowserContainerFullscreen)) {
-      [_toolbarUIUpdater updateState];
-    }
+    [_toolbarUIUpdater updateState];
     NewTabPageTabHelper* NTPHelper =
         NewTabPageTabHelper::FromWebState(tab.webState);
     if (NTPHelper && NTPHelper->IsActive()) {
@@ -2561,9 +2543,7 @@
   NewTabPageTabHelper* NTPHelper = NewTabPageTabHelper::FromWebState(webState);
   if (!NTPHelper || !NTPHelper->IsActive())
     return CGRectZero;
-  if (base::FeatureList::IsEnabled(
-          web::features::kBrowserContainerFullscreen) &&
-      !IsRegularXRegularSizeClass())
+  if (!IsRegularXRegularSizeClass())
     return self.contentArea.bounds;
   // NTP expects to be laid out behind the bottom toolbar.  It uses
   // |contentInset| to push content above the toolbar.
@@ -2947,8 +2927,6 @@
   // WebState view's superview is used as the base snapshot view.  The content
   // area is |headerHeight| from the top of its superview, so snapshots should
   // be inset from this amount.
-  bool outOfWeb =
-      base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen);
   bool usesContentInset = ios::GetChromeBrowserProvider()
                               ->GetFullscreenProvider()
                               ->IsInitialized() ||
@@ -2958,7 +2936,7 @@
   if ([self canShowTabStrip] && isNTPActive) {
     return UIEdgeInsetsZero;
   }
-  if (isNTPActive || (outOfWeb && !usesContentInset)) {
+  if (isNTPActive || !usesContentInset) {
     return UIEdgeInsetsMake(self.headerHeight, 0.0, self.bottomToolbarHeight,
                             0.0);
   }
@@ -3012,14 +2990,12 @@
   NewTabPageTabHelper* NTPHelper = NewTabPageTabHelper::FromWebState(webState);
   if (NTPHelper && NTPHelper->IsActive()) {
     return _ntpCoordinatorsForWebStates[webState].viewController.view;
-  } else if (base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen)) {
-    // The webstate view is getting resized because of fullscreen. Using its
-    // superview ensure that we have a view with a with a consistent size.
-    if (webState->GetView().superview)
-      return webState->GetView().superview;
   }
-  DCHECK(webState->GetView());
-  return webState->GetView();
+  UIView* webStateView = webState->GetView();
+  DCHECK(webStateView);
+  // |webStateView| is resized because of fullscreen. Using its superview when
+  // possible ensures that the snapshot has a consistent size.
+  return webStateView.superview ?: webStateView;
 }
 
 #pragma mark - SnapshotGeneratorDelegate helpers
@@ -3633,8 +3609,7 @@
 }
 
 - (CGFloat)overscrollHeaderHeight {
-  return self.headerHeight +
-         (self.usesFullscreenContainer ? 0 : StatusBarHeight());
+  return self.headerHeight;
 }
 
 #pragma mark - CRWNativeContentProvider methods
@@ -3751,33 +3726,25 @@
 #pragma mark - ToolbarHeightProviderForFullscreen
 
 - (CGFloat)collapsedTopToolbarHeight {
-  if (base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen) &&
-      IsVisibleURLNewTabPage(self.currentWebState) && ![self canShowTabStrip]) {
+  if (IsVisibleURLNewTabPage(self.currentWebState) && ![self canShowTabStrip]) {
     // When the NTP is displayed in a horizontally compact environment, the top
     // toolbars are hidden.
     return 0;
   }
-  CGFloat collapsedToolbarHeight =
-      ToolbarCollapsedHeight(self.traitCollection.preferredContentSizeCategory);
-  // |collapsedToolbarHeight| describes the distance past the top safe area.  If
-  // the browser container view is laid out using the full screen, it extends
-  // past the status bar, so that additional overlap is added here.
-  if (self.usesFullscreenContainer) {
-    collapsedToolbarHeight += self.view.safeAreaInsets.top;
-  }
-  return collapsedToolbarHeight;
+  return self.view.safeAreaInsets.top +
+         ToolbarCollapsedHeight(
+             self.traitCollection.preferredContentSizeCategory);
 }
 
 - (CGFloat)expandedTopToolbarHeight {
-  if (base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen) &&
-      IsVisibleURLNewTabPage(self.currentWebState) && ![self canShowTabStrip]) {
+  if (IsVisibleURLNewTabPage(self.currentWebState) && ![self canShowTabStrip]) {
     // When the NTP is displayed in a horizontally compact environment, the top
     // toolbars are hidden.
     return 0;
   }
   return [self primaryToolbarHeightWithInset] +
          ([self canShowTabStrip] ? self.tabStripView.frame.size.height : 0.0) +
-         (self.usesFullscreenContainer ? self.headerOffset : 0.0);
+         self.headerOffset;
 }
 
 - (CGFloat)bottomToolbarHeight {
@@ -4538,17 +4505,7 @@
     [self.contentArea addSubview:toolbarSnapshot];
     newPage = [self viewForTab:tab];
     newPage.userInteractionEnabled = NO;
-    if (base::FeatureList::IsEnabled(
-            web::features::kBrowserContainerFullscreen)) {
-      newPage.frame = self.view.bounds;
-    } else {
-      // Compute a frame for the new page by removing the status bar height
-      // from the bounds of |self.view|.
-      CGRect viewBounds, remainder;
-      CGRectDivide(self.view.bounds, &remainder, &viewBounds, StatusBarHeight(),
-                   CGRectMinYEdge);
-      newPage.frame = viewBounds;
-    }
+    newPage.frame = self.view.bounds;
   } else {
     [self viewForTab:tab].frame = self.contentArea.bounds;
     // Setting the frame here doesn't trigger a layout pass. Trigger it manually
@@ -4585,15 +4542,8 @@
 
   CGPoint origin = [self lastTapPoint];
 
-  // The animation will have the same frame as |self|, minus the status bar,
-  // so shift it down and reduce its height accordingly.
-  CGRect frame = self.view.bounds;
-  if (!self.usesFullscreenContainer ||
-      !base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen)) {
-    frame.origin.y += StatusBarHeight();
-    frame.size.height -= StatusBarHeight();
-  }
-  frame = [self.contentArea convertRect:frame fromView:self.view];
+  CGRect frame = [self.contentArea convertRect:self.view.bounds
+                                      fromView:self.view];
   ForegroundTabAnimationView* animatedView =
       [[ForegroundTabAnimationView alloc] initWithFrame:frame];
   animatedView.contentView = newPage;
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm
index b5709c7..cbd1445 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm
@@ -209,14 +209,6 @@
                                       forProtocol:@protocol(PageInfoCommands)];
     id mockApplicationCommandHandler =
         OCMProtocolMock(@protocol(ApplicationCommands));
-    bvc_ = [[BrowserViewController alloc]
-                      initWithTabModel:tabModel_
-                          browserState:chrome_browser_state_.get()
-                     dependencyFactory:factory
-            applicationCommandEndpoint:mockApplicationCommandHandler
-                     commandDispatcher:command_dispatcher_
-        browserContainerViewController:[[BrowserContainerViewController alloc]
-                                           init]];
 
     // Stub methods for TabModel.
     NSUInteger tabCount = 1;
@@ -235,18 +227,25 @@
     web::WebState::CreateParams params(chrome_browser_state_.get());
     std::unique_ptr<web::WebState> webState = web::WebState::Create(params);
     webStateImpl_.reset(static_cast<web::WebStateImpl*>(webState.release()));
+    AttachTabHelpers(webStateImpl_.get(), NO);
     [currentTab setWebState:webStateImpl_.get()];
 
-    SnapshotTabHelper::CreateForWebState(webStateImpl_.get(),
-                                         [[NSUUID UUID] UUIDString]);
-    SadTabTabHelper::CreateForWebState(webStateImpl_.get());
-
     // Load TemplateURLService.
     TemplateURLService* template_url_service =
         ios::TemplateURLServiceFactory::GetForBrowserState(
             chrome_browser_state_.get());
     template_url_service->Load();
 
+    // Instantiate the BVC.
+    bvc_ = [[BrowserViewController alloc]
+                      initWithTabModel:tabModel_
+                          browserState:chrome_browser_state_.get()
+                     dependencyFactory:factory
+            applicationCommandEndpoint:mockApplicationCommandHandler
+                     commandDispatcher:command_dispatcher_
+        browserContainerViewController:[[BrowserContainerViewController alloc]
+                                           init]];
+
     // Force the view to load.
     UIWindow* window = [[UIWindow alloc] initWithFrame:CGRectZero];
     [window addSubview:[bvc_ view]];
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
index 074b558..f25bdc6 100644
--- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -258,6 +258,7 @@
     "//ios/chrome/browser/ui/tab_grid:egtest_support",
     "//ios/chrome/browser/ui/toolbar/buttons",
     "//ios/chrome/browser/ui/toolbar/public",
+    "//ios/chrome/test:eg_test_support",
     "//ios/chrome/test:test_support",
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/base:base",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
index 6084acb6..f6b51c58 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
@@ -76,12 +76,8 @@
 CGFloat doodleTopMargin(BOOL toolbarPresent, CGFloat topInset) {
   if (!IsCompactWidth() && !IsCompactHeight())
     return kDoodleTopMarginRegularXRegular;
-  if (base::FeatureList::IsEnabled(
-          web::features::kBrowserContainerFullscreen) &&
-      base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen) &&
-      !base::FeatureList::IsEnabled(kBrowserContainerContainsNTP)) {
+  if (!base::FeatureList::IsEnabled(kBrowserContainerContainsNTP))
     topInset = StatusBarHeight();
-  }
   return topInset + kDoodleTopMarginOther +
          AlignValueToPixel(kDoodleScaledTopMarginOther *
                            SystemSuggestedFontSizeMultiplier());
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
index b39b7dd..c9dae9e6 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -267,7 +267,6 @@
   [super viewDidAppear:animated];
   // Resize the collection as it might have been rotated while not being
   // presented (e.g. rotation on stack view).
-  [self correctMissingSafeArea];
   [self updateConstraints];
 }
 
@@ -321,13 +320,11 @@
     [self.headerSynchronizer updateFakeOmniboxOnCollectionScroll];
     [self.headerSynchronizer updateConstraints];
   }
-  [self correctMissingSafeArea];
   [self updateOverscrollActionsState];
 }
 
 - (void)viewSafeAreaInsetsDidChange {
   [super viewSafeAreaInsetsDidChange];
-  [self correctMissingSafeArea];
   [self.headerSynchronizer
       updateFakeOmniboxOnNewWidth:self.collectionView.bounds.size.width];
   [self.headerSynchronizer updateConstraints];
@@ -640,24 +637,6 @@
 
 #pragma mark - Private
 
-// TODO(crbug.com/826369) Remove this when the NTP is conatined by the BVC
-// and removed from native content.  As a part of native content, the NTP is
-// contained by a view controller that is inset from safeArea.top.  Even
-// though content suggestions appear under the top safe area, they are blocked
-// by the browser container view controller.
-- (void)correctMissingSafeArea {
-  if (base::FeatureList::IsEnabled(web::features::kBrowserContainerFullscreen))
-    return;
-
-  UIEdgeInsets missingTop = UIEdgeInsetsZero;
-  // During the new tab animation the browser container view controller
-  // actually matches the browser view controller frame, so safe area does
-  // work, so be sure to check the parent view controller offset.
-  if (self.parentViewController.view.frame.origin.y == StatusBarHeight())
-    missingTop = UIEdgeInsetsMake(StatusBarHeight(), 0, 0, 0);
-  self.additionalSafeAreaInsets = missingTop;
-}
-
 - (void)handleLongPress:(UILongPressGestureRecognizer*)gestureRecognizer {
   if (self.editor.editing ||
       gestureRecognizer.state != UIGestureRecognizerStateBegan) {
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_test_utils.h b/ios/chrome/browser/ui/content_suggestions/ntp_home_test_utils.h
index 9b0889bd..768a36d 100644
--- a/ios/chrome/browser/ui/content_suggestions/ntp_home_test_utils.h
+++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_test_utils.h
@@ -5,12 +5,13 @@
 #ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_NTP_HOME_TEST_UTILS_H_
 #define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_NTP_HOME_TEST_UTILS_H_
 
-#import <EarlGrey/EarlGrey.h>
 #import <UIKit/UIKit.h>
 
 #include "components/ntp_snippets/callbacks.h"
 #include "url/gurl.h"
 
+@protocol GREYMatcher;
+
 namespace ntp_home {
 // Returns the view corresponding to the ContentSuggestionsViewController.
 // Returns nil if it is not in the view hierarchy.
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_test_utils.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_test_utils.mm
index 74151e9..0a0731b 100644
--- a/ios/chrome/browser/ui/content_suggestions/ntp_home_test_utils.mm
+++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_test_utils.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/ui/content_suggestions/ntp_home_test_utils.h"
 
+#import <EarlGrey/EarlGrey.h>
+
 #include <string>
 
 #include "base/callback.h"
diff --git a/ios/chrome/browser/ui/download/BUILD.gn b/ios/chrome/browser/ui/download/BUILD.gn
index 852cc5f..58d249e 100644
--- a/ios/chrome/browser/ui/download/BUILD.gn
+++ b/ios/chrome/browser/ui/download/BUILD.gn
@@ -123,6 +123,7 @@
     "//ios/chrome/browser/download:test_support",
     "//ios/chrome/browser/ui/browser_view",
     "//ios/chrome/browser/ui/util",
+    "//ios/chrome/test:eg_test_support",
     "//ios/chrome/test:test_support",
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_content_adjustment_util.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_content_adjustment_util.mm
index 3cdfa63a..0470648 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_content_adjustment_util.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_content_adjustment_util.mm
@@ -19,13 +19,4 @@
   DCHECK(model);
   CGFloat topPadding = model->current_toolbar_insets().top;
   proxy.scrollViewProxy.contentOffset = CGPointMake(0, -topPadding);
-  if (!base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen)) {
-    // With the fullscreen implementation living outside of web, this is no
-    // longer needed.
-    CGFloat bottomPadding = model->progress() * model->GetBottomToolbarHeight();
-    UIEdgeInsets contentInset = proxy.contentInset;
-    contentInset.top = topPadding;
-    contentInset.bottom = bottomPadding;
-    proxy.contentInset = contentInset;
-  }
 }
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
index 0baa384..57c4117 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
@@ -114,14 +114,10 @@
       yOffset = -56.0;
     }
   }
-  if (base::FeatureList::IsEnabled(
-          web::features::kBrowserContainerFullscreen) &&
-      base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen) &&
-      base::ios::IsRunningOnIOS12OrLater()) {
-    // In the fullscreen browser implementation, the safe area is included in
-    // the top inset as well as the toolbar heights.  Due to crbug.com/903635,
-    // however, this only occurs on iOS 12; pdf rendering does not correctly
-    // account for the safe area on iOS 11.
+  if (@available(iOS 12, *)) {
+    // The safe area is included in the top inset as well as the toolbar
+    // heights.  Due to crbug.com/903635, however, this only occurs on iOS 12;
+    // pdf rendering does not correctly account for the safe area on iOS 11.
     yOffset -=
         chrome_test_util::GetCurrentWebState()->GetView().safeAreaInsets.top;
   }
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer.mm
index e083962..05f0c1e 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer.mm
@@ -29,10 +29,6 @@
 @synthesize webState = _webState;
 
 - (instancetype)initWithModel:(FullscreenModel*)model {
-  // This can only be instantiated when the feature is enabled.
-  if (!base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen))
-    return nil;
-
   self = [super init];
   if (self) {
     _model = model;
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer_unittest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer_unittest.mm
index 5a2d43e..6dd51b1a 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer_unittest.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer_unittest.mm
@@ -27,9 +27,6 @@
 class FullscreenWebViewResizerTest : public PlatformTest {
  public:
   FullscreenWebViewResizerTest() {
-    // Make sure the features is enabled.
-    _features.InitAndEnableFeature(web::features::kOutOfWebFullscreen);
-
     // FullscreenModel setup.
     _model.SetExpandedToolbarHeight(kTopToolbarExpandedHeight);
     _model.SetCollapsedToolbarHeight(kTopToolbarCollapsedHeight);
diff --git a/ios/chrome/browser/ui/history/history_mediator.mm b/ios/chrome/browser/ui/history/history_mediator.mm
index 2c7d267..dcd1f833 100644
--- a/ios/chrome/browser/ui/history/history_mediator.mm
+++ b/ios/chrome/browser/ui/history/history_mediator.mm
@@ -42,7 +42,7 @@
 
 - (FaviconAttributes*)faviconForURL:(const GURL&)URL
                          completion:(void (^)(FaviconAttributes*))completion {
-  FaviconAttributes* cachedAttributes = self.faviconLoader->FaviconForUrl(
+  FaviconAttributes* cachedAttributes = self.faviconLoader->FaviconForPageUrl(
       URL, kFaviconWidthHeight, kFaviconMinWidthHeight,
       /*fallback_to_google_server=*/false, ^(FaviconAttributes* attributes) {
         completion(attributes);
diff --git a/ios/chrome/browser/ui/infobars/BUILD.gn b/ios/chrome/browser/ui/infobars/BUILD.gn
index a2b6303..2c41579 100644
--- a/ios/chrome/browser/ui/infobars/BUILD.gn
+++ b/ios/chrome/browser/ui/infobars/BUILD.gn
@@ -55,7 +55,7 @@
   sources = [
     "confirm_infobar_view.h",
     "confirm_infobar_view.mm",
-    "infobar_badge_ui_delegate",
+    "infobar_badge_ui_delegate.h",
     "infobar_constants.h",
     "infobar_constants.mm",
     "infobar_container_consumer.h",
diff --git a/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn b/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn
index f68050c..72091d07 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn
+++ b/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn
@@ -25,5 +25,6 @@
     "//ios/chrome/browser/ui/infobars/modals",
     "//ios/chrome/browser/ui/infobars/presentation",
     "//ios/chrome/browser/ui/table_view",
+    "//ios/chrome/browser/ui/util",
   ]
 }
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.h b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.h
index 384eaa2e..113e599 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.h
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.h
@@ -43,7 +43,8 @@
                                    browser:(Browser*)browser NS_UNAVAILABLE;
 
 // Present the InfobarBanner using |self.baseViewController|.
-- (void)presentInfobarBanner;
+- (void)presentInfobarBannerAnimated:(BOOL)animated
+                          completion:(ProceduralBlock)completion;
 
 // Present the InfobarModal using |self.baseViewController|.
 - (void)presentInfobarModal;
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm
index 37242f46..e29843c 100644
--- a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm
+++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.mm
@@ -8,14 +8,22 @@
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h"
 #import "ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator_implementation.h"
 #import "ios/chrome/browser/ui/infobars/infobar_badge_ui_delegate.h"
+#import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_positioner.h"
 #import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.h"
 #import "ios/chrome/browser/ui/infobars/presentation/infobar_modal_transition_driver.h"
+#import "ios/chrome/browser/ui/util/named_guide.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-@interface InfobarCoordinator () <InfobarCoordinatorImplementation> {
+namespace {
+// Banner View constants.
+const CGFloat kBannerOverlapWithOmnibox = 5.0;
+}  // namespace
+
+@interface InfobarCoordinator () <InfobarCoordinatorImplementation,
+                                  InfobarBannerPositioner> {
   // The AnimatedFullscreenDisable disables fullscreen by displaying the
   // Toolbar/s when an Infobar banner is presented.
   std::unique_ptr<AnimatedScopedFullscreenDisabler> animatedFullscreenDisabler_;
@@ -56,7 +64,8 @@
 
 #pragma mark - Public Methods.
 
-- (void)presentInfobarBanner {
+- (void)presentInfobarBannerAnimated:(BOOL)animated
+                          completion:(ProceduralBlock)completion {
   DCHECK(self.browserState);
   DCHECK(self.baseViewController);
   DCHECK(self.bannerViewController);
@@ -71,25 +80,29 @@
   [self.bannerViewController
       setModalPresentationStyle:UIModalPresentationCustom];
   self.bannerTransitionDriver = [[InfobarBannerTransitionDriver alloc] init];
+  self.bannerTransitionDriver.bannerPositioner = self;
   self.bannerViewController.transitioningDelegate = self.bannerTransitionDriver;
   [self.baseViewController presentViewController:self.bannerViewController
-                                        animated:YES
-                                      completion:nil];
+                                        animated:animated
+                                      completion:completion];
 }
 
 - (void)presentInfobarModal {
-  // Dismiss if we're already presenting a ViewController e.g. The
-  // BannerViewController could be presented at this time.
-  if (self.baseViewController.presentedViewController) {
-    [self.baseViewController dismissViewControllerAnimated:NO completion:nil];
-  }
+  ProceduralBlock modalPresentation = ^{
+    DCHECK(!self.bannerViewController);
+    DCHECK(self.baseViewController);
+    self.modalTransitionDriver = [[InfobarModalTransitionDriver alloc]
+        initWithTransitionMode:InfobarModalTransitionBase];
+    [self presentInfobarModalFrom:self.baseViewController
+                           driver:self.modalTransitionDriver];
+  };
 
-  DCHECK(!self.bannerViewController);
-  DCHECK(self.baseViewController);
-  self.modalTransitionDriver = [[InfobarModalTransitionDriver alloc]
-      initWithTransitionMode:InfobarModalTransitionBase];
-  [self presentInfobarModalFrom:self.baseViewController
-                         driver:self.modalTransitionDriver];
+  // Dismiss InfobarBanner first if being presented.
+  if (self.baseViewController.presentedViewController) {
+    [self dismissInfobarBanner:self animated:NO completion:modalPresentation];
+  } else {
+    modalPresentation();
+  }
 }
 
 - (void)dismissInfobarBannerAfterInteraction {
@@ -154,6 +167,17 @@
   }
 }
 
+#pragma mark InfobarBannerPositioner
+
+- (CGFloat)bannerYPosition {
+  NamedGuide* topLayout =
+      [NamedGuide guideWithName:kOmniboxGuide
+                           view:self.baseViewController.view];
+  return topLayout.constrainedView.frame.origin.y +
+         topLayout.constrainedView.frame.size.height -
+         kBannerOverlapWithOmnibox;
+}
+
 #pragma mark InfobarModalDelegate
 
 - (void)modalInfobarButtonWasPressed:(UIButton*)sender {
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm
index ebfef19..d957e70 100644
--- a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm
+++ b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm
@@ -170,7 +170,7 @@
   infobarCoordinator.badgeDelegate = self.mediator;
   infobarCoordinator.browserState = self.browserState;
   infobarCoordinator.baseViewController = self.baseViewController;
-  [infobarCoordinator presentInfobarBanner];
+  [infobarCoordinator presentInfobarBannerAnimated:YES completion:nil];
   self.infobarViewController = infobarCoordinator.bannerViewController;
   [self.childCoordinators addObject:infobarCoordinator];
 
diff --git a/ios/chrome/browser/ui/infobars/presentation/BUILD.gn b/ios/chrome/browser/ui/infobars/presentation/BUILD.gn
index 1907952e..6a639ce 100644
--- a/ios/chrome/browser/ui/infobars/presentation/BUILD.gn
+++ b/ios/chrome/browser/ui/infobars/presentation/BUILD.gn
@@ -7,6 +7,7 @@
   sources = [
     "infobar_banner_animator.h",
     "infobar_banner_animator.mm",
+    "infobar_banner_positioner.h",
     "infobar_banner_presentation_controller.h",
     "infobar_banner_presentation_controller.mm",
     "infobar_banner_transition_driver.h",
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_positioner.h b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_positioner.h
new file mode 100644
index 0000000..1f9f0d7
--- /dev/null
+++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_positioner.h
@@ -0,0 +1,18 @@
+// Copyright 2019 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_INFOBARS_PRESENTATION_INFOBAR_BANNER_POSITIONER_H_
+#define IOS_CHROME_BROWSER_UI_INFOBARS_PRESENTATION_INFOBAR_BANNER_POSITIONER_H_
+
+#import <UIKit/UIKit.h>
+
+// InfobarBannerPositioner contains methods used to position the InfobarBanner.
+@protocol InfobarBannerPositioner
+
+// Y axis value used to position the InfobarBanner.
+- (CGFloat)bannerYPosition;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_INFOBARS_PRESENTATION_INFOBAR_BANNER_POSITIONER_H_
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h
index 774ee511..cd5848c 100644
--- a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h
+++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h
@@ -7,9 +7,14 @@
 
 #import <UIKit/UIKit.h>
 
+@protocol InfobarBannerPositioner;
+
 // InfobarBanner Presentation Controller.
 @interface InfobarBannerPresentationController : UIPresentationController
 
+// Delegate used to position the InfobarBanner.
+@property(nonatomic, assign) id<InfobarBannerPositioner> bannerPositioner;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_INFOBARS_PRESENTATION_INFOBAR_BANNER_PRESENTATION_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.mm b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.mm
index 09e4d21..d304bde 100644
--- a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.mm
+++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.mm
@@ -4,48 +4,54 @@
 
 #import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h"
 
+#import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_positioner.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
 namespace {
-// Presented frame size and position.
-const CGFloat kContainerHeight = 70;
+// The presented view height.
+const CGFloat kDefaultContainerHeight = 70;
+// The presented view outer horizontal margins.
 const CGFloat kContainerHorizontalPadding = 8;
-const CGFloat kContainerTopPadding = 85;
+// The presented view maximum width.
+const CGFloat kContainerWidthMaxSize = 398;
+// The presented view default Y axis value.
+const CGFloat kDefaultBannerYPosition = 85;
 }
 
-@interface InfobarBannerPresentationController ()
-
-// UIView that contains information about the position and size of the container
-// and presented views.
-@property(nonatomic, strong) UIView* viewForPresentedView;
-
-@end
-
 @implementation InfobarBannerPresentationController
 
 - (void)presentationTransitionWillBegin {
-  self.containerView.frame = self.viewForPresentedView.frame;
+  self.containerView.frame = [self viewForPresentedView].frame;
 }
 
 - (void)containerViewWillLayoutSubviews {
-  self.containerView.frame = self.viewForPresentedView.frame;
-  self.presentedView.frame = self.viewForPresentedView.bounds;
+  self.containerView.frame = [self viewForPresentedView].frame;
+  self.presentedView.frame = [self viewForPresentedView].bounds;
 }
 
-// TODO(crbug.com/911864): PLACEHOLDER position and size for the banner
-// presented view.
 - (UIView*)viewForPresentedView {
   UIWindow* window = UIApplication.sharedApplication.keyWindow;
+
+  // Calculate the Banner container width.
   CGFloat safeAreaWidth = CGRectGetWidth(window.bounds);
   CGFloat maxAvailableWidth = safeAreaWidth - 2 * kContainerHorizontalPadding;
-  _viewForPresentedView = [[UIView alloc]
-      initWithFrame:CGRectMake(kContainerHorizontalPadding,
-                               kContainerTopPadding, maxAvailableWidth,
-                               kContainerHeight)];
+  CGFloat frameWidth = fmin(maxAvailableWidth, kContainerWidthMaxSize);
 
-  return _viewForPresentedView;
+  // Based on the container width, calculate the value in order to center the
+  // Banner in the X axis.
+  CGFloat bannerXPosition = (safeAreaWidth / 2) - (frameWidth / 2);
+
+  CGFloat bannerYPosition = [self.bannerPositioner bannerYPosition];
+  if (!bannerYPosition) {
+    bannerYPosition = kDefaultBannerYPosition;
+  }
+
+  return [[UIView alloc]
+      initWithFrame:CGRectMake(bannerXPosition, bannerYPosition, frameWidth,
+                               kDefaultContainerHeight)];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.h b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.h
index b9891a2..491b5b3 100644
--- a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.h
+++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.h
@@ -7,10 +7,15 @@
 
 #import <UIKit/UIKit.h>
 
+@protocol InfobarBannerPositioner;
+
 // The transition delegate used to present an InfobarBanner.
 @interface InfobarBannerTransitionDriver
     : NSObject <UIViewControllerTransitioningDelegate>
 
+// Delegate used to position the InfobarBanner.
+@property(nonatomic, assign) id<InfobarBannerPositioner> bannerPositioner;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_INFOBARS_PRESENTATION_INFOBAR_BANNER_TRANSITION_DRIVER_H_
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.mm b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.mm
index c8abb5a..2594313 100644
--- a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.mm
+++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.mm
@@ -25,6 +25,7 @@
       [[InfobarBannerPresentationController alloc]
           initWithPresentedViewController:presented
                  presentingViewController:presenting];
+  presentationController.bannerPositioner = self.bannerPositioner;
   return presentationController;
 }
 
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_modal_presentation_controller.mm b/ios/chrome/browser/ui/infobars/presentation/infobar_modal_presentation_controller.mm
index 47634494..c7e2c483 100644
--- a/ios/chrome/browser/ui/infobars/presentation/infobar_modal_presentation_controller.mm
+++ b/ios/chrome/browser/ui/infobars/presentation/infobar_modal_presentation_controller.mm
@@ -15,10 +15,8 @@
 const CGFloat kPresentedViewHeight = 267.0;
 // The presented view outer horizontal margins.
 const CGFloat kPresentedViewHorizontalMargin = 10.0;
-// The presented view origin on the X coordinate system of the parent view.
-const CGFloat kPresentedViewOriginX = 10.0;
-// The presented view origin on the Y coordinate system of the parent view.
-const CGFloat kPresentedViewOriginY = 277.0;
+// The presented view maximum width.
+const CGFloat kPresentedViewMaxWidth = 394.0;
 // The rounded corner radius for the container view.
 const CGFloat kContainerCornerRadius = 13.0;
 // The background colot for the container view.
@@ -29,24 +27,34 @@
 
 @implementation InfobarModalPresentationController
 
-// TODO(crbug.com/1372916): Placeholder size and position for the presented
-// view.
 - (void)containerViewWillLayoutSubviews {
-  CGRect safeAreaBounds = self.containerView.safeAreaLayoutGuide.layoutFrame;
-  CGFloat safeAreaWidth = CGRectGetWidth(safeAreaBounds);
-  CGFloat maxAvailableWidth =
-      safeAreaWidth - 2 * kPresentedViewHorizontalMargin;
-  self.presentedView.frame =
-      CGRectMake(kPresentedViewOriginX, kPresentedViewOriginY,
-                 maxAvailableWidth, kPresentedViewHeight);
+  self.presentedView.frame = [self frameForPresentedView];
 
+  // Style the presented and container views.
   self.presentedView.layer.cornerRadius = kContainerCornerRadius;
   self.presentedView.layer.masksToBounds = YES;
   self.presentedView.clipsToBounds = YES;
-
-  UIColor* backgroundColor = UIColorFromRGB(kContainerBackgroundColor);
   self.containerView.backgroundColor =
-      [backgroundColor colorWithAlphaComponent:kContainerBackgroundColorAlpha];
+      [UIColorFromRGB(kContainerBackgroundColor)
+          colorWithAlphaComponent:kContainerBackgroundColorAlpha];
+}
+
+- (CGRect)frameForPresentedView {
+  CGFloat containerWidth = CGRectGetWidth(self.containerView.bounds);
+  CGFloat containerHeight = CGRectGetHeight(self.containerView.bounds);
+
+  // Calculate the frame width.
+  CGFloat maxAvailableWidth =
+      containerWidth - 2 * kPresentedViewHorizontalMargin;
+  CGFloat frameWidth = fmin(maxAvailableWidth, kPresentedViewMaxWidth);
+
+  // Based on the container width calculate the values in order to center the
+  // frame in the X and Y axis.
+  CGFloat modalXPosition = (containerWidth / 2) - (frameWidth / 2);
+  CGFloat modalYPosition = (containerHeight / 2) - (kPresentedViewHeight / 2);
+
+  return CGRectMake(modalXPosition, modalYPosition, frameWidth,
+                    kPresentedViewHeight);
 }
 
 @end
diff --git a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
index 1202285..b3fad970 100644
--- a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
+++ b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
@@ -392,10 +392,8 @@
   CGFloat contentOffsetFromExpandedHeader =
       contentOffsetFromTheTop + self.initialHeaderInset;
   CGFloat topMargin = 0;
-  if (!_webViewProxy && base::FeatureList::IsEnabled(
-                            web::features::kBrowserContainerFullscreen)) {
+  if (!_webViewProxy)
     topMargin = self.scrollView.safeAreaInsets.top;
-  }
   if (contentOffsetFromExpandedHeader >= 0) {
     // Record initial content offset and dispatch delegate on state change.
     self.overscrollState = OverscrollState::NO_PULL_STARTED;
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm b/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm
index c9b90f1..a825f27 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm
@@ -168,7 +168,7 @@
 
         [strongSelf.dataSink itemHasChangedAfterDelay:strongItem];
       };
-  FaviconAttributes* cachedAttributes = self.faviconLoader->FaviconForUrl(
+  FaviconAttributes* cachedAttributes = self.faviconLoader->FaviconForPageUrl(
       item.faviconPageURL, kFaviconWidthHeight, kFaviconMinWidthHeight,
       /*fallback_to_google_server=*/false, completionBlock);
   DCHECK(cachedAttributes);
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.mm
index 61e0865..24a3c440 100644
--- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.mm
+++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.mm
@@ -119,7 +119,7 @@
                          completion:(void (^)(FaviconAttributes*))completion {
   FaviconLoader* faviconLoader =
       IOSChromeFaviconLoaderFactory::GetForBrowserState(self.browserState);
-  FaviconAttributes* cachedAttributes = faviconLoader->FaviconForUrl(
+  FaviconAttributes* cachedAttributes = faviconLoader->FaviconForPageUrl(
       URL, kFaviconWidthHeight, kFaviconMinWidthHeight,
       /*fallback_to_google_server=*/false, ^(FaviconAttributes* attributes) {
         completion(attributes);
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
index 5de8957..e66362c 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
@@ -19,6 +19,11 @@
     "time_range_selector_table_view_controller.mm",
   ]
   deps = [
+    "resources:clear_browsing_data_autofill",
+    "resources:clear_browsing_data_cached_images",
+    "resources:clear_browsing_data_cookies",
+    "resources:clear_browsing_data_history",
+    "resources:clear_browsing_data_passwords",
     "//components/browsing_data/core",
     "//components/feature_engagement/public",
     "//components/history/core/browser",
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
index 1965c3b..cb55a5f 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
@@ -77,6 +77,19 @@
 
 }  // namespace
 
+static NSDictionary* _imageNamesByItemTypes = @{
+  [NSNumber numberWithInteger:ItemTypeDataTypeBrowsingHistory] :
+      @"clear_browsing_data_history",
+  [NSNumber numberWithInteger:ItemTypeDataTypeCookiesSiteData] :
+      @"clear_browsing_data_cookies",
+  [NSNumber numberWithInteger:ItemTypeDataTypeCache] :
+      @"clear_browsing_data_cached_images",
+  [NSNumber numberWithInteger:ItemTypeDataTypeSavedPasswords] :
+      @"clear_browsing_data_passwords",
+  [NSNumber numberWithInteger:ItemTypeDataTypeAutofill] :
+      @"clear_browsing_data_autofill",
+};
+
 @interface ClearBrowsingDataManager () {
   // Access to the kDeleteTimePeriod preference.
   IntegerPrefMember _timeRangePref;
@@ -456,6 +469,8 @@
     tableViewClearDataItem.dataTypeMask = mask;
     tableViewClearDataItem.prefName = prefName;
     if (IsNewClearBrowsingDataUIEnabled()) {
+      tableViewClearDataItem.imageName = [_imageNamesByItemTypes
+          objectForKey:[NSNumber numberWithInteger:itemType]];
       if (itemType == ItemTypeDataTypeCookiesSiteData) {
         // Because there is no counter for cookies, an explanatory text is
         // displayed.
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/BUILD.gn b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/BUILD.gn
new file mode 100644
index 0000000..7b2c9c50c
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/BUILD.gn
@@ -0,0 +1,45 @@
+# Copyright 2019 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/ios/asset_catalog.gni")
+
+imageset("clear_browsing_data_autofill") {
+  sources = [
+    "clear_browsing_data_autofill.imageset/Contents.json",
+    "clear_browsing_data_autofill.imageset/clear_browsing_data_autofill@2x.png",
+    "clear_browsing_data_autofill.imageset/clear_browsing_data_autofill@3x.png",
+  ]
+}
+
+imageset("clear_browsing_data_cached_images") {
+  sources = [
+    "clear_browsing_data_cached_images.imageset/Contents.json",
+    "clear_browsing_data_cached_images.imageset/clear_browsing_data_cached_images@2x.png",
+    "clear_browsing_data_cached_images.imageset/clear_browsing_data_cached_images@3x.png",
+  ]
+}
+
+imageset("clear_browsing_data_cookies") {
+  sources = [
+    "clear_browsing_data_cookies.imageset/Contents.json",
+    "clear_browsing_data_cookies.imageset/clear_browsing_data_cookies@2x.png",
+    "clear_browsing_data_cookies.imageset/clear_browsing_data_cookies@3x.png",
+  ]
+}
+
+imageset("clear_browsing_data_history") {
+  sources = [
+    "clear_browsing_data_history.imageset/Contents.json",
+    "clear_browsing_data_history.imageset/clear_browsing_data_history@2x.png",
+    "clear_browsing_data_history.imageset/clear_browsing_data_history@3x.png",
+  ]
+}
+
+imageset("clear_browsing_data_passwords") {
+  sources = [
+    "clear_browsing_data_passwords.imageset/Contents.json",
+    "clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@2x.png",
+    "clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@3x.png",
+  ]
+}
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_autofill.imageset/Contents.json b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_autofill.imageset/Contents.json
new file mode 100644
index 0000000..f187e2a
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_autofill.imageset/Contents.json
@@ -0,0 +1,18 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "clear_browsing_data_autofill@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "clear_browsing_data_autofill@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_autofill.imageset/clear_browsing_data_autofill@2x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_autofill.imageset/clear_browsing_data_autofill@2x.png
new file mode 100644
index 0000000..c709557
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_autofill.imageset/clear_browsing_data_autofill@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_autofill.imageset/clear_browsing_data_autofill@3x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_autofill.imageset/clear_browsing_data_autofill@3x.png
new file mode 100644
index 0000000..a8a4b44
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_autofill.imageset/clear_browsing_data_autofill@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cached_images.imageset/Contents.json b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cached_images.imageset/Contents.json
new file mode 100644
index 0000000..2c4c9066
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cached_images.imageset/Contents.json
@@ -0,0 +1,18 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "clear_browsing_data_cached_images@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "clear_browsing_data_cached_images@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cached_images.imageset/clear_browsing_data_cached_images@2x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cached_images.imageset/clear_browsing_data_cached_images@2x.png
new file mode 100644
index 0000000..3b3cba4
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cached_images.imageset/clear_browsing_data_cached_images@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cached_images.imageset/clear_browsing_data_cached_images@3x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cached_images.imageset/clear_browsing_data_cached_images@3x.png
new file mode 100644
index 0000000..25d63a51
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cached_images.imageset/clear_browsing_data_cached_images@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cookies.imageset/Contents.json b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cookies.imageset/Contents.json
new file mode 100644
index 0000000..91cb1de
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cookies.imageset/Contents.json
@@ -0,0 +1,18 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "clear_browsing_data_cookies@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "clear_browsing_data_cookies@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cookies.imageset/clear_browsing_data_cookies@2x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cookies.imageset/clear_browsing_data_cookies@2x.png
new file mode 100644
index 0000000..0b2859e
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cookies.imageset/clear_browsing_data_cookies@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cookies.imageset/clear_browsing_data_cookies@3x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cookies.imageset/clear_browsing_data_cookies@3x.png
new file mode 100644
index 0000000..50ad85c
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_cookies.imageset/clear_browsing_data_cookies@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_history.imageset/Contents.json b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_history.imageset/Contents.json
new file mode 100644
index 0000000..42ffd479
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_history.imageset/Contents.json
@@ -0,0 +1,18 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "clear_browsing_data_history@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "clear_browsing_data_history@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_history.imageset/clear_browsing_data_history@2x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_history.imageset/clear_browsing_data_history@2x.png
new file mode 100644
index 0000000..7aaefb6
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_history.imageset/clear_browsing_data_history@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_history.imageset/clear_browsing_data_history@3x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_history.imageset/clear_browsing_data_history@3x.png
new file mode 100644
index 0000000..2692118
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_history.imageset/clear_browsing_data_history@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/Contents.json b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/Contents.json
new file mode 100644
index 0000000..a31b671
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/Contents.json
@@ -0,0 +1,18 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "clear_browsing_data_passwords@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "clear_browsing_data_passwords@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@2x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@2x.png
new file mode 100644
index 0000000..5128543
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@3x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@3x.png
new file mode 100644
index 0000000..d78f4c77
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/side_swipe/swipe_view.mm b/ios/chrome/browser/ui/side_swipe/swipe_view.mm
index b387569..436d4e3 100644
--- a/ios/chrome/browser/ui/side_swipe/swipe_view.mm
+++ b/ios/chrome/browser/ui/side_swipe/swipe_view.mm
@@ -61,11 +61,6 @@
     _toolbarTopConstraint = [[_topToolbarSnapshot topAnchor]
         constraintEqualToAnchor:self.topAnchor];
 
-    if (!base::FeatureList::IsEnabled(
-            web::features::kBrowserContainerFullscreen)) {
-      _toolbarTopConstraint.constant = -StatusBarHeight();
-    }
-
     _imageTopConstraint =
         [_imageView.topAnchor constraintEqualToAnchor:self.topAnchor
                                              constant:topMargin];
@@ -112,11 +107,6 @@
 
 - (void)setTopToolbarImage:(UIImage*)image {
   [self.topToolbarSnapshot setImage:image];
-  if (!base::FeatureList::IsEnabled(
-          web::features::kBrowserContainerFullscreen)) {
-    // Update constraints as StatusBarHeight changes depending on orientation.
-    self.toolbarTopConstraint.constant = -StatusBarHeight();
-  }
   [self.topToolbarSnapshot setNeedsLayout];
 }
 
diff --git a/ios/chrome/browser/ui/util/ui_util.mm b/ios/chrome/browser/ui/util/ui_util.mm
index 9444b19..42982751 100644
--- a/ios/chrome/browser/ui/util/ui_util.mm
+++ b/ios/chrome/browser/ui/util/ui_util.mm
@@ -74,10 +74,7 @@
 }
 
 CGFloat StatusBarHeight() {
-  if (base::FeatureList::IsEnabled(
-          web::features::kBrowserContainerFullscreen) &&
-      base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen) &&
-      base::FeatureList::IsEnabled(kBrowserContainerContainsNTP)) {
+  if (base::FeatureList::IsEnabled(kBrowserContainerContainsNTP)) {
     DCHECK(!base::ios::IsRunningOnIOS11OrLater());
   }
 
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 41b7944..234440a 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -33,7 +33,6 @@
     "root_view_controller_test.mm",
     "scoped_block_popups_pref.h",
     "scoped_block_popups_pref.mm",
-    "scoped_eg_synchronization_disabler.h",
     "scoped_key_window.h",
     "testing_application_context.h",
     "testing_application_context.mm",
@@ -69,6 +68,20 @@
   ]
 }
 
+source_set("eg_test_support") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  testonly = true
+  sources = [
+    "scoped_eg_synchronization_disabler.h",
+    "scoped_eg_synchronization_disabler.mm",
+  ]
+  deps = [
+    ":test_support",
+    "//base",
+    "//ios/third_party/earl_grey:earl_grey+link",
+  ]
+}
+
 source_set("block_cleanup_test") {
   # TODO(crbug.com/733237): Replace this comment with an explicit disable_arc config.
   # The files in this target depend on non-ARC memeory management.
@@ -139,6 +152,7 @@
     "//ios/chrome/browser/find_in_page:unit_tests",
     "//ios/chrome/browser/geolocation:unit_tests",
     "//ios/chrome/browser/history:unit_tests",
+    "//ios/chrome/browser/infobars:unit_tests",
     "//ios/chrome/browser/itunes_urls:unit_tests",
     "//ios/chrome/browser/language:unit_tests",
     "//ios/chrome/browser/main:unit_tests",
diff --git a/ios/chrome/test/scoped_eg_synchronization_disabler.h b/ios/chrome/test/scoped_eg_synchronization_disabler.h
index 9587618..21ebc86e 100644
--- a/ios/chrome/test/scoped_eg_synchronization_disabler.h
+++ b/ios/chrome/test/scoped_eg_synchronization_disabler.h
@@ -5,32 +5,19 @@
 #ifndef IOS_CHROME_TEST_SCOPED_EG_SYNCHRONIZATION_DISABLER_H_
 #define IOS_CHROME_TEST_SCOPED_EG_SYNCHRONIZATION_DISABLER_H_
 
-#import <EarlGrey/EarlGrey.h>
-
+#import <Foundation/Foundation.h>
 #include "base/macros.h"
 
 // Disables EarlGrey synchronization in constructor and returns back to the
 // original value in destructor.
 class ScopedSynchronizationDisabler {
  public:
-  ScopedSynchronizationDisabler()
-      : saved_eg_synchronization_enabled_value_(GetEgSynchronizationEnabled()) {
-    SetEgSynchronizationEnabled(NO);
-  }
-  ~ScopedSynchronizationDisabler() {
-    SetEgSynchronizationEnabled(saved_eg_synchronization_enabled_value_);
-  }
+  ScopedSynchronizationDisabler();
+  ~ScopedSynchronizationDisabler();
 
  private:
-  static bool GetEgSynchronizationEnabled() {
-    return [[GREYConfiguration sharedInstance]
-        boolValueForConfigKey:kGREYConfigKeySynchronizationEnabled];
-  }
-  static void SetEgSynchronizationEnabled(BOOL flag) {
-    [[GREYConfiguration sharedInstance]
-            setValue:@(flag)
-        forConfigKey:kGREYConfigKeySynchronizationEnabled];
-  }
+  static bool GetEgSynchronizationEnabled();
+  static void SetEgSynchronizationEnabled(BOOL flag);
 
   BOOL saved_eg_synchronization_enabled_value_ = NO;
 
diff --git a/ios/chrome/test/scoped_eg_synchronization_disabler.mm b/ios/chrome/test/scoped_eg_synchronization_disabler.mm
new file mode 100644
index 0000000..3de3c91
--- /dev/null
+++ b/ios/chrome/test/scoped_eg_synchronization_disabler.mm
@@ -0,0 +1,31 @@
+// Copyright 2019 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/test/scoped_eg_synchronization_disabler.h"
+
+#import <EarlGrey/EarlGrey.h>
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+ScopedSynchronizationDisabler::ScopedSynchronizationDisabler()
+    : saved_eg_synchronization_enabled_value_(GetEgSynchronizationEnabled()) {
+  SetEgSynchronizationEnabled(NO);
+}
+
+ScopedSynchronizationDisabler::~ScopedSynchronizationDisabler() {
+  SetEgSynchronizationEnabled(saved_eg_synchronization_enabled_value_);
+}
+
+bool ScopedSynchronizationDisabler::GetEgSynchronizationEnabled() {
+  return [[GREYConfiguration sharedInstance]
+      boolValueForConfigKey:kGREYConfigKeySynchronizationEnabled];
+}
+
+void ScopedSynchronizationDisabler::SetEgSynchronizationEnabled(BOOL flag) {
+  [[GREYConfiguration sharedInstance]
+          setValue:@(flag)
+      forConfigKey:kGREYConfigKeySynchronizationEnabled];
+}
diff --git a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.h b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.h
index bb8668d..35af8775 100644
--- a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.h
+++ b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.h
@@ -23,6 +23,54 @@
 @property(nonatomic) UIImage* suggestionTypeIcon;
 @property(nonatomic) GURL imageURL;
 
+// Simple suggestion with text.
++ (instancetype)simpleSuggestion;
+
+// Suggestion with detail text.
++ (instancetype)suggestionWithDetail;
+
+// Suggestion with text long enough to clip on iPhone.
++ (instancetype)clippingSuggestion;
+
+// Suggestion that can be appended.
++ (instancetype)appendableSuggestion;
+
+// Suggestion that will switch to open tab.
++ (instancetype)otherTabSuggestion;
+
+// Suggestion that can be deleted.
++ (instancetype)deletableSuggestion;
+
+// Suggestion with answer for weather.
++ (instancetype)weatherSuggestion;
+
+// Suggestion with answer for stock price.
++ (instancetype)stockSuggestion;
+
+// Suggestion with answer for definition.
++ (instancetype)definitionSuggestion;
+
+// Suggestion with answer for sunrise time.
++ (instancetype)sunriseSuggestion;
+
+// Suggestion with answer for knowledge.
++ (instancetype)knowledgeSuggestion;
+
+// Suggestion with answer for sports.
++ (instancetype)sportsSuggestion;
+
+// Suggestion with answer for "when is" (When is <some event>).
++ (instancetype)whenIsSuggestion;
+
+// Suggestion with answer for currency.
++ (instancetype)currencySuggestion;
+
+// Suggestion with answer for translate.
++ (instancetype)translateSuggestion;
+
+// Suggestion for calculator.
++ (instancetype)calculatorSuggestion;
+
 @end
 
 #endif  // IOS_SHOWCASE_OMNIBOX_POPUP_FAKE_AUTOCOMPLETE_SUGGESTION_H_
diff --git a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm
index 6fc3923a..27974b49 100644
--- a/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm
+++ b/ios/showcase/omnibox_popup/fake_autocomplete_suggestion.mm
@@ -10,6 +10,266 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+// Spacer attributed string for dividing parts of an autocomplete suggestion's
+// text and detail text.
+NSAttributedString* spacer() {
+  return [[NSAttributedString alloc] initWithString:@"  "];
+}
+
+// Standard attributed string for the text part of a suggestion.
+NSAttributedString* textString(NSString* text) {
+  return [[NSAttributedString alloc]
+      initWithString:text
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:17],
+            NSForegroundColorAttributeName : [UIColor blackColor],
+          }];
+}
+
+// Standard attributed string for the detail part of a suggestion.
+NSAttributedString* detailTextString(NSString* detailText) {
+  return [[NSAttributedString alloc]
+      initWithString:detailText
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:12],
+            NSForegroundColorAttributeName : [UIColor colorWithWhite:0
+                                                               alpha:0.41],
+          }];
+}
+
+// Main text for an autocomplete suggestion representing weather
+NSAttributedString* weatherText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"weather"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:16],
+          }];
+}
+
+// Detail text for an autocomplete suggestion representing weather
+NSAttributedString* weatherDetailText() {
+  NSAttributedString* number = [[NSAttributedString alloc]
+      initWithString:@"18"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:24],
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+  NSAttributedString* degreeSymbol = [[NSAttributedString alloc]
+      initWithString:@"°C"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:12],
+            NSBaselineOffsetAttributeName : @10.0f,
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+  NSAttributedString* date = [[NSAttributedString alloc]
+      initWithString:@"ven."
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:12],
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+
+  NSMutableAttributedString* answer =
+      [[NSMutableAttributedString alloc] initWithAttributedString:number];
+  [answer appendAttributedString:degreeSymbol];
+  [answer appendAttributedString:spacer()];
+  [answer appendAttributedString:date];
+
+  return [answer copy];
+}
+
+// Main text for an autocomplete suggestion representing stock price
+NSAttributedString* stockText() {
+  NSAttributedString* search = [[NSAttributedString alloc]
+      initWithString:@"goog stock"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:16],
+          }];
+  NSAttributedString* priceSource = [[NSAttributedString alloc]
+      initWithString:@"GOOG (NASDAQ), 13:18 UTC−4"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:12],
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+  NSMutableAttributedString* answer =
+      [[NSMutableAttributedString alloc] initWithAttributedString:search];
+  [answer appendAttributedString:spacer()];
+  [answer appendAttributedString:priceSource];
+  return [answer copy];
+}
+
+// Detail text for an autocomplete suggestion representing stock price
+NSAttributedString* stockDetailText() {
+  NSAttributedString* price = [[NSAttributedString alloc]
+      initWithString:@"1 209,29"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:24],
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+  NSAttributedString* priceChange = [[NSAttributedString alloc]
+      initWithString:@"-22,25 (-1,81%)"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:16],
+            NSForegroundColorAttributeName : [UIColor colorWithRed:197 / 255.0
+                                                             green:57 / 255.0
+                                                              blue:41 / 255.0
+                                                             alpha:1.0],
+          }];
+  NSMutableAttributedString* answer =
+      [[NSMutableAttributedString alloc] initWithAttributedString:price];
+  [answer appendAttributedString:spacer()];
+  [answer appendAttributedString:priceChange];
+  return [answer copy];
+}
+
+// Main text for an autocomplete suggestion representing a word definition
+NSAttributedString* definitionText() {
+  NSAttributedString* searchText = [[NSAttributedString alloc]
+      initWithString:@"define government"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:16],
+          }];
+  NSAttributedString* pronunciation = [[NSAttributedString alloc]
+      initWithString:@"• /ˈɡʌv(ə)nˌm(ə)nt/"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:14],
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+  NSMutableAttributedString* answer =
+      [[NSMutableAttributedString alloc] initWithAttributedString:searchText];
+  [answer appendAttributedString:spacer()];
+  [answer appendAttributedString:pronunciation];
+  return [answer copy];
+}
+
+// Detail text for an autocomplete suggestion representing a word definition
+NSAttributedString* definitionDetailText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"the group of people with the authority to govern a "
+                     @"country or state; a particular ministry in office. "
+                     @"Let's expand this definition to get to three lines also."
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:14],
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+}
+
+NSAttributedString* sunriseText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"sunrise in paris"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:16],
+          }];
+}
+
+NSAttributedString* sunriseDetailText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"06:35"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:24],
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+}
+
+NSAttributedString* knowledgeText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"how high is mount everest"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:16],
+          }];
+}
+
+NSAttributedString* knowledgeDetailText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"8 848 m"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:24],
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+}
+
+NSAttributedString* sportsText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"boston celtics"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:16],
+          }];
+}
+
+NSAttributedString* sportsDetailText() {
+  return [[NSAttributedString alloc]
+      initWithString:@" contre Pacers 30 mars à 00:00 UTC+1"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:14],
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+}
+
+NSAttributedString* whenIsText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"when is bastille day"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:16],
+          }];
+}
+
+NSAttributedString* whenIsDetailText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"dimanche 14 juillet 2019"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:20],
+
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+}
+
+NSAttributedString* currencyText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"100 usd"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:16],
+          }];
+}
+
+NSAttributedString* currencyDetailText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"100 Dollar américain = 89.01 Euro"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:20],
+
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+}
+
+NSAttributedString* translateText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"bonjour in chinese"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:16],
+          }];
+}
+
+NSAttributedString* translateDetailText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"你好 (Chinois (simplifié))"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:20],
+
+            NSForegroundColorAttributeName : [UIColor grayColor],
+          }];
+}
+
+NSAttributedString* calculatorText() {
+  return [[NSAttributedString alloc]
+      initWithString:@"= 3.46410162"
+          attributes:@{
+            NSFontAttributeName : [UIFont systemFontOfSize:17
+                                                    weight:UIFontWeightMedium],
+            NSForegroundColorAttributeName : [UIColor blackColor],
+          }];
+}
+}  // namespace
+
 @implementation FakeAutocompleteSuggestion
 
 - (instancetype)init {
@@ -31,4 +291,148 @@
   return self.imageURL.is_valid();
 }
 
++ (instancetype)simpleSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = textString(@"Simple suggestion");
+  return suggestion;
+}
+
++ (instancetype)suggestionWithDetail {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = textString(@"Suggestion with detail");
+  suggestion.detailText = detailTextString(@"Detail");
+  return suggestion;
+}
+
++ (instancetype)clippingSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text =
+      textString(@"Suggestion with text that clips because it is very long "
+                 @"and extends off the right end of the screen");
+  suggestion.detailText = detailTextString(
+      @"Detail about the suggestion that also clips because it is too long "
+      @"for the screen and extends off of the right edge.");
+  return suggestion;
+}
+
++ (instancetype)appendableSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = textString(@"Appendable suggestion");
+  suggestion.isAppendable = true;
+  return suggestion;
+}
+
++ (instancetype)otherTabSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = textString(@"Other tab suggestion");
+  suggestion.isTabMatch = true;
+  return suggestion;
+}
+
++ (instancetype)deletableSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = textString(@"Deletable suggestion");
+  suggestion.supportsDeletion = YES;
+  return suggestion;
+}
+
++ (instancetype)weatherSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = weatherText();
+  suggestion.hasAnswer = YES;
+  suggestion.detailText = weatherDetailText();
+  // The image currently doesn't display because there is no fake
+  // Image Retriever, but leaving this here in case this is ever necessary.
+  suggestion.imageURL =
+      GURL("https://ssl.gstatic.com/onebox/weather/128/sunny.png");
+  return suggestion;
+}
+
++ (instancetype)stockSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = stockText();
+  suggestion.hasAnswer = YES;
+  suggestion.detailText = stockDetailText();
+  return suggestion;
+}
+
++ (instancetype)definitionSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = definitionText();
+  suggestion.numberOfLines = 3;
+  suggestion.hasAnswer = YES;
+  suggestion.detailText = definitionDetailText();
+  return suggestion;
+}
+
++ (instancetype)sunriseSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = sunriseText();
+  suggestion.hasAnswer = YES;
+  suggestion.detailText = sunriseDetailText();
+  return suggestion;
+}
+
++ (instancetype)knowledgeSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = knowledgeText();
+  suggestion.hasAnswer = YES;
+  suggestion.detailText = knowledgeDetailText();
+  return suggestion;
+}
+
++ (instancetype)sportsSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = sportsText();
+  suggestion.hasAnswer = YES;
+  suggestion.detailText = sportsDetailText();
+  return suggestion;
+}
+
++ (instancetype)whenIsSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = whenIsText();
+  suggestion.hasAnswer = YES;
+  suggestion.detailText = whenIsDetailText();
+  return suggestion;
+}
+
++ (instancetype)currencySuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = currencyText();
+  suggestion.hasAnswer = YES;
+  suggestion.detailText = currencyDetailText();
+  return suggestion;
+}
+
++ (instancetype)translateSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = translateText();
+  suggestion.hasAnswer = YES;
+  suggestion.detailText = translateDetailText();
+  return suggestion;
+}
+
++ (instancetype)calculatorSuggestion {
+  FakeAutocompleteSuggestion* suggestion =
+      [[FakeAutocompleteSuggestion alloc] init];
+  suggestion.text = calculatorText();
+  return suggestion;
+}
+
 @end
diff --git a/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm b/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm
index 00ea775..0a3a9b27 100644
--- a/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm
+++ b/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm
@@ -4,7 +4,7 @@
 
 #import "ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.h"
 
-#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.h"
+#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.h"
 #import "ios/showcase/common/coordinator.h"
 #import "ios/showcase/common/protocol_alerter.h"
 #import "ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.h"
@@ -36,7 +36,7 @@
   // Ignore didScroll because it's fired all the time.
   [self.alerter ignoreSelector:@selector(autocompleteResultConsumerDidScroll:)];
 
-  self.popupViewController = [[OmniboxPopupLegacyViewController alloc] init];
+  self.popupViewController = [[OmniboxPopupViewController alloc] init];
   self.popupViewController.delegate =
       static_cast<id<AutocompleteResultConsumerDelegate>>(self.alerter);
 
diff --git a/ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.mm b/ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.mm
index 1d2a4f9..c7c2d64 100644
--- a/ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.mm
+++ b/ios/showcase/omnibox_popup/sc_omnibox_popup_mediator.mm
@@ -12,121 +12,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-// Spacer attributed string for dividing parts of an autocomplete suggestion's
-// text and detail text.
-NSAttributedString* spacer() {
-  return [[NSAttributedString alloc] initWithString:@"  "];
-}
-
-// Detail text for an autocomplete suggestion representing weather
-NSAttributedString* weatherDetailText() {
-  NSAttributedString* number = [[NSAttributedString alloc]
-      initWithString:@"18"
-          attributes:@{
-            NSFontAttributeName : [UIFont systemFontOfSize:24],
-            NSForegroundColorAttributeName : [UIColor grayColor],
-          }];
-  NSAttributedString* degreeSymbol = [[NSAttributedString alloc]
-      initWithString:@"°C"
-          attributes:@{
-            NSFontAttributeName : [UIFont systemFontOfSize:12],
-            NSBaselineOffsetAttributeName : @10.0f,
-            NSForegroundColorAttributeName : [UIColor grayColor],
-          }];
-  NSAttributedString* date = [[NSAttributedString alloc]
-      initWithString:@"ven."
-          attributes:@{
-            NSFontAttributeName : [UIFont systemFontOfSize:12],
-            NSForegroundColorAttributeName : [UIColor grayColor],
-          }];
-
-  NSMutableAttributedString* answer =
-      [[NSMutableAttributedString alloc] initWithAttributedString:number];
-  [answer appendAttributedString:degreeSymbol];
-  [answer appendAttributedString:spacer()];
-  [answer appendAttributedString:date];
-
-  return [answer copy];
-}
-
-// Main text for an autocomplete suggestion representing stock price
-NSAttributedString* stockText() {
-  NSAttributedString* search = [[NSAttributedString alloc]
-      initWithString:@"goog stock"
-          attributes:@{
-            NSFontAttributeName : [UIFont systemFontOfSize:16],
-          }];
-  NSAttributedString* priceSource = [[NSAttributedString alloc]
-      initWithString:@"GOOG (NASDAQ), 13:18 UTC−4"
-          attributes:@{
-            NSFontAttributeName : [UIFont systemFontOfSize:12],
-            NSForegroundColorAttributeName : [UIColor grayColor],
-          }];
-  NSMutableAttributedString* answer =
-      [[NSMutableAttributedString alloc] initWithAttributedString:search];
-  [answer appendAttributedString:spacer()];
-  [answer appendAttributedString:priceSource];
-  return [answer copy];
-}
-
-// Detail text for an autocomplete suggestion representing stock price
-NSAttributedString* stockDetailText() {
-  NSAttributedString* price = [[NSAttributedString alloc]
-      initWithString:@"1 209,29"
-          attributes:@{
-            NSFontAttributeName : [UIFont systemFontOfSize:24],
-            NSForegroundColorAttributeName : [UIColor grayColor],
-          }];
-  NSAttributedString* priceChange = [[NSAttributedString alloc]
-      initWithString:@"-22,25 (-1,81%)"
-          attributes:@{
-            NSFontAttributeName : [UIFont systemFontOfSize:16],
-            NSForegroundColorAttributeName : [UIColor colorWithRed:197 / 255.0
-                                                             green:57 / 255.0
-                                                              blue:41 / 255.0
-                                                             alpha:1.0],
-          }];
-  NSMutableAttributedString* answer =
-      [[NSMutableAttributedString alloc] initWithAttributedString:price];
-  [answer appendAttributedString:spacer()];
-  [answer appendAttributedString:priceChange];
-  return [answer copy];
-}
-
-// Main text for an autocomplete suggestion representing a word definition
-NSAttributedString* definitionText() {
-  NSAttributedString* searchText = [[NSAttributedString alloc]
-      initWithString:@"define government"
-          attributes:@{
-            NSFontAttributeName : [UIFont systemFontOfSize:16],
-          }];
-  NSAttributedString* pronunciation = [[NSAttributedString alloc]
-      initWithString:@"• /ˈɡʌv(ə)nˌm(ə)nt/"
-          attributes:@{
-            NSFontAttributeName : [UIFont systemFontOfSize:14],
-            NSForegroundColorAttributeName : [UIColor grayColor],
-          }];
-  NSMutableAttributedString* answer =
-      [[NSMutableAttributedString alloc] initWithAttributedString:searchText];
-  [answer appendAttributedString:spacer()];
-  [answer appendAttributedString:pronunciation];
-  return [answer copy];
-}
-
-// Detail text for an autocomplete suggestion representing a word definition
-NSAttributedString* definitionDetailText() {
-  return [[NSAttributedString alloc]
-      initWithString:@"the group of people with the authority to govern a "
-                     @"country or state; a particular ministry in office. "
-                     @"Let's expand this definition to get to three lines also."
-          attributes:@{
-            NSFontAttributeName : [UIFont systemFontOfSize:14],
-            NSForegroundColorAttributeName : [UIColor grayColor],
-          }];
-}
-}  // namespace
-
 @interface SCOmniboxPopupMediator ()
 
 @property(nonatomic, readonly, weak) id<AutocompleteResultConsumer> consumer;
@@ -146,80 +31,23 @@
 // Creates many fake suggestions and passes them along to the
 // AutocompleteResultConsumer.
 - (void)updateMatches {
-  FakeAutocompleteSuggestion* simpleSuggestion =
-      [[FakeAutocompleteSuggestion alloc] init];
-  simpleSuggestion.text =
-      [[NSAttributedString alloc] initWithString:@"Simple suggestion"];
-
-  FakeAutocompleteSuggestion* suggestionWithDetail =
-      [[FakeAutocompleteSuggestion alloc] init];
-  suggestionWithDetail.text =
-      [[NSAttributedString alloc] initWithString:@"Suggestion with detail"];
-  suggestionWithDetail.detailText =
-      [[NSAttributedString alloc] initWithString:@"Detail"];
-
-  FakeAutocompleteSuggestion* clippingSuggestion =
-      [[FakeAutocompleteSuggestion alloc] init];
-  clippingSuggestion.text = [[NSAttributedString alloc]
-      initWithString:@"Suggestion with text that clips because it is very long "
-                     @"and extends off the right end of the screen"];
-  clippingSuggestion.detailText = [[NSAttributedString alloc]
-      initWithString:
-          @"Detail about the suggestion that also clips because it is too long "
-          @"for the screen and extends off of the right edge."];
-
-  FakeAutocompleteSuggestion* appendableSuggestion =
-      [[FakeAutocompleteSuggestion alloc] init];
-  appendableSuggestion.text =
-      [[NSAttributedString alloc] initWithString:@"Appendable suggestion"];
-  appendableSuggestion.isAppendable = true;
-
-  FakeAutocompleteSuggestion* otherTabSuggestion =
-      [[FakeAutocompleteSuggestion alloc] init];
-  otherTabSuggestion.text =
-      [[NSAttributedString alloc] initWithString:@"Other tab suggestion"];
-  otherTabSuggestion.isTabMatch = true;
-
-  FakeAutocompleteSuggestion* deletableSuggestion =
-      [[FakeAutocompleteSuggestion alloc] init];
-  deletableSuggestion.text =
-      [[NSAttributedString alloc] initWithString:@"Deletable suggestion"];
-  deletableSuggestion.supportsDeletion = YES;
-
-  FakeAutocompleteSuggestion* weatherSuggestion =
-      [[FakeAutocompleteSuggestion alloc] init];
-  weatherSuggestion.text =
-      [[NSAttributedString alloc] initWithString:@"weather"];
-  weatherSuggestion.hasAnswer = YES;
-  weatherSuggestion.detailText = weatherDetailText();
-  // The image currently doesn't display because there is no fake
-  // Image Retriever, but leaving this here in case this is ever necessary.
-  weatherSuggestion.imageURL =
-      GURL("https://ssl.gstatic.com/onebox/weather/128/sunny.png");
-
-  FakeAutocompleteSuggestion* stockSuggestion =
-      [[FakeAutocompleteSuggestion alloc] init];
-  stockSuggestion.text = stockText();
-  stockSuggestion.hasAnswer = YES;
-  stockSuggestion.detailText = stockDetailText();
-
-  FakeAutocompleteSuggestion* definitionSuggestion =
-      [[FakeAutocompleteSuggestion alloc] init];
-  definitionSuggestion.text = definitionText();
-  definitionSuggestion.numberOfLines = 3;
-  definitionSuggestion.hasAnswer = YES;
-  definitionSuggestion.detailText = definitionDetailText();
-
   NSArray<id<AutocompleteSuggestion>>* suggestions = @[
-    simpleSuggestion,
-    suggestionWithDetail,
-    clippingSuggestion,
-    appendableSuggestion,
-    otherTabSuggestion,
-    deletableSuggestion,
-    stockSuggestion,
-    weatherSuggestion,
-    definitionSuggestion,
+    [FakeAutocompleteSuggestion simpleSuggestion],
+    [FakeAutocompleteSuggestion suggestionWithDetail],
+    [FakeAutocompleteSuggestion clippingSuggestion],
+    [FakeAutocompleteSuggestion appendableSuggestion],
+    [FakeAutocompleteSuggestion otherTabSuggestion],
+    [FakeAutocompleteSuggestion deletableSuggestion],
+    [FakeAutocompleteSuggestion stockSuggestion],
+    [FakeAutocompleteSuggestion weatherSuggestion],
+    [FakeAutocompleteSuggestion definitionSuggestion],
+    [FakeAutocompleteSuggestion sunriseSuggestion],
+    [FakeAutocompleteSuggestion knowledgeSuggestion],
+    [FakeAutocompleteSuggestion sportsSuggestion],
+    [FakeAutocompleteSuggestion whenIsSuggestion],
+    [FakeAutocompleteSuggestion currencySuggestion],
+    [FakeAutocompleteSuggestion translateSuggestion],
+    [FakeAutocompleteSuggestion calculatorSuggestion],
   ];
 
   [self.consumer updateMatches:suggestions withAnimation:YES];
diff --git a/ios/web/browsing_data/browsing_data_remover.mm b/ios/web/browsing_data/browsing_data_remover.mm
index 8aadb6ad..d850bdea 100644
--- a/ios/web/browsing_data/browsing_data_remover.mm
+++ b/ios/web/browsing_data/browsing_data_remover.mm
@@ -83,11 +83,19 @@
     return;
   }
 
+  for (id<BrowsingDataRemoverObserver> observer in observers_list_) {
+    [observer willRemoveBrowsingData:this];
+  }
+
   base::WeakPtr<BrowsingDataRemover> weak_ptr = weak_ptr_factory_.GetWeakPtr();
   ProceduralBlock completion_block = ^{
     if (BrowsingDataRemover* strong_ptr = weak_ptr.get()) {
       [strong_ptr->dummy_web_view_ removeFromSuperview];
       strong_ptr->dummy_web_view_ = nil;
+      for (id<BrowsingDataRemoverObserver> observer in strong_ptr
+               ->observers_list_) {
+        [observer didRemoveBrowsingData:this];
+      }
     }
     std::move(block_closure).Run();
   };
diff --git a/ios/web/browsing_data/browsing_data_remover_observer.h b/ios/web/browsing_data/browsing_data_remover_observer.h
index 60fef80e..fdb7106 100644
--- a/ios/web/browsing_data/browsing_data_remover_observer.h
+++ b/ios/web/browsing_data/browsing_data_remover_observer.h
@@ -7,9 +7,19 @@
 
 #import <Foundation/Foundation.h>
 
+namespace web {
+class BrowsingDataRemover;
+}
+
 // Protocol used to observe the BrowsingDataRemover.
 @protocol BrowsingDataRemoverObserver
 
+// Called when the |dataRemover| is about to remove browsing data.
+- (void)willRemoveBrowsingData:(web::BrowsingDataRemover*)dataRemover;
+
+// Called when the |dataRemover| has finished removing browsing data.
+- (void)didRemoveBrowsingData:(web::BrowsingDataRemover*)dataRemover;
+
 @end
 
 #endif  // IOS_WEB_BROWSING_DATA_BROWSING_DATA_REMOVER_OBSERVER_H_
diff --git a/ios/web/common/crw_web_view_content_view.mm b/ios/web/common/crw_web_view_content_view.mm
index 54c043a..5f0ad01 100644
--- a/ios/web/common/crw_web_view_content_view.mm
+++ b/ios/web/common/crw_web_view_content_view.mm
@@ -79,17 +79,6 @@
 
 #pragma mark Layout
 
-- (void)layoutSubviews {
-  [super layoutSubviews];
-
-  if (!base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen)) {
-    CGRect frame = self.bounds;
-    frame = UIEdgeInsetsInsetRect(frame, _contentInset);
-    frame = CGRectOffset(frame, _contentOffset.x, _contentOffset.y);
-    self.webView.frame = frame;
-  }
-}
-
 - (void)setContentOffset:(CGPoint)contentOffset {
   if (CGPointEqualToPoint(_contentOffset, contentOffset))
     return;
@@ -113,8 +102,6 @@
   _contentInset = contentInset;
   if (self.shouldUseViewContentInset) {
     [_scrollView setContentInset:contentInset];
-  } else {
-    [self resizeViewportForContentInsetChangeFromInsets:oldInsets];
   }
 }
 
@@ -127,30 +114,4 @@
   }
 }
 
-#pragma mark Private methods
-
-// Updates the viewport by updating the web view frame after self.contentInset
-// is changed to a new value from |oldInsets|.
-- (void)resizeViewportForContentInsetChangeFromInsets:(UIEdgeInsets)oldInsets {
-  if (base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen))
-    return;
-
-  // Update the content offset of the scroll view to match the padding
-  // that will be included in the frame.
-  CGFloat topPaddingChange = self.contentInset.top - oldInsets.top;
-  CGPoint contentOffset = [_scrollView contentOffset];
-  contentOffset.y += topPaddingChange;
-  [_scrollView setContentOffset:contentOffset];
-  // Update web view frame immediately to make |contentInset| animatable.
-  [self setNeedsLayout];
-  [self layoutIfNeeded];
-  // Setting WKWebView frame can mistakenly reset contentOffset. Change it
-  // back to the initial value if necessary.
-  // TODO(crbug.com/645857): Remove this workaround once WebKit bug is
-  // fixed.
-  if ([_scrollView contentOffset].y != contentOffset.y) {
-    [_scrollView setContentOffset:contentOffset];
-  }
-}
-
 @end
diff --git a/ios/web/features.mm b/ios/web/features.mm
index 1045776..ffc5ac54 100644
--- a/ios/web/features.mm
+++ b/ios/web/features.mm
@@ -26,12 +26,6 @@
 const base::Feature kCrashOnUnexpectedURLChange{
     "CrashOnUnexpectedURLChange", base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kBrowserContainerFullscreen{
-    "BrowserContainerFullscreen", base::FEATURE_ENABLED_BY_DEFAULT};
-
-const base::Feature kOutOfWebFullscreen{"OutOfWebFullscreen",
-                                        base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kHistoryClobberWorkaround{
     "WKWebViewHistoryClobberWorkaround", base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/ios/web/find_in_page/find_in_page_manager_impl.h b/ios/web/find_in_page/find_in_page_manager_impl.h
index f93d862..5620ce8d 100644
--- a/ios/web/find_in_page/find_in_page_manager_impl.h
+++ b/ios/web/find_in_page/find_in_page_manager_impl.h
@@ -58,6 +58,11 @@
     // the previous match on the page. No-op if no known matches exist. Returns
     // true if selected a match, false otherwise.
     bool GoToPreviousMatch();
+    // Removes |web_frame| from |frame_order| and |frame_match_count|. Resets
+    // |selected_frame_id| and |selected_match_index_in_selected_frame| if
+    // |web_frame| contains currently selected match. |web_frame| must not be
+    // null.
+    void RemoveFrame(WebFrame* web_frame);
     // Unique identifier for each find used to check that it is the most recent
     // find. This ensures that an old find doesn't decrement
     // |pending_frame_calls_count| after it has been reset by the new find.
@@ -81,6 +86,11 @@
     std::list<std::string>::iterator selected_frame_id = frame_order.end();
     // Index of the currently selected match or -1 if there is none.
     int selected_match_index_in_selected_frame = -1;
+
+   private:
+    // Returns true if |web_frame| contains the currently selected match, false
+    // otherwise. |web_frame| must not be null.
+    bool IsSelectedFrame(WebFrame* web_frame);
   };
 
   // Executes find logic for |FindInPageSearch| option.
@@ -95,9 +105,9 @@
   void ProcessFindInPageResult(const std::string& frame_id,
                                const int request_id,
                                const base::Value* result);
-  // Calls delegate DidCountMatches() method if |delegate_| is set and starts a
-  // FindInPageNext find. Called when the last frame returns results from a Find
-  // request.
+  // Calls delegate DidHighlightMatches() method if |delegate_| is set and
+  // starts a FindInPageNext find. Called when the last frame returns results
+  // from a Find request.
   void LastFindRequestCompleted();
   // Calls delegate DidSelectMatch() method to pass back index selected if
   // |delegate_| is set. |result| is a byproduct of using base::BindOnce() to
diff --git a/ios/web/find_in_page/find_in_page_manager_impl.mm b/ios/web/find_in_page/find_in_page_manager_impl.mm
index 4a10718..65d7fd8 100644
--- a/ios/web/find_in_page/find_in_page_manager_impl.mm
+++ b/ios/web/find_in_page/find_in_page_manager_impl.mm
@@ -115,6 +115,12 @@
   if (GetTotalMatchCount() == 0) {
     return false;
   }
+  // No currently selected match, but there are matches. Move iterator to
+  // beginning. This can happen if a frame containing the currently selected
+  // match is removed from the page.
+  if (selected_frame_id == frame_order.end()) {
+    selected_frame_id = frame_order.begin();
+  }
 
   bool next_match_is_in_selected_frame =
       selected_match_index_in_selected_frame + 1 <
@@ -141,6 +147,12 @@
   if (GetTotalMatchCount() == 0) {
     return false;
   }
+  // No currently selected match, but there are matches. Move iterator to
+  // beginning. This can happen if a frame containing the currently selected
+  // matchs is removed from the page.
+  if (selected_frame_id == frame_order.end()) {
+    selected_frame_id = frame_order.begin();
+  }
 
   bool previous_match_is_in_selected_frame =
       selected_match_index_in_selected_frame - 1 >= 0;
@@ -163,6 +175,25 @@
   return true;
 }
 
+void FindInPageManagerImpl::FindRequest::RemoveFrame(WebFrame* web_frame) {
+  if (IsSelectedFrame(web_frame)) {
+    // If currently selecting match in frame that will become unavailable,
+    // there will no longer be a selected match. Reset to unselected match
+    // state.
+    selected_frame_id = frame_order.end();
+    selected_match_index_in_selected_frame = -1;
+  }
+  frame_order.remove(web_frame->GetFrameId());
+  frame_match_count.erase(web_frame->GetFrameId());
+}
+
+bool FindInPageManagerImpl::FindRequest::IsSelectedFrame(WebFrame* web_frame) {
+  if (selected_frame_id == frame_order.end()) {
+    return false;
+  }
+  return *selected_frame_id == web_frame->GetFrameId();
+}
+
 void FindInPageManagerImpl::WebFrameDidBecomeAvailable(WebState* web_state,
                                                        WebFrame* web_frame) {
   const std::string frame_id = web_frame->GetFrameId();
@@ -178,8 +209,13 @@
 
 void FindInPageManagerImpl::WebFrameWillBecomeUnavailable(WebState* web_state,
                                                           WebFrame* web_frame) {
-  last_find_request_.frame_order.remove(web_frame->GetFrameId());
-  last_find_request_.frame_match_count.erase(web_frame->GetFrameId());
+  last_find_request_.RemoveFrame(web_frame);
+
+  if (delegate_ && last_find_request_.query) {
+    delegate_->DidHighlightMatches(web_state_,
+                                   last_find_request_.GetTotalMatchCount(),
+                                   last_find_request_.query);
+  }
 }
 
 void FindInPageManagerImpl::WebStateDestroyed(WebState* web_state) {
@@ -288,9 +324,9 @@
 
 void FindInPageManagerImpl::LastFindRequestCompleted() {
   if (delegate_) {
-    delegate_->DidCountMatches(web_state_,
-                               last_find_request_.GetTotalMatchCount(),
-                               last_find_request_.query);
+    delegate_->DidHighlightMatches(web_state_,
+                                   last_find_request_.GetTotalMatchCount(),
+                                   last_find_request_.query);
   }
   int total_matches = last_find_request_.GetTotalMatchCount();
   if (total_matches == 0) {
@@ -305,7 +341,7 @@
 void FindInPageManagerImpl::NotifyDelegateDidSelectMatch(
     const base::Value* result) {
   if (delegate_) {
-    delegate_->DidHighlightMatch(
+    delegate_->DidSelectMatch(
         web_state_, last_find_request_.GetCurrentSelectedMatchIndex());
   }
 }
diff --git a/ios/web/find_in_page/find_in_page_manger_impl_unittest.mm b/ios/web/find_in_page/find_in_page_manger_impl_unittest.mm
index fcc113c6..0014e5ff 100644
--- a/ios/web/find_in_page/find_in_page_manger_impl_unittest.mm
+++ b/ios/web/find_in_page/find_in_page_manger_impl_unittest.mm
@@ -522,4 +522,73 @@
   EXPECT_FALSE(fake_delegate_.state());
 }
 
+// Tests that Find in Page responds with index one for a successive
+// FindInPageNext after the frame containing the currently selected match is
+// removed.
+TEST_F(FindInPageManagerImplTest,
+       FindDidHighlightNextMatchAfterFrameDisappears) {
+  auto frame_with_one_match = CreateMainWebFrameWithJsResultForFind(
+      std::make_unique<base::Value>(1.0), kOneMatchFrameId);
+  FakeWebFrame* frame_with_one_match_ptr = frame_with_one_match.get();
+  auto frame_with_two_matches = CreateChildWebFrameWithJsResultForFind(
+      std::make_unique<base::Value>(2.0), kTwoMatchesFrameId);
+  FakeWebFrame* frame_with_two_matches_ptr = frame_with_two_matches.get();
+  test_web_state_->AddWebFrame(std::move(frame_with_one_match));
+  test_web_state_->AddWebFrame(std::move(frame_with_two_matches));
+
+  GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPageSearch);
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+    base::RunLoop().RunUntilIdle();
+    return fake_delegate_.state();
+  }));
+  ASSERT_EQ(2ul, frame_with_one_match_ptr->GetJavaScriptCallHistory().size());
+  EXPECT_EQ("__gCrWeb.findInPage.highlightMatch(0);",
+            frame_with_one_match_ptr->GetJavaScriptCallHistory()[1]);
+
+  test_web_state_->RemoveWebFrame(kOneMatchFrameId);
+  GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPageNext);
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+    base::RunLoop().RunUntilIdle();
+    return fake_delegate_.state()->index == 0;
+  }));
+  EXPECT_EQ("__gCrWeb.findInPage.highlightMatch(0);",
+            frame_with_two_matches_ptr->GetLastJavaScriptCall());
+}
+
+// Tests that Find in Page does not respond when frame is removed
+TEST_F(FindInPageManagerImplTest, FindDidNotRepondAfterFrameRemoved) {
+  auto frame_with_one_match = CreateMainWebFrameWithJsResultForFind(
+      std::make_unique<base::Value>(1.0), kOneMatchFrameId);
+  test_web_state_->AddWebFrame(std::move(frame_with_one_match));
+
+  test_web_state_->RemoveWebFrame(kOneMatchFrameId);
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_FALSE(fake_delegate_.state());
+}
+
+// Tests that Find in Page responds with a total match count of one to a
+// FindInPageSearch find when there is one match in a frame and then responds
+// with a total match count of zero when that frame is removed.
+TEST_F(FindInPageManagerImplTest, FindInPageUpdateMatchCountAfterFrameRemoved) {
+  auto frame_with_one_match = CreateMainWebFrameWithJsResultForFind(
+      std::make_unique<base::Value>(1.0), kOneMatchFrameId);
+  test_web_state_->AddWebFrame(std::move(frame_with_one_match));
+
+  GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPageSearch);
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+    base::RunLoop().RunUntilIdle();
+    return fake_delegate_.state();
+  }));
+
+  test_web_state_->RemoveWebFrame(kOneMatchFrameId);
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+    base::RunLoop().RunUntilIdle();
+    return fake_delegate_.state()->match_count == 0;
+  }));
+}
+
 }  // namespace web
diff --git a/ios/web/public/features.h b/ios/web/public/features.h
index 68b07ed..a9be613 100644
--- a/ios/web/public/features.h
+++ b/ios/web/public/features.h
@@ -35,12 +35,6 @@
 // https://crbug.com/841105.
 extern const base::Feature kCrashOnUnexpectedURLChange;
 
-// Used to make BrowserContainerViewController fullscreen.
-extern const base::Feature kBrowserContainerFullscreen;
-
-// Used to use the fullscreen implementation out of web.
-extern const base::Feature kOutOfWebFullscreen;
-
 // Used to enable the workaround for WKWebView history clobber bug
 // (crbug.com/887497).
 extern const base::Feature kHistoryClobberWorkaround;
diff --git a/ios/web/public/find_in_page/find_in_page_manager.h b/ios/web/public/find_in_page/find_in_page_manager.h
index 2864fe5..2e5bae1 100644
--- a/ios/web/public/find_in_page/find_in_page_manager.h
+++ b/ios/web/public/find_in_page/find_in_page_manager.h
@@ -39,9 +39,9 @@
   // |query| is ignored if |options| is not |FindInPageSearch|. If new search is
   // started before previous search finishes, old request will be discarded.
   //
-  // FindInPageManagerDelegate::DidCountMatches() will be called to return the
-  // total matches found if FindInPageSearch is passed, assuming it hasn't been
-  // discarded. FindInPageManagerDelegate::DidHighlightMatch() will also be
+  // FindInPageManagerDelegate::DidHighlightMatches() will be called to return
+  // the total matches found if FindInPageSearch is passed, assuming it hasn't
+  // been discarded. FindInPageManagerDelegate::DidSelectMatch() will also be
   // called if matches were found to inform client of the new match that was
   // highlighted for all FindInPageOptions.
   virtual void Find(NSString* query, FindInPageOptions options) = 0;
diff --git a/ios/web/public/find_in_page/find_in_page_manager_delegate.h b/ios/web/public/find_in_page/find_in_page_manager_delegate.h
index 3732d3a7..7c4c031 100644
--- a/ios/web/public/find_in_page/find_in_page_manager_delegate.h
+++ b/ios/web/public/find_in_page/find_in_page_manager_delegate.h
@@ -19,20 +19,23 @@
  public:
   FindInPageManagerDelegate() = default;
 
-  // Called when a search for |query| finished with |match_count| found after
-  // calling FindInPageManager::Find() with FindInPageSearch. Even if no matches
-  // are found, call will be made once a find has completed, assuming it has not
-  // been interrupted by another find. Client should check |query| to ensure
-  // that it is processing |match_count| for the correct find.
-  virtual void DidCountMatches(WebState* web_state,
-                               int match_count,
-                               NSString* query) = 0;
+  // Called when a search for |query| finished with |match_count| found and all
+  // matches were highlighted after calling FindInPageManager::Find() with
+  // FindInPageSearch. Even if no matches are found, call will be made once a
+  // find has completed, assuming it has not been interrupted by another find.
+  // Will also be called if the total match count in the current page changes.
+  // Client should check |query| to ensure that it is processing |match_count|
+  // for the correct find.
+  virtual void DidHighlightMatches(WebState* web_state,
+                                   int match_count,
+                                   NSString* query) = 0;
 
-  // Called when a match number |index| is highlighted. This is triggered by
-  // calling FindInPageManager::Find() with any FindInPageOptions to indicate
-  // the new match number that was highlighted. This method is not called if
-  // |FindInPageManager::Find| did not find any matches.
-  virtual void DidHighlightMatch(WebState* web_state, int index) = 0;
+  // Called when a match number |index| is selected. A selected match refers to
+  // a match that is highlighted in a unique manner different from the other
+  // matches. This is triggered by calling FindInPageManager::Find() with any
+  // FindInPageOptions to indicate the new match number that was selected. This
+  // method is not called if |FindInPageManager::Find| did not find any matches.
+  virtual void DidSelectMatch(WebState* web_state, int index) = 0;
 
  protected:
   virtual ~FindInPageManagerDelegate() = default;
diff --git a/ios/web/public/test/fakes/fake_find_in_page_manager_delegate.h b/ios/web/public/test/fakes/fake_find_in_page_manager_delegate.h
index d0bf1c332..1d9feb7 100644
--- a/ios/web/public/test/fakes/fake_find_in_page_manager_delegate.h
+++ b/ios/web/public/test/fakes/fake_find_in_page_manager_delegate.h
@@ -21,12 +21,12 @@
   ~FakeFindInPageManagerDelegate() override;
 
   // FindInPageManagerDelegate override
-  void DidCountMatches(WebState* web_state,
-                       int match_count,
-                       NSString* query) override;
-  void DidHighlightMatch(WebState* web_state, int index) override;
+  void DidHighlightMatches(WebState* web_state,
+                           int match_count,
+                           NSString* query) override;
+  void DidSelectMatch(WebState* web_state, int index) override;
 
-  // Holds the last response values passed to DidCountMatches.
+  // Holds the state passed to DidHighlightMatches and DidSelectMatch.
   struct State {
     State();
     ~State();
diff --git a/ios/web/public/test/fakes/fake_find_in_page_manager_delegate.mm b/ios/web/public/test/fakes/fake_find_in_page_manager_delegate.mm
index ed06f0b..4c4fbea7 100644
--- a/ios/web/public/test/fakes/fake_find_in_page_manager_delegate.mm
+++ b/ios/web/public/test/fakes/fake_find_in_page_manager_delegate.mm
@@ -18,17 +18,17 @@
 
 FakeFindInPageManagerDelegate::~FakeFindInPageManagerDelegate() = default;
 
-void FakeFindInPageManagerDelegate::DidCountMatches(WebState* web_state,
-                                                    int match_count,
-                                                    NSString* query) {
+void FakeFindInPageManagerDelegate::DidHighlightMatches(WebState* web_state,
+                                                        int match_count,
+                                                        NSString* query) {
   delegate_state_ = std::make_unique<State>();
   delegate_state_->web_state = web_state;
   delegate_state_->match_count = match_count;
   delegate_state_->query = query;
 }
 
-void FakeFindInPageManagerDelegate::DidHighlightMatch(WebState* web_state,
-                                                      int index) {
+void FakeFindInPageManagerDelegate::DidSelectMatch(WebState* web_state,
+                                                   int index) {
   if (!delegate_state_) {
     delegate_state_ = std::make_unique<State>();
   }
diff --git a/ios/web/shell/test/page_state_egtest.mm b/ios/web/shell/test/page_state_egtest.mm
index 27e6af1..b7edc1a 100644
--- a/ios/web/shell/test/page_state_egtest.mm
+++ b/ios/web/shell/test/page_state_egtest.mm
@@ -108,11 +108,9 @@
   WaitForOffset(kOffset2);
 }
 
-// TODO(crbug.com/946461): Fix and re-enable. This test is failing on devices
-// and official. Tests that the content offset of the webview scroll view is {0,
-// 0} after a load.
+// Tests that the content offset of the webview scroll view is {0, 0} after a
+// load.
 - (void)testZeroContentOffsetAfterLoad {
-  EARL_GREY_TEST_DISABLED(@"Test disabled.");
   // Set up the file-based server to load the tall page.
   const GURL baseURL = _server.GetURL(kLongPage1);
   bool success = [ShellEarlGrey loadURL:baseURL];
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 5eae10a..95a7716f 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -41,6 +41,8 @@
 #include "base/values.h"
 #include "crypto/symmetric_key.h"
 #import "ios/net/http_response_headers_util.h"
+#import "ios/web/browsing_data/browsing_data_remover.h"
+#import "ios/web/browsing_data/browsing_data_remover_observer.h"
 #import "ios/web/common/crw_content_view.h"
 #import "ios/web/common/crw_web_view_content_view.h"
 #include "ios/web/common/url_util.h"
@@ -248,14 +250,15 @@
 
 @end
 
-@interface CRWWebController ()<CRWContextMenuDelegate,
-                               CRWNativeContentDelegate,
-                               CRWSSLStatusUpdaterDataSource,
-                               CRWSSLStatusUpdaterDelegate,
-                               CRWWebControllerContainerViewDelegate,
-                               CRWWebViewScrollViewProxyObserver,
-                               WKNavigationDelegate,
-                               WKUIDelegate> {
+@interface CRWWebController () <BrowsingDataRemoverObserver,
+                                CRWContextMenuDelegate,
+                                CRWNativeContentDelegate,
+                                CRWSSLStatusUpdaterDataSource,
+                                CRWSSLStatusUpdaterDelegate,
+                                CRWWebControllerContainerViewDelegate,
+                                CRWWebViewScrollViewProxyObserver,
+                                WKNavigationDelegate,
+                                WKUIDelegate> {
   // The view used to display content.  Must outlive |_webViewProxy|. The
   // container view should be accessed through this property rather than
   // |self.view| from within this class, as |self.view| triggers creation while
@@ -643,6 +646,7 @@
         initWithBrowserState:browserState];
     _certVerificationErrors =
         std::make_unique<CertVerificationErrorsCacheType>(kMaxCertErrorsCount);
+    web::BrowsingDataRemover::FromBrowserState(browserState)->AddObserver(self);
     _navigationStates = [[CRWWKNavigationStates alloc] init];
     web::WebFramesManagerImpl::CreateForWebState(_webStateImpl);
     web::FindInPageManagerImpl::CreateForWebState(_webStateImpl);
@@ -2416,6 +2420,16 @@
   }
 }
 
+#pragma mark - BrowsingDataRemoverObserver
+
+- (void)willRemoveBrowsingData:(web::BrowsingDataRemover*)dataRemover {
+  self.webUsageEnabled = NO;
+}
+
+- (void)didRemoveBrowsingData:(web::BrowsingDataRemover*)dataRemover {
+  self.webUsageEnabled = YES;
+}
+
 #pragma mark - JavaScript history manipulation
 
 // Updates the HTML5 history state of the page using the current NavigationItem.
@@ -3724,23 +3738,9 @@
   // This will be resized later, but matching the final frame will minimize
   // re-rendering. Use the screen size because the application's key window
   // may still be nil.
-  CGRect containerViewFrame = CGRectZero;
-  if (UIApplication.sharedApplication.keyWindow) {
-    containerViewFrame = UIApplication.sharedApplication.keyWindow.bounds;
-  } else {
-    containerViewFrame = UIScreen.mainScreen.bounds;
-  }
-  if (base::FeatureList::IsEnabled(
-          web::features::kBrowserContainerFullscreen)) {
-    _containerView.frame = containerViewFrame;
-  } else {
-    // TODO(crbug.com/688259): Stop subtracting status bar height.
-    CGFloat statusBarHeight =
-        [[UIApplication sharedApplication] statusBarFrame].size.height;
-    containerViewFrame.origin.y += statusBarHeight;
-    containerViewFrame.size.height -= statusBarHeight;
-    _containerView.frame = containerViewFrame;
-  }
+  _containerView.frame = UIApplication.sharedApplication.keyWindow
+                             ? UIApplication.sharedApplication.keyWindow.bounds
+                             : UIScreen.mainScreen.bounds;
 
   DCHECK(!CGRectIsEmpty(_containerView.frame));
 
@@ -4486,6 +4486,12 @@
   self.webStateImpl->GetNavigationManagerImpl()
       .OnRendererInitiatedNavigationStarted(webViewURL);
 
+  // When a client-side redirect occurs while an interstitial warning is
+  // displayed, clear the warning and its navigation item, so that a new
+  // pending item is created for |context| in |registerLoadRequestForURL|. See
+  // crbug.com/861836.
+  self.webStateImpl->ClearTransientContent();
+
   std::unique_ptr<web::NavigationContextImpl> navigationContext =
       [self registerLoadRequestForURL:webViewURL
                sameDocumentNavigation:NO
diff --git a/ios/web/web_state/ui/crw_web_view_content_view_unittest.mm b/ios/web/web_state/ui/crw_web_view_content_view_unittest.mm
index 986917e..78a1cd8 100644
--- a/ios/web/web_state/ui/crw_web_view_content_view_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_view_content_view_unittest.mm
@@ -41,34 +41,4 @@
       UIEdgeInsetsEqualToEdgeInsets(contentInset, scrollView.contentInset));
 }
 
-// Tests the ContentInset method when shouldUseViewContentInset is set to NO.
-TEST_F(CRWWebViewContentViewTest, ContentInsetWithoutInsetForPadding) {
-  // This functionality has been moved out of the web// layer when
-  // kOutOfWebFullscreen is enabled.
-  if (base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen))
-    return;
-
-  UIView* webView = [[UIView alloc] init];
-  UIScrollView* scrollView = [[UIScrollView alloc] init];
-  [webView addSubview:scrollView];
-  CRWWebViewContentView* contentView =
-      [[CRWWebViewContentView alloc] initWithWebView:webView
-                                          scrollView:scrollView];
-  contentView.shouldUseViewContentInset = NO;
-  const CGRect frame = CGRectMake(0, 0, 100, 100);
-  contentView.frame = frame;
-
-  // Check that the content inset of the scroll view is not taken into account.
-  const UIEdgeInsets contentInset = UIEdgeInsetsMake(10, 20, 30, 40);
-  scrollView.contentInset = contentInset;
-  EXPECT_TRUE(UIEdgeInsetsEqualToEdgeInsets(UIEdgeInsetsZero,
-                                            contentView.contentInset));
-
-  // Set the content inset.
-  const CGRect resultFrame = CGRectMake(20, 10, 40, 60);
-  webView.frame = CGRectZero;
-  contentView.contentInset = contentInset;
-  EXPECT_TRUE(CGRectEqualToRect(resultFrame, webView.frame));
-}
-
 }  // namespace
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm
index 8bc440a..090709e 100644
--- a/ios/web/web_state/web_state_observer_inttest.mm
+++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -2180,7 +2180,10 @@
 
 // Tests stopping a navigation after allowing the navigation from
 // WebStatePolicyDecider. DidStartNavigation and DidFinishNavigation callbacks
-// are still called.
+// are still called on simulator. On iOS 12.2 device the navigation never
+// starts, which is ok, but the behavior can not be tested so the test is
+// simulator-only.
+#if TARGET_IPHONE_SIMULATOR
 TEST_P(WebStateObserverTest, StopNavigationAfterPolicyDeciderCallback) {
   GURL url(test_server_->GetURL("/hung"));
   NavigationContext* context = nullptr;
@@ -2209,6 +2212,7 @@
     return page_loaded_observer_ptr->did_finish_navigation_info();
   }));
 }
+#endif  // TARGET_IPHONE_SIMULATOR
 
 // Tests stopping a finished navigation. PageLoaded is never called.
 TEST_P(WebStateObserverTest, StopFinishedNavigation) {
diff --git a/ios/web/web_state/web_state_unittest.mm b/ios/web/web_state/web_state_unittest.mm
index 62f271f..c8b68d4 100644
--- a/ios/web/web_state/web_state_unittest.mm
+++ b/ios/web/web_state/web_state_unittest.mm
@@ -334,10 +334,9 @@
 // Verifies that large session can be restored. SlimNavigationManagder has max
 // session size limit of |wk_navigation_util::kMaxSessionSize|.
 TEST_P(WebStateTest, RestoreLargeSession) {
-// TODO(crbug.com/946898): Re-enable once fixed on device on iOS12.2
+// TODO(crbug.com/946898): This test is failing on device with slim-nav enabled.
 #if !TARGET_IPHONE_SIMULATOR
-  UIUserInterfaceIdiom idiom = [[UIDevice currentDevice] userInterfaceIdiom];
-  if (idiom == UIUserInterfaceIdiomPhone)
+  if (web::GetWebClient()->IsSlimNavigationManagerEnabled())
     return;
 #endif
   // Create session storage with large number of items.
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc
index abbefde..25914f96 100644
--- a/media/capture/video/video_capture_device_unittest.cc
+++ b/media/capture/video/video_capture_device_unittest.cc
@@ -63,12 +63,9 @@
   DISABLED_UsingRealWebcam_AllocateBadSize
 // We will always get YUYV from the Mac AVFoundation implementations.
 #define MAYBE_UsingRealWebcam_CaptureMjpeg DISABLED_UsingRealWebcam_CaptureMjpeg
-// TODO(crbug.com/923874).
-#define MAYBE_UsingRealWebcam_TakePhoto DISABLED_UsingRealWebcam_TakePhoto
-  // TODO(crbug.com/923874).
-#define MAYBE_UsingRealWebcam_GetPhotoState DISABLED_UsingRealWebcam_GetPhotoState
-  // TODO(crbug.com/923874).
-#define MAYBE_UsingRealWebcam_CaptureWithSize DISABLED_UsingRealWebcam_CaptureWithSize
+#define MAYBE_UsingRealWebcam_TakePhoto UsingRealWebcam_TakePhoto
+#define MAYBE_UsingRealWebcam_GetPhotoState UsingRealWebcam_GetPhotoState
+#define MAYBE_UsingRealWebcam_CaptureWithSize UsingRealWebcam_CaptureWithSize
 #define MAYBE_UsingRealWebcam_CheckPhotoCallbackRelease \
   UsingRealWebcam_CheckPhotoCallbackRelease
 #elif defined(OS_WIN)
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 6e7ba90..dde1433 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -154,14 +154,16 @@
       "android/promotion_hint_aggregator.h",
       "android/promotion_hint_aggregator_impl.cc",
       "android/promotion_hint_aggregator_impl.h",
+      "android/shared_image_pool.cc",
+      "android/shared_image_pool.h",
+      "android/shared_image_video.cc",
+      "android/shared_image_video.h",
       "android/surface_chooser_helper.cc",
       "android/surface_chooser_helper.h",
       "android/surface_texture_gl_owner.cc",
       "android/surface_texture_gl_owner.h",
       "android/texture_owner.cc",
       "android/texture_owner.h",
-      "android/texture_pool.cc",
-      "android/texture_pool.h",
       "android/video_frame_factory.h",
       "android/video_frame_factory_impl.cc",
       "android/video_frame_factory_impl.h",
@@ -445,7 +447,6 @@
       "android/promotion_hint_aggregator_impl_unittest.cc",
       "android/surface_chooser_helper_unittest.cc",
       "android/surface_texture_gl_owner_unittest.cc",
-      "android/texture_pool_unittest.cc",
       "android/video_frame_factory_impl_unittest.cc",
     ]
     deps = [
diff --git a/media/gpu/DEPS b/media/gpu/DEPS
index 5783704..b01fca3 100644
--- a/media/gpu/DEPS
+++ b/media/gpu/DEPS
@@ -15,5 +15,9 @@
   "+ui/platform_window",
 
   # media/gpu is not part of "media" target and should not use MEDIA_EXPORT.
-  "-media/base/media_export.h"
+  "-media/base/media_export.h",
+
+  # SharedImageVideo uses it.
+  "+components/viz/common/resources/resource_format_utils.h",
+  "+components/viz/common/resources/resource_sizes.h"
 ]
diff --git a/media/gpu/android/shared_image_pool.cc b/media/gpu/android/shared_image_pool.cc
new file mode 100644
index 0000000..a722d60
--- /dev/null
+++ b/media/gpu/android/shared_image_pool.cc
@@ -0,0 +1,94 @@
+// Copyright 2019 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/android/shared_image_pool.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "gpu/command_buffer/service/shared_image_representation.h"
+#include "media/gpu/command_buffer_helper.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/scoped_make_current.h"
+
+namespace media {
+
+SharedImagePool::SharedImagePool(scoped_refptr<CommandBufferHelper> helper)
+    : helper_(std::move(helper)), weak_factory_(this) {
+  if (helper_) {
+    helper_->SetWillDestroyStubCB(base::BindOnce(
+        &SharedImagePool::OnWillDestroyStub, weak_factory_.GetWeakPtr()));
+  }
+}
+
+SharedImagePool::~SharedImagePool() {
+  // All the refs should have been dropped by this time and pool should be
+  // empty. This is because video frames keep a ref of pool and once all frames
+  // are released, then only pool will get destructed.
+  DCHECK(pool_.empty());
+}
+
+void SharedImagePool::AddSharedImage(
+    std::unique_ptr<gpu::SharedImageRepresentationFactoryRef>
+        shared_image_ref) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(pool_.find(shared_image_ref.get()) == pool_.end());
+  // Don't permit additions after we've lost the stub.
+  // TODO(liberato): consider making this fail gracefully.  However, nobody
+  // should be doing this, so for now it's a DCHECK.
+  DCHECK(helper_);
+  pool_.insert(std::move(shared_image_ref));
+}
+
+void SharedImagePool::ReleaseSharedImage(
+    gpu::SharedImageRepresentationFactoryRef* shared_image_ref,
+    const gpu::SyncToken& sync_token) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  // If we don't have a sync token, or if we have no stub, then just finish.
+  if (!sync_token.HasData() || !helper_) {
+    OnSyncTokenReleased(shared_image_ref);
+    return;
+  }
+
+  // We keep a strong ref to |this| in the callback, so that we are guaranteed
+  // to receive it.  It's common for the last ref to us to be our caller, as
+  // a callback.  We need to stick around a bit longer than that if there's a
+  // sync token.  Plus, we're required to keep |helper_| around while a wait is
+  // still pending.
+  helper_->WaitForSyncToken(
+      sync_token,
+      base::BindOnce(&SharedImagePool::OnSyncTokenReleased,
+                     scoped_refptr<SharedImagePool>(this), shared_image_ref));
+}
+
+void SharedImagePool::OnSyncTokenReleased(
+    gpu::SharedImageRepresentationFactoryRef* shared_image_ref) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  // If there is no |helper_|, it means stub has been destroyed and pool has
+  // been already cleared.
+  if (!helper_) {
+    DCHECK(pool_.empty());
+    return;
+  }
+  auto iter = pool_.find(shared_image_ref);
+  DCHECK(iter != pool_.end());
+
+  // Drop the shared_image_ref.  This is safe without the context being current.
+  // It's also safe if the stub has been destroyed.
+  pool_.erase(iter);
+}
+
+void SharedImagePool::OnWillDestroyStub(bool have_context) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(helper_);
+
+  // Clearing the pools clears up all the refs which in turn releases all the
+  // codec buffers.
+  pool_.clear();
+  helper_ = nullptr;
+}
+
+}  // namespace media
diff --git a/media/gpu/android/shared_image_pool.h b/media/gpu/android/shared_image_pool.h
new file mode 100644
index 0000000..ac7307a
--- /dev/null
+++ b/media/gpu/android/shared_image_pool.h
@@ -0,0 +1,81 @@
+// Copyright 2019 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_ANDROID_SHARED_IMAGE_POOL_H_
+#define MEDIA_GPU_ANDROID_SHARED_IMAGE_POOL_H_
+
+#include <memory>
+
+#include "base/containers/flat_set.h"
+#include "base/containers/unique_ptr_adapters.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
+#include "media/gpu/media_gpu_export.h"
+
+namespace gpu {
+class SharedImageRepresentationFactoryRef;
+}  // namespace gpu
+
+namespace media {
+
+class CommandBufferHelper;
+
+// TODO(vikassoni): This is a temporary class which will go away soon once all
+// the video mailbox consumers switches to using shared image mailbox instead of
+// legacy mailbox. Video frame will have the ownership of shared image ref
+// instead of this shared image pool.
+// SharedImagePool owns shared image ref. Shared image are used to hold decoded
+// video frames. This pool allows shared images to outlive the decoder that
+// created them, since decoders are torn down when the pipeline is suspended,
+// but decoded frames can be on-screen indefinitely.
+class MEDIA_GPU_EXPORT SharedImagePool
+    : public base::RefCounted<SharedImagePool> {
+ public:
+  SharedImagePool(scoped_refptr<CommandBufferHelper> helper);
+
+  // Add a new shared image ref into the pool.  This may only be done before
+  // |stub_| is destroyed.  When |stub_| is destroyed, we will destroy/clear any
+  // refs that are in the pool.
+  void AddSharedImage(std::unique_ptr<gpu::SharedImageRepresentationFactoryRef>
+                          shared_image_ref);
+
+  // Release a shared image ref back into the pool.  |shared_image_ref| must
+  // have been added to the pool previously, and not released.  Otherwise, this
+  // is undefined. Note: since we don't actually pool things, this just forgets
+  // |shared_image_ref|. It's okay if this is called after we've lost |stub_|.
+  // If |sync_token| is not null, then we'll wait for that token before taking
+  // any action.
+  void ReleaseSharedImage(
+      gpu::SharedImageRepresentationFactoryRef* shared_image_ref,
+      const gpu::SyncToken& sync_token);
+
+ protected:
+  virtual ~SharedImagePool();
+
+  // Called after a sync token has been released, to free |shared_image_ref|.
+  void OnSyncTokenReleased(
+      gpu::SharedImageRepresentationFactoryRef* shared_image_ref);
+
+  // Called when |stub_| notifies us that the underlying stub will be destroyed.
+  void OnWillDestroyStub(bool have_context);
+
+ private:
+  friend class base::RefCounted<SharedImagePool>;
+  THREAD_CHECKER(thread_checker_);
+
+  scoped_refptr<CommandBufferHelper> helper_;
+
+  base::flat_set<std::unique_ptr<gpu::SharedImageRepresentationFactoryRef>,
+                 base::UniquePtrComparator>
+      pool_;
+
+  base::WeakPtrFactory<SharedImagePool> weak_factory_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_ANDROID_SHARED_IMAGE_POOL_H_
diff --git a/media/gpu/android/shared_image_video.cc b/media/gpu/android/shared_image_video.cc
new file mode 100644
index 0000000..adb406d6
--- /dev/null
+++ b/media/gpu/android/shared_image_video.cc
@@ -0,0 +1,155 @@
+// Copyright 2019 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/android/shared_image_video.h"
+
+#include <utility>
+
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "components/viz/common/resources/resource_sizes.h"
+#include "gpu/command_buffer/common/shared_image_usage.h"
+#include "gpu/command_buffer/service/abstract_texture.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/memory_tracking.h"
+#include "gpu/command_buffer/service/shared_image_representation.h"
+#include "gpu/command_buffer/service/texture_manager.h"
+#include "media/gpu/android/codec_image.h"
+
+namespace media {
+
+SharedImageVideo::SharedImageVideo(
+    const gpu::Mailbox& mailbox,
+    const gfx::ColorSpace color_space,
+    scoped_refptr<CodecImage> codec_image,
+    std::unique_ptr<gpu::gles2::AbstractTexture> abstract_texture,
+    scoped_refptr<gpu::SharedContextState> shared_context_state,
+    bool is_thread_safe)
+    : SharedImageBacking(
+          mailbox,
+          viz::RGBA_8888,
+          codec_image->GetSize(),
+          color_space,
+          (gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_GLES2),
+          viz::ResourceSizes::UncheckedSizeInBytes<size_t>(
+              codec_image->GetSize(),
+              viz::RGBA_8888),
+          is_thread_safe),
+      codec_image_(std::move(codec_image)),
+      abstract_texture_(std::move(abstract_texture)),
+      shared_context_state_(std::move(shared_context_state)) {
+  DCHECK(codec_image_);
+  DCHECK(shared_context_state_);
+
+  // Currently this backing is not thread safe.
+  DCHECK(!is_thread_safe);
+  shared_context_state_->AddContextLostObserver(this);
+}
+
+SharedImageVideo::~SharedImageVideo() {
+  codec_image_->ReleaseCodecBuffer();
+  if (shared_context_state_)
+    shared_context_state_->RemoveContextLostObserver(this);
+}
+
+bool SharedImageVideo::IsCleared() const {
+  return true;
+}
+
+void SharedImageVideo::SetCleared() {}
+
+void SharedImageVideo::Update() {}
+
+bool SharedImageVideo::ProduceLegacyMailbox(
+    gpu::MailboxManager* mailbox_manager) {
+  DCHECK(abstract_texture_);
+  mailbox_manager->ProduceTexture(mailbox(),
+                                  abstract_texture_->GetTextureBase());
+  return true;
+}
+
+void SharedImageVideo::Destroy() {}
+
+void SharedImageVideo::OnContextLost() {
+  // We release codec buffers when shared image context is lost. This is because
+  // texture owner's texture was created on shared context. Once shared context
+  // is lost, no one should try to use that texture.
+  codec_image_->ReleaseCodecBuffer();
+  shared_context_state_->RemoveContextLostObserver(this);
+  shared_context_state_ = nullptr;
+}
+
+// Representation of a SharedImageCodecImage as a GL Texture.
+class SharedImageRepresentationGLTextureVideo
+    : public gpu::SharedImageRepresentationGLTexture {
+ public:
+  SharedImageRepresentationGLTextureVideo(gpu::SharedImageManager* manager,
+                                          SharedImageVideo* backing,
+                                          gpu::MemoryTypeTracker* tracker,
+                                          gpu::gles2::Texture* texture)
+      : gpu::SharedImageRepresentationGLTexture(manager, backing, tracker),
+        texture_(texture) {}
+
+  gpu::gles2::Texture* GetTexture() override { return texture_; }
+
+  bool BeginAccess(GLenum mode) override {
+    auto* video_backing = static_cast<SharedImageVideo*>(backing());
+    DCHECK(video_backing);
+
+    // For (old) overlays, we don't have a texture owner, but overlay promotion
+    // might not happen for some reasons. In that case, it will try to draw
+    // which should results in no image.
+    if (!texture_owner())
+      return true;
+
+    // Render the codec image.
+    codec_image()->RenderToFrontBuffer();
+
+    // Bind the tex image if its not already bound.
+    if (!texture_owner()->binds_texture_on_update())
+      texture_owner()->EnsureTexImageBound();
+    return true;
+  }
+
+  void EndAccess() override {}
+
+ private:
+  SharedImageVideo* video_backing() {
+    auto* video_backing = static_cast<SharedImageVideo*>(backing());
+    return video_backing;
+  }
+
+  CodecImage* codec_image() {
+    DCHECK(video_backing());
+    return video_backing()->codec_image_.get();
+  }
+
+  TextureOwner* texture_owner() { return codec_image()->texture_owner().get(); }
+
+  gpu::gles2::Texture* texture_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedImageRepresentationGLTextureVideo);
+};
+
+std::unique_ptr<gpu::SharedImageRepresentationGLTexture>
+SharedImageVideo::ProduceGLTexture(gpu::SharedImageManager* manager,
+                                   gpu::MemoryTypeTracker* tracker) {
+  // TODO(vikassoni): Also fix how overlays work with shared images to enable
+  // this representation. To make overlays work, we need to add a new overlay
+  // representation which can notify promotion hints and schedule overlay
+  // planes via |codec_image_|.
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+std::unique_ptr<gpu::SharedImageRepresentationSkia>
+SharedImageVideo::ProduceSkia(
+    gpu::SharedImageManager* manager,
+    gpu::MemoryTypeTracker* tracker,
+    scoped_refptr<gpu::SharedContextState> context_state) {
+  // TODO(vikassoni): Implement in follow up patch.
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+}  // namespace media
diff --git a/media/gpu/android/shared_image_video.h b/media/gpu/android/shared_image_video.h
new file mode 100644
index 0000000..1a66d44a
--- /dev/null
+++ b/media/gpu/android/shared_image_video.h
@@ -0,0 +1,82 @@
+// Copyright 2019 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_ANDROID_SHARED_IMAGE_VIDEO_H_
+#define MEDIA_GPU_ANDROID_SHARED_IMAGE_VIDEO_H_
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "gpu/command_buffer/service/shared_context_state.h"
+#include "gpu/command_buffer/service/shared_image_backing.h"
+#include "media/gpu/media_gpu_export.h"
+
+namespace gpu {
+class SharedImageRepresentationGLTexture;
+class SharedImageRepresentationSkia;
+struct Mailbox;
+
+namespace gles2 {
+class AbstractTexture;
+}  // namespace gles2
+
+}  // namespace gpu
+
+namespace media {
+class CodecImage;
+
+// Implementation of SharedImageBacking that renders MediaCodec buffers to a
+// TextureOwner or overlay as needed in order to draw them.
+class MEDIA_GPU_EXPORT SharedImageVideo
+    : public gpu::SharedImageBacking,
+      public gpu::SharedContextState::ContextLostObserver {
+ public:
+  SharedImageVideo(
+      const gpu::Mailbox& mailbox,
+      const gfx::ColorSpace color_space,
+      scoped_refptr<CodecImage> codec_image,
+      std::unique_ptr<gpu::gles2::AbstractTexture> abstract_texture,
+      scoped_refptr<gpu::SharedContextState> shared_context_state,
+      bool is_thread_safe);
+
+  ~SharedImageVideo() override;
+
+  // SharedImageBacking implementation.
+  bool IsCleared() const override;
+  void SetCleared() override;
+  void Update() override;
+  bool ProduceLegacyMailbox(gpu::MailboxManager* mailbox_manager) override;
+  void Destroy() override;
+
+  // SharedContextState::ContextLostObserver implementation.
+  void OnContextLost() override;
+
+ protected:
+  std::unique_ptr<gpu::SharedImageRepresentationGLTexture> ProduceGLTexture(
+      gpu::SharedImageManager* manager,
+      gpu::MemoryTypeTracker* tracker) override;
+
+  std::unique_ptr<gpu::SharedImageRepresentationSkia> ProduceSkia(
+      gpu::SharedImageManager* manager,
+      gpu::MemoryTypeTracker* tracker,
+      scoped_refptr<gpu::SharedContextState> context_state) override;
+
+  // TODO(vikassoni): Add overlay and AHardwareBuffer representations in future
+  // patch. Overlays are anyways using legacy mailbox for now.
+
+ private:
+  friend class SharedImageRepresentationGLTextureVideo;
+
+  scoped_refptr<CodecImage> codec_image_;
+
+  // |abstract_texture_| is only used for legacy mailbox.
+  std::unique_ptr<gpu::gles2::AbstractTexture> abstract_texture_;
+  scoped_refptr<gpu::SharedContextState> shared_context_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedImageVideo);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_ANDROID_SHARED_IMAGE_VIDEO_H_
diff --git a/media/gpu/android/texture_owner.cc b/media/gpu/android/texture_owner.cc
index 9ff37c6f..d00fd6a 100644
--- a/media/gpu/android/texture_owner.cc
+++ b/media/gpu/android/texture_owner.cc
@@ -12,6 +12,7 @@
 #include "gpu/command_buffer/service/abstract_texture.h"
 #include "gpu/command_buffer/service/abstract_texture_impl_shared_context_state.h"
 #include "gpu/command_buffer/service/decoder_context.h"
+#include "gpu/command_buffer/service/texture_base.h"
 #include "media/gpu/android/image_reader_gl_owner.h"
 #include "media/gpu/android/surface_texture_gl_owner.h"
 #include "ui/gl/scoped_binders.h"
@@ -76,6 +77,10 @@
   return texture_->service_id();
 }
 
+gpu::TextureBase* TextureOwner::GetTextureBase() const {
+  return texture_->GetTextureBase();
+}
+
 void TextureOwner::ClearAbstractTexture() {
   texture_.reset();
 }
diff --git a/media/gpu/android/texture_owner.h b/media/gpu/android/texture_owner.h
index a09da29..93edf5b 100644
--- a/media/gpu/android/texture_owner.h
+++ b/media/gpu/android/texture_owner.h
@@ -25,6 +25,7 @@
 
 namespace gpu {
 class SharedContextState;
+class TextureBase;
 namespace gles2 {
 class AbstractTexture;
 }  // namespace gles2
@@ -66,6 +67,7 @@
 
   // Returns the GL texture id that the TextureOwner is attached to.
   GLuint GetTextureId() const;
+  gpu::TextureBase* GetTextureBase() const;
   virtual gl::GLContext* GetContext() const = 0;
   virtual gl::GLSurface* GetSurface() const = 0;
 
diff --git a/media/gpu/android/texture_pool.cc b/media/gpu/android/texture_pool.cc
deleted file mode 100644
index 4f5909d..0000000
--- a/media/gpu/android/texture_pool.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2018 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/android/texture_pool.h"
-
-#include "base/bind.h"
-#include "gpu/command_buffer/service/abstract_texture.h"
-#include "gpu/command_buffer/service/texture_manager.h"
-#include "media/gpu/command_buffer_helper.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/scoped_make_current.h"
-
-using gpu::gles2::AbstractTexture;
-
-namespace media {
-
-TexturePool::TexturePool(scoped_refptr<CommandBufferHelper> helper)
-    : helper_(std::move(helper)), weak_factory_(this) {
-  if (helper_) {
-    helper_->SetWillDestroyStubCB(base::BindOnce(
-        &TexturePool::OnWillDestroyStub, weak_factory_.GetWeakPtr()));
-  }
-}
-
-TexturePool::~TexturePool() {
-  // We'll drop all textures from the pool, if any.  It's okay if we don't have
-  // a current context, since AbstractTexture handles it.
-}
-
-void TexturePool::AddTexture(std::unique_ptr<AbstractTexture> texture) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  DCHECK(pool_.find(texture.get()) == pool_.end());
-  // Don't permit additions after we've lost the stub.
-  // TODO(liberato): consider making this fail gracefully.  However, nobody
-  // should be doing this, so for now it's a DCHECK.
-  DCHECK(helper_);
-  pool_.insert(std::move(texture));
-}
-
-void TexturePool::ReleaseTexture(AbstractTexture* texture,
-                                 const gpu::SyncToken& sync_token) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-  // If we don't have a sync token, or if we have no stub, then just finish.
-  if (!sync_token.HasData() || !helper_) {
-    OnSyncTokenReleased(texture);
-    return;
-  }
-
-  // We keep a strong ref to |this| in the callback, so that we are guaranteed
-  // to receive it.  It's common for the last ref to us to be our caller, as
-  // a callback.  We need to stick around a bit longer than that if there's a
-  // sync token.  Plus, we're required to keep |helper_| around while a wait is
-  // still pending.
-  helper_->WaitForSyncToken(
-      sync_token, base::BindOnce(&TexturePool::OnSyncTokenReleased,
-                                 scoped_refptr<TexturePool>(this), texture));
-}
-
-void TexturePool::OnSyncTokenReleased(AbstractTexture* texture) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  auto iter = pool_.find(texture);
-  DCHECK(iter != pool_.end());
-
-  // Drop the texture.  This is safe without the context being current.  It's
-  // also safe if the stub has been destroyed.
-
-  pool_.erase(iter);
-}
-
-void TexturePool::OnWillDestroyStub(bool have_context) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  DCHECK(helper_);
-  // TODO(liberato): Should we drop all unrendered codec buffers here?  It seems
-  // like a good idea, just to release the resources.  However, they won't block
-  // decoding, since decoding requires the stub too.  More generally, it might
-  // be worthwhile to have a callback on AbstractTexture that's called when it
-  // transitions to not owning a texture.
-
-  // Note that we don't have to do anything with |pool_|, since AbstractTextures
-  // can outlive the stub that created them.  They just don't have a texture.
-  helper_ = nullptr;
-}
-
-}  // namespace media
diff --git a/media/gpu/android/texture_pool.h b/media/gpu/android/texture_pool.h
deleted file mode 100644
index 0b9651a..0000000
--- a/media/gpu/android/texture_pool.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2018 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_ANDROID_TEXTURE_POOL_H_
-#define MEDIA_GPU_ANDROID_TEXTURE_POOL_H_
-
-#include "base/containers/flat_set.h"
-#include "base/containers/unique_ptr_adapters.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "gpu/ipc/service/command_buffer_stub.h"
-#include "media/gpu/media_gpu_export.h"
-
-namespace gpu {
-namespace gles2 {
-class AbstractTexture;
-}  // namespace gles2
-}  // namespace gpu
-
-namespace media {
-
-class CommandBufferHelper;
-
-// Owns Textures that are used to hold decoded video frames.  Allows them to
-// outlive the decoder that created them, since decoders are torn down when the
-// pipeline is suspended, but decoded frames can be on-screen indefinitely.
-// TODO(tmathmeyer): Convert this into a pool.  Right now, we just constantly
-// add new textures and remove them.
-class MEDIA_GPU_EXPORT TexturePool : public base::RefCounted<TexturePool> {
- public:
-  TexturePool(scoped_refptr<CommandBufferHelper> helper);
-
-  // Add a new texture into the pool.  This may only be done before |stub_| is
-  // destroyed.  When |stub_| is destroyed, we will destroy any textures that
-  // are in the pool.
-  //
-  // Note that if we were really a pool this would mean "add |texture| into the
-  // pool of available textures".  There would be some other call to allocate
-  // a texture from the pool.
-  void AddTexture(std::unique_ptr<gpu::gles2::AbstractTexture> texture);
-
-  // Release a texture back into the pool.  |texture| must have been added to
-  // the pool previously, and not released.  Otherwise, this is undefined.
-  // Note: since we don't actually pool things, this just forgets |texture|.
-  // It's okay if this is called after we've lost |stub_|.  If |sync_token| is
-  // not null, then we'll wait for that token before taking any action.
-  void ReleaseTexture(gpu::gles2::AbstractTexture* texture,
-                      const gpu::SyncToken& sync_token);
-
- protected:
-  virtual ~TexturePool();
-
-  // Called after a sync token has been released, to free |texture|.
-  void OnSyncTokenReleased(gpu::gles2::AbstractTexture* texture);
-
-  // Called when |stub_| notifies us that the underlying stub will be destroyed.
-  void OnWillDestroyStub(bool have_context);
-
- private:
-  friend class base::RefCounted<TexturePool>;
-  THREAD_CHECKER(thread_checker_);
-
-  scoped_refptr<CommandBufferHelper> helper_;
-
-  base::flat_set<std::unique_ptr<gpu::gles2::AbstractTexture>,
-                 base::UniquePtrComparator>
-      pool_;
-
-  base::WeakPtrFactory<TexturePool> weak_factory_;
-};
-
-}  // namespace media
-
-#endif  // MEDIA_GPU_ANDROID_TEXTURE_POOL_H_
diff --git a/media/gpu/android/video_frame_factory_impl.cc b/media/gpu/android/video_frame_factory_impl.cc
index f1f3e1b..b24ed37 100644
--- a/media/gpu/android/video_frame_factory_impl.cc
+++ b/media/gpu/android/video_frame_factory_impl.cc
@@ -4,6 +4,8 @@
 
 #include "media/gpu/android/video_frame_factory_impl.h"
 
+#include <memory>
+
 #include "base/android/android_image_reader_compat.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -17,6 +19,8 @@
 #include "gpu/command_buffer/common/constants.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/memory_tracking.h"
+#include "gpu/command_buffer/service/shared_image_factory.h"
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "gpu/ipc/service/command_buffer_stub.h"
 #include "gpu/ipc/service/gpu_channel.h"
@@ -27,7 +31,8 @@
 #include "media/gpu/android/codec_image.h"
 #include "media/gpu/android/codec_image_group.h"
 #include "media/gpu/android/codec_wrapper.h"
-#include "media/gpu/android/texture_pool.h"
+#include "media/gpu/android/shared_image_pool.h"
+#include "media/gpu/android/shared_image_video.h"
 #include "media/gpu/command_buffer_helper.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
 #include "ui/gl/android/surface_texture.h"
@@ -65,6 +70,16 @@
   return TextureOwner::Mode::kSurfaceTextureInsecure;
 }
 
+scoped_refptr<gpu::SharedContextState> GetSharedContext(
+    gpu::CommandBufferStub* stub,
+    gpu::ContextResult* result) {
+  auto shared_context =
+      stub->channel()->gpu_channel_manager()->GetSharedContextState(result);
+  if (*result != gpu::ContextResult::kSuccess)
+    return nullptr;
+  return shared_context;
+}
+
 void ContextStateResultUMA(gpu::ContextResult result) {
   UMA_HISTOGRAM_ENUMERATION(
       "Media.GpuVideoFrameFactory.SharedContextStateResult", result);
@@ -174,15 +189,15 @@
     return nullptr;
   stub_->AddDestructionObserver(this);
 
-  texture_pool_ = new TexturePool(CommandBufferHelper::Create(stub_));
+  shared_image_pool_ =
+      base::MakeRefCounted<SharedImagePool>(CommandBufferHelper::Create(stub_));
 
   decoder_helper_ = GLES2DecoderHelper::Create(stub_->decoder_context());
 
   gpu::ContextResult result;
-  scoped_refptr<gpu::SharedContextState> shared_context =
-      stub_->channel()->gpu_channel_manager()->GetSharedContextState(&result);
-  if (result != gpu::ContextResult::kSuccess) {
-    LOG(ERROR) << "Unable to get a shared context.";
+  auto shared_context = GetSharedContext(stub_, &result);
+  if (!shared_context) {
+    LOG(ERROR) << "GpuVideoFrameFactory: Unable to get a shared context.";
     ContextStateResultUMA(result);
     return nullptr;
   }
@@ -192,7 +207,8 @@
       shared_context->context(), shared_context->surface());
   if (!shared_context->IsCurrent(nullptr)) {
     result = gpu::ContextResult::kTransientFailure;
-    LOG(ERROR) << "Unable to make shared context current.";
+    LOG(ERROR)
+        << "GpuVideoFrameFactory: Unable to make shared context current.";
     ContextStateResultUMA(result);
     return nullptr;
   }
@@ -210,48 +226,34 @@
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   scoped_refptr<VideoFrame> frame;
-  std::unique_ptr<AbstractTexture> texture;
+  std::unique_ptr<gpu::SharedImageRepresentationFactoryRef> shared_image_ref;
   CodecImage* codec_image = nullptr;
   CreateVideoFrameInternal(std::move(output_buffer), std::move(texture_owner_),
                            timestamp, natural_size,
-                           std::move(promotion_hint_cb), &frame, &texture,
-                           &codec_image);
+                           std::move(promotion_hint_cb), &frame,
+                           &shared_image_ref, &codec_image);
   TRACE_EVENT0("media", "GpuVideoFrameFactory::CreateVideoFrame");
-  if (!frame || !texture)
+  if (!frame || !shared_image_ref)
     return;
 
   // Try to render this frame if possible.
   internal::MaybeRenderEarly(&images_);
 
-  // Callback to notify us when |texture| is going to drop its ref to the
-  // underlying texture.  This happens when we (a) are notified that |frame|
-  // has been released by the renderer and the sync token has cleared, or (b)
-  // when the stub is destroyed.  In the former case, we want to release any
-  // codec resources as quickly as possible so that we can re-use them.  In
-  // the latter case, decoding has stopped and we want to release any buffers
-  // so that the MediaCodec instance can clean up.  Note that the texture will
-  // remain renderable, but it won't necessarily refer to the frame it was
-  // supposed to; it'll be the most recently rendered frame.
-  auto cleanup_cb = base::BindOnce([](AbstractTexture* texture) {
-    gl::GLImage* image = texture->GetImage();
-    if (image)
-      static_cast<CodecImage*>(image)->ReleaseCodecBuffer();
-  });
-  texture->SetCleanupCallback(std::move(cleanup_cb));
-
   // Note that this keeps the pool around while any texture is.
-  auto drop_texture_ref = base::BindOnce(
-      [](scoped_refptr<TexturePool> texture_pool, AbstractTexture* texture,
+  auto drop_shared_image_ref = base::BindOnce(
+      [](scoped_refptr<SharedImagePool> shared_image_pool,
+         gpu::SharedImageRepresentationFactoryRef* shared_image_ref,
          const gpu::SyncToken& sync_token) {
-        texture_pool->ReleaseTexture(texture, sync_token);
+        shared_image_pool->ReleaseSharedImage(shared_image_ref, sync_token);
       },
-      texture_pool_, base::Unretained(texture.get()));
-  texture_pool_->AddTexture(std::move(texture));
+      shared_image_pool_, base::Unretained(shared_image_ref.get()));
 
-  // Guarantee that the AbstractTexture is released even if the VideoFrame is
+  shared_image_pool_->AddSharedImage(std::move(shared_image_ref));
+
+  // Guarantee that the SharedImageRef is released even if the VideoFrame is
   // dropped. Otherwise we could keep TextureRefs we don't need alive.
   auto release_cb = mojo::WrapCallbackWithDefaultInvokeIfNotRun(
-      BindToCurrentLoop(std::move(drop_texture_ref)), gpu::SyncToken());
+      BindToCurrentLoop(std::move(drop_shared_image_ref)), gpu::SyncToken());
   frame->SetReleaseMailboxCB(std::move(release_cb));
   task_runner->PostTask(FROM_HERE,
                         base::BindOnce(std::move(output_cb), std::move(frame)));
@@ -264,7 +266,8 @@
     gfx::Size natural_size,
     PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb,
     scoped_refptr<VideoFrame>* video_frame_out,
-    std::unique_ptr<AbstractTexture>* texture_out,
+    std::unique_ptr<gpu::SharedImageRepresentationFactoryRef>*
+        shared_image_ref_out,
     CodecImage** codec_image_out) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   if (!MakeContextCurrent(stub_))
@@ -318,7 +321,39 @@
       texture_owner_ ? texture_owner_->GetTextureId() : 0;
   texture->BindStreamTextureImage(image.get(), texture_owner_service_id);
 
-  gpu::Mailbox mailbox = decoder_helper_->CreateMailbox(texture.get());
+  gpu::ContextResult result;
+  auto shared_context = GetSharedContext(stub_, &result);
+  if (!shared_context) {
+    LOG(ERROR) << "GpuVideoFrameFactory: Unable to get a shared context.";
+    ContextStateResultUMA(result);
+    return;
+  }
+
+  // Generate a shared image mailbox.
+  auto mailbox = gpu::Mailbox::GenerateForSharedImage();
+
+  // Create a shared image.
+  // TODO(vikassoni): Hardcoding colorspace to SRGB. Figure how if media has a
+  // colorspace and wire it here.
+  // TODO(vikassoni): This shared image need to be thread safe eventually for
+  // webview to work with shared images.
+  auto shared_image = std::make_unique<SharedImageVideo>(
+      mailbox, gfx::ColorSpace::CreateSRGB(), std::move(image),
+      std::move(texture), std::move(shared_context),
+      false /* is_thread_safe */);
+
+  // Register it with shared image mailbox.
+  DCHECK(stub_->channel()->gpu_channel_manager()->shared_image_manager());
+  std::unique_ptr<gpu::SharedImageRepresentationFactoryRef> shared_image_ref =
+      stub_->channel()->gpu_channel_manager()->shared_image_manager()->Register(
+          std::move(shared_image),
+          stub_->channel()->shared_image_stub()->factory()->memory_tracker());
+
+  // Register it with legacy mailbox.
+  // NOTE: All the video mailbox consumers are using legacy mailbox as of now.
+  shared_image_ref->ProduceLegacyMailbox(
+      stub_->channel()->gpu_channel_manager()->mailbox_manager());
+
   gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
   mailbox_holders[0] =
       gpu::MailboxHolder(mailbox, gpu::SyncToken(), GL_TEXTURE_EXTERNAL_OES);
@@ -357,7 +392,7 @@
                                 !!texture_owner_);
 
   *video_frame_out = std::move(frame);
-  *texture_out = std::move(texture);
+  *shared_image_ref_out = std::move(shared_image_ref);
 }
 
 void GpuVideoFrameFactory::OnWillDestroyStub(bool have_context) {
diff --git a/media/gpu/android/video_frame_factory_impl.h b/media/gpu/android/video_frame_factory_impl.h
index 01c1f2c..85c91db 100644
--- a/media/gpu/android/video_frame_factory_impl.h
+++ b/media/gpu/android/video_frame_factory_impl.h
@@ -5,10 +5,13 @@
 #ifndef MEDIA_GPU_ANDROID_VIDEO_FRAME_FACTORY_IMPL_
 #define MEDIA_GPU_ANDROID_VIDEO_FRAME_FACTORY_IMPL_
 
+#include <memory>
+
 #include "base/optional.h"
 #include "base/single_thread_task_runner.h"
 #include "gpu/command_buffer/service/abstract_texture.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "gpu/command_buffer/service/shared_image_representation.h"
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "gpu/ipc/service/command_buffer_stub.h"
 #include "media/base/video_frame.h"
@@ -23,7 +26,7 @@
 namespace media {
 class CodecImageGroup;
 class GpuVideoFrameFactory;
-class TexturePool;
+class SharedImagePool;
 
 // VideoFrameFactoryImpl creates CodecOutputBuffer backed VideoFrames and tries
 // to eagerly render them to their surface to release the buffers back to the
@@ -97,7 +100,8 @@
       gfx::Size natural_size,
       PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb,
       scoped_refptr<VideoFrame>* video_frame_out,
-      std::unique_ptr<gpu::gles2::AbstractTexture>* texture_out,
+      std::unique_ptr<gpu::SharedImageRepresentationFactoryRef>*
+          shared_image_ref_out,
       CodecImage** codec_image_out);
 
   void OnWillDestroyStub(bool have_context) override;
@@ -123,8 +127,8 @@
   // replace this when SetImageGroup() is called.
   scoped_refptr<CodecImageGroup> image_group_;
 
-  // Pool which owns all the textures that we create.
-  scoped_refptr<TexturePool> texture_pool_;
+  // Pool which owns all the shared image refs that we create.
+  scoped_refptr<SharedImagePool> shared_image_pool_;
 
   THREAD_CHECKER(thread_checker_);
   base::WeakPtrFactory<GpuVideoFrameFactory> weak_factory_;
diff --git a/media/gpu/test/video_player/frame_renderer_thumbnail.cc b/media/gpu/test/video_player/frame_renderer_thumbnail.cc
index 048ad3cc..4a94e36 100644
--- a/media/gpu/test/video_player/frame_renderer_thumbnail.cc
+++ b/media/gpu/test/video_player/frame_renderer_thumbnail.cc
@@ -8,6 +8,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "build/build_config.h"
+#include "media/base/bind_to_current_loop.h"
 #include "media/gpu/test/rendering_helper.h"
 #include "media/gpu/test/video_decode_accelerator_unittest_helpers.h"
 #include "ui/gfx/codec/png_codec.h"
@@ -197,8 +198,8 @@
 
   // Create a new video frame associated with the mailbox.
   base::OnceCallback<void(const gpu::SyncToken&)> mailbox_holder_release_cb =
-      base::BindOnce(&FrameRendererThumbnail::DeleteTexture,
-                     base::Unretained(this), mailbox);
+      BindToCurrentLoop(base::BindOnce(&FrameRendererThumbnail::DeleteTexture,
+                                       base::Unretained(this), mailbox));
   scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
       pixel_format, mailbox_holders, std::move(mailbox_holder_release_cb),
       texture_size, gfx::Rect(texture_size), texture_size, base::TimeDelta());
@@ -424,7 +425,7 @@
 
 void FrameRendererThumbnail::DeleteTexture(const gpu::Mailbox& mailbox,
                                            const gpu::SyncToken&) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(renderer_sequence_checker_);
 
   base::AutoLock auto_lock(renderer_lock_);
   auto it = mailbox_texture_map_.find(mailbox);
diff --git a/media/gpu/test/video_player/frame_renderer_thumbnail.h b/media/gpu/test/video_player/frame_renderer_thumbnail.h
index 033f8a0..cebe2c4 100644
--- a/media/gpu/test/video_player/frame_renderer_thumbnail.h
+++ b/media/gpu/test/video_player/frame_renderer_thumbnail.h
@@ -84,7 +84,7 @@
   const std::vector<uint8_t> ConvertThumbnailToRGBA()
       EXCLUSIVE_LOCKS_REQUIRED(renderer_lock_);
 
-  // Destroy the texture associated with the specified |mailbox|.
+  // Destroy the texture associated with the |mailbox| on the renderer thread.
   void DeleteTexture(const gpu::Mailbox& mailbox, const gpu::SyncToken&);
 
   // The number of frames rendered so far.
diff --git a/media/gpu/test/video_player/test_vda_video_decoder.cc b/media/gpu/test/video_player/test_vda_video_decoder.cc
index 6e9b7ef..bfa1a5b 100644
--- a/media/gpu/test/video_player/test_vda_video_decoder.cc
+++ b/media/gpu/test/video_player/test_vda_video_decoder.cc
@@ -50,7 +50,9 @@
   weak_this_factory_.InvalidateWeakPtrs();
 
   // Delete all video frames and related textures.
+  frame_renderer_->AcquireGLContext();
   video_frames_.clear();
+  frame_renderer_->ReleaseGLContext();
 }
 
 void TestVDAVideoDecoder::Initialize(const VideoDecoderConfig& config,
@@ -63,6 +65,7 @@
 
   // Create decoder factory.
   std::unique_ptr<GpuVideoDecodeAcceleratorFactory> decoder_factory;
+  frame_renderer_->AcquireGLContext();
   bool hasGLContext = frame_renderer_->GetGLContext() != nullptr;
   if (hasGLContext) {
     decoder_factory = GpuVideoDecodeAcceleratorFactory::Create(
@@ -75,6 +78,7 @@
   } else {
     decoder_factory = GpuVideoDecodeAcceleratorFactory::CreateWithNoGL();
   }
+  frame_renderer_->ReleaseGLContext();
 
   if (!decoder_factory) {
     LOG_ASSERT(decoder_) << "Failed to create VideoDecodeAccelerator factory";
diff --git a/media/gpu/test/video_player/video_decoder_client.cc b/media/gpu/test/video_player/video_decoder_client.cc
index 15ca2b3..09808e0 100644
--- a/media/gpu/test/video_player/video_decoder_client.cc
+++ b/media/gpu/test/video_player/video_decoder_client.cc
@@ -9,22 +9,19 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "media/base/bind_to_current_loop.h"
-#include "media/base/video_frame.h"
-#include "media/gpu/gpu_video_decode_accelerator_factory.h"
-#include "media/gpu/linux/platform_video_frame_utils.h"
+#include "media/base/waiting.h"
+#include "media/gpu/macros.h"
 #include "media/gpu/test/video_decode_accelerator_unittest_helpers.h"
-#include "media/gpu/test/video_frame_helpers.h"
 #include "media/gpu/test/video_player/frame_renderer.h"
-
-#define DVLOGF(level) DVLOG(level) << __func__ << "(): "
-#define VLOGF(level) VLOG(level) << __func__ << "(): "
+#include "media/gpu/test/video_player/test_vda_video_decoder.h"
+#include "media/gpu/test/video_player/video.h"
 
 namespace media {
 namespace test {
 
 VideoDecoderClient::VideoDecoderClient(
+    const Video* video,
     const VideoPlayer::EventCallback& event_cb,
     std::unique_ptr<FrameRenderer> renderer,
     std::vector<std::unique_ptr<VideoFrameProcessor>> frame_processors,
@@ -32,9 +29,10 @@
     : event_cb_(event_cb),
       frame_renderer_(std::move(renderer)),
       frame_processors_(std::move(frame_processors)),
+      decoder_client_config_(config),
       decoder_client_thread_("VDAClientDecoderThread"),
       decoder_client_state_(VideoDecoderClientState::kUninitialized),
-      decoder_client_config_(config),
+      video_(video),
       weak_this_factory_(this) {
   DETACH_FROM_SEQUENCE(decoder_client_sequence_checker_);
   weak_this_ = weak_this_factory_.GetWeakPtr();
@@ -46,12 +44,6 @@
   DestroyDecoder();
   decoder_client_thread_.Stop();
 
-  // Clear video frames, triggering associated destruction callbacks while we
-  // still have a GLcontext.
-  frame_renderer_->AcquireGLContext();
-  video_frames_.clear();
-  frame_renderer_->ReleaseGLContext();
-
   // Wait until the frame processors are done, before destroying them. As the
   // decoder has been destroyed no new frames will be sent to the processors.
   WaitForFrameProcessors();
@@ -59,12 +51,13 @@
 
 // static
 std::unique_ptr<VideoDecoderClient> VideoDecoderClient::Create(
+    const Video* video,
     const VideoPlayer::EventCallback& event_cb,
     std::unique_ptr<FrameRenderer> frame_renderer,
     std::vector<std::unique_ptr<VideoFrameProcessor>> frame_processors,
     const VideoDecoderClientConfig& config) {
   auto decoder_client = base::WrapUnique(
-      new VideoDecoderClient(event_cb, std::move(frame_renderer),
+      new VideoDecoderClient(video, event_cb, std::move(frame_renderer),
                              std::move(frame_processors), config));
   if (!decoder_client->Initialize()) {
     return nullptr;
@@ -75,32 +68,29 @@
 bool VideoDecoderClient::Initialize() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(video_player_sequence_checker_);
   DCHECK(!decoder_client_thread_.IsRunning());
-  DCHECK(event_cb_.MaybeValid() && frame_renderer_);
+  DCHECK(event_cb_ && frame_renderer_);
+  DCHECK(video_);
+
+  encoded_data_helper_ =
+      std::make_unique<EncodedDataHelper>(video_->Data(), video_->Profile());
 
   if (!decoder_client_thread_.Start()) {
     VLOGF(1) << "Failed to start decoder thread";
     return false;
   }
 
-  // Create a decoder factory, which will be used to create decoders.
-  base::WaitableEvent done;
-  decoder_client_thread_.task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&VideoDecoderClient::CreateDecoderFactoryTask,
-                                weak_this_, &done));
-  done.Wait();
+  CreateDecoder();
 
   return true;
 }
 
-void VideoDecoderClient::CreateDecoder(
-    const VideoDecodeAccelerator::Config& config,
-    const std::vector<uint8_t>& stream) {
+void VideoDecoderClient::CreateDecoder() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(video_player_sequence_checker_);
 
   base::WaitableEvent done;
   decoder_client_thread_.task_runner()->PostTask(
       FROM_HERE, base::BindOnce(&VideoDecoderClient::CreateDecoderTask,
-                                weak_this_, config, &stream, &done));
+                                weak_this_, &done));
   done.Wait();
 }
 
@@ -146,218 +136,33 @@
       FROM_HERE, base::BindOnce(&VideoDecoderClient::ResetTask, weak_this_));
 }
 
-void VideoDecoderClient::ProvidePictureBuffers(
-    uint32_t requested_num_of_buffers,
-    VideoPixelFormat pixel_format,
-    uint32_t textures_per_buffer,
-    const gfx::Size& size,
-    uint32_t texture_target) {
+void VideoDecoderClient::CreateDecoderTask(base::WaitableEvent* done) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-  DCHECK_NE(pixel_format, PIXEL_FORMAT_UNKNOWN);
-  DCHECK_EQ(textures_per_buffer, 1u);
-  DVLOGF(4) << "Requested " << requested_num_of_buffers
-            << " picture buffers with size " << size.height() << "x"
-            << size.height();
-
-  // If using import mode, create a set of DMABuf-backed video frames.
-  if (decoder_client_config_.allocation_mode == AllocationMode::kImport) {
-    std::vector<PictureBuffer> picture_buffers;
-    for (uint32_t i = 0; i < requested_num_of_buffers; ++i) {
-      picture_buffers.emplace_back(GetNextPictureBufferId(), size);
-    }
-    decoder_->AssignPictureBuffers(picture_buffers);
-
-    // Create a video frame for each of the picture buffers and provide memory
-    // handles to the video frame's data to the decoder.
-    for (const PictureBuffer& picture_buffer : picture_buffers) {
-      scoped_refptr<VideoFrame> video_frame =
-          CreatePlatformVideoFrame(pixel_format, size);
-      LOG_ASSERT(video_frame) << "Failed to create video frame";
-      video_frames_.emplace(picture_buffer.id(), video_frame);
-      gfx::GpuMemoryBufferHandle handle =
-          CreateGpuMemoryBufferHandle(video_frame.get());
-      LOG_ASSERT(!handle.is_null()) << "Failed to create GPU memory handle";
-      decoder_->ImportBufferForPicture(picture_buffer.id(), pixel_format,
-                                       std::move(handle));
-    }
-  }
-
-  // If using allocate mode, request a set of texture-backed video frames from
-  // the renderer.
-  if (decoder_client_config_.allocation_mode == AllocationMode::kAllocate) {
-    std::vector<PictureBuffer> picture_buffers;
-    for (uint32_t i = 0; i < requested_num_of_buffers; ++i) {
-      uint32_t texture_id;
-      auto video_frame = frame_renderer_->CreateVideoFrame(
-          pixel_format, size, texture_target, &texture_id);
-      LOG_ASSERT(video_frame) << "Failed to create video frame";
-      int32_t picture_buffer_id = GetNextPictureBufferId();
-      PictureBuffer::TextureIds texture_ids(1, texture_id);
-      picture_buffers.emplace_back(picture_buffer_id, size, texture_ids,
-                                   texture_ids, texture_target, pixel_format);
-      video_frames_.emplace(picture_buffer_id, std::move(video_frame));
-    }
-    // The decoder requires an active GL context to allocate memory.
-    frame_renderer_->AcquireGLContext();
-    decoder_->AssignPictureBuffers(picture_buffers);
-    frame_renderer_->ReleaseGLContext();
-  }
-}
-
-void VideoDecoderClient::DismissPictureBuffer(int32_t picture_buffer_id) {
-  // TODO(dstaessens@) support dismissing picture buffers.
-  NOTIMPLEMENTED();
-}
-
-void VideoDecoderClient::PictureReady(const Picture& picture) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-  DVLOGF(4) << "Picture buffer ID: " << picture.picture_buffer_id();
-
-  FireEvent(VideoPlayerEvent::kFrameDecoded);
-
-  auto it = video_frames_.find(picture.picture_buffer_id());
-  LOG_ASSERT(it != video_frames_.end());
-  scoped_refptr<VideoFrame> video_frame = it->second;
-
-  // When using import mode, we wrap the video frame in another video frame that
-  // calls ReusePictureBufferTask() upon destruction. When the renderer and
-  // video frame processors are done using the video frame, the associated
-  // picture buffer will automatically be flagged for reuse.
-  if (decoder_client_config_.allocation_mode == AllocationMode::kImport) {
-    base::OnceClosure delete_cb = BindToCurrentLoop(
-        base::BindOnce(&VideoDecoderClient::ReusePictureBufferTask,
-                       base::Unretained(this), picture.picture_buffer_id()));
-
-    scoped_refptr<VideoFrame> wrapped_video_frame = VideoFrame::WrapVideoFrame(
-        video_frame, video_frame->format(), video_frame->visible_rect(),
-        video_frame->visible_rect().size());
-    wrapped_video_frame->AddDestructionObserver(std::move(delete_cb));
-
-    frame_renderer_->RenderFrame(wrapped_video_frame);
-
-    for (auto& frame_processor : frame_processors_)
-      frame_processor->ProcessVideoFrame(wrapped_video_frame,
-                                         current_frame_index_);
-  }
-
-  // When using allocate mode, direct texture memory access is not supported.
-  // Since this is required by the video frame processors we can't use these
-  // here. Wrapping a video frame inside another video frame is also not
-  // supported, so we have to render the frame and return the picture buffer
-  // synchronously here. See http://crbug/362521.
-  if (decoder_client_config_.allocation_mode == AllocationMode::kAllocate) {
-    frame_renderer_->RenderFrame(video_frame);
-    ReusePictureBufferTask(picture.picture_buffer_id());
-    return;
-  }
-
-  current_frame_index_++;
-}
-
-void VideoDecoderClient::NotifyEndOfBitstreamBuffer(
-    int32_t bitstream_buffer_id) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-  DCHECK_NE(VideoDecoderClientState::kIdle, decoder_client_state_);
-  DVLOGF(4);
-
-  num_outstanding_decode_requests_--;
-
-  // Queue the next fragment to be decoded.
-  decoder_client_thread_.task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&VideoDecoderClient::DecodeNextFragmentTask, weak_this_));
-}
-
-void VideoDecoderClient::NotifyFlushDone() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-  DCHECK_EQ(0u, num_outstanding_decode_requests_);
-
-  decoder_client_state_ = VideoDecoderClientState::kIdle;
-  FireEvent(VideoPlayerEvent::kFlushDone);
-}
-
-void VideoDecoderClient::NotifyResetDone() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-  DCHECK_EQ(0u, num_outstanding_decode_requests_);
-
-  // We finished resetting to a different point in the stream, so we should
-  // update the frame index. Currently only resetting to the start of the stream
-  // is supported, so we can set the frame index to zero here.
-  current_frame_index_ = 0;
-
-  decoder_client_state_ = VideoDecoderClientState::kIdle;
-  FireEvent(VideoPlayerEvent::kResetDone);
-}
-
-void VideoDecoderClient::NotifyError(VideoDecodeAccelerator::Error error) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-
-  switch (error) {
-    case VideoDecodeAccelerator::ILLEGAL_STATE:
-      LOG(FATAL) << "ILLEGAL_STATE";
-      break;
-    case VideoDecodeAccelerator::INVALID_ARGUMENT:
-      LOG(FATAL) << "INVALID_ARGUMENT";
-      break;
-    case VideoDecodeAccelerator::UNREADABLE_INPUT:
-      LOG(FATAL) << "UNREADABLE_INPUT";
-      break;
-    case VideoDecodeAccelerator::PLATFORM_FAILURE:
-      LOG(FATAL) << "PLATFORM_FAILURE";
-      break;
-    default:
-      LOG(FATAL) << "Unknown error";
-      break;
-  }
-}
-
-void VideoDecoderClient::CreateDecoderFactoryTask(base::WaitableEvent* done) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-  LOG_ASSERT(!decoder_factory_) << "Decoder factory already created";
-  DVLOGF(4);
-
-  frame_renderer_->AcquireGLContext();
-  bool hasGLContext = frame_renderer_->GetGLContext() != nullptr;
-  frame_renderer_->ReleaseGLContext();
-
-  if (hasGLContext) {
-    decoder_factory_ = GpuVideoDecodeAcceleratorFactory::Create(
-        base::BindRepeating(&FrameRenderer::GetGLContext,
-                            base::Unretained(frame_renderer_.get())),
-        base::BindRepeating([]() { return true; }),
-        base::BindRepeating([](uint32_t, uint32_t,
-                               const scoped_refptr<gl::GLImage>&,
-                               bool) { return true; }));
-  } else {
-    decoder_factory_ = GpuVideoDecodeAcceleratorFactory::CreateWithNoGL();
-  }
-
-  done->Signal();
-}
-
-void VideoDecoderClient::CreateDecoderTask(
-    VideoDecodeAccelerator::Config config,
-    const std::vector<uint8_t>* stream,
-    base::WaitableEvent* done) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-  LOG_ASSERT(decoder_factory_) << "Decoder factory not created yet";
   LOG_ASSERT(!decoder_) << "Can't create decoder: already created";
-  DVLOGF(4) << "Profile: " << config.profile;
+  LOG_ASSERT(video_);
 
-  decoder_config_ = config;
-  encoded_data_helper_ =
-      std::make_unique<EncodedDataHelper>(*stream, config.profile);
+  VideoDecoderConfig config(
+      video_->Codec(), video_->Profile(), PIXEL_FORMAT_I420, VideoColorSpace(),
+      VIDEO_ROTATION_0, video_->Resolution(), gfx::Rect(video_->Resolution()),
+      video_->Resolution(), std::vector<uint8_t>(0), EncryptionScheme());
 
-  gpu::GpuDriverBugWorkarounds gpu_driver_bug_workarounds;
-  gpu::GpuPreferences gpu_preferences;
-  decoder_ = decoder_factory_->CreateVDA(
-      this, config, gpu_driver_bug_workarounds, gpu_preferences);
-  LOG_ASSERT(decoder_) << "Failed creating a VDA";
+  VideoDecoder::InitCB init_cb = BindToCurrentLoop(base::BindRepeating(
+      &VideoDecoderClient::DecoderInitializedTask, weak_this_));
+  VideoDecoder::OutputCB output_cb = BindToCurrentLoop(
+      base::BindRepeating(&VideoDecoderClient::FrameReadyTask, weak_this_));
+  WaitingCB waiting_cb =
+      base::BindRepeating([](WaitingReason) { NOTIMPLEMENTED(); });
 
-  decoder_->TryToSetupDecodeOnSeparateThread(
-      weak_this_, base::ThreadTaskRunnerHandle::Get());
+  // TODO(dstaessens@) Currently we always create a VDA-based video decoder,
+  // change to use a factory that can create different types of decoders.
+  decoder_ = base::WrapUnique(
+      new TestVDAVideoDecoder(decoder_client_config_.allocation_mode,
+                              gfx::ColorSpace(), frame_renderer_.get()));
+  decoder_->Initialize(config, false, nullptr, init_cb, output_cb, waiting_cb);
 
-  decoder_client_state_ = VideoDecoderClientState::kIdle;
+  DCHECK_LE(decoder_client_config_.max_outstanding_decode_requests,
+            static_cast<size_t>(decoder_->GetMaxDecodeRequests()));
+
   done->Signal();
 }
 
@@ -370,18 +175,34 @@
   // Invalidate all scheduled tasks.
   weak_this_factory_.InvalidateWeakPtrs();
 
-  // Destroying a decoder requires an active GL context.
-  // TODO(dstaessens@) Investigate making the decoder manage the GL context.
+  // Destroy the decoder. This will destroy all video frames, which requires an
+  // active GLcontext.
   if (decoder_) {
-    frame_renderer_->AcquireGLContext();
     decoder_.reset();
-    frame_renderer_->ReleaseGLContext();
   }
 
   decoder_client_state_ = VideoDecoderClientState::kUninitialized;
   done->Signal();
 }
 
+void VideoDecoderClient::PlayTask() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
+  DVLOGF(4);
+
+  // This method should only be called when the decoder client is idle. If
+  // called e.g. while flushing, the behavior is undefined.
+  ASSERT_EQ(decoder_client_state_, VideoDecoderClientState::kIdle);
+
+  // Start decoding the first fragments. While in the decoding state new
+  // fragments will automatically be fed to the decoder, when the decoder
+  // notifies us it reached the end of a bitstream buffer.
+  decoder_client_state_ = VideoDecoderClientState::kDecoding;
+  for (size_t i = 0; i < decoder_client_config_.max_outstanding_decode_requests;
+       ++i) {
+    DecodeNextFragmentTask();
+  }
+}
+
 void VideoDecoderClient::DecodeNextFragmentTask() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
   DVLOGF(4);
@@ -404,54 +225,32 @@
     return;
   }
 
-  // Create shared memory to store the fragment.
-  // TODO(dstaessens@) Investigate using import mode when allocating memory.
-  base::SharedMemory shm;
-  bool success = shm.CreateAndMapAnonymous(fragment_size);
-  LOG_ASSERT(success) << "Failed to create shared memory";
-  memcpy(shm.memory(), fragment_bytes.data(), fragment_size);
-  base::SharedMemoryHandle handle = shm.TakeHandle();
-  LOG_ASSERT(handle.IsValid()) << "Failed to take shared memory handle";
+  scoped_refptr<DecoderBuffer> bitstream_buffer = DecoderBuffer::CopyFrom(
+      reinterpret_cast<const uint8_t*>(fragment_bytes.data()), fragment_size);
+  VideoDecoder::DecodeCB decode_cb = BindToCurrentLoop(
+      base::BindRepeating(&VideoDecoderClient::DecodeDoneTask, weak_this_));
 
-  int32_t bitstream_buffer_id = GetNextBitstreamBufferId();
-  BitstreamBuffer bitstream_buffer(bitstream_buffer_id, handle, fragment_size);
-
-  DVLOGF(4) << "Bitstream buffer id: " << bitstream_buffer_id;
-  decoder_->Decode(bitstream_buffer);
+  decoder_->Decode(std::move(bitstream_buffer), decode_cb);
   num_outstanding_decode_requests_++;
 
   // Throw event when we encounter a config info in a H.264 stream.
   if (media::test::EncodedDataHelper::HasConfigInfo(
           reinterpret_cast<const uint8_t*>(fragment_bytes.data()),
-          fragment_size, decoder_config_.profile)) {
+          fragment_size, video_->Profile())) {
     FireEvent(VideoPlayerEvent::kConfigInfo);
   }
 }
 
-void VideoDecoderClient::PlayTask() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-  DVLOGF(4);
-
-  // This method should only be called when the decoder client is idle. If
-  // called e.g. while flushing, the behavior is undefined.
-  ASSERT_EQ(decoder_client_state_, VideoDecoderClientState::kIdle);
-
-  // Start decoding the first fragments. While in the decoding state new
-  // fragments will automatically be fed to the decoder, when the decoder
-  // notifies us it reached the end of a bitstream buffer.
-  decoder_client_state_ = VideoDecoderClientState::kDecoding;
-  for (size_t i = 0; i < decoder_client_config_.max_outstanding_decode_requests;
-       ++i)
-    DecodeNextFragmentTask();
-}
-
 void VideoDecoderClient::FlushTask() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
   DVLOGF(4);
 
   // Changing the state to flushing will abort any pending decodes.
   decoder_client_state_ = VideoDecoderClientState::kFlushing;
-  decoder_->Flush();
+  VideoDecoder::DecodeCB flush_done_cb = BindToCurrentLoop(
+      base::BindRepeating(&VideoDecoderClient::FlushDoneTask, weak_this_));
+
+  decoder_->Decode(DecoderBuffer::CreateEOSBuffer(), flush_done_cb);
   FireEvent(VideoPlayerEvent::kFlushing);
 }
 
@@ -463,10 +262,83 @@
   decoder_client_state_ = VideoDecoderClientState::kResetting;
   // TODO(dstaessens@) Allow resetting to any point in the stream.
   encoded_data_helper_->Rewind();
-  decoder_->Reset();
+  base::RepeatingClosure reset_done_cb = BindToCurrentLoop(
+      base::BindRepeating(&VideoDecoderClient::ResetDoneTask, weak_this_));
+  decoder_->Reset(reset_done_cb);
   FireEvent(VideoPlayerEvent::kResetting);
 }
 
+void VideoDecoderClient::DecoderInitializedTask(bool status) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
+  DCHECK_EQ(VideoDecoderClientState::kUninitialized, decoder_client_state_);
+  LOG_ASSERT(status) << "Initializing decoder failed";
+
+  decoder_client_state_ = VideoDecoderClientState::kIdle;
+  FireEvent(VideoPlayerEvent::kInitialized);
+}
+
+void VideoDecoderClient::DecodeDoneTask(media::DecodeStatus status) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
+  DCHECK_NE(VideoDecoderClientState::kIdle, decoder_client_state_);
+  LOG_ASSERT((status == media::DecodeStatus::OK) ||
+             (status == media::DecodeStatus::ABORTED &&
+              decoder_client_state_ == VideoDecoderClientState::kResetting))
+      << "Decoding failed: " << GetDecodeStatusString(status);
+
+  DVLOGF(4);
+
+  num_outstanding_decode_requests_--;
+
+  // Queue the next fragment to be decoded.
+  decoder_client_thread_.task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&VideoDecoderClient::DecodeNextFragmentTask, weak_this_));
+}
+
+void VideoDecoderClient::FrameReadyTask(
+    const scoped_refptr<VideoFrame>& video_frame) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
+
+  // When using allocate mode the frame will be reused after this function, so
+  // the frame should be rendered synchronously in this case.
+  frame_renderer_->RenderFrame(video_frame);
+
+  // When using allocate mode, direct texture memory access is not supported.
+  // Since this is required by the video frame processors we can't use these.
+  if (decoder_client_config_.allocation_mode == AllocationMode::kImport) {
+    for (auto& frame_processor : frame_processors_)
+      frame_processor->ProcessVideoFrame(video_frame, current_frame_index_);
+  }
+
+  // Notify the test a frame has been decoded. We should only do this after
+  // scheduling the frame to be processed, so calling WaitForFrameProcessors()
+  // after receiving this event will always guarantee the frame to be processed.
+  FireEvent(VideoPlayerEvent::kFrameDecoded);
+
+  current_frame_index_++;
+}
+
+void VideoDecoderClient::FlushDoneTask(media::DecodeStatus status) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
+  DCHECK_EQ(0u, num_outstanding_decode_requests_);
+
+  decoder_client_state_ = VideoDecoderClientState::kIdle;
+  FireEvent(VideoPlayerEvent::kFlushDone);
+}
+
+void VideoDecoderClient::ResetDoneTask() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
+  DCHECK_EQ(0u, num_outstanding_decode_requests_);
+
+  // We finished resetting to a different point in the stream, so we should
+  // update the frame index. Currently only resetting to the start of the stream
+  // is supported, so we can set the frame index to zero here.
+  current_frame_index_ = 0;
+
+  decoder_client_state_ = VideoDecoderClientState::kIdle;
+  FireEvent(VideoPlayerEvent::kResetDone);
+}
+
 void VideoDecoderClient::FireEvent(VideoPlayerEvent event) {
   bool continue_decoding = event_cb_.Run(event);
   if (!continue_decoding) {
@@ -475,32 +347,5 @@
   }
 }
 
-void VideoDecoderClient::ReusePictureBufferTask(int32_t picture_buffer_id) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-  DCHECK(decoder_);
-  DVLOGF(4) << "Picture buffer ID: " << picture_buffer_id;
-
-  // Notify the decoder the picture buffer can be reused. The decoder will only
-  // request a limited set of picture buffers, when it runs out it will wait
-  // until picture buffers are flagged for reuse.
-  decoder_->ReusePictureBuffer(picture_buffer_id);
-}
-
-int32_t VideoDecoderClient::GetNextBitstreamBufferId() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-  // The bitstream buffer ID should always be positive, negative values are
-  // reserved for uninitialized buffers.
-  next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x7FFFFFFF;
-  return next_bitstream_buffer_id_;
-}
-
-int32_t VideoDecoderClient::GetNextPictureBufferId() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
-  // The picture buffer ID should always be positive, negative values are
-  // reserved for uninitialized buffers.
-  next_picture_buffer_id_ = (next_picture_buffer_id_ + 1) & 0x7FFFFFFF;
-  return next_picture_buffer_id_;
-}
-
 }  // namespace test
 }  // namespace media
diff --git a/media/gpu/test/video_player/video_decoder_client.h b/media/gpu/test/video_player/video_decoder_client.h
index 0c153d1..73756dc6 100644
--- a/media/gpu/test/video_player/video_decoder_client.h
+++ b/media/gpu/test/video_player/video_decoder_client.h
@@ -13,12 +13,14 @@
 #include "base/macros.h"
 #include "base/sequence_checker.h"
 #include "base/threading/thread.h"
+#include "media/base/decode_status.h"
+#include "media/base/video_decoder.h"
+#include "media/base/video_decoder_config.h"
 #include "media/gpu/test/video_player/video_player.h"
-#include "media/video/video_decode_accelerator.h"
 
 namespace media {
 
-class GpuVideoDecodeAcceleratorFactory;
+class Video;
 class VideoFrame;
 
 namespace test {
@@ -53,29 +55,23 @@
 // All communication with the decoder is done on the |decoder_client_thread_|,
 // so callbacks scheduled by the decoder can be executed asynchronously. This is
 // necessary if we don't want to interrupt the test flow.
-class VideoDecoderClient : public VideoDecodeAccelerator::Client {
+class VideoDecoderClient {
  public:
-  ~VideoDecoderClient() override;
+  ~VideoDecoderClient();
 
-  // Return an instance of the VideoDecoderClient. The |frame_renderer| and
-  // |frame_processors| will not be owned by the decoder client, the caller
+  // Return an instance of the VideoDecoderClient. The |video|, |frame_renderer|
+  // and |frame_processors| will not be owned by the decoder client, the caller
   // should guarantee they outlive the decoder client. The |event_cb| will be
   // called whenever an event occurs (e.g. frame decoded) and should be
-  // thread-safe.
+  // thread-safe. Initialization is performed asynchronous, upon completion a
+  // 'kInitialized' event will be thrown.
   static std::unique_ptr<VideoDecoderClient> Create(
+      const Video* const video,
       const VideoPlayer::EventCallback& event_cb,
       std::unique_ptr<FrameRenderer> frame_renderer,
       std::vector<std::unique_ptr<VideoFrameProcessor>> frame_processors,
       const VideoDecoderClientConfig& config);
 
-  // Create a decoder with specified |config| and video |stream|. The video
-  // will not be owned by the decoder client, the caller should guarantee it
-  // exists until DestroyDecoder() is called.
-  void CreateDecoder(const VideoDecodeAccelerator::Config& config,
-                     const std::vector<uint8_t>& stream);
-  // Destroy the currently active decoder.
-  void DestroyDecoder();
-
   // Wait until all frame processors have finished processing. Returns whether
   // processing was successful.
   bool WaitForFrameProcessors();
@@ -103,79 +99,71 @@
   };
 
   VideoDecoderClient(
+      const Video* const video,
       const VideoPlayer::EventCallback& event_cb,
       std::unique_ptr<FrameRenderer> renderer,
       std::vector<std::unique_ptr<VideoFrameProcessor>> frame_processors,
       const VideoDecoderClientConfig& config);
 
+  // Initialize the video decoder client.
   bool Initialize();
 
-  // VideoDecodeAccelerator::Client implementation
-  void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
-                             VideoPixelFormat pixel_format,
-                             uint32_t textures_per_buffer,
-                             const gfx::Size& size,
-                             uint32_t texture_target) override;
-  void DismissPictureBuffer(int32_t picture_buffer_id) override;
-  void PictureReady(const Picture& picture) override;
-  void NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) override;
-  void NotifyFlushDone() override;
-  void NotifyResetDone() override;
-  void NotifyError(VideoDecodeAccelerator::Error error) override;
+  // Create a new decoder for |video_|.
+  void CreateDecoder();
+  // Destroy the currently active decoder.
+  void DestroyDecoder();
 
-  void CreateDecoderFactoryTask(base::WaitableEvent* done);
-  void CreateDecoderTask(VideoDecodeAccelerator::Config config,
-                         const std::vector<uint8_t>* stream,
-                         base::WaitableEvent* done);
+  // Create a video decoder for |video_| on the |decoder_client_thread_|.
+  void CreateDecoderTask(base::WaitableEvent* done);
+  // Destroy the active video |decoder_| on the |decoder_client_thread_|.
   void DestroyDecoderTask(base::WaitableEvent* done);
 
-  // Instruct the decoder to decode the next video stream fragment.
-  void DecodeNextFragmentTask();
-  // Start decoding video stream fragments.
+  // Start decoding video stream fragments on the |decoder_client_thread_|.
   void PlayTask();
-  // Instruct the decoder to perform a flush.
+  // Instruct the decoder to decode the next video stream fragment on the
+  // |decoder_client_thread_|.
+  void DecodeNextFragmentTask();
+  // Instruct the decoder to perform a flush on the |decoder_client_thread_|.
   void FlushTask();
-  // Instruct the decoder to perform a Reset.
+  // Instruct the decoder to perform a Reset on the |decoder_client_thread_|.
   void ResetTask();
 
+  // The below functions are callbacks provided to the video decoder. They are
+  // all executed on the |decoder_client_thread_|.
+  // Called by the decoder when initialization has completed.
+  void DecoderInitializedTask(bool status);
+  // Called by the decoder when a fragment has been decoded.
+  void DecodeDoneTask(media::DecodeStatus status);
+  // Called by the decoder when a video frame is ready.
+  void FrameReadyTask(const scoped_refptr<VideoFrame>& video_frame);
+  // Called by the decoder when flushing has completed.
+  void FlushDoneTask(media::DecodeStatus status);
+  // Called by the decoder when resetting has completed.
+  void ResetDoneTask();
+
   // Fire the specified event.
   void FireEvent(VideoPlayerEvent event);
 
-  // Called when a picture buffer is ready to be re-used.
-  void ReusePictureBufferTask(int32_t picture_buffer_id);
-
-  // Get the next bitstream buffer id to be used.
-  int32_t GetNextBitstreamBufferId();
-  // Get the next picture buffer id to be used.
-  int32_t GetNextPictureBufferId();
-
   VideoPlayer::EventCallback event_cb_;
   std::unique_ptr<FrameRenderer> const frame_renderer_;
   std::vector<std::unique_ptr<VideoFrameProcessor>> const frame_processors_;
 
-  std::unique_ptr<GpuVideoDecodeAcceleratorFactory> decoder_factory_;
-  std::unique_ptr<VideoDecodeAccelerator> decoder_;
-  VideoDecodeAccelerator::Config decoder_config_;
+  std::unique_ptr<media::VideoDecoder> decoder_;
+  const VideoDecoderClientConfig decoder_client_config_;
   base::Thread decoder_client_thread_;
 
   // Decoder client state, should only be accessed on the decoder client thread.
   VideoDecoderClientState decoder_client_state_;
 
-  // Map of video frames the decoder uses as output, keyed on picture buffer id.
-  std::map<int32_t, scoped_refptr<VideoFrame>> video_frames_;
-
-  int32_t next_bitstream_buffer_id_ = 0;
-  int32_t next_picture_buffer_id_ = 0;
-
   // Index of the frame that's currently being decoded.
   size_t current_frame_index_ = 0;
   // The current number of outgoing bitstream buffers decode requests.
   size_t num_outstanding_decode_requests_ = 0;
-  // Video decoder client configuration.
-  const VideoDecoderClientConfig decoder_client_config_;
 
   // TODO(dstaessens@) Replace with StreamParser.
   std::unique_ptr<media::test::EncodedDataHelper> encoded_data_helper_;
+  // The video being decoded.
+  const Video* const video_;
 
   SEQUENCE_CHECKER(video_player_sequence_checker_);
   SEQUENCE_CHECKER(decoder_client_sequence_checker_);
diff --git a/media/gpu/test/video_player/video_player.cc b/media/gpu/test/video_player/video_player.cc
index 66a34a73..71a8718 100644
--- a/media/gpu/test/video_player/video_player.cc
+++ b/media/gpu/test/video_player/video_player.cc
@@ -53,20 +53,13 @@
   EventCallback event_cb =
       base::BindRepeating(&VideoPlayer::NotifyEvent, base::Unretained(this));
 
-  decoder_client_ = VideoDecoderClient::Create(
-      event_cb, std::move(frame_renderer), std::move(frame_processors), config);
+  decoder_client_ =
+      VideoDecoderClient::Create(video, event_cb, std::move(frame_renderer),
+                                 std::move(frame_processors), config);
   CHECK(decoder_client_) << "Failed to create decoder client";
 
-  // Create a decoder for the specified video.
-  // TODO(dstaessens@) Remove support for allocate mode, and always use import
-  // mode. Support for allocate mode is temporary maintained for older platforms
-  // that don't support import mode.
-  VideoDecodeAccelerator::Config decoder_config(video->Profile());
-  decoder_config.output_mode =
-      config.allocation_mode == AllocationMode::kImport
-          ? VideoDecodeAccelerator::Config::OutputMode::IMPORT
-          : VideoDecodeAccelerator::Config::OutputMode::ALLOCATE;
-  decoder_client_->CreateDecoder(decoder_config, video->Data());
+  // Wait until initialization is done.
+  WaitForEvent(VideoPlayerEvent::kInitialized);
 
   video_ = video;
   video_player_state_ = VideoPlayerState::kIdle;
diff --git a/media/gpu/test/video_player/video_player.h b/media/gpu/test/video_player/video_player.h
index da5a6112..24007d6 100644
--- a/media/gpu/test/video_player/video_player.h
+++ b/media/gpu/test/video_player/video_player.h
@@ -37,6 +37,7 @@
 };
 
 enum class VideoPlayerEvent : size_t {
+  kInitialized,
   kFrameDecoded,
   kFlushing,
   kFlushDone,
diff --git a/media/gpu/video_decode_accelerator_tests.cc b/media/gpu/video_decode_accelerator_tests.cc
index 421fe56..f494f45 100644
--- a/media/gpu/video_decode_accelerator_tests.cc
+++ b/media/gpu/video_decode_accelerator_tests.cc
@@ -202,7 +202,7 @@
 // decoder, without waiting for the result of the previous decode requests.
 TEST_F(VideoDecoderTest, FlushAtEndOfStream_MultipleOutstandingDecodes) {
   VideoDecoderClientConfig config;
-  config.max_outstanding_decode_requests = 5;
+  config.max_outstanding_decode_requests = 4;
   auto tvp = CreateVideoPlayer(g_env->video_, config);
 
   tvp->Play();
diff --git a/mojo/core/channel.cc b/mojo/core/channel.cc
index acc79e45..7daaaa1 100644
--- a/mojo/core/channel.cc
+++ b/mojo/core/channel.cc
@@ -22,7 +22,6 @@
 #include "mojo/public/cpp/platform/features.h"
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
-#include "base/debug/dump_without_crashing.h"
 #include "base/mac/mach_logging.h"
 #elif defined(OS_WIN)
 #include "base/win/win_util.h"
@@ -798,11 +797,6 @@
 }
 
 void Channel::OnError(Error error) {
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-  // TODO(crbug.com/946372): Remove when fixed.
-  if (base::FeatureList::IsEnabled(features::kMojoChannelMac))
-    base::debug::DumpWithoutCrashing();
-#endif
   if (delegate_)
     delegate_->OnChannelError(error);
 }
diff --git a/mojo/core/channel_mac.cc b/mojo/core/channel_mac.cc
index 1f51d2c1..ea28ae3 100644
--- a/mojo/core/channel_mac.cc
+++ b/mojo/core/channel_mac.cc
@@ -17,6 +17,8 @@
 #include "base/containers/buffer_iterator.h"
 #include "base/containers/circular_deque.h"
 #include "base/containers/span.h"
+#include "base/debug/crash_logging.h"
+#include "base/debug/dump_without_crashing.h"
 #include "base/logging.h"
 #include "base/mac/mach_logging.h"
 #include "base/mac/scoped_mach_msg_destroy.h"
@@ -24,6 +26,7 @@
 #include "base/mac/scoped_mach_vm.h"
 #include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_for_io.h"
+#include "base/strings/stringprintf.h"
 
 extern "C" {
 kern_return_t fileport_makeport(int fd, mach_port_t*);
@@ -248,7 +251,7 @@
       MACH_LOG(ERROR, kr) << "mach_msg send handshake";
 
       base::AutoLock lock(write_lock_);
-      OnWriteErrorLocked(Error::kConnectionFailed);
+      OnWriteErrorLocked(Error::kConnectionFailed, kr);
       return;
     }
 
@@ -385,7 +388,7 @@
               fileport_makeport(handle.GetFD().get(), &descriptor->name);
           if (kr != KERN_SUCCESS) {
             MACH_LOG(ERROR, kr) << "fileport_makeport";
-            OnWriteErrorLocked(Error::kDisconnected);
+            OnWriteErrorLocked(Error::kDisconnected, kr);
             return false;
           }
           descriptor->disposition = MACH_MSG_TYPE_MOVE_SEND;
@@ -394,7 +397,7 @@
         default:
           NOTREACHED() << "Unsupported handle type "
                        << static_cast<int>(handle.type());
-          OnWriteErrorLocked(Error::kDisconnected);
+          OnWriteErrorLocked(Error::kDisconnected, 0xbad04adl);
       }
     }
 
@@ -438,7 +441,7 @@
         MACH_LOG_IF(ERROR, kr != MACH_SEND_INVALID_DEST, kr) << "mach_msg send";
         send_buffer_contains_message_ = false;
         mach_msg_destroy(header);
-        OnWriteErrorLocked(Error::kDisconnected);
+        OnWriteErrorLocked(Error::kDisconnected, kr);
       }
       return false;
     }
@@ -626,7 +629,15 @@
   }
 
   // Marks the channel as unaccepting of new messages and shuts it down.
-  void OnWriteErrorLocked(Error error) {
+  void OnWriteErrorLocked(Error error, uint32_t error_code) {
+    // TODO(https://crbug.com/946372): Remove when fixed.
+    static base::debug::CrashKeyString* error_crash_key =
+        base::debug::AllocateCrashKeyString("channel-mac-write-error",
+                                            base::debug::CrashKeySize::Size32);
+    base::debug::SetCrashKeyString(error_crash_key,
+                                   base::StringPrintf("0x%x", error_code));
+    base::debug::DumpWithoutCrashing();
+
     reject_writes_ = true;
     io_task_runner_->PostTask(
         FROM_HERE, base::BindOnce(&ChannelMac::OnError, this, error));
diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn
index 13093151..a5efd42 100644
--- a/mojo/public/interfaces/bindings/tests/BUILD.gn
+++ b/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -320,7 +320,7 @@
 if (!is_ios) {
   component("test_export_blink_component") {
     testonly = true
-    deps = [
+    public_deps = [
       ":test_export_blink",
     ]
   }
diff --git a/mojo/public/java/system/BUILD.gn b/mojo/public/java/system/BUILD.gn
index 0025f55..49b2dbca 100644
--- a/mojo/public/java/system/BUILD.gn
+++ b/mojo/public/java/system/BUILD.gn
@@ -174,4 +174,5 @@
   shared_libraries = [ ":mojo_java_unittests" ]
   apk_name = "MojoTest"
   android_manifest = "javatests/AndroidManifest.xml"
+  enable_multidex = false
 }
diff --git a/net/android/java/src/org/chromium/net/AndroidKeyStore.java b/net/android/java/src/org/chromium/net/AndroidKeyStore.java
index 9d7f0ef2..c1b155d0 100644
--- a/net/android/java/src/org/chromium/net/AndroidKeyStore.java
+++ b/net/android/java/src/org/chromium/net/AndroidKeyStore.java
@@ -8,10 +8,14 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 
+import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.Signature;
 
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+
 /**
  * Specifies all the dependencies from the native OpenSSL engine on an Android KeyStore.
  */
@@ -25,6 +29,48 @@
     }
 
     /**
+     * Check if a given PrivateKey object supports a signature algorithm.
+     *
+     * @param privateKey The PrivateKey handle.
+     * @param algorithm The signature algorithm to use.
+     * @return whether the algorithm is supported.
+     */
+    @CalledByNative
+    private static boolean privateKeySupportsSignature(PrivateKey privateKey, String algorithm) {
+        try {
+            Signature signature = Signature.getInstance(algorithm);
+            signature.initSign(privateKey);
+        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+            return false;
+        } catch (Exception e) {
+            Log.e(TAG, "Exception while checking support for " + algorithm + ": " + e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Check if a given PrivateKey object supports an encryption algorithm.
+     *
+     * @param privateKey The PrivateKey handle.
+     * @param algorithm The signature algorithm to use.
+     * @return whether the algorithm is supported.
+     */
+    @CalledByNative
+    private static boolean privateKeySupportsCipher(PrivateKey privateKey, String algorithm) {
+        try {
+            Cipher cipher = Cipher.getInstance(algorithm);
+            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) {
+            return false;
+        } catch (Exception e) {
+            Log.e(TAG, "Exception while checking support for " + algorithm + ": " + e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * Sign a given message with a given PrivateKey object.
      *
      * @param privateKey The PrivateKey handle.
@@ -60,4 +106,38 @@
             return null;
         }
     }
+
+    /**
+     * Encrypts a given input with a given PrivateKey object.
+     *
+     * @param privateKey The PrivateKey handle.
+     * @param algorithm The cipher to use.
+     * @param input The input to encrypt.
+     * @return ciphertext as a byte buffer.
+     *
+     * Note: NONEwithRSA is not implemented in Android < 4.2. See
+     * getOpenSSLHandleForPrivateKey() below for a work-around.
+     */
+    @CalledByNative
+    private static byte[] encryptWithPrivateKey(
+            PrivateKey privateKey, String algorithm, byte[] message) {
+        Cipher cipher = null;
+        try {
+            cipher = Cipher.getInstance(algorithm);
+        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+            Log.e(TAG, "Cipher " + algorithm + " not supported: " + e);
+            return null;
+        }
+
+        try {
+            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+            return cipher.doFinal(message);
+        } catch (Exception e) {
+            Log.e(TAG,
+                    "Exception while encrypting input with " + algorithm + " and "
+                            + privateKey.getAlgorithm() + " private key ("
+                            + privateKey.getClass().getName() + "): " + e);
+            return null;
+        }
+    }
 }
diff --git a/net/android/keystore.cc b/net/android/keystore.cc
index fa1bc64..ce0aa792 100644
--- a/net/android/keystore.cc
+++ b/net/android/keystore.cc
@@ -31,6 +31,32 @@
   return ConvertJavaStringToUTF8(env, name);
 }
 
+bool PrivateKeySupportsSignature(const base::android::JavaRef<jobject>& key,
+                                 base::StringPiece algorithm) {
+  JNIEnv* env = AttachCurrentThread();
+
+  ScopedJavaLocalRef<jstring> algorithm_ref =
+      ConvertUTF8ToJavaString(env, algorithm);
+  DCHECK(!algorithm_ref.is_null());
+
+  jboolean result =
+      Java_AndroidKeyStore_privateKeySupportsSignature(env, key, algorithm_ref);
+  return !HasException(env) && result;
+}
+
+bool PrivateKeySupportsCipher(const base::android::JavaRef<jobject>& key,
+                              base::StringPiece algorithm) {
+  JNIEnv* env = AttachCurrentThread();
+
+  ScopedJavaLocalRef<jstring> algorithm_ref =
+      ConvertUTF8ToJavaString(env, algorithm);
+  DCHECK(!algorithm_ref.is_null());
+
+  jboolean result =
+      Java_AndroidKeyStore_privateKeySupportsCipher(env, key, algorithm_ref);
+  return !HasException(env) && result;
+}
+
 bool SignWithPrivateKey(const JavaRef<jobject>& private_key_ref,
                         base::StringPiece algorithm,
                         base::span<const uint8_t> input,
@@ -58,5 +84,32 @@
   return true;
 }
 
+bool EncryptWithPrivateKey(const JavaRef<jobject>& private_key_ref,
+                           base::StringPiece algorithm,
+                           base::span<const uint8_t> input,
+                           std::vector<uint8_t>* ciphertext) {
+  JNIEnv* env = AttachCurrentThread();
+
+  ScopedJavaLocalRef<jstring> algorithm_ref =
+      ConvertUTF8ToJavaString(env, algorithm);
+  DCHECK(!algorithm_ref.is_null());
+
+  // Convert message to byte[] array.
+  ScopedJavaLocalRef<jbyteArray> input_ref =
+      ToJavaByteArray(env, input.data(), input.size());
+  DCHECK(!input_ref.is_null());
+
+  // Invoke platform API
+  ScopedJavaLocalRef<jbyteArray> ciphertext_ref =
+      Java_AndroidKeyStore_encryptWithPrivateKey(env, private_key_ref,
+                                                 algorithm_ref, input_ref);
+  if (HasException(env) || ciphertext_ref.is_null())
+    return false;
+
+  // Write ciphertext to string.
+  JavaByteArrayToByteVector(env, ciphertext_ref, ciphertext);
+  return true;
+}
+
 }  // namespace android
 }  // namespace net
diff --git a/net/android/keystore.h b/net/android/keystore.h
index e563cd8..c8eb34b 100644
--- a/net/android/keystore.h
+++ b/net/android/keystore.h
@@ -37,6 +37,14 @@
 // Returns the name of the class which implements the private key.
 std::string GetPrivateKeyClassName(const base::android::JavaRef<jobject>& key);
 
+// Returns whether |key| supports the signature algorithm |algorithm|.
+bool PrivateKeySupportsSignature(const base::android::JavaRef<jobject>& key,
+                                 base::StringPiece algorithm);
+
+// Returns whether |key| supports the encryption algorithm |algorithm|.
+bool PrivateKeySupportsCipher(const base::android::JavaRef<jobject>& key,
+                              base::StringPiece algorithm);
+
 // Compute the signature of a given input using a private key. For more
 // details, please read the comments for the signWithPrivateKey method in
 // AndroidKeyStore.java.
@@ -51,6 +59,19 @@
                         base::span<const uint8_t> input,
                         std::vector<uint8_t>* signature);
 
+// Encrypts a given input using a private key. For more details, please read the
+// comments for the encryptWithPrivateKey method in AndroidKeyStore.java.
+//
+// |private_key| is a JNI reference for the private key.
+// |algorithm| is the name of the algorithm to use.
+// |input| is the input to encrypt.
+// |ciphertext| will receive the ciphertext on success.
+// Returns true on success, false on failure.
+bool EncryptWithPrivateKey(const base::android::JavaRef<jobject>& private_key,
+                           base::StringPiece algorithm,
+                           base::span<const uint8_t> input,
+                           std::vector<uint8_t>* ciphertext);
+
 }  // namespace android
 }  // namespace net
 
diff --git a/net/base/chunked_upload_data_stream.h b/net/base/chunked_upload_data_stream.h
index 5efd6714..65da00d 100644
--- a/net/base/chunked_upload_data_stream.h
+++ b/net/base/chunked_upload_data_stream.h
@@ -14,7 +14,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "net/base/completion_callback.h"
 #include "net/base/net_export.h"
 #include "net/base/upload_data_stream.h"
 
diff --git a/net/http/http_proxy_client_socket.h b/net/http/http_proxy_client_socket.h
index 7509bfd..4b5c071 100644
--- a/net/http/http_proxy_client_socket.h
+++ b/net/http/http_proxy_client_socket.h
@@ -12,7 +12,6 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "net/base/completion_callback.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/completion_repeating_callback.h"
 #include "net/base/host_port_pair.h"
diff --git a/net/http/http_stream_factory.h b/net/http/http_stream_factory.h
index ffffb93..3b3247a 100644
--- a/net/http/http_stream_factory.h
+++ b/net/http/http_stream_factory.h
@@ -18,7 +18,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
-#include "net/base/completion_callback.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/load_states.h"
 #include "net/base/net_export.h"
diff --git a/net/http/http_transaction.h b/net/http/http_transaction.h
index 4016b98..f8ddc87 100644
--- a/net/http/http_transaction.h
+++ b/net/http/http_transaction.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include "net/base/completion_callback.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/load_states.h"
 #include "net/base/net_error_details.h"
diff --git a/net/reporting/README.md b/net/reporting/README.md
index 82d663a2..4d14951 100644
--- a/net/reporting/README.md
+++ b/net/reporting/README.md
@@ -4,9 +4,9 @@
 to origins from various other components (e.g. HTTP Public Key Pinning,
 Interventions, or Content Security Policy could potentially use it).
 
-The parts of it that are exposed to the web platform are specified in
-the [draft spec](http://wicg.github.io/reporting/). This document
-assumes that you've read that one.
+The parts of it that are exposed to the web platform are specified in the [draft
+spec](https://w3c.github.io/reporting/). This document assumes that you've read
+that one.
 
 ## Reporting in Chromium
 
@@ -14,11 +14,6 @@
 that it can be used by other parts of the network stack (e.g. HPKP) or
 by non-browser embedders as well as by Chromium.
 
-Almost all of Reporting lives in `//net/reporting`; there is a small
-amount of code in `//chrome/browser/net` to set up Reporting in
-profiles and provide a persistent store for reports and endpoints
-across browser restarts.
-
 ### Inside `//net`
 
 * The top-level class is the *`ReportingService`*. This lives in the
@@ -26,52 +21,83 @@
   other parts of `//net` and other components: queueing reports,
   handling configuration headers, clearing browsing data, and so on.
 
-  * Within `ReportingService` lives *`ReportingContext`*, which in turn
-    contains the inner workings of Reporting, spread across several
-    classes:
+    * A *`ReportingPolicy`* specifies a number of parameters for the Reporting
+      API, such as the maximum number of reports and endpoints to queue, the
+      time interval between delivery attempts, whether or not to persist reports
+      and clients across network changes, etc. It is used to create a
+      `ReportingService` obeying the specified parameters.
 
-    * The *`ReportingCache`* stores undelivered reports and unexpired
-      endpoint configurations.
+    * Within `ReportingService` lives *`ReportingContext`*, which in turn
+      contains the inner workings of Reporting, spread across several classes:
 
-    * The *`ReportingHeaderParser`* parses `Report-To:` headers and
-      updates the `Cache` accordingly.
+        * The *`ReportingCache`* stores undelivered reports and endpoint
+          configurations (aka "clients" in the spec).
 
-    * The *`ReportingDeliveryAgent`* reads reports from the `Cache`,
-      decides which endpoints to deliver them to, and attempts to
-      do so. It uses a couple of helper classes:
+        * The *`ReportingHeaderParser`* parses `Report-To:` headers and updates
+          the cache accordingly.
 
-      * The *`ReportingUploader`* does the low-level work of delivering
-        reports: accepts a URL and JSON from the `DeliveryAgent`,
-        creates a `URLRequest`, and parses the result.
+        * The *`ReportingDeliveryAgent`* reads reports from the cache, decides
+          which endpoints to deliver them to, and attempts to do so. It uses a
+          couple of helper classes:
 
-      * The *`ReportingEndpointManager`* keeps track of which endpoints
-        are in use, and manages exponential backoff (using
-        `BackoffEntry`) for failing endpoints.
+            * The *`ReportingUploader`* does the low-level work of delivering
+              reports: accepts a URL and JSON from the `DeliveryAgent`, creates
+              a `URLRequest`, and parses the result. It also handles sending
+              CORS preflight requests for cross-origin report uploads.
 
-    * The *`ReportingGarbageCollector`* periodically examines the
-      `Cache` and removes reports that have remained undelivered for too
-      long, or that have failed delivery too many times.
+            * The *`ReportingEndpointManager`* chooses an endpoint from the
+              cache when one is requested by the `ReportingDeliveryAgent`, and
+              manages exponential backoff (using `BackoffEntry`) for failing
+              endpoints.
 
-    * The *`ReportingSerializer`* reads the `Cache` and serializes it
-      into a `base::Value` for persistent storage (in Chromium, as a
-      pref); it can also deserialize a serialized `Value` back into the
-      `Cache`.
+        * The *`ReportingGarbageCollector`* periodically examines the cache
+          and removes reports that have remained undelivered for too long, or
+          that have failed delivery too many times.
 
-    * The *`ReportingBrowsingDataRemover`* examines the `Cache` upon
-      request and removes browsing data (reports and endpoints) of
-      selected types and origins.
+        * The *`ReportingBrowsingDataRemover`* examines the cache upon request
+          and removes browsing data (reports and endpoints) of selected types
+          and origins.
+
+        * The *`ReportingDelegate`* calls upon the `NetworkDelegate` (see below)
+          to check permissions for queueing/sending reports and setting/using
+          clients.
+
+* The `ReportingService` is set up in a `URLRequestContext` by passing a
+  `ReportingPolicy` to the `URLRequestContextBuilder`. This creates a
+  `ReportingService` which is owned by the `URLRequestContextStorage`.
+
+* `Report-To:` headers are processed by an `HttpNetworkTransaction` when they
+  are received, and passed on to the `ReportingService` to be added to the
+  cache.
 
 ### Outside `//net`
 
-* In `*ProfileImplIOData*::InitializeInternal`, the `ReportingService`
-  is created and set in the `URLRequestContext`, where the net stack
-  can use it.
+* In the network service, a `network::NetworkContext` queues reports by getting
+  the `ReportingService` from the `URLRequestContext`.
 
-  (There is currently no interface to Reporting besides "hop over to
-  the IO thread and poke the `ReportingService` in your favorite
-  `URLRequestContext`", but that should change as various components
-  need to queue reports.)
+* The JavaScript [ReportingObserver](https://w3c.github.io/reporting/#observers)
+  interface lives [in `//third_party/blink/renderer/core/frame/`][1].
 
-* *`ChromeReportingDelegate`* implements `ReportingDelegate` and plumbs
-  the persistent data interface into prefs. It lives in
-  `//chrome/browser/net`.
+    * It queues reports via the `NetworkContext` using a
+      `blink::mojom::ReportingServiceProxy` (implemented [in
+      `//content/browser/net/`][2]), which can queue Intervention, Deprecation,
+      CSP Violation, and Feature Policy Violation reports.
+
+* The `ChromeNetworkDelegate` [in `//chrome/browser/net/`][3] checks permissions
+  for queueing reports and setting/using clients based on whether cookie access
+  is allowed, and checks permissions for sending reports using a
+  `ReportingPermissionsChecker`, which checks whether the user has allowed
+  report uploading via the BACKGROUND_SYNC permission.
+
+* Cronet can configure "preloaded" `Report-To:` headers (as well as Network
+  Error Logging headers) when initializing a `CronetURLRequestContext`, to allow
+  embedders to collect and send reports before having received a header in an
+  actual response.
+
+    * This functionality is tested on Android by way of sending Network Error
+      Logging reports [in the Cronet Java tests][4].
+
+[1]: https://chromium.googlesource.com/chromium/src/+/HEAD/third_party/blink/renderer/core/frame/reporting_observer.h
+[2]: https://chromium.googlesource.com/chromium/src/+/HEAD/content/browser/net/reporting_service_proxy.cc
+[3]: https://chromium.googlesource.com/chromium/src/+/HEAD/chrome/browser/net/chrome_network_delegate.h
+[4]: https://chromium.googlesource.com/chromium/src/+/HEAD/components/cronet/android/test/javatests/src/org/chromium/net/NetworkErrorLoggingTest.java
diff --git a/net/socket/fuzzed_datagram_client_socket.h b/net/socket/fuzzed_datagram_client_socket.h
index 8e5f02d..62c68db 100644
--- a/net/socket/fuzzed_datagram_client_socket.h
+++ b/net/socket/fuzzed_datagram_client_socket.h
@@ -10,7 +10,7 @@
 #include <stdint.h>
 
 #include "base/memory/weak_ptr.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/network_change_notifier.h"
 #include "net/log/net_log_with_source.h"
diff --git a/net/socket/fuzzed_socket.h b/net/socket/fuzzed_socket.h
index 17b9e542b..abe5961 100644
--- a/net/socket/fuzzed_socket.h
+++ b/net/socket/fuzzed_socket.h
@@ -10,7 +10,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_piece.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
 #include "net/log/net_log_with_source.h"
diff --git a/net/socket/socks5_client_socket.h b/net/socket/socks5_client_socket.h
index 6fe59e0..58f3d128 100644
--- a/net/socket/socks5_client_socket.h
+++ b/net/socket/socks5_client_socket.h
@@ -14,7 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/completion_repeating_callback.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/net_errors.h"
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h
index f0de4c1..90a7f96 100644
--- a/net/socket/ssl_client_socket.h
+++ b/net/socket/ssl_client_socket.h
@@ -12,7 +12,6 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/strings/string_piece.h"
-#include "net/base/completion_callback.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_export.h"
diff --git a/net/socket/ssl_client_socket_impl.h b/net/socket/ssl_client_socket_impl.h
index 301f12f..fef393a 100644
--- a/net/socket/ssl_client_socket_impl.h
+++ b/net/socket/ssl_client_socket_impl.h
@@ -17,7 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/io_buffer.h"
 #include "net/cert/cert_verifier.h"
diff --git a/net/socket/tcp_client_socket.h b/net/socket/tcp_client_socket.h
index 7fa4df6..8b6aa30d 100644
--- a/net/socket/tcp_client_socket.h
+++ b/net/socket/tcp_client_socket.h
@@ -12,7 +12,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/net_export.h"
 #include "net/socket/connection_attempts.h"
 #include "net/socket/socket_descriptor.h"
diff --git a/net/socket/unix_domain_client_socket_posix.h b/net/socket/unix_domain_client_socket_posix.h
index 83ded563..2397b91 100644
--- a/net/socket/unix_domain_client_socket_posix.h
+++ b/net/socket/unix_domain_client_socket_posix.h
@@ -11,7 +11,7 @@
 #include <string>
 
 #include "base/macros.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/net_export.h"
 #include "net/log/net_log_with_source.h"
 #include "net/socket/socket_descriptor.h"
diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h
index ca6e075..02a2ecf 100644
--- a/net/spdy/spdy_proxy_client_socket.h
+++ b/net/spdy/spdy_proxy_client_socket.h
@@ -15,7 +15,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "net/base/completion_callback.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/net_export.h"
diff --git a/net/ssl/ssl_platform_key_android.cc b/net/ssl/ssl_platform_key_android.cc
index 15fa630..8a13756 100644
--- a/net/ssl/ssl_platform_key_android.cc
+++ b/net/ssl/ssl_platform_key_android.cc
@@ -10,10 +10,11 @@
 #include <utility>
 #include <vector>
 
-#include "base/android/build_info.h"
 #include "base/android/scoped_java_ref.h"
+#include "base/containers/flat_set.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "net/android/keystore.h"
 #include "net/base/net_errors.h"
 #include "net/ssl/ssl_platform_key_util.h"
@@ -61,11 +62,37 @@
   }
 }
 
+// Java's public-key encryption algorithms are mis-named. It incorrectly
+// classifies RSA's "mode" as ECB.
+const char kRSANoPadding[] = "RSA/ECB/NoPadding";
+
 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate {
  public:
-  SSLPlatformKeyAndroid(int type, const JavaRef<jobject>& key)
-      : type_(type), provider_name_(android::GetPrivateKeyClassName(key)) {
+  SSLPlatformKeyAndroid(bssl::UniquePtr<EVP_PKEY> pubkey,
+                        const JavaRef<jobject>& key)
+      : pubkey_(std::move(pubkey)),
+        provider_name_(android::GetPrivateKeyClassName(key)) {
     key_.Reset(key);
+
+    base::Optional<bool> supports_rsa_no_padding;
+    for (uint16_t algorithm : SSLPrivateKey::DefaultAlgorithmPreferences(
+             EVP_PKEY_id(pubkey_.get()), true /* include PSS */)) {
+      const char* java_algorithm = GetJavaAlgorithm(algorithm);
+      if (java_algorithm &&
+          android::PrivateKeySupportsSignature(key_, java_algorithm)) {
+        preferences_.push_back(algorithm);
+      } else if (SSL_is_signature_algorithm_rsa_pss(algorithm)) {
+        // Check if we can use the fallback path instead.
+        if (!supports_rsa_no_padding) {
+          supports_rsa_no_padding =
+              android::PrivateKeySupportsCipher(key_, kRSANoPadding);
+        }
+        if (*supports_rsa_no_padding) {
+          preferences_.push_back(algorithm);
+          use_pss_fallback_.insert(algorithm);
+        }
+      }
+    }
   }
 
   ~SSLPlatformKeyAndroid() override {}
@@ -73,9 +100,7 @@
   std::string GetProviderName() override { return provider_name_; }
 
   std::vector<uint16_t> GetAlgorithmPreferences() override {
-    bool supports_pss = base::android::BuildInfo::GetInstance()->sdk_int() >=
-                        base::android::SDK_VERSION_NOUGAT;
-    return SSLPrivateKey::DefaultAlgorithmPreferences(type_, supports_pss);
+    return preferences_;
   }
 
   Error Sign(uint16_t algorithm,
@@ -87,6 +112,10 @@
       return SignRSAWithMD5SHA1(input, signature);
     }
 
+    if (use_pss_fallback_.contains(algorithm)) {
+      return SignPSSFallback(algorithm, input, signature);
+    }
+
     const char* java_algorithm = GetJavaAlgorithm(algorithm);
     if (!java_algorithm) {
       LOG(ERROR) << "Unknown algorithm " << algorithm;
@@ -119,9 +148,35 @@
     return OK;
   }
 
-  int type_;
+  Error SignPSSFallback(uint16_t algorithm,
+                        base::span<const uint8_t> input,
+                        std::vector<uint8_t>* signature) {
+    const EVP_MD* md = SSL_get_signature_algorithm_digest(algorithm);
+    uint8_t digest[EVP_MAX_MD_SIZE];
+    unsigned digest_len;
+    if (!EVP_Digest(input.data(), input.size(), digest, &digest_len, md,
+                    nullptr)) {
+      return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+    }
+
+    base::Optional<std::vector<uint8_t>> padded =
+        AddPSSPadding(pubkey_.get(), md, base::make_span(digest, digest_len));
+    if (!padded) {
+      return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+    }
+
+    if (!android::EncryptWithPrivateKey(key_, kRSANoPadding, *padded,
+                                        signature)) {
+      return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+    }
+    return OK;
+  }
+
+  bssl::UniquePtr<EVP_PKEY> pubkey_;
   ScopedJavaGlobalRef<jobject> key_;
   std::string provider_name_;
+  std::vector<uint16_t> preferences_;
+  base::flat_set<uint16_t> use_pss_fallback_;
 
   DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyAndroid);
 };
@@ -131,13 +186,12 @@
 scoped_refptr<SSLPrivateKey> WrapJavaPrivateKey(
     const X509Certificate* certificate,
     const JavaRef<jobject>& key) {
-  int type;
-  size_t max_length;
-  if (!GetClientCertInfo(certificate, &type, &max_length))
+  bssl::UniquePtr<EVP_PKEY> pubkey = GetClientCertPublicKey(certificate);
+  if (!pubkey)
     return nullptr;
 
   return base::MakeRefCounted<ThreadedSSLPrivateKey>(
-      std::make_unique<SSLPlatformKeyAndroid>(type, key),
+      std::make_unique<SSLPlatformKeyAndroid>(std::move(pubkey), key),
       GetSSLPlatformKeyTaskRunner());
 }
 
diff --git a/net/ssl/ssl_platform_key_android_unittest.cc b/net/ssl/ssl_platform_key_android_unittest.cc
index 636a4dc..bdad44d 100644
--- a/net/ssl/ssl_platform_key_android_unittest.cc
+++ b/net/ssl/ssl_platform_key_android_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "base/android/build_info.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
 #include "base/android/scoped_java_ref.h"
@@ -94,12 +93,9 @@
   scoped_refptr<SSLPrivateKey> key = WrapJavaPrivateKey(cert.get(), java_key);
   ASSERT_TRUE(key);
 
-  // All Android keys are expected to have the default preferences.
-  bool supports_pss = base::android::BuildInfo::GetInstance()->sdk_int() >=
-                      base::android::SDK_VERSION_NOUGAT;
-  EXPECT_EQ(
-      SSLPrivateKey::DefaultAlgorithmPreferences(test_key.type, supports_pss),
-      key->GetAlgorithmPreferences());
+  EXPECT_EQ(SSLPrivateKey::DefaultAlgorithmPreferences(test_key.type,
+                                                       true /* supports_pss */),
+            key->GetAlgorithmPreferences());
 
   TestSSLPrivateKeyMatches(key.get(), key_bytes);
 }
diff --git a/net/ssl/ssl_platform_key_mac.cc b/net/ssl/ssl_platform_key_mac.cc
index b08e4d1..b61d0d8d 100644
--- a/net/ssl/ssl_platform_key_mac.cc
+++ b/net/ssl/ssl_platform_key_mac.cc
@@ -52,23 +52,6 @@
 
 namespace {
 
-base::Optional<std::vector<uint8_t>> AddPSSPadding(
-    EVP_PKEY* pubkey,
-    const EVP_MD* md,
-    base::span<const uint8_t> digest) {
-  RSA* rsa = EVP_PKEY_get0_RSA(pubkey);
-  if (!rsa) {
-    return base::nullopt;
-  }
-  std::vector<uint8_t> ret(RSA_size(rsa));
-  if (digest.size() != EVP_MD_size(md) ||
-      !RSA_padding_add_PKCS1_PSS_mgf1(rsa, ret.data(), digest.data(), md, md,
-                                      -1 /* salt length is digest length */)) {
-    return base::nullopt;
-  }
-  return ret;
-}
-
 class ScopedCSSM_CC_HANDLE {
  public:
   ScopedCSSM_CC_HANDLE() : handle_(0) {}
diff --git a/net/ssl/ssl_platform_key_util.cc b/net/ssl/ssl_platform_key_util.cc
index 6a4dab0..9baac3b 100644
--- a/net/ssl/ssl_platform_key_util.cc
+++ b/net/ssl/ssl_platform_key_util.cc
@@ -16,6 +16,7 @@
 #include "third_party/boringssl/src/include/openssl/bytestring.h"
 #include "third_party/boringssl/src/include/openssl/ec_key.h"
 #include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/rsa.h"
 
 namespace net {
 
@@ -86,4 +87,21 @@
   return true;
 }
 
+base::Optional<std::vector<uint8_t>> AddPSSPadding(
+    EVP_PKEY* pubkey,
+    const EVP_MD* md,
+    base::span<const uint8_t> digest) {
+  RSA* rsa = EVP_PKEY_get0_RSA(pubkey);
+  if (!rsa) {
+    return base::nullopt;
+  }
+  std::vector<uint8_t> ret(RSA_size(rsa));
+  if (digest.size() != EVP_MD_size(md) ||
+      !RSA_padding_add_PKCS1_PSS_mgf1(rsa, ret.data(), digest.data(), md, md,
+                                      -1 /* salt length is digest length */)) {
+    return base::nullopt;
+  }
+  return ret;
+}
+
 }  // namespace net
diff --git a/net/ssl/ssl_platform_key_util.h b/net/ssl/ssl_platform_key_util.h
index 5b2fe55..eaf9ccc 100644
--- a/net/ssl/ssl_platform_key_util.h
+++ b/net/ssl/ssl_platform_key_util.h
@@ -6,8 +6,13 @@
 #define NET_SSL_SSL_PLATFORM_KEY_UTIL_H_
 
 #include <stddef.h>
+#include <stdint.h>
 
+#include <vector>
+
+#include "base/containers/span.h"
 #include "base/memory/ref_counted.h"
+#include "base/optional.h"
 #include "base/single_thread_task_runner.h"
 #include "net/base/net_export.h"
 #include "third_party/boringssl/src/include/openssl/base.h"
@@ -33,6 +38,14 @@
                                           int* out_type,
                                           size_t* out_max_length);
 
+// Returns the encoded form of |digest| for use with RSA-PSS with |pubkey|,
+// using |md| as the hash function and MGF-1 function, and the digest size of
+// |md| as the salt length.
+base::Optional<std::vector<uint8_t>> AddPSSPadding(
+    EVP_PKEY* pubkey,
+    const EVP_MD* md,
+    base::span<const uint8_t> digest);
+
 }  // namespace net
 
 #endif  // NET_SSL_SSL_PLATFORM_KEY_UTIL_H_
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index 383ec1c..2b80fba 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -21,7 +21,6 @@
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "net/base/auth.h"
-#include "net/base/completion_callback.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/load_states.h"
 #include "net/base/load_timing_info.h"
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc
index 70a2138..f9fad8c 100644
--- a/net/url_request/url_request_context.cc
+++ b/net/url_request/url_request_context.cc
@@ -28,7 +28,7 @@
 
 namespace net {
 
-URLRequestContext::URLRequestContext()
+URLRequestContext::URLRequestContext(bool allow_copy)
     : net_log_(nullptr),
       host_resolver_(nullptr),
       cert_verifier_(nullptr),
@@ -55,7 +55,8 @@
       url_requests_(std::make_unique<std::set<const URLRequest*>>()),
       enable_brotli_(false),
       check_cleartext_permitted_(false),
-      name_("unknown") {
+      name_("unknown"),
+      allow_copy_(allow_copy) {
   base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
       this, "URLRequestContext", base::ThreadTaskRunnerHandle::Get());
 }
@@ -67,35 +68,6 @@
       this);
 }
 
-void URLRequestContext::CopyFrom(const URLRequestContext* other) {
-  // Copy URLRequestContext parameters.
-  set_net_log(other->net_log_);
-  set_host_resolver(other->host_resolver_);
-  set_cert_verifier(other->cert_verifier_);
-  set_channel_id_service(other->channel_id_service_);
-  set_http_auth_handler_factory(other->http_auth_handler_factory_);
-  set_proxy_resolution_service(other->proxy_resolution_service_);
-  set_proxy_delegate(other->proxy_delegate_);
-  set_ssl_config_service(other->ssl_config_service_);
-  set_network_delegate(other->network_delegate_);
-  set_http_server_properties(other->http_server_properties_);
-  set_cookie_store(other->cookie_store_);
-  set_transport_security_state(other->transport_security_state_);
-  set_cert_transparency_verifier(other->cert_transparency_verifier_);
-  set_ct_policy_enforcer(other->ct_policy_enforcer_);
-  set_http_transaction_factory(other->http_transaction_factory_);
-  set_job_factory(other->job_factory_);
-  set_throttler_manager(other->throttler_manager_);
-  set_http_user_agent_settings(other->http_user_agent_settings_);
-  set_network_quality_estimator(other->network_quality_estimator_);
-#if BUILDFLAG(ENABLE_REPORTING)
-  set_reporting_service(other->reporting_service_);
-  set_network_error_logging_service(other->network_error_logging_service_);
-#endif  // BUILDFLAG(ENABLE_REPORTING)
-  set_enable_brotli(other->enable_brotli_);
-  set_check_cleartext_permitted(other->check_cleartext_permitted_);
-}
-
 const HttpNetworkSession::Params* URLRequestContext::GetNetworkSessionParams(
     ) const {
   HttpTransactionFactory* transaction_factory = http_transaction_factory();
@@ -179,4 +151,37 @@
   return true;
 }
 
+void URLRequestContext::CopyFrom(const URLRequestContext* other) {
+  // Copy disallowed in cases known to not currently need it. New copying should
+  // not be added as CopyFrom is fundamentally broken.
+  DCHECK(allow_copy_ && other->allow_copy_);
+
+  // Copy URLRequestContext parameters.
+  set_net_log(other->net_log_);
+  set_host_resolver(other->host_resolver_);
+  set_cert_verifier(other->cert_verifier_);
+  set_channel_id_service(other->channel_id_service_);
+  set_http_auth_handler_factory(other->http_auth_handler_factory_);
+  set_proxy_resolution_service(other->proxy_resolution_service_);
+  set_proxy_delegate(other->proxy_delegate_);
+  set_ssl_config_service(other->ssl_config_service_);
+  set_network_delegate(other->network_delegate_);
+  set_http_server_properties(other->http_server_properties_);
+  set_cookie_store(other->cookie_store_);
+  set_transport_security_state(other->transport_security_state_);
+  set_cert_transparency_verifier(other->cert_transparency_verifier_);
+  set_ct_policy_enforcer(other->ct_policy_enforcer_);
+  set_http_transaction_factory(other->http_transaction_factory_);
+  set_job_factory(other->job_factory_);
+  set_throttler_manager(other->throttler_manager_);
+  set_http_user_agent_settings(other->http_user_agent_settings_);
+  set_network_quality_estimator(other->network_quality_estimator_);
+#if BUILDFLAG(ENABLE_REPORTING)
+  set_reporting_service(other->reporting_service_);
+  set_network_error_logging_service(other->network_error_logging_service_);
+#endif  // BUILDFLAG(ENABLE_REPORTING)
+  set_enable_brotli(other->enable_brotli_);
+  set_check_cleartext_permitted(other->check_cleartext_permitted_);
+}
+
 }  // namespace net
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index 4d51f78b..d263ebd6 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -26,12 +26,25 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_request.h"
 
+class ChromeBrowserStateImplIOData;
+class ProfileImplIOData;
+
 namespace base {
 namespace trace_event {
 class ProcessMemoryDump;
 }
 }
 
+namespace chromecast {
+namespace shell {
+class URLRequestContextFactory;
+}
+}  // namespace chromecast
+
+namespace safe_browsing {
+class SafeBrowsingURLRequestContextGetter;
+}  // namespace safe_browsing
+
 namespace net {
 class CertVerifier;
 class ChannelIDService;
@@ -66,12 +79,11 @@
 class NET_EXPORT URLRequestContext
     : public base::trace_event::MemoryDumpProvider {
  public:
-  URLRequestContext();
+  // Contexts that are known to not currently be copied should set |allow_copy|
+  // to false to prevent added copying.
+  explicit URLRequestContext(bool allow_copy = true);
   ~URLRequestContext() override;
 
-  // Copies the state from |other| into this context.
-  void CopyFrom(const URLRequestContext* other);
-
   // May return nullptr if this context doesn't have an associated network
   // session.
   const HttpNetworkSession::Params* GetNetworkSessionParams() const;
@@ -296,6 +308,21 @@
   }
 
  private:
+  // Whitelist legacy usage of now-deprecated CopyFrom().
+  friend class ::ChromeBrowserStateImplIOData;
+  friend class ::ProfileImplIOData;
+  friend class chromecast::shell::URLRequestContextFactory;
+  friend class safe_browsing::SafeBrowsingURLRequestContextGetter;
+
+  // Copies the state from |other| into this context.
+  //
+  // Due to complex interdependencies between various fields as well as fields
+  // that should be unique to each context, copy is fundamentally broken, and
+  // should not be done. If a modified context is needed (and that is not
+  // typical), a new context should always be fully created (via
+  // URLRequestContextBuilder) rather than copying from a previous one.
+  void CopyFrom(const URLRequestContext* other);
+
   // ---------------------------------------------------------------------------
   // Important: When adding any new members below, consider whether they need to
   // be added to CopyFrom.
@@ -345,6 +372,8 @@
   // to be unique.
   std::string name_;
 
+  const bool allow_copy_;
+
   THREAD_CHECKER(thread_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(URLRequestContext);
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 6f567ae..c326cd8 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -146,7 +146,8 @@
 // it's not safe to subclass this.
 class ContainerURLRequestContext final : public URLRequestContext {
  public:
-  ContainerURLRequestContext() : storage_(this) {}
+  explicit ContainerURLRequestContext(bool allow_copy)
+      : URLRequestContext(allow_copy), storage_(this) {}
 
   ~ContainerURLRequestContext() override {
 #if BUILDFLAG(ENABLE_REPORTING)
@@ -393,7 +394,7 @@
 
 std::unique_ptr<URLRequestContext> URLRequestContextBuilder::Build() {
   std::unique_ptr<ContainerURLRequestContext> context(
-      new ContainerURLRequestContext());
+      new ContainerURLRequestContext(allow_copy_));
   URLRequestContextStorage* storage = context->storage();
 
   if (!name_.empty())
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index c637692d..4338284 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -369,6 +369,8 @@
       CreateHttpTransactionFactoryCallback
           create_http_network_transaction_factory);
 
+  void set_allow_copy() { allow_copy_ = true; }
+
   // Creates a mostly self-contained URLRequestContext. May only be called once
   // per URLRequestContextBuilder. After this is called, the Builder can be
   // safely destroyed.
@@ -444,6 +446,7 @@
   std::unique_ptr<HttpServerProperties> http_server_properties_;
   std::map<std::string, std::unique_ptr<URLRequestJobFactory::ProtocolHandler>>
       protocol_handlers_;
+  bool allow_copy_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(URLRequestContextBuilder);
 };
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index 6212aa61..dbfe3b9 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -17,7 +17,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "net/base/auth.h"
-#include "net/base/completion_callback.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_error_details.h"
 #include "net/base/net_export.h"
diff --git a/net/url_request/url_request_simple_job.h b/net/url_request/url_request_simple_job.h
index 55950c8..a27e819 100644
--- a/net/url_request/url_request_simple_job.h
+++ b/net/url_request/url_request_simple_job.h
@@ -12,7 +12,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_piece.h"
-#include "net/base/completion_callback.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/net_export.h"
 #include "net/url_request/url_range_request_job.h"
diff --git a/pdf/pdfium/fuzzers/BUILD.gn b/pdf/pdfium/fuzzers/BUILD.gn
index f509e5b1..3796224 100644
--- a/pdf/pdfium/fuzzers/BUILD.gn
+++ b/pdf/pdfium/fuzzers/BUILD.gn
@@ -304,7 +304,7 @@
         "//third_party/pdfium/testing/fuzzers:pdfium_xfa_fuzzer_src",
       ]
       dict = "dicts/pdf.dict"
-      seed_corpus = "//third_party/pdfium/testing/resources"
+      seed_corpus = "corpora/xfa"
     }
   }
 }
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/bug_1258_1.pdf b/pdf/pdfium/fuzzers/corpora/xfa/bug_1258_1.pdf
new file mode 100644
index 0000000..b5ac39c
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/bug_1258_1.pdf
Binary files differ
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/bug_1258_2.pdf b/pdf/pdfium/fuzzers/corpora/xfa/bug_1258_2.pdf
new file mode 100644
index 0000000..8dfc40f
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/bug_1258_2.pdf
Binary files differ
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/bug_1258_3.pdf b/pdf/pdfium/fuzzers/corpora/xfa/bug_1258_3.pdf
new file mode 100644
index 0000000..eca3719
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/bug_1258_3.pdf
Binary files differ
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/bug_1269_1.pdf b/pdf/pdfium/fuzzers/corpora/xfa/bug_1269_1.pdf
new file mode 100644
index 0000000..b2d4784
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/bug_1269_1.pdf
@@ -0,0 +1,45 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA 3 0 R
+>>
+endobj
+3 0 obj <<
+  /Length 114
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
+<template>
+<subform use=" .[$host.calculationsEnabled=$]">
+<field>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/bug_1269_2.pdf b/pdf/pdfium/fuzzers/corpora/xfa/bug_1269_2.pdf
new file mode 100644
index 0000000..5a15eae
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/bug_1269_2.pdf
@@ -0,0 +1,46 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA 3 0 R
+>>
+endobj
+3 0 obj <<
+  /Length 115
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
+<template>
+<defaultUi use=" .[c=$]">
+<field>
+<contentArea name="c">
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/bug_1269_3.pdf b/pdf/pdfium/fuzzers/corpora/xfa/bug_1269_3.pdf
new file mode 100644
index 0000000..8045537
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/bug_1269_3.pdf
@@ -0,0 +1,45 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA 3 0 R
+>>
+endobj
+3 0 obj <<
+  /Length 96
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
+<template>
+<template use=" .[Space($)]">
+<field>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/bug_1270.pdf b/pdf/pdfium/fuzzers/corpora/xfa/bug_1270.pdf
new file mode 100644
index 0000000..637b775
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/bug_1270.pdf
@@ -0,0 +1,45 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA 3 0 R
+>>
+endobj
+3 0 obj <<
+  /Length 84
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
+<template>
+<subform use="$">
+<field>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/bug_1272.pdf b/pdf/pdfium/fuzzers/corpora/xfa/bug_1272.pdf
new file mode 100644
index 0000000..3e600cc
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/bug_1272.pdf
@@ -0,0 +1,45 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA 3 0 R
+>>
+endobj
+3 0 obj <<
+  /Length 101
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
+<template>
+<subform use=" .[$.clone(1)]">
+<bindItems>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/bug_1273.pdf b/pdf/pdfium/fuzzers/corpora/xfa/bug_1273.pdf
new file mode 100644
index 0000000..8832597
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/bug_1273.pdf
@@ -0,0 +1,46 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA 3 0 R
+>>
+endobj
+3 0 obj <<
+  /Length 119
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
+<template>
+<subform>
+<breakBefore>
+<script>host.openList("""")</script>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/xfa_combobox.pdf b/pdf/pdfium/fuzzers/corpora/xfa/xfa_combobox.pdf
new file mode 100644
index 0000000..bdff67c
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/xfa_combobox.pdf
@@ -0,0 +1,234 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA [
+    (preamble)
+    3 0 R
+    (config)
+    4 0 R
+    (template)
+    5 0 R
+    (localeSet)
+    6 0 R
+    (postamble)
+    7 0 R
+  ]
+>>
+endobj
+3 0 obj <<
+  /Length 124
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2018-02-23T21:37:11Z" uuid="21482798-7bf0-40a4-bc5d-3cefdccf32b5">
+endstream
+endobj
+4 0 obj <<
+  /Length 642
+>>
+stream
+<config xmlns="http://www.xfa.org/schema/xci/3.0/">
+<agent name="designer">
+  <destination>pdf</destination>
+  <pdf>
+    <fontInfo/>
+  </pdf>
+</agent>
+<present>
+  <pdf>
+    <version>1.7</version>
+    <adobeExtensionLevel>8</adobeExtensionLevel>
+    <renderPolicy>client</renderPolicy>
+    <scriptModel>XFA</scriptModel>
+    <interactive>1</interactive>
+  </pdf>
+  <xdp>
+    <packets>*</packets>
+  </xdp>
+  <destination>pdf</destination>
+  <script>
+    <runScripts>server</runScripts>
+  </script>
+</present>
+<acrobat>
+  <acrobat7>
+    <dynamicRender>required</dynamicRender>
+  </acrobat7>
+  <validate>preSubmit</validate>
+</acrobat>
+</config>
+endstream
+endobj
+5 0 obj <<
+  /Length 716
+>>
+stream
+<template xmlns="http://www.xfa.org/schema/xfa-template/3.3/">
+  <subform name="form1" layout="tb" locale="en_US" restoreState="auto">
+    <pageSet>
+      <pageArea name="Page1" id="Page1">
+        <contentArea x="18pt" y="18pt" w="612pt" h="792pt"/>
+        <medium stock="default" short="612pt" long="792pt"/>
+      </pageArea>
+    </pageSet>
+    <subform w="576pt" h="756pt" name="Page1">
+      <field name="ImageField1" y="0pt" x="0pt" w="425pt" h="80pt">
+        <ui>
+          <choiceList open="userControl"/>
+        </ui>
+        <items save="1">
+          <text>clams</text>
+          <text>oysters</text>
+          <text>crabs</text>
+        </items>
+      </field>
+    </subform>
+  </subform>
+</template>
+endstream
+endobj
+6 0 obj <<
+  /Length 3455
+>>
+stream
+<localeSet xmlns="http://www.xfa.org/schema/xfa-locale-set/2.7/">
+  <locale name="en_US" desc="English (United States)">
+    <calendarSymbols name="gregorian">
+      <monthNames>
+        <month>January</month>
+        <month>February</month>
+        <month>March</month>
+        <month>April</month>
+        <month>May</month>
+        <month>June</month>
+        <month>July</month>
+        <month>August</month>
+        <month>September</month>
+        <month>October</month>
+        <month>November</month>
+        <month>December</month>
+      </monthNames>
+      <monthNames abbr="1">
+        <month>Jan</month>
+        <month>Feb</month>
+        <month>Mar</month>
+        <month>Apr</month>
+        <month>May</month>
+        <month>Jun</month>
+        <month>Jul</month>
+        <month>Aug</month>
+        <month>Sep</month>
+        <month>Oct</month>
+        <month>Nov</month>
+        <month>Dec</month>
+      </monthNames>
+      <dayNames>
+        <day>Sunday</day>
+        <day>Monday</day>
+        <day>Tuesday</day>
+        <day>Wednesday</day>
+        <day>Thursday</day>
+        <day>Friday</day>
+        <day>Saturday</day>
+      </dayNames>
+      <dayNames abbr="1">
+        <day>Sun</day>
+        <day>Mon</day>
+        <day>Tue</day>
+        <day>Wed</day>
+        <day>Thu</day>
+        <day>Fri</day>
+        <day>Sat</day>
+      </dayNames>
+      <meridiemNames>
+        <meridiem>AM</meridiem>
+        <meridiem>PM</meridiem>
+      </meridiemNames>
+      <eraNames>
+        <era>BC</era>
+        <era>AD</era>
+      </eraNames>
+    </calendarSymbols>
+    <datePatterns>
+      <datePattern name="full">EEEE, MMMM D, YYYY</datePattern>
+      <datePattern name="long">MMMM D, YYYY</datePattern>
+      <datePattern name="med">MMM D, YYYY</datePattern>
+      <datePattern name="short">M/D/YY</datePattern>
+    </datePatterns>
+    <timePatterns>
+      <timePattern name="full">h:MM:SS A Z</timePattern>
+      <timePattern name="long">h:MM:SS A Z</timePattern>
+      <timePattern name="med">h:MM:SS A</timePattern>
+      <timePattern name="short">h:MM A</timePattern>
+    </timePatterns>
+    <dateTimeSymbols>GyMdkHmsSEDFwWahKzZ</dateTimeSymbols>
+    <numberPatterns>
+      <numberPattern name="numeric">z,zz9.zzz</numberPattern>
+      <numberPattern name="currency">$z,zz9.99|($z,zz9.99)</numberPattern>
+      <numberPattern name="percent">z,zz9%</numberPattern>
+    </numberPatterns>
+    <numberSymbols>
+      <numberSymbol name="decimal">.</numberSymbol>
+      <numberSymbol name="grouping">,</numberSymbol>
+      <numberSymbol name="percent">%</numberSymbol>
+      <numberSymbol name="minus">-</numberSymbol>
+      <numberSymbol name="zero">0</numberSymbol>
+    </numberSymbols>
+    <currencySymbols>
+      <currencySymbol name="symbol">$</currencySymbol>
+      <currencySymbol name="isoname">USD</currencySymbol>
+      <currencySymbol name="decimal">.</currencySymbol>
+    </currencySymbols>
+    <typefaces>
+      <typeface name="Myriad Pro"/>
+      <typeface name="Minion Pro"/>
+      <typeface name="Courier Std"/>
+      <typeface name="Adobe Pi Std"/>
+      <typeface name="Adobe Hebrew"/>
+      <typeface name="Adobe Arabic"/>
+      <typeface name="Adobe Thai"/>
+      <typeface name="Kozuka Gothic Pro-VI M"/>
+      <typeface name="Kozuka Mincho Pro-VI R"/>
+      <typeface name="Adobe Ming Std L"/>
+      <typeface name="Adobe Song Std L"/>
+      <typeface name="Adobe Myungjo Std M"/>
+    </typefaces>
+  </locale>
+</localeSet>
+endstream
+endobj
+7 0 obj <<
+  /Length 11
+>>
+stream
+</xdp:xdp>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/xfa_date_time_edit.pdf b/pdf/pdfium/fuzzers/corpora/xfa/xfa_date_time_edit.pdf
new file mode 100644
index 0000000..b6dc9ff
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/xfa_date_time_edit.pdf
@@ -0,0 +1,229 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA [
+    (preamble)
+    3 0 R
+    (config)
+    4 0 R
+    (template)
+    5 0 R
+    (localeSet)
+    6 0 R
+    (postamble)
+    7 0 R
+  ]
+>>
+endobj
+3 0 obj <<
+  /Length 124
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2018-02-23T21:37:11Z" uuid="21482798-7bf0-40a4-bc5d-3cefdccf32b5">
+endstream
+endobj
+4 0 obj <<
+  /Length 642
+>>
+stream
+<config xmlns="http://www.xfa.org/schema/xci/3.0/">
+<agent name="designer">
+  <destination>pdf</destination>
+  <pdf>
+    <fontInfo/>
+  </pdf>
+</agent>
+<present>
+  <pdf>
+    <version>1.7</version>
+    <adobeExtensionLevel>8</adobeExtensionLevel>
+    <renderPolicy>client</renderPolicy>
+    <scriptModel>XFA</scriptModel>
+    <interactive>1</interactive>
+  </pdf>
+  <xdp>
+    <packets>*</packets>
+  </xdp>
+  <destination>pdf</destination>
+  <script>
+    <runScripts>server</runScripts>
+  </script>
+</present>
+<acrobat>
+  <acrobat7>
+    <dynamicRender>required</dynamicRender>
+  </acrobat7>
+  <validate>preSubmit</validate>
+</acrobat>
+</config>
+endstream
+endobj
+5 0 obj <<
+  /Length 567
+>>
+stream
+<template xmlns="http://www.xfa.org/schema/xfa-template/3.3/">
+  <subform name="form1" layout="tb" locale="en_US" restoreState="auto">
+    <pageSet>
+      <pageArea name="Page1" id="Page1">
+        <contentArea x="18pt" y="18pt" w="612pt" h="792pt"/>
+        <medium stock="default" short="612pt" long="792pt"/>
+      </pageArea>
+    </pageSet>
+    <subform w="576pt" h="756pt" name="Page1">
+      <field name="TextField1" y="0pt" x="0pt" w="425pt" h="80pt">
+        <ui>
+          <dateTimeEdit/>
+        </ui>
+      </field>
+    </subform>
+  </subform>
+</template>
+endstream
+endobj
+6 0 obj <<
+  /Length 3455
+>>
+stream
+<localeSet xmlns="http://www.xfa.org/schema/xfa-locale-set/2.7/">
+  <locale name="en_US" desc="English (United States)">
+    <calendarSymbols name="gregorian">
+      <monthNames>
+        <month>January</month>
+        <month>February</month>
+        <month>March</month>
+        <month>April</month>
+        <month>May</month>
+        <month>June</month>
+        <month>July</month>
+        <month>August</month>
+        <month>September</month>
+        <month>October</month>
+        <month>November</month>
+        <month>December</month>
+      </monthNames>
+      <monthNames abbr="1">
+        <month>Jan</month>
+        <month>Feb</month>
+        <month>Mar</month>
+        <month>Apr</month>
+        <month>May</month>
+        <month>Jun</month>
+        <month>Jul</month>
+        <month>Aug</month>
+        <month>Sep</month>
+        <month>Oct</month>
+        <month>Nov</month>
+        <month>Dec</month>
+      </monthNames>
+      <dayNames>
+        <day>Sunday</day>
+        <day>Monday</day>
+        <day>Tuesday</day>
+        <day>Wednesday</day>
+        <day>Thursday</day>
+        <day>Friday</day>
+        <day>Saturday</day>
+      </dayNames>
+      <dayNames abbr="1">
+        <day>Sun</day>
+        <day>Mon</day>
+        <day>Tue</day>
+        <day>Wed</day>
+        <day>Thu</day>
+        <day>Fri</day>
+        <day>Sat</day>
+      </dayNames>
+      <meridiemNames>
+        <meridiem>AM</meridiem>
+        <meridiem>PM</meridiem>
+      </meridiemNames>
+      <eraNames>
+        <era>BC</era>
+        <era>AD</era>
+      </eraNames>
+    </calendarSymbols>
+    <datePatterns>
+      <datePattern name="full">EEEE, MMMM D, YYYY</datePattern>
+      <datePattern name="long">MMMM D, YYYY</datePattern>
+      <datePattern name="med">MMM D, YYYY</datePattern>
+      <datePattern name="short">M/D/YY</datePattern>
+    </datePatterns>
+    <timePatterns>
+      <timePattern name="full">h:MM:SS A Z</timePattern>
+      <timePattern name="long">h:MM:SS A Z</timePattern>
+      <timePattern name="med">h:MM:SS A</timePattern>
+      <timePattern name="short">h:MM A</timePattern>
+    </timePatterns>
+    <dateTimeSymbols>GyMdkHmsSEDFwWahKzZ</dateTimeSymbols>
+    <numberPatterns>
+      <numberPattern name="numeric">z,zz9.zzz</numberPattern>
+      <numberPattern name="currency">$z,zz9.99|($z,zz9.99)</numberPattern>
+      <numberPattern name="percent">z,zz9%</numberPattern>
+    </numberPatterns>
+    <numberSymbols>
+      <numberSymbol name="decimal">.</numberSymbol>
+      <numberSymbol name="grouping">,</numberSymbol>
+      <numberSymbol name="percent">%</numberSymbol>
+      <numberSymbol name="minus">-</numberSymbol>
+      <numberSymbol name="zero">0</numberSymbol>
+    </numberSymbols>
+    <currencySymbols>
+      <currencySymbol name="symbol">$</currencySymbol>
+      <currencySymbol name="isoname">USD</currencySymbol>
+      <currencySymbol name="decimal">.</currencySymbol>
+    </currencySymbols>
+    <typefaces>
+      <typeface name="Myriad Pro"/>
+      <typeface name="Minion Pro"/>
+      <typeface name="Courier Std"/>
+      <typeface name="Adobe Pi Std"/>
+      <typeface name="Adobe Hebrew"/>
+      <typeface name="Adobe Arabic"/>
+      <typeface name="Adobe Thai"/>
+      <typeface name="Kozuka Gothic Pro-VI M"/>
+      <typeface name="Kozuka Mincho Pro-VI R"/>
+      <typeface name="Adobe Ming Std L"/>
+      <typeface name="Adobe Song Std L"/>
+      <typeface name="Adobe Myungjo Std M"/>
+    </typefaces>
+  </locale>
+</localeSet>
+endstream
+endobj
+7 0 obj <<
+  /Length 11
+>>
+stream
+</xdp:xdp>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/xfa_example.pdf b/pdf/pdfium/fuzzers/corpora/xfa/xfa_example.pdf
new file mode 100644
index 0000000..8464776
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/xfa_example.pdf
@@ -0,0 +1,230 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA [
+    (preamble)
+    3 0 R
+    (config)
+    4 0 R
+    (template)
+    5 0 R
+    (localeSet)
+    6 0 R
+    (postamble)
+    7 0 R
+  ]
+>>
+endobj
+3 0 obj <<
+  /Length 124
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2018-02-23T21:37:11Z" uuid="21482798-7bf0-40a4-bc5d-3cefdccf32b5">
+endstream
+endobj
+4 0 obj <<
+  /Length 642
+>>
+stream
+<config xmlns="http://www.xfa.org/schema/xci/3.0/">
+<agent name="designer">
+  <destination>pdf</destination>
+  <pdf>
+    <fontInfo/>
+  </pdf>
+</agent>
+<present>
+  <pdf>
+    <version>1.7</version>
+    <adobeExtensionLevel>8</adobeExtensionLevel>
+    <renderPolicy>client</renderPolicy>
+    <scriptModel>XFA</scriptModel>
+    <interactive>1</interactive>
+  </pdf>
+  <xdp>
+    <packets>*</packets>
+  </xdp>
+  <destination>pdf</destination>
+  <script>
+    <runScripts>server</runScripts>
+  </script>
+</present>
+<acrobat>
+  <acrobat7>
+    <dynamicRender>required</dynamicRender>
+  </acrobat7>
+  <validate>preSubmit</validate>
+</acrobat>
+</config>
+endstream
+endobj
+5 0 obj <<
+  /Length 633
+>>
+stream
+<template xmlns="http://www.xfa.org/schema/xfa-template/3.3/">
+  <subform name="form1" layout="tb" locale="zh_CN" restoreState="auto">
+    <pageSet>
+      <pageArea name="Page1" id="Page1">
+        <contentArea x="0.25in" y="0.25in" w="7.75in" h="11.25in"/>
+        <medium stock="default" short="612pt" long="792pt"/>
+      </pageArea>
+    </pageSet>
+    <subform w="576pt" h="756pt" name="Page1">
+      <draw name="HelloWorld" y="0.5in" x="0.5in" w="5in" h="2in">
+       <font typeface="Ahem" size="20pt"/>
+        <value>
+          <text>Hello, world.</text>
+        </value>
+      </draw>
+    </subform>
+  </subform>
+</template>
+endstream
+endobj
+6 0 obj <<
+  /Length 3455
+>>
+stream
+<localeSet xmlns="http://www.xfa.org/schema/xfa-locale-set/2.7/">
+  <locale name="en_US" desc="English (United States)">
+    <calendarSymbols name="gregorian">
+      <monthNames>
+        <month>January</month>
+        <month>February</month>
+        <month>March</month>
+        <month>April</month>
+        <month>May</month>
+        <month>June</month>
+        <month>July</month>
+        <month>August</month>
+        <month>September</month>
+        <month>October</month>
+        <month>November</month>
+        <month>December</month>
+      </monthNames>
+      <monthNames abbr="1">
+        <month>Jan</month>
+        <month>Feb</month>
+        <month>Mar</month>
+        <month>Apr</month>
+        <month>May</month>
+        <month>Jun</month>
+        <month>Jul</month>
+        <month>Aug</month>
+        <month>Sep</month>
+        <month>Oct</month>
+        <month>Nov</month>
+        <month>Dec</month>
+      </monthNames>
+      <dayNames>
+        <day>Sunday</day>
+        <day>Monday</day>
+        <day>Tuesday</day>
+        <day>Wednesday</day>
+        <day>Thursday</day>
+        <day>Friday</day>
+        <day>Saturday</day>
+      </dayNames>
+      <dayNames abbr="1">
+        <day>Sun</day>
+        <day>Mon</day>
+        <day>Tue</day>
+        <day>Wed</day>
+        <day>Thu</day>
+        <day>Fri</day>
+        <day>Sat</day>
+      </dayNames>
+      <meridiemNames>
+        <meridiem>AM</meridiem>
+        <meridiem>PM</meridiem>
+      </meridiemNames>
+      <eraNames>
+        <era>BC</era>
+        <era>AD</era>
+      </eraNames>
+    </calendarSymbols>
+    <datePatterns>
+      <datePattern name="full">EEEE, MMMM D, YYYY</datePattern>
+      <datePattern name="long">MMMM D, YYYY</datePattern>
+      <datePattern name="med">MMM D, YYYY</datePattern>
+      <datePattern name="short">M/D/YY</datePattern>
+    </datePatterns>
+    <timePatterns>
+      <timePattern name="full">h:MM:SS A Z</timePattern>
+      <timePattern name="long">h:MM:SS A Z</timePattern>
+      <timePattern name="med">h:MM:SS A</timePattern>
+      <timePattern name="short">h:MM A</timePattern>
+    </timePatterns>
+    <dateTimeSymbols>GyMdkHmsSEDFwWahKzZ</dateTimeSymbols>
+    <numberPatterns>
+      <numberPattern name="numeric">z,zz9.zzz</numberPattern>
+      <numberPattern name="currency">$z,zz9.99|($z,zz9.99)</numberPattern>
+      <numberPattern name="percent">z,zz9%</numberPattern>
+    </numberPatterns>
+    <numberSymbols>
+      <numberSymbol name="decimal">.</numberSymbol>
+      <numberSymbol name="grouping">,</numberSymbol>
+      <numberSymbol name="percent">%</numberSymbol>
+      <numberSymbol name="minus">-</numberSymbol>
+      <numberSymbol name="zero">0</numberSymbol>
+    </numberSymbols>
+    <currencySymbols>
+      <currencySymbol name="symbol">$</currencySymbol>
+      <currencySymbol name="isoname">USD</currencySymbol>
+      <currencySymbol name="decimal">.</currencySymbol>
+    </currencySymbols>
+    <typefaces>
+      <typeface name="Myriad Pro"/>
+      <typeface name="Minion Pro"/>
+      <typeface name="Courier Std"/>
+      <typeface name="Adobe Pi Std"/>
+      <typeface name="Adobe Hebrew"/>
+      <typeface name="Adobe Arabic"/>
+      <typeface name="Adobe Thai"/>
+      <typeface name="Kozuka Gothic Pro-VI M"/>
+      <typeface name="Kozuka Mincho Pro-VI R"/>
+      <typeface name="Adobe Ming Std L"/>
+      <typeface name="Adobe Song Std L"/>
+      <typeface name="Adobe Myungjo Std M"/>
+    </typefaces>
+  </locale>
+</localeSet>
+endstream
+endobj
+7 0 obj <<
+  /Length 11
+>>
+stream
+</xdp:xdp>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/xfa_multiline_textfield.pdf b/pdf/pdfium/fuzzers/corpora/xfa/xfa_multiline_textfield.pdf
new file mode 100644
index 0000000..85a63d5
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/xfa_multiline_textfield.pdf
@@ -0,0 +1,231 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA [
+    (preamble)
+    3 0 R
+    (config)
+    4 0 R
+    (template)
+    5 0 R
+    (localeSet)
+    6 0 R
+    (postamble)
+    7 0 R
+  ]
+>>
+endobj
+3 0 obj <<
+  /Length 124
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2018-02-23T21:37:11Z" uuid="21482798-7bf0-40a4-bc5d-3cefdccf32b5">
+endstream
+endobj
+4 0 obj <<
+  /Length 642
+>>
+stream
+<config xmlns="http://www.xfa.org/schema/xci/3.0/">
+<agent name="designer">
+  <destination>pdf</destination>
+  <pdf>
+    <fontInfo/>
+  </pdf>
+</agent>
+<present>
+  <pdf>
+    <version>1.7</version>
+    <adobeExtensionLevel>8</adobeExtensionLevel>
+    <renderPolicy>client</renderPolicy>
+    <scriptModel>XFA</scriptModel>
+    <interactive>1</interactive>
+  </pdf>
+  <xdp>
+    <packets>*</packets>
+  </xdp>
+  <destination>pdf</destination>
+  <script>
+    <runScripts>server</runScripts>
+  </script>
+</present>
+<acrobat>
+  <acrobat7>
+    <dynamicRender>required</dynamicRender>
+  </acrobat7>
+  <validate>preSubmit</validate>
+</acrobat>
+</config>
+endstream
+endobj
+5 0 obj <<
+  /Length 651
+>>
+stream
+<template xmlns="http://www.xfa.org/schema/xfa-template/3.3/">
+  <subform name="form1" layout="tb" locale="en_US" restoreState="auto">
+    <pageSet>
+      <pageArea name="Page1" id="Page1">
+        <contentArea x="18pt" y="18pt" w="612pt" h="792pt"/>
+        <medium stock="default" short="612pt" long="792pt"/>
+      </pageArea>
+    </pageSet>
+    <subform w="576pt" h="756pt" name="Page1">
+      <field name="TextField1" y="0pt" x="0pt" w="425pt" h="80pt">
+        <ui>
+          <textEdit multiLine="1">
+            <font typeface="Helvetica" size="16pt"/>
+          </textEdit>
+        </ui>
+      </field>
+    </subform>
+  </subform>
+</template>
+endstream
+endobj
+6 0 obj <<
+  /Length 3455
+>>
+stream
+<localeSet xmlns="http://www.xfa.org/schema/xfa-locale-set/2.7/">
+  <locale name="en_US" desc="English (United States)">
+    <calendarSymbols name="gregorian">
+      <monthNames>
+        <month>January</month>
+        <month>February</month>
+        <month>March</month>
+        <month>April</month>
+        <month>May</month>
+        <month>June</month>
+        <month>July</month>
+        <month>August</month>
+        <month>September</month>
+        <month>October</month>
+        <month>November</month>
+        <month>December</month>
+      </monthNames>
+      <monthNames abbr="1">
+        <month>Jan</month>
+        <month>Feb</month>
+        <month>Mar</month>
+        <month>Apr</month>
+        <month>May</month>
+        <month>Jun</month>
+        <month>Jul</month>
+        <month>Aug</month>
+        <month>Sep</month>
+        <month>Oct</month>
+        <month>Nov</month>
+        <month>Dec</month>
+      </monthNames>
+      <dayNames>
+        <day>Sunday</day>
+        <day>Monday</day>
+        <day>Tuesday</day>
+        <day>Wednesday</day>
+        <day>Thursday</day>
+        <day>Friday</day>
+        <day>Saturday</day>
+      </dayNames>
+      <dayNames abbr="1">
+        <day>Sun</day>
+        <day>Mon</day>
+        <day>Tue</day>
+        <day>Wed</day>
+        <day>Thu</day>
+        <day>Fri</day>
+        <day>Sat</day>
+      </dayNames>
+      <meridiemNames>
+        <meridiem>AM</meridiem>
+        <meridiem>PM</meridiem>
+      </meridiemNames>
+      <eraNames>
+        <era>BC</era>
+        <era>AD</era>
+      </eraNames>
+    </calendarSymbols>
+    <datePatterns>
+      <datePattern name="full">EEEE, MMMM D, YYYY</datePattern>
+      <datePattern name="long">MMMM D, YYYY</datePattern>
+      <datePattern name="med">MMM D, YYYY</datePattern>
+      <datePattern name="short">M/D/YY</datePattern>
+    </datePatterns>
+    <timePatterns>
+      <timePattern name="full">h:MM:SS A Z</timePattern>
+      <timePattern name="long">h:MM:SS A Z</timePattern>
+      <timePattern name="med">h:MM:SS A</timePattern>
+      <timePattern name="short">h:MM A</timePattern>
+    </timePatterns>
+    <dateTimeSymbols>GyMdkHmsSEDFwWahKzZ</dateTimeSymbols>
+    <numberPatterns>
+      <numberPattern name="numeric">z,zz9.zzz</numberPattern>
+      <numberPattern name="currency">$z,zz9.99|($z,zz9.99)</numberPattern>
+      <numberPattern name="percent">z,zz9%</numberPattern>
+    </numberPatterns>
+    <numberSymbols>
+      <numberSymbol name="decimal">.</numberSymbol>
+      <numberSymbol name="grouping">,</numberSymbol>
+      <numberSymbol name="percent">%</numberSymbol>
+      <numberSymbol name="minus">-</numberSymbol>
+      <numberSymbol name="zero">0</numberSymbol>
+    </numberSymbols>
+    <currencySymbols>
+      <currencySymbol name="symbol">$</currencySymbol>
+      <currencySymbol name="isoname">USD</currencySymbol>
+      <currencySymbol name="decimal">.</currencySymbol>
+    </currencySymbols>
+    <typefaces>
+      <typeface name="Myriad Pro"/>
+      <typeface name="Minion Pro"/>
+      <typeface name="Courier Std"/>
+      <typeface name="Adobe Pi Std"/>
+      <typeface name="Adobe Hebrew"/>
+      <typeface name="Adobe Arabic"/>
+      <typeface name="Adobe Thai"/>
+      <typeface name="Kozuka Gothic Pro-VI M"/>
+      <typeface name="Kozuka Mincho Pro-VI R"/>
+      <typeface name="Adobe Ming Std L"/>
+      <typeface name="Adobe Song Std L"/>
+      <typeface name="Adobe Myungjo Std M"/>
+    </typefaces>
+  </locale>
+</localeSet>
+endstream
+endobj
+7 0 obj <<
+  /Length 11
+>>
+stream
+</xdp:xdp>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/xfa_rectangle_node.pdf b/pdf/pdfium/fuzzers/corpora/xfa/xfa_rectangle_node.pdf
new file mode 100644
index 0000000..df10954
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/xfa_rectangle_node.pdf
@@ -0,0 +1,235 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA [
+    (preamble)
+    3 0 R
+    (config)
+    4 0 R
+    (template)
+    5 0 R
+    (localeSet)
+    6 0 R
+    (postamble)
+    7 0 R
+  ]
+>>
+endobj
+3 0 obj <<
+  /Length 124
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2018-02-23T21:37:11Z" uuid="21482798-7bf0-40a4-bc5d-3cefdccf32b5">
+endstream
+endobj
+4 0 obj <<
+  /Length 642
+>>
+stream
+<config xmlns="http://www.xfa.org/schema/xci/3.0/">
+<agent name="designer">
+  <destination>pdf</destination>
+  <pdf>
+    <fontInfo/>
+  </pdf>
+</agent>
+<present>
+  <pdf>
+    <version>1.7</version>
+    <adobeExtensionLevel>8</adobeExtensionLevel>
+    <renderPolicy>client</renderPolicy>
+    <scriptModel>XFA</scriptModel>
+    <interactive>1</interactive>
+  </pdf>
+  <xdp>
+    <packets>*</packets>
+  </xdp>
+  <destination>pdf</destination>
+  <script>
+    <runScripts>server</runScripts>
+  </script>
+</present>
+<acrobat>
+  <acrobat7>
+    <dynamicRender>required</dynamicRender>
+  </acrobat7>
+  <validate>preSubmit</validate>
+</acrobat>
+</config>
+endstream
+endobj
+5 0 obj <<
+  /Length 716
+>>
+stream
+<template xmlns="http://www.xfa.org/schema/xfa-template/3.3/">
+  <subform name="form1" layout="tb" locale="en_US" restoreState="auto">
+    <pageSet>
+      <pageArea name="Page1" id="Page1">
+        <contentArea x="18pt" y="18pt" w="612pt" h="792pt"/>
+        <medium stock="default" short="612pt" long="792pt"/>
+      </pageArea>
+    </pageSet>
+    <subform w="576pt" h="756pt" name="Page1">
+      <draw h="11.43mm" name="Rectangle3" w="30.48mm" x="170.18mm" y="65.868mm">
+        <ui>
+          <defaultUi />
+        </ui>
+        <value>
+          <rectangle>
+            <corner radius="5.08mm" />
+            <edge />
+          </rectangle>
+        </value>
+      </draw>
+    </subform>
+  </subform>
+</template>
+endstream
+endobj
+6 0 obj <<
+  /Length 3455
+>>
+stream
+<localeSet xmlns="http://www.xfa.org/schema/xfa-locale-set/2.7/">
+  <locale name="en_US" desc="English (United States)">
+    <calendarSymbols name="gregorian">
+      <monthNames>
+        <month>January</month>
+        <month>February</month>
+        <month>March</month>
+        <month>April</month>
+        <month>May</month>
+        <month>June</month>
+        <month>July</month>
+        <month>August</month>
+        <month>September</month>
+        <month>October</month>
+        <month>November</month>
+        <month>December</month>
+      </monthNames>
+      <monthNames abbr="1">
+        <month>Jan</month>
+        <month>Feb</month>
+        <month>Mar</month>
+        <month>Apr</month>
+        <month>May</month>
+        <month>Jun</month>
+        <month>Jul</month>
+        <month>Aug</month>
+        <month>Sep</month>
+        <month>Oct</month>
+        <month>Nov</month>
+        <month>Dec</month>
+      </monthNames>
+      <dayNames>
+        <day>Sunday</day>
+        <day>Monday</day>
+        <day>Tuesday</day>
+        <day>Wednesday</day>
+        <day>Thursday</day>
+        <day>Friday</day>
+        <day>Saturday</day>
+      </dayNames>
+      <dayNames abbr="1">
+        <day>Sun</day>
+        <day>Mon</day>
+        <day>Tue</day>
+        <day>Wed</day>
+        <day>Thu</day>
+        <day>Fri</day>
+        <day>Sat</day>
+      </dayNames>
+      <meridiemNames>
+        <meridiem>AM</meridiem>
+        <meridiem>PM</meridiem>
+      </meridiemNames>
+      <eraNames>
+        <era>BC</era>
+        <era>AD</era>
+      </eraNames>
+    </calendarSymbols>
+    <datePatterns>
+      <datePattern name="full">EEEE, MMMM D, YYYY</datePattern>
+      <datePattern name="long">MMMM D, YYYY</datePattern>
+      <datePattern name="med">MMM D, YYYY</datePattern>
+      <datePattern name="short">M/D/YY</datePattern>
+    </datePatterns>
+    <timePatterns>
+      <timePattern name="full">h:MM:SS A Z</timePattern>
+      <timePattern name="long">h:MM:SS A Z</timePattern>
+      <timePattern name="med">h:MM:SS A</timePattern>
+      <timePattern name="short">h:MM A</timePattern>
+    </timePatterns>
+    <dateTimeSymbols>GyMdkHmsSEDFwWahKzZ</dateTimeSymbols>
+    <numberPatterns>
+      <numberPattern name="numeric">z,zz9.zzz</numberPattern>
+      <numberPattern name="currency">$z,zz9.99|($z,zz9.99)</numberPattern>
+      <numberPattern name="percent">z,zz9%</numberPattern>
+    </numberPatterns>
+    <numberSymbols>
+      <numberSymbol name="decimal">.</numberSymbol>
+      <numberSymbol name="grouping">,</numberSymbol>
+      <numberSymbol name="percent">%</numberSymbol>
+      <numberSymbol name="minus">-</numberSymbol>
+      <numberSymbol name="zero">0</numberSymbol>
+    </numberSymbols>
+    <currencySymbols>
+      <currencySymbol name="symbol">$</currencySymbol>
+      <currencySymbol name="isoname">USD</currencySymbol>
+      <currencySymbol name="decimal">.</currencySymbol>
+    </currencySymbols>
+    <typefaces>
+      <typeface name="Myriad Pro"/>
+      <typeface name="Minion Pro"/>
+      <typeface name="Courier Std"/>
+      <typeface name="Adobe Pi Std"/>
+      <typeface name="Adobe Hebrew"/>
+      <typeface name="Adobe Arabic"/>
+      <typeface name="Adobe Thai"/>
+      <typeface name="Kozuka Gothic Pro-VI M"/>
+      <typeface name="Kozuka Mincho Pro-VI R"/>
+      <typeface name="Adobe Ming Std L"/>
+      <typeface name="Adobe Song Std L"/>
+      <typeface name="Adobe Myungjo Std M"/>
+    </typefaces>
+  </locale>
+</localeSet>
+endstream
+endobj
+7 0 obj <<
+  /Length 11
+>>
+stream
+</xdp:xdp>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/pdf/pdfium/fuzzers/corpora/xfa/xfa_textfield.pdf b/pdf/pdfium/fuzzers/corpora/xfa/xfa_textfield.pdf
new file mode 100644
index 0000000..38aaf0e1
--- /dev/null
+++ b/pdf/pdfium/fuzzers/corpora/xfa/xfa_textfield.pdf
@@ -0,0 +1,249 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA [
+    (preamble)
+    3 0 R
+    (config)
+    4 0 R
+    (template)
+    5 0 R
+    (localeSet)
+    6 0 R
+    (postamble)
+    7 0 R
+  ]
+>>
+endobj
+3 0 obj <<
+  /Length 124
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2018-02-23T21:37:11Z" uuid="21482798-7bf0-40a4-bc5d-3cefdccf32b5">
+endstream
+endobj
+4 0 obj <<
+  /Length 642
+>>
+stream
+<config xmlns="http://www.xfa.org/schema/xci/3.0/">
+<agent name="designer">
+  <destination>pdf</destination>
+  <pdf>
+    <fontInfo/>
+  </pdf>
+</agent>
+<present>
+  <pdf>
+    <version>1.7</version>
+    <adobeExtensionLevel>8</adobeExtensionLevel>
+    <renderPolicy>client</renderPolicy>
+    <scriptModel>XFA</scriptModel>
+    <interactive>1</interactive>
+  </pdf>
+  <xdp>
+    <packets>*</packets>
+  </xdp>
+  <destination>pdf</destination>
+  <script>
+    <runScripts>server</runScripts>
+  </script>
+</present>
+<acrobat>
+  <acrobat7>
+    <dynamicRender>required</dynamicRender>
+  </acrobat7>
+  <validate>preSubmit</validate>
+</acrobat>
+</config>
+endstream
+endobj
+5 0 obj <<
+  /Length 1144
+>>
+stream
+<template xmlns="http://www.xfa.org/schema/xfa-template/3.3/">
+  <subform name="form1" layout="tb" locale="en_US" restoreState="auto">
+    <pageSet>
+      <pageArea name="Page1" id="Page1">
+        <contentArea x="18pt" y="18pt" w="612pt" h="792pt"/>
+        <medium stock="default" short="612pt" long="792pt"/>
+      </pageArea>
+    </pageSet>
+    <subform w="576pt" h="756pt" name="Page1">
+      <field name="TextField1" y="0pt" x="0pt" w="200pt" h="32pt">
+        <font typeface="Ahem" size="20pt"/>
+        <ui>
+          <textEdit/>
+        </ui>
+        <para vAlign="middle"/>
+      </field>
+      <field name="Button1" y="42pt" x="0pt" w="100pt" h="32pt">
+        <ui>
+          <button highlight="inverted"/>
+        </ui>
+        <font typeface="Ahem" size="20pt"/>
+        <caption>
+          <value>
+            <text>Dummy</text>
+          </value>
+          <para vAlign="middle" hAlign="center"/>
+        </caption>
+        <border hand="right">
+          <edge stroke="raised"/>
+          <fill>
+            <color value="212,208,200"/>
+          </fill>
+        </border>
+      </field>
+    </subform>
+  </subform>
+</template>
+endstream
+endobj
+6 0 obj <<
+  /Length 3455
+>>
+stream
+<localeSet xmlns="http://www.xfa.org/schema/xfa-locale-set/2.7/">
+  <locale name="en_US" desc="English (United States)">
+    <calendarSymbols name="gregorian">
+      <monthNames>
+        <month>January</month>
+        <month>February</month>
+        <month>March</month>
+        <month>April</month>
+        <month>May</month>
+        <month>June</month>
+        <month>July</month>
+        <month>August</month>
+        <month>September</month>
+        <month>October</month>
+        <month>November</month>
+        <month>December</month>
+      </monthNames>
+      <monthNames abbr="1">
+        <month>Jan</month>
+        <month>Feb</month>
+        <month>Mar</month>
+        <month>Apr</month>
+        <month>May</month>
+        <month>Jun</month>
+        <month>Jul</month>
+        <month>Aug</month>
+        <month>Sep</month>
+        <month>Oct</month>
+        <month>Nov</month>
+        <month>Dec</month>
+      </monthNames>
+      <dayNames>
+        <day>Sunday</day>
+        <day>Monday</day>
+        <day>Tuesday</day>
+        <day>Wednesday</day>
+        <day>Thursday</day>
+        <day>Friday</day>
+        <day>Saturday</day>
+      </dayNames>
+      <dayNames abbr="1">
+        <day>Sun</day>
+        <day>Mon</day>
+        <day>Tue</day>
+        <day>Wed</day>
+        <day>Thu</day>
+        <day>Fri</day>
+        <day>Sat</day>
+      </dayNames>
+      <meridiemNames>
+        <meridiem>AM</meridiem>
+        <meridiem>PM</meridiem>
+      </meridiemNames>
+      <eraNames>
+        <era>BC</era>
+        <era>AD</era>
+      </eraNames>
+    </calendarSymbols>
+    <datePatterns>
+      <datePattern name="full">EEEE, MMMM D, YYYY</datePattern>
+      <datePattern name="long">MMMM D, YYYY</datePattern>
+      <datePattern name="med">MMM D, YYYY</datePattern>
+      <datePattern name="short">M/D/YY</datePattern>
+    </datePatterns>
+    <timePatterns>
+      <timePattern name="full">h:MM:SS A Z</timePattern>
+      <timePattern name="long">h:MM:SS A Z</timePattern>
+      <timePattern name="med">h:MM:SS A</timePattern>
+      <timePattern name="short">h:MM A</timePattern>
+    </timePatterns>
+    <dateTimeSymbols>GyMdkHmsSEDFwWahKzZ</dateTimeSymbols>
+    <numberPatterns>
+      <numberPattern name="numeric">z,zz9.zzz</numberPattern>
+      <numberPattern name="currency">$z,zz9.99|($z,zz9.99)</numberPattern>
+      <numberPattern name="percent">z,zz9%</numberPattern>
+    </numberPatterns>
+    <numberSymbols>
+      <numberSymbol name="decimal">.</numberSymbol>
+      <numberSymbol name="grouping">,</numberSymbol>
+      <numberSymbol name="percent">%</numberSymbol>
+      <numberSymbol name="minus">-</numberSymbol>
+      <numberSymbol name="zero">0</numberSymbol>
+    </numberSymbols>
+    <currencySymbols>
+      <currencySymbol name="symbol">$</currencySymbol>
+      <currencySymbol name="isoname">USD</currencySymbol>
+      <currencySymbol name="decimal">.</currencySymbol>
+    </currencySymbols>
+    <typefaces>
+      <typeface name="Myriad Pro"/>
+      <typeface name="Minion Pro"/>
+      <typeface name="Courier Std"/>
+      <typeface name="Adobe Pi Std"/>
+      <typeface name="Adobe Hebrew"/>
+      <typeface name="Adobe Arabic"/>
+      <typeface name="Adobe Thai"/>
+      <typeface name="Kozuka Gothic Pro-VI M"/>
+      <typeface name="Kozuka Mincho Pro-VI R"/>
+      <typeface name="Adobe Ming Std L"/>
+      <typeface name="Adobe Song Std L"/>
+      <typeface name="Adobe Myungjo Std M"/>
+    </typefaces>
+  </locale>
+</localeSet>
+endstream
+endobj
+7 0 obj <<
+  /Length 11
+>>
+stream
+</xdp:xdp>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+trailer <<
+  /Root 1 0 R
+>>
+%%EOF
diff --git a/remoting/base/socket_reader.h b/remoting/base/socket_reader.h
index 2581f197..1c5c957 100644
--- a/remoting/base/socket_reader.h
+++ b/remoting/base/socket_reader.h
@@ -5,10 +5,10 @@
 #ifndef REMOTING_BASE_SOCKET_READER_H_
 #define REMOTING_BASE_SOCKET_READER_H_
 
+#include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "net/base/completion_callback.h"
 
 namespace net {
 class IOBuffer;
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn
index 7aeefa7..1fd732b 100644
--- a/remoting/host/BUILD.gn
+++ b/remoting/host/BUILD.gn
@@ -381,6 +381,7 @@
     deps += [
       "//ash",
       "//remoting/host/chromeos",
+      "//ui/base/ime/chromeos",
     ]
 
     if (use_ozone) {
diff --git a/remoting/host/register_support_host_request_unittest.cc b/remoting/host/register_support_host_request_unittest.cc
index 51a715d..5f10998 100644
--- a/remoting/host/register_support_host_request_unittest.cc
+++ b/remoting/host/register_support_host_request_unittest.cc
@@ -77,8 +77,7 @@
   base::MessageLoop message_loop_;
   base::ScopedMockTimeMessageLoopTaskRunner mock_time_task_runner_;
   MockSignalStrategy signal_strategy_;
-  base::ObserverList<SignalStrategy::Listener, true>::Unchecked
-      signal_strategy_listeners_;
+  base::ObserverList<SignalStrategy::Listener, true> signal_strategy_listeners_;
   scoped_refptr<RsaKeyPair> key_pair_;
   base::MockCallback<RegisterSupportHostRequest::RegisterCallback> callback_;
 };
diff --git a/remoting/host/security_key/security_key_auth_handler_posix.cc b/remoting/host/security_key/security_key_auth_handler_posix.cc
index 3ecf953a..d27115b9 100644
--- a/remoting/host/security_key/security_key_auth_handler_posix.cc
+++ b/remoting/host/security_key/security_key_auth_handler_posix.cc
@@ -24,7 +24,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_checker.h"
-#include "net/base/completion_callback.h"
 #include "net/base/net_errors.h"
 #include "net/socket/stream_socket.h"
 #include "net/socket/unix_domain_server_socket_posix.h"
diff --git a/remoting/protocol/channel_multiplexer_unittest.cc b/remoting/protocol/channel_multiplexer_unittest.cc
index dbe07bd..c7754ba7a 100644
--- a/remoting/protocol/channel_multiplexer_unittest.cc
+++ b/remoting/protocol/channel_multiplexer_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/test/mock_callback.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "net/base/completion_repeating_callback.h"
 #include "net/base/net_errors.h"
 #include "net/socket/socket.h"
 #include "net/socket/stream_socket.h"
@@ -238,7 +239,7 @@
 
   scoped_refptr<net::IOBufferWithSize> buf = CreateTestBuffer(100);
 
-  base::MockCallback<net::CompletionCallback> cb1, cb2;
+  base::MockCallback<net::CompletionRepeatingCallback> cb1, cb2;
   EXPECT_CALL(cb1, Run(net::ERR_FAILED));
   EXPECT_CALL(cb2, Run(net::ERR_FAILED));
 
@@ -266,7 +267,7 @@
 
   scoped_refptr<net::IOBufferWithSize> buf = CreateTestBuffer(100);
 
-  base::MockCallback<net::CompletionCallback> cb1, cb2;
+  base::MockCallback<net::CompletionRepeatingCallback> cb1, cb2;
   EXPECT_CALL(cb1, Run(net::ERR_FAILED));
   EXPECT_CALL(cb2, Run(net::ERR_FAILED));
 
@@ -293,7 +294,7 @@
 
   scoped_refptr<net::IOBufferWithSize> buf = CreateTestBuffer(100);
 
-  base::MockCallback<net::CompletionCallback> cb1, cb2;
+  base::MockCallback<net::CompletionRepeatingCallback> cb1, cb2;
   EXPECT_CALL(cb1, Run(net::ERR_FAILED))
       .Times(AtMost(1))
       .WillOnce(InvokeWithoutArgs(this, &ChannelMultiplexerTest::DeleteAll));
diff --git a/remoting/protocol/fake_stream_socket.h b/remoting/protocol/fake_stream_socket.h
index a6b84ab..91709f8 100644
--- a/remoting/protocol/fake_stream_socket.h
+++ b/remoting/protocol/fake_stream_socket.h
@@ -12,7 +12,6 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
-#include "net/base/completion_callback.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "remoting/protocol/p2p_stream_socket.h"
 #include "remoting/protocol/stream_channel_factory.h"
diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h
index bf5d77a3..69d3e32 100644
--- a/remoting/protocol/jingle_session.h
+++ b/remoting/protocol/jingle_session.h
@@ -15,7 +15,6 @@
 #include "base/threading/thread_checker.h"
 #include "base/timer/timer.h"
 #include "crypto/rsa_private_key.h"
-#include "net/base/completion_callback.h"
 #include "remoting/protocol/authenticator.h"
 #include "remoting/protocol/datagram_channel_factory.h"
 #include "remoting/protocol/jingle_messages.h"
diff --git a/remoting/protocol/pseudotcp_adapter.cc b/remoting/protocol/pseudotcp_adapter.cc
index 5e052476..8470e71 100644
--- a/remoting/protocol/pseudotcp_adapter.cc
+++ b/remoting/protocol/pseudotcp_adapter.cc
@@ -15,7 +15,7 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
diff --git a/remoting/signaling/delegating_signal_strategy.h b/remoting/signaling/delegating_signal_strategy.h
index eb2e6df..f24980f 100644
--- a/remoting/signaling/delegating_signal_strategy.h
+++ b/remoting/signaling/delegating_signal_strategy.h
@@ -68,7 +68,7 @@
 
   IqCallback incoming_iq_callback_;
   IqCallback send_iq_callback_;
-  base::ObserverList<Listener>::Unchecked listeners_;
+  base::ObserverList<Listener> listeners_;
 
   base::WeakPtrFactory<DelegatingSignalStrategy> weak_factory_;
 
diff --git a/remoting/signaling/fake_signal_strategy.h b/remoting/signaling/fake_signal_strategy.h
index 67f870a..a5e5ba7 100644
--- a/remoting/signaling/fake_signal_strategy.h
+++ b/remoting/signaling/fake_signal_strategy.h
@@ -82,7 +82,7 @@
 
   SignalingAddress address_;
   PeerCallback peer_callback_;
-  base::ObserverList<Listener, true>::Unchecked listeners_;
+  base::ObserverList<Listener, true> listeners_;
 
   int last_id_;
 
diff --git a/remoting/signaling/ftl.proto b/remoting/signaling/ftl.proto
index 7547d51..97b4755 100644
--- a/remoting/signaling/ftl.proto
+++ b/remoting/signaling/ftl.proto
@@ -140,6 +140,7 @@
   MessageType message_type = 2;
   MessageClass message_class = 5;
   Id sender_id = 8;
+  bytes sender_registration_id = 17;
   Id receiver_id = 9;
   bytes message = 12;
 }
diff --git a/remoting/signaling/ftl_messaging_client.cc b/remoting/signaling/ftl_messaging_client.cc
index 7f72298..da06bfc 100644
--- a/remoting/signaling/ftl_messaging_client.cc
+++ b/remoting/signaling/ftl_messaging_client.cc
@@ -212,7 +212,9 @@
 
   ftl::ChromotingMessage chromoting_message;
   chromoting_message.ParseFromString(message.message());
-  callback_list_.Notify(message.sender_id().id(), chromoting_message.message());
+  callback_list_.Notify(message.sender_id().id(),
+                        message.sender_registration_id(),
+                        chromoting_message.message());
 }
 
 void FtlMessagingClient::OnMessageReceived(const ftl::InboxMessage& message) {
diff --git a/remoting/signaling/ftl_messaging_client.h b/remoting/signaling/ftl_messaging_client.h
index 97f695b..1b175abe 100644
--- a/remoting/signaling/ftl_messaging_client.h
+++ b/remoting/signaling/ftl_messaging_client.h
@@ -26,9 +26,11 @@
  public:
   using MessageCallback =
       base::RepeatingCallback<void(const std::string& sender_id,
+                                   const std::string& sender_registration_id,
                                    const std::string& message)>;
   using MessageCallbackSubscription =
       base::CallbackList<void(const std::string&,
+                              const std::string&,
                               const std::string&)>::Subscription;
   using DoneCallback = base::OnceCallback<void(const grpc::Status& status)>;
 
@@ -100,7 +102,8 @@
   RegistrationManager* registration_manager_;
   std::unique_ptr<Messaging::Stub> messaging_stub_;
   std::unique_ptr<MessageReceptionChannel> reception_channel_;
-  base::CallbackList<void(const std::string&, const std::string&)>
+  base::CallbackList<
+      void(const std::string&, const std::string&, const std::string&)>
       callback_list_;
 
   DISALLOW_COPY_AND_ASSIGN(FtlMessagingClient);
diff --git a/remoting/signaling/ftl_messaging_client_unittest.cc b/remoting/signaling/ftl_messaging_client_unittest.cc
index ac7c97f0..f51badfd 100644
--- a/remoting/signaling/ftl_messaging_client_unittest.cc
+++ b/remoting/signaling/ftl_messaging_client_unittest.cc
@@ -44,8 +44,8 @@
     test::GrpcServerResponder<ftl::AckMessagesResponse>;
 
 constexpr char kFakeSenderId[] = "fake_sender@gmail.com";
+constexpr char kFakeSenderRegId[] = "fake_sender_reg_id";
 constexpr char kFakeReceiverId[] = "fake_receiver@gmail.com";
-constexpr char kFakeRegistrationId[] = "fake_reg_id";
 constexpr char kMessage1Id[] = "msg_1";
 constexpr char kMessage2Id[] = "msg_1";
 constexpr char kMessage1Text[] = "Message 1";
@@ -56,6 +56,7 @@
   ftl::InboxMessage message;
   message.mutable_sender_id()->set_id(kFakeSenderId);
   message.mutable_receiver_id()->set_id(kFakeReceiverId);
+  message.set_sender_registration_id(kFakeSenderRegId);
   message.set_message_type(ftl::InboxMessage_MessageType_CHROMOTING_MESSAGE);
   message.set_message_id(message_id);
   ftl::ChromotingMessage crd_message;
@@ -223,6 +224,7 @@
   base::RunLoop run_loop;
   auto subscription = messaging_client_->RegisterMessageCallback(
       base::BindRepeating([](const std::string& sender_id,
+                             const std::string& sender_registration_id,
                              const std::string& message) { NOTREACHED(); }));
   messaging_client_->PullMessages(test::CheckStatusThenQuitRunLoopCallback(
       FROM_HERE, grpc::StatusCode::OK, &run_loop));
@@ -235,6 +237,7 @@
   base::RunLoop run_loop;
   auto subscription = messaging_client_->RegisterMessageCallback(
       base::BindRepeating([](const std::string& sender_id,
+                             const std::string& sender_registration_id,
                              const std::string& message) { NOTREACHED(); }));
   messaging_client_->PullMessages(test::CheckStatusThenQuitRunLoopCallback(
       FROM_HERE, grpc::StatusCode::UNAUTHENTICATED, &run_loop));
@@ -249,6 +252,7 @@
 
   auto subscription = messaging_client_->RegisterMessageCallback(
       base::BindRepeating([](const std::string& sender_id,
+                             const std::string& sender_registration_id,
                              const std::string& message) { NOTREACHED(); }));
 
   messaging_client_->PullMessages(test::CheckStatusThenQuitRunLoopCallback(
@@ -275,13 +279,13 @@
 TEST_F(FtlMessagingClientTest, TestPullMessages_ReturnsAndAcksTwoMessages) {
   base::RunLoop run_loop;
 
-  base::MockCallback<base::RepeatingCallback<void(const std::string& sender_id,
-                                                  const std::string& message)>>
-      mock_on_incoming_msg;
+  base::MockCallback<FtlMessagingClient::MessageCallback> mock_on_incoming_msg;
 
-  EXPECT_CALL(mock_on_incoming_msg, Run(kFakeSenderId, kMessage1Text))
+  EXPECT_CALL(mock_on_incoming_msg,
+              Run(kFakeSenderId, kFakeSenderRegId, kMessage1Text))
       .WillOnce(Return());
-  EXPECT_CALL(mock_on_incoming_msg, Run(kFakeSenderId, kMessage2Text))
+  EXPECT_CALL(mock_on_incoming_msg,
+              Run(kFakeSenderId, kFakeSenderRegId, kMessage2Text))
       .WillOnce(Return());
 
   auto subscription =
@@ -315,7 +319,7 @@
 TEST_F(FtlMessagingClientTest, TestSendMessage_Unauthenticated) {
   base::RunLoop run_loop;
   messaging_client_->SendMessage(
-      kFakeReceiverId, kFakeRegistrationId, kMessage1Text,
+      kFakeReceiverId, kFakeSenderRegId, kMessage1Text,
       test::CheckStatusThenQuitRunLoopCallback(
           FROM_HERE, grpc::StatusCode::UNAUTHENTICATED, &run_loop));
   ServerWaitAndRespondToInboxSendRequest(
@@ -349,13 +353,13 @@
 TEST_F(FtlMessagingClientTest, TestSendMessage_SendOneMessageWithRegId) {
   base::RunLoop run_loop;
   messaging_client_->SendMessage(
-      kFakeReceiverId, kFakeRegistrationId, kMessage1Text,
+      kFakeReceiverId, kFakeSenderRegId, kMessage1Text,
       test::CheckStatusThenQuitRunLoopCallback(FROM_HERE, grpc::StatusCode::OK,
                                                &run_loop));
   ServerWaitAndRespondToInboxSendRequest(
       base::BindOnce([](const ftl::InboxSendRequest& request) {
         EXPECT_EQ(1, request.dest_registration_ids_size());
-        EXPECT_EQ(kFakeRegistrationId, request.dest_registration_ids(0));
+        EXPECT_EQ(kFakeSenderRegId, request.dest_registration_ids(0));
         EXPECT_LT(0, request.time_to_live());
         EXPECT_EQ(kFakeReceiverId, request.dest_id().id());
         EXPECT_FALSE(request.message().message_id().empty());
diff --git a/remoting/signaling/signal_strategy.h b/remoting/signaling/signal_strategy.h
index 1adce232..d024479 100644
--- a/remoting/signaling/signal_strategy.h
+++ b/remoting/signaling/signal_strategy.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/observer_list_types.h"
 
 namespace jingle_xmpp {
 class XmlElement;
@@ -42,9 +43,9 @@
   // Callback interface for signaling event. Event handlers are not
   // allowed to destroy SignalStrategy, but may add or remove other
   // listeners.
-  class Listener {
+  class Listener : public base::CheckedObserver {
    public:
-    virtual ~Listener() {}
+    ~Listener() override {}
 
     // Called after state of the connection has changed. If the state
     // is DISCONNECTED, then GetError() can be used to get the reason
diff --git a/remoting/signaling/xmpp_signal_strategy.cc b/remoting/signaling/xmpp_signal_strategy.cc
index 4cf93c0..a0583592 100644
--- a/remoting/signaling/xmpp_signal_strategy.cc
+++ b/remoting/signaling/xmpp_signal_strategy.cc
@@ -143,7 +143,7 @@
 
   Error error_ = OK;
 
-  base::ObserverList<Listener, true>::Unchecked listeners_;
+  base::ObserverList<Listener, true> listeners_;
 
   base::RepeatingTimer keep_alive_timer_;
 
diff --git a/remoting/test/ftl_services_playground.cc b/remoting/test/ftl_services_playground.cc
index 8b7c2c1..8bd7d337 100644
--- a/remoting/test/ftl_services_playground.cc
+++ b/remoting/test/ftl_services_playground.cc
@@ -282,13 +282,16 @@
   std::move(on_done).Run();
 }
 
-void FtlServicesPlayground::OnMessageReceived(const std::string& sender_id,
-                                              const std::string& message) {
+void FtlServicesPlayground::OnMessageReceived(
+    const std::string& sender_id,
+    const std::string& sender_registration_id,
+    const std::string& message) {
   printf(
       "Received message:\n"
       "  Sender ID=%s\n"
+      "  Sender Registration ID=%s\n"
       "  Message=%s\n",
-      sender_id.c_str(), message.c_str());
+      sender_id.c_str(), sender_registration_id.c_str(), message.c_str());
 }
 
 void FtlServicesPlayground::OnStartReceivingMessagesDone(
diff --git a/remoting/test/ftl_services_playground.h b/remoting/test/ftl_services_playground.h
index dd3634a..563d615 100644
--- a/remoting/test/ftl_services_playground.h
+++ b/remoting/test/ftl_services_playground.h
@@ -65,6 +65,7 @@
   void StartReceivingMessages(base::OnceClosure on_done);
   void StopReceivingMessages(base::OnceClosure on_done);
   void OnMessageReceived(const std::string& sender_id,
+                         const std::string& sender_registration_id,
                          const std::string& message);
   void OnStartReceivingMessagesDone(base::OnceClosure on_done,
                                     const grpc::Status& status);
diff --git a/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc b/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc
index 9b934b1..757678a 100644
--- a/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc
+++ b/services/device/geolocation/wifi_data_provider_chromeos_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_task_environment.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/network/geolocation_handler.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/services/device/public/mojom/serial.mojom b/services/device/public/mojom/serial.mojom
index 231e171..4fde005 100644
--- a/services/device/public/mojom/serial.mojom
+++ b/services/device/public/mojom/serial.mojom
@@ -91,13 +91,7 @@
 // Discovers and enumerates serial devices available to the host.
 interface SerialPortManager {
   GetDevices() => (array<SerialPortInfo> devices);
-
-  // Creates a SerialPort instance attached to the port represented by |token|.
-  // When the pipe passed in |port_request| is closed the optional pipe passed
-  // in |watcher| will also be closed.
-  GetPort(mojo_base.mojom.UnguessableToken token,
-          SerialPort& port_request,
-          SerialPortConnectionWatcher? watcher);
+  GetPort(mojo_base.mojom.UnguessableToken token, SerialPort& port_request);
 };
 
 // Performs asynchronous I/O on serial devices.
@@ -146,6 +140,3 @@
   OnReadError(SerialReceiveError error);
   OnSendError(SerialSendError error);
 };
-
-interface SerialPortConnectionWatcher {
-};
diff --git a/services/device/serial/serial_port_impl.cc b/services/device/serial/serial_port_impl.cc
index 7bd4d89..5cec6719 100644
--- a/services/device/serial/serial_port_impl.cc
+++ b/services/device/serial/serial_port_impl.cc
@@ -20,13 +20,10 @@
 void SerialPortImpl::Create(
     const base::FilePath& path,
     mojom::SerialPortRequest request,
-    mojom::SerialPortConnectionWatcherPtrInfo watcher,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
-  auto impl = std::make_unique<SerialPortImpl>(path, std::move(ui_task_runner));
-  auto* impl_ptr = impl.get();
-  auto binding = mojo::MakeStrongBinding(std::move(impl), std::move(request));
-  if (watcher)
-    impl_ptr->SetWatcher(std::move(binding), std::move(watcher));
+  mojo::MakeStrongBinding(
+      std::make_unique<SerialPortImpl>(path, ui_task_runner),
+      std::move(request));
 }
 
 SerialPortImpl::SerialPortImpl(
@@ -39,17 +36,6 @@
 
 SerialPortImpl::~SerialPortImpl() = default;
 
-void SerialPortImpl::SetWatcher(
-    mojo::StrongBindingPtr<mojom::SerialPort> owning_binding,
-    mojom::SerialPortConnectionWatcherPtrInfo watcher) {
-  watcher_.Bind(std::move(watcher));
-  watcher_.set_connection_error_handler(base::BindOnce(
-      [](mojo::StrongBindingPtr<mojom::SerialPort> owning_binding) {
-        owning_binding->Close();
-      },
-      std::move(owning_binding)));
-}
-
 void SerialPortImpl::Open(mojom::SerialConnectionOptionsPtr options,
                           mojo::ScopedDataPipeConsumerHandle in_stream,
                           mojo::ScopedDataPipeProducerHandle out_stream,
diff --git a/services/device/serial/serial_port_impl.h b/services/device/serial/serial_port_impl.h
index 6e44808..c75decd2 100644
--- a/services/device/serial/serial_port_impl.h
+++ b/services/device/serial/serial_port_impl.h
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
 #include "services/device/public/mojom/serial.mojom.h"
@@ -33,7 +32,6 @@
   static void Create(
       const base::FilePath& path,
       mojom::SerialPortRequest request,
-      mojom::SerialPortConnectionWatcherPtrInfo watcher,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
 
   SerialPortImpl(const base::FilePath& path,
@@ -41,9 +39,6 @@
   ~SerialPortImpl() override;
 
  private:
-  void SetWatcher(mojo::StrongBindingPtr<mojom::SerialPort> owning_binding,
-                  mojom::SerialPortConnectionWatcherPtrInfo watcher);
-
   // mojom::SerialPort methods:
   void Open(mojom::SerialConnectionOptionsPtr options,
             mojo::ScopedDataPipeConsumerHandle in_stream,
@@ -71,14 +66,8 @@
                                const mojo::HandleSignalsState& state);
   void WriteToOutStream(uint32_t bytes_read, mojom::SerialReceiveError error);
 
-  // Underlying connection to the serial port.
   scoped_refptr<SerialIoHandler> io_handler_;
-
-  // Client interfaces.
   mojom::SerialPortClientAssociatedPtr client_;
-  mojom::SerialPortConnectionWatcherPtr watcher_;
-
-  // Data pipes for input and output.
   mojo::ScopedDataPipeConsumerHandle in_stream_;
   mojo::SimpleWatcher in_stream_watcher_;
   mojo::ScopedDataPipeProducerHandle out_stream_;
diff --git a/services/device/serial/serial_port_impl_unittest.cc b/services/device/serial/serial_port_impl_unittest.cc
index 8ef691ee..2e4405c7 100644
--- a/services/device/serial/serial_port_impl_unittest.cc
+++ b/services/device/serial/serial_port_impl_unittest.cc
@@ -5,8 +5,9 @@
 #include "services/device/serial/serial_port_impl.h"
 
 #include "base/macros.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
 #include "services/device/device_service_test_base.h"
+#include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/serial.mojom.h"
 
 namespace device {
@@ -19,55 +20,25 @@
   ~SerialPortImplTest() override = default;
 
  protected:
+  void SetUp() override {
+    DeviceServiceTestBase::SetUp();
+    connector()->BindInterface(mojom::kServiceName, &port_manager_);
+  }
+
+  void TearDown() override { port_manager_.reset(); }
+
+  mojom::SerialPortManagerPtr port_manager_;
   DISALLOW_COPY_AND_ASSIGN(SerialPortImplTest);
 };
 
-TEST_F(SerialPortImplTest, WatcherClosedWhenPortClosed) {
+// This is to simply test that on Linux/Mac/Windows a client can connect to
+// Device Service and bind the serial SerialPort interface correctly.
+// TODO(leonhsl): figure out how to add more robust tests.
+TEST_F(SerialPortImplTest, SimpleConnectTest) {
   mojom::SerialPortPtr serial_port;
-  mojom::SerialPortConnectionWatcherPtrInfo watcher_ptr;
-  auto watcher_binding = mojo::MakeStrongBinding(
-      std::make_unique<mojom::SerialPortConnectionWatcher>(),
-      mojo::MakeRequest(&watcher_ptr));
-  SerialPortImpl::Create(base::FilePath(), mojo::MakeRequest(&serial_port),
-                         std::move(watcher_ptr),
-                         base::ThreadTaskRunnerHandle::Get());
-
-  // To start with both the serial port connection and the connection watcher
-  // connection should remain open.
+  port_manager_->GetPort(base::UnguessableToken::Create(),
+                         mojo::MakeRequest(&serial_port));
   serial_port.FlushForTesting();
-  EXPECT_FALSE(serial_port.encountered_error());
-  watcher_binding->FlushForTesting();
-  EXPECT_TRUE(watcher_binding);
-
-  // When the serial port connection is closed the watcher connection should be
-  // closed.
-  serial_port.reset();
-  watcher_binding->FlushForTesting();
-  EXPECT_FALSE(watcher_binding);
-}
-
-TEST_F(SerialPortImplTest, PortClosedWhenWatcherClosed) {
-  mojom::SerialPortPtr serial_port;
-  mojom::SerialPortConnectionWatcherPtrInfo watcher_ptr;
-  auto watcher_binding = mojo::MakeStrongBinding(
-      std::make_unique<mojom::SerialPortConnectionWatcher>(),
-      mojo::MakeRequest(&watcher_ptr));
-  SerialPortImpl::Create(base::FilePath(), mojo::MakeRequest(&serial_port),
-                         std::move(watcher_ptr),
-                         base::ThreadTaskRunnerHandle::Get());
-
-  // To start with both the serial port connection and the connection watcher
-  // connection should remain open.
-  serial_port.FlushForTesting();
-  EXPECT_FALSE(serial_port.encountered_error());
-  watcher_binding->FlushForTesting();
-  EXPECT_TRUE(watcher_binding);
-
-  // When the watcher connection is closed, for safety, the serial port
-  // connection should also be closed.
-  watcher_binding->Close();
-  serial_port.FlushForTesting();
-  EXPECT_TRUE(serial_port.encountered_error());
 }
 
 }  // namespace
diff --git a/services/device/serial/serial_port_manager_impl.cc b/services/device/serial/serial_port_manager_impl.cc
index b63d273..6a0030d 100644
--- a/services/device/serial/serial_port_manager_impl.cc
+++ b/services/device/serial/serial_port_manager_impl.cc
@@ -39,18 +39,15 @@
   std::move(callback).Run(enumerator_->GetDevices());
 }
 
-void SerialPortManagerImpl::GetPort(
-    const base::UnguessableToken& token,
-    mojom::SerialPortRequest request,
-    mojom::SerialPortConnectionWatcherPtr watcher) {
+void SerialPortManagerImpl::GetPort(const base::UnguessableToken& token,
+                                    mojom::SerialPortRequest request) {
   if (!enumerator_)
     enumerator_ = SerialDeviceEnumerator::Create();
   base::Optional<base::FilePath> path = enumerator_->GetPathFromToken(token);
   if (path) {
     io_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&SerialPortImpl::Create, *path, std::move(request),
-                       watcher.PassInterface(), ui_task_runner_));
+        FROM_HERE, base::BindOnce(&SerialPortImpl::Create, *path,
+                                  std::move(request), ui_task_runner_));
   }
 }
 
diff --git a/services/device/serial/serial_port_manager_impl.h b/services/device/serial/serial_port_manager_impl.h
index a4ddaf6..7013395 100644
--- a/services/device/serial/serial_port_manager_impl.h
+++ b/services/device/serial/serial_port_manager_impl.h
@@ -39,8 +39,7 @@
   // mojom::SerialPortManager methods:
   void GetDevices(GetDevicesCallback callback) override;
   void GetPort(const base::UnguessableToken& token,
-               mojom::SerialPortRequest request,
-               mojom::SerialPortConnectionWatcherPtr watcher) override;
+               mojom::SerialPortRequest request) override;
 
   std::unique_ptr<SerialDeviceEnumerator> enumerator_;
 
diff --git a/services/device/serial/serial_port_manager_impl_unittest.cc b/services/device/serial/serial_port_manager_impl_unittest.cc
index 3714950f..c41ebc9 100644
--- a/services/device/serial/serial_port_manager_impl_unittest.cc
+++ b/services/device/serial/serial_port_manager_impl_unittest.cc
@@ -13,11 +13,9 @@
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/task/post_task.h"
-#include "base/test/bind_test_util.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread.h"
 #include "mojo/public/cpp/bindings/interface_ptr.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/device/device_service_test_base.h"
 #include "services/device/public/mojom/constants.mojom.h"
@@ -45,6 +43,46 @@
   mojo::MakeStrongBinding(std::move(manager), std::move(request));
 }
 
+void ExpectDevicesAndThen(const std::set<base::FilePath>& expected_paths,
+                          base::OnceClosure continuation,
+                          std::vector<mojom::SerialPortInfoPtr> results) {
+  EXPECT_EQ(expected_paths.size(), results.size());
+  std::set<base::FilePath> actual_paths;
+  for (size_t i = 0; i < results.size(); ++i)
+    actual_paths.insert(results[i]->path);
+  EXPECT_EQ(expected_paths, actual_paths);
+  std::move(continuation).Run();
+}
+
+void OnGotDevicesAndGetPort(mojom::SerialPortManagerPtr port_manager,
+                            base::OnceClosure continuation,
+                            std::vector<mojom::SerialPortInfoPtr> results) {
+  EXPECT_GT(results.size(), 0u);
+
+  mojom::SerialPortPtr serial_port;
+  port_manager->GetPort(results[0]->token, mojo::MakeRequest(&serial_port));
+  // Send a message on the pipe and wait for the response to make sure that the
+  // interface request was bound successfully.
+  serial_port.FlushForTesting();
+  EXPECT_FALSE(serial_port.encountered_error());
+  std::move(continuation).Run();
+}
+
+void OnGotDevicesForSimpleConnect(
+    mojom::SerialPortManagerPtr port_manager,
+    base::OnceClosure continuation,
+    std::vector<mojom::SerialPortInfoPtr> results) {
+  for (auto& device : results) {
+    mojom::SerialPortPtr serial_port;
+    port_manager->GetPort(device->token, mojo::MakeRequest(&serial_port));
+    // Send a message on the pipe and wait for the response to make sure that
+    // the interface request was bound successfully.
+    serial_port.FlushForTesting();
+    EXPECT_FALSE(serial_port.encountered_error());
+  }
+  std::move(continuation).Run();
+}
+
 }  // namespace
 
 class SerialPortManagerImplTest : public DeviceServiceTestBase {
@@ -72,38 +110,22 @@
   connector()->BindInterface(mojom::kServiceName, &port_manager);
 
   base::RunLoop loop;
-  port_manager->GetDevices(base::BindLambdaForTesting(
-      [&](std::vector<mojom::SerialPortInfoPtr> results) {
-        for (auto& device : results) {
-          mojom::SerialPortPtr serial_port;
-          port_manager->GetPort(device->token, mojo::MakeRequest(&serial_port),
-                                /*watcher=*/nullptr);
-          // Send a message on the pipe and wait for the response to make sure
-          // that the interface request was bound successfully.
-          serial_port.FlushForTesting();
-          EXPECT_FALSE(serial_port.encountered_error());
-        }
-        loop.Quit();
-      }));
+  auto* manager = port_manager.get();
+  manager->GetDevices(base::BindOnce(&OnGotDevicesForSimpleConnect,
+                                     std::move(port_manager),
+                                     loop.QuitClosure()));
   loop.Run();
 }
 
 TEST_F(SerialPortManagerImplTest, GetDevices) {
   mojom::SerialPortManagerPtr port_manager;
   BindSerialPortManager(mojo::MakeRequest(&port_manager));
-  const std::set<base::FilePath> expected_paths = {kFakeDevicePath1,
-                                                   kFakeDevicePath2};
+  std::set<base::FilePath> expected_paths = {kFakeDevicePath1,
+                                             kFakeDevicePath2};
 
   base::RunLoop loop;
-  port_manager->GetDevices(base::BindLambdaForTesting(
-      [&](std::vector<mojom::SerialPortInfoPtr> results) {
-        EXPECT_EQ(expected_paths.size(), results.size());
-        std::set<base::FilePath> actual_paths;
-        for (size_t i = 0; i < results.size(); ++i)
-          actual_paths.insert(results[i]->path);
-        EXPECT_EQ(expected_paths, actual_paths);
-        loop.Quit();
-      }));
+  port_manager->GetDevices(base::BindOnce(&ExpectDevicesAndThen, expected_paths,
+                                          loop.QuitClosure()));
   loop.Run();
 }
 
@@ -112,20 +134,9 @@
   BindSerialPortManager(mojo::MakeRequest(&port_manager));
 
   base::RunLoop loop;
-  port_manager->GetDevices(base::BindLambdaForTesting(
-      [&](std::vector<mojom::SerialPortInfoPtr> results) {
-        EXPECT_GT(results.size(), 0u);
-
-        mojom::SerialPortPtr serial_port;
-        port_manager->GetPort(results[0]->token,
-                              mojo::MakeRequest(&serial_port),
-                              /*watcher=*/nullptr);
-        // Send a message on the pipe and wait for the response to make sure
-        // that the interface request was bound successfully.
-        serial_port.FlushForTesting();
-        EXPECT_FALSE(serial_port.encountered_error());
-        loop.Quit();
-      }));
+  auto* manager = port_manager.get();
+  manager->GetDevices(base::BindOnce(
+      &OnGotDevicesAndGetPort, std::move(port_manager), loop.QuitClosure()));
   loop.Run();
 }
 
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc
index b105e27..a402097 100644
--- a/services/identity/public/cpp/identity_manager.cc
+++ b/services/identity/public/cpp/identity_manager.cc
@@ -321,10 +321,6 @@
   return diagnostics_provider_.get();
 }
 
-std::string IdentityManager::LegacySeedAccountInfo(const AccountInfo& info) {
-  return account_tracker_service_->SeedAccountInfo(info);
-}
-
 #if defined(OS_CHROMEOS)
 void IdentityManager::LegacySetPrimaryAccount(
     const std::string& gaia_id,
@@ -342,6 +338,10 @@
   gaia_cookie_manager_service_->ForceOnCookieChangeProcessing();
 }
 
+std::string IdentityManager::LegacySeedAccountInfo(const AccountInfo& info) {
+  return account_tracker_service_->SeedAccountInfo(info);
+}
+
 void IdentityManager::LegacyAddAccountFromSystem(
     const std::string& account_id) {
   token_service_->GetDelegate()->AddAccountFromSystem(account_id);
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h
index a8109f7..530095e 100644
--- a/services/identity/public/cpp/identity_manager.h
+++ b/services/identity/public/cpp/identity_manager.h
@@ -403,14 +403,6 @@
   // state of IdentityManager.
   DiagnosticsProvider* GetDiagnosticsProvider();
 
-  // Seeds the account whose account_id is given by
-  // AccountTrackerService::PickAccountIdForAccount() with its corresponding
-  // account information. Returns the same value PickAccountIdForAccount()
-  // when given the same arguments.
-  // NOTE: In normal usage, this method SHOULD NOT be called for getting the
-  // account id. It's only for replacement of production code.
-  std::string LegacySeedAccountInfo(const AccountInfo& info);
-
 #if defined(OS_CHROMEOS)
   // Sets the primary account info with IdentityManager.
   // TODO(https://crbug.com/814787): Eliminate this method.
@@ -427,6 +419,15 @@
   // or move it to the network::CookieManager.
   void ForceTriggerOnCookieChange();
 
+  // Seeds the account whose account_id is given by
+  // AccountTrackerService::PickAccountIdForAccount() with its corresponding
+  // account information. Returns the same value PickAccountIdForAccount()
+  // when given the same arguments.
+  // NOTE: In normal usage, this method SHOULD NOT be called for getting the
+  // account id. It's only for replacement of production code.
+  // TODO(https://crbug.com/926940): Eliminate the need to expose this.
+  std::string LegacySeedAccountInfo(const AccountInfo& info);
+
   // Adds a given account to the token service from a system account. This
   // API calls OAuth2TokenServiceDelegate::AddAccountFromSystem and it
   // triggers platform specific implementation for IOS.
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc
index 21cb5ac..43ebf0c 100644
--- a/services/identity/public/cpp/identity_manager_unittest.cc
+++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -1334,6 +1334,7 @@
 }
 #endif
 
+#if defined(OS_IOS)
 TEST_F(IdentityManagerTest, LegacySeedAccountInfo) {
   ASSERT_FALSE(
       identity_manager()
@@ -1357,7 +1358,6 @@
   EXPECT_EQ(account_info.gaia, kTestGaiaId2);
 }
 
-#if defined(OS_IOS)
 TEST_F(IdentityManagerTest, ForceTriggerOnCookieChange) {
   base::RunLoop run_loop;
   identity_manager_observer()->SetOnAccountsInCookieUpdatedCallback(
diff --git a/services/identity/public/cpp/identity_test_environment.cc b/services/identity/public/cpp/identity_test_environment.cc
index 0f47843..ed0a235 100644
--- a/services/identity/public/cpp/identity_test_environment.cc
+++ b/services/identity/public/cpp/identity_test_environment.cc
@@ -142,8 +142,6 @@
   AccountTrackerService::RegisterPrefs(test_pref_service->registry());
   ProfileOAuth2TokenService::RegisterProfilePrefs(
       test_pref_service->registry());
-  IdentityManager::RegisterProfilePrefs(test_pref_service->registry());
-  IdentityManager::RegisterLocalStatePrefs(test_pref_service->registry());
 
   owned_token_service_ =
       std::make_unique<FakeProfileOAuth2TokenService>(test_pref_service);
@@ -152,29 +150,47 @@
   owned_account_tracker_service_->Initialize(test_pref_service,
                                              base::FilePath());
 
+  owned_identity_manager_ = BuildIdentityManagerForTests(
+      test_signin_client, test_pref_service, owned_token_service_.get(),
+      owned_account_tracker_service_.get(), account_consistency,
+      test_url_loader_factory);
+
+  Initialize();
+}
+
+// static
+std::unique_ptr<IdentityManager>
+IdentityTestEnvironment::BuildIdentityManagerForTests(
+    SigninClient* signin_client,
+    sync_preferences::TestingPrefServiceSyncable* test_pref_service,
+    FakeProfileOAuth2TokenService* token_service,
+    AccountTrackerService* account_tracker_service,
+    signin::AccountConsistencyMethod account_consistency,
+    network::TestURLLoaderFactory* test_url_loader_factory) {
+  IdentityManager::RegisterProfilePrefs(test_pref_service->registry());
+  IdentityManager::RegisterLocalStatePrefs(test_pref_service->registry());
+
   auto account_fetcher_service = std::make_unique<AccountFetcherService>();
   account_fetcher_service->Initialize(
-      test_signin_client, owned_token_service_.get(),
-      owned_account_tracker_service_.get(),
+      signin_client, token_service, account_tracker_service,
       std::make_unique<image_fetcher::FakeImageDecoder>());
 
 #if defined(OS_CHROMEOS)
   std::unique_ptr<SigninManagerBase> signin_manager =
-      std::make_unique<SigninManagerBase>(test_signin_client,
-                                          owned_token_service_.get(),
-                                          owned_account_tracker_service_.get());
+      std::make_unique<SigninManagerBase>(signin_client, token_service,
+                                          account_tracker_service);
 #else
   std::unique_ptr<SigninManagerBase> signin_manager =
-      std::make_unique<SigninManager>(
-          test_signin_client, owned_token_service_.get(),
-          owned_account_tracker_service_.get(), nullptr, account_consistency);
+      std::make_unique<SigninManager>(signin_client, token_service,
+                                      account_tracker_service, nullptr,
+                                      account_consistency);
 #endif
   signin_manager->Initialize(test_pref_service);
 
   std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service;
   if (test_url_loader_factory != nullptr) {
     gaia_cookie_manager_service = std::make_unique<GaiaCookieManagerService>(
-        owned_token_service_.get(), test_signin_client,
+        token_service, signin_client,
         base::BindRepeating(
             [](network::TestURLLoaderFactory* test_url_loader_factory)
                 -> scoped_refptr<network::SharedURLLoaderFactory> {
@@ -183,7 +199,7 @@
             test_url_loader_factory));
   } else {
     gaia_cookie_manager_service = std::make_unique<GaiaCookieManagerService>(
-        owned_token_service_.get(), test_signin_client);
+        token_service, signin_client);
   }
 
   std::unique_ptr<PrimaryAccountMutator> primary_account_mutator;
@@ -191,32 +207,30 @@
 
 #if !defined(OS_CHROMEOS)
   primary_account_mutator = std::make_unique<PrimaryAccountMutatorImpl>(
-      owned_account_tracker_service_.get(),
+      account_tracker_service,
       static_cast<SigninManager*>(signin_manager.get()));
 #endif
 
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
   accounts_mutator = std::make_unique<AccountsMutatorImpl>(
-      owned_token_service_.get(), owned_account_tracker_service_.get(),
-      signin_manager.get(), test_pref_service);
+      token_service, account_tracker_service, signin_manager.get(),
+      test_pref_service);
 #endif
 
   std::unique_ptr<DiagnosticsProvider> diagnostics_provider =
       std::make_unique<DiagnosticsProviderImpl>(
-          owned_token_service_.get(), gaia_cookie_manager_service.get());
+          token_service, gaia_cookie_manager_service.get());
 
   std::unique_ptr<AccountsCookieMutator> accounts_cookie_mutator =
       std::make_unique<AccountsCookieMutatorImpl>(
           gaia_cookie_manager_service.get());
 
-  owned_identity_manager_ = std::make_unique<IdentityManager>(
+  return std::make_unique<IdentityManager>(
       std::move(gaia_cookie_manager_service), std::move(signin_manager),
-      std::move(account_fetcher_service), owned_token_service_.get(),
-      owned_account_tracker_service_.get(), std::move(primary_account_mutator),
+      std::move(account_fetcher_service), token_service,
+      account_tracker_service, std::move(primary_account_mutator),
       std::move(accounts_mutator), std::move(accounts_cookie_mutator),
       std::move(diagnostics_provider));
-
-  Initialize();
 }
 
 IdentityTestEnvironment::~IdentityTestEnvironment() {
diff --git a/services/identity/public/cpp/identity_test_environment.h b/services/identity/public/cpp/identity_test_environment.h
index caedd6257..504fe9b 100644
--- a/services/identity/public/cpp/identity_test_environment.h
+++ b/services/identity/public/cpp/identity_test_environment.h
@@ -352,6 +352,16 @@
   base::OnceClosure on_access_token_requested_callback_;
   std::vector<AccessTokenRequestState> requesters_;
 
+  // Create an IdentityManager instance for tests.
+  static std::unique_ptr<IdentityManager> BuildIdentityManagerForTests(
+      SigninClient* signin_client,
+      sync_preferences::TestingPrefServiceSyncable* test_pref_service,
+      FakeProfileOAuth2TokenService* token_service,
+      AccountTrackerService* account_tracker_service,
+      signin::AccountConsistencyMethod account_consistency =
+          signin::AccountConsistencyMethod::kDisabled,
+      network::TestURLLoaderFactory* test_url_loader_factory = nullptr);
+
   // Shared constructor initialization logic.
   void Initialize();
 
diff --git a/services/metrics/public/cpp/ukm_recorder.h b/services/metrics/public/cpp/ukm_recorder.h
index c547e09..2083c2d 100644
--- a/services/metrics/public/cpp/ukm_recorder.h
+++ b/services/metrics/public/cpp/ukm_recorder.h
@@ -29,7 +29,6 @@
 
 namespace blink {
 class Document;
-class NavigatorVR;
 }  // namespace blink
 
 namespace cc {
@@ -112,7 +111,6 @@
   friend TestRecordingHelper;
   friend autofill::TestAutofillClient;
   friend blink::Document;
-  friend blink::NavigatorVR;
   friend cc::UkmManager;
   friend content::CrossSiteDocumentResourceHandler;
   friend content::PluginServiceImpl;
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 4d7e6bf..3594cb4 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -13,6 +13,7 @@
 #include "base/command_line.h"
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/debug/dump_without_crashing.h"
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop_current.h"
@@ -1971,6 +1972,11 @@
   builder->set_host_mapping_rules(
       command_line->GetSwitchValueASCII(switches::kHostResolverRules));
 
+  // Allow legacy context CopyFrom() functionality only if network service is
+  // disabled. The new service-enabled world should never do such copying.
+  if (!base::FeatureList::IsEnabled(features::kNetworkService))
+    builder->set_allow_copy();
+
   auto result =
       URLRequestContextOwner(std::move(pref_service), builder->Build());
 
diff --git a/services/network/network_service.cc b/services/network/network_service.cc
index d1bc7256..7a8cae3f 100644
--- a/services/network/network_service.cc
+++ b/services/network/network_service.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/environment.h"
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
@@ -352,6 +353,7 @@
     mojom::NetworkContextParamsPtr params,
     std::unique_ptr<URLRequestContextBuilderMojo> builder,
     net::URLRequestContext** url_request_context) {
+  DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
   std::unique_ptr<NetworkContext> network_context =
       std::make_unique<NetworkContext>(this, std::move(request),
                                        std::move(params), std::move(builder));
diff --git a/services/resource_coordinator/public/cpp/resource_coordinator_features.h b/services/resource_coordinator/public/cpp/resource_coordinator_features.h
index e1fee61..f2a9f8b3 100644
--- a/services/resource_coordinator/public/cpp/resource_coordinator_features.h
+++ b/services/resource_coordinator/public/cpp/resource_coordinator_features.h
@@ -17,8 +17,6 @@
 // The features should be documented alongside the definition of their values
 // in the .cc file.
 extern const COMPONENT_EXPORT(SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_FEATURES)
-    base::Feature kGlobalResourceCoordinator;
-extern const COMPONENT_EXPORT(SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_FEATURES)
     base::Feature kPerformanceMeasurement;
 
 #if defined(OS_WIN)
diff --git a/services/tracing/perfetto/json_trace_exporter.cc b/services/tracing/perfetto/json_trace_exporter.cc
index cafaef6d..f86102c 100644
--- a/services/tracing/perfetto/json_trace_exporter.cc
+++ b/services/tracing/perfetto/json_trace_exporter.cc
@@ -23,6 +23,8 @@
 
 constexpr size_t kTraceEventBufferSizeInBytes = 100 * 1024;
 
+const char kStrippedArgument[] = "__stripped__";
+
 template <typename Nested>
 void AppendProtoArrayAsJSON(std::string* out, const Nested& array);
 
@@ -185,10 +187,12 @@
 
 JSONTraceExporter::JSONTraceExporter(
     ArgumentFilterPredicate argument_filter_predicate,
+    MetadataFilterPredicate metadata_filter_predicate,
     OnTraceEventJSONCallback callback)
     : out_(callback),
       metadata_(std::make_unique<base::DictionaryValue>()),
-      argument_filter_predicate_(std::move(argument_filter_predicate)) {}
+      argument_filter_predicate_(std::move(argument_filter_predicate)),
+      metadata_filter_predicate_(std::move(metadata_filter_predicate)) {}
 
 JSONTraceExporter::~JSONTraceExporter() = default;
 
@@ -291,6 +295,12 @@
 
 void JSONTraceExporter::AddChromeMetadata(
     const perfetto::protos::ChromeMetadata& metadata) {
+  if (!metadata_filter_predicate_.is_null() &&
+      !metadata_filter_predicate_.Run(metadata.name())) {
+    metadata_->SetString(metadata.name(), kStrippedArgument);
+    return;
+  }
+
   if (metadata.has_string_value()) {
     metadata_->SetString(metadata.name(), metadata.string_value());
   } else if (metadata.has_int_value()) {
@@ -308,6 +318,12 @@
 
 void JSONTraceExporter::SetTraceStatsMetadata(
     const perfetto::protos::TraceStats& trace_stats) {
+  if (!metadata_filter_predicate_.is_null() &&
+      !metadata_filter_predicate_.Run("perfetto_trace_stats")) {
+    metadata_->SetString("perfetto_trace_stats", kStrippedArgument);
+    return;
+  }
+
   auto dict = std::make_unique<base::DictionaryValue>();
   dict->SetInteger("producers_connected", trace_stats.producers_connected());
   dict->SetInteger("producers_seen", trace_stats.producers_seen());
@@ -500,7 +516,7 @@
     return true;
   }
   if (ArgumentNameIsStripped(name)) {
-    AddArg()->AppendF("\"%s\":\"__stripped__\"", name.c_str());
+    AddArg()->AppendF("\"%s\":\"%s\"", name.c_str(), kStrippedArgument);
     return true;
   }
   return false;
diff --git a/services/tracing/perfetto/json_trace_exporter.h b/services/tracing/perfetto/json_trace_exporter.h
index 3e38a96..9e96cba 100644
--- a/services/tracing/perfetto/json_trace_exporter.h
+++ b/services/tracing/perfetto/json_trace_exporter.h
@@ -51,12 +51,17 @@
                                    const char* event_name,
                                    ArgumentNameFilterPredicate*)>;
 
+  // Given a metadata name, returns if the event should be filtered or not.
+  using MetadataFilterPredicate =
+      base::RepeatingCallback<bool(const std::string& metadata_name)>;
+
   using OnTraceEventJSONCallback =
       base::RepeatingCallback<void(const std::string& json,
                                    base::DictionaryValue* metadata,
                                    bool has_more)>;
 
   JSONTraceExporter(ArgumentFilterPredicate argument_filter_predicate,
+                    MetadataFilterPredicate metadata_filter_predicate,
                     OnTraceEventJSONCallback callback);
   virtual ~JSONTraceExporter();
 
@@ -64,8 +69,12 @@
   // |json_callback| passed in the constructor with the converted trace data.
   void OnTraceData(std::vector<perfetto::TracePacket> packets, bool has_more);
 
-  void SetArgumentFilterForTesting(const ArgumentFilterPredicate& predicate) {
-    argument_filter_predicate_ = predicate;
+  void SetArgumentFilterForTesting(ArgumentFilterPredicate predicate) {
+    argument_filter_predicate_ = std::move(predicate);
+  }
+
+  void SetMetdataFilterPredicateForTesting(MetadataFilterPredicate predicate) {
+    metadata_filter_predicate_ = std::move(predicate);
   }
 
   void set_label_filter(const std::string& label_filter) {
@@ -259,6 +268,7 @@
   std::string legacy_system_ftrace_output_;
   std::unique_ptr<base::DictionaryValue> metadata_;
   ArgumentFilterPredicate argument_filter_predicate_;
+  MetadataFilterPredicate metadata_filter_predicate_;
 
   DISALLOW_COPY_AND_ASSIGN(JSONTraceExporter);
 };
diff --git a/services/tracing/perfetto/json_trace_exporter_unittest.cc b/services/tracing/perfetto/json_trace_exporter_unittest.cc
index da512a135..8a55cd2 100644
--- a/services/tracing/perfetto/json_trace_exporter_unittest.cc
+++ b/services/tracing/perfetto/json_trace_exporter_unittest.cc
@@ -85,8 +85,10 @@
 class TestJSONTraceExporter : public JSONTraceExporter {
  public:
   TestJSONTraceExporter(ArgumentFilterPredicate argument_filter_predicate,
+                        MetadataFilterPredicate metadata_filter_predicate,
                         OnTraceEventJSONCallback callback)
       : JSONTraceExporter(std::move(argument_filter_predicate),
+                          std::move(metadata_filter_predicate),
                           std::move(callback)) {}
   ~TestJSONTraceExporter() override = default;
 
@@ -189,6 +191,7 @@
   JsonTraceExporterTest()
       : json_trace_exporter_(new TestJSONTraceExporter(
             JSONTraceExporter::ArgumentFilterPredicate(),
+            JSONTraceExporter::MetadataFilterPredicate(),
             base::BindRepeating(&JsonTraceExporterTest::OnTraceEventJSON,
                                 base::Unretained(this)))) {}
 
@@ -615,6 +618,33 @@
             "\"metadata_2\":{\"dict\":{\"bool\":true}}}}");
 }
 
+TEST_F(JsonTraceExporterTest, TestMetadataFiltering) {
+  json_trace_exporter_->SetMetdataFilterPredicateForTesting(
+      base::BindRepeating([](const std::string& name) -> bool {
+        return name.find("2") != std::string::npos;
+      }));
+
+  json_trace_exporter_->metadata.emplace_back();
+  auto& m1 = json_trace_exporter_->metadata.back();
+  m1.set_name("metadata_1");
+  m1.set_bool_value(true);
+  json_trace_exporter_->metadata.emplace_back();
+  auto& m2 = json_trace_exporter_->metadata.back();
+  m2.set_name("metadata_20");
+  m2.set_int_value(50);
+  json_trace_exporter_->metadata.emplace_back();
+  auto& m3 = json_trace_exporter_->metadata.back();
+  m3.set_name("metadata_21");
+  m3.set_json_value("{\"dict\":{\"bool\":true}}");
+  json_trace_exporter_->OnTraceData(std::vector<perfetto::TracePacket>(),
+                                    false);
+  EXPECT_EQ(unparsed_trace_data_,
+            "{\"traceEvents\":[],"
+            "\"metadata\":{\"metadata_1\":\"__stripped__\","
+            "\"metadata_20\":50,"
+            "\"metadata_21\":{\"dict\":{\"bool\":true}}}}");
+}
+
 TEST_F(JsonTraceExporterTest, ComplexMultipleCallback) {
   // Allocate a string that will cause the buffer to be flushed after this
   // event.
diff --git a/services/tracing/perfetto/perfetto_tracing_coordinator.cc b/services/tracing/perfetto/perfetto_tracing_coordinator.cc
index f3b1f1f..73afadb 100644
--- a/services/tracing/perfetto/perfetto_tracing_coordinator.cc
+++ b/services/tracing/perfetto/perfetto_tracing_coordinator.cc
@@ -57,15 +57,18 @@
           base::BindRepeating(&IsMetadataWhitelisted));
     }
 
-    auto arg_filter_predicate =
-        chrome_config.IsArgumentFilterEnabled()
-            ? base::trace_event::TraceLog::GetInstance()
-                  ->GetArgumentFilterPredicate()
-            : JSONTraceExporter::ArgumentFilterPredicate();
+    JSONTraceExporter::ArgumentFilterPredicate arg_filter_predicate;
+    JSONTraceExporter::MetadataFilterPredicate metadata_filter_predicate;
+    if (chrome_config.IsArgumentFilterEnabled()) {
+      auto* trace_log = base::trace_event::TraceLog::GetInstance();
+      arg_filter_predicate = trace_log->GetArgumentFilterPredicate();
+      metadata_filter_predicate = trace_log->GetMetadataFilterPredicate();
+    }
     auto json_event_callback = base::BindRepeating(
         &TracingSession::OnJSONTraceEventCallback, base::Unretained(this));
     json_trace_exporter_ = std::make_unique<TrackEventJSONExporter>(
-        std::move(arg_filter_predicate), std::move(json_event_callback));
+        std::move(arg_filter_predicate), std::move(metadata_filter_predicate),
+        std::move(json_event_callback));
     perfetto::TracingService* service =
         PerfettoService::GetInstance()->GetService();
     consumer_endpoint_ = service->ConnectConsumer(this, /*uid=*/0);
diff --git a/services/tracing/perfetto/track_event_json_exporter.cc b/services/tracing/perfetto/track_event_json_exporter.cc
index 9878a95..01fbca4 100644
--- a/services/tracing/perfetto/track_event_json_exporter.cc
+++ b/services/tracing/perfetto/track_event_json_exporter.cc
@@ -29,8 +29,10 @@
 
 TrackEventJSONExporter::TrackEventJSONExporter(
     JSONTraceExporter::ArgumentFilterPredicate argument_filter_predicate,
+    JSONTraceExporter::MetadataFilterPredicate metadata_filter_predicate,
     JSONTraceExporter::OnTraceEventJSONCallback callback)
     : JSONTraceExporter(std::move(argument_filter_predicate),
+                        std::move(metadata_filter_predicate),
                         std::move(callback)),
       current_state_(0) {}
 
diff --git a/services/tracing/perfetto/track_event_json_exporter.h b/services/tracing/perfetto/track_event_json_exporter.h
index aa32c90..a98c976a 100644
--- a/services/tracing/perfetto/track_event_json_exporter.h
+++ b/services/tracing/perfetto/track_event_json_exporter.h
@@ -25,6 +25,7 @@
 class TrackEventJSONExporter : public JSONTraceExporter {
  public:
   TrackEventJSONExporter(ArgumentFilterPredicate argument_filter_predicate,
+                         MetadataFilterPredicate metadata_filter_predicate,
                          OnTraceEventJSONCallback callback);
 
   ~TrackEventJSONExporter() override;
diff --git a/services/tracing/perfetto/track_event_json_exporter_unittest.cc b/services/tracing/perfetto/track_event_json_exporter_unittest.cc
index 140f96cc..704867f 100644
--- a/services/tracing/perfetto/track_event_json_exporter_unittest.cc
+++ b/services/tracing/perfetto/track_event_json_exporter_unittest.cc
@@ -79,6 +79,7 @@
       const std::vector<perfetto::protos::TracePacket>& trace_packet_protos) {
     json_trace_exporter_.reset(new TrackEventJSONExporter(
         JSONTraceExporter::ArgumentFilterPredicate(),
+        JSONTraceExporter::MetadataFilterPredicate(),
         base::BindRepeating(&TrackEventJsonExporterTest::OnTraceEventJson,
                             base::Unretained(this))));
 
diff --git a/services/tracing/public/cpp/trace_event_args_whitelist.cc b/services/tracing/public/cpp/trace_event_args_whitelist.cc
index 908d35b..2e622d82 100644
--- a/services/tracing/public/cpp/trace_event_args_whitelist.cc
+++ b/services/tracing/public/cpp/trace_event_args_whitelist.cc
@@ -16,16 +16,17 @@
 // Each whitelist entry is used to whitelist an array arguments for a
 // single or group of trace events.
 struct WhitelistEntry {
-  // Category name of the intertested trace event.
+  // Category name of the interested trace event.
   const char* category_name;
-  // Pattern to match the intertested trace event name.
+  // Pattern to match the interested trace event name.
   const char* event_name;
-  // List of patterns that match the whitelisted arguements.
+  // List of patterns that match the whitelisted arguments.
   const char* const* arg_name_filter;
 };
 
 const char* const kScopedBlockingCallAllowedArgs[] = {"file_name",
                                                       "function_name", nullptr};
+const char* const kGetFallbackFontsAllowedArgs[] = {"script", nullptr};
 const char* const kGPUAllowedArgs[] = {nullptr};
 const char* const kInputLatencyAllowedArgs[] = {"data", nullptr};
 const char* const kMemoryDumpAllowedArgs[] = {"dumps", nullptr};
@@ -62,6 +63,8 @@
     {TRACE_DISABLED_BY_DEFAULT("system_stats"), "*", nullptr},
     {TRACE_DISABLED_BY_DEFAULT("v8.gc"), "*", kV8GCAllowedArgs},
     {"ui", "CachedFontLinkSettings::GetLinkedFonts", nullptr},
+    {"ui", "RenderTextHarfBuzz::GetFallbackFonts",
+     kGetFallbackFontsAllowedArgs},
     {"ui", "QueryLinkedFontsFromRegistry", nullptr},
     {"ui", "UserEvent", nullptr},
     {TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), "SequenceManager::PostTask",
diff --git a/services/ws/client_root.cc b/services/ws/client_root.cc
index fa14fcd..11b7718 100644
--- a/services/ws/client_root.cc
+++ b/services/ws/client_root.cc
@@ -83,6 +83,7 @@
   window_->AddObserver(this);
   if (window_->GetHost())
     window->GetHost()->AddObserver(this);
+  display::Screen::GetScreen()->AddObserver(this);
   client_surface_embedder_ =
       std::make_unique<aura::ClientSurfaceEmbedder>(window_);
   if (ShouldAssignLocalSurfaceIdImpl(window, is_top_level_))
@@ -105,6 +106,7 @@
   window_->RemoveObserver(this);
   if (window_->GetHost())
     window_->GetHost()->RemoveObserver(this);
+  display::Screen::GetScreen()->RemoveObserver(this);
 
   viz::HostFrameSinkManager* host_frame_sink_manager =
       window_->env()->context_factory_private()->GetHostFrameSinkManager();
@@ -457,8 +459,17 @@
   CheckForScaleFactorChange();
 }
 
-void ClientRoot::OnHostMovedInPixels(aura::WindowTreeHost* host,
-                                     const gfx::Point& new_origin_in_pixels) {
+void ClientRoot::OnDisplayMetricsChanged(const display::Display& display,
+                                         uint32_t changed_metrics) {
+  // WindowTreeHost display id should be updated before OnDisplayMetricsChanged.
+  // Early out if the changed display is not relevant.
+  if (!window_->GetHost() || window_->GetHost()->GetDisplayId() != display.id())
+    return;
+
+  // Only handle changes that could change the origin of the ClientRoot.
+  if (!(changed_metrics & (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_ROTATION)))
+    return;
+
   // Size or device-scale-factor change is handled in OnHostResized.
   const gfx::Rect new_bounds = GetBoundsToSend(window_);
   if (last_bounds_.size() != new_bounds.size() ||
diff --git a/services/ws/client_root.h b/services/ws/client_root.h
index 2cf805db..57ca4cc 100644
--- a/services/ws/client_root.h
+++ b/services/ws/client_root.h
@@ -15,6 +15,7 @@
 #include "components/viz/host/host_frame_sink_client.h"
 #include "ui/aura/window_observer.h"
 #include "ui/aura/window_tree_host_observer.h"
+#include "ui/display/display_observer.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 
@@ -46,6 +47,7 @@
 class COMPONENT_EXPORT(WINDOW_SERVICE) ClientRoot
     : public aura::WindowObserver,
       public aura::WindowTreeHostObserver,
+      public display::DisplayObserver,
       public viz::HostFrameSinkClient {
  public:
   ClientRoot(WindowTree* window_tree, aura::Window* window, bool is_top_level);
@@ -155,8 +157,10 @@
 
   // aura::WindowTreeHostObserver:
   void OnHostResized(aura::WindowTreeHost* host) override;
-  void OnHostMovedInPixels(aura::WindowTreeHost* host,
-                           const gfx::Point& new_origin_in_pixels) override;
+
+  // display::DisplayObsever:
+  void OnDisplayMetricsChanged(const display::Display& display,
+                               uint32_t changed_metrics) override;
 
   // viz::HostFrameSinkClient:
   void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
diff --git a/services/ws/host_context_factory.cc b/services/ws/host_context_factory.cc
index 550a330..90876748 100644
--- a/services/ws/host_context_factory.cc
+++ b/services/ws/host_context_factory.cc
@@ -9,6 +9,7 @@
 #include "components/viz/common/gpu/raster_context_provider.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "services/ws/ids.h"
+#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
 #include "services/ws/public/cpp/gpu/gpu.h"
 #include "ui/compositor/host/host_context_factory_private.h"
 
@@ -37,7 +38,7 @@
   if (!compositor)
     return;
 
-  scoped_refptr<viz::ContextProvider> context_provider =
+  scoped_refptr<ws::ContextProviderCommandBuffer> context_provider =
       gpu_->CreateContextProvider(std::move(gpu_channel));
   // If the binding fails, then we need to return early since the compositor
   // expects a successfully initialized/bound provider.
@@ -70,6 +71,16 @@
   return shared_main_thread_context_provider_;
 }
 
+scoped_refptr<viz::RasterContextProvider>
+HostContextFactory::SharedMainThreadRasterContextProvider() {
+  // Exo is currently the only client requesting this context provider.
+  // Exo does not request this context in the Window Service.
+  SharedMainThreadContextProvider();
+  DCHECK(!shared_main_thread_context_provider_ ||
+         shared_main_thread_context_provider_->RasterInterface());
+  return shared_main_thread_context_provider_;
+}
+
 void HostContextFactory::RemoveCompositor(ui::Compositor* compositor) {
   context_factory_private_->UnconfigureCompositor(compositor);
 }
diff --git a/services/ws/host_context_factory.h b/services/ws/host_context_factory.h
index 2436b1d..54990bb4 100644
--- a/services/ws/host_context_factory.h
+++ b/services/ws/host_context_factory.h
@@ -14,6 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "components/viz/common/display/renderer_settings.h"
 #include "components/viz/common/gpu/context_provider.h"
+#include "components/viz/common/gpu/raster_context_provider.h"
 #include "services/ws/public/cpp/raster_thread_helper.h"
 #include "ui/compositor/compositor.h"
 
@@ -27,6 +28,7 @@
 
 namespace ws {
 
+class ContextProviderCommandBuffer;
 class Gpu;
 
 // ui::ContextFactory used when the WindowService is acting as the viz host.
@@ -50,6 +52,8 @@
       base::WeakPtr<ui::Compositor> compositor) override;
   scoped_refptr<viz::ContextProvider> SharedMainThreadContextProvider()
       override;
+  scoped_refptr<viz::RasterContextProvider>
+  SharedMainThreadRasterContextProvider() override;
   void RemoveCompositor(ui::Compositor* compositor) override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
@@ -59,7 +63,8 @@
 
   RasterThreadHelper raster_thread_helper_;
   Gpu* gpu_;
-  scoped_refptr<viz::ContextProvider> shared_main_thread_context_provider_;
+  scoped_refptr<ws::ContextProviderCommandBuffer>
+      shared_main_thread_context_provider_;
 
   std::unique_ptr<ui::HostContextFactoryPrivate> context_factory_private_;
 
diff --git a/services/ws/public/cpp/gpu/gpu.cc b/services/ws/public/cpp/gpu/gpu.cc
index 70d2222..bd935a5 100644
--- a/services/ws/public/cpp/gpu/gpu.cc
+++ b/services/ws/public/cpp/gpu/gpu.cc
@@ -276,7 +276,7 @@
   return base::WrapUnique(new Gpu(std::move(gpu_ptr), std::move(task_runner)));
 }
 
-scoped_refptr<viz::ContextProvider> Gpu::CreateContextProvider(
+scoped_refptr<ws::ContextProviderCommandBuffer> Gpu::CreateContextProvider(
     scoped_refptr<gpu::GpuChannelHost> gpu_channel) {
   int32_t stream_id = 0;
   gpu::SchedulingPriority stream_priority = gpu::SchedulingPriority::kNormal;
@@ -293,6 +293,7 @@
   attributes.sample_buffers = 0;
   attributes.bind_generates_resource = false;
   attributes.lose_context_when_out_of_memory = true;
+  attributes.enable_raster_interface = true;
   return base::MakeRefCounted<ContextProviderCommandBuffer>(
       std::move(gpu_channel), GetGpuMemoryBufferManager(), stream_id,
       stream_priority, gpu::kNullSurfaceHandle,
diff --git a/services/ws/public/cpp/gpu/gpu.h b/services/ws/public/cpp/gpu/gpu.h
index a58bc24..4689d01 100644
--- a/services/ws/public/cpp/gpu/gpu.h
+++ b/services/ws/public/cpp/gpu/gpu.h
@@ -22,6 +22,8 @@
 
 namespace ws {
 
+class ContextProviderCommandBuffer;
+
 class Gpu : public gpu::GpuChannelEstablishFactory {
  public:
   // The Gpu has to be initialized in the main thread before establishing
@@ -37,7 +39,7 @@
     return gpu_memory_buffer_manager_.get();
   }
 
-  scoped_refptr<viz::ContextProvider> CreateContextProvider(
+  scoped_refptr<ws::ContextProviderCommandBuffer> CreateContextProvider(
       scoped_refptr<gpu::GpuChannelHost> gpu_channel);
 
   void CreateJpegDecodeAccelerator(
diff --git a/services/ws/public/mojom/ime/ime.typemap b/services/ws/public/mojom/ime/ime.typemap
index e1492ceb..c2a508d6 100644
--- a/services/ws/public/mojom/ime/ime.typemap
+++ b/services/ws/public/mojom/ime/ime.typemap
@@ -9,7 +9,7 @@
   "//services/ws/public/mojom/ime/ime_struct_traits.cc",
 ]
 public_deps = [
-  "//ui/base/ime:ime_types",
+  "//ui/base/ime",
 ]
 
 type_mappings = [
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index b692aca..562697a9 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -169,6 +169,10 @@
 #define SK_ENABLE_LEGACY_TEXT_COLOR
 #endif
 
+#ifndef SK_SUPPORT_LEGACY_TILEMODE_ENUM
+#define SK_SUPPORT_LEGACY_TILEMODE_ENUM
+#endif
+
 // We're turning this off indefinitely,
 // until we can figure out some fundamental problems with its approach.
 //
diff --git a/sql/database.cc b/sql/database.cc
index bcd2b922..b4edacf4 100644
--- a/sql/database.cc
+++ b/sql/database.cc
@@ -9,12 +9,9 @@
 #include <stdint.h>
 #include <string.h>
 
-#include "base/debug/alias.h"
-#include "base/debug/dump_without_crashing.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/format_macros.h"
-#include "base/json/json_file_value_serializer.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
@@ -169,14 +166,6 @@
   return current_expecter_cb_->Run(error);
 }
 
-void Database::ReportDiagnosticInfo(int extended_error, Statement* stmt) {
-  std::string debug_info = GetDiagnosticInfo(extended_error, stmt);
-  if (!debug_info.empty() && RegisterIntentToUpload()) {
-    DEBUG_ALIAS_FOR_CSTR(debug_buf, debug_info.c_str(), 2000);
-    base::debug::DumpWithoutCrashing();
-  }
-}
-
 // static
 void Database::SetErrorExpecter(Database::ErrorExpecterCallback* cb) {
   CHECK(!current_expecter_cb_);
@@ -493,109 +482,6 @@
 #endif
 }
 
-// Data is persisted in a file shared between databases in the same directory.
-// The "sqlite-diag" file contains a dictionary with the version number, and an
-// array of histogram tags for databases which have been dumped.
-bool Database::RegisterIntentToUpload() const {
-  static const char* kVersionKey = "version";
-  static const char* kDiagnosticDumpsKey = "DiagnosticDumps";
-  static int kVersion = 1;
-
-  if (histogram_tag_.empty())
-    return false;
-
-  if (!is_open())
-    return false;
-
-  if (in_memory_)
-    return false;
-
-  const base::FilePath db_path = DbPath();
-  if (db_path.empty())
-    return false;
-
-  // Put the collection of diagnostic data next to the databases.  In most
-  // cases, this is the profile directory, but safe-browsing stores a Cookies
-  // file in the directory above the profile directory.
-  base::FilePath breadcrumb_path = db_path.DirName().AppendASCII("sqlite-diag");
-
-  // Lock against multiple updates to the diagnostics file.  This code should
-  // seldom be called in the first place, and when called it should seldom be
-  // called for multiple databases, and when called for multiple databases there
-  // is _probably_ something systemic wrong with the user's system.  So the lock
-  // should never be contended, but when it is the database experience is
-  // already bad.
-  static base::NoDestructor<base::Lock> lock;
-  base::AutoLock auto_lock(*lock);
-
-  std::unique_ptr<base::Value> root;
-  if (!base::PathExists(breadcrumb_path)) {
-    std::unique_ptr<base::DictionaryValue> root_dict(
-        new base::DictionaryValue());
-    root_dict->SetInteger(kVersionKey, kVersion);
-
-    std::unique_ptr<base::ListValue> dumps(new base::ListValue);
-    dumps->AppendString(histogram_tag_);
-    root_dict->Set(kDiagnosticDumpsKey, std::move(dumps));
-
-    root = std::move(root_dict);
-  } else {
-    // Failure to read a valid dictionary implies that something is going wrong
-    // on the system.
-    JSONFileValueDeserializer deserializer(breadcrumb_path);
-    std::unique_ptr<base::Value> read_root(
-        deserializer.Deserialize(nullptr, nullptr));
-    if (!read_root.get())
-      return false;
-    std::unique_ptr<base::DictionaryValue> root_dict =
-        base::DictionaryValue::From(std::move(read_root));
-    if (!root_dict)
-      return false;
-
-    // Don't upload if the version is missing or newer.
-    int version = 0;
-    if (!root_dict->GetInteger(kVersionKey, &version) || version > kVersion)
-      return false;
-
-    base::ListValue* dumps = nullptr;
-    if (!root_dict->GetList(kDiagnosticDumpsKey, &dumps))
-      return false;
-
-    const size_t size = dumps->GetSize();
-    for (size_t i = 0; i < size; ++i) {
-      std::string s;
-
-      // Don't upload if the value isn't a string, or indicates a prior upload.
-      if (!dumps->GetString(i, &s) || s == histogram_tag_)
-        return false;
-    }
-
-    // Record intention to proceed with upload.
-    dumps->AppendString(histogram_tag_);
-    root = std::move(root_dict);
-  }
-
-  const base::FilePath breadcrumb_new =
-      breadcrumb_path.AddExtension(FILE_PATH_LITERAL("new"));
-  base::DeleteFile(breadcrumb_new, false);
-
-  // No upload if the breadcrumb file cannot be updated.
-  // TODO(shess): Consider ImportantFileWriter::WriteFileAtomically() to land
-  // the data on disk.  For now, losing the data is not a big problem, so the
-  // sync overhead would probably not be worth it.
-  JSONFileValueSerializer serializer(breadcrumb_new);
-  if (!serializer.Serialize(*root))
-    return false;
-  if (!base::PathExists(breadcrumb_new))
-    return false;
-  if (!base::ReplaceFile(breadcrumb_new, breadcrumb_path, nullptr)) {
-    base::DeleteFile(breadcrumb_new, false);
-    return false;
-  }
-
-  return true;
-}
-
 std::string Database::CollectErrorInfo(int error, Statement* stmt) const {
   // Buffer for accumulating debugging info about the error.  Place
   // more-relevant information earlier, in case things overflow the
diff --git a/sql/database.h b/sql/database.h
index e1c5577..ccb1dad 100644
--- a/sql/database.h
+++ b/sql/database.h
@@ -42,19 +42,10 @@
 class DatabaseMemoryDumpProvider;
 class Statement;
 
-// To allow some test classes to be friended.
 namespace test {
-class ScopedCommitHook;
 class ScopedErrorExpecter;
-class ScopedScalarFunction;
-class ScopedMockTimeSource;
 }  // namespace test
 
-// Exposes private Database functionality to unit tests.
-//
-// This class is only defined in test targets.
-class DatabaseTestPeer;
-
 // Handle to an open SQLite database.
 //
 // Instances of this class are thread-unsafe and DCHECK that they are accessed
@@ -457,11 +448,6 @@
   // OnSqliteError implementation).
   static bool IsExpectedSqliteError(int error);
 
-  // Collect various diagnostic information and post a crash dump to aid
-  // debugging.  Dump rate per database is limited to prevent overwhelming the
-  // crash server.
-  void ReportDiagnosticInfo(int extended_error, Statement* stmt);
-
   // Computes the path of a database's rollback journal.
   //
   // The journal file is created at the beginning of the database's first
@@ -512,12 +498,6 @@
   // (they should go through Statement).
   friend class Statement;
 
-  friend class DatabaseTestPeer;
-
-  friend class test::ScopedCommitHook;
-  friend class test::ScopedScalarFunction;
-  friend class test::ScopedMockTimeSource;
-
   FRIEND_TEST_ALL_PREFIXES(SQLDatabaseTest, CachedStatement);
   FRIEND_TEST_ALL_PREFIXES(SQLDatabaseTest, CollectDiagnosticInfo);
   FRIEND_TEST_ALL_PREFIXES(SQLDatabaseTest, GetAppropriateMmapSize);
@@ -681,23 +661,6 @@
   // passed to Open().
   base::FilePath DbPath() const;
 
-  // Helper to prevent uploading too many diagnostic dumps for a given database,
-  // since every dump will likely show the same problem.  Returns |true| if this
-  // function was not previously called for this database, and the persistent
-  // storage which tracks state was updated.
-  //
-  // |false| is returned if the function was previously called for this
-  // database, even across restarts.  |false| is also returned if the persistent
-  // storage cannot be updated, possibly indicating problems requiring user or
-  // admin intervention, such as filesystem corruption or disk full.  |false| is
-  // also returned if the persistent storage contains invalid data or is not
-  // readable.
-  //
-  // TODO(shess): It would make sense to reset the persistent state if the
-  // database is razed or recovered, or if the diagnostic code adds new
-  // capabilities.
-  bool RegisterIntentToUpload() const;
-
   // Helper to collect diagnostic info for a corrupt database.
   std::string CollectCorruptionInfo();
 
diff --git a/sql/database_unittest.cc b/sql/database_unittest.cc
index a145faa6..5add952 100644
--- a/sql/database_unittest.cc
+++ b/sql/database_unittest.cc
@@ -1066,40 +1066,6 @@
   EXPECT_NE(std::string::npos, error_info.find("version: 4"));
 }
 
-TEST_F(SQLDatabaseTest, RegisterIntentToUpload) {
-  base::FilePath breadcrumb_path =
-      db_path().DirName().AppendASCII("sqlite-diag");
-
-  // No stale diagnostic store.
-  ASSERT_TRUE(!base::PathExists(breadcrumb_path));
-
-  // The histogram tag is required to enable diagnostic features.
-  EXPECT_FALSE(db().RegisterIntentToUpload());
-  EXPECT_TRUE(!base::PathExists(breadcrumb_path));
-
-  db().Close();
-  db().set_histogram_tag("Test");
-  ASSERT_TRUE(db().Open(db_path()));
-
-  // Should signal upload only once.
-  EXPECT_TRUE(db().RegisterIntentToUpload());
-  EXPECT_TRUE(base::PathExists(breadcrumb_path));
-  EXPECT_FALSE(db().RegisterIntentToUpload());
-
-  // Changing the histogram tag should allow new upload to succeed.
-  db().Close();
-  db().set_histogram_tag("NewTest");
-  ASSERT_TRUE(db().Open(db_path()));
-  EXPECT_TRUE(db().RegisterIntentToUpload());
-  EXPECT_FALSE(db().RegisterIntentToUpload());
-
-  // Old tag is still prevented.
-  db().Close();
-  db().set_histogram_tag("Test");
-  ASSERT_TRUE(db().Open(db_path()));
-  EXPECT_FALSE(db().RegisterIntentToUpload());
-}
-
 // Test that a fresh database has mmap enabled by default, if mmap'ed I/O is
 // enabled by SQLite.
 TEST_F(SQLDatabaseTest, MmapInitiallyEnabled) {
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 210c9b41..29a4d8ba 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -764,2868 +764,5 @@
         }
       }
     ]
-  },
-  "Nougat Phone Tester": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "android_webview_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "android_webview_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "angle_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "base_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "base_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "blink_common_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "blink_common_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "blink_heap_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "blink_platform_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "webkit_unit_tests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "webkit_unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 2
-        },
-        "test": "blink_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "boringssl_crypto_tests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "boringssl_crypto_tests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "boringssl_ssl_tests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "boringssl_ssl_tests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "breakpad_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "breakpad_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "cacheinvalidation_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "args": [
-          "--gtest_filter=-*UsingRealWebcam*",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "capture_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "cast_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "cc_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "chrome_public_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 20
-        },
-        "test": "chrome_public_test_apk"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_chrome_public_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_chrome_public_test_apk",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 20
-        },
-        "test": "chrome_public_test_apk"
-      },
-      {
-        "args": [
-          "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json",
-          "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "chrome_public_test_vr_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 2
-        },
-        "test": "chrome_public_test_vr_apk"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "components_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "components_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 4
-        },
-        "test": "components_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "content_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 9
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--disable-perfetto",
-          "--gtest_filter=TracingControllerTest.*:BackgroundTracingManagerBrowserTest.*",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "nonperfetto_content_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "nonperfetto_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "content_shell_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 3
-        },
-        "test": "content_shell_test_apk"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_content_shell_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_content_shell_test_apk",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_shell_test_apk"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "content_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 3
-        },
-        "test": "content_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "crypto_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "device_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "device_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "display_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "display_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "events_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "events_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "gcm_unit_tests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "gfx_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "gin_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "gin_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "gl_tests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "gl_tests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "gl_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "gl_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "google_apis_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "gpu_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "ipc_tests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "jingle_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "latency_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "latency_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "libjingle_xmpp_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "libjingle_xmpp_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "media_service_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "media_service_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "media_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "media_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "midi_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "mojo_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "mojo_test_apk"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "mojo_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "mojo_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "net_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 3
-        },
-        "test": "net_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "sandbox_linux_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "services_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "services_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "shell_dialogs_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "shell_dialogs_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "skia_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "sql_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "storage_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "ui_android_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "ui_android_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "ui_base_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "ui_touch_selection_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "ui_touch_selection_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "unit_tests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 10
-        },
-        "test": "unit_tests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "url_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "url_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "viz_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "viz_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "vr_android_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "vr_android_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "vr_common_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "vr_common_unittests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "vr_pixeltests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "vr_pixeltests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "webview_instrumentation_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 7
-        },
-        "test": "webview_instrumentation_test_apk"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "wtf_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "wtf_unittests"
-      }
-    ]
   }
 }
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index b1e0245..fb7b274 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -712,10 +712,141 @@
     ]
   },
   "Android WebView O (dbg)": {
-    "cts_tests": [
+    "gtest_tests": [
       {
-        "arch": "arm64",
-        "platform": "O"
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "system_webview_shell_layout_test_apk"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "OPD3.170816.023",
+              "device_type": "walleye",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "system_webview_shell_layout_test_apk"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "webview_cts_tests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "chromium/android_webview/tools/cts_archive",
+              "location": "android_webview/tools/cts_archive",
+              "revision": "version:1.4"
+            },
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "OPD3.170816.023",
+              "device_type": "walleye",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "shards": 3
+        },
+        "test": "webview_cts_tests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
+            "webview_ui_test_app_test_apk"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "OPD3.170816.023",
+              "device_type": "walleye",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "webview_ui_test_app_test_apk"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.chrome.json b/testing/buildbot/chromium.chrome.json
index 9a8f625..6275d34 100644
--- a/testing/buildbot/chromium.chrome.json
+++ b/testing/buildbot/chromium.chrome.json
@@ -6,6 +6,11 @@
       "chrome"
     ]
   },
+  "chromeos-betty-google-rel": {
+    "additional_compile_targets": [
+      "chrome"
+    ]
+  },
   "linux-chromeos-google-rel": {
     "additional_compile_targets": [
       "chrome",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index d89cafb..08309ec 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -154,6 +154,23 @@
         "test": "google_apis_unittests"
       },
       {
+        "args": [
+          "--dbus-stub",
+          "--gtest_filter=SplitViewTest.SplitViewResize"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-14.04",
+              "pool": "Chrome-CrOS-VM"
+            }
+          ]
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 28e96345..e5c20b43 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -3286,25 +3286,6 @@
       },
       {
         "args": [
-          "--dbus-stub",
-          "--gtest_filter=SplitViewTest.SplitViewResize"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-14.04",
-              "pool": "Chrome-CrOS-VM"
-            }
-          ],
-          "hard_timeout": 3600,
-          "io_timeout": 3600
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "args": [
           "--vpython-dir=../../vpython_dir_linux_amd64",
           "--ozone-platform=headless",
           "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.services_unittests.filter"
@@ -3558,6 +3539,26 @@
         "test": "google_apis_unittests"
       },
       {
+        "args": [
+          "--dbus-stub",
+          "--gtest_filter=SplitViewTest.SplitViewResize"
+        ],
+        "isolate_coverage_data": true,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-14.04",
+              "pool": "Chrome-CrOS-VM"
+            }
+          ],
+          "hard_timeout": 3600,
+          "io_timeout": 3600
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
         "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index 998a4d97..7e8c24d 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -973,112 +973,6 @@
       }
     ]
   },
-  "Android FYI 32 Vk Release (Nexus 5X)": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "O",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "Chrome-GPU"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 4
-        },
-        "test": "angle_end2end_tests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "O",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "Chrome-GPU"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "angle_unittests"
-      }
-    ],
-    "isolated_scripts": [
-      {
-        "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only",
-          "--shard-timeout=500"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "O",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "Chrome-GPU"
-            }
-          ]
-        }
-      }
-    ]
-  },
   "Android FYI 32 Vk Release (Pixel 2)": {
     "gtest_tests": [
       {
@@ -1291,51 +1185,6 @@
       }
     ]
   },
-  "Android FYI 32 dEQP Vk Release (Nexus 5X)": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--deqp-egl-display-type=angle-vulkan",
-          "--enable-xml-result-parsing",
-          "--shard-timeout=500",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "name": "angle_deqp_gles2_vulkan_tests",
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "O",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "Chrome-GPU"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 4
-        },
-        "test": "angle_deqp_gles2_tests"
-      }
-    ]
-  },
   "Android FYI 32 dEQP Vk Release (Pixel 2)": {
     "gtest_tests": [
       {
@@ -1426,112 +1275,6 @@
       }
     ]
   },
-  "Android FYI 64 Vk Release (Nexus 5X)": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "O",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "Chrome-GPU"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 4
-        },
-        "test": "angle_end2end_tests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "O",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "Chrome-GPU"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "angle_unittests"
-      }
-    ],
-    "isolated_scripts": [
-      {
-        "args": [
-          "--gtest-benchmark-name=angle_perftests",
-          "-v",
-          "--one-frame-only",
-          "--shard-timeout=500"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--smoke-test-mode"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "O",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "Chrome-GPU"
-            }
-          ]
-        }
-      }
-    ]
-  },
   "Android FYI 64 Vk Release (Pixel 2)": {
     "gtest_tests": [
       {
@@ -1744,51 +1487,6 @@
       }
     ]
   },
-  "Android FYI 64 dEQP Vk Release (Nexus 5X)": {
-    "gtest_tests": [
-      {
-        "args": [
-          "--deqp-egl-display-type=angle-vulkan",
-          "--enable-xml-result-parsing",
-          "--shard-timeout=500",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "name": "angle_deqp_gles2_vulkan_tests",
-        "should_retry_with_patch": false,
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "O",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "Chrome-GPU"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 4
-        },
-        "test": "angle_deqp_gles2_tests"
-      }
-    ]
-  },
   "Android FYI 64 dEQP Vk Release (Pixel 2)": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/chromium.json b/testing/buildbot/chromium.json
index 848c4d13..c8cc92b 100644
--- a/testing/buildbot/chromium.json
+++ b/testing/buildbot/chromium.json
@@ -20,15 +20,7 @@
     "additional_compile_targets": [
       "all"
     ],
-    "scripts": [
-      {
-        "args": [
-          "linux-release-64/sizes"
-        ],
-        "name": "sizes",
-        "script": "sizes.py"
-      }
-    ]
+    "scripts": []
   },
   "mac-dbg": {
     "additional_compile_targets": [
@@ -39,15 +31,7 @@
     "additional_compile_targets": [
       "all"
     ],
-    "scripts": [
-      {
-        "args": [
-          "mac-release/sizes"
-        ],
-        "name": "sizes",
-        "script": "sizes.py"
-      }
-    ]
+    "scripts": []
   },
   "win-dbg": {
     "additional_compile_targets": [
diff --git a/testing/buildbot/filters/webui_polymer1_interactive_ui_tests.filter b/testing/buildbot/filters/webui_polymer1_interactive_ui_tests.filter
index da96b61..f35ce3443 100644
--- a/testing/buildbot/filters/webui_polymer1_interactive_ui_tests.filter
+++ b/testing/buildbot/filters/webui_polymer1_interactive_ui_tests.filter
@@ -24,4 +24,5 @@
 PrintPreviewNumberSettingsSectionInteractiveTest.BlurResetsEmptyInput
 PrintPreviewPagesSettingsTest.*
 PrintPreviewPrintHeaderInteractiveTest.FocusPrintOnReady
+PrintPreviewScalingSettingsInteractiveTest.InputAutoFocus
 SettingsUIBrowserTest.All
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py
index 9e9e84c..3f8549bb 100755
--- a/testing/buildbot/generate_buildbot_json.py
+++ b/testing/buildbot/generate_buildbot_json.py
@@ -958,6 +958,7 @@
       'mac-dummy-rel',
       # Defined in internal configs.
       'chromeos-amd64-generic-google-rel',
+      'chromeos-betty-google-rel',
     ]
 
   def check_input_file_consistency(self, verbose=False):
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index c853ea52..af618bc1 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -2416,6 +2416,8 @@
     "args": [
       "--use-webview-provider",
       "apks/SystemWebView.apk",
+      "--replace-system-package",
+      "org.chromium.webview_shell,apks/SystemWebViewShell.apk",
     ],
     "label": "//android_webview/tools/system_webview_shell:system_webview_shell_layout_test_apk",
     "type": "console_test_launcher",
@@ -2452,6 +2454,16 @@
     "script": "//testing/scripts/run_performance_tests.py",
     "type": "script",
   },
+  # This isolate is used by
+  # https://www.chromium.org/developers/cluster-telemetry
+  "ct_telemetry_perf_tests_without_chrome": {
+    "args": [
+      "../../tools/perf/run_benchmark",
+    ],
+    "label": "//chrome/test:ct_telemetry_perf_tests_without_chrome",
+    "script": "//testing/scripts/run_performance_tests.py",
+    "type": "script",
+  },
   "telemetry_perf_unittests": {
     "args": [
       "../../tools/perf/run_tests",
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py
index d53ae99..eb736f2e 100755
--- a/testing/buildbot/manage.py
+++ b/testing/buildbot/manage.py
@@ -184,6 +184,9 @@
 
   # These are defined by an android internal gn_isolate_map.pyl file.
   'chrome_apk',
+
+  # These are used by https://www.chromium.org/developers/cluster-telemetry.
+  'ct_telemetry_perf_tests_without_chrome',
 }
 
 
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 6e3ef005..9d0e449 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -485,13 +485,6 @@
       },
     }
   },
-  'oreo': {
-    'swarming': {
-      'dimensions': {
-        'device_os': 'O',
-      },
-    },
-  },
   'pie': {
     'swarming': {
       'dimensions': {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 8c8ddaa..c049da67c 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1118,12 +1118,6 @@
     ],
   },
   'sizes': {
-    'remove_from': [
-      'win32-dbg',
-      'win32-rel',
-      'win-dbg',
-      'win-rel',
-    ],
     'modifications': {
       # chromium.android.fyi
       'Android Cronet KitKat Builder': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index d5f45fa..c0fb33b 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -253,11 +253,6 @@
       'platform': 'N',
     },
 
-    'android_o_cts_tests': {
-      'arch': 'arm64',
-      'platform': 'O',
-    },
-
     'android_oreo_standard_gtests': {
       'chrome_public_test_apk': {
         'swarming': {
@@ -415,6 +410,12 @@
       'crypto_unittests': {},
       'display_unittests': {},
       'google_apis_unittests': {},
+      'interactive_ui_tests': {
+        'args': [
+          '--dbus-stub',
+          '--gtest_filter=SplitViewTest.SplitViewResize',
+        ],
+      },
       'ipc_tests': {},
       'jingle_unittests': {},
       'latency_unittests': {},
@@ -458,12 +459,6 @@
 
     'chromeos_device_friendly_gtests_experimental': {
       'chrome_login_tast_tests': {},
-      'interactive_ui_tests': {
-        'args': [
-          '--dbus-stub',
-          '--gtest_filter=SplitViewTest.SplitViewResize',
-        ],
-      },
       'services_unittests': {
         'args': [
           '--vpython-dir=../../vpython_dir_linux_amd64',
@@ -4211,9 +4206,6 @@
       'checkbins': {
         'script': 'checkbins.py',
       },
-      'sizes': {
-        'script': 'sizes.py',
-      },
     },
 
     'site_isolation_android_fyi_gtests': {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index fafa070..64f3cb86 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -173,9 +173,18 @@
       },
       'Android WebView O (dbg)': {
         'test_suites': {
-          'cts_tests': 'android_o_cts_tests',
+          'gtest_tests': 'webview_bot_gtests',
         },
-        'use_swarming': False,
+        'swarming': {
+          'dimension_sets': [
+            {
+              'device_os': 'OPD3.170816.023',
+              'device_type': 'walleye',
+              'os': 'Android',
+            },
+          ],
+        },
+        'use_swarming': True,
         'os_type': 'android',
       },
       'Android arm Builder (dbg)': {
@@ -596,23 +605,6 @@
           'isolated_scripts': 'memory_infra_isolated_scripts',
         },
       },
-      'Nougat Phone Tester': {
-        'swarming': {
-          'dimension_sets': [
-            {
-              'device_os': 'NRD91N',
-              'device_type': 'bullhead',
-              'os': 'Android',
-            },
-          ],
-          'expiration': 10800,
-          'hard_timeout': 960,
-        },
-        'os_type': 'android',
-        'test_suites': {
-          'gtest_tests': 'chromium_android_gtests',
-        },
-      },
     },
   },
   {
@@ -623,6 +615,11 @@
           'chrome',
         ],
       },
+      'chromeos-betty-google-rel': {
+        'additional_compile_targets': [
+          'chrome',
+        ],
+      },
       'linux-chromeos-google-rel': {
         'additional_compile_targets': [
           'chrome',
@@ -1941,19 +1938,6 @@
         },
       },
       # END Fake builder used as mirror targets for ANGLE's GPU tryservers
-      'Android FYI 32 Vk Release (Nexus 5X)': {
-        'os_type': 'android',
-        'skip_merge_script': True,
-        'mixins': [
-          'bullhead',
-          'gpu_pool',
-          'oreo',
-        ],
-        'test_suites': {
-          'gtest_tests': 'gpu_angle_gtests',
-          'isolated_scripts': 'gpu_angle_perftests',
-        },
-      },
       'Android FYI 32 Vk Release (Pixel 2)': {
         'os_type': 'android',
         'skip_merge_script': True,
@@ -1980,18 +1964,6 @@
           'isolated_scripts': 'gpu_angle_perftests',
         },
       },
-      'Android FYI 32 dEQP Vk Release (Nexus 5X)': {
-        'os_type': 'android',
-        'skip_merge_script': True,
-        'mixins': [
-          'bullhead',
-          'gpu_pool',
-          'oreo',
-        ],
-        'test_suites': {
-          'gtest_tests': 'gpu_angle_deqp_gles2_vulkan_tests',
-        },
-      },
       'Android FYI 32 dEQP Vk Release (Pixel 2)': {
         'os_type': 'android',
         'skip_merge_script': True,
@@ -2016,19 +1988,6 @@
           'gtest_tests': 'gpu_angle_deqp_gles2_vulkan_tests',
         },
       },
-      'Android FYI 64 Vk Release (Nexus 5X)': {
-        'os_type': 'android',
-        'skip_merge_script': True,
-        'mixins': [
-          'bullhead',
-          'gpu_pool',
-          'oreo',
-        ],
-        'test_suites': {
-          'gtest_tests': 'gpu_angle_gtests',
-          'isolated_scripts': 'gpu_angle_perftests',
-        },
-      },
       'Android FYI 64 Vk Release (Pixel 2)': {
         'os_type': 'android',
         'skip_merge_script': True,
@@ -2055,18 +2014,6 @@
           'isolated_scripts': 'gpu_angle_perftests',
         },
       },
-      'Android FYI 64 dEQP Vk Release (Nexus 5X)': {
-        'os_type': 'android',
-        'skip_merge_script': True,
-        'mixins': [
-          'bullhead',
-          'gpu_pool',
-          'oreo',
-        ],
-        'test_suites': {
-          'gtest_tests': 'gpu_angle_deqp_gles2_vulkan_tests',
-        },
-      },
       'Android FYI 64 dEQP Vk Release (Pixel 2)': {
         'os_type': 'android',
         'skip_merge_script': True,
diff --git a/testing/merge_scripts/PRESUBMIT.py b/testing/merge_scripts/PRESUBMIT.py
index 22a57f28..3ba0cf1 100644
--- a/testing/merge_scripts/PRESUBMIT.py
+++ b/testing/merge_scripts/PRESUBMIT.py
@@ -10,7 +10,7 @@
 
 def CommonChecks(input_api, output_api):
   return input_api.canned_checks.RunUnitTestsInDirectory(
-      input_api, output_api, '.', [ r'^.+_unittest\.py$'])
+      input_api, output_api, '.', [ r'^.+_test\.py$'])
 
 def CheckChangeOnUpload(input_api, output_api):
   return CommonChecks(input_api, output_api)
diff --git a/testing/merge_scripts/results_merger_unittest.py b/testing/merge_scripts/results_merger_test.py
similarity index 100%
rename from testing/merge_scripts/results_merger_unittest.py
rename to testing/merge_scripts/results_merger_test.py
diff --git a/testing/merge_scripts/standard_isolated_script_merge_test.py b/testing/merge_scripts/standard_isolated_script_merge_test.py
index 89ec900..7cd14360 100755
--- a/testing/merge_scripts/standard_isolated_script_merge_test.py
+++ b/testing/merge_scripts/standard_isolated_script_merge_test.py
@@ -17,12 +17,6 @@
 
 THIS_DIR = os.path.dirname(__file__)
 
-sys.path.insert(
-    0, os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..', 'unittests')))
-import test_env
-
-sys.path.insert(
-    0, os.path.abspath(os.path.join(THIS_DIR, '..', 'resources')))
 import standard_isolated_script_merge
 
 
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 6a62261d..0b52366d 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -35,6 +35,24 @@
             ]
         }
     ],
+    "AccessibilityImageDescriptions": [
+        {
+            "platforms": [
+                "windows",
+                "mac",
+                "chromeos",
+                "linux"
+            ],
+            "experiments": [
+                {
+                    "name": "AccessibilityImageDescriptions",
+                    "enable_features": [
+                        "ExperimentalAccessibilityLabels"
+                    ]
+                }
+            ]
+        }
+    ],
     "AccountConsistencyVariations": [
         {
             "platforms": [
diff --git a/third_party/android_crazy_linker/BUILD.gn b/third_party/android_crazy_linker/BUILD.gn
index 710a614..f9e1358 100644
--- a/third_party/android_crazy_linker/BUILD.gn
+++ b/third_party/android_crazy_linker/BUILD.gn
@@ -74,6 +74,7 @@
         "src/src/crazy_linker_elf_view.h",
         "src/src/crazy_linker_error.cpp",
         "src/src/crazy_linker_error.h",
+        "src/src/crazy_linker_expected.h",
         "src/src/crazy_linker_globals.cpp",
         "src/src/crazy_linker_globals.h",
         "src/src/crazy_linker_gnu_hash_table.cpp",
@@ -159,6 +160,7 @@
       "src/src/crazy_linker_elf_hash_table_unittest.cpp",
       "src/src/crazy_linker_elf_symbols_unittest.cpp",
       "src/src/crazy_linker_error_unittest.cpp",
+      "src/src/crazy_linker_expected_unittest.cpp",
       "src/src/crazy_linker_globals_unittest.cpp",
       "src/src/crazy_linker_gnu_hash_table_unittest.cpp",
       "src/src/crazy_linker_line_reader_unittest.cpp",
@@ -178,6 +180,9 @@
 
     include_dirs = [ "src/src" ]
 
+    # Required by crazy_linker_expected_unittest.cpp
+    defines = [ "CRAZY_DEBUG=1" ]
+
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     deps = [
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_debug.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_debug.cpp
index 9700be1..fbf0c33 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_debug.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_debug.cpp
@@ -94,6 +94,20 @@
   errno = old_errno;
 }
 
+void AssertionFailure(const char* location, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  {
+    LogBuffer log;
+    log.Append(location);
+    log.Append(": ");
+    log.AppendV(fmt, args);
+    log.Print();
+  }
+  va_end(args);
+  exit(1);
+}
+
 #endif  // CRAZY_DEBUG
 
 }  // namespace crazy
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_debug.h b/third_party/android_crazy_linker/src/src/crazy_linker_debug.h
index e6dc8f7..46119e95 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_debug.h
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_debug.h
@@ -33,16 +33,28 @@
 
 void Log(const char* location, const char* fmt, ...);
 void LogErrno(const char* location, const char* fmt, ...);
+void AssertionFailure(const char* location, const char* fmt, ...);
 
 #define LOG(...) ::crazy::Log(__PRETTY_FUNCTION__, __VA_ARGS__)
 #define LOG_ERRNO(...) ::crazy::LogErrno(__PRETTY_FUNCTION__, __VA_ARGS__)
 
-#else
+// NOTE: This form of ASSERT() that can be used within constexpr methods, inside
+// a comma operation, as in:
+//   return ASSERT(cond), <result>;
+// Which will be equivalent to:
+//   ASSERT(cond);
+//   return <result>;
+#define ASSERT(cond, ...)                                                \
+  (!(cond) ? ::crazy::AssertionFailure(__PRETTY_FUNCTION__, __VA_ARGS__) \
+           : (void)0)
+
+#else  // !CRAZY_DEBUG
 
 #define LOG(...) ((void)0)
 #define LOG_ERRNO(...) ((void)0)
+#define ASSERT(cond, ...) ((void)(cond))
 
-#endif
+#endif  // !CRAZY_DEBUG
 
 // Conditional logging.
 #define LOG_IF(cond, ...) \
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_expected.h b/third_party/android_crazy_linker/src/src/crazy_linker_expected.h
new file mode 100644
index 0000000..c583d414
--- /dev/null
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_expected.h
@@ -0,0 +1,108 @@
+// Copyright 2019 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 CRAZY_LINKER_OUTCOME_H
+#define CRAZY_LINKER_OUTCOME_H
+
+#include "crazy_linker_debug.h"
+#include "crazy_linker_error.h"
+
+#include <utility>
+
+namespace crazy {
+
+// Handy template for an object that can be either a value of type T, or hold
+// a non-owning pointer to a crazy::Error instance. The reason for this design
+// is to keep each Expected<T> instance small, since each Error instance is
+// pretty large (over 512 bytes), and generally allocated on the stack by the
+// caller. Usage examples:
+//
+//    Expected<int> getFoo() { return 42; }
+//    Expected<int> getBar(Error* error)  { return Expected<int>(error); }
+//    Expected<int> getBar2(Error* error) { return error; }  // equivalent!
+template <class T>
+struct Expected {
+  // No default constructor.
+  Expected() = delete;
+
+  // Value constructor.
+  constexpr Expected(const T& value) : has_value_(true), value_(value) {}
+  Expected(T&& value) : has_value_(true), value_(std::move(value)) {}
+
+  // Null-constructor, only valid if T can be constructed from nullptr.
+  constexpr Expected(nullptr_t) : has_value_(true), value_(nullptr) {}
+
+  // Error constructor.
+  Expected(Error* error) : has_value_(false), error_(error) {}
+
+  // Move constructor.
+  Expected(Expected&& other) noexcept : has_value_(other.has_value_) {
+    if (has_value_) {
+      value_ = std::move(other.value_);
+    } else {
+      error_ = other.error_;
+    }
+  }
+
+  // Move assigment.
+  Expected& operator=(Expected&& other) noexcept {
+    if (this != &other) {
+      this->~Expected();
+      *this = std::move(other);
+    }
+    return *this;
+  }
+
+  // Destructor.
+  ~Expected() {
+    if (has_value_) {
+      value_.~T();
+    }
+  }
+
+  // Bool operator, to write: if (expected) { ... use value. }
+  constexpr explicit operator bool() const { return has_value_; }
+
+  // Return reference to value. Assert if error.
+  constexpr const T& operator*() const { return value(); }
+  T& operator*() { return value(); }
+
+  constexpr const T& value() const& {
+    return ASSERT(has_value_, "No value in Expected<> instance!"), value_;
+  }
+
+  T& value() & {
+    return ASSERT(has_value_, "No value in Expected<> instance!"), value_;
+  }
+
+  T&& value() && {
+    return ASSERT(has_value_, "No value in Expected<> instance!"),
+           std::move(value_);
+  }
+
+  // Return reference to value, or a default value if it is an error.
+  constexpr const T& value_or(const T& default_value) const {
+    return has_value_ ? value_ : default_value;
+  }
+
+  // Return reference to error. Assert if value.
+  constexpr const Error* error() const {
+    ASSERT(!has_value_, "No error in Expected<> instance!");
+    return error_;
+  }
+
+  constexpr bool has_value() const { return has_value_; }
+  constexpr bool has_error() const { return !has_value_; }
+
+ private:
+  bool has_value_;
+  union {
+    T value_;
+    Error* error_;
+  };
+};
+
+}  // namespace crazy
+
+#endif  // CRAZY_LINKER_OUTCOME_H
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_expected_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_expected_unittest.cpp
new file mode 100644
index 0000000..08157ae
--- /dev/null
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_expected_unittest.cpp
@@ -0,0 +1,66 @@
+// Copyright 2019 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 "crazy_linker_expected.h"
+
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <new>
+
+namespace crazy {
+
+TEST(Expected, ValueConstructor) {
+  Expected<int> e{10};
+  ASSERT_TRUE(e);
+  ASSERT_TRUE(e.has_value());
+  ASSERT_FALSE(e.has_error());
+  ASSERT_EQ(10, *e);
+  ASSERT_EQ(10, e.value());
+  ASSERT_EQ(10, e.value_or(20));
+}
+
+TEST(Expected, ErrorConstructor) {
+  Error error;
+  Expected<int> e(&error);
+  ASSERT_FALSE(e);
+  ASSERT_FALSE(e.has_value());
+  ASSERT_TRUE(e.has_error());
+  ASSERT_EQ(10, e.value_or(10));
+  ASSERT_EQ(20, e.value_or(20));
+  ASSERT_EQ(&error, e.error());
+
+  int v = 10;
+  Expected<int*> e2(&v);
+  ASSERT_TRUE(e2);
+  ASSERT_EQ(&v, *e2);
+}
+
+TEST(Expectde, ValueMovesRValue) {
+  auto create_value = [](int value) {
+    return Expected<std::unique_ptr<int>>(std::make_unique<int>(value));
+  };
+
+  std::unique_ptr<int> ptr = create_value(10).value();
+  ASSERT_TRUE(ptr);
+  ASSERT_EQ(10, *ptr);
+}
+
+TEST(Expected, DeathInCaseOfInvalidUsage) {
+  Expected<int> e{10};
+  ASSERT_TRUE(e);
+  ASSERT_TRUE(e.has_value());
+  ASSERT_FALSE(e.has_error());
+  ASSERT_DEATH(e.error(), "No error in Expected<> instance!");
+
+  Error error;
+  Expected<int> e2(&error);
+  ASSERT_FALSE(e2);
+  ASSERT_FALSE(e2.has_value());
+  ASSERT_TRUE(e2.has_error());
+  ASSERT_DEATH(*e2, "No value in Expected<> instance!");
+  ASSERT_DEATH(e2.value(), "No value in Expected<> instance!");
+}
+
+}  // namespace crazy
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp
index c1689304..99d0a209 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp
@@ -32,7 +32,7 @@
   int weak_count = 0;
 
   // Check a symbol entry.
-  bool CheckSymbol(const char* symbol, SharedLibrary* lib) {
+  bool CheckSymbol(const char* symbol, const SharedLibrary* lib) {
     const ELF::Sym* entry = lib->LookupSymbolEntry(symbol);
     if (!entry)
       return false;
@@ -167,8 +167,9 @@
 
   while (!work_queue.IsEmpty()) {
     const LibraryView* lib = work_queue.PopFirst();
-    if (lib->IsCrazy()) {
-      if (lookup_state.CheckSymbol(symbol_name, lib->GetCrazy()))
+    const SharedLibrary* crazy_lib = lib->GetCrazy();
+    if (crazy_lib) {
+      if (lookup_state.CheckSymbol(symbol_name, crazy_lib))
         return lookup_state.found_addr;
     } else if (lib->IsSystem()) {
       LibraryView::SearchResult sym = lib->LookupSymbol(symbol_name);
@@ -178,8 +179,8 @@
 
     // If this is a crazy library, add non-visited dependencies
     // to the work queue.
-    if (lib->IsCrazy()) {
-      SharedLibrary::DependencyIterator iter(lib->GetCrazy());
+    if (crazy_lib) {
+      SharedLibrary::DependencyIterator iter(crazy_lib);
       while (iter.GetNext()) {
         LibraryView* dependency = FindKnownLibrary(iter.GetName());
         if (dependency && !visited_set.Has(dependency)) {
@@ -254,9 +255,8 @@
     return;
 
   // If this is a crazy library, perform manual cleanup first.
-  if (wrap->IsCrazy()) {
-    SharedLibrary* lib = wrap->GetCrazy();
-
+  SharedLibrary* lib = wrap->GetCrazy();
+  if (lib) {
     // Remove from internal list of crazy libraries.
     if (lib->list_next_)
       lib->list_next_->list_prev_ = lib->list_prev_;
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_library_view.h b/third_party/android_crazy_linker/src/src/crazy_linker_library_view.h
index f016ce73..59aeec3a 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_library_view.h
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_library_view.h
@@ -52,7 +52,8 @@
   const char* GetName() const { return name_.c_str(); }
 
   // Returns SharedLibrary handle if valid, nullptr otherwise.
-  SharedLibrary* GetCrazy() const { return IsCrazy() ? crazy_ : NULL; }
+  const SharedLibrary* GetCrazy() const { return IsCrazy() ? crazy_ : nullptr; }
+  SharedLibrary* GetCrazy() { return IsCrazy() ? crazy_ : nullptr; }
 
   // Returns system handle if valid, nullptr otherwise.
   void* GetSystem() const { return IsSystem() ? system_ : NULL; }
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp
index f7b737b..de136c4 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp
@@ -201,8 +201,8 @@
       return sym.address;
     }
 
-    if (lib->IsCrazy()) {
-      SharedLibrary* crazy = lib->GetCrazy();
+    const SharedLibrary* crazy = lib->GetCrazy();
+    if (crazy) {
       const ELF::Sym* entry = crazy->LookupSymbolEntry(symbol_name);
       if (entry)
         return reinterpret_cast<void*>(crazy->load_bias() + entry->st_value);
@@ -378,11 +378,12 @@
   return true;
 }
 
-const ELF::Sym* SharedLibrary::LookupSymbolEntry(const char* symbol_name) {
+const ELF::Sym* SharedLibrary::LookupSymbolEntry(
+    const char* symbol_name) const {
   return symbols_.LookupByName(symbol_name);
 }
 
-void* SharedLibrary::FindAddressForSymbol(const char* symbol_name) {
+void* SharedLibrary::FindAddressForSymbol(const char* symbol_name) const {
   return symbols_.LookupAddressByName(symbol_name, view_.load_bias());
 }
 
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h
index fbc7f8e..b0c7b89 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h
@@ -95,7 +95,7 @@
 
   // Return the ELF symbol entry for a given symbol, if defined by
   // this library, or NULL otherwise.
-  const ELF::Sym* LookupSymbolEntry(const char* symbol_name);
+  const ELF::Sym* LookupSymbolEntry(const char* symbol_name) const;
 
   // Find the nearest symbol near a given |address|. On success, return
   // true and set |*sym_name| to the symbol name, |*sym_addr| to its address
@@ -103,14 +103,14 @@
   bool FindNearestSymbolForAddress(void* address,
                                    const char** sym_name,
                                    void** sym_addr,
-                                   size_t* sym_size) {
+                                   size_t* sym_size) const {
     return symbols_.LookupNearestByAddress(
         address, load_bias(), sym_name, sym_addr, sym_size);
   }
 
   // Return the address of a given |symbol_name| if it is exported
   // by the library, NULL otherwise.
-  void* FindAddressForSymbol(const char* symbol_name);
+  void* FindAddressForSymbol(const char* symbol_name) const;
 
   // Create a new Ashmem region holding a copy of the library's RELRO section,
   // potentially relocated for a new |load_address|. On success, return true
@@ -157,7 +157,7 @@
   //    }
   class DependencyIterator {
    public:
-    explicit DependencyIterator(SharedLibrary* lib)
+    explicit DependencyIterator(const SharedLibrary* lib)
         : iter_(&lib->view_), symbols_(&lib->symbols_), dep_name_(NULL) {}
 
     bool GetNext();
@@ -165,9 +165,9 @@
     const char* GetName() const { return dep_name_; }
 
    private:
-    DependencyIterator();
-    DependencyIterator(const DependencyIterator&);
-    DependencyIterator& operator=(const DependencyIterator&);
+    DependencyIterator() = delete;
+    DependencyIterator(const DependencyIterator&) = delete;
+    DependencyIterator& operator=(const DependencyIterator&) = delete;
 
     ElfView::DynamicIterator iter_;
     const ElfSymbols* symbols_;
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp
index a9f3927..bb1b2035 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp
@@ -83,6 +83,17 @@
 
 namespace crazy {
 
+FileDescriptor& FileDescriptor::operator=(FileDescriptor&& other) noexcept {
+  if (this != &other) {
+    if (fd_ != kEmptyFD) {
+      DoClose(fd_);
+    }
+    fd_ = other.fd_;
+    other.fd_ = kEmptyFD;
+  }
+  return *this;
+}
+
 ssize_t FileDescriptor::Read(void* buffer, size_t buffer_size) {
   return TEMP_FAILURE_RETRY(::read(fd_, buffer, buffer_size));
 }
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_system.h b/third_party/android_crazy_linker/src/src/crazy_linker_system.h
index f5d877db..a6da0ab 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_system.h
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_system.h
@@ -11,6 +11,7 @@
 #include <sys/mman.h>
 #include <unistd.h>
 
+#include "crazy_linker_macros.h"
 #include "crazy_linker_util.h"  // for String
 
 // System abstraction used by the crazy linker.
@@ -49,6 +50,15 @@
 
   ~FileDescriptor() { Close(); }
 
+  CRAZY_DISALLOW_COPY_OPERATIONS(FileDescriptor)
+
+  // Move operations are allowed.
+  FileDescriptor(FileDescriptor&& other) noexcept : fd_(other.fd_) {
+    other.fd_ = kEmptyFD;
+  }
+
+  FileDescriptor& operator=(FileDescriptor&& other) noexcept;
+
   // Returns true if the descriptor is valid.
   bool IsOk() const { return fd_ != kEmptyFD; }
 
@@ -115,7 +125,9 @@
     return ret;
   }
 
- private:
+ protected:
+  explicit FileDescriptor(HandleType handle) : fd_(handle) {}
+
   static int DoOpenReadOnly(const char* path);
   static int DoOpenReadWrite(const char* path);
   static void DoClose(int fd);
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp
index d03121d5..f25ffaea 100644
--- a/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp
+++ b/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp
@@ -187,11 +187,12 @@
   // First, perform search in crazy libraries.
   {
     ScopedLockedGlobals globals;
-    LibraryView* wrap = globals->libraries()->FindLibraryForAddress(address);
+    const LibraryView* wrap =
+        globals->libraries()->FindLibraryForAddress(address);
     if (wrap && wrap->IsCrazy()) {
       size_t sym_size = 0;
 
-      SharedLibrary* lib = wrap->GetCrazy();
+      const SharedLibrary* lib = wrap->GetCrazy();
       ::memset(info, 0, sizeof(*info));
       info->dli_fname = lib->base_name();
       info->dli_fbase = reinterpret_cast<void*>(lib->load_address());
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn
index 2b89de9..67567fe7c 100644
--- a/third_party/android_deps/BUILD.gn
+++ b/third_party/android_deps/BUILD.gn
@@ -137,7 +137,7 @@
 # === Generated Code Start ===
 # This is generated, do not edit. Update BuildConfigGenerator.groovy instead.
 java_prebuilt("android_arch_lifecycle_common_java") {
-  jar_path = "libs/android_arch_lifecycle_common/common-1.0.0.jar"
+  jar_path = "libs/android_arch_lifecycle_common/common-1.1.1.jar"
   output_name = "android_arch_lifecycle_common"
   supports_android = true
   deps = [
@@ -146,8 +146,19 @@
 }
 
 # This is generated, do not edit. Update BuildConfigGenerator.groovy instead.
+java_prebuilt("android_arch_lifecycle_common_java8_java") {
+  jar_path = "libs/android_arch_lifecycle_common_java8/common-java8-1.1.1.jar"
+  output_name = "android_arch_lifecycle_common_java8"
+  supports_android = true
+  deps = [
+    ":android_arch_lifecycle_common_java",
+    ":com_android_support_support_annotations_java",
+  ]
+}
+
+# This is generated, do not edit. Update BuildConfigGenerator.groovy instead.
 android_aar_prebuilt("android_arch_lifecycle_runtime_java") {
-  aar_path = "libs/android_arch_lifecycle_runtime/runtime-1.0.0.aar"
+  aar_path = "libs/android_arch_lifecycle_runtime/runtime-1.1.1.aar"
   info_path =
       "libs/android_arch_lifecycle_runtime/android_arch_lifecycle_runtime.info"
   deps = [
@@ -642,7 +653,7 @@
 
 # This is generated, do not edit. Update BuildConfigGenerator.groovy instead.
 java_prebuilt("android_arch_core_common_java") {
-  jar_path = "libs/android_arch_core_common/common-1.0.0.jar"
+  jar_path = "libs/android_arch_core_common/common-1.1.1.jar"
   output_name = "android_arch_core_common"
   supports_android = true
 
diff --git a/third_party/android_deps/additional_readme_paths.json b/third_party/android_deps/additional_readme_paths.json
index 0f4b59a..495db62 100644
--- a/third_party/android_deps/additional_readme_paths.json
+++ b/third_party/android_deps/additional_readme_paths.json
@@ -1,6 +1,7 @@
 [
     "libs/android_arch_core_common",
     "libs/android_arch_lifecycle_common",
+    "libs/android_arch_lifecycle_common_java8",
     "libs/android_arch_lifecycle_runtime",
     "libs/androidx_annotation_annotation",
     "libs/androidx_lifecycle_lifecycle_common",
diff --git a/third_party/android_deps/libs/android_arch_core_common/README.chromium b/third_party/android_deps/libs/android_arch_core_common/README.chromium
index ce90cb88..71ecc48 100644
--- a/third_party/android_deps/libs/android_arch_core_common/README.chromium
+++ b/third_party/android_deps/libs/android_arch_core_common/README.chromium
@@ -1,7 +1,7 @@
 Name: Android Arch-Common
 Short Name: common
 URL: https://developer.android.com/topic/libraries/architecture/index.html
-Version: 1.0.0
+Version: 1.1.1
 License: Apache Version 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/android_deps/libs/android_arch_core_common/cipd.yaml b/third_party/android_deps/libs/android_arch_core_common/cipd.yaml
index 265ca553..bb27167 100644
--- a/third_party/android_deps/libs/android_arch_core_common/cipd.yaml
+++ b/third_party/android_deps/libs/android_arch_core_common/cipd.yaml
@@ -3,8 +3,8 @@
 # found in the LICENSE file.
 
 # To create CIPD package run the following command.
-# cipd create --pkg-def cipd.yaml -tag version:1.0.0-cr0
+# cipd create --pkg-def cipd.yaml -tag version:1.1.1-cr0
 package: chromium/third_party/android_deps/libs/android_arch_core_common
 description: "Android Arch-Common"
 data:
-- file: common-1.0.0.jar
+- file: common-1.1.1.jar
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_common/README.chromium b/third_party/android_deps/libs/android_arch_lifecycle_common/README.chromium
index 5ce69bcfc..619943a 100644
--- a/third_party/android_deps/libs/android_arch_lifecycle_common/README.chromium
+++ b/third_party/android_deps/libs/android_arch_lifecycle_common/README.chromium
@@ -1,7 +1,7 @@
 Name: Android Lifecycle-Common
 Short Name: common
 URL: https://developer.android.com/topic/libraries/architecture/index.html
-Version: 1.0.0
+Version: 1.1.1
 License: Apache Version 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_common/cipd.yaml b/third_party/android_deps/libs/android_arch_lifecycle_common/cipd.yaml
index 3eb9d7ea..dac14322 100644
--- a/third_party/android_deps/libs/android_arch_lifecycle_common/cipd.yaml
+++ b/third_party/android_deps/libs/android_arch_lifecycle_common/cipd.yaml
@@ -3,8 +3,8 @@
 # found in the LICENSE file.
 
 # To create CIPD package run the following command.
-# cipd create --pkg-def cipd.yaml -tag version:1.0.0-cr0
+# cipd create --pkg-def cipd.yaml -tag version:1.1.1-cr0
 package: chromium/third_party/android_deps/libs/android_arch_lifecycle_common
 description: "Android Lifecycle-Common"
 data:
-- file: common-1.0.0.jar
+- file: common-1.1.1.jar
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_common_java8/LICENSE b/third_party/android_deps/libs/android_arch_lifecycle_common_java8/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/third_party/android_deps/libs/android_arch_lifecycle_common_java8/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_common_java8/OWNERS b/third_party/android_deps/libs/android_arch_lifecycle_common_java8/OWNERS
new file mode 100644
index 0000000..7b571d97
--- /dev/null
+++ b/third_party/android_deps/libs/android_arch_lifecycle_common_java8/OWNERS
@@ -0,0 +1 @@
+file://third_party/android_deps/OWNERS
\ No newline at end of file
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_common_java8/README.chromium b/third_party/android_deps/libs/android_arch_lifecycle_common_java8/README.chromium
new file mode 100644
index 0000000..7e7e5e3
--- /dev/null
+++ b/third_party/android_deps/libs/android_arch_lifecycle_common_java8/README.chromium
@@ -0,0 +1,13 @@
+Name: Android Lifecycle-Common for Java 8 Language
+Short Name: common-java8
+URL: https://developer.android.com/topic/libraries/architecture/index.html
+Version: 1.1.1
+License: Apache Version 2.0
+License File: LICENSE
+Security Critical: yes
+
+Description:
+Android Lifecycle-Common for Java 8 Language
+
+Local Modifications:
+No modifications.
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_common_java8/cipd.yaml b/third_party/android_deps/libs/android_arch_lifecycle_common_java8/cipd.yaml
new file mode 100644
index 0000000..339b2c4
--- /dev/null
+++ b/third_party/android_deps/libs/android_arch_lifecycle_common_java8/cipd.yaml
@@ -0,0 +1,10 @@
+# Copyright 2018 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.
+
+# To create CIPD package run the following command.
+# cipd create --pkg-def cipd.yaml -tag version:1.1.1-cr0
+package: chromium/third_party/android_deps/libs/android_arch_lifecycle_common_java8
+description: "Android Lifecycle-Common for Java 8 Language"
+data:
+- file: common-java8-1.1.1.jar
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_runtime/README.chromium b/third_party/android_deps/libs/android_arch_lifecycle_runtime/README.chromium
index 6e6ed7a..010e1684 100644
--- a/third_party/android_deps/libs/android_arch_lifecycle_runtime/README.chromium
+++ b/third_party/android_deps/libs/android_arch_lifecycle_runtime/README.chromium
@@ -1,7 +1,7 @@
 Name: Android Lifecycle Runtime
 Short Name: runtime
 URL: https://developer.android.com/topic/libraries/architecture/index.html
-Version: 1.0.0
+Version: 1.1.1
 License: Apache Version 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_runtime/android_arch_lifecycle_runtime.info b/third_party/android_deps/libs/android_arch_lifecycle_runtime/android_arch_lifecycle_runtime.info
index acf40e8..0dfcb237 100644
--- a/third_party/android_deps/libs/android_arch_lifecycle_runtime/android_arch_lifecycle_runtime.info
+++ b/third_party/android_deps/libs/android_arch_lifecycle_runtime/android_arch_lifecycle_runtime.info
@@ -7,7 +7,7 @@
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
-is_manifest_empty = false
+is_manifest_empty = true
 resources = [  ]
 subjar_tuples = [  ]
 subjars = [  ]
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_runtime/cipd.yaml b/third_party/android_deps/libs/android_arch_lifecycle_runtime/cipd.yaml
index 4aa3b10..0770371 100644
--- a/third_party/android_deps/libs/android_arch_lifecycle_runtime/cipd.yaml
+++ b/third_party/android_deps/libs/android_arch_lifecycle_runtime/cipd.yaml
@@ -3,8 +3,8 @@
 # found in the LICENSE file.
 
 # To create CIPD package run the following command.
-# cipd create --pkg-def cipd.yaml -tag version:1.0.0-cr0
+# cipd create --pkg-def cipd.yaml -tag version:1.1.1-cr0
 package: chromium/third_party/android_deps/libs/android_arch_lifecycle_runtime
 description: "Android Lifecycle Runtime"
 data:
-- file: runtime-1.0.0.aar
+- file: runtime-1.1.1.aar
diff --git a/third_party/blink/perf_tests/OWNERS b/third_party/blink/perf_tests/OWNERS
index f1fb6d5b..2ffc6398 100644
--- a/third_party/blink/perf_tests/OWNERS
+++ b/third_party/blink/perf_tests/OWNERS
@@ -1,3 +1,4 @@
+cbiesinger@chromium.org
 eae@chromium.org
 eyaich@chromium.org
 haraken@chromium.org
diff --git a/third_party/blink/perf_tests/layout/large-grid.html b/third_party/blink/perf_tests/layout/large-grid.html
index ed25793..6793d95 100644
--- a/third_party/blink/perf_tests/layout/large-grid.html
+++ b/third_party/blink/perf_tests/layout/large-grid.html
@@ -51,8 +51,6 @@
 
 ui-icon {
     display: inline-block;
-    flex-shrink: 0;
-    contain: strict
 }
 
 [collapsed ] { display: none; }
@@ -64,7 +62,7 @@
 
 .eventChildrenContainer {
     display: grid;
-    grid-template-columns: 3em var(--conditions-column-size) 1fr;
+    grid-template-columns: 3em 0px 1fr;
     contain: content;
 }
 
@@ -77,7 +75,7 @@
 
 .actionBlock {
     display: grid;
-    grid-template-columns: var(--action-name-cell-size) 1fr;
+    grid-template-columns: 1fr;
     overflow: hidden;
     contain: content
 }
@@ -139,7 +137,7 @@
 
         setup();
         PerfTestRunner.measureRunsPerSecond({
-            description: "Measures performance of layout on a page containing Arabic.",
+            description: "Measures performance of laying out a large grid.",
             run: test
         });
     </script>
diff --git a/third_party/blink/public/blink_resources.grd b/third_party/blink/public/blink_resources.grd
index 36f8416..e447c255 100644
--- a/third_party/blink/public/blink_resources.grd
+++ b/third_party/blink/public/blink_resources.grd
@@ -30,6 +30,7 @@
 
       <include name="IDR_INSPECT_TOOL_COMMON_JS" file="../renderer/core/inspector/inspect_tool_common.js" type="BINDATA" compress="gzip"/>
       <include name="IDR_INSPECT_TOOL_COMMON_CSS" file="../renderer/core/inspector/inspect_tool_common.css" type="BINDATA" compress="gzip"/>
+      <include name="IDR_INSPECT_TOOL_DISTANCES_HTML" file="../renderer/core/inspector/inspect_tool_distances.html" type="BINDATA" compress="gzip"/>
       <include name="IDR_INSPECT_TOOL_HIGHLIGHT_HTML" file="../renderer/core/inspector/inspect_tool_highlight.html" type="BINDATA" compress="gzip"/>
       <include name="IDR_INSPECT_TOOL_PAUSED_HTML" file="../renderer/core/inspector/inspect_tool_paused.html" type="BINDATA" compress="gzip"/>
       <include name="IDR_INSPECT_TOOL_VIEWPORT_SIZE_HTML" file="../renderer/core/inspector/inspect_tool_viewport_size.html" type="BINDATA" compress="gzip"/>
diff --git a/third_party/blink/public/common/manifest/manifest.h b/third_party/blink/public/common/manifest/manifest.h
index f62b327..1d202f2d 100644
--- a/third_party/blink/public/common/manifest/manifest.h
+++ b/third_party/blink/public/common/manifest/manifest.h
@@ -195,7 +195,9 @@
   // Null if parsing failed or the field was not present.
   base::NullableString16 gcm_sender_id;
 
-  // Empty if the parsing failed or the field was not present.
+  // Empty if the parsing failed. Otherwise defaults to the start URL (or
+  // document URL if start URL isn't present) with filename, query, and fragment
+  // removed.
   GURL scope;
 };
 
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 96f7c52..8aae434 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -319,10 +319,7 @@
     ":mojom_core",
     ":mojom_platform",
   ]
-  component_deps_blink = [
-    "//third_party/blink/renderer/core",
-    "//third_party/blink/renderer/modules:modules_export_header",
-  ]
+  component_deps_blink = [ "//third_party/blink/renderer/core" ]
 
   export_class_attribute = "BLINK_COMMON_EXPORT"
   export_define = "BLINK_COMMON_IMPLEMENTATION=1"
diff --git a/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom b/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom
index 172a9e5e7..2454e9d 100644
--- a/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom
+++ b/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom
@@ -51,12 +51,23 @@
      => (array<mojo_base.mojom.FilePath> file_paths,
          array<mojo_base.mojom.File> file_handles);
 
-  // Returns a protobuf structured lookup list of
+  // Synchronously returns a protobuf structured lookup list of
+  // (full_font_name|postscript_name) => (font_file + ttc_index) to the
+  // renderer process as a ReadOnlySharedMemoryRegion if it is available
+  // immediately without any blocking operations. Use FontTableMatcher to
+  // perform searches in it. If it is not available without blocking operations,
+  // sync_available is false and no shared memory region is provided.
+  [Sync]
+  GetUniqueNameLookupTableIfAvailable()
+      => (bool sync_available,
+          mojo_base.mojom.ReadOnlySharedMemoryRegion? font_lookup_table);
+
+  // Asynchronously returns a protobuf structured lookup list of
   // (full_font_name|postscript_name) => (font_file + ttc_index) to the
   // renderer process as a ReadOnlySharedMemoryRegion. The lookup list is built
   // on the first renderer call to retrieving this list. Use FontTableMatcher
-  // to perform searches in it.
-  [Sync]
+  // to perform searches in it. Retrieval may take up to several seconds if the
+  // table needs rebuilding on browser side.
   GetUniqueNameLookupTable() =>
   (mojo_base.mojom.ReadOnlySharedMemoryRegion font_lookup_table);
 
diff --git a/third_party/blink/public/mojom/serial/serial.mojom b/third_party/blink/public/mojom/serial/serial.mojom
index 34533152..ee8d9cea 100644
--- a/third_party/blink/public/mojom/serial/serial.mojom
+++ b/third_party/blink/public/mojom/serial/serial.mojom
@@ -5,7 +5,6 @@
 module blink.mojom;
 
 import "mojo/public/mojom/base/unguessable_token.mojom";
-import "services/device/public/mojom/serial.mojom";
 
 struct SerialPortInfo {
   // Opaque identifier for this port.
@@ -32,9 +31,4 @@
 
   // Requests permission to access a port.
   RequestPort(array<SerialPortFilter> filters) => (SerialPortInfo? port);
-
-  // Connects an instance of the SerialPort interface attached to the serial
-  // port identified by |token|.
-  GetPort(mojo_base.mojom.UnguessableToken token,
-          device.mojom.SerialPort& port_request);
 };
diff --git a/third_party/blink/public/platform/web_callbacks.h b/third_party/blink/public/platform/web_callbacks.h
index b02fa41e..f7e9866 100644
--- a/third_party/blink/public/platform/web_callbacks.h
+++ b/third_party/blink/public/platform/web_callbacks.h
@@ -57,14 +57,6 @@
   virtual void OnError() {}
 };
 
-template <>
-class WebCallbacks<void, void> {
- public:
-  virtual ~WebCallbacks() = default;
-  virtual void OnSuccess() {}
-  virtual void OnError() {}
-};
-
 }  // namespace blink
 
 #endif
diff --git a/third_party/blink/public/platform/web_loading_behavior_flag.h b/third_party/blink/public/platform/web_loading_behavior_flag.h
index 5c0a225ff..b1342dd1 100644
--- a/third_party/blink/public/platform/web_loading_behavior_flag.h
+++ b/third_party/blink/public/platform/web_loading_behavior_flag.h
@@ -35,17 +35,8 @@
   // Indicates that a subresource on the page matched the subresource filtering
   // rules.
   kWebLoadingBehaviorSubresourceFilterMatch = 1 << 6,
-  // Indicates that a subresource on the page was a candidate for stale
-  // while revalidate and caused a network load.
-  kStaleWhileRevalidateResourceCandidateNetworkLoad = 1 << 7,
-  // Indicates that a subresource on the page was a candidate for stale
-  // while revalidate and caused a stale cache load.
-  kStaleWhileRevalidateResourceCandidateStaleCacheLoad = 1 << 8,
-  // Indicates that a subresource on the page was a candidate for stale
-  // while revalidate and caused a non-stale cache load.
-  kStaleWhileRevalidateResourceCandidateCacheLoad = 1 << 9,
   // Indicates that the page is an AMP document, with <html amp> tag.
-  kWebLoadingBehaviorAmpDocumentLoaded = 1 << 10,
+  kWebLoadingBehaviorAmpDocumentLoaded = 1 << 7,
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/platform/web_rtc_certificate_generator.h b/third_party/blink/public/platform/web_rtc_certificate_generator.h
index 7a9f1112..198f4b1c 100644
--- a/third_party/blink/public/platform/web_rtc_certificate_generator.h
+++ b/third_party/blink/public/platform/web_rtc_certificate_generator.h
@@ -31,13 +31,12 @@
 #ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_CERTIFICATE_GENERATOR_H_
 #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_CERTIFICATE_GENERATOR_H_
 
-#include "third_party/blink/public/platform/web_callbacks.h"
+#include <memory>
+
 #include "third_party/blink/public/platform/web_rtc_key_params.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/webrtc/api/peer_connection_interface.h"
 
-#include <memory>
-
 namespace base {
 class SingleThreadTaskRunner;
 }
@@ -45,7 +44,7 @@
 namespace blink {
 
 using WebRTCCertificateCallback =
-    WebCallbacks<rtc::scoped_refptr<rtc::RTCCertificate>, void>;
+    base::OnceCallback<void(rtc::scoped_refptr<rtc::RTCCertificate>)>;
 
 // Interface defining a class that can generate WebRTCCertificates
 // asynchronously.
@@ -58,12 +57,12 @@
   // completed.
   virtual void GenerateCertificate(
       const WebRTCKeyParams&,
-      std::unique_ptr<WebRTCCertificateCallback> observer,
+      WebRTCCertificateCallback completion_callback,
       scoped_refptr<base::SingleThreadTaskRunner>) = 0;
   virtual void GenerateCertificateWithExpiration(
       const WebRTCKeyParams&,
       uint64_t expires_ms,
-      std::unique_ptr<WebRTCCertificateCallback> observer,
+      WebRTCCertificateCallback completion_callback,
       scoped_refptr<base::SingleThreadTaskRunner>) = 0;
 
   // Determines if the parameters are supported by |GenerateCertificate|.
diff --git a/third_party/blink/public/platform/web_speech_synthesizer_client.h b/third_party/blink/public/platform/web_speech_synthesizer_client.h
index b6eb70db..dcf168d 100644
--- a/third_party/blink/public/platform/web_speech_synthesizer_client.h
+++ b/third_party/blink/public/platform/web_speech_synthesizer_client.h
@@ -43,9 +43,11 @@
   virtual void DidFinishSpeaking(const WebSpeechSynthesisUtterance&) = 0;
   virtual void SpeakingErrorOccurred(const WebSpeechSynthesisUtterance&) = 0;
   virtual void WordBoundaryEventOccurred(const WebSpeechSynthesisUtterance&,
-                                         unsigned char_index) = 0;
+                                         unsigned char_index,
+                                         unsigned char_length) = 0;
   virtual void SentenceBoundaryEventOccurred(const WebSpeechSynthesisUtterance&,
-                                             unsigned char_index) = 0;
+                                             unsigned char_index,
+                                             unsigned char_length) = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/platform/web_url_request.h b/third_party/blink/public/platform/web_url_request.h
index 45f8fa7..1a65786 100644
--- a/third_party/blink/public/platform/web_url_request.h
+++ b/third_party/blink/public/platform/web_url_request.h
@@ -208,10 +208,10 @@
 
   BLINK_PLATFORM_EXPORT WebString HttpHeaderField(const WebString& name) const;
   // It's not possible to set the referrer header using this method. Use
-  // SetHTTPReferrer instead.
+  // SetHttpReferrer instead.
   BLINK_PLATFORM_EXPORT void SetHttpHeaderField(const WebString& name,
                                                 const WebString& value);
-  BLINK_PLATFORM_EXPORT void SetHTTPReferrer(const WebString& referrer,
+  BLINK_PLATFORM_EXPORT void SetHttpReferrer(const WebString& referrer,
                                              network::mojom::ReferrerPolicy);
   BLINK_PLATFORM_EXPORT void AddHttpHeaderField(const WebString& name,
                                                 const WebString& value);
@@ -242,7 +242,7 @@
 
   // Sets an HTTP origin header if it is empty and the HTTP method of the
   // request requires it.
-  BLINK_PLATFORM_EXPORT void SetHTTPOriginIfNeeded(const WebSecurityOrigin&);
+  BLINK_PLATFORM_EXPORT void SetHttpOriginIfNeeded(const WebSecurityOrigin&);
 
   // True if the request was user initiated.
   BLINK_PLATFORM_EXPORT bool HasUserGesture() const;
diff --git a/third_party/blink/public/web/modules/mediastream/web_media_stream_utils.h b/third_party/blink/public/web/modules/mediastream/web_media_stream_utils.h
index 2d01bcb..edf158c 100644
--- a/third_party/blink/public/web/modules/mediastream/web_media_stream_utils.h
+++ b/third_party/blink/public/web/modules/mediastream/web_media_stream_utils.h
@@ -36,11 +36,6 @@
 BLINK_EXPORT void RemoveSinkFromMediaStreamTrack(
     const WebMediaStreamTrack& track,
     WebMediaStreamSink* sink);
-
-BLINK_EXPORT void OnFrameDroppedAtMediaStreamSink(
-    const WebMediaStreamTrack& track,
-    media::VideoCaptureFrameDropReason reason);
-
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_WEB_MEDIA_STREAM_UTILS_H_
diff --git a/third_party/blink/public/web/web_frame_serializer.h b/third_party/blink/public/web/web_frame_serializer.h
index 0c1d1c9..39ac0763 100644
--- a/third_party/blink/public/web/web_frame_serializer.h
+++ b/third_party/blink/public/web/web_frame_serializer.h
@@ -131,9 +131,6 @@
       const WebString& charset);
   // Generate the MOTW declaration.
   BLINK_EXPORT static WebString GenerateMarkOfTheWebDeclaration(const WebURL&);
-  // Generate the default base tag declaration.
-  BLINK_EXPORT static WebString GenerateBaseTagDeclaration(
-      const WebString& base_target);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index 55722e9..8ec78aa 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -680,6 +680,22 @@
   // Reports that visible elements in the frame shifted (bit.ly/lsm-explainer).
   virtual void DidObserveLayoutJank(double jank_fraction) {}
 
+  enum class LazyLoadBehavior {
+    kDeferredImage,    // An image is being deferred by the lazy load feature.
+    kDeferredFrame,    // A frame is being deferred by the lazy load feature.
+    kLazyLoadedImage,  // An image that was previously deferred by the lazy load
+                       // feature is being fully loaded.
+    kLazyLoadedFrame   // A frame that was previously deferred by the lazy load
+                       // feature is being fully loaded.
+  };
+
+  // Reports lazy loaded behavior when the frame or image is fully deferred or
+  // if the frame or image is loaded after being deferred. Called every time the
+  // behavior occurs. This does not apply to images that were loaded as
+  // placeholders.
+  virtual void DidObserveLazyLoadBehavior(
+      WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) {}
+
   // Script notifications ------------------------------------------------
 
   // Notifies that a new script context has been created for this frame.
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
index d2ad145..f44f349 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
@@ -288,8 +288,8 @@
   Persistent<GCObservation> observation;
   {
     ScriptState::Scope scope(MainScriptState());
-    observation =
-        GCObservation::Create(Promise(DOMWrapperWorld::MainWorld()).V8Value());
+    observation = MakeGarbageCollected<GCObservation>(
+        Promise(DOMWrapperWorld::MainWorld()).V8Value());
   }
 
   Gc();
diff --git a/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_initial_values.h.tmpl b/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_initial_values.h.tmpl
index ff35a219..ef475c3 100644
--- a/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_initial_values.h.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/style/templates/computed_style_initial_values.h.tmpl
@@ -122,7 +122,7 @@
  private:
   static const FilterOperations& InitialFilterInternal() {
     DEFINE_STATIC_LOCAL(Persistent<FilterOperationsWrapper>, ops,
-        (FilterOperationsWrapper::Create()));
+        (MakeGarbageCollected<FilterOperationsWrapper>()));
     return ops->Operations();
   }
 };
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 02bfeb46..7a2699d0 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -2119,6 +2119,7 @@
     "loader/resource/mock_image_resource_observer.cc",
     "loader/resource/mock_image_resource_observer.h",
     "loader/resource/multipart_image_resource_parser_test.cc",
+    "loader/resource_load_observer_for_frame_test.cc",
     "loader/text_resource_decoder_builder_test.cc",
     "loader/threadable_loader_test.cc",
     "messaging/blink_transferable_message_struct_traits_test.cc",
diff --git a/third_party/blink/renderer/core/animation/animatable/animatable_filter_operations.h b/third_party/blink/renderer/core/animation/animatable/animatable_filter_operations.h
index cdb0ab7..535678a 100644
--- a/third_party/blink/renderer/core/animation/animatable/animatable_filter_operations.h
+++ b/third_party/blink/renderer/core/animation/animatable/animatable_filter_operations.h
@@ -45,7 +45,8 @@
   }
 
   AnimatableFilterOperations(const FilterOperations& operations)
-      : operation_wrapper_(FilterOperationsWrapper::Create(operations)) {}
+      : operation_wrapper_(
+            MakeGarbageCollected<FilterOperationsWrapper>(operations)) {}
   ~AnimatableFilterOperations() override = default;
 
   const FilterOperations& Operations() const {
diff --git a/third_party/blink/renderer/core/animation/animation_test.cc b/third_party/blink/renderer/core/animation/animation_test.cc
index a0b62db..b69cfe8 100644
--- a/third_party/blink/renderer/core/animation/animation_test.cc
+++ b/third_party/blink/renderer/core/animation/animation_test.cc
@@ -54,7 +54,7 @@
 class AnimationAnimationTest : public RenderingTest {
  public:
   AnimationAnimationTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
   void SetUp() override {
     RenderingTest::SetUp();
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
index ced8569..e843700 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -1941,7 +1941,48 @@
     ASSERT_NE(nullptr, cc_transform);
     EXPECT_TRUE(cc_transform->has_potential_animation);
     EXPECT_TRUE(cc_transform->is_currently_animating);
+    EXPECT_EQ(cc::kNotScaled, cc_transform->starting_animation_scale);
+    EXPECT_EQ(cc::kNotScaled, cc_transform->maximum_animation_scale);
   }
+
+  // Make sure the animation is started on the compositor.
+  EXPECT_TRUE(CheckCanStartElementOnCompositor(*target));
+  EXPECT_EQ(document->Timeline().PendingAnimationsCount(), 1u);
+  cc::AnimationHost* host = document->View()->GetCompositorAnimationHost();
+  EXPECT_EQ(host->MainThreadAnimationsCount(), 0u);
+  EXPECT_EQ(host->CompositedAnimationsCount(), 1u);
+}
+
+TEST_P(AnimationCompositorAnimationsTest, CompositedScaleAnimation) {
+  // TODO(wangxianzhu): Fix this test for CompositeAfterPaint.
+  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+    return;
+
+  LoadTestData("scale-animation.html");
+  Document* document = GetFrame()->GetDocument();
+  Element* target = document->getElementById("target");
+  const ObjectPaintProperties* properties =
+      target->GetLayoutObject()->FirstFragment().PaintProperties();
+  ASSERT_NE(nullptr, properties);
+  const auto* transform = properties->Transform();
+  ASSERT_NE(nullptr, transform);
+  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ||
+      RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+    EXPECT_TRUE(transform->HasDirectCompositingReasons());
+    EXPECT_TRUE(transform->HasActiveTransformAnimation());
+    // Make sure the animation state is initialized in paint properties.
+    auto* property_trees =
+        document->View()->RootCcLayer()->layer_tree_host()->property_trees();
+    auto* cc_transform = property_trees->transform_tree.Node(
+        property_trees->element_id_to_transform_node_index
+            [transform->GetCompositorElementId()]);
+    ASSERT_NE(nullptr, cc_transform);
+    EXPECT_TRUE(cc_transform->has_potential_animation);
+    EXPECT_TRUE(cc_transform->is_currently_animating);
+    EXPECT_EQ(2.f, cc_transform->starting_animation_scale);
+    EXPECT_EQ(5.f, cc_transform->maximum_animation_scale);
+  }
+
   // Make sure the animation is started on the compositor.
   EXPECT_TRUE(CheckCanStartElementOnCompositor(*target));
   EXPECT_EQ(document->Timeline().PendingAnimationsCount(), 1u);
diff --git a/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc
index bf85356..a27c0c84 100644
--- a/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc
@@ -83,7 +83,7 @@
                              const FilterOperations& filter_operations)
       : property_(property),
         filter_operations_wrapper_(
-            FilterOperationsWrapper::Create(filter_operations)) {}
+            MakeGarbageCollected<FilterOperationsWrapper>(filter_operations)) {}
 
   bool IsValid(const StyleResolverState& state,
                const InterpolationValue&) const final {
diff --git a/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc b/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc
index d689c16..607e90a 100644
--- a/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc
+++ b/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc
@@ -260,7 +260,7 @@
     case FilterOperation::SEPIA: {
       double value = ClampParameter(
           ToInterpolableNumber(interpolable_value).Value(), type);
-      return BasicColorMatrixFilterOperation::Create(value, type);
+      return MakeGarbageCollected<BasicColorMatrixFilterOperation>(value, type);
     }
 
     case FilterOperation::BRIGHTNESS:
@@ -269,14 +269,15 @@
     case FilterOperation::OPACITY: {
       double value = ClampParameter(
           ToInterpolableNumber(interpolable_value).Value(), type);
-      return BasicComponentTransferFilterOperation::Create(value, type);
+      return MakeGarbageCollected<BasicComponentTransferFilterOperation>(value,
+                                                                         type);
     }
 
     case FilterOperation::BLUR: {
       Length std_deviation = LengthInterpolationFunctions::CreateLength(
           interpolable_value, non_interpolable_value.TypeNonInterpolableValue(),
           state.CssToLengthConversionData(), kValueRangeNonNegative);
-      return BlurFilterOperation::Create(std_deviation);
+      return MakeGarbageCollected<BlurFilterOperation>(std_deviation);
     }
 
     case FilterOperation::DROP_SHADOW: {
diff --git a/third_party/blink/renderer/core/animation/test_data/scale-animation.html b/third_party/blink/renderer/core/animation/test_data/scale-animation.html
new file mode 100644
index 0000000..e92917a9
--- /dev/null
+++ b/third_party/blink/renderer/core/animation/test_data/scale-animation.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<style>
+@keyframes test {
+  0% { transform: scale(2); }
+  100% { transform: scale(5); }
+}
+
+.animate {
+  animation-name: test;
+  animation-duration: 1s;
+}
+</style>
+<div id="target" class="animate"></div>
diff --git a/third_party/blink/renderer/core/css/css_font_face_src_value.cc b/third_party/blink/renderer/core/css/css_font_face_src_value.cc
index 96b5163..b7b52c32 100644
--- a/third_party/blink/renderer/core/css/css_font_face_src_value.cc
+++ b/third_party/blink/renderer/core/css/css_font_face_src_value.cc
@@ -85,7 +85,7 @@
                                          FontResourceClient* client) const {
   if (!fetched_) {
     ResourceRequest resource_request(absolute_resource_);
-    resource_request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
+    resource_request.SetHttpReferrer(SecurityPolicy::GenerateReferrer(
         referrer_.referrer_policy, resource_request.Url(), referrer_.referrer));
     ResourceLoaderOptions options;
     options.initiator_info.name = fetch_initiator_type_names::kCSS;
diff --git a/third_party/blink/renderer/core/css/css_image_set_value.cc b/third_party/blink/renderer/core/css/css_image_set_value.cc
index 09cd789..a8cd7be2 100644
--- a/third_party/blink/renderer/core/css/css_image_set_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_set_value.cc
@@ -114,7 +114,7 @@
     // transforms. https://bugs.webkit.org/show_bug.cgi?id=81698
     ImageWithScale image = BestImageForScaleFactor(device_scale_factor);
     ResourceRequest resource_request(document.CompleteURL(image.image_url));
-    resource_request.SetHTTPReferrer(image.referrer);
+    resource_request.SetHttpReferrer(image.referrer);
     ResourceLoaderOptions options;
     options.initiator_info.name = parser_mode_ == kUASheetMode
                                       ? fetch_initiator_type_names::kUacss
@@ -132,7 +132,7 @@
       params.SetClientLoFiPlaceholder();
     }
 
-    cached_image_ = StyleFetchedImageSet::Create(
+    cached_image_ = MakeGarbageCollected<StyleFetchedImageSet>(
         ImageResourceContent::Fetch(params, document.Fetcher()),
         image.scale_factor, this, params.Url());
     cached_scale_factor_ = device_scale_factor;
diff --git a/third_party/blink/renderer/core/css/css_image_value.cc b/third_party/blink/renderer/core/css/css_image_value.cc
index 2009f277..f0b8c04 100644
--- a/third_party/blink/renderer/core/css/css_image_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_value.cc
@@ -20,9 +20,11 @@
 
 #include "third_party/blink/renderer/core/css/css_image_value.h"
 
+#include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/renderer/core/css/css_markup.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
 #include "third_party/blink/renderer/core/style/style_fetched_image.h"
 #include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h"
@@ -60,7 +62,7 @@
     if (absolute_url_.IsEmpty())
       ReResolveURL(document);
     ResourceRequest resource_request(absolute_url_);
-    resource_request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
+    resource_request.SetHttpReferrer(SecurityPolicy::GenerateReferrer(
         referrer_.referrer_policy, resource_request.Url(), referrer_.referrer));
     ResourceLoaderOptions options;
     options.initiator_info.name = initiator_name_.IsEmpty()
@@ -82,11 +84,16 @@
         image_request_optimization == FetchParameters::kDeferImageLoad &&
         // Only http/https images are eligible to be lazily loaded.
         params.Url().ProtocolIsInHTTPFamily();
-    if (is_lazily_loaded)
+    if (is_lazily_loaded) {
+      if (document.GetFrame() && document.GetFrame()->Client()) {
+        document.GetFrame()->Client()->DidObserveLazyLoadBehavior(
+            WebLocalFrameClient::LazyLoadBehavior::kDeferredImage);
+      }
       params.SetLazyImageDeferred();
+    }
 
-    cached_image_ =
-        StyleFetchedImage::Create(document, params, is_lazily_loaded);
+    cached_image_ = MakeGarbageCollected<StyleFetchedImage>(document, params,
+                                                            is_lazily_loaded);
   }
   return cached_image_.Get();
 }
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index a46b912..f85710b 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -853,7 +853,7 @@
       field_template: "external",
       include_paths: ["third_party/blink/renderer/core/style/style_filter_data.h"],
       wrapper_pointer_name: "Persistent",
-      default_value: "StyleFilterData::Create()",
+      default_value: "MakeGarbageCollected<StyleFilterData>()",
       type_name: "StyleFilterData",
       computed_style_custom_functions: ["initial", "getter","setter"],
       converter: "ConvertFilterOperations",
@@ -1626,7 +1626,7 @@
       field_template: "external",
       include_paths: ["third_party/blink/renderer/core/style/style_filter_data.h"],
       wrapper_pointer_name: "Persistent",
-      default_value: "StyleFilterData::Create()",
+      default_value: "MakeGarbageCollected<StyleFilterData>()",
       type_name: "StyleFilterData",
       computed_style_custom_functions: ["initial", "getter", "setter"],
       converter: "ConvertFilterOperations",
diff --git a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
index 7059cfcb..20a3f16 100644
--- a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc
@@ -330,6 +330,9 @@
            Fallback::kSuccess;
   }
 
+  if (variable_data->Tokens().size() > kMaxSubstitutionTokens)
+    return false;
+
   result.tokens.AppendVector(variable_data->Tokens());
   // TODO(alancutter): Avoid adding backing strings multiple times in a row.
   result.backing_strings.AppendVector(variable_data->BackingStrings());
diff --git a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h
index 1338e8c6..d16fe74 100644
--- a/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h
+++ b/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h
@@ -54,6 +54,12 @@
   virtual void ApplyAnimation(const AtomicString& name) {}
 
  private:
+  // The maximum number of tokens that may be produced by a var()
+  // reference.
+  //
+  // https://drafts.csswg.org/css-variables/#long-variables
+  static const size_t kMaxSubstitutionTokens = 16384;
+
   struct Options {
     STACK_ALLOCATED();
 
@@ -213,6 +219,8 @@
   // need to be tracked for additional cycles, and invalidation only
   // applies back to cycle starts.
   HashSet<AtomicString> cycle_start_points_;
+
+  friend class CSSVariableResolverTest;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc b/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc
index eab50d1..0082ae7d 100644
--- a/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc
@@ -21,6 +21,7 @@
 #include "third_party/blink/renderer/core/html/html_element.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 
 namespace blink {
 
@@ -77,6 +78,26 @@
   const CSSValue* CreatePxValue(double px) {
     return CSSPrimitiveValue::Create(px, CSSPrimitiveValue::UnitType::kPixels);
   }
+
+  size_t MaxSubstitutionTokens() const {
+    return CSSVariableResolver::kMaxSubstitutionTokens;
+  }
+
+  void SetTestHTMLWithReferencedVariableValue(const String& referenced) {
+    StringBuilder builder;
+    builder.Append("<style>\n");
+    builder.Append("#target {\n");
+    builder.Append("  --x:var(--referenced);\n");
+    builder.Append("  --referenced:");
+    builder.Append(referenced);
+    builder.Append(";\n");
+    builder.Append("}\n");
+    builder.Append("</style>\n");
+    builder.Append("<div id=target></div>\n");
+
+    GetDocument().body()->SetInnerHTMLFromString(builder.ToString());
+    UpdateAllLifecyclePhasesForTest();
+  }
 };
 
 TEST_F(CSSVariableResolverTest, ParseEnvVariable_Missing_NestedVar) {
@@ -359,4 +380,130 @@
   inherited_variables->SetRegisteredVariable(name, nullptr);
 }
 
+TEST_F(CSSVariableResolverTest, TokenCountAboveLimitIsInValidForSubstitution) {
+  StringBuilder builder;
+  for (size_t i = 0; i < MaxSubstitutionTokens(); ++i)
+    builder.Append(":");
+  builder.Append(":");
+  builder.Append(";");
+  SetTestHTMLWithReferencedVariableValue(builder.ToString());
+
+  Element* target = GetDocument().getElementById("target");
+  ASSERT_TRUE(target);
+
+  // A custom property with more than MaxSubstitutionTokens() is valid ...
+  const CSSVariableData* referenced =
+      target->ComputedStyleRef().GetVariable("--referenced");
+  ASSERT_TRUE(referenced);
+  EXPECT_EQ(MaxSubstitutionTokens() + 1, referenced->Tokens().size());
+
+  // ... it is not valid for substitution, however.
+  EXPECT_FALSE(target->ComputedStyleRef().GetVariable("--x"));
+}
+
+TEST_F(CSSVariableResolverTest, TokenCountAtLimitIsValidForSubstitution) {
+  StringBuilder builder;
+  for (size_t i = 0; i < MaxSubstitutionTokens(); ++i)
+    builder.Append(":");
+  builder.Append(";");
+  SetTestHTMLWithReferencedVariableValue(builder.ToString());
+
+  Element* target = GetDocument().getElementById("target");
+  ASSERT_TRUE(target);
+
+  const CSSVariableData* referenced =
+      target->ComputedStyleRef().GetVariable("--referenced");
+  ASSERT_TRUE(referenced);
+  EXPECT_EQ(MaxSubstitutionTokens(), referenced->Tokens().size());
+
+  const CSSVariableData* x = target->ComputedStyleRef().GetVariable("--x");
+  ASSERT_TRUE(x);
+  EXPECT_EQ(MaxSubstitutionTokens(), x->Tokens().size());
+
+  EXPECT_EQ(*referenced, *x);
+}
+
+TEST_F(CSSVariableResolverTest, BillionLaughs) {
+  StringBuilder builder;
+  builder.Append("<style>\n");
+  builder.Append("#target {\n");
+
+  // Produces:
+  //
+  // --x1:lol;
+  // --x2:var(--x1)var(--x1);
+  // --x4:var(--x2)var(--x2);
+  // --x8:var(--x4)var(--x4);
+  // .. etc
+  builder.Append("  --x1:lol;\n");
+
+  size_t tokens = 1;
+  while (tokens <= MaxSubstitutionTokens()) {
+    tokens *= 2;
+    builder.Append("--x");
+    builder.AppendNumber(tokens);
+    builder.Append(":var(--x");
+    builder.AppendNumber(tokens / 2);
+    builder.Append(")");
+    builder.Append("var(--x");
+    builder.AppendNumber(tokens / 2);
+    builder.Append(")");
+    builder.Append(";");
+  }
+
+  builder.AppendNumber(tokens);
+  builder.Append(");\n");
+
+  builder.Append("--ref-last:var(--x");
+  builder.AppendNumber(tokens);
+  builder.Append(");");
+
+  builder.Append("--ref-next-to-last:var(--x");
+  builder.AppendNumber(tokens / 2);
+  builder.Append(");");
+
+  builder.Append("}\n");
+  builder.Append("</style>\n");
+  builder.Append("<div id=target></div>\n");
+
+  GetDocument().body()->SetInnerHTMLFromString(builder.ToString());
+  UpdateAllLifecyclePhasesForTest();
+
+  Element* target = GetDocument().getElementById("target");
+  ASSERT_TRUE(target);
+
+  // The last --x2^N variable is over the limit. Any reference to that
+  // should be invalid.
+  const CSSVariableData* ref_last =
+      target->ComputedStyleRef().GetVariable("--ref-last");
+  EXPECT_FALSE(ref_last);
+
+  // The next-to-last (--x2^(N-1)) variable is not over the limit. A reference
+  // to that is still valid.
+  const CSSVariableData* ref_next_to_last =
+      target->ComputedStyleRef().GetVariable("--ref-next-to-last");
+  ASSERT_TRUE(ref_next_to_last);
+  EXPECT_EQ(tokens / 2, ref_next_to_last->Tokens().size());
+
+  // Ensure that there are a limited number of unique backing strings.
+  // Each variable will have many backing strings, but should point to
+  // a small number of StringImpls.
+
+  HashSet<const StringImpl*> impls;
+  for (const String& string : ref_next_to_last->BackingStrings())
+    impls.insert(string.Impl());
+
+  size_t expected_unique_strings = 0;
+
+  // Each --x2^N property has a unique backing string (for its var-tokens, etc).
+  // For --x1, that unique string is of course "lol".
+  for (size_t i = (tokens / 2); i != 0; i = i >> 1)
+    expected_unique_strings += 1;
+
+  // --ref-next-to-last also has a backing string.
+  expected_unique_strings += 1;
+
+  EXPECT_EQ(expected_unique_strings, impls.size());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
index 95878a1..6eb5d95 100644
--- a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
+++ b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
@@ -76,9 +76,9 @@
     const CSSImageGeneratorValue& value) {
   if (value.IsPending()) {
     pending_image_properties_.insert(property);
-    return StylePendingImage::Create(value);
+    return MakeGarbageCollected<StylePendingImage>(value);
   }
-  return StyleGeneratedImage::Create(value);
+  return MakeGarbageCollected<StyleGeneratedImage>(value);
 }
 
 StyleImage* ElementStyleResources::SetOrPendingFromValue(
@@ -86,7 +86,7 @@
     const CSSImageSetValue& value) {
   if (value.IsCachePending(device_scale_factor_)) {
     pending_image_properties_.insert(property);
-    return StylePendingImage::Create(value);
+    return MakeGarbageCollected<StylePendingImage>(value);
   }
   return value.CachedImage(device_scale_factor_);
 }
@@ -96,7 +96,7 @@
     const CSSImageValue& value) {
   if (value.IsCachePending()) {
     pending_image_properties_.insert(property);
-    return StylePendingImage::Create(value);
+    return MakeGarbageCollected<StylePendingImage>(value);
   }
   value.RestoreCachedResourceIfNeeded(element_->GetDocument());
   return value.CachedImage();
@@ -155,7 +155,7 @@
   }
 
   if (CSSPaintValue* paint_value = pending_image->CssPaintValue()) {
-    StyleGeneratedImage* image = StyleGeneratedImage::Create(*paint_value);
+    auto* image = MakeGarbageCollected<StyleGeneratedImage>(*paint_value);
     style->AddPaintImage(image);
     return image;
   }
@@ -163,7 +163,7 @@
   if (CSSImageGeneratorValue* image_generator_value =
           pending_image->CssImageGeneratorValue()) {
     image_generator_value->LoadSubimages(element_->GetDocument());
-    return StyleGeneratedImage::Create(*image_generator_value);
+    return MakeGarbageCollected<StyleGeneratedImage>(*image_generator_value);
   }
 
   if (CSSImageSetValue* image_set_value = pending_image->CssImageSetValue()) {
diff --git a/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc b/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc
index 3598a4d..f4d3121 100644
--- a/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc
@@ -174,8 +174,9 @@
           state.GetElementStyleResources().GetSVGResourceFromValue(
               state.GetTreeScope(), *url_value,
               ElementStyleResources::kAllowExternalResource);
-      operations.Operations().push_back(ReferenceFilterOperation::Create(
-          url_value->ValueForSerialization(), resource));
+      operations.Operations().push_back(
+          MakeGarbageCollected<ReferenceFilterOperation>(
+              url_value->ValueForSerialization(), resource));
       continue;
     }
 
@@ -198,8 +199,8 @@
       case CSSValueID::kSaturate:
       case CSSValueID::kHueRotate: {
         operations.Operations().push_back(
-            BasicColorMatrixFilterOperation::Create(first_number,
-                                                    operation_type));
+            MakeGarbageCollected<BasicColorMatrixFilterOperation>(
+                first_number, operation_type));
         break;
       }
       case CSSValueID::kInvert:
@@ -207,8 +208,8 @@
       case CSSValueID::kContrast:
       case CSSValueID::kOpacity: {
         operations.Operations().push_back(
-            BasicComponentTransferFilterOperation::Create(first_number,
-                                                          operation_type));
+            MakeGarbageCollected<BasicComponentTransferFilterOperation>(
+                first_number, operation_type));
         break;
       }
       case CSSValueID::kBlur: {
@@ -217,7 +218,7 @@
           std_deviation = first_value->ConvertToLength(conversion_data);
         }
         operations.Operations().push_back(
-            BlurFilterOperation::Create(std_deviation));
+            MakeGarbageCollected<BlurFilterOperation>(std_deviation));
         break;
       }
       case CSSValueID::kDropShadow: {
@@ -282,8 +283,8 @@
       case CSSValueID::kSaturate:
       case CSSValueID::kHueRotate: {
         operations.Operations().push_back(
-            BasicColorMatrixFilterOperation::Create(first_number,
-                                                    operation_type));
+            MakeGarbageCollected<BasicColorMatrixFilterOperation>(
+                first_number, operation_type));
         break;
       }
       case CSSValueID::kInvert:
@@ -291,8 +292,8 @@
       case CSSValueID::kContrast:
       case CSSValueID::kOpacity: {
         operations.Operations().push_back(
-            BasicComponentTransferFilterOperation::Create(first_number,
-                                                          operation_type));
+            MakeGarbageCollected<BasicComponentTransferFilterOperation>(
+                first_number, operation_type));
         break;
       }
       case CSSValueID::kBlur: {
@@ -301,7 +302,7 @@
           std_deviation = first_value->ConvertToLength(conversion_data);
         }
         operations.Operations().push_back(
-            BlurFilterOperation::Create(std_deviation));
+            MakeGarbageCollected<BlurFilterOperation>(std_deviation));
         break;
       }
       case CSSValueID::kDropShadow: {
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc
index 0d79e06..f2ed5f9 100644
--- a/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc
@@ -11,7 +11,8 @@
 
 class StyleAdjusterTest : public RenderingTest {
  public:
-  StyleAdjusterTest() : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+  StyleAdjusterTest()
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 };
 
 TEST_F(StyleAdjusterTest, TouchActionPropagatedAcrossIframes) {
diff --git a/third_party/blink/renderer/core/css/style_change_reason.cc b/third_party/blink/renderer/core/css/style_change_reason.cc
index 8df8ebc..8229295 100644
--- a/third_party/blink/renderer/core/css/style_change_reason.cc
+++ b/third_party/blink/renderer/core/css/style_change_reason.cc
@@ -47,6 +47,7 @@
 const char kShadow[] = "Shadow";
 const char kStyleInvalidator[] = "StyleInvalidator";
 const char kStyleSheetChange[] = "StyleSheetChange";
+const char kUseFallback[] = "UseFallback";
 const char kViewportUnits[] = "ViewportUnits";
 const char kVisitedLink[] = "VisitedLink";
 const char kVisuallyOrdered[] = "VisuallyOrdered";
diff --git a/third_party/blink/renderer/core/css/style_change_reason.h b/third_party/blink/renderer/core/css/style_change_reason.h
index a7a3f38..58bda958 100644
--- a/third_party/blink/renderer/core/css/style_change_reason.h
+++ b/third_party/blink/renderer/core/css/style_change_reason.h
@@ -48,6 +48,7 @@
 extern const char kShadow[];
 extern const char kStyleInvalidator[];
 extern const char kStyleSheetChange[];
+extern const char kUseFallback[];
 extern const char kViewportUnits[];
 extern const char kVisitedLink[];
 extern const char kVisuallyOrdered[];
diff --git a/third_party/blink/renderer/core/css/threaded/filter_operation_resolver_threaded_test.cc b/third_party/blink/renderer/core/css/threaded/filter_operation_resolver_threaded_test.cc
index 2b608ae..ea21431b 100644
--- a/third_party/blink/renderer/core/css/threaded/filter_operation_resolver_threaded_test.cc
+++ b/third_party/blink/renderer/core/css/threaded/filter_operation_resolver_threaded_test.cc
@@ -26,7 +26,7 @@
     FilterOperations fo =
         FilterOperationResolver::CreateOffscreenFilterOperations(*value, font);
     ASSERT_EQ(fo.size(), 1ul);
-    EXPECT_EQ(*fo.at(0), *BasicColorMatrixFilterOperation::Create(
+    EXPECT_EQ(*fo.at(0), *MakeGarbageCollected<BasicColorMatrixFilterOperation>(
                              0.5, FilterOperation::SEPIA));
   });
 }
@@ -43,8 +43,9 @@
     FilterOperations fo =
         FilterOperationResolver::CreateOffscreenFilterOperations(*value, font);
     ASSERT_EQ(fo.size(), 1ul);
-    EXPECT_EQ(*fo.at(0), *BasicComponentTransferFilterOperation::Create(
-                             0.5, FilterOperation::BRIGHTNESS));
+    EXPECT_EQ(*fo.at(0),
+              *MakeGarbageCollected<BasicComponentTransferFilterOperation>(
+                  0.5, FilterOperation::BRIGHTNESS));
   });
 }
 
@@ -60,7 +61,8 @@
     FilterOperations fo =
         FilterOperationResolver::CreateOffscreenFilterOperations(*value, font);
     ASSERT_EQ(fo.size(), 1ul);
-    EXPECT_EQ(*fo.at(0), *BlurFilterOperation::Create(Length::Fixed(10)));
+    EXPECT_EQ(*fo.at(0),
+              *MakeGarbageCollected<BlurFilterOperation>(Length::Fixed(10)));
   });
 }
 
@@ -95,10 +97,11 @@
         FilterOperationResolver::CreateOffscreenFilterOperations(*value, font);
     EXPECT_FALSE(fo.IsEmpty());
     ASSERT_EQ(fo.size(), 2ul);
-    EXPECT_EQ(*fo.at(0), *BasicColorMatrixFilterOperation::Create(
+    EXPECT_EQ(*fo.at(0), *MakeGarbageCollected<BasicColorMatrixFilterOperation>(
                              0.5, FilterOperation::SEPIA));
-    EXPECT_EQ(*fo.at(1), *BasicComponentTransferFilterOperation::Create(
-                             0.5, FilterOperation::BRIGHTNESS));
+    EXPECT_EQ(*fo.at(1),
+              *MakeGarbageCollected<BasicComponentTransferFilterOperation>(
+                  0.5, FilterOperation::BRIGHTNESS));
   });
 }
 
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
index 839d12c..330f3ac 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
@@ -54,7 +54,12 @@
   // Note that we're not testing the display lock here, just the budget so we
   // can do minimal work to ensure we have a context, ignoring containment and
   // other requirements.
-  SetBodyInnerHTML(R"HTML(
+  SetHtmlInnerHTML(R"HTML(
+    <style>
+      div {
+        contain: style layout;
+      }
+    </style>
     <div id="container"></div>
   )HTML");
 
@@ -68,11 +73,8 @@
   ASSERT_TRUE(element->GetDisplayLockContext());
   UnyieldingDisplayLockBudget budget(element->GetDisplayLockContext());
 
-  // Since the lifecycle is clean, we don't actually need any updates.
-  EXPECT_FALSE(budget.NeedsLifecycleUpdates());
-
-  // Dirtying the element will cause us to do updates.
-  element->GetLayoutObject()->SetNeedsLayout("");
+  // When acquiring, we need to update the layout with the locked size, so we
+  // need an update.
   EXPECT_TRUE(budget.NeedsLifecycleUpdates());
 
   // Check everything twice since it shouldn't matter how many times we ask the
@@ -88,8 +90,6 @@
     budget.DidPerformPhase(DisplayLockBudget::Phase::kStyle);
     budget.DidPerformPhase(DisplayLockBudget::Phase::kLayout);
     budget.DidPerformPhase(DisplayLockBudget::Phase::kPrePaint);
-    UpdateAllLifecyclePhasesForTest();
-    EXPECT_FALSE(budget.NeedsLifecycleUpdates());
   }
 }
 
@@ -111,11 +111,8 @@
   ASSERT_TRUE(element->GetDisplayLockContext());
   StrictYieldingDisplayLockBudget budget(element->GetDisplayLockContext());
 
-  // Since the lifecycle is clean, we don't actually need any updates.
-  EXPECT_FALSE(budget.NeedsLifecycleUpdates());
-
-  // Dirtying the element will cause us to do updates.
-  element->GetLayoutObject()->SetNeedsLayout("");
+  // When acquiring, we need to update the layout with the locked size, so we
+  // need an update.
   EXPECT_TRUE(budget.NeedsLifecycleUpdates());
 
   {
@@ -232,7 +229,12 @@
   // Note that we're not testing the display lock here, just the budget so we
   // can do minimal work to ensure we have a context, ignoring containment and
   // other requirements.
-  SetBodyInnerHTML(R"HTML(
+  SetHtmlInnerHTML(R"HTML(
+    <style>
+      div {
+        contain: style layout;
+      }
+    </style>
     <div id="container"></div>
   )HTML");
 
@@ -246,18 +248,8 @@
   ASSERT_TRUE(element->GetDisplayLockContext());
   StrictYieldingDisplayLockBudget budget(element->GetDisplayLockContext());
 
-  // Since the lifecycle is clean, we don't actually need any updates.
-  EXPECT_FALSE(budget.NeedsLifecycleUpdates());
-
-  // Dirtying the element will cause us to do updates.
-  element->GetLayoutObject()->SetNeedsLayout("");
-  EXPECT_TRUE(budget.NeedsLifecycleUpdates());
-
-  // Cleaning the lifecycle phases makes the budget not want any more updates.
-  UpdateAllLifecyclePhasesForTest();
-  EXPECT_FALSE(budget.NeedsLifecycleUpdates());
-
-  element->GetLayoutObject()->SetNeedsLayout("");
+  // When acquiring, we need to update the layout with the locked size, so we
+  // need an update.
   EXPECT_TRUE(budget.NeedsLifecycleUpdates());
   budget.WillStartLifecycleUpdate();
 
@@ -296,11 +288,8 @@
 
   WTF::ScopedMockClock clock;
 
-  // Since the lifecycle is clean, we don't actually need any updates.
-  EXPECT_FALSE(budget.NeedsLifecycleUpdates());
-
-  // Dirtying the element will cause us to do updates.
-  element->GetLayoutObject()->SetNeedsLayout("");
+  // When acquiring, we need to update the layout with the locked size, so we
+  // need an update.
   EXPECT_TRUE(budget.NeedsLifecycleUpdates());
 
   budget.WillStartLifecycleUpdate();
@@ -410,8 +399,9 @@
 
   WTF::ScopedMockClock clock;
 
-  // Since the lifecycle is clean, we don't actually need any updates.
-  EXPECT_FALSE(budget->NeedsLifecycleUpdates());
+  // When acquiring, we need to update the layout with the locked size, so we
+  // need an update.
+  EXPECT_TRUE(budget->NeedsLifecycleUpdates());
 
   // Dirtying the element will cause us to do updates.
   GetDocument().getElementById("child")->SetInnerHTMLFromString("a");
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index 62d1b24..fe2cd08 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -39,6 +39,7 @@
     "Containment requirement is not satisfied.";
 const char* kElementIsDisconnected = "Element is disconnected.";
 const char* kLockCommitted = "Lock commit was requested.";
+const char* kInvalidOptions = "Invalid options.";
 }  // namespace rejection_names
 
 // Helper function to convert a display locking state to a string. Used in
@@ -53,8 +54,6 @@
       return "kCommitting";
     case DisplayLockContext::kUnlocked:
       return "kUnlocked";
-    case DisplayLockContext::kPendingAcquire:
-      return "kPendingAcquire";
   }
   return "";
 }
@@ -77,6 +76,12 @@
   return promise;
 }
 
+base::Optional<LayoutSize> ParseAndVerifySize(const Vector<double>& size) {
+  if (size.size() != 2 || size[0] < 0 || size[1] < 0)
+    return {};
+  return LayoutSize(static_cast<float>(size[0]), static_cast<float>(size[1]));
+}
+
 }  // namespace
 
 DisplayLockContext::DisplayLockContext(Element* element,
@@ -156,45 +161,59 @@
   }
   activatable_ = options && options->activatable();
 
+  if (options && options->hasSize()) {
+    auto parsed_size = ParseAndVerifySize(options->size());
+    if (!parsed_size) {
+      return GetRejectedPromise(script_state, rejection_names::kInvalidOptions);
+    }
+    locked_frame_rect_ = LayoutRect(LayoutPoint(), *parsed_size);
+  } else {
+    locked_frame_rect_ = LayoutRect();
+  }
+
   // We always reschedule a timeout task even if we're not starting a new
   // acquire. The reason for this is that the last acquire dictates the timeout
   // interval. Note that the following call cancels any existing timeout tasks.
   RescheduleTimeoutTask(timeout_ms);
 
-  if (state_ == kPendingAcquire) {
-    DCHECK(acquire_resolver_);
+  if (acquire_resolver_)
     return acquire_resolver_->Promise();
-  }
-  DCHECK(!acquire_resolver_);
 
-  // At this point, if we're not unlocked, then we must already be locked.
-  if (state_ != kUnlocked)
+  // At this point, we updated state based on the options so if we're locked,
+  // resolve.
+  if (IsLocked())
     return GetResolvedPromise(script_state);
 
   update_budget_.reset();
-  is_locked_after_connect_ = element_->isConnected();
 
-  // If we're already connected then we need to ensure that 1. layout is clean
-  // and 2. we have removed the current painted output.
+  // If we're already connected then we need to ensure that we update our layout
+  // size based on the options and we have cleared the painted output.
   if (ConnectedToView()) {
     acquire_resolver_ =
         MakeGarbageCollected<ScriptPromiseResolver>(script_state);
-    state_ = kPendingAcquire;
+    if (auto* layout_object = element_->GetLayoutObject()) {
+      layout_object->SetNeedsLayout(
+          layout_invalidation_reason::kDisplayLockCommitting);
+    }
     MarkPaintLayerNeedsRepaint();
     ScheduleAnimation();
+    // TODO(vmpstr): This needs to be set after invalidation above, since we
+    // want the object to layout once. After the changes to separate self and
+    // child layout, this would no longer be required and we can set the
+    // container as locked earlier.
+    state_ = kLocked;
     return acquire_resolver_->Promise();
   }
 
-  // Otherwise (if we're not connected), we can acquire the lock immediately.
-  locked_frame_rect_ = LayoutRect();
   state_ = kLocked;
+  // Otherwise (if we're not connected), resolve immediately.
   return GetResolvedPromise(script_state);
 }
 
 ScriptPromise DisplayLockContext::update(ScriptState* script_state) {
   TRACE_EVENT0("blink", "DisplayLockContext::update()");
   // Reject if we're unlocked or disconnected.
-  if (state_ == kUnlocked || state_ == kPendingAcquire || !ConnectedToView()) {
+  if (state_ == kUnlocked || !ConnectedToView()) {
     return GetRejectedPromise(script_state,
                               rejection_names::kElementIsUnlocked);
   }
@@ -251,8 +270,7 @@
   // If we're in a state where a co-operative update doesn't make sense (e.g. we
   // haven't acquired the lock, or we're already sync committing), then do
   // whatever commit() would do.
-  if (state_ == kPendingAcquire || state_ == kCommitting ||
-      !ConnectedToView()) {
+  if (state_ == kCommitting || !ConnectedToView()) {
     return commit(script_state);
   }
 
@@ -314,8 +332,7 @@
 }
 
 bool DisplayLockContext::ShouldStyle(LifecycleTarget target) const {
-  return (target == kSelf && is_locked_after_connect_) || update_forced_ ||
-         state_ > kUpdating ||
+  return target == kSelf || update_forced_ || state_ > kUpdating ||
          (state_ == kUpdating &&
           update_budget_->ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
 }
@@ -327,10 +344,8 @@
     return;
   }
 
-  if (state_ != kCommitting && state_ != kUpdating &&
-      state_ != kPendingAcquire && !update_forced_) {
+  if (state_ != kCommitting && state_ != kUpdating && !update_forced_)
     return;
-  }
 
   blocked_style_traversal_type_ = kStyleUpdateNotRequired;
 
@@ -478,21 +493,24 @@
     return;
   }
 
-  // If we have just started to acquire, we can unlock immediately since we
-  // didn't have a chance to lock yet.
-  if (state_ == kPendingAcquire) {
+  // If we have an acquire resolver, it means that we haven't had a chance to
+  // run the lifecycle yet to clear the painted output. However, we're being
+  // requested to commit. So, we can commit immediately and reject the acquire
+  // callback at the same time.
+  if (acquire_resolver_) {
     FinishAcquireResolver(kReject, rejection_names::kLockCommitted);
     FinishCommitResolver(kResolve);
     CancelTimeoutTask();
     state_ = kUnlocked;
-    return;
+  } else if (state_ != kUpdating) {
+    ScheduleAnimation();
   }
 
-  if (state_ != kUpdating)
-    ScheduleAnimation();
+  // We might already be unlocked due to above, but we should still mark
+  // ancestor chains for updates below.
+  if (state_ < kCommitting)
+    state_ = kCommitting;
 
-  DCHECK_LT(state_, kCommitting);
-  state_ = kCommitting;
   update_budget_.reset();
 
   // We're committing without a budget, so ensure we can reach style.
@@ -686,27 +704,18 @@
 }
 
 void DisplayLockContext::DidFinishLifecycleUpdate(const LocalFrameView& view) {
-  if (state_ == kPendingAcquire) {
+  if (acquire_resolver_) {
     if (!ElementSupportsDisplayLocking()) {
       FinishAcquireResolver(kReject, rejection_names::kContainmentNotSatisfied);
       CancelTimeoutTask();
       state_ = kUnlocked;
       return;
     }
-
     FinishAcquireResolver(kResolve);
-    state_ = kLocked;
-    auto* layout_object = element_->GetLayoutObject();
-    // TODO(vmpstr): Note that we may be in a nested display lock, so it's
-    // unclear which frame rect to save here since we have not necessarily done
-    // a layout to acquire this lock. We need to figure out what to do here. For
-    // now, just stash whatever the current frame rect is. See crbug.com/926276.
-    if (layout_object && layout_object->IsBox()) {
-      locked_frame_rect_ = ToLayoutBox(layout_object)->FrameRect();
-    } else {
-      locked_frame_rect_ = LayoutRect();
-    }
-    return;
+    // TODO(vmpstr): When size: auto is supported, we need to get the size from
+    // the layout object here.
+    DCHECK(locked_frame_rect_);
+    // Fallthrough here in case we're already updating.
   }
 
   if (state_ == kCommitting) {
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h
index d8b7dbe..88cde991 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.h
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -55,7 +55,6 @@
     kUpdating,
     kCommitting,
     kUnlocked,
-    kPendingAcquire,
   };
 
   // The type of style that was blocked by this display lock.
@@ -141,10 +140,8 @@
   bool ShouldCommitForActivation() const;
 
   // Returns true if this lock is locked. Note from the outside perspective, the
-  // lock is locked any time the state is not kUnlocked or kPendingAcquire.
-  bool IsLocked() const {
-    return state_ != kUnlocked && state_ != kPendingAcquire;
-  }
+  // lock is locked any time the state is not kUnlocked.
+  bool IsLocked() const { return state_ != kUnlocked; }
 
   // Called when the layout tree is attached. This is used to verify
   // containment.
@@ -192,6 +189,11 @@
     needs_prepaint_subtree_walk_ = true;
   }
 
+  const LayoutRect& GetLockedFrameRect() const {
+    DCHECK(locked_frame_rect_);
+    return *locked_frame_rect_;
+  }
+
  private:
   friend class DisplayLockContextTest;
   friend class DisplayLockBudgetTest;
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
index d76b0536..560aa6f7 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
@@ -136,63 +136,6 @@
   frame_test_helpers::WebViewHelper web_view_helper_;
 };
 
-TEST_F(DisplayLockContextTest, LockBeforeAppendStyleDirtyBits) {
-  SetHtmlInnerHTML(R"HTML(
-    <style>
-    div {
-      width: 100px;
-      height: 100px;
-      contain: content;
-    }
-    </style>
-    <body></body>
-  )HTML");
-  auto* element = GetDocument().CreateRawElement(html_names::kDivTag);
-  auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
-  {
-    ScriptState::Scope scope(script_state);
-    element->getDisplayLockForBindings()->acquire(script_state, nullptr);
-  }
-  GetDocument().body()->appendChild(element);
-
-  // We immediately finish acquiring the lock.
-  EXPECT_FALSE(
-      element->GetDisplayLockContext()->ShouldStyle(DisplayLockContext::kSelf));
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldStyle(
-      DisplayLockContext::kChildren));
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldLayout());
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
-  EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
-
-  // If the element is dirty, it will stay dirty.
-  element->setAttribute("style", "color: red;");
-  EXPECT_TRUE(element->NeedsStyleRecalc());
-  EXPECT_FALSE(element->ChildNeedsStyleRecalc());
-
-  UpdateAllLifecyclePhasesForTest();
-  EXPECT_TRUE(element->NeedsStyleRecalc());
-  EXPECT_FALSE(element->GetComputedStyle());
-
-  // If we block style recalc on element when we traverse to it, we should mark
-  // it dirty appropriately later.
-  GetDocument().body()->SetNeedsStyleRecalc(
-      kSubtreeStyleChange, StyleChangeReasonForTracing::Create("test"));
-  UpdateAllLifecyclePhasesForTest();
-  EXPECT_FALSE(GetDocument().body()->ChildNeedsStyleRecalc());
-  EXPECT_TRUE(element->NeedsStyleRecalc());
-  EXPECT_EQ(element->GetStyleChangeType(), kLocalStyleChange);
-  {
-    ScriptState::Scope scope(script_state);
-    element->getDisplayLockForBindings()->commit(script_state);
-  }
-  EXPECT_TRUE(GetDocument().body()->ChildNeedsStyleRecalc());
-  EXPECT_TRUE(element->NeedsStyleRecalc());
-  EXPECT_EQ(element->GetStyleChangeType(), kSubtreeStyleChange);
-  UpdateAllLifecyclePhasesForTest();
-  EXPECT_FALSE(GetDocument().body()->ChildNeedsStyleRecalc());
-  EXPECT_FALSE(element->NeedsStyleRecalc());
-}
-
 TEST_F(DisplayLockContextTest, LockAfterAppendStyleDirtyBits) {
   SetHtmlInnerHTML(R"HTML(
     <style>
@@ -211,17 +154,6 @@
     ScriptState::Scope scope(script_state);
     element->getDisplayLockForBindings()->acquire(script_state, nullptr);
   }
-  // We should be in pending acquire state. In this mode, we're still
-  // technically not locked.
-  EXPECT_TRUE(
-      element->GetDisplayLockContext()->ShouldStyle(DisplayLockContext::kSelf));
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldStyle(
-      DisplayLockContext::kChildren));
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldLayout());
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
-  EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
-
-  UpdateAllLifecyclePhasesForTest();
 
   // Finished acquiring the lock.
   // Note that because the element is locked after append, the "self" phase for
@@ -339,17 +271,6 @@
     element->getDisplayLockForBindings()->acquire(script_state, nullptr);
   }
 
-  // We should be in pending acquire state. In this mode, we're still
-  // technically not locked.
-  EXPECT_TRUE(
-      element->GetDisplayLockContext()->ShouldStyle(DisplayLockContext::kSelf));
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldStyle(
-      DisplayLockContext::kChildren));
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldLayout());
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
-  EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
-  EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
-
   UpdateAllLifecyclePhasesForTest();
 
   // Sanity checks to ensure the element is locked.
@@ -429,16 +350,6 @@
     element->getDisplayLockForBindings()->acquire(script_state, nullptr);
   }
 
-  // We should be in pending acquire state, which means we would allow things
-  // like style and layout but disallow paint. This is still considered an
-  // unlocked state.
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldStyle(
-      DisplayLockContext::kChildren));
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldLayout());
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
-  EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
-  EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
-
   UpdateAllLifecyclePhasesForTest();
 
   // Sanity checks to ensure the element is locked.
@@ -922,16 +833,6 @@
     element->getDisplayLockForBindings()->acquire(script_state, nullptr);
   }
 
-  // We should be in pending acquire state, which means we would allow things
-  // like style and layout but disallow paint. This is sitll considered an
-  // unlocked state.
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldStyle(
-      DisplayLockContext::kChildren));
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldLayout());
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
-  EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
-  EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
-
   UpdateAllLifecyclePhasesForTest();
 
   // Sanity checks to ensure the element is locked.
@@ -1011,20 +912,16 @@
     container->getDisplayLockForBindings()->acquire(script_state, nullptr);
   }
 
-  EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
-  EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
-  EXPECT_FALSE(host->DisplayLockPreventsActivation());
-  EXPECT_FALSE(container->DisplayLockPreventsActivation());
-  EXPECT_FALSE(slotted->DisplayLockPreventsActivation());
-
-  UpdateAllLifecyclePhasesForTest();
-
   EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
   EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
   EXPECT_FALSE(host->DisplayLockPreventsActivation());
   EXPECT_TRUE(container->DisplayLockPreventsActivation());
   EXPECT_TRUE(slotted->DisplayLockPreventsActivation());
 
+  // Ensure that we resolve the acquire callback, thus finishing the acquire
+  // step.
+  UpdateAllLifecyclePhasesForTest();
+
   {
     ScriptState::Scope scope(script_state);
     container->getDisplayLockForBindings()->commit(script_state);
@@ -1074,15 +971,6 @@
     ScriptState::Scope scope(script_state);
     element->getDisplayLockForBindings()->acquire(script_state, nullptr);
   }
-  // We should be in pending acquire state, which means we would allow things
-  // like style and layout but disallow paint. This is still considered an
-  // unlocked state.
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldStyle(
-      DisplayLockContext::kChildren));
-  EXPECT_TRUE(element->GetDisplayLockContext()->ShouldLayout());
-  EXPECT_FALSE(element->GetDisplayLockContext()->ShouldPaint());
-  EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
-  EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
 
   UpdateAllLifecyclePhasesForTest();
 
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_options.idl b/third_party/blink/renderer/core/display_lock/display_lock_options.idl
index 3404d33..098d2b6 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_options.idl
+++ b/third_party/blink/renderer/core/display_lock/display_lock_options.idl
@@ -5,5 +5,6 @@
 dictionary DisplayLockOptions {
   unrestricted double timeout;
   boolean activatable = false;
+  sequence<double> size;
 };
 
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
index 98444a74..18d7bc6 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
@@ -25,6 +25,10 @@
 };
 
 TEST_F(DisplayLockUtilitiesTest, ActivatableLockedInclusiveAncestors) {
+  // TODO(vmpstr): Implement for layout ng.
+  if (RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
   SetBodyInnerHTML(R"HTML(
     <style>
       div {
diff --git a/third_party/blink/renderer/core/dom/character_data.cc b/third_party/blink/renderer/core/dom/character_data.cc
index afe071b..f0f3ada 100644
--- a/third_party/blink/renderer/core/dom/character_data.cc
+++ b/third_party/blink/renderer/core/dom/character_data.cc
@@ -34,6 +34,7 @@
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/parkable_string_manager.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 
 namespace blink {
 
@@ -102,10 +103,15 @@
     return;
   }
 
-  String new_str = this->data();
-  new_str.insert(data, offset);
+  String current_data = this->data();
+  StringBuilder new_str;
+  new_str.ReserveCapacity(data.length() + current_data.length());
+  new_str.Append(StringView(current_data, 0, offset));
+  new_str.Append(data);
+  new_str.Append(StringView(current_data, offset));
 
-  SetDataAndUpdate(new_str, offset, 0, data.length(), kUpdateFromNonParser);
+  SetDataAndUpdate(new_str.ToString(), offset, 0, data.length(),
+                   kUpdateFromNonParser);
 
   GetDocument().DidInsertText(*this, offset, data.length());
 }
@@ -143,10 +149,13 @@
                            exception_state))
     return;
 
-  String new_str = data();
-  new_str.Remove(offset, real_count);
-
-  SetDataAndUpdate(new_str, offset, real_count, 0, kUpdateFromNonParser);
+  String current_data = this->data();
+  StringBuilder new_str;
+  new_str.ReserveCapacity(current_data.length() - real_count);
+  new_str.Append(StringView(current_data, 0, offset));
+  new_str.Append(StringView(current_data, offset + real_count));
+  SetDataAndUpdate(new_str.ToString(), offset, real_count, 0,
+                   kUpdateFromNonParser);
 
   GetDocument().DidRemoveText(*this, offset, real_count);
 }
@@ -160,11 +169,14 @@
                            exception_state))
     return;
 
-  String new_str = this->data();
-  new_str.Remove(offset, real_count);
-  new_str.insert(data, offset);
+  String current_data = this->data();
+  StringBuilder new_str;
+  new_str.ReserveCapacity(data.length() + current_data.length() - real_count);
+  new_str.Append(StringView(current_data, 0, offset));
+  new_str.Append(data);
+  new_str.Append(StringView(current_data, offset + real_count));
 
-  SetDataAndUpdate(new_str, offset, real_count, data.length(),
+  SetDataAndUpdate(new_str.ToString(), offset, real_count, data.length(),
                    kUpdateFromNonParser);
 
   // update DOM ranges
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index e7c7237..52412cef 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -2959,7 +2959,7 @@
     return HTMLDocumentParser::Create(ToHTMLDocument(*this),
                                       parser_sync_policy_);
   // FIXME: this should probably pass the frame instead
-  return XMLDocumentParser::Create(*this, View());
+  return MakeGarbageCollected<XMLDocumentParser>(*this, View());
 }
 
 bool Document::IsFrameSet() const {
diff --git a/third_party/blink/renderer/core/dom/events/event.cc b/third_party/blink/renderer/core/dom/events/event.cc
index b73cc413..21f83b3 100644
--- a/third_party/blink/renderer/core/dom/events/event.cc
+++ b/third_party/blink/renderer/core/dom/events/event.cc
@@ -164,11 +164,14 @@
   if (return_value) {
     UseCounter::Count(ExecutionContext::From(script_state),
                       WebFeature::kEventSetReturnValueTrue);
+    // Don't allow already prevented events to be reset.
+    if (!defaultPrevented())
+      default_prevented_ = false;
   } else {
     UseCounter::Count(ExecutionContext::From(script_state),
                       WebFeature::kEventSetReturnValueFalse);
+    preventDefault();
   }
-  SetDefaultPrevented(!return_value);
 }
 
 const AtomicString& Event::InterfaceName() const {
diff --git a/third_party/blink/renderer/core/dom/events/event.h b/third_party/blink/renderer/core/dom/events/event.h
index bdab0df8e..bce7cf1 100644
--- a/third_party/blink/renderer/core/dom/events/event.h
+++ b/third_party/blink/renderer/core/dom/events/event.h
@@ -239,9 +239,6 @@
 
   bool defaultPrevented() const { return default_prevented_; }
   virtual void preventDefault();
-  void SetDefaultPrevented(bool default_prevented) {
-    default_prevented_ = default_prevented;
-  }
 
   bool DefaultHandled() const { return default_handled_; }
   void SetDefaultHandled() { default_handled_ = true; }
diff --git a/third_party/blink/renderer/core/editing/finder/text_finder_test.cc b/third_party/blink/renderer/core/editing/finder/text_finder_test.cc
index 9555596..99b243c 100644
--- a/third_party/blink/renderer/core/editing/finder/text_finder_test.cc
+++ b/third_party/blink/renderer/core/editing/finder/text_finder_test.cc
@@ -581,16 +581,18 @@
 
 TEST_F(TextFinderTest, ScopeWithTimeouts) {
   // Make a long string.
-  String text(Vector<UChar>(100));
-  text.Fill('a');
   String search_pattern("abc");
+  StringBuilder text;
   // Make 4 substrings "abc" in text.
-  text.insert(search_pattern, 1);
-  text.insert(search_pattern, 10);
-  text.insert(search_pattern, 50);
-  text.insert(search_pattern, 90);
+  for (int i = 0; i < 100; ++i) {
+    if (i == 1 || i == 10 || i == 50 || i == 90) {
+      text.Append(search_pattern);
+    } else {
+      text.Append('a');
+    }
+  }
 
-  GetDocument().body()->SetInnerHTMLFromString(text);
+  GetDocument().body()->SetInnerHTMLFromString(text.ToString());
   GetDocument().UpdateStyleAndLayout();
 
   int identifier = 0;
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
index c2feef60..fdc1982 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -746,6 +746,12 @@
     client->DidObserveLayoutJank(jank_fraction);
 }
 
+void LocalFrameClientImpl::DidObserveLazyLoadBehavior(
+    WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) {
+  if (WebLocalFrameClient* client = web_frame_->Client())
+    client->DidObserveLazyLoadBehavior(lazy_load_behavior);
+}
+
 bool LocalFrameClientImpl::ShouldTrackUseCounter(const KURL& url) {
   if (web_frame_->Client())
     return web_frame_->Client()->ShouldTrackUseCounter(url);
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
index 099d8d7..0419fbac 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.h
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -151,6 +151,8 @@
   void DidObserveNewFeatureUsage(mojom::WebFeature) override;
   void DidObserveNewCssPropertyUsage(int, bool) override;
   void DidObserveLayoutJank(double jank_fraction) override;
+  void DidObserveLazyLoadBehavior(
+      WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) override;
   bool ShouldTrackUseCounter(const KURL&) override;
   void SelectorMatchChanged(const Vector<String>& added_selectors,
                             const Vector<String>& removed_selectors) override;
diff --git a/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc b/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc
index 073e3ce..a2c10f0 100644
--- a/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc
+++ b/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc
@@ -184,7 +184,7 @@
     request.SetFetchCredentialsMode(
         network::mojom::FetchCredentialsMode::kOmit);
     if (EqualIgnoringASCIICase(WebString::FromUTF8(header_field), "referer")) {
-      request.SetHTTPReferrer(WebString::FromUTF8(header_value),
+      request.SetHttpReferrer(WebString::FromUTF8(header_value),
                               network::mojom::ReferrerPolicy::kDefault);
     } else {
       request.SetHttpHeaderField(WebString::FromUTF8(header_field),
diff --git a/third_party/blink/renderer/core/exported/web_frame_serializer.cc b/third_party/blink/renderer/core/exported/web_frame_serializer.cc
index a3393b4..00541dd 100644
--- a/third_party/blink/renderer/core/exported/web_frame_serializer.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_serializer.cc
@@ -494,14 +494,4 @@
   return builder.ToString();
 }
 
-WebString WebFrameSerializer::GenerateBaseTagDeclaration(
-    const WebString& base_target) {
-  // TODO(yosin) We should call |FrameSerializer::baseTagDeclarationOf()|.
-  if (base_target.IsEmpty())
-    return String("<base href=\".\">");
-  String base_string = "<base href=\".\" target=\"" +
-                       static_cast<const String&>(base_target) + "\">";
-  return base_string;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 3c8041c..f54ff82 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -9648,19 +9648,20 @@
   ScriptState::Scope entered_context_scope(script_state);
   v8::Context::BackupIncumbentScope incumbent_context_scope(
       script_state->GetContext());
-  main_window->open(
-      script_state->GetIsolate(),
-      USVStringOrTrustedURL::FromTrustedURL(TrustedURL::Create(destination)),
-      "frame1", "", exception_state);
+  main_window->open(script_state->GetIsolate(),
+                    USVStringOrTrustedURL::FromTrustedURL(
+                        MakeGarbageCollected<TrustedURL>(destination)),
+                    "frame1", "", exception_state);
   ASSERT_FALSE(remote_client.LastRequest().IsNull());
   EXPECT_EQ(remote_client.LastRequest().Url(), WebURL(KURL(destination)));
 
   // Pointing a named frame to an empty URL should just return a reference to
   // the frame's window without navigating it.
-  DOMWindow* result = main_window->open(
-      script_state->GetIsolate(),
-      USVStringOrTrustedURL::FromTrustedURL(TrustedURL::Create("")), "frame1",
-      "", exception_state);
+  DOMWindow* result =
+      main_window->open(script_state->GetIsolate(),
+                        USVStringOrTrustedURL::FromTrustedURL(
+                            MakeGarbageCollected<TrustedURL>("")),
+                        "frame1", "", exception_state);
   EXPECT_EQ(remote_client.LastRequest().Url(), WebURL(KURL(destination)));
   EXPECT_EQ(result, WebFrame::ToCoreFrame(*remote_frame)->DomWindow());
 
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
index c6fa769..23f82d77 100644
--- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -440,7 +440,7 @@
 }
 
 WorkerClients* WebSharedWorkerImpl::CreateWorkerClients() {
-  WorkerClients* worker_clients = WorkerClients::Create();
+  auto* worker_clients = MakeGarbageCollected<WorkerClients>();
   CoreInitializer::GetInstance().ProvideLocalFileSystemToWorker(
       *worker_clients);
   CoreInitializer::GetInstance().ProvideIndexedDBClientToWorker(
diff --git a/third_party/blink/renderer/core/exported/worker_shadow_page.cc b/third_party/blink/renderer/core/exported/worker_shadow_page.cc
index 9903ffc8..1f2993c 100644
--- a/third_party/blink/renderer/core/exported/worker_shadow_page.cc
+++ b/third_party/blink/renderer/core/exported/worker_shadow_page.cc
@@ -105,7 +105,7 @@
     request.SetHttpHeaderField(WebString::FromUTF8(kDoNotTrackHeader), "1");
   }
   if (!preferences_.enable_referrers) {
-    request.SetHTTPReferrer(WebString(),
+    request.SetHttpReferrer(WebString(),
                             network::mojom::ReferrerPolicy::kDefault);
   }
 }
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 46fbccf..e19ad5a 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -226,8 +226,10 @@
 }
 
 TrustedTypePolicyFactory* LocalDOMWindow::trustedTypes() const {
-  if (!trusted_types_)
-    trusted_types_ = TrustedTypePolicyFactory::Create(GetExecutionContext());
+  if (!trusted_types_) {
+    trusted_types_ =
+        MakeGarbageCollected<TrustedTypePolicyFactory>(GetExecutionContext());
+  }
   return trusted_types_.Get();
 }
 
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
index 764bcda5..0cccfe4 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -48,6 +48,7 @@
 #include "third_party/blink/public/platform/web_worker_fetch_context.h"
 #include "third_party/blink/public/web/web_frame_load_type.h"
 #include "third_party/blink/public/web/web_history_commit_type.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/public/web/web_navigation_params.h"
 #include "third_party/blink/public/web/web_triggering_event_info.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -241,6 +242,13 @@
   // Reports that visible elements in the frame shifted (bit.ly/lsm-explainer).
   virtual void DidObserveLayoutJank(double jank_fraction) {}
 
+  // Reports lazy loaded behavior when the frame or image is fully deferred or
+  // if the frame or image is loaded after being deferred. Called every time the
+  // behavior occurs. This does not apply to images that were loaded as
+  // placeholders.
+  virtual void DidObserveLazyLoadBehavior(
+      WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) {}
+
   // Will be called by a Page upon DidCommitLoad, deciding whether to track
   // UseCounter usage or not based on its url.
   virtual bool ShouldTrackUseCounter(const KURL&) { return true; }
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index ef9869a..a6f7152 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -961,11 +961,11 @@
   if (nested_layout_count_)
     return;
 
-  // TODO(crbug.com/946004): Move the following line into a DCHECK_IS_ON() block
-  // when we no longer see missing layout reports in LayoutNG.
+#if DCHECK_IS_ON()
   // Post-layout assert that nobody was re-marked as needing layout during
   // layout.
   GetLayoutView()->AssertSubtreeIsLaidOut();
+#endif
 
   if (frame_->IsMainFrame()) {
     // Scrollbars changing state can cause a visual viewport size change.
@@ -2886,9 +2886,9 @@
   // These asserts ensure that parent frames are clean, when child frames
   // finished updating layout and style.
   CheckDoesNotNeedLayout();
-  // TODO(crbug.com/946004): Move the following line into a DCHECK_IS_ON() block
-  // when we no longer see missing layout reports in LayoutNG.
+#if DCHECK_IS_ON()
   frame_->GetDocument()->GetLayoutView()->AssertLaidOut();
+#endif
 
   UpdateGeometriesIfNeeded();
 
diff --git a/third_party/blink/renderer/core/frame/local_frame_view_test.cc b/third_party/blink/renderer/core/frame/local_frame_view_test.cc
index 455d0ef..7d29ee71 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view_test.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view_test.cc
@@ -51,7 +51,7 @@
 class LocalFrameViewTest : public RenderingTest {
  protected:
   LocalFrameViewTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()),
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
         chrome_client_(MakeGarbageCollected<AnimationMockChromeClient>()) {
     EXPECT_CALL(GetAnimationMockChromeClient(), AttachRootGraphicsLayer(_, _))
         .Times(AnyNumber());
diff --git a/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc b/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
index 83d68f25..40b54ff 100644
--- a/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
@@ -98,6 +98,20 @@
 
 namespace blink {
 
+namespace {
+
+// Generate the default base tag declaration.
+String GenerateBaseTagDeclaration(const WebString& base_target) {
+  // TODO(yosin) We should call |FrameSerializer::baseTagDeclarationOf()|.
+  if (base_target.IsEmpty())
+    return String("<base href=\".\">");
+  String base_string = "<base href=\".\" target=\"" +
+                       static_cast<const String&>(base_target) + "\">";
+  return base_string;
+}
+
+}  // namespace
+
 // Maximum length of data buffer which is used to temporary save generated
 // html content data. This is a soft limit which might be passed if a very large
 // contegious string is found in the html document.
@@ -239,8 +253,7 @@
   if (IsHTMLBaseElement(*element)) {
     result.Append("-->");
     // Append a new base tag declaration.
-    result.Append(WebFrameSerializer::GenerateBaseTagDeclaration(
-        param->document->BaseTarget()));
+    result.Append(GenerateBaseTagDeclaration(param->document->BaseTarget()));
   }
 
   return result.ToString();
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 67e67d91b..ad3feab0 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -960,7 +960,7 @@
   String referrer = referrer_url.IsEmpty()
                         ? GetFrame()->GetDocument()->OutgoingReferrer()
                         : String(referrer_url.GetString());
-  request.ToMutableResourceRequest().SetHTTPReferrer(
+  request.ToMutableResourceRequest().SetHttpReferrer(
       SecurityPolicy::GenerateReferrer(
           GetFrame()->GetDocument()->GetReferrerPolicy(), request.Url(),
           referrer));
diff --git a/third_party/blink/renderer/core/html/forms/text_control_element.cc b/third_party/blink/renderer/core/html/forms/text_control_element.cc
index f71a901..d3460f0 100644
--- a/third_party/blink/renderer/core/html/forms/text_control_element.cc
+++ b/third_party/blink/renderer/core/html/forms/text_control_element.cc
@@ -292,8 +292,8 @@
   if (OpenShadowRoot())
     return;
 
-  String text = InnerEditorValue();
-  unsigned text_length = text.length();
+  String original_text = InnerEditorValue();
+  unsigned text_length = original_text.length();
   unsigned replacement_length = replacement.length();
   unsigned new_selection_start = selectionStart();
   unsigned new_selection_end = selectionEnd();
@@ -301,12 +301,12 @@
   start = std::min(start, text_length);
   end = std::min(end, text_length);
 
-  if (start < end)
-    text.replace(start, end - start, replacement);
-  else
-    text.insert(replacement, start);
+  StringBuilder text;
+  text.Append(StringView(original_text, 0, start));
+  text.Append(replacement);
+  text.Append(StringView(original_text, end));
 
-  setValue(text, TextFieldEventBehavior::kDispatchNoEvent,
+  setValue(text.ToString(), TextFieldEventBehavior::kDispatchNoEvent,
            TextControlSetValueSelection::kDoNotSet);
 
   if (selection_mode == "select") {
diff --git a/third_party/blink/renderer/core/html/html_object_element.cc b/third_party/blink/renderer/core/html/html_object_element.cc
index d7e15be..f69f7230 100644
--- a/third_party/blink/renderer/core/html/html_object_element.cc
+++ b/third_party/blink/renderer/core/html/html_object_element.cc
@@ -25,6 +25,7 @@
 #include "third_party/blink/renderer/core/html/html_object_element.h"
 
 #include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
+#include "third_party/blink/renderer/core/css/style_change_reason.h"
 #include "third_party/blink/renderer/core/dom/attribute.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/element_traversal.h"
@@ -337,8 +338,15 @@
 }
 
 void HTMLObjectElement::ReattachFallbackContent() {
-  if (!GetDocument().InStyleRecalc())
-    LazyReattachIfAttached();
+  if (!GetDocument().InStyleRecalc()) {
+    // TODO(futhark): Currently needs kSubtreeStyleChange because a style recalc
+    // for the object element does not detect the changed need for descendant
+    // style when we have a change in HTMLObjectElement::ChildrenCanHaveStyle().
+    SetNeedsStyleRecalc(
+        kSubtreeStyleChange,
+        StyleChangeReasonForTracing::Create(style_change_reason::kUseFallback));
+    SetForceReattachLayoutTree();
+  }
 }
 
 void HTMLObjectElement::RenderFallbackContent(Frame* frame) {
@@ -365,9 +373,6 @@
   }
 
   use_fallback_content_ = true;
-
-  // TODO(schenney): crbug.com/572908 Style gets recalculated which is
-  // suboptimal.
   ReattachFallbackContent();
 }
 
diff --git a/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc b/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
index 5039504e..8f10c9df 100644
--- a/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
+++ b/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
@@ -8,6 +8,7 @@
 
 #include "base/metrics/histogram_macros.h"
 #include "third_party/blink/public/platform/web_effective_connection_type.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/frame/frame.h"
@@ -167,6 +168,8 @@
             .GetFrame()
             ->Client()
             ->GetEffectiveConnectionType());
+    element_->GetDocument().GetFrame()->Client()->DidObserveLazyLoadBehavior(
+        WebLocalFrameClient::LazyLoadBehavior::kLazyLoadedFrame);
   }
 
   std::unique_ptr<LazyLoadRequestInfo> scoped_request_info =
@@ -388,8 +391,11 @@
       break;
   }
 
-  if (action == FrameInitialDeferralAction::kDeferred)
+  if (action == FrameInitialDeferralAction::kDeferred) {
+    element_->GetDocument().GetFrame()->Client()->DidObserveLazyLoadBehavior(
+        WebLocalFrameClient::LazyLoadBehavior::kDeferredFrame);
     was_recorded_as_deferred_ = true;
+  }
 }
 
 void LazyLoadFrameObserver::Trace(Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc b/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
index 3caa0ea..c1a36918 100644
--- a/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
+++ b/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
@@ -94,7 +94,7 @@
                                        UserGestureToken::kNewGesture);
   Video()->Play();
 
-  WaitForEvent::Create(Video(), event_type_names::kPlay);
+  MakeGarbageCollected<WaitForEvent>(Video(), event_type_names::kPlay);
   test::RunPendingTasks();
 
   EXPECT_TRUE(Video()->IsFullscreen());
@@ -109,7 +109,7 @@
                                        UserGestureToken::kNewGesture);
   Video()->Play();
 
-  WaitForEvent::Create(Video(), event_type_names::kPlay);
+  MakeGarbageCollected<WaitForEvent>(Video(), event_type_names::kPlay);
   test::RunPendingTasks();
 
   EXPECT_FALSE(Video()->IsFullscreen());
@@ -123,7 +123,7 @@
                                        UserGestureToken::kNewGesture);
   Video()->Play();
 
-  WaitForEvent::Create(Video(), event_type_names::kPlay);
+  MakeGarbageCollected<WaitForEvent>(Video(), event_type_names::kPlay);
   test::RunPendingTasks();
   ASSERT_TRUE(Video()->IsFullscreen());
 
@@ -144,7 +144,7 @@
                                        UserGestureToken::kNewGesture);
   Video()->Play();
 
-  WaitForEvent::Create(Video(), event_type_names::kPlay);
+  MakeGarbageCollected<WaitForEvent>(Video(), event_type_names::kPlay);
   Video()->webkitEnterFullscreen();
   test::RunPendingTasks();
   ASSERT_TRUE(Video()->IsFullscreen());
diff --git a/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc b/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
index c2661ecb..79242d5b 100644
--- a/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
+++ b/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc
@@ -118,16 +118,16 @@
     PictureInPictureController::From(GetDocument())
         .EnterPictureInPicture(Video(), nullptr);
 
-    WaitForEvent::Create(video_.Get(),
-                         event_type_names::kEnterpictureinpicture);
+    MakeGarbageCollected<WaitForEvent>(
+        video_.Get(), event_type_names::kEnterpictureinpicture);
   }
 
   void SimulateLeavePictureInPicture() {
     PictureInPictureController::From(GetDocument())
         .ExitPictureInPicture(Video(), nullptr);
 
-    WaitForEvent::Create(video_.Get(),
-                         event_type_names::kLeavepictureinpicture);
+    MakeGarbageCollected<WaitForEvent>(
+        video_.Get(), event_type_names::kLeavepictureinpicture);
   }
 
  private:
diff --git a/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc b/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc
index 864b517..2015d26 100644
--- a/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc
+++ b/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc
@@ -44,7 +44,7 @@
 class FallbackCursorEventManagerTest : public RenderingTest {
  protected:
   FallbackCursorEventManagerTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()),
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
         chrome_client_(MakeGarbageCollected<FallbackCursorChromeClient>()) {
     RuntimeEnabledFeatures::SetFallbackCursorModeEnabled(true);
   }
diff --git a/third_party/blink/renderer/core/input/keyboard_event_manager.cc b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
index d4e0e36..0a8009a 100644
--- a/third_party/blink/renderer/core/input/keyboard_event_manager.cc
+++ b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
@@ -236,7 +236,7 @@
   KeyboardEvent* keydown =
       KeyboardEvent::Create(key_down_event, frame_->GetDocument()->domWindow());
   if (matched_an_access_key)
-    keydown->SetDefaultPrevented(true);
+    keydown->preventDefault();
   keydown->SetTarget(node);
 
   keydown->SetStopPropagation(!should_send_key_events_to_js);
diff --git a/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
index 8d86d0f..710f1e5b 100644
--- a/third_party/blink/renderer/core/inspector/browser_protocol.pdl
+++ b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -4696,6 +4696,7 @@
       searchForNode
       searchForUAShadowDOM
       captureAreaScreenshot
+      showDistances
       none
 
   # Disables domain notifications.
diff --git a/third_party/blink/renderer/core/inspector/dom_patch_support.cc b/third_party/blink/renderer/core/inspector/dom_patch_support.cc
index 2c51503b..32ed885 100644
--- a/third_party/blink/renderer/core/inspector/dom_patch_support.cc
+++ b/third_party/blink/renderer/core/inspector/dom_patch_support.cc
@@ -76,7 +76,8 @@
   DCHECK(new_document);
   new_document->SetContextFeatures(GetDocument().GetContextFeatures());
   if (!GetDocument().IsHTMLDocument()) {
-    DocumentParser* parser = XMLDocumentParser::Create(*new_document, nullptr);
+    DocumentParser* parser =
+        MakeGarbageCollected<XMLDocumentParser>(*new_document, nullptr);
     parser->Append(markup);
     parser->Finish();
     parser->Detach();
diff --git a/third_party/blink/renderer/core/inspector/inspect_tool_distances.html b/third_party/blink/renderer/core/inspector/inspect_tool_distances.html
new file mode 100644
index 0000000..f7d65c4
--- /dev/null
+++ b/third_party/blink/renderer/core/inspector/inspect_tool_distances.html
@@ -0,0 +1,97 @@
+<!--
+ Copyright 2019 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.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+
+/**
+ * @param {!Object} data
+ */
+function drawDistances(data)
+{
+  const rect = quadToRect(getVisualQuad(data));
+  const context = window.context;
+  context.save();
+  context.strokeStyle = '#f00';
+  context.lineWidth = 1;
+  context.rect(rect.x - 0.5, rect.y - 0.5, rect.w + 1, rect.h + 1);
+  context.stroke();
+  context.restore();
+}
+
+/**
+ * @param {!Object} data
+ * @return {!Array<number>}
+ */
+function getVisualQuad(data) {
+  const style = data['style'];
+  if (shouldUseVisualBorder(style))
+    return data['border'];
+  else if (ShouldUseVisualPadding(style))
+    return data['padding'];
+  return data['content'];
+
+  /**
+   * @param {!Object} style
+   * @return {boolean}
+   */
+  function shouldUseVisualBorder(style) {
+    const sides = ['top', 'right', 'bottom', 'left'];
+    for (const side of sides) {
+      const border_width = style[`border-${side}-width`];
+      const border_style = style[`border-${side}-style`];
+      const border_color = style[`border-${side}-color`];
+      if (border_width != '0px' && border_style != 'none' &&
+          !border_color.endsWith('00'))
+        return true;
+    }
+    const outline_width = style['outline-width'];
+    const outline_style = style['outline-style'];
+    const outline_color = style['outline-color'];
+    if (outline_width != '0px' && outline_style != 'none' &&
+        !outline_color.endsWith('00'))
+      return true;
+    const box_shadow = style['box-shadow'];
+    if (box_shadow != 'none')
+      return true;
+    return false;
+  }
+
+  /**
+   * @param {!Object} style
+   * @return {boolean}
+   */
+  function ShouldUseVisualPadding(style) {
+    const bg_color = style['background-color'];
+    const bg_image = style['background-image'];
+    if (!bg_color.startsWith('#FFFFFF') && !bg_color.endsWith('00'))
+      return true;
+    if (bg_image != 'none')
+      return true;
+    return false;
+  }
+}
+
+/**
+ * @param {!Array<number>} quad
+ * @return {!Object}
+ */
+function quadToRect(quad) {
+  return {
+    x: quad[0],
+    y: quad[1],
+    w: quad[4] - quad[0],
+    h: quad[5] - quad[1]
+  }
+}
+
+</script>
+</head>
+<body class="fill">
+  <canvas id="canvas" class="fill"></canvas>
+</body>
+</html>
diff --git a/third_party/blink/renderer/core/inspector/inspect_tools.cc b/third_party/blink/renderer/core/inspector/inspect_tools.cc
index 756e438..e8320b2 100644
--- a/third_party/blink/renderer/core/inspector/inspect_tools.cc
+++ b/third_party/blink/renderer/core/inspector/inspect_tools.cc
@@ -9,6 +9,8 @@
 #include "third_party/blink/public/platform/web_input_event_result.h"
 #include "third_party/blink/public/platform/web_keyboard_event.h"
 #include "third_party/blink/public/platform/web_pointer_event.h"
+#include "third_party/blink/renderer/core/css/css_color_value.h"
+#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/dom/static_node_list.h"
@@ -318,6 +320,95 @@
   visitor->Trace(node_);
 }
 
+// NearbyDistanceTool ----------------------------------------------------------
+
+CString NearbyDistanceTool::GetDataResourceName() {
+  return "inspect_tool_distances.html";
+}
+
+bool NearbyDistanceTool::HandleMouseDown(const WebMouseEvent& event,
+                                         bool* swallow_next_mouse_up) {
+  return true;
+}
+
+bool NearbyDistanceTool::HandleMouseMove(const WebMouseEvent& event) {
+  Node* node = HoveredNodeForEvent(overlay_->GetFrame(), event, true);
+
+  // Do not highlight within user agent shadow root
+  ShadowRoot* shadow_root = InspectorDOMAgent::UserAgentShadowRoot(node);
+  if (shadow_root)
+    node = &shadow_root->host();
+
+  // Shadow roots don't have boxes - use host element instead.
+  if (node && node->IsShadowRoot())
+    node = node->ParentOrShadowHostNode();
+
+  if (!node)
+    return true;
+
+  if (auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node)) {
+    if (!IsA<LocalFrame>(frame_owner->ContentFrame())) {
+      // Do not consume event so that remote frame can handle it.
+      overlay_->hideHighlight();
+      hovered_node_.Clear();
+      return false;
+    }
+  }
+
+  // Store values for the highlight.
+  hovered_node_ = node;
+  return true;
+}
+
+bool NearbyDistanceTool::HandleMouseUp(const WebMouseEvent& event) {
+  return true;
+}
+
+void NearbyDistanceTool::Draw(float scale) {
+  Node* node = hovered_node_.Get();
+  if (!node)
+    return;
+  node->GetDocument().EnsurePaintLocationDataValidForNode(node);
+  LayoutObject* layout_object = node->GetLayoutObject();
+  if (!layout_object)
+    return;
+
+  CSSStyleDeclaration* style =
+      MakeGarbageCollected<CSSComputedStyleDeclaration>(node, true);
+  std::unique_ptr<protocol::DictionaryValue> computed_style =
+      protocol::DictionaryValue::create();
+  for (size_t i = 0; i < style->length(); ++i) {
+    AtomicString name(style->item(i));
+    const CSSValue* value = style->GetPropertyCSSValueInternal(name);
+    if (!value)
+      continue;
+    if (value->IsColorValue()) {
+      Color color = static_cast<const cssvalue::CSSColorValue*>(value)->Value();
+      String hex_color =
+          String::Format("#%02X%02X%02X%02X", color.Red(), color.Green(),
+                         color.Blue(), color.Alpha());
+      computed_style->setString(name, hex_color);
+    } else {
+      computed_style->setString(name, value->CssText());
+    }
+  }
+
+  std::unique_ptr<protocol::DOM::BoxModel> model;
+  InspectorHighlight::GetBoxModel(node, &model);
+  std::unique_ptr<protocol::DictionaryValue> object =
+      protocol::DictionaryValue::create();
+  object->setArray("content", model->getContent()->toValue());
+  object->setArray("padding", model->getPadding()->toValue());
+  object->setArray("border", model->getBorder()->toValue());
+  object->setObject("style", std::move(computed_style));
+  overlay_->EvaluateInOverlay("drawDistances", std::move(object));
+}
+
+void NearbyDistanceTool::Trace(blink::Visitor* visitor) {
+  InspectTool::Trace(visitor);
+  visitor->Trace(hovered_node_);
+}
+
 // ShowViewSizeTool ------------------------------------------------------------
 
 void ShowViewSizeTool::Draw(float scale) {
diff --git a/third_party/blink/renderer/core/inspector/inspect_tools.h b/third_party/blink/renderer/core/inspector/inspect_tools.h
index 1b5b8be..1a5aab9 100644
--- a/third_party/blink/renderer/core/inspector/inspect_tools.h
+++ b/third_party/blink/renderer/core/inspector/inspect_tools.h
@@ -88,6 +88,25 @@
 
 // -----------------------------------------------------------------------------
 
+class NearbyDistanceTool : public InspectTool {
+ public:
+  NearbyDistanceTool() = default;
+
+ private:
+  CString GetDataResourceName() override;
+  bool HandleMouseDown(const WebMouseEvent& event,
+                       bool* swallow_next_mouse_up) override;
+  bool HandleMouseMove(const WebMouseEvent& event) override;
+  bool HandleMouseUp(const WebMouseEvent& event) override;
+  void Draw(float scale) override;
+  void Trace(blink::Visitor* visitor) override;
+
+  Member<Node> hovered_node_;
+  DISALLOW_COPY_AND_ASSIGN(NearbyDistanceTool);
+};
+
+// -----------------------------------------------------------------------------
+
 class ShowViewSizeTool : public InspectTool {
  public:
   ShowViewSizeTool() = default;
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
index b5cdaf89..34c0572 100644
--- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -860,7 +860,7 @@
       // seems to require storing the referrer info that is currently stored
       // inside state_'s kExtraRequestHeaders, somewhere else.
       if (header_name.LowerASCII() == http_names::kReferer.LowerASCII()) {
-        request.SetHTTPReferrer(
+        request.SetHttpReferrer(
             Referrer(value, network::mojom::ReferrerPolicy::kAlways));
       } else {
         request.SetHttpHeaderField(header_name, AtomicString(value));
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
index cb84c02..ed1b4c5e 100644
--- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -239,13 +239,12 @@
       return;
     DrawingRecorder recorder(graphics_context, frame_overlay,
                              DisplayItem::kFrameOverlay);
-    LocalFrameView* view = overlay_->OverlayMainFrame()->View();
     // The overlay frame is has a standalone paint property tree. Paint it in
     // its root space into a paint record, then draw the record into the proper
     // target space in the overlaid frame.
     PaintRecordBuilder paint_record_builder(nullptr, &graphics_context);
-    view->PaintOutsideOfLifecycle(paint_record_builder.Context(),
-                                  kGlobalPaintNormalPhase);
+    overlay_->OverlayMainFrame()->View()->PaintOutsideOfLifecycle(
+        paint_record_builder.Context(), kGlobalPaintNormalPhase);
     graphics_context.DrawRecord(paint_record_builder.EndRecording());
   }
 
@@ -317,12 +316,11 @@
     : frame_impl_(frame_impl),
       inspected_frames_(inspected_frames),
       resize_timer_active_(false),
-      timer_(
+      resize_timer_(
           frame_impl->GetFrame()->GetTaskRunner(TaskType::kInternalInspector),
           this,
-          &InspectorOverlayAgent::OnTimer),
+          &InspectorOverlayAgent::OnResizeTimer),
       disposed_(false),
-      needs_update_(false),
       v8_session_(v8_session),
       dom_agent_(dom_agent),
       swallow_next_mouse_up_(false),
@@ -405,7 +403,8 @@
     overlay_host_->ClearListener();
     overlay_host_.Clear();
   }
-  timer_.Stop();
+  resize_timer_.Stop();
+  resize_timer_active_ = false;
   frame_overlay_.reset();
   frame_resource_name_ = CString();
   PickTheRightTool();
@@ -610,27 +609,9 @@
   return Response::OK();
 }
 
-void InspectorOverlayAgent::UpdateOverlayPage() {
-  if (!inspect_tool_)
-    return;
-
-  if (needs_update_) {
-    needs_update_ = false;
-    RebuildOverlayPage();
-  }
-  OverlayMainFrame()->View()->UpdateAllLifecyclePhases(
-      DocumentLifecycle::LifecycleUpdateReason::kOther);
-}
-
 void InspectorOverlayAgent::UpdatePrePaint() {
-  if (!inspect_tool_)
-    return;
-
-  if (!frame_overlay_) {
-    frame_overlay_ = std::make_unique<FrameOverlay>(
-        GetFrame(), std::make_unique<InspectorPageOverlayDelegate>(*this));
-  }
-  frame_overlay_->UpdatePrePaint();
+  if (frame_overlay_)
+    frame_overlay_->UpdatePrePaint();
 }
 
 void InspectorOverlayAgent::PaintOverlay(GraphicsContext& context) {
@@ -677,7 +658,9 @@
     }
   }
 
-  if (!inspect_tool_)
+  LocalFrame* frame = GetFrame();
+  if (!frame || !frame->View() || !frame->ContentLayoutObject() ||
+      !inspect_tool_)
     return WebInputEventResult::kNotHandled;
 
   bool handled = inspect_tool_->HandleInputEvent(
@@ -763,34 +746,28 @@
 }
 
 void InspectorOverlayAgent::ScheduleUpdate() {
-  auto& client = GetFrame()->GetPage()->GetChromeClient();
-  if (!inspect_tool_) {
-    if (frame_overlay_) {
-      frame_overlay_.reset();
-      client.SetCursorOverridden(false);
-      client.SetCursor(PointerCursor(), GetFrame());
-      if (auto* frame_view = frame_impl_->GetFrameView())
-        frame_view->SetPaintArtifactCompositorNeedsUpdate();
-    }
-    return;
-  }
-  needs_update_ = true;
-  client.ScheduleAnimation(GetFrame()->View());
+  GetFrame()->GetPage()->GetChromeClient().ScheduleAnimation(
+      GetFrame()->View());
 }
 
-void InspectorOverlayAgent::RebuildOverlayPage() {
+bool InspectorOverlayAgent::UpdateOverlayPageSize() {
   LocalFrameView* view = frame_impl_->GetFrameView();
   LocalFrame* frame = GetFrame();
   if (!view || !frame)
-    return;
+    return false;
 
   IntSize viewport_size = frame->GetPage()->GetVisualViewport().Size();
   OverlayPage()->GetVisualViewport().SetSize(viewport_size);
-  UpdateFrameForTool();
+  return true;
+}
 
-  Reset(viewport_size);
+void InspectorOverlayAgent::UpdateOverlayPage() {
+  if (!UpdateOverlayPageSize())
+    return;
   if (inspect_tool_)
     inspect_tool_->Draw(WindowToViewportScale());
+  OverlayMainFrame()->View()->UpdateAllLifecyclePhases(
+      DocumentLifecycle::LifecycleUpdateReason::kOther);
 }
 
 static std::unique_ptr<protocol::DictionaryValue> BuildObjectForSize(
@@ -866,8 +843,9 @@
   if (resource_name == frame_resource_name_) {
     if (overlay_page_) {
       OverlayMainFrame()->SetPageZoomFactor(WindowToViewportScale());
-      OverlayMainFrame()->View()->Resize(
-          OverlayPage()->GetVisualViewport().Size());
+      IntSize viewport_size = OverlayPage()->GetVisualViewport().Size();
+      OverlayMainFrame()->View()->Resize(viewport_size);
+      Reset(viewport_size);
     }
     return;
   }
@@ -888,7 +866,8 @@
   frame->View()->SetBaseBackgroundColor(Color::kTransparent);
 
   frame->SetPageZoomFactor(WindowToViewportScale());
-  frame->View()->Resize(OverlayPage()->GetVisualViewport().Size());
+  IntSize viewport_size = OverlayPage()->GetVisualViewport().Size();
+  frame->View()->Resize(viewport_size);
 
   scoped_refptr<SharedBuffer> data = SharedBuffer::Create();
   data->Append("<style>", static_cast<size_t>(7));
@@ -921,6 +900,7 @@
 #elif defined(OS_POSIX)
   EvaluateInOverlay("setPlatform", "linux");
 #endif
+  Reset(viewport_size);
 }
 
 LocalFrame* InspectorOverlayAgent::OverlayMainFrame() {
@@ -997,9 +977,18 @@
   return ToCoreStringWithUndefinedOrNullCheck(string);
 }
 
-void InspectorOverlayAgent::OnTimer(TimerBase*) {
-  resize_timer_active_ = false;
-  PickTheRightTool();
+void InspectorOverlayAgent::OnResizeTimer(TimerBase*) {
+  if (resize_timer_active_) {
+    // Restore the original tool.
+    PickTheRightTool();
+    return;
+  }
+
+  // Show the resize tool.
+  SetInspectTool(MakeGarbageCollected<ShowViewSizeTool>());
+  resize_timer_active_ = true;
+  resize_timer_.Stop();
+  resize_timer_.StartOneShot(TimeDelta::FromSeconds(1), FROM_HERE);
 }
 
 void InspectorOverlayAgent::OverlayResumed() {
@@ -1014,9 +1003,12 @@
 
 void InspectorOverlayAgent::PageLayoutInvalidated(bool resized) {
   if (resized && show_size_on_resize_.Get()) {
-    resize_timer_active_ = true;
-    timer_.StartOneShot(TimeDelta::FromSeconds(1), FROM_HERE);
-    SetInspectTool(MakeGarbageCollected<ShowViewSizeTool>());
+    resize_timer_active_ = false;
+    // Handle the resize in the next cycle to decouple overlay page rebuild from
+    // the main page layout to avoid document lifecycle issues caused by
+    // Microtask::PerformCheckpoint() called when we rebuild the overlay page.
+    resize_timer_.Stop();
+    resize_timer_.StartOneShot(TimeDelta::FromSeconds(0), FROM_HERE);
     return;
   }
   ScheduleUpdate();
@@ -1062,7 +1054,8 @@
   if (mode != protocol::Overlay::InspectModeEnum::None &&
       mode != protocol::Overlay::InspectModeEnum::SearchForNode &&
       mode != protocol::Overlay::InspectModeEnum::SearchForUAShadowDOM &&
-      mode != protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot) {
+      mode != protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot &&
+      mode != protocol::Overlay::InspectModeEnum::ShowDistances) {
     return Response::Error(
         String("Unknown mode \"" + mode + "\" was provided."));
   }
@@ -1098,6 +1091,9 @@
   } else if (inspect_mode ==
              protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot) {
     inspect_tool = MakeGarbageCollected<ScreenshotTool>();
+  } else if (inspect_mode ==
+             protocol::Overlay::InspectModeEnum::ShowDistances) {
+    inspect_tool = MakeGarbageCollected<NearbyDistanceTool>();
   } else if (!paused_in_debugger_message_.Get().IsNull()) {
     inspect_tool = MakeGarbageCollected<PausedInDebuggerTool>(
         paused_in_debugger_message_.Get());
@@ -1109,8 +1105,23 @@
   if (inspect_tool_)
     inspect_tool_->Dispose();
   inspect_tool_ = inspect_tool;
-  if (inspect_tool_)
+  if (inspect_tool_) {
     inspect_tool_->Init(this, GetFrontend());
+    if (UpdateOverlayPageSize()) {
+      if (!frame_overlay_) {
+        frame_overlay_ = std::make_unique<FrameOverlay>(
+            GetFrame(), std::make_unique<InspectorPageOverlayDelegate>(*this));
+      }
+      UpdateFrameForTool();
+    }
+  } else if (frame_overlay_) {
+    frame_overlay_.reset();
+    auto& client = GetFrame()->GetPage()->GetChromeClient();
+    client.SetCursorOverridden(false);
+    client.SetCursor(PointerCursor(), GetFrame());
+    if (auto* frame_view = frame_impl_->GetFrameView())
+      frame_view->SetPaintArtifactCompositorNeedsUpdate();
+  }
   ScheduleUpdate();
 }
 
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
index f2c68a3f..9cad199 100644
--- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
+++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
@@ -196,9 +196,9 @@
   Page* OverlayPage();
   LocalFrame* OverlayMainFrame();
   void Reset(const IntSize& viewport_size);
-  void OnTimer(TimerBase*);
+  void OnResizeTimer(TimerBase*);
+  bool UpdateOverlayPageSize();
   void UpdateOverlayPage();
-  void RebuildOverlayPage();
 
   protocol::Response CompositingEnabled();
 
@@ -220,9 +220,8 @@
   Member<InspectorOverlayChromeClient> overlay_chrome_client_;
   Member<InspectorOverlayHost> overlay_host_;
   bool resize_timer_active_;
-  TaskRunnerTimer<InspectorOverlayAgent> timer_;
+  TaskRunnerTimer<InspectorOverlayAgent> resize_timer_;
   bool disposed_;
-  bool needs_update_;
   v8_inspector::V8InspectorSession* v8_session_;
   Member<InspectorDOMAgent> dom_agent_;
   std::unique_ptr<FrameOverlay> frame_overlay_;
diff --git a/third_party/blink/renderer/core/inspector/main_thread_debugger.cc b/third_party/blink/renderer/core/inspector/main_thread_debugger.cc
index 8eb3c101..8ab12c5 100644
--- a/third_party/blink/renderer/core/inspector/main_thread_debugger.cc
+++ b/third_party/blink/renderer/core/inspector/main_thread_debugger.cc
@@ -358,8 +358,9 @@
   ExecutionContext* execution_context = ToExecutionContext(context);
   DCHECK(execution_context);
   DCHECK(execution_context->IsDocument());
-  return ToV8(MemoryInfo::Create(MemoryInfo::Precision::Bucketized),
-              context->Global(), isolate);
+  return ToV8(
+      MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Bucketized),
+      context->Global(), isolate);
 }
 
 void MainThreadDebugger::installAdditionalCommandLineAPI(
diff --git a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc
index e4724bf2..38f3e6e 100644
--- a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc
+++ b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc
@@ -39,7 +39,7 @@
   String global_scope_name =
       StringView("LayoutWorklet #") + String::Number(global_scope_number);
 
-  WorkerClients* worker_clients = WorkerClients::Create();
+  auto* worker_clients = MakeGarbageCollected<WorkerClients>();
   ProvideContentSettingsClientToWorker(
       worker_clients, frame->Client()->CreateWorkerContentSettingsClient());
 
diff --git a/third_party/blink/renderer/core/layout/force_legacy_layout_test.cc b/third_party/blink/renderer/core/layout/force_legacy_layout_test.cc
index 3725224..e4c5ff1 100644
--- a/third_party/blink/renderer/core/layout/force_legacy_layout_test.cc
+++ b/third_party/blink/renderer/core/layout/force_legacy_layout_test.cc
@@ -25,7 +25,7 @@
 class ForceLegacyLayoutTest : public RenderingTest {
  public:
   ForceLegacyLayoutTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 };
 
 TEST_F(ForceLegacyLayoutTest, ForceLegacyBfcRecalcAncestorStyle) {
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc
index cdac8554..66ebd6d 100644
--- a/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -442,8 +442,12 @@
   if (auto* context = GetDisplayLockContext()) {
     // In a display locked element, we might be prevented from doing layout in
     // which case we should abort.
-    if (LayoutBlockedByDisplayLock())
+    if (LayoutBlockedByDisplayLock()) {
+      // TODO(vmpstr): This is probably wrong, we need to do full self-layout
+      // here, but for now just update our frame rect.
+      SetFrameRect(context->GetLockedFrameRect());
       return;
+    }
     // If we're display locked, then our layout should go into a pending frame
     // rect without updating the frame rect visible to the ancestors. The
     // following scoped object provides this functionality: it puts in place the
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 6901571f..c97c2df 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -392,11 +392,6 @@
     LayoutObject& layout_object_;
     bool preexisting_forbidden_;
   };
-#endif  // DCHECK_IS_ON()
-
-  // TODO(crbug.com/946004): When we no longer see missing layouts in LayoutNG,
-  // move the following two functions back to the DCHECK_IS_ON() block and
-  // remove relevant branches and CHECK.
 
   void AssertLaidOut() const {
 #ifndef NDEBUG
@@ -404,16 +399,9 @@
       ShowLayoutTreeForThis();
 #endif
     SECURITY_DCHECK(!NeedsLayout() || LayoutBlockedByDisplayLock());
-    if (!RuntimeEnabledFeatures::LayoutNGEnabled())
-      return;
-    CHECK(!NeedsLayout() || LayoutBlockedByDisplayLock()) << this;
   }
 
   void AssertSubtreeIsLaidOut() const {
-#if !DCHECK_IS_ON()
-    if (!RuntimeEnabledFeatures::LayoutNGEnabled())
-      return;
-#endif
     for (const LayoutObject* layout_object = this; layout_object;
          layout_object = layout_object->LayoutBlockedByDisplayLock()
                              ? layout_object->NextInPreOrderAfterChildren()
@@ -422,7 +410,6 @@
     }
   }
 
-#if DCHECK_IS_ON()
   void AssertClearedPaintInvalidationFlags() const {
 #ifndef NDEBUG
     if (PaintInvalidationStateIsDirty() && !PrePaintBlockedByDisplayLock()) {
@@ -441,7 +428,7 @@
     }
   }
 
-#endif  // DCHECK_IS_ON()
+#endif
 
   // LayoutObject tree manipulation
   //////////////////////////////////////////
diff --git a/third_party/blink/renderer/core/layout/layout_view_test.cc b/third_party/blink/renderer/core/layout/layout_view_test.cc
index 6e8a9fd4..bf63a66 100644
--- a/third_party/blink/renderer/core/layout/layout_view_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_view_test.cc
@@ -12,7 +12,8 @@
 
 class LayoutViewTest : public RenderingTest {
  public:
-  LayoutViewTest() : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+  LayoutViewTest()
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 };
 
 TEST_F(LayoutViewTest, UpdateCountersLayout) {
diff --git a/third_party/blink/renderer/core/layout/map_coordinates_test.cc b/third_party/blink/renderer/core/layout/map_coordinates_test.cc
index a4fad37..0e34e5c 100644
--- a/third_party/blink/renderer/core/layout/map_coordinates_test.cc
+++ b/third_party/blink/renderer/core/layout/map_coordinates_test.cc
@@ -13,7 +13,8 @@
 
 class MapCoordinatesTest : public RenderingTest {
  public:
-  MapCoordinatesTest() : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+  MapCoordinatesTest()
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
   FloatPoint MapLocalToAncestor(const LayoutObject*,
                                 const LayoutBoxModelObject* ancestor,
                                 FloatPoint,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
index 9fa36e0..2d37e38 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -9,6 +9,7 @@
 
 #include "third_party/blink/renderer/core/layout/layout_block_flow.h"
 #include "third_party/blink/renderer/core/layout/layout_inline.h"
+#include "third_party/blink/renderer/core/layout/layout_list_marker.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/layout_text.h"
 #include "third_party/blink/renderer/core/layout/logical_values.h"
@@ -644,11 +645,24 @@
       continue;
     }
 
-    const Font& font = start_item.Style()->GetFont();
+    const ComputedStyle& start_style = *start_item.Style();
+    const Font& font = start_style.GetFont();
     TextDirection direction = start_item.Direction();
     unsigned end_index = index + 1;
     unsigned end_offset = start_item.EndOffset();
 
+    // Symbol marker is painted as graphics. Create a ShapeResult of space
+    // glyphs with the desired size to make it less special for line breaker.
+    if (UNLIKELY(start_item.IsSymbolMarker())) {
+      LayoutUnit symbol_width = LayoutListMarker::WidthOfSymbol(start_style);
+      DCHECK_GT(symbol_width, 0);
+      start_item.shape_result_ = ShapeResult::CreateForSpaces(
+          &font, direction, start_item.StartOffset(), start_item.Length(),
+          symbol_width);
+      index++;
+      continue;
+    }
+
     // Scan forward until an item is encountered that should trigger a shaping
     // break. This ensures that adjacent text items are shaped together whenever
     // possible as this is required for accurate cross-element shaping.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
index 1853628..6de9217 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -4,7 +4,6 @@
 
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h"
 
-#include "third_party/blink/renderer/core/layout/layout_list_marker.h"
 #include "third_party/blink/renderer/core/layout/logical_values.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h"
@@ -489,12 +488,6 @@
     BreakText(item_result, item, shape_result, available_width - position_,
               line_info);
 
-    if (item.IsSymbolMarker()) {
-      LayoutUnit symbol_width = LayoutListMarker::WidthOfSymbol(*item.Style());
-      if (symbol_width > 0)
-        item_result->inline_size = symbol_width;
-    }
-
     LayoutUnit next_position = position_ + item_result->inline_size;
     bool is_overflow = next_position > available_width;
     DCHECK(is_overflow || item_result->shape_result);
@@ -525,12 +518,6 @@
   item_result->inline_size = shape_result.SnappedWidth().ClampNegativeToZero();
   item_result->shape_result = ShapeResultView::Create(&shape_result);
 
-  if (item.IsSymbolMarker()) {
-    LayoutUnit symbol_width = LayoutListMarker::WidthOfSymbol(*item.Style());
-    if (symbol_width > 0)
-      item_result->inline_size = symbol_width;
-  }
-
   DCHECK(!item_result->may_break_inside);
   DCHECK(!item_result->can_break_after);
   trailing_whitespace_ = WhitespaceState::kUnknown;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
index 154213ec..fd522374 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
@@ -449,10 +449,6 @@
         other.bitfields_.percentage_block_storage)
       return false;
 
-    if (bitfields_.replaced_percentage_inline_storage !=
-        other.bitfields_.replaced_percentage_inline_storage)
-      return false;
-
     if (bitfields_.replaced_percentage_block_storage !=
         other.bitfields_.replaced_percentage_block_storage)
       return false;
@@ -567,7 +563,6 @@
           flags(kFixedSizeBlockIsDefinite),
           percentage_inline_storage(kSameAsAvailable),
           percentage_block_storage(kSameAsAvailable),
-          replaced_percentage_inline_storage(kSameAsAvailable),
           replaced_percentage_block_storage(kSameAsAvailable) {}
 
     bool MaySkipLayout(const Bitfields& other) const {
@@ -587,7 +582,6 @@
 
     unsigned percentage_inline_storage : 2;           // NGPercentageStorage
     unsigned percentage_block_storage : 2;            // NGPercentageStorage
-    unsigned replaced_percentage_inline_storage : 2;  // NGPercentageStorage
     unsigned replaced_percentage_block_storage : 2;   // NGPercentageStorage
   };
 
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc
index d26dfb9..0e1e53ab 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc
@@ -11,7 +11,7 @@
 class LayoutSVGForeignObjectTest : public RenderingTest {
  public:
   LayoutSVGForeignObjectTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 };
 
 TEST_F(LayoutSVGForeignObjectTest, DivInForeignObject) {
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text_test.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_text_test.cc
index 150e6ff..e295cb8 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_text_test.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text_test.cc
@@ -10,7 +10,8 @@
 
 class LayoutSVGTextTest : public RenderingTest {
  public:
-  LayoutSVGTextTest() : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+  LayoutSVGTextTest()
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 };
 
 TEST_F(LayoutSVGTextTest, RectBasedHitTest) {
diff --git a/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc b/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc
index d9fdc6244..77ece29a 100644
--- a/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc
+++ b/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc
@@ -18,7 +18,7 @@
                               public RenderingTest {
  public:
   VisualRectMappingTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
  protected:
   LayoutView& GetLayoutView() const { return *GetDocument().GetLayoutView(); }
diff --git a/third_party/blink/renderer/core/loader/BUILD.gn b/third_party/blink/renderer/core/loader/BUILD.gn
index fd19304..2bd8b4c 100644
--- a/third_party/blink/renderer/core/loader/BUILD.gn
+++ b/third_party/blink/renderer/core/loader/BUILD.gn
@@ -123,6 +123,10 @@
     "resource/text_resource.h",
     "resource/xsl_style_sheet_resource.cc",
     "resource/xsl_style_sheet_resource.h",
+    "resource_load_observer_for_frame.cc",
+    "resource_load_observer_for_frame.h",
+    "resource_load_observer_for_worker.cc",
+    "resource_load_observer_for_worker.h",
     "scheduled_navigation.cc",
     "scheduled_navigation.h",
     "subresource_filter.cc",
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.cc b/third_party/blink/renderer/core/loader/base_fetch_context.cc
index 87c488a..23310e60 100644
--- a/third_party/blink/renderer/core/loader/base_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -115,7 +115,7 @@
       GetResourceFetcherProperties().GetFetchClientSettingsObject();
   // TODO(domfarolino): we can probably *just set* the HTTP `Referer` here
   // no matter what now.
-  if (!request.DidSetHTTPReferrer()) {
+  if (!request.DidSetHttpReferrer()) {
     String referrer_to_use = request.ReferrerString();
     network::mojom::ReferrerPolicy referrer_policy_to_use =
         request.GetReferrerPolicy();
@@ -129,7 +129,7 @@
 
     // TODO(domfarolino): Stop storing ResourceRequest's referrer as a header
     // and store it elsewhere. See https://crbug.com/850813.
-    request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
+    request.SetHttpReferrer(SecurityPolicy::GenerateReferrer(
         referrer_policy_to_use, request.Url(), referrer_to_use));
   } else {
     CHECK_EQ(
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 4f59b58..1b39f4d 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -79,8 +79,7 @@
 #include "third_party/blink/renderer/core/loader/interactive_detector.h"
 #include "third_party/blink/renderer/core/loader/loader_factory_for_frame.h"
 #include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
-#include "third_party/blink/renderer/core/loader/ping_loader.h"
-#include "third_party/blink/renderer/core/loader/progress_tracker.h"
+#include "third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h"
 #include "third_party/blink/renderer/core/loader/subresource_filter.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
@@ -233,6 +232,9 @@
   init.frame_scheduler = frame.GetFrameScheduler();
   init.archive = loader.Archive();
   ResourceFetcher* fetcher = MakeGarbageCollected<ResourceFetcher>(init);
+  fetcher->SetResourceLoadObserver(
+      MakeGarbageCollected<ResourceLoadObserverForFrame>(
+          *frame_or_imported_document, fetcher->GetProperties()));
   fetcher->SetImagesEnabled(frame.GetSettings()->GetImagesEnabled());
   fetcher->SetAutoLoadImages(
       frame.GetSettings()->GetLoadsImagesAutomatically());
@@ -255,7 +257,11 @@
       MakeGarbageCollected<LoaderFactoryForFrame>(frame_or_imported_document),
       *document);
   init.frame_scheduler = frame.GetFrameScheduler();
-  return MakeGarbageCollected<ResourceFetcher>(init);
+  auto* fetcher = MakeGarbageCollected<ResourceFetcher>(init);
+  fetcher->SetResourceLoadObserver(
+      MakeGarbageCollected<ResourceLoadObserverForFrame>(
+          frame_or_imported_document, fetcher->GetProperties()));
+  return fetcher;
 }
 
 FrameFetchContext::FrameFetchContext(
@@ -435,182 +441,6 @@
   }
 }
 
-void FrameFetchContext::DispatchWillSendRequest(
-    uint64_t identifier,
-    const ResourceRequest& request,
-    const ResourceResponse& redirect_response,
-    ResourceType resource_type,
-    const FetchInitiatorInfo& initiator_info) {
-  if (GetResourceFetcherProperties().IsDetached())
-    return;
-
-  if (redirect_response.IsNull()) {
-    // Progress doesn't care about redirects, only notify it when an
-    // initial request is sent.
-    GetFrame()->Loader().Progress().WillStartLoading(identifier,
-                                                     request.Priority());
-  }
-  probe::WillSendRequest(Probe(), identifier, MasterDocumentLoader(), Url(),
-                         request, redirect_response, initiator_info,
-                         resource_type);
-  Document& document = frame_or_imported_document_->GetDocument();
-  if (auto* idleness_detector = GetFrame()->GetIdlenessDetector())
-    idleness_detector->OnWillSendRequest(document.Fetcher());
-  if (auto* interactive_detector = InteractiveDetector::From(document))
-    interactive_detector->OnResourceLoadBegin(base::nullopt);
-}
-
-void FrameFetchContext::DispatchDidReceiveResponse(
-    uint64_t identifier,
-    const ResourceRequest& request,
-    const ResourceResponse& response,
-    Resource* resource,
-    ResourceResponseType response_type) {
-  if (GetResourceFetcherProperties().IsDetached())
-    return;
-
-  if (GetSubresourceFilter() && resource->GetResourceRequest().IsAdResource())
-    GetSubresourceFilter()->ReportAdRequestId(response.RequestId());
-
-  if (response.GetCTPolicyCompliance() ==
-      ResourceResponse::kCTPolicyDoesNotComply) {
-    CountUsage(
-        GetFrame()->IsMainFrame()
-            ? WebFeature::
-                  kCertificateTransparencyNonCompliantSubresourceInMainFrame
-            : WebFeature::
-                  kCertificateTransparencyNonCompliantResourceInSubframe);
-  }
-
-  if (response_type == ResourceResponseType::kFromMemoryCache) {
-    GetLocalFrameClient()->DispatchDidLoadResourceFromMemoryCache(
-        resource->GetResourceRequest(), response);
-
-    // Note: probe::WillSendRequest needs to precede before this probe method.
-    probe::MarkResourceAsCached(GetFrame(), MasterDocumentLoader(), identifier);
-    if (response.IsNull())
-      return;
-  }
-
-  MixedContentChecker::CheckMixedPrivatePublic(GetFrame(),
-                                               response.RemoteIPAddress());
-
-  PreloadHelper::CanLoadResources resource_loading_policy =
-      response_type == ResourceResponseType::kFromMemoryCache
-          ? PreloadHelper::kDoNotLoadResources
-          : PreloadHelper::kLoadResourcesAndPreconnect;
-  PreloadHelper::LoadLinksFromHeader(
-      response.HttpHeaderField(http_names::kLink), response.CurrentRequestUrl(),
-      *GetFrame(), &frame_or_imported_document_->GetDocument(),
-      resource_loading_policy, PreloadHelper::kLoadAll, nullptr);
-
-  if (response.HasMajorCertificateErrors()) {
-    MixedContentChecker::HandleCertificateError(GetFrame(), response,
-                                                request.GetRequestContext());
-  }
-
-  if (response.IsLegacyTLSVersion()) {
-    UseCounter::Count(&frame_or_imported_document_->GetDocument(),
-                      WebFeature::kLegacyTLSVersionInSubresource);
-    GetLocalFrameClient()->ReportLegacyTLSVersion(response.CurrentRequestUrl());
-  }
-
-  GetFrame()->Loader().Progress().IncrementProgress(identifier, response);
-  GetLocalFrameClient()->DispatchDidReceiveResponse(response);
-  DocumentLoader* document_loader = MasterDocumentLoader();
-  probe::DidReceiveResourceResponse(Probe(), identifier, document_loader,
-                                    response, resource);
-  // It is essential that inspector gets resource response BEFORE console.
-  GetFrame()->Console().ReportResourceResponseReceived(document_loader,
-                                                       identifier, response);
-}
-
-void FrameFetchContext::DispatchDidReceiveData(uint64_t identifier,
-                                               const char* data,
-                                               uint64_t data_length) {
-  if (GetResourceFetcherProperties().IsDetached())
-    return;
-
-  GetFrame()->Loader().Progress().IncrementProgress(identifier, data_length);
-  probe::DidReceiveData(Probe(), identifier, MasterDocumentLoader(), data,
-                        data_length);
-}
-
-void FrameFetchContext::DispatchDidReceiveEncodedData(
-    uint64_t identifier,
-    size_t encoded_data_length) {
-  if (GetResourceFetcherProperties().IsDetached())
-    return;
-  probe::DidReceiveEncodedDataLength(Probe(), MasterDocumentLoader(),
-                                     identifier, encoded_data_length);
-}
-
-void FrameFetchContext::DispatchDidDownloadToBlob(uint64_t identifier,
-                                                  BlobDataHandle* blob) {
-  if (GetResourceFetcherProperties().IsDetached() || !blob)
-    return;
-
-  probe::DidReceiveBlob(Probe(), identifier, MasterDocumentLoader(), blob);
-}
-
-void FrameFetchContext::DispatchDidFinishLoading(
-    uint64_t identifier,
-    TimeTicks finish_time,
-    int64_t encoded_data_length,
-    int64_t decoded_body_length,
-    bool should_report_corb_blocking,
-    ResourceResponseType response_type) {
-  if (GetResourceFetcherProperties().IsDetached())
-    return;
-
-  GetFrame()->Loader().Progress().CompleteProgress(identifier);
-  probe::DidFinishLoading(Probe(), identifier, MasterDocumentLoader(),
-                          finish_time, encoded_data_length, decoded_body_length,
-                          should_report_corb_blocking);
-
-  Document& document = frame_or_imported_document_->GetDocument();
-  if (auto* interactive_detector = InteractiveDetector::From(document))
-    interactive_detector->OnResourceLoadEnd(finish_time);
-
-  if (LocalFrame* frame = document.GetFrame()) {
-    if (IdlenessDetector* idleness_detector = frame->GetIdlenessDetector())
-      idleness_detector->OnDidLoadResource();
-  }
-
-  if (response_type == ResourceResponseType::kNotFromMemoryCache)
-    document.CheckCompleted();
-}
-
-void FrameFetchContext::DispatchDidFail(const KURL& url,
-                                        uint64_t identifier,
-                                        const ResourceError& error,
-                                        int64_t encoded_data_length,
-                                        bool is_internal_request) {
-  if (GetResourceFetcherProperties().IsDetached())
-    return;
-
-  GetFrame()->Loader().Progress().CompleteProgress(identifier);
-  probe::DidFailLoading(Probe(), identifier, MasterDocumentLoader(), error);
-
-  // Notification to FrameConsole should come AFTER InspectorInstrumentation
-  // call, DevTools front-end relies on this.
-  if (!is_internal_request) {
-    GetFrame()->Console().DidFailLoading(MasterDocumentLoader(), identifier,
-                                         error);
-  }
-  Document& document = frame_or_imported_document_->GetDocument();
-  if (auto* interactive_detector = InteractiveDetector::From(document)) {
-    // We have not yet recorded load_finish_time. Pass nullopt here; we will
-    // call CurrentTimeTicksInSeconds lazily when we need it.
-    interactive_detector->OnResourceLoadEnd(base::nullopt);
-  }
-  if (LocalFrame* frame = document.GetFrame()) {
-    if (IdlenessDetector* idleness_detector = frame->GetIdlenessDetector())
-      idleness_detector->OnDidLoadResource();
-  }
-  document.CheckCompleted();
-}
-
 void FrameFetchContext::RecordLoadingActivity(
     const ResourceRequest& request,
     ResourceType type,
@@ -634,12 +464,6 @@
   }
 }
 
-void FrameFetchContext::DidObserveLoadingBehavior(
-    WebLoadingBehaviorFlag behavior) {
-  if (GetDocumentLoader())
-    GetDocumentLoader()->DidObserveLoadingBehavior(behavior);
-}
-
 void FrameFetchContext::AddResourceTiming(const ResourceTimingInfo& info) {
   // Normally, |document_| is cleared on Document shutdown. However, Documents
   // for HTML imports will also not have a LocalFrame set: in that case, also
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h
index 28c3f003..32a35a9c 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -55,8 +55,6 @@
 class FrameOrImportedDocument;
 class LocalFrame;
 class LocalFrameClient;
-class ResourceError;
-class ResourceResponse;
 class Settings;
 class WebContentSettingsClient;
 
@@ -90,39 +88,10 @@
                       const FetchInitiatorInfo&,
                       WebScopedVirtualTimePauser&,
                       ResourceType) override;
-  void DispatchWillSendRequest(
-      uint64_t identifier,
-      const ResourceRequest&,
-      const ResourceResponse& redirect_response,
-      ResourceType,
-      const FetchInitiatorInfo& = FetchInitiatorInfo()) override;
-  void DispatchDidReceiveResponse(uint64_t identifier,
-                                  const ResourceRequest&,
-                                  const ResourceResponse&,
-                                  Resource*,
-                                  ResourceResponseType) override;
-  void DispatchDidReceiveData(uint64_t identifier,
-                              const char* data,
-                              uint64_t data_length) override;
-  void DispatchDidReceiveEncodedData(uint64_t identifier,
-                                     size_t encoded_data_length) override;
-  void DispatchDidDownloadToBlob(uint64_t identifier, BlobDataHandle*) override;
-  void DispatchDidFinishLoading(uint64_t identifier,
-                                TimeTicks finish_time,
-                                int64_t encoded_data_length,
-                                int64_t decoded_body_length,
-                                bool should_report_corb_blocking,
-                                ResourceResponseType) override;
-  void DispatchDidFail(const KURL&,
-                       uint64_t identifier,
-                       const ResourceError&,
-                       int64_t encoded_data_length,
-                       bool is_internal_request) override;
 
   void RecordLoadingActivity(const ResourceRequest&,
                              ResourceType,
                              const AtomicString& fetch_initiator_name) override;
-  void DidObserveLoadingBehavior(WebLoadingBehaviorFlag) override;
 
   void AddResourceTiming(const ResourceTimingInfo&) override;
   bool AllowImage(bool images_enabled, const KURL&) const override;
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
index 1810689..f1bf9fb 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
@@ -234,16 +234,6 @@
     return reason;
   }
 
-  bool DispatchWillSendRequestAndVerifyIsAd(const KURL& url) {
-    ResourceRequest request(url);
-    ResourceResponse response;
-    FetchInitiatorInfo initiator_info;
-
-    GetFetchContext()->DispatchWillSendRequest(
-        1, request, response, ResourceType::kImage, initiator_info);
-    return request.IsAdResource();
-  }
-
   void AppendExecutingScriptToAdTracker(const String& url) {
     AdTracker* ad_tracker = document->GetFrame()->GetAdTracker();
     ad_tracker->WillExecuteScript(document, url);
@@ -1099,42 +1089,6 @@
   EXPECT_EQ(String(), resource_request.HttpHeaderField("Save-Data"));
 }
 
-// Tests that the embedder gets correct notification when a resource is loaded
-// from the memory cache.
-TEST_F(FrameFetchContextMockedLocalFrameClientTest,
-       LoadResourceFromMemoryCache) {
-  ResourceRequest resource_request(url);
-  resource_request.SetRequestContext(mojom::RequestContextType::IMAGE);
-  Resource* resource = MockResource::Create(resource_request);
-  EXPECT_CALL(
-      *client,
-      DispatchDidLoadResourceFromMemoryCache(
-          testing::AllOf(
-              testing::Property(&ResourceRequest::Url, url),
-              testing::Property(&ResourceRequest::GetRequestContext,
-                                mojom::RequestContextType::IMAGE)),
-          testing::Property(&ResourceResponse::IsNull, true)));
-  GetFetchContext()->DispatchDidReceiveResponse(
-      CreateUniqueIdentifier(), resource_request, resource->GetResponse(),
-      resource, FetchContext::ResourceResponseType::kFromMemoryCache);
-}
-
-// Tests that when a resource with certificate errors is loaded from the memory
-// cache, the embedder is notified.
-TEST_F(FrameFetchContextMockedLocalFrameClientTest,
-       MemoryCacheCertificateError) {
-  ResourceRequest resource_request(url);
-  resource_request.SetRequestContext(mojom::RequestContextType::IMAGE);
-  ResourceResponse response(url);
-  response.SetHasMajorCertificateErrors(true);
-  Resource* resource = MockResource::Create(resource_request);
-  resource->SetResponse(response);
-  EXPECT_CALL(*client, DidDisplayContentWithCertificateErrors());
-  GetFetchContext()->DispatchDidReceiveResponse(
-      CreateUniqueIdentifier(), resource_request, resource->GetResponse(),
-      resource, FetchContext::ResourceResponseType::kFromMemoryCache);
-}
-
 TEST_F(FrameFetchContextSubresourceFilterTest, Filter) {
   SetFilterPolicy(WebDocumentSubresourceFilter::kDisallow);
 
@@ -1244,62 +1198,6 @@
   EXPECT_EQ("hi", request.HttpHeaderField(http_names::kUserAgent));
 }
 
-TEST_F(FrameFetchContextTest, DispatchWillSendRequestWhenDetached) {
-  ResourceRequest request(KURL("https://www.example.com/"));
-  ResourceResponse response;
-  FetchInitiatorInfo initiator_info;
-
-  dummy_page_holder = nullptr;
-
-  GetFetchContext()->DispatchWillSendRequest(
-      1, request, response, ResourceType::kRaw, initiator_info);
-  // Should not crash.
-}
-
-TEST_F(FrameFetchContextTest, DispatchDidReceiveResponseWhenDetached) {
-  ResourceRequest request(KURL("https://www.example.com/"));
-  Resource* resource = MockResource::Create(request);
-  ResourceResponse response;
-
-  dummy_page_holder = nullptr;
-
-  GetFetchContext()->DispatchDidReceiveResponse(
-      3, request, response, resource,
-      FetchContext::ResourceResponseType::kNotFromMemoryCache);
-  // Should not crash.
-}
-
-TEST_F(FrameFetchContextTest, DispatchDidReceiveDataWhenDetached) {
-  dummy_page_holder = nullptr;
-
-  GetFetchContext()->DispatchDidReceiveData(3, "abcd", 4);
-  // Should not crash.
-}
-
-TEST_F(FrameFetchContextTest, DispatchDidReceiveEncodedDataWhenDetached) {
-  dummy_page_holder = nullptr;
-
-  GetFetchContext()->DispatchDidReceiveEncodedData(8, 9);
-  // Should not crash.
-}
-
-TEST_F(FrameFetchContextTest, DispatchDidFinishLoadingWhenDetached) {
-  dummy_page_holder = nullptr;
-
-  GetFetchContext()->DispatchDidFinishLoading(
-      4, base::TimeTicks() + base::TimeDelta::FromSecondsD(0.3), 8, 10, false,
-      FetchContext::ResourceResponseType::kNotFromMemoryCache);
-  // Should not crash.
-}
-
-TEST_F(FrameFetchContextTest, DispatchDidFailWhenDetached) {
-  dummy_page_holder = nullptr;
-
-  GetFetchContext()->DispatchDidFail(
-      KURL(), 8, ResourceError::Failure(NullURL()), 5, false);
-  // Should not crash.
-}
-
 TEST_F(FrameFetchContextTest, ShouldLoadNewResourceWhenDetached) {
   dummy_page_holder = nullptr;
 
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index cf5bad04..f772889 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -177,7 +177,7 @@
   // TODO(domfarolino): Stop storing ResourceRequest's generated referrer as a
   // header and instead use a separate member. See https://crbug.com/850813.
   if (client_redirect_policy == ClientRedirectPolicy::kClientRedirect) {
-    request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
+    request.SetHttpReferrer(SecurityPolicy::GenerateReferrer(
         frame_->GetDocument()->GetReferrerPolicy(),
         frame_->GetDocument()->Url(),
         frame_->GetDocument()->OutgoingReferrer()));
@@ -631,7 +631,7 @@
 
   // TODO(domfarolino): Stop storing ResourceRequest's generated referrer as a
   // header and instead use a separate member. See https://crbug.com/850813.
-  request.SetHTTPReferrer(referrer);
+  request.SetHttpReferrer(referrer);
   request.SetHTTPOriginToMatchReferrerIfNeeded();
 }
 
diff --git a/third_party/blink/renderer/core/loader/history_item.cc b/third_party/blink/renderer/core/loader/history_item.cc
index f7f2a5b3..50d2953f 100644
--- a/third_party/blink/renderer/core/loader/history_item.cc
+++ b/third_party/blink/renderer/core/loader/history_item.cc
@@ -154,7 +154,7 @@
   ResourceRequest request(url_string_);
   // TODO(domfarolino): Stop storing ResourceRequest's generated referrer as a
   // header and instead use a separate member. See https://crbug.com/850813.
-  request.SetHTTPReferrer(referrer_);
+  request.SetHttpReferrer(referrer_);
   request.SetCacheMode(cache_mode);
   if (form_data_) {
     request.SetHTTPMethod(http_names::kPOST);
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc b/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc
index 5e8599b..c4fecee 100644
--- a/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc
+++ b/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc
@@ -159,7 +159,7 @@
   fetch_params.SetContentSecurityPolicyNonce(options_.Nonce());
 
   // [SMSR] "... its referrer policy to options's referrer policy." [spec text]
-  // Note: For now this is done below with SetHTTPReferrer()
+  // Note: For now this is done below with SetHttpReferrer()
   network::mojom::ReferrerPolicy referrer_policy =
       module_request.Options().GetReferrerPolicy();
   if (referrer_policy == network::mojom::ReferrerPolicy::kDefault)
@@ -173,14 +173,14 @@
       options_.CredentialsMode());
 
   // Step 5. "... referrer is referrer, ..." [spec text]
-  // Note: For now this is done below with SetHTTPReferrer()
+  // Note: For now this is done below with SetHttpReferrer()
   String referrer_string = module_request.ReferrerString();
   if (referrer_string == Referrer::ClientReferrerString())
     referrer_string = fetch_client_settings_object.GetOutgoingReferrer();
 
   // TODO(domfarolino): Stop storing ResourceRequest's referrer as a
   // blink::Referrer (https://crbug.com/850813).
-  fetch_params.MutableResourceRequest().SetHTTPReferrer(
+  fetch_params.MutableResourceRequest().SetHttpReferrer(
       SecurityPolicy::GenerateReferrer(referrer_policy,
                                        fetch_params.GetResourceRequest().Url(),
                                        referrer_string));
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
new file mode 100644
index 0000000..a6c2965
--- /dev/null
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -0,0 +1,233 @@
+// Copyright 2019 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 "third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h"
+
+#include "third_party/blink/renderer/core/core_probes_inl.h"
+#include "third_party/blink/renderer/core/frame/frame_console.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/local_frame_client.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
+#include "third_party/blink/renderer/core/loader/frame_loader.h"
+#include "third_party/blink/renderer/core/loader/frame_or_imported_document.h"
+#include "third_party/blink/renderer/core/loader/idleness_detector.h"
+#include "third_party/blink/renderer/core/loader/interactive_detector.h"
+#include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
+#include "third_party/blink/renderer/core/loader/preload_helper.h"
+#include "third_party/blink/renderer/core/loader/progress_tracker.h"
+#include "third_party/blink/renderer/core/loader/subresource_filter.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+
+namespace blink {
+
+ResourceLoadObserverForFrame::ResourceLoadObserverForFrame(
+    const FrameOrImportedDocument& frame_or_imported_document,
+    const ResourceFetcherProperties& fetcher_properties)
+    : frame_or_imported_document_(frame_or_imported_document),
+      fetcher_properties_(fetcher_properties) {}
+ResourceLoadObserverForFrame::~ResourceLoadObserverForFrame() = default;
+
+void ResourceLoadObserverForFrame::WillSendRequest(
+    uint64_t identifier,
+    const ResourceRequest& request,
+    const ResourceResponse& redirect_response,
+    ResourceType resource_type,
+    const FetchInitiatorInfo& initiator_info) {
+  LocalFrame& frame = frame_or_imported_document_->GetFrame();
+  if (redirect_response.IsNull()) {
+    // Progress doesn't care about redirects, only notify it when an
+    // initial request is sent.
+    frame.Loader().Progress().WillStartLoading(identifier, request.Priority());
+  }
+  DocumentLoader& document_loader =
+      frame_or_imported_document_->GetMasterDocumentLoader();
+  Document& document = frame_or_imported_document_->GetDocument();
+  probe::WillSendRequest(
+      GetProbe(), identifier, &document_loader,
+      fetcher_properties_->GetFetchClientSettingsObject().GlobalObjectUrl(),
+      request, redirect_response, initiator_info, resource_type);
+  if (auto* idleness_detector = frame.GetIdlenessDetector())
+    idleness_detector->OnWillSendRequest(document.Fetcher());
+  if (auto* interactive_detector = InteractiveDetector::From(document))
+    interactive_detector->OnResourceLoadBegin(base::nullopt);
+}
+
+void ResourceLoadObserverForFrame::DidReceiveResponse(
+    uint64_t identifier,
+    const ResourceRequest& request,
+    const ResourceResponse& response,
+    Resource* resource,
+    ResponseSource response_source) {
+  LocalFrame& frame = frame_or_imported_document_->GetFrame();
+  DocumentLoader& document_loader =
+      frame_or_imported_document_->GetMasterDocumentLoader();
+  LocalFrameClient* frame_client = frame.Client();
+  SubresourceFilter* subresource_filter =
+      document_loader.GetSubresourceFilter();
+  if (subresource_filter && resource->GetResourceRequest().IsAdResource())
+    subresource_filter->ReportAdRequestId(response.RequestId());
+
+  DCHECK(frame_client);
+  if (response.GetCTPolicyCompliance() ==
+      ResourceResponse::kCTPolicyDoesNotComply) {
+    CountUsage(
+        frame.IsMainFrame()
+            ? WebFeature::
+                  kCertificateTransparencyNonCompliantSubresourceInMainFrame
+            : WebFeature::
+                  kCertificateTransparencyNonCompliantResourceInSubframe);
+  }
+
+  if (response_source == ResponseSource::kFromMemoryCache) {
+    frame_client->DispatchDidLoadResourceFromMemoryCache(
+        resource->GetResourceRequest(), response);
+
+    // Note: probe::WillSendRequest needs to precede before this probe method.
+    probe::MarkResourceAsCached(&frame, &document_loader, identifier);
+    if (response.IsNull())
+      return;
+  }
+
+  MixedContentChecker::CheckMixedPrivatePublic(&frame,
+                                               response.RemoteIPAddress());
+
+  PreloadHelper::CanLoadResources resource_loading_policy =
+      response_source == ResponseSource::kFromMemoryCache
+          ? PreloadHelper::kDoNotLoadResources
+          : PreloadHelper::kLoadResourcesAndPreconnect;
+  PreloadHelper::LoadLinksFromHeader(
+      response.HttpHeaderField(http_names::kLink), response.CurrentRequestUrl(),
+      frame, &frame_or_imported_document_->GetDocument(),
+      resource_loading_policy, PreloadHelper::kLoadAll, nullptr);
+
+  if (response.HasMajorCertificateErrors()) {
+    MixedContentChecker::HandleCertificateError(&frame, response,
+                                                request.GetRequestContext());
+  }
+
+  if (response.IsLegacyTLSVersion()) {
+    CountUsage(WebFeature::kLegacyTLSVersionInSubresource);
+    frame_client->ReportLegacyTLSVersion(response.CurrentRequestUrl());
+  }
+
+  frame.Loader().Progress().IncrementProgress(identifier, response);
+  frame_client->DispatchDidReceiveResponse(response);
+  probe::DidReceiveResourceResponse(GetProbe(), identifier, &document_loader,
+                                    response, resource);
+  // It is essential that inspector gets resource response BEFORE console.
+  frame.Console().ReportResourceResponseReceived(&document_loader, identifier,
+                                                 response);
+}
+
+void ResourceLoadObserverForFrame::DidReceiveData(
+    uint64_t identifier,
+    base::span<const char> chunk) {
+  LocalFrame& frame = frame_or_imported_document_->GetFrame();
+  DocumentLoader& document_loader =
+      frame_or_imported_document_->GetMasterDocumentLoader();
+  frame.Loader().Progress().IncrementProgress(identifier, chunk.size());
+  probe::DidReceiveData(GetProbe(), identifier, &document_loader, chunk.data(),
+                        chunk.size());
+}
+
+void ResourceLoadObserverForFrame::DidReceiveTransferSizeUpdate(
+    uint64_t identifier,
+    int transfer_size_diff) {
+  DCHECK_GT(transfer_size_diff, 0);
+  DocumentLoader& document_loader =
+      frame_or_imported_document_->GetMasterDocumentLoader();
+  probe::DidReceiveEncodedDataLength(GetProbe(), &document_loader, identifier,
+                                     transfer_size_diff);
+}
+
+void ResourceLoadObserverForFrame::DidDownloadToBlob(uint64_t identifier,
+                                                     BlobDataHandle* blob) {
+  if (blob) {
+    probe::DidReceiveBlob(
+        GetProbe(), identifier,
+        &frame_or_imported_document_->GetMasterDocumentLoader(), blob);
+  }
+}
+
+void ResourceLoadObserverForFrame::DidFinishLoading(
+    uint64_t identifier,
+    TimeTicks finish_time,
+    int64_t encoded_data_length,
+    int64_t decoded_body_length,
+    bool should_report_corb_blocking,
+    ResponseSource response_source) {
+  LocalFrame& frame = frame_or_imported_document_->GetFrame();
+  DocumentLoader& document_loader =
+      frame_or_imported_document_->GetMasterDocumentLoader();
+  frame.Loader().Progress().CompleteProgress(identifier);
+  probe::DidFinishLoading(GetProbe(), identifier, &document_loader, finish_time,
+                          encoded_data_length, decoded_body_length,
+                          should_report_corb_blocking);
+
+  Document& document = frame_or_imported_document_->GetDocument();
+  if (auto* interactive_detector = InteractiveDetector::From(document)) {
+    interactive_detector->OnResourceLoadEnd(finish_time);
+  }
+  if (LocalFrame* frame = document.GetFrame()) {
+    if (IdlenessDetector* idleness_detector = frame->GetIdlenessDetector()) {
+      idleness_detector->OnDidLoadResource();
+    }
+  }
+  if (response_source == ResponseSource::kNotFromMemoryCache) {
+    document.CheckCompleted();
+  }
+}
+
+void ResourceLoadObserverForFrame::DidFailLoading(const KURL&,
+                                                  uint64_t identifier,
+                                                  const ResourceError& error,
+                                                  int64_t,
+                                                  bool is_internal_request) {
+  LocalFrame& frame = frame_or_imported_document_->GetFrame();
+  DocumentLoader& document_loader =
+      frame_or_imported_document_->GetMasterDocumentLoader();
+  frame.Loader().Progress().CompleteProgress(identifier);
+  probe::DidFailLoading(GetProbe(), identifier, &document_loader, error);
+
+  // Notification to FrameConsole should come AFTER InspectorInstrumentation
+  // call, DevTools front-end relies on this.
+  if (!is_internal_request) {
+    frame.Console().DidFailLoading(&document_loader, identifier, error);
+  }
+  Document& document = frame_or_imported_document_->GetDocument();
+  if (auto* interactive_detector = InteractiveDetector::From(document)) {
+    // We have not yet recorded load_finish_time. Pass nullopt here; we will
+    // call CurrentTimeTicksInSeconds lazily when we need it.
+    interactive_detector->OnResourceLoadEnd(base::nullopt);
+  }
+  if (LocalFrame* frame = document.GetFrame()) {
+    if (IdlenessDetector* idleness_detector = frame->GetIdlenessDetector()) {
+      idleness_detector->OnDidLoadResource();
+    }
+  }
+  document.CheckCompleted();
+}
+
+void ResourceLoadObserverForFrame::Trace(Visitor* visitor) {
+  visitor->Trace(frame_or_imported_document_);
+  visitor->Trace(fetcher_properties_);
+  ResourceLoadObserver::Trace(visitor);
+}
+
+CoreProbeSink* ResourceLoadObserverForFrame::GetProbe() {
+  return probe::ToCoreProbeSink(
+      frame_or_imported_document_->GetFrame().GetDocument());
+}
+
+void ResourceLoadObserverForFrame::CountUsage(WebFeature feature) {
+  frame_or_imported_document_->GetMasterDocumentLoader().GetUseCounter().Count(
+      feature, &frame_or_imported_document_->GetFrame());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
new file mode 100644
index 0000000..91bc2af
--- /dev/null
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
@@ -0,0 +1,73 @@
+// Copyright 2019 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 THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LOAD_OBSERVER_FOR_FRAME_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LOAD_OBSERVER_FOR_FRAME_H_
+
+#include <inttypes.h>
+
+#include "base/containers/span.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/frame/web_feature_forward.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
+
+namespace blink {
+
+class CoreProbeSink;
+class FrameOrImportedDocument;
+class ResourceFetcherProperties;
+
+// ResourceLoadObserver implementation associated with a frame.
+class CORE_EXPORT ResourceLoadObserverForFrame final
+    : public ResourceLoadObserver {
+ public:
+  ResourceLoadObserverForFrame(
+      const FrameOrImportedDocument& frame_or_imported_document,
+      const ResourceFetcherProperties& properties);
+  ~ResourceLoadObserverForFrame() override;
+
+  // ResourceLoadObserver implementation.
+  void WillSendRequest(uint64_t identifier,
+                       const ResourceRequest&,
+                       const ResourceResponse& redirect_response,
+                       ResourceType,
+                       const FetchInitiatorInfo&) override;
+  void DidReceiveResponse(uint64_t identifier,
+                          const ResourceRequest& request,
+                          const ResourceResponse& response,
+                          Resource* resource,
+                          ResponseSource) override;
+  void DidReceiveData(uint64_t identifier,
+                      base::span<const char> chunk) override;
+  void DidReceiveTransferSizeUpdate(uint64_t identifier,
+                                    int transfer_size_diff) override;
+  void DidDownloadToBlob(uint64_t identifier, BlobDataHandle*) override;
+  void DidFinishLoading(uint64_t identifier,
+                        TimeTicks finish_time,
+                        int64_t encoded_data_length,
+                        int64_t decoded_body_length,
+                        bool should_report_corb_blocking,
+                        ResponseSource) override;
+  void DidFailLoading(const KURL&,
+                      uint64_t identifier,
+                      const ResourceError&,
+                      int64_t encoded_data_length,
+                      bool is_internal_request) override;
+  void Trace(Visitor*) override;
+
+ private:
+  CoreProbeSink* GetProbe();
+  void CountUsage(WebFeature);
+
+  // There are some overlap between |frame_or_imported_document| and
+  // |fetcher_properties_|.
+  // Use this when you want to access frame, document, etc. directly.
+  const Member<const FrameOrImportedDocument> frame_or_imported_document_;
+  // Use this whenever possible.
+  const Member<const ResourceFetcherProperties> fetcher_properties_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LOAD_OBSERVER_FOR_FRAME_H_
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame_test.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame_test.cc
new file mode 100644
index 0000000..66a290a
--- /dev/null
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame_test.cc
@@ -0,0 +1,59 @@
+// Copyright 2019 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 "third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/loader/empty_clients.h"
+#include "third_party/blink/renderer/core/loader/frame_or_imported_document.h"
+#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/loader/testing/mock_resource.h"
+#include "third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h"
+
+namespace blink {
+
+// Tests that when a resource with certificate errors is loaded from the memory
+// cache, the embedder is notified.
+TEST(ResourceLoadObserverForFrameTest, MemoryCacheCertificateError) {
+  class MockFrameClient final : public EmptyLocalFrameClient {
+   public:
+    void DidDisplayContentWithCertificateErrors() override {
+      did_display_content_with_certificate_errors_called_ = true;
+    }
+
+    bool IsDidDisplayContentWithCertificateErrorsCalled() const {
+      return did_display_content_with_certificate_errors_called_;
+    }
+
+   private:
+    bool did_display_content_with_certificate_errors_called_ = false;
+  };
+
+  auto* client = MakeGarbageCollected<MockFrameClient>();
+  auto dummy_page_holder =
+      std::make_unique<DummyPageHolder>(IntSize(), nullptr, client);
+  LocalFrame& frame = dummy_page_holder->GetFrame();
+  auto* observer = MakeGarbageCollected<ResourceLoadObserverForFrame>(
+      *MakeGarbageCollected<FrameOrImportedDocument>(
+          *frame.GetDocument()->Loader(), *frame.GetDocument()),
+      *MakeGarbageCollected<TestResourceFetcherProperties>());
+  KURL url("https://www.example.com/");
+  ResourceRequest resource_request(url);
+  resource_request.SetRequestContext(mojom::RequestContextType::IMAGE);
+  ResourceResponse response(url);
+  response.SetHasMajorCertificateErrors(true);
+  Resource* resource = MockResource::Create(resource_request);
+  resource->SetResponse(response);
+
+  EXPECT_FALSE(client->IsDidDisplayContentWithCertificateErrorsCalled());
+  observer->DidReceiveResponse(
+      99, resource_request, resource->GetResponse(), resource,
+      ResourceLoadObserver::ResponseSource::kFromMemoryCache);
+  EXPECT_TRUE(client->IsDidDisplayContentWithCertificateErrorsCalled());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc
new file mode 100644
index 0000000..d38e0b0
--- /dev/null
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc
@@ -0,0 +1,104 @@
+// Copyright 2019 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 "third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h"
+
+#include "third_party/blink/public/platform/web_mixed_content.h"
+#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
+#include "third_party/blink/public/platform/web_worker_fetch_context.h"
+#include "third_party/blink/renderer/core/core_probes_inl.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+
+namespace blink {
+
+ResourceLoadObserverForWorker::ResourceLoadObserverForWorker(
+    CoreProbeSink& probe,
+    const ResourceFetcherProperties& properties,
+    scoped_refptr<WebWorkerFetchContext> web_context)
+    : probe_(probe),
+      fetcher_properties_(properties),
+      web_context_(std::move(web_context)) {}
+
+ResourceLoadObserverForWorker::~ResourceLoadObserverForWorker() = default;
+
+void ResourceLoadObserverForWorker::WillSendRequest(
+    uint64_t identifier,
+    const ResourceRequest& request,
+    const ResourceResponse& redirect_response,
+    ResourceType resource_type,
+    const FetchInitiatorInfo& initiator_info) {
+  probe::WillSendRequest(
+      probe_, identifier, nullptr,
+      fetcher_properties_->GetFetchClientSettingsObject().GlobalObjectUrl(),
+      request, redirect_response, initiator_info, resource_type);
+}
+
+void ResourceLoadObserverForWorker::DidReceiveResponse(
+    uint64_t identifier,
+    const ResourceRequest& request,
+    const ResourceResponse& response,
+    Resource* resource,
+    ResponseSource) {
+  if (response.HasMajorCertificateErrors()) {
+    WebMixedContentContextType context_type =
+        WebMixedContent::ContextTypeFromRequestContext(
+            request.GetRequestContext(),
+            false /* strictMixedContentCheckingForPlugin */);
+    if (context_type == WebMixedContentContextType::kBlockable) {
+      web_context_->DidRunContentWithCertificateErrors();
+    } else {
+      web_context_->DidDisplayContentWithCertificateErrors();
+    }
+  }
+  probe::DidReceiveResourceResponse(probe_, identifier, nullptr, response,
+                                    resource);
+}
+
+void ResourceLoadObserverForWorker::DidReceiveData(
+    uint64_t identifier,
+    base::span<const char> chunk) {
+  probe::DidReceiveData(probe_, identifier, nullptr, chunk.data(),
+                        chunk.size());
+}
+
+void ResourceLoadObserverForWorker::DidReceiveTransferSizeUpdate(
+    uint64_t identifier,
+    int transfer_size_diff) {
+  DCHECK_GT(transfer_size_diff, 0);
+  probe::DidReceiveEncodedDataLength(probe_, nullptr, identifier,
+                                     transfer_size_diff);
+}
+
+void ResourceLoadObserverForWorker::DidDownloadToBlob(uint64_t identifier,
+                                                      BlobDataHandle* blob) {}
+
+void ResourceLoadObserverForWorker::DidFinishLoading(
+    uint64_t identifier,
+    TimeTicks finish_time,
+    int64_t encoded_data_length,
+    int64_t decoded_body_length,
+    bool should_report_corb_blocking,
+    ResponseSource) {
+  probe::DidFinishLoading(probe_, identifier, nullptr, finish_time,
+                          encoded_data_length, decoded_body_length,
+                          should_report_corb_blocking);
+}
+
+void ResourceLoadObserverForWorker::DidFailLoading(const KURL&,
+                                                   uint64_t identifier,
+                                                   const ResourceError& error,
+                                                   int64_t,
+                                                   bool) {
+  probe::DidFailLoading(probe_, identifier, nullptr, error);
+}
+
+void ResourceLoadObserverForWorker::Trace(Visitor* visitor) {
+  visitor->Trace(probe_);
+  visitor->Trace(fetcher_properties_);
+  ResourceLoadObserver::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
new file mode 100644
index 0000000..262327b
--- /dev/null
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
@@ -0,0 +1,64 @@
+// Copyright 2019 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 THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LOAD_OBSERVER_FOR_WORKER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LOAD_OBSERVER_FOR_WORKER_H_
+
+#include <inttypes.h>
+
+#include "base/containers/span.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
+
+namespace blink {
+
+class CoreProbeSink;
+class ResourceFetcherProperties;
+class WebWorkerFetchContext;
+
+// ResourceLoadObserver implementation associated with a worker or worklet.
+class ResourceLoadObserverForWorker final : public ResourceLoadObserver {
+ public:
+  ResourceLoadObserverForWorker(CoreProbeSink& probe,
+                                const ResourceFetcherProperties& properties,
+                                scoped_refptr<WebWorkerFetchContext>);
+  ~ResourceLoadObserverForWorker() override;
+
+  // ResourceLoadObserver implementation.
+  void WillSendRequest(uint64_t identifier,
+                       const ResourceRequest&,
+                       const ResourceResponse& redirect_response,
+                       ResourceType,
+                       const FetchInitiatorInfo&) override;
+  void DidReceiveResponse(uint64_t identifier,
+                          const ResourceRequest& request,
+                          const ResourceResponse& response,
+                          Resource* resource,
+                          ResponseSource) override;
+  void DidReceiveData(uint64_t identifier,
+                      base::span<const char> chunk) override;
+  void DidReceiveTransferSizeUpdate(uint64_t identifier,
+                                    int transfer_size_diff) override;
+  void DidDownloadToBlob(uint64_t identifier, BlobDataHandle*) override;
+  void DidFinishLoading(uint64_t identifier,
+                        TimeTicks finish_time,
+                        int64_t encoded_data_length,
+                        int64_t decoded_body_length,
+                        bool should_report_corb_blocking,
+                        ResponseSource) override;
+  void DidFailLoading(const KURL&,
+                      uint64_t identifier,
+                      const ResourceError&,
+                      int64_t encoded_data_length,
+                      bool is_internal_request) override;
+  void Trace(Visitor*) override;
+
+ private:
+  const Member<CoreProbeSink> probe_;
+  const Member<const ResourceFetcherProperties> fetcher_properties_;
+  const scoped_refptr<WebWorkerFetchContext> web_context_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_RESOURCE_LOAD_OBSERVER_FOR_WORKER_H_
diff --git a/third_party/blink/renderer/core/loader/threadable_loader.cc b/third_party/blink/renderer/core/loader/threadable_loader.cc
index b1557c0..87b3013 100644
--- a/third_party/blink/renderer/core/loader/threadable_loader.cc
+++ b/third_party/blink/renderer/core/loader/threadable_loader.cc
@@ -347,7 +347,7 @@
   // TODO(domfarolino): Stop setting the HTTPReferrer header, and instead use
   // ResourceRequest::referrer_. See https://crbug.com/850813.
   if (override_referrer_)
-    request.SetHTTPReferrer(referrer_after_redirect_);
+    request.SetHttpReferrer(referrer_after_redirect_);
 }
 
 void ThreadableLoader::LoadPreflightRequest(
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
index 066f4cf..2708286 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -214,70 +214,6 @@
     request.SetHttpHeaderField(http_names::kSaveData, "on");
 }
 
-void WorkerFetchContext::DispatchWillSendRequest(
-    uint64_t identifier,
-    const ResourceRequest& request,
-    const ResourceResponse& redirect_response,
-    ResourceType resource_type,
-    const FetchInitiatorInfo& initiator_info) {
-  probe::WillSendRequest(Probe(), identifier, nullptr, Url(), request,
-                         redirect_response, initiator_info, resource_type);
-}
-
-void WorkerFetchContext::DispatchDidReceiveResponse(
-    uint64_t identifier,
-    const ResourceRequest& request,
-    const ResourceResponse& response,
-    Resource* resource,
-    ResourceResponseType) {
-  if (response.HasMajorCertificateErrors()) {
-    WebMixedContentContextType context_type =
-        WebMixedContent::ContextTypeFromRequestContext(
-            request.GetRequestContext(),
-            false /* strictMixedContentCheckingForPlugin */);
-    if (context_type == WebMixedContentContextType::kBlockable) {
-      web_context_->DidRunContentWithCertificateErrors();
-    } else {
-      web_context_->DidDisplayContentWithCertificateErrors();
-    }
-  }
-  probe::DidReceiveResourceResponse(Probe(), identifier, nullptr, response,
-                                    resource);
-}
-
-void WorkerFetchContext::DispatchDidReceiveData(uint64_t identifier,
-                                                const char* data,
-                                                uint64_t data_length) {
-  probe::DidReceiveData(Probe(), identifier, nullptr, data, data_length);
-}
-
-void WorkerFetchContext::DispatchDidReceiveEncodedData(
-    uint64_t identifier,
-    size_t encoded_data_length) {
-  probe::DidReceiveEncodedDataLength(Probe(), nullptr, identifier,
-                                     encoded_data_length);
-}
-
-void WorkerFetchContext::DispatchDidFinishLoading(
-    uint64_t identifier,
-    TimeTicks finish_time,
-    int64_t encoded_data_length,
-    int64_t decoded_body_length,
-    bool should_report_corb_blocking,
-    ResourceResponseType) {
-  probe::DidFinishLoading(Probe(), identifier, nullptr, finish_time,
-                          encoded_data_length, decoded_body_length,
-                          should_report_corb_blocking);
-}
-
-void WorkerFetchContext::DispatchDidFail(const KURL& url,
-                                         uint64_t identifier,
-                                         const ResourceError& error,
-                                         int64_t encoded_data_length,
-                                         bool is_internal_request) {
-  probe::DidFailLoading(Probe(), identifier, nullptr, error);
-}
-
 void WorkerFetchContext::AddResourceTiming(const ResourceTimingInfo& info) {
   // TODO(nhiroki): Add ResourceTiming API support once it's spec'ed for
   // worklets.
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.h b/third_party/blink/renderer/core/loader/worker_fetch_context.h
index 71c8b580..8fb9de04 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.h
@@ -16,7 +16,6 @@
 namespace blink {
 
 class CoreProbeSink;
-class Resource;
 class SubresourceFilter;
 class WebWorkerFetchContext;
 class WorkerContentSettingsClient;
@@ -76,32 +75,6 @@
                       WebScopedVirtualTimePauser&,
                       ResourceType) override;
   void AddAdditionalRequestHeaders(ResourceRequest&) override;
-  void DispatchWillSendRequest(uint64_t,
-                               const ResourceRequest&,
-                               const ResourceResponse&,
-                               ResourceType,
-                               const FetchInitiatorInfo&) override;
-  void DispatchDidReceiveResponse(uint64_t identifier,
-                                  const ResourceRequest&,
-                                  const ResourceResponse&,
-                                  Resource*,
-                                  ResourceResponseType) override;
-  void DispatchDidReceiveData(uint64_t identifier,
-                              const char* data,
-                              uint64_t data_length) override;
-  void DispatchDidReceiveEncodedData(uint64_t identifier,
-                                     size_t encoded_data_length) override;
-  void DispatchDidFinishLoading(uint64_t identifier,
-                                TimeTicks finish_time,
-                                int64_t encoded_data_length,
-                                int64_t decoded_body_length,
-                                bool should_report_corb_blocking,
-                                ResourceResponseType) override;
-  void DispatchDidFail(const KURL&,
-                       uint64_t identifier,
-                       const ResourceError&,
-                       int64_t encoded_data_length,
-                       bool isInternalRequest) override;
   void AddResourceTiming(const ResourceTimingInfo&) override;
   void PopulateResourceRequest(ResourceType,
                                const ClientHintsPreferences&,
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc
index ac65f93..780ae32 100644
--- a/third_party/blink/renderer/core/page/create_window.cc
+++ b/third_party/blink/renderer/core/page/create_window.cc
@@ -339,7 +339,7 @@
   // ensure the proper referrer is set now.
   // TODO(domfarolino): Stop setting ResourceRequest's HTTP Referrer and store
   // this is a separate member. See https://crbug.com/850813.
-  frame_request.GetResourceRequest().SetHTTPReferrer(
+  frame_request.GetResourceRequest().SetHttpReferrer(
       SecurityPolicy::GenerateReferrer(
           active_frame->GetDocument()->GetReferrerPolicy(), completed_url,
           active_frame->GetDocument()->OutgoingReferrer()));
diff --git a/third_party/blink/renderer/core/page/drag_controller_test.cc b/third_party/blink/renderer/core/page/drag_controller_test.cc
index 1b1ab874..3dfd1b3 100644
--- a/third_party/blink/renderer/core/page/drag_controller_test.cc
+++ b/third_party/blink/renderer/core/page/drag_controller_test.cc
@@ -44,7 +44,7 @@
 class DragControllerTest : public RenderingTest {
  protected:
   DragControllerTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()),
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
 
         chrome_client_(MakeGarbageCollected<DragMockChromeClient>()) {}
   LocalFrame& GetFrame() const { return *GetDocument().GetFrame(); }
diff --git a/third_party/blink/renderer/core/page/print_context_test.cc b/third_party/blink/renderer/core/page/print_context_test.cc
index 1c6bbfa..6487b77f 100644
--- a/third_party/blink/renderer/core/page/print_context_test.cc
+++ b/third_party/blink/renderer/core/page/print_context_test.cc
@@ -141,7 +141,7 @@
 class PrintContextFrameTest : public PrintContextTest {
  public:
   PrintContextFrameTest()
-      : PrintContextTest(SingleChildLocalFrameClient::Create()) {}
+      : PrintContextTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 };
 
 #define EXPECT_SKRECT_EQ(expectedX, expectedY, expectedWidth, expectedHeight, \
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
index 5e48234a..4eb4669 100644
--- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
@@ -803,11 +803,11 @@
 
 namespace {
 
-bool ScrollsWithFrame(const LocalFrame& frame, LayoutBox* object) {
+bool ScrollsWithFrame(const LocalFrame& frame, LayoutObject* object) {
   DCHECK(object);
-  DCHECK(object->Layer()->GetLayoutBox() == object);
+  DCHECK(object->EnclosingLayer());
 
-  if (object->Layer()->AncestorScrollingLayer() ==
+  if (object->EnclosingLayer()->AncestorScrollingLayer() ==
       frame.ContentLayoutObject()->Layer())
     return true;
 
@@ -885,10 +885,9 @@
     if (!element->GetLayoutObject())
       continue;
 
-    Region* region =
-        ScrollsWithFrame(*frame, ToLayoutBox(element->GetLayoutObject()))
-            ? scrolling_region
-            : fixed_region;
+    Region* region = ScrollsWithFrame(*frame, element->GetLayoutObject())
+                         ? scrolling_region
+                         : fixed_region;
 
     if (plugin->WantsWheelEvents()) {
       IntRect box = frame_view->ConvertToRootFrame(plugin->FrameRect());
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
index 94d64d8..0c7e4c4 100644
--- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
@@ -38,6 +38,7 @@
 #include "third_party/blink/renderer/core/css/css_style_sheet.h"
 #include "third_party/blink/renderer/core/css/style_sheet_list.h"
 #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
+#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
@@ -46,6 +47,7 @@
 #include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/html/html_iframe_element.h"
+#include "third_party/blink/renderer/core/html/html_object_element.h"
 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/page/page.h"
@@ -1021,6 +1023,85 @@
   EXPECT_TRUE(region.IsEmpty());
 }
 
+// Ensure we don't crash when a plugin becomes a LayoutInline
+TEST_P(ScrollingCoordinatorTest, PluginBecomesLayoutInline) {
+  HistogramTester histogram_tester;
+  LoadHTML(R"HTML(
+    <style>
+      body {
+        margin: 0;
+        height: 3000px;
+      }
+    </style>
+    <object id="plugin" type="appilcation/x-webkit-test-plugin"></object>
+    <script>
+      document.getElementById("plugin")
+              .appendChild(document.createElement("label"))
+    </script>
+  )HTML");
+
+  // This test passes if it doesn't crash. We're trying to make sure
+  // ScrollingCoordinator can deal with LayoutInline plugins when generating
+  // NonFastScrollableRegions.
+  HTMLObjectElement* plugin =
+      ToHTMLObjectElement(GetFrame()->GetDocument()->getElementById("plugin"));
+  ASSERT_TRUE(plugin->GetLayoutObject()->IsLayoutInline());
+  ForceFullCompositingUpdate();
+}
+
+// Ensure NonFastScrollableRegions are correctly generated for both fixed and
+// in-flow plugins that need them.
+TEST_P(ScrollingCoordinatorTest, NonFastScrollableRegionsForPlugins) {
+  HistogramTester histogram_tester;
+  LoadHTML(R"HTML(
+    <style>
+      body {
+        margin: 0;
+        height: 3000px;
+      }
+      #plugin {
+        width: 300px;
+        height: 300px;
+      }
+      #pluginfixed {
+        width: 200px;
+        height: 200px;
+      }
+      #fixed {
+        position: fixed;
+        top: 500px;
+      }
+    </style>
+    <div id="fixed">
+      <object id="pluginfixed" type="application/x-webkit-test-plugin"></object>
+    </div>
+    <object id="plugin" type="application/x-webkit-test-plugin"></object>
+  )HTML");
+
+  HTMLObjectElement* plugin =
+      ToHTMLObjectElement(GetFrame()->GetDocument()->getElementById("plugin"));
+  HTMLObjectElement* plugin_fixed = ToHTMLObjectElement(
+      GetFrame()->GetDocument()->getElementById("pluginfixed"));
+  // NonFastScrollableRegions are generated for plugins that require wheel
+  // events.
+  plugin->OwnedPlugin()->SetWantsWheelEvents(true);
+  plugin_fixed->OwnedPlugin()->SetWantsWheelEvents(true);
+
+  ForceFullCompositingUpdate();
+
+  Region scrolling;
+  Region fixed;
+  Page* page = GetFrame()->GetPage();
+  page->GetScrollingCoordinator()
+      ->ComputeShouldHandleScrollGestureOnMainThreadRegion(
+          To<LocalFrame>(page->MainFrame()), &scrolling, &fixed);
+
+  EXPECT_TRUE(scrolling.IsRect());
+  EXPECT_TRUE(fixed.IsRect());
+  EXPECT_EQ(scrolling.Rects().at(0), IntRect(0, 0, 300, 300));
+  EXPECT_EQ(fixed.Rects().at(0), IntRect(0, 500, 200, 200));
+}
+
 TEST_P(ScrollingCoordinatorTest, overflowScrolling) {
   RegisterMockedHttpURLLoad("overflow-scrolling.html");
   NavigateTo(base_url_ + "overflow-scrolling.html");
diff --git a/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc b/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
index abf1e69..3dedf85a2 100644
--- a/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
+++ b/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
@@ -102,7 +102,7 @@
   return scroll_snap_type;
 }
 
-void SnapCoordinator::UpdateSnapContainerData(const LayoutBox& snap_container) {
+void SnapCoordinator::UpdateSnapContainerData(LayoutBox& snap_container) {
   if (snap_container.Style()->GetScrollSnapType().is_none)
     return;
 
@@ -165,6 +165,11 @@
           CalculateSnapAreaData(*snap_area, snap_container));
     }
   }
+
+  auto old_snap_container_data = GetSnapContainerData(snap_container);
+  if (old_snap_container_data != snap_container_data)
+    snap_container.SetNeedsPaintPropertyUpdate();
+
   snap_container_map_.Set(&snap_container, snap_container_data);
 }
 
@@ -236,7 +241,9 @@
 base::Optional<FloatPoint> SnapCoordinator::GetSnapPosition(
     const LayoutBox& snap_container,
     const cc::SnapSelectionStrategy& strategy) const {
-  auto iter = snap_container_map_.find(&snap_container);
+  // const_cast is safe here because we only need to modify the type to match
+  // the key type, not actually mutating the object.
+  auto iter = snap_container_map_.find(&const_cast<LayoutBox&>(snap_container));
   if (iter == snap_container_map_.end())
     return base::nullopt;
 
@@ -345,7 +352,9 @@
 
 base::Optional<cc::SnapContainerData> SnapCoordinator::GetSnapContainerData(
     const LayoutBox& snap_container) const {
-  auto iter = snap_container_map_.find(&snap_container);
+  // const_cast is safe here because we only need to modify the type to match
+  // the key type, not actually mutating the object.
+  auto iter = snap_container_map_.find(&const_cast<LayoutBox&>(snap_container));
   if (iter != snap_container_map_.end()) {
     return iter->value;
   }
@@ -369,7 +378,9 @@
 }
 
 void SnapCoordinator::ShowSnapDataFor(const LayoutBox* snap_container) {
-  auto iter = snap_container_map_.find(snap_container);
+  // const_cast is safe here because we only need to modify the type to match
+  // the key type, not actually mutating the object.
+  auto iter = snap_container_map_.find(const_cast<LayoutBox*>(snap_container));
   if (iter == snap_container_map_.end())
     return;
   LOG(INFO) << iter->value;
diff --git a/third_party/blink/renderer/core/page/scrolling/snap_coordinator.h b/third_party/blink/renderer/core/page/scrolling/snap_coordinator.h
index 6f8747e3..8381ad0 100644
--- a/third_party/blink/renderer/core/page/scrolling/snap_coordinator.h
+++ b/third_party/blink/renderer/core/page/scrolling/snap_coordinator.h
@@ -51,7 +51,6 @@
   // Called by LocalFrameView::PerformPostLayoutTasks(), so that the snap data
   // are updated whenever a layout happens.
   void UpdateAllSnapContainerData();
-  void UpdateSnapContainerData(const LayoutBox&);
 
   // SnapAtCurrentPosition(), SnapForEndPosition(), SnapForDirection(), and
   // SnapForEndAndDirection() return true if snapping was performed, and false
@@ -85,7 +84,9 @@
   bool PerformSnapping(const LayoutBox& snap_container,
                        const cc::SnapSelectionStrategy& strategy) const;
 
-  HashMap<const LayoutBox*, cc::SnapContainerData> snap_container_map_;
+  void UpdateSnapContainerData(LayoutBox&);
+
+  HashMap<LayoutBox*, cc::SnapContainerData> snap_container_map_;
   DISALLOW_COPY_AND_ASSIGN(SnapCoordinator);
 };
 
diff --git a/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc b/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
index 3a527ee..f7f3099 100644
--- a/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
 #include "third_party/blink/renderer/core/layout/layout_box.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -18,16 +19,24 @@
 #include "third_party/blink/renderer/core/scroll/scroll_types.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h"
 
 namespace blink {
 
 using html_names::kStyleAttr;
 
-class SnapCoordinatorTest : public testing::Test {
+class SnapCoordinatorTest : public testing::Test,
+                            public UseMockScrollbarSettings {
  protected:
+  SnapCoordinatorTest() : UseMockScrollbarSettings() {}
   void SetUp() override {
     page_holder_ = std::make_unique<DummyPageHolder>();
 
+    page_holder_->GetPage().GetSettings().SetAcceleratedCompositingEnabled(
+        true);
+    GetDocument().View()->SetParentVisible(true);
+    GetDocument().View()->SetSelfVisible(true);
+
     SetHTML(R"HTML(
       <style>
           #snap-container {
@@ -51,7 +60,7 @@
         </div>
       </body>
     )HTML");
-    GetDocument().UpdateStyleAndLayout();
+    UpdateAllLifecyclePhasesForTest();
   }
 
   void TearDown() override { page_holder_ = nullptr; }
@@ -104,7 +113,13 @@
         </div>
       </div>
       )HTML");
-    GetDocument().UpdateStyleAndLayout();
+    UpdateAllLifecyclePhasesForTest();
+  }
+
+  void UpdateAllLifecyclePhasesForTest() {
+    GetDocument().View()->UpdateAllLifecyclePhases(
+        DocumentLifecycle::LifecycleUpdateReason::kTest);
+    GetDocument().View()->RunPostLifecycleSteps();
   }
 
   std::unique_ptr<DummyPageHolder> page_holder_;
@@ -113,7 +128,7 @@
 TEST_F(SnapCoordinatorTest, SimpleSnapElement) {
   Element& snap_element = *GetDocument().getElementById("snap-element");
   snap_element.setAttribute(kStyleAttr, "scroll-snap-align: start;");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
 
   EXPECT_EQ(1U, SizeOfSnapAreas(SnapContainer()));
 }
@@ -121,7 +136,23 @@
 TEST_F(SnapCoordinatorTest, NestedSnapElement) {
   Element& snap_element = *GetDocument().getElementById("nested-snap-element");
   snap_element.setAttribute(kStyleAttr, "scroll-snap-align: start;");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
+
+  EXPECT_EQ(1U, SizeOfSnapAreas(SnapContainer()));
+}
+
+TEST_F(SnapCoordinatorTest, ModifySnapElement) {
+  Element& snap_element = *GetDocument().getElementById("snap-element");
+  snap_element.setAttribute(kStyleAttr, "scroll-snap-align: start;");
+  UpdateAllLifecyclePhasesForTest();
+  EXPECT_EQ(1U, SizeOfSnapAreas(SnapContainer()));
+
+  snap_element.setAttribute(kStyleAttr, "scroll-snap-align: end;");
+
+  // Set scrollable area will set paint invalidation while scroll, will crash
+  // if snap-element not set needs update.
+  SnapContainer().GetLayoutBox()->SetShouldDoFullPaintInvalidation();
+  UpdateAllLifecyclePhasesForTest();
 
   EXPECT_EQ(1U, SizeOfSnapAreas(SnapContainer()));
 }
@@ -133,7 +164,7 @@
   Element* intermediate = GetDocument().getElementById("intermediate");
   intermediate->setAttribute(kStyleAttr, "overflow: scroll;");
 
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
 
   // Intermediate scroller captures nested snap elements first so ancestor
   // does not get them.
@@ -145,7 +176,7 @@
   Element& snap_element =
       *GetDocument().getElementById("snap-element-fixed-position");
   snap_element.setAttribute(kStyleAttr, "scroll-snap-align: start;");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
 
   // Position fixed elements are contained in document and not its immediate
   // ancestor scroller. They cannot be a valid snap destination so they should
@@ -160,12 +191,12 @@
 TEST_F(SnapCoordinatorTest, UpdateStyleForSnapElement) {
   Element& snap_element = *GetDocument().getElementById("snap-element");
   snap_element.setAttribute(kStyleAttr, "scroll-snap-align: start;");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
 
   EXPECT_EQ(1U, SizeOfSnapAreas(SnapContainer()));
 
   snap_element.remove();
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
 
   EXPECT_EQ(0U, SizeOfSnapAreas(SnapContainer()));
 
@@ -176,7 +207,7 @@
         <div style='width:2000px; height:2000px;'></div>
     </div>
   )HTML");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
 
   EXPECT_EQ(1U, SizeOfSnapAreas(SnapContainer()));
 }
@@ -202,7 +233,7 @@
     </body>
   )HTML");
 
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
 
   // Sanity check that body is the viewport defining element
   EXPECT_EQ(GetDocument().body(), GetDocument().ViewportDefiningElement());
@@ -240,7 +271,7 @@
     </html>
   )HTML");
 
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
 
   // Sanity check that document element is the viewport defining element
   EXPECT_EQ(GetDocument().documentElement(),
@@ -285,7 +316,7 @@
     </html>
   )HTML");
 
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
 
   // Sanity check that document element is the viewport defining element
   EXPECT_EQ(GetDocument().documentElement(),
@@ -322,7 +353,7 @@
       scroller_element->GetLayoutBox()->GetScrollableArea();
   Element* area_element = GetDocument().getElementById("area");
   area_element->setAttribute(kStyleAttr, "scroll-snap-align: start;");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
   SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
 
   base::Optional<cc::SnapContainerData> data =
@@ -356,7 +387,7 @@
   EXPECT_EQ(FloatPoint(20, 20), scrollable_area->ScrollPosition());
   Element* area_element = GetDocument().getElementById("area");
   area_element->setAttribute(kStyleAttr, "scroll-snap-align: start;");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
   SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
 
   base::Optional<cc::SnapContainerData> data =
@@ -405,7 +436,7 @@
     <div id="area"></div>
     </div>
     )HTML");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
 
   Element* body = GetDocument().body();
   EXPECT_EQ(body, GetDocument().ViewportDefiningElement());
@@ -414,7 +445,7 @@
   EXPECT_EQ(FloatPoint(20, 20), scrollable_area->ScrollPosition());
   Element* area_element = GetDocument().getElementById("area");
   area_element->setAttribute(kStyleAttr, "scroll-snap-align: start;");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
   SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
   base::Optional<cc::SnapContainerData> data =
       snap_coordinator->GetSnapContainerData(*GetDocument().GetLayoutView());
@@ -449,7 +480,7 @@
   Element* scroller_element = GetDocument().getElementById("scroller");
   scroller_element->setAttribute(
       kStyleAttr, "margin: 3px; border: 10px solid; padding: 4px;");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
   SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
   base::Optional<cc::SnapContainerData> data =
       snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
@@ -491,7 +522,7 @@
   Element* area_element = GetDocument().getElementById("area");
   area_element->setAttribute(kStyleAttr,
                              "scroll-snap-align: start; scroll-margin: -8px;");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
   Element* scroller_element = GetDocument().getElementById("scroller");
   SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
   base::Optional<cc::SnapContainerData> data =
@@ -539,7 +570,7 @@
         scroll-padding-bottom: 14px;
         scroll-padding-left: 16px;
       )HTML");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
   SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
   base::Optional<cc::SnapContainerData> data =
       snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
@@ -573,7 +604,7 @@
   Element* area_element = GetDocument().getElementById("area");
   area_element->setAttribute(kStyleAttr,
                              "scroll-snap-align: end; transform: scale(4, 4);");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
   Element* scroller_element = GetDocument().getElementById("scroller");
   SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
   base::Optional<cc::SnapContainerData> data =
@@ -611,7 +642,7 @@
                              "scroll-snap-align: start; left: -200px;");
   Element* scroller_element = GetDocument().getElementById("scroller");
   scroller_element->setAttribute(kStyleAttr, "writing-mode: vertical-rl;");
-  GetDocument().UpdateStyleAndLayout();
+  UpdateAllLifecyclePhasesForTest();
   SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
   base::Optional<cc::SnapContainerData> data =
       snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
diff --git a/third_party/blink/renderer/core/page/spatial_navigation_test.cc b/third_party/blink/renderer/core/page/spatial_navigation_test.cc
index 37b916c..e5b817b1 100644
--- a/third_party/blink/renderer/core/page/spatial_navigation_test.cc
+++ b/third_party/blink/renderer/core/page/spatial_navigation_test.cc
@@ -22,7 +22,7 @@
 class SpatialNavigationTest : public RenderingTest {
  public:
   SpatialNavigationTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
   LayoutRect TopOfVisualViewport() {
     LayoutRect visual_viewport = RootViewport(&GetFrame());
diff --git a/third_party/blink/renderer/core/page/touch_adjustment_test.cc b/third_party/blink/renderer/core/page/touch_adjustment_test.cc
index c12c96c5..57eafa2 100644
--- a/third_party/blink/renderer/core/page/touch_adjustment_test.cc
+++ b/third_party/blink/renderer/core/page/touch_adjustment_test.cc
@@ -31,7 +31,7 @@
 class TouchAdjustmentTest : public RenderingTest {
  protected:
   TouchAdjustmentTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()),
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
         chrome_client_(MakeGarbageCollected<MockChromeClient>()) {}
 
   LocalFrame& GetFrame() const { return *GetDocument().GetFrame(); }
diff --git a/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc b/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc
index 9b48a50c1..cf596d2 100644
--- a/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc
+++ b/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc
@@ -21,7 +21,8 @@
 class BoxPaintInvalidatorTest : public PaintControllerPaintTest {
  public:
   BoxPaintInvalidatorTest()
-      : PaintControllerPaintTest(SingleChildLocalFrameClient::Create()) {}
+      : PaintControllerPaintTest(
+            MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
  protected:
   PaintInvalidationReason ComputePaintInvalidationReason(
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
index b315fba..06f087e 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
@@ -20,7 +20,7 @@
 class CompositedLayerMappingTest : public RenderingTest {
  public:
   CompositedLayerMappingTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
  protected:
   IntRect RecomputeInterestRect(const GraphicsLayer* graphics_layer) {
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
index 84bb888..a7f801e 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
@@ -13,7 +13,7 @@
 class CompositingInputsUpdaterTest : public RenderingTest {
  public:
   CompositingInputsUpdaterTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 };
 
 // Tests that transitioning a sticky away from an ancestor overflow layer that
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
index 0d9a581fe..1e9800b0 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
@@ -18,7 +18,7 @@
 class CompositingReasonFinderTest : public RenderingTest {
  public:
   CompositingReasonFinderTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
  private:
   void SetUp() override {
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
index fb10734..ff2fd07 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
@@ -14,7 +14,7 @@
 class CompositingRequirementsUpdaterTest : public RenderingTest {
  public:
   CompositingRequirementsUpdaterTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
   void SetUp() final;
 };
diff --git a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor_test.cc b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor_test.cc
index 2add7985..dc2990c 100644
--- a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor_test.cc
@@ -16,7 +16,7 @@
 class PaintLayerCompositorTest : public RenderingTest {
  public:
   PaintLayerCompositorTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
  private:
   void SetUp() override {
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
index c6dae94d..bd936d01 100644
--- a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
+++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
@@ -29,7 +29,7 @@
 
  public:
   ImagePaintTimingDetectorTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()),
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
         ScopedFirstContentfulPaintPlusPlusForTest(true),
         base_url_("http://www.test.com/") {}
 
diff --git a/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc b/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
index ccde698..b1af14b 100644
--- a/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
+++ b/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
@@ -22,7 +22,7 @@
 
                                               CSSLinearGradientValue>(
         nullptr, nullptr, nullptr, nullptr, nullptr, cssvalue::kRepeating);
-    return StyleGeneratedImage::Create(*gradient);
+    return MakeGarbageCollected<StyleGeneratedImage>(*gradient);
   }
 };
 
diff --git a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h
index 4ce2ac44..8512b20 100644
--- a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h
+++ b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h
@@ -15,7 +15,8 @@
 class PaintAndRasterInvalidationTest : public PaintControllerPaintTest {
  public:
   PaintAndRasterInvalidationTest()
-      : PaintControllerPaintTest(SingleChildLocalFrameClient::Create()) {}
+      : PaintControllerPaintTest(
+            MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
  protected:
   ContentLayerClientImpl* GetContentLayerClient(size_t index = 0) const {
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index 6e6c373c..c4d5ea3a8 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -3258,7 +3258,7 @@
   if (GetLayoutObject().HasReflection() && GetLayoutObject().IsBox()) {
     BoxReflection reflection = BoxReflectionForPaintLayer(*this, style);
     filter_operations.Operations().push_back(
-        BoxReflectFilterOperation::Create(reflection));
+        MakeGarbageCollected<BoxReflectFilterOperation>(reflection));
   }
   return filter_operations;
 }
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 86bfd85..360f933c 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -2439,12 +2439,13 @@
       scrollbar_size = LayoutTheme::GetTheme().ScrollbarControlSizeForPart(
           style_source.StyleRef().Appearance());
     }
-    scrollbar = Scrollbar::Create(ScrollableArea(), orientation, scrollbar_size,
-                                  &ScrollableArea()
-                                       ->GetLayoutBox()
-                                       ->GetFrame()
-                                       ->GetPage()
-                                       ->GetChromeClient());
+    scrollbar = MakeGarbageCollected<Scrollbar>(ScrollableArea(), orientation,
+                                                scrollbar_size,
+                                                &ScrollableArea()
+                                                     ->GetLayoutBox()
+                                                     ->GetFrame()
+                                                     ->GetPage()
+                                                     ->GetChromeClient());
   }
   ScrollableArea()->GetLayoutBox()->GetDocument().View()->AddScrollbar(
       scrollbar);
diff --git a/third_party/blink/renderer/core/paint/paint_layer_test.cc b/third_party/blink/renderer/core/paint/paint_layer_test.cc
index b35bf3b..0557fbd 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_test.cc
@@ -17,7 +17,8 @@
 
 class PaintLayerTest : public PaintTestConfigurations, public RenderingTest {
  public:
-  PaintLayerTest() : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+  PaintLayerTest()
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
   void SetUp() override {
     RenderingTest::SetUp();
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h
index 0166f288..07115c9 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h
@@ -20,7 +20,8 @@
 class PaintPropertyTreeBuilderTest : public PaintControllerPaintTest {
  public:
   PaintPropertyTreeBuilderTest()
-      : PaintControllerPaintTest(SingleChildLocalFrameClient::Create()) {}
+      : PaintControllerPaintTest(
+            MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
  protected:
   void LoadTestData(const char* file_name);
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc
index a34a4c94..6eda864 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc
@@ -17,7 +17,8 @@
 class PaintPropertyTreePrinterTest : public PaintControllerPaintTest {
  public:
   PaintPropertyTreePrinterTest()
-      : PaintControllerPaintTest(SingleChildLocalFrameClient::Create()) {}
+      : PaintControllerPaintTest(
+            MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
  private:
   void SetUp() override {
diff --git a/third_party/blink/renderer/core/paint/svg_filter_painter.cc b/third_party/blink/renderer/core/paint/svg_filter_painter.cc
index c0c61403..fad3c91 100644
--- a/third_party/blink/renderer/core/paint/svg_filter_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_filter_painter.cc
@@ -98,7 +98,7 @@
     return nullptr;
   }
 
-  SVGFilterGraphNodeMap* node_map = SVGFilterGraphNodeMap::Create();
+  auto* node_map = MakeGarbageCollected<SVGFilterGraphNodeMap>();
   FilterEffectBuilder builder(object.ObjectBoundingBox(), 1);
   Filter* filter = builder.BuildReferenceFilter(
       ToSVGFilterElement(*filter_.GetElement()), nullptr, node_map);
diff --git a/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc b/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
index 09118b7..f6d66c7 100644
--- a/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
+++ b/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
@@ -16,7 +16,7 @@
       private ScopedFirstContentfulPaintPlusPlusForTest {
  public:
   TextPaintTimingDetectorTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()),
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
         ScopedFirstContentfulPaintPlusPlusForTest(true) {}
   void SetUp() override {
     RenderingTest::SetUp();
diff --git a/third_party/blink/renderer/core/scroll/programmatic_scroll_animator.h b/third_party/blink/renderer/core/scroll/programmatic_scroll_animator.h
index 4e4b708f..bd2820b6 100644
--- a/third_party/blink/renderer/core/scroll/programmatic_scroll_animator.h
+++ b/third_party/blink/renderer/core/scroll/programmatic_scroll_animator.h
@@ -27,10 +27,6 @@
   DISALLOW_COPY_AND_ASSIGN(ProgrammaticScrollAnimator);
 
  public:
-  static ProgrammaticScrollAnimator* Create(ScrollableArea* scrollable_area) {
-    return MakeGarbageCollected<ProgrammaticScrollAnimator>(scrollable_area);
-  }
-
   explicit ProgrammaticScrollAnimator(ScrollableArea*);
   ~ProgrammaticScrollAnimator() override;
 
diff --git a/third_party/blink/renderer/core/scroll/scroll_animator_test.cc b/third_party/blink/renderer/core/scroll/scroll_animator_test.cc
index e2db9ab..8a5921a 100644
--- a/third_party/blink/renderer/core/scroll/scroll_animator_test.cc
+++ b/third_party/blink/renderer/core/scroll/scroll_animator_test.cc
@@ -60,14 +60,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(MockScrollableAreaForAnimatorTest);
 
  public:
-  static MockScrollableAreaForAnimatorTest* Create(
-      bool scroll_animator_enabled,
-      const ScrollOffset& min_offset,
-      const ScrollOffset& max_offset) {
-    return MakeGarbageCollected<MockScrollableAreaForAnimatorTest>(
-        scroll_animator_enabled, min_offset, max_offset);
-  }
-
   explicit MockScrollableAreaForAnimatorTest(bool scroll_animator_enabled,
                                              const ScrollOffset& min_offset,
                                              const ScrollOffset& max_offset)
@@ -191,9 +183,9 @@
 // TODO(skobes): Add unit tests for composited scrolling paths.
 
 TEST(ScrollAnimatorTest, MainThreadStates) {
-  MockScrollableAreaForAnimatorTest* scrollable_area =
-      MockScrollableAreaForAnimatorTest::Create(true, ScrollOffset(),
-                                                ScrollOffset(1000, 1000));
+  auto* scrollable_area =
+      MakeGarbageCollected<MockScrollableAreaForAnimatorTest>(
+          true, ScrollOffset(), ScrollOffset(1000, 1000));
   ScrollAnimator* scroll_animator =
       MakeGarbageCollected<ScrollAnimator>(scrollable_area, GetMockedTime);
 
@@ -245,9 +237,9 @@
 }
 
 TEST(ScrollAnimatorTest, MainThreadEnabled) {
-  MockScrollableAreaForAnimatorTest* scrollable_area =
-      MockScrollableAreaForAnimatorTest::Create(true, ScrollOffset(),
-                                                ScrollOffset(1000, 1000));
+  auto* scrollable_area =
+      MakeGarbageCollected<MockScrollableAreaForAnimatorTest>(
+          true, ScrollOffset(), ScrollOffset(1000, 1000));
   ScrollAnimator* scroll_animator =
       MakeGarbageCollected<ScrollAnimator>(scrollable_area, GetMockedTime);
 
@@ -325,9 +317,9 @@
 // Test that a smooth scroll offset animation is aborted when followed by a
 // non-smooth scroll offset animation.
 TEST(ScrollAnimatorTest, AnimatedScrollAborted) {
-  MockScrollableAreaForAnimatorTest* scrollable_area =
-      MockScrollableAreaForAnimatorTest::Create(true, ScrollOffset(),
-                                                ScrollOffset(1000, 1000));
+  auto* scrollable_area =
+      MakeGarbageCollected<MockScrollableAreaForAnimatorTest>(
+          true, ScrollOffset(), ScrollOffset(1000, 1000));
   ScrollAnimator* scroll_animator =
       MakeGarbageCollected<ScrollAnimator>(scrollable_area, GetMockedTime);
 
@@ -373,9 +365,9 @@
 // Test that a smooth scroll offset animation running on the compositor is
 // completed on the main thread.
 TEST(ScrollAnimatorTest, AnimatedScrollTakeover) {
-  MockScrollableAreaForAnimatorTest* scrollable_area =
-      MockScrollableAreaForAnimatorTest::Create(true, ScrollOffset(),
-                                                ScrollOffset(1000, 1000));
+  auto* scrollable_area =
+      MakeGarbageCollected<MockScrollableAreaForAnimatorTest>(
+          true, ScrollOffset(), ScrollOffset(1000, 1000));
   TestScrollAnimator* scroll_animator =
       MakeGarbageCollected<TestScrollAnimator>(scrollable_area, GetMockedTime);
 
@@ -425,9 +417,9 @@
 }
 
 TEST(ScrollAnimatorTest, Disabled) {
-  MockScrollableAreaForAnimatorTest* scrollable_area =
-      MockScrollableAreaForAnimatorTest::Create(false, ScrollOffset(),
-                                                ScrollOffset(1000, 1000));
+  auto* scrollable_area =
+      MakeGarbageCollected<MockScrollableAreaForAnimatorTest>(
+          false, ScrollOffset(), ScrollOffset(1000, 1000));
   ScrollAnimator* scroll_animator =
       MakeGarbageCollected<ScrollAnimator>(scrollable_area, GetMockedTime);
 
@@ -458,9 +450,9 @@
 // Test that cancelling an animation resets the animation state.
 // See crbug.com/598548.
 TEST(ScrollAnimatorTest, CancellingAnimationResetsState) {
-  MockScrollableAreaForAnimatorTest* scrollable_area =
-      MockScrollableAreaForAnimatorTest::Create(true, ScrollOffset(),
-                                                ScrollOffset(1000, 1000));
+  auto* scrollable_area =
+      MakeGarbageCollected<MockScrollableAreaForAnimatorTest>(
+          true, ScrollOffset(), ScrollOffset(1000, 1000));
   ScrollAnimator* scroll_animator =
       MakeGarbageCollected<ScrollAnimator>(scrollable_area, GetMockedTime);
 
@@ -524,9 +516,9 @@
 // Test the behavior when in WaitingToCancelOnCompositor and a new user scroll
 // happens.
 TEST(ScrollAnimatorTest, CancellingCompositorAnimation) {
-  MockScrollableAreaForAnimatorTest* scrollable_area =
-      MockScrollableAreaForAnimatorTest::Create(true, ScrollOffset(),
-                                                ScrollOffset(1000, 1000));
+  auto* scrollable_area =
+      MakeGarbageCollected<MockScrollableAreaForAnimatorTest>(
+          true, ScrollOffset(), ScrollOffset(1000, 1000));
   TestScrollAnimator* scroll_animator =
       MakeGarbageCollected<TestScrollAnimator>(scrollable_area, GetMockedTime);
 
@@ -604,9 +596,9 @@
 // This test verifies that impl only animation updates get cleared once they
 // are pushed to compositor animation host.
 TEST(ScrollAnimatorTest, ImplOnlyAnimationUpdatesCleared) {
-  MockScrollableAreaForAnimatorTest* scrollable_area =
-      MockScrollableAreaForAnimatorTest::Create(true, ScrollOffset(),
-                                                ScrollOffset(1000, 1000));
+  auto* scrollable_area =
+      MakeGarbageCollected<MockScrollableAreaForAnimatorTest>(
+          true, ScrollOffset(), ScrollOffset(1000, 1000));
   TestScrollAnimator* animator =
       MakeGarbageCollected<TestScrollAnimator>(scrollable_area, GetMockedTime);
 
@@ -642,9 +634,9 @@
 }
 
 TEST(ScrollAnimatorTest, MainThreadAnimationTargetAdjustment) {
-  MockScrollableAreaForAnimatorTest* scrollable_area =
-      MockScrollableAreaForAnimatorTest::Create(true, ScrollOffset(-100, -100),
-                                                ScrollOffset(1000, 1000));
+  auto* scrollable_area =
+      MakeGarbageCollected<MockScrollableAreaForAnimatorTest>(
+          true, ScrollOffset(-100, -100), ScrollOffset(1000, 1000));
   ScrollAnimator* animator =
       MakeGarbageCollected<ScrollAnimator>(scrollable_area, GetMockedTime);
   scrollable_area->SetScrollAnimator(animator);
diff --git a/third_party/blink/renderer/core/scroll/scrollable_area.cc b/third_party/blink/renderer/core/scroll/scrollable_area.cc
index 4f7461d..2ad539e 100644
--- a/third_party/blink/renderer/core/scroll/scrollable_area.cc
+++ b/third_party/blink/renderer/core/scroll/scrollable_area.cc
@@ -115,9 +115,11 @@
 
 ProgrammaticScrollAnimator& ScrollableArea::GetProgrammaticScrollAnimator()
     const {
-  if (!programmatic_scroll_animator_)
+  if (!programmatic_scroll_animator_) {
     programmatic_scroll_animator_ =
-        ProgrammaticScrollAnimator::Create(const_cast<ScrollableArea*>(this));
+        MakeGarbageCollected<ProgrammaticScrollAnimator>(
+            const_cast<ScrollableArea*>(this));
+  }
 
   return *programmatic_scroll_animator_;
 }
diff --git a/third_party/blink/renderer/core/scroll/scrollable_area_test.cc b/third_party/blink/renderer/core/scroll/scrollable_area_test.cc
index 65efb01..82abe1f 100644
--- a/third_party/blink/renderer/core/scroll/scrollable_area_test.cc
+++ b/third_party/blink/renderer/core/scroll/scrollable_area_test.cc
@@ -106,7 +106,7 @@
   EXPECT_CALL(*scrollable_area, LayerForHorizontalScrollbar())
       .WillRepeatedly(Return(&graphics_layer));
 
-  Scrollbar* scrollbar = Scrollbar::Create(
+  auto* scrollbar = MakeGarbageCollected<Scrollbar>(
       scrollable_area, kHorizontalScrollbar, kRegularScrollbar, nullptr);
   graphics_layer.ResetTrackedRasterInvalidations();
   scrollbar->SetNeedsPaintInvalidation(kNoPart);
diff --git a/third_party/blink/renderer/core/scroll/scrollbar.h b/third_party/blink/renderer/core/scroll/scrollbar.h
index 5936c1b..78766f6 100644
--- a/third_party/blink/renderer/core/scroll/scrollbar.h
+++ b/third_party/blink/renderer/core/scroll/scrollbar.h
@@ -48,14 +48,6 @@
 class CORE_EXPORT Scrollbar : public GarbageCollectedFinalized<Scrollbar>,
                               public DisplayItemClient {
  public:
-  static Scrollbar* Create(ScrollableArea* scrollable_area,
-                           ScrollbarOrientation orientation,
-                           ScrollbarControlSize size,
-                           ChromeClient* chrome_client) {
-    return MakeGarbageCollected<Scrollbar>(scrollable_area, orientation, size,
-                                           chrome_client);
-  }
-
   // Theme object ownership remains with the caller and it must outlive the
   // scrollbar.
   static Scrollbar* CreateForTesting(ScrollableArea* scrollable_area,
diff --git a/third_party/blink/renderer/core/streams/BUILD.gn b/third_party/blink/renderer/core/streams/BUILD.gn
index 1d8e79c..b270faa 100644
--- a/third_party/blink/renderer/core/streams/BUILD.gn
+++ b/third_party/blink/renderer/core/streams/BUILD.gn
@@ -33,9 +33,12 @@
     "stream_script_function.h",
     "transform_stream.cc",
     "transform_stream.h",
-    "transform_stream_default_controller.cc",
-    "transform_stream_default_controller.h",
+    "transform_stream_default_controller_interface.h",
+    "transform_stream_default_controller_wrapper.cc",
+    "transform_stream_default_controller_wrapper.h",
     "transform_stream_transformer.h",
+    "transform_stream_wrapper.cc",
+    "transform_stream_wrapper.h",
     "underlying_source_base.cc",
     "underlying_source_base.h",
     "writable_stream.cc",
diff --git a/third_party/blink/renderer/core/streams/transform_stream.cc b/third_party/blink/renderer/core/streams/transform_stream.cc
index 97e39f8..8454e2a 100644
--- a/third_party/blink/renderer/core/streams/transform_stream.cc
+++ b/third_party/blink/renderer/core/streams/transform_stream.cc
@@ -4,125 +4,18 @@
 
 #include "third_party/blink/renderer/core/streams/transform_stream.h"
 
-#include "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_wrapper.h"
-#include "third_party/blink/renderer/core/streams/transform_stream_default_controller.h"
 #include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
+#include "third_party/blink/renderer/core/streams/transform_stream_wrapper.h"
 #include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
 #include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
-// Base class for FlushAlgorithm and TransformAlgorithm. Contains common
-// construction code and members.
-class TransformStream::Algorithm : public ScriptFunction {
- public:
-  // This is templated just to avoid having two identical copies of the
-  // function.
-  template <typename T>
-  static v8::Local<v8::Function> Create(TransformStreamTransformer* transformer,
-                                        ScriptState* script_state,
-                                        ExceptionState& exception_state) {
-    auto* algorithm =
-        MakeGarbageCollected<T>(transformer, script_state, exception_state);
-    return algorithm->BindToV8Function();
-  }
-
-  Algorithm(TransformStreamTransformer* transformer,
-            ScriptState* script_state,
-            ExceptionState& exception_state)
-      : ScriptFunction(script_state),
-        transformer_(transformer),
-        interface_name_(exception_state.InterfaceName()),
-        property_name_(exception_state.PropertyName()) {}
-
-  void Trace(Visitor* visitor) override {
-    visitor->Trace(transformer_);
-    ScriptFunction::Trace(visitor);
-  }
-
- protected:
-  // AlgorithmScope holds the stack-allocated objects used by the CallRaw()
-  // methods for FlushAlgorithm and TransformAlgorithm.
-  class AlgorithmScope {
-    STACK_ALLOCATED();
-
-   public:
-    AlgorithmScope(Algorithm* owner,
-                   const v8::FunctionCallbackInfo<v8::Value>& info,
-                   v8::Local<v8::Value> controller)
-        : controller_(owner->GetScriptState(), controller),
-          exception_state_(owner->GetScriptState()->GetIsolate(),
-                           // Using the original context would result in every
-                           // exception claiming to have happened during
-                           // construction. Since that is not helpful, don't
-                           // annotate exceptions with where we think they came
-                           // from.
-                           ExceptionState::kUnknownContext,
-                           owner->interface_name_,
-                           owner->property_name_),
-          reject_promise_scope_(info, exception_state_) {}
-
-    TransformStreamDefaultController* GetController() { return &controller_; }
-
-    ExceptionState* GetExceptionState() { return &exception_state_; }
-
-   private:
-    TransformStreamDefaultController controller_;
-    ExceptionState exception_state_;
-    ExceptionToRejectPromiseScope reject_promise_scope_;
-  };
-
-  Member<TransformStreamTransformer> transformer_;
-  const char* const interface_name_;
-  const char* const property_name_;
-};
-
-class TransformStream::FlushAlgorithm : public TransformStream::Algorithm {
- protected:
-  using Algorithm::Algorithm;
-
- private:
-  void CallRaw(const v8::FunctionCallbackInfo<v8::Value>& info) override {
-    DCHECK_EQ(info.Length(), 1);
-    AlgorithmScope algorithm_scope(this, info, info[0]);
-    ExceptionState& exception_state = *algorithm_scope.GetExceptionState();
-
-    transformer_->Flush(algorithm_scope.GetController(), exception_state);
-    if (exception_state.HadException())
-      return;
-    V8SetReturnValue(info,
-                     ScriptPromise::CastUndefined(GetScriptState()).V8Value());
-  }
-};
-
-class TransformStream::TransformAlgorithm : public TransformStream::Algorithm {
- protected:
-  using Algorithm::Algorithm;
-
- private:
-  void CallRaw(const v8::FunctionCallbackInfo<v8::Value>& info) override {
-    DCHECK_EQ(info.Length(), 2);
-    AlgorithmScope algorithm_scope(this, info, info[1]);
-    ExceptionState& exception_state = *algorithm_scope.GetExceptionState();
-
-    transformer_->Transform(info[0], algorithm_scope.GetController(),
-                            exception_state);
-    if (exception_state.HadException())
-      return;
-    V8SetReturnValue(info,
-                     ScriptPromise::CastUndefined(GetScriptState()).V8Value());
-  }
-};
-
 TransformStream::TransformStream() = default;
 TransformStream::TransformStream(ReadableStream* readable,
                                  WritableStream* writable)
@@ -174,22 +67,13 @@
 
   auto* ts = MakeGarbageCollected<TransformStream>();
 
-  v8::Local<v8::Value> args[] = {transformer.V8Value(),
-                                 writable_strategy.V8Value(),
-                                 readable_strategy.V8Value()};
-  v8::Local<v8::Value> stream;
-  {
-    v8::TryCatch block(script_state->GetIsolate());
-    if (!V8ScriptRunner::CallExtra(script_state, "createTransformStream", args)
-             .ToLocal(&stream)) {
-      DCHECK(block.HasCaught());
-      exception_state.RethrowV8Exception(block.Exception());
-      return nullptr;
-    }
-  }
-  DCHECK(stream->IsObject());
-  if (!ts->InitInternal(script_state, stream.As<v8::Object>(), exception_state))
+  TransformStreamWrapper::InitFromJS(
+      script_state, transformer, writable_strategy, readable_strategy,
+      &ts->readable_, &ts->writable_, exception_state);
+
+  if (exception_state.HadException()) {
     return nullptr;
+  }
 
   return ts;
 }
@@ -197,24 +81,12 @@
 void TransformStream::Init(TransformStreamTransformer* transformer,
                            ScriptState* script_state,
                            ExceptionState& exception_state) {
-  auto transform_algorithm = Algorithm::Create<TransformAlgorithm>(
-      transformer, script_state, exception_state);
-  auto flush_algorithm = Algorithm::Create<FlushAlgorithm>(
-      transformer, script_state, exception_state);
-  v8::Local<v8::Value> args[] = {transform_algorithm, flush_algorithm};
-  v8::Local<v8::Value> stream;
-  {
-    v8::TryCatch block(script_state->GetIsolate());
-    if (!V8ScriptRunner::CallExtra(script_state, "createTransformStreamSimple",
-                                   args)
-             .ToLocal(&stream)) {
-      DCHECK(block.HasCaught());
-      exception_state.RethrowV8Exception(block.Exception());
-      return;
-    }
+  TransformStreamWrapper::Init(script_state, transformer, &readable_,
+                               &writable_, exception_state);
+
+  if (exception_state.HadException()) {
+    return;
   }
-  DCHECK(stream->IsObject());
-  InitInternal(script_state, stream.As<v8::Object>(), exception_state);
 }
 
 void TransformStream::Trace(Visitor* visitor) {
@@ -223,40 +95,4 @@
   ScriptWrappable::Trace(visitor);
 }
 
-bool TransformStream::InitInternal(ScriptState* script_state,
-                                   v8::Local<v8::Object> stream,
-                                   ExceptionState& exception_state) {
-  v8::Local<v8::Value> readable, writable;
-  v8::Local<v8::Value> args[] = {stream};
-  v8::TryCatch block(script_state->GetIsolate());
-  if (!V8ScriptRunner::CallExtra(script_state, "getTransformStreamReadable",
-                                 args)
-           .ToLocal(&readable)) {
-    exception_state.RethrowV8Exception(block.Exception());
-    return false;
-  }
-  if (!V8ScriptRunner::CallExtra(script_state, "getTransformStreamWritable",
-                                 args)
-           .ToLocal(&writable)) {
-    exception_state.RethrowV8Exception(block.Exception());
-    return false;
-  }
-
-  DCHECK(readable->IsObject());
-  readable_ = ReadableStreamWrapper::CreateFromInternalStream(
-      script_state, readable.As<v8::Object>(), exception_state);
-
-  if (!readable_)
-    return false;
-
-  DCHECK(writable->IsObject());
-  writable_ = WritableStreamWrapper::CreateFromInternalStream(
-      script_state, writable.As<v8::Object>(), exception_state);
-
-  if (!writable_)
-    return false;
-
-  return true;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/streams/transform_stream.h b/third_party/blink/renderer/core/streams/transform_stream.h
index 76aa9962..2704ec4 100644
--- a/third_party/blink/renderer/core/streams/transform_stream.h
+++ b/third_party/blink/renderer/core/streams/transform_stream.h
@@ -24,8 +24,8 @@
 class Visitor;
 class WritableStream;
 
-// Creates and wraps a JavaScript TransformStream object with a transformation
-// defined in C++. Provides access to the readable and writable streams.
+// Creates and wraps a (readable, writable) pair in a TransformStream object.
+// The transformation may be defined in C++ or JavaScript.
 //
 // On-heap references to this class must always be via a Member, and
 // must always have an ancestor in the V8 heap, or the internal JavaScript
diff --git a/third_party/blink/renderer/core/streams/transform_stream_default_controller.h b/third_party/blink/renderer/core/streams/transform_stream_default_controller.h
deleted file mode 100644
index c60dd5c..0000000
--- a/third_party/blink/renderer/core/streams/transform_stream_default_controller.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-// Thin wrapper for the JavaScript TransformStreamDefaultController object. The
-// API mimics the JavaScript API
-// https://streams.spec.whatwg.org/#ts-default-controller-class but unneeded
-// parts have not been implemented.
-class CORE_EXPORT TransformStreamDefaultController final {
-  STACK_ALLOCATED();
-
- public:
-  TransformStreamDefaultController(ScriptState*,
-                                   v8::Local<v8::Value> controller);
-
-  void Enqueue(v8::Local<v8::Value> chunk, ExceptionState&);
-
- private:
-  Member<ScriptState> script_state_;
-  v8::Local<v8::Value> controller_;
-
-  DISALLOW_COPY_AND_ASSIGN(TransformStreamDefaultController);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_H_
diff --git a/third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h b/third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h
new file mode 100644
index 0000000..3ce6138
--- /dev/null
+++ b/third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h
@@ -0,0 +1,37 @@
+// Copyright 2019 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 THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_INTERFACE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_INTERFACE_H_
+
+#include "base/macros.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class ExceptionState;
+
+// Thin wrapper for TransformStreamDefaultController object. This abstracts away
+// the differences between the JavaScript and C++ implementations.
+// The API mimics the JavaScript API
+// https://streams.spec.whatwg.org/#ts-default-controller-class but unneeded
+// parts have not been implemented.
+class CORE_EXPORT TransformStreamDefaultControllerInterface {
+  STACK_ALLOCATED();
+
+ public:
+  TransformStreamDefaultControllerInterface() = default;
+  virtual ~TransformStreamDefaultControllerInterface() = default;
+
+  virtual void Enqueue(v8::Local<v8::Value> chunk, ExceptionState&) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TransformStreamDefaultControllerInterface);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_INTERFACE_H_
diff --git a/third_party/blink/renderer/core/streams/transform_stream_default_controller.cc b/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.cc
similarity index 71%
rename from third_party/blink/renderer/core/streams/transform_stream_default_controller.cc
rename to third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.cc
index 8f23289..c421610 100644
--- a/third_party/blink/renderer/core/streams/transform_stream_default_controller.cc
+++ b/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.cc
@@ -2,20 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/streams/transform_stream_default_controller.h"
+#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.h"
 
 #include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
 
 namespace blink {
 
-TransformStreamDefaultController::TransformStreamDefaultController(
-    ScriptState* script_state,
-    v8::Local<v8::Value> controller)
+TransformStreamDefaultControllerWrapper::
+    TransformStreamDefaultControllerWrapper(ScriptState* script_state,
+                                            v8::Local<v8::Value> controller)
     : script_state_(script_state), controller_(controller) {
   DCHECK(controller->IsObject());
 }
 
-void TransformStreamDefaultController::Enqueue(
+void TransformStreamDefaultControllerWrapper::Enqueue(
     v8::Local<v8::Value> chunk,
     ExceptionState& exception_state) {
   DCHECK(controller_->IsObject());
diff --git a/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.h b/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.h
new file mode 100644
index 0000000..7c60936
--- /dev/null
+++ b/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.h
@@ -0,0 +1,38 @@
+// Copyright 2019 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 THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_WRAPPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_WRAPPER_H_
+
+#include "base/macros.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+// Implementation of TransformStreamDefaultControllerInterface for the V8 Extras
+// implementation of Streams.
+class CORE_EXPORT TransformStreamDefaultControllerWrapper final
+    : public TransformStreamDefaultControllerInterface {
+  STACK_ALLOCATED();
+
+ public:
+  TransformStreamDefaultControllerWrapper(ScriptState*,
+                                          v8::Local<v8::Value> controller);
+
+  void Enqueue(v8::Local<v8::Value> chunk, ExceptionState&) override;
+
+ private:
+  Member<ScriptState> script_state_;
+  v8::Local<v8::Value> controller_;
+
+  DISALLOW_COPY_AND_ASSIGN(TransformStreamDefaultControllerWrapper);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_WRAPPER_H_
diff --git a/third_party/blink/renderer/core/streams/transform_stream_test.cc b/third_party/blink/renderer/core/streams/transform_stream_test.cc
index 607778d..774ff47 100644
--- a/third_party/blink/renderer/core/streams/transform_stream_test.cc
+++ b/third_party/blink/renderer/core/streams/transform_stream_test.cc
@@ -15,7 +15,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
 #include "third_party/blink/renderer/core/streams/readable_stream.h"
 #include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
-#include "third_party/blink/renderer/core/streams/transform_stream_default_controller.h"
+#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h"
 #include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
 #include "third_party/blink/renderer/core/streams/writable_stream.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
@@ -113,12 +113,12 @@
 class IdentityTransformer final : public TransformStreamTransformer {
  public:
   void Transform(v8::Local<v8::Value> chunk,
-                 TransformStreamDefaultController* controller,
+                 TransformStreamDefaultControllerInterface* controller,
                  ExceptionState& exception_state) override {
     controller->Enqueue(chunk, exception_state);
   }
 
-  void Flush(TransformStreamDefaultController* controller,
+  void Flush(TransformStreamDefaultControllerInterface* controller,
              ExceptionState& exception_state) override {}
 };
 
@@ -126,9 +126,11 @@
  public:
   MOCK_METHOD3(Transform,
                void(v8::Local<v8::Value> chunk,
-                    TransformStreamDefaultController*,
+                    TransformStreamDefaultControllerInterface*,
                     ExceptionState&));
-  MOCK_METHOD2(Flush, void(TransformStreamDefaultController*, ExceptionState&));
+  MOCK_METHOD2(Flush,
+               void(TransformStreamDefaultControllerInterface*,
+                    ExceptionState&));
 };
 
 // If this doesn't work then nothing else will.
@@ -328,9 +330,9 @@
         : global_(global), isolate_(isolate) {}
 
     void Transform(v8::Local<v8::Value>,
-                   TransformStreamDefaultController*,
+                   TransformStreamDefaultControllerInterface*,
                    ExceptionState&) override {}
-    void Flush(TransformStreamDefaultController* controller,
+    void Flush(TransformStreamDefaultControllerInterface* controller,
                ExceptionState& exception_state) override {
       controller->Enqueue(ToV8("a", global_, isolate_), exception_state);
     }
@@ -366,11 +368,12 @@
   class ThrowFromTransformTransformer : public TransformStreamTransformer {
    public:
     void Transform(v8::Local<v8::Value>,
-                   TransformStreamDefaultController*,
+                   TransformStreamDefaultControllerInterface*,
                    ExceptionState& exception_state) override {
       exception_state.ThrowTypeError(kMessage);
     }
-    void Flush(TransformStreamDefaultController*, ExceptionState&) override {}
+    void Flush(TransformStreamDefaultControllerInterface*,
+               ExceptionState&) override {}
   };
   V8TestingScope scope;
   auto* script_state = scope.GetScriptState();
@@ -406,9 +409,9 @@
   class ThrowFromFlushTransformer : public TransformStreamTransformer {
    public:
     void Transform(v8::Local<v8::Value>,
-                   TransformStreamDefaultController*,
+                   TransformStreamDefaultControllerInterface*,
                    ExceptionState&) override {}
-    void Flush(TransformStreamDefaultController*,
+    void Flush(TransformStreamDefaultControllerInterface*,
                ExceptionState& exception_state) override {
       exception_state.ThrowTypeError(kMessage);
     }
diff --git a/third_party/blink/renderer/core/streams/transform_stream_transformer.h b/third_party/blink/renderer/core/streams/transform_stream_transformer.h
index 46b7f9a7..9fc6d91 100644
--- a/third_party/blink/renderer/core/streams/transform_stream_transformer.h
+++ b/third_party/blink/renderer/core/streams/transform_stream_transformer.h
@@ -14,7 +14,7 @@
 namespace blink {
 
 class ExceptionState;
-class TransformStreamDefaultController;
+class TransformStreamDefaultControllerInterface;
 class Visitor;
 
 // Interface to be implemented by C++ code that needs to create a
@@ -33,9 +33,10 @@
   virtual ~TransformStreamTransformer() = default;
 
   virtual void Transform(v8::Local<v8::Value> chunk,
-                         TransformStreamDefaultController*,
+                         TransformStreamDefaultControllerInterface*,
                          ExceptionState&) = 0;
-  virtual void Flush(TransformStreamDefaultController*, ExceptionState&) = 0;
+  virtual void Flush(TransformStreamDefaultControllerInterface*,
+                     ExceptionState&) = 0;
 
   virtual void Trace(Visitor*) {}
 
diff --git a/third_party/blink/renderer/core/streams/transform_stream_wrapper.cc b/third_party/blink/renderer/core/streams/transform_stream_wrapper.cc
new file mode 100644
index 0000000..5069438
--- /dev/null
+++ b/third_party/blink/renderer/core/streams/transform_stream_wrapper.cc
@@ -0,0 +1,222 @@
+// Copyright 2019 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 "third_party/blink/renderer/core/streams/transform_stream_wrapper.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
+#include "third_party/blink/renderer/core/streams/readable_stream.h"
+#include "third_party/blink/renderer/core/streams/readable_stream_wrapper.h"
+#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h"
+#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.h"
+#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
+#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
+
+namespace blink {
+
+// Base class for FlushAlgorithm and TransformAlgorithm. Contains common
+// construction code and members.
+class TransformStreamWrapper::Algorithm : public ScriptFunction {
+ public:
+  // This is templated just to avoid having two identical copies of the
+  // function.
+  template <typename T>
+  static v8::Local<v8::Function> Create(TransformStreamTransformer* transformer,
+                                        ScriptState* script_state,
+                                        ExceptionState& exception_state) {
+    auto* algorithm =
+        MakeGarbageCollected<T>(transformer, script_state, exception_state);
+    return algorithm->BindToV8Function();
+  }
+
+  Algorithm(TransformStreamTransformer* transformer,
+            ScriptState* script_state,
+            ExceptionState& exception_state)
+      : ScriptFunction(script_state),
+        transformer_(transformer),
+        interface_name_(exception_state.InterfaceName()),
+        property_name_(exception_state.PropertyName()) {}
+
+  void Trace(Visitor* visitor) override {
+    visitor->Trace(transformer_);
+    ScriptFunction::Trace(visitor);
+  }
+
+ protected:
+  // AlgorithmScope holds the stack-allocated objects used by the CallRaw()
+  // methods for FlushAlgorithm and TransformAlgorithm.
+  class AlgorithmScope {
+    STACK_ALLOCATED();
+
+   public:
+    AlgorithmScope(Algorithm* owner,
+                   const v8::FunctionCallbackInfo<v8::Value>& info,
+                   v8::Local<v8::Value> controller)
+        : controller_(owner->GetScriptState(), controller),
+          exception_state_(owner->GetScriptState()->GetIsolate(),
+                           // Using the original context would result in every
+                           // exception claiming to have happened during
+                           // construction. Since that is not helpful, don't
+                           // annotate exceptions with where we think they came
+                           // from.
+                           ExceptionState::kUnknownContext,
+                           owner->interface_name_,
+                           owner->property_name_),
+          reject_promise_scope_(info, exception_state_) {}
+
+    TransformStreamDefaultControllerInterface* GetController() {
+      return &controller_;
+    }
+
+    ExceptionState* GetExceptionState() { return &exception_state_; }
+
+   private:
+    TransformStreamDefaultControllerWrapper controller_;
+    ExceptionState exception_state_;
+    ExceptionToRejectPromiseScope reject_promise_scope_;
+  };
+
+  Member<TransformStreamTransformer> transformer_;
+  const char* const interface_name_;
+  const char* const property_name_;
+};
+
+class TransformStreamWrapper::FlushAlgorithm
+    : public TransformStreamWrapper::Algorithm {
+ protected:
+  using Algorithm::Algorithm;
+
+ private:
+  void CallRaw(const v8::FunctionCallbackInfo<v8::Value>& info) override {
+    DCHECK_EQ(info.Length(), 1);
+    AlgorithmScope algorithm_scope(this, info, info[0]);
+    ExceptionState& exception_state = *algorithm_scope.GetExceptionState();
+
+    transformer_->Flush(algorithm_scope.GetController(), exception_state);
+    if (exception_state.HadException())
+      return;
+    V8SetReturnValue(info,
+                     ScriptPromise::CastUndefined(GetScriptState()).V8Value());
+  }
+};
+
+class TransformStreamWrapper::TransformAlgorithm
+    : public TransformStreamWrapper::Algorithm {
+ protected:
+  using Algorithm::Algorithm;
+
+ private:
+  void CallRaw(const v8::FunctionCallbackInfo<v8::Value>& info) override {
+    DCHECK_EQ(info.Length(), 2);
+    AlgorithmScope algorithm_scope(this, info, info[1]);
+    ExceptionState& exception_state = *algorithm_scope.GetExceptionState();
+
+    transformer_->Transform(info[0], algorithm_scope.GetController(),
+                            exception_state);
+    if (exception_state.HadException())
+      return;
+    V8SetReturnValue(info,
+                     ScriptPromise::CastUndefined(GetScriptState()).V8Value());
+  }
+};
+
+// static
+void TransformStreamWrapper::InitFromJS(ScriptState* script_state,
+                                        ScriptValue transformer,
+                                        ScriptValue writable_strategy,
+                                        ScriptValue readable_strategy,
+                                        Member<ReadableStream>* readable,
+                                        Member<WritableStream>* writable,
+                                        ExceptionState& exception_state) {
+  DCHECK(!RuntimeEnabledFeatures::StreamsNativeEnabled());
+
+  v8::Local<v8::Value> args[] = {transformer.V8Value(),
+                                 writable_strategy.V8Value(),
+                                 readable_strategy.V8Value()};
+  v8::Local<v8::Value> stream;
+  {
+    v8::TryCatch block(script_state->GetIsolate());
+    if (!V8ScriptRunner::CallExtra(script_state, "createTransformStream", args)
+             .ToLocal(&stream)) {
+      DCHECK(block.HasCaught());
+      exception_state.RethrowV8Exception(block.Exception());
+      return;
+    }
+  }
+  DCHECK(stream->IsObject());
+  InitInternal(script_state, stream.As<v8::Object>(), readable, writable,
+               exception_state);
+}
+
+// static
+void TransformStreamWrapper::Init(ScriptState* script_state,
+                                  TransformStreamTransformer* transformer,
+                                  Member<ReadableStream>* readable,
+                                  Member<WritableStream>* writable,
+                                  ExceptionState& exception_state) {
+  auto transform_algorithm = Algorithm::Create<TransformAlgorithm>(
+      transformer, script_state, exception_state);
+  auto flush_algorithm = Algorithm::Create<FlushAlgorithm>(
+      transformer, script_state, exception_state);
+  v8::Local<v8::Value> args[] = {transform_algorithm, flush_algorithm};
+  v8::Local<v8::Value> stream;
+  {
+    v8::TryCatch block(script_state->GetIsolate());
+    if (!V8ScriptRunner::CallExtra(script_state, "createTransformStreamSimple",
+                                   args)
+             .ToLocal(&stream)) {
+      DCHECK(block.HasCaught());
+      exception_state.RethrowV8Exception(block.Exception());
+      return;
+    }
+  }
+  DCHECK(stream->IsObject());
+  InitInternal(script_state, stream.As<v8::Object>(), readable, writable,
+               exception_state);
+}
+
+// static
+void TransformStreamWrapper::InitInternal(ScriptState* script_state,
+                                          v8::Local<v8::Object> stream,
+                                          Member<ReadableStream>* readable_out,
+                                          Member<WritableStream>* writable_out,
+                                          ExceptionState& exception_state) {
+  v8::Local<v8::Value> readable, writable;
+  v8::Local<v8::Value> args[] = {stream};
+  v8::TryCatch block(script_state->GetIsolate());
+  if (!V8ScriptRunner::CallExtra(script_state, "getTransformStreamReadable",
+                                 args)
+           .ToLocal(&readable)) {
+    exception_state.RethrowV8Exception(block.Exception());
+    return;
+  }
+  if (!V8ScriptRunner::CallExtra(script_state, "getTransformStreamWritable",
+                                 args)
+           .ToLocal(&writable)) {
+    exception_state.RethrowV8Exception(block.Exception());
+    return;
+  }
+
+  DCHECK(readable->IsObject());
+  *readable_out = ReadableStreamWrapper::CreateFromInternalStream(
+      script_state, readable.As<v8::Object>(), exception_state);
+
+  if (!*readable_out)
+    return;
+
+  DCHECK(writable->IsObject());
+  *writable_out = WritableStreamWrapper::CreateFromInternalStream(
+      script_state, writable.As<v8::Object>(), exception_state);
+
+  return;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/streams/transform_stream_wrapper.h b/third_party/blink/renderer/core/streams/transform_stream_wrapper.h
new file mode 100644
index 0000000..0f26714
--- /dev/null
+++ b/third_party/blink/renderer/core/streams/transform_stream_wrapper.h
@@ -0,0 +1,58 @@
+// Copyright 2019 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 THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_WRAPPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_WRAPPER_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class ExceptionState;
+class ReadableStream;
+class ScriptState;
+class TransformStreamTransformer;
+class WritableStream;
+
+// Helpers to create a TransformStream using V8 Extras. This is not a subclass
+// of TransformStream, because it is only needed during creation of the object.
+class TransformStreamWrapper {
+  STATIC_ONLY(TransformStreamWrapper);
+
+ public:
+  // Creates a (readable, writable) pair from JS objects.
+  static void InitFromJS(ScriptState*,
+                         ScriptValue transformer,
+                         ScriptValue writable_strategy,
+                         ScriptValue readable_strategy,
+                         Member<ReadableStream>*,
+                         Member<WritableStream>*,
+                         ExceptionState&);
+
+  // Creates a (readable, writable) pair from a C++ object.
+  static void Init(ScriptState*,
+                   TransformStreamTransformer*,
+                   Member<ReadableStream>*,
+                   Member<WritableStream>*,
+                   ExceptionState&);
+
+ private:
+  class Algorithm;
+  class FlushAlgorithm;
+  class TransformAlgorithm;
+
+  // Creates a (readable, writable) pair from an internal V8 Extras
+  // TransformStream object.
+  static void InitInternal(ScriptState*,
+                           v8::Local<v8::Object> stream,
+                           Member<ReadableStream>*,
+                           Member<WritableStream>*,
+                           ExceptionState&);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_WRAPPER_H_
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index 87221513..7580d12 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -1153,7 +1153,7 @@
   void RemoveVariable(const AtomicString&, bool is_inherited_property);
 
   // Handles both inherited and non-inherited variables
-  CSSVariableData* GetVariable(const AtomicString&) const;
+  CORE_EXPORT CSSVariableData* GetVariable(const AtomicString&) const;
 
   CSSVariableData* GetVariable(const AtomicString&,
                                bool is_inherited_property) const;
diff --git a/third_party/blink/renderer/core/style/computed_style_test.cc b/third_party/blink/renderer/core/style/computed_style_test.cc
index a75e5b2..fda48d5 100644
--- a/third_party/blink/renderer/core/style/computed_style_test.cc
+++ b/third_party/blink/renderer/core/style/computed_style_test.cc
@@ -326,8 +326,9 @@
   auto* gradient = MakeGarbageCollected<cssvalue::CSSLinearGradientValue>(
       nullptr, nullptr, nullptr, nullptr, nullptr, cssvalue::kRepeating);
 
-  StyleImage* image_value = StyleGeneratedImage::Create(*gradient);
-  StyleImage* other_image_value = StyleGeneratedImage::Create(*gradient);
+  auto* image_value = MakeGarbageCollected<StyleGeneratedImage>(*gradient);
+  auto* other_image_value =
+      MakeGarbageCollected<StyleGeneratedImage>(*gradient);
 
   EXPECT_TRUE(DataEquivalent(image_value, other_image_value));
 
diff --git a/third_party/blink/renderer/core/style/filter_operation.cc b/third_party/blink/renderer/core/style/filter_operation.cc
index 9d1dea87..5f504419 100644
--- a/third_party/blink/renderer/core/style/filter_operation.cc
+++ b/third_party/blink/renderer/core/style/filter_operation.cc
@@ -115,7 +115,7 @@
     default:
       NOTREACHED();
   }
-  return BasicColorMatrixFilterOperation::Create(result, type_);
+  return MakeGarbageCollected<BasicColorMatrixFilterOperation>(result, type_);
 }
 
 FilterOperation* BasicComponentTransferFilterOperation::Blend(
@@ -154,7 +154,8 @@
     default:
       NOTREACHED();
   }
-  return BasicComponentTransferFilterOperation::Create(result, type_);
+  return MakeGarbageCollected<BasicComponentTransferFilterOperation>(result,
+                                                                     type_);
 }
 
 FloatRect BlurFilterOperation::MapRect(const FloatRect& rect) const {
@@ -167,11 +168,11 @@
                                             double progress) const {
   Length::Type length_type = std_deviation_.GetType();
   if (!from)
-    return BlurFilterOperation::Create(std_deviation_.Blend(
+    return MakeGarbageCollected<BlurFilterOperation>(std_deviation_.Blend(
         Length(length_type), progress, kValueRangeNonNegative));
 
   const auto* from_op = To<BlurFilterOperation>(from);
-  return BlurFilterOperation::Create(std_deviation_.Blend(
+  return MakeGarbageCollected<BlurFilterOperation>(std_deviation_.Blend(
       from_op->std_deviation_, progress, kValueRangeNonNegative));
 }
 
diff --git a/third_party/blink/renderer/core/style/filter_operation.h b/third_party/blink/renderer/core/style/filter_operation.h
index d7b40f6..10f8dfb4 100644
--- a/third_party/blink/renderer/core/style/filter_operation.h
+++ b/third_party/blink/renderer/core/style/filter_operation.h
@@ -126,11 +126,6 @@
 
 class CORE_EXPORT ReferenceFilterOperation : public FilterOperation {
  public:
-  static ReferenceFilterOperation* Create(const AtomicString& url,
-                                          SVGResource* resource) {
-    return MakeGarbageCollected<ReferenceFilterOperation>(url, resource);
-  }
-
   ReferenceFilterOperation(const AtomicString& url, SVGResource*);
 
   bool AffectsOpacity() const override { return true; }
@@ -174,11 +169,6 @@
 // matrix effect.  For HUE_ROTATE, the angle of rotation is stored in m_amount.
 class CORE_EXPORT BasicColorMatrixFilterOperation : public FilterOperation {
  public:
-  static BasicColorMatrixFilterOperation* Create(double amount,
-                                                 OperationType type) {
-    return MakeGarbageCollected<BasicColorMatrixFilterOperation>(amount, type);
-  }
-
   BasicColorMatrixFilterOperation(double amount, OperationType type)
       : FilterOperation(type), amount_(amount) {}
 
@@ -218,12 +208,6 @@
 class CORE_EXPORT BasicComponentTransferFilterOperation
     : public FilterOperation {
  public:
-  static BasicComponentTransferFilterOperation* Create(double amount,
-                                                       OperationType type) {
-    return MakeGarbageCollected<BasicComponentTransferFilterOperation>(amount,
-                                                                       type);
-  }
-
   BasicComponentTransferFilterOperation(double amount, OperationType type)
       : FilterOperation(type), amount_(amount) {}
 
@@ -262,11 +246,7 @@
 
 class CORE_EXPORT BlurFilterOperation : public FilterOperation {
  public:
-  static BlurFilterOperation* Create(const Length& std_deviation) {
-    return MakeGarbageCollected<BlurFilterOperation>(std_deviation);
-  }
-
-  BlurFilterOperation(const Length& std_deviation)
+  explicit BlurFilterOperation(const Length& std_deviation)
       : FilterOperation(BLUR), std_deviation_(std_deviation) {}
 
   const Length& StdDeviation() const { return std_deviation_; }
@@ -334,11 +314,7 @@
 
 class CORE_EXPORT BoxReflectFilterOperation : public FilterOperation {
  public:
-  static BoxReflectFilterOperation* Create(const BoxReflection& reflection) {
-    return MakeGarbageCollected<BoxReflectFilterOperation>(reflection);
-  }
-
-  BoxReflectFilterOperation(const BoxReflection& reflection)
+  explicit BoxReflectFilterOperation(const BoxReflection& reflection)
       : FilterOperation(BOX_REFLECT), reflection_(reflection) {}
 
   const BoxReflection& Reflection() const { return reflection_; }
diff --git a/third_party/blink/renderer/core/style/filter_operations.h b/third_party/blink/renderer/core/style/filter_operations.h
index f71b359..6b90e1b 100644
--- a/third_party/blink/renderer/core/style/filter_operations.h
+++ b/third_party/blink/renderer/core/style/filter_operations.h
@@ -85,14 +85,6 @@
 class FilterOperationsWrapper
     : public GarbageCollected<FilterOperationsWrapper> {
  public:
-  static FilterOperationsWrapper* Create() {
-    return MakeGarbageCollected<FilterOperationsWrapper>();
-  }
-
-  static FilterOperationsWrapper* Create(const FilterOperations& operations) {
-    return MakeGarbageCollected<FilterOperationsWrapper>(operations);
-  }
-
   FilterOperationsWrapper() = default;
   explicit FilterOperationsWrapper(const FilterOperations& operations)
       : operations_(operations) {}
diff --git a/third_party/blink/renderer/core/style/filter_operations_test.cc b/third_party/blink/renderer/core/style/filter_operations_test.cc
index 6682791..2e66f20f 100644
--- a/third_party/blink/renderer/core/style/filter_operations_test.cc
+++ b/third_party/blink/renderer/core/style/filter_operations_test.cc
@@ -38,7 +38,8 @@
 
 TEST(FilterOperationsTest, mapRectBlur) {
   FilterOperations ops;
-  ops.Operations().push_back(BlurFilterOperation::Create(Length::Fixed(20.0)));
+  ops.Operations().push_back(
+      MakeGarbageCollected<BlurFilterOperation>(Length::Fixed(20.0)));
   EXPECT_TRUE(ops.HasFilterThatMovesPixels());
   EXPECT_EQ(IntRect(-57, -57, 124, 124),
             EnclosingIntRect(ops.MapRect(FloatRect(0, 0, 10, 10))));
@@ -55,7 +56,7 @@
 
 TEST(FilterOperationsTest, mapRectBoxReflect) {
   FilterOperations ops;
-  ops.Operations().push_back(BoxReflectFilterOperation::Create(
+  ops.Operations().push_back(MakeGarbageCollected<BoxReflectFilterOperation>(
       BoxReflection(BoxReflection::kVerticalReflection, 100)));
   EXPECT_TRUE(ops.HasFilterThatMovesPixels());
 
@@ -69,7 +70,7 @@
   FilterOperations ops;
   ops.Operations().push_back(DropShadowFilterOperation::Create(ShadowData(
       FloatPoint(100, 200), 0, 0, kNormal, StyleColor(Color::kBlack))));
-  ops.Operations().push_back(BoxReflectFilterOperation::Create(
+  ops.Operations().push_back(MakeGarbageCollected<BoxReflectFilterOperation>(
       BoxReflection(BoxReflection::kVerticalReflection, 50)));
   EXPECT_TRUE(ops.HasFilterThatMovesPixels());
   EXPECT_EQ(FloatRect(0, -160, 110, 370), ops.MapRect(FloatRect(0, 0, 10, 10)));
diff --git a/third_party/blink/renderer/core/style/style_fetched_image.cc b/third_party/blink/renderer/core/style/style_fetched_image.cc
index a100e3f..f6586b4 100644
--- a/third_party/blink/renderer/core/style/style_fetched_image.cc
+++ b/third_party/blink/renderer/core/style/style_fetched_image.cc
@@ -23,8 +23,11 @@
 
 #include "third_party/blink/renderer/core/style/style_fetched_image.h"
 
+#include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/renderer/core/css/css_image_value.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
@@ -163,6 +166,10 @@
   DCHECK(is_lazyload_possibly_deferred_);
   is_lazyload_possibly_deferred_ = false;
   document_ = &document;
+  if (document.GetFrame() && document.GetFrame()->Client()) {
+    document.GetFrame()->Client()->DidObserveLazyLoadBehavior(
+        WebLocalFrameClient::LazyLoadBehavior::kLazyLoadedImage);
+  }
   image_->LoadDeferredImage(document_->Fetcher());
 }
 
diff --git a/third_party/blink/renderer/core/style/style_fetched_image.h b/third_party/blink/renderer/core/style/style_fetched_image.h
index 3039806..6371282 100644
--- a/third_party/blink/renderer/core/style/style_fetched_image.h
+++ b/third_party/blink/renderer/core/style/style_fetched_image.h
@@ -41,13 +41,6 @@
   USING_PRE_FINALIZER(StyleFetchedImage, Dispose);
 
  public:
-  static StyleFetchedImage* Create(const Document& document,
-                                   FetchParameters& params,
-                                   bool is_lazyload_deferred) {
-    return MakeGarbageCollected<StyleFetchedImage>(document, params,
-                                                   is_lazyload_deferred);
-  }
-
   StyleFetchedImage(const Document&,
                     FetchParameters&,
                     bool is_lazyload_deferred);
diff --git a/third_party/blink/renderer/core/style/style_fetched_image_set.h b/third_party/blink/renderer/core/style/style_fetched_image_set.h
index b45894c..e993b2b 100644
--- a/third_party/blink/renderer/core/style/style_fetched_image_set.h
+++ b/third_party/blink/renderer/core/style/style_fetched_image_set.h
@@ -47,14 +47,6 @@
   USING_PRE_FINALIZER(StyleFetchedImageSet, Dispose);
 
  public:
-  static StyleFetchedImageSet* Create(ImageResourceContent* image,
-                                      float image_scale_factor,
-                                      CSSImageSetValue* value,
-                                      const KURL& url) {
-    return MakeGarbageCollected<StyleFetchedImageSet>(image, image_scale_factor,
-                                                      value, url);
-  }
-
   StyleFetchedImageSet(ImageResourceContent*,
                        float image_scale_factor,
                        CSSImageSetValue*,
diff --git a/third_party/blink/renderer/core/style/style_filter_data.h b/third_party/blink/renderer/core/style/style_filter_data.h
index 98b5b13a..cf416fe0 100644
--- a/third_party/blink/renderer/core/style/style_filter_data.h
+++ b/third_party/blink/renderer/core/style/style_filter_data.h
@@ -33,10 +33,6 @@
 
 class StyleFilterData final : public GarbageCollected<StyleFilterData> {
  public:
-  static StyleFilterData* Create() {
-    return MakeGarbageCollected<StyleFilterData>();
-  }
-
   StyleFilterData();
   explicit StyleFilterData(const StyleFilterData&);
 
diff --git a/third_party/blink/renderer/core/style/style_generated_image.h b/third_party/blink/renderer/core/style/style_generated_image.h
index d350642..5fdb3eb 100644
--- a/third_party/blink/renderer/core/style/style_generated_image.h
+++ b/third_party/blink/renderer/core/style/style_generated_image.h
@@ -39,11 +39,7 @@
 // paint(...) function.
 class CORE_EXPORT StyleGeneratedImage final : public StyleImage {
  public:
-  static StyleGeneratedImage* Create(const CSSImageGeneratorValue& value) {
-    return MakeGarbageCollected<StyleGeneratedImage>(value);
-  }
-
-  StyleGeneratedImage(const CSSImageGeneratorValue&);
+  explicit StyleGeneratedImage(const CSSImageGeneratorValue&);
 
   WrappedImagePtr Data() const override { return image_generator_value_.Get(); }
 
diff --git a/third_party/blink/renderer/core/style/style_pending_image.h b/third_party/blink/renderer/core/style/style_pending_image.h
index d99b114..37a8af2 100644
--- a/third_party/blink/renderer/core/style/style_pending_image.h
+++ b/third_party/blink/renderer/core/style/style_pending_image.h
@@ -44,10 +44,6 @@
 // ComputedStyle after it has been returned from the style selector.
 class StylePendingImage final : public StyleImage {
  public:
-  static StylePendingImage* Create(const CSSValue& value) {
-    return MakeGarbageCollected<StylePendingImage>(value);
-  }
-
   explicit StylePendingImage(const CSSValue& value)
       : value_(const_cast<CSSValue*>(&value)) {
     is_pending_image_ = true;
diff --git a/third_party/blink/renderer/core/svg/animation/smil_time_container.h b/third_party/blink/renderer/core/svg/animation/smil_time_container.h
index eaee06b..ad3e1ad 100644
--- a/third_party/blink/renderer/core/svg/animation/smil_time_container.h
+++ b/third_party/blink/renderer/core/svg/animation/smil_time_container.h
@@ -45,10 +45,6 @@
 
 class SMILTimeContainer : public GarbageCollectedFinalized<SMILTimeContainer> {
  public:
-  static SMILTimeContainer* Create(SVGSVGElement& owner) {
-    return MakeGarbageCollected<SMILTimeContainer>(owner);
-  }
-
   explicit SMILTimeContainer(SVGSVGElement& owner);
   ~SMILTimeContainer();
 
diff --git a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
index 1c727cd..84fe45a 100644
--- a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
+++ b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
@@ -78,11 +78,6 @@
 
 class ConditionEventListener final : public NativeEventListener {
  public:
-  static ConditionEventListener* Create(SVGSMILElement* animation,
-                                        SVGSMILElement::Condition* condition) {
-    return MakeGarbageCollected<ConditionEventListener>(animation, condition);
-  }
-
   ConditionEventListener(SVGSMILElement* animation,
                          SVGSMILElement::Condition* condition)
       : animation_(animation), condition_(condition) {}
@@ -193,7 +188,8 @@
   if (!target || !target->IsSVGElement())
     return;
   DCHECK(!event_listener_);
-  event_listener_ = ConditionEventListener::Create(&timed_element, this);
+  event_listener_ =
+      MakeGarbageCollected<ConditionEventListener>(&timed_element, this);
   base_element_ = ToSVGElement(target);
   base_element_->addEventListener(name_, event_listener_, false);
   timed_element.AddReferenceTo(base_element_);
@@ -473,9 +469,9 @@
     type = Condition::kEventBase;
   }
 
-  conditions_.push_back(
-      Condition::Create(type, begin_or_end, AtomicString(base_id),
-                        AtomicString(name_string), offset, repeat));
+  conditions_.push_back(MakeGarbageCollected<Condition>(
+      type, begin_or_end, AtomicString(base_id), AtomicString(name_string),
+      offset, repeat));
 
   if (type == Condition::kEventBase && begin_or_end == kEnd)
     has_end_event_conditions_ = true;
diff --git a/third_party/blink/renderer/core/svg/animation/svg_smil_element.h b/third_party/blink/renderer/core/svg/animation/svg_smil_element.h
index ccca384..5ff56d7 100644
--- a/third_party/blink/renderer/core/svg/animation/svg_smil_element.h
+++ b/third_party/blink/renderer/core/svg/animation/svg_smil_element.h
@@ -186,16 +186,6 @@
    public:
     enum Type { kEventBase, kSyncbase, kAccessKey };
 
-    static Condition* Create(Type type,
-                             BeginOrEnd begin_or_end,
-                             const AtomicString& base_id,
-                             const AtomicString& name,
-                             SMILTime offset,
-                             int repeat = -1) {
-      return MakeGarbageCollected<Condition>(type, begin_or_end, base_id, name,
-                                             offset, repeat);
-    }
-
     Condition(Type,
               BeginOrEnd,
               const AtomicString& base_id,
diff --git a/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h b/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h
index f112e88..e532659 100644
--- a/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h
+++ b/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h
@@ -42,10 +42,6 @@
 class SVGFilterGraphNodeMap final
     : public GarbageCollected<SVGFilterGraphNodeMap> {
  public:
-  static SVGFilterGraphNodeMap* Create() {
-    return MakeGarbageCollected<SVGFilterGraphNodeMap>();
-  }
-
   SVGFilterGraphNodeMap();
 
   typedef HeapHashSet<Member<FilterEffect>> FilterEffectSet;
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image.cc b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
index 1106d5a6..551f3a6 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image.cc
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
@@ -429,6 +429,11 @@
   if (SkColorGetA(flags.getColor()) < 255)
     return true;
 
+  // This is needed to preserve the dark mode filter that
+  // has been set in GraphicsContext.
+  if (flags.getColorFilter())
+    return true;
+
   return flags.getBlendMode() != SkBlendMode::kSrcOver;
 }
 
@@ -744,7 +749,7 @@
 
   Page::PageClients page_clients;
   FillWithEmptyClients(page_clients);
-  chrome_client_ = SVGImageChromeClient::Create(this);
+  chrome_client_ = MakeGarbageCollected<SVGImageChromeClient>(this);
   page_clients.chrome_client = chrome_client_.Get();
 
   // FIXME: If this SVG ends up loading itself, we might leak the world.
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
index fe25613..05898236 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
@@ -49,10 +49,6 @@
           &SVGImageChromeClient::AnimationTimerFired)),
       timeline_state_(kRunning) {}
 
-SVGImageChromeClient* SVGImageChromeClient::Create(SVGImage* image) {
-  return MakeGarbageCollected<SVGImageChromeClient>(image);
-}
-
 bool SVGImageChromeClient::IsSVGImageChromeClient() const {
   return true;
 }
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
index 5953da2d..ead7000f 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
@@ -41,8 +41,6 @@
 
 class CORE_EXPORT SVGImageChromeClient final : public EmptyChromeClient {
  public:
-  static SVGImageChromeClient* Create(SVGImage*);
-
   explicit SVGImageChromeClient(SVGImage*);
 
   bool IsSVGImageChromeClient() const override;
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h b/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h
index cc2fe31f..63e8dcf 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h
@@ -88,6 +88,8 @@
 
   PaintImage PaintImageForCurrentFrame() override;
 
+  bool IsSVGImageForContainer() const override { return true; }
+
  protected:
   void DrawPattern(GraphicsContext&,
                    const FloatRect&,
diff --git a/third_party/blink/renderer/core/svg/svg_pattern_element.cc b/third_party/blink/renderer/core/svg/svg_pattern_element.cc
index 96f3536..f6213d5 100644
--- a/third_party/blink/renderer/core/svg/svg_pattern_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_pattern_element.cc
@@ -246,8 +246,7 @@
 }
 
 const SVGPatternElement* SVGPatternElement::ReferencedElement() const {
-  return ToSVGPatternElementOrNull(
-      TargetElementFromIRIString(HrefString(), GetTreeScope()));
+  return ToSVGPatternElementOrNull(resource_ ? resource_->Target() : nullptr);
 }
 
 void SVGPatternElement::CollectPatternAttributes(
diff --git a/third_party/blink/renderer/core/svg/svg_svg_element.cc b/third_party/blink/renderer/core/svg/svg_svg_element.cc
index e0677bbe..0a18c3ea 100644
--- a/third_party/blink/renderer/core/svg/svg_svg_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_svg_element.cc
@@ -84,7 +84,7 @@
                                         SVGLengthMode::kHeight,
                                         SVGLength::Initial::kPercent100,
                                         CSSPropertyID::kHeight)),
-      time_container_(SMILTimeContainer::Create(*this)),
+      time_container_(MakeGarbageCollected<SMILTimeContainer>(*this)),
       translation_(SVGPoint::Create()),
       current_scale_(1) {
   AddToPropertyMap(x_);
diff --git a/third_party/blink/renderer/core/testing/callback_function_test.h b/third_party/blink/renderer/core/testing/callback_function_test.h
index a20bc0f..37cf10e1 100644
--- a/third_party/blink/renderer/core/testing/callback_function_test.h
+++ b/third_party/blink/renderer/core/testing/callback_function_test.h
@@ -24,10 +24,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static CallbackFunctionTest* Create() {
-    return MakeGarbageCollected<CallbackFunctionTest>();
-  }
-
   String testCallback(V8TestCallback*,
                       const String&,
                       const String&,
diff --git a/third_party/blink/renderer/core/testing/core_unit_test_helper.cc b/third_party/blink/renderer/core/testing/core_unit_test_helper.cc
index 3119e92..a2e8030a 100644
--- a/third_party/blink/renderer/core/testing/core_unit_test_helper.cc
+++ b/third_party/blink/renderer/core/testing/core_unit_test_helper.cc
@@ -19,7 +19,8 @@
   DCHECK(!child_) << "This test helper only supports one child frame.";
 
   LocalFrame* parent_frame = owner_element->GetDocument().GetFrame();
-  auto* child_client = LocalFrameClientWithParent::Create(parent_frame);
+  auto* child_client =
+      MakeGarbageCollected<LocalFrameClientWithParent>(parent_frame);
   child_ =
       LocalFrame::Create(child_client, *parent_frame->GetPage(), owner_element);
   child_->CreateView(IntSize(500, 500), Color::kTransparent);
diff --git a/third_party/blink/renderer/core/testing/core_unit_test_helper.h b/third_party/blink/renderer/core/testing/core_unit_test_helper.h
index a7ad2b9..8528c08 100644
--- a/third_party/blink/renderer/core/testing/core_unit_test_helper.h
+++ b/third_party/blink/renderer/core/testing/core_unit_test_helper.h
@@ -27,10 +27,6 @@
 
 class SingleChildLocalFrameClient final : public EmptyLocalFrameClient {
  public:
-  static SingleChildLocalFrameClient* Create() {
-    return MakeGarbageCollected<SingleChildLocalFrameClient>();
-  }
-
   explicit SingleChildLocalFrameClient() = default;
 
   void Trace(blink::Visitor* visitor) override {
@@ -51,10 +47,6 @@
 
 class LocalFrameClientWithParent final : public EmptyLocalFrameClient {
  public:
-  static LocalFrameClientWithParent* Create(LocalFrame* parent) {
-    return MakeGarbageCollected<LocalFrameClientWithParent>(parent);
-  }
-
   explicit LocalFrameClientWithParent(LocalFrame* parent) : parent_(parent) {}
 
   void Trace(blink::Visitor* visitor) override {
diff --git a/third_party/blink/renderer/core/testing/dictionary_test.h b/third_party/blink/renderer/core/testing/dictionary_test.h
index 21858b4..33bb414d 100644
--- a/third_party/blink/renderer/core/testing/dictionary_test.h
+++ b/third_party/blink/renderer/core/testing/dictionary_test.h
@@ -27,10 +27,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static DictionaryTest* Create() {
-    return MakeGarbageCollected<DictionaryTest>();
-  }
-
   DictionaryTest();
   ~DictionaryTest() override;
 
diff --git a/third_party/blink/renderer/core/testing/gc_observation.h b/third_party/blink/renderer/core/testing/gc_observation.h
index 63454ee..0ce1dbcb6 100644
--- a/third_party/blink/renderer/core/testing/gc_observation.h
+++ b/third_party/blink/renderer/core/testing/gc_observation.h
@@ -42,10 +42,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static GCObservation* Create(v8::Local<v8::Value> observed_value) {
-    return MakeGarbageCollected<GCObservation>(observed_value);
-  }
-
   explicit GCObservation(v8::Local<v8::Value>);
 
   // Caution: It is only feasible to determine whether an object was
diff --git a/third_party/blink/renderer/core/testing/hit_test_layer_rect.h b/third_party/blink/renderer/core/testing/hit_test_layer_rect.h
index a36c691..e078089 100644
--- a/third_party/blink/renderer/core/testing/hit_test_layer_rect.h
+++ b/third_party/blink/renderer/core/testing/hit_test_layer_rect.h
@@ -45,11 +45,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static HitTestLayerRect* Create(DOMRectReadOnly* layer_rect,
-                                  DOMRectReadOnly* hit_test_rect) {
-    return MakeGarbageCollected<HitTestLayerRect>(layer_rect, hit_test_rect);
-  }
-
   HitTestLayerRect(DOMRectReadOnly* layer_rect, DOMRectReadOnly* hit_test_rect)
       : layer_rect_(layer_rect), hit_test_rect_(hit_test_rect) {}
 
diff --git a/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.cc b/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.cc
index 8e0056e..a67ab69 100644
--- a/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.cc
+++ b/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.cc
@@ -50,7 +50,8 @@
 
 void HitTestLayerRectList::Append(DOMRectReadOnly* layer_rect,
                                   DOMRectReadOnly* hit_test_rect) {
-  list_.push_back(HitTestLayerRect::Create(layer_rect, hit_test_rect));
+  list_.push_back(
+      MakeGarbageCollected<HitTestLayerRect>(layer_rect, hit_test_rect));
 }
 
 void HitTestLayerRectList::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.h b/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.h
index 5f8b935..ae539329 100644
--- a/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.h
+++ b/third_party/blink/renderer/core/testing/hit_test_layer_rect_list.h
@@ -45,10 +45,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static HitTestLayerRectList* Create() {
-    return MakeGarbageCollected<HitTestLayerRectList>();
-  }
-
   HitTestLayerRectList();
 
   unsigned length() const;
diff --git a/third_party/blink/renderer/core/testing/internal_settings.h b/third_party/blink/renderer/core/testing/internal_settings.h
index da670b1..6b87770c 100644
--- a/third_party/blink/renderer/core/testing/internal_settings.h
+++ b/third_party/blink/renderer/core/testing/internal_settings.h
@@ -77,9 +77,6 @@
     bool original_scroll_top_left_interop_enabled_;
   };
 
-  static InternalSettings* Create(Page& page) {
-    return MakeGarbageCollected<InternalSettings>(page);
-  }
   static InternalSettings* From(Page&);
 
   explicit InternalSettings(Page&);
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc
index 258c23f9..4eeb1d0 100644
--- a/third_party/blink/renderer/core/testing/internals.cc
+++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -336,7 +336,7 @@
     return nullptr;
   }
 
-  return GCObservation::Create(observed_value);
+  return MakeGarbageCollected<GCObservation>(observed_value);
 }
 
 unsigned Internals::updateStyleAndReturnAffectedElementCount(
@@ -1944,7 +1944,7 @@
 
     const auto& content_layers = pac->GetExtraDataForTesting()->content_layers;
 
-    HitTestLayerRectList* hit_test_rects = HitTestLayerRectList::Create();
+    auto* hit_test_rects = MakeGarbageCollected<HitTestLayerRectList>();
     for (const auto& layer : content_layers) {
       const cc::TouchActionRegion& touch_action_region =
           layer->touch_action_region();
@@ -1986,7 +1986,7 @@
       // on layers outside the document hierarchy (e.g. when we replace the
       // document with a video layer).
       if (GraphicsLayer* root_layer = compositor->PaintRootGraphicsLayer()) {
-        HitTestLayerRectList* hit_test_rects = HitTestLayerRectList::Create();
+        auto* hit_test_rects = MakeGarbageCollected<HitTestLayerRectList>();
         AccumulateTouchActionRectList(compositor, root_layer, hit_test_rects);
         return hit_test_rects;
       }
@@ -2575,31 +2575,31 @@
 }
 
 TypeConversions* Internals::typeConversions() const {
-  return TypeConversions::Create();
+  return MakeGarbageCollected<TypeConversions>();
 }
 
 DictionaryTest* Internals::dictionaryTest() const {
-  return DictionaryTest::Create();
+  return MakeGarbageCollected<DictionaryTest>();
 }
 
 RecordTest* Internals::recordTest() const {
-  return RecordTest::Create();
+  return MakeGarbageCollected<RecordTest>();
 }
 
 SequenceTest* Internals::sequenceTest() const {
-  return SequenceTest::create();
+  return MakeGarbageCollected<SequenceTest>();
 }
 
 UnionTypesTest* Internals::unionTypesTest() const {
-  return UnionTypesTest::Create();
+  return MakeGarbageCollected<UnionTypesTest>();
 }
 
 OriginTrialsTest* Internals::originTrialsTest() const {
-  return OriginTrialsTest::Create();
+  return MakeGarbageCollected<OriginTrialsTest>();
 }
 
 CallbackFunctionTest* Internals::callbackFunctionTest() const {
-  return CallbackFunctionTest::Create();
+  return MakeGarbageCollected<CallbackFunctionTest>();
 }
 
 Vector<String> Internals::getReferencedFilePaths() const {
diff --git a/third_party/blink/renderer/core/testing/internals.h b/third_party/blink/renderer/core/testing/internals.h
index 6a8fc28..1a8cf0bd11 100644
--- a/third_party/blink/renderer/core/testing/internals.h
+++ b/third_party/blink/renderer/core/testing/internals.h
@@ -90,10 +90,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static Internals* Create(ExecutionContext* context) {
-    return MakeGarbageCollected<Internals>(context);
-  }
-
   static void ResetToConsistentState(Page*);
 
   explicit Internals(ExecutionContext*);
diff --git a/third_party/blink/renderer/core/testing/origin_trials_test.h b/third_party/blink/renderer/core/testing/origin_trials_test.h
index 8b4aa05..0420b2e4 100644
--- a/third_party/blink/renderer/core/testing/origin_trials_test.h
+++ b/third_party/blink/renderer/core/testing/origin_trials_test.h
@@ -22,10 +22,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static OriginTrialsTest* Create() {
-    return MakeGarbageCollected<OriginTrialsTest>();
-  }
-
   OriginTrialsTest() = default;
   ~OriginTrialsTest() override = default;
 
diff --git a/third_party/blink/renderer/core/testing/record_test.h b/third_party/blink/renderer/core/testing/record_test.h
index 9d73783..58bab2a 100644
--- a/third_party/blink/renderer/core/testing/record_test.h
+++ b/third_party/blink/renderer/core/testing/record_test.h
@@ -21,8 +21,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static RecordTest* Create() { return MakeGarbageCollected<RecordTest>(); }
-
   RecordTest();
   ~RecordTest() override;
 
diff --git a/third_party/blink/renderer/core/testing/sequence_test.h b/third_party/blink/renderer/core/testing/sequence_test.h
index 8a98f7e..2d558bd 100644
--- a/third_party/blink/renderer/core/testing/sequence_test.h
+++ b/third_party/blink/renderer/core/testing/sequence_test.h
@@ -19,8 +19,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static SequenceTest* create() { return MakeGarbageCollected<SequenceTest>(); }
-
   SequenceTest();
   ~SequenceTest() override;
 
diff --git a/third_party/blink/renderer/core/testing/type_conversions.h b/third_party/blink/renderer/core/testing/type_conversions.h
index 93e2c90..515a398 100644
--- a/third_party/blink/renderer/core/testing/type_conversions.h
+++ b/third_party/blink/renderer/core/testing/type_conversions.h
@@ -35,10 +35,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static TypeConversions* Create() {
-    return MakeGarbageCollected<TypeConversions>();
-  }
-
   TypeConversions()
       : long_(0),
         unsigned_long_(0),
diff --git a/third_party/blink/renderer/core/testing/union_types_test.h b/third_party/blink/renderer/core/testing/union_types_test.h
index 7397c6d..1ab8319 100644
--- a/third_party/blink/renderer/core/testing/union_types_test.h
+++ b/third_party/blink/renderer/core/testing/union_types_test.h
@@ -17,10 +17,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static UnionTypesTest* Create() {
-    return MakeGarbageCollected<UnionTypesTest>();
-  }
-
   UnionTypesTest() : attribute_type_(kSpecificTypeNone) {}
   ~UnionTypesTest() override = default;
 
diff --git a/third_party/blink/renderer/core/testing/v8/web_core_test_support.cc b/third_party/blink/renderer/core/testing/v8/web_core_test_support.cc
index 793e2424..102d0a3 100644
--- a/third_party/blink/renderer/core/testing/v8/web_core_test_support.cc
+++ b/third_party/blink/renderer/core/testing/v8/web_core_test_support.cc
@@ -54,11 +54,12 @@
   v8::Local<v8::Object> global = script_state->GetContext()->Global();
   ExecutionContext* execution_context = ExecutionContext::From(script_state);
   if (execution_context->IsDocument()) {
-    return ToV8(Internals::Create(execution_context), global,
+    return ToV8(MakeGarbageCollected<Internals>(execution_context), global,
                 script_state->GetIsolate());
   }
   if (execution_context->IsWorkerGlobalScope()) {
-    return ToV8(WorkerInternals::Create(), global, script_state->GetIsolate());
+    return ToV8(MakeGarbageCollected<WorkerInternals>(), global,
+                script_state->GetIsolate());
   }
   return v8::Local<v8::Value>();
 }
diff --git a/third_party/blink/renderer/core/testing/wait_for_event.cc b/third_party/blink/renderer/core/testing/wait_for_event.cc
index 65f30b0..a8f5281 100644
--- a/third_party/blink/renderer/core/testing/wait_for_event.cc
+++ b/third_party/blink/renderer/core/testing/wait_for_event.cc
@@ -8,11 +8,6 @@
 
 namespace blink {
 
-// static
-WaitForEvent* WaitForEvent::Create(Element* element, const AtomicString& name) {
-  return MakeGarbageCollected<WaitForEvent>(element, name);
-}
-
 WaitForEvent::WaitForEvent(Element* element, const AtomicString& name)
     : element_(element), event_name_(name) {
   element_->addEventListener(event_name_, this);
diff --git a/third_party/blink/renderer/core/testing/wait_for_event.h b/third_party/blink/renderer/core/testing/wait_for_event.h
index 0ef1498..9949bd3c 100644
--- a/third_party/blink/renderer/core/testing/wait_for_event.h
+++ b/third_party/blink/renderer/core/testing/wait_for_event.h
@@ -16,8 +16,6 @@
 // on the given element.
 class WaitForEvent : public NativeEventListener {
  public:
-  static WaitForEvent* Create(Element*, const AtomicString&);
-
   WaitForEvent(Element*, const AtomicString&);
 
   void Invoke(ExecutionContext*, Event*) final;
diff --git a/third_party/blink/renderer/core/testing/worker_internals.cc b/third_party/blink/renderer/core/testing/worker_internals.cc
index ef227ba..af4e51b 100644
--- a/third_party/blink/renderer/core/testing/worker_internals.cc
+++ b/third_party/blink/renderer/core/testing/worker_internals.cc
@@ -18,7 +18,7 @@
 WorkerInternals::WorkerInternals() = default;
 
 OriginTrialsTest* WorkerInternals::originTrialsTest() const {
-  return OriginTrialsTest::Create();
+  return MakeGarbageCollected<OriginTrialsTest>();
 }
 
 void WorkerInternals::countFeature(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/testing/worker_internals.h b/third_party/blink/renderer/core/testing/worker_internals.h
index 72eaf50..d5abaf77 100644
--- a/third_party/blink/renderer/core/testing/worker_internals.h
+++ b/third_party/blink/renderer/core/testing/worker_internals.h
@@ -18,10 +18,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static WorkerInternals* Create() {
-    return MakeGarbageCollected<WorkerInternals>();
-  }
-
   explicit WorkerInternals();
   ~WorkerInternals() override;
 
diff --git a/third_party/blink/renderer/core/timing/dom_window_performance.cc b/third_party/blink/renderer/core/timing/dom_window_performance.cc
index 10ccb05..e156972 100644
--- a/third_party/blink/renderer/core/timing/dom_window_performance.cc
+++ b/third_party/blink/renderer/core/timing/dom_window_performance.cc
@@ -38,7 +38,7 @@
 
 WindowPerformance* DOMWindowPerformance::performance() {
   if (!performance_)
-    performance_ = WindowPerformance::Create(GetSupplementable());
+    performance_ = MakeGarbageCollected<WindowPerformance>(GetSupplementable());
   return performance_.Get();
 }
 
diff --git a/third_party/blink/renderer/core/timing/memory_info.h b/third_party/blink/renderer/core/timing/memory_info.h
index af93db2..162b38c 100644
--- a/third_party/blink/renderer/core/timing/memory_info.h
+++ b/third_party/blink/renderer/core/timing/memory_info.h
@@ -58,9 +58,6 @@
   // time (50 ms). A Bucketized value means that the numbers will be bucketized
   // and cached for a long period of time (20 minutes).
   enum class Precision { Precise, Bucketized };
-  static MemoryInfo* Create(Precision precision) {
-    return MakeGarbageCollected<MemoryInfo>(precision);
-  }
 
   explicit MemoryInfo(Precision precision);
 
diff --git a/third_party/blink/renderer/core/timing/memory_info_test.cc b/third_party/blink/renderer/core/timing/memory_info_test.cc
index ec95e15..ccaa6750 100644
--- a/third_party/blink/renderer/core/timing/memory_info_test.cc
+++ b/third_party/blink/renderer/core/timing/memory_info_test.cc
@@ -130,7 +130,7 @@
   std::vector<v8::Local<v8::ArrayBuffer>> objects;
 
   MemoryInfo* bucketized_memory =
-      MemoryInfo::Create(MemoryInfo::Precision::Bucketized);
+      MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Bucketized);
 
   // Check that the values are monotone and rounded.
   CheckValues(bucketized_memory, MemoryInfo::Precision::Bucketized);
@@ -141,7 +141,7 @@
   objects.push_back(v8::ArrayBuffer::New(isolate, 100));
 
   MemoryInfo* bucketized_memory2 =
-      MemoryInfo::Create(MemoryInfo::Precision::Bucketized);
+      MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Bucketized);
   // The old bucketized values must be equal to the new bucketized values.
   CheckEqual(bucketized_memory, bucketized_memory2);
 
@@ -160,7 +160,7 @@
     AdvanceClock(60 * 30);
     objects.push_back(v8::ArrayBuffer::New(isolate, 100));
     MemoryInfo* bucketized_memory3 =
-        MemoryInfo::Create(MemoryInfo::Precision::Bucketized);
+        MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Bucketized);
     CheckValues(bucketized_memory3, MemoryInfo::Precision::Bucketized);
     // The limit should remain unchanged.
     EXPECT_EQ(bucketized_memory3->jsHeapSizeLimit(),
@@ -174,7 +174,7 @@
   std::vector<v8::Local<v8::ArrayBuffer>> objects;
 
   MemoryInfo* precise_memory =
-      MemoryInfo::Create(MemoryInfo::Precision::Precise);
+      MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Precise);
   // Check that the precise values are monotone and not heavily rounded.
   CheckValues(precise_memory, MemoryInfo::Precision::Precise);
 
@@ -186,7 +186,7 @@
   // be noticed by the used heap size in the precise MemoryInfo case.
   objects.push_back(v8::ArrayBuffer::New(isolate, 100));
   MemoryInfo* precise_memory2 =
-      MemoryInfo::Create(MemoryInfo::Precision::Precise);
+      MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Precise);
   // The old precise values must be equal to the new precise values.
   CheckEqual(precise_memory, precise_memory2);
 
@@ -197,7 +197,7 @@
     objects.push_back(v8::ArrayBuffer::New(isolate, 100));
 
     MemoryInfo* new_precise_memory =
-        MemoryInfo::Create(MemoryInfo::Precision::Precise);
+        MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Precise);
 
     CheckValues(new_precise_memory, MemoryInfo::Precision::Precise);
     // The old precise used heap size must be different from the new one.
@@ -220,7 +220,7 @@
   // Using MemoryInfo::Precision::Bucketized to ensure that the runtime-enabled
   // flag overrides the Precision passed onto the method.
   MemoryInfo* precise_memory =
-      MemoryInfo::Create(MemoryInfo::Precision::Bucketized);
+      MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Bucketized);
   // Check that the precise values are monotone and not heavily rounded.
   CheckValues(precise_memory, MemoryInfo::Precision::Precise);
 
@@ -230,7 +230,7 @@
   // PreciseMemoryInfoEnabled flag is on.
   objects.push_back(v8::ArrayBuffer::New(isolate, 100));
   MemoryInfo* precise_memory2 =
-      MemoryInfo::Create(MemoryInfo::Precision::Bucketized);
+      MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Bucketized);
   CheckValues(precise_memory2, MemoryInfo::Precision::Precise);
   // The old precise JS heap size value must NOT be equal to the new value.
   EXPECT_NE(precise_memory2->usedJSHeapSize(),
@@ -240,9 +240,9 @@
 TEST_F(MemoryInfoTest, ZeroTime) {
   // In this test, we make sure that even if the CurrentTimeTicks() value is
   // very close to 0, we still obtain memory information from the first call to
-  // MemoryInfo::Create. We cannot just subtract CurrentTimeTicks() here
-  // because many places have DCHECKs for !time.is_null(), which would be hit if
-  // we set the clock to be exactly 0.
+  // MakeGarbageCollected<MemoryInfo>. We cannot just subtract
+  // CurrentTimeTicks() here because many places have DCHECKs for
+  // !time.is_null(), which would be hit if we set the clock to be exactly 0.
   AdvanceClock(-CurrentTimeTicksInSeconds() + 0.0001);
   V8TestingScope scope;
   v8::Isolate* isolate = scope.GetIsolate();
@@ -250,7 +250,7 @@
   objects.push_back(v8::ArrayBuffer::New(isolate, 100));
 
   MemoryInfo* precise_memory =
-      MemoryInfo::Create(MemoryInfo::Precision::Precise);
+      MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Precise);
   CheckValues(precise_memory, MemoryInfo::Precision::Precise);
   EXPECT_LT(0u, precise_memory->usedJSHeapSize());
   EXPECT_LT(0u, precise_memory->totalJSHeapSize());
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc
index ca3a5713..e79cafc3 100644
--- a/third_party/blink/renderer/core/timing/performance.cc
+++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -563,8 +563,8 @@
 
 void Performance::AddResourceTiming(const WebResourceTimingInfo& info,
                                     const AtomicString& initiator_type) {
-  PerformanceEntry* entry =
-      PerformanceResourceTiming::Create(info, time_origin_, initiator_type);
+  auto* entry = MakeGarbageCollected<PerformanceResourceTiming>(
+      info, time_origin_, initiator_type);
   NotifyObserversOfEntry(*entry);
   // https://w3c.github.io/resource-timing/#dfn-add-a-performanceresourcetiming-entry
   if (CanAddResourceTimingEntry() &&
@@ -717,7 +717,7 @@
     it->setHighResDuration(
         ConvertTimeDeltaToDOMHighResTimeStamp(it->duration()));
   }
-  PerformanceEntry* entry = PerformanceLongTaskTiming::Create(
+  auto* entry = MakeGarbageCollected<PerformanceLongTaskTiming>(
       MonotonicTimeToDOMHighResTimeStamp(start_time),
       MonotonicTimeToDOMHighResTimeStamp(end_time), name, frame_src, frame_id,
       frame_name, sub_task_attributions);
@@ -735,7 +735,7 @@
                                    PerformanceMarkOptions* mark_options,
                                    ExceptionState& exception_state) {
   if (!user_timing_)
-    user_timing_ = UserTiming::Create(*this);
+    user_timing_ = MakeGarbageCollected<UserTiming>(*this);
   PerformanceMark* performance_mark = user_timing_->Mark(
       script_state, mark_name, mark_options, exception_state);
   if (performance_mark)
@@ -747,7 +747,7 @@
 
 void Performance::clearMarks(const AtomicString& mark_name) {
   if (!user_timing_)
-    user_timing_ = UserTiming::Create(*this);
+    user_timing_ = MakeGarbageCollected<UserTiming>(*this);
   user_timing_->ClearMarks(mark_name);
 }
 
@@ -876,7 +876,7 @@
   StringOrDouble original_end = end;
 
   if (!user_timing_)
-    user_timing_ = UserTiming::Create(*this);
+    user_timing_ = MakeGarbageCollected<UserTiming>(*this);
   PerformanceMeasure* performance_measure =
       user_timing_->Measure(script_state, measure_name, original_start,
                             original_end, detail, exception_state);
@@ -887,7 +887,7 @@
 
 void Performance::clearMeasures(const AtomicString& measure_name) {
   if (!user_timing_)
-    user_timing_ = UserTiming::Create(*this);
+    user_timing_ = MakeGarbageCollected<UserTiming>(*this);
   user_timing_->ClearMeasures(measure_name);
 }
 
diff --git a/third_party/blink/renderer/core/timing/performance_layout_jank.cc b/third_party/blink/renderer/core/timing/performance_layout_jank.cc
index 1dce523..141c4be 100644
--- a/third_party/blink/renderer/core/timing/performance_layout_jank.cc
+++ b/third_party/blink/renderer/core/timing/performance_layout_jank.cc
@@ -10,11 +10,6 @@
 
 namespace blink {
 
-// static
-PerformanceLayoutJank* PerformanceLayoutJank::Create(double fraction) {
-  return MakeGarbageCollected<PerformanceLayoutJank>(fraction);
-}
-
 PerformanceLayoutJank::PerformanceLayoutJank(double fraction)
     : PerformanceEntry(g_empty_atom, 0.0, 0.0), fraction_(fraction) {}
 
diff --git a/third_party/blink/renderer/core/timing/performance_layout_jank.h b/third_party/blink/renderer/core/timing/performance_layout_jank.h
index 4ff99271..50d590d 100644
--- a/third_party/blink/renderer/core/timing/performance_layout_jank.h
+++ b/third_party/blink/renderer/core/timing/performance_layout_jank.h
@@ -19,9 +19,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static PerformanceLayoutJank* Create(double fraction);
-
-  PerformanceLayoutJank(double fraction);
+  explicit PerformanceLayoutJank(double fraction);
   ~PerformanceLayoutJank() override;
 
   AtomicString entryType() const override;
diff --git a/third_party/blink/renderer/core/timing/performance_long_task_timing.cc b/third_party/blink/renderer/core/timing/performance_long_task_timing.cc
index 970b0f9..06d932d 100644
--- a/third_party/blink/renderer/core/timing/performance_long_task_timing.cc
+++ b/third_party/blink/renderer/core/timing/performance_long_task_timing.cc
@@ -13,20 +13,6 @@
 
 namespace blink {
 
-// static
-PerformanceLongTaskTiming* PerformanceLongTaskTiming::Create(
-    double start_time,
-    double end_time,
-    const AtomicString& name,
-    const String& frame_src,
-    const String& frame_id,
-    const String& frame_name,
-    const SubTaskAttribution::EntriesVector& sub_task_attributions) {
-  return MakeGarbageCollected<PerformanceLongTaskTiming>(
-      start_time, end_time, name, frame_src, frame_id, frame_name,
-      sub_task_attributions);
-}
-
 PerformanceLongTaskTiming::PerformanceLongTaskTiming(
     double start_time,
     double end_time,
diff --git a/third_party/blink/renderer/core/timing/performance_long_task_timing.h b/third_party/blink/renderer/core/timing/performance_long_task_timing.h
index e903a1e7..70b0c28 100644
--- a/third_party/blink/renderer/core/timing/performance_long_task_timing.h
+++ b/third_party/blink/renderer/core/timing/performance_long_task_timing.h
@@ -20,15 +20,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static PerformanceLongTaskTiming* Create(
-      double start_time,
-      double end_time,
-      const AtomicString& name,
-      const String& frame_src,
-      const String& frame_id,
-      const String& frame_name,
-      const SubTaskAttribution::EntriesVector& sub_task_attributions);
-
   PerformanceLongTaskTiming(
       double start_time,
       double end_time,
diff --git a/third_party/blink/renderer/core/timing/performance_measure.h b/third_party/blink/renderer/core/timing/performance_measure.h
index e80be2a2..bb15e1f1 100644
--- a/third_party/blink/renderer/core/timing/performance_measure.h
+++ b/third_party/blink/renderer/core/timing/performance_measure.h
@@ -38,15 +38,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static PerformanceMeasure* Create(ScriptState* script_state,
-                                    const AtomicString& name,
-                                    double start_time,
-                                    double end_time,
-                                    const ScriptValue& detail) {
-    return MakeGarbageCollected<PerformanceMeasure>(
-        script_state, name, start_time, end_time, detail);
-  }
-
   PerformanceMeasure(ScriptState*,
                      const AtomicString& name,
                      double start_time,
diff --git a/third_party/blink/renderer/core/timing/performance_navigation.h b/third_party/blink/renderer/core/timing/performance_navigation.h
index 04e2d82..7300462 100644
--- a/third_party/blink/renderer/core/timing/performance_navigation.h
+++ b/third_party/blink/renderer/core/timing/performance_navigation.h
@@ -49,10 +49,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(PerformanceNavigation);
 
  public:
-  static PerformanceNavigation* Create(LocalFrame* frame) {
-    return MakeGarbageCollected<PerformanceNavigation>(frame);
-  }
-
   explicit PerformanceNavigation(LocalFrame*);
 
   enum PerformanceNavigationType {
diff --git a/third_party/blink/renderer/core/timing/performance_observer_test.cc b/third_party/blink/renderer/core/timing/performance_observer_test.cc
index c307df6..86fb7a5 100644
--- a/third_party/blink/renderer/core/timing/performance_observer_test.cc
+++ b/third_party/blink/renderer/core/timing/performance_observer_test.cc
@@ -74,7 +74,7 @@
   EXPECT_EQ(0, NumPerformanceEntries());
 
   // add a layoutjank to performance so getEntries() returns it
-  PerformanceLayoutJank* entry = PerformanceLayoutJank::Create(1234);
+  auto* entry = MakeGarbageCollected<PerformanceLayoutJank>(1234);
   base_->AddLayoutJankBuffer(*entry);
 
   // call observe with the buffered flag
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.h b/third_party/blink/renderer/core/timing/performance_resource_timing.h
index c9738ab..c31a17ef 100644
--- a/third_party/blink/renderer/core/timing/performance_resource_timing.h
+++ b/third_party/blink/renderer/core/timing/performance_resource_timing.h
@@ -58,12 +58,6 @@
                             TimeTicks time_origin,
                             const AtomicString& initiator_type);
   ~PerformanceResourceTiming() override;
-  static PerformanceResourceTiming* Create(const WebResourceTimingInfo& info,
-                                           TimeTicks time_origin,
-                                           const AtomicString& initiator_type) {
-    return MakeGarbageCollected<PerformanceResourceTiming>(info, time_origin,
-                                                           initiator_type);
-  }
 
   AtomicString entryType() const override;
   PerformanceEntryType EntryTypeEnum() const override;
diff --git a/third_party/blink/renderer/core/timing/performance_timing.h b/third_party/blink/renderer/core/timing/performance_timing.h
index 332bed8..841737f 100644
--- a/third_party/blink/renderer/core/timing/performance_timing.h
+++ b/third_party/blink/renderer/core/timing/performance_timing.h
@@ -60,10 +60,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(PerformanceTiming);
 
  public:
-  static PerformanceTiming* Create(LocalFrame* frame) {
-    return MakeGarbageCollected<PerformanceTiming>(frame);
-  }
-
   explicit PerformanceTiming(LocalFrame*);
 
   uint64_t navigationStart() const;
diff --git a/third_party/blink/renderer/core/timing/performance_user_timing.cc b/third_party/blink/renderer/core/timing/performance_user_timing.cc
index efec9b14..d16f9a9 100644
--- a/third_party/blink/renderer/core/timing/performance_user_timing.cc
+++ b/third_party/blink/renderer/core/timing/performance_user_timing.cc
@@ -229,7 +229,7 @@
       "blink.user_timing", measure_name.Utf8().data(), hash,
       trace_event::ToTraceTimestamp(end_time_monotonic));
 
-  PerformanceMeasure* measure = PerformanceMeasure::Create(
+  auto* measure = MakeGarbageCollected<PerformanceMeasure>(
       script_state, measure_name, start_time, end_time, detail);
   InsertPerformanceEntry(measures_map_, *measure);
   if (end_time >= start_time) {
diff --git a/third_party/blink/renderer/core/timing/performance_user_timing.h b/third_party/blink/renderer/core/timing/performance_user_timing.h
index a6c2d0e..d70dd47 100644
--- a/third_party/blink/renderer/core/timing/performance_user_timing.h
+++ b/third_party/blink/renderer/core/timing/performance_user_timing.h
@@ -42,10 +42,6 @@
 
 class UserTiming final : public GarbageCollected<UserTiming> {
  public:
-  static UserTiming* Create(Performance& performance) {
-    return MakeGarbageCollected<UserTiming>(performance);
-  }
-
   explicit UserTiming(Performance&);
 
   PerformanceMark* Mark(ScriptState* script_state,
diff --git a/third_party/blink/renderer/core/timing/window_performance.cc b/third_party/blink/renderer/core/timing/window_performance.cc
index 9e4bf25..1a001f5 100644
--- a/third_party/blink/renderer/core/timing/window_performance.cc
+++ b/third_party/blink/renderer/core/timing/window_performance.cc
@@ -149,14 +149,14 @@
 
 PerformanceTiming* WindowPerformance::timing() const {
   if (!timing_)
-    timing_ = PerformanceTiming::Create(GetFrame());
+    timing_ = MakeGarbageCollected<PerformanceTiming>(GetFrame());
 
   return timing_.Get();
 }
 
 PerformanceNavigation* WindowPerformance::navigation() const {
   if (!navigation_)
-    navigation_ = PerformanceNavigation::Create(GetFrame());
+    navigation_ = MakeGarbageCollected<PerformanceNavigation>(GetFrame());
 
   return navigation_.Get();
 }
@@ -167,9 +167,10 @@
   // course over time about what changes would be implemented) can be found at
   // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/no00RdMnGio,
   // and the relevant bug is https://crbug.com/807651.
-  return MemoryInfo::Create(Platform::Current()->IsLockedToSite()
-                                ? MemoryInfo::Precision::Precise
-                                : MemoryInfo::Precision::Bucketized);
+  return MakeGarbageCollected<MemoryInfo>(
+      Platform::Current()->IsLockedToSite()
+          ? MemoryInfo::Precision::Precise
+          : MemoryInfo::Precision::Bucketized);
 }
 
 PerformanceNavigationTiming*
@@ -436,7 +437,7 @@
 
 void WindowPerformance::AddLayoutJankFraction(double jank_fraction) {
   DCHECK(origin_trials::LayoutJankAPIEnabled(GetExecutionContext()));
-  PerformanceLayoutJank* entry = PerformanceLayoutJank::Create(jank_fraction);
+  auto* entry = MakeGarbageCollected<PerformanceLayoutJank>(jank_fraction);
   if (HasObserverFor(PerformanceEntry::kLayoutJank))
     NotifyObserversOfEntry(*entry);
   if (ShouldBufferEntries())
diff --git a/third_party/blink/renderer/core/timing/window_performance.h b/third_party/blink/renderer/core/timing/window_performance.h
index 1f0dec8..82c33c8 100644
--- a/third_party/blink/renderer/core/timing/window_performance.h
+++ b/third_party/blink/renderer/core/timing/window_performance.h
@@ -51,10 +51,6 @@
   friend class WindowPerformanceTest;
 
  public:
-  static WindowPerformance* Create(LocalDOMWindow* window) {
-    return MakeGarbageCollected<WindowPerformance>(window);
-  }
-
   explicit WindowPerformance(LocalDOMWindow*);
   ~WindowPerformance() override;
 
diff --git a/third_party/blink/renderer/core/timing/window_performance_test.cc b/third_party/blink/renderer/core/timing/window_performance_test.cc
index dfcbc403..8b9b77e 100644
--- a/third_party/blink/renderer/core/timing/window_performance_test.cc
+++ b/third_party/blink/renderer/core/timing/window_performance_test.cc
@@ -88,8 +88,8 @@
   void ResetPerformance() {
     page_holder_ = std::make_unique<DummyPageHolder>(IntSize(800, 600));
     page_holder_->GetDocument().SetURL(KURL("https://example.com"));
-    performance_ =
-        WindowPerformance::Create(page_holder_->GetDocument().domWindow());
+    performance_ = MakeGarbageCollected<WindowPerformance>(
+        page_holder_->GetDocument().domWindow());
     performance_->time_origin_ = GetTimeOrigin();
   }
 
diff --git a/third_party/blink/renderer/core/timing/worker_global_scope_performance.cc b/third_party/blink/renderer/core/timing/worker_global_scope_performance.cc
index 33c98128..bf5f6e0 100644
--- a/third_party/blink/renderer/core/timing/worker_global_scope_performance.cc
+++ b/third_party/blink/renderer/core/timing/worker_global_scope_performance.cc
@@ -63,7 +63,7 @@
 WorkerPerformance* WorkerGlobalScopePerformance::performance(
     WorkerGlobalScope* worker_global_scope) {
   if (!performance_)
-    performance_ = WorkerPerformance::Create(worker_global_scope);
+    performance_ = MakeGarbageCollected<WorkerPerformance>(worker_global_scope);
   return performance_.Get();
 }
 
diff --git a/third_party/blink/renderer/core/timing/worker_performance.h b/third_party/blink/renderer/core/timing/worker_performance.h
index 25b65cd..6665289 100644
--- a/third_party/blink/renderer/core/timing/worker_performance.h
+++ b/third_party/blink/renderer/core/timing/worker_performance.h
@@ -43,10 +43,6 @@
 
 class WorkerPerformance final : public Performance {
  public:
-  static WorkerPerformance* Create(WorkerGlobalScope* context) {
-    return MakeGarbageCollected<WorkerPerformance>(context);
-  }
-
   explicit WorkerPerformance(WorkerGlobalScope*);
 
   ExecutionContext* GetExecutionContext() const override {
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_html.h b/third_party/blink/renderer/core/trustedtypes/trusted_html.h
index ca102e4f..bbfa231 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_html.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_html.h
@@ -15,11 +15,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static TrustedHTML* Create(const String& html) {
-    return MakeGarbageCollected<TrustedHTML>(html);
-  }
-
-  TrustedHTML(const String& html);
+  explicit TrustedHTML(const String& html);
 
   // TrustedHTML.idl
   String toString() const;
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_script.h b/third_party/blink/renderer/core/trustedtypes/trusted_script.h
index 3a5abb5e..429790ac 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_script.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_script.h
@@ -15,11 +15,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static TrustedScript* Create(const String& script) {
-    return MakeGarbageCollected<TrustedScript>(script);
-  }
-
-  TrustedScript(const String& script);
+  explicit TrustedScript(const String& script);
 
   // TrustedScript.idl
   String toString() const;
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h b/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h
index 1dba5412..d3981c2e 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h
@@ -15,11 +15,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static TrustedScriptURL* Create(const String& url) {
-    return MakeGarbageCollected<TrustedScriptURL>(url);
-  }
-
-  TrustedScriptURL(const String& url);
+  explicit TrustedScriptURL(const String& url);
 
   // TrustedScriptURL.idl
   String toString() const;
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.cc b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.cc
index c439848..f2f45a8 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.cc
@@ -21,14 +21,6 @@
   policy_options_->setExposed(exposed);
 }
 
-TrustedTypePolicy* TrustedTypePolicy::Create(
-    const String& policy_name,
-    TrustedTypePolicyOptions* policy_options,
-    bool exposed) {
-  return MakeGarbageCollected<TrustedTypePolicy>(policy_name, policy_options,
-                                                 exposed);
-}
-
 TrustedHTML* TrustedTypePolicy::createHTML(ScriptState* script_state,
                                            const String& input,
                                            ExceptionState& exception_state) {
@@ -71,7 +63,7 @@
     exception_state.RethrowV8Exception(try_catch.Exception());
     return nullptr;
   }
-  return TrustedHTML::Create(html);
+  return MakeGarbageCollected<TrustedHTML>(html);
 }
 
 TrustedScript* TrustedTypePolicy::CreateScript(
@@ -91,7 +83,7 @@
     exception_state.RethrowV8Exception(try_catch.Exception());
     return nullptr;
   }
-  return TrustedScript::Create(script);
+  return MakeGarbageCollected<TrustedScript>(script);
 }
 
 TrustedScriptURL* TrustedTypePolicy::CreateScriptURL(
@@ -113,7 +105,7 @@
     exception_state.RethrowV8Exception(try_catch.Exception());
     return nullptr;
   }
-  return TrustedScriptURL::Create(script_url);
+  return MakeGarbageCollected<TrustedScriptURL>(script_url);
 }
 
 TrustedURL* TrustedTypePolicy::CreateURL(v8::Isolate* isolate,
@@ -132,7 +124,7 @@
     exception_state.RethrowV8Exception(try_catch.Exception());
     return nullptr;
   }
-  return TrustedURL::Create(url);
+  return MakeGarbageCollected<TrustedURL>(url);
 }
 
 String TrustedTypePolicy::name() const {
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h
index f6fcbcb..46e3755 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h
@@ -23,10 +23,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static TrustedTypePolicy* Create(const String& policy_name,
-                                   TrustedTypePolicyOptions*,
-                                   bool exposed);
-
   TrustedTypePolicy(const String& policy_name,
                     TrustedTypePolicyOptions*,
                     bool exposed);
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
index 7b9d9fb8..cc2c0c84 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
@@ -51,7 +51,7 @@
     UseCounter::Count(GetExecutionContext(),
                       WebFeature::kTrustedTypesDefaultPolicyUsed);
   }
-  TrustedTypePolicy* policy = TrustedTypePolicy::Create(
+  auto* policy = MakeGarbageCollected<TrustedTypePolicy>(
       policy_name, const_cast<TrustedTypePolicyOptions*>(policy_options),
       exposed);
   policy_map_.insert(policy_name, policy);
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h
index 530da4b..e73d6cb2 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h
@@ -25,10 +25,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(TrustedTypePolicyFactory);
 
  public:
-  static TrustedTypePolicyFactory* Create(ExecutionContext* context) {
-    return MakeGarbageCollected<TrustedTypePolicyFactory>(context);
-  }
-
   explicit TrustedTypePolicyFactory(ExecutionContext*);
 
   // TrustedTypePolicyFactory.idl
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc b/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
index 17f7fe76..2aa31dfd 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
@@ -186,7 +186,7 @@
 
 // GetStringFromTrustedType() tests
 TEST(TrustedTypesUtilTest, GetStringFromTrustedType_TrustedHTML) {
-  TrustedHTML* html = TrustedHTML::Create("A string");
+  auto* html = MakeGarbageCollected<TrustedHTML>("A string");
   StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL
       trusted_value =
           StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL::
@@ -195,7 +195,7 @@
 }
 
 TEST(TrustedTypesUtilTest, GetStringFromTrustedType_TrustedScript) {
-  TrustedScript* script = TrustedScript::Create("A string");
+  auto* script = MakeGarbageCollected<TrustedScript>("A string");
   StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL
       trusted_value =
           StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL::
@@ -205,7 +205,7 @@
 
 TEST(TrustedTypesUtilTest, GetStringFromTrustedType_TrustedScriptURL) {
   String url_address = "http://www.example.com/";
-  TrustedScriptURL* script_url = TrustedScriptURL::Create(url_address);
+  auto* script_url = MakeGarbageCollected<TrustedScriptURL>(url_address);
   StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL
       trusted_value =
           StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL::
@@ -215,7 +215,7 @@
 
 TEST(TrustedTypesUtilTest, GetStringFromTrustedType_TrustedScriptURL_Relative) {
   String url_address = "relative/url.html";
-  TrustedScriptURL* script_url = TrustedScriptURL::Create(url_address);
+  auto* script_url = MakeGarbageCollected<TrustedScriptURL>(url_address);
   StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL
       trusted_value =
           StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL::
@@ -225,7 +225,7 @@
 
 TEST(TrustedTypesUtilTest, GetStringFromTrustedType_TrustedURL) {
   String url_address = "http://www.example.com/";
-  TrustedURL* url = TrustedURL::Create(url_address);
+  auto* url = MakeGarbageCollected<TrustedURL>(url_address);
   StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL
       trusted_value =
           StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL::
@@ -235,7 +235,7 @@
 
 TEST(TrustedTypesUtilTest, GetStringFromTrustedType_TrustedURL_Relative) {
   String url_address = "relative/url.html";
-  TrustedURL* url = TrustedURL::Create(url_address);
+  auto* url = MakeGarbageCollected<TrustedURL>(url_address);
   StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL
       trusted_value =
           StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL::
@@ -253,7 +253,7 @@
 
 // GetStringFromTrustedTypeWithoutCheck() tests
 TEST(TrustedTypesUtilTest, GetStringFromTrustedTypeWithoutCheck_TrustedHTML) {
-  TrustedHTML* html = TrustedHTML::Create("A string");
+  auto* html = MakeGarbageCollected<TrustedHTML>("A string");
   StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL
       trusted_value =
           StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL::
@@ -263,7 +263,7 @@
 }
 
 TEST(TrustedTypesUtilTest, GetStringFromTrustedTypeWithoutCheck_TrustedScript) {
-  TrustedScript* script = TrustedScript::Create("A string");
+  auto* script = MakeGarbageCollected<TrustedScript>("A string");
   StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL
       trusted_value =
           StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL::
@@ -275,7 +275,7 @@
 TEST(TrustedTypesUtilTest,
      GetStringFromTrustedTypeWithoutCheck_TrustedScriptURL) {
   String url_address = "http://www.example.com/";
-  TrustedScriptURL* script_url = TrustedScriptURL::Create(url_address);
+  auto* script_url = MakeGarbageCollected<TrustedScriptURL>(url_address);
   StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL
       trusted_value =
           StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL::
@@ -286,7 +286,7 @@
 
 TEST(TrustedTypesUtilTest, GetStringFromTrustedTypeWithoutCheck_TrustedURL) {
   String url_address = "http://www.example.com/";
-  TrustedURL* url = TrustedURL::Create(url_address);
+  auto* url = MakeGarbageCollected<TrustedURL>(url_address);
   StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL
       trusted_value =
           StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURLOrTrustedURL::
@@ -313,7 +313,7 @@
 
 // GetStringFromTrustedHTML tests
 TEST(TrustedTypesUtilTest, GetStringFromTrustedHTML_TrustedHTML) {
-  TrustedHTML* html = TrustedHTML::Create("A string");
+  auto* html = MakeGarbageCollected<TrustedHTML>("A string");
   StringOrTrustedHTML trusted_value =
       StringOrTrustedHTML::FromTrustedHTML(html);
   GetStringFromTrustedHTMLWorks(trusted_value, "A string");
@@ -327,7 +327,7 @@
 
 // GetStringFromTrustedScript tests
 TEST(TrustedTypesUtilTest, GetStringFromTrustedScript_TrustedScript) {
-  TrustedScript* script = TrustedScript::Create("A string");
+  auto* script = MakeGarbageCollected<TrustedScript>("A string");
   StringOrTrustedScript trusted_value =
       StringOrTrustedScript::FromTrustedScript(script);
   GetStringFromTrustedScriptWorks(trusted_value, "A string");
@@ -342,7 +342,7 @@
 // GetStringFromTrustedScriptURL tests
 TEST(TrustedTypesUtilTest, GetStringFromTrustedScriptURL_TrustedScriptURL) {
   String url_address = "http://www.example.com/";
-  TrustedScriptURL* script_url = TrustedScriptURL::Create(url_address);
+  auto* script_url = MakeGarbageCollected<TrustedScriptURL>(url_address);
   StringOrTrustedScriptURL trusted_value =
       StringOrTrustedScriptURL::FromTrustedScriptURL(script_url);
   GetStringFromTrustedScriptURLWorks(trusted_value, "http://www.example.com/");
@@ -357,7 +357,7 @@
 // GetStringFromTrustedURL tests
 TEST(TrustedTypesUtilTest, GetStringFromTrustedURL_TrustedURL) {
   String url_address = "http://www.example.com/";
-  TrustedURL* url = TrustedURL::Create(url_address);
+  auto* url = MakeGarbageCollected<TrustedURL>(url_address);
   USVStringOrTrustedURL trusted_value =
       USVStringOrTrustedURL::FromTrustedURL(url);
   GetStringFromTrustedURLWorks(trusted_value, "http://www.example.com/");
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_url.h b/third_party/blink/renderer/core/trustedtypes/trusted_url.h
index d2f8ee2..755f1b29 100644
--- a/third_party/blink/renderer/core/trustedtypes/trusted_url.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_url.h
@@ -15,11 +15,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static TrustedURL* Create(const String& url) {
-    return MakeGarbageCollected<TrustedURL>(url);
-  }
-
-  TrustedURL(const String& url);
+  explicit TrustedURL(const String& url);
 
   // TrustedURL.idl
   String toString() const;
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc
index 7c7d5977..60259c58 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -327,7 +327,7 @@
 }
 
 WorkerClients* DedicatedWorker::CreateWorkerClients() {
-  WorkerClients* worker_clients = WorkerClients::Create();
+  auto* worker_clients = MakeGarbageCollected<WorkerClients>();
   CoreInitializer::GetInstance().ProvideLocalFileSystemToWorker(
       *worker_clients);
   CoreInitializer::GetInstance().ProvideIndexedDBClientToWorker(
diff --git a/third_party/blink/renderer/core/workers/experimental/task_worklet.cc b/third_party/blink/renderer/core/workers/experimental/task_worklet.cc
index 43af57eff..aa76962 100644
--- a/third_party/blink/renderer/core/workers/experimental/task_worklet.cc
+++ b/third_party/blink/renderer/core/workers/experimental/task_worklet.cc
@@ -112,7 +112,7 @@
   DCHECK_LT(GetNumberOfGlobalScopes(), kMaxTaskWorkletThreads);
   TaskWorkletMessagingProxy* proxy =
       MakeGarbageCollected<TaskWorkletMessagingProxy>(GetExecutionContext());
-  proxy->Initialize(WorkerClients::Create(), ModuleResponsesMap(),
+  proxy->Initialize(MakeGarbageCollected<WorkerClients>(), ModuleResponsesMap(),
                     WorkerBackingThreadStartupData::CreateDefault());
   return proxy;
 }
diff --git a/third_party/blink/renderer/core/workers/experimental/thread_pool.cc b/third_party/blink/renderer/core/workers/experimental/thread_pool.cc
index ffe9ce8a..4cf3876 100644
--- a/third_party/blink/renderer/core/workers/experimental/thread_pool.cc
+++ b/third_party/blink/renderer/core/workers/experimental/thread_pool.cc
@@ -118,7 +118,8 @@
       context->GetContentSecurityPolicy()->Headers(),
       network::mojom::ReferrerPolicy::kDefault, context->GetSecurityOrigin(),
       context->IsSecureContext(), context->GetHttpsState(),
-      WorkerClients::Create(), context->GetSecurityContext().AddressSpace(),
+      MakeGarbageCollected<WorkerClients>(),
+      context->GetSecurityContext().AddressSpace(),
       OriginTrialContext::GetTokens(context).get(), devtools_worker_token,
       std::move(settings), kV8CacheOptionsDefault,
       nullptr /* worklet_module_responses_map */,
diff --git a/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h b/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h
index 2b954ef..20628c3 100644
--- a/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h
+++ b/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h
@@ -29,13 +29,6 @@
     : public GarbageCollectedFinalized<WorkerAnimationFrameProvider>,
       public BeginFrameProviderClient {
  public:
-  static WorkerAnimationFrameProvider* Create(
-      ExecutionContext* context,
-      const BeginFrameProviderParams& begin_frame_provider_params) {
-    return MakeGarbageCollected<WorkerAnimationFrameProvider>(
-        context, begin_frame_provider_params);
-  }
-
   WorkerAnimationFrameProvider(
       ExecutionContext* context,
       const BeginFrameProviderParams& begin_frame_provider_params);
diff --git a/third_party/blink/renderer/core/workers/worker_clients.h b/third_party/blink/renderer/core/workers/worker_clients.h
index 2f5ca1c..009b7b6 100644
--- a/third_party/blink/renderer/core/workers/worker_clients.h
+++ b/third_party/blink/renderer/core/workers/worker_clients.h
@@ -47,10 +47,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(WorkerClients);
 
  public:
-  static WorkerClients* Create() {
-    return MakeGarbageCollected<WorkerClients>();
-  }
-
   WorkerClients() = default;
 
   void Trace(blink::Visitor* visitor) override {
diff --git a/third_party/blink/renderer/core/workers/worker_content_settings_client.cc b/third_party/blink/renderer/core/workers/worker_content_settings_client.cc
index f3d50d2..7c806a9 100644
--- a/third_party/blink/renderer/core/workers/worker_content_settings_client.cc
+++ b/third_party/blink/renderer/core/workers/worker_content_settings_client.cc
@@ -38,11 +38,6 @@
 
 namespace blink {
 
-WorkerContentSettingsClient* WorkerContentSettingsClient::Create(
-    std::unique_ptr<WebContentSettingsClient> client) {
-  return MakeGarbageCollected<WorkerContentSettingsClient>(std::move(client));
-}
-
 WorkerContentSettingsClient::~WorkerContentSettingsClient() = default;
 
 bool WorkerContentSettingsClient::RequestFileSystemAccessSync() {
@@ -102,7 +97,8 @@
     std::unique_ptr<WebContentSettingsClient> client) {
   DCHECK(clients);
   WorkerContentSettingsClient::ProvideTo(
-      *clients, WorkerContentSettingsClient::Create(std::move(client)));
+      *clients,
+      MakeGarbageCollected<WorkerContentSettingsClient>(std::move(client)));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/workers/worker_content_settings_client.h b/third_party/blink/renderer/core/workers/worker_content_settings_client.h
index 3af24f0..31ff5d71 100644
--- a/third_party/blink/renderer/core/workers/worker_content_settings_client.h
+++ b/third_party/blink/renderer/core/workers/worker_content_settings_client.h
@@ -51,9 +51,6 @@
  public:
   static const char kSupplementName[];
 
-  static WorkerContentSettingsClient* Create(
-      std::unique_ptr<WebContentSettingsClient>);
-
   explicit WorkerContentSettingsClient(
       std::unique_ptr<WebContentSettingsClient>);
   virtual ~WorkerContentSettingsClient();
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc
index 3dc75df87..3378eca 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -139,13 +139,15 @@
 
 WorkerLocation* WorkerGlobalScope::location() const {
   if (!location_)
-    location_ = WorkerLocation::Create(Url());
+    location_ = MakeGarbageCollected<WorkerLocation>(Url());
   return location_.Get();
 }
 
 WorkerNavigator* WorkerGlobalScope::navigator() const {
-  if (!navigator_)
-    navigator_ = WorkerNavigator::Create(user_agent_, GetExecutionContext());
+  if (!navigator_) {
+    navigator_ = MakeGarbageCollected<WorkerNavigator>(user_agent_,
+                                                       GetExecutionContext());
+  }
   return navigator_.Get();
 }
 
@@ -434,9 +436,10 @@
       timers_(GetTaskRunner(TaskType::kJavascriptTimer)),
       time_origin_(time_origin),
       font_selector_(MakeGarbageCollected<OffscreenFontSelector>(this)),
-      animation_frame_provider_(WorkerAnimationFrameProvider::Create(
-          this,
-          creation_params->begin_frame_provider_params)),
+      animation_frame_provider_(
+          MakeGarbageCollected<WorkerAnimationFrameProvider>(
+              this,
+              creation_params->begin_frame_provider_params)),
       agent_cluster_id_(creation_params->agent_cluster_id.is_empty()
                             ? base::UnguessableToken::Create()
                             : creation_params->agent_cluster_id),
@@ -546,7 +549,7 @@
 
 TrustedTypePolicyFactory* WorkerGlobalScope::trustedTypes() {
   if (!trusted_types_) {
-    trusted_types_ = TrustedTypePolicyFactory::Create(this);
+    trusted_types_ = MakeGarbageCollected<TrustedTypePolicyFactory>(this);
   }
   return trusted_types_.Get();
 }
diff --git a/third_party/blink/renderer/core/workers/worker_location.h b/third_party/blink/renderer/core/workers/worker_location.h
index d6918b6..e6fcee19 100644
--- a/third_party/blink/renderer/core/workers/worker_location.h
+++ b/third_party/blink/renderer/core/workers/worker_location.h
@@ -39,10 +39,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static WorkerLocation* Create(const KURL& url) {
-    return MakeGarbageCollected<WorkerLocation>(url);
-  }
-
   explicit WorkerLocation(const KURL& url) : url_(url) {}
 
   KURL Url() const override { return url_; }
diff --git a/third_party/blink/renderer/core/workers/worker_navigator.h b/third_party/blink/renderer/core/workers/worker_navigator.h
index 9bf2765..c3de94f 100644
--- a/third_party/blink/renderer/core/workers/worker_navigator.h
+++ b/third_party/blink/renderer/core/workers/worker_navigator.h
@@ -54,11 +54,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(WorkerNavigator);
 
  public:
-  static WorkerNavigator* Create(const String& user_agent,
-                                 ExecutionContext* context) {
-    return MakeGarbageCollected<WorkerNavigator>(user_agent, context);
-  }
-
   explicit WorkerNavigator(const String&, ExecutionContext* context);
   ~WorkerNavigator() override;
 
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
index abfa7d6f..6d3170a 100644
--- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/loader/loader_factory_for_worker.h"
 #include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
+#include "third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h"
 #include "third_party/blink/renderer/core/loader/subresource_filter.h"
 #include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
 #include "third_party/blink/renderer/core/loader/worker_resource_fetcher_properties.h"
@@ -24,6 +25,7 @@
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
 #include "third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
@@ -282,30 +284,33 @@
     ContentSecurityPolicy& content_security_policy) {
   DCHECK(IsContextThread());
   InitializeWebFetchContextIfNeeded();
-  ResourceFetcherProperties* properties = nullptr;
-  FetchContext* context = nullptr;
-  ResourceFetcher::LoaderFactory* loader_factory = nullptr;
+  ResourceFetcher* fetcher = nullptr;
   if (web_worker_fetch_context_) {
-    properties = MakeGarbageCollected<WorkerResourceFetcherProperties>(
-        *this, fetch_client_settings_object, web_worker_fetch_context_);
-    context = MakeGarbageCollected<WorkerFetchContext>(
-        *this, web_worker_fetch_context_, subresource_filter_,
-        content_security_policy);
-    loader_factory = MakeGarbageCollected<LoaderFactoryForWorker>(
-        *this, web_worker_fetch_context_);
+    fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
+        *MakeGarbageCollected<WorkerResourceFetcherProperties>(
+            *this, fetch_client_settings_object, web_worker_fetch_context_),
+
+        MakeGarbageCollected<WorkerFetchContext>(
+            *this, web_worker_fetch_context_, subresource_filter_,
+            content_security_policy),
+        GetTaskRunner(TaskType::kNetworking),
+        MakeGarbageCollected<LoaderFactoryForWorker>(*this,
+                                                     web_worker_fetch_context_),
+        *this));
+    fetcher->SetResourceLoadObserver(
+        MakeGarbageCollected<ResourceLoadObserverForWorker>(
+            *probe::ToCoreProbeSink(static_cast<ExecutionContext*>(this)),
+            fetcher->GetProperties(), web_worker_fetch_context_));
   } else {
     // This code path is for unittests.
-    properties = MakeGarbageCollected<NullResourceFetcherProperties>();
-    context = &FetchContext::NullInstance();
+    fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
+        *MakeGarbageCollected<NullResourceFetcherProperties>(),
+        &FetchContext::NullInstance(), GetTaskRunner(TaskType::kNetworking)));
   }
-  ResourceFetcherInit init(*properties, context,
-                           GetTaskRunner(TaskType::kNetworking), loader_factory,
-                           *this);
-  auto* resource_fetcher = MakeGarbageCollected<ResourceFetcher>(init);
   if (IsContextPaused())
-    resource_fetcher->SetDefersLoading(true);
-  resource_fetchers_.insert(resource_fetcher);
-  return resource_fetcher;
+    fetcher->SetDefersLoading(true);
+  resource_fetchers_.insert(fetcher);
+  return fetcher;
 }
 
 ResourceFetcher* WorkerOrWorkletGlobalScope::Fetcher() const {
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test.cc b/third_party/blink/renderer/core/workers/worker_thread_test.cc
index 09e7128d..56ce1311 100644
--- a/third_party/blink/renderer/core/workers/worker_thread_test.cc
+++ b/third_party/blink/renderer/core/workers/worker_thread_test.cc
@@ -369,9 +369,9 @@
           nullptr /* web_worker_fetch_context */, headers,
           network::mojom::ReferrerPolicy::kDefault, security_origin_.get(),
           false /* starter_secure_context */,
-          CalculateHttpsState(security_origin_.get()), WorkerClients::Create(),
-          mojom::IPAddressSpace::kLocal, nullptr /* originTrialToken */,
-          base::UnguessableToken::Create(),
+          CalculateHttpsState(security_origin_.get()),
+          MakeGarbageCollected<WorkerClients>(), mojom::IPAddressSpace::kLocal,
+          nullptr /* originTrialToken */, base::UnguessableToken::Create(),
           std::make_unique<WorkerSettings>(std::make_unique<Settings>().get()),
           kV8CacheOptionsDefault, nullptr /* worklet_module_responses_map */);
 
diff --git a/third_party/blink/renderer/core/xml/document_xslt.cc b/third_party/blink/renderer/core/xml/document_xslt.cc
index 2bbb4c6..ab5aa46 100644
--- a/third_party/blink/renderer/core/xml/document_xslt.cc
+++ b/third_party/blink/renderer/core/xml/document_xslt.cc
@@ -26,11 +26,7 @@
   USING_GARBAGE_COLLECTED_MIXIN(DOMContentLoadedListener);
 
  public:
-  static DOMContentLoadedListener* Create(ProcessingInstruction* pi) {
-    return MakeGarbageCollected<DOMContentLoadedListener>(pi);
-  }
-
-  DOMContentLoadedListener(ProcessingInstruction* pi)
+  explicit DOMContentLoadedListener(ProcessingInstruction* pi)
       : processing_instruction_(pi) {}
 
   void Invoke(ExecutionContext* execution_context, Event* event) override {
@@ -118,7 +114,7 @@
   if (!RuntimeEnabledFeatures::XSLTEnabled() || !document.GetFrame())
     return true;
 
-  DOMContentLoadedListener* listener = DOMContentLoadedListener::Create(pi);
+  auto* listener = MakeGarbageCollected<DOMContentLoadedListener>(pi);
   document.addEventListener(event_type_names::kDOMContentLoaded, listener,
                             false);
   DCHECK(!pi->EventListenerForXSLT());
diff --git a/third_party/blink/renderer/core/xml/native_xpath_ns_resolver.h b/third_party/blink/renderer/core/xml/native_xpath_ns_resolver.h
index 921f117..442dcfb 100644
--- a/third_party/blink/renderer/core/xml/native_xpath_ns_resolver.h
+++ b/third_party/blink/renderer/core/xml/native_xpath_ns_resolver.h
@@ -35,10 +35,6 @@
 
 class NativeXPathNSResolver final : public XPathNSResolver {
  public:
-  static NativeXPathNSResolver* Create(Node* node) {
-    return MakeGarbageCollected<NativeXPathNSResolver>(node);
-  }
-
   explicit NativeXPathNSResolver(Node*);
 
   AtomicString lookupNamespaceURI(const String& prefix) override;
diff --git a/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc b/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
index f59fc76..5eebb52 100644
--- a/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
+++ b/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
@@ -460,7 +460,7 @@
     return true;
   }
 
-  XMLDocumentParser* parser = XMLDocumentParser::Create(
+  auto* parser = MakeGarbageCollected<XMLDocumentParser>(
       fragment, context_element, parser_content_policy);
   bool well_formed = parser->AppendFragmentSource(chunk);
 
diff --git a/third_party/blink/renderer/core/xml/parser/xml_document_parser.h b/third_party/blink/renderer/core/xml/parser/xml_document_parser.h
index cdffa58..aaf355cb 100644
--- a/third_party/blink/renderer/core/xml/parser/xml_document_parser.h
+++ b/third_party/blink/renderer/core/xml/parser/xml_document_parser.h
@@ -73,16 +73,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(XMLDocumentParser);
 
  public:
-  static XMLDocumentParser* Create(Document& document, LocalFrameView* view) {
-    return MakeGarbageCollected<XMLDocumentParser>(document, view);
-  }
-  static XMLDocumentParser* Create(DocumentFragment* fragment,
-                                   Element* element,
-                                   ParserContentPolicy parser_content_policy) {
-    return MakeGarbageCollected<XMLDocumentParser>(fragment, element,
-                                                   parser_content_policy);
-  }
-
   explicit XMLDocumentParser(Document&, LocalFrameView* = nullptr);
   XMLDocumentParser(DocumentFragment*, Element*, ParserContentPolicy);
   ~XMLDocumentParser() override;
diff --git a/third_party/blink/renderer/core/xml/xpath_evaluator.cc b/third_party/blink/renderer/core/xml/xpath_evaluator.cc
index 3c1cede..7965d2e2 100644
--- a/third_party/blink/renderer/core/xml/xpath_evaluator.cc
+++ b/third_party/blink/renderer/core/xml/xpath_evaluator.cc
@@ -47,7 +47,7 @@
 }
 
 XPathNSResolver* XPathEvaluator::createNSResolver(Node* node_resolver) {
-  return NativeXPathNSResolver::Create(node_resolver);
+  return MakeGarbageCollected<NativeXPathNSResolver>(node_resolver);
 }
 
 XPathResult* XPathEvaluator::evaluate(const String& expression,
diff --git a/third_party/blink/renderer/core/xml/xpath_expression.cc b/third_party/blink/renderer/core/xml/xpath_expression.cc
index 7002fbb..7bc0d20 100644
--- a/third_party/blink/renderer/core/xml/xpath_expression.cc
+++ b/third_party/blink/renderer/core/xml/xpath_expression.cc
@@ -44,7 +44,7 @@
     const String& expression,
     XPathNSResolver* resolver,
     ExceptionState& exception_state) {
-  XPathExpression* expr = XPathExpression::Create();
+  auto* expr = MakeGarbageCollected<XPathExpression>();
   Parser parser;
 
   expr->top_expression_ =
@@ -73,7 +73,7 @@
   }
 
   EvaluationContext evaluation_context(*context_node);
-  XPathResult* result = XPathResult::Create(
+  auto* result = MakeGarbageCollected<XPathResult>(
       evaluation_context, top_expression_->Evaluate(evaluation_context));
 
   if (evaluation_context.had_type_conversion_error) {
diff --git a/third_party/blink/renderer/core/xml/xpath_expression.h b/third_party/blink/renderer/core/xml/xpath_expression.h
index 5e6655f..be7c60a 100644
--- a/third_party/blink/renderer/core/xml/xpath_expression.h
+++ b/third_party/blink/renderer/core/xml/xpath_expression.h
@@ -46,10 +46,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static XPathExpression* Create() {
-    return MakeGarbageCollected<XPathExpression>();
-  }
-
   static XPathExpression* CreateExpression(const String& expression,
                                            XPathNSResolver*,
                                            ExceptionState&);
diff --git a/third_party/blink/renderer/core/xml/xpath_result.h b/third_party/blink/renderer/core/xml/xpath_result.h
index 80b25fcf..59a06470 100644
--- a/third_party/blink/renderer/core/xml/xpath_result.h
+++ b/third_party/blink/renderer/core/xml/xpath_result.h
@@ -59,11 +59,6 @@
     kFirstOrderedNodeType = 9
   };
 
-  static XPathResult* Create(xpath::EvaluationContext& context,
-                             const xpath::Value& value) {
-    return MakeGarbageCollected<XPathResult>(context, value);
-  }
-
   XPathResult(xpath::EvaluationContext&, const xpath::Value&);
 
   void ConvertTo(uint16_t type, ExceptionState&);
diff --git a/third_party/blink/renderer/core/xml/xpath_value.cc b/third_party/blink/renderer/core/xml/xpath_value.cc
index 402f907..491c3427 100644
--- a/third_party/blink/renderer/core/xml/xpath_value.cc
+++ b/third_party/blink/renderer/core/xml/xpath_value.cc
@@ -64,7 +64,7 @@
     context.had_type_conversion_error = true;
 
   if (!data_)
-    data_ = ValueData::Create();
+    data_ = MakeGarbageCollected<ValueData>();
 
   type_ = kNodeSetValue;
   return data_->GetNodeSet();
diff --git a/third_party/blink/renderer/core/xml/xpath_value.h b/third_party/blink/renderer/core/xml/xpath_value.h
index ff23f413..3a3e523 100644
--- a/third_party/blink/renderer/core/xml/xpath_value.h
+++ b/third_party/blink/renderer/core/xml/xpath_value.h
@@ -39,17 +39,6 @@
 
 class ValueData : public GarbageCollectedFinalized<ValueData> {
  public:
-  static ValueData* Create() { return MakeGarbageCollected<ValueData>(); }
-  static ValueData* Create(const NodeSet& node_set) {
-    return MakeGarbageCollected<ValueData>(node_set);
-  }
-  static ValueData* Create(NodeSet* node_set) {
-    return MakeGarbageCollected<ValueData>(node_set);
-  }
-  static ValueData* Create(const String& string) {
-    return MakeGarbageCollected<ValueData>(string);
-  }
-
   ValueData() : node_set_(NodeSet::Create()) {}
   explicit ValueData(const NodeSet& node_set)
       : node_set_(NodeSet::Create(node_set)) {}
@@ -82,22 +71,22 @@
       : type_(kStringValue),
         bool_(false),
         number_(0),
-        data_(ValueData::Create(value)) {}
+        data_(MakeGarbageCollected<ValueData>(value)) {}
   Value(const String& value)
       : type_(kStringValue),
         bool_(false),
         number_(0),
-        data_(ValueData::Create(value)) {}
+        data_(MakeGarbageCollected<ValueData>(value)) {}
   Value(const NodeSet& value)
       : type_(kNodeSetValue),
         bool_(false),
         number_(0),
-        data_(ValueData::Create(value)) {}
+        data_(MakeGarbageCollected<ValueData>(value)) {}
   Value(Node* value)
       : type_(kNodeSetValue),
         bool_(false),
         number_(0),
-        data_(ValueData::Create()) {
+        data_(MakeGarbageCollected<ValueData>()) {
     data_->GetNodeSet().Append(value);
   }
   void Trace(blink::Visitor*);
@@ -113,7 +102,7 @@
       : type_(kNodeSetValue),
         bool_(false),
         number_(0),
-        data_(ValueData::Create(value)) {}
+        data_(MakeGarbageCollected<ValueData>(value)) {}
 
   Type GetType() const { return type_; }
 
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
index 2489247..b5cc4378 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -230,11 +230,6 @@
     : public GarbageCollectedFinalized<XMLHttpRequest::BlobLoader>,
       public FileReaderLoaderClient {
  public:
-  static BlobLoader* Create(XMLHttpRequest* xhr,
-                            scoped_refptr<BlobDataHandle> handle) {
-    return MakeGarbageCollected<BlobLoader>(xhr, std::move(handle));
-  }
-
   BlobLoader(XMLHttpRequest* xhr, scoped_refptr<BlobDataHandle> handle)
       : xhr_(xhr),
         loader_(std::make_unique<FileReaderLoader>(
@@ -289,7 +284,7 @@
     scoped_refptr<SecurityOrigin> isolated_world_security_origin)
     : ContextLifecycleObserver(context),
       progress_event_throttle_(
-          XMLHttpRequestProgressEventThrottle::Create(this)),
+          MakeGarbageCollected<XMLHttpRequestProgressEventThrottle>(this)),
       isolate_(isolate),
       is_isolated_world_(is_isolated_world),
       isolated_world_security_origin_(
@@ -552,7 +547,7 @@
 
 XMLHttpRequestUpload* XMLHttpRequest::upload() {
   if (!upload_)
-    upload_ = XMLHttpRequestUpload::Create(this);
+    upload_ = MakeGarbageCollected<XMLHttpRequestUpload>(this);
   return upload_;
 }
 
@@ -1689,8 +1684,8 @@
     // In this case, we have sent the request with DownloadToBlob true,
     // but the user changed the response type after that. Hence we need to
     // read the response data and provide it to this object.
-    blob_loader_ =
-        BlobLoader::Create(this, response_blob_->GetBlobDataHandle());
+    blob_loader_ = MakeGarbageCollected<BlobLoader>(
+        this, response_blob_->GetBlobDataHandle());
   } else {
     DidFinishLoadingInternal();
   }
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h
index fa0087f..d8b7719a 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h
@@ -53,12 +53,6 @@
     : public GarbageCollectedFinalized<XMLHttpRequestProgressEventThrottle>,
       public TimerBase {
  public:
-  static XMLHttpRequestProgressEventThrottle* Create(
-      XMLHttpRequest* event_target) {
-    return MakeGarbageCollected<XMLHttpRequestProgressEventThrottle>(
-        event_target);
-  }
-
   explicit XMLHttpRequestProgressEventThrottle(XMLHttpRequest*);
   ~XMLHttpRequestProgressEventThrottle() override;
 
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_upload.h b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_upload.h
index 5119a2d..9c08914 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_upload.h
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_upload.h
@@ -41,10 +41,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static XMLHttpRequestUpload* Create(XMLHttpRequest* xml_http_request) {
-    return MakeGarbageCollected<XMLHttpRequestUpload>(xml_http_request);
-  }
-
   explicit XMLHttpRequestUpload(XMLHttpRequest*);
 
   XMLHttpRequest* XmlHttpRequest() const { return xml_http_request_; }
diff --git a/third_party/blink/renderer/devtools/BUILD.gn b/third_party/blink/renderer/devtools/BUILD.gn
index 15a28ac0..62a1293a 100644
--- a/third_party/blink/renderer/devtools/BUILD.gn
+++ b/third_party/blink/renderer/devtools/BUILD.gn
@@ -523,7 +523,6 @@
   "front_end/profiler/HeapSnapshotProxy.js",
   "front_end/profiler/HeapSnapshotView.js",
   "front_end/profiler/HeapTimelineOverview.js",
-  "front_end/profiler/IsolateManager.js",
   "front_end/profiler/IsolateSelector.js",
   "front_end/profiler/LiveHeapProfileView.js",
   "front_end/profiler/liveHeapProfile.css",
@@ -607,6 +606,7 @@
   "front_end/sdk/FilmStripModel.js",
   "front_end/sdk/HARLog.js",
   "front_end/sdk/HeapProfilerModel.js",
+  "front_end/sdk/IsolateManager.js",
   "front_end/sdk/LayerTreeBase.js",
   "front_end/sdk/LogModel.js",
   "front_end/sdk/module.json",
diff --git a/third_party/blink/renderer/devtools/front_end/elements/StylePropertyTreeElement.js b/third_party/blink/renderer/devtools/front_end/elements/StylePropertyTreeElement.js
index fc355e8c..edea0b5 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/StylePropertyTreeElement.js
+++ b/third_party/blink/renderer/devtools/front_end/elements/StylePropertyTreeElement.js
@@ -609,14 +609,15 @@
 
     this._prompt = new Elements.StylesSidebarPane.CSSPropertyPrompt(this, isEditingName);
     this._prompt.setAutocompletionTimeout(0);
-    if (section)
-      section.startEditing();
 
     // Do not live-edit "content" property of pseudo elements. crbug.com/433889
     if (!isEditingName && (!this._parentPane.node().pseudoType() || this.name !== 'content'))
       this._prompt.addEventListener(UI.TextPrompt.Events.TextChanged, this._applyFreeFlowStyleTextEdit.bind(this));
 
+    // Attach prompt before `section.startEditing()`, which manually sets height. crbug.com/949383
     const proxyElement = this._prompt.attachAndStartEditing(selectElement, blurListener.bind(this, context));
+    if (section)
+      section.startEditing();
     this._navigateToSource(selectElement, true);
 
     proxyElement.addEventListener('keydown', this._editingNameValueKeyDown.bind(this, context), false);
diff --git a/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js b/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js
index 2e2986d..e8b74a7 100644
--- a/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js
+++ b/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js
@@ -7,10 +7,7 @@
  * @implements {SDK.SDKModelObserver<!SDK.HeapProfilerModel>}
  */
 PerfUI.LiveHeapProfile = class {
-  /**
-   * @override
-   */
-  run() {
+  constructor() {
     SDK.targetManager.observeModels(SDK.HeapProfilerModel, this);
     requestIdleCallback(() => this.onUpdateProfiles(), {timeout: 100});
     PerfUI.LiveHeapProfile.hasStartedForTest(true);
@@ -30,10 +27,16 @@
 
   /**
    * @override
+   */
+  run() {
+  }
+
+  /**
+   * @override
    * @param {!SDK.HeapProfilerModel} model
    */
   modelAdded(model) {
-    model.startSampling(1024);
+    model.startSampling(1e4);
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/IsolateManager.js b/third_party/blink/renderer/devtools/front_end/profiler/IsolateManager.js
deleted file mode 100644
index 87e3c34..0000000
--- a/third_party/blink/renderer/devtools/front_end/profiler/IsolateManager.js
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2019 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.
-
-/**
- * @extends {Common.Object}
- * @implements {SDK.SDKModelObserver}
- */
-Profiler.IsolateManager = class extends Common.Object {
-  constructor() {
-    super();
-    /** @type {!Map<string, !Profiler.IsolateManager.Isolate>} */
-    this._isolates = new Map();
-    // _isolateIdByModel contains null while the isolateId is being retrieved.
-    /** @type {!Map<!SDK.RuntimeModel, ?string>} */
-    this._isolateIdByModel = new Map();
-    SDK.targetManager.observeModels(SDK.RuntimeModel, this);
-  }
-
-  /**
-   * @override
-   * @param {!SDK.RuntimeModel} model
-   */
-  modelAdded(model) {
-    this._modelAdded(model);
-  }
-
-  /**
-   * @param {!SDK.RuntimeModel} model
-   */
-  async _modelAdded(model) {
-    this._isolateIdByModel.set(model, null);
-    const isolateId = await model.isolateId();
-    if (!this._isolateIdByModel.has(model)) {
-      // The model has been removed during await.
-      return;
-    }
-    this._isolateIdByModel.delete(model);
-    if (!isolateId)
-      return;
-    this._isolateIdByModel.set(model, isolateId);
-    let isolate = this._isolates.get(isolateId);
-    if (!isolate) {
-      isolate = new Profiler.IsolateManager.Isolate(isolateId);
-      this._isolates.set(isolateId, isolate);
-    }
-    const event = !isolate._models.size ? Profiler.IsolateManager.Events.IsolateAdded :
-                                          Profiler.IsolateManager.Events.IsolateChanged;
-    isolate._models.add(model);
-    this.dispatchEventToListeners(event, isolate);
-  }
-
-  /**
-   * @override
-   * @param {!SDK.RuntimeModel} model
-   */
-  modelRemoved(model) {
-    const isolateId = this._isolateIdByModel.get(model);
-    this._isolateIdByModel.delete(model);
-    if (!isolateId)
-      return;
-    const isolate = this._isolates.get(isolateId);
-    isolate._models.delete(model);
-    if (isolate._models.size) {
-      this.dispatchEventToListeners(Profiler.IsolateManager.Events.IsolateChanged, isolate);
-    } else {
-      this.dispatchEventToListeners(Profiler.IsolateManager.Events.IsolateRemoved, isolate);
-      this._isolates.delete(isolateId);
-    }
-  }
-
-  /**
-   * @param {!SDK.RuntimeModel} model
-   * @return {?Profiler.IsolateManager.Isolate}
-   */
-  isolateByModel(model) {
-    return this._isolates.get(this._isolateIdByModel.get(model) || '') || null;
-  }
-};
-
-/** @enum {symbol} */
-Profiler.IsolateManager.Events = {
-  IsolateAdded: Symbol('IsolateAdded'),
-  IsolateRemoved: Symbol('IsolateRemoved'),
-  IsolateChanged: Symbol('IsolateChanged')
-};
-
-Profiler.IsolateManager.Isolate = class {
-  /**
-   * @param {string} id
-   */
-  constructor(id) {
-    this._id = id;
-    /** @type {!Set<!SDK.RuntimeModel>} */
-    this._models = new Set();
-  }
-
-  /**
-   * @return {string}
-   */
-  id() {
-    return this._id;
-  }
-
-  /**
-   * @return {!Set<!SDK.RuntimeModel>}
-   */
-  models() {
-    return this._models;
-  }
-};
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js b/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js
index 417446d..8ef5c4d 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js
+++ b/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js
@@ -4,6 +4,7 @@
 
 /**
  * @implements {UI.ListDelegate<!Profiler.IsolateSelector.ListItem>}
+ * @implements {SDK.IsolateManager.Observer}
  */
 Profiler.IsolateSelector = class extends UI.VBox {
   constructor() {
@@ -16,14 +17,11 @@
     this.contentElement.appendChild(this._list.element);
 
     this.registerRequiredCSS('profiler/profileLauncherView.css');
-    /** @type {!Map<!Profiler.IsolateManager.Isolate, !Profiler.IsolateSelector.ListItem>} */
+    /** @type {!Map<!SDK.IsolateManager.Isolate, !Profiler.IsolateSelector.ListItem>} */
     this._itemByIsolate = new Map();
     this._updateTimer = null;
 
-    this._isolateManager = new Profiler.IsolateManager();
-    this._isolateManager.addEventListener(Profiler.IsolateManager.Events.IsolateAdded, this._isolateAdded, this);
-    this._isolateManager.addEventListener(Profiler.IsolateManager.Events.IsolateRemoved, this._isolateRemoved, this);
-    this._isolateManager.addEventListener(Profiler.IsolateManager.Events.IsolateChanged, this._isolateChanged, this);
+    SDK.isolateManager.observeIsolates(this);
 
     SDK.targetManager.addEventListener(SDK.TargetManager.Events.NameChanged, this._targetChanged, this);
     SDK.targetManager.addEventListener(SDK.TargetManager.Events.InspectedURLChanged, this._targetChanged, this);
@@ -44,10 +42,10 @@
   }
 
   /**
-   * @param {!Common.Event} event
+   * @override
+   * @param {!SDK.IsolateManager.Isolate} isolate
    */
-  _isolateAdded(event) {
-    const isolate = /** @type {!Profiler.IsolateManager.Isolate} */ (event.data);
+  isolateAdded(isolate) {
     const item = new Profiler.IsolateSelector.ListItem(isolate);
     const index = item.model().target() === SDK.targetManager.mainTarget() ? 0 : this._items.length;
     this._items.insert(index, item);
@@ -58,20 +56,20 @@
   }
 
   /**
-   * @param {!Common.Event} event
+   * @override
+   * @param {!SDK.IsolateManager.Isolate} isolate
    */
-  _isolateChanged(event) {
-    const isolate = /** @type {!Profiler.IsolateManager.Isolate} */ (event.data);
+  isolateChanged(isolate) {
     const item = this._itemByIsolate.get(isolate);
     item.updateTitle();
     this._update();
   }
 
   /**
-   * @param {!Common.Event} event
+   * @override
+   * @param {!SDK.IsolateManager.Isolate} isolate
    */
-  _isolateRemoved(event) {
-    const isolate = /** @type {!Profiler.IsolateManager.Isolate} */ (event.data);
+  isolateRemoved(isolate) {
     const item = this._itemByIsolate.get(isolate);
     this._items.remove(this._items.indexOf(item));
     this._itemByIsolate.delete(isolate);
@@ -86,7 +84,7 @@
     const model = target.model(SDK.RuntimeModel);
     if (!model)
       return;
-    const isolate = this._isolateManager.isolateByModel(model);
+    const isolate = SDK.isolateManager.isolateByModel(model);
     const item = isolate && this._itemByIsolate.get(isolate);
     if (item)
       item.updateTitle();
@@ -142,14 +140,15 @@
   _updateStats() {
     for (const item of this._itemByIsolate.values())
       item.updateStats();
-    const heapStatsUpdateIntervalMs = 2000;
-    this._updateTimer = setTimeout(() => this._updateStats(), heapStatsUpdateIntervalMs);
+    this._updateTimer = setTimeout(() => this._updateStats(), Profiler.IsolateSelector._heapStatsUpdateIntervalMs);
   }
 };
 
+Profiler.IsolateSelector._heapStatsUpdateIntervalMs = 2000;
+
 Profiler.IsolateSelector.ListItem = class {
   /**
-   * @param {!Profiler.IsolateManager.Isolate} isolateInfo
+   * @param {!SDK.IsolateManager.Isolate} isolateInfo
    */
   constructor(isolateInfo) {
     this._isolateInfo = isolateInfo;
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/module.json b/third_party/blink/renderer/devtools/front_end/profiler/module.json
index f5095ed7..5fb4ec3 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/module.json
+++ b/third_party/blink/renderer/devtools/front_end/profiler/module.json
@@ -108,7 +108,6 @@
         "HeapSnapshotGridNodes.js",
         "HeapSnapshotView.js",
         "HeapTimelineOverview.js",
-        "IsolateManager.js",
         "IsolateSelector.js",
         "LiveHeapProfileView.js",
         "ProfileLauncherView.js",
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/IsolateManager.js b/third_party/blink/renderer/devtools/front_end/sdk/IsolateManager.js
new file mode 100644
index 0000000..8de9463
--- /dev/null
+++ b/third_party/blink/renderer/devtools/front_end/sdk/IsolateManager.js
@@ -0,0 +1,162 @@
+// Copyright 2019 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.
+
+/**
+ * @extends {Common.Object}
+ * @implements {SDK.SDKModelObserver}
+ */
+SDK.IsolateManager = class extends Common.Object {
+  constructor() {
+    super();
+    console.assert(!SDK.isolateManager, 'Use SDK.isolateManager singleton.');
+    /** @type {!Map<string, !SDK.IsolateManager.Isolate>} */
+    this._isolates = new Map();
+    // _isolateIdByModel contains null while the isolateId is being retrieved.
+    /** @type {!Map<!SDK.RuntimeModel, ?string>} */
+    this._isolateIdByModel = new Map();
+    /** @type {!Set<!SDK.IsolateManager.Observer>} */
+    this._observers = new Set();
+    SDK.targetManager.observeModels(SDK.RuntimeModel, this);
+  }
+
+  /**
+   * @param {!SDK.IsolateManager.Observer} observer
+   */
+  observeIsolates(observer) {
+    if (this._observers.has(observer))
+      throw new Error('Observer can only be registered once');
+    this._observers.add(observer);
+    for (const isolate of this._isolates.values())
+      observer.isolateAdded(isolate);
+  }
+
+  /**
+   * @param {!SDK.IsolateManager.Observer} observer
+   */
+  unobserveIsolates(observer) {
+    this._observers.delete(observer);
+  }
+
+  /**
+   * @override
+   * @param {!SDK.RuntimeModel} model
+   */
+  modelAdded(model) {
+    this._modelAdded(model);
+  }
+
+  /**
+   * @param {!SDK.RuntimeModel} model
+   */
+  async _modelAdded(model) {
+    this._isolateIdByModel.set(model, null);
+    const isolateId = await model.isolateId();
+    if (!this._isolateIdByModel.has(model)) {
+      // The model has been removed during await.
+      return;
+    }
+    if (!isolateId) {
+      this._isolateIdByModel.delete(model);
+      return;
+    }
+    this._isolateIdByModel.set(model, isolateId);
+    let isolate = this._isolates.get(isolateId);
+    if (!isolate) {
+      isolate = new SDK.IsolateManager.Isolate(isolateId);
+      this._isolates.set(isolateId, isolate);
+    }
+    isolate._models.add(model);
+    if (isolate._models.size === 1) {
+      for (const observer of this._observers)
+        observer.isolateAdded(isolate);
+    } else {
+      for (const observer of this._observers)
+        observer.isolateChanged(isolate);
+    }
+  }
+
+  /**
+   * @override
+   * @param {!SDK.RuntimeModel} model
+   */
+  modelRemoved(model) {
+    const isolateId = this._isolateIdByModel.get(model);
+    this._isolateIdByModel.delete(model);
+    if (!isolateId)
+      return;
+    const isolate = this._isolates.get(isolateId);
+    isolate._models.delete(model);
+    if (isolate._models.size) {
+      for (const observer of this._observers)
+        observer.isolateChanged(isolate);
+      return;
+    }
+    for (const observer of this._observers)
+      observer.isolateRemoved(isolate);
+    this._isolates.delete(isolateId);
+  }
+
+  /**
+   * @param {!SDK.RuntimeModel} model
+   * @return {?SDK.IsolateManager.Isolate}
+   */
+  isolateByModel(model) {
+    return this._isolates.get(this._isolateIdByModel.get(model) || '') || null;
+  }
+
+  /**
+   * @return {!IteratorIterable<!SDK.IsolateManager.Isolate>}
+   */
+  isolates() {
+    return this._isolates.values();
+  }
+};
+
+/**
+ * @interface
+ */
+SDK.IsolateManager.Observer = function() {};
+
+SDK.IsolateManager.Observer.prototype = {
+  /**
+   * @param {!SDK.IsolateManager.Isolate} isolate
+   */
+  isolateAdded(isolate) {},
+
+  /**
+   * @param {!SDK.IsolateManager.Isolate} isolate
+   */
+  isolateRemoved(isolate) {},
+  /**
+   * @param {!SDK.IsolateManager.Isolate} isolate
+   */
+  isolateChanged(isolate) {},
+};
+
+SDK.IsolateManager.Isolate = class {
+  /**
+   * @param {string} id
+   */
+  constructor(id) {
+    this._id = id;
+    /** @type {!Set<!SDK.RuntimeModel>} */
+    this._models = new Set();
+  }
+
+  /**
+   * @return {string}
+   */
+  id() {
+    return this._id;
+  }
+
+  /**
+   * @return {!Set<!SDK.RuntimeModel>}
+   */
+  models() {
+    return this._models;
+  }
+};
+
+SDK.isolateManager = new SDK.IsolateManager();
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/module.json b/third_party/blink/renderer/devtools/front_end/sdk/module.json
index d58a50b..c268885 100644
--- a/third_party/blink/renderer/devtools/front_end/sdk/module.json
+++ b/third_party/blink/renderer/devtools/front_end/sdk/module.json
@@ -328,6 +328,7 @@
         "TracingModel.js",
         "OverlayModel.js",
         "RuntimeModel.js",
+        "IsolateManager.js",
         "ScreenCaptureModel.js",
         "Script.js",
         "ServiceWorkerCacheModel.js",
diff --git a/third_party/blink/renderer/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js b/third_party/blink/renderer/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js
index 281c34c..6eff15b7 100644
--- a/third_party/blink/renderer/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js
+++ b/third_party/blink/renderer/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js
@@ -46,12 +46,17 @@
 
     breakpointLocations.sort((item1, item2) => item1.uiLocation.compareTo(item2.uiLocation));
 
+    /** @type {!Multimap<string, string>} */
+    const breakpointEntriesForLine = new Multimap();
+
     /** @type {!Multimap<string, !{breakpoint: !Bindings.BreakpointManager.Breakpoint, uiLocation: !Workspace.UILocation}>} */
     const locationForEntry = new Multimap();
     for (const breakpointLocation of breakpointLocations) {
       const uiLocation = breakpointLocation.uiLocation;
-      const entryDescriptor = uiLocation.uiSourceCode.url() + ':' + uiLocation.lineNumber;
+      const entryDescriptor = `${uiLocation.uiSourceCode.url()}:${uiLocation.lineNumber}:${uiLocation.columnNumber}`;
       locationForEntry.set(entryDescriptor, breakpointLocation);
+      const lineDescriptor = `${uiLocation.uiSourceCode.url()}:${uiLocation.lineNumber}`;
+      breakpointEntriesForLine.set(lineDescriptor, entryDescriptor);
     }
 
     const details = UI.context.flavor(SDK.DebuggerPausedDetails);
@@ -81,7 +86,10 @@
           !!selectedUILocation && locations.some(location => location.uiLocation.id() === selectedUILocation.id());
       const hasEnabled = locations.some(location => location.breakpoint.enabled());
       const hasDisabled = locations.some(location => !location.breakpoint.enabled());
-      promises.push(this._resetEntry(/** @type {!Element}*/ (entry), uiLocation, isSelected, hasEnabled, hasDisabled));
+      const showCoumn =
+          breakpointEntriesForLine.get(`${uiLocation.uiSourceCode.url()}:${uiLocation.lineNumber}`).size > 1;
+      promises.push(
+          this._resetEntry(/** @type {!Element}*/ (entry), uiLocation, isSelected, hasEnabled, hasDisabled, showCoumn));
       entry[Sources.JavaScriptBreakpointsSidebarPane._breakpointLocationsSymbol] = locations;
       if (isSelected)
         shouldShowView = true;
@@ -105,32 +113,28 @@
    * @param {boolean} isSelected
    * @param {boolean} hasEnabled
    * @param {boolean} hasDisabled
-   * @return {!Promise<undefined>}
+   * @param {boolean} showColumn
+   * @return {!Promise}
    */
-  _resetEntry(element, uiLocation, isSelected, hasEnabled, hasDisabled) {
+  async _resetEntry(element, uiLocation, isSelected, hasEnabled, hasDisabled, showColumn) {
     element[Sources.JavaScriptBreakpointsSidebarPane._locationSymbol] = uiLocation;
     element.classList.toggle('breakpoint-hit', isSelected);
 
     const checkboxLabel = element[Sources.JavaScriptBreakpointsSidebarPane._checkboxLabelSymbol];
-    checkboxLabel.textElement.textContent = uiLocation.linkText();
+    checkboxLabel.textElement.textContent =
+        uiLocation.linkText() + (showColumn ? ':' + (uiLocation.columnNumber + 1) : '');
     checkboxLabel.checkboxElement.checked = hasEnabled;
     checkboxLabel.checkboxElement.indeterminate = hasEnabled && hasDisabled;
 
     const snippetElement = element[Sources.JavaScriptBreakpointsSidebarPane._snippetElementSymbol];
-    return uiLocation.uiSourceCode.requestContent().then(fillSnippetElement.bind(null, snippetElement));
-
-    /**
-     * @param {!Element} snippetElement
-     * @param {?string} content
-     */
-    function fillSnippetElement(snippetElement, content) {
-      const lineNumber = uiLocation.lineNumber;
-      const text = new TextUtils.Text(content || '');
-      if (lineNumber < text.lineCount()) {
-        const lineText = text.lineAt(lineNumber);
-        const maxSnippetLength = 200;
-        snippetElement.textContent = lineText.trimEnd(maxSnippetLength);
-      }
+    const content = await uiLocation.uiSourceCode.requestContent();
+    const lineNumber = uiLocation.lineNumber;
+    const text = new TextUtils.Text(content || '');
+    if (lineNumber < text.lineCount()) {
+      const lineText = text.lineAt(lineNumber);
+      const maxSnippetLength = 200;
+      snippetElement.textContent =
+          lineText.substring(showColumn ? uiLocation.columnNumber : 0).trimEnd(maxSnippetLength);
     }
   }
 
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 2a7f86fd..24999f7 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -55,6 +55,7 @@
     "event_modules.h",
     "event_modules_factory.h",
     "event_target_modules.h",
+    "modules_export.h",
     "modules_initializer.cc",
     "modules_initializer.h",
   ]
@@ -80,10 +81,6 @@
     "//tools/v8_context_snapshot:use_v8_context_snapshot",
   ]
 
-  public_deps = [
-    ":modules_export_header",
-  ]
-
   deps = [
     ":make_modules_generated",
     ":module_names",
@@ -194,20 +191,6 @@
   }
 }
 
-# modules_export.h is in its own build target to allow mojo types to use it
-# without depending on the whole of modules.
-source_set("modules_export_header") {
-  # Opening up for mojo types to use this header.
-  visibility = []
-  visibility = [
-    "//third_party/blink/public/mojom:mojom_modules_blink",
-    "//third_party/blink/renderer/*",
-  ]
-  sources = [
-    "modules_export.h",
-  ]
-}
-
 jumbo_source_set("modules_testing") {
   sources = [
     "$bindings_modules_v8_output_dir/v8_internals_partial.cc",
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet.cc
index b0df59eb..72d6025a 100644
--- a/third_party/blink/renderer/modules/animationworklet/animation_worklet.cc
+++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet.cc
@@ -46,7 +46,7 @@
         AnimationWorkletProxyClient::FromDocument(document, worklet_id_);
   }
 
-  WorkerClients* worker_clients = WorkerClients::Create();
+  auto* worker_clients = MakeGarbageCollected<WorkerClients>();
   ProvideAnimationWorkletProxyClientTo(worker_clients, proxy_client_);
 
   AnimationWorkletMessagingProxy* proxy =
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc
index c72460c..30b5b91 100644
--- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc
+++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc
@@ -37,13 +37,6 @@
 
 }  // namespace
 
-AnimationWorkletGlobalScope* AnimationWorkletGlobalScope::Create(
-    std::unique_ptr<GlobalScopeCreationParams> creation_params,
-    WorkerThread* thread) {
-  return MakeGarbageCollected<AnimationWorkletGlobalScope>(
-      std::move(creation_params), thread);
-}
-
 AnimationWorkletGlobalScope::AnimationWorkletGlobalScope(
     std::unique_ptr<GlobalScopeCreationParams> creation_params,
     WorkerThread* thread)
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h
index b384136aa..f27dcaea 100644
--- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h
+++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h
@@ -33,10 +33,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static AnimationWorkletGlobalScope* Create(
-      std::unique_ptr<GlobalScopeCreationParams>,
-      WorkerThread*);
-
   AnimationWorkletGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
                               WorkerThread*);
   ~AnimationWorkletGlobalScope() override;
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc
index aab162e..d0a6432 100644
--- a/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc
+++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc
@@ -79,7 +79,7 @@
 class WorkletAnimationTest : public RenderingTest {
  public:
   WorkletAnimationTest()
-      : RenderingTest(SingleChildLocalFrameClient::Create()) {}
+      : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
 
   void SetUp() override {
     RenderingTest::SetUp();
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
index 6856bd2..e9a1585 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
@@ -272,8 +272,8 @@
     return;
   }
 
-  auto* scan =
-      BluetoothLEScan::Create(id, this, std::move(result->get_options()));
+  auto* scan = MakeGarbageCollected<BluetoothLEScan>(
+      id, this, std::move(result->get_options()));
   resolver->Resolve(scan);
 }
 
@@ -377,7 +377,7 @@
   if (result->appearance_is_set)
     appearance = result->appearance;
 
-  auto* event = BluetoothAdvertisingEvent::Create(
+  auto* event = MakeGarbageCollected<BluetoothAdvertisingEvent>(
       event_type_names::kAdvertisementreceived, bluetooth_device, result->name,
       uuids, appearance, tx_power, rssi, manufacturer_data, service_data);
   DispatchEvent(*event);
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth.h b/third_party/blink/renderer/modules/bluetooth/bluetooth.h
index 35ccc4942..a8655d1 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth.h
@@ -26,10 +26,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(Bluetooth);
 
  public:
-  static Bluetooth* Create(ExecutionContext* context) {
-    return MakeGarbageCollected<Bluetooth>(context);
-  }
-
   explicit Bluetooth(ExecutionContext*);
   ~Bluetooth() override;
 
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h b/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h
index 23a8a6eb..a9e6a8c 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h
@@ -19,28 +19,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static BluetoothAdvertisingEvent* Create(
-      const AtomicString& event_type,
-      const BluetoothAdvertisingEventInit* initializer) {
-    return MakeGarbageCollected<BluetoothAdvertisingEvent>(event_type,
-                                                           initializer);
-  }
-
-  static BluetoothAdvertisingEvent* Create(
-      const AtomicString& event_type,
-      BluetoothDevice* device,
-      const String& name,
-      const HeapVector<StringOrUnsignedLong>& uuids,
-      base::Optional<uint16_t> appearance,
-      base::Optional<int8_t> txPower,
-      base::Optional<int8_t> rssi,
-      BluetoothManufacturerDataMap* manufacturer_data_map,
-      BluetoothServiceDataMap* service_data_map) {
-    return MakeGarbageCollected<BluetoothAdvertisingEvent>(
-        event_type, device, name, uuids, appearance, txPower, rssi,
-        manufacturer_data_map, service_data_map);
-  }
-
   BluetoothAdvertisingEvent(const AtomicString& event_type,
                             const BluetoothAdvertisingEventInit* initializer);
 
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_attribute_instance_map.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_attribute_instance_map.cc
index 76c96872..fc8fb49 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_attribute_instance_map.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_attribute_instance_map.cc
@@ -50,7 +50,7 @@
       characteristic_id_to_object_.at(instance_id);
 
   if (!characteristic) {
-    characteristic = BluetoothRemoteGATTCharacteristic::Create(
+    characteristic = MakeGarbageCollected<BluetoothRemoteGATTCharacteristic>(
         context, std::move(remote_gatt_characteristic), service, device_);
     characteristic_id_to_object_.insert(instance_id, characteristic);
   }
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.cc
index 041806dc..8ffe4237 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.cc
@@ -6,11 +6,6 @@
 
 namespace blink {
 
-BluetoothCharacteristicProperties* BluetoothCharacteristicProperties::Create(
-    uint32_t properties) {
-  return MakeGarbageCollected<BluetoothCharacteristicProperties>(properties);
-}
-
 bool BluetoothCharacteristicProperties::broadcast() const {
   return properties & Property::kBroadcast;
 }
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.h b/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.h
index 7a3d3da..e23f0fe 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.h
@@ -16,8 +16,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static BluetoothCharacteristicProperties* Create(uint32_t properties);
-
   explicit BluetoothCharacteristicProperties(uint32_t properties);
 
   // IDL exposed interface:
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_device.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_device.cc
index d69d3a2..9d62040 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_device.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_device.cc
@@ -27,7 +27,7 @@
       attribute_instance_map_(
           MakeGarbageCollected<BluetoothAttributeInstanceMap>(this)),
       device_(std::move(device)),
-      gatt_(BluetoothRemoteGATTServer::Create(context, this)),
+      gatt_(MakeGarbageCollected<BluetoothRemoteGATTServer>(context, this)),
       bluetooth_(bluetooth) {}
 
 BluetoothRemoteGATTService* BluetoothDevice::GetOrCreateRemoteGATTService(
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc
index 8b6bfc9..c8ea84d4 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc
@@ -6,14 +6,6 @@
 
 namespace blink {
 
-BluetoothLEScan* BluetoothLEScan::Create(
-    mojo::BindingId id,
-    Bluetooth* bluetooth,
-    mojom::blink::WebBluetoothRequestLEScanOptionsPtr options) {
-  return MakeGarbageCollected<BluetoothLEScan>(id, bluetooth,
-                                               std::move(options));
-}
-
 BluetoothLEScan::BluetoothLEScan(
     mojo::BindingId id,
     Bluetooth* bluetooth,
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h b/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h
index 881007c..dade26253 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h
@@ -16,11 +16,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static BluetoothLEScan* Create(
-      mojo::BindingId,
-      Bluetooth*,
-      mojom::blink::WebBluetoothRequestLEScanOptionsPtr);
-
   BluetoothLEScan(mojo::BindingId,
                   Bluetooth*,
                   mojom::blink::WebBluetoothRequestLEScanOptionsPtr);
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc
index 38a7d71..9c64dabd 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc
@@ -34,17 +34,8 @@
       characteristic_(std::move(characteristic)),
       service_(service),
       device_(device) {
-  properties_ =
-      BluetoothCharacteristicProperties::Create(characteristic_->properties);
-}
-
-BluetoothRemoteGATTCharacteristic* BluetoothRemoteGATTCharacteristic::Create(
-    ExecutionContext* context,
-    mojom::blink::WebBluetoothRemoteGATTCharacteristicPtr characteristic,
-    BluetoothRemoteGATTService* service,
-    BluetoothDevice* device) {
-  return MakeGarbageCollected<BluetoothRemoteGATTCharacteristic>(
-      context, std::move(characteristic), service, device);
+  properties_ = MakeGarbageCollected<BluetoothCharacteristicProperties>(
+      characteristic_->properties);
 }
 
 void BluetoothRemoteGATTCharacteristic::SetValue(DOMDataView* dom_data_view) {
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h
index 16a11bf..fdc670e 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h
@@ -50,12 +50,6 @@
       BluetoothRemoteGATTService*,
       BluetoothDevice*);
 
-  static BluetoothRemoteGATTCharacteristic* Create(
-      ExecutionContext*,
-      mojom::blink::WebBluetoothRemoteGATTCharacteristicPtr,
-      BluetoothRemoteGATTService*,
-      BluetoothDevice*);
-
   // Save value.
   void SetValue(DOMDataView*);
 
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc
index 6ddf67e2..dc80911 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc
@@ -24,12 +24,6 @@
                                                      BluetoothDevice* device)
     : ContextLifecycleObserver(context), device_(device), connected_(false) {}
 
-BluetoothRemoteGATTServer* BluetoothRemoteGATTServer::Create(
-    ExecutionContext* context,
-    BluetoothDevice* device) {
-  return MakeGarbageCollected<BluetoothRemoteGATTServer>(context, device);
-}
-
 void BluetoothRemoteGATTServer::ContextDestroyed(ExecutionContext*) {
   Dispose();
 }
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h
index 3fb9e13..abb7fd4d 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h
@@ -34,8 +34,6 @@
  public:
   BluetoothRemoteGATTServer(ExecutionContext*, BluetoothDevice*);
 
-  static BluetoothRemoteGATTServer* Create(ExecutionContext*, BluetoothDevice*);
-
   // ContextLifecycleObserver:
   void ContextDestroyed(ExecutionContext*) override;
 
diff --git a/third_party/blink/renderer/modules/bluetooth/navigator_bluetooth.cc b/third_party/blink/renderer/modules/bluetooth/navigator_bluetooth.cc
index 74a31c5..3acc1bdb 100644
--- a/third_party/blink/renderer/modules/bluetooth/navigator_bluetooth.cc
+++ b/third_party/blink/renderer/modules/bluetooth/navigator_bluetooth.cc
@@ -32,7 +32,7 @@
   if (!GetSupplementable()->GetFrame())
     return nullptr;
 
-  bluetooth_ = Bluetooth::Create(
+  bluetooth_ = MakeGarbageCollected<Bluetooth>(
       GetSupplementable()->GetFrame()->GetDocument()->GetExecutionContext());
   return bluetooth_.Get();
 }
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc
index f826df1..cbb224d0 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache.cc
+++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -571,14 +571,6 @@
   mojom::blink::FetchAPIResponsePtr fetch_api_response_;
 };
 
-Cache* Cache::Create(
-    GlobalFetch::ScopedFetcher* fetcher,
-    mojom::blink::CacheStorageCacheAssociatedPtrInfo cache_ptr_info,
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
-  return MakeGarbageCollected<Cache>(fetcher, std::move(cache_ptr_info),
-                                     std::move(task_runner));
-}
-
 ScriptPromise Cache::match(ScriptState* script_state,
                            const RequestInfo& request,
                            const CacheQueryOptions* options,
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.h b/third_party/blink/renderer/modules/cache_storage/cache.h
index 223bb3b..d3f7589 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache.h
+++ b/third_party/blink/renderer/modules/cache_storage/cache.h
@@ -49,10 +49,6 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static Cache* Create(GlobalFetch::ScopedFetcher*,
-                       mojom::blink::CacheStorageCacheAssociatedPtrInfo,
-                       scoped_refptr<base::SingleThreadTaskRunner>);
-
   Cache(GlobalFetch::ScopedFetcher*,
         mojom::blink::CacheStorageCacheAssociatedPtrInfo,
         scoped_refptr<base::SingleThreadTaskRunner>);
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_storage.cc b/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
index fa28db2..64c7213c 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
+++ b/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
@@ -81,11 +81,6 @@
 
 }  // namespace
 
-CacheStorage* CacheStorage::Create(ExecutionContext* context,
-                                   GlobalFetch::ScopedFetcher* fetcher) {
-  return MakeGarbageCollected<CacheStorage>(context, fetcher);
-}
-
 ScriptPromise CacheStorage::open(ScriptState* script_state,
                                  const String& cache_name) {
   int64_t trace_id = blink::cache_storage::CreateTraceId();
@@ -139,10 +134,10 @@
                   TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN, "status",
                   "success");
               // See https://bit.ly/2S0zRAS for task types.
-              resolver->Resolve(
-                  Cache::Create(fetcher, std::move(result->get_cache()),
-                                resolver->GetExecutionContext()->GetTaskRunner(
-                                    blink::TaskType::kMiscPlatformAPI)));
+              resolver->Resolve(MakeGarbageCollected<Cache>(
+                  fetcher, std::move(result->get_cache()),
+                  resolver->GetExecutionContext()->GetTaskRunner(
+                      blink::TaskType::kMiscPlatformAPI)));
             }
           },
           WrapPersistent(resolver), WrapPersistent(scoped_fetcher_.Get()),
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_storage.h b/third_party/blink/renderer/modules/cache_storage/cache_storage.h
index 1e79e631..4e5ae78 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache_storage.h
+++ b/third_party/blink/renderer/modules/cache_storage/cache_storage.h
@@ -30,8 +30,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(CacheStorage);
 
  public:
-  static CacheStorage* Create(ExecutionContext*, GlobalFetch::ScopedFetcher*);
-
   CacheStorage(ExecutionContext*, GlobalFetch::ScopedFetcher*);
   ~CacheStorage() override;
 
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_test.cc b/third_party/blink/renderer/modules/cache_storage/cache_test.cc
index e971a22c..c75a11dc 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache_test.cc
+++ b/third_party/blink/renderer/modules/cache_storage/cache_test.cc
@@ -55,10 +55,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(ScopedFetcherForTests);
 
  public:
-  static ScopedFetcherForTests* Create() {
-    return MakeGarbageCollected<ScopedFetcherForTests>();
-  }
-
   ScopedFetcherForTests() : fetch_count_(0), expected_url_(nullptr) {}
 
   ScriptPromise Fetch(ScriptState* script_state,
@@ -281,7 +277,7 @@
     binding_ = std::make_unique<
         mojo::AssociatedBinding<mojom::blink::CacheStorageCache>>(
         cache_.get(), std::move(request));
-    return Cache::Create(
+    return MakeGarbageCollected<Cache>(
         fetcher, cache_ptr.PassInterface(),
         blink::scheduler::GetSingleThreadTaskRunnerForTesting());
   }
@@ -402,7 +398,7 @@
 TEST_F(CacheStorageTest, Basics) {
   ScriptState::Scope scope(GetScriptState());
   NonThrowableExceptionState exception_state;
-  ScopedFetcherForTests* fetcher = ScopedFetcherForTests::Create();
+  auto* fetcher = MakeGarbageCollected<ScopedFetcherForTests>();
   Cache* cache =
       CreateCache(fetcher, std::make_unique<NotImplementedErrorCache>());
   DCHECK(cache);
@@ -434,7 +430,7 @@
 TEST_F(CacheStorageTest, BasicArguments) {
   ScriptState::Scope scope(GetScriptState());
   NonThrowableExceptionState exception_state;
-  ScopedFetcherForTests* fetcher = ScopedFetcherForTests::Create();
+  auto* fetcher = MakeGarbageCollected<ScopedFetcherForTests>();
   Cache* cache =
       CreateCache(fetcher, std::make_unique<NotImplementedErrorCache>());
   DCHECK(cache);
@@ -513,7 +509,7 @@
 TEST_F(CacheStorageTest, BatchOperationArguments) {
   ScriptState::Scope scope(GetScriptState());
   NonThrowableExceptionState exception_state;
-  ScopedFetcherForTests* fetcher = ScopedFetcherForTests::Create();
+  auto* fetcher = MakeGarbageCollected<ScopedFetcherForTests>();
   Cache* cache =
       CreateCache(fetcher, std::make_unique<NotImplementedErrorCache>());
   DCHECK(cache);
@@ -607,7 +603,7 @@
 TEST_F(CacheStorageTest, MatchResponseTest) {
   ScriptState::Scope scope(GetScriptState());
   NonThrowableExceptionState exception_state;
-  ScopedFetcherForTests* fetcher = ScopedFetcherForTests::Create();
+  auto* fetcher = MakeGarbageCollected<ScopedFetcherForTests>();
   const String request_url = "http://request.url/";
   const String response_url = "http://match.response.test/";
 
@@ -654,7 +650,7 @@
 TEST_F(CacheStorageTest, KeysResponseTest) {
   ScriptState::Scope scope(GetScriptState());
   NonThrowableExceptionState exception_state;
-  ScopedFetcherForTests* fetcher = ScopedFetcherForTests::Create();
+  auto* fetcher = MakeGarbageCollected<ScopedFetcherForTests>();
   const String url1 = "http://first.request/";
   const String url2 = "http://second.request/";
 
@@ -717,7 +713,7 @@
 TEST_F(CacheStorageTest, MatchAllAndBatchResponseTest) {
   ScriptState::Scope scope(GetScriptState());
   NonThrowableExceptionState exception_state;
-  ScopedFetcherForTests* fetcher = ScopedFetcherForTests::Create();
+  auto* fetcher = MakeGarbageCollected<ScopedFetcherForTests>();
   const String url1 = "http://first.response/";
   const String url2 = "http://second.response/";
 
@@ -770,7 +766,7 @@
 TEST_F(CacheStorageTest, Add) {
   ScriptState::Scope scope(GetScriptState());
   NonThrowableExceptionState exception_state;
-  ScopedFetcherForTests* fetcher = ScopedFetcherForTests::Create();
+  auto* fetcher = MakeGarbageCollected<ScopedFetcherForTests>();
   const String url = "http://www.cacheadd.test/";
   const String content_type = "text/plain";
   const String content = "hello cache";
diff --git a/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc b/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc
index 8862b88..7e274de 100644
--- a/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc
+++ b/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc
@@ -68,7 +68,7 @@
             "provider.");
         return nullptr;
       }
-      caches_ = CacheStorage::Create(
+      caches_ = MakeGarbageCollected<CacheStorage>(
           context, GlobalFetch::ScopedFetcher::From(fetching_scope));
     }
     return caches_;
diff --git a/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.h b/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.h
index 16d1f45..d9367e08 100644
--- a/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.h
+++ b/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.h
@@ -23,10 +23,6 @@
  public:
   using CachesMap = HashMap<String, mojom::blink::CacheStoragePtr>;
 
-  static InspectorCacheStorageAgent* Create(InspectedFrames* frames) {
-    return MakeGarbageCollected<InspectorCacheStorageAgent>(frames);
-  }
-
   explicit InspectorCacheStorageAgent(InspectedFrames*);
   ~InspectorCacheStorageAgent() override;
   void Trace(blink::Visitor*) override;
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
index 5d79219e..e3d982f 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -1735,14 +1735,23 @@
     return;
 
   if (dirty_width < 0) {
-    dirty_x += dirty_width;
-    dirty_width = base::saturated_cast<int>(base::SafeUnsignedAbs(dirty_width));
+    if (dirty_x < 0) {
+      dirty_x = dirty_width = 0;
+    } else {
+      dirty_x += dirty_width;
+      dirty_width =
+          base::saturated_cast<int>(base::SafeUnsignedAbs(dirty_width));
+    }
   }
 
   if (dirty_height < 0) {
-    dirty_y += dirty_height;
-    dirty_height =
-        base::saturated_cast<int>(base::SafeUnsignedAbs(dirty_height));
+    if (dirty_y < 0) {
+      dirty_y = dirty_height = 0;
+    } else {
+      dirty_y += dirty_height;
+      dirty_height =
+          base::saturated_cast<int>(base::SafeUnsignedAbs(dirty_height));
+    }
   }
 
   IntRect dest_rect(dirty_x, dirty_y, dirty_width, dirty_height);
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
index 5f42eec8..bc2d1f5 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
@@ -148,7 +148,7 @@
 
   PaintWorkletProxyClient* proxy_client = PaintWorkletProxyClient::Create(
       To<Document>(GetExecutionContext()), worklet_id_);
-  WorkerClients* worker_clients = WorkerClients::Create();
+  auto* worker_clients = MakeGarbageCollected<WorkerClients>();
   ProvidePaintWorkletProxyClientTo(worker_clients, proxy_client);
 
   PaintWorkletMessagingProxy* proxy =
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
index 15f7078a..6ee87442 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
@@ -39,7 +39,7 @@
   String global_scope_name =
       StringView("PaintWorklet #") + String::Number(global_scope_number);
 
-  WorkerClients* worker_clients = WorkerClients::Create();
+  auto* worker_clients = MakeGarbageCollected<WorkerClients>();
   ProvideContentSettingsClientToWorker(
       worker_clients, frame->Client()->CreateWorkerContentSettingsClient());
 
diff --git a/third_party/blink/renderer/modules/encoding/text_decoder_stream.cc b/third_party/blink/renderer/modules/encoding/text_decoder_stream.cc
index 08ae2148..9cee1c7 100644
--- a/third_party/blink/renderer/modules/encoding/text_decoder_stream.cc
+++ b/third_party/blink/renderer/modules/encoding/text_decoder_stream.cc
@@ -10,7 +10,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/streams/retain_wrapper_during_construction.h"
-#include "third_party/blink/renderer/core/streams/transform_stream_default_controller.h"
+#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h"
 #include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
 #include "third_party/blink/renderer/modules/encoding/encoding.h"
@@ -40,7 +40,7 @@
   // Implements the type conversion part of the "decode and enqueue a chunk"
   // algorithm.
   void Transform(v8::Local<v8::Value> chunk,
-                 TransformStreamDefaultController* controller,
+                 TransformStreamDefaultControllerInterface* controller,
                  ExceptionState& exception_state) override {
     ArrayBufferOrArrayBufferView bufferSource;
     V8ArrayBufferOrArrayBufferView::ToImpl(
@@ -68,7 +68,7 @@
   }
 
   // Implements the "encode and flush" algorithm.
-  void Flush(TransformStreamDefaultController* controller,
+  void Flush(TransformStreamDefaultControllerInterface* controller,
              ExceptionState& exception_state) override {
     DecodeAndEnqueue(nullptr, 0u, WTF::FlushBehavior::kDataEOF, controller,
                      exception_state);
@@ -85,7 +85,7 @@
   void DecodeAndEnqueue(const char* start,
                         uint32_t length,
                         WTF::FlushBehavior flush,
-                        TransformStreamDefaultController* controller,
+                        TransformStreamDefaultControllerInterface* controller,
                         ExceptionState& exception_state) {
     const UChar kBOM = 0xFEFF;
 
diff --git a/third_party/blink/renderer/modules/encoding/text_encoder_stream.cc b/third_party/blink/renderer/modules/encoding/text_encoder_stream.cc
index 5d827fc..b3a4bd5f 100644
--- a/third_party/blink/renderer/modules/encoding/text_encoder_stream.cc
+++ b/third_party/blink/renderer/modules/encoding/text_encoder_stream.cc
@@ -14,7 +14,7 @@
 #include "base/stl_util.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_string_resource.h"
 #include "third_party/blink/renderer/core/streams/retain_wrapper_during_construction.h"
-#include "third_party/blink/renderer/core/streams/transform_stream_default_controller.h"
+#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h"
 #include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -37,7 +37,7 @@
   // Implements the "encode and enqueue a chunk" algorithm. For efficiency, only
   // the characters at the end of chunks are special-cased.
   void Transform(v8::Local<v8::Value> chunk,
-                 TransformStreamDefaultController* controller,
+                 TransformStreamDefaultControllerInterface* controller,
                  ExceptionState& exception_state) override {
     // Let |input| be the result of converting |chunk| to a DOMString. If this
     // throws an exception, then return a promise rejected with that exception.
@@ -73,7 +73,7 @@
   }
 
   // Implements the "encode and flush" algorithm.
-  void Flush(TransformStreamDefaultController* controller,
+  void Flush(TransformStreamDefaultControllerInterface* controller,
              ExceptionState& exception_state) override {
     if (!pending_high_surrogate_.has_value())
       return;
diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
index b3a3e023..5b4ce16 100644
--- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
+++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -382,7 +382,7 @@
   bool starter_secure_context = document->IsSecureContext();
   const HttpsState starter_https_state = document->GetHttpsState();
 
-  WorkerClients* worker_clients = WorkerClients::Create();
+  auto* worker_clients = MakeGarbageCollected<WorkerClients>();
   ProvideIndexedDBClientToWorker(worker_clients,
                                  IndexedDBClient::Create(*worker_clients));
 
diff --git a/third_party/blink/renderer/modules/indexeddb/BUILD.gn b/third_party/blink/renderer/modules/indexeddb/BUILD.gn
index 80c1435..48b1124 100644
--- a/third_party/blink/renderer/modules/indexeddb/BUILD.gn
+++ b/third_party/blink/renderer/modules/indexeddb/BUILD.gn
@@ -25,6 +25,15 @@
     "idb_factory.h",
     "idb_index.cc",
     "idb_index.h",
+    "idb_key.cc",
+    "idb_key.h",
+    "idb_key_path.cc",
+    "idb_key_path.h",
+    "idb_key_range.cc",
+    "idb_key_range.h",
+    "idb_metadata.cc",
+    "idb_metadata.h",
+    "idb_name_and_version.h",
     "idb_object_store.cc",
     "idb_object_store.h",
     "idb_observation.cc",
@@ -44,11 +53,15 @@
     "idb_tracing.h",
     "idb_transaction.cc",
     "idb_transaction.h",
+    "idb_value.cc",
+    "idb_value.h",
     "idb_value_wrapping.cc",
     "idb_value_wrapping.h",
     "idb_version_change_event.cc",
     "idb_version_change_event.h",
     "indexed_db.h",
+    "indexed_db_blink_mojom_traits.cc",
+    "indexed_db_blink_mojom_traits.h",
     "indexed_db_client.cc",
     "indexed_db_client.h",
     "indexed_db_database_callbacks_impl.cc",
@@ -78,34 +91,6 @@
   ]
 
   public_deps = [
-    ":mojo_wrapped_idb_types",
     "//third_party/blink/public/mojom:mojom_modules_blink",
   ]
 }
-
-# Some of the code is in its own build target to that it can be used
-# from the mojo type IDBKeyRange without creating a dependency cycle
-# between indexeddb and the mojo bindings.
-blink_modules_sources("mojo_wrapped_idb_types") {
-  visibility = []
-  visibility = [
-    "//third_party/blink/public/mojom:mojom_modules_blink",
-    "//third_party/blink/renderer/modules/*",
-  ]
-
-  sources = [
-    "idb_key.cc",
-    "idb_key.h",
-    "idb_key_path.cc",
-    "idb_key_path.h",
-    "idb_key_range.cc",
-    "idb_key_range.h",
-    "idb_metadata.cc",
-    "idb_metadata.h",
-    "idb_name_and_version.h",
-    "idb_value.cc",
-    "idb_value.h",
-    "indexed_db_blink_mojom_traits.cc",
-    "indexed_db_blink_mojom_traits.h",
-  ]
-}
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink.typemap b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink.typemap
index 7ad4e3a6..536050e 100644
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink.typemap
+++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink.typemap
@@ -19,7 +19,6 @@
 ]
 deps = [
   "//mojo/public/cpp/bindings",
-  "//third_party/blink/renderer/modules/indexeddb:mojo_wrapped_idb_types",
   "//third_party/blink/renderer/platform/wtf",
 ]
 type_mappings = [
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser.cc b/third_party/blink/renderer/modules/manifest/manifest_parser.cc
index 201a4b8..beff880e 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser.cc
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser.cc
@@ -224,20 +224,24 @@
   GURL scope = ParseURL(dictionary, "scope", manifest_url_,
                         ParseURLOriginRestrictions::kSameOriginOnly);
 
-  if (!scope.is_empty()) {
-    // According to the spec, if the start_url cannot be parsed, the document
-    // URL should be used as the start URL. If the start_url could not be
-    // parsed, check that the document URL is within scope.
-    GURL check_in_scope = start_url.is_empty() ? document_url_ : start_url;
-    if (check_in_scope.GetOrigin() != scope.GetOrigin() ||
-        !base::StartsWith(check_in_scope.path(), scope.path(),
-                          base::CompareCase::SENSITIVE)) {
-      AddErrorInfo(
-          "property 'scope' ignored. Start url should be within scope "
-          "of scope URL.");
-      return GURL();
-    }
+  // This will change to remove the |document_url_| fallback in the future.
+  // See https://github.com/w3c/manifest/issues/668.
+  const GURL& default_value = start_url.is_empty() ? document_url_ : start_url;
+  DCHECK(default_value.is_valid());
+
+  if (scope.is_empty())
+    return default_value.GetWithoutFilename();
+
+  if (default_value.GetOrigin() != scope.GetOrigin() ||
+      !base::StartsWith(default_value.path(), scope.path(),
+                        base::CompareCase::SENSITIVE)) {
+    AddErrorInfo(
+        "property 'scope' ignored. Start url should be within scope "
+        "of scope URL.");
+    return default_value.GetWithoutFilename();
   }
+
+  DCHECK(scope.is_valid());
   return scope;
 }
 
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser.h b/third_party/blink/renderer/modules/manifest/manifest_parser.h
index 7e058d6..633284e 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser.h
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser.h
@@ -101,8 +101,9 @@
       const base::DictionaryValue& dictionary);
 
   // Parses the 'scope' field of the manifest, as defined in:
-  // https://w3c.github.io/manifest/#dfn-steps-for-processing-the-scope-member
-  // Returns the parsed GURL if any, an empty GURL if the parsing failed.
+  // https://w3c.github.io/manifest/#scope-member. Returns the parsed GURL if
+  // any, or start URL (falling back to document URL) without filename, path,
+  // and query if there is no defined scope or if the parsing failed.
   GURL ParseScope(const base::DictionaryValue& dictionary,
                   const GURL& start_url);
 
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
index 98e3ead..ae5087e 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
@@ -102,8 +102,8 @@
   // Empty Manifest is not a parsing error.
   EXPECT_EQ(0u, GetErrorCount());
 
-  // Check that all the fields are null in that case.
-  ASSERT_TRUE(manifest.IsEmpty());
+  // Check that the fields are null or set to their default values.
+  ASSERT_FALSE(manifest.IsEmpty());
   ASSERT_TRUE(manifest.name.is_null());
   ASSERT_TRUE(manifest.short_name.is_null());
   ASSERT_TRUE(manifest.start_url.is_empty());
@@ -113,7 +113,7 @@
   ASSERT_FALSE(manifest.background_color.has_value());
   ASSERT_TRUE(manifest.splash_screen_url.is_empty());
   ASSERT_TRUE(manifest.gcm_sender_id.is_null());
-  ASSERT_TRUE(manifest.scope.is_empty());
+  ASSERT_EQ(default_document_url.GetWithoutFilename(), manifest.scope);
 }
 
 TEST_F(ManifestParserTest, MultipleErrorsReporting) {
@@ -307,18 +307,22 @@
     EXPECT_EQ(0u, GetErrorCount());
   }
 
-  // Don't parse if property isn't a string.
+  // Return the default value if the property isn't a string.
   {
     Manifest manifest = ParseManifest("{ \"scope\": {} }");
-    ASSERT_TRUE(manifest.scope.is_empty());
+    ASSERT_EQ(manifest.scope.spec(),
+              default_document_url.GetWithoutFilename().spec());
     EXPECT_EQ(1u, GetErrorCount());
     EXPECT_EQ("property 'scope' ignored, type string expected.", errors()[0]);
   }
 
-  // Don't parse if property isn't a string.
+  // Return the default value if property isn't a string.
   {
-    Manifest manifest = ParseManifest("{ \"scope\": 42 }");
-    ASSERT_TRUE(manifest.scope.is_empty());
+    Manifest manifest = ParseManifest(
+        "{ \"scope\": 42, "
+        "\"start_url\": \"http://foo.com/land/landing.html\" }");
+    ASSERT_EQ(manifest.scope.spec(),
+              default_document_url.Resolve("land/").spec());
     EXPECT_EQ(1u, GetErrorCount());
     EXPECT_EQ("property 'scope' ignored, type string expected.", errors()[0]);
   }
@@ -341,7 +345,8 @@
         "\"start_url\": \"http://foo.com/index.html\" }",
         GURL("http://foo.com/manifest.json"),
         GURL("http://foo.com/index.html"));
-    ASSERT_TRUE(manifest.scope.is_empty());
+    ASSERT_EQ(manifest.scope.spec(),
+              default_document_url.GetWithoutFilename().spec());
     EXPECT_EQ(1u, GetErrorCount());
     EXPECT_EQ(
         "property 'scope' ignored. Start url should be within scope "
@@ -356,7 +361,8 @@
         "\"start_url\": \"http://bar.com/land/landing.html\" }",
         GURL("http://foo.com/manifest.json"),
         GURL("http://foo.com/index.html"));
-    ASSERT_TRUE(manifest.scope.is_empty());
+    ASSERT_EQ(manifest.scope.spec(),
+              default_document_url.GetWithoutFilename().spec());
     ASSERT_EQ(2u, GetErrorCount());
     EXPECT_EQ(
         "property 'start_url' ignored, should be same origin as document.",
@@ -369,12 +375,12 @@
 
   // scope and start URL have diferent origin than document URL.
   {
+    GURL document_url("http://bar.com/index.html");
     Manifest manifest = ParseManifestWithURLs(
         "{ \"scope\": \"http://foo.com/land\", "
         "\"start_url\": \"http://foo.com/land/landing.html\" }",
-        GURL("http://foo.com/manifest.json"),
-        GURL("http://bar.com/index.html"));
-    ASSERT_TRUE(manifest.scope.is_empty());
+        GURL("http://foo.com/manifest.json"), document_url);
+    ASSERT_EQ(manifest.scope.spec(), document_url.GetWithoutFilename().spec());
     ASSERT_EQ(2u, GetErrorCount());
     EXPECT_EQ(
         "property 'start_url' ignored, should be same origin as document.",
@@ -395,10 +401,12 @@
 
   // No start URL. Document is out of scope.
   {
+    GURL document_url("http://foo.com/index.html");
     Manifest manifest =
         ParseManifestWithURLs("{ \"scope\": \"http://foo.com/land\" }",
                               GURL("http://foo.com/manifest.json"),
                               GURL("http://foo.com/index.html"));
+    ASSERT_EQ(manifest.scope.spec(), document_url.GetWithoutFilename().spec());
     ASSERT_EQ(1u, GetErrorCount());
     EXPECT_EQ(
         "property 'scope' ignored. Start url should be within scope "
@@ -432,9 +440,33 @@
     ASSERT_EQ(manifest.scope.spec(), "http://foo.com/");
     EXPECT_EQ(0u, GetErrorCount());
   }
+
+  // Scope defaults to start_url with the filename, query, and fragment removed.
+  {
+    blink::Manifest manifest =
+        ParseManifest("{ \"start_url\": \"land/landing.html\" }");
+    ASSERT_EQ(manifest.scope.spec(),
+              default_document_url.Resolve("land/").spec());
+    EXPECT_EQ(0u, GetErrorCount());
+  }
+
+  {
+    blink::Manifest manifest =
+        ParseManifest("{ \"start_url\": \"land/land/landing.html\" }");
+    ASSERT_EQ(manifest.scope.spec(),
+              default_document_url.Resolve("land/land/").spec());
+    EXPECT_EQ(0u, GetErrorCount());
+  }
+
+  // Scope defaults to document_url if start_url is not present.
+  {
+    blink::Manifest manifest = ParseManifest("{}");
+    ASSERT_EQ(manifest.scope.spec(), default_document_url.Resolve(".").spec());
+    EXPECT_EQ(0u, GetErrorCount());
+  }
 }
 
-TEST_F(ManifestParserTest, DisplayParserRules) {
+TEST_F(ManifestParserTest, DisplayParseRules) {
   // Smoke test.
   {
     Manifest manifest = ParseManifest("{ \"display\": \"browser\" }");
@@ -516,7 +548,7 @@
   }
 }
 
-TEST_F(ManifestParserTest, OrientationParserRules) {
+TEST_F(ManifestParserTest, OrientationParseRules) {
   // Smoke test.
   {
     Manifest manifest = ParseManifest("{ \"orientation\": \"natural\" }");
@@ -632,7 +664,6 @@
   {
     Manifest manifest = ParseManifest("{ \"icons\": [] }");
     EXPECT_EQ(manifest.icons.size(), 0u);
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(0u, GetErrorCount());
   }
 
@@ -640,7 +671,6 @@
   {
     Manifest manifest = ParseManifest("{ \"icons\": [ {} ] }");
     EXPECT_EQ(manifest.icons.size(), 0u);
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(0u, GetErrorCount());
   }
 
@@ -648,7 +678,6 @@
   {
     Manifest manifest = ParseManifest("{ \"icons\": [ { \"icons\": [] } ] }");
     EXPECT_EQ(manifest.icons.size(), 0u);
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(0u, GetErrorCount());
   }
 
@@ -1013,7 +1042,6 @@
   {
     Manifest manifest = ParseManifest("{ \"file_handler\": [] }");
     EXPECT_FALSE(manifest.file_handler.has_value());
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(1u, GetErrorCount());
     EXPECT_EQ("no file handlers were specified.", errors()[0]);
   }
@@ -1121,7 +1149,6 @@
   {
     Manifest manifest = ParseManifest("{ \"share_target\": {} }");
     EXPECT_FALSE(manifest.share_target.has_value());
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(1u, GetErrorCount());
     EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
               errors()[0]);
@@ -1132,7 +1159,6 @@
     Manifest manifest =
         ParseManifest("{ \"share_target\": { \"action\": \"\" } }");
     EXPECT_FALSE(manifest.share_target.has_value());
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(3u, GetErrorCount());
     EXPECT_EQ(
         "Method should be set to either GET or POST. It currently defaults to "
@@ -1154,7 +1180,6 @@
     Manifest manifest =
         ParseManifest("{ \"share_target\": { \"params\": {} } }");
     EXPECT_FALSE(manifest.share_target.has_value());
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(1u, GetErrorCount());
     EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
               errors()[0]);
@@ -1165,7 +1190,6 @@
     Manifest manifest = ParseManifest(
         "{ \"share_target\": {\"incorrect_key\": \"some_value\" } }");
     ASSERT_FALSE(manifest.share_target.has_value());
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(1u, GetErrorCount());
     EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
               errors()[0]);
@@ -1228,7 +1252,6 @@
         "{ \"share_target\": { \"action\": {}, \"params\": {} } }",
         manifest_url, document_url);
     EXPECT_FALSE(manifest.share_target.has_value());
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(2u, GetErrorCount());
     EXPECT_EQ("property 'action' ignored, type string expected.", errors()[0]);
     EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
@@ -1241,7 +1264,6 @@
         "{ \"share_target\": { \"action\": 42, \"params\": {} } }",
         manifest_url, document_url);
     EXPECT_FALSE(manifest.share_target.has_value());
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(2u, GetErrorCount());
     EXPECT_EQ("property 'action' ignored, type string expected.", errors()[0]);
     EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
@@ -1254,7 +1276,6 @@
         "{ \"share_target\": { \"action\": \"\", \"params\": \"\" } }",
         manifest_url, document_url);
     EXPECT_FALSE(manifest.share_target.has_value());
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(3u, GetErrorCount());
     EXPECT_EQ(
         "Method should be set to either GET or POST. It currently defaults to "
@@ -1277,7 +1298,6 @@
         "{ \"share_target\": { \"action\": \"\", \"params\": 42 } }",
         manifest_url, document_url);
     EXPECT_FALSE(manifest.share_target.has_value());
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(3u, GetErrorCount());
     EXPECT_EQ(
         "Method should be set to either GET or POST. It currently defaults to "
@@ -1377,7 +1397,6 @@
         "{} } }",
         manifest_url, document_url);
     EXPECT_FALSE(manifest.share_target.has_value());
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(2u, GetErrorCount());
     EXPECT_EQ("property 'action' ignored, URL is invalid.", errors()[0]);
     EXPECT_EQ("property 'share_target' ignored. Property 'action' is invalid.",
@@ -1392,7 +1411,6 @@
         "\"params\": {} }",
         manifest_url, document_url);
     EXPECT_FALSE(manifest.share_target.has_value());
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(2u, GetErrorCount());
     EXPECT_EQ("property 'action' ignored, should be same origin as document.",
               errors()[0]);
@@ -2041,7 +2059,6 @@
   {
     Manifest manifest = ParseManifest("{ \"related_applications\": []}");
     EXPECT_EQ(manifest.related_applications.size(), 0u);
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(0u, GetErrorCount());
   }
 
@@ -2049,7 +2066,6 @@
   {
     Manifest manifest = ParseManifest("{ \"related_applications\": [{}]}");
     EXPECT_EQ(manifest.related_applications.size(), 0u);
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(1u, GetErrorCount());
     EXPECT_EQ("'platform' is a required field, related application ignored.",
               errors()[0]);
@@ -2060,7 +2076,6 @@
     Manifest manifest =
         ParseManifest("{ \"related_applications\": [{\"platform\": 123}]}");
     EXPECT_EQ(manifest.related_applications.size(), 0u);
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(2u, GetErrorCount());
     EXPECT_EQ("property 'platform' ignored, type string expected.",
               errors()[0]);
@@ -2075,7 +2090,6 @@
     Manifest manifest =
         ParseManifest("{ \"related_applications\": [{\"id\": \"foo\"}]}");
     EXPECT_EQ(manifest.related_applications.size(), 0u);
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(1u, GetErrorCount());
     EXPECT_EQ("'platform' is a required field, related application ignored.",
               errors()[0]);
@@ -2086,7 +2100,6 @@
     Manifest manifest = ParseManifest(
         "{ \"related_applications\": [{\"platform\": \"play\"}]}");
     EXPECT_EQ(manifest.related_applications.size(), 0u);
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(1u, GetErrorCount());
     EXPECT_EQ("one of 'url' or 'id' is required, related application ignored.",
               errors()[0]);
@@ -2111,7 +2124,6 @@
     Manifest manifest = ParseManifest(
         "{ \"related_applications\": ["
         "{\"platform\": \"play\", \"url\": \"http://www.foo.com:co&uk\"}]}");
-    EXPECT_TRUE(manifest.IsEmpty());
     EXPECT_EQ(2u, GetErrorCount());
     EXPECT_EQ("property 'url' ignored, URL is invalid.", errors()[0]);
     EXPECT_EQ("one of 'url' or 'id' is required, related application ignored.",
diff --git a/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css b/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
index 66aaa52..037d6673 100644
--- a/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
+++ b/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
@@ -986,7 +986,7 @@
 audio::-internal-media-controls-text-track-list-item,
 video::-internal-media-controls-text-track-list-item {
   padding-left: 58px;
-  display: block;
+  justify-content: space-between;
 }
 
 audio::-internal-media-controls-text-track-list-header,
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_sink.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_sink.cc
index edf3070..71a6f20 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_sink.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_sink.cc
@@ -34,7 +34,10 @@
     media::VideoCaptureFrameDropReason reason) {
   if (connected_track_.IsNull())
     return;
-  OnFrameDroppedAtMediaStreamSink(connected_track_, reason);
+
+  if (auto* const video_track =
+          MediaStreamVideoTrack::GetVideoTrack(connected_track_))
+    video_track->OnFrameDropped(reason);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/web_media_stream_utils.cc b/third_party/blink/renderer/modules/mediastream/web_media_stream_utils.cc
index 8a8a402..6dd3958 100644
--- a/third_party/blink/renderer/modules/mediastream/web_media_stream_utils.cc
+++ b/third_party/blink/renderer/modules/mediastream/web_media_stream_utils.cc
@@ -44,13 +44,4 @@
     video_track->RemoveSink(sink);
 }
 
-void OnFrameDroppedAtMediaStreamSink(
-    const WebMediaStreamTrack& track,
-    media::VideoCaptureFrameDropReason reason) {
-  MediaStreamVideoTrack* const video_track =
-      MediaStreamVideoTrack::GetVideoTrack(track);
-  if (video_track)
-    video_track->OnFrameDropped(reason);
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc
index 340e8ded..015b22f 100644
--- a/third_party/blink/renderer/modules/modules_initializer.cc
+++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -235,7 +235,8 @@
       inspected_frames, dom_agent));
   if (allow_view_agents) {
     session->Append(InspectorDatabaseAgent::Create(page));
-    session->Append(InspectorCacheStorageAgent::Create(inspected_frames));
+    session->Append(
+        MakeGarbageCollected<InspectorCacheStorageAgent>(inspected_frames));
   }
 }
 
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc
index 08ca5bc..3895841 100644
--- a/third_party/blink/renderer/modules/payments/payment_request.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -1218,7 +1218,7 @@
 
   PaymentRequestUpdateEvent* event = PaymentMethodChangeEvent::Create(
       script_state, event_type_names::kPaymentmethodchange, init);
-  DispatchPaymentRequestUpdateEvent(event);
+  DispatchPaymentRequestUpdateEvent(this, event);
 }
 
 void PaymentRequest::OnShippingAddressChange(PaymentAddressPtr address) {
@@ -1237,7 +1237,7 @@
 
   PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create(
       GetExecutionContext(), event_type_names::kShippingaddresschange);
-  DispatchPaymentRequestUpdateEvent(event);
+  DispatchPaymentRequestUpdateEvent(this, event);
 }
 
 void PaymentRequest::OnShippingOptionChange(const String& shipping_option_id) {
@@ -1247,7 +1247,7 @@
 
   PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create(
       GetExecutionContext(), event_type_names::kShippingoptionchange);
-  DispatchPaymentRequestUpdateEvent(event);
+  DispatchPaymentRequestUpdateEvent(this, event);
 }
 
 void PaymentRequest::OnPayerDetailChange(
@@ -1257,19 +1257,10 @@
   DCHECK(GetPendingAcceptPromiseResolver());
   DCHECK(!complete_resolver_);
 
+  payment_response_->UpdatePayerDetail(std::move(detail));
   PaymentRequestUpdateEvent* event = PaymentRequestUpdateEvent::Create(
       GetExecutionContext(), event_type_names::kPayerdetailchange);
-  event->SetTarget(payment_response_);
-  event->SetPaymentRequest(this);
-  payment_response_->UpdatePayerDetail(std::move(detail));
-  payment_response_->DispatchEvent(*event);
-  if (!event->is_waiting_for_update()) {
-    // DispatchEvent runs synchronously. The method is_waiting_for_update()
-    // returns true if the merchant called event.updateWith() within the event
-    // handler. Calling this method is optional. If the method is not called,
-    // the renderer sends a message to the browser to re-enable UI interactions.
-    payment_provider_->NoUpdatedPaymentDetails();
-  }
+  DispatchPaymentRequestUpdateEvent(payment_response_, event);
 }
 
 void PaymentRequest::OnPaymentResponse(PaymentResponsePtr response) {
@@ -1542,10 +1533,11 @@
 }
 
 void PaymentRequest::DispatchPaymentRequestUpdateEvent(
+    EventTarget* event_target,
     PaymentRequestUpdateEvent* event) {
-  event->SetTarget(this);
+  event->SetTarget(event_target);
   event->SetPaymentRequest(this);
-  DispatchEvent(*event);
+  event_target->DispatchEvent(*event);
   if (!event->is_waiting_for_update()) {
     // DispatchEvent runs synchronously. The method is_waiting_for_update()
     // returns true if the merchant called event.updateWith() within the event
diff --git a/third_party/blink/renderer/modules/payments/payment_request.h b/third_party/blink/renderer/modules/payments/payment_request.h
index d95f924..b7f7cc2 100644
--- a/third_party/blink/renderer/modules/payments/payment_request.h
+++ b/third_party/blink/renderer/modules/payments/payment_request.h
@@ -144,7 +144,8 @@
 
   // Implements the PaymentRequest updated algorithm.
   // https://w3c.github.io/payment-request/#paymentrequest-updated-algorithm
-  void DispatchPaymentRequestUpdateEvent(PaymentRequestUpdateEvent* event);
+  void DispatchPaymentRequestUpdateEvent(EventTarget* event_target,
+                                         PaymentRequestUpdateEvent* event);
 
   Member<const PaymentOptions> options_;
   Member<PaymentAddress> shipping_address_;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
index 40543ae..6ef0fb2 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -277,30 +277,6 @@
              : OfferExtmapAllowMixedSetting::kDisabled;
 }
 
-// Helper class for RTCPeerConnection::generateCertificate.
-class WebRTCCertificateObserver : public WebRTCCertificateCallback {
- public:
-  // Takes ownership of |resolver|.
-  static WebRTCCertificateObserver* Create(ScriptPromiseResolver* resolver) {
-    return new WebRTCCertificateObserver(resolver);
-  }
-
-  ~WebRTCCertificateObserver() override = default;
-
- private:
-  explicit WebRTCCertificateObserver(ScriptPromiseResolver* resolver)
-      : resolver_(resolver) {}
-
-  void OnSuccess(rtc::scoped_refptr<rtc::RTCCertificate> certificate) override {
-    resolver_->Resolve(
-        MakeGarbageCollected<RTCCertificate>(std::move(certificate)));
-  }
-
-  void OnError() override { resolver_->Reject(); }
-
-  Persistent<ScriptPromiseResolver> resolver_;
-};
-
 webrtc::PeerConnectionInterface::IceTransportsType IceTransportPolicyFromString(
     const String& policy) {
   if (policy == "relay")
@@ -1168,6 +1144,18 @@
   }
 }
 
+void RTCPeerConnection::GenerateCertificateCompleted(
+    ScriptPromiseResolver* resolver,
+    rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
+  if (!certificate) {
+    resolver->Reject();
+    return;
+  }
+
+  resolver->Resolve(
+      MakeGarbageCollected<RTCCertificate>(std::move(certificate)));
+}
+
 bool RTCPeerConnection::HasDocumentMedia() const {
   UserMediaController* user_media_controller = UserMediaController::From(
       To<Document>(GetExecutionContext())->GetFrame());
@@ -1649,8 +1637,10 @@
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise promise = resolver->Promise();
 
-  std::unique_ptr<WebRTCCertificateObserver> certificate_observer(
-      WebRTCCertificateObserver::Create(resolver));
+  // Helper closure callback for RTCPeerConnection::generateCertificate.
+  auto completion_callback =
+      WTF::Bind(RTCPeerConnection::GenerateCertificateCompleted,
+                WrapPersistent(resolver));
 
   // Generate certificate. The |certificateObserver| will resolve the promise
   // asynchronously upon completion. The observer will manage its own
@@ -1660,10 +1650,10 @@
           ->GetTaskRunner(blink::TaskType::kInternalMedia);
   if (!expires) {
     certificate_generator->GenerateCertificate(
-        key_params.value(), std::move(certificate_observer), task_runner);
+        key_params.value(), std::move(completion_callback), task_runner);
   } else {
     certificate_generator->GenerateCertificateWithExpiration(
-        key_params.value(), expires.value(), std::move(certificate_observer),
+        key_params.value(), expires.value(), std::move(completion_callback),
         task_runner);
   }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
index 0a49d21c..74d7161 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
@@ -40,6 +40,7 @@
 #include "third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
 #include "third_party/blink/renderer/modules/crypto/normalize_algorithm.h"
 #include "third_party/blink/renderer/modules/event_target_modules.h"
@@ -331,6 +332,9 @@
       bool success);
   void NoteVoidRequestCompleted(RTCSetSessionDescriptionOperation operation,
                                 bool success);
+  static void GenerateCertificateCompleted(
+      ScriptPromiseResolver* resolver,
+      rtc::scoped_refptr<rtc::RTCCertificate> certificate);
   // Checks if the document that the peer connection lives in has ever executed
   // getUserMedia().
   bool HasDocumentMedia() const;
diff --git a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc
index 81f878903..629874a27 100644
--- a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc
+++ b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc
@@ -169,7 +169,8 @@
   PictureInPictureControllerImpl::From(GetDocument())
       .EnterPictureInPicture(Video(), nullptr);
 
-  WaitForEvent::Create(Video(), event_type_names::kEnterpictureinpicture);
+  MakeGarbageCollected<WaitForEvent>(Video(),
+                                     event_type_names::kEnterpictureinpicture);
 
   EXPECT_NE(nullptr, PictureInPictureControllerImpl::From(GetDocument())
                          .PictureInPictureElement());
@@ -191,11 +192,13 @@
 
   PictureInPictureControllerImpl::From(GetDocument())
       .EnterPictureInPicture(Video(), nullptr);
-  WaitForEvent::Create(Video(), event_type_names::kEnterpictureinpicture);
+  MakeGarbageCollected<WaitForEvent>(Video(),
+                                     event_type_names::kEnterpictureinpicture);
 
   PictureInPictureControllerImpl::From(GetDocument())
       .ExitPictureInPicture(Video(), nullptr);
-  WaitForEvent::Create(Video(), event_type_names::kLeavepictureinpicture);
+  MakeGarbageCollected<WaitForEvent>(Video(),
+                                     event_type_names::kLeavepictureinpicture);
 
   EXPECT_EQ(nullptr, PictureInPictureControllerImpl::From(GetDocument())
                          .PictureInPictureElement());
@@ -215,7 +218,8 @@
   PictureInPictureControllerImpl::From(GetDocument())
       .EnterPictureInPicture(Video(), nullptr);
 
-  WaitForEvent::Create(Video(), event_type_names::kEnterpictureinpicture);
+  MakeGarbageCollected<WaitForEvent>(Video(),
+                                     event_type_names::kEnterpictureinpicture);
 
   EXPECT_TRUE(PictureInPictureControllerImpl::From(GetDocument())
                   .GetDelegateBindingForTesting()
@@ -239,11 +243,13 @@
 
   PictureInPictureControllerImpl::From(GetDocument())
       .EnterPictureInPicture(Video(), nullptr);
-  WaitForEvent::Create(Video(), event_type_names::kEnterpictureinpicture);
+  MakeGarbageCollected<WaitForEvent>(Video(),
+                                     event_type_names::kEnterpictureinpicture);
 
   PictureInPictureControllerImpl::From(GetDocument())
       .ExitPictureInPicture(Video(), nullptr);
-  WaitForEvent::Create(Video(), event_type_names::kLeavepictureinpicture);
+  MakeGarbageCollected<WaitForEvent>(Video(),
+                                     event_type_names::kLeavepictureinpicture);
 
   EXPECT_FALSE(PictureInPictureControllerImpl::From(GetDocument())
                    .GetDelegateBindingForTesting()
@@ -265,7 +271,8 @@
   PictureInPictureControllerImpl::From(GetDocument())
       .EnterPictureInPicture(Video(), nullptr);
 
-  WaitForEvent::Create(Video(), event_type_names::kEnterpictureinpicture);
+  MakeGarbageCollected<WaitForEvent>(Video(),
+                                     event_type_names::kEnterpictureinpicture);
 
   // `SetDelegate()` may or may not have been called yet. Waiting a bit for it.
   test::RunPendingTasks();
@@ -287,7 +294,8 @@
   PictureInPictureControllerImpl::From(GetDocument())
       .EnterPictureInPicture(Video(), nullptr);
 
-  WaitForEvent::Create(Video(), event_type_names::kEnterpictureinpicture);
+  MakeGarbageCollected<WaitForEvent>(Video(),
+                                     event_type_names::kEnterpictureinpicture);
 
   // `SetDelegate()` may or may not have been called yet. Waiting a bit for it.
   test::RunPendingTasks();
diff --git a/third_party/blink/renderer/modules/serial/DEPS b/third_party/blink/renderer/modules/serial/DEPS
index ee7d4d0..755fee5 100644
--- a/third_party/blink/renderer/modules/serial/DEPS
+++ b/third_party/blink/renderer/modules/serial/DEPS
@@ -1,4 +1,3 @@
 include_rules = [
-  "+base/unguessable_token.h",
-  "+services/device/public/mojom",
+  "+base/unguessable_token.h"
 ]
diff --git a/third_party/blink/renderer/modules/serial/serial.cc b/third_party/blink/renderer/modules/serial/serial.cc
index 04c1e5a8..25f99f1 100644
--- a/third_party/blink/renderer/modules/serial/serial.cc
+++ b/third_party/blink/renderer/modules/serial/serial.cc
@@ -50,11 +50,6 @@
   return event_target_names::kSerial;
 }
 
-void Serial::ContextDestroyed(ExecutionContext*) {
-  for (auto& entry : port_cache_)
-    entry.value->ContextDestroyed();
-}
-
 ScriptPromise Serial::getPorts(ScriptState* script_state) {
   auto* context = GetExecutionContext();
   if (!context) {
@@ -117,12 +112,6 @@
   return resolver->Promise();
 }
 
-void Serial::GetPort(const base::UnguessableToken& token,
-                     device::mojom::blink::SerialPortRequest request) {
-  EnsureServiceConnection();
-  service_->GetPort(token, std::move(request));
-}
-
 void Serial::Trace(Visitor* visitor) {
   visitor->Trace(get_ports_promises_);
   visitor->Trace(request_port_promises_);
@@ -166,8 +155,8 @@
 SerialPort* Serial::GetOrCreatePort(mojom::blink::SerialPortInfoPtr info) {
   SerialPort* port = port_cache_.at(TokenToString(info->token));
   if (!port) {
-    port = MakeGarbageCollected<SerialPort>(this, std::move(info));
-    port_cache_.insert(TokenToString(port->token()), port);
+    port = MakeGarbageCollected<SerialPort>(std::move(info));
+    port_cache_.insert(TokenToString(port->Token()), port);
   }
   return port;
 }
diff --git a/third_party/blink/renderer/modules/serial/serial.h b/third_party/blink/renderer/modules/serial/serial.h
index 886a52e..195ec073 100644
--- a/third_party/blink/renderer/modules/serial/serial.h
+++ b/third_party/blink/renderer/modules/serial/serial.h
@@ -36,17 +36,11 @@
   ExecutionContext* GetExecutionContext() const override;
   const AtomicString& InterfaceName() const override;
 
-  // ContextLifecycleObserver
-  void ContextDestroyed(ExecutionContext*) override;
-
-  // Web-exposed interfaces
   DEFINE_ATTRIBUTE_EVENT_LISTENER(connect, kConnect)
   DEFINE_ATTRIBUTE_EVENT_LISTENER(disconnect, kDisconnect)
   ScriptPromise getPorts(ScriptState*);
   ScriptPromise requestPort(ScriptState*, const SerialPortRequestOptions*);
 
-  void GetPort(const base::UnguessableToken& token,
-               device::mojom::blink::SerialPortRequest request);
   void Trace(Visitor*) override;
 
  private:
diff --git a/third_party/blink/renderer/modules/serial/serial_port.cc b/third_party/blink/renderer/modules/serial/serial_port.cc
index bf98e94..e46dccb 100644
--- a/third_party/blink/renderer/modules/serial/serial_port.cc
+++ b/third_party/blink/renderer/modules/serial/serial_port.cc
@@ -3,43 +3,36 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/modules/serial/serial_port.h"
-
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/streams/readable_stream.h"
-#include "third_party/blink/renderer/core/streams/writable_stream.h"
-#include "third_party/blink/renderer/modules/serial/serial.h"
 
 namespace blink {
 
-SerialPort::SerialPort(Serial* parent, mojom::blink::SerialPortInfoPtr info)
-    : info_(std::move(info)), parent_(parent) {}
+SerialPort::SerialPort(mojom::blink::SerialPortInfoPtr info)
+    : info_(std::move(info)) {}
 
 SerialPort::~SerialPort() = default;
 
+ReadableStream* SerialPort::in() {
+  return nullptr;
+}
+
+WritableStream* SerialPort::out() {
+  return nullptr;
+}
+
 ScriptPromise SerialPort::open(ScriptState* script_state,
                                const SerialOptions* options) {
-  if (port_)
-    return ScriptPromise::CastUndefined(script_state);
-
-  parent_->GetPort(info_->token, mojo::MakeRequest(&port_));
-  // TODO(https://crbug.com/884928): Call port_->Open() and initialize the
-  // ReadableStream and WritableStream.
-  return ScriptPromise::CastUndefined(script_state);
+  return ScriptPromise::RejectWithDOMException(
+      script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError));
 }
 
 ScriptPromise SerialPort::close(ScriptState* script_state) {
-  ContextDestroyed();
-  return ScriptPromise::CastUndefined(script_state);
+  return ScriptPromise::RejectWithDOMException(
+      script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError));
 }
 
-void SerialPort::ContextDestroyed() {
-  // Release connection-related resources as quickly as possible.
-  port_.reset();
-}
-
-void SerialPort::Trace(Visitor* visitor) {
-  visitor->Trace(parent_);
-  ScriptWrappable::Trace(visitor);
+const base::UnguessableToken& SerialPort::Token() const {
+  return info_->token;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/serial/serial_port.h b/third_party/blink/renderer/modules/serial/serial_port.h
index 3073b99..631f1d159 100644
--- a/third_party/blink/renderer/modules/serial/serial_port.h
+++ b/third_party/blink/renderer/modules/serial/serial_port.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERIAL_SERIAL_PORT_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_SERIAL_SERIAL_PORT_H_
 
-#include "services/device/public/mojom/serial.mojom-blink.h"
 #include "third_party/blink/public/mojom/serial/serial.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -19,7 +18,6 @@
 
 class ReadableStream;
 class ScriptState;
-class Serial;
 class SerialOptions;
 class WritableStream;
 
@@ -27,26 +25,19 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  explicit SerialPort(Serial* parent, mojom::blink::SerialPortInfoPtr info);
+  explicit SerialPort(mojom::blink::SerialPortInfoPtr info);
   ~SerialPort() override;
 
-  // Web-exposed functions
-  ReadableStream* in() const { return nullptr; }
-  WritableStream* out() const { return nullptr; }
+  ReadableStream* in();
+  WritableStream* out();
 
   ScriptPromise open(ScriptState*, const SerialOptions* options);
   ScriptPromise close(ScriptState*);
 
-  const base::UnguessableToken& token() const { return info_->token; }
-
-  void ContextDestroyed();
-  void Trace(Visitor*) override;
+  const base::UnguessableToken& Token() const;
 
  private:
   mojom::blink::SerialPortInfoPtr info_;
-  device::mojom::blink::SerialPortPtr port_;
-
-  Member<Serial> parent_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis.cc b/third_party/blink/renderer/modules/speech/speech_synthesis.cc
index b9ab1f6..a236d8e 100644
--- a/third_party/blink/renderer/modules/speech/speech_synthesis.cc
+++ b/third_party/blink/renderer/modules/speech/speech_synthesis.cc
@@ -153,6 +153,7 @@
 void SpeechSynthesis::FireEvent(const AtomicString& type,
                                 SpeechSynthesisUtterance* utterance,
                                 uint32_t char_index,
+                                uint32_t char_length,
                                 const String& name) {
   double millis;
   if (!GetElapsedTimeMillis(&millis))
@@ -161,6 +162,7 @@
   SpeechSynthesisEventInit* init = SpeechSynthesisEventInit::Create();
   init->setUtterance(utterance);
   init->setCharIndex(char_index);
+  init->setCharLength(char_length);
   init->setElapsedTime(millis - (utterance->StartTime() * 1000.0));
   init->setName(name);
   utterance->DispatchEvent(*SpeechSynthesisEvent::Create(type, init));
@@ -204,7 +206,7 @@
     // generic error.
     FireErrorEvent(utterance, 0, "synthesis-failed");
   } else {
-    FireEvent(event_type_names::kEnd, utterance, 0, String());
+    FireEvent(event_type_names::kEnd, utterance, 0, 0, String());
   }
 
   // Start the next utterance if we just finished one and one was pending.
@@ -215,7 +217,8 @@
 void SpeechSynthesis::BoundaryEventOccurred(
     PlatformSpeechSynthesisUtterance* utterance,
     SpeechBoundary boundary,
-    unsigned char_index) {
+    unsigned char_index,
+    unsigned char_length) {
   DEFINE_STATIC_LOCAL(const String, word_boundary_string, ("word"));
   DEFINE_STATIC_LOCAL(const String, sentence_boundary_string, ("sentence"));
 
@@ -223,12 +226,12 @@
     case kSpeechWordBoundary:
       FireEvent(event_type_names::kBoundary,
                 static_cast<SpeechSynthesisUtterance*>(utterance->Client()),
-                char_index, word_boundary_string);
+                char_index, char_length, word_boundary_string);
       break;
     case kSpeechSentenceBoundary:
       FireEvent(event_type_names::kBoundary,
                 static_cast<SpeechSynthesisUtterance*>(utterance->Client()),
-                char_index, sentence_boundary_string);
+                char_index, char_length, sentence_boundary_string);
       break;
     default:
       NOTREACHED();
@@ -239,7 +242,7 @@
     PlatformSpeechSynthesisUtterance* utterance) {
   if (utterance->Client())
     FireEvent(event_type_names::kStart,
-              static_cast<SpeechSynthesisUtterance*>(utterance->Client()), 0,
+              static_cast<SpeechSynthesisUtterance*>(utterance->Client()), 0, 0,
               String());
 }
 
@@ -248,7 +251,7 @@
   is_paused_ = true;
   if (utterance->Client())
     FireEvent(event_type_names::kPause,
-              static_cast<SpeechSynthesisUtterance*>(utterance->Client()), 0,
+              static_cast<SpeechSynthesisUtterance*>(utterance->Client()), 0, 0,
               String());
 }
 
@@ -257,7 +260,7 @@
   is_paused_ = false;
   if (utterance->Client())
     FireEvent(event_type_names::kResume,
-              static_cast<SpeechSynthesisUtterance*>(utterance->Client()), 0,
+              static_cast<SpeechSynthesisUtterance*>(utterance->Client()), 0, 0,
               String());
 }
 
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis.h b/third_party/blink/renderer/modules/speech/speech_synthesis.h
index d351d3a..afcbce1 100644
--- a/third_party/blink/renderer/modules/speech/speech_synthesis.h
+++ b/third_party/blink/renderer/modules/speech/speech_synthesis.h
@@ -83,13 +83,15 @@
   void SpeakingErrorOccurred(PlatformSpeechSynthesisUtterance*) override;
   void BoundaryEventOccurred(PlatformSpeechSynthesisUtterance*,
                              SpeechBoundary,
-                             unsigned char_index) override;
+                             unsigned char_index,
+                             unsigned char_length) override;
 
   void StartSpeakingImmediately();
   void HandleSpeakingCompleted(SpeechSynthesisUtterance*, bool error_occurred);
   void FireEvent(const AtomicString& type,
                  SpeechSynthesisUtterance*,
                  uint32_t char_index,
+                 uint32_t char_length,
                  const String& name);
 
   void FireErrorEvent(SpeechSynthesisUtterance*,
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.cc b/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.cc
index db8ff331..63a47b9 100644
--- a/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.cc
+++ b/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.cc
@@ -19,6 +19,7 @@
     : SpeechSynthesisEvent(type,
                            init->utterance(),
                            init->charIndex(),
+                           init->charLength(),
                            init->elapsedTime(),
                            init->name()),
       error_(init->error()) {}
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_event.cc b/third_party/blink/renderer/modules/speech/speech_synthesis_event.cc
index 9148c91..540ffbfb 100644
--- a/third_party/blink/renderer/modules/speech/speech_synthesis_event.cc
+++ b/third_party/blink/renderer/modules/speech/speech_synthesis_event.cc
@@ -31,18 +31,20 @@
     const AtomicString& type,
     const SpeechSynthesisEventInit* init) {
   return MakeGarbageCollected<SpeechSynthesisEvent>(
-      type, init->utterance(), init->charIndex(), init->elapsedTime(),
-      init->name());
+      type, init->utterance(), init->charIndex(), init->charLength(),
+      init->elapsedTime(), init->name());
 }
 
 SpeechSynthesisEvent::SpeechSynthesisEvent(const AtomicString& type,
                                            SpeechSynthesisUtterance* utterance,
                                            unsigned char_index,
+                                           unsigned char_length,
                                            float elapsed_time,
                                            const String& name)
     : Event(type, Bubbles::kNo, Cancelable::kNo),
       utterance_(utterance),
       char_index_(char_index),
+      char_length_(char_length),
       elapsed_time_(elapsed_time),
       name_(name) {}
 
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_event.h b/third_party/blink/renderer/modules/speech/speech_synthesis_event.h
index 31cae84..77ce3b8 100644
--- a/third_party/blink/renderer/modules/speech/speech_synthesis_event.h
+++ b/third_party/blink/renderer/modules/speech/speech_synthesis_event.h
@@ -42,11 +42,13 @@
   SpeechSynthesisEvent(const AtomicString& type,
                        SpeechSynthesisUtterance*,
                        unsigned char_index,
+                       unsigned char_length,
                        float elapsed_time,
                        const String& name);
 
   SpeechSynthesisUtterance* utterance() const { return utterance_; }
   unsigned charIndex() const { return char_index_; }
+  unsigned charLength() const { return char_length_; }
   float elapsedTime() const { return elapsed_time_; }
   const String& name() const { return name_; }
 
@@ -59,6 +61,7 @@
  private:
   Member<SpeechSynthesisUtterance> utterance_;
   unsigned char_index_;
+  unsigned char_length_;
   float elapsed_time_;
   String name_;
 };
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_event.idl b/third_party/blink/renderer/modules/speech/speech_synthesis_event.idl
index b64b848..493fc0a 100644
--- a/third_party/blink/renderer/modules/speech/speech_synthesis_event.idl
+++ b/third_party/blink/renderer/modules/speech/speech_synthesis_event.idl
@@ -30,6 +30,7 @@
 ] interface SpeechSynthesisEvent : Event {
     readonly attribute SpeechSynthesisUtterance utterance;
     readonly attribute unsigned long charIndex;
+    [RuntimeEnabled=SpeechSynthesisEventCharLength] readonly attribute unsigned long charLength;
     readonly attribute float elapsedTime;
     readonly attribute DOMString name;
 };
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_event_init.idl b/third_party/blink/renderer/modules/speech/speech_synthesis_event_init.idl
index 0c1386f..2066fc7 100644
--- a/third_party/blink/renderer/modules/speech/speech_synthesis_event_init.idl
+++ b/third_party/blink/renderer/modules/speech/speech_synthesis_event_init.idl
@@ -6,6 +6,7 @@
 dictionary SpeechSynthesisEventInit : EventInit {
     required SpeechSynthesisUtterance utterance;
     unsigned long charIndex = 0;
+    [RuntimeEnabled=SpeechSynthesisEventCharLength] unsigned long charLength = 0;
     float elapsedTime = 0;
     DOMString name = "";
 };
diff --git a/third_party/blink/renderer/modules/speech/testing/platform_speech_synthesizer_mock.cc b/third_party/blink/renderer/modules/speech/testing/platform_speech_synthesizer_mock.cc
index 5d9830ec..15a3ff0 100644
--- a/third_party/blink/renderer/modules/speech/testing/platform_speech_synthesizer_mock.cc
+++ b/third_party/blink/renderer/modules/speech/testing/platform_speech_synthesizer_mock.cc
@@ -110,9 +110,13 @@
   Client()->DidStartSpeaking(current_utterance_);
 
   // Fire a fake word and then sentence boundary event.
-  Client()->BoundaryEventOccurred(current_utterance_, kSpeechWordBoundary, 0);
+  String utterance_text = current_utterance_->GetText();
+  int char_length = utterance_text.find(' ');
+  int sentence_length = current_utterance_->GetText().length();
+  Client()->BoundaryEventOccurred(current_utterance_, kSpeechWordBoundary, 0,
+                                  char_length);
   Client()->BoundaryEventOccurred(current_utterance_, kSpeechSentenceBoundary,
-                                  current_utterance_->GetText().length());
+                                  0, sentence_length);
 
   // Give the fake speech job some time so that pause and other functions have
   // time to be called.
diff --git a/third_party/blink/renderer/modules/vr/navigator_vr.cc b/third_party/blink/renderer/modules/vr/navigator_vr.cc
index 1fcb431..c96fae37 100644
--- a/third_party/blink/renderer/modules/vr/navigator_vr.cc
+++ b/third_party/blink/renderer/modules/vr/navigator_vr.cc
@@ -104,7 +104,7 @@
       return nullptr;
     }
 
-    xr_ = XR::Create(*frame, ukm_source_id_);
+    xr_ = XR::Create(*frame, GetSourceId());
   }
   return xr_;
 }
@@ -131,7 +131,7 @@
   if (!did_log_getVRDisplays_ && GetDocument()->IsInMainFrame()) {
     did_log_getVRDisplays_ = true;
 
-    ukm::builders::XR_WebXR(GetDocument()->UkmSourceID())
+    ukm::builders::XR_WebXR(GetSourceId())
         .SetDidRequestAvailableDevices(1)
         .Record(GetDocument()->UkmRecorder());
   }
@@ -201,18 +201,9 @@
 NavigatorVR::NavigatorVR(Navigator& navigator)
     : Supplement<Navigator>(navigator),
       FocusChangedObserver(navigator.GetFrame()->GetPage()),
-      ukm_source_id_(ukm::UkmRecorder::GetNewSourceID()) {
+      ukm_source_id_(GetDocument()->UkmSourceID()) {
   navigator.GetFrame()->DomWindow()->RegisterEventListenerObserver(this);
   FocusedFrameChanged();
-
-  if (navigator.GetFrame() && WebFrame::FromFrame(navigator.GetFrame())) {
-    WebFrame* main_frame = WebFrame::FromFrame(navigator.GetFrame())->Top();
-    if (main_frame) {
-      url::Origin main_frame_origin = main_frame->GetSecurityOrigin();
-      GetDocument()->UkmRecorder()->UpdateSourceURL(ukm_source_id_,
-                                                    main_frame_origin.GetURL());
-    }
-  }
 }
 
 int64_t NavigatorVR::GetSourceId() const {
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
index 2243c353..b8854d1 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
@@ -36,7 +36,6 @@
 #include "third_party/blink/renderer/platform/audio/vector_math.h"
 #include "third_party/blink/renderer/platform/bindings/exception_messages.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/wtf/cpu.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
 
 #if defined(ARCH_CPU_X86_FAMILY)
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet.cc
index 7403a9d7..004b6dc 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_worklet.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_worklet.cc
@@ -82,7 +82,8 @@
   AudioWorkletMessagingProxy* proxy =
       MakeGarbageCollected<AudioWorkletMessagingProxy>(GetExecutionContext(),
                                                        this);
-  proxy->Initialize(WorkerClients::Create(), ModuleResponsesMap());
+  proxy->Initialize(MakeGarbageCollected<WorkerClients>(),
+                    ModuleResponsesMap());
   return proxy;
 }
 
diff --git a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.cc b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.cc
index 58d7cc7..a26178a4 100644
--- a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.cc
+++ b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.cc
@@ -90,8 +90,8 @@
     case WorkletType::ANIMATION_WORKLET: {
       TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("animation-worklet"),
                    "AnimationAndPaintWorkletThread::CreateWorkerGlobalScope");
-      return AnimationWorkletGlobalScope::Create(std::move(creation_params),
-                                                 this);
+      return MakeGarbageCollected<AnimationWorkletGlobalScope>(
+          std::move(creation_params), this);
     }
     case WorkletType::PAINT_WORKLET:
       TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("paint-worklet"),
diff --git a/third_party/blink/renderer/modules/worklet/worklet_thread_test_common.cc b/third_party/blink/renderer/modules/worklet/worklet_thread_test_common.cc
index a42679ef..86fadfc 100644
--- a/third_party/blink/renderer/modules/worklet/worklet_thread_test_common.cc
+++ b/third_party/blink/renderer/modules/worklet/worklet_thread_test_common.cc
@@ -52,7 +52,7 @@
     PaintWorkletProxyClient* proxy_client) {
   if (!proxy_client)
     proxy_client = MakeGarbageCollected<PaintWorkletProxyClient>(1, nullptr);
-  WorkerClients* clients = WorkerClients::Create();
+  WorkerClients* clients = MakeGarbageCollected<WorkerClients>();
   ProvidePaintWorkletProxyClientTo(clients, proxy_client);
 
   std::unique_ptr<AnimationAndPaintWorkletThread> thread =
@@ -74,7 +74,7 @@
         nullptr     /* mutator_runner */
     );
   }
-  WorkerClients* clients = WorkerClients::Create();
+  WorkerClients* clients = MakeGarbageCollected<WorkerClients>();
   ProvideAnimationWorkletProxyClientTo(clients, proxy_client);
 
   std::unique_ptr<AnimationAndPaintWorkletThread> thread =
diff --git a/third_party/blink/renderer/modules/xr/xr_rigid_transform.idl b/third_party/blink/renderer/modules/xr/xr_rigid_transform.idl
index 29e3ad0..4d1000f5 100644
--- a/third_party/blink/renderer/modules/xr/xr_rigid_transform.idl
+++ b/third_party/blink/renderer/modules/xr/xr_rigid_transform.idl
@@ -13,6 +13,5 @@
   readonly attribute DOMPointReadOnly position;
   readonly attribute DOMPointReadOnly orientation;
   readonly attribute Float32Array matrix;
-
-  XRRigidTransform inverse();
+  readonly attribute XRRigidTransform inverse;
 };
diff --git a/third_party/blink/renderer/platform/audio/vector_math.cc b/third_party/blink/renderer/platform/audio/vector_math.cc
index 38a8b95b..1fee474 100644
--- a/third_party/blink/renderer/platform/audio/vector_math.cc
+++ b/third_party/blink/renderer/platform/audio/vector_math.cc
@@ -27,15 +27,15 @@
 
 #include <cmath>
 
+#include "base/compiler_specific.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/cpu.h"
 
 #if defined(OS_MACOSX)
 #include "third_party/blink/renderer/platform/audio/mac/vector_math_mac.h"
-#elif WTF_CPU_ARM_NEON
+#elif defined(CPU_ARM_NEON)
 #include "third_party/blink/renderer/platform/audio/cpu/arm/vector_math_neon.h"
-#elif HAVE_MIPS_MSA_INTRINSICS
+#elif defined(HAVE_MIPS_MSA_INTRINSICS)
 #include "third_party/blink/renderer/platform/audio/cpu/mips/vector_math_msa.h"
 #elif defined(ARCH_CPU_X86_FAMILY)
 #include "third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x86.h"
@@ -50,9 +50,9 @@
 namespace {
 #if defined(OS_MACOSX)
 namespace impl = mac;
-#elif WTF_CPU_ARM_NEON
+#elif defined(CPU_ARM_NEON)
 namespace impl = neon;
-#elif HAVE_MIPS_MSA_INTRINSICS
+#elif defined(HAVE_MIPS_MSA_INTRINSICS)
 namespace impl = msa;
 #elif defined(ARCH_CPU_X86_FAMILY)
 namespace impl = x86;
diff --git a/third_party/blink/renderer/platform/exported/web_speech_synthesizer_client_impl.cc b/third_party/blink/renderer/platform/exported/web_speech_synthesizer_client_impl.cc
index 53efa13..94cbf043 100644
--- a/third_party/blink/renderer/platform/exported/web_speech_synthesizer_client_impl.cc
+++ b/third_party/blink/renderer/platform/exported/web_speech_synthesizer_client_impl.cc
@@ -72,15 +72,18 @@
 
 void WebSpeechSynthesizerClientImpl::WordBoundaryEventOccurred(
     const WebSpeechSynthesisUtterance& utterance,
-    unsigned char_index) {
-  client_->BoundaryEventOccurred(utterance, kSpeechWordBoundary, char_index);
+    unsigned char_index,
+    unsigned char_length) {
+  client_->BoundaryEventOccurred(utterance, kSpeechWordBoundary, char_index,
+                                 char_length);
 }
 
 void WebSpeechSynthesizerClientImpl::SentenceBoundaryEventOccurred(
     const WebSpeechSynthesisUtterance& utterance,
-    unsigned char_index) {
-  client_->BoundaryEventOccurred(utterance, kSpeechSentenceBoundary,
-                                 char_index);
+    unsigned char_index,
+    unsigned char_length) {
+  client_->BoundaryEventOccurred(utterance, kSpeechSentenceBoundary, char_index,
+                                 char_length);
 }
 
 void WebSpeechSynthesizerClientImpl::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/platform/exported/web_speech_synthesizer_client_impl.h b/third_party/blink/renderer/platform/exported/web_speech_synthesizer_client_impl.h
index f298083..3b16b7a 100644
--- a/third_party/blink/renderer/platform/exported/web_speech_synthesizer_client_impl.h
+++ b/third_party/blink/renderer/platform/exported/web_speech_synthesizer_client_impl.h
@@ -52,9 +52,11 @@
   void DidResumeSpeaking(const WebSpeechSynthesisUtterance&) override;
   void SpeakingErrorOccurred(const WebSpeechSynthesisUtterance&) override;
   void WordBoundaryEventOccurred(const WebSpeechSynthesisUtterance&,
-                                 unsigned char_index) override;
+                                 unsigned char_index,
+                                 unsigned char_length) override;
   void SentenceBoundaryEventOccurred(const WebSpeechSynthesisUtterance&,
-                                     unsigned char_index) override;
+                                     unsigned char_index,
+                                     unsigned char_length) override;
 
   void Trace(blink::Visitor*);
 
diff --git a/third_party/blink/renderer/platform/exported/web_url_request.cc b/third_party/blink/renderer/platform/exported/web_url_request.cc
index 942ecdd..09b823c 100644
--- a/third_party/blink/renderer/platform/exported/web_url_request.cc
+++ b/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -158,7 +158,7 @@
   resource_request_->SetHttpHeaderField(name, value);
 }
 
-void WebURLRequest::SetHTTPReferrer(
+void WebURLRequest::SetHttpReferrer(
     const WebString& web_referrer,
     network::mojom::ReferrerPolicy referrer_policy) {
   // WebString doesn't have the distinction between empty and null. We use
@@ -168,7 +168,7 @@
       web_referrer.IsEmpty() ? Referrer::NoReferrer() : String(web_referrer);
   // TODO(domfarolino): Stop storing ResourceRequest's generated referrer as a
   // header and instead use a separate member. See https://crbug.com/850813.
-  resource_request_->SetHTTPReferrer(Referrer(referrer, referrer_policy));
+  resource_request_->SetHttpReferrer(Referrer(referrer, referrer_policy));
 }
 
 void WebURLRequest::AddHttpHeaderField(const WebString& name,
@@ -218,8 +218,8 @@
   return resource_request_->GetReferrerPolicy();
 }
 
-void WebURLRequest::SetHTTPOriginIfNeeded(const WebSecurityOrigin& origin) {
-  resource_request_->SetHTTPOriginIfNeeded(origin.Get());
+void WebURLRequest::SetHttpOriginIfNeeded(const WebSecurityOrigin& origin) {
+  resource_request_->SetHttpOriginIfNeeded(origin.Get());
 }
 
 bool WebURLRequest::HasUserGesture() const {
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
index 1d2f395..5d6090dd 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
@@ -1507,13 +1507,7 @@
   }
 
   // Add zero-width spaces at some of the safe to break offsets.
-  String inserted_zero_width_spaces = test_word;
-  inserted_zero_width_spaces.Ensure16Bit();
-  unsigned enlarged_by = 0;
-  for (unsigned safe_to_break_position : safe_to_break_positions) {
-    inserted_zero_width_spaces.insert(u"\u200B",
-                                      safe_to_break_position + enlarged_by++);
-  }
+  String inserted_zero_width_spaces(u"RA\u200BD\u200BDAYoVa\u200BD\u200BD");
   HarfBuzzShaper refShaper(inserted_zero_width_spaces);
   scoped_refptr<ShapeResult> referenceResult =
       refShaper.Shape(&testFont, TextDirection::kLtr);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
index 31bfc28..9da3914 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
@@ -1591,6 +1591,36 @@
   return result;
 }
 
+scoped_refptr<ShapeResult> ShapeResult::CreateForSpaces(const Font* font,
+                                                        TextDirection direction,
+                                                        unsigned start_index,
+                                                        unsigned length,
+                                                        float width) {
+  DCHECK_GT(length, 0u);
+  const SimpleFontData* font_data = font->PrimaryFont();
+  scoped_refptr<ShapeResult> result =
+      ShapeResult::Create(font, length, direction);
+  result->num_glyphs_ = length;
+  DCHECK_EQ(result->num_glyphs_, length);  // no overflow
+  result->has_vertical_offsets_ =
+      font_data->PlatformData().IsVerticalAnyUpright();
+  hb_direction_t hb_direction =
+      IsLtr(direction) ? HB_DIRECTION_LTR : HB_DIRECTION_RTL;
+  scoped_refptr<ShapeResult::RunInfo> run = RunInfo::Create(
+      font_data, hb_direction, CanvasRotationInVertical::kRegular,
+      HB_SCRIPT_COMMON, start_index, length, length);
+  result->width_ = run->width_ = width;
+  for (unsigned i = 0; i < length; i++) {
+    HarfBuzzRunGlyphData& glyph_data = run->glyph_data_[i];
+    glyph_data.SetGlyphAndPositions(font_data->SpaceGlyph(), i, width,
+                                    FloatSize(), true);
+    width = 0;
+  }
+  result->runs_.push_back(std::move(run));
+  result->UpdateStartIndex();
+  return result;
+}
+
 void ShapeResult::ToString(StringBuilder* output) const {
   output->Append("#chars=");
   output->AppendNumber(num_characters_);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
index fd97fd1..f0f2b4e 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
@@ -134,6 +134,11 @@
       float position,
       unsigned start_index,
       unsigned length);
+  static scoped_refptr<ShapeResult> CreateForSpaces(const Font* font,
+                                                    TextDirection direction,
+                                                    unsigned start_index,
+                                                    unsigned length,
+                                                    float width);
   ~ShapeResult();
 
   // Returns a mutable unique instance. If |this| has more than 1 ref count,
diff --git a/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc b/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc
index f094851b..fbc3e874 100644
--- a/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc
+++ b/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/public/platform/interface_provider.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/skia/include/ports/SkTypeface_win.h"
 
 namespace {
@@ -34,7 +35,7 @@
 
 sk_sp<SkTypeface> FontUniqueNameLookupWin::MatchUniqueName(
     const String& font_unique_name) {
-  if (!EnsureMatchingServiceConnected())
+  if (!IsFontUniqueNameLookupReadyForSyncLookup())
     return nullptr;
 
   base::Optional<FontTableMatcher::MatchResult> match_result =
@@ -74,26 +75,77 @@
   return local_typeface;
 }
 
-bool FontUniqueNameLookupWin::EnsureMatchingServiceConnected() {
-  if (font_table_matcher_)
+bool FontUniqueNameLookupWin::IsFontUniqueNameLookupReadyForSyncLookup() {
+  // If we have the table already, we're ready for sync lookups.
+  if (font_table_matcher_.get())
     return true;
 
-  mojom::blink::DWriteFontProxyPtr service;
-  Platform::Current()->GetInterfaceProvider()->GetInterface(
-      mojo::MakeRequest(&service));
+  if (!RuntimeEnabledFeatures::FontSrcLocalMatchingEnabled())
+    return true;
 
-  base::ReadOnlySharedMemoryRegion region_ptr;
-  if (!service->GetUniqueNameLookupTable(&region_ptr)) {
-    // Tests like StyleEngineTest do not set up a full browser where Blink can
-    // connect to a browser side service for font lookups. Placing a DCHECK here
-    // is too strict for such a case.
-    LOG(ERROR) << "Unable to connect to browser side service for src: local() "
-                  "font lookup.";
-    return false;
+  // We have previously determined via IPC whether the table is sync available.
+  // Return what we found out before.
+  if (sync_available_.has_value())
+    return sync_available_.value();
+
+  // If we haven't asked the browser before, probe synchronously - if the table
+  // is available on the browser side, we can continue with sync operation.
+
+  EnsureServiceConnected();
+
+  bool sync_available_from_mojo = false;
+  base::ReadOnlySharedMemoryRegion shared_memory_region;
+  service_->GetUniqueNameLookupTableIfAvailable(&sync_available_from_mojo,
+                                                &shared_memory_region);
+  sync_available_ = sync_available_from_mojo;
+
+  if (*sync_available_) {
+    // Adopt the shared memory region, do not notify anyone in callbacks as
+    // PrepareFontUniqueNameLookup must not have been called yet. Just return
+    // true from this function.
+    DCHECK_EQ(pending_callbacks_.size(), 0u);
+    ReceiveReadOnlySharedMemoryRegion(std::move(shared_memory_region));
   }
 
-  font_table_matcher_ = std::make_unique<FontTableMatcher>(region_ptr.Map());
-  return true;
+  // If it wasn't available synchronously LocalFontFaceSource has to call
+  // PrepareFontUniqueNameLookup.
+  return *sync_available_;
+}
+
+void FontUniqueNameLookupWin::EnsureServiceConnected() {
+  Platform::Current()->GetInterfaceProvider()->GetInterface(
+      mojo::MakeRequest(&service_));
+}
+
+void FontUniqueNameLookupWin::PrepareFontUniqueNameLookup(
+    NotifyFontUniqueNameLookupReady callback) {
+  DCHECK(!font_table_matcher_.get());
+  DCHECK(RuntimeEnabledFeatures::FontSrcLocalMatchingEnabled());
+
+  pending_callbacks_.push_back(std::move(callback));
+
+  // We bind the service on the first call to PrepareFontUniqueNameLookup. After
+  // that we do not need to make additional IPC requests to retrieve the table.
+  // The observing callback was added to the list, so all clients will be
+  // informed when the lookup table has arrived.
+  if (pending_callbacks_.size() > 1)
+    return;
+
+  EnsureServiceConnected();
+
+  service_->GetUniqueNameLookupTable(base::BindRepeating(
+      &FontUniqueNameLookupWin::ReceiveReadOnlySharedMemoryRegion,
+      base::Unretained(this)));
+}
+
+void FontUniqueNameLookupWin::ReceiveReadOnlySharedMemoryRegion(
+    base::ReadOnlySharedMemoryRegion shared_memory_region) {
+  font_table_matcher_ =
+      std::make_unique<FontTableMatcher>(shared_memory_region.Map());
+  while (!pending_callbacks_.IsEmpty()) {
+    NotifyFontUniqueNameLookupReady callback = pending_callbacks_.TakeFirst();
+    std::move(callback).Run();
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h b/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h
index 2ef0638..73aec63 100644
--- a/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h
+++ b/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h
@@ -6,7 +6,9 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FONT_UNIQUE_NAME_LOOKUP_WIN_H_
 
 #include "third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h"
+#include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom-blink.h"
 #include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h"
+#include "third_party/blink/renderer/platform/wtf/deque.h"
 
 namespace blink {
 
@@ -16,8 +18,19 @@
   ~FontUniqueNameLookupWin() override;
   sk_sp<SkTypeface> MatchUniqueName(const String& font_unique_name) override;
 
+  bool IsFontUniqueNameLookupReadyForSyncLookup() override;
+
+  void PrepareFontUniqueNameLookup(
+      NotifyFontUniqueNameLookupReady callback) override;
+
  private:
-  bool EnsureMatchingServiceConnected();
+  void EnsureServiceConnected();
+
+  mojom::blink::DWriteFontProxyPtr service_;
+  WTF::Deque<NotifyFontUniqueNameLookupReady> pending_callbacks_;
+  base::Optional<bool> sync_available_;
+  void ReceiveReadOnlySharedMemoryRegion(
+      base::ReadOnlySharedMemoryRegion shared_memory_region);
 
   DISALLOW_COPY_AND_ASSIGN(FontUniqueNameLookupWin);
 };
diff --git a/third_party/blink/renderer/platform/graphics/cpu/arm/webgl_image_conversion_neon.h b/third_party/blink/renderer/platform/graphics/cpu/arm/webgl_image_conversion_neon.h
index 6316c32e..92216012 100644
--- a/third_party/blink/renderer/platform/graphics/cpu/arm/webgl_image_conversion_neon.h
+++ b/third_party/blink/renderer/platform/graphics/cpu/arm/webgl_image_conversion_neon.h
@@ -27,7 +27,9 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CPU_ARM_WEBGL_IMAGE_CONVERSION_NEON_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CPU_ARM_WEBGL_IMAGE_CONVERSION_NEON_H_
 
-#if WTF_CPU_ARM_NEON
+#include "base/compiler_specific.h"
+
+#if defined(CPU_ARM_NEON)
 
 #include <arm_neon.h>
 
@@ -292,6 +294,6 @@
 
 }  // namespace blink
 
-#endif  // WTF_CPU_ARM_NEON
+#endif  // CPU_ARM_NEON
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CPU_ARM_WEBGL_IMAGE_CONVERSION_NEON_H_
diff --git a/third_party/blink/renderer/platform/graphics/cpu/mips/webgl_image_conversion_msa.h b/third_party/blink/renderer/platform/graphics/cpu/mips/webgl_image_conversion_msa.h
index 3de6294..7b46516 100644
--- a/third_party/blink/renderer/platform/graphics/cpu/mips/webgl_image_conversion_msa.h
+++ b/third_party/blink/renderer/platform/graphics/cpu/mips/webgl_image_conversion_msa.h
@@ -5,7 +5,9 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CPU_MIPS_WEBGL_IMAGE_CONVERSION_MSA_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CPU_MIPS_WEBGL_IMAGE_CONVERSION_MSA_H_
 
-#if HAVE_MIPS_MSA_INTRINSICS
+#include "base/compiler_specific.h"
+
+#if defined(HAVE_MIPS_MSA_INTRINSICS)
 
 #include "third_party/blink/renderer/platform/cpu/mips/common_macros_msa.h"
 
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc b/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc
index 9218a24..ae1ed8a3 100644
--- a/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc
+++ b/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc
@@ -53,10 +53,20 @@
     result = DarkModeClassification::kApplyDarkModeFilter;
   } else {
     std::vector<float> features;
-    if (!ComputeImageFeatures(image, src_rect, &features, &sampled_pixels))
-      result = DarkModeClassification::kDoNotApplyDarkModeFilter;
-    else
+    if (!ComputeImageFeatures(image, src_rect, &features, &sampled_pixels)) {
+      // TODO(v.paturi): Implement an SVG classifier which can decide if a
+      // filter should be applied based on the image's content and it's
+      // visibility on a dark background.
+      // Force this function to return true for any SVG image so that the
+      // filter will be set in the PaintFlags in GraphicsContext::DrawImage.
+      if (image.IsSVGImage() || image.IsSVGImageForContainer()) {
+        result = DarkModeClassification::kApplyDarkModeFilter;
+      } else {
+        result = DarkModeClassification::kDoNotApplyDarkModeFilter;
+      }
+    } else {
       result = ClassifyImage(features);
+    }
   }
 
   // Store the classification result in the image object using src_rect's
diff --git a/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc b/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc
index 6b3e6666..c5e652f 100644
--- a/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc
+++ b/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc
@@ -34,6 +34,7 @@
 #include "third_party/blink/renderer/platform/graphics/image_decoding_store.h"
 #include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"
 #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
+#include "third_party/blink/renderer/platform/histogram.h"
 #include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/shared_buffer.h"
@@ -41,6 +42,39 @@
 
 namespace blink {
 
+namespace {
+
+// Do not rename entries or reuse numeric values to ensure the histogram is
+// consistent over time.
+enum IncrementalDecodePerImageType {
+  kJpegIncrementalNeeded = 0,
+  kJpegAllDataReceivedInitially = 1,
+  kWebPIncrementalNeeded = 2,
+  kWebPAllDataReceivedInitially = 3,
+  kBoundaryValue
+};
+
+void ReportIncrementalDecodeNeeded(bool all_data_received,
+                                   const String& image_type) {
+  DCHECK(IsMainThread());
+  DEFINE_STATIC_LOCAL(EnumerationHistogram, incremental_decode_needed_histogram,
+                      ("Blink.ImageDecoders.IncrementalDecodeNeeded",
+                       IncrementalDecodePerImageType::kBoundaryValue));
+  if (image_type == "jpg") {
+    incremental_decode_needed_histogram.Count(
+        all_data_received
+            ? IncrementalDecodePerImageType::kJpegAllDataReceivedInitially
+            : IncrementalDecodePerImageType::kJpegIncrementalNeeded);
+  } else if (image_type == "webp") {
+    incremental_decode_needed_histogram.Count(
+        all_data_received
+            ? IncrementalDecodePerImageType::kWebPAllDataReceivedInitially
+            : IncrementalDecodePerImageType::kWebPIncrementalNeeded);
+  }
+}
+
+}  // namespace
+
 struct DeferredFrameData {
   DISALLOW_NEW();
 
@@ -138,6 +172,13 @@
     frames[i].duration = FrameDurationAtIndex(i);
   }
 
+  // Report UMA about whether incremental decoding is done for JPEG/WebP images.
+  const String image_type = FilenameExtension();
+  if (!first_decoding_generator_created_ &&
+      (image_type == "jpg" || image_type == "webp")) {
+    ReportIncrementalDecodeNeeded(all_data_received_, image_type);
+  }
+
   const bool is_eligible_for_accelerated_decoding =
       !first_decoding_generator_created_ && all_data_received_;
   auto generator = DecodingImageGenerator::Create(
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc b/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
index 4018b09c..af217be 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
@@ -5,6 +5,8 @@
 #include "third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h"
 
 #include <memory>
+
+#include "base/compiler_specific.h"
 #include "base/numerics/checked_math.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/graphics/cpu/arm/webgl_image_conversion_neon.h"
@@ -449,7 +451,7 @@
   simd::UnpackOneRowOfBGRA8LittleToRGBA8(source32, destination32,
                                          pixels_per_row);
 #endif
-#if HAVE_MIPS_MSA_INTRINSICS
+#if defined(HAVE_MIPS_MSA_INTRINSICS)
   simd::unpackOneRowOfBGRA8LittleToRGBA8MSA(source32, destination32,
                                             pixels_per_row);
 #endif
@@ -477,10 +479,10 @@
   simd::UnpackOneRowOfRGBA5551LittleToRGBA8(source, destination,
                                             pixels_per_row);
 #endif
-#if WTF_CPU_ARM_NEON
+#if defined(CPU_ARM_NEON)
   simd::UnpackOneRowOfRGBA5551ToRGBA8(source, destination, pixels_per_row);
 #endif
-#if HAVE_MIPS_MSA_INTRINSICS
+#if defined(HAVE_MIPS_MSA_INTRINSICS)
   simd::unpackOneRowOfRGBA5551ToRGBA8MSA(source, destination, pixels_per_row);
 #endif
 
@@ -507,10 +509,10 @@
   simd::UnpackOneRowOfRGBA4444LittleToRGBA8(source, destination,
                                             pixels_per_row);
 #endif
-#if WTF_CPU_ARM_NEON
+#if defined(CPU_ARM_NEON)
   simd::UnpackOneRowOfRGBA4444ToRGBA8(source, destination, pixels_per_row);
 #endif
-#if HAVE_MIPS_MSA_INTRINSICS
+#if defined(HAVE_MIPS_MSA_INTRINSICS)
   simd::unpackOneRowOfRGBA4444ToRGBA8MSA(source, destination, pixels_per_row);
 #endif
   for (unsigned i = 0; i < pixels_per_row; ++i) {
@@ -722,7 +724,7 @@
 #if defined(ARCH_CPU_X86_FAMILY)
   simd::PackOneRowOfRGBA8LittleToR8(source, destination, pixels_per_row);
 #endif
-#if HAVE_MIPS_MSA_INTRINSICS
+#if defined(HAVE_MIPS_MSA_INTRINSICS)
   simd::packOneRowOfRGBA8LittleToR8MSA(source, destination, pixels_per_row);
 #endif
   for (unsigned i = 0; i < pixels_per_row; ++i) {
@@ -779,7 +781,7 @@
 #if defined(ARCH_CPU_X86_FAMILY)
   simd::PackOneRowOfRGBA8LittleToRA8(source, destination, pixels_per_row);
 #endif
-#if HAVE_MIPS_MSA_INTRINSICS
+#if defined(HAVE_MIPS_MSA_INTRINSICS)
   simd::packOneRowOfRGBA8LittleToRA8MSA(source, destination, pixels_per_row);
 #endif
   for (unsigned i = 0; i < pixels_per_row; ++i) {
@@ -891,7 +893,7 @@
 #if defined(ARCH_CPU_X86_FAMILY)
   simd::PackOneRowOfRGBA8LittleToRGBA8(source, destination, pixels_per_row);
 #endif
-#if HAVE_MIPS_MSA_INTRINSICS
+#if defined(HAVE_MIPS_MSA_INTRINSICS)
   simd::packOneRowOfRGBA8LittleToRGBA8MSA(source, destination, pixels_per_row);
 #endif
   for (unsigned i = 0; i < pixels_per_row; ++i) {
@@ -918,11 +920,11 @@
           uint16_t>(const uint8_t* source,
                     uint16_t* destination,
                     unsigned pixels_per_row) {
-#if WTF_CPU_ARM_NEON
+#if defined(CPU_ARM_NEON)
   simd::PackOneRowOfRGBA8ToUnsignedShort4444(source, destination,
                                              pixels_per_row);
 #endif
-#if HAVE_MIPS_MSA_INTRINSICS
+#if defined(HAVE_MIPS_MSA_INTRINSICS)
   simd::packOneRowOfRGBA8ToUnsignedShort4444MSA(source, destination,
                                                 pixels_per_row);
 #endif
@@ -986,11 +988,11 @@
           uint16_t>(const uint8_t* source,
                     uint16_t* destination,
                     unsigned pixels_per_row) {
-#if WTF_CPU_ARM_NEON
+#if defined(CPU_ARM_NEON)
   simd::PackOneRowOfRGBA8ToUnsignedShort5551(source, destination,
                                              pixels_per_row);
 #endif
-#if HAVE_MIPS_MSA_INTRINSICS
+#if defined(HAVE_MIPS_MSA_INTRINSICS)
   simd::packOneRowOfRGBA8ToUnsignedShort5551MSA(source, destination,
                                                 pixels_per_row);
 #endif
@@ -1054,11 +1056,11 @@
           uint16_t>(const uint8_t* source,
                     uint16_t* destination,
                     unsigned pixels_per_row) {
-#if WTF_CPU_ARM_NEON
+#if defined(CPU_ARM_NEON)
   simd::PackOneRowOfRGBA8ToUnsignedShort565(source, destination,
                                             pixels_per_row);
 #endif
-#if HAVE_MIPS_MSA_INTRINSICS
+#if defined(HAVE_MIPS_MSA_INTRINSICS)
   simd::packOneRowOfRGBA8ToUnsignedShort565MSA(source, destination,
                                                pixels_per_row);
 #endif
diff --git a/third_party/blink/renderer/platform/graphics/image.h b/third_party/blink/renderer/platform/graphics/image.h
index 6ce60ae..c6738b7e 100644
--- a/third_party/blink/renderer/platform/graphics/image.h
+++ b/third_party/blink/renderer/platform/graphics/image.h
@@ -88,6 +88,11 @@
       InterpolationQuality = kInterpolationNone);
 
   virtual bool IsSVGImage() const { return false; }
+  // TODO(v.paturi): Remove this function once
+  // |ShouldApplyDarkModeFilterToImage| is refactored.
+  // It's suggested that this function not be used anywhere
+  // else in the mean time.
+  virtual bool IsSVGImageForContainer() const { return false; }
   virtual bool IsBitmapImage() const { return false; }
   virtual bool IsStaticBitmapImage() const { return false; }
   virtual bool IsPlaceholderImage() const { return false; }
diff --git a/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h b/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
index 5a7af03..e28077f 100644
--- a/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
+++ b/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
@@ -14,7 +14,7 @@
 #include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
 #include "third_party/skia/include/gpu/GrContext.h"
-#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
+#include "third_party/skia/include/gpu/mock/GrMockTypes.h"
 
 namespace blink {
 
@@ -24,8 +24,10 @@
                                    cc::ImageDecodeCache* cache = nullptr)
       : gl_(gl),
         image_decode_cache_(cache ? cache : &stub_image_decode_cache_) {
-    sk_sp<const GrGLInterface> gl_interface(GrGLCreateNullInterface());
-    gr_context_ = GrContext::MakeGL(std::move(gl_interface));
+    GrMockOptions mockOptions;
+    mockOptions.fConfigOptions[kBGRA_8888_GrPixelConfig] =
+        mockOptions.fConfigOptions[kRGBA_8888_GrPixelConfig];
+    gr_context_ = GrContext::MakeMock(&mockOptions);
     // enable all gpu features.
     for (unsigned feature = 0; feature < gpu::NUMBER_OF_GPU_FEATURE_TYPES;
          ++feature) {
diff --git a/third_party/blink/renderer/platform/heap/heap_test.cc b/third_party/blink/renderer/platform/heap/heap_test.cc
index 84aec721..9ee39be 100644
--- a/third_party/blink/renderer/platform/heap/heap_test.cc
+++ b/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -65,10 +65,6 @@
 
 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
  public:
-  static IntWrapper* Create(int x) {
-    return MakeGarbageCollected<IntWrapper>(x);
-  }
-
   virtual ~IntWrapper() {
     destructor_calls_.fetch_add(1, std::memory_order_relaxed);
   }
@@ -397,7 +393,6 @@
 
 class SimpleObject : public GarbageCollected<SimpleObject> {
  public:
-  static SimpleObject* Create() { return MakeGarbageCollected<SimpleObject>(); }
   SimpleObject() = default;
   void Trace(blink::Visitor* visitor) {}
   char GetPayload(int i) { return payload[i]; }
@@ -416,10 +411,6 @@
 class HeapTestSuperClass
     : public GarbageCollectedFinalized<HeapTestSuperClass> {
  public:
-  static HeapTestSuperClass* Create() {
-    return MakeGarbageCollected<HeapTestSuperClass>();
-  }
-
   HeapTestSuperClass() = default;
   virtual ~HeapTestSuperClass() { ++destructor_calls_; }
 
@@ -439,10 +430,6 @@
 class HeapTestSubClass : public HeapTestOtherSuperClass,
                          public HeapTestSuperClass {
  public:
-  static HeapTestSubClass* Create() {
-    return MakeGarbageCollected<HeapTestSubClass>();
-  }
-
   HeapTestSubClass() : magic_(kClassMagic) {}
   ~HeapTestSubClass() override {
     EXPECT_EQ(kClassMagic, magic_);
@@ -575,7 +562,7 @@
   std::unique_ptr<GlobalIntWrapperPersistent> CreateGlobalPersistent(
       int value) {
     return std::make_unique<GlobalIntWrapperPersistent>(
-        IntWrapper::Create(value));
+        MakeGarbageCollected<IntWrapper>(value));
   }
 
   void AddGlobalPersistent() {
@@ -598,7 +585,7 @@
             CreateGlobalPersistent(0x0ed0cabb);
 
         for (int i = 0; i < kNumberOfAllocations; i++) {
-          wrapper = IntWrapper::Create(0x0bbac0de);
+          wrapper = MakeGarbageCollected<IntWrapper>(0x0bbac0de);
           if (!(i % 10)) {
             global_persistent = CreateGlobalPersistent(0x0ed0cabb);
           }
@@ -639,7 +626,8 @@
                 HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>>();
 
         for (int i = 0; i < kNumberOfAllocations; i++) {
-          weak_map->insert(static_cast<unsigned>(i), IntWrapper::Create(0));
+          weak_map->insert(static_cast<unsigned>(i),
+                           MakeGarbageCollected<IntWrapper>(0));
           test::YieldCurrentThread();
         }
 
@@ -688,7 +676,7 @@
     explicit RefCountedChain(int count) {
       if (count > 0) {
         --count;
-        persistent_chain_ = PersistentChain::Create(count);
+        persistent_chain_ = MakeGarbageCollected<PersistentChain>(count);
       }
     }
 
@@ -697,10 +685,6 @@
 
   class PersistentChain : public GarbageCollectedFinalized<PersistentChain> {
    public:
-    static PersistentChain* Create(int count) {
-      return MakeGarbageCollected<PersistentChain>(count);
-    }
-
     explicit PersistentChain(int count) {
       ref_counted_chain_ = base::AdoptRef(RefCountedChain::Create(count));
     }
@@ -712,7 +696,7 @@
   };
 
   void RunThread() override {
-    PersistentChain::Create(100);
+    MakeGarbageCollected<PersistentChain>(100);
 
     // Upon thread detach, GCs will run until all persistents have been
     // released. We verify that the draining of persistents proceeds
@@ -732,8 +716,6 @@
 
 class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
  public:
-  static TraceCounter* Create() { return MakeGarbageCollected<TraceCounter>(); }
-
   TraceCounter() : trace_count_(0) {}
 
   void Trace(blink::Visitor* visitor) { trace_count_++; }
@@ -745,7 +727,7 @@
 
 TEST(HeapTest, IsHeapObjectAliveForConstPointer) {
   // See http://crbug.com/661363.
-  SimpleObject* object = SimpleObject::Create();
+  auto* object = MakeGarbageCollected<SimpleObject>();
   HeapObjectHeader* header = HeapObjectHeader::FromPayload(object);
   header->Mark();
   EXPECT_TRUE(ThreadHeap::IsHeapObjectAlive(object));
@@ -755,11 +737,7 @@
 
 class ClassWithMember : public GarbageCollected<ClassWithMember> {
  public:
-  static ClassWithMember* Create() {
-    return MakeGarbageCollected<ClassWithMember>();
-  }
-
-  ClassWithMember() : trace_counter_(TraceCounter::Create()) {}
+  ClassWithMember() : trace_counter_(MakeGarbageCollected<TraceCounter>()) {}
 
   void Trace(blink::Visitor* visitor) {
     visitor->Trace(trace_counter_);
@@ -773,10 +751,6 @@
 class SimpleFinalizedObject
     : public GarbageCollectedFinalized<SimpleFinalizedObject> {
  public:
-  static SimpleFinalizedObject* Create() {
-    return MakeGarbageCollected<SimpleFinalizedObject>();
-  }
-
   SimpleFinalizedObject() = default;
   ~SimpleFinalizedObject() { ++destructor_calls_; }
 
@@ -819,8 +793,6 @@
 
 class Bar : public GarbageCollectedFinalized<Bar> {
  public:
-  static Bar* Create() { return MakeGarbageCollected<Bar>(); }
-
   Bar() : magic_(kMagic) { live_++; }
 
   void FinalizeGarbageCollectedObject() {
@@ -842,8 +814,6 @@
 
 class Baz : public GarbageCollected<Baz> {
  public:
-  static Baz* Create(Bar* bar) { return MakeGarbageCollected<Baz>(bar); }
-
   explicit Baz(Bar* bar) : bar_(bar) {}
 
   void Trace(blink::Visitor* visitor) { visitor->Trace(bar_); }
@@ -859,10 +829,6 @@
 
 class Foo : public Bar {
  public:
-  static Foo* Create(Bar* bar) { return MakeGarbageCollected<Foo>(bar); }
-
-  static Foo* Create(Foo* foo) { return MakeGarbageCollected<Foo>(foo); }
-
   Foo(Bar* bar) : Bar(), bar_(bar), points_to_foo_(false) {}
 
   Foo(Foo* foo) : Bar(), bar_(foo), points_to_foo_(true) {}
@@ -881,11 +847,9 @@
 
 class Bars : public Bar {
  public:
-  static Bars* Create() { return MakeGarbageCollected<Bars>(); }
-
   Bars() : width_(0) {
     for (unsigned i = 0; i < kWidth; i++) {
-      bars_[i] = Bar::Create();
+      bars_[i] = MakeGarbageCollected<Bar>();
       width_++;
     }
   }
@@ -906,12 +870,10 @@
 
 class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
  public:
-  static ConstructorAllocation* Create() {
-    return MakeGarbageCollected<ConstructorAllocation>();
+  ConstructorAllocation() {
+    int_wrapper_ = MakeGarbageCollected<IntWrapper>(42);
   }
 
-  ConstructorAllocation() { int_wrapper_ = IntWrapper::Create(42); }
-
   void Trace(blink::Visitor* visitor) { visitor->Trace(int_wrapper_); }
 
  private:
@@ -920,11 +882,9 @@
 
 class LargeHeapObject : public GarbageCollectedFinalized<LargeHeapObject> {
  public:
-  LargeHeapObject() { int_wrapper_ = IntWrapper::Create(23); }
+  LargeHeapObject() { int_wrapper_ = MakeGarbageCollected<IntWrapper>(23); }
   ~LargeHeapObject() { destructor_calls_++; }
-  static LargeHeapObject* Create() {
-    return MakeGarbageCollected<LargeHeapObject>();
-  }
+
   char Get(size_t i) { return data_[i]; }
   void Set(size_t i, char c) { data_[i] = c; }
   size_t length() { return kLength; }
@@ -953,10 +913,6 @@
 class RefCountedAndGarbageCollected
     : public GarbageCollectedFinalized<RefCountedAndGarbageCollected> {
  public:
-  static RefCountedAndGarbageCollected* Create() {
-    return MakeGarbageCollected<RefCountedAndGarbageCollected>();
-  }
-
   RefCountedAndGarbageCollected() : ref_count_(0) {}
   ~RefCountedAndGarbageCollected() { ++destructor_calls_; }
 
@@ -992,10 +948,6 @@
     : public HeapTestOtherSuperClass,
       public GarbageCollectedFinalized<RefCountedAndGarbageCollected2> {
  public:
-  static RefCountedAndGarbageCollected2* Create() {
-    return MakeGarbageCollected<RefCountedAndGarbageCollected2>();
-  }
-
   RefCountedAndGarbageCollected2() : ref_count_(0) {}
   ~RefCountedAndGarbageCollected2() { ++destructor_calls_; }
 
@@ -1029,10 +981,6 @@
 
 class Weak : public Bar {
  public:
-  static Weak* Create(Bar* strong, Bar* weak) {
-    return MakeGarbageCollected<Weak>(strong, weak);
-  }
-
   Weak(Bar* strong_bar, Bar* weak_bar)
       : Bar(), strong_bar_(strong_bar), weak_bar_(weak_bar) {}
 
@@ -1056,10 +1004,6 @@
 
 class WithWeakMember : public Bar {
  public:
-  static WithWeakMember* Create(Bar* strong, Bar* weak) {
-    return MakeGarbageCollected<WithWeakMember>(strong, weak);
-  }
-
   WithWeakMember(Bar* strong_bar, Bar* weak_bar)
       : Bar(), strong_bar_(strong_bar), weak_bar_(weak_bar) {}
 
@@ -1080,9 +1024,6 @@
   USING_PRE_FINALIZER(Observable, WillFinalize);
 
  public:
-  static Observable* Create(Bar* bar) {
-    return MakeGarbageCollected<Observable>(bar);
-  }
   explicit Observable(Bar* bar) : bar_(bar), was_destructed_(false) {}
   ~Observable() { was_destructed_ = true; }
   void Trace(blink::Visitor* visitor) { visitor->Trace(bar_); }
@@ -1108,9 +1049,6 @@
   USING_PRE_FINALIZER(ObservableWithPreFinalizer, Dispose);
 
  public:
-  static ObservableWithPreFinalizer* Create() {
-    return MakeGarbageCollected<ObservableWithPreFinalizer>();
-  }
   ObservableWithPreFinalizer() : was_destructed_(false) {}
   ~ObservableWithPreFinalizer() { was_destructed_ = true; }
   void Trace(blink::Visitor* visitor) {}
@@ -1134,9 +1072,6 @@
   USING_PRE_FINALIZER(PreFinalizerBase, Dispose);
 
  public:
-  static PreFinalizerBase* Create() {
-    return MakeGarbageCollected<PreFinalizerBase>();
-  }
   PreFinalizerBase() : was_destructed_(false) {}
   virtual ~PreFinalizerBase() { was_destructed_ = true; }
   virtual void Trace(blink::Visitor* visitor) {}
@@ -1176,9 +1111,6 @@
   USING_PRE_FINALIZER(PreFinalizerSubClass, Dispose);
 
  public:
-  static PreFinalizerSubClass* Create() {
-    return MakeGarbageCollected<PreFinalizerSubClass>();
-  }
   PreFinalizerSubClass() : was_destructed_(false) {}
   ~PreFinalizerSubClass() override { was_destructed_ = true; }
   void Trace(blink::Visitor* visitor) override {}
@@ -1197,10 +1129,6 @@
 template <typename T>
 class FinalizationObserver : public GarbageCollected<FinalizationObserver<T>> {
  public:
-  static FinalizationObserver* Create(T* data) {
-    return MakeGarbageCollected<FinalizationObserver>(data);
-  }
-
   FinalizationObserver(T* data) : data_(data), did_call_will_finalize_(false) {}
 
   bool DidCallWillFinalize() const { return did_call_will_finalize_; }
@@ -1277,8 +1205,6 @@
 
 class PointsBack : public GarbageCollectedFinalized<PointsBack> {
  public:
-  static PointsBack* Create() { return MakeGarbageCollected<PointsBack>(); }
-
   PointsBack() : back_pointer_(nullptr) { ++alive_count_; }
   ~PointsBack() { --alive_count_; }
 
@@ -1300,10 +1226,6 @@
 
 class SuperClass : public GarbageCollectedFinalized<SuperClass> {
  public:
-  static SuperClass* Create(PointsBack* points_back) {
-    return MakeGarbageCollected<SuperClass>(points_back);
-  }
-
   explicit SuperClass(PointsBack* points_back) : points_back_(points_back) {
     points_back_->SetBackPointer(this);
     ++alive_count_;
@@ -1343,10 +1265,6 @@
 
 class SubClass : public SuperClass {
  public:
-  static SubClass* Create(PointsBack* points_back) {
-    return MakeGarbageCollected<SubClass>(points_back);
-  }
-
   explicit SubClass(PointsBack* points_back)
       : SuperClass(points_back), data_(MakeGarbageCollected<SubData>()) {
     ++alive_count_;
@@ -1380,8 +1298,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(UseMixin);
 
  public:
-  static UseMixin* Create() { return MakeGarbageCollected<UseMixin>(); }
-
   UseMixin() {
     // Verify that WTF::IsGarbageCollectedType<> works as expected for mixins.
     static_assert(WTF::IsGarbageCollectedType<UseMixin>::value,
@@ -1403,7 +1319,7 @@
   DISALLOW_NEW();
 
  public:
-  VectorObject() { value_ = SimpleFinalizedObject::Create(); }
+  VectorObject() { value_ = MakeGarbageCollected<SimpleFinalizedObject>(); }
 
   void Trace(blink::Visitor* visitor) { visitor->Trace(value_); }
 
@@ -1417,7 +1333,9 @@
   DISALLOW_NEW();
 
  public:
-  VectorObjectNoTrace() { value_ = SimpleFinalizedObject::Create(); }
+  VectorObjectNoTrace() {
+    value_ = MakeGarbageCollected<SimpleFinalizedObject>();
+  }
 
  private:
   Member<SimpleFinalizedObject> value_;
@@ -1490,11 +1408,11 @@
 
   ~FinalizationAllocator() {
     for (int i = 0; i < 10; ++i)
-      *wrapper_ = IntWrapper::Create(42);
+      *wrapper_ = MakeGarbageCollected<IntWrapper>(42);
     for (int i = 0; i < 512; ++i)
       MakeGarbageCollected<OneKiloByteObject>();
     for (int i = 0; i < 32; ++i)
-      LargeHeapObject::Create();
+      MakeGarbageCollected<LargeHeapObject>();
   }
 
   void Trace(blink::Visitor* visitor) {}
@@ -1513,11 +1431,11 @@
 
   void Dispose() {
     for (int i = 0; i < 10; ++i)
-      *wrapper_ = IntWrapper::Create(42);
+      *wrapper_ = MakeGarbageCollected<IntWrapper>(42);
     for (int i = 0; i < 512; ++i)
       MakeGarbageCollected<OneKiloByteObject>();
     for (int i = 0; i < 32; ++i)
-      LargeHeapObject::Create();
+      MakeGarbageCollected<LargeHeapObject>();
   }
 
   void Trace(blink::Visitor* visitor) {}
@@ -1655,7 +1573,7 @@
   {
     RefCountedAndGarbageCollected::destructor_calls_ = 0;
     Persistent<RefCountedAndGarbageCollected> ref_counted =
-        RefCountedAndGarbageCollected::Create();
+        MakeGarbageCollected<RefCountedAndGarbageCollected>();
     PreciselyCollectGarbage();
     EXPECT_EQ(0, RefCountedAndGarbageCollected::destructor_calls_);
   }
@@ -1663,10 +1581,11 @@
   EXPECT_EQ(1, RefCountedAndGarbageCollected::destructor_calls_);
   RefCountedAndGarbageCollected::destructor_calls_ = 0;
 
-  Persistent<PointsBack> points_back1 = PointsBack::Create();
-  Persistent<PointsBack> points_back2 = PointsBack::Create();
-  Persistent<SuperClass> super_class = SuperClass::Create(points_back1);
-  Persistent<SubClass> sub_class = SubClass::Create(points_back2);
+  Persistent<PointsBack> points_back1 = MakeGarbageCollected<PointsBack>();
+  Persistent<PointsBack> points_back2 = MakeGarbageCollected<PointsBack>();
+  Persistent<SuperClass> super_class =
+      MakeGarbageCollected<SuperClass>(points_back1);
+  Persistent<SubClass> sub_class = MakeGarbageCollected<SubClass>(points_back2);
   EXPECT_EQ(2, PointsBack::alive_count_);
   EXPECT_EQ(2, SuperClass::alive_count_);
   EXPECT_EQ(1, SubClass::alive_count_);
@@ -1889,13 +1808,14 @@
 }
 
 TEST(HeapTest, SimplePersistent) {
-  Persistent<TraceCounter> trace_counter = TraceCounter::Create();
+  Persistent<TraceCounter> trace_counter = MakeGarbageCollected<TraceCounter>();
   EXPECT_EQ(0, trace_counter->TraceCount());
   PreciselyCollectGarbage();
   int saved_trace_count = trace_counter->TraceCount();
   EXPECT_LT(0, saved_trace_count);
 
-  Persistent<ClassWithMember> class_with_member = ClassWithMember::Create();
+  Persistent<ClassWithMember> class_with_member =
+      MakeGarbageCollected<ClassWithMember>();
   EXPECT_EQ(0, class_with_member->TraceCount());
   PreciselyCollectGarbage();
   EXPECT_LT(0, class_with_member->TraceCount());
@@ -1907,7 +1827,7 @@
   {
     SimpleFinalizedObject::destructor_calls_ = 0;
     Persistent<SimpleFinalizedObject> finalized =
-        SimpleFinalizedObject::Create();
+        MakeGarbageCollected<SimpleFinalizedObject>();
     EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
     PreciselyCollectGarbage();
     EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
@@ -1953,13 +1873,13 @@
   SimpleFinalizedObject::destructor_calls_ = 0;
   EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
   for (int i = 0; i < 1000; i++)
-    SimpleFinalizedObject::Create();
+    MakeGarbageCollected<SimpleFinalizedObject>();
   ThreadState::Current()->CollectGarbage(
       BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
       BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC);
   EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
   for (int i = 0; i < 10000; i++)
-    SimpleFinalizedObject::Create();
+    MakeGarbageCollected<SimpleFinalizedObject>();
   EXPECT_EQ(1000, SimpleFinalizedObject::destructor_calls_);
   PreciselyCollectGarbage();
   EXPECT_EQ(11000, SimpleFinalizedObject::destructor_calls_);
@@ -1969,7 +1889,7 @@
   ClearOutOldGarbage();
 
   // Create free lists that can be reused for IntWrappers created in
-  // LargeHeapObject::create().
+  // MakeGarbageCollected<LargeHeapObject>().
   Persistent<IntWrapper> p1 = MakeGarbageCollected<IntWrapper>(1);
   for (int i = 0; i < 100; i++) {
     MakeGarbageCollected<IntWrapper>(i);
@@ -1981,17 +1901,17 @@
   LargeHeapObject::destructor_calls_ = 0;
   EXPECT_EQ(0, LargeHeapObject::destructor_calls_);
   for (int i = 0; i < 10; i++)
-    LargeHeapObject::Create();
+    MakeGarbageCollected<LargeHeapObject>();
   ThreadState::Current()->CollectGarbage(
       BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
       BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC);
   EXPECT_EQ(0, LargeHeapObject::destructor_calls_);
   for (int i = 0; i < 10; i++) {
-    LargeHeapObject::Create();
+    MakeGarbageCollected<LargeHeapObject>();
     EXPECT_EQ(i + 1, LargeHeapObject::destructor_calls_);
   }
-  LargeHeapObject::Create();
-  LargeHeapObject::Create();
+  MakeGarbageCollected<LargeHeapObject>();
+  MakeGarbageCollected<LargeHeapObject>();
   EXPECT_EQ(10, LargeHeapObject::destructor_calls_);
   ThreadState::Current()->CollectGarbage(
       BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
@@ -2015,10 +1935,6 @@
 
 class SimpleFinalizedEagerObject : public SimpleFinalizedEagerObjectBase {
  public:
-  static SimpleFinalizedEagerObject* Create() {
-    return MakeGarbageCollected<SimpleFinalizedEagerObject>();
-  }
-
   SimpleFinalizedEagerObject() = default;
   ~SimpleFinalizedEagerObject() override { ++destructor_calls_; }
 
@@ -2035,10 +1951,6 @@
     : public GarbageCollectedFinalized<SimpleFinalizedObjectInstanceOfTemplate>,
       public ParameterizedButEmpty<SimpleFinalizedObjectInstanceOfTemplate> {
  public:
-  static SimpleFinalizedObjectInstanceOfTemplate* Create() {
-    return MakeGarbageCollected<SimpleFinalizedObjectInstanceOfTemplate>();
-  }
-
   SimpleFinalizedObjectInstanceOfTemplate() = default;
   ~SimpleFinalizedObjectInstanceOfTemplate() { ++destructor_calls_; }
 
@@ -2059,11 +1971,11 @@
   EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
   EXPECT_EQ(0, SimpleFinalizedEagerObject::destructor_calls_);
   for (int i = 0; i < 1000; i++)
-    SimpleFinalizedObject::Create();
+    MakeGarbageCollected<SimpleFinalizedObject>();
   for (int i = 0; i < 100; i++)
-    SimpleFinalizedEagerObject::Create();
+    MakeGarbageCollected<SimpleFinalizedEagerObject>();
   for (int i = 0; i < 100; i++)
-    SimpleFinalizedObjectInstanceOfTemplate::Create();
+    MakeGarbageCollected<SimpleFinalizedObjectInstanceOfTemplate>();
   ThreadState::Current()->CollectGarbage(
       BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
       BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC);
@@ -2076,9 +1988,9 @@
   {
     HeapTestSubClass::destructor_calls_ = 0;
     HeapTestSuperClass::destructor_calls_ = 0;
-    HeapTestSubClass* t1 = HeapTestSubClass::Create();
-    HeapTestSubClass* t2 = HeapTestSubClass::Create();
-    HeapTestSuperClass* t3 = HeapTestSuperClass::Create();
+    auto* t1 = MakeGarbageCollected<HeapTestSubClass>();
+    auto* t2 = MakeGarbageCollected<HeapTestSubClass>();
+    auto* t3 = MakeGarbageCollected<HeapTestSuperClass>();
     // FIXME(oilpan): Ignore unused variables.
     (void)t1;
     (void)t2;
@@ -2097,7 +2009,8 @@
 
 TEST(HeapTest, TypedArenaSanity) {
   // We use TraceCounter for allocating an object on the general heap.
-  Persistent<TraceCounter> general_heap_object = TraceCounter::Create();
+  Persistent<TraceCounter> general_heap_object =
+      MakeGarbageCollected<TraceCounter>();
   Persistent<IntNode> typed_heap_object = IntNode::Create(0);
   EXPECT_NE(PageFromObject(general_heap_object.Get()),
             PageFromObject(typed_heap_object.Get()));
@@ -2121,10 +2034,10 @@
     Persistent<Baz> h1;
     Persistent<Baz> h2;
     {
-      h1 = Baz::Create(Bar::Create());
+      h1 = MakeGarbageCollected<Baz>(MakeGarbageCollected<Bar>());
       PreciselyCollectGarbage();
       EXPECT_EQ(1u, Bar::live_);
-      h2 = Baz::Create(Bar::Create());
+      h2 = MakeGarbageCollected<Baz>(MakeGarbageCollected<Bar>());
       PreciselyCollectGarbage();
       EXPECT_EQ(2u, Bar::live_);
     }
@@ -2142,13 +2055,13 @@
   ClearOutOldGarbage();
   {
     Bar::live_ = 0;
-    Persistent<Bar> bar = Bar::Create();
+    Persistent<Bar> bar = MakeGarbageCollected<Bar>();
 #if DCHECK_IS_ON()
     DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(bar));
 #endif
     EXPECT_EQ(1u, Bar::live_);
     {
-      Foo* foo = Foo::Create(bar);
+      auto* foo = MakeGarbageCollected<Foo>(bar);
 #if DCHECK_IS_ON()
       DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(foo));
 #endif
@@ -2171,17 +2084,17 @@
   const unsigned kDepth = 100000;
   Bar::live_ = 0;
   {
-    Bar* bar = Bar::Create();
+    auto* bar = MakeGarbageCollected<Bar>();
 #if DCHECK_IS_ON()
     DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(bar));
 #endif
-    Foo* foo = Foo::Create(bar);
+    auto* foo = MakeGarbageCollected<Foo>(bar);
 #if DCHECK_IS_ON()
     DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(foo));
 #endif
     EXPECT_EQ(2u, Bar::live_);
     for (unsigned i = 0; i < kDepth; i++) {
-      Foo* foo2 = Foo::Create(foo);
+      auto* foo2 = MakeGarbageCollected<Foo>(foo);
       foo = foo2;
 #if DCHECK_IS_ON()
       DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(foo));
@@ -2200,7 +2113,7 @@
   ClearOutOldGarbage();
   Bar::live_ = 0;
   {
-    Bars* bars = Bars::Create();
+    auto* bars = MakeGarbageCollected<Bars>();
     unsigned width = Bars::kWidth;
     EXPECT_EQ(width + 1, Bar::live_);
     ConservativelyCollectGarbage();
@@ -2239,8 +2152,8 @@
 
     // If the additions below cause garbage collections, these
     // pointers should be found by conservative stack scanning.
-    IntWrapper* one(IntWrapper::Create(1));
-    IntWrapper* another_one(IntWrapper::Create(1));
+    auto* one(MakeGarbageCollected<IntWrapper>(1));
+    auto* another_one(MakeGarbageCollected<IntWrapper>(1));
 
     map->insert(one, one);
 
@@ -2280,8 +2193,8 @@
     IntWrapper* dozen = nullptr;
 
     for (int i = 1; i < 1000; i++) {  // 999 iterations.
-      IntWrapper* i_wrapper(IntWrapper::Create(i));
-      IntWrapper* i_squared(IntWrapper::Create(i * i));
+      auto* i_wrapper(MakeGarbageCollected<IntWrapper>(i));
+      auto* i_squared(MakeGarbageCollected<IntWrapper>(i * i));
       map->insert(i_wrapper, i_squared);
       if (i == 12)
         dozen = i_wrapper;
@@ -2311,7 +2224,7 @@
   size_t initial_object_payload_size = heap.ObjectPayloadSizeForTesting();
   {
     Persistent<ConstructorAllocation> constructor_allocation =
-        ConstructorAllocation::Create();
+        MakeGarbageCollected<ConstructorAllocation>();
   }
   ClearOutOldGarbage();
   size_t after_free = heap.ObjectPayloadSizeForTesting();
@@ -2329,7 +2242,8 @@
   {
     int slack =
         8;  // LargeHeapObject points to an IntWrapper that is also allocated.
-    Persistent<LargeHeapObject> object = LargeHeapObject::Create();
+    Persistent<LargeHeapObject> object =
+        MakeGarbageCollected<LargeHeapObject>();
 #if DCHECK_IS_ON()
     DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(object));
     DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(
@@ -2365,7 +2279,7 @@
       EXPECT_EQ(0, IntWrapper::destructor_calls_);
       EXPECT_EQ(0, LargeHeapObject::destructor_calls_);
       for (int i = 0; i < 10; i++)
-        object = LargeHeapObject::Create();
+        object = MakeGarbageCollected<LargeHeapObject>();
     }
     ClearOutOldGarbage();
     EXPECT_EQ(after_allocation,
@@ -2424,7 +2338,6 @@
 
 class Container : public GarbageCollected<Container> {
  public:
-  static Container* Create() { return MakeGarbageCollected<Container>(); }
   HeapHashMap<Member<IntWrapper>, Member<IntWrapper>> map;
   HeapHashSet<Member<IntWrapper>> set;
   HeapHashSet<Member<IntWrapper>> set2;
@@ -2456,7 +2369,7 @@
 };
 
 TEST(HeapTest, HeapVectorFilledWithValue) {
-  IntWrapper* val = IntWrapper::Create(1);
+  auto* val = MakeGarbageCollected<IntWrapper>(1);
   HeapVector<Member<IntWrapper>> vector(10, val);
   EXPECT_EQ(10u, vector.size());
   for (wtf_size_t i = 0; i < vector.size(); i++)
@@ -2464,12 +2377,12 @@
 }
 
 TEST(HeapTest, HeapVectorWithInlineCapacity) {
-  IntWrapper* one = IntWrapper::Create(1);
-  IntWrapper* two = IntWrapper::Create(2);
-  IntWrapper* three = IntWrapper::Create(3);
-  IntWrapper* four = IntWrapper::Create(4);
-  IntWrapper* five = IntWrapper::Create(5);
-  IntWrapper* six = IntWrapper::Create(6);
+  auto* one = MakeGarbageCollected<IntWrapper>(1);
+  auto* two = MakeGarbageCollected<IntWrapper>(2);
+  auto* three = MakeGarbageCollected<IntWrapper>(3);
+  auto* four = MakeGarbageCollected<IntWrapper>(4);
+  auto* five = MakeGarbageCollected<IntWrapper>(5);
+  auto* six = MakeGarbageCollected<IntWrapper>(6);
   {
     HeapVector<Member<IntWrapper>, 2> vector;
     vector.push_back(one);
@@ -2592,7 +2505,7 @@
       sizeof(Container::ValueType);
   vector.ReserveCapacity(size);
   for (unsigned i = 0; i < size; ++i)
-    vector.push_back(IntWrapper::Create(i));
+    vector.push_back(MakeGarbageCollected<IntWrapper>(i));
   ConservativelyCollectGarbage();
 }
 
@@ -2648,35 +2561,35 @@
   Persistent<DequeWU> deque_wu2 = MakeGarbageCollected<DequeWU>();
   Persistent<DequeUW> deque_uw = MakeGarbageCollected<DequeUW>();
   Persistent<DequeUW> deque_uw2 = MakeGarbageCollected<DequeUW>();
-  Persistent<Container> container = Container::Create();
+  Persistent<Container> container = MakeGarbageCollected<Container>();
 
   ClearOutOldGarbage();
   {
-    Persistent<IntWrapper> one(IntWrapper::Create(1));
-    Persistent<IntWrapper> two(IntWrapper::Create(2));
-    Persistent<IntWrapper> one_b(IntWrapper::Create(1));
-    Persistent<IntWrapper> two_b(IntWrapper::Create(2));
-    Persistent<IntWrapper> one_c(IntWrapper::Create(1));
-    Persistent<IntWrapper> one_d(IntWrapper::Create(1));
-    Persistent<IntWrapper> one_e(IntWrapper::Create(1));
-    Persistent<IntWrapper> one_f(IntWrapper::Create(1));
+    Persistent<IntWrapper> one(MakeGarbageCollected<IntWrapper>(1));
+    Persistent<IntWrapper> two(MakeGarbageCollected<IntWrapper>(2));
+    Persistent<IntWrapper> one_b(MakeGarbageCollected<IntWrapper>(1));
+    Persistent<IntWrapper> two_b(MakeGarbageCollected<IntWrapper>(2));
+    Persistent<IntWrapper> one_c(MakeGarbageCollected<IntWrapper>(1));
+    Persistent<IntWrapper> one_d(MakeGarbageCollected<IntWrapper>(1));
+    Persistent<IntWrapper> one_e(MakeGarbageCollected<IntWrapper>(1));
+    Persistent<IntWrapper> one_f(MakeGarbageCollected<IntWrapper>(1));
     {
-      IntWrapper* three_b(IntWrapper::Create(3));
-      IntWrapper* three_c(IntWrapper::Create(3));
-      IntWrapper* three_d(IntWrapper::Create(3));
-      IntWrapper* three_e(IntWrapper::Create(3));
-      IntWrapper* three_f(IntWrapper::Create(3));
-      IntWrapper* three(IntWrapper::Create(3));
-      IntWrapper* four_b(IntWrapper::Create(4));
-      IntWrapper* four_c(IntWrapper::Create(4));
-      IntWrapper* four_d(IntWrapper::Create(4));
-      IntWrapper* four_e(IntWrapper::Create(4));
-      IntWrapper* four_f(IntWrapper::Create(4));
-      IntWrapper* four(IntWrapper::Create(4));
-      IntWrapper* five_c(IntWrapper::Create(5));
-      IntWrapper* five_d(IntWrapper::Create(5));
-      IntWrapper* five_e(IntWrapper::Create(5));
-      IntWrapper* five_f(IntWrapper::Create(5));
+      auto* three_b(MakeGarbageCollected<IntWrapper>(3));
+      auto* three_c(MakeGarbageCollected<IntWrapper>(3));
+      auto* three_d(MakeGarbageCollected<IntWrapper>(3));
+      auto* three_e(MakeGarbageCollected<IntWrapper>(3));
+      auto* three_f(MakeGarbageCollected<IntWrapper>(3));
+      auto* three(MakeGarbageCollected<IntWrapper>(3));
+      auto* four_b(MakeGarbageCollected<IntWrapper>(4));
+      auto* four_c(MakeGarbageCollected<IntWrapper>(4));
+      auto* four_d(MakeGarbageCollected<IntWrapper>(4));
+      auto* four_e(MakeGarbageCollected<IntWrapper>(4));
+      auto* four_f(MakeGarbageCollected<IntWrapper>(4));
+      auto* four(MakeGarbageCollected<IntWrapper>(4));
+      auto* five_c(MakeGarbageCollected<IntWrapper>(5));
+      auto* five_d(MakeGarbageCollected<IntWrapper>(5));
+      auto* five_e(MakeGarbageCollected<IntWrapper>(5));
+      auto* five_f(MakeGarbageCollected<IntWrapper>(5));
 
       // Member Collections.
       member_member2->insert(one, two);
@@ -2914,12 +2827,12 @@
 
   typedef Vector<Persistent<IntWrapper>> PersistentVector;
 
-  Persistent<IntWrapper> one(IntWrapper::Create(1));
-  Persistent<IntWrapper> two(IntWrapper::Create(2));
-  Persistent<IntWrapper> three(IntWrapper::Create(3));
-  Persistent<IntWrapper> four(IntWrapper::Create(4));
-  Persistent<IntWrapper> five(IntWrapper::Create(5));
-  Persistent<IntWrapper> six(IntWrapper::Create(6));
+  Persistent<IntWrapper> one(MakeGarbageCollected<IntWrapper>(1));
+  Persistent<IntWrapper> two(MakeGarbageCollected<IntWrapper>(2));
+  Persistent<IntWrapper> three(MakeGarbageCollected<IntWrapper>(3));
+  Persistent<IntWrapper> four(MakeGarbageCollected<IntWrapper>(4));
+  Persistent<IntWrapper> five(MakeGarbageCollected<IntWrapper>(5));
+  Persistent<IntWrapper> six(MakeGarbageCollected<IntWrapper>(6));
   {
     PersistentVector vector;
     vector.push_back(one);
@@ -2980,12 +2893,12 @@
 
   typedef Vector<CrossThreadPersistent<IntWrapper>> CrossThreadPersistentVector;
 
-  CrossThreadPersistent<IntWrapper> one(IntWrapper::Create(1));
-  CrossThreadPersistent<IntWrapper> two(IntWrapper::Create(2));
-  CrossThreadPersistent<IntWrapper> three(IntWrapper::Create(3));
-  CrossThreadPersistent<IntWrapper> four(IntWrapper::Create(4));
-  CrossThreadPersistent<IntWrapper> five(IntWrapper::Create(5));
-  CrossThreadPersistent<IntWrapper> six(IntWrapper::Create(6));
+  CrossThreadPersistent<IntWrapper> one(MakeGarbageCollected<IntWrapper>(1));
+  CrossThreadPersistent<IntWrapper> two(MakeGarbageCollected<IntWrapper>(2));
+  CrossThreadPersistent<IntWrapper> three(MakeGarbageCollected<IntWrapper>(3));
+  CrossThreadPersistent<IntWrapper> four(MakeGarbageCollected<IntWrapper>(4));
+  CrossThreadPersistent<IntWrapper> five(MakeGarbageCollected<IntWrapper>(5));
+  CrossThreadPersistent<IntWrapper> six(MakeGarbageCollected<IntWrapper>(6));
   {
     CrossThreadPersistentVector vector;
     vector.push_back(one);
@@ -3046,14 +2959,14 @@
 
   typedef HashSet<Persistent<IntWrapper>> PersistentSet;
 
-  IntWrapper* one_raw = IntWrapper::Create(1);
+  auto* one_raw = MakeGarbageCollected<IntWrapper>(1);
   Persistent<IntWrapper> one(one_raw);
   Persistent<IntWrapper> one2(one_raw);
-  Persistent<IntWrapper> two(IntWrapper::Create(2));
-  Persistent<IntWrapper> three(IntWrapper::Create(3));
-  Persistent<IntWrapper> four(IntWrapper::Create(4));
-  Persistent<IntWrapper> five(IntWrapper::Create(5));
-  Persistent<IntWrapper> six(IntWrapper::Create(6));
+  Persistent<IntWrapper> two(MakeGarbageCollected<IntWrapper>(2));
+  Persistent<IntWrapper> three(MakeGarbageCollected<IntWrapper>(3));
+  Persistent<IntWrapper> four(MakeGarbageCollected<IntWrapper>(4));
+  Persistent<IntWrapper> five(MakeGarbageCollected<IntWrapper>(5));
+  Persistent<IntWrapper> six(MakeGarbageCollected<IntWrapper>(6));
   {
     PersistentSet set;
     set.insert(one);
@@ -3097,14 +3010,14 @@
 
   typedef HashSet<CrossThreadPersistent<IntWrapper>> CrossThreadPersistentSet;
 
-  IntWrapper* one_raw = IntWrapper::Create(1);
+  auto* one_raw = MakeGarbageCollected<IntWrapper>(1);
   CrossThreadPersistent<IntWrapper> one(one_raw);
   CrossThreadPersistent<IntWrapper> one2(one_raw);
-  CrossThreadPersistent<IntWrapper> two(IntWrapper::Create(2));
-  CrossThreadPersistent<IntWrapper> three(IntWrapper::Create(3));
-  CrossThreadPersistent<IntWrapper> four(IntWrapper::Create(4));
-  CrossThreadPersistent<IntWrapper> five(IntWrapper::Create(5));
-  CrossThreadPersistent<IntWrapper> six(IntWrapper::Create(6));
+  CrossThreadPersistent<IntWrapper> two(MakeGarbageCollected<IntWrapper>(2));
+  CrossThreadPersistent<IntWrapper> three(MakeGarbageCollected<IntWrapper>(3));
+  CrossThreadPersistent<IntWrapper> four(MakeGarbageCollected<IntWrapper>(4));
+  CrossThreadPersistent<IntWrapper> five(MakeGarbageCollected<IntWrapper>(5));
+  CrossThreadPersistent<IntWrapper> six(MakeGarbageCollected<IntWrapper>(6));
   {
     CrossThreadPersistentSet set;
     set.insert(one);
@@ -3149,8 +3062,8 @@
  public:
   NonTrivialObject() = default;
   explicit NonTrivialObject(int num) {
-    deque_.push_back(IntWrapper::Create(num));
-    vector_.push_back(IntWrapper::Create(num));
+    deque_.push_back(MakeGarbageCollected<IntWrapper>(num));
+    vector_.push_back(MakeGarbageCollected<IntWrapper>(num));
   }
   void Trace(blink::Visitor* visitor) {
     visitor->Trace(deque_);
@@ -3215,21 +3128,21 @@
   Persistent<WeakSet> weak_set = MakeGarbageCollected<WeakSet>();
   Persistent<WeakCountedSet> weak_counted_set = new WeakCountedSet();
 
-  Persistent<IntWrapper> two = IntWrapper::Create(2);
+  Persistent<IntWrapper> two = MakeGarbageCollected<IntWrapper>(2);
 
-  keep_numbers_alive->push_back(IntWrapper::Create(103));
-  keep_numbers_alive->push_back(IntWrapper::Create(10));
+  keep_numbers_alive->push_back(MakeGarbageCollected<IntWrapper>(103));
+  keep_numbers_alive->push_back(MakeGarbageCollected<IntWrapper>(10));
 
   {
-    weak_strong->insert(IntWrapper::Create(1), two);
-    strong_weak->insert(two, IntWrapper::Create(1));
-    weak_weak->insert(two, IntWrapper::Create(42));
-    weak_weak->insert(IntWrapper::Create(42), two);
-    weak_set->insert(IntWrapper::Create(0));
+    weak_strong->insert(MakeGarbageCollected<IntWrapper>(1), two);
+    strong_weak->insert(two, MakeGarbageCollected<IntWrapper>(1));
+    weak_weak->insert(two, MakeGarbageCollected<IntWrapper>(42));
+    weak_weak->insert(MakeGarbageCollected<IntWrapper>(42), two);
+    weak_set->insert(MakeGarbageCollected<IntWrapper>(0));
     weak_set->insert(two);
     weak_set->insert(keep_numbers_alive->at(0));
     weak_set->insert(keep_numbers_alive->at(1));
-    weak_counted_set->insert(IntWrapper::Create(0));
+    weak_counted_set->insert(MakeGarbageCollected<IntWrapper>(0));
     weak_counted_set->insert(two);
     weak_counted_set->insert(two);
     weak_counted_set->insert(two);
@@ -3269,17 +3182,17 @@
 
   const Set& const_set = *set1.Get();
 
-  keep_numbers_alive->push_back(IntWrapper::Create(2));
-  keep_numbers_alive->push_back(IntWrapper::Create(103));
-  keep_numbers_alive->push_back(IntWrapper::Create(10));
+  keep_numbers_alive->push_back(MakeGarbageCollected<IntWrapper>(2));
+  keep_numbers_alive->push_back(MakeGarbageCollected<IntWrapper>(103));
+  keep_numbers_alive->push_back(MakeGarbageCollected<IntWrapper>(10));
 
-  set1->insert(IntWrapper::Create(0));
+  set1->insert(MakeGarbageCollected<IntWrapper>(0));
   set1->insert(keep_numbers_alive->at(0));
   set1->insert(keep_numbers_alive->at(1));
   set1->insert(keep_numbers_alive->at(2));
 
   set2->clear();
-  set2->insert(IntWrapper::Create(42));
+  set2->insert(MakeGarbageCollected<IntWrapper>(42));
   set2->clear();
 
   EXPECT_EQ(4u, set1->size());
@@ -3417,7 +3330,7 @@
   Persistent<Map> map(MakeGarbageCollected<Map>());
   Persistent<RefMap> ref_map(MakeGarbageCollected<RefMap>());
 
-  Persistent<IntWrapper> luck(IntWrapper::Create(103));
+  Persistent<IntWrapper> luck(MakeGarbageCollected<IntWrapper>(103));
 
   int base_line, ref_base_line;
 
@@ -3428,11 +3341,13 @@
     PreciselyCollectGarbage();
     PreciselyCollectGarbage();
 
-    stack_map.insert(IntWrapper::Create(42), ThingWithDestructor(1729));
+    stack_map.insert(MakeGarbageCollected<IntWrapper>(42),
+                     ThingWithDestructor(1729));
     stack_map.insert(luck, ThingWithDestructor(8128));
-    stack_ref_map.insert(IntWrapper::Create(42),
-                         RefCountedAndGarbageCollected::Create());
-    stack_ref_map.insert(luck, RefCountedAndGarbageCollected::Create());
+    stack_ref_map.insert(MakeGarbageCollected<IntWrapper>(42),
+                         MakeGarbageCollected<RefCountedAndGarbageCollected>());
+    stack_ref_map.insert(luck,
+                         MakeGarbageCollected<RefCountedAndGarbageCollected>());
 
     base_line = ThingWithDestructor::live_things_with_destructor_;
     ref_base_line = RefCountedAndGarbageCollected::destructor_calls_;
@@ -3453,11 +3368,11 @@
   // Now use maps kept alive with persistents. Here we don't expect any
   // destructors to be called before there have been GCs.
 
-  map->insert(IntWrapper::Create(42), ThingWithDestructor(1729));
+  map->insert(MakeGarbageCollected<IntWrapper>(42), ThingWithDestructor(1729));
   map->insert(luck, ThingWithDestructor(8128));
-  ref_map->insert(IntWrapper::Create(42),
-                  RefCountedAndGarbageCollected::Create());
-  ref_map->insert(luck, RefCountedAndGarbageCollected::Create());
+  ref_map->insert(MakeGarbageCollected<IntWrapper>(42),
+                  MakeGarbageCollected<RefCountedAndGarbageCollected>());
+  ref_map->insert(luck, MakeGarbageCollected<RefCountedAndGarbageCollected>());
 
   base_line = ThingWithDestructor::live_things_with_destructor_;
   ref_base_line = RefCountedAndGarbageCollected::destructor_calls_;
@@ -3579,15 +3494,19 @@
   Persistent<WUSet> weak_unwrapped = MakeGarbageCollected<WUSet>();
   Persistent<UWSet> unwrapped_weak = MakeGarbageCollected<UWSet>();
 
-  Persistent<IntWrapper> two = IntWrapper::Create(2);
+  Persistent<IntWrapper> two = MakeGarbageCollected<IntWrapper>(2);
 
-  weak_strong->insert(PairWeakStrong(IntWrapper::Create(1), &*two));
+  weak_strong->insert(
+      PairWeakStrong(MakeGarbageCollected<IntWrapper>(1), &*two));
   weak_strong->insert(PairWeakStrong(&*two, &*two));
-  strong_weak->insert(PairStrongWeak(&*two, IntWrapper::Create(1)));
+  strong_weak->insert(
+      PairStrongWeak(&*two, MakeGarbageCollected<IntWrapper>(1)));
   strong_weak->insert(PairStrongWeak(&*two, &*two));
-  weak_unwrapped->insert(PairWeakUnwrapped(IntWrapper::Create(1), 2));
+  weak_unwrapped->insert(
+      PairWeakUnwrapped(MakeGarbageCollected<IntWrapper>(1), 2));
   weak_unwrapped->insert(PairWeakUnwrapped(&*two, 2));
-  unwrapped_weak->insert(PairUnwrappedWeak(2, IntWrapper::Create(1)));
+  unwrapped_weak->insert(
+      PairUnwrappedWeak(2, MakeGarbageCollected<IntWrapper>(1)));
   unwrapped_weak->insert(PairUnwrappedWeak(2, &*two));
 
   CheckPairSets<WSSet, SWSet, WUSet, UWSet>(
@@ -3671,8 +3590,8 @@
       Persistent<HeapVector<Member<IntWrapper>>> keep_numbers_alive =
           MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
       for (int i = 0; i < 128; i += 2) {
-        IntWrapper* wrapped = IntWrapper::Create(i);
-        IntWrapper* wrapped2 = IntWrapper::Create(i + 1);
+        auto* wrapped = MakeGarbageCollected<IntWrapper>(i);
+        auto* wrapped2 = MakeGarbageCollected<IntWrapper>(i + 1);
         keep_numbers_alive->push_back(wrapped);
         keep_numbers_alive->push_back(wrapped2);
         weak_strong->insert(wrapped, wrapped2);
@@ -3796,7 +3715,7 @@
         }
         if (add_afterwards) {
           for (int i = 1000; i < 1100; i++) {
-            IntWrapper* wrapped = IntWrapper::Create(i);
+            auto* wrapped = MakeGarbageCollected<IntWrapper>(i);
             keep_numbers_alive->push_back(wrapped);
             weak_strong->insert(wrapped, wrapped);
             strong_weak->insert(wrapped, wrapped);
@@ -3889,9 +3808,9 @@
       Persistent<RefCountedAndGarbageCollected> persistent;
       {
         Persistent<RefCountedAndGarbageCollected> ref_ptr1 =
-            RefCountedAndGarbageCollected::Create();
+            MakeGarbageCollected<RefCountedAndGarbageCollected>();
         Persistent<RefCountedAndGarbageCollected> ref_ptr2 =
-            RefCountedAndGarbageCollected::Create();
+            MakeGarbageCollected<RefCountedAndGarbageCollected>();
         PreciselyCollectGarbage();
         EXPECT_EQ(0, RefCountedAndGarbageCollected::destructor_calls_);
         persistent = ref_ptr1.Get();
@@ -3917,16 +3836,16 @@
   ClearOutOldGarbage();
   Bar::live_ = 0;
   {
-    Persistent<Bar> h1 = Bar::Create();
+    Persistent<Bar> h1 = MakeGarbageCollected<Bar>();
     Persistent<Weak> h4;
     Persistent<WithWeakMember> h5;
     PreciselyCollectGarbage();
     ASSERT_EQ(1u, Bar::live_);  // h1 is live.
     {
-      Bar* h2 = Bar::Create();
-      Bar* h3 = Bar::Create();
-      h4 = Weak::Create(h2, h3);
-      h5 = WithWeakMember::Create(h2, h3);
+      auto* h2 = MakeGarbageCollected<Bar>();
+      auto* h3 = MakeGarbageCollected<Bar>();
+      h4 = MakeGarbageCollected<Weak>(h2, h3);
+      h5 = MakeGarbageCollected<WithWeakMember>(h2, h3);
       ConservativelyCollectGarbage();
       EXPECT_EQ(5u, Bar::live_);  // The on-stack pointer keeps h3 alive.
       EXPECT_FALSE(h3->HasBeenFinalized());
@@ -3956,9 +3875,9 @@
 TEST(HeapTest, FinalizationObserver) {
   Persistent<FinalizationObserver<Observable>> o;
   {
-    Observable* foo = Observable::Create(Bar::Create());
+    auto* foo = MakeGarbageCollected<Observable>(MakeGarbageCollected<Bar>());
     // |o| observes |foo|.
-    o = FinalizationObserver<Observable>::Create(foo);
+    o = MakeGarbageCollected<FinalizationObserver<Observable>>(foo);
   }
   // FinalizationObserver doesn't have a strong reference to |foo|. So |foo|
   // and its member will be collected.
@@ -3967,7 +3886,7 @@
   EXPECT_TRUE(o->DidCallWillFinalize());
 
   FinalizationObserverWithHashMap::did_call_will_finalize_ = false;
-  Observable* foo = Observable::Create(Bar::Create());
+  auto* foo = MakeGarbageCollected<Observable>(MakeGarbageCollected<Bar>());
   FinalizationObserverWithHashMap::ObserverMap& map =
       FinalizationObserverWithHashMap::Observe(*foo);
   EXPECT_EQ(1u, map.size());
@@ -3984,14 +3903,14 @@
 
 TEST(HeapTest, PreFinalizer) {
   Observable::will_finalize_was_called_ = false;
-  { Observable::Create(Bar::Create()); }
+  { MakeGarbageCollected<Observable>(MakeGarbageCollected<Bar>()); }
   PreciselyCollectGarbage();
   EXPECT_TRUE(Observable::will_finalize_was_called_);
 }
 
 TEST(HeapTest, PreFinalizerUnregistersItself) {
   ObservableWithPreFinalizer::dispose_was_called_ = false;
-  ObservableWithPreFinalizer::Create();
+  MakeGarbageCollected<ObservableWithPreFinalizer>();
   PreciselyCollectGarbage();
   EXPECT_TRUE(ObservableWithPreFinalizer::dispose_was_called_);
   // Don't crash, and assertions don't fail.
@@ -4001,7 +3920,7 @@
   g_dispose_was_called_for_pre_finalizer_base = false;
   g_dispose_was_called_for_pre_finalizer_sub_class = false;
   g_dispose_was_called_for_pre_finalizer_mixin = false;
-  PreFinalizerSubClass::Create();
+  MakeGarbageCollected<PreFinalizerSubClass>();
   PreciselyCollectGarbage();
   EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_base);
   EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_sub_class);
@@ -4010,8 +3929,8 @@
 }
 
 TEST(HeapTest, Comparisons) {
-  Persistent<Bar> bar_persistent = Bar::Create();
-  Persistent<Foo> foo_persistent = Foo::Create(bar_persistent);
+  Persistent<Bar> bar_persistent = MakeGarbageCollected<Bar>();
+  Persistent<Foo> foo_persistent = MakeGarbageCollected<Foo>(bar_persistent);
   EXPECT_TRUE(bar_persistent != foo_persistent);
   bar_persistent = foo_persistent;
   EXPECT_TRUE(bar_persistent == foo_persistent);
@@ -4041,13 +3960,13 @@
   Vector<Address> object_addresses;
   Vector<Address> end_addresses;
   for (int i = 0; i < 10; i++) {
-    SimpleObject* object = SimpleObject::Create();
+    auto* object = MakeGarbageCollected<SimpleObject>();
     Address object_address = reinterpret_cast<Address>(object);
     object_addresses.push_back(object_address);
     end_addresses.push_back(object_address + sizeof(SimpleObject) - 1);
   }
   Address large_object_address =
-      reinterpret_cast<Address>(LargeHeapObject::Create());
+      reinterpret_cast<Address>(MakeGarbageCollected<LargeHeapObject>());
   Address large_object_end_address =
       large_object_address + sizeof(LargeHeapObject) - 1;
 
@@ -4136,10 +4055,10 @@
   HeapHashMap<void*, IntDeque>::iterator it2 = map2->find(key);
   EXPECT_EQ(0u, map2->at(key).size());
 
-  it->value.push_back(IntWrapper::Create(42));
+  it->value.push_back(MakeGarbageCollected<IntWrapper>(42));
   EXPECT_EQ(1u, map->at(key).size());
 
-  it2->value.push_back(IntWrapper::Create(42));
+  it2->value.push_back(MakeGarbageCollected<IntWrapper>(42));
   EXPECT_EQ(1u, map2->at(key).size());
 
   Persistent<HeapHashMap<void*, IntVector>> keep_alive(map);
@@ -4164,7 +4083,7 @@
 TEST(HeapTest, GarbageCollectedMixin) {
   ClearOutOldGarbage();
 
-  Persistent<UseMixin> usemixin = UseMixin::Create();
+  Persistent<UseMixin> usemixin = MakeGarbageCollected<UseMixin>();
   EXPECT_EQ(0, UseMixin::trace_count_);
   PreciselyCollectGarbage();
   EXPECT_EQ(1, UseMixin::trace_count_);
@@ -4176,7 +4095,7 @@
 
   Persistent<HeapHashSet<WeakMember<Mixin>>> weak_map =
       MakeGarbageCollected<HeapHashSet<WeakMember<Mixin>>>();
-  weak_map->insert(UseMixin::Create());
+  weak_map->insert(MakeGarbageCollected<UseMixin>());
   PreciselyCollectGarbage();
   EXPECT_EQ(0u, weak_map->size());
 }
@@ -4194,7 +4113,7 @@
   HeapHashMap<void*, IntSet>::iterator it = map->find(key);
   EXPECT_EQ(0u, map->at(key).size());
 
-  it->value.insert(IntWrapper::Create(42));
+  it->value.insert(MakeGarbageCollected<IntWrapper>(42));
   EXPECT_EQ(1u, map->at(key).size());
 
   Persistent<HeapHashMap<void*, IntSet>> keep_alive(map);
@@ -4219,8 +4138,8 @@
   EXPECT_EQ(0u, it->size());
   EXPECT_EQ(0u, it2->size());
 
-  it->push_back(IntWrapper::Create(42));
-  it2->push_back(IntWrapper::Create(42));
+  it->push_back(MakeGarbageCollected<IntWrapper>(42));
+  it2->push_back(MakeGarbageCollected<IntWrapper>(42));
   EXPECT_EQ(1u, it->size());
   EXPECT_EQ(1u, it2->size());
 
@@ -4489,7 +4408,7 @@
   const wtf_size_t kStackSize = 10;
 
   for (wtf_size_t i = 0; i < kStackSize; i++)
-    stack->Push(TerminatedArrayItem(IntWrapper::Create(i)));
+    stack->Push(TerminatedArrayItem(MakeGarbageCollected<IntWrapper>(i)));
 
   ConservativelyCollectGarbage();
   EXPECT_EQ(0, IntWrapper::destructor_calls_);
@@ -4627,7 +4546,8 @@
   HeapHashMap<Member<IntWrapper>, std::unique_ptr<SimpleClassWithDestructor>>
       map;
   SimpleClassWithDestructor* has_destructor = new SimpleClassWithDestructor();
-  map.insert(IntWrapper::Create(1), base::WrapUnique(has_destructor));
+  map.insert(MakeGarbageCollected<IntWrapper>(1),
+             base::WrapUnique(has_destructor));
   SimpleClassWithDestructor::was_destructed_ = false;
   map.clear();
   EXPECT_TRUE(SimpleClassWithDestructor::was_destructed_);
@@ -4635,7 +4555,7 @@
 
 class MixinA : public GarbageCollectedMixin {
  public:
-  MixinA() : obj_(IntWrapper::Create(100)) {}
+  MixinA() : obj_(MakeGarbageCollected<IntWrapper>(100)) {}
   void Trace(blink::Visitor* visitor) override {
     trace_count_++;
     visitor->Trace(obj_);
@@ -4650,7 +4570,7 @@
 
 class MixinB : public GarbageCollectedMixin {
  public:
-  MixinB() : obj_(IntWrapper::Create(101)) {}
+  MixinB() : obj_(MakeGarbageCollected<IntWrapper>(101)) {}
   void Trace(blink::Visitor* visitor) override { visitor->Trace(obj_); }
   Member<IntWrapper> obj_;
 };
@@ -4661,7 +4581,7 @@
   USING_GARBAGE_COLLECTED_MIXIN(MultipleMixins);
 
  public:
-  MultipleMixins() : obj_(IntWrapper::Create(102)) {}
+  MultipleMixins() : obj_(MakeGarbageCollected<IntWrapper>(102)) {}
   void Trace(blink::Visitor* visitor) override {
     visitor->Trace(obj_);
     MixinA::Trace(visitor);
@@ -4672,7 +4592,7 @@
 
 class DerivedMultipleMixins : public MultipleMixins {
  public:
-  DerivedMultipleMixins() : obj_(IntWrapper::Create(103)) {}
+  DerivedMultipleMixins() : obj_(MakeGarbageCollected<IntWrapper>(103)) {}
 
   void Trace(blink::Visitor* visitor) override {
     trace_called_++;
@@ -4792,17 +4712,17 @@
 template <typename Set>
 void SetWithCustomWeaknessHandling() {
   typedef typename Set::iterator Iterator;
-  Persistent<IntWrapper> living_int(IntWrapper::Create(42));
+  Persistent<IntWrapper> living_int(MakeGarbageCollected<IntWrapper>(42));
   Persistent<Set> set1(MakeGarbageCollected<Set>());
   {
     Set set2;
     Set* set3 = MakeGarbageCollected<Set>();
-    set2.insert(
-        PairWithWeakHandling(IntWrapper::Create(0), IntWrapper::Create(1)));
-    set3->insert(
-        PairWithWeakHandling(IntWrapper::Create(2), IntWrapper::Create(3)));
-    set1->insert(
-        PairWithWeakHandling(IntWrapper::Create(4), IntWrapper::Create(5)));
+    set2.insert(PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(0),
+                                     MakeGarbageCollected<IntWrapper>(1)));
+    set3->insert(PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(2),
+                                      MakeGarbageCollected<IntWrapper>(3)));
+    set1->insert(PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(4),
+                                      MakeGarbageCollected<IntWrapper>(5)));
     ConservativelyCollectGarbage();
     // The first set is pointed to from a persistent, so it's referenced, but
     // the weak processing may have taken place.
@@ -4826,12 +4746,14 @@
   }
   PreciselyCollectGarbage();
   EXPECT_EQ(0u, set1->size());
-  set1->insert(PairWithWeakHandling(IntWrapper::Create(103), living_int));
+  set1->insert(
+      PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(103), living_int));
   // This one gets zapped at GC time because nothing holds the 103 alive.
-  set1->insert(PairWithWeakHandling(living_int, IntWrapper::Create(103)));
+  set1->insert(
+      PairWithWeakHandling(living_int, MakeGarbageCollected<IntWrapper>(103)));
   set1->insert(PairWithWeakHandling(
-      IntWrapper::Create(103),
-      IntWrapper::Create(103)));  // This one gets zapped too.
+      MakeGarbageCollected<IntWrapper>(103),
+      MakeGarbageCollected<IntWrapper>(103)));  // This one gets zapped too.
   set1->insert(PairWithWeakHandling(living_int, living_int));
   // This one is identical to the previous and doesn't add anything.
   set1->insert(PairWithWeakHandling(living_int, living_int));
@@ -4858,19 +4780,19 @@
   OffHeapInt::destructor_calls_ = 0;
 
   Persistent<Map> map1(MakeGarbageCollected<Map>());
-  Persistent<IntWrapper> living_int(IntWrapper::Create(42));
+  Persistent<IntWrapper> living_int(MakeGarbageCollected<IntWrapper>(42));
   {
     Map map2;
     Map* map3 = MakeGarbageCollected<Map>();
-    map2.insert(
-        PairWithWeakHandling(IntWrapper::Create(0), IntWrapper::Create(1)),
-        OffHeapInt::Create(1001));
-    map3->insert(
-        PairWithWeakHandling(IntWrapper::Create(2), IntWrapper::Create(3)),
-        OffHeapInt::Create(1002));
-    map1->insert(
-        PairWithWeakHandling(IntWrapper::Create(4), IntWrapper::Create(5)),
-        OffHeapInt::Create(1003));
+    map2.insert(PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(0),
+                                     MakeGarbageCollected<IntWrapper>(1)),
+                OffHeapInt::Create(1001));
+    map3->insert(PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(2),
+                                      MakeGarbageCollected<IntWrapper>(3)),
+                 OffHeapInt::Create(1002));
+    map1->insert(PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(4),
+                                      MakeGarbageCollected<IntWrapper>(5)),
+                 OffHeapInt::Create(1003));
     EXPECT_EQ(0, OffHeapInt::destructor_calls_);
 
     ConservativelyCollectGarbage();
@@ -4904,14 +4826,16 @@
 
   OffHeapInt::destructor_calls_ = 0;
 
-  map1->insert(PairWithWeakHandling(IntWrapper::Create(103), living_int),
-               OffHeapInt::Create(2000));
-  map1->insert(PairWithWeakHandling(living_int, IntWrapper::Create(103)),
-               OffHeapInt::Create(2001));  // This one gets zapped at GC time
-  // because nothing holds the 103 alive.
   map1->insert(
-      PairWithWeakHandling(IntWrapper::Create(103), IntWrapper::Create(103)),
-      OffHeapInt::Create(2002));  // This one gets zapped too.
+      PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(103), living_int),
+      OffHeapInt::Create(2000));
+  map1->insert(
+      PairWithWeakHandling(living_int, MakeGarbageCollected<IntWrapper>(103)),
+      OffHeapInt::Create(2001));  // This one gets zapped at GC time
+  // because nothing holds the 103 alive.
+  map1->insert(PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(103),
+                                    MakeGarbageCollected<IntWrapper>(103)),
+               OffHeapInt::Create(2002));  // This one gets zapped too.
   scoped_refptr<OffHeapInt> dupe_int(OffHeapInt::Create(2003));
   map1->insert(PairWithWeakHandling(living_int, living_int), dupe_int);
   map1->insert(
@@ -4940,20 +4864,20 @@
   OffHeapInt::destructor_calls_ = 0;
 
   Persistent<Map> map1(MakeGarbageCollected<Map>());
-  Persistent<IntWrapper> living_int(IntWrapper::Create(42));
+  Persistent<IntWrapper> living_int(MakeGarbageCollected<IntWrapper>(42));
 
   {
     Map map2;
     Map* map3 = MakeGarbageCollected<Map>();
-    map2.insert(
-        OffHeapInt::Create(1001),
-        PairWithWeakHandling(IntWrapper::Create(0), IntWrapper::Create(1)));
-    map3->insert(
-        OffHeapInt::Create(1002),
-        PairWithWeakHandling(IntWrapper::Create(2), IntWrapper::Create(3)));
-    map1->insert(
-        OffHeapInt::Create(1003),
-        PairWithWeakHandling(IntWrapper::Create(4), IntWrapper::Create(5)));
+    map2.insert(OffHeapInt::Create(1001),
+                PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(0),
+                                     MakeGarbageCollected<IntWrapper>(1)));
+    map3->insert(OffHeapInt::Create(1002),
+                 PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(2),
+                                      MakeGarbageCollected<IntWrapper>(3)));
+    map1->insert(OffHeapInt::Create(1003),
+                 PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(4),
+                                      MakeGarbageCollected<IntWrapper>(5)));
     EXPECT_EQ(0, OffHeapInt::destructor_calls_);
 
     ConservativelyCollectGarbage();
@@ -4987,15 +4911,17 @@
 
   OffHeapInt::destructor_calls_ = 0;
 
-  map1->insert(OffHeapInt::Create(2000),
-               PairWithWeakHandling(IntWrapper::Create(103), living_int));
+  map1->insert(
+      OffHeapInt::Create(2000),
+      PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(103), living_int));
   // This one gets zapped at GC time because nothing holds the 103 alive.
-  map1->insert(OffHeapInt::Create(2001),
-               PairWithWeakHandling(living_int, IntWrapper::Create(103)));
+  map1->insert(
+      OffHeapInt::Create(2001),
+      PairWithWeakHandling(living_int, MakeGarbageCollected<IntWrapper>(103)));
   map1->insert(OffHeapInt::Create(2002),
-               PairWithWeakHandling(
-                   IntWrapper::Create(103),
-                   IntWrapper::Create(103)));  // This one gets zapped too.
+               PairWithWeakHandling(MakeGarbageCollected<IntWrapper>(103),
+                                    MakeGarbageCollected<IntWrapper>(
+                                        103)));  // This one gets zapped too.
   scoped_refptr<OffHeapInt> dupe_int(OffHeapInt::Create(2003));
   map1->insert(dupe_int, PairWithWeakHandling(living_int, living_int));
   // This one is identical to the previous and doesn't add anything.
@@ -5019,7 +4945,7 @@
     HeapHashMap<int, WeakMember<IntWrapper>>* map) {
   // Key cannot be zero in hashmap.
   for (int i = 1; i < 11; i++)
-    map->insert(i, IntWrapper::Create(i));
+    map->insert(i, MakeGarbageCollected<IntWrapper>(i));
 }
 
 // crbug.com/402426
@@ -5031,13 +4957,13 @@
   HeapHashMap<int, WeakMember<IntWrapper>>::AddResult result =
       map->insert(800, nullptr);
   ConservativelyCollectGarbage();
-  result.stored_value->value = IntWrapper::Create(42);
+  result.stored_value->value = MakeGarbageCollected<IntWrapper>(42);
 }
 
 TEST(HeapTest, Bind) {
   base::OnceClosure closure =
       WTF::Bind(static_cast<void (Bar::*)(Visitor*)>(&Bar::Trace),
-                WrapPersistent(Bar::Create()), nullptr);
+                WrapPersistent(MakeGarbageCollected<Bar>()), nullptr);
   // OffHeapInt* should not make Persistent.
   base::OnceClosure closure2 =
       WTF::Bind(&OffHeapInt::VoidFunction, OffHeapInt::Create(1));
@@ -5046,7 +4972,7 @@
   EXPECT_EQ(1u, Bar::live_);
 
   UseMixin::trace_count_ = 0;
-  Mixin* mixin = UseMixin::Create();
+  auto* mixin = MakeGarbageCollected<UseMixin>();
   base::OnceClosure mixin_closure =
       WTF::Bind(static_cast<void (Mixin::*)(Visitor*)>(&Mixin::Trace),
                 WrapPersistent(mixin), nullptr);
@@ -5110,7 +5036,7 @@
   ClearOutOldGarbage();
   OffHeapInt::destructor_calls_ = 0;
 
-  Persistent<IntWrapper> living_int(IntWrapper::Create(42));
+  Persistent<IntWrapper> living_int(MakeGarbageCollected<IntWrapper>(42));
 
   typedef scoped_refptr<OffHeapInt> Key;
   typedef HeapHashMap<Key, WeakSet, WTF::DefaultHash<Key>::Hash,
@@ -5120,7 +5046,8 @@
   map->insert(OffHeapInt::Create(1), WeakSet());
   {
     WeakSet& set = map->begin()->value;
-    set.insert(IntWrapper::Create(103));  // Weak set can't hold this long.
+    set.insert(MakeGarbageCollected<IntWrapper>(
+        103));               // Weak set can't hold this long.
     set.insert(living_int);  // This prevents the set from being emptied.
     EXPECT_EQ(2u, set.size());
   }
@@ -5150,10 +5077,10 @@
   for (int keep_outer_alive = 0; keep_outer_alive <= 1; keep_outer_alive++) {
     for (int keep_inner_alive = 0; keep_inner_alive <= 1; keep_inner_alive++) {
       Persistent<OuterMap> outer = MakeGarbageCollected<OuterMap>();
-      Persistent<IntWrapper> one = IntWrapper::Create(1);
-      Persistent<IntWrapper> two = IntWrapper::Create(2);
+      Persistent<IntWrapper> one = MakeGarbageCollected<IntWrapper>(1);
+      Persistent<IntWrapper> two = MakeGarbageCollected<IntWrapper>(2);
       outer->insert(one, InnerMap());
-      outer->begin()->value.insert(two, IntWrapper::Create(3));
+      outer->begin()->value.insert(two, MakeGarbageCollected<IntWrapper>(3));
       EXPECT_EQ(1u, outer->at(one).size());
       if (!keep_outer_alive)
         one.Clear();
@@ -5173,13 +5100,13 @@
         EXPECT_EQ(0u, outer->size());
       }
       outer->clear();
-      Persistent<IntWrapper> deep = IntWrapper::Create(42);
-      Persistent<IntWrapper> home = IntWrapper::Create(103);
-      Persistent<IntWrapper> composite = IntWrapper::Create(91);
+      Persistent<IntWrapper> deep = MakeGarbageCollected<IntWrapper>(42);
+      Persistent<IntWrapper> home = MakeGarbageCollected<IntWrapper>(103);
+      Persistent<IntWrapper> composite = MakeGarbageCollected<IntWrapper>(91);
       Persistent<HeapVector<Member<IntWrapper>>> keep_alive =
           MakeGarbageCollected<HeapVector<Member<IntWrapper>>>();
       for (int i = 0; i < 10000; i++) {
-        IntWrapper* value = IntWrapper::Create(i);
+        auto* value = MakeGarbageCollected<IntWrapper>(i);
         keep_alive->push_back(value);
         OuterMap::AddResult new_entry = outer->insert(value, InnerMap());
         new_entry.stored_value->value.insert(deep, home);
@@ -5214,8 +5141,8 @@
 };
 
 TEST(HeapTest, EphemeronsPointToEphemerons) {
-  Persistent<IntWrapper> key = IntWrapper::Create(42);
-  Persistent<IntWrapper> key2 = IntWrapper::Create(103);
+  Persistent<IntWrapper> key = MakeGarbageCollected<IntWrapper>(42);
+  Persistent<IntWrapper> key2 = MakeGarbageCollected<IntWrapper>(103);
 
   Persistent<EphemeronWrapper> chain;
   for (int i = 0; i < 100; i++) {
@@ -5225,7 +5152,7 @@
       chain->GetMap().insert(key2, old_head);
     else
       chain->GetMap().insert(key, old_head);
-    chain->GetMap().insert(IntWrapper::Create(103),
+    chain->GetMap().insert(MakeGarbageCollected<IntWrapper>(103),
                            MakeGarbageCollected<EphemeronWrapper>());
   }
 
@@ -5271,10 +5198,10 @@
 
   Persistent<Set> set = MakeGarbageCollected<Set>();
 
-  Persistent<IntWrapper> wp1 = IntWrapper::Create(1);
-  Persistent<IntWrapper> wp2 = IntWrapper::Create(2);
-  Persistent<IntWrapper> pw1 = IntWrapper::Create(3);
-  Persistent<IntWrapper> pw2 = IntWrapper::Create(4);
+  Persistent<IntWrapper> wp1 = MakeGarbageCollected<IntWrapper>(1);
+  Persistent<IntWrapper> wp2 = MakeGarbageCollected<IntWrapper>(2);
+  Persistent<IntWrapper> pw1 = MakeGarbageCollected<IntWrapper>(3);
+  Persistent<IntWrapper> pw2 = MakeGarbageCollected<IntWrapper>(4);
 
   weak_pair_map->insert(wp1, PairWithWeakHandling(wp1, wp1));
   weak_pair_map->insert(wp2, PairWithWeakHandling(wp1, wp1));
@@ -5353,9 +5280,9 @@
 TEST(HeapTest, IndirectStrongToWeak) {
   typedef HeapHashMap<WeakMember<IntWrapper>, Member<Link1>> Map;
   Persistent<Map> map = MakeGarbageCollected<Map>();
-  Persistent<IntWrapper> dead_object =
-      IntWrapper::Create(100);  // Named for "Drowning by Numbers" (1988).
-  Persistent<IntWrapper> life_object = IntWrapper::Create(42);
+  Persistent<IntWrapper> dead_object = MakeGarbageCollected<IntWrapper>(
+      100);  // Named for "Drowning by Numbers" (1988).
+  Persistent<IntWrapper> life_object = MakeGarbageCollected<IntWrapper>(42);
   map->insert(dead_object, MakeGarbageCollected<Link1>(dead_object));
   map->insert(life_object, MakeGarbageCollected<Link1>(life_object));
   EXPECT_EQ(2u, map->size());
@@ -5381,12 +5308,9 @@
 class TraceIfNeededTester
     : public GarbageCollectedFinalized<TraceIfNeededTester<T>> {
  public:
-  static TraceIfNeededTester<T>* Create() {
-    return new TraceIfNeededTester<T>();
-  }
-  static TraceIfNeededTester<T>* Create(const T& obj) {
-    return new TraceIfNeededTester<T>(obj);
-  }
+  TraceIfNeededTester() = default;
+  explicit TraceIfNeededTester(const T& obj) : obj_(obj) {}
+
   void Trace(blink::Visitor* visitor) {
     TraceIfNeeded<T>::Trace(visitor, obj_);
   }
@@ -5394,8 +5318,6 @@
   ~TraceIfNeededTester() = default;
 
  private:
-  TraceIfNeededTester() = default;
-  explicit TraceIfNeededTester(const T& obj) : obj_(obj) {}
   T obj_;
 };
 
@@ -5403,7 +5325,7 @@
   DISALLOW_NEW();
 
  public:
-  PartObject() : obj_(SimpleObject::Create()) {}
+  PartObject() : obj_(MakeGarbageCollected<SimpleObject>()) {}
   void Trace(blink::Visitor* visitor) { visitor->Trace(obj_); }
 
  private:
@@ -5630,7 +5552,7 @@
   // deque's buffer.
   int i = 0;
   for (; i < 60; ++i)
-    deque->push_back(IntWrapper::Create(i));
+    deque->push_back(MakeGarbageCollected<IntWrapper>(i));
 
   EXPECT_EQ(60u, deque->size());
   i = 0;
@@ -5654,7 +5576,7 @@
   // Append even more, eventually causing an expansion of the underlying
   // buffer once the end index wraps around and reaches the start index.
   for (i = 0; i < 70; ++i)
-    deque->push_back(IntWrapper::Create(60 + i));
+    deque->push_back(MakeGarbageCollected<IntWrapper>(60 + i));
 
   // Verify that the final buffer expansion copied the start and end segments
   // of the old buffer to both ends of the expanded buffer, along with
@@ -5850,7 +5772,7 @@
     // mixin base.
     DCHECK(ThreadState::Current()->IsGCForbidden());
     for (size_t i = 0; i < number_of_large_objects_to_allocate; i++) {
-      LargeHeapObject* large_object = LargeHeapObject::Create();
+      auto* large_object = MakeGarbageCollected<LargeHeapObject>();
       EXPECT_TRUE(large_object);
       EXPECT_EQ(0, member->TraceCount());
     }
@@ -5921,10 +5843,6 @@
     : public GarbageCollectedFinalized<
           ThreadedClearOnShutdownTester::HeapObject> {
  public:
-  static HeapObject* Create(bool test_destructor) {
-    return MakeGarbageCollected<HeapObject>(test_destructor);
-  }
-
   explicit HeapObject(bool test_destructor)
       : test_destructor_(test_destructor) {}
   ~HeapObject() {
@@ -5939,7 +5857,7 @@
     // object. Done while terminating the test thread, so
     // verify that this brings about the release of the
     // persistent also.
-    GetHeapObjectSet().insert(Create(false));
+    GetHeapObjectSet().insert(MakeGarbageCollected<HeapObject>(false));
   }
 
   void Trace(blink::Visitor* visitor) {}
@@ -5975,7 +5893,7 @@
 void ThreadedClearOnShutdownTester::RunWhileAttached() {
   EXPECT_EQ(42, ThreadSpecificIntWrapper().Value());
   // Creates a thread-specific singleton to a weakly held object.
-  GetWeakHeapObjectSet().insert(HeapObject::Create(true));
+  GetWeakHeapObjectSet().insert(MakeGarbageCollected<HeapObject>(true));
 }
 
 }  // namespace
@@ -5987,10 +5905,6 @@
 // Verify that WeakMember<const T> compiles and behaves as expected.
 class WithWeakConstObject final : public GarbageCollected<WithWeakConstObject> {
  public:
-  static WithWeakConstObject* Create(const IntWrapper* int_wrapper) {
-    return MakeGarbageCollected<WithWeakConstObject>(int_wrapper);
-  }
-
   WithWeakConstObject(const IntWrapper* int_wrapper) : wrapper_(int_wrapper) {}
 
   void Trace(blink::Visitor* visitor) { visitor->Trace(wrapper_); }
@@ -6004,8 +5918,8 @@
 TEST(HeapTest, TestWeakConstObject) {
   Persistent<WithWeakConstObject> weak_wrapper;
   {
-    const IntWrapper* wrapper = IntWrapper::Create(42);
-    weak_wrapper = WithWeakConstObject::Create(wrapper);
+    const auto* wrapper = MakeGarbageCollected<IntWrapper>(42);
+    weak_wrapper = MakeGarbageCollected<WithWeakConstObject>(wrapper);
     ConservativelyCollectGarbage();
     EXPECT_EQ(wrapper, weak_wrapper->Value());
     // Stub out any stack reference.
@@ -6078,7 +5992,7 @@
 
   for (int i = 1; i <= 100; ++i) {
     KeyWithCopyingMoveConstructor key(i, string);
-    map.insert(key, IntWrapper::Create(i));
+    map.insert(key, MakeGarbageCollected<IntWrapper>(i));
   }
 
   EXPECT_FALSE(string.Impl()->HasOneRef());
@@ -6092,9 +6006,6 @@
       public DoublyLinkedListNode<DoublyLinkedListNodeImpl> {
  public:
   DoublyLinkedListNodeImpl() = default;
-  static DoublyLinkedListNodeImpl* Create() {
-    return MakeGarbageCollected<DoublyLinkedListNodeImpl>();
-  }
 
   static int destructor_calls_;
   ~DoublyLinkedListNodeImpl() { ++destructor_calls_; }
@@ -6116,9 +6027,6 @@
 class HeapDoublyLinkedListContainer
     : public GarbageCollected<HeapDoublyLinkedListContainer<T>> {
  public:
-  static HeapDoublyLinkedListContainer<T>* Create() {
-    return MakeGarbageCollected<HeapDoublyLinkedListContainer<T>>();
-  }
   HeapDoublyLinkedListContainer<T>() = default;
   HeapDoublyLinkedList<T> list_;
   void Trace(Visitor* visitor) { visitor->Trace(list_); }
@@ -6126,12 +6034,12 @@
 
 TEST(HeapTest, HeapDoublyLinkedList) {
   Persistent<HeapDoublyLinkedListContainer<DoublyLinkedListNodeImpl>>
-      container =
-          HeapDoublyLinkedListContainer<DoublyLinkedListNodeImpl>::Create();
+      container = MakeGarbageCollected<
+          HeapDoublyLinkedListContainer<DoublyLinkedListNodeImpl>>();
   DoublyLinkedListNodeImpl::destructor_calls_ = 0;
 
-  container->list_.Append(DoublyLinkedListNodeImpl::Create());
-  container->list_.Append(DoublyLinkedListNodeImpl::Create());
+  container->list_.Append(MakeGarbageCollected<DoublyLinkedListNodeImpl>());
+  container->list_.Append(MakeGarbageCollected<DoublyLinkedListNodeImpl>());
 
   PreciselyCollectGarbage();
   EXPECT_EQ(DoublyLinkedListNodeImpl::destructor_calls_, 0);
diff --git a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h
index f34b2b00..48c4032 100644
--- a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h
+++ b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h
@@ -37,7 +37,6 @@
 #include "third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader.h"
 #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/cpu.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc b/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc
index fa3aaab..1d88a7e 100644
--- a/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc
+++ b/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc
@@ -1198,14 +1198,15 @@
 
       for (String interlace : interlace_status) {
         PNGSample high_bit_depth_sample(png_sample);
-        high_bit_depth_sample.filename.insert(interlace, 0);
-        high_bit_depth_sample.filename.insert("2x2_16bit", 0);
+        high_bit_depth_sample.filename =
+            "2x2_16bit" + interlace + high_bit_depth_sample.filename;
         high_bit_depth_sample.is_high_bit_depth = true;
         png_samples.push_back(high_bit_depth_sample);
       }
       if (include_8bit_pngs) {
         PNGSample regular_bit_depth_sample(png_sample);
-        regular_bit_depth_sample.filename.insert("2x2_8bit", 0);
+        regular_bit_depth_sample.filename =
+            "2x2_8bit" + regular_bit_depth_sample.filename;
         regular_bit_depth_sample.is_high_bit_depth = false;
         png_samples.push_back(regular_bit_depth_sample);
       }
diff --git a/third_party/blink/renderer/platform/loader/BUILD.gn b/third_party/blink/renderer/platform/loader/BUILD.gn
index be56961b..a6effe85 100644
--- a/third_party/blink/renderer/platform/loader/BUILD.gn
+++ b/third_party/blink/renderer/platform/loader/BUILD.gn
@@ -69,6 +69,7 @@
     "fetch/resource_fetcher_properties.h",
     "fetch/resource_finish_observer.h",
     "fetch/resource_load_info.h",
+    "fetch/resource_load_observer.h",
     "fetch/resource_load_priority.h",
     "fetch/resource_load_scheduler.cc",
     "fetch/resource_load_scheduler.h",
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
index 0ee79558..7dd8c17 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
@@ -83,38 +83,6 @@
                                   WebScopedVirtualTimePauser&,
                                   ResourceType) {}
 
-void FetchContext::DispatchWillSendRequest(uint64_t,
-                                           const ResourceRequest&,
-                                           const ResourceResponse&,
-                                           ResourceType,
-                                           const FetchInitiatorInfo&) {}
-
-void FetchContext::DispatchDidReceiveResponse(uint64_t,
-                                              const ResourceRequest&,
-                                              const ResourceResponse&,
-                                              Resource*,
-                                              ResourceResponseType) {}
-
-void FetchContext::DispatchDidReceiveData(uint64_t, const char*, uint64_t) {}
-
-void FetchContext::DispatchDidReceiveEncodedData(uint64_t, size_t) {}
-
-void FetchContext::DispatchDidDownloadToBlob(uint64_t identifier,
-                                             BlobDataHandle*) {}
-
-void FetchContext::DispatchDidFinishLoading(uint64_t,
-                                            TimeTicks,
-                                            int64_t,
-                                            int64_t,
-                                            bool,
-                                            ResourceResponseType) {}
-
-void FetchContext::DispatchDidFail(const KURL&,
-                                   uint64_t,
-                                   const ResourceError&,
-                                   int64_t,
-                                   bool) {}
-
 bool FetchContext::ShouldLoadNewResource(ResourceType type) const {
   return !GetResourceFetcherProperties().ShouldBlockLoadingSubResource();
 }
@@ -124,8 +92,6 @@
     ResourceType,
     const AtomicString& fetch_initiator_name) {}
 
-void FetchContext::DidObserveLoadingBehavior(WebLoadingBehaviorFlag) {}
-
 void FetchContext::AddResourceTiming(const ResourceTimingInfo&) {}
 
 void FetchContext::PopulateResourceRequest(
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
index ad006a3..a5dd6db 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -41,7 +41,6 @@
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/resource_request_blocked_reason.h"
-#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
 #include "third_party/blink/public/platform/web_url_loader.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
@@ -61,9 +60,7 @@
 class ClientHintsPreferences;
 class KURL;
 class PlatformProbeSink;
-class ResourceError;
 class ResourceFetcherProperties;
-class ResourceResponse;
 class ResourceTimingInfo;
 class WebScopedVirtualTimePauser;
 
@@ -124,42 +121,6 @@
                               WebScopedVirtualTimePauser& virtual_time_pauser,
                               ResourceType);
 
-  // The last callback before a request is actually sent to the browser process.
-  // This is called on initial and every redirect request.
-  virtual void DispatchWillSendRequest(
-      uint64_t identifier,
-      const ResourceRequest&,
-      const ResourceResponse& redirect_response,
-      ResourceType,
-      const FetchInitiatorInfo& = FetchInitiatorInfo());
-  enum class ResourceResponseType { kNotFromMemoryCache, kFromMemoryCache };
-  // |request| and |resource| are provided separately because when it's from
-  // the memory cache |request| and |resource->GetResourceRequest()| don't
-  // match. |response| may not yet be set to |resource| when this function is
-  // called.
-  virtual void DispatchDidReceiveResponse(uint64_t identifier,
-                                          const ResourceRequest& request,
-                                          const ResourceResponse& response,
-                                          Resource* resource,
-                                          ResourceResponseType);
-  virtual void DispatchDidReceiveData(uint64_t identifier,
-                                      const char* data,
-                                      uint64_t data_length);
-  virtual void DispatchDidReceiveEncodedData(uint64_t identifier,
-                                             size_t encoded_data_length);
-  virtual void DispatchDidDownloadToBlob(uint64_t identifier, BlobDataHandle*);
-  virtual void DispatchDidFinishLoading(uint64_t identifier,
-                                        TimeTicks finish_time,
-                                        int64_t encoded_data_length,
-                                        int64_t decoded_body_length,
-                                        bool should_report_corb_blocking,
-                                        ResourceResponseType);
-  virtual void DispatchDidFail(const KURL&,
-                               uint64_t identifier,
-                               const ResourceError&,
-                               int64_t encoded_data_length,
-                               bool is_internal_request);
-
   bool ShouldLoadNewResource(ResourceType) const;
 
   // Called when a resource load is first requested, which may not be when the
@@ -168,8 +129,6 @@
                                      ResourceType,
                                      const AtomicString& fetch_initiator_name);
 
-  virtual void DidObserveLoadingBehavior(WebLoadingBehaviorFlag);
-
   virtual void AddResourceTiming(const ResourceTimingInfo&);
   virtual bool AllowImage(bool, const KURL&) const { return false; }
   virtual base::Optional<ResourceRequestBlockedReason> CanRequest(
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 0e96155..9411538 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -31,8 +31,6 @@
 #include <limits>
 #include <utility>
 
-#include "base/feature_list.h"
-#include "base/metrics/field_trial_params.h"
 #include "base/time/time.h"
 #include "third_party/blink/public/common/mime_util/mime_util.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
@@ -54,6 +52,7 @@
 #include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
 #include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
@@ -226,35 +225,6 @@
   return new_priority;
 }
 
-const base::Feature kStaleWhileRevalidateExperiment{
-    "StaleWhileRevalidateExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
-
-bool MatchesStaleWhileRevalidateControlList(const String& host) {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<String>,
-                                  stale_while_revalidate_control_hosts, ());
-  if (stale_while_revalidate_control_hosts->IsNull()) {
-    *stale_while_revalidate_control_hosts =
-        GetFieldTrialParamValueByFeature(kStaleWhileRevalidateExperiment,
-                                         "control_hosts")
-            .c_str();
-  }
-  return !host.IsEmpty() &&
-         stale_while_revalidate_control_hosts->Find(host) != kNotFound;
-}
-
-bool MatchesStaleWhileRevalidateAllowList(const String& host) {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<String>,
-                                  stale_while_revalidate_allow_hosts, ());
-  if (stale_while_revalidate_allow_hosts->IsNull()) {
-    *stale_while_revalidate_allow_hosts =
-        GetFieldTrialParamValueByFeature(kStaleWhileRevalidateExperiment,
-                                         "hosts")
-            .c_str();
-  }
-  return !host.IsEmpty() &&
-         stale_while_revalidate_allow_hosts->Find(host) != kNotFound;
-}
-
 std::unique_ptr<TracedValue> BeginResourceLoadData(
     const blink::ResourceRequest& request) {
   auto value = std::make_unique<TracedValue>();
@@ -545,6 +515,10 @@
   return *properties_;
 }
 
+bool ResourceFetcher::IsDetached() const {
+  return properties_->IsDetached();
+}
+
 Resource* ResourceFetcher::CachedResource(const KURL& resource_url) const {
   if (resource_url.IsEmpty())
     return nullptr;
@@ -619,24 +593,24 @@
 void ResourceFetcher::DidLoadResourceFromMemoryCache(
     uint64_t identifier,
     Resource* resource,
-    const ResourceRequest& original_request) {
-  ResourceRequest request = original_request;
+    const ResourceRequest& request) {
+  if (IsDetached() || !resource_load_observer_)
+    return;
 
-  Context().DispatchWillSendRequest(
+  resource_load_observer_->WillSendRequest(
       identifier, request, ResourceResponse() /* redirects */,
       resource->GetType(), resource->Options().initiator_info);
-  Context().DispatchDidReceiveResponse(
+  resource_load_observer_->DidReceiveResponse(
       identifier, request, resource->GetResponse(), resource,
-      FetchContext::ResourceResponseType::kFromMemoryCache);
-
+      ResourceLoadObserver::ResponseSource::kFromMemoryCache);
   if (resource->EncodedSize() > 0) {
-    Context().DispatchDidReceiveData(identifier, nullptr,
-                                     resource->EncodedSize());
+    resource_load_observer_->DidReceiveData(
+        identifier, base::span<const char>(nullptr, resource->EncodedSize()));
   }
 
-  Context().DispatchDidFinishLoading(
+  resource_load_observer_->DidFinishLoading(
       identifier, TimeTicks(), 0, resource->GetResponse().DecodedBodyLength(),
-      false, FetchContext::ResourceResponseType::kFromMemoryCache);
+      false, ResourceLoadObserver::ResponseSource::kFromMemoryCache);
 }
 
 Resource* ResourceFetcher::ResourceForStaticData(
@@ -830,33 +804,14 @@
   if (resource_type == ResourceType::kLinkPrefetch)
     resource_request.SetHttpHeaderField(http_names::kPurpose, "prefetch");
 
-  bool resource_allows_stale_while_revalidate = false;
-  bool host_matches_control =
-      MatchesStaleWhileRevalidateControlList(params.Url().Host());
-  bool host_matches_allow = false;
-  if (!host_matches_control) {
-    host_matches_allow =
-        MatchesStaleWhileRevalidateAllowList(params.Url().Host());
-  }
-  if (host_matches_allow)
-    resource_allows_stale_while_revalidate = host_matches_allow;
-
-  // For the finch experiment indicate that the resource likely supports
-  // stale while revalidate (based on a list of hosts). This allows us
-  // to only log metrics for sites that would possibly benefit from
-  // stale while revalidate being enabled.
-  resource_request.SetStaleRevalidateCandidate(
-      (host_matches_allow || host_matches_control) &&
-      !params.IsStaleRevalidation());
   // Indicate whether the network stack can return a stale resource. If a
   // stale resource is returned a StaleRevalidation request will be scheduled.
   // Explicitly disallow stale responses for fetchers that don't have SWR
   // enabled (via origin trial), and non-GET requests.
-  resource_request.SetAllowStaleResponse(
-      (resource_allows_stale_while_revalidate ||
-       stale_while_revalidate_enabled_) &&
-      resource_request.HttpMethod() == http_names::kGET &&
-      !params.IsStaleRevalidation());
+  resource_request.SetAllowStaleResponse(stale_while_revalidate_enabled_ &&
+                                         resource_request.HttpMethod() ==
+                                             http_names::kGET &&
+                                         !params.IsStaleRevalidation());
 
   Context().AddAdditionalRequestHeaders(resource_request);
 
@@ -950,7 +905,7 @@
 
   if (!RuntimeEnabledFeatures::OutOfBlinkCorsEnabled() &&
       resource_request.RequestorOrigin()) {
-    resource_request.SetHTTPOriginIfNeeded(
+    resource_request.SetHttpOriginIfNeeded(
         resource_request.RequestorOrigin().get());
   }
 
@@ -1020,20 +975,10 @@
       InitializeRevalidation(resource_request, resource);
       break;
     case kUse:
-      bool used_stale = false;
       if (resource_request.AllowsStaleResponse() &&
           resource->ShouldRevalidateStaleResponse()) {
-        used_stale = true;
         ScheduleStaleRevalidate(resource);
       }
-      if (resource_request.IsStaleRevalidateCandidate()) {
-        context_->DidObserveLoadingBehavior(
-            used_stale
-                ? WebLoadingBehaviorFlag::
-                      kStaleWhileRevalidateResourceCandidateStaleCacheLoad
-                : WebLoadingBehaviorFlag::
-                      kStaleWhileRevalidateResourceCandidateCacheLoad);
-      }
 
       if (resource->IsLinkPreload() && !params.IsLinkPreload())
         resource->SetLinkPreload(false);
@@ -1638,6 +1583,7 @@
     properties_->Detach();
   }
 
+  resource_load_observer_ = nullptr;
   console_logger_->Detach();
   loader_factory_ = nullptr;
 
@@ -1805,30 +1751,19 @@
     // is fresh at the time of the network stack handling but not at the time
     // handling here and we should not be forcing a revalidation in that case.
     // eg. network stack returning a resource with max-age=0.
-    bool used_stale = false;
     if (resource->GetResourceRequest().AllowsStaleResponse() &&
         resource->StaleRevalidationRequested()) {
-      used_stale = true;
       ScheduleStaleRevalidate(resource);
     }
-
-    if (resource->GetResourceRequest().IsStaleRevalidateCandidate()) {
-      WebLoadingBehaviorFlag behavior = WebLoadingBehaviorFlag::
-          kStaleWhileRevalidateResourceCandidateCacheLoad;
-      if (used_stale) {
-        behavior = WebLoadingBehaviorFlag::
-            kStaleWhileRevalidateResourceCandidateStaleCacheLoad;
-      } else if (resource->NetworkAccessed()) {
-        behavior = WebLoadingBehaviorFlag::
-            kStaleWhileRevalidateResourceCandidateNetworkLoad;
-      }
-      context_->DidObserveLoadingBehavior(behavior);
-    }
   }
-  Context().DispatchDidFinishLoading(
-      resource->InspectorId(), response_end, encoded_data_length,
-      resource->GetResponse().DecodedBodyLength(), should_report_corb_blocking,
-      FetchContext::ResourceResponseType::kNotFromMemoryCache);
+  if (resource_load_observer_) {
+    DCHECK(!IsDetached());
+    resource_load_observer_->DidFinishLoading(
+        resource->InspectorId(), response_end, encoded_data_length,
+        resource->GetResponse().DecodedBodyLength(),
+        should_report_corb_blocking,
+        ResourceLoadObserver::ResponseSource::kNotFromMemoryCache);
+  }
   resource->ReloadIfLoFiOrPlaceholderImage(this, Resource::kReloadIfNeeded);
 }
 
@@ -1853,11 +1788,14 @@
         mojom::WebFeature::kCertificateTransparencyRequiredErrorOnResourceLoad);
   }
   resource->FinishAsError(error, task_runner_.get());
-  const bool is_internal_request = resource->Options().initiator_info.name ==
-                                   fetch_initiator_type_names::kInternal;
-  Context().DispatchDidFail(
-      resource->LastResourceRequest().Url(), resource->InspectorId(), error,
-      resource->GetResponse().EncodedDataLength(), is_internal_request);
+  if (resource_load_observer_) {
+    DCHECK(!IsDetached());
+    const bool is_internal_request = resource->Options().initiator_info.name ==
+                                     fetch_initiator_type_names::kInternal;
+    resource_load_observer_->DidFailLoading(
+        resource->LastResourceRequest().Url(), resource->InspectorId(), error,
+        resource->GetResponse().EncodedDataLength(), is_internal_request);
+  }
   resource->ReloadIfLoFiOrPlaceholderImage(this, Resource::kReloadIfNeeded);
 }
 
@@ -1895,10 +1833,12 @@
                                             resource->Options().initiator_info);
 
     resource->VirtualTimePauser().PauseVirtualTime();
-    Context().DispatchWillSendRequest(resource->InspectorId(), request,
-                                      response, resource->GetType(),
-                                      resource->Options().initiator_info);
-
+    if (resource_load_observer_) {
+      DCHECK(!IsDetached());
+      resource_load_observer_->WillSendRequest(
+          resource->InspectorId(), request, response, resource->GetType(),
+          resource->Options().initiator_info);
+    }
     // TODO(shaochuan): Saving modified ResourceRequest back to |resource|,
     // remove once dispatchWillSendRequest() takes const ResourceRequest.
     // crbug.com/632580
@@ -2106,6 +2046,7 @@
 void ResourceFetcher::Trace(blink::Visitor* visitor) {
   visitor->Trace(context_);
   visitor->Trace(properties_);
+  visitor->Trace(resource_load_observer_);
   visitor->Trace(console_logger_);
   visitor->Trace(loader_factory_);
   visitor->Trace(scheduler_);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
index f0e46972..39566c8a 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -59,6 +59,7 @@
 class Resource;
 class ResourceError;
 class ResourceFetcherProperties;
+class ResourceLoadObserver;
 class ResourceTimingInfo;
 class WebURLLoader;
 struct ResourceFetcherInit;
@@ -113,6 +114,21 @@
   //   to the ResourceFetcher constructor.
   const ResourceFetcherProperties& GetProperties() const;
 
+  // Returns whether this fetcher is detached from the associated context.
+  bool IsDetached() const;
+
+  // Returns the observer object associated with this fetcher.
+  ResourceLoadObserver* GetResourceLoadObserver() {
+    // When detached, we must have a null observer.
+    DCHECK(!IsDetached() || !resource_load_observer_);
+    return resource_load_observer_;
+  }
+  // This must be called right after construction.
+  void SetResourceLoadObserver(ResourceLoadObserver* observer) {
+    DCHECK(!IsDetached());
+    resource_load_observer_ = observer;
+  }
+
   // Triggers a fetch based on the given FetchParameters (if there isn't a
   // suitable Resource already cached) and registers the given ResourceClient
   // with the Resource. Guaranteed to return a non-null Resource of the subtype
@@ -343,6 +359,7 @@
   void RevalidateStaleResource(Resource* stale_resource);
 
   Member<DetachableProperties> properties_;
+  Member<ResourceLoadObserver> resource_load_observer_;
   Member<FetchContext> context_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   const Member<DetachableConsoleLogger> console_logger_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
index 7ad8d0c..714d8df 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -44,6 +44,7 @@
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_info.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
@@ -51,6 +52,7 @@
 #include "third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h"
 #include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
@@ -99,6 +101,46 @@
   ResourceFetcherTest() = default;
   ~ResourceFetcherTest() override { GetMemoryCache()->EvictResources(); }
 
+  class TestResourceLoadObserver final : public ResourceLoadObserver {
+   public:
+    // ResourceLoadObserver implementation.
+    void WillSendRequest(uint64_t identifier,
+                         const ResourceRequest& request,
+                         const ResourceResponse& redirect_response,
+                         ResourceType,
+                         const FetchInitiatorInfo&) override {
+      request_ = request;
+    }
+    void DidReceiveResponse(uint64_t identifier,
+                            const ResourceRequest& request,
+                            const ResourceResponse& response,
+                            Resource* resource,
+                            ResponseSource source) override {}
+    void DidReceiveData(uint64_t identifier,
+                        base::span<const char> chunk) override {}
+    void DidReceiveTransferSizeUpdate(uint64_t identifier,
+                                      int transfer_size_diff) override {}
+    void DidDownloadToBlob(uint64_t identifier, BlobDataHandle*) override {}
+    void DidFinishLoading(uint64_t identifier,
+                          TimeTicks finish_time,
+                          int64_t encoded_data_length,
+                          int64_t decoded_body_length,
+                          bool should_report_corb_blocking,
+                          ResponseSource) override {}
+    void DidFailLoading(const KURL&,
+                        uint64_t identifier,
+                        const ResourceError&,
+                        int64_t encoded_data_length,
+                        bool is_internal_request) override {}
+
+    const base::Optional<ResourceRequest>& GetLastRequest() const {
+      return request_;
+    }
+
+   private:
+    base::Optional<ResourceRequest> request_;
+  };
+
  protected:
   scoped_refptr<scheduler::FakeTaskRunner> CreateTaskRunner() {
     return base::MakeRefCounted<scheduler::FakeTaskRunner>();
@@ -107,7 +149,8 @@
                                  FetchContext* context) {
     return MakeGarbageCollected<ResourceFetcher>(
         ResourceFetcherInit(properties, context, CreateTaskRunner(),
-                            MakeGarbageCollected<TestLoaderFactory>()));
+                            MakeGarbageCollected<TestLoaderFactory>(),
+                            *MakeGarbageCollected<NullConsoleLogger>()));
   }
   ResourceFetcher* CreateFetcher(const ResourceFetcherProperties& properties) {
     return CreateFetcher(properties, MakeGarbageCollected<MockFetchContext>());
@@ -187,9 +230,11 @@
   resource->ResponseReceived(response);
   resource->FinishForTest();
 
+  auto* observer = MakeGarbageCollected<TestResourceLoadObserver>();
   // Fetch the cached resource. The request to DispatchWillSendRequest should
   // preserve the ad bit.
   auto* fetcher = CreateFetcher(*properties, context);
+  fetcher->SetResourceLoadObserver(observer);
   ResourceRequest resource_request(url);
   resource_request.SetIsAdResource();
   resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
@@ -198,8 +243,7 @@
   Resource* new_resource = RawResource::Fetch(fetch_params, fetcher, nullptr);
 
   EXPECT_EQ(resource, new_resource);
-  base::Optional<ResourceRequest> new_request =
-      context->RequestFromWillSendRequest();
+  base::Optional<ResourceRequest> new_request = observer->GetLastRequest();
   EXPECT_TRUE(new_request.has_value());
   EXPECT_TRUE(new_request.value().IsAdResource());
 }
@@ -861,10 +905,12 @@
 TEST_F(ResourceFetcherTest, StaleWhileRevalidate) {
   scoped_refptr<const SecurityOrigin> source_origin =
       SecurityOrigin::CreateUniqueOpaque();
+  auto* observer = MakeGarbageCollected<TestResourceLoadObserver>();
   MockFetchContext* context = MakeGarbageCollected<MockFetchContext>();
   auto* fetcher = CreateFetcher(
       *MakeGarbageCollected<TestResourceFetcherProperties>(source_origin),
       context);
+  fetcher->SetResourceLoadObserver(observer);
 
   KURL url("http://127.0.0.1:8000/foo.html");
   FetchParameters fetch_params{ResourceRequest(url)};
@@ -903,8 +949,7 @@
   EXPECT_TRUE(GetMemoryCache()->Contains(resource));
   static_cast<scheduler::FakeTaskRunner*>(fetcher->GetTaskRunner().get())
       ->RunUntilIdle();
-  base::Optional<ResourceRequest> swr_request =
-      context->RequestFromWillSendRequest();
+  base::Optional<ResourceRequest> swr_request = observer->GetLastRequest();
   ASSERT_TRUE(swr_request.has_value());
   EXPECT_EQ(ResourceLoadPriority::kVeryLow, swr_request->Priority());
   platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h b/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
new file mode 100644
index 0000000..a51666bd
--- /dev/null
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
@@ -0,0 +1,90 @@
+// Copyright 2019 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOAD_OBSERVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOAD_OBSERVER_H_
+
+#include <inttypes.h>
+
+#include "base/containers/span.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+class KURL;
+class ResourceError;
+class ResourceRequest;
+class ResourceResponse;
+struct FetchInitiatorInfo;
+
+// ResourceLoadObserver is a collection of functions which meet following
+// conditions.
+// 1. It's not possible to implement it in platform/loader.
+// 2. It's about individual loading operation. For example, a function
+//    notifying that all requests are gone would not belong to this class.
+// 3. It is called when the loader gets some input, typically from the network
+//    subsystem. There may be some cases where the source of the input is not
+//    from network - For example, this class may have a function which is called
+//    when ResourceFetcher::RequestResource is called. On the other hand, this
+//    class will not have "operation"s, such as PrepareRequest.
+class PLATFORM_EXPORT ResourceLoadObserver
+    : public GarbageCollectedFinalized<ResourceLoadObserver> {
+ public:
+  virtual ~ResourceLoadObserver() = default;
+
+  // Called when the request is about to be sent. This is called on initial and
+  // every redirect request.
+  virtual void WillSendRequest(uint64_t identifier,
+                               const ResourceRequest&,
+                               const ResourceResponse& redirect_response,
+                               ResourceType,
+                               const FetchInitiatorInfo&) = 0;
+
+  enum ResponseSource { kFromMemoryCache, kNotFromMemoryCache };
+  // Called when a response is received.
+  // |request| and |resource| are provided separately because when it's from
+  // the memory cache |request| and |resource->GetResourceRequest()| don't
+  // match. |response| may not yet be set to |resource| when this function is
+  // called.
+  // TODO(yhirano): Use const* Resource.
+  virtual void DidReceiveResponse(uint64_t identifier,
+                                  const ResourceRequest& request,
+                                  const ResourceResponse& response,
+                                  Resource* resource,
+                                  ResponseSource) = 0;
+
+  // Called when a response body chunk is received.
+  virtual void DidReceiveData(uint64_t identifier,
+                              base::span<const char> chunk) = 0;
+
+  // Called when receiving an update for "network transfer size" for a request.
+  virtual void DidReceiveTransferSizeUpdate(uint64_t identifier,
+                                            int transfer_size_diff) = 0;
+
+  // Called when receiving a Blob as a response.
+  virtual void DidDownloadToBlob(uint64_t identifier, BlobDataHandle*) = 0;
+
+  // Called when a request finishes successfully.
+  virtual void DidFinishLoading(uint64_t identifier,
+                                TimeTicks finish_time,
+                                int64_t encoded_data_length,
+                                int64_t decoded_body_length,
+                                bool should_report_corb_blocking,
+                                ResponseSource) = 0;
+
+  // Called when a request fails.
+  virtual void DidFailLoading(const KURL&,
+                              uint64_t identifier,
+                              const ResourceError&,
+                              int64_t encoded_data_length,
+                              bool is_internal_request) = 0;
+
+  virtual void Trace(Visitor*) {}
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOAD_OBSERVER_H_
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index dd183e0..8912fb01 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -60,6 +60,7 @@
 #include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
 #include "third_party/blink/renderer/platform/loader/fetch/response_body_loader.h"
 #include "third_party/blink/renderer/platform/loader/fetch/shared_buffer_bytes_consumer.h"
 #include "third_party/blink/renderer/platform/loader/mixed_content_autoupgrade_status.h"
@@ -791,9 +792,11 @@
   Context().PrepareRequest(*new_request, resource_->Options().initiator_info,
                            unused_virtual_time_pauser,
                            resource_->GetType());
-  Context().DispatchWillSendRequest(
-      resource_->InspectorId(), *new_request, redirect_response_to_pass,
-      resource_->GetType(), options.initiator_info);
+  if (auto* observer = fetcher_->GetResourceLoadObserver()) {
+    observer->WillSendRequest(resource_->InspectorId(), *new_request,
+                              redirect_response_to_pass, resource_->GetType(),
+                              options.initiator_info);
+  }
 
   // First-party cookie logic moved from DocumentLoader in Blink to
   // net::URLRequest in the browser. Assert that Blink didn't try to change it
@@ -1008,9 +1011,11 @@
       response_with_type ? *response_with_type : response;
 
   // FrameType never changes during the lifetime of a request.
-  Context().DispatchDidReceiveResponse(
-      resource_->InspectorId(), initial_request, response_to_pass, resource_,
-      FetchContext::ResourceResponseType::kNotFromMemoryCache);
+  if (auto* observer = fetcher_->GetResourceLoadObserver()) {
+    observer->DidReceiveResponse(
+        resource_->InspectorId(), initial_request, response_to_pass, resource_,
+        ResourceLoadObserver::ResponseSource::kNotFromMemoryCache);
+  }
 
   // When streaming, unpause virtual time early to prevent deadlocking
   // against stream consumer in case stream has backpressure enabled.
@@ -1082,14 +1087,18 @@
 void ResourceLoader::DidReceiveData(const char* data, int length) {
   CHECK_GE(length, 0);
 
-  Context().DispatchDidReceiveData(resource_->InspectorId(), data, length);
+  if (auto* observer = fetcher_->GetResourceLoadObserver()) {
+    observer->DidReceiveData(resource_->InspectorId(),
+                             base::make_span(data, length));
+  }
   resource_->AppendData(data, length);
 }
 
 void ResourceLoader::DidReceiveTransferSizeUpdate(int transfer_size_diff) {
-  DCHECK_GT(transfer_size_diff, 0);
-  Context().DispatchDidReceiveEncodedData(resource_->InspectorId(),
-                                          transfer_size_diff);
+  if (auto* observer = fetcher_->GetResourceLoadObserver()) {
+    observer->DidReceiveTransferSizeUpdate(resource_->InspectorId(),
+                                           transfer_size_diff);
+  }
 }
 
 void ResourceLoader::DidFinishLoadingFirstPartInMultipart() {
@@ -1367,7 +1376,11 @@
   if (scheduler_client_id_ == ResourceLoadScheduler::kInvalidClientId)
     return;
 
-  Context().DispatchDidReceiveData(resource_->InspectorId(), nullptr, delta);
+  if (auto* observer = fetcher_->GetResourceLoadObserver()) {
+    observer->DidReceiveData(
+        resource_->InspectorId(),
+        base::span<const char>(nullptr, static_cast<size_t>(delta)));
+  }
   resource_->DidDownloadData(delta);
 }
 
@@ -1378,7 +1391,9 @@
   if (scheduler_client_id_ == ResourceLoadScheduler::kInvalidClientId)
     return;
 
-  Context().DispatchDidDownloadToBlob(resource_->InspectorId(), blob.get());
+  if (auto* observer = fetcher_->GetResourceLoadObserver()) {
+    observer->DidDownloadToBlob(resource_->InspectorId(), blob.get());
+  }
   resource_->DidDownloadToBlob(blob);
 
   blob_finished_ = true;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
index 189e5cc3..37c61db 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -58,7 +58,6 @@
       keepalive_(false),
       should_reset_app_cache_(false),
       allow_stale_response_(false),
-      stale_revalidate_candidate_(false),
       cache_mode_(mojom::FetchCacheMode::kDefault),
       skip_service_worker_(false),
       download_to_cache_only_(false),
@@ -105,7 +104,7 @@
       new_referrer.IsEmpty() ? Referrer::NoReferrer() : String(new_referrer);
   // TODO(domfarolino): Stop storing ResourceRequest's generated referrer as a
   // header and instead use a separate member. See https://crbug.com/850813.
-  request->SetHTTPReferrer(Referrer(referrer, new_referrer_policy));
+  request->SetHttpReferrer(Referrer(referrer, new_referrer_policy));
   request->SetSkipServiceWorker(skip_service_worker);
   request->SetRedirectStatus(RedirectStatus::kFollowedRedirect);
 
@@ -218,7 +217,7 @@
   http_header_fields_.Set(name, value);
 }
 
-void ResourceRequest::SetHTTPReferrer(const Referrer& referrer) {
+void ResourceRequest::SetHttpReferrer(const Referrer& referrer) {
   if (referrer.referrer.IsEmpty())
     http_header_fields_.Remove(http_names::kReferer);
   else
@@ -241,7 +240,7 @@
   http_header_fields_.Remove(http_names::kOrigin);
 }
 
-void ResourceRequest::SetHTTPOriginIfNeeded(const SecurityOrigin* origin) {
+void ResourceRequest::SetHttpOriginIfNeeded(const SecurityOrigin* origin) {
   if (NeedsHTTPOrigin())
     SetHTTPOrigin(origin);
 }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
index 726ddff..0ded11e 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -152,8 +152,8 @@
   const AtomicString& HttpReferrer() const {
     return HttpHeaderField(http_names::kReferer);
   }
-  void SetHTTPReferrer(const Referrer&);
-  bool DidSetHTTPReferrer() const { return did_set_http_referrer_; }
+  void SetHttpReferrer(const Referrer&);
+  bool DidSetHttpReferrer() const { return did_set_http_referrer_; }
   void ClearHTTPReferrer();
 
   void SetReferrerPolicy(network::mojom::ReferrerPolicy referrer_policy) {
@@ -173,7 +173,7 @@
   }
   void SetHTTPOrigin(const SecurityOrigin*);
   void ClearHTTPOrigin();
-  void SetHTTPOriginIfNeeded(const SecurityOrigin*);
+  void SetHttpOriginIfNeeded(const SecurityOrigin*);
   void SetHTTPOriginToMatchReferrerIfNeeded();
 
   void SetHTTPUserAgent(const AtomicString& http_user_agent) {
@@ -379,13 +379,6 @@
   void SetAllowStaleResponse(bool value) { allow_stale_response_ = value; }
   bool AllowsStaleResponse() const { return allow_stale_response_; }
 
-  void SetStaleRevalidateCandidate(bool value) {
-    stale_revalidate_candidate_ = value;
-  }
-  bool IsStaleRevalidateCandidate() const {
-    return stale_revalidate_candidate_;
-  }
-
   const base::Optional<base::UnguessableToken>& GetDevToolsToken() const {
     return devtools_token_;
   }
@@ -452,7 +445,6 @@
   bool keepalive_ : 1;
   bool should_reset_app_cache_ : 1;
   bool allow_stale_response_ : 1;
-  bool stale_revalidate_candidate_ : 1;
   mojom::FetchCacheMode cache_mode_;
   bool skip_service_worker_ : 1;
   bool download_to_cache_only_ : 1;
diff --git a/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc b/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
index dd14bf1..d8aaf80 100644
--- a/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/response_body_loader.cc
@@ -97,7 +97,7 @@
       return {};
     }
     auto handle = bytes_consumer_->DrainAsDataPipe();
-    if (handle) {
+    if (handle && bytes_consumer_->GetPublicState() == PublicState::kClosed) {
       HandleResult(Result::kDone);
     }
     return handle;
diff --git a/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc b/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
index b288ac0..e7cc1ea 100644
--- a/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
@@ -800,11 +800,14 @@
 
   EXPECT_TRUE(consumer.DrainAsDataPipe());
 
+  task_runner->RunUntilIdle();
+
   EXPECT_FALSE(client->LoadingIsCancelled());
   EXPECT_FALSE(client->LoadingIsFinished());
   EXPECT_FALSE(client->LoadingIsFailed());
 
-  task_runner->RunUntilIdle();
+  completion_notifier->SignalComplete();
+
   EXPECT_FALSE(client->LoadingIsCancelled());
   EXPECT_TRUE(client->LoadingIsFinished());
   EXPECT_FALSE(client->LoadingIsFailed());
diff --git a/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h b/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
index 8cf13a26..bcef719 100644
--- a/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
+++ b/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
@@ -34,20 +34,6 @@
   void CountUsage(mojom::WebFeature) const override {}
   void CountDeprecation(mojom::WebFeature) const override {}
 
-  // The last ResourceRequest passed to DispatchWillSendRequest.
-  base::Optional<ResourceRequest> RequestFromWillSendRequest() const {
-    return will_send_request_;
-  }
-
-  // FetchContext:
-  void DispatchWillSendRequest(
-      uint64_t identifier,
-      const ResourceRequest& request,
-      const ResourceResponse& redirect_response,
-      ResourceType,
-      const FetchInitiatorInfo& = FetchInitiatorInfo()) override {
-    will_send_request_ = request;
-  }
   bool AllowImage(bool images_enabled, const KURL&) const override {
     return true;
   }
@@ -75,7 +61,6 @@
 
  private:
   uint64_t transfer_size_ = 0;
-  base::Optional<ResourceRequest> will_send_request_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc b/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc
index 216cb4fd..5a411aa 100644
--- a/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc
+++ b/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc
@@ -192,13 +192,12 @@
     } else {
       mime_header->multipart_type_ =
           parsed_content_type.ParameterValueForName("type");
-      mime_header->end_of_part_boundary_ =
-          parsed_content_type.ParameterValueForName("boundary");
-      if (mime_header->end_of_part_boundary_.IsNull()) {
+      String boundary = parsed_content_type.ParameterValueForName("boundary");
+      if (boundary.IsNull()) {
         DVLOG(1) << "No boundary found in multipart MIME header.";
         return nullptr;
       }
-      mime_header->end_of_part_boundary_.insert("--", 0);
+      mime_header->end_of_part_boundary_ = "--" + boundary;
       mime_header->end_of_document_boundary_ =
           mime_header->end_of_part_boundary_;
       mime_header->end_of_document_boundary_ =
diff --git a/third_party/blink/renderer/platform/network/mime/mime_type_registry.cc b/third_party/blink/renderer/platform/network/mime/mime_type_registry.cc
index 67b20abd..7a8df3c 100644
--- a/third_party/blink/renderer/platform/network/mime/mime_type_registry.cc
+++ b/third_party/blink/renderer/platform/network/mime/mime_type_registry.cc
@@ -109,14 +109,6 @@
           EqualIgnoringASCIICase(mime_type, "image/webp"));
 }
 
-bool MIMETypeRegistry::IsModernImageMIMEType(const String& mime_type) {
-  return (EqualIgnoringASCIICase(mime_type, "image/gif") ||
-          EqualIgnoringASCIICase(mime_type, "image/jpeg") ||
-          EqualIgnoringASCIICase(mime_type, "image/png") ||
-          EqualIgnoringASCIICase(mime_type, "image/svg+xml") ||
-          EqualIgnoringASCIICase(mime_type, "image/webp"));
-}
-
 bool MIMETypeRegistry::IsSupportedJavaScriptMIMEType(const String& mime_type) {
   return blink::IsSupportedJavascriptMimeType(ToLowerASCIIOrEmpty(mime_type));
 }
diff --git a/third_party/blink/renderer/platform/network/mime/mime_type_registry.h b/third_party/blink/renderer/platform/network/mime/mime_type_registry.h
index 6d10852c..3a16835 100644
--- a/third_party/blink/renderer/platform/network/mime/mime_type_registry.h
+++ b/third_party/blink/renderer/platform/network/mime/mime_type_registry.h
@@ -64,10 +64,6 @@
   // Checks to see if a mime type is suitable for being encoded.
   static bool IsSupportedImageMIMETypeForEncoding(const String& mime_type);
 
-  // Checks to see if a mime type is one of the default modern formats supported
-  // when the 'legacy-image-formats' feature is disabled.
-  static bool IsModernImageMIMEType(const String& mime_type);
-
   // Checks to see if a mime type is suitable for being loaded as a JavaScript
   // resource.
   static bool IsSupportedJavaScriptMIMEType(const String& mime_type);
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 946af32..ba6b3d8 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1333,6 +1333,10 @@
       name: "SmoothScrollJSIntervention",
       status: "stable",
     },
+    {
+      name: "SpeechSynthesisEventCharLength",
+      status: "experimental",
+    },
     // Used as argument in attribute of stable-release functions/interfaces
     // where a runtime-enabled feature name is required for correct IDL syntax.
     // This is a global flag; do not change its status.
diff --git a/third_party/blink/renderer/platform/speech/platform_speech_synthesizer.h b/third_party/blink/renderer/platform/speech/platform_speech_synthesizer.h
index f15bc8ea..0739d16 100644
--- a/third_party/blink/renderer/platform/speech/platform_speech_synthesizer.h
+++ b/third_party/blink/renderer/platform/speech/platform_speech_synthesizer.h
@@ -52,7 +52,8 @@
   virtual void SpeakingErrorOccurred(PlatformSpeechSynthesisUtterance*) = 0;
   virtual void BoundaryEventOccurred(PlatformSpeechSynthesisUtterance*,
                                      SpeechBoundary,
-                                     unsigned char_index) = 0;
+                                     unsigned char_index,
+                                     unsigned char_length) = 0;
   virtual void VoicesDidChange() = 0;
 
  protected:
diff --git a/third_party/blink/renderer/platform/transforms/transformation_matrix.cc b/third_party/blink/renderer/platform/transforms/transformation_matrix.cc
index eaf0563..7a63f9d 100644
--- a/third_party/blink/renderer/platform/transforms/transformation_matrix.cc
+++ b/third_party/blink/renderer/platform/transforms/transformation_matrix.cc
@@ -30,6 +30,7 @@
 #include <cmath>
 #include <cstdlib>
 
+#include "base/compiler_specific.h"
 #include "third_party/blink/renderer/platform/geometry/float_box.h"
 #include "third_party/blink/renderer/platform/geometry/float_quad.h"
 #include "third_party/blink/renderer/platform/geometry/float_rect.h"
@@ -39,7 +40,6 @@
 #include "third_party/blink/renderer/platform/transforms/affine_transform.h"
 #include "third_party/blink/renderer/platform/transforms/rotation.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/cpu.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "ui/gfx/transform.h"
@@ -48,7 +48,7 @@
 #include <emmintrin.h>
 #endif
 
-#if HAVE_MIPS_MSA_INTRINSICS
+#if defined(HAVE_MIPS_MSA_INTRINSICS)
 #include "third_party/blink/renderer/platform/cpu/mips/common_macros_msa.h"
 #endif
 
@@ -340,7 +340,7 @@
       : "memory", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v16", "v17",
         "v18", "v19", "v20", "v21", "v22", "v23", "24", "25", "v26", "v27",
         "v28", "v29", "v30");
-#elif HAVE_MIPS_MSA_INTRINSICS
+#elif defined(HAVE_MIPS_MSA_INTRINSICS)
   const double rDet = 1 / det;
   const double* mat = &(matrix[0][0]);
   v2f64 mat0, mat1, mat2, mat3, mat4, mat5, mat6, mat7;
@@ -1345,7 +1345,7 @@
       : "memory", "x9", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
         "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", "v0", "v1",
         "v2", "v3", "v4", "v5", "v6", "v7");
-#elif HAVE_MIPS_MSA_INTRINSICS
+#elif defined(HAVE_MIPS_MSA_INTRINSICS)
   v2f64 v_right_m0, v_right_m1, v_right_m2, v_right_m3, v_right_m4, v_right_m5,
       v_right_m6, v_right_m7;
   v2f64 v_left_m0, v_left_m1, v_left_m2, v_left_m3, v_left_m4, v_left_m5,
diff --git a/third_party/blink/renderer/platform/wtf/BUILD.gn b/third_party/blink/renderer/platform/wtf/BUILD.gn
index 7b59536c..9d861555 100644
--- a/third_party/blink/renderer/platform/wtf/BUILD.gn
+++ b/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -50,7 +50,6 @@
     "casting.h",
     "conditional_destructor.h",
     "container_annotations.h",
-    "cpu.h",
     "date_math.cc",
     "date_math.h",
     "decimal.cc",
@@ -79,7 +78,6 @@
     "dtoa/utils.h",
     "dynamic_annotations.cc",
     "dynamic_annotations.h",
-    "experimental/container_type_operations.h",
     "forward.h",
     "functional.h",
     "get_ptr.h",
@@ -293,7 +291,6 @@
     "deque_test.cc",
     "doubly_linked_list_test.cc",
     "dtoa_test.cc",
-    "experimental/container_type_operations_test.cc",
     "functional_test.cc",
     "hash_map_test.cc",
     "hash_set_test.cc",
diff --git a/third_party/blink/renderer/platform/wtf/README.md b/third_party/blink/renderer/platform/wtf/README.md
index 179ffb5..5889044 100644
--- a/third_party/blink/renderer/platform/wtf/README.md
+++ b/third_party/blink/renderer/platform/wtf/README.md
@@ -61,10 +61,6 @@
 
   [threading.h], [threading_primitives.h]
 
-* **Compile-time switch macros**
-
-  [cpu.h] (e.g. `WTF_CPU_ARM_NEON`),
-
 * **Miscellaneous**
 
   [std_lib_extras.h] (`DEFINE_STATIC_LOCAL` etc.),
@@ -103,7 +99,6 @@
 [functional.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/functional.h
 [threading.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/threading.h
 [threading_primitives.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/threading_primitives.h
-[cpu.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/cpu.h
 [build_config.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/build_config.h
 [std_lib_extras.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/std_lib_extras.h
 [time.h]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/wtf/time.h
diff --git a/third_party/blink/renderer/platform/wtf/cpu.h b/third_party/blink/renderer/platform/wtf/cpu.h
deleted file mode 100644
index 033f6ee..0000000
--- a/third_party/blink/renderer/platform/wtf/cpu.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
- * Copyright (C) 2007-2009 Torch Mobile, Inc.
- * Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved.
- * Copyright (C) 2013 Samsung Electronics. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_CPU_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_CPU_H_
-
-#if defined(arm) || defined(__arm__) || defined(ARM) || defined(_ARM_)
-
-#if !defined(__ARMEB__) && !defined(__ARM_EABI__) && !defined(__EABI__) && \
-    !defined(__VFP_FP__) && !defined(_WIN32_WCE) && !defined(ANDROID)
-#error Chromium does not support middle endian architecture
-#endif
-
-// WTF_CPU_ARM_NEON is 0 or 1, and should not use defined(WTF_CPU_ARM_NEON).
-#if defined(__ARM_NEON__) && !defined(WTF_CPU_ARM_NEON)
-#define WTF_CPU_ARM_NEON 1
-#endif
-
-#endif /* ARM */
-
-#if !defined(WTF_CPU_ARM_NEON)
-#define WTF_CPU_ARM_NEON 0
-#endif
-
-// HAVE_MIPS_MSA_INTRINSICS is 0 or 1, and we should not use
-// defined(HAVE_MIPS_MSA_INTRINSICS).
-#if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5)
-#define HAVE_MIPS_MSA_INTRINSICS 1
-#else
-#define HAVE_MIPS_MSA_INTRINSICS 0
-#endif
-
-#endif /* WTF_CPU_h */
diff --git a/third_party/blink/renderer/platform/wtf/experimental/README.md b/third_party/blink/renderer/platform/wtf/experimental/README.md
deleted file mode 100644
index d2438d62..0000000
--- a/third_party/blink/renderer/platform/wtf/experimental/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# WTF Experimental
-
-This directory is a place for work-in-progress implementation of [HashTable v2].
-
-**Warning**: The content of this directory is not ready for production use.
-Don't use files in this directory without prior consent of the author.
-
-## Experimental files policy
-
-The use of experimental files must be closely controlled and monitored by
-the author. If any anomalies caused by files in this directory are observed,
-please contact the author (essentially yutak@chromium.org) immediately.
-
-When files in this directory become ready for production use, they should be
-moved out of this directory.
-
-[HashTable v2]: https://docs.google.com/document/d/1-N-vUWg790wJc1CHCC4C_v-HtQNg9n9w5Y_6KtaKFlU/edit?usp=sharing
diff --git a/third_party/blink/renderer/platform/wtf/experimental/container_type_operations.h b/third_party/blink/renderer/platform/wtf/experimental/container_type_operations.h
deleted file mode 100644
index 2383a04..0000000
--- a/third_party/blink/renderer/platform/wtf/experimental/container_type_operations.h
+++ /dev/null
@@ -1,621 +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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_EXPERIMENTAL_CONTAINER_TYPE_OPERATIONS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_EXPERIMENTAL_CONTAINER_TYPE_OPERATIONS_H_
-
-// *****************************************************************************
-// EXPERIMENTAL: DO NOT USE IN PRODUCTION CODE YET!
-// *****************************************************************************
-
-#include <stdint.h>
-#include <type_traits>
-#include <utility>
-
-namespace WTF {
-namespace experimental {
-
-// ContainerTypeOperations defines type operations in containers that are not
-// specific to container implementation, such as placement initialization and
-// copying or moving elements.
-//
-// The class template ContainerTypeOperations can be specialized so you can
-// define customized operations such as fast copy with memcpy().
-//
-// TODO(yutak): Implement good enough defaults for common data types such as
-// fundamental types or scoped_refptr<T>, so in most cases people don't have to
-// care about those functions.
-//
-// ====================================
-// ContainerTypeOperations requirements
-// ====================================
-//
-// Each ContainerTypeOperations implementation must meet all the requiements
-// marked as "minimal complete definition" below. The absent functions will be
-// supplemented with sensible defaults created from present functions.
-//
-// Naming conventions used below:
-//
-//     uninitialized_storage (or simply "uninitialized")
-//         A variable name indicating the memory it points to is in the
-//         container's storage, and is uninitialized, that is, T's constructor
-//         is not called on it.
-//     storage
-//         A variable name indicating the memory it points to is in the
-//         container's storage, and is initialized.
-//     value
-//         A variable name indicating the memory it points to is not necessarily
-//         in the container's storage. Generally, it indicates a value specified
-//         by the user of the container.
-//     T
-//         The main value type of the container. The container's storage will
-//         contain an array of Ts.
-//     InT
-//         A type name that's possibly different from T. The actual type depends
-//         on what the user code has specified to a member function of a
-//         container. This is useful to avoid type conversions to T, and this
-//         technique is called "heterogeneous lookup" (introduced in C++14
-//         version of std containers).
-//
-//         In the actual traits implementation, the corresponding function does
-//         not have to be a function template. It can be a set of overloaded
-//         functions, or even a combination of function templates and
-//         functions, as long as all the desirable input types can be accepted.
-//         For example, suppose you are implementing Assign() explained below.
-//         In this case, both of the following are OK:
-//
-//         (a) Accepts any input value
-//             template <typename InT>
-//             static void Assign(T& storage, InT&& value);
-//
-//         (b) Accepts String and const char* (suppose T is String-ish)
-//             static void Assign(T& storage, const String& value);
-//             static void Assign(T& storage, const char* value);
-//
-//         At least, T must be acceptable as a replacement of InT in any
-//         function definitions.
-//
-// 1. Default initialization
-//
-//     static void DefaultInitialize(T& uninitialized);
-//     static void DefaultInitializeRange(T* uninitialized_begin,
-//                                        T* uninitialized_end);
-//
-//     Minimal complete definition:
-//     DefaultInitialize() or DefaultInitializeRange().
-//
-//     After one of these functions is called, the memory range will become
-//     initialized.
-//
-// 2. Destruction
-//
-//     static void Destruct(T& storage);
-//     static void DestructRange(T* storage_begin,
-//                               T* storage_end);
-//
-//     Minimal complete definition: Destruct() or DestructRange().
-//
-//     After one of these functions is called, the memory range will become
-//     uninitialized.
-//
-// 3. Copy and move
-//
-//     static void Assign(T& storage, const InT& value);  // Copy
-//     static void Assign(T& storage, InT&& value);  // Move
-//     // Note: you can implement both in one function template if you use
-//     // "forwarding reference".
-//
-//     static void CopyRange(const InT* value_begin,
-//                           const InT* value_end,
-//                           T* storage_begin);
-//     static void MoveRange(InT* value_begin,
-//                           InT* value_end,
-//                           T* storage_begin);
-//
-//     static void CopyOverlappingRange(const InT* value_begin,
-//                                      const InT* value_end,
-//                                      T* storage_begin);
-//     static void MoveOverlappingRange(InT* value_begin,
-//                                      InT* value_end,
-//                                      T* storage_begin);
-//
-//     Minimal complete definition: Copying Assign().
-//
-//     The storage will remain initialized even after moving, as if you call
-//     std::move(). You need to destruct the elements separately.
-//
-// 4. Uninitialized copy and fill
-//
-//     static void UninitializedCopy(const InT* value_begin,
-//                                   const InT* value_end,
-//                                   T* uninitialized_begin);
-//
-//     static void UninitializedFill(const InT& value,
-//                                   T* uninitialized_begin,
-//                                   T* uninitialized_end);
-//
-//     Minimal complete definition: None (Will be implemented as initialize +
-//     copy).
-//
-// 5. Equality
-//
-//     static bool Equal(const T& stored_value,
-//                       const InT& other_value);
-//     static bool EqualRange(const T* storage_begin,
-//                            const T* storage_end,
-//                            const InT* other_begin);
-//
-//     Minimal complete definition: Equal() or EqualRange().
-
-//
-// GenericContainerTypeOperations
-//
-
-// This class template defines type operations that work for any type T.
-template <typename T>
-struct GenericContainerTypeOperations {
-  static void DefaultInitialize(T& uninitialized);
-
-  static void Destruct(T& storage);
-
-  template <typename InT>
-  static void Assign(T& storage, InT&& value);
-
-  template <typename InT>
-  static void UninitializedCopy(const InT* value_begin,
-                                const InT* value_end,
-                                T* uninitialized_begin);
-
-  template <typename InT>
-  static void UninitializedFill(const InT& value,
-                                T* uninitialized_begin,
-                                T* uninitialized_end);
-
-  template <typename InT>
-  static bool Equal(const T& stored_value, const InT& other_value);
-};
-
-//
-// ContainerTypeOperations
-//
-
-// The global definition of ContainerTypeOperations.
-template <typename T>
-struct ContainerTypeOperations : GenericContainerTypeOperations<T> {};
-
-// TODO(yutak): More specializations for POD types and smart pointers.
-
-//
-// CompleteContainerTypeOperations
-//
-
-// CompleteContainerTypeOperations supplements missing functions as defined
-// above and creates a class template that has every function listed above.
-
-namespace internal {
-// This internal block contains all the implementation detail needed to
-// supplement the missing functions in ContainerTypeOperations<T>.
-
-// Define a predicate struct named Has##FunctionName##Function that tests the
-// existence of a static member function |FunctionName| in TypeOperation taking
-// the arguments specified in the "..." part of the macro.
-#define DEFINE_FUNCTION_DETECTOR(FunctionName, ...)                 \
-  template <typename TypeOperations, typename T>                    \
-  auto test##FunctionName##Function(int32_t)->decltype(             \
-      TypeOperations::FunctionName(__VA_ARGS__), std::true_type()); \
-  template <typename TypeOperations, typename T>                    \
-  std::false_type test##FunctionName##Function(int64_t);            \
-  template <typename TypeOperations, typename T>                    \
-  struct Has##FunctionName##Function                                \
-      : decltype(test##FunctionName##Function<TypeOperations, T>(0)) {}
-// A semicolon is required after the macro use.
-
-// In the following, we define a number of class templates named
-// <FunctionName>Supplement, which provides the default implementation of the
-// function if it is missing in TypeOperations.
-
-DEFINE_FUNCTION_DETECTOR(DefaultInitialize, std::declval<T&>());
-DEFINE_FUNCTION_DETECTOR(DefaultInitializeRange,
-                         std::declval<T*>(),
-                         std::declval<T*>());
-
-template <typename TypeOperations,
-          typename T,
-          bool hasDefaultInitializeFunction =
-              HasDefaultInitializeFunction<TypeOperations, T>::value,
-          bool hasDefaultInitializeRangeFunction =
-              HasDefaultInitializeRangeFunction<TypeOperations, T>::value>
-struct DefaultInitializeSupplement;
-
-template <typename TypeOperations, typename T>
-struct DefaultInitializeSupplement<TypeOperations, T, true, true> {};
-
-template <typename TypeOperations, typename T>
-struct DefaultInitializeSupplement<TypeOperations, T, true, false> {
-  static void DefaultInitializeRange(T* uninitialized_begin,
-                                     T* uninitialized_end) {
-    for (T* uninitialized = uninitialized_begin;
-         uninitialized != uninitialized_end; ++uninitialized) {
-      TypeOperations::DefaultInitialize(*uninitialized);
-    }
-  }
-};
-
-template <typename TypeOperations, typename T>
-struct DefaultInitializeSupplement<TypeOperations, T, false, true> {
-  static void DefaultInitialize(T& uninitialized) {
-    TypeOperations::DefaultInitializeRange(&uninitialized, &uninitialized + 1);
-  }
-};
-
-// DefaultInitializeSupplement<TypeOperations, T, false, false> is invalid.
-
-DEFINE_FUNCTION_DETECTOR(Destruct, std::declval<T&>());
-DEFINE_FUNCTION_DETECTOR(DestructRange, std::declval<T*>(), std::declval<T*>());
-
-template <typename TypeOperations,
-          typename T,
-          bool hasDestructFunction =
-              HasDestructFunction<TypeOperations, T>::value,
-          bool hasDestructRangeFunction =
-              HasDestructRangeFunction<TypeOperations, T>::value>
-struct DestructSupplement;
-
-template <typename TypeOperations, typename T>
-struct DestructSupplement<TypeOperations, T, true, true> {};
-
-template <typename TypeOperations, typename T>
-struct DestructSupplement<TypeOperations, T, true, false> {
-  static void DestructRange(T* storage_begin, T* storage_end) {
-    for (T* storage = storage_begin; storage != storage_end; ++storage) {
-      TypeOperations::Destruct(*storage);
-    }
-  }
-};
-
-template <typename TypeOperations, typename T>
-struct DestructSupplement<TypeOperations, T, false, true> {
-  static void Destruct(T& storage) {
-    TypeOperations::DestructRange(&storage, &storage + 1);
-  }
-};
-
-// DestructSupplement<TypeOperations, T, false, false> is invalid.
-
-DEFINE_FUNCTION_DETECTOR(CopyRange,
-                         std::declval<const T*>(),
-                         std::declval<const T*>(),
-                         std::declval<T*>());
-
-template <typename TypeOperations,
-          typename T,
-          bool hasCopyRangeFunction =
-              HasCopyRangeFunction<TypeOperations, T>::value>
-struct CopyRangeSupplement;
-
-template <typename TypeOperations, typename T>
-struct CopyRangeSupplement<TypeOperations, T, true> {};
-
-template <typename TypeOperations, typename T>
-struct CopyRangeSupplement<TypeOperations, T, false> {
-  template <typename InT>
-  static void CopyRange(const InT* value_begin,
-                        const InT* value_end,
-                        T* storage_begin) {
-    T* storage = storage_begin;
-    for (const InT *value = value_begin; value < value_end;
-         ++value, ++storage) {
-      TypeOperations::Assign(*storage, *value);
-    }
-  }
-};
-
-DEFINE_FUNCTION_DETECTOR(MoveRange,
-                         std::declval<T*>(),
-                         std::declval<T*>(),
-                         std::declval<T*>());
-
-template <typename TypeOperations,
-          typename T,
-          bool hasMoveRangeFunction =
-              HasMoveRangeFunction<TypeOperations, T>::value>
-struct MoveRangeSupplement;
-
-template <typename TypeOperations, typename T>
-struct MoveRangeSupplement<TypeOperations, T, true> {};
-
-template <typename TypeOperations, typename T>
-struct MoveRangeSupplement<TypeOperations, T, false> {
-  template <typename InT>
-  static void MoveRange(InT* value_begin, InT* value_end, T* storage_begin) {
-    T* storage = storage_begin;
-    for (InT *value = value_begin; value != value_end; ++value, ++storage) {
-      TypeOperations::Assign(*storage, std::move(*value));
-    }
-  }
-};
-
-DEFINE_FUNCTION_DETECTOR(CopyOverlappingRange,
-                         std::declval<const T*>(),
-                         std::declval<const T*>(),
-                         std::declval<T*>());
-
-template <typename TypeOperations,
-          typename T,
-          bool hasCopyOverlappingRangeFunction =
-              HasCopyOverlappingRangeFunction<TypeOperations, T>::value>
-struct CopyOverlappingRangeSupplement;
-
-template <typename TypeOperations, typename T>
-struct CopyOverlappingRangeSupplement<TypeOperations, T, true> {};
-
-template <typename TypeOperations, typename T>
-struct CopyOverlappingRangeSupplement<TypeOperations, T, false> {
-  template <typename InT>
-  static void CopyOverlappingRange(const T* value_begin,
-                                   const T* value_end,
-                                   InT* storage_begin) {
-    const void* value_address = reinterpret_cast<const void*>(value_begin);
-    const void* storage_address = reinterpret_cast<const void*>(storage_begin);
-
-    if (value_address > storage_address) {
-      // Copy forward.
-      //
-      // SupplementedTypeOperations::CopyRange() cannot be used here, because
-      // user-supplied CopyRange() may not support overlapping cases.
-      //
-      // Our own implementation is safe, so we delegate the work to
-      // CopyRangeSupplement<TypeOperations, T, false>.
-      CopyRangeSupplement<TypeOperations, T, false>::CopyRange(
-          value_begin, value_end, storage_begin);
-    } else if (value_address < storage_address) {
-      // Copy backward.
-      if (value_begin == value_end)
-        return;
-      const T* value = value_end;
-      T* storage = storage_begin + (value_end - value_begin);
-      do {
-        --value;
-        --storage;
-        TypeOperations::Assign(*storage, *value);
-      } while (value != value_begin);
-    }
-  }
-};
-
-DEFINE_FUNCTION_DETECTOR(MoveOverlappingRange,
-                         std::declval<T*>(),
-                         std::declval<T*>(),
-                         std::declval<T*>());
-
-template <typename TypeOperations,
-          typename T,
-          bool hasMoveOverlappingRange =
-              HasMoveOverlappingRangeFunction<TypeOperations, T>::value>
-struct MoveOverlappingRangeSupplement;
-
-template <typename TypeOperations, typename T>
-struct MoveOverlappingRangeSupplement<TypeOperations, T, true> {};
-
-template <typename TypeOperations, typename T>
-struct MoveOverlappingRangeSupplement<TypeOperations, T, false> {
-  template <typename InT>
-  static void MoveOverlappingRange(T* value_begin,
-                                   T* value_end,
-                                   InT* storage_begin) {
-    const void* value_address = reinterpret_cast<const void*>(value_begin);
-    const void* storage_address = reinterpret_cast<const void*>(storage_begin);
-
-    if (value_address > storage_address) {
-      // Move forward.
-      MoveRangeSupplement<TypeOperations, T, false>::MoveRange(
-          value_begin, value_end, storage_begin);
-    } else if (value_address < storage_address) {
-      // Move backward.
-      if (value_begin == value_end)
-        return;
-      const T* value = value_end;
-      T* storage = storage_begin + (value_end - value_begin);
-      do {
-        --value;
-        --storage;
-        TypeOperations::Assign(*storage, std::move(*value));
-      } while (value != value_begin);
-    }
-  }
-};
-
-DEFINE_FUNCTION_DETECTOR(UninitializedCopy,
-                         std::declval<const T*>(),
-                         std::declval<const T*>(),
-                         std::declval<T*>());
-
-template <typename TypeOperations,
-          typename T,
-          bool hasUninitializedCopy =
-              HasUninitializedCopyFunction<TypeOperations, T>::value>
-struct UninitializedCopySupplement;
-
-template <typename TypeOperations, typename T>
-struct UninitializedCopySupplement<TypeOperations, T, true> {};
-
-template <typename TypeOperations, typename T>
-struct UninitializedCopySupplement<TypeOperations, T, false> {
-  template <typename InT>
-  static void UninitializedCopy(const InT* value_begin,
-                                const InT* value_end,
-                                T* uninitialized_begin) {
-    // To pick the correct version of DefaultInitialize().
-    struct SupplementedTypeOperations
-        : TypeOperations,
-          DefaultInitializeSupplement<TypeOperations, T> {};
-    T* uninitialized = uninitialized_begin;
-    for (const InT *value = value_begin; value != value_end;
-         ++value, ++uninitialized) {
-      SupplementedTypeOperations::DefaultInitialize(*uninitialized);
-      SupplementedTypeOperations::Assign(*uninitialized, *value);
-    }
-  }
-};
-
-DEFINE_FUNCTION_DETECTOR(UninitializedFill,
-                         std::declval<const T&>(),
-                         std::declval<T*>(),
-                         std::declval<T*>());
-
-template <typename TypeOperations,
-          typename T,
-          bool hasUninitializedFill =
-              HasUninitializedFillFunction<TypeOperations, T>::value>
-struct UninitializedFillSupplement;
-
-template <typename TypeOperations, typename T>
-struct UninitializedFillSupplement<TypeOperations, T, true> {};
-
-template <typename TypeOperations, typename T>
-struct UninitializedFillSupplement<TypeOperations, T, false> {
-  template <typename InT>
-  static void UninitializedFill(const InT& value,
-                                T* uninitialized_begin,
-                                T* uninitialized_end) {
-    struct SupplementedTypeOperations
-        : TypeOperations,
-          DefaultInitializeSupplement<TypeOperations, T> {};
-    for (T* uninitialized = uninitialized_begin;
-         uninitialized != uninitialized_end; ++uninitialized) {
-      SupplementedTypeOperations::DefaultInitialize(*uninitialized);
-      SupplementedTypeOperations::Assign(*uninitialized, value);
-    }
-  }
-};
-
-DEFINE_FUNCTION_DETECTOR(Equal,
-                         std::declval<const T&>(),
-                         std::declval<const T&>());
-DEFINE_FUNCTION_DETECTOR(EqualRange,
-                         std::declval<const T*>(),
-                         std::declval<const T*>(),
-                         std::declval<const T*>());
-
-template <typename TypeOperations,
-          typename T,
-          bool hasEqual = HasEqualFunction<TypeOperations, T>::value,
-          bool hasEqualRange = HasEqualRangeFunction<TypeOperations, T>::value>
-struct EqualSupplement;
-
-template <typename TypeOperations, typename T>
-struct EqualSupplement<TypeOperations, T, true, true> {};
-
-template <typename TypeOperations, typename T>
-struct EqualSupplement<TypeOperations, T, true, false> {
-  template <typename InT>
-  static bool EqualRange(const T* storage_begin,
-                         const T* storage_end,
-                         const InT* other_begin) {
-    const InT* other = other_begin;
-    for (const T *storage = storage_begin; storage != storage_end;
-         ++storage, ++other) {
-      if (!TypeOperations::Equal(*storage, *other))
-        return false;
-    }
-    return true;
-  }
-};
-
-template <typename TypeOperations, typename T>
-struct EqualSupplement<TypeOperations, T, false, true> {
-  template <typename InT>
-  static bool Equal(const T& stored_value, const InT& other_value) {
-    return TypeOperations::EqualRange(&stored_value, &stored_value + 1,
-                                      &other_value);
-  }
-};
-
-// EqualSupplement<TypeOperations, T, false, false> is invalid.
-
-#undef DEFINE_FUNCTION_DETECTOR
-
-}  // namespace internal
-
-// Finally, CompleteContainerTypeOperations is defined by concerting all the
-// supplement classes. This can be applied to any ContainerTypeOperations
-// conforming to the requirements above.
-template <typename TypeOperations, typename T>
-struct CompleteContainerTypeOperations
-    : TypeOperations,
-      internal::DefaultInitializeSupplement<TypeOperations, T>,
-      internal::DestructSupplement<TypeOperations, T>,
-      internal::CopyRangeSupplement<TypeOperations, T>,
-      internal::MoveRangeSupplement<TypeOperations, T>,
-      internal::CopyOverlappingRangeSupplement<TypeOperations, T>,
-      internal::MoveOverlappingRangeSupplement<TypeOperations, T>,
-      internal::UninitializedCopySupplement<TypeOperations, T>,
-      internal::UninitializedFillSupplement<TypeOperations, T>,
-      internal::EqualSupplement<TypeOperations, T> {};
-
-//
-// CompletedContainerTypeOperations
-//
-
-// Complete*d*ContainerTypeOperations is ContainerTypeOperations<T> with
-// supplemented functions.
-template <typename T>
-struct CompletedContainerTypeOperations
-    : CompleteContainerTypeOperations<ContainerTypeOperations<T>, T> {};
-
-//
-// GenericContainerTypeOperations<T> definitions
-//
-
-template <typename T>
-void GenericContainerTypeOperations<T>::DefaultInitialize(T& uninitialized) {
-  new (&uninitialized) T;
-}
-
-template <typename T>
-void GenericContainerTypeOperations<T>::Destruct(T& storage) {
-  storage.~T();
-}
-
-template <typename T>
-template <typename InT>
-void GenericContainerTypeOperations<T>::Assign(T& storage, InT&& value) {
-  storage = std::forward<InT>(value);
-}
-
-template <typename T>
-template <typename InT>
-void GenericContainerTypeOperations<T>::UninitializedCopy(
-    const InT* value_begin,
-    const InT* value_end,
-    T* uninitialized_begin) {
-  const InT* value = value_begin;
-  T* uninitialized = uninitialized_begin;
-  for (; value != value_end; ++value, ++uninitialized)
-    new (uninitialized) T(*value);
-}
-
-template <typename T>
-template <typename InT>
-void GenericContainerTypeOperations<T>::UninitializedFill(
-    const InT& value,
-    T* uninitialized_begin,
-    T* uninitialized_end) {
-  for (T* uninitialized = uninitialized_begin;
-       uninitialized != uninitialized_end; ++uninitialized) {
-    new (uninitialized) T(value);
-  }
-}
-
-template <typename T>
-template <typename InT>
-bool GenericContainerTypeOperations<T>::Equal(const T& stored_value,
-                                              const InT& other_value) {
-  return stored_value == other_value;
-}
-
-}  // namespace experimental
-}  // namespace WTF
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_EXPERIMENTAL_CONTAINER_TYPE_OPERATIONS_H_
diff --git a/third_party/blink/renderer/platform/wtf/experimental/container_type_operations_test.cc b/third_party/blink/renderer/platform/wtf/experimental/container_type_operations_test.cc
deleted file mode 100644
index 4d56398..0000000
--- a/third_party/blink/renderer/platform/wtf/experimental/container_type_operations_test.cc
+++ /dev/null
@@ -1,83 +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 "third_party/blink/renderer/platform/wtf/experimental/container_type_operations.h"
-
-#include <cstring>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace WTF {
-namespace experimental {
-
-namespace {
-
-struct Pod {
-  int a;
-  int* b;
-  char c[7];
-};
-
-bool operator==(const Pod& left, const Pod& right) {
-  return left.a == right.a && left.b == right.b &&
-         memcmp(left.c, right.c, sizeof(left.c)) == 0;
-}
-
-}  // namespace
-
-template <typename T>
-class ContainerTypeOperationsTest : public testing::Test {};
-
-TYPED_TEST_SUITE_P(ContainerTypeOperationsTest);
-
-TYPED_TEST_P(ContainerTypeOperationsTest, Completeness) {
-  using Ops = CompletedContainerTypeOperations<TypeParam>;
-  // Call all functions in Ops and make sure they are callable.
-
-  constexpr size_t SIZE = 4;
-  // We need to initialize the content of |data| to let the compiler think
-  // accessing this memory is safe. If the compiler detects undefined behavior,
-  // it may "optimize" the code in an unexpected way and make the assertions
-  // fail.
-  alignas(TypeParam) char data[sizeof(TypeParam) * SIZE] = {0};
-  TypeParam* storage = reinterpret_cast<TypeParam*>(data);
-
-  Ops::DefaultInitialize(*storage);
-  Ops::Destruct(*storage);
-
-  Ops::DefaultInitializeRange(storage, storage + SIZE);
-  Ops::DestructRange(storage, storage + SIZE);
-
-  Ops::DefaultInitializeRange(storage, storage + SIZE);
-  // We also need to zero-initialize this variable for the same reason as above.
-  TypeParam lvalue{};
-  Ops::Assign(*storage, lvalue);
-  Ops::Assign(*storage, TypeParam());  // rvalue.
-  Ops::CopyRange(storage, storage + 2, storage + 2);
-  Ops::MoveRange(storage, storage + 2, storage + 2);
-  Ops::CopyOverlappingRange(storage, storage + 3, storage + 1);
-  Ops::MoveOverlappingRange(storage, storage + 3, storage + 1);
-
-  Ops::DestructRange(storage, storage + 2);
-  Ops::UninitializedCopy(storage + 2, storage + 4, storage);
-  Ops::DestructRange(storage, storage + 2);
-  Ops::UninitializedFill(lvalue, storage, storage + 2);
-
-  // The first element may be moved. Let's make sure it is in some valid state.
-  Ops::Assign(*storage, lvalue);
-
-  EXPECT_TRUE(Ops::Equal(*storage, *storage));
-  EXPECT_TRUE(Ops::EqualRange(storage, storage + SIZE, storage));
-
-  Ops::DestructRange(storage, storage + SIZE);
-}
-
-REGISTER_TYPED_TEST_SUITE_P(ContainerTypeOperationsTest, Completeness);
-
-using PodTestTypes = testing::Types<int, char, int*, Pod>;
-
-INSTANTIATE_TYPED_TEST_SUITE_P(Pod, ContainerTypeOperationsTest, PodTestTypes);
-
-}  // namespace experimental
-}  // namespace WTF
diff --git a/third_party/blink/renderer/platform/wtf/math_extras.h b/third_party/blink/renderer/platform/wtf/math_extras.h
index 6ff8162..724f607f 100644
--- a/third_party/blink/renderer/platform/wtf/math_extras.h
+++ b/third_party/blink/renderer/platform/wtf/math_extras.h
@@ -29,10 +29,10 @@
 #include <cmath>
 #include <cstddef>
 #include <limits>
+
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/cpu.h"
 
 #if defined(COMPILER_MSVC)
 // Make math.h behave like other platforms.
diff --git a/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h b/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h
index 96b56b4..bb2566f 100644
--- a/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h
+++ b/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h
@@ -23,8 +23,9 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_ASCII_FAST_PATH_H_
 
 #include <stdint.h>
+
+#include "base/compiler_specific.h"
 #include "build/build_config.h"
-#include "third_party/blink/renderer/platform/wtf/cpu.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/unicode.h"
 
@@ -148,7 +149,7 @@
     DCHECK(!(source[i] & 0xff00));
     destination[i] = static_cast<LChar>(source[i]);
   }
-#elif defined(COMPILER_GCC) && WTF_CPU_ARM_NEON && \
+#elif defined(COMPILER_GCC) && defined(CPU_ARM_NEON) && \
     !defined(ARCH_CPU_BIG_ENDIAN) && defined(NDEBUG)
   const LChar* const end = destination + length;
   const uintptr_t kMemoryAccessSize = 8;
diff --git a/third_party/blink/renderer/platform/wtf/text/wtf_string.cc b/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
index d8f31a6..5dd32b4 100644
--- a/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
+++ b/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
@@ -66,53 +66,6 @@
     : String(characters, SafeCast<unsigned>(length)) {}
 #endif  // defined(ARCH_CPU_64_BITS)
 
-void String::append(const StringView& string) {
-  if (string.IsEmpty())
-    return;
-  if (!impl_) {
-    impl_ = string.ToString().ReleaseImpl();
-    return;
-  }
-
-  // FIXME: This is extremely inefficient. So much so that we might want to
-  // take this out of String's API. We can make it better by optimizing the
-  // case where exactly one String is pointing at this StringImpl, but even
-  // then it's going to require a call into the allocator every single time.
-
-  if (impl_->Is8Bit() && string.Is8Bit()) {
-    LChar* data;
-    CHECK_LE(string.length(),
-             std::numeric_limits<unsigned>::max() - impl_->length());
-    scoped_refptr<StringImpl> new_impl = StringImpl::CreateUninitialized(
-        impl_->length() + string.length(), data);
-    memcpy(data, impl_->Characters8(), impl_->length() * sizeof(LChar));
-    memcpy(data + impl_->length(), string.Characters8(),
-           string.length() * sizeof(LChar));
-    impl_ = std::move(new_impl);
-    return;
-  }
-
-  UChar* data;
-  CHECK_LE(string.length(),
-           std::numeric_limits<unsigned>::max() - impl_->length());
-  scoped_refptr<StringImpl> new_impl =
-      StringImpl::CreateUninitialized(impl_->length() + string.length(), data);
-
-  if (impl_->Is8Bit())
-    StringImpl::CopyChars(data, impl_->Characters8(), impl_->length());
-  else
-    StringImpl::CopyChars(data, impl_->Characters16(), impl_->length());
-
-  if (string.Is8Bit())
-    StringImpl::CopyChars(data + impl_->length(), string.Characters8(),
-                          string.length());
-  else
-    StringImpl::CopyChars(data + impl_->length(), string.Characters16(),
-                          string.length());
-
-  impl_ = std::move(new_impl);
-}
-
 int CodePointCompare(const String& a, const String& b) {
   return CodePointCompare(a.Impl(), b.Impl());
 }
@@ -122,67 +75,6 @@
                                            reinterpret_cast<const LChar*>(b));
 }
 
-template <typename CharType>
-scoped_refptr<StringImpl> InsertInternal(scoped_refptr<StringImpl> impl,
-                                         const CharType* characters_to_insert,
-                                         unsigned length_to_insert,
-                                         unsigned position) {
-  if (!length_to_insert)
-    return impl;
-
-  DCHECK(characters_to_insert);
-  UChar* data;  // FIXME: We should be able to create an 8 bit string here.
-  CHECK_LE(length_to_insert,
-           std::numeric_limits<unsigned>::max() - impl->length());
-  scoped_refptr<StringImpl> new_impl =
-      StringImpl::CreateUninitialized(impl->length() + length_to_insert, data);
-
-  if (impl->Is8Bit())
-    StringImpl::CopyChars(data, impl->Characters8(), position);
-  else
-    StringImpl::CopyChars(data, impl->Characters16(), position);
-
-  StringImpl::CopyChars(data + position, characters_to_insert,
-                        length_to_insert);
-
-  if (impl->Is8Bit())
-    StringImpl::CopyChars(data + position + length_to_insert,
-                          impl->Characters8() + position,
-                          impl->length() - position);
-  else
-    StringImpl::CopyChars(data + position + length_to_insert,
-                          impl->Characters16() + position,
-                          impl->length() - position);
-
-  return new_impl;
-}
-
-void String::insert(const StringView& string, unsigned position) {
-  if (string.IsEmpty()) {
-    if (string.IsNull())
-      return;
-    if (IsNull())
-      impl_ = string.ToString().ReleaseImpl();
-    return;
-  }
-
-  if (position >= length()) {
-    if (string.Is8Bit())
-      append(string);
-    else
-      append(string);
-    return;
-  }
-
-  DCHECK(impl_);
-  if (string.Is8Bit())
-    impl_ = InsertInternal(std::move(impl_), string.Characters8(),
-                           string.length(), position);
-  else
-    impl_ = InsertInternal(std::move(impl_), string.Characters16(),
-                           string.length(), position);
-}
-
 UChar32 String::CharacterStartingAt(unsigned i) const {
   if (!impl_ || i >= impl_->length())
     return 0;
diff --git a/third_party/blink/renderer/platform/wtf/text/wtf_string.h b/third_party/blink/renderer/platform/wtf/text/wtf_string.h
index 63c5782..c437f113 100644
--- a/third_party/blink/renderer/platform/wtf/text/wtf_string.h
+++ b/third_party/blink/renderer/platform/wtf/text/wtf_string.h
@@ -269,8 +269,6 @@
     return impl_ ? impl_->EndsWith(character) : false;
   }
 
-  void insert(const StringView&, unsigned pos);
-
   // TODO(esprehn): replace strangely both modifies this String *and* return a
   // value. It should only do one of those.
   String& Replace(UChar pattern, UChar replacement) {
@@ -487,8 +485,8 @@
   static String Make8BitFrom16BitSource(const UChar*,
                                         wtf_size_t) WARN_UNUSED_RESULT;
   template <wtf_size_t inlineCapacity>
-  static String Make8BitFrom16BitSource(
-      const Vector<UChar, inlineCapacity>& buffer) WARN_UNUSED_RESULT {
+  static WARN_UNUSED_RESULT String
+  Make8BitFrom16BitSource(const Vector<UChar, inlineCapacity>& buffer) {
     return Make8BitFrom16BitSource(buffer.data(), buffer.size());
   }
 
@@ -538,8 +536,6 @@
  private:
   friend struct HashTraits<String>;
 
-  void append(const StringView&);
-
   scoped_refptr<StringImpl> impl_;
 };
 
diff --git a/third_party/blink/tools/blinkpy/style/checkers/cpp.py b/third_party/blink/tools/blinkpy/style/checkers/cpp.py
index 90c55040..e7ab3a7 100644
--- a/third_party/blink/tools/blinkpy/style/checkers/cpp.py
+++ b/third_party/blink/tools/blinkpy/style/checkers/cpp.py
@@ -1866,7 +1866,7 @@
     # FIXME: figure out if they're using default arguments in fn proto.
 
     # Check if they're using a precise-width integer type.
-    matched = search(r'\b((un)?signed\s+)?(short|long\s+long)\b', line)
+    matched = search(r'\b((un)?signed\s+)?(short|(long\s+)?long)\b', line)
     if matched:
         error(line_number, 'runtime/int', 1,
               'Use a precise-width integer type from <stdint.h> or <cstdint>'
diff --git a/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py b/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
index 1e16baa..2ac8cc0 100644
--- a/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
+++ b/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
@@ -467,6 +467,14 @@
         self.assert_lint('signed long   long a = 1', errmsg % 'signed long   long  [runtime/int] [1]')
         self.assert_lint('long long a = 1', errmsg % 'long long  [runtime/int] [1]')
         self.assert_lint('uint64_t longlong = 1', '')
+        self.assert_lint('unsigned long a = 1', errmsg % 'unsigned long  [runtime/int] [1]')
+        self.assert_lint('signed   long a = 1', errmsg % 'signed   long  [runtime/int] [1]')
+        self.assert_lint('long a = 1', errmsg % 'long  [runtime/int] [1]')
+        self.assert_lint('signed int   long a = 1', errmsg % 'long  [runtime/int] [1]')
+        self.assert_lint('unsigned   long   int a = 1', errmsg % 'unsigned   long  [runtime/int] [1]')
+        self.assert_lint('unsigned longlong = 1', '')
+        self.assert_lint('signed   int a = 1', '')
+        self.assert_lint('int a = 1', '')
 
     # Test C-style cast cases.
     def test_cstyle_cast(self):
@@ -1515,7 +1523,6 @@
         self.assert_lint('int a : 30;', errmsg)
         self.assert_lint('mutable int a : 14;', errmsg)
         self.assert_lint('const char a : 6;', errmsg)
-        self.assert_lint('long int a : 30;', errmsg)
         self.assert_lint('int a = 1 ? 0 : 30;', '')
 
     # Bitfields which are not declared unsigned or bool will generate a warning.
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt.config.json b/third_party/blink/tools/blinkpy/third_party/wpt/wpt.config.json
index 3a67415..5715de5 100644
--- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt.config.json
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt.config.json
@@ -20,6 +20,10 @@
   },
   "aliases": [
     {
+      "url-path": "/wpt_internal/",
+      "local-dir": "../../../../../web_tests/wpt_internal"
+    },
+    {
       "url-path": "/wpt_automation/",
       "local-dir": "../../../../../web_tests/external/wpt_automation"
     },
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
index e66db2a..5927929 100644
--- a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
+++ b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
@@ -499,6 +499,7 @@
                     '/mock-checkout/third_party/blink/tools/blinkpy/third_party/wpt/wpt/wpt',
                     'manifest',
                     '--work',
+                    '--no-download',
                     '--tests-root',
                     MOCK_WEB_TESTS + 'external/wpt',
                 ]
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_manifest.py b/third_party/blink/tools/blinkpy/w3c/wpt_manifest.py
index 1d5c160..b96481e 100644
--- a/third_party/blink/tools/blinkpy/w3c/wpt_manifest.py
+++ b/third_party/blink/tools/blinkpy/w3c/wpt_manifest.py
@@ -77,6 +77,8 @@
         """
         items = self.raw_dict['items']
         for test_type in self.test_types:
+            if test_type not in items:
+                continue
             if path_in_wpt in items[test_type]:
                 return items[test_type][path_in_wpt]
         return None
@@ -117,8 +119,11 @@
         url_items = {}
         if 'items' not in self.raw_dict:
             return url_items
+        items = self.raw_dict['items']
         for test_type in self.test_types:
-            for records in self.raw_dict['items'][test_type].itervalues():
+            if test_type not in items:
+                continue
+            for records in items[test_type].itervalues():
                 for item in filter(self._is_not_jsshell, records):
                     url_items[self._get_url_from_item(item)] = item
         return url_items
@@ -164,11 +169,11 @@
            [("==", "foo/bar/baz-match.html"),
             ("!=", "foo/bar/baz-mismatch.html")]
         """
-        all_items = self.raw_dict['items']
-        if path_in_wpt not in all_items['reftest']:
+        items = self.raw_dict['items']
+        if path_in_wpt not in items.get('reftest', {}):
             return []
         reftest_list = []
-        for item in all_items['reftest'][path_in_wpt]:
+        for item in items['reftest'][path_in_wpt]:
             for ref_path_in_wpt, expectation in item[1]:
                 reftest_list.append((expectation, ref_path_in_wpt))
         return reftest_list
@@ -210,7 +215,7 @@
         """Generates MANIFEST.json on the specified directory."""
         finder = PathFinder(host.filesystem)
         wpt_exec_path = finder.path_from_blink_tools('blinkpy', 'third_party', 'wpt', 'wpt', 'wpt')
-        cmd = ['python', wpt_exec_path, 'manifest', '--work', '--tests-root', dest_path]
+        cmd = ['python', wpt_exec_path, 'manifest', '--work', '--no-download', '--tests-root', dest_path]
 
         # ScriptError will be raised if the command fails.
         host.executive.run_command(
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_manifest_unittest.py b/third_party/blink/tools/blinkpy/w3c/wpt_manifest_unittest.py
index 1bd6c428..eb9a5be65 100644
--- a/third_party/blink/tools/blinkpy/w3c/wpt_manifest_unittest.py
+++ b/third_party/blink/tools/blinkpy/w3c/wpt_manifest_unittest.py
@@ -32,6 +32,7 @@
                     '/mock-checkout/third_party/blink/tools/blinkpy/third_party/wpt/wpt/wpt',
                     'manifest',
                     '--work',
+                    '--no-download',
                     '--tests-root',
                     MOCK_WEB_TESTS + 'external/wpt',
                 ]
@@ -57,6 +58,7 @@
                     '/mock-checkout/third_party/blink/tools/blinkpy/third_party/wpt/wpt/wpt',
                     'manifest',
                     '--work',
+                    '--no-download',
                     '--tests-root',
                     MOCK_WEB_TESTS + 'external/wpt',
                 ]
@@ -70,6 +72,42 @@
         with self.assertRaises(ScriptError):
             WPTManifest.ensure_manifest(host)
 
+    def test_ensure_manifest_takes_optional_dest(self):
+        host = MockHost()
+        WPTManifest.ensure_manifest(host, 'wpt_internal')
+        self.assertEqual(
+            host.executive.calls,
+            [
+                [
+                    'python',
+                    '/mock-checkout/third_party/blink/tools/blinkpy/third_party/wpt/wpt/wpt',
+                    'manifest',
+                    '--work',
+                    '--no-download',
+                    '--tests-root',
+                    MOCK_WEB_TESTS + 'wpt_internal',
+                ]
+            ]
+        )
+
+    def test_does_not_throw_when_missing_some_test_types(self):
+        manifest_json = '''
+{
+    "items": {
+        "testharness": {
+            "test.any.js": [
+                ["/test.any.html", {}]
+            ]
+        }
+    }
+}
+        '''
+        manifest = WPTManifest(manifest_json)
+        self.assertTrue(manifest.is_test_file('test.any.js'))
+        self.assertEqual(manifest.all_url_items(),
+                         {u'/test.any.html': [u'/test.any.html', {}]})
+        self.assertEqual(manifest.extract_reference_list('/foo/bar.html'), [])
+
     def test_all_url_items_skips_jsshell_tests(self):
         manifest_json = '''
 {
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py b/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
index 661ccdbd..5b5eb40 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
@@ -99,10 +99,17 @@
         self._printer.write_update('Collecting tests ...')
         running_all_tests = False
 
-        if self._options.manifest_update and (not args or any('external' in path for path in args)):
-            self._printer.write_update('Generating MANIFEST.json for web-platform-tests ...')
-            WPTManifest.ensure_manifest(self._port.host)
-            self._printer.write_update('Completed generating manifest.')
+        if self._options.manifest_update:
+            # TODO(robertma): Consolidate the two cases to `for wpt_path in
+            # WPT_DIRS` when external/wpt is moved to wpt.
+            if not args or any('external' in path for path in args):
+                self._printer.write_update('Generating MANIFEST.json for external/wpt...')
+                WPTManifest.ensure_manifest(self._port.host)
+                self._printer.write_update('Completed generating manifest.')
+            if not args or any('wpt_internal' in path for path in args):
+                self._printer.write_update('Generating MANIFEST.json for wpt_internal...')
+                WPTManifest.ensure_manifest(self._port.host, 'wpt_internal')
+                self._printer.write_update('Completed generating manifest.')
 
         self._printer.write_update('Collecting tests ...')
         try:
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/base.py b/third_party/blink/tools/blinkpy/web_tests/port/base.py
index bca3d49..191540b 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/base.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/base.py
@@ -102,14 +102,6 @@
 # And one for external/wpt/signed-exchange/resources/127.0.0.1.sxg.pem
 SXG_WPT_FINGERPRINT = '0Rt4mT6SJXojEMHTnKnlJ/hBKMBcI4kteBlhR1eTTdk='
 
-# The following two constants must match. When adding a new WPT root, also
-# remember to add an alias rule to third_party/wpt/wpt.config.json.
-WPT_DIRS = ['external/wpt']
-# WPT_REGEX captures: 1. the root directory of WPT relative to web_tests
-# (without a trailing slash), 2. the path of the test within WPT (without a
-# leading slash).
-WPT_REGEX = re.compile(r'^(?:virtual/[^/]+/)?(external/wpt)/(.*)$')
-
 
 class Port(object):
     """Abstract class for Port-specific hooks for the web_test package."""
@@ -182,6 +174,19 @@
 
     FLAG_EXPECTATIONS_PREFIX = 'FlagExpectations'
 
+    # The following two constants must match. When adding a new WPT root, also
+    # remember to add an alias rule to third_party/wpt/wpt.config.json.
+    # WPT_DIRS maps WPT roots on the file system to URL prefixes on wptserve.
+    # The order matters: the empty URL prefix MUST be the last one.
+    WPT_DIRS = collections.OrderedDict([
+        ('wpt_internal', 'wpt_internal/'),
+        ('external/wpt', ''),
+    ])
+    # WPT_REGEX captures: 1. the root directory of WPT relative to web_tests
+    # (without a trailing slash), 2. the path of the test within WPT (without a
+    # leading slash).
+    WPT_REGEX = re.compile(r'^(?:virtual/[^/]+/)?(external/wpt|wpt_internal)/(.*)$')
+
     # Because this is an abstract base class, arguments to functions may be
     # unused in this class - pylint: disable=unused-argument
 
@@ -696,7 +701,7 @@
             return reftest_list
 
         # Try to extract information from MANIFEST.json.
-        match = WPT_REGEX.match(test_name)
+        match = self.WPT_REGEX.match(test_name)
         if not match:
             return []
         wpt_path = match.group(1)
@@ -724,13 +729,13 @@
         suites = self.virtual_test_suites()
         if paths:
             tests.extend(self._virtual_tests_matching_paths(paths, suites))
-            if (any(wpt_path in path for wpt_path in WPT_DIRS for path in paths)
+            if (any(wpt_path in path for wpt_path in self.WPT_DIRS for path in paths)
                     # TODO(robertma): Remove this special case when external/wpt is moved to wpt.
                     or any('external' in path for path in paths)):
                 tests.extend(self._wpt_test_urls_matching_paths(paths))
         else:
             tests.extend(self._all_virtual_tests(suites))
-            tests.extend([wpt_path + test for wpt_path in WPT_DIRS
+            tests.extend([wpt_path + test for wpt_path in self.WPT_DIRS
                           for test in self._wpt_manifest(wpt_path).all_urls()])
 
         return tests
@@ -740,10 +745,10 @@
         # When collecting test cases, skip these directories.
         skipped_directories = set(
             ['platform', 'resources', 'support', 'script-tests',
-             'reference', 'reftest']
-            # Also ignore all WPT directories. Note that this is only an
-            # optimization; is_non_wpt_test_file should skip WPT regardless.
-            + WPT_DIRS)
+             'reference', 'reftest'])
+        # Also ignore all WPT directories. Note that this is only an
+        # optimization; is_non_wpt_test_file should skip WPT regardless.
+        skipped_directories |= set(self.WPT_DIRS)
         files = find_files.find(self._filesystem, self.web_tests_dir(), paths, skipped_directories,
                                 lambda _, dirname, filename: self.is_non_wpt_test_file(dirname, filename),
                                 self.test_key)
@@ -777,7 +782,7 @@
         # Convert dirname to a relative path to web_tests with slashes
         # normalized and ensure it has a trailing slash.
         normalized_test_dir = self.relative_test_filename(dirname) + self.TEST_PATH_SEPARATOR
-        if any([normalized_test_dir.startswith(d + self.TEST_PATH_SEPARATOR) for d in WPT_DIRS]):
+        if any(normalized_test_dir.startswith(d + self.TEST_PATH_SEPARATOR) for d in self.WPT_DIRS):
             return False
         extension = self._filesystem.splitext(filename)[1]
         if 'inspector-protocol' in dirname and extension == '.js':
@@ -789,7 +794,7 @@
 
     @memoized
     def _wpt_manifest(self, path):
-        assert path in WPT_DIRS
+        assert path in self.WPT_DIRS
         # Convert '/' to the platform-specific separator.
         path = self._filesystem.normpath(path)
         manifest_path = self._filesystem.join(self.web_tests_dir(), path, MANIFEST_NAME)
@@ -799,7 +804,7 @@
         return WPTManifest(self._filesystem.read_text_file(manifest_path))
 
     def is_slow_wpt_test(self, test_file):
-        match = WPT_REGEX.match(test_file)
+        match = self.WPT_REGEX.match(test_file)
         if not match:
             return False
         wpt_path = match.group(1)
@@ -1177,7 +1182,7 @@
     @staticmethod
     def is_wpt_test(test):
         """Whether a test is considered a web-platform-tests test."""
-        return WPT_REGEX.match(test)
+        return Port.WPT_REGEX.match(test)
 
     @staticmethod
     def should_use_wptserve(test):
@@ -1624,7 +1629,7 @@
             paths = [path.replace(self._filesystem.sep, '/') for path in paths]
 
         tests = []
-        for wpt_path in WPT_DIRS:
+        for wpt_path in self.WPT_DIRS:
             tests += self._wpt_test_urls(wpt_path, paths)
         return tests
 
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py b/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
index 38d69173..f2ce42d0 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
@@ -54,6 +54,25 @@
             return TestPort(host, **kwargs)
         return Port(host, port_name or 'baseport', **kwargs)
 
+    def test_validate_wpt_dirs(self):
+        # Keys should not have trailing slashes.
+        for wpt_path in Port.WPT_DIRS.keys():
+            self.assertFalse(wpt_path.endswith('/'))
+        # Values should not be empty (except the last one).
+        for url_prefix in Port.WPT_DIRS.values()[:-1]:
+            self.assertNotEqual(url_prefix, '')
+        self.assertEqual(Port.WPT_DIRS.values()[-1], '')
+
+    def test_validate_wpt_regex(self):
+        self.assertEquals(Port.WPT_REGEX.match('external/wpt/foo/bar.html').groups(),
+                          ('external/wpt', 'foo/bar.html'))
+        self.assertEquals(Port.WPT_REGEX.match('virtual/test/external/wpt/foo/bar.html').groups(),
+                          ('external/wpt', 'foo/bar.html'))
+        self.assertEquals(Port.WPT_REGEX.match('wpt_internal/foo/bar.html').groups(),
+                          ('wpt_internal', 'foo/bar.html'))
+        self.assertEquals(Port.WPT_REGEX.match('virtual/test/wpt_internal/foo/bar.html').groups(),
+                          ('wpt_internal', 'foo/bar.html'))
+
     def test_setup_test_run(self):
         port = self.make_port()
         # This routine is a no-op. We just test it for coverage.
@@ -500,6 +519,16 @@
         filesystem.write_text_file(WEB_TEST_DIR + '/external/wpt/console/console-is-a-namespace.any.js', '')
         filesystem.write_text_file(WEB_TEST_DIR + '/external/wpt/common/blank.html', 'foo')
 
+        filesystem.write_text_file(WEB_TEST_DIR + '/wpt_internal/MANIFEST.json', json.dumps({
+            'items': {
+                'testharness': {
+                    'dom/bar.html': [
+                        ['/dom/bar.html', {}]
+                    ]
+                }
+            }}))
+        filesystem.write_text_file(WEB_TEST_DIR + '/wpt_internal/dom/bar.html', 'baz')
+
     def test_find_none_if_not_in_manifest(self):
         port = self.make_port(with_tests=True)
         PortTest._add_manifest_to_mock_file_system(port.host.filesystem)
@@ -552,6 +581,9 @@
         self.assertEqual(port.tests(['external/wpt/dom/ranges/Range-attributes.html']),
                          ['external/wpt/dom/ranges/Range-attributes.html'])
 
+        # wpt_internal should work the same.
+        self.assertEqual(port.tests(['wpt_internal']), ['wpt_internal/dom/bar.html'])
+
     def test_virtual_wpt_tests_paths(self):
         port = self.make_port(with_tests=True)
         PortTest._add_manifest_to_mock_file_system(port.host.filesystem)
@@ -580,6 +612,12 @@
         self.assertEqual(port.tests(['virtual/virtual_wpt_dom/external/wpt/dom/ranges/Range-attributes.html']),
                          ['virtual/virtual_wpt_dom/external/wpt/dom/ranges/Range-attributes.html'])
 
+        # wpt_internal should work the same.
+        self.assertEqual(port.tests(['virtual/virtual_wpt_dom/wpt_internal']),
+                         ['virtual/virtual_wpt_dom/wpt_internal/dom/bar.html'])
+        self.assertEqual(port.tests(['virtual/virtual_wpt_dom/']),
+                         dom_wpt + ['virtual/virtual_wpt_dom/wpt_internal/dom/bar.html'])
+
     def test_is_non_wpt_test_file(self):
         port = self.make_port(with_tests=True)
         self.assertTrue(port.is_non_wpt_test_file('', 'foo.html'))
@@ -604,6 +642,7 @@
         self.assertFalse(port.is_non_wpt_test_file(WEB_TEST_DIR + '/external/wpt/console', 'console-is-a-namespace.any.js'))
         self.assertFalse(port.is_non_wpt_test_file(WEB_TEST_DIR + '/external/wpt', 'testharness_runner.html'))
         self.assertTrue(port.is_non_wpt_test_file(WEB_TEST_DIR + '/external/wpt_automation', 'foo.html'))
+        self.assertFalse(port.is_non_wpt_test_file(WEB_TEST_DIR + '/wpt_internal/console', 'console-is-a-namespace.any.js'))
 
     def test_is_wpt_test(self):
         self.assertTrue(Port.is_wpt_test('external/wpt/dom/ranges/Range-attributes.html'))
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/driver.py b/third_party/blink/tools/blinkpy/web_tests/port/driver.py
index d966ec8..f81e3a1 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/driver.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/driver.py
@@ -30,7 +30,6 @@
 import logging
 import re
 import shlex
-import sys
 import time
 
 from blinkpy.common.system import path
@@ -156,6 +155,7 @@
         port - reference back to the port object.
         worker_number - identifier for a particular worker/driver instance
         """
+        self.WPT_DIRS = port.WPT_DIRS
         self._port = port
         self._worker_number = worker_number
         self._no_timeout = no_timeout
@@ -176,6 +176,7 @@
         # "#LEAK". This leak detection is enabled only when the flag
         # --enable-leak-detection is passed to content_shell.
         self._leaked = False
+        self._leak_log = None
 
         # stderr reading is scoped on a per-test (not per-block) basis, so we store the accumulated
         # stderr output, as well as if we've seen #EOF on this driver instance.
@@ -274,6 +275,7 @@
                             pid=pid)
 
     def _get_crash_log(self, stdout, stderr, newer_than):
+        # pylint: disable=protected-access
         return self._port._get_crash_log(self._crashed_process_name, self._crashed_pid, stdout, stderr, newer_than)
 
     # FIXME: Seems this could just be inlined into callers.
@@ -289,7 +291,6 @@
     HTTP_DIR = 'http/tests/'
     HTTP_LOCAL_DIR = 'http/tests/local/'
     HTTP_HOST_AND_PORTS = ('127.0.0.1', 8000, 8443)
-    WPT_DIR = 'external/wpt/'
     WPT_HOST_AND_PORTS = ('web-platform.test', 8001, 8444)
 
     def is_http_test(self, test_name):
@@ -311,17 +312,29 @@
             return path.abspath_to_uri(self._port.host.platform, self._port.abspath_for_test(test_name))
 
         if using_wptserve:
-            test_dir_prefix = self.WPT_DIR
+            for wpt_path, url_prefix in self.WPT_DIRS.items():
+                # The keys of WPT_DIRS do not have trailing slashes.
+                wpt_path += '/'
+                if test_name.startswith(wpt_path):
+                    test_dir_prefix = wpt_path
+                    test_url_prefix = url_prefix
+                    break
+            else:
+                # We really shouldn't reach here, but in case we do, fail gracefully.
+                _log.error('Unrecognized WPT test name: %s', test_name)
+                test_dir_prefix = 'external/wpt/'
+                test_url_prefix = ''
             hostname, insecure_port, secure_port = self.WPT_HOST_AND_PORTS
         else:
             test_dir_prefix = self.HTTP_DIR
+            test_url_prefix = ''
             hostname, insecure_port, secure_port = self.HTTP_HOST_AND_PORTS
 
         relative_path = test_name[len(test_dir_prefix):]
 
         if '/https/' in test_name or '.https.' in test_name or '.serviceworker.' in test_name:
-            return 'https://%s:%d/%s' % (hostname, secure_port, relative_path)
-        return 'http://%s:%d/%s' % (hostname, insecure_port, relative_path)
+            return 'https://%s:%d/%s%s' % (hostname, secure_port, test_url_prefix, relative_path)
+        return 'http://%s:%d/%s%s' % (hostname, insecure_port, test_url_prefix, relative_path)
 
     def _get_uri_prefixes(self, hostname, insecure_port, secure_port):
         """Returns the HTTP and HTTPS URI prefix for a hostname."""
@@ -347,7 +360,10 @@
                 return self.HTTP_DIR + uri[len(prefix):]
         for prefix in self._get_uri_prefixes(*self.WPT_HOST_AND_PORTS):
             if uri.startswith(prefix):
-                return self.WPT_DIR + uri[len(prefix):]
+                relative_path = uri[len(prefix):]
+                for wpt_path, url_prefix in self.WPT_DIRS.items():
+                    if relative_path.startswith(url_prefix):
+                        return wpt_path + '/' + relative_path[len(url_prefix):]
         raise NotImplementedError('unknown url type: %s' % uri)
 
     def has_crashed(self):
@@ -381,7 +397,6 @@
         self._crashed_process_name = None
         self._crashed_pid = None
         self._leaked = False
-        self._leak_log = None
         cmd_line = self.cmd_line(per_test_args)
         self._server_process = self._port.server_process_constructor(
             self._port, server_name, cmd_line, environment, more_logging=self._port.get_option('driver_logging'))
@@ -579,6 +594,7 @@
                 if out_line[-1] != '\n':
                     _log.error(
                         'Last character read from DRT stdout line was not a newline!  This indicates either a NRWT or DRT bug.')
+                # pylint: disable=protected-access
                 content_length_before_header_check = block._content_length
                 self._process_stdout_line(block, out_line)
                 # FIXME: Unlike HTTP, DRT dumps the content right after printing a Content-Length header.
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py b/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py
index 45fe2ec..9e5d1bf 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/driver_unittest.py
@@ -38,6 +38,8 @@
 
 class DriverTest(unittest.TestCase):
 
+    # pylint: disable=protected-access
+
     def make_port(self):
         return Port(MockSystemHost(), 'test', optparse.Values({'configuration': 'Release'}))
 
@@ -62,9 +64,18 @@
         self.assertEqual(driver.test_to_uri('http/tests/https/bar.html'), 'https://127.0.0.1:8443/https/bar.html')
         self.assertEqual(driver.test_to_uri('http/tests/bar.https.html'), 'https://127.0.0.1:8443/bar.https.html')
         self.assertEqual(driver.test_to_uri('http/tests/barhttps.html'), 'http://127.0.0.1:8000/barhttps.html')
-        self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.html'), 'http://web-platform.test:8001/foo/bar.html')
-        self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.https.html'), 'https://web-platform.test:8444/foo/bar.https.html')
-        self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.serviceworker.html'), 'https://web-platform.test:8444/foo/bar.serviceworker.html')
+        self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.html'),
+                         'http://web-platform.test:8001/foo/bar.html')
+        self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.https.html'),
+                         'https://web-platform.test:8444/foo/bar.https.html')
+        self.assertEqual(driver.test_to_uri('external/wpt/foo/bar.serviceworker.html'),
+                         'https://web-platform.test:8444/foo/bar.serviceworker.html')
+        self.assertEqual(driver.test_to_uri('wpt_internal/foo/bar.html'),
+                         'http://web-platform.test:8001/wpt_internal/foo/bar.html')
+        self.assertEqual(driver.test_to_uri('wpt_internal/foo/bar.https.html'),
+                         'https://web-platform.test:8444/wpt_internal/foo/bar.https.html')
+        self.assertEqual(driver.test_to_uri('wpt_internal/foo/bar.serviceworker.html'),
+                         'https://web-platform.test:8444/wpt_internal/foo/bar.serviceworker.html')
 
     def test_uri_to_test(self):
         port = self.make_port()
@@ -73,9 +84,18 @@
         self.assertEqual(driver.uri_to_test('http://127.0.0.1:8000/foo.html'), 'http/tests/foo.html')
         self.assertEqual(driver.uri_to_test('https://127.0.0.1:8443/https/bar.html'), 'http/tests/https/bar.html')
         self.assertEqual(driver.uri_to_test('https://127.0.0.1:8443/bar.https.html'), 'http/tests/bar.https.html')
-        self.assertEqual(driver.uri_to_test('http://web-platform.test:8001/foo/bar.html'), 'external/wpt/foo/bar.html')
-        self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/foo/bar.https.html'), 'external/wpt/foo/bar.https.html')
-        self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/foo/bar.serviceworker.html'), 'external/wpt/foo/bar.serviceworker.html')
+        self.assertEqual(driver.uri_to_test('http://web-platform.test:8001/foo/bar.html'),
+                         'external/wpt/foo/bar.html')
+        self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/foo/bar.https.html'),
+                         'external/wpt/foo/bar.https.html')
+        self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/foo/bar.serviceworker.html'),
+                         'external/wpt/foo/bar.serviceworker.html')
+        self.assertEqual(driver.uri_to_test('http://web-platform.test:8001/wpt_internal/foo/bar.html'),
+                         'wpt_internal/foo/bar.html')
+        self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/wpt_internal/foo/bar.https.html'),
+                         'wpt_internal/foo/bar.https.html')
+        self.assertEqual(driver.uri_to_test('https://web-platform.test:8444/wpt_internal/foo/bar.serviceworker.html'),
+                         'wpt_internal/foo/bar.serviceworker.html')
 
     def test_read_block(self):
         port = self.make_port()
@@ -272,22 +292,22 @@
 
     def test_multiple_enable_features(self):
         self._assert_coalesced_switches(
-            [ '--A', '--enable-features=Z,X',
-              '--enable-features=Y', '--X', '--enable-features=X,Y',
-              '--enable-features=X', '--enable-features=X,X'],
+            ['--A', '--enable-features=Z,X',
+             '--enable-features=Y', '--X', '--enable-features=X,Y',
+             '--enable-features=X', '--enable-features=X,X'],
             ['--A', '--X', '--enable-features=X,Y,Z'])
 
     def test_multiple_disable_features(self):
         self._assert_coalesced_switches(
-            [ '--A', '--disable-features=Z,X',
-              '--disable-features=Y', '--X', '--disable-features=X,Y',
-              '--disable-features=X', '--disable-features=X,X'],
+            ['--A', '--disable-features=Z,X',
+             '--disable-features=Y', '--X', '--disable-features=X,Y',
+             '--disable-features=X', '--disable-features=X,X'],
             ['--A', '--X', '--disable-features=X,Y,Z'])
 
     def test_enable_and_disable_features(self):
         # The coalescing of --enable-features and --disable-features is
         # independent (may both enable and disable the same feature).
         self._assert_coalesced_switches(
-            [ '--A', '--disable-features=Z','--disable-features=E,X',
-              '--enable-features=Y', '--X', '--enable-features=X,Y'],
+            ['--A', '--disable-features=Z', '--disable-features=E,X',
+             '--enable-features=Y', '--X', '--enable-features=X,Y'],
             ['--A', '--X', '--enable-features=X,Y', '--disable-features=E,X,Z'])
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/test.py b/third_party/blink/tools/blinkpy/web_tests/port/test.py
index f7b6b6de..0d777d7 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/test.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/test.py
@@ -31,7 +31,6 @@
 
 from blinkpy.common import exit_codes
 from blinkpy.common.system.crash_logs import CrashLogs
-from blinkpy.web_tests.models import test_run_results
 from blinkpy.web_tests.models.test_configuration import TestConfiguration
 from blinkpy.web_tests.port.base import Port, VirtualTestSuite
 from blinkpy.web_tests.port.driver import DeviceFailure, Driver, DriverOutput
@@ -513,6 +512,7 @@
                              args=['--virtual-arg'], references_use_default_args=True),
             VirtualTestSuite(prefix='virtual_wpt', base='external/wpt', args=['--virtual-arg']),
             VirtualTestSuite(prefix='virtual_wpt_dom', base='external/wpt/dom', args=['--virtual-arg']),
+            VirtualTestSuite(prefix='virtual_wpt_dom', base='wpt_internal/dom', args=['--virtual-arg']),
         ]
 
 
diff --git a/third_party/blink/web_tests/.gitignore b/third_party/blink/web_tests/.gitignore
index 0840580..545ade9 100644
--- a/third_party/blink/web_tests/.gitignore
+++ b/third_party/blink/web_tests/.gitignore
@@ -1,2 +1,3 @@
+wpt_internal/MANIFEST.json
 # Ignore compiled java tests:
 java/*.class
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
index 3a17590..6aef71f 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -87,8 +87,6 @@
 crbug.com/922437 external/wpt/css/css-text/word-break/word-break-break-all-013.html [ Skip ]
 
 # New failures are appended below by the script.
-crbug.com/591099 bluetooth/server/getPrimaryService/gen-reconnect-during-error.html [ Pass ]
-crbug.com/591099 compositing/animation/busy-indicator.html [ Pass ]
 crbug.com/591099 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ]
 crbug.com/591099 css3/filters/effect-drop-shadow-hw.html [ Pass ]
 crbug.com/591099 css3/filters/filter-repaint-composited-fallback-crash.html [ Pass ]
@@ -96,7 +94,6 @@
 crbug.com/591099 editing/selection/paint-hyphen.html [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/floats/float-nowrap-3.html [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/floats/floats-line-wrap-shifted-001.html [ Pass ]
-crbug.com/591099 external/wpt/css/CSS2/floats/floats-wrap-bfc-006.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-empty-001.xht [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-empty-004.xht [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-insert-001e.xht [ Pass ]
@@ -288,15 +285,12 @@
 crbug.com/591099 external/wpt/fetch/api/redirect/redirect-count.any.worker.html [ Pass ]
 crbug.com/591099 external/wpt/fetch/api/request/request-keepalive-quota.html?include=slow-2 [ Pass ]
 crbug.com/591099 external/wpt/fullscreen/api/element-ready-check-containing-iframe-manual.html [ Pass ]
-crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ]
-crbug.com/591099 external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.tentative.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/html/user-activation/activation-transfer-without-click.tentative.html [ Pass ]
 crbug.com/845902 external/wpt/quirks/line-height-trailing-collapsable-whitespace.html [ Pass ]
 crbug.com/591099 external/wpt/referrer-policy/no-referrer/http-rp/same-origin/http-http/shared-worker/keep-origin-redirect/generic.http.html [ Pass ]
 crbug.com/591099 external/wpt/referrer-policy/no-referrer/http-rp/same-origin/http-http/shared-worker/no-redirect/generic.http.html [ Pass ]
 crbug.com/591099 external/wpt/referrer-policy/no-referrer/meta-referrer/same-origin/http-http/shared-worker/keep-origin-redirect/generic.http.html [ Pass ]
 crbug.com/591099 external/wpt/referrer-policy/no-referrer/meta-referrer/same-origin/http-http/shared-worker/no-redirect/generic.http.html [ Pass ]
-crbug.com/591099 external/wpt/screen-orientation/onchange-event.html [ Failure ]
 crbug.com/591099 external/wpt/wasm/webapi/rejected-arg.any.serviceworker.html [ Pass ]
 crbug.com/591099 external/wpt/webauthn/createcredential-extensions.https.html [ Pass ]
 crbug.com/591099 external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html [ Pass ]
@@ -311,9 +305,6 @@
 crbug.com/835484 fast/css/outline-narrowLine.html [ Failure ]
 crbug.com/855279 fast/css/text-overflow-ellipsis-vertical-hittest.html [ Pass ]
 crbug.com/591099 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under.html [ Failure ]
-crbug.com/591099 fast/dom/SelectorAPI/resig-SelectorsAPI-test.xhtml [ Pass ]
-crbug.com/591099 fast/dom/shadow/focus-controller-recursion-crash.html [ Pass ]
-crbug.com/591099 fast/dom/shadow/svg-style-in-shadow-tree-crash.html [ Pass ]
 crbug.com/591099 fast/events/before-unload-return-value-from-listener.html [ Pass ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-list-translate.html [ Failure ]
@@ -332,36 +323,20 @@
 crbug.com/591099 fast/writing-mode/auto-sizing-orthogonal-flows.html [ Failure ]
 crbug.com/591099 fast/writing-mode/percentage-height-orthogonal-writing-modes.html [ Failure ]
 crbug.com/591099 fast/writing-mode/table-percent-width-quirk.html [ Pass ]
-crbug.com/591099 html/marquee/marquee-destroyed-without-removed-from-crash.html [ Pass ]
 crbug.com/591099 http/tests/appcache/non-html.xhtml [ Crash Failure Pass ]
 crbug.com/591099 http/tests/csspaint/invalidation-border-image.html [ Pass ]
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-grid.js [ Failure ]
-crbug.com/591099 http/tests/devtools/elements/styles-1/edit-value-url-with-color.js [ Pass ]
-crbug.com/591099 http/tests/devtools/elements/user-properties.js [ Pass ]
 crbug.com/591099 http/tests/devtools/sources/debugger-frameworks/frameworks-jquery.js [ Crash Pass ]
 crbug.com/591099 http/tests/devtools/sources/debugger/debugger-proto-property.js [ Pass Timeout ]
 crbug.com/591099 http/tests/devtools/tracing-session-id.js [ Pass ]
 crbug.com/591099 http/tests/devtools/tracing/console-timeline.js [ Pass ]
-crbug.com/591099 http/tests/fetch/chromium/response-blob-gc-crash.html [ Pass ]
-crbug.com/591099 http/tests/fetch/serviceworker-proxied/thorough/cookie-nocors-base-https-other-https.html [ Pass ]
-crbug.com/591099 http/tests/fetch/serviceworker-proxied/thorough/redirect-nocors-base-https-other-https.html [ Pass ]
-crbug.com/591099 http/tests/fetch/serviceworker/thorough/cookie-nocors-base-https-other-https.html [ Pass ]
-crbug.com/591099 http/tests/fetch/serviceworker/thorough/redirect-nocors-base-https-other-https.html [ Pass ]
-crbug.com/591099 http/tests/fetch/serviceworker/thorough/scheme-blob-base-https-other-https.html [ Pass ]
-crbug.com/591099 http/tests/fetch/window/thorough/cors-preflight2-base-https-other-https.html [ Pass ]
-crbug.com/591099 http/tests/fetch/workers/thorough/auth-base-https-other-https.html [ Pass ]
-crbug.com/591099 http/tests/fetch/workers/thorough/cookie-nocors-base-https-other-https.html [ Pass ]
 crbug.com/591099 http/tests/html/validation-bubble-oopif-clip.html [ Pass ]
 crbug.com/591099 http/tests/media/autoplay/document-user-activation-cross-origin-feature-policy-disabled.html [ Failure ]
 crbug.com/591099 http/tests/media/video-load-metadata-decode-error.html [ Pass ]
-crbug.com/591099 http/tests/multipart/multipart-main-resource.html [ Pass ]
 crbug.com/591099 http/tests/security/inactive-document-with-empty-security-origin.html [ Pass ]
 crbug.com/591099 http/tests/security/upgrade-insecure-requests/iframe-upgrade.https.html [ Crash ]
-crbug.com/591099 http/tests/security/video-poster-cross-origin-crash2.html [ Pass ]
-crbug.com/591099 http/tests/webfont/crbug-655076.html [ Pass ]
 crbug.com/591099 images/feature-policy-oversized-images-resize.html [ Pass ]
 crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-origin-url.js [ Crash Pass ]
-crbug.com/591099 jquery/offset.html [ Pass ]
 crbug.com/591099 paint/invalidation/flexbox/scrollbars-changed.html [ Failure ]
 crbug.com/835484 paint/invalidation/outline/inline-focus.html [ Failure ]
 crbug.com/591099 paint/invalidation/overflow/opacity-change-on-overflow-float.html [ Failure ]
@@ -371,10 +346,6 @@
 crbug.com/591099 printing/iframe-svg-in-object-print.html [ Failure ]
 crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ]
 crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ]
-crbug.com/591099 storage/indexeddb/structured-clone.html [ Pass ]
-crbug.com/591099 storage/websql/open-database-creation-callback-isolated-world.html [ Pass ]
-crbug.com/591099 storage/websql/transaction-error-callback.html [ Pass ]
-crbug.com/591099 svg/animations/svg-animation-policy-once.html [ Pass ]
 crbug.com/591099 svg/zoom/page/zoom-svg-float-border-padding.xml [ Pass ]
 crbug.com/591099 tables/mozilla/bugs/bug14159-1.html [ Pass ]
 crbug.com/591099 virtual/android/rootscroller/set-root-scroller.html [ Pass ]
@@ -382,6 +353,7 @@
 crbug.com/916511 virtual/composite-after-paint/paint/background/scrolling-background-with-negative-z-child.html [ Crash ]
 crbug.com/591099 virtual/composite-after-paint/paint/invalidation/box/margin.html [ Failure Pass ]
 Bug(none) virtual/disable-blink-gen-property-trees/ [ Skip ]
+crbug.com/917392 virtual/display-lock/display-lock/lock-after-append/acquire-after-resize.html [ Failure ]
 crbug.com/591099 virtual/display-lock/display-lock/lock-after-append/measure-forced-layout-after-commit.html [ Failure ]
 crbug.com/591099 virtual/display-lock/display-lock/lock-after-append/measure-forced-layout.html [ Failure ]
 crbug.com/591099 virtual/display-lock/display-lock/lock-after-append/measure-updated-layout.html [ Failure ]
@@ -392,7 +364,6 @@
 crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/measure-updated-layout.html [ Failure ]
 crbug.com/591099 virtual/exotic-color-space/ [ Skip ]
 crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Pass ]
-crbug.com/591099 virtual/gpu-rasterization/images/image-page-injected-script-crash.html [ Pass ]
 crbug.com/591099 virtual/gpu/fast/canvas/OffscreenCanvas-copyImage.html [ Pass ]
 crbug.com/591099 virtual/gpu/fast/canvas/OffscreenCanvas-filter.html [ Pass ]
 crbug.com/591099 virtual/gpu/fast/canvas/canvas-blend-image.html [ Pass ]
@@ -407,10 +378,7 @@
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 virtual/new-remote-playback-pipeline/ [ Skip ]
 crbug.com/591099 virtual/nobinary-for-devtools/http/tests/devtools/elements/highlight/highlight-css-grid.js [ Failure ]
-crbug.com/591099 virtual/nobinary-for-devtools/http/tests/devtools/elements/styles-1/edit-value-url-with-color.js [ Pass ]
-crbug.com/591099 virtual/nobinary-for-devtools/http/tests/devtools/elements/user-properties.js [ Pass ]
 crbug.com/591099 virtual/nobinary-for-devtools/http/tests/devtools/sources/debugger-frameworks/frameworks-jquery.js [ Crash Pass ]
-crbug.com/591099 virtual/nobinary-for-devtools/http/tests/devtools/sources/debugger/debugger-proto-property.js [ Pass ]
 crbug.com/591099 virtual/nobinary-for-devtools/http/tests/devtools/tracing-session-id.js [ Pass ]
 crbug.com/591099 virtual/nobinary-for-devtools/http/tests/devtools/tracing/console-timeline.js [ Pass ]
 crbug.com/591099 virtual/nobinary-for-inspector-protocol/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-origin-url.js [ Crash Pass ]
@@ -419,9 +387,6 @@
 crbug.com/591099 virtual/prefer_compositing_to_lcd_text/ [ Skip ]
 crbug.com/591099 virtual/scroll_customization/ [ Skip ]
 crbug.com/591099 virtual/stable/ [ Skip ]
-crbug.com/591099 virtual/streaming-preload/http/tests/fetch/chromium/response-json-gc-crash.html [ Pass ]
-crbug.com/591099 virtual/streaming-preload/http/tests/fetch/serviceworker/thorough/cors-base-https-other-https.html [ Pass ]
-crbug.com/591099 virtual/streaming-preload/http/tests/fetch/workers/thorough/cors-preflight-base-https-other-https.html [ Pass ]
 crbug.com/591099 virtual/streams-native/external/wpt/fetch/api/basic/error-after-response.html [ Pass ]
 crbug.com/591099 virtual/streams-native/external/wpt/fetch/api/request/request-cache-default-conditional.html [ Pass ]
 crbug.com/591099 virtual/streams-native/external/wpt/fetch/api/request/request-keepalive-quota.html?include=slow-2 [ Pass ]
@@ -429,14 +394,8 @@
 crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects-list-translate.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
-crbug.com/591099 virtual/user-activation-v2/fullscreen/model/fully-exit-fullscreen-nested-iframe.html [ Pass ]
 crbug.com/591099 virtual/video-surface-layer/media/W3C/video/networkState/networkState_during_progress.html [ Pass ]
-crbug.com/591099 virtual/video-surface-layer/media/autoplay-when-visible.html [ Pass ]
 crbug.com/591099 virtual/video-surface-layer/media/color-profile-video-seek-filter.html [ Pass ]
-crbug.com/591099 virtual/video-surface-layer/media/media-ended.html [ Pass ]
 crbug.com/591099 virtual/video-surface-layer/media/stable/video-object-fit-stable.html [ Pass ]
-crbug.com/591099 virtual/video-surface-layer/media/video-controls-hide-on-move-outside-controls.html [ Pass ]
-crbug.com/591099 virtual/video-surface-layer/media/video-object-fit-change.html [ Pass ]
 crbug.com/591099 virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCIceTransport-extension.https.html [ Failure Pass ]
 crbug.com/591099 vr/getFrameData_oneframeupdate.html [ Pass ]
-crbug.com/591099 webexposed/global-interface-listing-shared-worker.html [ Pass ]
diff --git a/third_party/blink/web_tests/MSANExpectations b/third_party/blink/web_tests/MSANExpectations
index 9652ea9..a360399a 100644
--- a/third_party/blink/web_tests/MSANExpectations
+++ b/third_party/blink/web_tests/MSANExpectations
@@ -157,6 +157,7 @@
 crbug.com/856601 [ Linux ] external/wpt/IndexedDB/idlharness.any.worker.html [ Timeout Pass ]
 crbug.com/856601 [ Linux ] external/wpt/IndexedDB/idlharness.https.any.serviceworker.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/IndexedDB/interfaces.any.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] external/wpt/appmanifest/idlharness.window.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/bluetooth/idl/idlharness.tentative.window.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/cookie-store/idlharness.tentative.https.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/css/css-animations/idlharness.html [ Pass Timeout ]
@@ -170,6 +171,7 @@
 crbug.com/856601 [ Linux ] external/wpt/fetch/cors-rfc1918/idlharness.tentative.any.worker.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/gamepad/idlharness.window.html [ Timeout Pass ]
 crbug.com/856601 [ Linux ] external/wpt/hr-time/idlharness.any.sharedworker.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] external/wpt/media-capabilities/idlharness.any.worker.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/mediacapture-image/idlharness.window.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/mediacapture-streams/idlharness.https.window.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/netinfo/idlharness.any.worker.html [ Pass Timeout ]
@@ -193,6 +195,7 @@
 crbug.com/856601 [ Linux ] external/wpt/subresource-integrity/idlharness.window.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/svg/idlharness.window.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/touch-events/idlharness.window.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] external/wpt/wake-lock/idlharness.https.any.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/webstorage/idlharness.window.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/idlharness.https.window.html [ Pass Timeout ]
@@ -220,7 +223,10 @@
 crbug.com/856601 [ Linux ] virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window.html [ Timeout Pass ]
 crbug.com/856601 [ Linux ] external/wpt/css/filter-effects/interfaces.any.html [ Timeout Pass ]
 crbug.com/856601 [ Linux ] external/wpt/webxr/idlharness.https.window.html [ Timeout Pass ]
-
+crbug.com/856601 [ Linux ] virtual/streams-native/external/wpt/fetch/api/idl.any.sharedworker.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] fast/js/toString-stack-overflow.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] virtual/nobinary-for-devtools/http/tests/devtools/editor/text-editor-ctrl-d-2.js [ Pass Timeout ]
 
 # background-fetch tests crash on MSAN
 crbug.com/869818 [ Linux ] external/wpt/background-fetch/fetch.https.window.html [ Pass Crash ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index 03094e46..7b51a59 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -2024,6 +2024,7 @@
 external/wpt/payment-request/payment-response/complete-method-manual.https.html [ WontFix ]
 external/wpt/payment-request/payment-response/methodName-attribute-manual.https.html [ WontFix ]
 external/wpt/payment-request/payment-response/onpayerdetailchange-attribute-manual.https.html [ WontFix ]
+external/wpt/payment-request/payment-response/payerdetailschange-updateWith-immediate-manual.https.html [ WontFix ]
 external/wpt/payment-request/payment-response/payerEmail-attribute-manual.https.html [ WontFix ]
 external/wpt/payment-request/payment-response/payerName-attribute-manual.https.html [ WontFix ]
 external/wpt/payment-request/payment-response/payerPhone-attribute-manual.https.html [ WontFix ]
@@ -2246,3 +2247,4 @@
 external/wpt/payment-request/billing-address-changed-manual.https.html [ WontFix ]
 external/wpt/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-event-manual.html [ WontFix ]
 external/wpt/payment-request/payment-response/retry-method-warnings-manual.https.html [ WontFix ]
+external/wpt/payment-request/payment-response/payerdetailschange-updateWith-manual.https.html [ WontFix ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 5b3f8b62..7fc6d5db 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -278,6 +278,7 @@
 crbug.com/882663 display-lock [ Skip ]
 crbug.com/926276 virtual/display-lock/display-lock/lock-after-append/nested-update.html [ Timeout ]
 crbug.com/926276 virtual/display-lock/display-lock/lock-after-append/nested-update-and-commit.html [ Timeout ]
+crbug.com/944412 virtual/display-lock/display-lock/lock-after-append/acquire-on-no-containment.html [ Crash Pass ]
 
 # Sheriff 2018/05/25
 crbug.com/846747 http/tests/navigation/navigation-interrupted-by-fragment.html  [ Pass Timeout ]
@@ -1754,7 +1755,6 @@
 crbug.com/891427 external/wpt/resource-timing/resource_timing_buffer_full_eventually.html [ Pass Failure Timeout Crash ]
 crbug.com/891427 fast/canvas/canvas-drawImage-live-video.html [ Pass Failure Timeout Crash ]
 # Next 1 here: https://ci.chromium.org/buildbot/tryserver.blink/win7-blink-rel/1180
-crbug.com/891427 editing/pasteboard/drop-text-without-selection.html [ Pass Failure Timeout Crash ]
 # Next 2 here: https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-blink-rel/1541
 crbug.com/891427 virtual/android/rootscroller/gesture-scroll-document-not-root-scroller.html [ Pass Failure Timeout Crash ]
 crbug.com/891427 virtual/threaded/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.js [ Pass Failure Timeout Crash ]
@@ -2842,8 +2842,12 @@
 
 crbug.com/863896 http/tests/permissions/test-query.html [ Timeout ]
 
-# This test requires enabling the flag CustomUserTiming in a virtual test.
-crbug.com/758385 http/tests/performance-timing/custom-user-timing/ [ Skip ]
+# These tests will pass when we ship User Timing L3.
+crbug.com/758385 external/wpt/user-timing/mark-errors.html [ Failure ]
+crbug.com/758385 external/wpt/user-timing/mark-l3.html [ Failure ]
+crbug.com/758385 external/wpt/user-timing/mark-measure-return-objects.html [ Failure ]
+crbug.com/758385 external/wpt/user-timing/measure-l3.html [ Failure ]
+crbug.com/758385 external/wpt/user-timing/measure-with-dict.html [ Failure ]
 
 crbug.com/876485 fast/performance/performance-measure-null-exception.html [ Failure ]
 
@@ -3023,6 +3027,7 @@
 crbug.com/939181 virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Failure Timeout ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/html/semantics/embedded-content/media-elements/src_object_blob.html [ Timeout ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/service-workers/service-worker/websocket.https.html [ Timeout ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/websockets/Secure-Close-4999-reason.any.html [ Timeout ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/websockets/Secure-Send-data.any.html [ Timeout ]
@@ -3236,9 +3241,6 @@
 crbug.com/626703 external/wpt/css/css-text/white-space/text-space-trim-trim-inner-001.xht [ Failure ]
 crbug.com/626703 external/wpt/svg/painting/marker-006.svg [ Failure ]
 crbug.com/626703 external/wpt/svg/painting/marker-005.svg [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/css/css-variables/variable-exponential-blowup.html [ Timeout Crash ]
-crbug.com/626703 [ Mac ] external/wpt/css/css-variables/variable-exponential-blowup.html [ Timeout ]
-crbug.com/626703 [ Win ] external/wpt/css/css-variables/variable-exponential-blowup.html [ Timeout Crash ]
 crbug.com/626703 [ Mac10.13 ] external/wpt/preload/dynamic-adding-preload-imagesrcset.html [ Timeout ]
 crbug.com/906369 external/wpt/css/css-text/text-transform/text-transform-capitalize-033.html [ Failure ]
 crbug.com/626703 virtual/outofblink-cors/external/wpt/fetch/content-type/response.window.html [ Timeout ]
@@ -5343,7 +5345,6 @@
 crbug.com/824539 [ Android ] editing/execCommand/5190926.html [ Failure Timeout ]
 crbug.com/824539 [ Android ] editing/inserting/5156401-2.html [ Failure ]
 ### See crbug.com/891427 comment near the top of this file:
-###crbug.com/824539 [ Android ] editing/pasteboard/drop-text-without-selection.html [ Failure ]
 crbug.com/824539 [ Android ] editing/pasteboard/paste-line-endings-001.html [ Failure Timeout ]
 crbug.com/824539 [ Android ] editing/pasteboard/paste-line-endings-002.html [ Failure Timeout ]
 crbug.com/824539 [ Android ] editing/pasteboard/paste-line-endings-003.html [ Failure Timeout ]
@@ -5912,11 +5913,6 @@
 # Sheriff 2019-02-06
 crbug.com/929435 [ Mac ] external/wpt/webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html [ Pass Failure ]
 
-# Sheriff 2019-02-11
-### external/wpt/html/semantics/links/links-created-by-a-and-area-elements/
-crbug.com/626703 external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html [ Failure Timeout Pass ]
-crbug.com/930873 external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html [ Timeout Pass ]
-
 # Sheriff 2019-02-12
 crbug.com/931349 [ Mac ] fast/events/popup-blocking-timers5.html [ Failure Timeout Pass ]
 crbug.com/931349 [ Mac ] media/video-played-ranges-1.html [ Failure Timeout Pass ]
@@ -6160,6 +6156,11 @@
 # Sheriff 2019-03-29
 crbug.com/947477 external/wpt/editing/run/removeformat.html [ Pass Crash Timeout ]
 
+# Adjusting v8 console implementation, pass failure until v8 change lands
+crbug.com/948257 external/wpt/console/console-label-conversion.any.html [ Pass Failure ]
+crbug.com/948257 external/wpt/console/console-label-conversion.any.worker.html [ Pass Failure ]
+crbug.com/948678 external/wpt/console/idlharness.any.html [ Pass Failure ]
+
 ### external/wpt/fetch/sec-metadata/
 crbug.com/947023 external/wpt/fetch/sec-metadata/font.tentative.https.sub.html [ Pass Failure ]
 crbug.com/947023 external/wpt/fetch/sec-metadata/report.tentative.https.sub.html [ Pass Timeout ]
@@ -6168,3 +6169,20 @@
 # Sheriff 2019-04-02
 crbug.com/947690 [ Debug ] http/tests/history/back-during-beforeunload.html [ Pass Failure ]
 crbug.com/948785 [ Debug ] virtual/user-activation-v2/fast/events/pointerevents/pointer-event-consumed-touchstart-in-slop-region.html [ Pass Failure ]
+
+# Sheriff 2019-04-03
+crbug.com/947951 [ Win7 ] external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html [ Pass Failure ]
+crbug.com/949167 external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html [ Pass Timeout ]
+crbug.com/949207 external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html [ Pass Timeout ]
+crbug.com/949403 virtual/display-lock/display-lock/lock-after-append/acquire-on-composited-layer.html [ Pass Crash ]
+crbug.com/949440 [ Mac10.13 Debug ] http/tests/devtools/layers/layers-panel-mouse-events.js [ Pass Crash ]
+crbug.com/949440 [ Mac10.13 Debug ] http/tests/devtools/layers/layers-3d-view-hit-testing.js [ Pass Crash ]
+crbug.com/949440 [ Mac10.13 Debug ] virtual/nobinary-for-devtools/http/tests/devtools/layers/layers-3d-view-hit-testing.js [ Pass Crash ]
+crbug.com/949440 [ Mac10.13 Debug ] virtual/nobinary-for-devtools/http/tests/devtools/layers/layers-panel-mouse-events.js [ Pass Crash ]
+crbug.com/949442 [ Mac10.13 Debug ] external/wpt/accelerometer/Accelerometer.https.html [ Pass Failure ]
+crbug.com/949442 [ Mac10.13 Debug ] external/wpt/orientation-sensor/AbsoluteOrientationSensor.https.html [ Pass Failure ]
+crbug.com/949443 [ Mac10.13 Debug ] fast/block/inline-children-root-linebox-crash.html [ Pass Crash ]
+crbug.com/949444 [ Mac10.13 Debug ] fast/events/sequential-focus-navigation-starting-point.html [ Pass Crash ]
+crbug.com/949444 [ Mac10.13 Debug ] virtual/mouseevent_fractional/fast/events/sequential-focus-navigation-starting-point.html [ Pass Crash ]
+crbug.com/949444 [ Mac10.13 Debug ] virtual/user-activation-v2/fast/events/sequential-focus-navigation-starting-point.html [ Pass Crash ]
+crbug.com/949445 [ Mac10.13 Debug ] fast/forms/text/input-text-scroll-left-on-blur.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index a525d69..cd00ea6 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1,10 +1,5 @@
 [
   {
-    "prefix": "custom-user-timing",
-    "base": "http/tests/performance-timing/custom-user-timing",
-    "args": ["--enable-blink-features=CustomUserTiming"]
-  },
-  {
     "prefix": "gpu",
     "base": "fast/canvas",
     "args": ["--enable-accelerated-2d-canvas"]
diff --git a/third_party/blink/web_tests/animations/animation-matrix-negative-scale-unmatrix-expected.txt b/third_party/blink/web_tests/animations/animation-matrix-negative-scale-unmatrix-expected.txt
deleted file mode 100644
index 7ef22e9..0000000
--- a/third_party/blink/web_tests/animations/animation-matrix-negative-scale-unmatrix-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-PASS
diff --git a/third_party/blink/web_tests/animations/animation-matrix-negative-scale-unmatrix.html b/third_party/blink/web_tests/animations/animation-matrix-negative-scale-unmatrix.html
index 125c28a..05f1a887 100644
--- a/third_party/blink/web_tests/animations/animation-matrix-negative-scale-unmatrix.html
+++ b/third_party/blink/web_tests/animations/animation-matrix-negative-scale-unmatrix.html
@@ -21,13 +21,10 @@
                 to { transform: matrix(1, 0, 0, 1, 0, 0); }
             }
         </style>
+        <script src="../resources/testharness.js"></script>
+        <script src="../resources/testharnessreport.js"></script>
         <script type="text/javascript" charset="utf-8">
-            if (window.testRunner) {
-                testRunner.dumpAsText();
-                testRunner.waitUntilDone();
-            }
-
-            result = "PASS";
+            var test = async_test("This test performs an animation of the matrix operator");
 
             function snapshot()
             {
@@ -35,12 +32,9 @@
                 var matrix = new WebKitCSSMatrix(boxComputedStyle.transform);
 
                 // "d" component (scaleY) should be negative.
-                if (matrix["d"] > 0)
-                    result = "FAIL(scaleY was positive, expected to be negative)";
+                assert_less_than_equal(matrix["d"] , 0, "'d' component(scaleY) should be negative");
 
                 document.getElementById('result').innerHTML = result;
-                if (window.testRunner)
-                    testRunner.notifyDone();
             }
 
             function startAnimation()
@@ -48,7 +42,7 @@
                 document.getElementById("box").style.animationName = "anim";
             }
 
-            document.addEventListener('webkitAnimationStart', snapshot, false);
+            document.addEventListener('webkitAnimationStart', test.step_func_done(snapshot), false);
         </script>
     </head>
     <body>
diff --git a/third_party/blink/web_tests/animations/animation-shorthand-name-order-expected.txt b/third_party/blink/web_tests/animations/animation-shorthand-name-order-expected.txt
deleted file mode 100644
index 2b32d56..0000000
--- a/third_party/blink/web_tests/animations/animation-shorthand-name-order-expected.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-PASS Test 1: animationName was test
-PASS Test 1: animationDuration was 3s
-PASS Test 1: animationTimingFunction was ease
-PASS Test 1: animationDelay was 0s
-PASS Test 1: animationIterationCount was 1
-PASS Test 1: animationDirection was normal
-PASS Test 1: animationFillMode was none
-PASS Test 2: animationName was test
-PASS Test 2: animationDuration was 3s
-PASS Test 2: animationTimingFunction was ease
-PASS Test 2: animationDelay was 0s
-PASS Test 2: animationIterationCount was 1
-PASS Test 2: animationDirection was normal
-PASS Test 2: animationFillMode was none
-PASS Test 3: animationName was test
-PASS Test 3: animationDuration was 3s
-PASS Test 3: animationTimingFunction was ease
-PASS Test 3: animationDelay was 0s
-PASS Test 3: animationIterationCount was 1
-PASS Test 3: animationDirection was normal
-PASS Test 3: animationFillMode was forwards
-PASS Test 4: animationName was test
-PASS Test 4: animationDuration was 3s
-PASS Test 4: animationTimingFunction was ease
-PASS Test 4: animationDelay was 0s
-PASS Test 4: animationIterationCount was 1
-PASS Test 4: animationDirection was normal
-PASS Test 4: animationFillMode was forwards
-PASS Test 5: animationName was test
-PASS Test 5: animationDuration was 3s
-PASS Test 5: animationTimingFunction was linear
-PASS Test 5: animationDelay was 0s
-PASS Test 5: animationIterationCount was 1
-PASS Test 5: animationDirection was normal
-PASS Test 5: animationFillMode was forwards
-PASS Test 6: animationName was test
-PASS Test 6: animationDuration was 3s
-PASS Test 6: animationTimingFunction was linear
-PASS Test 6: animationDelay was 0s
-PASS Test 6: animationIterationCount was 1
-PASS Test 6: animationDirection was normal
-PASS Test 6: animationFillMode was forwards
-PASS Test 7: animationName was test
-PASS Test 7: animationDuration was 3s
-PASS Test 7: animationTimingFunction was linear
-PASS Test 7: animationDelay was 4s
-PASS Test 7: animationIterationCount was 5
-PASS Test 7: animationDirection was normal
-PASS Test 7: animationFillMode was forwards
-PASS Test 8: animationName was test
-PASS Test 8: animationDuration was 3s
-PASS Test 8: animationTimingFunction was linear
-PASS Test 8: animationDelay was 4s
-PASS Test 8: animationIterationCount was infinite
-PASS Test 8: animationDirection was alternate
-PASS Test 8: animationFillMode was forwards
-PASS Test 9: animationName was test
-PASS Test 9: animationDuration was 3s
-PASS Test 9: animationTimingFunction was linear
-PASS Test 9: animationDelay was 4s
-PASS Test 9: animationIterationCount was infinite
-PASS Test 9: animationDirection was alternate
-PASS Test 9: animationFillMode was none
-PASS Test 10: animationName was linear
-PASS Test 10: animationDuration was 3s
-PASS Test 10: animationTimingFunction was ease
-PASS Test 10: animationDelay was 4s
-PASS Test 10: animationIterationCount was infinite
-PASS Test 10: animationDirection was alternate
-PASS Test 10: animationFillMode was forwards
-
diff --git a/third_party/blink/web_tests/animations/animation-shorthand-name-order.html b/third_party/blink/web_tests/animations/animation-shorthand-name-order.html
index 5a465b2..382d744 100644
--- a/third_party/blink/web_tests/animations/animation-shorthand-name-order.html
+++ b/third_party/blink/web_tests/animations/animation-shorthand-name-order.html
@@ -36,7 +36,10 @@
     to { left: 100px; }
 }
 </style>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
 <script>
+var test = async_test("Shorthand animation name ordering test");
 
 const PROPERTIES_TO_TEST = [
     "animationName",
@@ -96,7 +99,6 @@
 }
 
 function runIndividualTest(testIndex) {
-    var result = document.getElementById("result");
     var element = document.getElementById("box");
 
     clearElementAnimationStyle(element);
@@ -111,31 +113,21 @@
 
     for (var i=0; i < PROPERTIES_TO_TEST.length; i++) {
         var value = computedStyle[PROPERTIES_TO_TEST[i]];
-        if (value == EXPECTED_VALUES[testIndex][i])
-            result.innerHTML += "PASS Test " + (numTestsComplete + 1) + ": " + PROPERTIES_TO_TEST[i] + " was " + value + "<br>";
-        else
-            result.innerHTML += "FAIL Test " + (numTestsComplete + 1) + ": " + PROPERTIES_TO_TEST[i] + " was " + value + " should be " + EXPECTED_VALUES[testIndex][i] + "<br>";
+        assert_equals(value, EXPECTED_VALUES[testIndex][i], "Test " + (numTestsComplete + 1) + ": " + PROPERTIES_TO_TEST[i] + " was " + value + " should be " + EXPECTED_VALUES[testIndex][i]);
     }
 
     numTestsComplete++;
     if (numTestsComplete < TEST_INPUTS.length)
         runIndividualTest(numTestsComplete);
     else {
-        if (window.testRunner)
-            testRunner.notifyDone();
+        test.done();
     }
 }
 
-if (window.testRunner) {
-    testRunner.dumpAsText();
-    testRunner.waitUntilDone();
-}
-
-window.addEventListener("load", runTests, false);
+window.addEventListener("load", test.step_func(runTests), false);
 </script>
 </head>
 <body>
 <div id="box"></div>
-<div id="result"></div>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/animations/animation-shorthand-overriding-expected.txt b/third_party/blink/web_tests/animations/animation-shorthand-overriding-expected.txt
deleted file mode 100644
index 07395ec..0000000
--- a/third_party/blink/web_tests/animations/animation-shorthand-overriding-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Testing animationName on a: PASS
-Testing animationDuration on a: PASS
-Testing animationTimingFunction on a: PASS
-Testing animationDelay on a: PASS
-Testing animationIterationCount on a: PASS
-Testing animationDirection on a: PASS
-Testing animationFillMode on a: PASS
-
diff --git a/third_party/blink/web_tests/animations/animation-shorthand-overriding.html b/third_party/blink/web_tests/animations/animation-shorthand-overriding.html
index bf556560..0faed0c 100644
--- a/third_party/blink/web_tests/animations/animation-shorthand-overriding.html
+++ b/third_party/blink/web_tests/animations/animation-shorthand-overriding.html
@@ -1,6 +1,6 @@
-<html> 
+<html>
 <head>
-<title>Test animation shorthand property</title> 
+<title>Test animation shorthand property</title>
 <style type="text/css">
 @keyframes circle {
     from { transform:rotate(0deg); }
@@ -28,10 +28,10 @@
     animation-name: inner-circle;
 }
 </style>
+  <script src="../resources/testharness.js"></script>
+  <script src="../resources/testharnessreport.js"></script>
   <script type="text/javascript" charset="utf-8">
-    if (window.testRunner)
-        testRunner.dumpAsText();
-  
+    var test = async_test("Test animation shorthand property");
     const kProperties = [
       "animationName",
       "animationDuration",
@@ -42,31 +42,24 @@
       "animationFillMode"
     ];
     const kExpectedResult =  { id: 'a',  values: [ "inner-circle", "5s", "linear", "0s", "1", "normal", "none" ] };
-    
+
     function start()
     {
       var resultsString = " ";
       var el = document.getElementById(kExpectedResult.id);
       var elStyle = window.getComputedStyle(el);
-        
+
       for (var i=0; i < kProperties.length; i++) {
           var computedValue = elStyle[kProperties[i]];
           var expectedValue = kExpectedResult.values[i];
-          if (computedValue == expectedValue)
-            resultsString += "Testing " + kProperties[i] + " on " + kExpectedResult.id + ": PASS" + "<br>";
-          else
-            resultsString += "Testing " + kProperties[i] + " on " + kExpectedResult.id + " expected <code>" + expectedValue + "</code> got <code>" + computedValue + "</code>: FAIL" + "<br>";
+          assert_equals(computedValue, expectedValue, "Testing " + kProperties[i] + " on " + kExpectedResult.id + " expected " + expectedValue);
       }
-
-      var results = document.getElementById('result');
-      results.innerHTML = resultsString;
     }
-    
-    window.addEventListener('load', start, false);
+
+    window.addEventListener('load', test.step_func_done(start), false);
   </script>
-</head> 
+</head>
 <body>
 <div><div id="a"></div></div>
-<div id="result"/>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/animations/animation-shorthand-removed-expected.txt b/third_party/blink/web_tests/animations/animation-shorthand-removed-expected.txt
deleted file mode 100644
index 27bb6d3a4..0000000
--- a/third_party/blink/web_tests/animations/animation-shorthand-removed-expected.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-Testing animationName on a: PASS
-Testing animationDuration on a: PASS
-Testing animationTimingFunction on a: PASS
-Testing animationDelay on a: PASS
-Testing animationIterationCount on a: PASS
-Testing animationDirection on a: PASS
-Testing animationFillMode on a: PASS
-Testing animationName on b: PASS
-Testing animationDuration on b: PASS
-Testing animationTimingFunction on b: PASS
-Testing animationDelay on b: PASS
-Testing animationIterationCount on b: PASS
-Testing animationDirection on b: PASS
-Testing animationFillMode on b: PASS
-Testing animationName on c: PASS
-Testing animationDuration on c: PASS
-Testing animationTimingFunction on c: PASS
-Testing animationDelay on c: PASS
-Testing animationIterationCount on c: PASS
-Testing animationDirection on c: PASS
-Testing animationFillMode on c: PASS
-Testing animationName on d: PASS
-Testing animationDuration on d: PASS
-Testing animationTimingFunction on d: PASS
-Testing animationDelay on d: PASS
-Testing animationIterationCount on d: PASS
-Testing animationDirection on d: PASS
-Testing animationFillMode on d: PASS
-Testing animationName on e: PASS
-Testing animationDuration on e: PASS
-Testing animationTimingFunction on e: PASS
-Testing animationDelay on e: PASS
-Testing animationIterationCount on e: PASS
-Testing animationDirection on e: PASS
-Testing animationFillMode on e: PASS
-Testing animationName on f: PASS
-Testing animationDuration on f: PASS
-Testing animationTimingFunction on f: PASS
-Testing animationDelay on f: PASS
-Testing animationIterationCount on f: PASS
-Testing animationDirection on f: PASS
-Testing animationFillMode on f: PASS
-Testing animationName on g: PASS
-Testing animationDuration on g: PASS
-Testing animationTimingFunction on g: PASS
-Testing animationDelay on g: PASS
-Testing animationIterationCount on g: PASS
-Testing animationDirection on g: PASS
-Testing animationFillMode on g: PASS
-Testing animationName on h: PASS
-Testing animationDuration on h: PASS
-Testing animationTimingFunction on h: PASS
-Testing animationDelay on h: PASS
-Testing animationIterationCount on h: PASS
-Testing animationDirection on h: PASS
-Testing animationFillMode on h: PASS
-
diff --git a/third_party/blink/web_tests/animations/animation-shorthand-removed.html b/third_party/blink/web_tests/animations/animation-shorthand-removed.html
index 9d2af2a..ee9245d 100644
--- a/third_party/blink/web_tests/animations/animation-shorthand-removed.html
+++ b/third_party/blink/web_tests/animations/animation-shorthand-removed.html
@@ -10,12 +10,10 @@
 
 @keyframes anim1 { }
 </style>
+  <script src="../resources/testharness.js"></script>
+  <script src="../resources/testharnessreport.js"></script>
   <script type="text/javascript" charset="utf-8">
-    if (window.testRunner) {
-        testRunner.dumpAsText();
-        testRunner.waitUntilDone();
-    }
-
+    var asyncHandle = async_test("Test removal of animation shorthand property");
     const kProperties = [
       "animationName",
       "animationDuration",
@@ -60,7 +58,7 @@
           el.style[kProperties[i]] = curEl.values[i];
         }
       });
-      setTimeout(remove, 0);
+      asyncHandle.step_timeout(asyncHandle.step_func(remove), 0);
     }
 
     function remove() {
@@ -68,7 +66,7 @@
         var el = document.getElementById(curEl.id);
         el.style.removeProperty("animation");
       });
-      setTimeout(test, 0);
+      asyncHandle.step_timeout(asyncHandle.step_func_done(test), 0);
     }
 
     function test() {
@@ -80,21 +78,12 @@
         for (var i=0; i < kProperties.length; i++) {
           var computedValue = elStyle[kProperties[i]];
           var expectedValue = kExpectedResults[i];
-          if (computedValue == expectedValue)
-            resultsString += "Testing " + kProperties[i] + " on " + curEl.id + ": PASS" + "<br>";
-          else
-            resultsString += "Testing " + kProperties[i] + " on " + curEl.id + " expected <code>" + expectedValue + "</code> got <code>" + computedValue + "</code>: FAIL" + "<br>";
-
+          assert_equals(computedValue, expectedValue, "Testing " + kProperties[i] + " on " + curEl.id + " expected " + expectedValue);
         }
       });
-
-      var results = document.getElementById('result');
-      results.innerHTML = resultsString;
-      if (window.testRunner)
-          testRunner.notifyDone();
     }
 
-    window.addEventListener('load', start, false);
+    window.addEventListener('load', asyncHandle.step_func(start), false);
   </script>
 </head>
 <body>
@@ -106,7 +95,6 @@
 <div id="f" class="box"></div>
 <div id="g" class="box"></div>
 <div id="h" class="box"></div>
-<div id="result">
 </div>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/animations/change-in-animation-frame-expected.txt b/third_party/blink/web_tests/animations/change-in-animation-frame-expected.txt
deleted file mode 100644
index 7ef22e9..0000000
--- a/third_party/blink/web_tests/animations/change-in-animation-frame-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-PASS
diff --git a/third_party/blink/web_tests/animations/change-in-animation-frame.html b/third_party/blink/web_tests/animations/change-in-animation-frame.html
index e9f9634..15ec90c0 100644
--- a/third_party/blink/web_tests/animations/change-in-animation-frame.html
+++ b/third_party/blink/web_tests/animations/change-in-animation-frame.html
@@ -1,17 +1,14 @@
 <!DOCTYPE html>
 <div id="pass" style="visibility: hidden">PASS</div>
 <div id="fail" style="visibility: visible">FAIL</div>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
 <script>
-if (window.testRunner) {
-  testRunner.dumpAsText();
-  testRunner.waitUntilDone();
-}
-
-requestAnimationFrame(function() {
+var test = async_test("Test changing in animation frame");
+requestAnimationFrame(test.step_func_done(() => {
   document.getElementById('pass').animate([{visibility: 'visible'}, {visibility: 'visible'}], {fill: 'forwards'});
   document.getElementById('fail').animate([{visibility: 'hidden'}, {visibility: 'hidden'}], {fill: 'forwards'});
-  if (window.testRunner) {
-    testRunner.notifyDone();
-  }
-});
+  assert_equals(getComputedStyle(document.getElementById('pass')).visibility, "visible");
+  assert_equals(getComputedStyle(document.getElementById('fail')).visibility, "hidden");
+}));
 </script>
diff --git a/third_party/blink/web_tests/animations/display-change-does-not-terminate-animation-expected.txt b/third_party/blink/web_tests/animations/display-change-does-not-terminate-animation-expected.txt
deleted file mode 100644
index 2ea10165..0000000
--- a/third_party/blink/web_tests/animations/display-change-does-not-terminate-animation-expected.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-Tests that changing the display property of a running animation to a value other than 'none' does not cause it to terminate or re-start.
-
-target
-INFO: Start event fired
-INFO: Setting display to inline
-PASS: Left property was not reset
-INFO: Setting display to block
-PASS: Left property was not reset
-INFO: Setting display to inline-block
-PASS: Left property was not reset
-INFO: Setting display to inline-table
-PASS: Left property was not reset
-INFO: Setting display to list-item
-PASS: Left property was not reset
-INFO: Setting display to run-in
-PASS: Left property was not reset
-INFO: Setting display to table
-PASS: Left property was not reset
-INFO: Setting display to table-caption
-PASS: Left property was not reset
-INFO: Setting display to table-column-group
-PASS: Left property was not reset
-INFO: Setting display to table-header-group
-PASS: Left property was not reset
-INFO: Setting display to table-footer-group
-PASS: Left property was not reset
-INFO: Setting display to table-row-group
-PASS: Left property was not reset
-INFO: Setting display to table-cell
-PASS: Left property was not reset
-INFO: Setting display to table-column
-PASS: Left property was not reset
-INFO: Setting display to table-row
-PASS: Left property was not reset
diff --git a/third_party/blink/web_tests/animations/display-change-does-not-terminate-animation.html b/third_party/blink/web_tests/animations/display-change-does-not-terminate-animation.html
index 20fc1c9c..97b829e6 100644
--- a/third_party/blink/web_tests/animations/display-change-does-not-terminate-animation.html
+++ b/third_party/blink/web_tests/animations/display-change-does-not-terminate-animation.html
@@ -21,40 +21,31 @@
         to   { left: 200px; }
     }
   </style>
+  <script src="../resources/testharness.js"></script>
+  <script src="../resources/testharnessreport.js"></script>
   <script type="text/javascript">
-    if (window.testRunner) {
-      testRunner.dumpAsText();
-      testRunner.waitUntilDone();
-    }
-
-    function log(message) {
-      var div = document.createElement('div');
-      div.textContent = message;
-      document.getElementById('log').appendChild(div);
-    }
+    var test = async_test("Tests that changing the display property of a running animation to a value other than 'none' does not cause it to terminate or re-start");
 
     var target;
+    var onStartFunc = test.step_func(onStart);
+
     function go() {
       target = document.getElementById('target');
-      target.addEventListener('animationstart', onStart);
+      target.addEventListener('animationstart', onStartFunc);
       target.classList.add('animated');
     }
 
     function onStart(e) {
-      log('INFO: Start event fired');
-      target.removeEventListener('animationstart', onStart);
-      target.addEventListener('animationstart', onRestart);
-      setTimeout(setDisplay.bind(null, 0), 20);
+      target.removeEventListener('animationstart', onStartFunc);
+      target.addEventListener('animationstart', test.step_func(onRestart));
+      test.step_timeout(setDisplay.bind(null, 0), 20);
     }
 
     function checkLeftValue(previousValue, isLast) {
       var currentValue = getComputedStyle(target).left;
-      var pass = parseFloat(previousValue) <= parseFloat(currentValue);
-      log((pass ? 'PASS' : 'FAIL') + ': Left property was ' + (pass ? 'not ' : '') + 'reset' +
-          (pass ? '' : ' (saw change from ' + previousValue + ' to ' + currentValue + ')'));
-      if (isLast && window.testRunner) {
-        testRunner.notifyDone();
-      }
+      assert_less_than_equal(parseFloat(previousValue), parseFloat(currentValue), 'Left property should not be reset');
+      if (isLast)
+        test.done();
     }
 
     var values = [
@@ -75,31 +66,20 @@
       'table-row'
     ];
     function setDisplay(index) {
-      log('INFO: Setting display to ' + values[index]);
       var isLast = index === values.length - 1;
-      setTimeout(checkLeftValue.bind(null, getComputedStyle(target).left, isLast), 0);
+      test.step_timeout(checkLeftValue.bind(null, getComputedStyle(target).left, isLast), 0);
       target.style.display = values[index];
       if (!isLast) {
-        setTimeout(setDisplay.bind(null, index + 1, true), 20);
+        test.step_timeout(setDisplay.bind(null, index + 1, true), 20);
       }
     }
 
     function onRestart(e) {
-      // Clear log to avoid flakiness in failure output.
-      document.getElementById('log').innerHTML = '';
-      log('FAIL: Start event fired again');
-      if (window.testRunner) {
-        testRunner.notifyDone();
-      }
+      assert_unreached("Start event fired again");
     }
   </script>
 </head>
 <body onload="go()">
-  <p>
-    Tests that changing the display property of a running animation to a value
-    other than 'none' does not cause it to terminate or re-start.
-  </p>
   <div id="target">target</div>
-  <div id="log"></div>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/animations/display-none-cancels-nested-animations-expected.txt b/third_party/blink/web_tests/animations/display-none-cancels-nested-animations-expected.txt
deleted file mode 100644
index 7ef22e9..0000000
--- a/third_party/blink/web_tests/animations/display-none-cancels-nested-animations-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-PASS
diff --git a/third_party/blink/web_tests/animations/display-none-cancels-nested-animations.html b/third_party/blink/web_tests/animations/display-none-cancels-nested-animations.html
index 274ac89..b027703 100644
--- a/third_party/blink/web_tests/animations/display-none-cancels-nested-animations.html
+++ b/third_party/blink/web_tests/animations/display-none-cancels-nested-animations.html
@@ -23,13 +23,13 @@
 <div id='container'>
   <div id='child' class='hideMe'></div>
 </div>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
 <script>
-if (window.testRunner) {
-    testRunner.waitUntilDone();
-    testRunner.dumpAsText();
-}
+var test = async_test("Test if display none cancels nested animations");
+
 var firstCall = true;
-child.addEventListener('animationstart', function(e) {
+child.addEventListener('animationstart', test.step_func((e) => {
     if (firstCall) {
         container.classList.add('hideMe');
         container.offsetTop;
@@ -37,11 +37,8 @@
         firstCall = false;
         return;
     }
-    document.documentElement.textContent = 'PASS';
-    if (window.testRunner) {
-        testRunner.notifyDone();
-    }
-});
+    test.done();
+}));
 child.classList.remove('hideMe');
 </script>
 
diff --git a/third_party/blink/web_tests/animations/display-none-iframe-has-no-animation-expected.txt b/third_party/blink/web_tests/animations/display-none-iframe-has-no-animation-expected.txt
deleted file mode 100644
index 7ef22e9..0000000
--- a/third_party/blink/web_tests/animations/display-none-iframe-has-no-animation-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-PASS
diff --git a/third_party/blink/web_tests/animations/display-none-iframe-has-no-animation.html b/third_party/blink/web_tests/animations/display-none-iframe-has-no-animation.html
index ff1cc935..513e07edc 100644
--- a/third_party/blink/web_tests/animations/display-none-iframe-has-no-animation.html
+++ b/third_party/blink/web_tests/animations/display-none-iframe-has-no-animation.html
@@ -1,12 +1,13 @@
 <!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
 <script type="text/javascript">
+  var test = async_test("Tests that children of a display:none iframe do not run animations");
+
   function go() {
-    if (window.testRunner) {
-      testRunner.waitUntilDone();
-    }
     // Wait a couple of frames for the animation inside the iframe to progress.
-    requestAnimationFrame(function() {
-      requestAnimationFrame(function() {
+    requestAnimationFrame(test.step_func(() => {
+      requestAnimationFrame(test.step_func_done(() => {
         var iframe = document.getElementById("iframe");
         iframe.style.display = "block";
         var innerDoc = iframe.contentDocument;
@@ -14,21 +15,11 @@
 
         // If the animation has been running, then we expect "left" to be
         // non-zero.
-        if (parseInt(getComputedStyle(target).left, 10) == 0)
-          document.write("PASS");
-        else
-          document.write("FAIL");
-        if (window.testRunner) {
-          testRunner.dumpAsText();
-          testRunner.notifyDone();
-        }
-      });
-    });
+        assert_equals(parseInt(getComputedStyle(target).left, 10), 0);
+      }));
+    }));
   };
 </script>
 <body onload="go()">
-  <p>
-    Tests that children of a display:none iframe do not run animations.
-  </p>
   <iframe id="iframe" style="display:none" src="resources/frame_with_animation.html"></iframe>
 </body>
diff --git a/third_party/blink/web_tests/animations/fill-unset-properties-expected.txt b/third_party/blink/web_tests/animations/fill-unset-properties-expected.txt
deleted file mode 100644
index cef1c41..0000000
--- a/third_party/blink/web_tests/animations/fill-unset-properties-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-Testing transitionDuration: PASS
-Testing transitionProperty: PASS
-Testing transitionDelay: PASS
-Testing transitionTimingFunction: PASS
-Testing animationName: PASS
-Testing animationDuration: PASS
-Testing animationDelay: PASS
-Testing animationFillMode: PASS
-
diff --git a/third_party/blink/web_tests/animations/fill-unset-properties.html b/third_party/blink/web_tests/animations/fill-unset-properties.html
index 9f70a8b1..a78e6c1 100644
--- a/third_party/blink/web_tests/animations/fill-unset-properties.html
+++ b/third_party/blink/web_tests/animations/fill-unset-properties.html
@@ -1,6 +1,6 @@
-<html> 
+<html>
 <head>
-<title>Unfilled Properties Test</title> 
+<title>Unfilled Properties Test</title>
 <style type="text/css" media="screen">
 #box {
     height: 50px;
@@ -21,10 +21,11 @@
 @keyframes d { }
 @keyframes e { }
 </style>
+  <script src="../resources/testharness.js"></script>
+  <script src="../resources/testharnessreport.js"></script>
   <script type="text/javascript" charset="utf-8">
-    if (window.testRunner)
-        testRunner.dumpAsText();
-  
+    var test = async_test("Unfilled Properties Test");
+
     const kExpectedResults = [
       { 'property': 'transitionDuration', 'value': '1s, 2s' },
       { 'property': 'transitionProperty', 'value': 'opacity, left, opacity, top, width, opacity, height, opacity' },
@@ -35,33 +36,25 @@
       { 'property': 'animationDelay',     'value': '1s' },
       { 'property': 'animationFillMode',  'value': 'forwards, backwards' },
     ];
-    
+
     function start()
     {
         var box = document.getElementById('box');
         var resultsString = "";
         var boxStyle = window.getComputedStyle(box);
-        
+
         kExpectedResults.forEach(function(curItem) {
           var computedValue = boxStyle[curItem.property];
           var expectedValue = curItem.value;
-          if (computedValue == expectedValue)
-            resultsString += "Testing " + curItem.property + ": PASS" + "<br>";
-          else
-            resultsString += "Testing " + curItem.property + " expected <code>" + curItem.value + "</code> got <code>" + computedValue + "</code>: FAIL" + "<br>";
+          assert_equals(computedValue, expectedValue, "Testing " + curItem.property + " expected " + curItem.value);
         });
-
-        var results = document.getElementById('result');
-        results.innerHTML = resultsString;
     }
-    
-    window.addEventListener('load', start, false);
+
+    window.addEventListener('load', test.step_func_done(start), false);
   </script>
-</head> 
+</head>
 <body>
 <div id="box">
 </div>
-<div id="result">
-</div>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/animations/keyframe-autoclose-brace-expected.txt b/third_party/blink/web_tests/animations/keyframe-autoclose-brace-expected.txt
deleted file mode 100644
index 634f0e60..0000000
--- a/third_party/blink/web_tests/animations/keyframe-autoclose-brace-expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Tests parsing the @keyframes rule without closing brace. "User agents must close all open constructs ... at the end of the style sheet." (http://www.w3.org/TR/CSS21/syndata.html#parsing-errors). So it must be parsed as if all braces are closed.
-PASS: keyframes rule has length 4
diff --git a/third_party/blink/web_tests/animations/keyframe-autoclose-brace.html b/third_party/blink/web_tests/animations/keyframe-autoclose-brace.html
index 6f320d3..2557161 100644
--- a/third_party/blink/web_tests/animations/keyframe-autoclose-brace.html
+++ b/third_party/blink/web_tests/animations/keyframe-autoclose-brace.html
@@ -12,7 +12,11 @@
         60%  { left: 200px; }
         to   { left: 300px;
   </style>
+  <script src="../resources/testharness.js"></script>
+  <script src="../resources/testharnessreport.js"></script>
   <script type="text/javascript" charset="utf-8">
+    var asyncHandle = async_test("Tests parsing the @keyframes rule without closing brace. 'User agents must close all open constructs ... at the end of the style sheet.'(http://www.w3.org/TR/CSS21/syndata.html#parsing-errors). So it must be parsed as if all braces are closed");
+
     function findKeyframesRule(rule)
     {
         var ss = document.styleSheets;
@@ -22,28 +26,20 @@
                     return ss[i].cssRules[j];
             }
         }
-        
+
         return null;
     }
-        
+
     function test()
     {
-        if (window.testRunner)
-            testRunner.dumpAsText();
-
         var keyframes = findKeyframesRule("foo");
         var length = keyframes ? keyframes.cssRules.length : undefined;
-        document.getElementById("console").textContent = length === 4
-            ? "PASS: keyframes rule has length 4"
-            : ("FAIL: keyframes rule should have length 4 but had length " + length);
+        assert_equals(length, 4, 'keyframes rule should have length 4');
     }
-    
+
+    window.onload = asyncHandle.step_func_done(test);
   </script>
 </head>
-<body onload="test()">
-<div>Tests parsing the @keyframes rule without closing brace. &quot;User agents must close all open constructs ... at the end of the style sheet.&quot;
-(<a href="http://www.w3.org/TR/CSS21/syndata.html#parsing-errors">http://www.w3.org/TR/CSS21/syndata.html#parsing-errors</a>). So it must be parsed as if
-all braces are closed.</div>
-<div id="console"></div>
+<body>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/animations/keyframe-selector-negative-percentage-expected.txt b/third_party/blink/web_tests/animations/keyframe-selector-negative-percentage-expected.txt
deleted file mode 100644
index 92420042..0000000
--- a/third_party/blink/web_tests/animations/keyframe-selector-negative-percentage-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-The background color of this element should be green and the text should be white.
-PASS: background color is green
-PASS: text color is white
-
diff --git a/third_party/blink/web_tests/animations/keyframe-selector-negative-percentage.html b/third_party/blink/web_tests/animations/keyframe-selector-negative-percentage.html
index 1830703..c24fc29 100644
--- a/third_party/blink/web_tests/animations/keyframe-selector-negative-percentage.html
+++ b/third_party/blink/web_tests/animations/keyframe-selector-negative-percentage.html
@@ -5,31 +5,20 @@
 <style>
 #test { background-color: red; color: black }
 @keyframes fade { -10% { color: red; } }
-#test { background-color: green; }                 /* if skipped, then background will be red */ 
+#test { background-color: green; }                 /* if skipped, then background will be red */
 #test { color: white; }                            /* if skipped, then text will be black */
 </style>
 </head>
 <body>
 <div id="test">The background color of this element should be green and the text should be white.</div>
-<div id="result"></div>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
 <script>
-if (window.testRunner)
-    testRunner.dumpAsText();
 var r = '';
 var s = getComputedStyle(document.getElementById("test"));
-if (s.backgroundColor === "rgb(0, 128, 0)") {
-  r += 'PASS: background color is green';
-} else {
-  r += 'FAIL: background color not green';
-}
-r += '<br>';
-if (s.color === "rgb(255, 255, 255)") {
-  r += 'PASS: text color is white';
-} else {
-  r += 'FAIL: text color not white';
-}
-r += '<br>';
-document.getElementById("result").innerHTML = r;
+assert_equals(s.backgroundColor, "rgb(0, 128, 0)", 'background color should be green');
+assert_equals(s.color, "rgb(255, 255, 255)", 'text color should be white');
+done();
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/animations/wrong-keyframe-name-expected.txt b/third_party/blink/web_tests/animations/wrong-keyframe-name-expected.txt
deleted file mode 100644
index 549ba22..0000000
--- a/third_party/blink/web_tests/animations/wrong-keyframe-name-expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Tests that an animation does not run when it specifies an incorrect name.
-PASS
diff --git a/third_party/blink/web_tests/animations/wrong-keyframe-name.html b/third_party/blink/web_tests/animations/wrong-keyframe-name.html
index 9cccd80..668db79 100644
--- a/third_party/blink/web_tests/animations/wrong-keyframe-name.html
+++ b/third_party/blink/web_tests/animations/wrong-keyframe-name.html
@@ -31,26 +31,16 @@
     }
 }
 </style>
-Tests that an animation does not run when it specifies an incorrect name.
-<div id="result">FAIL - nothing happened</div>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
 <div id="test1"></div>
 <div id="test2"></div>
 <div id="test3"></div>
 <script>
-if (window.testRunner) {
-    testRunner.dumpAsText();
-    testRunner.waitUntilDone();
-}
-var pass = true;
-test1.addEventListener('animationstart', function() {
+var test = async_test("Tests that an animation does not run when it specifies an incorrect name");
+test1.addEventListener('animationstart', test.step_func(() => {
     test2.style.animationName = 'green';
-});
-test2.addEventListener('animationstart', function() {
-    result.innerText = pass ? 'PASS' : 'FAIL';
-    if (window.testRunner)
-        testRunner.notifyDone();
-});
-test3.addEventListener('animationstart', function() {
-    pass = false;
-});
+}));
+test2.addEventListener('animationstart', test.step_func_done(() => {}));
+test3.addEventListener('animationstart', test.unreached_func("Should not run when it specifies an incorrect name"));
 </script>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/acquire-after-resize.html b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-after-resize.html
index 0a7558c..31f43420 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/acquire-after-resize.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-after-resize.html
@@ -13,10 +13,6 @@
   width: 50px;
   height: 50px;
 }
-#large {
-  width: 150px;
-  height: 150px;
-}
 #spacer {
   width: 50px;
   height: 50px;
@@ -42,8 +38,7 @@
 
 function runTest() {
   let container = document.getElementById("small");
-  container.id = "large";
-  container.displayLock.acquire({ timeout: Infinity }).then(
+  container.displayLock.acquire({ timeout: Infinity, size: [150, 150] }).then(
     () => { finishTest("PASS"); },
     (e) => { finishTest("FAIL " + e.message); });
 }
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/delayed-acquire-removes-painted-output.html b/third_party/blink/web_tests/display-lock/lock-after-append/delayed-acquire-removes-painted-output.html
index bb4c87a..6d4316d 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/delayed-acquire-removes-painted-output.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/delayed-acquire-removes-painted-output.html
@@ -33,7 +33,7 @@
 
 function runTest() {
   let container = document.getElementById("container");
-  container.displayLock.acquire({ timeout: Infinity }).then(() => {
+  container.displayLock.acquire({ timeout: Infinity, size: [150, 150] }).then(() => {
     finishTest();
   });
 }
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/locked-attribute.html b/third_party/blink/web_tests/display-lock/lock-after-append/locked-attribute.html
index e969bbe..9164a09a 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/locked-attribute.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/locked-attribute.html
@@ -18,7 +18,7 @@
     t.step(() => assert_false(container.displayLock.locked, "initial context is unlocked"));
 
     let acquire_promise = container.displayLock.acquire({ timeout: Infinity });
-    t.step(() => assert_false(container.displayLock.locked, "context before acquire finishes is unlocked"));
+    t.step(() => assert_true(container.displayLock.locked, "context before acquire finishes is locked"));
 
     await acquire_promise;
     t.step(() => assert_true(container.displayLock.locked, "context after acquire finishes is locked"));
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-prevents-anchor-links.html b/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-prevents-anchor-links.html
index 2c1be09..b1772b9 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-prevents-anchor-links.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-prevents-anchor-links.html
@@ -38,7 +38,7 @@
 
 function runTest() {
   let container = document.getElementById("container");
-  container.displayLock.acquire({ timeout: Infinity }).then(() => {
+  container.displayLock.acquire({ timeout: Infinity, size: [150, 150] }).then(() => {
     location.href += "#target";
     requestAnimationFrame(finishTest);
   });
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-prevents-scroll-into-view.html b/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-prevents-scroll-into-view.html
index 8ef786f..e2e4b19 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-prevents-scroll-into-view.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-prevents-scroll-into-view.html
@@ -38,7 +38,7 @@
 
 function runTest() {
   let container = document.getElementById("container");
-  container.displayLock.acquire({ timeout: Infinity }).then(() => {
+  container.displayLock.acquire({ timeout: Infinity, size: [150, 150] }).then(() => {
     document.getElementById("target").scrollIntoView();
     requestAnimationFrame(finishTest);
   });
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-shifted-down.html b/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-shifted-down.html
index bf9ce4e..d8ed88b1 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-shifted-down.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/locked-element-shifted-down.html
@@ -42,7 +42,7 @@
 
 function runTest() {
   let container = document.getElementById("container");
-  container.displayLock.acquire({ timeout: Infinity }).then(() => {
+  container.displayLock.acquire({ timeout: Infinity, size: [150, 150] }).then(() => {
     document.getElementById("spacer").style.height = "100px";
     finishTest("PASS");
   });
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout-after-commit.html b/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout-after-commit.html
index 0091e45b..08df37e 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout-after-commit.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout-after-commit.html
@@ -6,8 +6,6 @@
   background: lightgreen;
 }
 #small {
-  width: 100px;
-  height: 100px;
 }
 #large {
   width: 200px;
@@ -73,7 +71,7 @@
 
   async function runTest() {
     let container = document.getElementById("small");
-    await container.displayLock.acquire({ timeout: Infinity });
+    await container.displayLock.acquire({ timeout: Infinity, size: [100, 100] });
 
     construct(container);
     measureForced();
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout.html b/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout.html
index 4675fdf6..8d5da176 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/measure-forced-layout.html
@@ -6,8 +6,6 @@
   background: lightgreen;
 }
 #small {
-  width: 100px;
-  height: 100px;
 }
 #large {
   width: 200px;
@@ -73,7 +71,7 @@
 
   async function runTest() {
     let container = document.getElementById("small");
-    await container.displayLock.acquire({ timeout: Infinity });
+    await container.displayLock.acquire({ timeout: Infinity, size: [100, 100] });
 
     construct(container);
     measureForced();
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/measure-updated-layout.html b/third_party/blink/web_tests/display-lock/lock-after-append/measure-updated-layout.html
index 5538f4f..166f2dd 100644
--- a/third_party/blink/web_tests/display-lock/lock-after-append/measure-updated-layout.html
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/measure-updated-layout.html
@@ -6,8 +6,6 @@
   background: lightgreen;
 }
 #small {
-  width: 100px;
-  height: 100px;
 }
 #large {
   width: 200px;
@@ -73,7 +71,7 @@
 
   async function runTest() {
     let container = document.getElementById("small");
-    await container.displayLock.acquire({ timeout: Infinity });
+    await container.displayLock.acquire({ timeout: Infinity, size: [100, 100] });
 
     construct(container);
 
diff --git a/third_party/blink/web_tests/editing/pasteboard/drop-text-without-selection.html b/third_party/blink/web_tests/editing/pasteboard/drop-text-without-selection.html
index a5644e4..a6fc4434 100644
--- a/third_party/blink/web_tests/editing/pasteboard/drop-text-without-selection.html
+++ b/third_party/blink/web_tests/editing/pasteboard/drop-text-without-selection.html
@@ -1,10 +1,7 @@
-<script>
-if (window.testRunner) {
-    testRunner.dumpEditingCallbacks();
-    testRunner.dumpAsLayoutWithPixelResults();
-}
-</script>
-<body onload="runTest()">
+<!doctype html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<body>
 <p>
     This is a test for <i><a href="https://bugs.webkit.org/show_bug.cgi?id=8394">http://bugzilla.opendarwin.org/show_bug.cgi?id=8394</a>
     Editable region does not accept dropped text if there is no selection</i>.
@@ -18,12 +15,8 @@
 <a id="link" href="http://www.ibm.com/">drop me into the text field</a>
 
 <script>
-
-function runTest() {
-    if (!window.testRunner)
-        return;
-
-    testRunner.waitUntilDone();
+test(() => {
+    assert_own_property(window, 'eventSender');
 
     var link = document.getElementById("link");
 
@@ -42,8 +35,8 @@
     eventSender.mouseMoveTo(x, y);
     eventSender.mouseUp();
 
-    testRunner.notifyDone();
-}
+    assert_equals(field.value, 'http://www.ibm.com/');
+});
 
 </script>
 
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
index 3006095..d36cced 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -5671,6 +5671,12 @@
      {}
     ]
    ],
+   "payment-request/payment-response/payerdetailschange-updateWith-manual.https.html": [
+    [
+     "/payment-request/payment-response/payerdetailschange-updateWith-manual.https.html",
+     {}
+    ]
+   ],
    "payment-request/payment-response/rejects_if_not_active-manual.https.html": [
     [
      "/payment-request/payment-response/rejects_if_not_active-manual.https.html",
@@ -6433,6 +6439,12 @@
      {}
     ]
    ],
+   "web-nfc/NFCReader_options_url-manual.https.html": [
+    [
+     "/web-nfc/NFCReader_options_url-manual.https.html",
+     {}
+    ]
+   ],
    "web-nfc/nfc_hw_disabled-manual.https.html": [
     [
      "/web-nfc/nfc_hw_disabled-manual.https.html",
@@ -159403,26 +159415,11 @@
      {}
     ]
    ],
-   "dom/events/AddEventListenerOptions-passive-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "dom/events/Event-defaultPrevented-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "dom/events/Event-dispatch-listener-order.window-expected.txt": [
     [
      {}
     ]
    ],
-   "dom/events/Event-returnValue-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "dom/events/EventListener-handleEvent-expected.txt": [
     [
      {}
@@ -174238,6 +174235,11 @@
      {}
     ]
    ],
+   "html/semantics/forms/the-output-element/mutations.window-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "html/semantics/forms/the-output-element/output-setcustomvalidity-expected.txt": [
     [
      {}
@@ -174473,11 +174475,6 @@
      {}
     ]
    ],
-   "html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.tentative-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base-expected.txt": [
     [
      {}
@@ -197678,6 +197675,11 @@
      {}
     ]
    ],
+   "user-timing/resources/user-timing-helper.js": [
+    [
+     {}
+    ]
+   ],
    "user-timing/resources/webperftestharness.js": [
     [
      {}
@@ -198383,6 +198385,11 @@
      {}
     ]
    ],
+   "web-nfc/NFCReader_options_url-manual.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "web-nfc/NFCReadingEvent_constructor.https-expected.txt": [
     [
      {}
@@ -252791,6 +252798,12 @@
      {}
     ]
    ],
+   "html/semantics/embedded-content/media-elements/src_object_blob.html": [
+    [
+     "/html/semantics/embedded-content/media-elements/src_object_blob.html",
+     {}
+    ]
+   ],
    "html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html": [
     [
      "/html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html",
@@ -255897,6 +255910,12 @@
      {}
     ]
    ],
+   "html/semantics/forms/the-output-element/mutations.window.js": [
+    [
+     "/html/semantics/forms/the-output-element/mutations.window.html",
+     {}
+    ]
+   ],
    "html/semantics/forms/the-output-element/output-setcustomvalidity.html": [
     [
      "/html/semantics/forms/the-output-element/output-setcustomvalidity.html",
@@ -256290,13 +256309,17 @@
    "html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html": [
     [
      "/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html": [
     [
      "/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "html/semantics/rellist-feature-detection.html": [
@@ -293861,6 +293884,12 @@
      {}
     ]
    ],
+   "svg/pservers/pattern-with-invalid-base-cloned-crash.html": [
+    [
+     "/svg/pservers/pattern-with-invalid-base-cloned-crash.html",
+     {}
+    ]
+   ],
    "svg/pservers/scripted/stop-color-inheritance-currentcolor.svg": [
     [
      "/svg/pservers/scripted/stop-color-inheritance-currentcolor.svg",
@@ -295161,12 +295190,30 @@
      {}
     ]
    ],
+   "user-timing/mark-errors.html": [
+    [
+     "/user-timing/mark-errors.html",
+     {}
+    ]
+   ],
+   "user-timing/mark-l3.html": [
+    [
+     "/user-timing/mark-l3.html",
+     {}
+    ]
+   ],
    "user-timing/mark-measure-feature-detection.html": [
     [
      "/user-timing/mark-measure-feature-detection.html",
      {}
     ]
    ],
+   "user-timing/mark-measure-return-objects.html": [
+    [
+     "/user-timing/mark-measure-return-objects.html",
+     {}
+    ]
+   ],
    "user-timing/mark.any.js": [
     [
      "/user-timing/mark.any.html",
@@ -295189,6 +295236,18 @@
      {}
     ]
    ],
+   "user-timing/measure-l3.html": [
+    [
+     "/user-timing/measure-l3.html",
+     {}
+    ]
+   ],
+   "user-timing/measure-with-dict.html": [
+    [
+     "/user-timing/measure-with-dict.html",
+     {}
+    ]
+   ],
    "user-timing/measure.html": [
     [
      "/user-timing/measure.html",
@@ -299143,6 +299202,14 @@
      {}
     ]
    ],
+   "webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html": [
+    [
+     "/webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html",
+     {
+      "timeout": "long"
+     }
+    ]
+   ],
    "webrtc/RTCPeerConnection-iceConnectionState.https.html": [
     [
      "/webrtc/RTCPeerConnection-iceConnectionState.https.html",
@@ -390687,7 +390754,7 @@
    "testharness"
   ],
   "css/css-variables/variable-exponential-blowup.html": [
-   "513a6f1628f17d31211b75ce4351b7dc95523a87",
+   "36a67d343882dd59d8139dd9edc8d94a2cf44b54",
    "testharness"
   ],
   "css/css-variables/variable-first-letter.html": [
@@ -407118,10 +407185,6 @@
    "ae750702c79d0e2f493537ade1c78558987f536e",
    "testharness"
   ],
-  "dom/events/AddEventListenerOptions-passive-expected.txt": [
-   "82aafaa0c0df1819320fe4bbd4ca47cbd9214396",
-   "support"
-  ],
   "dom/events/AddEventListenerOptions-passive.html": [
    "bf41580325c87b0d6680e4800e5c1cd57102765a",
    "testharness"
@@ -407146,10 +407209,6 @@
    "8fef005eb57772ada0260a469eca5de95cd7e183",
    "testharness"
   ],
-  "dom/events/Event-defaultPrevented-expected.txt": [
-   "d61a3b6cddf92ac1fc84aa1c5d689ab3b06730dd",
-   "support"
-  ],
   "dom/events/Event-defaultPrevented.html": [
    "2548fa3e064bb1911b52025273975f02614ffefc",
    "testharness"
@@ -407199,7 +407258,7 @@
    "testharness"
   ],
   "dom/events/Event-dispatch-on-disabled-elements.html": [
-   "b4786ab16b5db6fc569394d806e10fd9665200dd",
+   "72e63c4d1e97f1113dd7db357921fd1b0ab9372b",
    "testharness"
   ],
   "dom/events/Event-dispatch-order.html": [
@@ -407250,10 +407309,6 @@
    "33989eb4bf95262b8beba6b760a7b2fa62a5499b",
    "testharness"
   ],
-  "dom/events/Event-returnValue-expected.txt": [
-   "fa10e604035ee0fdb6633be1652f7803d11347e4",
-   "support"
-  ],
   "dom/events/Event-returnValue.html": [
    "08df2d41416ffccf65c9fe606469181a9f95f6a8",
    "testharness"
@@ -426738,6 +426793,10 @@
    "56a99028deb273359f32fc14b53b9317a4b9c76d",
    "testharness"
   ],
+  "html/semantics/embedded-content/media-elements/src_object_blob.html": [
+   "481a8184ea2fdc6220b147d43a653ed510cfd104",
+   "testharness"
+  ],
   "html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html": [
    "3dd43cc3f5524a32b7438e33481552653076cbe8",
    "testharness"
@@ -427175,7 +427234,7 @@
    "testharness"
   ],
   "html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html": [
-   "043c941b123b186ee8814aa93d750403be5962e9",
+   "2acae212d231f6433ae4eff01039a263d9fa817b",
    "testharness"
   ],
   "html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html": [
@@ -430262,6 +430321,14 @@
    "cccdc37487e38917fec3aff21ed772ce760b8f05",
    "testharness"
   ],
+  "html/semantics/forms/the-output-element/mutations.window-expected.txt": [
+   "aaca4d44330d67bc6c39514741e8d82efb9d5bb5",
+   "support"
+  ],
+  "html/semantics/forms/the-output-element/mutations.window.js": [
+   "aedfc8a54cb499587aed4c10942f67798bcbe66f",
+   "testharness"
+  ],
   "html/semantics/forms/the-output-element/output-setcustomvalidity-expected.txt": [
    "e5d2579bdb8384a7406629506a6dc415b10871dc",
    "support"
@@ -430875,19 +430942,15 @@
    "support"
   ],
   "html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html": [
-   "32bf32c30418fa32e376f6813d72d7e3a74f72d4",
+   "97320090cf039c7352d3f302a42c4bee8765bbd7",
    "testharness"
   ],
-  "html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.tentative-expected.txt": [
-   "f6a44d6bfb0ac1777716ca9ea90561f33fc7a587",
-   "support"
-  ],
   "html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base-expected.txt": [
    "aab46c1ec6afd0709f9e87e761ad0f0fcc0ebeb5",
    "support"
   ],
   "html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html": [
-   "44b91a2ffb0c5c09cdf2ab4f2246c5f7bb28f5dc",
+   "8d1b54baccdfd49403c6d192d4c287d3d8818636",
    "testharness"
   ],
   "html/semantics/links/linktypes/alternate-css-ref.html": [
@@ -450162,6 +450225,10 @@
    "85a44a819cd8555e032520f887cf89508bdb98b6",
    "manual"
   ],
+  "payment-request/payment-response/payerdetailschange-updateWith-manual.https.html": [
+   "30e27088e7de1384489fcf9aa72391d353e34b36",
+   "manual"
+  ],
   "payment-request/payment-response/rejects_if_not_active-manual.https.html": [
    "516573c581a0a047a2f9b9a89d027568f8567c05",
    "manual"
@@ -468486,6 +468553,10 @@
    "73516f62c15232a2a0409e3ca75684bff3fc92d7",
    "testharness"
   ],
+  "svg/pservers/pattern-with-invalid-base-cloned-crash.html": [
+   "04a453545f5938489eb111a23a16c8c89065ed4e",
+   "testharness"
+  ],
   "svg/pservers/reftests/meshgradient-basic-001-ref.png": [
    "691bff6244cd0abe046536efc0a100329b62d407",
    "support"
@@ -473775,7 +473846,7 @@
    "support"
   ],
   "tools/wpt/run.py": [
-   "0ffc779d9339c20d78c673b6102d35aba71ad636",
+   "ffdd8efa946310cb6fa1c3fe61b33546919b2176",
    "support"
   ],
   "tools/wpt/testfiles.py": [
@@ -473887,7 +473958,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/chrome.py": [
-   "5b586bad8c2214eb55dc1c3d43119f66981d7a7f",
+   "71f246f4b6d8452f321517ac62dc42e0db978e42",
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/chrome_android.py": [
@@ -473895,7 +473966,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/edge.py": [
-   "027c8f87d493c29f5c38e02d7e0540aa8cca9fcd",
+   "21d41d1be2f20d28d5789bb0a08cf50884fe7e1f",
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/edge_webdriver.py": [
@@ -474259,7 +474330,7 @@
    "support"
   ],
   "tools/wptserve/wptserve/handlers.py": [
-   "2dd01e29338115c1c4c6e4a35973835fe0193137",
+   "e846ff807a6163688473d80e9cdbaca8d13f45ff",
    "support"
   ],
   "tools/wptserve/wptserve/logger.py": [
@@ -474279,7 +474350,7 @@
    "support"
   ],
   "tools/wptserve/wptserve/response.py": [
-   "00a609b2950ddbb696bf80f2ec0038f427f8f465",
+   "efc65ef180133a95dd606fd9a32742faf9cae52f",
    "support"
   ],
   "tools/wptserve/wptserve/router.py": [
@@ -475454,10 +475525,22 @@
    "e47a3ba7a981e978cdf015f8fc6bfbae6762dba9",
    "testharness"
   ],
+  "user-timing/mark-errors.html": [
+   "c182a39c65e12a4a697e4c42fb2bd7e3aa3c874d",
+   "testharness"
+  ],
+  "user-timing/mark-l3.html": [
+   "429768d5557dbe04d6cddc20f526ab33ae8c9b44",
+   "testharness"
+  ],
   "user-timing/mark-measure-feature-detection.html": [
    "6f1ad489e95680fc5d1be4e25dcaa2eeee9a0aa5",
    "testharness"
   ],
+  "user-timing/mark-measure-return-objects.html": [
+   "d2d8cc3c70ed78dd040b1ac451e36cf45731e362",
+   "testharness"
+  ],
   "user-timing/mark.any.js": [
    "781bbcbfca6cc042b7ef4d493f46215cf7a0d7df",
    "testharness"
@@ -475470,6 +475553,14 @@
    "e1f4c4e0f49484cedd8b6025bbe854c0503c94c1",
    "testharness"
   ],
+  "user-timing/measure-l3.html": [
+   "0e8dacfef2bb71897bb5fe6872c783d71f8c36ef",
+   "testharness"
+  ],
+  "user-timing/measure-with-dict.html": [
+   "83990a6c33314e4a7f6b965e21f0eafe2a2d92fb",
+   "testharness"
+  ],
   "user-timing/measure.html": [
    "40f71a3362b581f3d0b23f5c0202a5d400a499b9",
    "testharness"
@@ -475498,6 +475589,10 @@
    "d0ab11e39aeff5b51f9294396c037744682b4bf9",
    "testharness"
   ],
+  "user-timing/resources/user-timing-helper.js": [
+   "8d43768ec2819620bf637c41918e8a6e6bc72181",
+   "support"
+  ],
   "user-timing/resources/webperftestharness.js": [
    "4a8e2de69fc803c7fd06d7372a0de395aceec670",
    "support"
@@ -476870,6 +476965,14 @@
    "5a0e88433f23d0ca8f71df8d9fcd0c7ebe036345",
    "testharness"
   ],
+  "web-nfc/NFCReader_options_url-manual.https-expected.txt": [
+   "97cc23738ebe96d5e6e719719465ee9c716653cc",
+   "support"
+  ],
+  "web-nfc/NFCReader_options_url-manual.https.html": [
+   "882d663c65491d9182ee6c4b7c5fb55e0da8923c",
+   "manual"
+  ],
   "web-nfc/NFCReadingEvent_constructor.https-expected.txt": [
    "c0163f7946ac4c87e9d0ebe96447e00ca7b92dae",
    "support"
@@ -479879,9 +479982,13 @@
    "testharness"
   ],
   "webrtc/RTCPeerConnection-helper.js": [
-   "90867b24fdab3f3228d8d25a1685ce62d03db69d",
+   "efbb1a23c88b2a5f524391cbe66c8495624ceaa3",
    "support"
   ],
+  "webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html": [
+   "dbfc41e0c375dea0711a8cf312846cbdb27c570b",
+   "testharness"
+  ],
   "webrtc/RTCPeerConnection-iceConnectionState-expected.txt": [
    "b28601423de0b987c27db05d4b4061ece60f0129",
    "support"
@@ -484883,7 +484990,7 @@
    "support"
   ],
   "webxr/idlharness.https.window-expected.txt": [
-   "65bc029f50ac9e07823df1698a329da04268e4fc",
+   "a00bc3610a5f316dd8cf94aa659d28b471ee09a1",
    "support"
   ],
   "webxr/idlharness.https.window.js": [
@@ -484979,7 +485086,7 @@
    "testharness"
   ],
   "webxr/xrRigidTransform_inverse.https.html": [
-   "ddae2af6469034e67dc579dfd6cfb53b86f28d6a",
+   "e795a99538e27d7a85a75c652b9b972d119e91d6",
    "testharness"
   ],
   "webxr/xrRigidTransform_matrix.https.html": [
@@ -485015,7 +485122,7 @@
    "testharness"
   ],
   "webxr/xrSession_requestAnimationFrame_data_valid.https.html": [
-   "6c567d2fda6888ee0b30e4f4716e75ee4763516d",
+   "2278666a1d7cfc43362b5e09ddf0df25fef42681",
    "testharness"
   ],
   "webxr/xrSession_requestAnimationFrame_getViewerPose.https.html": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-variables/variable-exponential-blowup.html b/third_party/blink/web_tests/external/wpt/css/css-variables/variable-exponential-blowup.html
index 513a6f16..36a67d34 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-variables/variable-exponential-blowup.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-variables/variable-exponential-blowup.html
@@ -10,8 +10,8 @@
   let css = `
     --v0: "Something really really really long";
   `;
-  for (let i = 0; i < 30; ++i)
-    css += `--v${i + 1}: var(--v${i}), var(--v${i});`;
+  for (let i = 0; i < 31; ++i)
+    css += `--v${i + 1}: var(--v${i}) var(--v${i});`;
   let s = document.createElement("style");
   s.innerHTML = `
     :root { ${css}; }
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/AddEventListenerOptions-passive-expected.txt b/third_party/blink/web_tests/external/wpt/dom/events/AddEventListenerOptions-passive-expected.txt
deleted file mode 100644
index 82aafaa..0000000
--- a/third_party/blink/web_tests/external/wpt/dom/events/AddEventListenerOptions-passive-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-PASS Supports passive option on addEventListener only
-PASS preventDefault should be ignored if-and-only-if the passive option is true
-FAIL returnValue should be ignored if-and-only-if the passive option is true assert_equals: Incorrect defaultPrevented for options: {"passive":true} expected false but got true
-PASS passive behavior of one listener should be unaffected by the presence of other listeners
-PASS Equivalence of option values
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/Event-defaultPrevented-expected.txt b/third_party/blink/web_tests/external/wpt/dom/events/Event-defaultPrevented-expected.txt
deleted file mode 100644
index d61a3b6c..0000000
--- a/third_party/blink/web_tests/external/wpt/dom/events/Event-defaultPrevented-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-This is a testharness.js-based test.
-PASS When an event is created, defaultPrevented should be initialized to false.
-PASS initEvent should work correctly (not cancelable).
-PASS preventDefault() should not change defaultPrevented if cancelable is false.
-FAIL returnValue should not change defaultPrevented if cancelable is false. assert_equals: defaultPrevented expected false but got true
-PASS initEvent should work correctly (cancelable).
-PASS preventDefault() should change defaultPrevented if cancelable is true.
-PASS returnValue should change defaultPrevented if cancelable is true.
-PASS initEvent should unset defaultPrevented.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-on-disabled-elements.html b/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-on-disabled-elements.html
index b4786ab1..72e63c4 100644
--- a/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-on-disabled-elements.html
+++ b/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-on-disabled-elements.html
@@ -6,6 +6,16 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="/resources/testdriver.js"></script>
 <script src="/resources/testdriver-vendor.js"></script>
+<style>
+  @keyframes fade {
+    0% {
+      opacity: 1;
+    }
+    100% {
+      opacity: 0;
+    }
+  }
+</style>
 <body>
 <script>
 // HTML elements that can be disabled
@@ -100,94 +110,62 @@
 }, "Calling click() on disabled elements must not dispatch events.");
 
 promise_test(async () => {
-  // Style sheet that controls transition.
-  const style = document.createElement("style");
-  style.innerText = `
-    ${formElements.join(", ")} {
-      opacity: 0.1;
-      transition-property: opacity;
-      transition-duration: .1s;
-    }
-    .transition {
-      opacity: 1;
-    }
-  `;
-  document.head.appendChild(style);
-
-  // Triggers the transition in the element being tested.
-  const transitionTrigger = document.createElement("button");
-  transitionTrigger.innerText = "Trigger button";
-  document.body.appendChild(transitionTrigger);
-
   // For each form element type, set up transition event handlers.
   for (const localName of formElements) {
     const elem = document.createElement(localName);
     elem.disabled = true;
     document.body.appendChild(elem);
-    const transitionPromises = [
+    const eventPromises = [
       "transitionrun",
       "transitionstart",
       "transitionend",
     ].map(eventType => {
       return new Promise(r => {
-        const handlerName = `on${eventType}`;
-        elem[handlerName] = ev => {
-          elem[handlerName] = null;
-          r();
-        };
+        elem.addEventListener(eventType, r);
       });
     });
-
-    // Trigger transitions specifically on this element
-    // it requires a trusted event.
-    transitionTrigger.onclick = () => {
-      elem.classList.toggle("transition");
-    };
-    await test_driver.click(transitionTrigger);
-
+    // Flushing style triggers transition.
+    getComputedStyle(elem).opacity;
+    elem.style.transition = "opacity .1s";
+    elem.style.opacity = 0;
+    getComputedStyle(elem).opacity;
     // All the events fire...
-    await Promise.all(transitionPromises);
-    elem.classList.remove("transition");
+    await Promise.all(eventPromises);
+    elem.remove();
+  }
+}, "CSS Transitions transitionrun, transitionstart, transitionend events fire on disabled form elements");
 
-    // Let's now test the "transitioncancel" event.
+promise_test(async () => {
+  // For each form element type, set up transition event handlers.
+  for (const localName of formElements) {
+    const elem = document.createElement(localName);
+    elem.disabled = true;
+    document.body.appendChild(elem);
+    getComputedStyle(elem).opacity;
+    elem.style.transition = "opacity 100s";
+    // We use ontransitionstart to cancel the event.
     elem.ontransitionstart = () => {
-      // Cancel the transition by hiding it.
       elem.style.display = "none";
-      elem.classList.remove("transition");
     };
-
-    // Trigger the transition again!
     const promiseToCancel = new Promise(r => {
       elem.ontransitioncancel = r;
     });
-    await test_driver.click(transitionTrigger);
+    // Flushing style triggers the transition.
+    elem.style.opacity = 0;
+    getComputedStyle(elem).opacity;
     await promiseToCancel;
     // And we are done with this element.
     elem.remove();
   }
-  // And we are done with the test... clean up.
-  transitionTrigger.remove();
-  style.remove();
-}, "CSS Transitions events fire on disabled form elements");
+}, "CSS Transitions transitioncancel event fires on disabled form elements");
 
 promise_test(async () => {
-  const style = document.createElement("style");
-  style.innerText = `
-    .animate {
-      animation: fade .1s 2;
-    }
-    @keyframes fade {
-      0% { opacity: 1; }
-      100% { opacity: 0.2; }
-    }
-  `;
-  document.head.appendChild(style);
   // For each form element type, set up transition event handlers.
   for (const localName of formElements) {
     const elem = document.createElement(localName);
     document.body.appendChild(elem);
     elem.disabled = true;
-    const transitionPromises = [
+    const eventPromises = [
       "animationstart",
       "animationiteration",
       "animationend",
@@ -196,49 +174,38 @@
         elem.addEventListener(eventType, r, { once: true });
       });
     });
+    elem.style.animation = "fade .1s 2";
     elem.classList.add("animate");
     // All the events fire...
-    await Promise.all(transitionPromises);
+    await Promise.all(eventPromises);
     elem.remove();
   }
-  // And we are done with the test... clean up.
-  style.remove();
-}, "CSS Animation events fire on disabled form elements");
+}, "CSS Animation animationstart, animationiteration, animationend fire on disabled form elements");
 
 promise_test(async () => {
-  const style = document.createElement("style");
-  style.innerText = `
-    .animate {
-      animation: fade .1s 2;
-    }
-    @keyframes fade {
-      0% { opacity: 1; }
-      100% { opacity: 0.2; }
-    }
-  `;
-  document.head.appendChild(style);
   // For each form element type, set up transition event handlers.
   for (const localName of formElements) {
     const elem = document.createElement(localName);
     document.body.appendChild(elem);
     elem.disabled = true;
-    // Let's now test the "animationcancel" event
+
     const promiseToCancel = new Promise(r => {
       elem.addEventListener("animationcancel", r);
     });
+
     elem.addEventListener("animationstart", () => {
       // Cancel the animation by hiding it.
       elem.style.display = "none";
     });
+
+    // Trigger the animation
+    elem.style.animation = "fade 100s";
     elem.classList.add("animate");
-    // Trigger the animation again!
     await promiseToCancel;
     // And we are done with this element.
     elem.remove();
   }
-  // And we are done with the test... clean up.
-  style.remove();
-}, "CSS Animation's cancel events fire on disabled form elements");
+}, "CSS Animation's animationcancel event fires on disabled form elements");
 
 promise_test(async () => {
   for (const localName of formElements) {
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/Event-returnValue-expected.txt b/third_party/blink/web_tests/external/wpt/dom/events/Event-returnValue-expected.txt
deleted file mode 100644
index fa10e604..0000000
--- a/third_party/blink/web_tests/external/wpt/dom/events/Event-returnValue-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-This is a testharness.js-based test.
-PASS When an event is created, returnValue should be initialized to true.
-PASS preventDefault() should not change returnValue if cancelable is false.
-FAIL returnValue=false should have no effect if cancelable is false. assert_true: returnValue expected true got false
-PASS preventDefault() should change returnValue if cancelable is true.
-PASS returnValue should change returnValue if cancelable is true.
-PASS initEvent should unset returnValue.
-FAIL returnValue=true should have no effect once the canceled flag was set. assert_true: expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/src_object_blob.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/src_object_blob.html
new file mode 100644
index 0000000..481a818
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/src_object_blob.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>HTMLMediaElement.srcObject blob</title>
+<script src='/common/media.js'></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video></video>
+<script>
+  async_test(function(t) {
+    t.step(function() {
+      fetch(getVideoURI('/media/movie_5'))
+        .then(function(response) {
+          return response.blob();
+        })
+        .then(function(blob) {
+          let video = document.querySelector("video");
+          video.srcObject = blob;
+          video.addEventListener('ended', function() {
+            t.done();
+          });
+          video.play().catch(function(error) {
+            assert(false, error);
+          });
+        })
+        .catch(function(error) {
+          assert(false, error);
+        });
+    });
+  });
+</script>
+
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html
index 043c941..2acae212 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html
@@ -45,7 +45,7 @@
             video.play();
         }
 
-        function cueEnteredOrExited() {
+        function cueEnteredOrExited(event) {
             var currentCue = event.target;
             assert_equals(testTrack.track.cues.getCueById(cueCount).text, currentCue.text);
             assert_equals(currentCue.id, cueCount.toString());
@@ -56,4 +56,4 @@
 
     });
     </script>
-</video>
\ No newline at end of file
+</video>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-output-element/mutations.window-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-output-element/mutations.window-expected.txt
new file mode 100644
index 0000000..aaca4d4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-output-element/mutations.window-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL Descendant mutations and output.value and .defaultValue assert_equals: .defaultValue after setting textContent expected "x" but got ""
+PASS output and output.form.reset()
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-output-element/mutations.window.js b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-output-element/mutations.window.js
new file mode 100644
index 0000000..aedfc8a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-output-element/mutations.window.js
@@ -0,0 +1,36 @@
+function assert_equal_values(output, value, message) {
+  assert_equals(output.value, value, `.value ${message}`);
+  assert_equals(output.defaultValue, value, `.defaultValue ${message}`);
+}
+function assert_values(output, value, defaultValue, message) {
+  assert_equals(output.value, value, `.value ${message}`);
+  assert_equals(output.defaultValue, defaultValue, `.defaultValue ${message}`);
+}
+
+test(() => {
+  const output = document.createElement("output"),
+        child = output.appendChild(document.createElement("span"));
+  assert_equal_values(output, "", "start");
+  child.textContent = "x";
+  assert_equal_values(output, "x", "after setting textContent");
+  output.value = "some";
+  assert_values(output, "some", "x", "after setting value");
+  child.textContent = "y";
+  assert_values(output, "y", "x", "after setting textContent again");
+}, "Descendant mutations and output.value and .defaultValue");
+
+test(() => {
+  const form = document.createElement("form"),
+        output = form.appendChild(document.createElement("output"));
+  output.textContent = "value";
+  assert_equal_values(output, "value", "after setting textContent");
+  output.value = "heya";
+  assert_values(output, "heya", "value", "after setting value");
+  form.reset();
+  assert_equal_values(output, "value", "after form.reset()");
+
+  output.innerHTML = "<div>something</div>";
+  assert_equal_values(output, "something", "after setting innerHTML");
+  form.reset();
+  assert_equal_values(output, "something", "after form.reset() again");
+}, "output and output.form.reset()");
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html b/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html
index 32bf32c3..9732009 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html
@@ -2,6 +2,7 @@
 <html>
 <head>
   <meta charset=utf-8>
+  <meta name="timeout" content="long">
   <title>Test behavior of target=_blank links</title>
   <script src=/resources/testharness.js></script>
   <script src=/resources/testharnessreport.js></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.tentative-expected.txt
deleted file mode 100644
index f6a44d6..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.tentative-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This is a testharness.js-based test.
-PASS Anchor element with target=_blank with rel=noopener
-PASS Anchor element with target=_blank with rel=opener
-FAIL Anchor element with target=_blank with implicit rel=noopener assert_equals: expected false but got true
-PASS Anchor element with target=_blank with rel=opener+noopener
-PASS Anchor element with target=_blank with rel=noopener+opener
-PASS Area element with target=_blank with rel=noopener
-PASS Area element with target=_blank with rel=opener
-FAIL Area element with target=_blank with implicit rel=noopener assert_equals: expected false but got true
-PASS Area element with target=_blank with rel=opener+noopener
-PASS Area element with target=_blank with rel=noopener+opener
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html b/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html
index 44b91a2..8d1b54b 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html
@@ -2,6 +2,7 @@
 <html>
 <head>
   <meta charset=utf-8>
+  <meta name="timeout" content="long">
   <title>Test behavior of base target=_blank links</title>
   <script src=/resources/testharness.js></script>
   <script src=/resources/testharnessreport.js></script>
diff --git a/third_party/blink/web_tests/external/wpt/netinfo/idlharness.any.js b/third_party/blink/web_tests/external/wpt/netinfo/idlharness.any.js
index 4610508..96b114f 100644
--- a/third_party/blink/web_tests/external/wpt/netinfo/idlharness.any.js
+++ b/third_party/blink/web_tests/external/wpt/netinfo/idlharness.any.js
@@ -10,7 +10,7 @@
   ['html', 'dom'],
   idl_array => {
     idl_array.add_objects({ NetworkInformation: ['navigator.connection'] });
-    if (self.isWorker) {
+    if (self.GLOBAL.isWorker()) {
       idl_array.add_objects({ WorkerNavigator: ['navigator'] });
     } else {
       idl_array.add_objects({ Navigator: ['navigator'] });
diff --git a/third_party/blink/web_tests/external/wpt/netinfo/idlharness.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/netinfo/idlharness.any.worker-expected.txt
deleted file mode 100644
index 7680600c..0000000
--- a/third_party/blink/web_tests/external/wpt/netinfo/idlharness.any.worker-expected.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-This is a testharness.js-based test.
-PASS idl_test setup
-PASS NetworkInformation interface: existence and properties of interface object
-PASS NetworkInformation interface object length
-PASS NetworkInformation interface object name
-PASS NetworkInformation interface: existence and properties of interface prototype object
-PASS NetworkInformation interface: existence and properties of interface prototype object's "constructor" property
-PASS NetworkInformation interface: existence and properties of interface prototype object's @@unscopables property
-PASS NetworkInformation interface: attribute type
-PASS NetworkInformation interface: attribute effectiveType
-PASS NetworkInformation interface: attribute downlinkMax
-PASS NetworkInformation interface: attribute downlink
-PASS NetworkInformation interface: attribute rtt
-PASS NetworkInformation interface: attribute saveData
-PASS NetworkInformation interface: attribute onchange
-PASS NetworkInformation must be primary interface of navigator.connection
-PASS Stringification of navigator.connection
-PASS NetworkInformation interface: navigator.connection must inherit property "type" with the proper type
-PASS NetworkInformation interface: navigator.connection must inherit property "effectiveType" with the proper type
-PASS NetworkInformation interface: navigator.connection must inherit property "downlinkMax" with the proper type
-PASS NetworkInformation interface: navigator.connection must inherit property "downlink" with the proper type
-PASS NetworkInformation interface: navigator.connection must inherit property "rtt" with the proper type
-PASS NetworkInformation interface: navigator.connection must inherit property "saveData" with the proper type
-PASS NetworkInformation interface: navigator.connection must inherit property "onchange" with the proper type
-PASS Navigator interface: existence and properties of interface object
-FAIL Navigator interface: navigator must not have property "connection" assert_false: expected false got true
-PASS WorkerNavigator interface: attribute connection
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/payment-request/payment-response/payerdetailschange-updateWith-immediate-manual.https.html b/third_party/blink/web_tests/external/wpt/payment-request/payment-response/payerdetailschange-updateWith-immediate-manual.https.html
new file mode 100644
index 0000000..912ceaa6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/payment-request/payment-response/payerdetailschange-updateWith-immediate-manual.https.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Dispatching PaymentRequestUpdateEvent for "payerdetailschange"</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="helpers.js"></script>
+<script>
+function testImmediateUpdate({ textContent: testName }) {
+  promise_test(async t => {
+    const response = await getPaymentResponse({ requestPayerName: true });
+    const eventPromise = new Promise((resolve, reject) => {
+      response.addEventListener(
+        "payerdetailchange",
+        ev => {
+          // Forces updateWith() to be run in the next event loop tick so that
+          // [[waitForUpdate]] is already true when it runs.
+          t.step_timeout(() => {
+            try {
+              ev.updateWith({});
+              resolve(); // This is bad.
+            } catch (err) {
+              reject(err); // this is good.
+            }
+          });
+        },
+        { once: true }
+      );
+    });
+
+    const retryPromise = response.retry({
+      payer: { name: "Change me!" },
+    });
+    await promise_rejects(
+      t,
+      "InvalidStateError",
+      eventPromise,
+      "The event loop already spun, so [[waitForUpdate]] is now true"
+    );
+    await retryPromise;
+    await response.complete("success");
+  }, testName.trim());
+}
+</script>
+<h2>Handling PaymentResponse.prototype.onpayerdetailchange events</h2>
+<p>
+  The test brings up the Payment Request UI window.
+  When shown the payment sheet, use any details and hit pay.
+</p>
+<p>
+  When asked to retry the payment:
+</p>
+<ol>
+  <li>
+    <p>
+      Change payer's name to anything.
+    </p>
+    <button onclick="testImmediateUpdate(this);">
+      updateWith() must be called immediately, otherwise must throw an InvalidStateError.
+    </button>
+  </li>
+  <li>
+    <button onclick="done();">DONE!</button>
+  </li>
+</ol>
+<small>
+  If you find a buggy test, please <a href="https://github.com/web-platform-tests/wpt/issues">file a bug</a>
+  and tag one of the <a href="https://github.com/web-platform-tests/wpt/blob/master/payment-request/OWNERS">owners</a>.
+</small>
diff --git a/third_party/blink/web_tests/external/wpt/payment-request/payment-response/payerdetailschange-updateWith-manual.https.html b/third_party/blink/web_tests/external/wpt/payment-request/payment-response/payerdetailschange-updateWith-manual.https.html
new file mode 100644
index 0000000..30e2708
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/payment-request/payment-response/payerdetailschange-updateWith-manual.https.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Dispatching PaymentRequestUpdateEvent for "payerdetailschange"</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="helpers.js"></script>
+<script>
+function runTest(button) {
+  button.disabled = true;
+  promise_test(async t => {
+    const response = await getPaymentResponse({ requestPayerName: true });
+    const eventPromise = new Promise((_, reject) => {
+      response.addEventListener("payerdetailchange", ev => {
+        // [[waitForUpdate]] becomes true...
+        ev.updateWith({});
+        // So calling it again throws "InvalidStateError".
+        try {
+          ev.updateWith({});
+        } catch (err) {
+          reject(err);
+        }
+      });
+    });
+    await response.retry({
+      payer: { name: "Change me!" },
+    });
+    await promise_rejects(t, "InvalidStateError", eventPromise);
+    await response.complete("success");
+  }, button.textContent.trim());
+}
+</script>
+<h2>Handling PaymentResponse.prototype.onpayerdetailchange events</h2>
+<p>
+  The test brings up the Payment Request UI window.
+  When shown the payment sheet, use any details and hit pay.
+</p>
+<p>
+  When asked to retry the payment:
+</p>
+<ol>
+  <li>
+    <p>
+      Change payer's name to anything.
+    </p>
+    <button onclick="runTest(this);">
+      Calling PaymentRequestUpdateEvent updateWith() twice throws an "InvalidStateError".
+    </button>
+  </li>
+  <li>
+    <button onclick="done();">DONE!</button>
+  </li>
+</ol>
+<small>
+  If you find a buggy test, please <a href="https://github.com/web-platform-tests/wpt/issues">file a bug</a>
+  and tag one of the <a href="https://github.com/web-platform-tests/wpt/blob/master/payment-request/OWNERS">owners</a>.
+</small>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/data-transfer-files.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/data-transfer-files.https.html
new file mode 100644
index 0000000..cc8ab6e6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/data-transfer-files.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Post a file in a navigation controlled by a service worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<body>
+<iframe id=testframe name=testframe></iframe>
+<form id=testform method=post action="/html/semantics/forms/form-submission-0/resources/file-submission.py" target=testframe enctype="multipart/form-data">
+<input name=testinput id=testinput type=file>
+</form>
+<script>
+// Test that DataTransfer with a File entry works when posted to a
+// service worker that falls back to network. Regression test for
+// https://crbug.com/944145.
+promise_test(async (t) => {
+  const scope = '/html/semantics/forms/form-submission-0/resources/';
+  const header = `pipe=header(Service-Worker-Allowed,${scope})`;
+  const script = `resources/fetch-event-network-fallback-worker.js?${header}`;
+
+  const registration = await service_worker_unregister_and_register(
+      t, script, scope);
+  await wait_for_state(t, registration.installing, 'activated');
+
+  const dataTransfer = new DataTransfer();
+  dataTransfer.items.add(new File(['foobar'], 'name'));
+  assert_equals(1, dataTransfer.files.length);
+
+  testinput.files = dataTransfer.files;
+  testform.submit();
+
+  const data = await new Promise(resolve => {
+    onmessage = e => {
+      if (e.source !== testframe) return;
+      resolve(e.data);
+    };
+  });
+  assert_equals(data, "FieldStorage('testinput', 'name', 'foobar')");
+}, 'Posting a File in a navigation handled by a service worker');
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-event-network-fallback-worker.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-event-network-fallback-worker.js
index daa200c..376bdbed 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-event-network-fallback-worker.js
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-event-network-fallback-worker.js
@@ -1,3 +1,3 @@
 self.addEventListener('fetch', () => {
-    // Do nothing.
-  });
+  // Do nothing.
+});
diff --git a/third_party/blink/web_tests/external/wpt/speech-api/SpeechSynthesisEvent-constructor-expected.txt b/third_party/blink/web_tests/external/wpt/speech-api/SpeechSynthesisEvent-constructor-expected.txt
deleted file mode 100644
index 666caa9..0000000
--- a/third_party/blink/web_tests/external/wpt/speech-api/SpeechSynthesisEvent-constructor-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-This is a testharness.js-based test.
-PASS SpeechSynthesisEvent with no arguments throws TypeError
-PASS SpeechSynthesisEvent with no eventInitDict throws TypeError
-PASS SpeechSynthesisEvent with empty eventInitDict throws TypeError (requires
-    utterance)
-PASS SpeechSynthesisEvent with eventInitDict not having utterance throws
-    TypeError
-FAIL SpeechSynthesisEvent with eventInitDict having an utterance assert_equals: expected (number) 0 but got (undefined) undefined
-FAIL SpeechSynthesisEvent with custom eventInitDict assert_equals: expected (number) 3 but got (undefined) undefined
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/speech-api/idlharness.window-expected.txt b/third_party/blink/web_tests/external/wpt/speech-api/idlharness.window-expected.txt
index 36527b0..8499637 100644
--- a/third_party/blink/web_tests/external/wpt/speech-api/idlharness.window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/speech-api/idlharness.window-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 223 tests; 65 PASS, 158 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 223 tests; 66 PASS, 157 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL idl_test setup promise_test: Unhandled rejection with value: "Timed out waiting for voice"
 PASS Partial interface Window: original interface defined
 FAIL SpeechRecognition interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing
@@ -193,7 +193,7 @@
 PASS SpeechSynthesisEvent interface: existence and properties of interface prototype object's @@unscopables property
 PASS SpeechSynthesisEvent interface: attribute utterance
 PASS SpeechSynthesisEvent interface: attribute charIndex
-FAIL SpeechSynthesisEvent interface: attribute charLength assert_true: The prototype object must have a property "charLength" expected true got false
+PASS SpeechSynthesisEvent interface: attribute charLength
 PASS SpeechSynthesisEvent interface: attribute elapsedTime
 PASS SpeechSynthesisEvent interface: attribute name
 PASS SpeechSynthesisErrorEvent interface: existence and properties of interface object
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/pattern-with-invalid-base-cloned-crash.html b/third_party/blink/web_tests/external/wpt/svg/pservers/pattern-with-invalid-base-cloned-crash.html
new file mode 100644
index 0000000..04a45354
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/pservers/pattern-with-invalid-base-cloned-crash.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<base id="base" href="invalid:">
+<svg id="svg">
+  <pattern id="pat" xlink:href="#pat"/>
+</svg>
+<script>
+  async_test(t => {
+    onload = t.step_func_done(() => {
+      let pattern = document.getElementById("pat");
+      base.href = "";
+      document.body.insertBefore(document.getElementById("svg").cloneNode(true),
+                                 document.body.firstChild);
+      document.body.offsetTop;
+      pattern.setAttribute("clip-rule", "evenodd");
+      document.body.offsetTop;
+      pattern.setAttribute("width", "0");
+      document.getElementById("svg").setAttribute("systemLanguage", "x-nonexistent");
+      document.body.offsetTop;
+    });
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
index 0ffc779d..ffdd8ef 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
@@ -106,7 +106,7 @@
 
 
 def check_environ(product):
-    if product not in ("firefox", "servo"):
+    if product not in ("chrome", "firefox", "servo"):
         config_builder = serve.build_config(os.path.join(wpt_root, "config.json"))
         # Override the ports to avoid looking for free ports
         config_builder.ssl = {"type": "none"}
@@ -278,15 +278,6 @@
             logger.info("Automatically turning on experimental features for Chrome Dev")
             kwargs["binary_args"].append("--enable-experimental-web-platform-features")
 
-        # Allow audio autoplay without a user gesture.
-        kwargs["binary_args"].append("--autoplay-policy=no-user-gesture-required")
-
-        # Allow WebRTC tests to call getUserMedia.
-        kwargs["binary_args"] += ["--use-fake-ui-for-media-stream", "--use-fake-device-for-media-stream"]
-
-        # Shorten delay for Reporting <https://w3c.github.io/reporting/>.
-        kwargs["binary_args"].append("--short-reporting-delay")
-
 
 class ChromeAndroid(BrowserSetup):
     name = "chrome_android"
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome.py
index 5b586ba..71f246f 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome.py
@@ -56,15 +56,29 @@
     if test_type == "testharness":
         capabilities["pageLoadStrategy"] = "none"
 
-    for (kwarg, capability) in [("binary", "binary"), ("binary_args", "args")]:
-        if kwargs[kwarg] is not None:
-            capabilities["goog:chromeOptions"][capability] = kwargs[kwarg]
+    chrome_options = capabilities["goog:chromeOptions"]
+    if kwargs["binary"] is not None:
+        chrome_options["binary"] = kwargs["binary"]
 
-    if kwargs["headless"]:
-        if "args" not in capabilities["goog:chromeOptions"]:
-            capabilities["goog:chromeOptions"]["args"] = []
-        if "--headless" not in capabilities["goog:chromeOptions"]["args"]:
-            capabilities["goog:chromeOptions"]["args"].append("--headless")
+    # Here we set a few Chrome flags that are always passed.
+    chrome_options["args"] = []
+    # Allow audio autoplay without a user gesture.
+    chrome_options["args"].append("--autoplay-policy=no-user-gesture-required")
+    # Allow WebRTC tests to call getUserMedia.
+    chrome_options["args"].append("--use-fake-ui-for-media-stream")
+    chrome_options["args"].append("--use-fake-device-for-media-stream")
+    # Shorten delay for Reporting <https://w3c.github.io/reporting/>.
+    chrome_options["args"].append("--short-reporting-delay")
+    # Point all .test domains to localhost for Chrome
+    chrome_options["args"].append("--host-resolver-rules=MAP nonexistent.*.test ~NOTFOUND, MAP *.test 127.0.0.1")
+
+    # Copy over any other flags that were passed in via --binary_args
+    if kwargs["binary_args"] is not None:
+        chrome_options["args"].extend(kwargs["binary_args"])
+
+    # Pass the --headless flag to Chrome if WPT's own --headless flag was set
+    if kwargs["headless"] and "--headless" not in chrome_options["args"]:
+        chrome_options["args"].append("--headless")
 
     executor_kwargs["capabilities"] = capabilities
 
@@ -76,7 +90,7 @@
 
 
 def env_options():
-    return {}
+    return {"server_host": "127.0.0.1"}
 
 
 class ChromeBrowser(Browser):
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edge.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edge.py
index 027c8f8..21d41d1b 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edge.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edge.py
@@ -102,8 +102,8 @@
 
 
 def run_info_extras(**kwargs):
-    osReleaseCommand = "(Get-ItemProperty 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion').ReleaseId"
-    osBuildCommand = "(Get-ItemProperty 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion').BuildLabEx"
+    osReleaseCommand = r"(Get-ItemProperty 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion').ReleaseId"
+    osBuildCommand = r"(Get-ItemProperty 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion').BuildLabEx"
     try:
         os_release = subprocess.check_output(["powershell.exe", osReleaseCommand]).strip()
         os_build = subprocess.check_output(["powershell.exe", osBuildCommand]).strip()
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/handlers.py b/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/handlers.py
index 2dd01e2..e846ff8 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/handlers.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/handlers.py
@@ -159,8 +159,8 @@
         rv = (self.load_headers(request, os.path.join(os.path.split(path)[0], "__dir__")) +
               self.load_headers(request, path))
 
-        if not any(key.lower() == "content-type" for (key, _) in rv):
-            rv.insert(0, ("Content-Type", guess_content_type(path)))
+        if not any(key.lower() == b"content-type" for (key, _) in rv):
+            rv.insert(0, (b"Content-Type", guess_content_type(path).encode("ascii")))
 
         return rv
 
@@ -173,14 +173,14 @@
             use_sub = False
 
         try:
-            with open(headers_path) as headers_file:
+            with open(headers_path, "rb") as headers_file:
                 data = headers_file.read()
         except IOError:
             return []
         else:
             if use_sub:
                 data = template(request, data, escape_type="none")
-            return [tuple(item.strip() for item in line.split(":", 1))
+            return [tuple(item.strip() for item in line.split(b":", 1))
                     for line in data.splitlines() if line]
 
     def get_data(self, response, path, byte_ranges):
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/response.py b/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/response.py
index 00a609b2..efc65ef 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/response.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/response.py
@@ -8,7 +8,7 @@
 from .logger import get_logger
 from io import BytesIO
 
-from six import binary_type, text_type, itervalues
+from six import binary_type, text_type, integer_types, itervalues, PY3
 from hyperframe.frame import HeadersFrame, DataFrame, ContinuationFrame
 from hpack.struct import HeaderTuple
 
@@ -157,6 +157,8 @@
         cookies = self.headers.get("Set-Cookie")
         parser = BaseCookie()
         for cookie in cookies:
+            if PY3:
+                cookie = cookie.decode("iso-8859-1")
             parser.load(cookie)
 
         if name in parser.keys():
@@ -237,18 +239,18 @@
     def __init__(self, boundary=None, default_content_type=None):
         self.items = []
         if boundary is None:
-            boundary = str(uuid.uuid4())
+            boundary = text_type(uuid.uuid4())
         self.boundary = boundary
         self.default_content_type = default_content_type
 
     def __call__(self):
-        boundary = "--" + self.boundary
-        rv = ["", boundary]
+        boundary = b"--" + self.boundary.encode("ascii")
+        rv = [b"", boundary]
         for item in self.items:
-            rv.append(str(item))
+            rv.append(item.to_bytes())
             rv.append(boundary)
-        rv[-1] += "--"
-        return "\r\n".join(rv)
+        rv[-1] += b"--"
+        return b"\r\n".join(rv)
 
     def append_part(self, data, content_type=None, headers=None):
         if content_type is None:
@@ -265,6 +267,7 @@
 
 class MultipartPart(object):
     def __init__(self, data, content_type=None, headers=None):
+        assert isinstance(data, binary_type), data
         self.headers = ResponseHeaders()
 
         if content_type is not None:
@@ -272,7 +275,7 @@
 
         if headers is not None:
             for name, value in headers:
-                if name.lower() == "content-type":
+                if name.lower() == b"content-type":
                     func = self.headers.set
                 else:
                     func = self.headers.append
@@ -280,13 +283,36 @@
 
         self.data = data
 
-    def __str__(self):
+    def to_bytes(self):
         rv = []
-        for item in self.headers:
-            rv.append("%s: %s" % item)
-        rv.append("")
+        for key, value in self.headers:
+            assert isinstance(key, binary_type)
+            assert isinstance(value, binary_type)
+            rv.append(b"%s: %s" % (key, value))
+        rv.append(b"")
         rv.append(self.data)
-        return "\r\n".join(rv)
+        return b"\r\n".join(rv)
+
+
+def _maybe_encode(s):
+    """Encodes a text-type string into binary data using iso-8859-1.
+
+    Returns `str` in Python 2 and `bytes` in Python 3. The function is a no-op
+    if the argument already has a binary type.
+    """
+    if isinstance(s, binary_type):
+        return s
+
+    # Python 3 assumes iso-8859-1 when parsing headers, which will garble text
+    # with non ASCII characters. We try to encode the text back to binary.
+    # https://github.com/python/cpython/blob/273fc220b25933e443c82af6888eb1871d032fb8/Lib/http/client.py#L213
+    if isinstance(s, text_type):
+        return s.encode("iso-8859-1")
+
+    if isinstance(s, integer_types):
+        return b"%i" % (s,)
+
+    raise TypeError("Unexpected value in ResponseHeaders: %r" % s)
 
 
 class ResponseHeaders(object):
@@ -301,6 +327,8 @@
         :param key: Name of the header to set
         :param value: Value to set the header to
         """
+        key = _maybe_encode(key)
+        value = _maybe_encode(value)
         self.data[key.lower()] = (key, [value])
 
     def append(self, key, value):
@@ -310,6 +338,8 @@
         :param key: Name of the header to add
         :param value: Value to set for the header
         """
+        key = _maybe_encode(key)
+        value = _maybe_encode(value)
         if key.lower() in self.data:
             self.data[key.lower()][1].append(value)
         else:
@@ -317,6 +347,7 @@
 
     def get(self, key, default=missing):
         """Get the set values for a particular header."""
+        key = _maybe_encode(key)
         try:
             return self[key]
         except KeyError:
@@ -328,12 +359,15 @@
         """Get a list of values for a particular header
 
         """
+        key = _maybe_encode(key)
         return self.data[key.lower()][1]
 
     def __delitem__(self, key):
+        key = _maybe_encode(key)
         del self.data[key.lower()]
 
     def __contains__(self, key):
+        key = _maybe_encode(key)
         return key.lower() in self.data
 
     def __setitem__(self, key, value):
@@ -623,6 +657,9 @@
         self.file_chunk_size = 32 * 1024
         self.default_status = 200
 
+    def _seen_header(self, name):
+        return self.encode(name.lower()) in self._headers_seen
+
     def write_status(self, code, message=None):
         """Write out the status line of a response.
 
@@ -648,19 +685,25 @@
         """
         if not self._status_written:
             self.write_status(self.default_status)
-        self._headers_seen.add(name.lower())
-        self.write("%s: %s\r\n" % (name, value))
+        self._headers_seen.add(self.encode(name.lower()))
+        self.write(name)
+        self.write(b": ")
+        if isinstance(value, int):
+            self.write(text_type(value))
+        else:
+            self.write(value)
+        self.write(b"\r\n")
         if not self._response.explicit_flush:
             self.flush()
 
     def write_default_headers(self):
         for name, f in [("Server", self._handler.version_string),
                         ("Date", self._handler.date_time_string)]:
-            if name.lower() not in self._headers_seen:
+            if not self._seen_header(name):
                 self.write_header(name, f())
 
         if (isinstance(self._response.content, (binary_type, text_type)) and
-            "content-length" not in self._headers_seen):
+            not self._seen_header("content-length")):
             #Would be nice to avoid double-encoding here
             self.write_header("Content-Length", len(self.encode(self._response.content)))
 
@@ -675,7 +718,7 @@
             self.write_default_headers()
 
         self.write("\r\n")
-        if "content-length" not in self._headers_seen:
+        if not self._seen_header("content-length"):
             self._response.close_connection = True
         if not self._response.explicit_flush:
             self.flush()
@@ -735,7 +778,7 @@
         elif isinstance(data, text_type):
             return data.encode(self._response.encoding)
         else:
-            raise ValueError
+            raise ValueError("data %r should be text or binary, but is %s" % (data, type(data)))
 
     def flush(self):
         """Flush the output. Returns False if the flush failed due to
diff --git a/third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/usertimingl3-mark-type.html b/third_party/blink/web_tests/external/wpt/user-timing/mark-errors.html
similarity index 88%
rename from third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/usertimingl3-mark-type.html
rename to third_party/blink/web_tests/external/wpt/user-timing/mark-errors.html
index 3357871..c182a39 100644
--- a/third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/usertimingl3-mark-type.html
+++ b/third_party/blink/web_tests/external/wpt/user-timing/mark-errors.html
@@ -1,13 +1,9 @@
 <!DOCTYPE HTML>
 <meta charset=utf-8>
-<title>UserTimingL3: Mark</title>
+<title>UserTimingL3: errors are thrown when mark() is called incorrectly.</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <h1>UserTimingL3: Mark</h1>
-<p>
-Performance.mark method accepts dictionary as the second argument.
-</p>
-<div id="log"></div>
 <script>
   test(function() {
     assert_throws(new TypeError(), function() { self.performance.mark("mark1", 123); }, "Number passed as a dict argument should cause type-error.")
diff --git a/third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/po-customusertiming-mark.html b/third_party/blink/web_tests/external/wpt/user-timing/mark-l3.html
similarity index 89%
rename from third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/po-customusertiming-mark.html
rename to third_party/blink/web_tests/external/wpt/user-timing/mark-l3.html
index 1c75eda..429768d 100644
--- a/third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/po-customusertiming-mark.html
+++ b/third_party/blink/web_tests/external/wpt/user-timing/mark-l3.html
@@ -1,14 +1,9 @@
 <!DOCTYPE HTML>
 <meta charset=utf-8>
-<title>Custom User Timing: Mark</title>
+<title>User Timing L3: mark</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="performanceobservers.js"></script>
-<h1>Custom User Timing: Mark</h1>
-<p>
-Performance.mark method takes in custom detail and custom start time.
-</p>
-<div id="log"></div>
+<script src="resources/user-timing-helpers.js"></script>
 <script>
   async_test(function (t) {
     let mark_entries = [];
diff --git a/third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/po-customusertiming-featuredetection.html b/third_party/blink/web_tests/external/wpt/user-timing/mark-measure-return-objects.html
similarity index 87%
rename from third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/po-customusertiming-featuredetection.html
rename to third_party/blink/web_tests/external/wpt/user-timing/mark-measure-return-objects.html
index 8476084..d2d8cc3c 100644
--- a/third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/po-customusertiming-featuredetection.html
+++ b/third_party/blink/web_tests/external/wpt/user-timing/mark-measure-return-objects.html
@@ -1,8 +1,8 @@
 <!DOCTYPE HTML>
 <meta charset=utf-8>
-<title>Custom User Timing: L3 API returns a mark/measure object</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
+<title>UserTiming L3: mark/measure methods return objects.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
 <p>Custom User Timing: L3 API returns a mark/measure object</p>
 <div id="log"></div>
 <script>
diff --git a/third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/usertiminel3-measure.html b/third_party/blink/web_tests/external/wpt/user-timing/measure-l3.html
similarity index 90%
rename from third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/usertiminel3-measure.html
rename to third_party/blink/web_tests/external/wpt/user-timing/measure-l3.html
index 9add2f6..0e8dacf 100644
--- a/third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/usertiminel3-measure.html
+++ b/third_party/blink/web_tests/external/wpt/user-timing/measure-l3.html
@@ -1,13 +1,8 @@
 <!DOCTYPE HTML>
 <meta charset=utf-8>
-<title>UserTimingL3: Measure</title>
+<title>UserTiming L3: Measure basic usage</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<h1>UserTimingL3: Measure</h1>
-<p>
-This test suite is to test performance.measure API with the added L3 feature.
-</p>
-<div id="log"></div>
 <script>
   function endTime(entry) {
     return entry.startTime + entry.duration;
diff --git a/third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/po-customusertiming-measure.html b/third_party/blink/web_tests/external/wpt/user-timing/measure-with-dict.html
similarity index 93%
rename from third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/po-customusertiming-measure.html
rename to third_party/blink/web_tests/external/wpt/user-timing/measure-with-dict.html
index 9b53ccf..83990a6 100644
--- a/third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/po-customusertiming-measure.html
+++ b/third_party/blink/web_tests/external/wpt/user-timing/measure-with-dict.html
@@ -1,14 +1,9 @@
 <!DOCTYPE HTML>
 <meta charset=utf-8>
-<title>Custom User Timing: measure</title>
-<script src="../../../../resources/testharness.js"></script>
-<script src="../../../../resources/testharnessreport.js"></script>
-<script src="performanceobservers.js"></script>
-<h1>Custom User Timing: measure</h1>
-<p>
-Custom User Timing: measure
-</p>
-<div id="log"></div>
+<title>User Timing L3: measure is customizable</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/user-timing-helpers.js"></script>
 <script>
   async_test(function (t) {
     let measureEntries = [];
diff --git a/third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/performanceobservers.js b/third_party/blink/web_tests/external/wpt/user-timing/resources/user-timing-helper.js
similarity index 100%
rename from third_party/blink/web_tests/http/tests/performance-timing/custom-user-timing/performanceobservers.js
rename to third_party/blink/web_tests/external/wpt/user-timing/resources/user-timing-helper.js
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/NFCReader_options_url-manual.https-expected.txt b/third_party/blink/web_tests/external/wpt/web-nfc/NFCReader_options_url-manual.https-expected.txt
new file mode 100644
index 0000000..97cc2373
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-nfc/NFCReader_options_url-manual.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Test that the url of NFCReaderOptions filters relevant data sources correctly. promise_test: Unhandled rejection with value: object "ReferenceError: NFCWriter is not defined"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/NFCReader_options_url-manual.https.html b/third_party/blink/web_tests/external/wpt/web-nfc/NFCReader_options_url-manual.https.html
new file mode 100644
index 0000000..882d663
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-nfc/NFCReader_options_url-manual.https.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Web NFC Test: NFCReader NFCReaderOptions url test</title>
+<link rel="author" title="Intel" href="http://www.intel.com"/>
+<link rel="help" href="https://w3c.github.io/web-nfc/"/>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name="flags" content="interact">
+
+<p>Tap an NFC tag to the test device with NFC support.</p>
+
+<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
+
+<div id="log"></div>
+
+<script>
+
+"use strict";
+
+setup({ explicit_timeout: true });
+
+promise_test(async t => {
+  const writer = new NFCWriter();
+  const reader1 = new NFCReader({url: `${location.origin}/custom/invalid`});
+  const reader2 = new NFCReader({url: `${location.origin}/custom/path`});
+  await writer.push({
+    url: "/custom/path/update",
+    records: [{ recordType: "text", data: "valid" }]
+  });
+
+  reader1.onreading = t.unreached_func("reading event should not be fired.");
+  reader1.start();
+
+  const readerWatcher = new EventWatcher(t, reader2, ["reading", "error"]);
+  reader2.start();
+  const event = await readerWatcher.wait_for("reading");
+  const message = event.message;
+  assert_equals(message.records[0].recordType, "text");
+  assert_equals(message.records[0].data, "valid");
+  assert_equals(message.url, `${location.origin}/custom/path/update`);
+}, "Test that the url of NFCReaderOptions filters relevant data sources correctly.");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-helper.js b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-helper.js
index 90867b2..efbb1a23 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-helper.js
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-helper.js
@@ -224,6 +224,21 @@
   });
 }
 
+// Returns a promise that resolves when |pc.iceConnectionState| is in one of the
+// wanted states.
+function waitForIceStateChange(pc, wantedStates) {
+  return new Promise((resolve) => {
+    if (wantedStates.includes(pc.iceConnectionState)) {
+      resolve();
+      return;
+    }
+    pc.addEventListener('iceconnectionstatechange', () => {
+      if (wantedStates.includes(pc.iceConnectionState))
+        resolve();
+    });
+  });
+}
+
 // Returns a promise that resolves when |pc.connectionState| is 'connected'.
 function listenToConnected(pc) {
   return new Promise((resolve) => {
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html
new file mode 100644
index 0000000..dbfc41e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<meta charset=utf-8>
+<meta name="timeout" content="long">
+<title>RTCPeerConnection.prototype.iceConnectionState - disconnection</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="RTCPeerConnection-helper.js"></script>
+<script>
+  'use strict';
+  promise_test(async t => {
+    const caller = new RTCPeerConnection();
+    t.add_cleanup(() => caller.close());
+    const callee = new RTCPeerConnection();
+    t.add_cleanup(() => callee.close());
+
+    const stream = await navigator.mediaDevices.getUserMedia({audio:true});
+    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
+    const [track] = stream.getTracks();
+    caller.addTrack(track, stream);
+    exchangeIceCandidates(caller, callee);
+    await doSignalingHandshake(caller, callee);
+
+    await listenToIceConnected(caller);
+
+    callee.close();
+    await waitForIceStateChange(caller, ['disconnected', 'failed']);
+    // TODO: this should eventually transition to failed but that takes
+    // somewhat long (15-30s) so is not testable.
+  }, 'ICE goes to disconnected if the other side goes away');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
index 65bc029..a00bc36 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 216 tests; 202 PASS, 14 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 216 tests; 203 PASS, 13 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Navigator: original interface defined
 PASS Partial dictionary WebGLContextAttributes: original dictionary defined
@@ -124,7 +124,7 @@
 PASS XRRigidTransform interface: attribute position
 PASS XRRigidTransform interface: attribute orientation
 PASS XRRigidTransform interface: attribute matrix
-FAIL XRRigidTransform interface: attribute inverse assert_throws: getting property on prototype object must throw TypeError function "function () { [native code] }" did not throw
+PASS XRRigidTransform interface: attribute inverse
 PASS XRRay interface: existence and properties of interface object
 PASS XRRay interface object length
 PASS XRRay interface object name
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html
index ddae2af..e795a99 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrRigidTransform_inverse.https.html
@@ -29,14 +29,14 @@
   // An identity transform should be equal to it's inverse.
   let identity_transform = new XRRigidTransform();
   t.step(() => {
-    assert_transform_approx_equals(identity_transform, identity_transform.inverse());
+    assert_transform_approx_equals(identity_transform, identity_transform.inverse);
   });
 
   // Inversed transforms should yield the expected results
   let transform = new XRRigidTransform(
       { x: 1.0, y: 2.0, z: 3.0 },
       { x: 0.0, y: 0.0, z: 0.0, w: 1.0 });
-  let inverse_transform = transform.inverse();
+  let inverse_transform = transform.inverse;
   let expected_inverse = new XRRigidTransform(
       { x: -1.0, y: -2.0, z: -3.0 },
       { x: 0.0, y: 0.0, z: 0.0, w: 1.0 });
@@ -47,7 +47,7 @@
   transform = new XRRigidTransform(
       { x: 0.0, y: 0.0, z: 0.0 },
       { x: 1.0, y: 0.0, z: 0.0, w: 1.0 });
-  inverse_transform = transform.inverse();
+  inverse_transform = transform.inverse;
   expected_inverse = new XRRigidTransform(
       { x: 0.0, y: 0.0, z: 0.0 },
       { x: -1.0, y: 0.0, z: 0.0, w: 1.0 });
@@ -58,7 +58,7 @@
   transform = new XRRigidTransform(
       { x: 1.0, y: 2.0, z: 3.0 },
       { x: 0.0, y: 1.0, z: 0.0, w: 1.0 });
-  inverse_transform = transform.inverse();
+  inverse_transform = transform.inverse;
   expected_inverse = new XRRigidTransform(
       { x: 3.0, y: -2.0, z: -1.0 },
       { x: 0.0, y: -1.0, z: 0.0, w: 1.0 });
@@ -70,33 +70,33 @@
   transform = new XRRigidTransform(
       { x: 1.0, y: 2.0, z: 3.0 },
       { x: 1.0, y: 2.0, z: 3.0, w: 4.0 });
-  inverse_transform = transform.inverse();
+  inverse_transform = transform.inverse;
   t.step(() => {
-    assert_transform_approx_equals(transform, inverse_transform.inverse());
+    assert_transform_approx_equals(transform, inverse_transform.inverse);
   });
 
   transform = new XRRigidTransform(
       { x: -9.0, y: 8.0, z: -7.0 },
       { x: 6.0, y: -5.0, z: 4.0, w: 3.0 });
-  inverse_transform = transform.inverse();
+  inverse_transform = transform.inverse;
   t.step(() => {
-    assert_transform_approx_equals(transform, inverse_transform.inverse());
+    assert_transform_approx_equals(transform, inverse_transform.inverse);
   });
 
   transform = new XRRigidTransform(
       { x: -2.0, y: 1.0, z: -4.0 },
       { x: 0.0, y: 1.0, z: 0.0, w: 1.0 });
-  inverse_transform = transform.inverse();
+  inverse_transform = transform.inverse;
   t.step(() => {
-    assert_transform_approx_equals(transform, inverse_transform.inverse());
+    assert_transform_approx_equals(transform, inverse_transform.inverse);
   });
 
   transform = new XRRigidTransform(
       { x: 2.0, y: -1.0, z: 4.0 },
       { x: 1.0, y: 0.0, z: 0.0, w: 1.0 });
-  inverse_transform = transform.inverse();
+  inverse_transform = transform.inverse;
   t.step(() => {
-    assert_transform_approx_equals(transform, inverse_transform.inverse());
+    assert_transform_approx_equals(transform, inverse_transform.inverse);
   });
 
   resolve();
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html
index 6c567d2..2278666 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html
@@ -36,7 +36,7 @@
       assert_not_equals(view, null);
       assert_not_equals(view.transform, null);
 
-      let inv_view_transform = view.transform.inverse();
+      let inv_view_transform = view.transform.inverse;
       assert_not_equals(inv_view_transform, null);
       assert_not_equals(inv_view_transform.matrix, null);
       assert_equals(inv_view_transform.matrix.length, 16);
diff --git a/third_party/blink/web_tests/fast/speechsynthesis/speech-synthesis-boundary-events-expected.txt b/third_party/blink/web_tests/fast/speechsynthesis/speech-synthesis-boundary-events-expected.txt
index 9dc68f8..d8769b5 100644
--- a/third_party/blink/web_tests/fast/speechsynthesis/speech-synthesis-boundary-events-expected.txt
+++ b/third_party/blink/web_tests/fast/speechsynthesis/speech-synthesis-boundary-events-expected.txt
@@ -3,8 +3,8 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 Speech started
-Boundary event: word, Character index: 0
-Boundary event: sentence, Character index: 14
+Boundary event: word, Character index: 0, Character length: 4
+Boundary event: sentence, Character index: 0, Character length: 14
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/blink/web_tests/fast/speechsynthesis/speech-synthesis-boundary-events.html b/third_party/blink/web_tests/fast/speechsynthesis/speech-synthesis-boundary-events.html
index 689768e..c116b281 100644
--- a/third_party/blink/web_tests/fast/speechsynthesis/speech-synthesis-boundary-events.html
+++ b/third_party/blink/web_tests/fast/speechsynthesis/speech-synthesis-boundary-events.html
@@ -25,7 +25,8 @@
     }
 
     u.onboundary = function(event) {
-       debug("Boundary event: " + event.name + ", Character index: " + event.charIndex);
+       debug("Boundary event: " + event.name + ", Character index: " +
+                event.charIndex + ", Character length: " + event.charLength);
     }
 
     u.onend = function(event) {
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-breakpoints/breakpoints-sidebar-pane-expected.txt b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-breakpoints/breakpoints-sidebar-pane-expected.txt
new file mode 100644
index 0000000..16c1c8c
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-breakpoints/breakpoints-sidebar-pane-expected.txt
@@ -0,0 +1,19 @@
+Tests that breakpoints appear correct in the sidebar pane.
+
+Script source was shown.
+
+Set first breakpoint.
+Breakpoint sidebar pane 
+a.js:18  return a + b;
+
+Set second breakpoint on the same line.
+Breakpoint sidebar pane 
+a.js:18:3return a + b;
+a.js:18:16
+
+Set a third breakpoint on a different line.
+Breakpoint sidebar pane 
+a.js:17  b = b / 2;
+a.js:18:3return a + b;
+a.js:18:16
+
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-breakpoints/breakpoints-sidebar-pane.js b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-breakpoints/breakpoints-sidebar-pane.js
new file mode 100644
index 0000000..ec90376
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-breakpoints/breakpoints-sidebar-pane.js
@@ -0,0 +1,33 @@
+// Copyright 2018 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(`Tests that breakpoints appear correct in the sidebar pane.\n`);
+  await TestRunner.loadModule('sources_test_runner');
+  await TestRunner.showPanel('sources');
+  await TestRunner.navigatePromise('resources/a.html');
+
+  const sourceFrame = await SourcesTestRunner.showScriptSourcePromise(
+      'a.js');
+  TestRunner.addResult('Script source was shown.');
+
+  const debuggerPlugin = SourcesTestRunner.debuggerPlugin(sourceFrame);
+
+  TestRunner.addResult('\nSet first breakpoint.');
+  debuggerPlugin._setBreakpoint(17, 2, '', true);
+  await SourcesTestRunner.waitBreakpointSidebarPane();
+  SourcesTestRunner.dumpBreakpointSidebarPane();
+
+  TestRunner.addResult('\nSet second breakpoint on the same line.');
+  debuggerPlugin._setBreakpoint(17, 15, '', true);
+  await SourcesTestRunner.waitBreakpointSidebarPane();
+  SourcesTestRunner.dumpBreakpointSidebarPane();
+
+  TestRunner.addResult('\nSet a third breakpoint on a different line.');
+  debuggerPlugin._setBreakpoint(16, 2, '', true);
+  await SourcesTestRunner.waitBreakpointSidebarPane();
+  SourcesTestRunner.dumpBreakpointSidebarPane();
+
+  TestRunner.completeTest();
+})();
diff --git a/third_party/blink/web_tests/http/tests/images/feature-policy-image-policies-with-border-radius-expected.txt b/third_party/blink/web_tests/http/tests/images/feature-policy-image-policies-with-border-radius-expected.txt
index fbf5694..e66cbe1 100644
--- a/third_party/blink/web_tests/http/tests/images/feature-policy-image-policies-with-border-radius-expected.txt
+++ b/third_party/blink/web_tests/http/tests/images/feature-policy-image-policies-with-border-radius-expected.txt
@@ -1,2 +1 @@
 CONSOLE ERROR: Feature policy violation: unoptimized-lossy-images is not allowed in this document.
-CONSOLE ERROR: Feature policy violation: legacy-image-formats is not allowed in this document.
diff --git a/third_party/blink/web_tests/http/tests/images/feature-policy-image-policies-with-border-radius.html b/third_party/blink/web_tests/http/tests/images/feature-policy-image-policies-with-border-radius.html
index 058c88b..06c3ced 100644
--- a/third_party/blink/web_tests/http/tests/images/feature-policy-image-policies-with-border-radius.html
+++ b/third_party/blink/web_tests/http/tests/images/feature-policy-image-policies-with-border-radius.html
@@ -4,4 +4,4 @@
   font: 10px Ahem;
 }
 </style>
-<body><iframe src="resources/frame-with-images-with-border-radius.html" allow="legacy-image-formats 'none'; unoptimized-lossy-images 'none'" width="440" height="180"></iframe></body>
+<body><iframe src="resources/frame-with-images-with-border-radius.html" allow="unoptimized-lossy-images 'none'" width="440" height="180"></iframe></body>
diff --git a/third_party/blink/web_tests/platform/android/editing/pasteboard/drop-text-without-selection-expected.png b/third_party/blink/web_tests/platform/android/editing/pasteboard/drop-text-without-selection-expected.png
deleted file mode 100644
index cbe21d6..0000000
--- a/third_party/blink/web_tests/platform/android/editing/pasteboard/drop-text-without-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/android/editing/pasteboard/drop-text-without-selection-expected.txt b/third_party/blink/web_tests/platform/android/editing/pasteboard/drop-text-without-selection-expected.txt
deleted file mode 100644
index 0bf88688..0000000
--- a/third_party/blink/web_tests/platform/android/editing/pasteboard/drop-text-without-selection-expected.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x40
-        LayoutText {#text} at (0,0) size 104x19
-          text run at (0,0) width 104: "This is a test for "
-        LayoutInline {I} at (0,0) size 750x39
-          LayoutInline {A} at (0,0) size 348x19 [color=#0000EE]
-            LayoutText {#text} at (104,0) size 348x19
-              text run at (104,0) width 348: "http://bugzilla.opendarwin.org/show_bug.cgi?id=8394"
-          LayoutText {#text} at (451,0) size 750x39
-            text run at (451,0) width 5: " "
-            text run at (455,0) width 295: "Editable region does not accept dropped text if"
-            text run at (0,20) width 125: "there is no selection"
-        LayoutText {#text} at (124,20) size 5x19
-          text run at (124,20) width 5: "."
-      LayoutBlockFlow {P} at (0,56) size 784x20
-        LayoutText {#text} at (0,0) size 653x19
-          text run at (0,0) width 478: "The text field should accept drag-and-dropped text, such as the link, even if "
-          text run at (478,0) width 175: "no text is currently selected."
-      LayoutBlockFlow (anonymous) at (0,102) size 784x22
-        LayoutTextControl {INPUT} at (0,0) size 154x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
-        LayoutText {#text} at (154,1) size 4x19
-          text run at (154,1) width 4: " "
-        LayoutInline {A} at (0,0) size 162x19 [color=#0000EE]
-          LayoutText {#text} at (158,1) size 162x19
-            text run at (158,1) width 162: "drop me into the text field"
-        LayoutText {#text} at (0,0) size 0x0
-layer at (8,100) size 784x2 clip at (0,0) size 0x0
-  LayoutBlockFlow {HR} at (0,92) size 784x2 [border: (1px inset #EEEEEE)]
-layer at (10,113) size 150x16
-  LayoutBlockFlow {DIV} at (2,3) size 150x16
-    LayoutText {#text} at (0,0) size 119x16
-      text run at (0,0) width 119: "http://www.ibm.com/"
-selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
-selection end:   position 19 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
diff --git a/third_party/blink/web_tests/platform/linux/editing/pasteboard/drop-text-without-selection-expected.png b/third_party/blink/web_tests/platform/linux/editing/pasteboard/drop-text-without-selection-expected.png
deleted file mode 100644
index df297ed..0000000
--- a/third_party/blink/web_tests/platform/linux/editing/pasteboard/drop-text-without-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/editing/pasteboard/drop-text-without-selection-expected.txt b/third_party/blink/web_tests/platform/linux/editing/pasteboard/drop-text-without-selection-expected.txt
deleted file mode 100644
index 1bda26a..0000000
--- a/third_party/blink/web_tests/platform/linux/editing/pasteboard/drop-text-without-selection-expected.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x40
-        LayoutText {#text} at (0,0) size 104x19
-          text run at (0,0) width 104: "This is a test for "
-        LayoutInline {I} at (0,0) size 783x39
-          LayoutInline {A} at (0,0) size 347x19 [color=#0000EE]
-            LayoutText {#text} at (104,0) size 347x19
-              text run at (104,0) width 347: "http://bugzilla.opendarwin.org/show_bug.cgi?id=8394"
-          LayoutText {#text} at (451,0) size 783x39
-            text run at (451,0) width 4: " "
-            text run at (455,0) width 328: "Editable region does not accept dropped text if there"
-            text run at (0,20) width 89: "is no selection"
-        LayoutText {#text} at (89,20) size 4x19
-          text run at (89,20) width 4: "."
-      LayoutBlockFlow {P} at (0,56) size 784x20
-        LayoutText {#text} at (0,0) size 653x19
-          text run at (0,0) width 478: "The text field should accept drag-and-dropped text, such as the link, even if "
-          text run at (478,0) width 175: "no text is currently selected."
-      LayoutBlockFlow (anonymous) at (0,102) size 784x22
-        LayoutTextControl {INPUT} at (0,0) size 181x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
-        LayoutText {#text} at (181,1) size 4x19
-          text run at (181,1) width 4: " "
-        LayoutInline {A} at (0,0) size 162x19 [color=#0000EE]
-          LayoutText {#text} at (185,1) size 162x19
-            text run at (185,1) width 162: "drop me into the text field"
-        LayoutText {#text} at (0,0) size 0x0
-layer at (8,100) size 784x2 clip at (0,0) size 0x0
-  LayoutBlockFlow {HR} at (0,92) size 784x2 [border: (1px inset #EEEEEE)]
-layer at (10,113) size 177x16
-  LayoutBlockFlow {DIV} at (2,3) size 177x16
-    LayoutText {#text} at (0,0) size 118x16
-      text run at (0,0) width 118: "http://www.ibm.com/"
-selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
-selection end:   position 19 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/editing/pasteboard/drop-text-without-selection-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/editing/pasteboard/drop-text-without-selection-expected.png
deleted file mode 100644
index c83a0d90..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.10/editing/pasteboard/drop-text-without-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/editing/pasteboard/drop-text-without-selection-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/editing/pasteboard/drop-text-without-selection-expected.txt
deleted file mode 100644
index b89fab2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.10/editing/pasteboard/drop-text-without-selection-expected.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x36
-        LayoutText {#text} at (0,0) size 108x18
-          text run at (0,0) width 108: "This is a test for "
-        LayoutInline {I} at (0,0) size 764x36
-          LayoutInline {A} at (0,0) size 353x18 [color=#0000EE]
-            LayoutText {#text} at (107,0) size 353x18
-              text run at (107,0) width 353: "http://bugzilla.opendarwin.org/show_bug.cgi?id=8394"
-          LayoutText {#text} at (459,0) size 764x36
-            text run at (459,0) width 5: " "
-            text run at (463,0) width 301: "Editable region does not accept dropped text if"
-            text run at (0,18) width 128: "there is no selection"
-        LayoutText {#text} at (127,18) size 5x18
-          text run at (127,18) width 5: "."
-      LayoutBlockFlow {P} at (0,52) size 784x18
-        LayoutText {#text} at (0,0) size 667x18
-          text run at (0,0) width 487: "The text field should accept drag-and-dropped text, such as the link, even if "
-          text run at (486,0) width 181: "no text is currently selected."
-      LayoutBlockFlow (anonymous) at (0,96) size 784x19
-        LayoutTextControl {INPUT} at (0,0) size 131x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
-        LayoutText {#text} at (131,0) size 4x18
-          text run at (131,0) width 4: " "
-        LayoutInline {A} at (0,0) size 166x18 [color=#0000EE]
-          LayoutText {#text} at (135,0) size 166x18
-            text run at (135,0) width 166: "drop me into the text field"
-        LayoutText {#text} at (0,0) size 0x0
-layer at (8,94) size 784x2 clip at (0,0) size 0x0
-  LayoutBlockFlow {HR} at (0,86) size 784x2 [border: (1px inset #EEEEEE)]
-layer at (11,107) size 125x13
-  LayoutBlockFlow {DIV} at (3,3) size 125x13
-    LayoutText {#text} at (0,0) size 106x13
-      text run at (0,0) width 106: "http://www.ibm.com/"
-selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
-selection end:   position 19 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/editing/pasteboard/drop-text-without-selection-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/editing/pasteboard/drop-text-without-selection-expected.png
deleted file mode 100644
index ff49027..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.11/editing/pasteboard/drop-text-without-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/editing/pasteboard/drop-text-without-selection-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.11/editing/pasteboard/drop-text-without-selection-expected.txt
deleted file mode 100644
index abdad5d..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.11/editing/pasteboard/drop-text-without-selection-expected.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x36
-        LayoutText {#text} at (0,0) size 108x18
-          text run at (0,0) width 108: "This is a test for "
-        LayoutInline {I} at (0,0) size 764x36
-          LayoutInline {A} at (0,0) size 353x18 [color=#0000EE]
-            LayoutText {#text} at (107,0) size 353x18
-              text run at (107,0) width 353: "http://bugzilla.opendarwin.org/show_bug.cgi?id=8394"
-          LayoutText {#text} at (459,0) size 764x36
-            text run at (459,0) width 5: " "
-            text run at (463,0) width 301: "Editable region does not accept dropped text if"
-            text run at (0,18) width 128: "there is no selection"
-        LayoutText {#text} at (127,18) size 5x18
-          text run at (127,18) width 5: "."
-      LayoutBlockFlow {P} at (0,52) size 784x18
-        LayoutText {#text} at (0,0) size 667x18
-          text run at (0,0) width 487: "The text field should accept drag-and-dropped text, such as the link, even if "
-          text run at (486,0) width 181: "no text is currently selected."
-      LayoutBlockFlow (anonymous) at (0,96) size 784x19
-        LayoutTextControl {INPUT} at (0,0) size 131x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
-        LayoutText {#text} at (131,0) size 4x18
-          text run at (131,0) width 4: " "
-        LayoutInline {A} at (0,0) size 166x18 [color=#0000EE]
-          LayoutText {#text} at (135,0) size 166x18
-            text run at (135,0) width 166: "drop me into the text field"
-        LayoutText {#text} at (0,0) size 0x0
-layer at (8,94) size 784x2 clip at (0,0) size 0x0
-  LayoutBlockFlow {HR} at (0,86) size 784x2 [border: (1px inset #EEEEEE)]
-layer at (11,107) size 125x13
-  LayoutBlockFlow {DIV} at (3,3) size 125x13
-    LayoutText {#text} at (0,0) size 109x13
-      text run at (0,0) width 109: "http://www.ibm.com/"
-selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
-selection end:   position 19 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/editing/pasteboard/drop-text-without-selection-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/editing/pasteboard/drop-text-without-selection-expected.png
deleted file mode 100644
index 3101aa9..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/editing/pasteboard/drop-text-without-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.tentative-expected.txt b/third_party/blink/web_tests/platform/mac-retina/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.tentative-expected.txt
deleted file mode 100644
index e69de29..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/external/wpt/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.tentative-expected.txt
+++ /dev/null
diff --git a/third_party/blink/web_tests/platform/mac/editing/pasteboard/drop-text-without-selection-expected.png b/third_party/blink/web_tests/platform/mac/editing/pasteboard/drop-text-without-selection-expected.png
deleted file mode 100644
index 50445e0..0000000
--- a/third_party/blink/web_tests/platform/mac/editing/pasteboard/drop-text-without-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/editing/pasteboard/drop-text-without-selection-expected.txt b/third_party/blink/web_tests/platform/mac/editing/pasteboard/drop-text-without-selection-expected.txt
deleted file mode 100644
index e3a15d7..0000000
--- a/third_party/blink/web_tests/platform/mac/editing/pasteboard/drop-text-without-selection-expected.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x36
-        LayoutText {#text} at (0,0) size 108x18
-          text run at (0,0) width 108: "This is a test for "
-        LayoutInline {I} at (0,0) size 764x36
-          LayoutInline {A} at (0,0) size 353x18 [color=#0000EE]
-            LayoutText {#text} at (107,0) size 353x18
-              text run at (107,0) width 353: "http://bugzilla.opendarwin.org/show_bug.cgi?id=8394"
-          LayoutText {#text} at (459,0) size 764x36
-            text run at (459,0) width 5: " "
-            text run at (463,0) width 301: "Editable region does not accept dropped text if"
-            text run at (0,18) width 128: "there is no selection"
-        LayoutText {#text} at (127,18) size 5x18
-          text run at (127,18) width 5: "."
-      LayoutBlockFlow {P} at (0,52) size 784x18
-        LayoutText {#text} at (0,0) size 667x18
-          text run at (0,0) width 487: "The text field should accept drag-and-dropped text, such as the link, even if "
-          text run at (486,0) width 181: "no text is currently selected."
-      LayoutBlockFlow (anonymous) at (0,96) size 784x19
-        LayoutTextControl {INPUT} at (0,0) size 131x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
-        LayoutText {#text} at (131,0) size 4x18
-          text run at (131,0) width 4: " "
-        LayoutInline {A} at (0,0) size 166x18 [color=#0000EE]
-          LayoutText {#text} at (135,0) size 166x18
-            text run at (135,0) width 166: "drop me into the text field"
-        LayoutText {#text} at (0,0) size 0x0
-layer at (8,94) size 784x2 clip at (0,0) size 0x0
-  LayoutBlockFlow {HR} at (0,86) size 784x2 [border: (1px inset #EEEEEE)]
-layer at (11,107) size 125x13
-  LayoutBlockFlow {DIV} at (3,3) size 125x13
-    LayoutText {#text} at (0,0) size 110x13
-      text run at (0,0) width 110: "http://www.ibm.com/"
-selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
-selection end:   position 19 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
diff --git a/third_party/blink/web_tests/platform/win/editing/pasteboard/drop-text-without-selection-expected.png b/third_party/blink/web_tests/platform/win/editing/pasteboard/drop-text-without-selection-expected.png
deleted file mode 100644
index edef147..0000000
--- a/third_party/blink/web_tests/platform/win/editing/pasteboard/drop-text-without-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/pasteboard/drop-text-without-selection-expected.txt b/third_party/blink/web_tests/platform/win/editing/pasteboard/drop-text-without-selection-expected.txt
deleted file mode 100644
index 77542d3..0000000
--- a/third_party/blink/web_tests/platform/win/editing/pasteboard/drop-text-without-selection-expected.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x40
-        LayoutText {#text} at (0,0) size 99x19
-          text run at (0,0) width 99: "This is a test for "
-        LayoutInline {I} at (0,0) size 752x39
-          LayoutInline {A} at (0,0) size 349x19 [color=#0000EE]
-            LayoutText {#text} at (99,0) size 349x19
-              text run at (99,0) width 349: "http://bugzilla.opendarwin.org/show_bug.cgi?id=8394"
-          LayoutText {#text} at (448,0) size 752x39
-            text run at (448,0) width 4: " "
-            text run at (452,0) width 300: "Editable region does not accept dropped text if"
-            text run at (0,20) width 126: "there is no selection"
-        LayoutText {#text} at (126,20) size 4x19
-          text run at (126,20) width 4: "."
-      LayoutBlockFlow {P} at (0,56) size 784x20
-        LayoutText {#text} at (0,0) size 625x19
-          text run at (0,0) width 458: "The text field should accept drag-and-dropped text, such as the link, even if "
-          text run at (458,0) width 167: "no text is currently selected."
-      LayoutBlockFlow (anonymous) at (0,102) size 784x22
-        LayoutTextControl {INPUT} at (0,0) size 173x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
-        LayoutText {#text} at (173,1) size 4x19
-          text run at (173,1) width 4: " "
-        LayoutInline {A} at (0,0) size 154x19 [color=#0000EE]
-          LayoutText {#text} at (177,1) size 154x19
-            text run at (177,1) width 154: "drop me into the text field"
-        LayoutText {#text} at (0,0) size 0x0
-layer at (8,100) size 784x2 clip at (0,0) size 0x0
-  LayoutBlockFlow {HR} at (0,92) size 784x2 [border: (1px inset #EEEEEE)]
-layer at (10,113) size 169x16
-  LayoutBlockFlow {DIV} at (2,3) size 169x16
-    LayoutText {#text} at (0,0) size 118x16
-      text run at (0,0) width 118: "http://www.ibm.com/"
-selection start: position 0 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
-selection end:   position 19 of child 0 {#text} of child 0 {DIV} of {#document-fragment} of child 7 {INPUT} of body
diff --git a/third_party/blink/web_tests/virtual/custom-user-timing/http/tests/performance-timing/custom-user-timing/README.txt b/third_party/blink/web_tests/virtual/custom-user-timing/http/tests/performance-timing/custom-user-timing/README.txt
deleted file mode 100644
index dedb3cf..0000000
--- a/third_party/blink/web_tests/virtual/custom-user-timing/http/tests/performance-timing/custom-user-timing/README.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This directory contains the test cases for Custom User Timing. For now, the
-Custom User Timing are still working in progress and not ready to be web-exposed
- yet. Some of them, if appropriate to be web-platform-tests, will be upstreamed
-to web-platform-tests after Custom User Timing are fully implemented.
-
-The test cases in this directory requires enabling of runtime feature flag
-CustomUserTiming.
\ No newline at end of file
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 25903f9..54dba854 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -7367,6 +7367,7 @@
 interface SpeechSynthesisEvent : Event
     attribute @@toStringTag
     getter charIndex
+    getter charLength
     getter elapsedTime
     getter name
     getter utterance
@@ -10540,11 +10541,11 @@
     method constructor
 interface XRRigidTransform
     attribute @@toStringTag
+    getter inverse
     getter matrix
     getter orientation
     getter position
     method constructor
-    method inverse
 interface XRSession : EventTarget
     attribute @@toStringTag
     getter environmentBlendMode
diff --git a/third_party/blink/web_tests/wpt_internal/README b/third_party/blink/web_tests/wpt_internal/README
new file mode 100644
index 0000000..b10a3dc
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/README
@@ -0,0 +1,10 @@
+This directory is the internal counterpart of external/wpt. All WPT features are
+enabled in this directory, including wptserve: this directory is mapped to
+wpt_staging/ on wptserve.
+
+Tests in this directory can use Blink internal testing APIs (`wpt lint` is NOT
+enforced in this directory), and they will not be exported to upstream. Please
+try to use external/wpt whenever possible.
+
+Note: tests have to go into subdirectories. Files in the root level of
+wpt_internal are not recognized as tests.
diff --git a/third_party/blink/web_tests/wpt_internal/infrastructure/wpt-server-http.sub.html b/third_party/blink/web_tests/wpt_internal/infrastructure/wpt-server-http.sub.html
new file mode 100644
index 0000000..c997bf8e
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/infrastructure/wpt-server-http.sub.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>Basic server-side substituion and testharness</title>
+<meta charset="utf-8" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+  <script>
+    assert_true('{{domains[www]}}'.startsWith('www.'));
+    assert_true({{ports[http][0]}} > 0);
+    done();
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html b/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html
index f156a65..0ed917c 100644
--- a/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html
+++ b/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html
@@ -82,7 +82,7 @@
           let grip_pose = frame.getPose(source.gripSpace, referenceSpace);
           let input_pose = frame.getPose(source.targetRaySpace, referenceSpace);
 
-          let view_matrix = pose.views[0].transform.inverse().matrix;
+          let view_matrix = pose.views[0].transform.inverse.matrix;
           let grip_matrix = grip_pose.transform.matrix;
           let ray_matrix = input_pose.transform.matrix;
 
diff --git a/third_party/closure_compiler/externs/accessibility_private.js b/third_party/closure_compiler/externs/accessibility_private.js
index a919ab1..4d56450 100644
--- a/third_party/closure_compiler/externs/accessibility_private.js
+++ b/third_party/closure_compiler/externs/accessibility_private.js
@@ -256,6 +256,12 @@
 chrome.accessibilityPrivate.toggleDictation = function() {};
 
 /**
+ * Opens or closes the virtual keyboard.
+ * @param {!boolean} isVisible
+ */
+chrome.accessibilityPrivate.setVirtualKeyboardVisible = function(isVisible) {};
+
+/**
  * Fired whenever ChromeVox should output introduction.
  * @type {!ChromeEvent}
  */
diff --git a/third_party/custom_tabs_client/BUILD.gn b/third_party/custom_tabs_client/BUILD.gn
index 61f9e6e9..0ed6e792 100644
--- a/third_party/custom_tabs_client/BUILD.gn
+++ b/third_party/custom_tabs_client/BUILD.gn
@@ -63,6 +63,7 @@
     "src/customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java",
     "src/customtabs/src/android/support/customtabs/browseractions/BrowserServiceFileProvider.java",
     "src/customtabs/src/android/support/customtabs/browseractions/BrowserServiceImageReadTask.java",
+    "src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityBuilder.java",
     "src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityService.java",
     "src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityServiceWrapper.java",
     "src/customtabs/src/android/support/customtabs/trusted/TrustedWebActivityServiceConnectionManager.java",
diff --git a/third_party/feed/README.chromium b/third_party/feed/README.chromium
index 06f7708..8a3c669 100644
--- a/third_party/feed/README.chromium
+++ b/third_party/feed/README.chromium
@@ -2,7 +2,7 @@
 Short name: feed
 URL: https://chromium.googlesource.com/feed
 Version: 0
-Revision: 23ca33876e4ef3128673ec2b20c7fa4ffdce0bb0
+Revision: d1e6b4e648a89fb58f706eb182f16053fa95f1fe
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/feed/java_sources.gni b/third_party/feed/java_sources.gni
index 73e9b16c..c89a97f1 100644
--- a/third_party/feed/java_sources.gni
+++ b/third_party/feed/java_sources.gni
@@ -74,6 +74,7 @@
   "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/drivers/ZeroStateDriver.java",
   "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/pendingdismiss/ClusterPendingDismissHelper.java",
   "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/pendingdismiss/PendingDismissHandler.java",
+  "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/scroll/BasicStreamScrollTracker.java",
   "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/scroll/ScrollRestorer.java",
   "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/viewholders/ContinuationViewHolder.java",
   "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/viewholders/FeedViewHolder.java",
@@ -104,6 +105,12 @@
   "src/src/main/java/com/google/android/libraries/feed/common/functional/Predicate.java",
   "src/src/main/java/com/google/android/libraries/feed/common/functional/Supplier.java",
   "src/src/main/java/com/google/android/libraries/feed/common/functional/Suppliers.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/intern/HashPoolInterner.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/intern/InternedMap.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/intern/Interner.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/intern/InternerWithStats.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/intern/PoolInternerBase.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/intern/WeakPoolInterner.java",
   "src/src/main/java/com/google/android/libraries/feed/common/locale/LocaleUtils.java",
   "src/src/main/java/com/google/android/libraries/feed/common/logging/Dumpable.java",
   "src/src/main/java/com/google/android/libraries/feed/common/logging/Dumper.java",
@@ -118,7 +125,6 @@
   "src/src/main/java/com/google/android/libraries/feed/feedactionparser/FeedActionParser.java",
   "src/src/main/java/com/google/android/libraries/feed/feedactionparser/FeedActionParserFactory.java",
   "src/src/main/java/com/google/android/libraries/feed/feedactionparser/internal/ActionTypeConverter.java",
-  "src/src/main/java/com/google/android/libraries/feed/feedactionparser/internal/ElementTypeConverter.java",
   "src/src/main/java/com/google/android/libraries/feed/feedactionparser/internal/PietFeedActionPayloadRetriever.java",
   "src/src/main/java/com/google/android/libraries/feed/feedactionparser/internal/TooltipInfoImpl.java",
   "src/src/main/java/com/google/android/libraries/feed/feedactionreader/FeedActionReader.java",
@@ -186,10 +192,10 @@
   "src/src/main/java/com/google/android/libraries/feed/host/logging/BasicLoggingApi.java",
   "src/src/main/java/com/google/android/libraries/feed/host/logging/ContentLoggingData.java",
   "src/src/main/java/com/google/android/libraries/feed/host/logging/ElementLoggingData.java",
-  "src/src/main/java/com/google/android/libraries/feed/host/logging/ElementType.java",
   "src/src/main/java/com/google/android/libraries/feed/host/logging/InternalFeedError.java",
   "src/src/main/java/com/google/android/libraries/feed/host/logging/LoggingApi.java",
   "src/src/main/java/com/google/android/libraries/feed/host/logging/RequestReason.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/logging/ScrollType.java",
   "src/src/main/java/com/google/android/libraries/feed/host/logging/SessionEvent.java",
   "src/src/main/java/com/google/android/libraries/feed/host/logging/SpinnerType.java",
   "src/src/main/java/com/google/android/libraries/feed/host/logging/ZeroStateShowReason.java",
@@ -303,7 +309,10 @@
   "src/src/main/java/com/google/android/libraries/feed/sharedstream/publicapi/menumeasurer/MenuMeasurer.java",
   "src/src/main/java/com/google/android/libraries/feed/sharedstream/publicapi/menumeasurer/Size.java",
   "src/src/main/java/com/google/android/libraries/feed/sharedstream/removetrackingfactory/StreamRemoveTrackingFactory.java",
+  "src/src/main/java/com/google/android/libraries/feed/sharedstream/scroll/ScrollEvents.java",
+  "src/src/main/java/com/google/android/libraries/feed/sharedstream/scroll/ScrollLogger.java",
   "src/src/main/java/com/google/android/libraries/feed/sharedstream/scroll/ScrollRestoreHelper.java",
+  "src/src/main/java/com/google/android/libraries/feed/sharedstream/scroll/ScrollTracker.java",
   "src/src/main/java/com/google/android/libraries/feed/sharedstream/scroll/StreamScrollMonitor.java",
   "src/src/main/java/com/google/android/libraries/feed/sharedstream/ui/MaterialSpinnerView.java",
 ]
diff --git a/third_party/feed/proto_sources.gni b/third_party/feed/proto_sources.gni
index 1bc1b94..fc52a3e1 100644
--- a/third_party/feed/proto_sources.gni
+++ b/third_party/feed/proto_sources.gni
@@ -36,6 +36,7 @@
   "src/src/main/proto/search/now/wire/feed/consistency_token.proto",
   "src/src/main/proto/search/now/wire/feed/content_id.proto",
   "src/src/main/proto/search/now/wire/feed/data_operation.proto",
+  "src/src/main/proto/search/now/wire/feed/display_info.proto",
   "src/src/main/proto/search/now/wire/feed/feature.proto",
   "src/src/main/proto/search/now/wire/feed/feed_action.proto",
   "src/src/main/proto/search/now/wire/feed/feed_action_query_data.proto",
diff --git a/third_party/google_android_play_core/README.chromium b/third_party/google_android_play_core/README.chromium
index e3b3bb1..dc2032ab69 100644
--- a/third_party/google_android_play_core/README.chromium
+++ b/third_party/google_android_play_core/README.chromium
@@ -1,6 +1,6 @@
-Name: Goole Android Play Core
+Name: Play Core Library
 Short Name: Play Core
-URL: https://developers.google.com/android/guides/setup
+URL: https://developer.android.com/guide/app-bundle/playcore
 Version: 1.3.7
 License: Android Software Development Kit License
 License File: LICENSE
diff --git a/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml
index 8935952..09825ed 100644
--- a/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml
+++ b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml
@@ -1019,7 +1019,7 @@
     </request>
   </interface>
 
-  <interface name="zcr_input_method_surface_v1" version="17">
+  <interface name="zcr_input_method_surface_v1" version="18">
     <description summary="An input method window">
       An interface that may be implemented by a wl_surface to host IME contents.
     </description>
@@ -1029,6 +1029,35 @@
 	Unmap and destroy the input mtehod surface.
       </description>
     </request>
+
+    <!-- Version 18 additions -->
+
+    <request name="set_bounds" since="18">
+      <description summary="set window bounds">
+	Set the "visible bounds" of a window from the user's perspective.
+
+	The bounds are double buffered, and will be applied at the
+	time wl_surface.commit of the corresponding wl_surface is called.
+
+	Once the bounds are set, it is not possible to unset them, and they will
+	remain the same until set_bounds is called again, even if a new sub-
+	surface or buffer is attached.
+
+	If never set, the value is the surface content bounds. This updates
+	dynamically on every commit.
+
+	The bounds are relative to the given display. If the display is invalid,
+	they are assumed to be relative to the primary display.
+
+	The width and height must be greater than zero.
+      </description>
+      <arg name="display_id_hi" type="uint"/>
+      <arg name="display_id_lo" type="uint"/>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+    </request>
   </interface>
 
 </protocol>
diff --git a/third_party/webxr_test_pages/webxr-samples/360-photos.html b/third_party/webxr_test_pages/webxr-samples/360-photos.html
index 2d09320d..9f8487f 100644
--- a/third_party/webxr_test_pages/webxr-samples/360-photos.html
+++ b/third_party/webxr_test_pages/webxr-samples/360-photos.html
@@ -186,7 +186,7 @@
           for (let view of pose.views) {
             let renderView = new WebXRView();
             renderView.projectionMatrix = view.projectionMatrix;
-            renderView.viewMatrix = view.transform.inverse().matrix;
+            renderView.viewMatrix = view.transform.inverse.matrix;
             renderView.viewport = session.renderState.baseLayer.getViewport(view);
 
             // It's important to take into account which eye the view is
diff --git a/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html b/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html
index 980baae4a..0f349ee44 100644
--- a/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html
+++ b/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html
@@ -205,7 +205,7 @@
             gl.viewport(viewport.x, viewport.y,
                         viewport.width, viewport.height);
 
-            scene.draw(view.projectionMatrix, view.transform.inverse().matrix);
+            scene.draw(view.projectionMatrix, view.transform.inverse.matrix);
           }
         }
 
diff --git a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/scenes/scene.js b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/scenes/scene.js
index e7d54c4..55ebbf6 100644
--- a/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/scenes/scene.js
+++ b/third_party/webxr_test_pages/webxr-samples/js/cottontail/src/scenes/scene.js
@@ -28,7 +28,7 @@
   constructor(view, pose, layer) {
     super(
       view ? view.projectionMatrix : null,
-      view ? view.transform.inverse().matrix : null,
+      view ? view.transform.inverse.matrix : null,
       (layer && view) ? layer.getViewport(view) : null,
       view ? view.eye : 'left'
     );
diff --git a/third_party/webxr_test_pages/webxr-samples/magic-window.html b/third_party/webxr_test_pages/webxr-samples/magic-window.html
index f247e46..29a32fa 100644
--- a/third_party/webxr_test_pages/webxr-samples/magic-window.html
+++ b/third_party/webxr_test_pages/webxr-samples/magic-window.html
@@ -188,7 +188,7 @@
             gl.viewport(viewport.x, viewport.y,
                         viewport.width, viewport.height);
 
-            scene.draw(view.projectionMatrix, view.transform.inverse().matrix);
+            scene.draw(view.projectionMatrix, view.transform.inverse.matrix);
           }
         }
 
diff --git a/third_party/webxr_test_pages/webxr-samples/mirroring.html b/third_party/webxr_test_pages/webxr-samples/mirroring.html
index 66002e72..6288b618 100644
--- a/third_party/webxr_test_pages/webxr-samples/mirroring.html
+++ b/third_party/webxr_test_pages/webxr-samples/mirroring.html
@@ -169,7 +169,7 @@
             gl.viewport(viewport.x, viewport.y,
                         viewport.width, viewport.height);
 
-            scene.draw(view.projectionMatrix, view.transform.inverse().matrix);
+            scene.draw(view.projectionMatrix, view.transform.inverse.matrix);
           }
         }
 
diff --git a/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html b/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html
index 0398ec99..b71847f 100644
--- a/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html
+++ b/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html
@@ -234,7 +234,7 @@
             // scene.drawXRViews() function, which handles gathering these
             // values internally.
             renderView.projectionMatrix = view.projectionMatrix;
-            renderView.viewMatrix = view.transform.inverse().matrix;
+            renderView.viewMatrix = view.transform.inverse.matrix;
             renderView.viewport = session.renderState.baseLayer.getViewport(view);
             views.push(renderView);
           }
diff --git a/third_party/webxr_test_pages/webxr-samples/xr-presentation.html b/third_party/webxr_test_pages/webxr-samples/xr-presentation.html
index 973da55d..48a364a8 100644
--- a/third_party/webxr_test_pages/webxr-samples/xr-presentation.html
+++ b/third_party/webxr_test_pages/webxr-samples/xr-presentation.html
@@ -206,7 +206,7 @@
             // projection and view matricies from the current view and pose.
             // We bound the framebuffer and viewport up above, and are passing
             // in the appropriate matrices here to be used when rendering.
-            scene.draw(view.projectionMatrix, view.transform.inverse().matrix);
+            scene.draw(view.projectionMatrix, view.transform.inverse.matrix);
           }
         } else {
           // There's several options for handling cases where no pose is given.
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index a4aa307c..bc4bd8da 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -33,8 +33,7 @@
     <classpathentry kind="src" path="chrome/android/java/src"/>
     <classpathentry kind="src" path="chrome/android/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/junit/src"/>
-    <classpathentry kind="src" path="chrome/android/sync_shell/javatests/src"/>
-    <classpathentry kind="src" path="chrome/android/touchless/fallback/src"/>
+    <classpathentry kind="src" path="chrome/android/touchless/fallback/java/src"/>
     <classpathentry kind="src" path="chrome/android/touchless/java/src"/>
     <classpathentry kind="src" path="chrome/android/touchless/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/libs/client/junit/src"/>
@@ -46,7 +45,6 @@
     <classpathentry kind="src" path="chrome/android/webapk/shell_apk/src"/>
     <classpathentry kind="src" path="chrome/test/android/cast_emulator/src"/>
     <classpathentry kind="src" path="chrome/test/android/javatests/src"/>
-    <classpathentry kind="src" path="chrome/test/android/unit_tests_apk/src"/>
     <classpathentry kind="src" path="chrome/test/chromedriver/test/webview_shell/java/src"/>
     <classpathentry kind="src" path="chromecast/browser/android/apk/src"/>
     <classpathentry kind="src" path="components/autofill/android/java/src"/>
@@ -66,15 +64,12 @@
     <classpathentry kind="src" path="components/invalidation/impl/android/junit/src"/>
     <classpathentry kind="src" path="components/location/android/java/src"/>
     <classpathentry kind="src" path="components/navigation_interception/android/java/src"/>
-    <classpathentry kind="src" path="components/ntp_tiles/android/java/src"/>
     <classpathentry kind="src" path="components/offline_items_collection/core/android/java/src"/>
     <classpathentry kind="src" path="components/omnibox/browser/android/java/src"/>
     <classpathentry kind="src" path="components/payments/content/android/java/src"/>
     <classpathentry kind="src" path="components/policy/android/java/src"/>
     <classpathentry kind="src" path="components/policy/android/javatests/src"/>
     <classpathentry kind="src" path="components/policy/android/junit/src"/>
-    <classpathentry kind="src" path="components/precache/android/java/src"/>
-    <classpathentry kind="src" path="components/precache/android/javatests/src"/>
     <classpathentry kind="src" path="components/signin/core/browser/android/java/src"/>
     <classpathentry kind="src" path="components/signin/core/browser/android/javatests/src"/>
     <classpathentry kind="src" path="components/sync/android/java/src"/>
@@ -84,7 +79,6 @@
     <classpathentry kind="src" path="components/variations/android/java/src"/>
     <classpathentry kind="src" path="components/embedder_support/android/java/src"/>
     <classpathentry kind="src" path="components/web_restrictions/browser/java/src"/>
-    <classpathentry kind="src" path="components/web_restrictions/browser/javatests/src"/>
     <classpathentry kind="src" path="components/web_restrictions/browser/junit/src"/>
     <classpathentry kind="src" path="components/minidump_uploader/android/java/src"/>
     <classpathentry kind="src" path="components/minidump_uploader/android/javatests/src"/>
@@ -98,12 +92,9 @@
     <classpathentry kind="src" path="content/shell/android/javatests/src"/>
     <classpathentry kind="src" path="content/shell/android/linker_test_apk/src"/>
     <classpathentry kind="src" path="content/shell/android/shell_apk/src"/>
-    <classpathentry kind="src" path="device/battery/android/java/src"/>
     <classpathentry kind="src" path="device/bluetooth/android/java/src"/>
     <classpathentry kind="src" path="device/gamepad/android/java/src"/>
-    <classpathentry kind="src" path="device/nfc/android/java/src"/>
     <classpathentry kind="src" path="device/usb/android/java/src"/>
-    <classpathentry kind="src" path="device/vibration/android/java/src"/>
     <classpathentry kind="src" path="media/base/android/java/src"/>
     <classpathentry kind="src" path="mojo/public/java/base/src"/>
     <classpathentry kind="src" path="mojo/public/java/bindings/src"/>
@@ -117,8 +108,6 @@
     <classpathentry kind="src" path="remoting/android/java/src"/>
     <classpathentry kind="src" path="remoting/android/javatests/src"/>
     <classpathentry kind="src" path="services/service_manager/public/java/src"/>
-    <classpathentry kind="src" path="services/data_decoder/public/cpp/android/src"/>
-    <classpathentry kind="src" path="testing/android/appurify_support/java/src"/>
     <classpathentry kind="src" path="testing/android/broker/java/src"/>
     <classpathentry kind="src" path="testing/android/driver/java/src"/>
     <classpathentry kind="src" path="testing/android/junit/java/src"/>
@@ -132,195 +121,68 @@
     <classpathentry kind="src" path="third_party/custom_tabs_client/src/Application/src/main/java"/>
     <classpathentry kind="src" path="third_party/custom_tabs_client/src/shared/src/main/java"/>
     <classpathentry kind="src" path="third_party/gif_player/src"/>
-    <classpathentry kind="src" path="third_party/jmake/src"/>
     <classpathentry kind="src" path="third_party/junit/src/src/main/java"/>
     <classpathentry kind="src" path="third_party/mockito/src/src/main/java"/>
     <classpathentry kind="src" path="tools/android/memconsumer/java/src"/>
     <classpathentry kind="src" path="ui/android/java/src"/>
     <classpathentry kind="src" path="ui/android/javatests/src"/>
-    <classpathentry kind="src" path="out/Debug/chrome_public_apk/gen"/>
-    <classpathentry kind="src" path="out/Debug/content_shell_apk/gen"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/accessibility_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/activity_type_ids_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/android_resource_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/autocomplete_match_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/autocomplete_match_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/ax_enumerations_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/base_java_application_state"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/base_java_library_load_from_apk_status_codes"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/base_java_library_process_type"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/base_java_memory_pressure_level"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/bitmap_format_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/bookmark_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/browsing_data_utils_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/certificate_mime_types_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/cert_verify_status_android_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/clear_browsing_data_tab_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/chromium_url_request_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/connectivity_check_result_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/console_message_level_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/content_gamepad_mapping"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/content_setting_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/content_settings_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/data_use_ui_message_enum_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/data_reduction_proxy_savings_cleared_enum_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/device_sensors_consts_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/gesture_event_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/http_cache_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/infobar_action_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/infobar_delegate_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/invalidate_types_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/investigated_scenario_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/media_android_captureapitype"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/media_android_imageformat"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/model_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/most_visited_tile_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/navigation_controller_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/net_request_priority_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/network_change_notifier_android_types_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/network_change_notifier_types_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/network_quality_observations_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/offline_page_feature_enums_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/offline_page_model_enums_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/page_info_connection_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/page_transition_types_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/payments_journey_logger_enum_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/popup_item_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/private_key_types_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/profile_account_management_metrics_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/quick_action_category_enum_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/readback_response_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/result_codes_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/screen_orientation_values_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/security_state_enums_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/selection_event_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/sensor_manager_android_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/shortcut_source_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/signin_metrics_enum_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/speech_recognition_error_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/stop_source_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/system_ui_resource_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/tab_load_status_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/text_input_type_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/top_controls_state_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/touch_device_types_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/touch_handle_orientation_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/traffic_stats_error_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/url_request_error_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/url_request_failed_job_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/usb_descriptors_javagen"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/web_display_mode"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/web_input_event_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/website_settings_action_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/web_text_input_type"/>
-    <classpathentry kind="src" path="out/Debug/gen/enums/window_open_disposition_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/templates/base_build_config_gen"/>
-    <classpathentry kind="src" path="out/Debug/gen/templates/base_native_libraries_gen"/>
-    <classpathentry kind="src" path="out/Debug/gen/templates/chrome_version_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/templates/dom_distiller_core_font_family_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/templates/dom_distiller_core_theme_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/templates/load_states_list"/>
-    <classpathentry kind="src" path="out/Debug/gen/templates/net_errors_java"/>
-    <classpathentry kind="src" path="out/Debug/gen/templates/resource_id_java"/>
-    <classpathentry kind="src" path="out/Debug/java_mojo/device_battery_mojo_bindings/src"/>
-    <classpathentry kind="src" path="out/Debug/java_mojo/mojo_public_test_interfaces_mojom/src"/>
-    <classpathentry kind="src" path="out/Debug/java_proto/cacheinvalidation_proto_java/src"/>
-    <classpathentry kind="src" path="out/Debug/java_proto/document_tab_model_info_proto_java/src"/>
-    <classpathentry kind="src" path="out/Debug/java_proto/partner_location_descriptor_proto_java/src"/>
-    <classpathentry kind="src" path="out/Debug/java_proto/test_support_proto_java/src"/>
-    <classpathentry kind="src" path="out/Debug/remoting_apk/gen"/>
-    <classpathentry kind="src" path="out/Debug/webview_instrumentation_test_apk/gen"/>
-    <classpathentry kind="lib" path="third_party/android_sdk/public/extras/google/gcm/gcm-client/dist/gcm.jar" sourcepath="third_party/android_sdk/public/extras/google/gcm/gcm-client/src"/>
-    <classpathentry kind="lib" path="third_party/android_sdk/public/platforms/android-28/android.jar" sourcepath="third_party/android_sdk/public/sources/">
+    <classpathentry kind="lib" path="../src/third_party/android_sdk/public/extras/google/gcm/gcm-client/dist/gcm.jar" sourcepath="../src/third_party/android_sdk/public/extras/google/gcm/gcm-client/src"/>
+    <classpathentry kind="lib" path="../src/third_party/android_sdk/public/platforms/android-28/android.jar" sourcepath="../src/third_party/android_sdk/public/sources/">
         <attributes>
             <attribute name="javadoc_location" value="http://developer.android.com/reference/"/>
         </attributes>
     </classpathentry>
-    <classpathentry kind="lib" path="third_party/android_sdk/public/platforms/android-25/data/layoutlib.jar" sourcepath="third_party/android_sdk/public/sources/"/>
-    <classpathentry kind="lib" path="third_party/android_sdk/public/platforms/android-25/uiautomator.jar" sourcepath="third_party/android_sdk/public/sources"/>
-    <classpathentry kind="lib" path="third_party/android_sdk/public/extras/android/support/design/libs/android-support-design.jar" sourcepath="third_party/android_sdk/public/sources"/>
-    <classpathentry kind="lib" path="third_party/android_sdk/public/extras/android/support/v7/mediarouter/libs/android-support-v7-mediarouter.jar" sourcepath="third_party/android_sdk/public/sources"/>
-    <classpathentry kind="lib" path="third_party/android_sdk/public/extras/android/support/v7/recyclerview/libs/android-support-v7-recyclerview.jar" sourcepath="third_party/android_sdk/public/sources"/>
-    <classpathentry kind="lib" path="third_party/android_sdk/public/extras/android/support/v13/android-support-v13.jar" sourcepath="third_party/android_sdk/public/sources"/>
-    <classpathentry kind="lib" path="third_party/android_sdk/public/extras/android/support/v7/appcompat/libs/android-support-v7-appcompat.jar" sourcepath="third_party/android_sdk/public/sources"/>
-    <classpathentry kind="lib" path="third_party/bouncycastle/lib/bcprov-jdk16-1.46.jar"/>
-    <classpathentry kind="lib" path="third_party/byte_buddy/lib/byte-buddy-1.4.17.jar"/>
-    <classpathentry kind="lib" path="third_party/hamcrest/lib/hamcrest-library-1.3.jar"/>
-    <classpathentry kind="lib" path="third_party/intellij/lib/annotations-12.0.jar"/>
-    <classpathentry kind="lib" path="third_party/junit/src/lib/hamcrest-core-1.3.jar" sourcepath="third_party/junit/src/lib/hamcrest-core-1.3-sources.jar"/>
-    <classpathentry kind="lib" path="third_party/objenesis/lib/objenesis-2.4.jar"/>
-    <classpathentry kind="lib" path="third_party/sqlite4java/lib/sqlite4java-0.282.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/cacheinvalidation_proto_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/content_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/jsr_305_javalib.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/net_java.jar"/>
+    <classpathentry kind="lib" path="../src/third_party/android_sdk/public/extras/android/support/design/libs/android-support-design.jar" sourcepath="../src/third_party/android_sdk/public/sources"/>
+    <classpathentry kind="lib" path="../src/third_party/android_sdk/public/extras/android/support/v7/mediarouter/libs/android-support-v7-mediarouter.jar" sourcepath="../src/third_party/android_sdk/public/sources"/>
+    <classpathentry kind="lib" path="../src/third_party/android_sdk/public/extras/android/support/v7/recyclerview/libs/android-support-v7-recyclerview.jar" sourcepath="../src/third_party/android_sdk/public/sources"/>
+    <classpathentry kind="lib" path="../src/third_party/android_sdk/public/extras/android/support/v13/android-support-v13.jar" sourcepath="../src/third_party/android_sdk/public/sources"/>
+    <classpathentry kind="lib" path="../src/third_party/android_sdk/public/extras/android/support/v7/appcompat/libs/android-support-v7-appcompat.jar" sourcepath="../src/third_party/android_sdk/public/sources"/>
+    <classpathentry kind="lib" path="../src/third_party/junit/src/lib/hamcrest-core-1.3.jar" sourcepath="../src/third_party/junit/src/lib/hamcrest-core-1.3-sources.jar"/>
 
     <!-- GN: R (resources) and NativeLibraries classes. -->
-    <classpathentry kind="lib" path="out/Debug/gen/chrome/android/chrome_public_apk/chrome_public_apk.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/gen/chrome/android/chrome_public_apk/chrome_public_apk.jar"/>
 
     <!-- GN: library jars, includes generated Java files. -->
-    <classpathentry kind="lib" path="out/Debug/lib.java/android_webview/android_webview_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/base/base_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/chrome/android/chrome_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/chrome/android/document_tab_model_info_proto_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/bookmarks/common/android/bookmarks_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/dom_distiller/content/browser/android/dom_distiller_content_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/dom_distiller/core/android/dom_distiller_core_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/gcm_driver/android/gcm_driver_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/gcm_driver/instance_id/android/instance_id_driver_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/invalidation/impl/java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/invalidation/impl/proto_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/navigation_interception/android/navigation_interception_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/omnibox/browser/browser_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/policy/android/policy_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/payments/content/payment_request_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/precache/android/precache_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/service_tab_launcher/service_tab_launcher_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/signin/core/browser/android/java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/variations/android/variations_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/components/embedder_suppport/android/web_contents_delegate_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/content/public/android/content_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/device/battery/android/battery_monitor_android.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/device/battery/mojo_bindings_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/device/bluetooth/java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/device/nfc/mojo_bindings_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/device/vibration/android/vibration_manager_android.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/device/vibration/mojo_bindings_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/media/base/android/media_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/media/midi/midi_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/mojo/public/java/bindings.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/mojo/public/java/system.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/mojo/public/java/system/system_impl_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/net/android/net_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/printing/printing_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/services/data_decoder/public/android/safe_json_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/services/service_manager/public/mojom/mojom_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/sync/android/sync_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/sync/test_support_proto_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/android_data_chart/android_data_chart_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/android_media/android_media_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/android_protobuf/protobuf_nano_javalib.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/android_swipe_refresh/android_swipe_refresh_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/android_tools/android_support_design_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/cacheinvalidation/cacheinvalidation_javalib.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/cacheinvalidation/cacheinvalidation_proto_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/cardboard-java/cardboard-java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/gif_player/gif_player_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/guava/guava-20.0.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/robolectric/robolectric_annotations_java.jar" sourcepath="third_party/robolectric/robolectric/robolectric-annotations/src/main/java"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/robolectric/robolectric_java.jar" sourcepath="third_party/robolectric/robolectric/robolectric/src/main/java"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/robolectric/robolectric_resources_java.jar" sourcepath="third_party/robolectric/robolectric/robolectric-resources/src/main/java"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/robolectric/robolectric_utils_java.jar" sourcepath="third_party/robolectric/robolectric/robolectric-utils/src/main/java"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/robolectric/shadows-core-3.2.jar" sourcepath="third_party/robolectric/robolectric/robolectric-shadows/shadows-core/src/main/java"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/robolectric/shadows-multidex-3.0.jar" sourcepath="third_party/robolectric/robolectric/robolectric-shadows/shadows-multidex/src/main/java"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/android_deps/com_android_support_support_compat_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/android_support_test_runner/runner-0.5-release-no-dep.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/android_support_test_runner/rules_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/third_party/blink/public/blink_headers_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/ui/accessibility/ui_accessibility_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/ui/android/ui_full_java.interface.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/ui/android/ui_java.jar"/>
-    <classpathentry kind="lib" path="out/Debug/lib.java/ui/base/mojo/mojo_bindings_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/android_webview/android_webview_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/base/base_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/chrome/android/chrome_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/chrome/android/document_tab_model_info_proto_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/bookmarks/common/android/bookmarks_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/dom_distiller/content/browser/android/dom_distiller_content_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/dom_distiller/core/android/dom_distiller_core_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/gcm_driver/android/gcm_driver_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/gcm_driver/instance_id/android/instance_id_driver_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/invalidation/impl/java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/invalidation/impl/proto_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/navigation_interception/android/navigation_interception_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/omnibox/browser/browser_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/policy/android/policy_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/signin/core/browser/android/java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/components/variations/android/variations_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/content/public/android/content_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/device/bluetooth/java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/media/base/android/media_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/media/midi/midi_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/mojo/public/java/system/system_impl_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/net/android/net_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/printing/printing_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/services/service_manager/public/mojom/mojom_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/android_data_chart/android_data_chart_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/android_media/android_media_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/android_protobuf/protobuf_nano_javalib.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/android_swipe_refresh/android_swipe_refresh_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/cacheinvalidation/cacheinvalidation_javalib.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/cacheinvalidation/cacheinvalidation_proto_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/gif_player/gif_player_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/robolectric/robolectric_annotations_java.jar" sourcepath="../src/third_party/robolectric/robolectric/robolectric-annotations/src/main/java"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/robolectric/robolectric_java.jar" sourcepath="../src/third_party/robolectric/robolectric/robolectric/src/main/java"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/robolectric/robolectric_resources_java.jar" sourcepath="../src/third_party/robolectric/robolectric/robolectric-resources/src/main/java"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/robolectric/robolectric_utils_java.jar" sourcepath="../src/third_party/robolectric/robolectric/robolectric-utils/src/main/java"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/robolectric/shadows-core-3.2.jar" sourcepath="../src/third_party/robolectric/robolectric/robolectric-shadows/shadows-core/src/main/java"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/android_deps/com_android_support_support_compat_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/android_support_test_runner/rules_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/third_party/blink/public/blink_headers_java.jar"/>
+    <classpathentry kind="lib" path="../src/out/Debug/lib.java/ui/android/ui_full_java.interface.jar"/>
 
     <!-- {% block additional_entries %} -->
     <!-- When this file is processed as a jinja2 template, additional
diff --git a/tools/android/roll/android_deps/build.gradle b/tools/android/roll/android_deps/build.gradle
index 91ce60a..a3a4734 100644
--- a/tools/android/roll/android_deps/build.gradle
+++ b/tools/android/roll/android_deps/build.gradle
@@ -15,9 +15,10 @@
     // Note about the configuration names: they are defined in buildSrc/ChromiumPlugin
 
     // Architecture components
-    def archComponentsVersion = '1.0.0'
+    def archComponentsVersion = '1.1.1'
     compile "android.arch.lifecycle:runtime:${archComponentsVersion}"
     compile "android.arch.lifecycle:common:${archComponentsVersion}"
+    compile "android.arch.lifecycle:common-java8:${archComponentsVersion}"
 
     // Play services libraries
     // See https://developers.google.com/android/guides/releases for updates
diff --git a/tools/android/sdk_updater/update_sdk.py b/tools/android/sdk_updater/update_sdk.py
index fd6bc7e4..8ca5e38 100755
--- a/tools/android/sdk_updater/update_sdk.py
+++ b/tools/android/sdk_updater/update_sdk.py
@@ -192,6 +192,36 @@
       temp_file.delete = False
 
 
+def GetCipdPackagePath(pkg_yaml_file):
+  """Find CIPD package path in .yaml file.
+
+  There should one line in .yaml file, e.g.:
+  "package: chrome_internal/third_party/android_sdk/internal/q/add-ons" or
+  "package: chromium/third_party/android_sdk/public/platforms"
+
+  Args:
+    pkg_yaml_file: The yaml file to find CIPD package path.
+
+  Returns:
+    The CIPD package path in yaml file.
+  """
+  cipd_package_path = ''
+  with open(pkg_yaml_file) as f:
+    pattern = re.compile(
+        # Match the argument with "package: "
+        r'(^\s*package:\s*)'
+        # The CIPD package path we want
+        r'([\w\/-]+)'
+        # End of string
+        r'(\s*?$)')
+    for line in f:
+      found = re.match(pattern, line)
+      if found:
+        cipd_package_path = found.group(2)
+        break
+  return cipd_package_path
+
+
 def UploadSdkPackage(sdk_root, dry_run, service_url, package, yaml_file,
                      verbose):
   """Build and upload a package instance file to CIPD.
@@ -213,13 +243,18 @@
     New instance ID when CIPD package created.
 
   Raises:
-    IOError: cannot find .yaml file or instance ID for package.
+    IOError: cannot find .yaml file, CIPD package path or instance ID for
+    package.
     CalledProcessError: cipd command failed to create package.
   """
   pkg_yaml_file = yaml_file or os.path.join(sdk_root, 'cipd_%s.yaml' % package)
   if not os.path.exists(pkg_yaml_file):
     raise IOError('Cannot find .yaml file for package %s' % package)
 
+  cipd_package_path = GetCipdPackagePath(pkg_yaml_file)
+  if not cipd_package_path:
+    raise IOError('Cannot find CIPD package path in %s' % pkg_yaml_file)
+
   if dry_run:
     print('This `package` command (without -n/--dry-run) would create and ' +
           'upload the package %s to CIPD.' % package)
@@ -236,10 +271,8 @@
     # e.g.: chromium/third_party/android_sdk/public/platforms:\
     # Kg2t9p0YnQk8bldUv4VA3o156uPXLUfIFAmVZ-Gm5ewC
     pattern = re.compile(
-        # Match the argument with
-        # "Instance: chromium/third_party/android_sdk/public/%s:"
-        (r'(^\s*Instance:\schromium\/third_party\/android_sdk\/public\/%s:)' %
-         package) +
+        # Match the argument with "Instance: %s:" for cipd_package_path
+        (r'(^\s*Instance: %s:)' % cipd_package_path) +
         # instance ID e.g. DLK621q5_Bga5EsOr7cp6bHWWxFKx6UHLu_Ix_m3AckC.
         r'([-\w.]+)'
         # End of string
diff --git a/tools/bisect-builds.py b/tools/bisect-builds.py
index 7187579..639c90b 100755
--- a/tools/bisect-builds.py
+++ b/tools/bisect-builds.py
@@ -641,6 +641,8 @@
 # pylint: disable=W0613
 def AskIsGoodBuild(rev, exit_status, stdout, stderr):
   """Asks the user whether build |rev| is good or bad."""
+  if exit_status:
+    print 'Chrome exit_status: %d. Use s to see output' % exit_status
   # Loop until we get a response that we can parse.
   while True:
     response = raw_input('Revision %s is '
diff --git a/tools/chrome_proxy/webdriver/quic.py b/tools/chrome_proxy/webdriver/quic.py
index bd57e11..91c123e 100644
--- a/tools/chrome_proxy/webdriver/quic.py
+++ b/tools/chrome_proxy/webdriver/quic.py
@@ -60,14 +60,5 @@
       self.assertLessEqual(1, proxy_status['count'])
       self.assertEqual(0, proxy_status['sum'])
 
-      # Navigate to one more page to ensure that established QUIC connection
-      # is used for the next request. Give 3 seconds extra headroom for the QUIC
-      # connection to be established.
-      time.sleep(3)
-      t.LoadURL('http://check.googlezip.net/test.html')
-      proxy_usage = t.GetHistogram('Net.QuicAlternativeProxy.Usage')
-      # Bucket ALTERNATIVE_PROXY_USAGE_NO_RACE should have at least onesample.
-      self.assertLessEqual(1, proxy_usage['buckets'][0]['count'])
-
 if __name__ == '__main__':
   IntegrationTest.RunAllTests()
diff --git a/tools/emacs/gn.el b/tools/emacs/gn.el
index b2137e0..1189bfa 100644
--- a/tools/emacs/gn.el
+++ b/tools/emacs/gn.el
@@ -86,16 +86,16 @@
 (defvar gn-font-lock-var-keywords
   '("all_dependent_configs" "allow_circular_includes_from" "arflags" "args"
     "asmflags" "assert_no_deps" "bundle_deps_filter" "bundle_executable_dir"
-    "bundle_plugins_dir" "bundle_resources_dir" "bundle_root_dir" "cflags"
-    "cflags_c" "cflags_cc" "cflags_objc" "cflags_objcc" "check_includes"
-    "code_signing_args" "code_signing_outputs" "code_signing_script"
-    "code_signing_sources" "complete_static_lib" "configs" "data" "data_deps"
-    "defines" "depfile" "deps" "include_dirs" "inputs" "ldflags" "lib_dirs"
-    "libs" "output_dir" "output_extension" "output_name"
-    "output_prefix_override" "outputs" "pool" "precompiled_header"
-    "precompiled_header_type" "precompiled_source" "product_type" "public"
-    "public_configs" "public_deps" "response_file_contents" "script" "sources"
-    "testonly" "visibility" "write_runtime_deps" "bundle_contents_dir"))
+    "bundle_resources_dir" "bundle_root_dir" "cflags" "cflags_c" "cflags_cc"
+    "cflags_objc" "cflags_objcc" "check_includes" "code_signing_args"
+    "code_signing_outputs" "code_signing_script" "code_signing_sources"
+    "complete_static_lib" "configs" "data" "data_deps" "defines" "depfile"
+    "deps" "include_dirs" "inputs" "ldflags" "lib_dirs" "libs" "output_dir"
+    "output_extension" "output_name" "output_prefix_override" "outputs" "pool"
+    "precompiled_header" "precompiled_header_type" "precompiled_source"
+    "product_type" "public" "public_configs" "public_deps"
+    "response_file_contents" "script" "sources" "testonly" "visibility"
+    "write_runtime_deps" "bundle_contents_dir"))
 
 (defconst gn-font-lock-keywords
   `((,(regexp-opt gn-font-lock-reserved-keywords 'words) .
diff --git a/tools/idl_parser/idl_parser.py b/tools/idl_parser/idl_parser.py
index 216c1901..9f79e5a 100755
--- a/tools/idl_parser/idl_parser.py
+++ b/tools/idl_parser/idl_parser.py
@@ -1127,6 +1127,9 @@
     self.tokens = lexer.KnownTokens()
     self.yaccobj = yacc.yacc(module=self, tabmodule=None, debug=debug,
                              optimize=0, write_tables=0)
+    # TODO: Make our code compatible with defaulted_states. Currently disabled
+    #       for compatibility.
+    self.yaccobj.defaulted_states = {}
     self.parse_debug = debug
     self.verbose = verbose
     self.mute_error = mute_error
diff --git a/tools/ipc_fuzzer/BUILD.gn b/tools/ipc_fuzzer/BUILD.gn
index 8abe247..d86fdf77 100644
--- a/tools/ipc_fuzzer/BUILD.gn
+++ b/tools/ipc_fuzzer/BUILD.gn
@@ -29,6 +29,7 @@
     testonly = true
     deps = [
       "//tools/ipc_fuzzer/fuzzer:ipc_fuzzer",
+      "//tools/ipc_fuzzer/get_accessible_interfaces:get_accessible_interfaces",
       "//tools/ipc_fuzzer/message_dump:ipc_message_dump",
       "//tools/ipc_fuzzer/message_replay:ipc_fuzzer_replay",
       "//tools/ipc_fuzzer/message_tools:ipc_message_list",
diff --git a/tools/ipc_fuzzer/DEPS b/tools/ipc_fuzzer/DEPS
index 1af0666..18a462e8 100644
--- a/tools/ipc_fuzzer/DEPS
+++ b/tools/ipc_fuzzer/DEPS
@@ -1,4 +1,7 @@
 include_rules = [
+  "+content/public/app",
+  "+chrome/app",
+  "+services/service_manager/public/cpp",
   "+third_party/re2",
   "+tools/ipc_fuzzer/message_lib",
 ]
diff --git a/tools/ipc_fuzzer/get_accessible_interfaces/BUILD.gn b/tools/ipc_fuzzer/get_accessible_interfaces/BUILD.gn
new file mode 100644
index 0000000..9fe6ae9d
--- /dev/null
+++ b/tools/ipc_fuzzer/get_accessible_interfaces/BUILD.gn
@@ -0,0 +1,11 @@
+executable("get_accessible_interfaces") {
+  sources = [
+    "get_accessible_interfaces.cc",
+  ]
+
+  deps = [
+    "//base",
+    "//chrome/app:chrome_service_manifests",
+    "//content/public/app:service_manifests",
+  ]
+}
diff --git a/tools/ipc_fuzzer/get_accessible_interfaces/get_accessible_interfaces.cc b/tools/ipc_fuzzer/get_accessible_interfaces/get_accessible_interfaces.cc
new file mode 100644
index 0000000..dc1617e
--- /dev/null
+++ b/tools/ipc_fuzzer/get_accessible_interfaces/get_accessible_interfaces.cc
@@ -0,0 +1,71 @@
+// Copyright 2019 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 <iostream>
+#include <string>
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/json/json_writer.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "chrome/app/chrome_content_browser_overlay_manifest.h"
+#include "content/public/app/content_browser_manifest.h"
+#include "services/service_manager/public/cpp/manifest.h"
+
+base::ListValue GetInterfacesForCapability(
+    const service_manager::Manifest::ExposedCapabilityMap& exposed_capabilities,
+    const std::string& capability) {
+  auto it = exposed_capabilities.find(capability);
+  if (it == exposed_capabilities.end()) {
+    return base::ListValue();
+  }
+
+  base::ListValue interface_names;
+  for (const auto& interface_name : it->second) {
+    interface_names.GetList().emplace_back(base::Value(interface_name));
+  }
+
+  return interface_names;
+}
+
+void PrintAccessibleInterfaces(const service_manager::Manifest& manifest,
+                               const std::string& capability) {
+  base::DictionaryValue interfaces;
+  base::ListValue exposed_capabilities =
+      GetInterfacesForCapability(manifest.exposed_capabilities, capability);
+  interfaces.SetKey("exposed_capabilities", std::move(exposed_capabilities));
+
+  for (const auto& entry : manifest.exposed_interface_filter_capabilities) {
+    base::ListValue interface_names =
+        GetInterfacesForCapability(entry.second, capability);
+    interfaces.SetPath({"exposed_interface_filter_capabilities", entry.first},
+                       std::move(interface_names));
+  }
+
+  std::string output;
+  base::JSONWriter::WriteWithOptions(
+      interfaces, base::JSONWriter::OPTIONS_PRETTY_PRINT, &output);
+  std::cout << output;
+}
+
+int main(int argc, const char** argv) {
+  base::AtExitManager at_exit;
+  base::CommandLine::Init(argc, argv);
+
+  service_manager::Manifest manifest = content::GetContentBrowserManifest();
+  manifest.Amend(GetChromeContentBrowserOverlayManifest());
+
+  auto args = base::CommandLine::ForCurrentProcess()->GetArgs();
+  for (const base::CommandLine::StringType& arg : args) {
+#if defined(OS_WIN)
+    PrintAccessibleInterfaces(manifest, base::UTF16ToASCII(arg));
+#else
+    PrintAccessibleInterfaces(manifest, arg);
+#endif
+  }
+
+  return 0;
+}
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index a949d77..14c6b88 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -940,6 +940,7 @@
     """
 
     android = 'target_os="android"' in vals['gn_args']
+    ios = 'target_os="ios"' in vals['gn_args']
     fuchsia = 'target_os="fuchsia"' in vals['gn_args']
     win = self.platform == 'win32' or 'target_os="win"' in vals['gn_args']
     possible_runtime_deps_rpaths = {}
@@ -961,8 +962,8 @@
         rpaths = [
             target + '.runtime_deps',
             'obj/%s.stamp.runtime_deps' % label.replace(':', '/')]
-      elif fuchsia:
-        # Only emit a runtime deps file for the group() target on Fuchsia.
+      elif ios or fuchsia:
+        # iOS and Fuchsia targets end up as groups.
         label = isolate_map[target]['label']
         rpaths = ['obj/%s.stamp.runtime_deps' % label.replace(':', '/')]
       elif (isolate_map[target]['type'] == 'script' or
@@ -1175,7 +1176,7 @@
     elif is_android and test_type != "script":
       cmdline = []
       if asan:
-        cmdline += [os.path.join('bin', 'run_with_asan')]
+        cmdline += [os.path.join('bin', 'run_with_asan'), '--']
       cmdline += [
           '../../testing/test_env.py',
           '../../build/android/test_wrapper/logdog_wrapper.py',
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index e807bc0..661496d 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -93,6 +93,7 @@
 
     'chromium.chrome': {
       'chromeos-amd64-generic-google-rel': 'official_cros_chrome_sdk',
+      'chromeos-betty-google-rel': 'official_cros_chrome_sdk',
       'linux-chromeos-google-rel': 'official_goma_chromeos_minimal_symbols',
       'linux-google-rel': 'official_goma',
       'mac-google-rel': 'official_goma',
@@ -366,16 +367,12 @@
       'Android FYI Release (Nexus 9)': 'gpu_tests_android_release_trybot_arm64',
       'Android FYI Release (NVIDIA Shield TV)': 'gpu_tests_android_release_trybot_arm64',
       'Android FYI Release (Pixel 2)': 'gpu_tests_android_release_trybot',
-      'Android FYI 32 Vk Release (Nexus 5X)': 'gpu_tests_android_vulkan_release_trybot',
       'Android FYI 32 Vk Release (Pixel 2)': 'gpu_tests_android_vulkan_release_trybot',
       'Android FYI 32 Vk Release (Pixel XL)': 'gpu_tests_android_vulkan_release_trybot',
-      'Android FYI 64 Vk Release (Nexus 5X)': 'gpu_tests_android_vulkan_release_trybot_arm64',
       'Android FYI 64 Vk Release (Pixel 2)': 'gpu_tests_android_vulkan_release_trybot_arm64',
       'Android FYI 64 Vk Release (Pixel XL)': 'gpu_tests_android_vulkan_release_trybot_arm64',
-      'Android FYI 32 dEQP Vk Release (Nexus 5X)': 'deqp_android_vulkan_release_trybot',
       'Android FYI 32 dEQP Vk Release (Pixel 2)': 'deqp_android_vulkan_release_trybot',
       'Android FYI 32 dEQP Vk Release (Pixel XL)': 'deqp_android_vulkan_release_trybot',
-      'Android FYI 64 dEQP Vk Release (Nexus 5X)': 'deqp_android_vulkan_release_trybot_arm64',
       'Android FYI 64 dEQP Vk Release (Pixel 2)': 'deqp_android_vulkan_release_trybot_arm64',
       'Android FYI 64 dEQP Vk Release (Pixel XL)': 'deqp_android_vulkan_release_trybot_arm64',
       'GPU FYI Linux Builder': 'gpu_fyi_tests_release_trybot',
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 3eacc95..8796f44 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -20322,6 +20322,7 @@
 </action>
 
 <action name="TabContextMenu_SendTabToSelf_Clicked">
+  <obsolete>Deprecated because of using histogram.</obsolete>
   <owner>jeffreycohen@chromium.org</owner>
   <owner>sebsg@chromium.org</owner>
   <description>
@@ -20331,6 +20332,7 @@
 </action>
 
 <action name="TabContextMenu_SendTabToSelf_Shown">
+  <obsolete>Deprecated because of using histogram.</obsolete>
   <owner>jeffreycohen@chromium.org</owner>
   <owner>sebsg@chromium.org</owner>
   <description>Self share option shows in the tab context menu.</description>
@@ -21081,6 +21083,7 @@
 </action>
 
 <action name="ViewContextMenu_SendTabToSelf_Clicked">
+  <obsolete>Deprecated because of using histogram.</obsolete>
   <owner>jeffreycohen@chromium.org</owner>
   <owner>sebsg@chromium.org</owner>
   <description>
@@ -21090,6 +21093,7 @@
 </action>
 
 <action name="ViewContextMenu_SendTabToSelf_Shown">
+  <obsolete>Deprecated because of using histogram.</obsolete>
   <owner>jeffreycohen@chromium.org</owner>
   <owner>sebsg@chromium.org</owner>
   <description>Self share option shows in the view context menu.</description>
diff --git a/tools/metrics/common/models.py b/tools/metrics/common/models.py
index f923f8f..56d84c5 100644
--- a/tools/metrics/common/models.py
+++ b/tools/metrics/common/models.py
@@ -269,9 +269,10 @@
       if node.hasAttribute(attr):
         obj[attr] = attr_type(node.getAttribute(attr))
       if attr_re is not None:
-        if not re.match(attr_re, obj[attr]):
+        attr_val = obj.get(attr, '')
+        if not re.match(attr_re, attr_val):
           raise ValueError('%s "%s" does not match regex "%s"' %
-                           (attr, obj[attr], attr_re))
+                           (attr, attr_val, attr_re))
 
     if self.text_attribute and node.firstChild:
       obj[self.text_attribute] = node.firstChild.nodeValue
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 3ffaa9a..b5cd068 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -9142,7 +9142,7 @@
   <int value="24" label="Add to contacts"/>
   <int value="25" label="Spellcheck suggestion"/>
   <int value="26" label="Add to dictionary"/>
-  <int value="27" label="Context spelling toggle (Ask Google for suggestions)"/>
+  <int value="27" label="Context spelling toggle (Use enhanced spell check)"/>
   <int value="28" label="Cut text"/>
   <int value="29" label="Paste text"/>
   <int value="30" label="Call"/>
@@ -11723,6 +11723,15 @@
   <int value="6" label="kImageBMP"/>
 </enum>
 
+<enum name="DecodeSwapChainNotUsedReason">
+  <int value="0" label="Software frame"/>
+  <int value="1" label="NV12 overlays not supported"/>
+  <int value="2" label="Failed to present decode swap chain"/>
+  <int value="3" label="Texture is not a decoder resource"/>
+  <int value="4" label="Texture is a shared resource"/>
+  <int value="5" label="Transform is incompatible with overlays"/>
+</enum>
+
 <enum name="DefaultBrowserAsyncAttemptResult">
   <obsolete>
     Deprecated 2015/11. Renamed to SetDefaultAttemptResult.
@@ -12132,7 +12141,7 @@
   <int value="7" label="Profile Signin Confirmation (Link Chrome Data)"/>
   <int value="8" label="Hung Renderer"/>
   <int value="9" label="Session Crashed"/>
-  <int value="10" label="Confirm Bubble (Ask Google for Suggestions)"/>
+  <int value="10" label="Confirm Bubble (Use enhanced spell check)"/>
   <int value="11" label="Update Recommended"/>
   <int value="12" label="Crypto Password"/>
   <int value="13" label="Safe Browsing Download Feedback"/>
@@ -18935,6 +18944,7 @@
   <int value="1325" label="AUTOTESTPRIVATE_SETSHELFAUTOHIDEBEHAVIOR"/>
   <int value="1326" label="AUTOTESTPRIVATE_EXPORTCROSTINI"/>
   <int value="1327" label="AUTOTESTPRIVATE_IMPORTCROSTINI"/>
+  <int value="1328" label="ACCESSIBILITY_PRIVATE_SETVIRTUALKEYBOARDVISIBLE"/>
 </enum>
 
 <enum name="ExtensionIconState">
@@ -28665,6 +28675,13 @@
   <int value="11" label="CountLow RangeChecksum BucketOrder"/>
 </enum>
 
+<enum name="IncrementalDecodeNeeded">
+  <int value="0" label="JPEGIncrementalDecodeNeeded"/>
+  <int value="1" label="JPEGAllDataReceivedInitially"/>
+  <int value="2" label="WebPIncrementalDecodeNeeded"/>
+  <int value="3" label="WebPAllDataReceivedInitially"/>
+</enum>
+
 <enum name="IndexedDatabaseMethods">
   <obsolete>
     Deprecated as of July 2018.
@@ -28847,6 +28864,20 @@
   <int value="7" label="ARC"/>
 </enum>
 
+<enum name="InputMethodDecoderEvent">
+  <int value="3" label="WordCommitted"/>
+  <int value="4" label="SuggestionPickedManually"/>
+  <int value="5" label="TextDeleteBackspace"/>
+  <int value="6" label="WordDeleteBackspace"/>
+  <int value="7" label="RevertAutoCorrect"/>
+  <int value="11" label="WordAutoCorrection"/>
+  <int value="22" label="PredictionPicked"/>
+  <int value="25" label="WordDeleted"/>
+  <int value="26" label="WordEdited"/>
+  <int value="103" label="SpaceCommitted"/>
+  <int value="104" label="SpaceDeleted"/>
+</enum>
+
 <enum name="InputMethodID">
   <int value="109700" label="xkb:am:phonetic:arm">
     Armenian Phonetic keyboard
@@ -31910,17 +31941,6 @@
 </enum>
 
 <enum name="LoginCustomFlags">
-  <summary>Chrome flags that lead to Chrome restart on Chrome OS.</summary>
-<!--
-Values in LoginCustomFlags are:  value=(uint32_t)MD5(label).
-
-See "Flag Histograms" in README.md for information about how to update this
-section.
-
-Don't remove entries when removing a flag; they are still used to decode data
-from previous Chrome versions.
--->
-
   <int value="-2146832142" label="SyncPseudoUSSSearchEngines:enabled"/>
   <int value="-2146613579" label="V8Future:disabled"/>
   <int value="-2145472146" label="OfflinePagesResourceBasedSnapshot:disabled"/>
@@ -32048,6 +32068,7 @@
   <int value="-1971086581" label="print-scaling"/>
   <int value="-1965587041" label="omnibox-tab-switch-suggestions"/>
   <int value="-1964261747" label="WebVrVsyncAlign:disabled"/>
+  LoginCustomFlags
   <int value="-1963427770" label="EmojiHandwritingVoiceInput:disabled"/>
   <int value="-1963402827" label="enable-topchrome-md"/>
   <int value="-1962749353" label="SimplifiedNTP:enabled"/>
@@ -32075,6 +32096,7 @@
   <int value="-1943313820" label="SystemKeyboardLock:disabled"/>
   <int value="-1942730618" label="WebAuthenticationTouchId:disabled"/>
   <int value="-1942419166" label="SyncPseudoUSSApps:disabled"/>
+  <int value="-1942057472" label="ExperimentalAccessibilityLabels:enabled"/>
   <int value="-1941852572" label="floating-virtual-keyboard"/>
   <int value="-1940806558" label="enable-syncfs-directory-operation"/>
   <int value="-1940377152" label="MacRTL:enabled"/>
@@ -32644,6 +32666,18 @@
       label="SupervisedUserCommittedInterstitials:enabled"/>
   <int value="-1096595907" label="disable-new-virtual-keyboard-behavior"/>
   <int value="-1095947169" label="ModalPermissionDialogView:disabled"/>
+  <summary>Chrome flags that lead to Chrome restart on Chrome OS.</summary>
+<!--
+Values in LoginCustomFlags are:  value=(uint32_t)MD5(label).
+
+See "Flag Histograms" in README.md for information about how to update this
+section.
+
+Don't remove entries when removing a flag; they are still used to decode data
+from previous Chrome versions.
+-->
+
+  <int value="-1086728979" label="kids-management-url-classification:enabled"/>
   <int value="-1085492638" label="FetchKeepaliveTimeoutSetting:enabled"/>
   <int value="-1084855234" label="UnfilteredBluetoothDevices:disabled"/>
   <int value="-1084055006" label="disable-web-notification-custom-layouts"/>
@@ -33270,6 +33304,7 @@
   <int value="-56235502" label="WebRtcHideLocalIpsWithMdns:enabled"/>
   <int value="-55944747" label="disable-child-account-detection"/>
   <int value="-55592344" label="SyncPseudoUSSDictionary:disabled"/>
+  <int value="-54796636" label="kids-management-url-classification:disabled"/>
   <int value="-52483823" label="disable-new-video-renderer"/>
   <int value="-52241456" label="enable-single-click-autofill"/>
   <int value="-51567065" label="EnableFeedbackPanel:disabled"/>
@@ -33632,6 +33667,7 @@
   <int value="564522013" label="Av1Decoder:disabled"/>
   <int value="565406673" label="EnableVirtualKeyboardMdUi:enabled"/>
   <int value="567368307" label="enable-experimental-canvas-features"/>
+  <int value="575380532" label="ExperimentalAccessibilityLabels:disabled"/>
   <int value="575394365" label="AndroidPaymentApps:disabled"/>
   <int value="576701073" label="WebPaymentsJustInTimePaymentApp:disabled"/>
   <int value="576878329" label="enable-background-blur"/>
@@ -33701,6 +33737,7 @@
   <int value="656864700" label="FillOnAccountSelectHttp:disabled"/>
   <int value="659086147" label="OverlayScrollbarFlashWhenMouseEnter:enabled"/>
   <int value="663027937" label="NewTabPageCustomLinks:enabled"/>
+  <int value="663294302" label="ForceUseAPDownloadProtection:disabled"/>
   <int value="664363259" label="SiteCharacteristicsDatabase:enabled"/>
   <int value="664591021" label="EnableContinueReading:enabled"/>
   <int value="665409384"
@@ -33816,7 +33853,6 @@
   <int value="841276069" label="ChromeHomeDoodle:disabled"/>
   <int value="841343322" label="disable-new-korean-ime"/>
   <int value="841779535" label="password-export:enabled"/>
-  <int value="841935705" label="UseAPDownloadProtection:enabled"/>
   <int value="842432903" label="CaptureThumbnailOnNavigatingAway:enabled"/>
   <int value="842789526" label="CloudPrinterHandler:disabled"/>
   <int value="843896452" label="UserActivationV2:enabled"/>
@@ -34056,6 +34092,7 @@
   <int value="1226624874" label="Mus:disabled"/>
   <int value="1228115769" label="SiteCharacteristicsDatabase:disabled"/>
   <int value="1229299518" label="SingleTabMode:disabled"/>
+  <int value="1234601252" label="ForceUseAPDownloadProtection:enabled"/>
   <int value="1235800887" label="V8Ignition:enabled"/>
   <int value="1235940786" label="ChromeHomePersistentIph:enabled"/>
   <int value="1237297772" label="no-pings"/>
@@ -34110,7 +34147,6 @@
   <int value="1304636193" label="ArcEnableUnifiedAudioFocus:enabled"/>
   <int value="1307003774" label="AutofillEnableCompanyName:disabled"/>
   <int value="1308537004" label="force-pnacl-subzero"/>
-  <int value="1311802125" label="UseAPDownloadProtection:disabled"/>
   <int value="1311860720" label="ChromeHomeNtpRedesign:disabled"/>
   <int value="1312025202" label="NTPOfflinePageSuggestions:disabled"/>
   <int value="1314681756" label="NoStatePrefetch:disabled"/>
@@ -34168,6 +34204,7 @@
   <int value="1386300777"
       label="OmniboxUIExperimentHideSuggestionUrlTrivialSubdomains:disabled"/>
   <int value="1389729816" label="data-reduction-proxy-lo-fi"/>
+  <int value="1392935139" label="KidsManagementUrlClassification:enabled"/>
   <int value="1393500952" label="EnableVirtualKeyboardUkm:disabled"/>
   <int value="1393722373" label="SaveEditedPDFForm:disabled"/>
   <int value="1397069250" label="NetworkService:disabled"/>
@@ -34572,6 +34609,7 @@
   <int value="2015547864" label="NetworkServiceInProcess:enabled"/>
   <int value="2018386804" label="IPH_ReopenTab:disabled"/>
   <int value="2020107447" label="AndroidPayIntegrationV1:enabled"/>
+  <int value="2024172900" label="KidsManagementUrlClassification:disabled"/>
   <int value="2032558514"
       label="RemoveUsageOfDeprecatedGaiaSigninEndpoint:enabled"/>
   <int value="2034198538" label="TabHoverCards:enabled"/>
@@ -49339,17 +49377,17 @@
   <int value="5" label="Sent, no form id"/>
 </enum>
 
-<enum name="SendTabToSelf">
-  <int value="0" label="SendTabToSelf menu item is shown."/>
-  <int value="1" label="SendTabToSelf menu item is clicked."/>
-</enum>
-
 <enum name="SendTabToSelfAddEntryStatus">
   <int value="0" label="Success"/>
   <int value="1" label="Failure"/>
   <int value="2" label="Duplicate"/>
 </enum>
 
+<enum name="SendTabToSelfClickResult">
+  <int value="0" label="SendTabToSelf menu item is shown."/>
+  <int value="1" label="SendTabToSelf menu item is clicked."/>
+</enum>
+
 <enum name="ServiceProcessEventType">
   <int value="0" label="SERVICE_EVENT_INITIALIZE"/>
   <int value="1" label="SERVICE_EVENT_ENABLED_ON_LAUNCH"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 52fe950fc..5763322 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -11740,6 +11740,20 @@
   </summary>
 </histogram>
 
+<histogram name="Blink.ImageDecoders.IncrementalDecodeNeeded"
+    enum="IncrementalDecodeNeeded" expires_after="2020-4-2">
+  <owner>mbarowsky@chromium.org</owner>
+  <owner>andrescj@chromium.org</owner>
+  <summary>
+    For JPEG and WebP images, whether all image data has been received before
+    decoding begins or whether we are still receiving data and will need to send
+    partial image data to the decoder and pause/resume decoding until complete.
+
+    It is emitted when the DeferredImageDecoder is about to create the first
+    DecodingImageGenerator for an image.
+  </summary>
+</histogram>
+
 <histogram name="Blink.ImageDecoders.Jpeg.Area" units="pixels">
   <owner>andrescj@chromium.org</owner>
   <summary>
@@ -15251,7 +15265,7 @@
 </histogram>
 
 <histogram name="ChildProcess.HungRendererCause"
-    enum="RendererUnresponsiveCause" expires_after="M73">
+    enum="RendererUnresponsiveCause" expires_after="M74">
   <owner>cmumford@chromium.org</owner>
   <summary>
     What the browser was waiting for from the renderer when it was reported as
@@ -41131,6 +41145,16 @@
   </summary>
 </histogram>
 
+<histogram name="GPU.DirectComposition.DecodeSwapChainNotUsedReason"
+    enum="DecodeSwapChainNotUsedReason" expires_after="M76">
+  <owner>sunnyps@chromium.org</owner>
+  <owner>zmo@chromium.org</owner>
+  <summary>
+    The reason decode swap chain wasn't used to present a video frame. Recorded
+    on each present. See also GPU.DirectComposition.VideoPresentationMode.
+  </summary>
+</histogram>
+
 <histogram name="GPU.DirectComposition.DecodeSwapChainPresentResult"
     enum="Hresult" expires_after="M75">
   <obsolete>
@@ -41159,6 +41183,9 @@
 
 <histogram name="GPU.DirectComposition.DecodeSwapChainUsed"
     enum="BooleanDecodeSwapChainUsed" expires_after="M76">
+  <obsolete>
+    Deprecated 4/2019. Replaced by GPU.DirectComposition.VideoPresentationMode.
+  </obsolete>
   <owner>sunnyps@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
@@ -42503,7 +42530,7 @@
 </histogram>
 
 <histogram name="Histogram.TooManyBuckets.1000" enum="HistogramNameHash"
-    expires_after="M75">
+    expires_after="M78">
   <owner>asvitkine@chromium.org</owner>
   <owner>bcwhite@chromium.org</owner>
   <summary>
@@ -44485,6 +44512,15 @@
   </summary>
 </histogram>
 
+<histogram name="InputMethod.VirtualKeyboard.DecoderEvent"
+    enum="InputMethodDecoderEvent" expires_after="2019-08-01">
+  <owner>essential-inputs-team@google.com</owner>
+  <summary>
+    Chrome OS histogram that counts events from the decoder triggered by the
+    virtual keyboard.
+  </summary>
+</histogram>
+
 <histogram name="InputMethod.VirtualKeyboard.Duration" units="seconds">
   <owner>essential-inputs-team@google.com</owner>
   <summary>How long the virtual keyboard was visible.</summary>
@@ -78649,6 +78685,11 @@
     The type can be misleading. For example if the user typed 'http:/', it gets
     marked as a query because it cannot be opened as a URL even though the user
     probably wanted and selected a URL from the list of suggestions.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -78661,6 +78702,11 @@
     this histogram because both of these are referred to as paste-and-go in the
     code.) These typically involve right-clicking in the omnibox and selecting
     that option from the dropdown.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -78674,6 +78720,11 @@
     because paste-and-search/paste-and-go actions ignore the current content of
     the omnibox dropdown (if it is open) when they happen, we pretend the
     dropdown is closed when logging these.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -78683,13 +78734,25 @@
   <summary>
     Whether the user deleted text immediately before selecting an omnibox
     suggestion. This is usually the result of pressing backspace or delete.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
 <histogram name="Omnibox.NumEvents" enum="UsedOmnibox">
   <owner>mpearson@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
-  <summary>The number of times users used the omnibox to go somewhere.</summary>
+  <summary>
+    The number of times users used the omnibox to go somewhere.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
+  </summary>
 </histogram>
 
 <histogram name="Omnibox.NumTypedTerms" units="terms">
@@ -78699,6 +78762,11 @@
     The number of terms in the text the user entered in the omnibox when they
     used the omnibox to go somewhere. Terms are defined by splitting on
     whitespace. All values larger than 6 are recorded in bucket 6.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -78706,7 +78774,13 @@
   <owner>mpearson@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
   <summary>
-    What the user was viewing when the user used the omnibox to go somewhere.
+    The type of page the user was viewing when the user used the omnibox to go
+    somewhere.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -78959,6 +79033,11 @@
     second item in the dropdown will be recorded as bucket 1. The selected
     position is always set to 0 when the popup is closed at the time of
     navigation or if the user did a paste-and-search or paste-and-go action.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -79044,6 +79123,11 @@
     Omnibox.SuggestionUsed.OfferedTabMatch. Only recent versions of the browser
     send the metric. Therefore, other metrics may include datapoints not covered
     by this metric (unless one narrows the data by version.)
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -79053,6 +79137,11 @@
   <summary>
     The provider of the suggestion the user selected when the user used the
     omnibox to go somewhere.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -79064,6 +79153,11 @@
     The provider of the suggestion the user selected when the user used the
     omnibox to go somewhere, only for omnibox interactions that start in the
     specified page context:
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -79074,6 +79168,11 @@
   <summary>
     The provider and result type of the suggestion the user selected when the
     user used the omnibox to go somewhere.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -79086,6 +79185,11 @@
     The provider and result type of the suggestion the user selected when the
     user used the omnibox to go somewhere, only for omnibox interactions that
     start in the specified page context:
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -79155,6 +79259,11 @@
   <summary>
     The rough type of the suggestion the user selected when the user used the
     omnibox to go somewhere.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -79166,6 +79275,11 @@
     The rough type of the suggestion the user selected when the user used the
     omnibox to go somewhere, only for omnibox interactions that start in the
     specified page context:
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -79190,6 +79304,11 @@
     This metric should be stricly less than
     Omnibox.SuggestionUsed.OfferedTabMatch, and is typically used to discover
     the percentage of offered tab matches that the user accepts.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -79300,6 +79419,11 @@
     omnibox to go somewhere. Switched on March 27 2018 from an bucketing where
     every typed length is emitted exactly (up to 500) to ordinary exponential
     bucketing.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -79313,6 +79437,11 @@
     (thus seeing the current web page's URL again), then wrote in the omnibox
     again, this duration starts from the time of the second series of
     modification.
+
+    In M-74 and earlier, this was only recorded if the user had no incognito
+    windows open. In M-75 and later, it records all omnibox interactions
+    regardless, in order to be consistent with how user actions and histograms
+    are handled.
   </summary>
 </histogram>
 
@@ -79458,8 +79587,11 @@
   </summary>
 </histogram>
 
-<histogram name="OmniboxViewViews.SendTabToSelf" enum="SendTabToSelf"
-    expires_after="M78">
+<histogram name="OmniboxViewViews.SendTabToSelf"
+    enum="SendTabToSelfClickResult" expires_after="M78">
+  <obsolete>
+    Obsolete because of using suffixes.
+  </obsolete>
   <owner>jeffreycohen@chromium.org</owner>
   <owner>sebsg@chromium.org</owner>
   <summary>
@@ -80827,6 +80959,9 @@
 
 <histogram name="PageLoad.Clients.Ads.Resources.Bytes.Unfinished" units="KB"
     expires_after="2019-09-05">
+  <obsolete>
+    Deprecated 04/2019 in favor of PageLoad.Experimental.Bytes.Unfinished.
+  </obsolete>
   <owner>jkarlin@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <summary>
@@ -81714,6 +81849,18 @@
   </summary>
 </histogram>
 
+<histogram name="PageLoad.Experimental.Bytes.Unfinished" units="KB"
+    expires_after="2020-04-05">
+  <owner>johnidel@chromium.org</owner>
+  <owner>jkarlin@chromium.org</owner>
+  <summary>
+    Total number of network bytes that were used to load resources that did not
+    finish loading on the page (e.g. ongoing video). This includes resource
+    loads that were canceled or resource loads that were ongoing when the page
+    was destroyed.
+  </summary>
+</histogram>
+
 <histogram name="PageLoad.Experimental.Cache.RequestPercent.ParseStop"
     units="%">
   <obsolete>
@@ -107519,6 +107666,16 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="SendTabToSelf.ClickResult"
+    enum="SendTabToSelfClickResult" expires_after="M78">
+  <owner>jeffreycohen@chromium.org</owner>
+  <owner>sebsg@chromium.org</owner>
+  <owner>tgupta@chromium.org</owner>
+  <summary>
+    Record whether the user has clicked the item when it is shown.
+  </summary>
+</histogram>
+
 <histogram name="SendTabToSelf.Sync.AddEntryStatus"
     enum="SendTabToSelfAddEntryStatus" expires_after="M78">
   <owner>jeffreycohen@chromium.org</owner>
@@ -130849,6 +131006,13 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="WebApk.Uninstall" enum="BooleanHit"
+    expires_after="2020-01-01">
+  <owner>pkotwicz@chromium.org</owner>
+  <owner>yfriedman@chromium.org</owner>
+  <summary>Records that a WebAPK was uninstalled.</summary>
+</histogram>
+
 <histogram name="WebApk.Update.GooglePlayUpdateResult"
     enum="WebApkGooglePlayInstallResult">
   <owner>hanxi@chromium.org</owner>
@@ -149198,6 +149362,18 @@
   <affected-histogram name="Security.TimeOnPage2"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="SendTabToSelfEntryPoint" separator="."
+    ordering="prefix">
+  <owner>jeffreycohen@chromium.org</owner>
+  <owner>sebsg@chromium.org</owner>
+  <owner>tgupta@chromium.org</owner>
+  <suffix name="ContentMenu" label="Option shown in the content context menu"/>
+  <suffix name="LinkMenu" label="Option shown in the link context menu"/>
+  <suffix name="OmniboxMenu" label="Option shown in the omnibox context menu"/>
+  <suffix name="TabMenu" label="Option shown in the tab context menu"/>
+  <affected-histogram name="SendTabToSelf.ClickResult"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="ServiceWorker.ContextRequestType" separator=".">
   <obsolete>
     The affected histogram is obsolete.
@@ -151306,6 +151482,7 @@
   <suffix name="Other" label="Installed by other sources"/>
   <affected-histogram name="WebApk.Session.TotalDuration2"/>
   <affected-histogram name="WebApk.ShellApkVersion2"/>
+  <affected-histogram name="WebApk.Uninstall"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="WebApkType" separator=".">
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 36e5b1d7..5d9c65b1 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -3565,6 +3565,14 @@
     <summary>
       Measure of total private memory consumed by process.
     </summary>
+    <aggregation>
+      <history>
+        <index fields="metrics.ProcessType"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="PrivateSwapFootprint">
     <summary>
@@ -3578,6 +3586,13 @@
       services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom)
       of associated metrics.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <enumeration export="False"/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="Resident">
     <summary>
diff --git a/tools/metrics/ukm/ukm_model.py b/tools/metrics/ukm/ukm_model.py
index dbebeed..a363d5c9 100644
--- a/tools/metrics/ukm/ukm_model.py
+++ b/tools/metrics/ukm/ukm_model.py
@@ -18,13 +18,16 @@
 
 _ENUMERATION_TYPE = models.ObjectNodeType(
     'enumeration',
-    attributes=[],
+    attributes=[
+      ('export', unicode, r'^(?i)(|true|false)$'),
+    ],
     single_line=True)
 
 _QUANTILES_TYPE = models.ObjectNodeType(
     'quantiles',
     attributes=[
       ('type', unicode, None),
+      ('export', unicode, r'^(?i)(|true|false)$'),
     ],
     single_line=True)
 
@@ -76,7 +79,8 @@
     alphabetization=[('metric', _LOWERCASE_NAME_FN)],
     attributes=[
       ('name', unicode, r'^[A-Za-z0-9.]+$'),
-      ('singular', bool, None)],
+      ('singular', unicode, r'^(?i)(|true|false)$'),
+    ],
     extra_newlines=(1, 1, 1),
     children=[
         models.ChildType('obsolete', _OBSOLETE_TYPE, multiple=False),
diff --git a/tools/metrics/ukm/ukm_model_test.py b/tools/metrics/ukm/ukm_model_test.py
index a0274235..d681a49b 100755
--- a/tools/metrics/ukm/ukm_model_test.py
+++ b/tools/metrics/ukm/ukm_model_test.py
@@ -34,7 +34,16 @@
       </history>
     </aggregation>
   </metric>
-  <metric name="Metric2"/>
+  <metric name="Metric2">
+    <aggregation>
+      <history>
+        <statistics>
+          <enumeration export="False"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
+  <metric name="Metric3"/>
 </event>
 
 </ukm-configuration>
diff --git a/tools/perf/contrib/vr_benchmarks/BUILD.gn b/tools/perf/contrib/vr_benchmarks/BUILD.gn
index fef976f..e4f682d 100644
--- a/tools/perf/contrib/vr_benchmarks/BUILD.gn
+++ b/tools/perf/contrib/vr_benchmarks/BUILD.gn
@@ -37,7 +37,10 @@
       "//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk",
     ]
 
-    data_deps += [ "//chrome/android:vr_nfc_simulator_apk" ]
+    data_deps += [
+      "//chrome/android:chrome_modern_public_bundle",
+      "//chrome/android:vr_nfc_simulator_apk",
+    ]
 
     # We'll only ever use the assets if it's a Chrome-branded build. We don't have
     # a way of checking whether the files are actually present to copy, but the
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index bbae3a4..d9e5d022 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -215,6 +215,7 @@
 crbug.com/910207 [ Nexus_5X ] rendering.mobile/yahoo_news_2018 [ Skip ]
 crbug.com/901526 [ All ] rendering.mobile/microsoft_fireflies [ Skip ]
 crbug.com/924400 [ Nexus6_Webview ] rendering.mobile/canvas_animation_no_clear [ Skip ]
+crbug.com/949366 [ Nexus5X_Webview ] rendering.mobile/google_news_mobile_2018 [ Skip ]
 
 # Benchmark: rasterize_and_record_micro.top_25
 crbug.com/764543 [ All ] rasterize_and_record_micro.top_25/file://static_top_25/wikipedia.html [ Skip ]
@@ -231,6 +232,8 @@
 # crbug.com/894744 [ Android ] startup.mobile/intent:coldish:bbc [ Skip ]
 # crbug.com/894744 [ Android ] startup.mobile/intent:warm:bbc [ Skip ]
 # crbug.com/894744 [ Android ] startup.mobile/cct:coldish:bbc [ Skip ]
+crbug.com/948789 [ Nexus_5 ] startup.mobile/maps_pwa:with_http_cache [ Skip ]
+crbug.com/948789 [ Nexus_5X ] startup.mobile/maps_pwa:with_http_cache [ Skip ]
 
 # Benchmark: system_health.common_desktop
 crbug.com/773084 [ Mac ] system_health.common_desktop/browse:tools:maps [ Skip ]
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc
index 43e4045a..5798985 100644
--- a/ui/android/delegated_frame_host_android.cc
+++ b/ui/android/delegated_frame_host_android.cc
@@ -307,6 +307,11 @@
   if (!enable_surface_synchronization_)
     return;
 
+  // We should never attempt to embed an invalid surface. Catch this here to
+  // track down the root cause. Otherwise we will have vague crashes later on
+  // at serialization time.
+  CHECK(new_local_surface_id.is_valid());
+
   local_surface_id_ = new_local_surface_id;
   surface_size_in_pixels_ = new_size_in_pixels;
 
diff --git a/ui/android/java/res/color/blue_when_enabled.xml b/ui/android/java/res/color/blue_when_enabled.xml
index 7644e5d..8257553 100644
--- a/ui/android/java/res/color/blue_when_enabled.xml
+++ b/ui/android/java/res/color/blue_when_enabled.xml
@@ -4,7 +4,6 @@
      found in the LICENSE file.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="@dimen/default_disabled_alpha"
-        android:color="@color/modern_grey_800" android:state_enabled="false" />
+    <item android:color="@color/disabled_text_color_link" android:state_enabled="false" />
     <item android:color="@color/default_text_color_link"/>
 </selector>
diff --git a/ui/android/java/res/values/colors.xml b/ui/android/java/res/values/colors.xml
index a90f1a5e..d8ed3ff 100644
--- a/ui/android/java/res/values/colors.xml
+++ b/ui/android/java/res/values/colors.xml
@@ -15,6 +15,7 @@
     <!-- Text color for clickable text. -->
     <color name="default_text_color_link">@color/modern_blue_600</color>
     <color name="disabled_text_color">@color/black_alpha_38</color>
+    <color name="disabled_text_color_link">@color/modern_grey_800_alpha_38</color>
     <color name="error_text_color">@color/default_red</color>
 
     <!-- Common icon colors for drawables. -->
diff --git a/ui/android/java/res_night/values-night/colors.xml b/ui/android/java/res_night/values-night/colors.xml
index 169f143..ab7b09d 100644
--- a/ui/android/java/res_night/values-night/colors.xml
+++ b/ui/android/java/res_night/values-night/colors.xml
@@ -11,6 +11,7 @@
     <color name="default_text_color_blue">@color/modern_blue_300</color>
     <color name="default_text_color_link">@color/modern_blue_300</color>
     <color name="disabled_text_color">@color/white_alpha_38</color>
+    <color name="disabled_text_color_link">@color/modern_grey_300_alpha_38</color>
 
     <!-- Common icon colors for drawables. -->
     <color name="default_icon_color">@color/default_icon_color_white</color>
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 141af6a..38b56afe 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -187,6 +187,7 @@
     "//skia",
     "//ui/base",
     "//ui/base/clipboard",
+    "//ui/base/ime/init",
     "//ui/display",
     "//ui/events",
     "//ui/events:dom_keyboard_layout",
@@ -317,7 +318,7 @@
     "//skia",
     "//testing/gtest",
     "//ui/base:test_support",
-    "//ui/base/ime",
+    "//ui/base/ime/init",
     "//ui/compositor:test_support",
     "//ui/display",
     "//ui/display/manager",
@@ -368,7 +369,7 @@
     "//skia",
     "//third_party/icu",
     "//ui/base",
-    "//ui/base/ime",
+    "//ui/base/ime/init",
     "//ui/compositor",
     "//ui/compositor:test_support",
     "//ui/display",
@@ -462,7 +463,7 @@
       "//base/test:test_support",
       "//net",
       "//testing/gtest",
-      "//ui/base/ime:ime",
+      "//ui/base/ime/init",
       "//ui/display:display",
       "//ui/gfx",
       "//ui/gfx/geometry",
diff --git a/ui/aura/demo/demo_main.cc b/ui/aura/demo/demo_main.cc
index dcdd568..76c1c17 100644
--- a/ui/aura/demo/demo_main.cc
+++ b/ui/aura/demo/demo_main.cc
@@ -28,7 +28,7 @@
 #include "ui/aura/window_delegate.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/hit_test.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/compositor/paint_recorder.h"
 #include "ui/compositor/test/in_process_context_factory.h"
 #include "ui/events/event.h"
diff --git a/ui/aura/mus/mus_context_factory.cc b/ui/aura/mus/mus_context_factory.cc
index 26c1b8f..5f5b2cc 100644
--- a/ui/aura/mus/mus_context_factory.cc
+++ b/ui/aura/mus/mus_context_factory.cc
@@ -12,8 +12,6 @@
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "services/ws/public/cpp/gpu/command_buffer_metrics.h"
 #include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
-#include "services/ws/public/cpp/gpu/gpu.h"
-#include "services/ws/public/cpp/gpu/shared_worker_context_provider_factory.h"
 #include "ui/aura/mus/window_port_mus.h"
 #include "ui/aura/window_tree_host.h"
 
@@ -180,6 +178,14 @@
   return main_context_provider_;
 }
 
+scoped_refptr<viz::RasterContextProvider>
+MusContextFactory::SharedMainThreadRasterContextProvider() {
+  // Exo is currently the only client requesting this context provider.
+  // Exo does not request this context in MUS.
+  NOTREACHED();
+  return nullptr;
+}
+
 void MusContextFactory::RemoveCompositor(ui::Compositor* compositor) {
   // No per compositor state is kept so there is nothing to do here.
 }
diff --git a/ui/aura/mus/mus_context_factory.h b/ui/aura/mus/mus_context_factory.h
index 19e9d7cb..98e9f37 100644
--- a/ui/aura/mus/mus_context_factory.h
+++ b/ui/aura/mus/mus_context_factory.h
@@ -52,6 +52,10 @@
       base::WeakPtr<ui::Compositor> compositor) override;
   scoped_refptr<viz::ContextProvider> SharedMainThreadContextProvider()
       override;
+
+  scoped_refptr<viz::RasterContextProvider>
+  SharedMainThreadRasterContextProvider() override;
+
   void RemoveCompositor(ui::Compositor* compositor) override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc
index 838902b..c6a5c47 100644
--- a/ui/aura/mus/window_tree_client.cc
+++ b/ui/aura/mus/window_tree_client.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include <stack>
 #include <string>
 #include <utility>
 #include <vector>
@@ -1643,7 +1644,19 @@
   WindowMus* window = GetWindowByServerId(window_id);
   if (!window)
     return;
-  window->GetWindow()->CleanupGestureState();
+  // Do not call Window::CleanupGestureState(); it creates extra
+  // ET_TOUCH_CANCELLED events unexpectedly and causes some troubles. Instead,
+  // here the code simply cleans up the state within the gesture recognizer. See
+  // https://crbug.com/948420.
+  std::stack<Window*> ws;
+  ws.push(window->GetWindow());
+  while (!ws.empty()) {
+    Window* w = ws.top();
+    ws.pop();
+    w->env()->gesture_recognizer()->CleanupStateForConsumer(w);
+    for (auto* c : w->children())
+      ws.push(c);
+  }
 }
 
 void WindowTreeClient::OnWindowResizeLoopStarted(ws::Id window_id) {
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc
index 37befd7..36c68b618 100644
--- a/ui/aura/mus/window_tree_client_unittest.cc
+++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -63,6 +63,7 @@
 #include "ui/events/event.h"
 #include "ui/events/event_observer.h"
 #include "ui/events/event_utils.h"
+#include "ui/events/gestures/gesture_recognizer.h"
 #include "ui/events/test/test_event_handler.h"
 #include "ui/gfx/geometry/dip_util.h"
 #include "ui/gfx/geometry/rect.h"
@@ -1468,6 +1469,35 @@
   top_level->env()->RemoveEventObserver(&test_event_observer);
 }
 
+#if defined(OS_CHROMEOS)
+// The handling of gesture recognition behavior makes sense only in ChromeOS.
+TEST_F(WindowTreeClientTest, CleanupGestureState) {
+  auto top_level = CreateTopLevel();
+  test::EventCountDelegate delegate;
+  Window window(&delegate);
+  window.Init(ui::LAYER_NOT_DRAWN);
+  top_level->host->window()->AddChild(&window);
+  window.SetBounds(gfx::Rect(0, 0, 100, 100));
+  window.Show();
+
+  ui::TouchEvent event(
+      ui::ET_TOUCH_PRESSED, window.bounds().CenterPoint(),
+      ui::EventTimeForNow(),
+      ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1));
+  window_tree_client()->OnWindowInputEvent(1, server_id(&window), 0,
+                                           ui::Event::Clone(event), false);
+  EXPECT_LT(0, delegate.GetGestureCountAndReset());
+  ui::GestureRecognizer* gesture_recognizer =
+      window.env()->gesture_recognizer();
+  EXPECT_EQ(&window, gesture_recognizer->GetTouchLockedTarget(event));
+
+  window_tree_client()->CleanupGestureState(
+      server_id(top_level->host->window()));
+  EXPECT_EQ(0, delegate.GetGestureCountAndReset());
+  EXPECT_FALSE(gesture_recognizer->GetTouchLockedTarget(event));
+}
+#endif
+
 // Verifies focus is reverted if the server replied that the change failed.
 TEST_F(WindowTreeClientTest, SetFocusFailed) {
   Window child(nullptr);
diff --git a/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc b/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc
index c0e50613..c2e2089f 100644
--- a/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc
+++ b/ui/aura/native_window_occlusion_tracker_win_interactive_test.cc
@@ -25,7 +25,7 @@
 #include "ui/aura/window_occlusion_tracker.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/aura/window_tree_host_platform.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/display/win/dpi.h"
 #include "ui/gfx/geometry/rect.h"
diff --git a/ui/aura/test/aura_test_base.cc b/ui/aura/test/aura_test_base.cc
index 03db199..2217469 100644
--- a/ui/aura/test/aura_test_base.cc
+++ b/ui/aura/test/aura_test_base.cc
@@ -13,7 +13,7 @@
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/test/test_windows.h"
 #include "ui/aura/window.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/base/ui_base_switches.h"
diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc
index 89224eb..752724506 100644
--- a/ui/aura/test/aura_test_helper.cc
+++ b/ui/aura/test/aura_test_helper.cc
@@ -27,8 +27,8 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_targeter.h"
-#include "ui/base/ime/input_method_factory.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_factory.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/platform_window_defaults.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/layer_animator.h"
diff --git a/ui/aura/test/ui_controls_factory_ozone.cc b/ui/aura/test/ui_controls_factory_ozone.cc
index c729b40a..f2bd4f9 100644
--- a/ui/aura/test/ui_controls_factory_ozone.cc
+++ b/ui/aura/test/ui_controls_factory_ozone.cc
@@ -25,7 +25,6 @@
 #include "ui/display/screen.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/test/events_test_utils.h"
-#include "ui/gfx/geometry/point_conversions.h"
 
 namespace aura {
 namespace test {
@@ -130,7 +129,7 @@
   bool SendMouseMoveNotifyWhenDone(long screen_x,
                                    long screen_y,
                                    base::OnceClosure closure) override {
-    gfx::PointF host_location(screen_x, screen_y);
+    gfx::Point host_location(screen_x, screen_y);
     int64_t display_id = display::kInvalidDisplayId;
     if (!ScreenDIPToHostPixels(&host_location, &display_id))
       return false;
@@ -159,14 +158,13 @@
                                      int button_state,
                                      base::OnceClosure closure,
                                      int accelerator_state) override {
-    gfx::PointF host_location;
+    gfx::Point host_location;
     int64_t display_id = display::kInvalidDisplayId;
     if (last_mouse_location_.has_value()) {
       host_location = last_mouse_location_.value();
       display_id = last_mouse_display_id_;
     } else {
-      host_location =
-          gfx::PointF(host_->window()->env()->last_mouse_location());
+      host_location = host_->window()->env()->last_mouse_location();
       if (!ScreenDIPToHostPixels(&host_location, &display_id))
         return false;
     }
@@ -230,7 +228,7 @@
                                      int y,
                                      base::OnceClosure task) override {
     DCHECK_NE(0, action);
-    gfx::PointF host_location(x, y);
+    gfx::Point host_location(x, y);
     int64_t display_id = display::kInvalidDisplayId;
     if (!ScreenDIPToHostPixels(&host_location, &display_id))
       return false;
@@ -265,24 +263,8 @@
                        int64_t display_id,
                        base::OnceClosure closure) {
     if (event_injector_) {
-      auto event_to_inject = ui::Event::Clone(*event);
-
-      if (event_to_inject->IsLocatedEvent()) {
-        // EventInjector expects coordinates relative to host and in DIPs.
-        display::Display display;
-        CHECK(display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id,
-                                                                    &display));
-
-        ui::LocatedEvent* located_event = event_to_inject->AsLocatedEvent();
-        gfx::PointF location_in_host_dip = gfx::ScalePoint(
-            located_event->location_f(), 1 / display.device_scale_factor(),
-            1 / display.device_scale_factor());
-        located_event->set_location_f(location_in_host_dip);
-        located_event->set_root_location_f(location_in_host_dip);
-      }
-
       event_injector_->InjectEvent(
-          display_id, std::move(event_to_inject),
+          display_id, ui::Event::Clone(*event),
           base::BindOnce(&OnWindowServiceProcessedEvent, std::move(closure)));
       return;
     }
@@ -322,7 +304,7 @@
   }
 
   void PostMouseEvent(ui::EventType type,
-                      const gfx::PointF& host_location,
+                      const gfx::Point& host_location,
                       int flags,
                       int changed_button_flags,
                       int64_t display_id,
@@ -335,7 +317,7 @@
   }
 
   void PostMouseEventTask(ui::EventType type,
-                          const gfx::PointF& host_location,
+                          const gfx::Point& host_location,
                           int flags,
                           int changed_button_flags,
                           int64_t display_id,
@@ -351,7 +333,7 @@
   }
 
   void PostTouchEvent(ui::EventType type,
-                      const gfx::PointF& host_location,
+                      const gfx::Point& host_location,
                       int id,
                       int64_t display_id,
                       base::OnceClosure closure) {
@@ -362,14 +344,14 @@
   }
 
   void PostTouchEventTask(ui::EventType type,
-                          const gfx::PointF& host_location,
+                          const gfx::Point& host_location,
                           int id,
                           int64_t display_id,
                           base::OnceClosure closure) {
     ui::PointerDetails details(ui::EventPointerType::POINTER_TYPE_TOUCH, id,
                                1.0f, 1.0f, 0.0f);
-    ui::TouchEvent touch_event(type, host_location, host_location,
-                               ui::EventTimeForNow(), details);
+    ui::TouchEvent touch_event(type, host_location, ui::EventTimeForNow(),
+                               details);
     SendEventToSink(&touch_event, display_id, std::move(closure));
   }
 
@@ -385,18 +367,19 @@
         ->BindInterface(ws::mojom::kServiceName, &event_injector_);
   }
 
-  bool ScreenDIPToHostPixels(gfx::PointF* location, int64_t* display_id) {
+  bool ScreenDIPToHostPixels(gfx::Point* location, int64_t* display_id) {
     // The location needs to be in display's coordinate.
     display::Display display =
-        display::Screen::GetScreen()->GetDisplayNearestPoint(
-            gfx::ToFlooredPoint(*location));
+        display::Screen::GetScreen()->GetDisplayNearestPoint(*location);
     if (!display.is_valid()) {
       LOG(ERROR) << "Failed to find the display for " << location->ToString();
       return false;
     }
     *display_id = display.id();
     *location -= display.bounds().OffsetFromOrigin();
-    location->Scale(display.device_scale_factor());
+    *location =
+        gfx::ScaleToFlooredPoint(*location, display.device_scale_factor(),
+                                 display.device_scale_factor());
     return true;
   }
 
@@ -406,7 +389,7 @@
   // The mouse location for the last SendMouseEventsNotifyWhenDone call. This is
   // used rather than Env::last_mouse_location() as Env::last_mouse_location()
   // is updated asynchronously with mus.
-  base::Optional<gfx::PointF> last_mouse_location_;
+  base::Optional<gfx::Point> last_mouse_location_;
 
   // The display ID where the last SendMouseEventsNotifyWhenDone occurred. This
   // is used along with |last_mouse_location_| to send the mouse event to the
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index fe1ee75..fe8b3bd 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -9,6 +9,7 @@
 #include <algorithm>
 #include <utility>
 
+#include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
@@ -1106,11 +1107,23 @@
 }
 
 bool Window::CleanupGestureState() {
+  // If it's in the process already, nothing has to be done. Reentrant can
+  // happen through some event handlers for CancelActiveTouches().
+  if (cleaning_up_gesture_state_)
+    return false;
+
+  base::AutoReset<bool> in_cleanup(&cleaning_up_gesture_state_, true);
   bool state_modified = false;
   state_modified |= env_->gesture_recognizer()->CancelActiveTouches(this);
   state_modified |= env_->gesture_recognizer()->CleanupStateForConsumer(this);
-  for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
-    state_modified |= (*iter)->CleanupGestureState();
+  // Potentially event handlers for CancelActiveTouches() within
+  // CleanupGestureState may change the window hierarchy (or reorder the
+  // |children_|), and therefore iterating over |children_| is not safe. Use
+  // WindowTracker to track the list of children.
+  WindowTracker children(children_);
+  while (!children.windows().empty()) {
+    Window* child = children.Pop();
+    state_modified |= child->CleanupGestureState();
   }
   return state_modified;
 }
diff --git a/ui/aura/window.h b/ui/aura/window.h
index 79714a4e..a2b72f2f 100644
--- a/ui/aura/window.h
+++ b/ui/aura/window.h
@@ -665,6 +665,9 @@
   // Whether layer is initialized as non-opaque. Defaults to false.
   bool transparent_;
 
+  // Whether it's in a process of CleanupGestureState() or not.
+  bool cleaning_up_gesture_state_ = false;
+
   std::unique_ptr<LayoutManager> layout_manager_;
   std::unique_ptr<WindowTargeter> targeter_;
 
diff --git a/ui/aura/window_event_dispatcher.cc b/ui/aura/window_event_dispatcher.cc
index c3ba085..0766de1e 100644
--- a/ui/aura/window_event_dispatcher.cc
+++ b/ui/aura/window_event_dispatcher.cc
@@ -697,6 +697,12 @@
   // We observe all windows regardless of what root Window (if any) they're
   // attached to.
   observer_manager_.Remove(window);
+
+  // In theory this should be cleaned up by other checks, but we are getting
+  // crashes that seem to indicate otherwise. See https://crbug.com/942552 for
+  // one case.
+  if (window == mouse_moved_handler_)
+    mouse_moved_handler_ = nullptr;
 }
 
 void WindowEventDispatcher::OnWindowAddedToRootWindow(Window* attached) {
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc
index 7e3e64b..808578a 100644
--- a/ui/aura/window_tree_host.cc
+++ b/ui/aura/window_tree_host.cc
@@ -20,8 +20,8 @@
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_targeter.h"
 #include "ui/aura/window_tree_host_observer.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_factory.h"
 #include "ui/base/layout.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/base/view_prop.h"
diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc
index 3721ba1..3e95a2b 100644
--- a/ui/aura/window_unittest.cc
+++ b/ui/aura/window_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/bind_test_util.h"
 #include "build/build_config.h"
 #include "cc/trees/layer_tree_frame_sink.h"
 #include "services/ws/public/mojom/window_tree_constants.mojom.h"
@@ -3316,6 +3317,94 @@
   EXPECT_NE(local_surface_id5, local_surface_id6);
 }
 
+// This delegate moves its parent window to the specified one when the gesture
+// ends.
+class HandleGestureEndDelegate : public TestWindowDelegate {
+ public:
+  explicit HandleGestureEndDelegate(
+      base::OnceCallback<void(Window*)> on_gesture_end)
+      : on_gesture_end_(std::move(on_gesture_end)) {}
+  ~HandleGestureEndDelegate() override = default;
+
+ private:
+  // WindowDelegate:
+  void OnGestureEvent(ui::GestureEvent* event) override {
+    switch (event->type()) {
+      case ui::ET_GESTURE_SCROLL_END:
+      case ui::ET_GESTURE_END:
+      case ui::ET_GESTURE_PINCH_END: {
+        if (on_gesture_end_)
+          std::move(on_gesture_end_).Run(static_cast<Window*>(event->target()));
+        break;
+      }
+      default:
+        break;
+    }
+  }
+
+  base::OnceCallback<void(Window*)> on_gesture_end_;
+  DISALLOW_COPY_AND_ASSIGN(HandleGestureEndDelegate);
+};
+
+TEST_P(WindowTest, CleanupGestureStateChangesWindowHierarchy) {
+  Window window(nullptr);
+  window.Init(ui::LAYER_NOT_DRAWN);
+  root_window()->AddChild(&window);
+  window.SetBounds(gfx::Rect(0, 0, 100, 100));
+  window.Show();
+  Window window2(nullptr);
+  window2.Init(ui::LAYER_NOT_DRAWN);
+  root_window()->AddChild(&window2);
+  root_window()->StackChildAtBottom(&window2);
+  window2.Show();
+  HandleGestureEndDelegate delegate(base::BindLambdaForTesting(
+      [&](Window* target_window) { window2.AddChild(target_window); }));
+  std::unique_ptr<Window> child = std::make_unique<Window>(&delegate);
+  child->Init(ui::LAYER_NOT_DRAWN);
+  window.AddChild(child.get());
+  child->SetBounds(gfx::Rect(0, 0, 100, 100));
+  child->Show();
+  EXPECT_EQ(1u, window.children().size());
+  EXPECT_EQ(0u, window2.children().size());
+
+  ui::test::EventGenerator event_generator(root_window(), child.get());
+  event_generator.PressTouch();
+  window.CleanupGestureState();
+  EXPECT_EQ(0u, window.children().size());
+  EXPECT_EQ(1u, window2.children().size());
+  child.reset();
+}
+
+TEST_P(WindowTest, CleanupGestureStateDeleteOtherWindows) {
+  Window window(nullptr);
+  window.Init(ui::LAYER_NOT_DRAWN);
+  root_window()->AddChild(&window);
+  window.SetBounds(gfx::Rect(0, 0, 200, 200));
+  window.Show();
+  std::unique_ptr<Window> child1 = std::make_unique<Window>(nullptr);
+  child1->Init(ui::LAYER_NOT_DRAWN);
+  child1->SetBounds(gfx::Rect(100, 100, 100, 100));
+  window.AddChild(child1.get());
+  child1->Show();
+  HandleGestureEndDelegate delegate(base::BindLambdaForTesting(
+      [&](Window* target_window) { child1.reset(); }));
+  std::unique_ptr<Window> child2 = std::make_unique<Window>(&delegate);
+  child2->Init(ui::LAYER_NOT_DRAWN);
+  window.AddChild(child2.get());
+  child2->SetBounds(gfx::Rect(0, 0, 100, 100));
+  child2->Show();
+  window.StackChildAtBottom(child2.get());
+  EXPECT_EQ(2u, window.children().size());
+  EXPECT_EQ(child2.get(), window.children().front());
+
+  ui::test::EventGenerator event_generator(root_window(), child2.get());
+  event_generator.PressTouch();
+  window.CleanupGestureState();
+  EXPECT_EQ(1u, window.children().size());
+  EXPECT_FALSE(child1);
+  child2.reset();
+}
+
 INSTANTIATE_TEST_SUITE_P(/* no prefix */,
                          WindowTest,
                          ::testing::Values(Env::Mode::LOCAL, Env::Mode::MUS));
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index a9f5ba1f..67cfa13 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -720,6 +720,10 @@
       "//ui/base/ime",
       "//ui/events",
     ]
+
+    if (is_win) {
+      deps += [ "//ui/base/ime/win" ]
+    }
   }
 
   if (is_chromeos) {
@@ -732,6 +736,7 @@
     deps += [
       # Generates a header used by input_method_whitelist.cc
       "//chromeos/ime:gencode",
+      "//ui/base/ime/chromeos",
     ]
   }
 
@@ -895,36 +900,6 @@
     ]
   }
 
-  if (build_ime) {
-    sources += [
-      "ime/candidate_window_unittest.cc",
-      "ime/chromeos/extension_ime_util_unittest.cc",
-      "ime/chromeos/ime_keyboard_unittest.cc",
-      "ime/chromeos/input_method_util_unittest.cc",
-      "ime/composition_text_unittest.cc",
-      "ime/input_method_base_unittest.cc",
-      "ime/input_method_chromeos_unittest.cc",
-      "ime/mojo/ime_struct_traits_unittest.cc",
-      "ime/win/imm32_manager_unittest.cc",
-      "ime/win/on_screen_keyboard_display_manager_unittest.cc",
-      "ime/win/tsf_input_scope_unittest.cc",
-      "ime/win/tsf_text_store_unittest.cc",
-    ]
-    if (is_linux && use_aura && !is_chromeos) {
-      if (use_x11 || use_ozone) {
-        sources += [ "ime/input_method_auralinux_unittest.cc" ]
-      } else {
-        sources += [ "ime/input_method_minimal_unittest.cc" ]
-      }
-    }
-    if (use_x11) {
-      sources += [ "ime/composition_text_util_pango_unittest.cc" ]
-    }
-    if (is_chromeos || use_ozone) {
-      sources += [ "ime/character_composer_unittest.cc" ]
-    }
-  }
-
   deps = [
     ":ui_base_test_resources_grit",
     ":ui_base_unittests_bundle_data",
@@ -952,6 +927,51 @@
     "//url",
   ]
 
+  if (build_ime) {
+    sources += [
+      "ime/candidate_window_unittest.cc",
+      "ime/composition_text_unittest.cc",
+      "ime/input_method_base_unittest.cc",
+      "ime/mojo/ime_struct_traits_unittest.cc",
+    ]
+    if (is_win) {
+      sources += [
+        "ime/win/imm32_manager_unittest.cc",
+        "ime/win/on_screen_keyboard_display_manager_unittest.cc",
+        "ime/win/tsf_input_scope_unittest.cc",
+        "ime/win/tsf_text_store_unittest.cc",
+      ]
+      deps += [ "//ui/base/ime/win" ]
+    }
+    if (is_chromeos) {
+      sources += [
+        "ime/chromeos/extension_ime_util_unittest.cc",
+        "ime/chromeos/ime_keyboard_unittest.cc",
+        "ime/chromeos/input_method_chromeos_unittest.cc",
+        "ime/chromeos/input_method_util_unittest.cc",
+      ]
+      deps += [ "//ui/base/ime/chromeos" ]
+    }
+    if (is_linux && use_aura && !is_chromeos) {
+      if (use_x11 || use_ozone) {
+        sources += [ "ime/linux/input_method_auralinux_unittest.cc" ]
+        deps += [
+          "//ui/base/ime/init",
+          "//ui/base/ime/linux",
+        ]
+      }
+      if (!use_x11) {
+        sources += [ "ime/input_method_minimal_unittest.cc" ]
+      }
+    }
+    if (use_x11) {
+      sources += [ "ime/linux/composition_text_util_pango_unittest.cc" ]
+    }
+    if (is_chromeos || use_ozone) {
+      sources += [ "ime/character_composer_unittest.cc" ]
+    }
+  }
+
   # Include the correct ui_base_test resources per platform.
   if (is_android) {
     deps += [ ":ui_base_test_android_assets" ]
diff --git a/ui/base/idle/BUILD.gn b/ui/base/idle/BUILD.gn
index ba4ea15a..d9e3eea 100644
--- a/ui/base/idle/BUILD.gn
+++ b/ui/base/idle/BUILD.gn
@@ -19,7 +19,7 @@
   ]
 
   if (is_chromeos) {
-    deps += [ "//chromeos/dbus" ]
+    deps += [ "//chromeos/dbus/session_manager" ]
   }
 
   sources = [
diff --git a/ui/base/idle/idle_chromeos.cc b/ui/base/idle/idle_chromeos.cc
index 4fd2677..a58a285 100644
--- a/ui/base/idle/idle_chromeos.cc
+++ b/ui/base/idle/idle_chromeos.cc
@@ -5,7 +5,6 @@
 #include "ui/base/idle/idle.h"
 
 #include "base/time/time.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "ui/base/user_activity/user_activity_detector.h"
 
@@ -18,8 +17,7 @@
 }
 
 bool CheckIdleStateIsLocked() {
-  return chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
-      IsScreenLocked();
+  return chromeos::SessionManagerClient::Get()->IsScreenLocked();
 }
 
 }  // namespace ui
diff --git a/ui/base/ime/BUILD.gn b/ui/base/ime/BUILD.gn
index 30825ee..5323a67 100644
--- a/ui/base/ime/BUILD.gn
+++ b/ui/base/ime/BUILD.gn
@@ -3,10 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/jumbo.gni")
-import("//build/config/jumbo.gni")
-import("//build/config/linux/pangocairo/pangocairo.gni")
 import("//build/config/ui.gni")
-import("//testing/test.gni")
 
 source_set("text_input_types") {
   sources = [
@@ -16,70 +13,35 @@
   ]
 }
 
-jumbo_component("ime_types") {
-  output_name = "ui_base_ime_types"
-  sources = [
-    "candidate_window.cc",
-    "candidate_window.h",
-    "composition_text.cc",
-    "composition_text.h",
-    "ime_text_span.cc",
-    "ime_text_span.h",
-    "infolist_entry.cc",
-    "infolist_entry.h",
-  ]
-
-  defines = [ "IS_UI_BASE_IME_TYPES_IMPL" ]
-
-  deps = [
-    "//base",
-    "//ui/gfx/range",
-  ]
-
-  public_deps = [
-    ":text_input_types",
-    "//skia",
-  ]
-
-  if (is_chromeos || use_ozone) {
-    sources += [
-      "character_composer.cc",
-      "character_composer.h",
-    ]
-    deps += [
-      "//ui/events:dom_keycode_converter",
-      "//ui/events:events",
-      "//ui/events:events_base",
-    ]
-  }
-}
-
 jumbo_component("ime") {
   output_name = "ui_base_ime"
   sources = [
+    "candidate_window.cc",
+    "candidate_window.h",
+    "character_composer.cc",
+    "character_composer.h",
+    "composition_text.cc",
+    "composition_text.h",
     "constants.cc",
     "constants.h",
     "ime_bridge.cc",
     "ime_bridge.h",
+    "ime_candidate_window_handler_interface.h",
     "ime_engine_handler_interface.h",
     "ime_input_context_handler_interface.h",
+    "ime_text_span.cc",
+    "ime_text_span.h",
+    "infolist_entry.cc",
+    "infolist_entry.h",
     "input_method.h",
     "input_method_base.cc",
     "input_method_base.h",
-    "input_method_chromeos.cc",
-    "input_method_chromeos.h",
     "input_method_delegate.cc",
     "input_method_delegate.h",
-    "input_method_factory.cc",
-    "input_method_factory.h",
-    "input_method_initializer.cc",
-    "input_method_initializer.h",
     "input_method_keyboard_controller.h",
     "input_method_keyboard_controller_observer.h",
     "input_method_keyboard_controller_stub.cc",
     "input_method_keyboard_controller_stub.h",
-    "input_method_mac.h",
-    "input_method_mac.mm",
     "input_method_minimal.cc",
     "input_method_minimal.h",
     "input_method_observer.h",
@@ -90,172 +52,21 @@
     "text_edit_commands.h",
     "text_input_client.cc",
     "text_input_client.h",
-    "win/imm32_manager.cc",
-    "win/imm32_manager.h",
-    "win/on_screen_keyboard_display_manager_input_pane.cc",
-    "win/on_screen_keyboard_display_manager_input_pane.h",
-    "win/on_screen_keyboard_display_manager_tab_tip.cc",
-    "win/on_screen_keyboard_display_manager_tab_tip.h",
-    "win/tsf_bridge.cc",
-    "win/tsf_bridge.h",
-    "win/tsf_event_router.cc",
-    "win/tsf_event_router.h",
-    "win/tsf_input_scope.cc",
-    "win/tsf_input_scope.h",
-    "win/tsf_text_store.cc",
-    "win/tsf_text_store.h",
   ]
 
-  if (is_chromeos) {
-    sources += [
-      "chromeos/component_extension_ime_manager.cc",
-      "chromeos/component_extension_ime_manager.h",
-      "chromeos/extension_ime_util.cc",
-      "chromeos/extension_ime_util.h",
-      "chromeos/fake_ime_keyboard.cc",
-      "chromeos/fake_ime_keyboard.h",
-      "chromeos/fake_input_method_delegate.cc",
-      "chromeos/fake_input_method_delegate.h",
-      "chromeos/ime_candidate_window_handler_interface.h",
-      "chromeos/ime_keyboard.cc",
-      "chromeos/ime_keyboard.h",
-      "chromeos/ime_keymap.cc",
-      "chromeos/ime_keymap.h",
-      "chromeos/input_method_delegate.h",
-      "chromeos/input_method_descriptor.cc",
-      "chromeos/input_method_descriptor.h",
-      "chromeos/input_method_manager.cc",
-      "chromeos/input_method_manager.h",
-      "chromeos/input_method_util.cc",
-      "chromeos/input_method_util.h",
-      "chromeos/mock_component_extension_ime_manager.cc",
-      "chromeos/mock_component_extension_ime_manager.h",
-      "chromeos/mock_component_extension_ime_manager_delegate.cc",
-      "chromeos/mock_component_extension_ime_manager_delegate.h",
-      "chromeos/mock_ime_candidate_window_handler.cc",
-      "chromeos/mock_ime_candidate_window_handler.h",
-      "chromeos/mock_ime_engine_handler.cc",
-      "chromeos/mock_ime_engine_handler.h",
-    ]
-  }
-
-  # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
-  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
-
   defines = [ "IS_UI_BASE_IME_IMPL" ]
 
-  deps = [
+  public_deps = [
+    ":text_input_types",
     "//base",
     "//base:i18n",
-    "//base/third_party/dynamic_annotations",
-    "//net",
+    "//skia",
     "//third_party/icu",
-    "//ui/base",
-    "//ui/display",
     "//ui/events",
+    "//ui/events:dom_keycode_converter",
+    "//ui/events:events",
     "//ui/gfx",
     "//ui/gfx/geometry",
     "//ui/gfx/range",
-    "//url",
   ]
-
-  public_deps = [
-    ":ime_types",
-  ]
-
-  if (is_desktop_linux) {
-    sources += [
-      "input_method_auralinux.cc",
-      "input_method_auralinux.h",
-    ]
-  }
-
-  if (is_linux) {
-    public_deps += [ "//ui/base/ime/linux" ]
-  }
-
-  if (!is_chromeos && is_linux) {
-    sources += [
-      "linux/text_edit_command_auralinux.cc",
-      "linux/text_edit_command_auralinux.h",
-      "linux/text_edit_key_bindings_delegate_auralinux.cc",
-      "linux/text_edit_key_bindings_delegate_auralinux.h",
-    ]
-  }
-
-  if (!toolkit_views && !use_aura) {
-    sources -= [
-      "input_method_factory.cc",
-      "input_method_factory.h",
-      "input_method_minimal.cc",
-      "input_method_minimal.h",
-    ]
-  }
-
-  if (is_chromeos) {
-    deps += [
-      "//chromeos",
-      "//chromeos/ime:gencode",
-      "//services/ws/public/cpp/input_devices",
-      "//ui/base/ime/chromeos/public/interfaces",
-      "//ui/chromeos/strings",
-    ]
-    sources += [
-      "chromeos/ime_keyboard_mus.cc",
-      "chromeos/ime_keyboard_mus.h",
-    ]
-  }
-
-  if (use_pangocairo) {
-    configs += [ "//build/config/linux/pangocairo" ]
-    sources += [
-      "composition_text_util_pango.cc",
-      "composition_text_util_pango.h",
-    ]
-  }
-  if (use_x11) {
-    configs += [ "//build/config/linux:x11" ]
-    deps += [ "//ui/gfx/x" ]
-  }
-
-  if (is_win) {
-    cflags = [ "/wd4324" ]  # Structure was padded due to __declspec(align()), which is
-                            # uninteresting.
-
-    sources += [
-      "input_method_win_base.cc",
-      "input_method_win_base.h",
-      "input_method_win_imm32.cc",
-      "input_method_win_imm32.h",
-      "input_method_win_tsf.cc",
-      "input_method_win_tsf.h",
-    ]
-    libs = [ "imm32.lib" ]
-
-    jumbo_excluded_sources = [
-      # tsf_text_store.cc needs INITGUID to be defined before
-      # including any header to properly generate GUID objects. That
-      # is not guaranteed when included in a jumbo build.
-      "win/tsf_text_store.cc",
-    ]
-  }
-
-  if (is_mac) {
-    libs = [ "AppKit.framework" ]
-  }
-
-  if (is_fuchsia) {
-    sources += [
-      "fuchsia/input_method_keyboard_controller_fuchsia.cc",
-      "fuchsia/input_method_keyboard_controller_fuchsia.h",
-      "input_method_fuchsia.cc",
-      "input_method_fuchsia.h",
-    ]
-
-    deps += [
-      "//third_party/fuchsia-sdk/sdk:ui_input",
-      "//ui/events",
-      "//ui/events:dom_keycode_converter",
-    ]
-  }
 }
diff --git a/ui/base/ime/candidate_window.h b/ui/base/ime/candidate_window.h
index 82c3fac..57e40d04 100644
--- a/ui/base/ime/candidate_window.h
+++ b/ui/base/ime/candidate_window.h
@@ -18,14 +18,14 @@
 namespace ui {
 
 // CandidateWindow represents the structure of candidates generated from IME.
-class COMPONENT_EXPORT(UI_BASE_IME_TYPES) CandidateWindow {
+class COMPONENT_EXPORT(UI_BASE_IME) CandidateWindow {
  public:
   enum Orientation {
     HORIZONTAL = 0,
     VERTICAL = 1,
   };
 
-  struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) CandidateWindowProperty {
+  struct COMPONENT_EXPORT(UI_BASE_IME) CandidateWindowProperty {
     CandidateWindowProperty();
     virtual ~CandidateWindowProperty();
     int page_size;
@@ -41,7 +41,7 @@
   };
 
   // Represents a candidate entry.
-  struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) Entry {
+  struct COMPONENT_EXPORT(UI_BASE_IME) Entry {
     Entry();
     Entry(const Entry& other);
     virtual ~Entry();
diff --git a/ui/base/ime/character_composer.h b/ui/base/ime/character_composer.h
index 57642c4..42baf12 100644
--- a/ui/base/ime/character_composer.h
+++ b/ui/base/ime/character_composer.h
@@ -20,7 +20,7 @@
 
 // A class to recognize compose and dead key sequence.
 // Outputs composed character.
-class COMPONENT_EXPORT(UI_BASE_IME_TYPES) CharacterComposer {
+class COMPONENT_EXPORT(UI_BASE_IME) CharacterComposer {
  public:
   using ComposeBuffer = std::vector<DomKey>;
 
diff --git a/ui/base/ime/chromeos/BUILD.gn b/ui/base/ime/chromeos/BUILD.gn
new file mode 100644
index 0000000..aee4bc0
--- /dev/null
+++ b/ui/base/ime/chromeos/BUILD.gn
@@ -0,0 +1,62 @@
+# Copyright 2019 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")
+
+assert(is_chromeos)
+
+jumbo_component("chromeos") {
+  output_name = "ui_base_ime_chromeos"
+
+  sources = [
+    "component_extension_ime_manager.cc",
+    "component_extension_ime_manager.h",
+    "extension_ime_util.cc",
+    "extension_ime_util.h",
+    "fake_ime_keyboard.cc",
+    "fake_ime_keyboard.h",
+    "fake_input_method_delegate.cc",
+    "fake_input_method_delegate.h",
+    "ime_keyboard.cc",
+    "ime_keyboard.h",
+    "ime_keyboard_mus.cc",
+    "ime_keyboard_mus.h",
+    "ime_keymap.cc",
+    "ime_keymap.h",
+    "input_method_chromeos.cc",
+    "input_method_chromeos.h",
+    "input_method_delegate.h",
+    "input_method_descriptor.cc",
+    "input_method_descriptor.h",
+    "input_method_manager.cc",
+    "input_method_manager.h",
+    "input_method_util.cc",
+    "input_method_util.h",
+    "mock_component_extension_ime_manager.cc",
+    "mock_component_extension_ime_manager.h",
+    "mock_component_extension_ime_manager_delegate.cc",
+    "mock_component_extension_ime_manager_delegate.h",
+    "mock_ime_candidate_window_handler.cc",
+    "mock_ime_candidate_window_handler.h",
+    "mock_ime_engine_handler.cc",
+    "mock_ime_engine_handler.h",
+  ]
+
+  defines = [ "IS_UI_BASE_IME_CHROMEOS_IMPL" ]
+
+  public_deps = [
+    "//ui/base/ime",
+    "//ui/base/ime/chromeos/public/interfaces",
+    "//url",
+  ]
+
+  deps = [
+    "//chromeos",
+    "//chromeos/ime:gencode",
+    "//services/ws/public/cpp/input_devices",
+    "//third_party/icu",
+    "//ui/base",
+    "//ui/chromeos/strings",
+  ]
+}
diff --git a/ui/base/ime/chromeos/component_extension_ime_manager.h b/ui/base/ime/chromeos/component_extension_ime_manager.h
index 6b8ea37..b6bd2d4 100644
--- a/ui/base/ime/chromeos/component_extension_ime_manager.h
+++ b/ui/base/ime/chromeos/component_extension_ime_manager.h
@@ -20,7 +20,7 @@
 namespace chromeos {
 
 // Represents an engine in component extension IME.
-struct COMPONENT_EXPORT(UI_BASE_IME) ComponentExtensionEngine {
+struct COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) ComponentExtensionEngine {
   ComponentExtensionEngine();
   ComponentExtensionEngine(const ComponentExtensionEngine& other);
   ~ComponentExtensionEngine();
@@ -35,7 +35,7 @@
 };
 
 // Represents a component extension IME.
-struct COMPONENT_EXPORT(UI_BASE_IME) ComponentExtensionIME {
+struct COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) ComponentExtensionIME {
   ComponentExtensionIME();
   ComponentExtensionIME(const ComponentExtensionIME& other);
   ~ComponentExtensionIME();
@@ -48,7 +48,8 @@
 };
 
 // Provides an interface to list/load/unload for component extension IME.
-class COMPONENT_EXPORT(UI_BASE_IME) ComponentExtensionIMEManagerDelegate {
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
+    ComponentExtensionIMEManagerDelegate {
  public:
   ComponentExtensionIMEManagerDelegate();
   virtual ~ComponentExtensionIMEManagerDelegate();
@@ -70,7 +71,7 @@
 };
 
 // This class manages component extension input method.
-class COMPONENT_EXPORT(UI_BASE_IME) ComponentExtensionIMEManager {
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) ComponentExtensionIMEManager {
  public:
   ComponentExtensionIMEManager();
   virtual ~ComponentExtensionIMEManager();
diff --git a/ui/base/ime/chromeos/extension_ime_util.h b/ui/base/ime/chromeos/extension_ime_util.h
index 9266f5f1..60c6bd81 100644
--- a/ui/base/ime/chromeos/extension_ime_util.h
+++ b/ui/base/ime/chromeos/extension_ime_util.h
@@ -37,88 +37,90 @@
 
 // Extension id, path (relative to |chrome::DIR_RESOURCES|) and IME engine
 // id for the builtin-in Braille IME extension.
-COMPONENT_EXPORT(UI_BASE_IME) extern const char kBrailleImeExtensionId[];
-COMPONENT_EXPORT(UI_BASE_IME)
+COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
+extern const char kBrailleImeExtensionId[];
+COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
 extern const char kBrailleImeExtensionPath[];
-COMPONENT_EXPORT(UI_BASE_IME) extern const char kBrailleImeEngineId[];
+COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) extern const char kBrailleImeEngineId[];
 
 // The fake language name used for ARC IMEs.
-COMPONENT_EXPORT(UI_BASE_IME) extern const char kArcImeLanguage[];
+COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) extern const char kArcImeLanguage[];
 
 // Returns InputMethodID for |engine_id| in |extension_id| of extension IME.
 // This function does not check |extension_id| is installed extension IME nor
 // |engine_id| is really a member of |extension_id|.
-std::string COMPONENT_EXPORT(UI_BASE_IME)
+std::string COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     GetInputMethodID(const std::string& extension_id,
                      const std::string& engine_id);
 
 // Returns InputMethodID for |engine_id| in |extension_id| of component
 // extension IME, This function does not check |extension_id| is component one
 // nor |engine_id| is really a member of |extension_id|.
-std::string COMPONENT_EXPORT(UI_BASE_IME)
+std::string COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     GetComponentInputMethodID(const std::string& extension_id,
                               const std::string& engine_id);
 
 // Returns InputMethodID for |engine_id| in |extension_id| of ARC IME.
 // This function does not check |extension_id| is one for ARC IME nor
 // |engine_id| is really an installed ARC IME.
-std::string COMPONENT_EXPORT(UI_BASE_IME)
+std::string COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     GetArcInputMethodID(const std::string& extension_id,
                         const std::string& engine_id);
 
 // Returns extension ID if |input_method_id| is extension IME ID or component
 // extension IME ID. Otherwise returns an empty string ("").
-std::string COMPONENT_EXPORT(UI_BASE_IME)
+std::string COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     GetExtensionIDFromInputMethodID(const std::string& input_method_id);
 
 // Returns InputMethodID from engine id (e.g. xkb:fr:fra), or returns itself if
 // the |engine_id| is not a known engine id.
 // The caller must make sure the |engine_id| is from system input methods
 // instead of 3rd party input methods.
-std::string COMPONENT_EXPORT(UI_BASE_IME)
+std::string COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     GetInputMethodIDByEngineID(const std::string& engine_id);
 
 // Returns true if |input_method_id| is extension IME ID. This function does not
 // check |input_method_id| is installed extension IME.
-bool COMPONENT_EXPORT(UI_BASE_IME)
+bool COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     IsExtensionIME(const std::string& input_method_id);
 
 // Returns true if |input_method_id| is component extension IME ID. This
 // function does not check |input_method_id| is really whitelisted one or not.
 // If you want to check |input_method_id| is whitelisted component extension
 // IME, please use ComponentExtensionIMEManager::IsWhitelisted instead.
-bool COMPONENT_EXPORT(UI_BASE_IME)
+bool COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     IsComponentExtensionIME(const std::string& input_method_id);
 
 // Returns true if |input_method_id| is a Arc IME ID. This function does not
 // check |input_method_id| is really a installed Arc IME.
-bool COMPONENT_EXPORT(UI_BASE_IME) IsArcIME(const std::string& input_method_id);
+bool COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
+    IsArcIME(const std::string& input_method_id);
 
 // Returns true if the |input_method| is a member of |extension_id| of extension
 // IME, otherwise returns false.
-bool COMPONENT_EXPORT(UI_BASE_IME)
+bool COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     IsMemberOfExtension(const std::string& input_method_id,
                         const std::string& extension_id);
 
 // Returns true if the |input_method_id| is the extension based xkb keyboard,
 // otherwise returns false.
-bool COMPONENT_EXPORT(UI_BASE_IME)
+bool COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     IsKeyboardLayoutExtension(const std::string& input_method_id);
 
 // Returns true if |language| is the fake one for ARC IMEs.
-bool COMPONENT_EXPORT(UI_BASE_IME)
+bool COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     IsLanguageForArcIME(const std::string& language);
 
 // Returns input method component id from the extension-based InputMethodID
 // for component IME extensions. This function does not check that
 // |input_method_id| is installed.
-std::string COMPONENT_EXPORT(UI_BASE_IME)
+std::string COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     GetComponentIDByInputMethodID(const std::string& input_method_id);
 
 // Gets legacy xkb id (e.g. xkb:us::eng) from the new extension based xkb id
 // (e.g. _comp_ime_...xkb:us::eng). If the given id is not prefixed with
 // 'xkb:', just return the same as the given id.
-std::string COMPONENT_EXPORT(UI_BASE_IME)
+std::string COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
     MaybeGetLegacyXkbId(const std::string& input_method_id);
 
 }  // namespace extension_ime_util
diff --git a/ui/base/ime/chromeos/fake_ime_keyboard.h b/ui/base/ime/chromeos/fake_ime_keyboard.h
index 37892d72..fe96c34 100644
--- a/ui/base/ime/chromeos/fake_ime_keyboard.h
+++ b/ui/base/ime/chromeos/fake_ime_keyboard.h
@@ -16,7 +16,8 @@
 namespace chromeos {
 namespace input_method {
 
-class COMPONENT_EXPORT(UI_BASE_IME) FakeImeKeyboard : public ImeKeyboard {
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) FakeImeKeyboard
+    : public ImeKeyboard {
  public:
   FakeImeKeyboard();
   ~FakeImeKeyboard() override;
diff --git a/ui/base/ime/chromeos/fake_input_method_delegate.h b/ui/base/ime/chromeos/fake_input_method_delegate.h
index de045d3..ff1a46378 100644
--- a/ui/base/ime/chromeos/fake_input_method_delegate.h
+++ b/ui/base/ime/chromeos/fake_input_method_delegate.h
@@ -16,7 +16,7 @@
 namespace chromeos {
 namespace input_method {
 
-class COMPONENT_EXPORT(UI_BASE_IME) FakeInputMethodDelegate
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) FakeInputMethodDelegate
     : public InputMethodDelegate {
  public:
   typedef base::RepeatingCallback<base::string16(
diff --git a/ui/base/ime/chromeos/ime_keyboard.h b/ui/base/ime/chromeos/ime_keyboard.h
index 421412d8..3e32db6 100644
--- a/ui/base/ime/chromeos/ime_keyboard.h
+++ b/ui/base/ime/chromeos/ime_keyboard.h
@@ -20,7 +20,7 @@
   unsigned int repeat_interval_in_ms;
 };
 
-class COMPONENT_EXPORT(UI_BASE_IME) ImeKeyboard {
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) ImeKeyboard {
  public:
   class Observer {
    public:
@@ -91,15 +91,6 @@
   // non-UI threads.
   virtual bool SetAutoRepeatRate(const AutoRepeatRate& rate) = 0;
 
-  // On success, set current auto repeat rate on |out_rate| and returns true.
-  // Returns false otherwise. This function is protected: for testability.
-  static COMPONENT_EXPORT(UI_BASE_IME) bool GetAutoRepeatRateForTesting(
-      AutoRepeatRate* out_rate);
-
-  // Returns false if |layout_name| contains a bad character.
-  static COMPONENT_EXPORT(UI_BASE_IME) bool CheckLayoutNameForTesting(
-      const std::string& layout_name);
-
   bool caps_lock_is_enabled_;
   std::string last_layout_;
 
diff --git a/ui/base/ime/chromeos/ime_keyboard_mus.h b/ui/base/ime/chromeos/ime_keyboard_mus.h
index 8f96c9b..fe3e03d2 100644
--- a/ui/base/ime/chromeos/ime_keyboard_mus.h
+++ b/ui/base/ime/chromeos/ime_keyboard_mus.h
@@ -16,7 +16,8 @@
 namespace chromeos {
 namespace input_method {
 
-class COMPONENT_EXPORT(UI_BASE_IME) ImeKeyboardMus : public ImeKeyboard {
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) ImeKeyboardMus
+    : public ImeKeyboard {
  public:
   explicit ImeKeyboardMus(
       ws::InputDeviceControllerClient* input_device_controller_client);
diff --git a/ui/base/ime/chromeos/ime_keymap.h b/ui/base/ime/chromeos/ime_keymap.h
index 4b09d00..2908107 100644
--- a/ui/base/ime/chromeos/ime_keymap.h
+++ b/ui/base/ime/chromeos/ime_keymap.h
@@ -12,11 +12,11 @@
 namespace ui {
 
 // Translates the DOM4 key code string to ui::KeyboardCode.
-COMPONENT_EXPORT(UI_BASE_IME)
+COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
 KeyboardCode DomKeycodeToKeyboardCode(const std::string& code);
 
 // Translates the ui::KeyboardCode to DOM4 key code string.
-COMPONENT_EXPORT(UI_BASE_IME)
+COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS)
 std::string KeyboardCodeToDomKeycode(KeyboardCode code);
 
 }  // namespace ui
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/chromeos/input_method_chromeos.cc
similarity index 99%
rename from ui/base/ime/input_method_chromeos.cc
rename to ui/base/ime/chromeos/input_method_chromeos.cc
index 61dc589..3394ba7 100644
--- a/ui/base/ime/input_method_chromeos.cc
+++ b/ui/base/ime/chromeos/input_method_chromeos.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 "ui/base/ime/input_method_chromeos.h"
+#include "ui/base/ime/chromeos/input_method_chromeos.h"
 
 #include <stddef.h>
 
diff --git a/ui/base/ime/input_method_chromeos.h b/ui/base/ime/chromeos/input_method_chromeos.h
similarity index 96%
rename from ui/base/ime/input_method_chromeos.h
rename to ui/base/ime/chromeos/input_method_chromeos.h
index eef6635f..219f5cf 100644
--- a/ui/base/ime/input_method_chromeos.h
+++ b/ui/base/ime/chromeos/input_method_chromeos.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_BASE_IME_INPUT_METHOD_CHROMEOS_H_
-#define UI_BASE_IME_INPUT_METHOD_CHROMEOS_H_
+#ifndef UI_BASE_IME_CHROMEOS_INPUT_METHOD_CHROMEOS_H_
+#define UI_BASE_IME_CHROMEOS_INPUT_METHOD_CHROMEOS_H_
 
 #include <stdint.h>
 
@@ -25,7 +25,7 @@
 namespace ui {
 
 // A ui::InputMethod implementation based on IBus.
-class COMPONENT_EXPORT(UI_BASE_IME) InputMethodChromeOS
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) InputMethodChromeOS
     : public InputMethodBase {
  public:
   explicit InputMethodChromeOS(internal::InputMethodDelegate* delegate);
@@ -181,4 +181,4 @@
 
 }  // namespace ui
 
-#endif  // UI_BASE_IME_INPUT_METHOD_CHROMEOS_H_
+#endif  // UI_BASE_IME_CHROMEOS_INPUT_METHOD_CHROMEOS_H_
diff --git a/ui/base/ime/input_method_chromeos_unittest.cc b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc
similarity index 99%
rename from ui/base/ime/input_method_chromeos_unittest.cc
rename to ui/base/ime/chromeos/input_method_chromeos_unittest.cc
index fd1101d1..59863cfe 100644
--- a/ui/base/ime/input_method_chromeos_unittest.cc
+++ b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/base/ime/input_method_chromeos.h"
+#include "ui/base/ime/chromeos/input_method_chromeos.h"
 
 #include <stddef.h>
 #include <stdint.h>
diff --git a/ui/base/ime/chromeos/input_method_descriptor.h b/ui/base/ime/chromeos/input_method_descriptor.h
index 09c76136..194600c 100644
--- a/ui/base/ime/chromeos/input_method_descriptor.h
+++ b/ui/base/ime/chromeos/input_method_descriptor.h
@@ -15,7 +15,7 @@
 namespace input_method {
 
 // A structure which represents an input method.
-class COMPONENT_EXPORT(UI_BASE_IME) InputMethodDescriptor {
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) InputMethodDescriptor {
  public:
   InputMethodDescriptor();
   InputMethodDescriptor(const std::string& id,
diff --git a/ui/base/ime/chromeos/input_method_manager.h b/ui/base/ime/chromeos/input_method_manager.h
index 0f83c5b8..ecb06c5 100644
--- a/ui/base/ime/chromeos/input_method_manager.h
+++ b/ui/base/ime/chromeos/input_method_manager.h
@@ -33,7 +33,7 @@
 // This class manages input methodshandles.  Classes can add themselves as
 // observers. Clients can get an instance of this library class by:
 // InputMethodManager::Get().
-class COMPONENT_EXPORT(UI_BASE_IME) InputMethodManager {
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) InputMethodManager {
  public:
   enum UISessionState {
     STATE_LOGIN_SCREEN = 0,
@@ -259,17 +259,17 @@
 
   // Gets the global instance of InputMethodManager. Initialize() must be called
   // first.
-  static COMPONENT_EXPORT(UI_BASE_IME) InputMethodManager* Get();
+  static COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) InputMethodManager* Get();
 
   // Sets the global instance. |instance| will be owned by the internal pointer
   // and deleted by Shutdown().
   // TODO(nona): Instanciate InputMethodManagerImpl inside of this function once
   //             crbug.com/164375 is fixed.
-  static COMPONENT_EXPORT(UI_BASE_IME) void Initialize(
+  static COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) void Initialize(
       InputMethodManager* instance);
 
   // Destroy the global instance.
-  static COMPONENT_EXPORT(UI_BASE_IME) void Shutdown();
+  static COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) void Shutdown();
 
   // Get the current UI session state (e.g. login screen, lock screen, etc.).
   virtual UISessionState GetUISessionState() = 0;
diff --git a/ui/base/ime/chromeos/input_method_util.h b/ui/base/ime/chromeos/input_method_util.h
index f47f64b..ad2118c 100644
--- a/ui/base/ime/chromeos/input_method_util.h
+++ b/ui/base/ime/chromeos/input_method_util.h
@@ -29,7 +29,7 @@
 };
 
 // A class which provides miscellaneous input method utility functions.
-class COMPONENT_EXPORT(UI_BASE_IME) InputMethodUtil {
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) InputMethodUtil {
  public:
   explicit InputMethodUtil(InputMethodDelegate* delegate);
   ~InputMethodUtil();
diff --git a/ui/base/ime/chromeos/input_method_whitelist.h b/ui/base/ime/chromeos/input_method_whitelist.h
index 217dc937..8c749ab 100644
--- a/ui/base/ime/chromeos/input_method_whitelist.h
+++ b/ui/base/ime/chromeos/input_method_whitelist.h
@@ -21,7 +21,7 @@
 
 // A class which has white listed input method list. The list is generated by
 // gen_input_methods.py from input_methods.txt.
-class COMPONENT_EXPORT(UI_BASE_IME) InputMethodWhitelist {
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) InputMethodWhitelist {
  public:
   InputMethodWhitelist();
   ~InputMethodWhitelist();
diff --git a/ui/base/ime/chromeos/mock_component_extension_ime_manager.h b/ui/base/ime/chromeos/mock_component_extension_ime_manager.h
index bb1483c..5ad2acf 100644
--- a/ui/base/ime/chromeos/mock_component_extension_ime_manager.h
+++ b/ui/base/ime/chromeos/mock_component_extension_ime_manager.h
@@ -10,7 +10,7 @@
 
 namespace chromeos {
 
-class COMPONENT_EXPORT(UI_BASE_IME) MockComponentExtensionIMEManager
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) MockComponentExtensionIMEManager
     : public ComponentExtensionIMEManager {
  public:
   input_method::InputMethodDescriptors GetXkbIMEAsInputMethodDescriptor()
diff --git a/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h b/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h
index e7c8650..a092e8076 100644
--- a/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h
+++ b/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h
@@ -12,7 +12,7 @@
 namespace chromeos {
 namespace input_method {
 
-class COMPONENT_EXPORT(UI_BASE_IME) MockComponentExtIMEManagerDelegate
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) MockComponentExtIMEManagerDelegate
     : public ComponentExtensionIMEManagerDelegate {
  public:
   MockComponentExtIMEManagerDelegate();
diff --git a/ui/base/ime/chromeos/mock_ime_candidate_window_handler.h b/ui/base/ime/chromeos/mock_ime_candidate_window_handler.h
index 029e393..18b614b5 100644
--- a/ui/base/ime/chromeos/mock_ime_candidate_window_handler.h
+++ b/ui/base/ime/chromeos/mock_ime_candidate_window_handler.h
@@ -9,12 +9,12 @@
 
 #include "base/component_export.h"
 #include "ui/base/ime/candidate_window.h"
-#include "ui/base/ime/chromeos/ime_candidate_window_handler_interface.h"
+#include "ui/base/ime/ime_candidate_window_handler_interface.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace chromeos {
 
-class COMPONENT_EXPORT(UI_BASE_IME) MockIMECandidateWindowHandler
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) MockIMECandidateWindowHandler
     : public IMECandidateWindowHandlerInterface {
  public:
   struct UpdateLookupTableArg {
diff --git a/ui/base/ime/chromeos/mock_ime_engine_handler.h b/ui/base/ime/chromeos/mock_ime_engine_handler.h
index 5668f5b..4d895f85 100644
--- a/ui/base/ime/chromeos/mock_ime_engine_handler.h
+++ b/ui/base/ime/chromeos/mock_ime_engine_handler.h
@@ -15,7 +15,7 @@
 
 namespace chromeos {
 
-class COMPONENT_EXPORT(UI_BASE_IME) MockIMEEngineHandler
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) MockIMEEngineHandler
     : public ui::IMEEngineHandlerInterface {
  public:
   MockIMEEngineHandler();
diff --git a/ui/base/ime/chromeos/mock_input_method_manager.h b/ui/base/ime/chromeos/mock_input_method_manager.h
index 2461ea1a..2a1a8f5 100644
--- a/ui/base/ime/chromeos/mock_input_method_manager.h
+++ b/ui/base/ime/chromeos/mock_input_method_manager.h
@@ -16,7 +16,7 @@
 class ImeKeyboard;
 
 // The mock InputMethodManager for testing.
-class COMPONENT_EXPORT(UI_BASE_IME) MockInputMethodManager
+class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) MockInputMethodManager
     : public InputMethodManager,
       public ui::InputMethodKeyboardController {
  public:
diff --git a/ui/base/ime/composition_text.h b/ui/base/ime/composition_text.h
index cddf445e..ba7b76f 100644
--- a/ui/base/ime/composition_text.h
+++ b/ui/base/ime/composition_text.h
@@ -15,7 +15,7 @@
 namespace ui {
 
 // A struct represents the status of an ongoing composition text.
-struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) CompositionText {
+struct COMPONENT_EXPORT(UI_BASE_IME) CompositionText {
   CompositionText();
   CompositionText(const CompositionText& other);
   ~CompositionText();
diff --git a/ui/base/ime/composition_text_util_pango.h b/ui/base/ime/composition_text_util_pango.h
deleted file mode 100644
index 062f31e..0000000
--- a/ui/base/ime/composition_text_util_pango.h
+++ /dev/null
@@ -1,27 +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 UI_BASE_IME_COMPOSITION_TEXT_UTIL_PANGO_H_
-#define UI_BASE_IME_COMPOSITION_TEXT_UTIL_PANGO_H_
-
-#include "base/component_export.h"
-#include "ui/base/glib/glib_integers.h"
-
-typedef struct _PangoAttrList PangoAttrList;
-
-namespace ui {
-
-struct CompositionText;
-
-// Extracts composition text information (text, underlines, selection range)
-// from given Gtk preedit data (utf-8 text, pango attributes, cursor position).
-COMPONENT_EXPORT(UI_BASE_IME)
-void ExtractCompositionTextFromGtkPreedit(const gchar* utf8_text,
-                                          PangoAttrList* attrs,
-                                          int cursor_position,
-                                          CompositionText* composition);
-
-}  // namespace ui
-
-#endif  // UI_BASE_IME_COMPOSITION_TEXT_UTIL_PANGO_H_
diff --git a/ui/base/ime/fuchsia/BUILD.gn b/ui/base/ime/fuchsia/BUILD.gn
new file mode 100644
index 0000000..83e6d24
--- /dev/null
+++ b/ui/base/ime/fuchsia/BUILD.gn
@@ -0,0 +1,30 @@
+# Copyright 2019 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")
+
+assert(is_fuchsia)
+
+jumbo_component("fuchsia") {
+  output_name = "ui_base_ime_fuchsia"
+
+  sources = [
+    "input_method_fuchsia.cc",
+    "input_method_fuchsia.h",
+    "input_method_keyboard_controller_fuchsia.cc",
+    "input_method_keyboard_controller_fuchsia.h",
+  ]
+
+  defines = [ "IS_UI_BASE_IME_FUCHSIA_IMPL" ]
+
+  public_deps = [
+    "//third_party/fuchsia-sdk/sdk:ui_input",
+    "//ui/base/ime",
+    "//ui/events",
+  ]
+
+  deps = [
+    "//ui/events:dom_keycode_converter",
+  ]
+}
diff --git a/ui/base/ime/input_method_fuchsia.cc b/ui/base/ime/fuchsia/input_method_fuchsia.cc
similarity index 98%
rename from ui/base/ime/input_method_fuchsia.cc
rename to ui/base/ime/fuchsia/input_method_fuchsia.cc
index e8c3bd6..c975291 100644
--- a/ui/base/ime/input_method_fuchsia.cc
+++ b/ui/base/ime/fuchsia/input_method_fuchsia.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 "ui/base/ime/input_method_fuchsia.h"
+#include "ui/base/ime/fuchsia/input_method_fuchsia.h"
 
 #include <fuchsia/ui/input/cpp/fidl.h>
 #include <memory>
diff --git a/ui/base/ime/input_method_fuchsia.h b/ui/base/ime/fuchsia/input_method_fuchsia.h
similarity index 94%
rename from ui/base/ime/input_method_fuchsia.h
rename to ui/base/ime/fuchsia/input_method_fuchsia.h
index 8e5c099..4707189c 100644
--- a/ui/base/ime/input_method_fuchsia.h
+++ b/ui/base/ime/fuchsia/input_method_fuchsia.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_BASE_IME_INPUT_METHOD_FUCHSIA_H_
-#define UI_BASE_IME_INPUT_METHOD_FUCHSIA_H_
+#ifndef UI_BASE_IME_FUCHSIA_INPUT_METHOD_FUCHSIA_H_
+#define UI_BASE_IME_FUCHSIA_INPUT_METHOD_FUCHSIA_H_
 
 #include <fuchsia/ui/input/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
@@ -73,4 +73,4 @@
 
 }  // namespace ui
 
-#endif  // UI_BASE_IME_INPUT_METHOD_FUCHSIA_H_
+#endif  // UI_BASE_IME_FUCHSIA_INPUT_METHOD_FUCHSIA_H_
diff --git a/ui/base/ime/ime_bridge.h b/ui/base/ime/ime_bridge.h
index 7c77a43f..846bbba 100644
--- a/ui/base/ime/ime_bridge.h
+++ b/ui/base/ime/ime_bridge.h
@@ -13,7 +13,7 @@
 #include "ui/base/ime/ime_input_context_handler_interface.h"
 
 #if defined(OS_CHROMEOS)
-#include "ui/base/ime/chromeos/ime_candidate_window_handler_interface.h"
+#include "ui/base/ime/ime_candidate_window_handler_interface.h"
 
 namespace chromeos {
 class IMECandidateWindowHandlerInterface;
diff --git a/ui/base/ime/chromeos/ime_candidate_window_handler_interface.h b/ui/base/ime/ime_candidate_window_handler_interface.h
similarity index 87%
rename from ui/base/ime/chromeos/ime_candidate_window_handler_interface.h
rename to ui/base/ime/ime_candidate_window_handler_interface.h
index 0c1989f..4d30a63 100644
--- a/ui/base/ime/chromeos/ime_candidate_window_handler_interface.h
+++ b/ui/base/ime/ime_candidate_window_handler_interface.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_BASE_IME_CHROMEOS_IME_CNADIDATE_WINDOW_HANDLER_INTERFACE_H_
-#define UI_BASE_IME_CHROMEOS_IME_CNADIDATE_WINDOW_HANDLER_INTERFACE_H_
+#ifndef UI_BASE_IME_IME_CANDIDATE_WINDOW_HANDLER_INTERFACE_H_
+#define UI_BASE_IME_IME_CANDIDATE_WINDOW_HANDLER_INTERFACE_H_
 
 #include <stdint.h>
 
@@ -52,4 +52,4 @@
 
 }  // namespace chromeos
 
-#endif  // UI_BASE_IME_CHROMEOS_IME_CNADIDATE_WINDOW_HANDLER_INTERFACE_H_
+#endif  // UI_BASE_IME_IME_CANDIDATE_WINDOW_HANDLER_INTERFACE_H_
diff --git a/ui/base/ime/ime_text_span.h b/ui/base/ime/ime_text_span.h
index 4e449567..4125a3b 100644
--- a/ui/base/ime/ime_text_span.h
+++ b/ui/base/ime/ime_text_span.h
@@ -18,7 +18,7 @@
 // Intentionally keep sync with blink::WebImeTextSpan defined in:
 // third_party/WebKit/public/web/WebImeTextSpan.h
 
-struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan {
+struct COMPONENT_EXPORT(UI_BASE_IME) ImeTextSpan {
   enum class Type {
     // Creates a composition marker.
     kComposition,
diff --git a/ui/base/ime/infolist_entry.h b/ui/base/ime/infolist_entry.h
index 54d6320..107db39 100644
--- a/ui/base/ime/infolist_entry.h
+++ b/ui/base/ime/infolist_entry.h
@@ -11,7 +11,7 @@
 namespace ui {
 
 // The data model of infolist window.
-struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) InfolistEntry {
+struct COMPONENT_EXPORT(UI_BASE_IME) InfolistEntry {
   base::string16 title;
   base::string16 body;
   bool highlighted;
diff --git a/ui/base/ime/init/BUILD.gn b/ui/base/ime/init/BUILD.gn
new file mode 100644
index 0000000..f054326
--- /dev/null
+++ b/ui/base/ime/init/BUILD.gn
@@ -0,0 +1,45 @@
+# Copyright 2019 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")
+
+jumbo_component("init") {
+  output_name = "ui_base_ime_init"
+
+  sources = [
+    "input_method_factory.cc",
+    "input_method_factory.h",
+    "input_method_initializer.cc",
+    "input_method_initializer.h",
+  ]
+
+  defines = [ "IS_UI_BASE_IME_INIT_IMPL" ]
+
+  public_deps = [
+    "//base",
+    "//ui/base/ime",
+    "//ui/gfx:native_widget_types",
+  ]
+
+  deps = [
+    "//ui/base",
+  ]
+
+  if (is_win) {
+    deps += [ "//ui/base/ime/win" ]
+  }
+  if (is_mac) {
+    deps += [ "//ui/base/ime/mac" ]
+  }
+  if (is_chromeos) {
+    deps += [ "//ui/base/ime/chromeos" ]
+  }
+  if (is_fuchsia) {
+    deps += [ "//ui/base/ime/fuchsia" ]
+  }
+  if (is_linux && !is_chromeos) {
+    deps += [ "//ui/base/ime/linux" ]
+  }
+}
diff --git a/ui/base/ime/input_method_factory.cc b/ui/base/ime/init/input_method_factory.cc
similarity index 87%
rename from ui/base/ime/input_method_factory.cc
rename to ui/base/ime/init/input_method_factory.cc
index 2cd9b79..b79ccae 100644
--- a/ui/base/ime/input_method_factory.cc
+++ b/ui/base/ime/init/input_method_factory.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 "ui/base/ime/input_method_factory.h"
+#include "ui/base/ime/init/input_method_factory.h"
 
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
@@ -12,16 +12,16 @@
 #include "ui/gfx/switches.h"
 
 #if defined(OS_CHROMEOS)
-#include "ui/base/ime/input_method_chromeos.h"
+#include "ui/base/ime/chromeos/input_method_chromeos.h"
 #elif defined(OS_WIN)
-#include "ui/base/ime/input_method_win_imm32.h"
-#include "ui/base/ime/input_method_win_tsf.h"
+#include "ui/base/ime/win/input_method_win_imm32.h"
+#include "ui/base/ime/win/input_method_win_tsf.h"
 #elif defined(OS_MACOSX)
-#include "ui/base/ime/input_method_mac.h"
+#include "ui/base/ime/mac/input_method_mac.h"
 #elif defined(OS_FUCHSIA)
-#include "ui/base/ime/input_method_fuchsia.h"
+#include "ui/base/ime/fuchsia/input_method_fuchsia.h"
 #elif defined(USE_AURA) && (defined(USE_X11) || defined(USE_OZONE))
-#include "ui/base/ime/input_method_auralinux.h"
+#include "ui/base/ime/linux/input_method_auralinux.h"
 #else
 #include "ui/base/ime/input_method_minimal.h"
 #endif
diff --git a/ui/base/ime/input_method_factory.h b/ui/base/ime/init/input_method_factory.h
similarity index 67%
rename from ui/base/ime/input_method_factory.h
rename to ui/base/ime/init/input_method_factory.h
index 0f94731..ef2ac395 100644
--- a/ui/base/ime/input_method_factory.h
+++ b/ui/base/ime/init/input_method_factory.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_BASE_IME_INPUT_METHOD_FACTORY_H_
-#define UI_BASE_IME_INPUT_METHOD_FACTORY_H_
+#ifndef UI_BASE_IME_INIT_INPUT_METHOD_FACTORY_H_
+#define UI_BASE_IME_INIT_INPUT_METHOD_FACTORY_H_
 
 #include <memory>
 
 #include "base/compiler_specific.h"
 #include "base/component_export.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/gfx/native_widget_types.h"
 
 namespace ui {
@@ -20,16 +20,16 @@
 class InputMethod;
 
 // Creates a new instance of InputMethod and returns it.
-COMPONENT_EXPORT(UI_BASE_IME)
+COMPONENT_EXPORT(UI_BASE_IME_INIT)
 std::unique_ptr<InputMethod> CreateInputMethod(
     internal::InputMethodDelegate* delegate,
     gfx::AcceleratedWidget widget);
 
 // Makes CreateInputMethod return a MockInputMethod.
-COMPONENT_EXPORT(UI_BASE_IME) void SetUpInputMethodFactoryForTesting();
-COMPONENT_EXPORT(UI_BASE_IME)
+COMPONENT_EXPORT(UI_BASE_IME_INIT) void SetUpInputMethodFactoryForTesting();
+COMPONENT_EXPORT(UI_BASE_IME_INIT)
 void SetUpInputMethodForTesting(InputMethod* input_method);
 
 }  // namespace ui;
 
-#endif  // UI_BASE_IME_INPUT_METHOD_FACTORY_H_
+#endif  // UI_BASE_IME_INIT_INPUT_METHOD_FACTORY_H_
diff --git a/ui/base/ime/input_method_initializer.cc b/ui/base/ime/init/input_method_initializer.cc
similarity index 95%
rename from ui/base/ime/input_method_initializer.cc
rename to ui/base/ime/init/input_method_initializer.cc
index b64f362a..18250fb 100644
--- a/ui/base/ime/input_method_initializer.cc
+++ b/ui/base/ime/init/input_method_initializer.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 "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 
 #include "build/build_config.h"
 
@@ -12,7 +12,7 @@
 #include "base/logging.h"
 #include "ui/base/ime/linux/fake_input_method_context_factory.h"
 #elif defined(OS_WIN)
-#include "ui/base/ime/input_method_factory.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/win/tsf_bridge.h"
 #endif
 
diff --git a/ui/base/ime/input_method_initializer.h b/ui/base/ime/init/input_method_initializer.h
similarity index 64%
rename from ui/base/ime/input_method_initializer.h
rename to ui/base/ime/init/input_method_initializer.h
index 2105a88..924f356 100644
--- a/ui/base/ime/input_method_initializer.h
+++ b/ui/base/ime/init/input_method_initializer.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_BASE_IME_INPUT_METHOD_INITIALIZER_H_
-#define UI_BASE_IME_INPUT_METHOD_INITIALIZER_H_
+#ifndef UI_BASE_IME_INIT_INPUT_METHOD_INITIALIZER_H_
+#define UI_BASE_IME_INIT_INPUT_METHOD_INITIALIZER_H_
 
 #include "base/component_export.h"
 
@@ -11,20 +11,20 @@
 
 // Initializes thread-local resources for input method. This function should be
 // called in the UI thread before input method is used.
-COMPONENT_EXPORT(UI_BASE_IME) void InitializeInputMethod();
+COMPONENT_EXPORT(UI_BASE_IME_INIT) void InitializeInputMethod();
 
 // Shutdown thread-local resources for input method. This function should be
 // called in the UI thread after input method is used.
-COMPONENT_EXPORT(UI_BASE_IME) void ShutdownInputMethod();
+COMPONENT_EXPORT(UI_BASE_IME_INIT) void ShutdownInputMethod();
 
 // Initializes thread-local resources for input method. This function is
 // intended to be called from Setup function of unit tests.
-COMPONENT_EXPORT(UI_BASE_IME) void InitializeInputMethodForTesting();
+COMPONENT_EXPORT(UI_BASE_IME_INIT) void InitializeInputMethodForTesting();
 
 // Initializes thread-local resources for input method. This function is
 // intended to be called from TearDown function of unit tests.
-COMPONENT_EXPORT(UI_BASE_IME) void ShutdownInputMethodForTesting();
+COMPONENT_EXPORT(UI_BASE_IME_INIT) void ShutdownInputMethodForTesting();
 
 }  // namespace ui
 
-#endif  // UI_BASE_IME_INPUT_METHOD_INITIALIZER_H_
+#endif  // UI_BASE_IME_INIT_INPUT_METHOD_INITIALIZER_H_
diff --git a/ui/base/ime/input_method_minimal_unittest.cc b/ui/base/ime/input_method_minimal_unittest.cc
index 146b02a..f8d2a506 100644
--- a/ui/base/ime/input_method_minimal_unittest.cc
+++ b/ui/base/ime/input_method_minimal_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/ime/dummy_text_input_client.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/ime/input_method_delegate.h"
-#include "ui/base/ime/input_method_initializer.h"
 #include "ui/events/event.h"
 
 namespace ui {
diff --git a/ui/base/ime/linux/BUILD.gn b/ui/base/ime/linux/BUILD.gn
index 6469e32..6065ebc 100644
--- a/ui/base/ime/linux/BUILD.gn
+++ b/ui/base/ime/linux/BUILD.gn
@@ -3,6 +3,9 @@
 # found in the LICENSE file.
 
 import("//build/config/jumbo.gni")
+import("//build/config/linux/pangocairo/pangocairo.gni")
+
+assert(is_linux && !is_chromeos)
 
 jumbo_component("linux") {
   output_name = "ui_base_ime_linux"
@@ -11,18 +14,28 @@
     "fake_input_method_context.h",
     "fake_input_method_context_factory.cc",
     "fake_input_method_context_factory.h",
+    "input_method_auralinux.cc",
+    "input_method_auralinux.h",
     "linux_input_method_context.h",
     "linux_input_method_context_factory.cc",
     "linux_input_method_context_factory.h",
+    "text_edit_command_auralinux.cc",
+    "text_edit_command_auralinux.h",
+    "text_edit_key_bindings_delegate_auralinux.cc",
+    "text_edit_key_bindings_delegate_auralinux.h",
   ]
 
   defines = [ "IS_UI_BASE_IME_LINUX_IMPL" ]
 
-  deps = [
-    "//base",
+  public_deps = [
+    "//ui/base/ime",
   ]
 
-  public_deps = [
-    "//ui/base/ime:ime_types",
-  ]
+  if (use_pangocairo) {
+    configs += [ "//build/config/linux/pangocairo" ]
+    sources += [
+      "composition_text_util_pango.cc",
+      "composition_text_util_pango.h",
+    ]
+  }
 }
diff --git a/ui/base/ime/composition_text_util_pango.cc b/ui/base/ime/linux/composition_text_util_pango.cc
similarity index 97%
rename from ui/base/ime/composition_text_util_pango.cc
rename to ui/base/ime/linux/composition_text_util_pango.cc
index e5980f36..71c8ad3 100644
--- a/ui/base/ime/composition_text_util_pango.cc
+++ b/ui/base/ime/linux/composition_text_util_pango.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 "ui/base/ime/composition_text_util_pango.h"
+#include "ui/base/ime/linux/composition_text_util_pango.h"
 
 #include <pango/pango-attributes.h>
 #include <stddef.h>
@@ -14,7 +14,7 @@
 
 namespace ui {
 
-void ExtractCompositionTextFromGtkPreedit(const gchar* utf8_text,
+void ExtractCompositionTextFromGtkPreedit(const char* utf8_text,
                                           PangoAttrList* attrs,
                                           int cursor_position,
                                           CompositionText* composition) {
diff --git a/ui/base/ime/linux/composition_text_util_pango.h b/ui/base/ime/linux/composition_text_util_pango.h
new file mode 100644
index 0000000..4ad021a
--- /dev/null
+++ b/ui/base/ime/linux/composition_text_util_pango.h
@@ -0,0 +1,27 @@
+// 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 UI_BASE_IME_LINUX_COMPOSITION_TEXT_UTIL_PANGO_H_
+#define UI_BASE_IME_LINUX_COMPOSITION_TEXT_UTIL_PANGO_H_
+
+#include "base/component_export.h"
+
+typedef struct _PangoAttrList PangoAttrList;
+
+namespace ui {
+
+struct CompositionText;
+
+// Extracts composition text information (text, underlines, selection range)
+// from given Gtk preedit data (utf-8 text, pango attributes, cursor position).
+COMPONENT_EXPORT(UI_BASE_IME_LINUX)
+void ExtractCompositionTextFromGtkPreedit(
+    const char* utf8_text,
+    PangoAttrList* attrs,
+    int cursor_position,
+    CompositionText* composition);
+
+}  // namespace ui
+
+#endif  // UI_BASE_IME_LINUX_COMPOSITION_TEXT_UTIL_PANGO_H_
diff --git a/ui/base/ime/composition_text_util_pango_unittest.cc b/ui/base/ime/linux/composition_text_util_pango_unittest.cc
similarity index 98%
rename from ui/base/ime/composition_text_util_pango_unittest.cc
rename to ui/base/ime/linux/composition_text_util_pango_unittest.cc
index e097575..c75fbab 100644
--- a/ui/base/ime/composition_text_util_pango_unittest.cc
+++ b/ui/base/ime/linux/composition_text_util_pango_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/base/ime/composition_text_util_pango.h"
+#include "ui/base/ime/linux/composition_text_util_pango.h"
 
 #include <pango/pango-attributes.h>
 #include <stddef.h>
diff --git a/ui/base/ime/input_method_auralinux.cc b/ui/base/ime/linux/input_method_auralinux.cc
similarity index 99%
rename from ui/base/ime/input_method_auralinux.cc
rename to ui/base/ime/linux/input_method_auralinux.cc
index 9a79312..1bfa4258 100644
--- a/ui/base/ime/input_method_auralinux.cc
+++ b/ui/base/ime/linux/input_method_auralinux.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 "ui/base/ime/input_method_auralinux.h"
+#include "ui/base/ime/linux/input_method_auralinux.h"
 
 #include "base/auto_reset.h"
 #include "base/bind.h"
diff --git a/ui/base/ime/input_method_auralinux.h b/ui/base/ime/linux/input_method_auralinux.h
similarity index 94%
rename from ui/base/ime/input_method_auralinux.h
rename to ui/base/ime/linux/input_method_auralinux.h
index 199d561a..39e2094 100644
--- a/ui/base/ime/input_method_auralinux.h
+++ b/ui/base/ime/linux/input_method_auralinux.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_BASE_IME_INPUT_METHOD_AURALINUX_H_
-#define UI_BASE_IME_INPUT_METHOD_AURALINUX_H_
+#ifndef UI_BASE_IME_LINUX_INPUT_METHOD_AURALINUX_H_
+#define UI_BASE_IME_LINUX_INPUT_METHOD_AURALINUX_H_
 
 #include <memory>
 
@@ -18,7 +18,7 @@
 // A ui::InputMethod implementation for Aura on Linux platforms. The
 // implementation details are separated to ui::LinuxInputMethodContext
 // interface.
-class COMPONENT_EXPORT(UI_BASE_IME) InputMethodAuraLinux
+class COMPONENT_EXPORT(UI_BASE_IME_LINUX) InputMethodAuraLinux
     : public InputMethodBase,
       public LinuxInputMethodContextDelegate {
  public:
@@ -107,4 +107,4 @@
 
 }  // namespace ui
 
-#endif  // UI_BASE_IME_INPUT_METHOD_AURALINUX_H_
+#endif  // UI_BASE_IME_LINUX_INPUT_METHOD_AURALINUX_H_
diff --git a/ui/base/ime/input_method_auralinux_unittest.cc b/ui/base/ime/linux/input_method_auralinux_unittest.cc
similarity index 99%
rename from ui/base/ime/input_method_auralinux_unittest.cc
rename to ui/base/ime/linux/input_method_auralinux_unittest.cc
index 594e063..ad01a466 100644
--- a/ui/base/ime/input_method_auralinux_unittest.cc
+++ b/ui/base/ime/linux/input_method_auralinux_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/base/ime/input_method_auralinux.h"
+#include "ui/base/ime/linux/input_method_auralinux.h"
 
 #include <stddef.h>
 
@@ -12,8 +12,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/ime/dummy_text_input_client.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/ime/input_method_delegate.h"
-#include "ui/base/ime/input_method_initializer.h"
 #include "ui/base/ime/linux/fake_input_method_context.h"
 #include "ui/base/ime/linux/linux_input_method_context_factory.h"
 #include "ui/events/event.h"
diff --git a/ui/base/ime/linux/text_edit_command_auralinux.h b/ui/base/ime/linux/text_edit_command_auralinux.h
index 4eda237..fbdc396 100644
--- a/ui/base/ime/linux/text_edit_command_auralinux.h
+++ b/ui/base/ime/linux/text_edit_command_auralinux.h
@@ -15,7 +15,7 @@
 
 // Represents a command that performs a specific operation on text.
 // Copy and assignment are explicitly allowed; these objects live in vectors.
-class COMPONENT_EXPORT(UI_BASE_IME) TextEditCommandAuraLinux {
+class COMPONENT_EXPORT(UI_BASE_IME_LINUX) TextEditCommandAuraLinux {
  public:
   TextEditCommandAuraLinux(TextEditCommand command, const std::string& argument)
       : command_(command), argument_(argument) {}
diff --git a/ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h b/ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h
index fb1e479c..560929a 100644
--- a/ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h
+++ b/ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h
@@ -18,7 +18,7 @@
 //
 // On desktop Linux, we've traditionally supported the user's custom
 // keybindings. We need to support this in both content/ and in views/.
-class COMPONENT_EXPORT(UI_BASE_IME) TextEditKeyBindingsDelegateAuraLinux {
+class COMPONENT_EXPORT(UI_BASE_IME_LINUX) TextEditKeyBindingsDelegateAuraLinux {
  public:
   // Matches a key event against the users' platform specific key bindings,
   // false will be returned if the key event doesn't correspond to a predefined
@@ -33,10 +33,10 @@
 
 // Sets/Gets the global TextEditKeyBindingsDelegateAuraLinux. No ownership
 // changes. Can be NULL.
-COMPONENT_EXPORT(UI_BASE_IME)
+COMPONENT_EXPORT(UI_BASE_IME_LINUX)
 void SetTextEditKeyBindingsDelegate(
     TextEditKeyBindingsDelegateAuraLinux* delegate);
-COMPONENT_EXPORT(UI_BASE_IME)
+COMPONENT_EXPORT(UI_BASE_IME_LINUX)
 TextEditKeyBindingsDelegateAuraLinux* GetTextEditKeyBindingsDelegate();
 
 }  // namespace ui
diff --git a/ui/base/ime/mac/BUILD.gn b/ui/base/ime/mac/BUILD.gn
new file mode 100644
index 0000000..30bab06
--- /dev/null
+++ b/ui/base/ime/mac/BUILD.gn
@@ -0,0 +1,24 @@
+# Copyright 2019 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")
+
+assert(is_mac)
+
+jumbo_component("mac") {
+  output_name = "ui_base_ime_mac"
+
+  sources = [
+    "input_method_mac.h",
+    "input_method_mac.mm",
+  ]
+
+  defines = [ "IS_UI_BASE_IME_MAC_IMPL" ]
+
+  public_deps = [
+    "//ui/base/ime",
+  ]
+
+  libs = [ "AppKit.framework" ]
+}
diff --git a/ui/base/ime/input_method_mac.h b/ui/base/ime/mac/input_method_mac.h
similarity index 81%
rename from ui/base/ime/input_method_mac.h
rename to ui/base/ime/mac/input_method_mac.h
index d547379d..304b103 100644
--- a/ui/base/ime/input_method_mac.h
+++ b/ui/base/ime/mac/input_method_mac.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_BASE_IME_INPUT_METHOD_MAC_H_
-#define UI_BASE_IME_INPUT_METHOD_MAC_H_
+#ifndef UI_BASE_IME_MAC_INPUT_METHOD_MAC_H_
+#define UI_BASE_IME_MAC_INPUT_METHOD_MAC_H_
 
 #include "base/component_export.h"
 #include "base/macros.h"
@@ -15,7 +15,8 @@
 // On the Mac, key events don't pass through InputMethod.
 // Instead, NSTextInputClient calls are bridged to the currently focused
 // ui::TextInputClient object.
-class COMPONENT_EXPORT(UI_BASE_IME) InputMethodMac : public InputMethodBase {
+class COMPONENT_EXPORT(UI_BASE_IME_MAC) InputMethodMac
+    : public InputMethodBase {
  public:
   explicit InputMethodMac(internal::InputMethodDelegate* delegate);
   ~InputMethodMac() override;
@@ -32,4 +33,4 @@
 
 }  // namespace ui
 
-#endif  // UI_BASE_IME_INPUT_METHOD_MAC_H_
+#endif  // UI_BASE_IME_MAC_INPUT_METHOD_MAC_H_
diff --git a/ui/base/ime/input_method_mac.mm b/ui/base/ime/mac/input_method_mac.mm
similarity index 95%
rename from ui/base/ime/input_method_mac.mm
rename to ui/base/ime/mac/input_method_mac.mm
index f23bce9..d7a6cd89 100644
--- a/ui/base/ime/input_method_mac.mm
+++ b/ui/base/ime/mac/input_method_mac.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.
 
-#include "ui/base/ime/input_method_mac.h"
+#include "ui/base/ime/mac/input_method_mac.h"
 
 #import <Cocoa/Cocoa.h>
 
diff --git a/ui/base/ime/mock_input_method.h b/ui/base/ime/mock_input_method.h
index 58104ab..2d72e99a 100644
--- a/ui/base/ime/mock_input_method.h
+++ b/ui/base/ime/mock_input_method.h
@@ -24,7 +24,7 @@
 // A mock ui::InputMethod implementation for testing. You can get the instance
 // of this class as the global input method with calling
 // SetUpInputMethodFactoryForTesting() which is declared in
-// ui/base/ime/input_method_factory.h
+// ui/base/ime/init/input_method_factory.h
 class COMPONENT_EXPORT(UI_BASE_IME) MockInputMethod : public InputMethod {
  public:
   explicit MockInputMethod(internal::InputMethodDelegate* delegate);
diff --git a/ui/base/ime/mojo/ime_types.typemap b/ui/base/ime/mojo/ime_types.typemap
index acdc8fff..4e800fc6 100644
--- a/ui/base/ime/mojo/ime_types.typemap
+++ b/ui/base/ime/mojo/ime_types.typemap
@@ -15,7 +15,7 @@
   "//ui/base/ime/mojo/ime_types_struct_traits.cc",
 ]
 public_deps = [
-  "//ui/base/ime:ime_types",
+  "//ui/base/ime",
 ]
 deps = [
   "//ui/gfx/range",
diff --git a/ui/base/ime/win/BUILD.gn b/ui/base/ime/win/BUILD.gn
new file mode 100644
index 0000000..e241603
--- /dev/null
+++ b/ui/base/ime/win/BUILD.gn
@@ -0,0 +1,53 @@
+# Copyright 2019 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")
+
+assert(is_win)
+
+jumbo_component("win") {
+  output_name = "ui_base_ime_win"
+  sources = [
+    "imm32_manager.cc",
+    "imm32_manager.h",
+    "input_method_win_base.cc",
+    "input_method_win_base.h",
+    "input_method_win_imm32.cc",
+    "input_method_win_imm32.h",
+    "input_method_win_tsf.cc",
+    "input_method_win_tsf.h",
+    "on_screen_keyboard_display_manager_input_pane.cc",
+    "on_screen_keyboard_display_manager_input_pane.h",
+    "on_screen_keyboard_display_manager_tab_tip.cc",
+    "on_screen_keyboard_display_manager_tab_tip.h",
+    "tsf_bridge.cc",
+    "tsf_bridge.h",
+    "tsf_event_router.cc",
+    "tsf_event_router.h",
+    "tsf_input_scope.cc",
+    "tsf_input_scope.h",
+    "tsf_text_store.cc",
+    "tsf_text_store.h",
+  ]
+
+  defines = [ "IS_UI_BASE_IME_WIN_IMPL" ]
+
+  public_deps = [
+    "//ui/base/ime",
+  ]
+
+  deps = [
+    "//ui/base",
+    "//ui/display",
+  ]
+
+  libs = [ "imm32.lib" ]
+
+  jumbo_excluded_sources = [
+    # tsf_text_store.cc needs INITGUID to be defined before
+    # including any header to properly generate GUID objects. That
+    # is not guaranteed when included in a jumbo build.
+    "tsf_text_store.cc",
+  ]
+}
diff --git a/ui/base/ime/win/imm32_manager.h b/ui/base/ime/win/imm32_manager.h
index fcd29d3e..958b3c1 100644
--- a/ui/base/ime/win/imm32_manager.h
+++ b/ui/base/ime/win/imm32_manager.h
@@ -74,7 +74,7 @@
 //   hand, we can NEVER disable either TSF or CUAS in Windows Vista, i.e.
 //   THIS CLASS IS NOT ONLY USED ON THE INPUT CONTEXTS OF EAST-ASIAN
 //   LANGUAGES BUT ALSO USED ON THE INPUT CONTEXTS OF ALL LANGUAGES.
-class COMPONENT_EXPORT(UI_BASE_IME) IMM32Manager {
+class COMPONENT_EXPORT(UI_BASE_IME_WIN) IMM32Manager {
  public:
   IMM32Manager();
   virtual ~IMM32Manager();
diff --git a/ui/base/ime/input_method_win_base.cc b/ui/base/ime/win/input_method_win_base.cc
similarity index 99%
rename from ui/base/ime/input_method_win_base.cc
rename to ui/base/ime/win/input_method_win_base.cc
index bd7edb1..7de0c93 100644
--- a/ui/base/ime/input_method_win_base.cc
+++ b/ui/base/ime/win/input_method_win_base.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 "ui/base/ime/input_method_win_base.h"
+#include "ui/base/ime/win/input_method_win_base.h"
 
 #include <stddef.h>
 #include <stdint.h>
diff --git a/ui/base/ime/input_method_win_base.h b/ui/base/ime/win/input_method_win_base.h
similarity index 93%
rename from ui/base/ime/input_method_win_base.h
rename to ui/base/ime/win/input_method_win_base.h
index 3d9a513..ed4cddc 100644
--- a/ui/base/ime/input_method_win_base.h
+++ b/ui/base/ime/win/input_method_win_base.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_BASE_IME_INPUT_METHOD_WIN_BASE_H_
-#define UI_BASE_IME_INPUT_METHOD_WIN_BASE_H_
+#ifndef UI_BASE_IME_WIN_INPUT_METHOD_WIN_BASE_H_
+#define UI_BASE_IME_WIN_INPUT_METHOD_WIN_BASE_H_
 
 #include <windows.h>
 
@@ -18,7 +18,7 @@
 namespace ui {
 
 // A common InputMethod base implementation for Windows.
-class COMPONENT_EXPORT(UI_BASE_IME) InputMethodWinBase
+class COMPONENT_EXPORT(UI_BASE_IME_WIN) InputMethodWinBase
     : public InputMethodBase {
  public:
   InputMethodWinBase(internal::InputMethodDelegate* delegate,
@@ -97,4 +97,4 @@
 
 }  // namespace ui
 
-#endif  // UI_BASE_IME_INPUT_METHOD_WIN_BASE_H_
+#endif  // UI_BASE_IME_WIN_INPUT_METHOD_WIN_BASE_H_
diff --git a/ui/base/ime/input_method_win_imm32.cc b/ui/base/ime/win/input_method_win_imm32.cc
similarity index 99%
rename from ui/base/ime/input_method_win_imm32.cc
rename to ui/base/ime/win/input_method_win_imm32.cc
index 48ebd26..15030eb 100644
--- a/ui/base/ime/input_method_win_imm32.cc
+++ b/ui/base/ime/win/input_method_win_imm32.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 "ui/base/ime/input_method_win_imm32.h"
+#include "ui/base/ime/win/input_method_win_imm32.h"
 
 #include <stddef.h>
 #include <stdint.h>
diff --git a/ui/base/ime/input_method_win_imm32.h b/ui/base/ime/win/input_method_win_imm32.h
similarity index 92%
rename from ui/base/ime/input_method_win_imm32.h
rename to ui/base/ime/win/input_method_win_imm32.h
index 62f4a40..819912d 100644
--- a/ui/base/ime/input_method_win_imm32.h
+++ b/ui/base/ime/win/input_method_win_imm32.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_BASE_IME_INPUT_METHOD_WIN_IMM32_H_
-#define UI_BASE_IME_INPUT_METHOD_WIN_IMM32_H_
+#ifndef UI_BASE_IME_WIN_INPUT_METHOD_WIN_IMM32_H_
+#define UI_BASE_IME_WIN_INPUT_METHOD_WIN_IMM32_H_
 
 #include <windows.h>
 
@@ -12,13 +12,13 @@
 #include "base/compiler_specific.h"
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "ui/base/ime/input_method_win_base.h"
 #include "ui/base/ime/win/imm32_manager.h"
+#include "ui/base/ime/win/input_method_win_base.h"
 
 namespace ui {
 
 // A common InputMethod implementation based on IMM32.
-class COMPONENT_EXPORT(UI_BASE_IME) InputMethodWinImm32
+class COMPONENT_EXPORT(UI_BASE_IME_WIN) InputMethodWinImm32
     : public InputMethodWinBase {
  public:
   InputMethodWinImm32(internal::InputMethodDelegate* delegate,
@@ -100,4 +100,4 @@
 
 }  // namespace ui
 
-#endif  // UI_BASE_IME_INPUT_METHOD_WIN_IMM32_H_
+#endif  // UI_BASE_IME_WIN_INPUT_METHOD_WIN_IMM32_H_
diff --git a/ui/base/ime/input_method_win_tsf.cc b/ui/base/ime/win/input_method_win_tsf.cc
similarity index 98%
rename from ui/base/ime/input_method_win_tsf.cc
rename to ui/base/ime/win/input_method_win_tsf.cc
index f84b5e3..5eff607 100644
--- a/ui/base/ime/input_method_win_tsf.cc
+++ b/ui/base/ime/win/input_method_win_tsf.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 "ui/base/ime/input_method_win_tsf.h"
+#include "ui/base/ime/win/input_method_win_tsf.h"
 
 #include "ui/base/ime/text_input_client.h"
 #include "ui/base/ime/win/tsf_bridge.h"
diff --git a/ui/base/ime/input_method_win_tsf.h b/ui/base/ime/win/input_method_win_tsf.h
similarity index 86%
rename from ui/base/ime/input_method_win_tsf.h
rename to ui/base/ime/win/input_method_win_tsf.h
index e3c0eedf..b04867d6 100644
--- a/ui/base/ime/input_method_win_tsf.h
+++ b/ui/base/ime/win/input_method_win_tsf.h
@@ -2,22 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_BASE_IME_INPUT_METHOD_WIN_TSF_H_
-#define UI_BASE_IME_INPUT_METHOD_WIN_TSF_H_
+#ifndef UI_BASE_IME_WIN_INPUT_METHOD_WIN_TSF_H_
+#define UI_BASE_IME_WIN_INPUT_METHOD_WIN_TSF_H_
 
 #include <windows.h>
 
 #include <string>
 
 #include "base/component_export.h"
-#include "ui/base/ime/input_method_win_base.h"
+#include "ui/base/ime/win/input_method_win_base.h"
 
 namespace ui {
 
 class TSFEventRouter;
 
 // An InputMethod implementation based on Windows TSF API.
-class COMPONENT_EXPORT(UI_BASE_IME) InputMethodWinTSF
+class COMPONENT_EXPORT(UI_BASE_IME_WIN) InputMethodWinTSF
     : public InputMethodWinBase {
  public:
   InputMethodWinTSF(internal::InputMethodDelegate* delegate,
@@ -56,4 +56,4 @@
 
 }  // namespace ui
 
-#endif  // UI_BASE_IME_INPUT_METHOD_WIN_TSF_H_
+#endif  // UI_BASE_IME_WIN_INPUT_METHOD_WIN_TSF_H_
diff --git a/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h b/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h
index aa7319c..5edbb96 100644
--- a/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h
+++ b/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h
@@ -26,7 +26,7 @@
 
 // This class provides an implementation of the OnScreenKeyboardDisplayManager
 // that uses InputPane which is available on Windows >= 10.0.10240.0.
-class COMPONENT_EXPORT(UI_BASE_IME)
+class COMPONENT_EXPORT(UI_BASE_IME_WIN)
     OnScreenKeyboardDisplayManagerInputPane final
     : public InputMethodKeyboardController {
  public:
diff --git a/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h b/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h
index 8fa8d1f..c32989e 100644
--- a/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h
+++ b/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h
@@ -21,7 +21,8 @@
 // This class provides an implementation of the InputMethodKeyboardController
 // that uses heuristics and the TabTip.exe to display the on screen keyboard.
 // Used on Windows > 7 and Windows < 10.0.10240.0
-class COMPONENT_EXPORT(UI_BASE_IME) OnScreenKeyboardDisplayManagerTabTip final
+class COMPONENT_EXPORT(UI_BASE_IME_WIN)
+    OnScreenKeyboardDisplayManagerTabTip final
     : public InputMethodKeyboardController {
  public:
   OnScreenKeyboardDisplayManagerTabTip(HWND hwnd);
diff --git a/ui/base/ime/win/tsf_bridge.h b/ui/base/ime/win/tsf_bridge.h
index f7ada4b73..2fbc7bf 100644
--- a/ui/base/ime/win/tsf_bridge.h
+++ b/ui/base/ime/win/tsf_bridge.h
@@ -26,7 +26,7 @@
 // of text inputting and current focused TextInputClient.
 //
 // All methods in this class must be used in UI thread.
-class COMPONENT_EXPORT(UI_BASE_IME) TSFBridge {
+class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFBridge {
  public:
   virtual ~TSFBridge();
 
diff --git a/ui/base/ime/win/tsf_event_router.h b/ui/base/ime/win/tsf_event_router.h
index 9f09d7e..9e950f3 100644
--- a/ui/base/ime/win/tsf_event_router.h
+++ b/ui/base/ime/win/tsf_event_router.h
@@ -44,7 +44,7 @@
 
 // This class monitors TSF related events and forwards them to given
 // |observer|.
-class COMPONENT_EXPORT(UI_BASE_IME) TSFEventRouter {
+class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFEventRouter {
  public:
   // Do not pass NULL to |observer|.
   explicit TSFEventRouter(TSFEventRouterObserver* observer);
diff --git a/ui/base/ime/win/tsf_input_scope.h b/ui/base/ime/win/tsf_input_scope.h
index a9ea345..a895cb13 100644
--- a/ui/base/ime/win/tsf_input_scope.h
+++ b/ui/base/ime/win/tsf_input_scope.h
@@ -18,12 +18,12 @@
 
 // Initializes the TSF for input scopes. It loads the tsf dll and get the
 // function pointer for setting the input scopes in TSF.
-COMPONENT_EXPORT(UI_BASE_IME) void InitializeTsfForInputScopes();
+COMPONENT_EXPORT(UI_BASE_IME_WIN) void InitializeTsfForInputScopes();
 
 // Returns InputScope list corresoponding to ui::TextInputType and
 // ui::TextInputMode.
 // This function is only used from following functions but declared for test.
-COMPONENT_EXPORT(UI_BASE_IME)
+COMPONENT_EXPORT(UI_BASE_IME_WIN)
 std::vector<InputScope> GetInputScopes(TextInputType text_input_type,
                                        TextInputMode text_input_mode);
 
@@ -33,7 +33,7 @@
 // in the target field.
 // The returned instance has 0 reference count. The caller must maintain its
 // reference count.
-COMPONENT_EXPORT(UI_BASE_IME)
+COMPONENT_EXPORT(UI_BASE_IME_WIN)
 ITfInputScope* CreateInputScope(TextInputType text_input_type,
                                 TextInputMode text_input_mode);
 
@@ -41,7 +41,7 @@
 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms629026.aspx
 // Does nothing on Windows XP in case TSF is disabled.
 // NOTE: For TSF-aware window, you should use ITfInputScope instead.
-COMPONENT_EXPORT(UI_BASE_IME)
+COMPONENT_EXPORT(UI_BASE_IME_WIN)
 void SetInputScopeForTsfUnawareWindow(HWND window_handle,
                                       TextInputType text_input_type,
                                       TextInputMode text_input_mode);
diff --git a/ui/base/ime/win/tsf_text_store.cc b/ui/base/ime/win/tsf_text_store.cc
index 602c5523..5ff63417 100644
--- a/ui/base/ime/win/tsf_text_store.cc
+++ b/ui/base/ime/win/tsf_text_store.cc
@@ -300,42 +300,48 @@
   const uint32_t end_pos = acp_end - composition_start_;
 
   if (start_pos == end_pos) {
-    // According to MSDN document, if |acp_start| and |acp_end| are equal it is
-    // OK to just return E_INVALIDARG.
-    // http://msdn.microsoft.com/en-us/library/ms538435
-    // But when using Pinin IME of Windows 8, this method is called with the
-    // equal values of |acp_start| and |acp_end|. So we handle this condition.
-    if (start_pos == 0) {
-      if (text_input_client_->GetCompositionCharacterBounds(0, &tmp_rect)) {
+    if (text_input_client_->HasCompositionText()) {
+      // According to MSDN document, if |acp_start| and |acp_end| are equal it
+      // is OK to just return E_INVALIDARG.
+      // http://msdn.microsoft.com/en-us/library/ms538435
+      // But when using Pinin IME of Windows 8, this method is called with the
+      // equal values of |acp_start| and |acp_end|. So we handle this condition.
+      if (start_pos == 0) {
+        if (text_input_client_->GetCompositionCharacterBounds(0, &tmp_rect)) {
+          tmp_rect.set_width(0);
+          result_rect = gfx::Rect(tmp_rect);
+        } else {
+          return TS_E_NOLAYOUT;
+        }
+      } else if (text_input_client_->GetCompositionCharacterBounds(
+                     start_pos - 1, &tmp_rect)) {
+        tmp_rect.set_x(tmp_rect.right());
         tmp_rect.set_width(0);
         result_rect = gfx::Rect(tmp_rect);
-      } else if (string_buffer_document_.size() == composition_start_) {
-        result_rect = gfx::Rect(text_input_client_->GetCaretBounds());
+
       } else {
         return TS_E_NOLAYOUT;
       }
-    } else if (text_input_client_->GetCompositionCharacterBounds(start_pos - 1,
-                                                                 &tmp_rect)) {
-      tmp_rect.set_x(tmp_rect.right());
-      tmp_rect.set_width(0);
-      result_rect = gfx::Rect(tmp_rect);
-
     } else {
-      return TS_E_NOLAYOUT;
+      result_rect = gfx::Rect(text_input_client_->GetCaretBounds());
     }
   } else {
-    if (text_input_client_->GetCompositionCharacterBounds(start_pos,
-                                                          &tmp_rect)) {
-      result_rect = gfx::Rect(tmp_rect);
-      if (text_input_client_->GetCompositionCharacterBounds(end_pos - 1,
+    if (text_input_client_->HasCompositionText()) {
+      if (text_input_client_->GetCompositionCharacterBounds(start_pos,
                                                             &tmp_rect)) {
-        result_rect.set_width(tmp_rect.x() - result_rect.x() +
-                              tmp_rect.width());
-        result_rect.set_height(tmp_rect.y() - result_rect.y() +
-                               tmp_rect.height());
+        result_rect = gfx::Rect(tmp_rect);
+        if (text_input_client_->GetCompositionCharacterBounds(end_pos - 1,
+                                                              &tmp_rect)) {
+          result_rect.set_width(tmp_rect.x() - result_rect.x() +
+                                tmp_rect.width());
+          result_rect.set_height(tmp_rect.y() - result_rect.y() +
+                                 tmp_rect.height());
+        } else {
+          // We may not be able to get the last character bounds, so we use the
+          // first character bounds instead of returning TS_E_NOLAYOUT.
+        }
       } else {
-        // We may not be able to get the last character bounds, so we use the
-        // first character bounds instead of returning TS_E_NOLAYOUT.
+        return TS_E_NOLAYOUT;
       }
     } else {
       // Hack for PPAPI flash. PPAPI flash does not support GetCaretBounds, so
@@ -583,8 +589,12 @@
   // TextInputClient::InsertText to complete the current composition. When there
   // are some committed text, it is not necessarily true that composition_string
   // is empty. We need to complete current composition with committed text and
-  // start new composition with composition_string.
-  if ((new_composition_start > last_composition_start) && text_input_client_) {
+  // start new composition with composition_string. Another scenario would be if
+  // the replacement text is coming from on-screen keyboard, we should replace
+  // current selection with new text.
+  if (((new_composition_start > last_composition_start) ||
+       (wparam_keydown_fired_ == 0 && !has_composition_range_)) &&
+      text_input_client_) {
     CommitTextAndEndCompositionIfAny(last_composition_start,
                                      new_composition_start);
   }
@@ -1003,10 +1013,16 @@
       return;
     }
 
+    bool notify_text_change =
+        (text_store_acp_sink_mask_ & TS_AS_TEXT_CHANGE) != 0;
+    bool notify_selection_change =
+        (text_store_acp_sink_mask_ & TS_AS_SEL_CHANGE) != 0;
+
+    bool text_changed = false;
+    bool selection_changed = false;
+    TS_TEXTCHANGE text_change = {};
+
     if (latest_buffer_from_client.compare(string_buffer_document_)) {
-      TS_TEXTCHANGE text_change = {};
-      bool notify_text_change =
-          (text_store_acp_sink_mask_ & TS_AS_TEXT_CHANGE) != 0;
 
       // Execute diffing algorithm only if we need to send notification.
       if (notify_text_change) {
@@ -1024,18 +1040,22 @@
           }
         }
 
-        // if two strings have same length, find last difference.
-        if (latest_buffer_from_client.size() ==
-            string_buffer_document_.size()) {
-          for (acp_new_end = latest_buffer_from_client.size() - 1;
-               acp_new_end > acp_start; acp_new_end--) {
+        // Compare two strings to find last difference.
+        while (acp_old_end > 0 && acp_new_end > 0) {
+          acp_old_end--;
+          acp_new_end--;
+          if (acp_old_end >= acp_start && acp_new_end >= acp_start) {
             if (latest_buffer_from_client.at(acp_new_end) !=
-                string_buffer_document_.at(acp_new_end)) {
+                string_buffer_document_.at(acp_old_end)) {
+              acp_old_end++;
+              acp_new_end++;
               break;
             }
+          } else {
+            acp_old_end++;
+            acp_new_end++;
+            break;
           }
-          acp_new_end = acp_new_end + 1;
-          acp_old_end = acp_new_end;
         }
 
         text_change.acpStart = acp_start;
@@ -1044,19 +1064,25 @@
       }
 
       string_buffer_document_ = latest_buffer_from_client;
-
-      if (notify_text_change) {
-        text_store_acp_sink_->OnTextChange(0, &text_change);
-      }
+      text_changed = true;
     }
 
     if (!selection_.EqualsIgnoringDirection(latest_selection_from_client)) {
       selection_.set_start(latest_selection_from_client.GetMin());
       selection_.set_end(latest_selection_from_client.GetMax());
 
-      if (text_store_acp_sink_mask_ & TS_AS_SEL_CHANGE) {
-        text_store_acp_sink_->OnSelectionChange();
-      }
+      selection_changed = true;
+    }
+
+    // We should notify input service about text/selection change only after
+    // the cache has already been updated because input service may call back
+    // into us during notification.
+    if (notify_text_change && text_changed) {
+      text_store_acp_sink_->OnTextChange(0, &text_change);
+    }
+
+    if (notify_selection_change && selection_changed) {
+      text_store_acp_sink_->OnSelectionChange();
     }
   }
 }
diff --git a/ui/base/ime/win/tsf_text_store.h b/ui/base/ime/win/tsf_text_store.h
index afe21967..51f7261 100644
--- a/ui/base/ime/win/tsf_text_store.h
+++ b/ui/base/ime/win/tsf_text_store.h
@@ -99,7 +99,7 @@
 //
 // More information about TSF can be found here:
 //   http://msdn.microsoft.com/en-us/library/ms629032
-class COMPONENT_EXPORT(UI_BASE_IME) TSFTextStore
+class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore
     : public ITextStoreACP,
       public ITfContextOwnerCompositionSink,
       public ITfKeyTraceEventSink,
diff --git a/ui/base/ime/win/tsf_text_store_unittest.cc b/ui/base/ime/win/tsf_text_store_unittest.cc
index 4fc9685..ab48cf0 100644
--- a/ui/base/ime/win/tsf_text_store_unittest.cc
+++ b/ui/base/ime/win/tsf_text_store_unittest.cc
@@ -1117,6 +1117,8 @@
     composition_range()->set_start(0);
     composition_range()->set_end(5);
 
+    // Need to set |has_composition_range_| to indicate composition scenario.
+    *has_composition_range() = true;
     return S_OK;
   }
 
@@ -1211,6 +1213,7 @@
   HRESULT LockGranted(DWORD flags) {
     SetInternalState(L"0123456789012", 0, 0, 0);
     layout_prepared_character_num_ = 13;
+    has_composition_text_ = true;
 
     TsViewCookie view_cookie = 0;
     EXPECT_EQ(S_OK, text_store_->GetActiveView(&view_cookie));
@@ -1231,7 +1234,8 @@
     GetTextExtNoLayoutTest(view_cookie, 13, 13);
 
     layout_prepared_character_num_ = 0;
-    GetTextExtNoLayoutTest(view_cookie, 0, 0);
+    has_composition_text_ = false;
+    GetTextExtTest(view_cookie, 0, 0, 1, 2, 4, 6);
 
     SetInternalState(L"", 0, 0, 0);
     GetTextExtTest(view_cookie, 0, 0, 1, 2, 4, 6);
@@ -1241,12 +1245,14 @@
     // bounds.
     SetInternalState(L"abc", 0, 0, 3);
     layout_prepared_character_num_ = 2;
+    has_composition_text_ = true;
     GetTextExtTest(view_cookie, 0, 0, 11, 12, 11, 20);
 
     // TODO(nona, kinaba): Remove following test case after PPAPI supporting
     // GetCompositionCharacterBounds.
     SetInternalState(L"a", 0, 0, 1);
     layout_prepared_character_num_ = 0;
+    has_composition_text_ = false;
     GetTextExtTest(view_cookie, 0, 1, 1, 2, 4, 6);
     return S_OK;
   }
@@ -1263,8 +1269,11 @@
 
   gfx::Rect GetCaretBounds() { return gfx::Rect(1, 2, 3, 4); }
 
+  bool ClientHasCompositionText() { return has_composition_text_; }
+
  private:
   uint32_t layout_prepared_character_num_;
+  bool has_composition_text_;
 
   DISALLOW_COPY_AND_ASSIGN(GetTextExtTestCallback);
 };
@@ -1279,6 +1288,10 @@
       .WillRepeatedly(Invoke(
           &callback, &GetTextExtTestCallback::GetCompositionCharacterBounds));
 
+  EXPECT_CALL(text_input_client_, HasCompositionText())
+      .WillRepeatedly(
+          Invoke(&callback, &GetTextExtTestCallback::ClientHasCompositionText));
+
   EXPECT_CALL(*sink_, OnLockGranted(_))
       .WillOnce(Invoke(&callback, &GetTextExtTestCallback::LockGranted));
 
@@ -1567,6 +1580,10 @@
 // 8.  renderer proc changes buffer from "" to "OPQ".
 // 9.  renderer proc changes buffer from "OPQ" to "OPR".
 // 10. renderer proc changes buffer from "OPR" to "SPR".
+// 11. renderer proc changes buffer from "SPR" to "STPR".
+// 12. renderer proc changes buffer from "STPR" to "PR".
+// 13. renderer proc changes buffer from "PR" to "UPR".
+// 14. renderer proc changes buffer from "UPR" to "UPVWR".
 class DiffingAlgorithmTestCallback : public TSFTextStoreTestCallback {
  public:
   explicit DiffingAlgorithmTestCallback(TSFTextStore* text_store)
@@ -1916,6 +1933,153 @@
     GetSelectionTest(0, 1);
     return S_OK;
   }
+  // 11. renderer proc changes buffer from "SPR" to "STPR".
+  HRESULT LockGranted11(DWORD flags) {
+    SetTextRange(0, 4);
+    SetTextBuffer(L"STPR");
+    SetSelectionRange(2, 2);
+    return S_OK;
+  }
+
+  HRESULT OnTextChange11(DWORD flag, const TS_TEXTCHANGE* pChange) {
+    HRESULT result = S_OK;
+    EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+    EXPECT_EQ(1, pChange->acpStart);
+    EXPECT_EQ(1, pChange->acpOldEnd);
+    EXPECT_EQ(2, pChange->acpNewEnd);
+
+    EXPECT_EQ(S_OK, result);
+    return S_OK;
+  }
+
+  HRESULT LockGranted11a(DWORD flags) {
+    GetTextTest(1, 2, L"T", 2);
+
+    return S_OK;
+  }
+
+  HRESULT OnSelectionChange11() {
+    HRESULT result = S_OK;
+    EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+    EXPECT_EQ(S_OK, result);
+    return S_OK;
+  }
+
+  HRESULT LockGranted11b(DWORD flags) {
+    GetSelectionTest(2, 2);
+    return S_OK;
+  }
+
+  // 12. renderer proc changes buffer from "STPR" to "PR".
+  HRESULT LockGranted12(DWORD flags) {
+    SetTextRange(0, 2);
+    SetTextBuffer(L"PR");
+    SetSelectionRange(0, 0);
+    return S_OK;
+  }
+
+  HRESULT OnTextChange12(DWORD flag, const TS_TEXTCHANGE* pChange) {
+    HRESULT result = S_OK;
+    EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+    EXPECT_EQ(0, pChange->acpStart);
+    EXPECT_EQ(2, pChange->acpOldEnd);
+    EXPECT_EQ(0, pChange->acpNewEnd);
+
+    EXPECT_EQ(S_OK, result);
+    return S_OK;
+  }
+
+  HRESULT LockGranted12a(DWORD flags) {
+    GetTextTest(0, 2, L"PR", 2);
+
+    return S_OK;
+  }
+
+  HRESULT OnSelectionChange12() {
+    HRESULT result = S_OK;
+    EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+    EXPECT_EQ(S_OK, result);
+    return S_OK;
+  }
+
+  HRESULT LockGranted12b(DWORD flags) {
+    GetSelectionTest(0, 0);
+    return S_OK;
+  }
+
+  // 13. renderer proc changes buffer from "PR" to "UPR".
+  HRESULT LockGranted13(DWORD flags) {
+    SetTextRange(0, 3);
+    SetTextBuffer(L"UPR");
+    SetSelectionRange(1, 1);
+    return S_OK;
+  }
+
+  HRESULT OnTextChange13(DWORD flag, const TS_TEXTCHANGE* pChange) {
+    HRESULT result = S_OK;
+    EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+    EXPECT_EQ(0, pChange->acpStart);
+    EXPECT_EQ(0, pChange->acpOldEnd);
+    EXPECT_EQ(1, pChange->acpNewEnd);
+
+    EXPECT_EQ(S_OK, result);
+    return S_OK;
+  }
+
+  HRESULT LockGranted13a(DWORD flags) {
+    GetTextTest(0, 1, L"U", 1);
+
+    return S_OK;
+  }
+
+  HRESULT OnSelectionChange13() {
+    HRESULT result = S_OK;
+    EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+    EXPECT_EQ(S_OK, result);
+    return S_OK;
+  }
+
+  HRESULT LockGranted13b(DWORD flags) {
+    GetSelectionTest(1, 1);
+    return S_OK;
+  }
+
+  // 14. renderer proc changes buffer from "UPR" to "UPVWR".
+  HRESULT LockGranted14(DWORD flags) {
+    SetTextRange(0, 5);
+    SetTextBuffer(L"UPVWR");
+    SetSelectionRange(4, 4);
+    return S_OK;
+  }
+
+  HRESULT OnTextChange14(DWORD flag, const TS_TEXTCHANGE* pChange) {
+    HRESULT result = S_OK;
+    EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+    EXPECT_EQ(2, pChange->acpStart);
+    EXPECT_EQ(2, pChange->acpOldEnd);
+    EXPECT_EQ(4, pChange->acpNewEnd);
+
+    EXPECT_EQ(S_OK, result);
+    return S_OK;
+  }
+
+  HRESULT LockGranted14a(DWORD flags) {
+    GetTextTest(2, 4, L"VW", 4);
+
+    return S_OK;
+  }
+
+  HRESULT OnSelectionChange14() {
+    HRESULT result = S_OK;
+    EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+    EXPECT_EQ(S_OK, result);
+    return S_OK;
+  }
+
+  HRESULT LockGranted14b(DWORD flags) {
+    GetSelectionTest(4, 4);
+    return S_OK;
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(DiffingAlgorithmTestCallback);
@@ -1934,7 +2098,15 @@
       .WillOnce(Invoke(&callback, &DiffingAlgorithmTestCallback::OnTextChange8))
       .WillOnce(Invoke(&callback, &DiffingAlgorithmTestCallback::OnTextChange9))
       .WillOnce(
-          Invoke(&callback, &DiffingAlgorithmTestCallback::OnTextChange10));
+          Invoke(&callback, &DiffingAlgorithmTestCallback::OnTextChange10))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::OnTextChange11))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::OnTextChange12))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::OnTextChange13))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::OnTextChange14));
 
   EXPECT_CALL(*sink_, OnSelectionChange())
       .WillOnce(
@@ -1953,8 +2125,16 @@
           Invoke(&callback, &DiffingAlgorithmTestCallback::OnSelectionChange8))
       .WillOnce(
           Invoke(&callback, &DiffingAlgorithmTestCallback::OnSelectionChange9))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::OnSelectionChange10))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::OnSelectionChange11))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::OnSelectionChange12))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::OnSelectionChange13))
       .WillOnce(Invoke(&callback,
-                       &DiffingAlgorithmTestCallback::OnSelectionChange10));
+                       &DiffingAlgorithmTestCallback::OnSelectionChange14));
 
   EXPECT_CALL(text_input_client_, InsertText(_))
       .WillOnce(Invoke(&callback, &DiffingAlgorithmTestCallback::InsertText2));
@@ -1989,7 +2169,27 @@
       .WillOnce(
           Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted10a))
       .WillOnce(
-          Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted10b));
+          Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted10b))
+      .WillOnce(Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted11))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted11a))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted11b))
+      .WillOnce(Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted12))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted12a))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted12b))
+      .WillOnce(Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted13))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted13a))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted13b))
+      .WillOnce(Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted14))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted14a))
+      .WillOnce(
+          Invoke(&callback, &DiffingAlgorithmTestCallback::LockGranted14b));
 
   ON_CALL(text_input_client_, GetTextRange(_))
       .WillByDefault(
@@ -2034,6 +2234,17 @@
   EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
   EXPECT_EQ(S_OK, result);
   result = kInvalidResult;
+  EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+  EXPECT_EQ(S_OK, result);
+  result = kInvalidResult;
+  EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+  EXPECT_EQ(S_OK, result);
+  result = kInvalidResult;
+  EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+  EXPECT_EQ(S_OK, result);
+  result = kInvalidResult;
+  EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+  EXPECT_EQ(S_OK, result);
 }
 
 }  // namespace
diff --git a/ui/chromeos/events/BUILD.gn b/ui/chromeos/events/BUILD.gn
index 91b0b84..a6af3750 100644
--- a/ui/chromeos/events/BUILD.gn
+++ b/ui/chromeos/events/BUILD.gn
@@ -22,7 +22,7 @@
     "//base",
     "//chromeos",
     "//device/udev_linux",
-    "//ui/base/ime",
+    "//ui/base/ime/chromeos",
     "//ui/events",
     "//ui/events:dom_keycode_converter",
     "//ui/events/devices",
diff --git a/ui/chromeos/translations/ui_chromeos_strings_ta.xtb b/ui/chromeos/translations/ui_chromeos_strings_ta.xtb
index 7c13b1f..fbd05e6 100644
--- a/ui/chromeos/translations/ui_chromeos_strings_ta.xtb
+++ b/ui/chromeos/translations/ui_chromeos_strings_ta.xtb
@@ -575,6 +575,7 @@
 <translation id="7864662577698025113">புதிய சேவையைச் சேர்</translation>
 <translation id="7873831373602885875"><ph name="FOLDER_NAME" /> இல் சேமிக்க முடியவில்லை. அனைத்து மாற்றங்களும் ‘பதிவிறக்கங்கள்’ கோப்புறையில் உள்ள <ph name="DOWNLOADS_FOLDER" /> கோப்புறையில் சேமிக்கப்படும்.</translation>
 <translation id="7881969471599061635">வசனங்களை முடக்கு</translation>
+<translation id="78946041517601018">பகிர்ந்த இயக்ககங்கள்</translation>
 <translation id="7896906914454843592">விரிவாக்கப்பட்ட யுஎஸ் விசைப்பலகை</translation>
 <translation id="7898607018410277265">குஜராத்தி விசைப்பலகை (புதிய ஒலிப்புமுறை)</translation>
 <translation id="7917972308273378936">லிதுவேனியன் விசைப்பலகை</translation>
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index c1dd9a0..102c2fc 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -67,6 +67,7 @@
 class FrameSinkManagerImpl;
 class ContextProvider;
 class HostFrameSinkManager;
+class RasterContextProvider;
 }
 
 namespace ui {
@@ -86,10 +87,11 @@
  public:
   virtual ~ContextFactoryObserver() {}
 
-  // Notifies that the viz::ContextProvider returned from
-  // ui::ContextFactory::SharedMainThreadContextProvider was lost.  When this
-  // is called, the old resources (e.g. shared context, GL helper) still
-  // exist, but are about to be destroyed. Getting a reference to those
+  // Notifies that the viz::ContextProviders returned from
+  // ui::ContextFactory::SharedMainThreadContextProvider and/or
+  // ui::ContextFactory::SharedMainThreadRasterContextProvider were lost.
+  // When this is called, the old resources (e.g. shared context, GL helper)
+  // still exist, but are about to be destroyed. Getting a reference to those
   // resources from the ContextFactory (e.g. through
   // SharedMainThreadContextProvider()) will return newly recreated, valid
   // resources.
@@ -171,6 +173,11 @@
   virtual scoped_refptr<viz::ContextProvider>
   SharedMainThreadContextProvider() = 0;
 
+  // Return a reference to a shared offscreen context provider usable from the
+  // main thread.
+  virtual scoped_refptr<viz::RasterContextProvider>
+  SharedMainThreadRasterContextProvider() = 0;
+
   // Destroys per-compositor data.
   virtual void RemoveCompositor(Compositor* compositor) = 0;
 
diff --git a/ui/compositor/test/fake_context_factory.cc b/ui/compositor/test/fake_context_factory.cc
index 8fa8836..945c13c1 100644
--- a/ui/compositor/test/fake_context_factory.cc
+++ b/ui/compositor/test/fake_context_factory.cc
@@ -51,6 +51,11 @@
   return nullptr;
 }
 
+scoped_refptr<viz::RasterContextProvider>
+FakeContextFactory::SharedMainThreadRasterContextProvider() {
+  return nullptr;
+}
+
 void FakeContextFactory::RemoveCompositor(ui::Compositor* compositor) {
   frame_sink_ = nullptr;
 }
diff --git a/ui/compositor/test/fake_context_factory.h b/ui/compositor/test/fake_context_factory.h
index 45f1fb18..ae3bf61 100644
--- a/ui/compositor/test/fake_context_factory.h
+++ b/ui/compositor/test/fake_context_factory.h
@@ -35,6 +35,8 @@
       base::WeakPtr<ui::Compositor> compositor) override;
   scoped_refptr<viz::ContextProvider> SharedMainThreadContextProvider()
       override;
+  scoped_refptr<viz::RasterContextProvider>
+  SharedMainThreadRasterContextProvider() override;
   void RemoveCompositor(ui::Compositor* compositor) override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc
index b61cff8e..d9a4a65 100644
--- a/ui/compositor/test/in_process_context_factory.cc
+++ b/ui/compositor/test/in_process_context_factory.cc
@@ -311,6 +311,14 @@
   return shared_main_thread_contexts_;
 }
 
+scoped_refptr<viz::RasterContextProvider>
+InProcessContextFactory::SharedMainThreadRasterContextProvider() {
+  SharedMainThreadContextProvider();
+  DCHECK(!shared_main_thread_contexts_ ||
+         shared_main_thread_contexts_->RasterInterface());
+  return shared_main_thread_contexts_;
+}
+
 void InProcessContextFactory::RemoveCompositor(Compositor* compositor) {
   auto it = per_compositor_data_.find(compositor);
   if (it == per_compositor_data_.end())
diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h
index 1ecf65d..58dfb4f 100644
--- a/ui/compositor/test/in_process_context_factory.h
+++ b/ui/compositor/test/in_process_context_factory.h
@@ -65,6 +65,9 @@
 
   scoped_refptr<viz::ContextProvider> SharedMainThreadContextProvider()
       override;
+  scoped_refptr<viz::RasterContextProvider>
+  SharedMainThreadRasterContextProvider() override;
+
   void RemoveCompositor(Compositor* compositor) override;
   gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
   cc::TaskGraphRunner* GetTaskGraphRunner() override;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js b/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js
index 7a6589e..770a4b3f 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js
@@ -104,6 +104,14 @@
     currentMenu: null,
 
     /**
+     * Padding used when restricting menu height when the window is too small
+     * to show the entire menu.
+     * @type {number}
+     * @private
+     */
+    menuEndGap_: 18,  // padding on cr.menu + 2px
+
+    /**
      * Checks if the menu(s) should be closed based on the target of a mouse
      * click or a touch event target.
      * @param {Event} e The event object.
@@ -145,11 +153,12 @@
       }
       style.top = itemRect.top + 'px';
       // Size the subMenu to fit inside the height of the viewport
-      const menuEndGap = 18;  // padding on cr.menu + 2px
       // Always set the maximum height so that expanding the window
       // allows the menu height to grow crbug/934207
-      style.maxHeight = (viewportHeight - itemRect.top - menuEndGap) + 'px';
-      if ((itemRect.top + childRect.height + menuEndGap) > viewportHeight) {
+      style.maxHeight =
+          (viewportHeight - itemRect.top - this.menuEndGap_) + 'px';
+      if ((itemRect.top + childRect.height + this.menuEndGap_) >
+          viewportHeight) {
         style.overflowY = 'scroll';
       } else {
         style.overflowY = 'auto';
@@ -554,13 +563,34 @@
     },
 
     /**
-     * Positions the menu below the menu button. At this point we do not use any
-     * advanced positioning logic to ensure the menu fits in the viewport.
+     * Positions the menu below the menu button. We check the menu fits
+     * in the viewport, and enable scrolling if required.
      * @private
      */
     positionMenu_: function() {
       positionPopupAroundElement(
           this, this.menu, this.anchorType, this.invertLeftRight);
+      // Check if menu is larger than the viewport and adjust its height
+      // and enable scrolling if so. Note: style.bottom would have been set to
+      // 0.
+      const viewportHeight = window.innerHeight;
+      const menuRect = this.menu.getBoundingClientRect();
+      const style = this.menu.style;
+      // Make sure the top of the menu is in the viewport.
+      let top = menuRect.top;
+      if (top < 0) {
+        top = 0;
+      }
+      // Limit the height to fit in the viewport.
+      style.maxHeight = (viewportHeight - top - this.menuEndGap_) + 'px';
+      // Make the menu scrollable if needed.
+      if ((top + menuRect.height + this.menuEndGap_) > viewportHeight) {
+        style.overflowY = 'scroll';
+        style.top = '0';
+        style.bottom = 'auto';
+      } else {
+        style.overflowY = 'auto';
+      }
     },
 
     /**
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js
index ef2eaa3..2e7d975d 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js
@@ -332,3 +332,19 @@
   // Check that the sub-menu has been hidden.
   assertTrue(subMenu.hasAttribute('hidden'));
 }
+
+/**
+ * Tests that the top level menu is resized when the parent
+ * window is too small to fit in without clipping.
+ */
+function testShrinkWindowSizesTopMenu() {
+  menubutton.showMenu(true);
+  const menuPosition = topMenu.getBoundingClientRect();
+  // Reduce window innerHeight so the menu won't fit.
+  window.innerHeight = menuPosition.bottom - 10;
+  // Call showMenu() which will first hide it, then re-open
+  // it to force the resizing behavior.
+  menubutton.showMenu(true);
+  const shrunkPosition = topMenu.getBoundingClientRect();
+  assertTrue(shrunkPosition.bottom < window.innerHeight);
+}
diff --git a/ui/file_manager/image_loader/piex/tests.html b/ui/file_manager/image_loader/piex/tests.html
index 9a8daf70..5b303605 100644
--- a/ui/file_manager/image_loader/piex/tests.html
+++ b/ui/file_manager/image_loader/piex/tests.html
@@ -38,7 +38,7 @@
         this.result = result;
         Module.removeFunction(callback);
         Module._free(memory);
-        resolve(this);
+        resolve(this.result);
       }, 'vi');
 
       // Process the image: blocks until |callback| is called.
@@ -151,13 +151,10 @@
   }
 
   self.Module = {
-    onRuntimeInitialized: () => {
-      piexModuleReady instanceof Function ? piexModuleReady() : undefined;
-    }
+    onRuntimeInitialized: piexModuleReady,
   };
 
-  window.onload = () => {
-    // Load the wasm module, now the piexModuleReady handler is installed.
+  window.onload = function piexModuleLoad() {
     let script = document.createElement('script');
     document.head.appendChild(script);
     script.src = '/a.out.js';
@@ -188,20 +185,18 @@
     if (!buffer)
       return;
 
-    // Log the fetch time.
+    let imageBuffer = new ImageBuffer(buffer);
     const elapsed = performance.now() - time;
     console.log('test: fetch time', elapsed.toFixed(3));
 
     // Extract the preview|thumbnail images, render them.
     new Promise((resolve, reject) => {
-      new ImageBuffer(buffer).process(resolve, reject);
-    }).then((imageBuffer) => {
+      imageBuffer.process(resolve, reject);
+    }).then((result) => {
       let preview = imageBuffer.preview();
       let thumb = imageBuffer.thumbnail();
       time = performance.now() - time;
-      const maker = imageBuffer.result.maker || '';
-      const model = imageBuffer.result.model || '';
-      console.log('test:', image, maker, model);
+      console.log('test:', image, result.maker, result.model);
       window.images_ = 0;
       renderResult(image, preview);
       renderResult(image, thumb);
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
index 237ee97..8aadd5fb 100644
--- a/ui/gfx/render_text_harfbuzz.cc
+++ b/ui/gfx/render_text_harfbuzz.cc
@@ -25,6 +25,7 @@
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "third_party/icu/source/common/unicode/ubidi.h"
+#include "third_party/icu/source/common/unicode/uscript.h"
 #include "third_party/icu/source/common/unicode/utf16.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkFontMetrics.h"
@@ -1817,7 +1818,8 @@
   std::vector<Font> fallback_font_list;
   {
     SCOPED_UMA_HISTOGRAM_LONG_TIMER("RenderTextHarfBuzz.GetFallbackFontsTime");
-    TRACE_EVENT0("ui", "RenderTextHarfBuzz::GetFallbackFonts");
+    TRACE_EVENT1("ui", "RenderTextHarfBuzz::GetFallbackFonts", "script",
+                 TRACE_STR_COPY(uscript_getShortName(font_params.script)));
     fallback_font_list = GetFallbackFonts(primary_font);
 
 #if defined(OS_WIN)
diff --git a/ui/gl/gl_image_native_pixmap.cc b/ui/gl/gl_image_native_pixmap.cc
index 1520a28..cba649a7 100644
--- a/ui/gl/gl_image_native_pixmap.cc
+++ b/ui/gl/gl_image_native_pixmap.cc
@@ -28,7 +28,7 @@
 #define DRM_FORMAT_ABGR8888 FOURCC('A', 'B', '2', '4')
 #define DRM_FORMAT_XRGB8888 FOURCC('X', 'R', '2', '4')
 #define DRM_FORMAT_XBGR8888 FOURCC('X', 'B', '2', '4')
-#define DRM_FORMAT_ABGR2101010 FOURCC('A', 'B', '3', '0')
+#define DRM_FORMAT_XBGR2101010 FOURCC('X', 'B', '3', '0')
 #define DRM_FORMAT_YVU420 FOURCC('Y', 'V', '1', '2')
 #define DRM_FORMAT_NV12 FOURCC('N', 'V', '1', '2')
 
@@ -88,9 +88,7 @@
     case gfx::BufferFormat::BGRX_8888:
       return DRM_FORMAT_XRGB8888;
     case gfx::BufferFormat::RGBX_1010102:
-      // We should use here DRM_FORMAT_XBGR2101010 format, but EGL on Intel
-      // doesn't support it for scanout, see https://crbug.com/776093#c14.
-      return DRM_FORMAT_ABGR2101010;
+      return DRM_FORMAT_XBGR2101010;
     case gfx::BufferFormat::YVU_420:
       return DRM_FORMAT_YVU420;
     case gfx::BufferFormat::YUV_420_BIPLANAR:
@@ -121,9 +119,7 @@
       return gfx::BufferFormat::BGRA_8888;
     case DRM_FORMAT_XRGB8888:
       return gfx::BufferFormat::BGRX_8888;
-    case DRM_FORMAT_ABGR2101010:
-      // We should support DRM_FORMAT_XBGR2101010 format instead, but EGL on
-      // Intel doesn't support it for scanout, see https://crbug.com/776093#c14.
+    case DRM_FORMAT_XBGR2101010:
       return gfx::BufferFormat::RGBX_1010102;
     case DRM_FORMAT_RGB565:
       return gfx::BufferFormat::BGR_565;
diff --git a/ui/gl/gl_image_native_pixmap_unittest.cc b/ui/gl/gl_image_native_pixmap_unittest.cc
index 96414e1..0a622e7 100644
--- a/ui/gl/gl_image_native_pixmap_unittest.cc
+++ b/ui/gl/gl_image_native_pixmap_unittest.cc
@@ -101,7 +101,8 @@
     GLImageNativePixmapTestDelegate<gfx::BufferFormat::RGBX_8888>,
     GLImageNativePixmapTestDelegate<gfx::BufferFormat::RGBA_8888>,
     GLImageNativePixmapTestDelegate<gfx::BufferFormat::BGRX_8888>,
-    GLImageNativePixmapTestDelegate<gfx::BufferFormat::BGRA_8888>>;
+    GLImageNativePixmapTestDelegate<gfx::BufferFormat::BGRA_8888>,
+    GLImageNativePixmapTestDelegate<gfx::BufferFormat::RGBX_1010102>>;
 
 #if !defined(MEMORY_SANITIZER)
 // Fails under MSAN: crbug.com/886995
diff --git a/ui/keyboard/BUILD.gn b/ui/keyboard/BUILD.gn
index b1862db..107da45 100644
--- a/ui/keyboard/BUILD.gn
+++ b/ui/keyboard/BUILD.gn
@@ -88,6 +88,8 @@
   sources = [
     "test/keyboard_test_util.cc",
     "test/keyboard_test_util.h",
+    "test/test_keyboard_controller_observer.cc",
+    "test/test_keyboard_controller_observer.h",
     "test/test_keyboard_layout_delegate.cc",
     "test/test_keyboard_layout_delegate.h",
     "test/test_keyboard_ui_factory.cc",
@@ -175,7 +177,7 @@
     "//ui/aura:test_support",
     "//ui/base",
     "//ui/base:test_support",
-    "//ui/base/ime",
+    "//ui/base/ime/init",
     "//ui/compositor:test_support",
     "//ui/events:test_support",
     "//ui/gfx",
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc
index 0506a53..4df6483 100644
--- a/ui/keyboard/keyboard_controller_unittest.cc
+++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -20,8 +20,8 @@
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/window.h"
 #include "ui/base/ime/dummy_text_input_client.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_factory.h"
 #include "ui/base/ime/text_input_client.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/compositor/compositor.h"
diff --git a/ui/keyboard/test/test_keyboard_controller_observer.cc b/ui/keyboard/test/test_keyboard_controller_observer.cc
new file mode 100644
index 0000000..ce215a7
--- /dev/null
+++ b/ui/keyboard/test/test_keyboard_controller_observer.cc
@@ -0,0 +1,21 @@
+// Copyright 2019 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/keyboard/test/test_keyboard_controller_observer.h"
+
+namespace keyboard {
+
+TestKeyboardControllerObserver::TestKeyboardControllerObserver() = default;
+
+TestKeyboardControllerObserver::~TestKeyboardControllerObserver() = default;
+
+void TestKeyboardControllerObserver::OnKeyboardEnabledChanged(bool is_enabled) {
+  if (is_enabled) {
+    enabled_count++;
+  } else {
+    disabled_count++;
+  }
+}
+
+}  // namespace keyboard
diff --git a/ui/keyboard/test/test_keyboard_controller_observer.h b/ui/keyboard/test/test_keyboard_controller_observer.h
new file mode 100644
index 0000000..96fe735
--- /dev/null
+++ b/ui/keyboard/test/test_keyboard_controller_observer.h
@@ -0,0 +1,27 @@
+// Copyright 2019 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_KEYBOARD_TEST_TEST_KEYBOARD_CONTROLLER_OBSERVER_H_
+#define UI_KEYBOARD_TEST_TEST_KEYBOARD_CONTROLLER_OBSERVER_H_
+
+#include "ui/keyboard/keyboard_controller_observer.h"
+
+namespace keyboard {
+
+// A KeyboardControllerObserver that counts occurrences of events for testing.
+struct TestKeyboardControllerObserver : public KeyboardControllerObserver {
+  TestKeyboardControllerObserver();
+  ~TestKeyboardControllerObserver() override;
+
+  // KeyboardControllerObserver:
+  void OnKeyboardEnabledChanged(bool is_enabled) override;
+
+  int enabled_count = 0;
+  int disabled_count = 0;
+  DISALLOW_COPY_AND_ASSIGN(TestKeyboardControllerObserver);
+};
+
+}  // namespace keyboard
+
+#endif  // UI_KEYBOARD_TEST_TEST_KEYBOARD_CONTROLLER_OBSERVER_H_
diff --git a/ui/ozone/DEPS b/ui/ozone/DEPS
index 261e887..281c592 100644
--- a/ui/ozone/DEPS
+++ b/ui/ozone/DEPS
@@ -4,6 +4,8 @@
   "+skia/ext",
   "+third_party/khronos",
   "+third_party/skia",
+  "+ui/base/ime",
+  "-ui/base/ime/init",
   "+ui/display",
   "+ui/events",
   "+ui/base/cursor",
diff --git a/ui/ozone/ozone.gni b/ui/ozone/ozone.gni
index d1cd5a7..c4766e40 100644
--- a/ui/ozone/ozone.gni
+++ b/ui/ozone/ozone.gni
@@ -67,7 +67,6 @@
       ozone_platform = "x11"
       ozone_platform_gbm = true
       ozone_platform_x11 = true
-      ozone_platform_wayland = true
     } else if (is_desktop_linux) {
       ozone_platform = "x11"
       ozone_platform_wayland = true
diff --git a/ui/ozone/platform/drm/common/drm_overlay_manager.cc b/ui/ozone/platform/drm/common/drm_overlay_manager.cc
index 57cefd0..0d23613 100644
--- a/ui/ozone/platform/drm/common/drm_overlay_manager.cc
+++ b/ui/ozone/platform/drm/common/drm_overlay_manager.cc
@@ -38,6 +38,7 @@
 }
 
 void DrmOverlayManager::ResetCache() {
+  TRACE_EVENT0("hwoverlays", "DrmOverlayManager::ResetCache");
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   cache_.Clear();
 }
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
index 8ce4812..e1c2075 100644
--- a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
+++ b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
@@ -74,6 +74,11 @@
 DrmGpuDisplayManager::~DrmGpuDisplayManager() {
 }
 
+void DrmGpuDisplayManager::SetClearOverlayCacheCallback(
+    base::RepeatingClosure callback) {
+  clear_overlay_cache_callback_ = std::move(callback);
+}
+
 MovableDisplaySnapshots DrmGpuDisplayManager::GetDisplays() {
   std::vector<std::unique_ptr<DrmDisplay>> old_displays;
   old_displays.swap(displays_);
@@ -157,6 +162,9 @@
     return false;
   }
 
+  if (clear_overlay_cache_callback_)
+    clear_overlay_cache_callback_.Run();
+
   return display->Configure(&mode, origin);
 }
 
@@ -167,6 +175,9 @@
     return false;
   }
 
+  if (clear_overlay_cache_callback_)
+    clear_overlay_cache_callback_.Run();
+
   return display->Configure(nullptr, gfx::Point());
 }
 
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
index 40d71dea..e2af38c90 100644
--- a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
+++ b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
@@ -9,6 +9,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/callback.h"
 #include "base/macros.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
@@ -31,6 +32,10 @@
                        DrmDeviceManager* drm_device_manager);
   ~DrmGpuDisplayManager();
 
+  // Sets a callback that will be notified when display configuration may have
+  // changed to clear the overlay configuration cache.
+  void SetClearOverlayCacheCallback(base::RepeatingClosure callback);
+
   // Returns a list of the connected displays. When this is called the list of
   // displays is refreshed.
   MovableDisplaySnapshots GetDisplays();
@@ -68,6 +73,8 @@
 
   std::vector<std::unique_ptr<DrmDisplay>> displays_;
 
+  base::RepeatingClosure clear_overlay_cache_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(DrmGpuDisplayManager);
 };
 
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc b/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc
index 36f852c..aa513e8 100644
--- a/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc
+++ b/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc
@@ -14,7 +14,7 @@
 namespace ui {
 
 DrmOverlayManagerGpu::DrmOverlayManagerGpu(DrmThreadProxy* drm_thread_proxy)
-    : drm_thread_proxy_(drm_thread_proxy), weak_ptr_factory_(this) {}
+    : drm_thread_proxy_(drm_thread_proxy) {}
 
 DrmOverlayManagerGpu::~DrmOverlayManagerGpu() = default;
 
@@ -24,6 +24,18 @@
   TRACE_EVENT_ASYNC_BEGIN0(
       "hwoverlays", "DrmOverlayManagerGpu::SendOverlayValidationRequest", this);
 
+  // Adds a callback for the DRM thread to let us know when display
+  // configuration has changed and to reset cache of valid overlay
+  // configurations. This happens in SendOverlayValidationRequest() because the
+  // DrmThread has been started by this point *and* we are on the thread the
+  // callback should run on. Those two conditions are not necessarily true in
+  // the constructor.
+  if (!has_set_clear_cache_callback_) {
+    has_set_clear_cache_callback_ = true;
+    drm_thread_proxy_->SetClearOverlayCacheCallback(base::BindRepeating(
+        &DrmOverlayManagerGpu::ResetCache, weak_ptr_factory_.GetWeakPtr()));
+  }
+
   drm_thread_proxy_->CheckOverlayCapabilities(
       widget, candidates,
       base::BindOnce(&DrmOverlayManagerGpu::ReceiveOverlayValidationResponse,
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h b/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h
index 44d7d178..da669308 100644
--- a/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h
+++ b/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h
@@ -21,11 +21,6 @@
   explicit DrmOverlayManagerGpu(DrmThreadProxy* drm_thread_proxy);
   ~DrmOverlayManagerGpu() override;
 
-  // TODO(crbug.com/930173): Plumb some sort of display configuration
-  // information into this class. DrmOverlayManagerHost checks if the overlay
-  // candidates are contained by the display rect. The overlay configuration
-  // cache also needs to be reset when display configuration changes.
-
  private:
   // DrmOverlayManager:
   void SendOverlayValidationRequest(
@@ -39,7 +34,9 @@
 
   DrmThreadProxy* const drm_thread_proxy_;
 
-  base::WeakPtrFactory<DrmOverlayManagerGpu> weak_ptr_factory_;
+  bool has_set_clear_cache_callback_ = false;
+
+  base::WeakPtrFactory<DrmOverlayManagerGpu> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(DrmOverlayManagerGpu);
 };
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.cc b/ui/ozone/platform/drm/gpu/drm_thread.cc
index 2669df8..48153537 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -208,6 +208,10 @@
   *out_framebuffer = std::move(framebuffer);
 }
 
+void DrmThread::SetClearOverlayCacheCallback(base::RepeatingClosure callback) {
+  display_manager_->SetClearOverlayCacheCallback(std::move(callback));
+}
+
 void DrmThread::SchedulePageFlip(
     gfx::AcceleratedWidget widget,
     std::vector<DrmOverlayPlane> planes,
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.h b/ui/ozone/platform/drm/gpu/drm_thread.h
index b65b30f..211ec46e 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread.h
+++ b/ui/ozone/platform/drm/gpu/drm_thread.h
@@ -78,6 +78,7 @@
                               gfx::NativePixmapHandle handle,
                               std::unique_ptr<GbmBuffer>* buffer,
                               scoped_refptr<DrmFramebuffer>* framebuffer);
+  void SetClearOverlayCacheCallback(base::RepeatingClosure callback);
   void AddBindingCursorDevice(ozone::mojom::DeviceCursorRequest request);
   void AddBindingDrmDevice(ozone::mojom::DrmDeviceRequest request);
 
diff --git a/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc b/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
index 97a9e23..c336edd 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
+++ b/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
@@ -15,9 +15,9 @@
 
 namespace ui {
 
-DrmThreadProxy::DrmThreadProxy() {}
+DrmThreadProxy::DrmThreadProxy() = default;
 
-DrmThreadProxy::~DrmThreadProxy() {}
+DrmThreadProxy::~DrmThreadProxy() = default;
 
 // Used only with the paramtraits implementation.
 void DrmThreadProxy::BindThreadIntoMessagingProxy(
@@ -25,7 +25,6 @@
   messaging_proxy->SetDrmThread(&drm_thread_);
 }
 
-// Used only for the mojo implementation.
 void DrmThreadProxy::StartDrmThread(base::OnceClosure binding_drainer) {
   drm_thread_.Start(std::move(binding_drainer));
 }
@@ -64,6 +63,17 @@
                      base::Passed(std::move(handle)), buffer, framebuffer));
 }
 
+void DrmThreadProxy::SetClearOverlayCacheCallback(
+    base::RepeatingClosure callback) {
+  DCHECK(drm_thread_.task_runner());
+
+  drm_thread_.task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&DrmThread::SetClearOverlayCacheCallback,
+                     base::Unretained(&drm_thread_),
+                     CreateSafeRepeatingCallback(std::move(callback))));
+}
+
 void DrmThreadProxy::CheckOverlayCapabilities(
     gfx::AcceleratedWidget widget,
     const std::vector<OverlaySurfaceCandidate>& candidates,
diff --git a/ui/ozone/platform/drm/gpu/drm_thread_proxy.h b/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
index 47c818d..a32b70dd 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
+++ b/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
@@ -55,6 +55,11 @@
                               std::unique_ptr<GbmBuffer>* buffer,
                               scoped_refptr<DrmFramebuffer>* framebuffer);
 
+  // Sets a callback that will be notified when display configuration may have
+  // changed to clear the overlay configuration cache. |callback| will be run on
+  // origin thread.
+  void SetClearOverlayCacheCallback(base::RepeatingClosure reset_callback);
+
   // Checks if overlay |candidates| can be displayed asynchronously and then
   // runs |callback|. Testing the overlay configuration requires posting a task
   // to the DRM thread, but |callback| will be run on origin thread.
diff --git a/ui/ozone/platform/drm/gpu/proxy_helpers.h b/ui/ozone/platform/drm/gpu/proxy_helpers.h
index b0d8a52..d25933b 100644
--- a/ui/ozone/platform/drm/gpu/proxy_helpers.h
+++ b/ui/ozone/platform/drm/gpu/proxy_helpers.h
@@ -41,14 +41,16 @@
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     base::OnceClosure callback);
 
-// Creates a callback that will run |callback| on the calling thread. Useful
-// when posting a task on a different thread and expecting a callback when the
-// task finished (and the callback needs to run on the original thread).
+// Creates a RepeatingCallback that will run |callback| on the calling thread.
+// Useful when posting a task on a different thread and expecting a callback
+// when the task finished (and the callback needs to run on the original
+// thread).
 template <typename... Args>
-base::Callback<void(Args...)> CreateSafeCallback(
-    const base::Callback<void(Args...)>& callback) {
-  return base::Bind(&internal::PostAsyncTask<Args...>,
-                    base::ThreadTaskRunnerHandle::Get(), callback);
+base::RepeatingCallback<void(Args...)> CreateSafeRepeatingCallback(
+    base::RepeatingCallback<void(Args...)> callback) {
+  return base::BindRepeating(&internal::PostAsyncTask<Args...>,
+                             base::ThreadTaskRunnerHandle::Get(),
+                             std::move(callback));
 }
 
 // Creates a OnceCallback that will run |callback| on the calling thread. Useful
diff --git a/ui/ozone/platform/scenic/DEPS b/ui/ozone/platform/scenic/DEPS
index 1f7f0de..627265fd 100644
--- a/ui/ozone/platform/scenic/DEPS
+++ b/ui/ozone/platform/scenic/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
   "+mojo/public",
   "+third_party/skia/include",
-  "+ui/base/ime",
 ]
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn
index 7981c68..bc651e1 100644
--- a/ui/ozone/platform/wayland/BUILD.gn
+++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -108,7 +108,6 @@
     "//ui/base",
     "//ui/base:buildflags",
     "//ui/base/ime/linux",
-    "//ui/display/manager",
     "//ui/events",
     "//ui/events:dom_keycode_converter",
     "//ui/events/keycodes:xkb",
@@ -127,6 +126,10 @@
     "//ui/platform_window/platform_window_handler",
   ]
 
+  if (is_linux && !is_chromeos) {
+    deps += ["//ui/base/ime/linux"]
+  }
+
   defines = [ "OZONE_IMPLEMENTATION" ]
 
   if (use_wayland_gbm) {
diff --git a/ui/ozone/platform/wayland/DEPS b/ui/ozone/platform/wayland/DEPS
index cb91c80..dfc8f06 100644
--- a/ui/ozone/platform/wayland/DEPS
+++ b/ui/ozone/platform/wayland/DEPS
@@ -2,11 +2,6 @@
   "+ui/base/buildflags.h",  # Doesn't bring in all of ui/base.
   "+ui/base/hit_test.h", # UI hit test doesn't bring in all of ui/base.
   "+ui/base/ui_base_features.h",
-  "+ui/base/ime/character_composer.h",
-  "+ui/base/ime/composition_text.h",
-  "+ui/base/ime/ime_text_span.h",
-  "+ui/base/ime/linux/linux_input_method_context.h",
-  "+ui/base/ime/linux/linux_input_method_context_factory.h",
   "+mojo/public",
   "+ui/base/dragdrop/drag_drop_types.h",
   "+ui/base/dragdrop/os_exchange_data.h",
diff --git a/ui/ozone/platform/wayland/common/wayland_util.h b/ui/ozone/platform/wayland/common/wayland_util.h
index a6cbdd96..739229f 100644
--- a/ui/ozone/platform/wayland/common/wayland_util.h
+++ b/ui/ozone/platform/wayland/common/wayland_util.h
@@ -20,16 +20,10 @@
 
 namespace gfx {
 class Size;
-enum class SwapResult;
-struct PresentationFeedback;
 }  // namespace gfx
 
 namespace wl {
 
-// Corresponds to mojom::WaylandConnection::ScheduleBufferSwapCallback.
-using BufferSwapCallback =
-    base::OnceCallback<void(gfx::SwapResult, const gfx::PresentationFeedback&)>;
-
 using RequestSizeCallback = base::OnceCallback<void(const gfx::Size&)>;
 
 using OnRequestBufferCallback =
diff --git a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
index 08086eb6..0f3583d 100644
--- a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
+++ b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
@@ -28,12 +28,15 @@
 namespace ui {
 
 GbmPixmapWayland::GbmPixmapWayland(WaylandSurfaceFactory* surface_manager,
-                                   WaylandConnectionProxy* connection)
-    : surface_manager_(surface_manager), connection_(connection) {}
+                                   WaylandConnectionProxy* connection,
+                                   gfx::AcceleratedWidget widget)
+    : surface_manager_(surface_manager),
+      connection_(connection),
+      widget_(widget) {}
 
 GbmPixmapWayland::~GbmPixmapWayland() {
   if (gbm_bo_)
-    connection_->DestroyZwpLinuxDmabuf(GetUniqueId());
+    connection_->DestroyZwpLinuxDmabuf(widget_, GetUniqueId());
 }
 
 bool GbmPixmapWayland::InitializeBuffer(gfx::Size size,
diff --git a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
index 3f43538b..b99a36d 100644
--- a/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
+++ b/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h
@@ -23,7 +23,8 @@
 class GbmPixmapWayland : public gfx::NativePixmap {
  public:
   GbmPixmapWayland(WaylandSurfaceFactory* surface_manager,
-                   WaylandConnectionProxy* connection);
+                   WaylandConnectionProxy* connection,
+                   gfx::AcceleratedWidget widget);
 
   // Creates a buffer object and initializes the pixmap buffer.
   bool InitializeBuffer(gfx::Size size,
@@ -57,10 +58,13 @@
   // gbm_bo wrapper for struct gbm_bo.
   std::unique_ptr<GbmBuffer> gbm_bo_;
 
-  WaylandSurfaceFactory* surface_manager_ = nullptr;
+  WaylandSurfaceFactory* const surface_manager_;
 
   // Represents a connection to Wayland.
-  WaylandConnectionProxy* connection_ = nullptr;
+  WaylandConnectionProxy* const connection_;
+
+  // Represents widget this pixmap backs.
+  const gfx::AcceleratedWidget widget_;
 
   DISALLOW_COPY_AND_ASSIGN(GbmPixmapWayland);
 };
diff --git a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
index bbc49264..2d2cc50f07 100644
--- a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
+++ b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
@@ -11,6 +11,7 @@
 #include "base/trace_event/trace_event.h"
 #include "ui/gfx/gpu_fence.h"
 #include "ui/ozone/common/egl_util.h"
+#include "ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h"
 #include "ui/ozone/platform/wayland/gpu/wayland_surface_factory.h"
 
 namespace ui {
@@ -27,9 +28,11 @@
 
 GbmSurfacelessWayland::GbmSurfacelessWayland(
     WaylandSurfaceFactory* surface_factory,
+    WaylandConnectionProxy* connection,
     gfx::AcceleratedWidget widget)
     : SurfacelessEGL(gfx::Size()),
       surface_factory_(surface_factory),
+      connection_(connection),
       widget_(widget),
       has_implicit_external_sync_(
           HasEGLExtension("EGL_ARM_implicit_external_sync")),
@@ -200,18 +203,23 @@
         submitted_frame_->ScheduleOverlayPlanes(widget_);
 
     if (!schedule_planes_succeeded) {
-      OnSubmission(gfx::SwapResult::SWAP_FAILED, nullptr);
-      OnPresentation(gfx::PresentationFeedback::Failure());
+      last_swap_buffers_result_ = false;
+
+      std::move(submitted_frame_->completion_callback)
+          .Run(gfx::SwapResult::SWAP_FAILED, nullptr);
+      // Notify the caller, the buffer is never presented on a screen.
+      std::move(submitted_frame_->presentation_callback)
+          .Run(gfx::PresentationFeedback::Failure());
+
+      submitted_frame_.reset();
       return;
     }
 
-    auto callback =
-        base::BindOnce(&GbmSurfacelessWayland::OnScheduleBufferSwapDone,
-                       weak_factory_.GetWeakPtr());
-    uint32_t buffer_id = planes_.back().pixmap->GetUniqueId();
-    surface_factory_->ScheduleBufferSwap(widget_, buffer_id,
-                                         submitted_frame_->damage_region_,
-                                         std::move(callback));
+    submitted_frame_->buffer_id = planes_.back().pixmap->GetUniqueId();
+    connection_->ScheduleBufferSwap(widget_, submitted_frame_->buffer_id,
+                                    submitted_frame_->damage_region_);
+
+    planes_.clear();
   }
 }
 
@@ -228,31 +236,16 @@
   SubmitFrame();
 }
 
-void GbmSurfacelessWayland::OnScheduleBufferSwapDone(
-    gfx::SwapResult result,
-    const gfx::PresentationFeedback& feedback) {
-  OnSubmission(result, nullptr);
-  OnPresentation(feedback);
-  planes_.clear();
-}
-
-void GbmSurfacelessWayland::OnSubmission(
-    gfx::SwapResult result,
-    std::unique_ptr<gfx::GpuFence> out_fence) {
-  submitted_frame_->swap_result = result;
-}
-
-void GbmSurfacelessWayland::OnPresentation(
-    const gfx::PresentationFeedback& feedback) {
-  // Explicitly destroy overlays to free resources (e.g., fences) early.
+void GbmSurfacelessWayland::OnSubmission(uint32_t buffer_id,
+                                         const gfx::SwapResult& swap_result) {
   submitted_frame_->overlays.clear();
 
-  gfx::SwapResult result = submitted_frame_->swap_result;
-  std::move(submitted_frame_->completion_callback).Run(result, nullptr);
-  std::move(submitted_frame_->presentation_callback).Run(feedback);
-  submitted_frame_.reset();
+  DCHECK_EQ(submitted_frame_->buffer_id, buffer_id);
+  std::move(submitted_frame_->completion_callback).Run(swap_result, nullptr);
 
-  if (result == gfx::SwapResult::SWAP_FAILED) {
+  pending_presentation_frames_.push_back(std::move(submitted_frame_));
+
+  if (swap_result != gfx::SwapResult::SWAP_ACK) {
     last_swap_buffers_result_ = false;
     return;
   }
@@ -260,4 +253,13 @@
   SubmitFrame();
 }
 
+void GbmSurfacelessWayland::OnPresentation(
+    uint32_t buffer_id,
+    const gfx::PresentationFeedback& feedback) {
+  auto* frame = pending_presentation_frames_.front().get();
+  DCHECK_EQ(frame->buffer_id, buffer_id);
+  std::move(frame->presentation_callback).Run(feedback);
+  pending_presentation_frames_.erase(pending_presentation_frames_.begin());
+}
+
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
index f86dd4b0..dfd3d91f 100644
--- a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
+++ b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
@@ -16,6 +16,7 @@
 
 namespace ui {
 
+class WaylandConnectionProxy;
 class WaylandSurfaceFactory;
 
 // A GLSurface for Wayland Ozone platform that uses surfaceless drawing. Drawing
@@ -25,6 +26,7 @@
 class GbmSurfacelessWayland : public gl::SurfacelessEGL {
  public:
   GbmSurfacelessWayland(WaylandSurfaceFactory* surface_factory,
+                        WaylandConnectionProxy* connection,
                         gfx::AcceleratedWidget widget);
 
   void QueueOverlayPlane(OverlayPlane plane);
@@ -57,6 +59,10 @@
   EGLConfig GetConfig() override;
   void SetRelyOnImplicitSync() override;
 
+  void OnSubmission(uint32_t buffer_id, const gfx::SwapResult& swap_result);
+  void OnPresentation(uint32_t buffer_id,
+                      const gfx::PresentationFeedback& feedback);
+
  private:
   ~GbmSurfacelessWayland() override;
 
@@ -68,7 +74,10 @@
     void Flush();
 
     bool ready = false;
-    gfx::SwapResult swap_result = gfx::SwapResult::SWAP_FAILED;
+
+    // The id of the buffer, which represents this frame.
+    uint32_t buffer_id = 0;
+
     // A region of the updated content in a corresponding frame. It's used to
     // advice Wayland which part of a buffer is going to be updated. Passing {0,
     // 0, 0, 0} results in a whole buffer update on the Wayland compositor side.
@@ -83,18 +92,14 @@
   EGLSyncKHR InsertFence(bool implicit);
   void FenceRetired(PendingFrame* frame);
 
-  void OnScheduleBufferSwapDone(gfx::SwapResult result,
-                                const gfx::PresentationFeedback& feedback);
-  void OnSubmission(gfx::SwapResult result,
-                    std::unique_ptr<gfx::GpuFence> out_fence);
-  void OnPresentation(const gfx::PresentationFeedback& feedback);
-
-  WaylandSurfaceFactory* surface_factory_;
+  WaylandSurfaceFactory* const surface_factory_;
+  WaylandConnectionProxy* const connection_;
   std::vector<OverlayPlane> planes_;
 
   // The native surface. Deleting this is allowed to free the EGLNativeWindow.
   gfx::AcceleratedWidget widget_;
   std::vector<std::unique_ptr<PendingFrame>> unsubmitted_frames_;
+  std::vector<std::unique_ptr<PendingFrame>> pending_presentation_frames_;
   std::unique_ptr<PendingFrame> submitted_frame_;
   bool has_implicit_external_sync_;
   bool last_swap_buffers_result_ = true;
diff --git a/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc b/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
index d9ed612..ca84e0d 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
@@ -8,14 +8,20 @@
 
 #include "base/bind.h"
 #include "base/process/process.h"
+#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
 #include "third_party/khronos/EGL/egl.h"
 #include "ui/ozone/common/linux/drm_util_linux.h"
+#include "ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h"
+#include "ui/ozone/platform/wayland/gpu/wayland_surface_factory.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
 
 namespace ui {
 
-WaylandConnectionProxy::WaylandConnectionProxy(WaylandConnection* connection)
+WaylandConnectionProxy::WaylandConnectionProxy(WaylandConnection* connection,
+                                               WaylandSurfaceFactory* factory)
     : connection_(connection),
+      factory_(factory),
+      associated_binding_(this),
       gpu_thread_runner_(base::ThreadTaskRunnerHandle::Get()) {}
 
 WaylandConnectionProxy::~WaylandConnectionProxy() = default;
@@ -35,6 +41,33 @@
 #endif
 }
 
+void WaylandConnectionProxy::OnSubmission(gfx::AcceleratedWidget widget,
+                                          uint32_t buffer_id,
+                                          gfx::SwapResult swap_result) {
+  DCHECK(gpu_thread_runner_->BelongsToCurrentThread());
+  DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
+  auto* surface = factory_->GetSurface(widget);
+  // There can be a race between destruction and submitting the last frames. The
+  // surface can be destroyed by the time the host receives a request to destroy
+  // a buffer, and is able to call the OnSubmission for that specific buffer.
+  if (surface)
+    surface->OnSubmission(buffer_id, swap_result);
+}
+
+void WaylandConnectionProxy::OnPresentation(
+    gfx::AcceleratedWidget widget,
+    uint32_t buffer_id,
+    const gfx::PresentationFeedback& feedback) {
+  DCHECK(gpu_thread_runner_->BelongsToCurrentThread());
+  DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
+  auto* surface = factory_->GetSurface(widget);
+  // There can be a race between destruction and presenting the last frames. The
+  // surface can be destroyed by the time the host receives a request to destroy
+  // a buffer, and is able to call the OnPresentation for that specific buffer.
+  if (surface)
+    surface->OnPresentation(buffer_id, feedback);
+}
+
 void WaylandConnectionProxy::CreateZwpLinuxDmabuf(
     base::File file,
     gfx::Size size,
@@ -69,10 +102,9 @@
   // from the thread, which is used to call these methods. Thus, rebind the
   // interface on a first call to ensure mojo calls will always happen on a
   // sequence we want.
-  if (!bound_) {
-    wc_ptr_.Bind(std::move(wc_ptr_info_));
-    bound_ = true;
-  }
+  if (!wc_ptr_.is_bound())
+    BindHostInterface();
+
   DCHECK(gpu_thread_runner_->BelongsToCurrentThread());
   DCHECK(wc_ptr_);
   wc_ptr_->CreateZwpLinuxDmabuf(std::move(file), size.width(), size.height(),
@@ -80,31 +112,36 @@
                                 planes_count, buffer_id);
 }
 
-void WaylandConnectionProxy::DestroyZwpLinuxDmabuf(uint32_t buffer_id) {
+void WaylandConnectionProxy::DestroyZwpLinuxDmabuf(
+    gfx::AcceleratedWidget widget,
+    uint32_t buffer_id) {
   DCHECK(gpu_thread_runner_);
+
   // Do a mojo call on the GpuMainThread instead of the io child thread to
   // ensure proper functionality.
   gpu_thread_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(&WaylandConnectionProxy::DestroyZwpLinuxDmabufInternal,
-                     base::Unretained(this), buffer_id));
+                     base::Unretained(this), widget, buffer_id));
 }
 
-void WaylandConnectionProxy::DestroyZwpLinuxDmabufInternal(uint32_t buffer_id) {
+void WaylandConnectionProxy::DestroyZwpLinuxDmabufInternal(
+    gfx::AcceleratedWidget widget,
+    uint32_t buffer_id) {
   DCHECK(gpu_thread_runner_->BelongsToCurrentThread());
   DCHECK(wc_ptr_);
+
   wc_ptr_->DestroyZwpLinuxDmabuf(buffer_id);
 }
 
 void WaylandConnectionProxy::ScheduleBufferSwap(
     gfx::AcceleratedWidget widget,
     uint32_t buffer_id,
-    const gfx::Rect& damage_region,
-    wl::BufferSwapCallback callback) {
+    const gfx::Rect& damage_region) {
   DCHECK(gpu_thread_runner_->BelongsToCurrentThread());
   DCHECK(wc_ptr_);
-  wc_ptr_->ScheduleBufferSwap(widget, buffer_id, damage_region,
-                              std::move(callback));
+
+  wc_ptr_->ScheduleBufferSwap(widget, buffer_id, damage_region);
 }
 
 void WaylandConnectionProxy::CreateShmBufferForWidget(
@@ -112,10 +149,9 @@
     base::File file,
     size_t length,
     const gfx::Size size) {
-  if (!bound_) {
-    wc_ptr_.Bind(std::move(wc_ptr_info_));
-    bound_ = true;
-  }
+  if (!wc_ptr_.is_bound())
+    BindHostInterface();
+
   DCHECK(wc_ptr_);
   wc_ptr_->CreateShmBufferForWidget(widget, std::move(file), length, size);
 }
@@ -163,4 +199,15 @@
   bindings_.AddBinding(this, std::move(request));
 }
 
+void WaylandConnectionProxy::BindHostInterface() {
+  DCHECK(!wc_ptr_.is_bound());
+  wc_ptr_.Bind(std::move(wc_ptr_info_));
+
+  // Setup associated interface.
+  ozone::mojom::WaylandConnectionClientAssociatedPtrInfo client_ptr_info;
+  auto request = MakeRequest(&client_ptr_info);
+  wc_ptr_->SetWaylandConnectionClient(std::move(client_ptr_info));
+  associated_binding_.Bind(std::move(request));
+}
+
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h b/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h
index 9ac1542..6b97559e 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h
+++ b/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h
@@ -10,8 +10,10 @@
 #include "base/macros.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "ui/gfx/native_widget_types.h"
+#include "ui/gl/gl_surface.h"
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
 #include "ui/ozone/public/interfaces/wayland/wayland_connection.mojom.h"
@@ -28,6 +30,7 @@
 namespace ui {
 
 class WaylandConnection;
+class WaylandSurfaceFactory;
 class WaylandWindow;
 
 // Provides a proxy connection to a WaylandConnection object on
@@ -39,12 +42,22 @@
 // sequence.
 class WaylandConnectionProxy : public ozone::mojom::WaylandConnectionClient {
  public:
-  explicit WaylandConnectionProxy(WaylandConnection* connection);
+  WaylandConnectionProxy(WaylandConnection* connection,
+                         WaylandSurfaceFactory* factory);
   ~WaylandConnectionProxy() override;
 
   // WaylandConnectionProxy overrides:
   void SetWaylandConnection(ozone::mojom::WaylandConnectionPtr wc_ptr) override;
   void ResetGbmDevice() override;
+  // These two calls get the surface, which backs the |widget| and notifies it
+  // about the submission and the presentation. After the surface receives the
+  // OnSubmission call, it can schedule a new buffer for swap.
+  void OnSubmission(gfx::AcceleratedWidget widget,
+                    uint32_t buffer_id,
+                    gfx::SwapResult swap_result) override;
+  void OnPresentation(gfx::AcceleratedWidget widget,
+                      uint32_t buffer_id,
+                      const gfx::PresentationFeedback& feedback) override;
 
   // Methods, which must be used when GPU is hosted on a different process
   // aka gpu process.
@@ -61,16 +74,21 @@
                             uint32_t buffer_id);
 
   // Asks Wayland to destroy a wl_buffer.
-  void DestroyZwpLinuxDmabuf(uint32_t buffer_id);
+  void DestroyZwpLinuxDmabuf(gfx::AcceleratedWidget widget, uint32_t buffer_id);
 
   // Asks Wayland to find a wl_buffer with the |buffer_id| and schedule a
   // buffer swap for a WaylandWindow, which backs the following |widget|.
-  // The |callback| is called once a frame callback from the Wayland server
-  // is received.
+  // Once the buffer is submitted and presented, the OnSubmission and
+  // OnPresentation are called. Note, it's not guaranteed the OnPresentation
+  // will follow the OnSubmission immediately, but the OnPresentation must never
+  // be called before the OnSubmission is called for that particular buffer.
+  // This logic must be checked by the client, though the host ensures this
+  // logic as well. This call must not be done twice for the same |widget| until
+  // the OnSubmission is called (which actually means the client can continue
+  // sending buffer swap requests).
   void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
                           uint32_t buffer_id,
-                          const gfx::Rect& damage_region,
-                          wl::BufferSwapCallback callback);
+                          const gfx::Rect& damage_region);
 
 #if defined(WAYLAND_GBM)
   // Returns a gbm_device based on a DRM render node.
@@ -127,12 +145,19 @@
                                     uint32_t current_format,
                                     uint32_t planes_count,
                                     uint32_t buffer_id);
-  void DestroyZwpLinuxDmabufInternal(uint32_t buffer_id);
+  void DestroyZwpLinuxDmabufInternal(gfx::AcceleratedWidget widget,
+                                     uint32_t buffer_id);
+
+  void BindHostInterface();
 
   // Non-owned pointer to a WaylandConnection. It is only used in a single
   // process mode, when a shared dmabuf approach is not used.
   WaylandConnection* const connection_;
 
+  // Non-owned. Only used to get registered surfaces and notify them about
+  // submission and presentation of buffers.
+  WaylandSurfaceFactory* const factory_;
+
 #if defined(WAYLAND_GBM)
   // A DRM render node based gbm device.
   std::unique_ptr<GbmDevice> gbm_device_;
@@ -144,7 +169,9 @@
   // process side. It's used for a multi-process mode.
   ozone::mojom::WaylandConnectionPtr wc_ptr_;
   ozone::mojom::WaylandConnectionPtrInfo wc_ptr_info_;
-  bool bound_ = false;
+
+  mojo::AssociatedBinding<ozone::mojom::WaylandConnectionClient>
+      associated_binding_;
 
   // A task runner, which is initialized in a multi-process mode. It is used to
   // ensure all the methods of this class are run on GpuMainThread. This is
diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc b/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
index e0c80a9a..163df70 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_surface_factory.cc
@@ -84,7 +84,8 @@
   // If there is a gbm device available, use surfaceless gl surface.
   if (!connection_->gbm_device())
     return nullptr;
-  return gl::InitializeGLSurface(new GbmSurfacelessWayland(factory_, window));
+  return gl::InitializeGLSurface(
+      new GbmSurfacelessWayland(factory_, connection_, window));
 #else
   return nullptr;
 #endif
@@ -113,15 +114,17 @@
 
 }  // namespace
 
-WaylandSurfaceFactory::WaylandSurfaceFactory(WaylandConnectionProxy* connection)
-    : connection_(connection) {
-  if (connection_)
-    egl_implementation_ =
-        std::make_unique<GLOzoneEGLWayland>(connection_, this);
-}
+WaylandSurfaceFactory::WaylandSurfaceFactory() {}
 
 WaylandSurfaceFactory::~WaylandSurfaceFactory() {}
 
+void WaylandSurfaceFactory::SetProxy(WaylandConnectionProxy* proxy) {
+  DCHECK(!connection_ && proxy);
+  connection_ = proxy;
+
+  egl_implementation_ = std::make_unique<GLOzoneEGLWayland>(connection_, this);
+}
+
 void WaylandSurfaceFactory::RegisterSurface(gfx::AcceleratedWidget widget,
                                             GbmSurfacelessWayland* surface) {
   widget_to_surface_map_.insert(std::make_pair(widget, surface));
@@ -133,19 +136,13 @@
 
 GbmSurfacelessWayland* WaylandSurfaceFactory::GetSurface(
     gfx::AcceleratedWidget widget) const {
+  GbmSurfacelessWayland* surface = nullptr;
   auto it = widget_to_surface_map_.find(widget);
-  DCHECK(it != widget_to_surface_map_.end());
-  return it->second;
+  if (it != widget_to_surface_map_.end())
+    surface = it->second;
+  return surface;
 }
 
-void WaylandSurfaceFactory::ScheduleBufferSwap(
-    gfx::AcceleratedWidget widget,
-    uint32_t buffer_id,
-    const gfx::Rect& damage_region,
-    wl::BufferSwapCallback callback) {
-  connection_->ScheduleBufferSwap(widget, buffer_id, damage_region,
-                                  std::move(callback));
-}
 
 std::unique_ptr<SurfaceOzoneCanvas>
 WaylandSurfaceFactory::CreateCanvasForWidget(gfx::AcceleratedWidget widget) {
@@ -180,7 +177,7 @@
     gfx::BufferUsage usage) {
 #if defined(WAYLAND_GBM)
   scoped_refptr<GbmPixmapWayland> pixmap =
-      base::MakeRefCounted<GbmPixmapWayland>(this, connection_);
+      base::MakeRefCounted<GbmPixmapWayland>(this, connection_, widget);
   if (!pixmap->InitializeBuffer(size, format, usage))
     return nullptr;
   return pixmap;
diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_factory.h b/ui/ozone/platform/wayland/gpu/wayland_surface_factory.h
index 39116b7..e2730d6 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_surface_factory.h
+++ b/ui/ozone/platform/wayland/gpu/wayland_surface_factory.h
@@ -15,10 +15,6 @@
 #include "ui/ozone/platform/wayland/common/wayland_util.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
 
-namespace gfx {
-class Rect;
-}  // namespace gfx
-
 namespace ui {
 
 class GbmSurfacelessWayland;
@@ -26,14 +22,12 @@
 
 class WaylandSurfaceFactory : public SurfaceFactoryOzone {
  public:
-  explicit WaylandSurfaceFactory(WaylandConnectionProxy* connection);
+  WaylandSurfaceFactory();
   ~WaylandSurfaceFactory() override;
 
+  void SetProxy(WaylandConnectionProxy* proxy);
+
   // These methods are used, when a dmabuf based approach is used.
-  void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
-                          uint32_t buffer_id,
-                          const gfx::Rect& damage_region_,
-                          wl::BufferSwapCallback callback);
   void RegisterSurface(gfx::AcceleratedWidget widget,
                        GbmSurfacelessWayland* surface);
   void UnregisterSurface(gfx::AcceleratedWidget widget);
diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
index 2eee676..970e031f 100644
--- a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
+++ b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
@@ -89,7 +89,9 @@
 
 class WaylandSurfaceFactoryTest : public WaylandTest {
  public:
-  WaylandSurfaceFactoryTest() : surface_factory_(connection_proxy_.get()) {}
+  WaylandSurfaceFactoryTest() {
+    surface_factory_.SetProxy(connection_proxy_.get());
+  }
 
   ~WaylandSurfaceFactoryTest() override {}
 
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager.cc b/ui/ozone/platform/wayland/host/wayland_buffer_manager.cc
index 80e06d8..f44d61d 100644
--- a/ui/ozone/platform/wayland/host/wayland_buffer_manager.cc
+++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager.cc
@@ -42,9 +42,9 @@
 
 }  // namespace
 
-WaylandBufferManager::Buffer::Buffer() = default;
-WaylandBufferManager::Buffer::Buffer(const gfx::Size& buffer_size)
-    : size(buffer_size) {}
+WaylandBufferManager::Buffer::Buffer(const gfx::Size& buffer_size,
+                                     uint32_t buffer_id)
+    : size(buffer_size), buffer_id(buffer_id) {}
 WaylandBufferManager::Buffer::~Buffer() = default;
 
 WaylandBufferManager::WaylandBufferManager(WaylandConnection* connection)
@@ -75,7 +75,7 @@
   }
 
   std::unique_ptr<Buffer> buffer =
-      std::make_unique<Buffer>(gfx::Size(width, height));
+      std::make_unique<Buffer>(gfx::Size(width, height), buffer_id);
   buffers_.insert(std::make_pair(buffer_id, std::move(buffer)));
 
   auto callback = base::BindOnce(&WaylandBufferManager::OnCreateBufferComplete,
@@ -86,12 +86,10 @@
   return true;
 }
 
-// TODO(msisov): handle buffer swap failure or success.
 bool WaylandBufferManager::ScheduleBufferSwap(gfx::AcceleratedWidget widget,
                                               uint32_t buffer_id,
-                                              const gfx::Rect& damage_region,
-                                              wl::BufferSwapCallback callback) {
-  TRACE_EVENT1("wayland", "WaylandBufferManager::ScheduleBufferSwap",
+                                              const gfx::Rect& damage_region) {
+  TRACE_EVENT1("wayland", "WaylandBufferManager::ScheduleSwapBuffer",
                "Buffer id", buffer_id);
 
   if (!ValidateDataFromGpu(widget, buffer_id))
@@ -106,11 +104,11 @@
 
   Buffer* buffer = it->second.get();
   DCHECK(buffer);
+  DCHECK(!buffer->swapped && !buffer->presented);
 
   // Assign a widget to this buffer, which is used to find a corresponding
   // WaylandWindow.
   buffer->widget = widget;
-  buffer->buffer_swap_callback = std::move(callback);
   buffer->damage_region = damage_region;
 
   if (buffer->wl_buffer) {
@@ -130,15 +128,7 @@
     error_message_ = "Trying to destroy non-existing buffer";
     return false;
   }
-  // It can happen that a buffer is destroyed before a frame callback comes.
-  // Thus, just mark this as a successful swap, which is ok to do.
-  Buffer* buffer = it->second.get();
-  if (!buffer->buffer_swap_callback.is_null()) {
-    std::move(buffer->buffer_swap_callback)
-        .Run(gfx::SwapResult::SWAP_ACK,
-             gfx::PresentationFeedback(base::TimeTicks::Now(),
-                                       base::TimeDelta(), 0));
-  }
+
   buffers_.erase(it);
 
   connection_->ScheduleFlush();
@@ -283,10 +273,47 @@
     SwapBuffer(buffer);
 }
 
-void WaylandBufferManager::OnBufferSwapped(Buffer* buffer) {
-  DCHECK(!buffer->buffer_swap_callback.is_null());
-  std::move(buffer->buffer_swap_callback)
-      .Run(buffer->swap_result, std::move(buffer->feedback));
+void WaylandBufferManager::OnSubmission(Buffer* buffer,
+                                        const gfx::SwapResult& swap_result) {
+  DCHECK(!buffer->swapped);
+
+  buffer->wl_frame_callback.reset();
+  buffer->swapped = true;
+  connection_->OnSubmission(buffer->widget, buffer->buffer_id,
+                            gfx::SwapResult::SWAP_ACK);
+
+  // If presentation feedback is not supported, use a fake feedback.
+  if (!connection_->presentation()) {
+    DCHECK(!buffer->wp_presentation_feedback && !buffer->presented);
+    OnPresentation(buffer, gfx::PresentationFeedback(base::TimeTicks::Now(),
+                                                     base::TimeDelta(), 0));
+  } else if (buffer->presented) {
+    DCHECK(!buffer->wp_presentation_feedback);
+    // If the buffer has been presented before the frame callback aka
+    // completion callback (in the future, release callback is going to be
+    // used), present the feedback to the GPU.
+    OnPresentation(buffer, buffer->feedback);
+  } else {
+    DCHECK(buffer->wp_presentation_feedback);
+  }
+}
+
+void WaylandBufferManager::OnPresentation(
+    Buffer* buffer,
+    const gfx::PresentationFeedback& feedback) {
+  buffer->presented = true;
+  buffer->feedback = feedback;
+
+  // If buffer has already been swapped, we can safely notify about the
+  // presentation as well.
+  if (buffer->swapped) {
+    connection_->OnPresentation(buffer->widget, buffer->buffer_id,
+                                buffer->feedback);
+
+    // Reset the status so that DCHECK passes in ::ScheduleBufferSwap call.
+    buffer->presented = false;
+    buffer->swapped = false;
+  }
 }
 
 // static
@@ -295,27 +322,15 @@
                                              uint32_t time) {
   WaylandBufferManager* self = static_cast<WaylandBufferManager*>(data);
   DCHECK(self);
+
   for (auto& item : self->buffers_) {
     Buffer* buffer = item.second.get();
     if (buffer->wl_frame_callback.get() == callback) {
-      buffer->swap_result = gfx::SwapResult::SWAP_ACK;
       buffer->wl_frame_callback.reset();
-
-      // If presentation feedback is not supported, use a fake feedback
-      if (!self->connection_->presentation()) {
-        buffer->feedback = gfx::PresentationFeedback(base::TimeTicks::Now(),
-                                                     base::TimeDelta(), 0);
-      }
-      // If presentation feedback event either has already been fired or
-      // has not been set, trigger swap callback.
-      if (!buffer->wp_presentation_feedback)
-        self->OnBufferSwapped(buffer);
-
+      self->OnSubmission(buffer, gfx::SwapResult::SWAP_ACK);
       return;
     }
   }
-
-  NOTREACHED();
 }
 
 // static
@@ -339,29 +354,20 @@
     uint32_t flags) {
   WaylandBufferManager* self = static_cast<WaylandBufferManager*>(data);
   DCHECK(self);
-
   for (auto& item : self->buffers_) {
     Buffer* buffer = item.second.get();
     if (buffer->wp_presentation_feedback.get() == wp_presentation_feedback) {
-      buffer->feedback = gfx::PresentationFeedback(
-          GetPresentationFeedbackTimeStamp(tv_sec_hi, tv_sec_lo, tv_nsec),
-          base::TimeDelta::FromNanoseconds(refresh),
-          GetPresentationKindFlags(flags));
+      DCHECK(!buffer->presented);
       buffer->wp_presentation_feedback.reset();
-
-      // Some compositors not always fire PresentationFeedback and Frame
-      // events in the same order (i.e, frame callbacks coming always before
-      // feedback presented/discaded ones). So, check FrameCallbackDone has
-      // already been called at this point, if yes, trigger the swap callback.
-      // otherwise it will be triggered in the upcoming frame callback.
-      if (!buffer->wl_frame_callback)
-        self->OnBufferSwapped(buffer);
-
+      self->OnPresentation(
+          buffer,
+          gfx::PresentationFeedback(
+              GetPresentationFeedbackTimeStamp(tv_sec_hi, tv_sec_lo, tv_nsec),
+              base::TimeDelta::FromNanoseconds(refresh),
+              GetPresentationKindFlags(flags)));
       return;
     }
   }
-
-  NOTREACHED();
 }
 
 // static
@@ -370,27 +376,15 @@
     struct wp_presentation_feedback* wp_presentation_feedback) {
   WaylandBufferManager* self = static_cast<WaylandBufferManager*>(data);
   DCHECK(self);
-
   for (auto& item : self->buffers_) {
     Buffer* buffer = item.second.get();
     if (buffer->wp_presentation_feedback.get() == wp_presentation_feedback) {
-      // Frame callback must come before a feedback is presented.
-      buffer->feedback = gfx::PresentationFeedback::Failure();
+      DCHECK(!buffer->presented);
       buffer->wp_presentation_feedback.reset();
-
-      // Some compositors not always fire PresentationFeedback and Frame
-      // events in the same order (i.e, frame callbacks coming always before
-      // feedback presented/discaded ones). So, check FrameCallbackDone has
-      // already been called at this point, if yes, trigger the swap callback.
-      // Otherwise it will be triggered in the upcoming frame callback.
-      if (!buffer->wl_frame_callback)
-        self->OnBufferSwapped(buffer);
-
+      self->OnPresentation(buffer, gfx::PresentationFeedback::Failure());
       return;
     }
   }
-
-  NOTREACHED();
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager.h b/ui/ozone/platform/wayland/host/wayland_buffer_manager.h
index 435484a0..c0ea0039 100644
--- a/ui/ozone/platform/wayland/host/wayland_buffer_manager.h
+++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager.h
@@ -51,11 +51,13 @@
   // Assigns a wl_buffer with |buffer_id| to a window with the same |widget|. On
   // error, false is returned and |error_message_| is set. A |damage_region|
   // identifies which part of the buffer is updated. If an empty region is
-  // provided, the whole buffer is updated.
+  // provided, the whole buffer is updated. Once a frame callback or
+  // presentation callback is received, WaylandConnection::OnSubmission and
+  // WaylandConnection::OnPresentation are called. Though, it is guaranteed
+  // OnPresentation won't be called earlier than OnSubmission.
   bool ScheduleBufferSwap(gfx::AcceleratedWidget widget,
                           uint32_t buffer_id,
-                          const gfx::Rect& damage_region,
-                          wl::BufferSwapCallback callback);
+                          const gfx::Rect& damage_region);
 
   // Destroys a buffer with |buffer_id| in |buffers_|. On error, false is
   // returned and |error_message_| is set.
@@ -75,13 +77,16 @@
   // to, its buffer id for simplier buffer management and other members specific
   // to this Buffer object on run-time.
   struct Buffer {
-    Buffer();
-    explicit Buffer(const gfx::Size& buffer_size);
+    Buffer() = delete;
+    Buffer(const gfx::Size& buffer_size, uint32_t buffer_id);
     ~Buffer();
 
     // Actual buffer size.
     const gfx::Size size;
 
+    // The id of the buffer.
+    const uint32_t buffer_id;
+
     // Widget to attached/being attach WaylandWindow.
     gfx::AcceleratedWidget widget = gfx::kNullAcceleratedWidget;
 
@@ -90,9 +95,6 @@
     // repainted.
     gfx::Rect damage_region;
 
-    // A buffer swap result once the buffer is committed.
-    gfx::SwapResult swap_result;
-
     // A feedback, which is received if a presentation feedback protocol is
     // supported.
     gfx::PresentationFeedback feedback;
@@ -100,9 +102,9 @@
     // A wl_buffer backed by a dmabuf created on the GPU side.
     wl::Object<struct wl_buffer> wl_buffer;
 
-    // A callback, which is called once the |wl_frame_callback| from the server
-    // is received.
-    wl::BufferSwapCallback buffer_swap_callback;
+    // Provide the status of this buffer. Reset on each new swap.
+    bool swapped = false;
+    bool presented = false;
 
     // A Wayland callback, which is triggered once wl_buffer has been committed
     // and it is right time to notify the GPU that it can start a new drawing
@@ -137,7 +139,9 @@
   void OnCreateBufferComplete(uint32_t buffer_id,
                               wl::Object<struct wl_buffer> new_buffer);
 
-  void OnBufferSwapped(Buffer* buffer);
+  void OnSubmission(Buffer* buffer, const gfx::SwapResult& swap_result);
+  void OnPresentation(Buffer* buffer,
+                      const gfx::PresentationFeedback& feedback);
 
   // wl_callback_listener
   static void FrameCallbackDone(void* data,
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc
index 0d10fa3c..0be2a976 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.cc
+++ b/ui/ozone/platform/wayland/host/wayland_connection.cc
@@ -183,6 +183,11 @@
   return modifiers;
 }
 
+void WaylandConnection::SetWaylandConnectionClient(
+    ozone::mojom::WaylandConnectionClientAssociatedPtrInfo client) {
+  client_associated_ptr_.Bind(std::move(client));
+}
+
 void WaylandConnection::CreateZwpLinuxDmabuf(
     base::File file,
     uint32_t width,
@@ -212,18 +217,14 @@
   }
 }
 
-void WaylandConnection::ScheduleBufferSwap(
-    gfx::AcceleratedWidget widget,
-    uint32_t buffer_id,
-    const gfx::Rect& damage_region,
-    ScheduleBufferSwapCallback callback) {
+void WaylandConnection::ScheduleBufferSwap(gfx::AcceleratedWidget widget,
+                                           uint32_t buffer_id,
+                                           const gfx::Rect& damage_region) {
   DCHECK(base::MessageLoopCurrentForUI::IsSet());
 
   CHECK(buffer_manager_);
-  if (!buffer_manager_->ScheduleBufferSwap(widget, buffer_id, damage_region,
-                                           std::move(callback))) {
+  if (!buffer_manager_->ScheduleBufferSwap(widget, buffer_id, damage_region))
     TerminateGpuProcess(buffer_manager_->error_message());
-  }
 }
 
 void WaylandConnection::CreateShmBufferForWidget(gfx::AcceleratedWidget widget,
@@ -249,6 +250,21 @@
     TerminateGpuProcess("Failed to destroy SHM buffer.");
 }
 
+void WaylandConnection::OnSubmission(gfx::AcceleratedWidget widget,
+                                     uint32_t buffer_id,
+                                     const gfx::SwapResult& swap_result) {
+  DCHECK(client_associated_ptr_);
+  client_associated_ptr_->OnSubmission(widget, buffer_id, swap_result);
+}
+
+void WaylandConnection::OnPresentation(
+    gfx::AcceleratedWidget widget,
+    uint32_t buffer_id,
+    const gfx::PresentationFeedback& feedback) {
+  DCHECK(client_associated_ptr_);
+  client_associated_ptr_->OnPresentation(widget, buffer_id, feedback);
+}
+
 PlatformClipboard* WaylandConnection::GetPlatformClipboard() {
   return this;
 }
@@ -295,7 +311,8 @@
 }
 
 void WaylandConnection::OnChannelDestroyed() {
-  binding_.Unbind();
+  client_associated_ptr_.reset();
+  binding_.Close();
   if (buffer_manager_)
     buffer_manager_->ClearState();
 }
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h
index c1ec041..2edbdb7 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.h
+++ b/ui/ozone/platform/wayland/host/wayland_connection.h
@@ -52,6 +52,8 @@
   //
   // These overridden methods below are invoked by the GPU when hardware
   // accelerated rendering is used.
+  void SetWaylandConnectionClient(
+      ozone::mojom::WaylandConnectionClientAssociatedPtrInfo client) override;
   //
   // Called by the GPU and asks to import a wl_buffer based on a gbm file
   // descriptor.
@@ -68,13 +70,14 @@
   void DestroyZwpLinuxDmabuf(uint32_t buffer_id) override;
   // Called by the GPU and asks to attach a wl_buffer with a |buffer_id| to a
   // WaylandWindow with the specified |widget|.
+  // Calls OnSubmission and OnPresentation on successful swap and pixels
+  // presented.
   void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
                           uint32_t buffer_id,
-                          const gfx::Rect& damage_region,
-                          ScheduleBufferSwapCallback callback) override;
+                          const gfx::Rect& damage_region) override;
   // These overridden methods below are invoked by the GPU when hardware
   // accelerated rendering is not used. Check comments in the
-  // ui/ozone/public/interfaces/wayland/host/wayland_connection.mojom.
+  // ui/ozone/public/interfaces/wayland/wayland_connection.mojom.
   void CreateShmBufferForWidget(gfx::AcceleratedWidget widget,
                                 base::File file,
                                 uint64_t length,
@@ -83,6 +86,20 @@
                                  const gfx::Rect& damage) override;
   void DestroyShmBuffer(gfx::AcceleratedWidget widget) override;
 
+  // These methods are exclusively used by the WaylandBufferManager to notify
+  // the |client_associated_ptr_| about buffer swaps' results.
+  // TODO(msisov): move these and the above mojo methods into the
+  // WaylandBufferManager and establish end-to-end communication with
+  // WaylandBufferManagerGpu and WaylandBufferManagerHost instead (basically, to
+  // avoid having the WaylandConnection as proxy in between).
+  // https://crbug.com/947411
+  void OnSubmission(gfx::AcceleratedWidget widget,
+                    uint32_t buffer_id,
+                    const gfx::SwapResult& swap_result);
+  void OnPresentation(gfx::AcceleratedWidget widget,
+                      uint32_t buffer_id,
+                      const gfx::PresentationFeedback& feedback);
+
   // Schedules a flush of the Wayland connection.
   void ScheduleFlush();
 
@@ -278,6 +295,7 @@
   // Stores the callback to be invoked upon data reading from clipboard.
   RequestDataClosure read_clipboard_closure_;
 
+  ozone::mojom::WaylandConnectionClientAssociatedPtr client_associated_ptr_;
   mojo::Binding<ozone::mojom::WaylandConnection> binding_;
 
   // A callback, which is used to terminate a GPU process in case of invalid
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index c368863f..55a51f9 100644
--- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -13,7 +13,6 @@
 #include "base/memory/ptr_util.h"
 #include "ui/base/buildflags.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
-#include "ui/display/manager/fake_display_delegate.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/events/system_input_injector.h"
 #include "ui/gfx/linux/client_native_pixmap_dmabuf.h"
@@ -114,7 +113,7 @@
 
   std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate()
       override {
-    return std::make_unique<display::FakeDisplayDelegate>();
+    return nullptr;
   }
 
   std::unique_ptr<PlatformScreen> CreateScreen() override {
@@ -168,8 +167,10 @@
   }
 
   void InitializeGPU(const InitParams& args) override {
-    proxy_.reset(new WaylandConnectionProxy(connection_.get()));
-    surface_factory_.reset(new WaylandSurfaceFactory(proxy_.get()));
+    surface_factory_ = std::make_unique<WaylandSurfaceFactory>();
+    proxy_ = std::make_unique<WaylandConnectionProxy>(connection_.get(),
+                                                      surface_factory_.get());
+    surface_factory_->SetProxy(proxy_.get());
 #if defined(WAYLAND_GBM)
     const base::FilePath drm_node_path = path_finder_.GetDrmRenderNodePath();
     if (drm_node_path.empty()) {
diff --git a/ui/ozone/platform/wayland/test/wayland_test.cc b/ui/ozone/platform/wayland/test/wayland_test.cc
index 11f3b7a0..e96443b 100644
--- a/ui/ozone/platform/wayland/test/wayland_test.cc
+++ b/ui/ozone/platform/wayland/test/wayland_test.cc
@@ -31,7 +31,8 @@
       std::make_unique<StubKeyboardLayoutEngine>());
 #endif
   connection_.reset(new WaylandConnection);
-  connection_proxy_.reset(new WaylandConnectionProxy(connection_.get()));
+  connection_proxy_.reset(
+      new WaylandConnectionProxy(connection_.get(), nullptr));
   window_ = std::make_unique<WaylandWindow>(&delegate_, connection_.get());
 }
 
diff --git a/ui/ozone/public/interfaces/wayland/wayland_connection.mojom b/ui/ozone/public/interfaces/wayland/wayland_connection.mojom
index f7fc677..713ac9a2 100644
--- a/ui/ozone/public/interfaces/wayland/wayland_connection.mojom
+++ b/ui/ozone/public/interfaces/wayland/wayland_connection.mojom
@@ -14,6 +14,9 @@
 // Used by the GPU for communication with a WaylandConnection on the browser
 // process.
 interface WaylandConnection {
+  // Sets up an associated pipe between the Client and Host.
+  SetWaylandConnectionClient(associated WaylandConnectionClient client);
+
   // Methods used for hardware accelerated rendering:
   //
   // Asks Wayland to create a wl_buffer based on the dmabuf |file| descriptor.
@@ -32,9 +35,7 @@
 
   // Swaps wl_buffers for a WaylandWindow with the following |widget|.
   ScheduleBufferSwap(gfx.mojom.AcceleratedWidget widget, uint32 buffer_id,
-                     gfx.mojom.Rect damage_region)
-      => (gfx.mojom.SwapResult swap_result,
-          gfx.mojom.PresentationFeedback feedback);
+                     gfx.mojom.Rect damage_region);
 
   // Methods used for software rendering:
   //
@@ -65,4 +66,14 @@
   // avoid using zwp_linux_dmabuf protocol, which means using wl_egl_surface in
   // a single process mode, and software rendering in a multiple process mode.
   ResetGbmDevice();
+
+  // Signals about swap completion.
+  OnSubmission(gfx.mojom.AcceleratedWidget widget,
+               uint32 buffer_id,
+               gfx.mojom.SwapResult swap_result);
+
+  // Signals about presentation.
+  OnPresentation(gfx.mojom.AcceleratedWidget widget,
+                 uint32 buffer_id,
+                 gfx.mojom.PresentationFeedback feedback);
 };
diff --git a/ui/platform_window/mojo/BUILD.gn b/ui/platform_window/mojo/BUILD.gn
index 4a344c3..b42cf4f 100644
--- a/ui/platform_window/mojo/BUILD.gn
+++ b/ui/platform_window/mojo/BUILD.gn
@@ -11,7 +11,7 @@
   output_name = "mojo_ime_lib"
 
   public_deps = [
-    "//ui/base/ime:ime_types",
+    "//ui/base/ime",
   ]
   deps = [
     ":interfaces",
diff --git a/ui/strings/translations/ui_strings_ta.xtb b/ui/strings/translations/ui_strings_ta.xtb
index 7788315..2d3b6a9 100644
--- a/ui/strings/translations/ui_strings_ta.xtb
+++ b/ui/strings/translations/ui_strings_ta.xtb
@@ -21,6 +21,7 @@
 <translation id="169515659049020177">Shift</translation>
 <translation id="1710340000377843106">இப்போது</translation>
 <translation id="1752946267035950200">{MINUTES,plural, =1{1 நிமிடம்}other{# நிமிடங்கள்}}</translation>
+<translation id="1756116796893109054">தாவலை அனுப்புகிறது...</translation>
 <translation id="1761785978543082658"><ph name="QUANTITY" /> பை</translation>
 <translation id="1801827354178857021">காலம்</translation>
 <translation id="1803208670097017349">{MONTHS,plural, =1{1 மாதம்}other{# மாதங்கள்}}</translation>
@@ -52,11 +53,14 @@
 <translation id="2515586267016047495">Alt</translation>
 <translation id="2522350507219695259">அளவுத்திருத்தம் முடிந்தது</translation>
 <translation id="252373100621549798">அறியாதது</translation>
+<translation id="2573731672208488250">{HOURS,plural, =1{ஒரு மணிநேரத்தில்}other{#h மணிநேரத்தில்}}</translation>
 <translation id="2583543531130364912">டச்ஸ்கிரீனை அளவுத்திருத்தம் செய்யவும்</translation>
 <translation id="2666092431469916601">மேலே</translation>
+<translation id="2701330563083355633"><ph name="DEVICE_NAME" /> சாதனத்தில் இருந்து பகிரப்பட்டுள்ளது</translation>
 <translation id="2743387203779672305">கிளிப்போர்டுக்கு நகலெடு</translation>
 <translation id="2803313416453193357">கோப்புறையைத் திற</translation>
 <translation id="2824719307700604149">{YEARS,plural, =1{1 ஆண்டுக்கு முன்}other{# ஆண்டுகளுக்கு முன்}}</translation>
+<translation id="2907671656515444832">{DAYS,plural, =1{ஒரு நாளில்}other{#d நாட்களில்}}</translation>
 <translation id="2931838996092594335">கிளிக் செய்க</translation>
 <translation id="3036649622769666520">கோப்புகளைத் திற</translation>
 <translation id="3049748772180311791"><ph name="QUANTITY" /> மெ.பை</translation>
@@ -115,6 +119,7 @@
 <translation id="5613020302032141669">இடது அம்பு</translation>
 <translation id="5754277640426581776">{MINUTES,plural, =1{1 நிமிடம்}other{# நிமிடங்கள்}}</translation>
 <translation id="5768079895599174203">{DAYS,plural, =1{1 நாள், }other{# நாட்கள், }}</translation>
+<translation id="5866104238061687188">{YEARS,plural, =1{ஓர் ஆண்டில்}other{#y ஆண்டுகளில்}}</translation>
 <translation id="5895138241574237353">மறுதொடக்கம்</translation>
 <translation id="5906667377645263094">{SECONDS,plural, =1{1 நிமிடம் உள்ளது}other{# நிமிடங்கள் உள்ளன}}</translation>
 <translation id="5941711191222866238">சிறிதாக்கு</translation>
@@ -170,6 +175,7 @@
 <translation id="7907591526440419938">கோப்பைத் திற</translation>
 <translation id="7969046989155602842">கமாண்ட்</translation>
 <translation id="8074552109918343525">{MAX_UNREAD_NOTIFICATIONS,plural, =1{1க்கு மேற்பட்ட அறிவிப்புகள் படிக்கப்படாமல் உள்ளன}other{#க்கு மேற்பட்ட அறிவிப்புகள் படிக்கப்படாமல் உள்ளன}}</translation>
+<translation id="8086866675552927481">{MINUTES,plural, =1{ஒரு நிமிடத்தில்}other{#m நிமிடங்களில்}}</translation>
 <translation id="8087772101393322318"><ph name="KEY_MODIFIER_NAME" />+<ph name="KEY_COMBO_NAME" /></translation>
 <translation id="8106081041558092062">{HOURS,plural, =1{1 மணிநேரம் முன்பு}other{# மணிநேரம் முன்பு}}</translation>
 <translation id="8131263257437993507">{SECONDS,plural, =1{1 நொடி உள்ளது}other{# நொடிகள் உள்ளன}}</translation>
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index df53ef4..21e5c91 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -531,7 +531,7 @@
     "//ui/accessibility:ax_enums_mojo",
     "//ui/base",
     "//ui/base/clipboard",
-    "//ui/base/ime",
+    "//ui/base/ime/init",
     "//ui/compositor",
     "//ui/display",
     "//ui/events",
@@ -549,7 +549,10 @@
 
   if (is_linux && !is_chromeos) {
     sources -= [ "window/window_button_order_provider.cc" ]
-    deps += [ "//ui/shell_dialogs" ]
+    deps += [
+      "//ui/base/ime/linux",
+      "//ui/shell_dialogs",
+    ]
   } else {
     public -= [
       "linux_ui/linux_ui.h",
@@ -908,7 +911,7 @@
     "//ui/base",
     "//ui/base:test_support",
     "//ui/base/clipboard:clipboard_test_support",
-    "//ui/base/ime",
+    "//ui/base/ime/init",
     "//ui/compositor",
     "//ui/compositor:test_support",
     "//ui/events",
@@ -1113,7 +1116,7 @@
     "//ui/base",
     "//ui/base:test_support",
     "//ui/base/clipboard",
-    "//ui/base/ime",
+    "//ui/base/ime/init",
     "//ui/compositor:test_support",
     "//ui/events:dom_keycode_converter",
     "//ui/events:events_base",
@@ -1176,6 +1179,10 @@
     ]
   }
 
+  if (is_linux && !is_chromeos) {
+    deps += [ "//ui/base/ime/linux" ]
+  }
+
   if (has_native_accessibility) {
     sources += [
       "accessibility/ax_virtual_view_unittest.cc",
@@ -1274,6 +1281,7 @@
     "//skia",
     "//testing/gtest",
     "//ui/base:test_support",
+    "//ui/base/ime",
     "//ui/compositor",
     "//ui/events:test_support",
     "//ui/gl:test_support",
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.mm b/ui/views/cocoa/bridged_native_widget_host_impl.mm
index db8c010..3508e9db 100644
--- a/ui/views/cocoa/bridged_native_widget_host_impl.mm
+++ b/ui/views/cocoa/bridged_native_widget_host_impl.mm
@@ -13,8 +13,8 @@
 #include "ui/base/cocoa/remote_accessibility_api.h"
 #include "ui/base/cocoa/remote_layer_api.h"
 #include "ui/base/hit_test.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_factory.h"
 #include "ui/compositor/recyclable_compositor_mac.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/dip_util.h"
diff --git a/ui/views/cocoa/drag_drop_client_mac.mm b/ui/views/cocoa/drag_drop_client_mac.mm
index 7826c2f2..34aeec3 100644
--- a/ui/views/cocoa/drag_drop_client_mac.mm
+++ b/ui/views/cocoa/drag_drop_client_mac.mm
@@ -62,12 +62,7 @@
   NSImage* image = gfx::NSImageFromImageSkiaWithColorSpace(
       provider_mac.GetDragImage(), base::mac::GetSRGBColorSpace());
 
-  // TODO(crbug/876201): This shouldn't happen. When a repro for this
-  // is identified and the bug is fixed, change the early return to
-  // a DCHECK.
-  if (!image || NSEqualSizes([image size], NSZeroSize))
-    return;
-
+  DCHECK(!NSEqualSizes([image size], NSZeroSize));
   NSDraggingItem* drag_item = provider_mac.GetDraggingItem();
 
   // Subtract the image's height from the y location so that the mouse will be
diff --git a/ui/views/controls/button/menu_button_controller.cc b/ui/views/controls/button/menu_button_controller.cc
index 02031d0..0699575 100644
--- a/ui/views/controls/button/menu_button_controller.cc
+++ b/ui/views/controls/button/menu_button_controller.cc
@@ -63,10 +63,10 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MenuButtonController::MenuButtonController(
-    MenuButton* menu_button,
+    Button* button,
     MenuButtonListener* listener,
     std::unique_ptr<ButtonControllerDelegate> delegate)
-    : ButtonController(menu_button, std::move(delegate)), listener_(listener) {}
+    : ButtonController(button, std::move(delegate)), listener_(listener) {}
 
 MenuButtonController::~MenuButtonController() = default;
 
@@ -238,9 +238,7 @@
 
     // We don't set our state here. It's handled in the MenuController code or
     // by our click listener.
-    // TODO(cyan): Remove the static cast.
-    listener_->OnMenuButtonClicked(static_cast<MenuButton*>(button()),
-                                   menu_position, event);
+    listener_->OnMenuButtonClicked(button(), menu_position, event);
 
     if (!ref) {
       // The menu was deleted while showing. Don't attempt any processing.
diff --git a/ui/views/controls/button/menu_button_controller.h b/ui/views/controls/button/menu_button_controller.h
index 207d35e4..7932afb 100644
--- a/ui/views/controls/button/menu_button_controller.h
+++ b/ui/views/controls/button/menu_button_controller.h
@@ -40,8 +40,7 @@
     DISALLOW_COPY_AND_ASSIGN(PressedLock);
   };
 
-  // TODO(cyan): MenuButtonController should take in a Button.
-  MenuButtonController(MenuButton* menu_button,
+  MenuButtonController(Button* button,
                        MenuButtonListener* listener,
                        std::unique_ptr<ButtonControllerDelegate> delegate);
   ~MenuButtonController() override;
diff --git a/ui/views/controls/button/menu_button_listener.h b/ui/views/controls/button/menu_button_listener.h
index 17079e3..f02e814 100644
--- a/ui/views/controls/button/menu_button_listener.h
+++ b/ui/views/controls/button/menu_button_listener.h
@@ -16,7 +16,7 @@
 }
 
 namespace views {
-class MenuButton;
+class Button;
 
 // An interface implemented by an object to let it know that a menu button was
 // clicked.
@@ -26,7 +26,7 @@
   // point to display the menu, and |event| is the event causing the click, if
   // any. (Note: "Clicked" refers to any activation, including e.g. accelerators
   // and key events).
-  virtual void OnMenuButtonClicked(MenuButton* source,
+  virtual void OnMenuButtonClicked(Button* source,
                                    const gfx::Point& point,
                                    const ui::Event* event) = 0;
 
diff --git a/ui/views/controls/button/menu_button_unittest.cc b/ui/views/controls/button/menu_button_unittest.cc
index 1ca5e49d..18665c52d 100644
--- a/ui/views/controls/button/menu_button_unittest.cc
+++ b/ui/views/controls/button/menu_button_unittest.cc
@@ -156,7 +156,7 @@
   TestMenuButtonListener() = default;
   ~TestMenuButtonListener() override = default;
 
-  void OnMenuButtonClicked(MenuButton* source,
+  void OnMenuButtonClicked(Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override {
     last_source_ = source;
@@ -186,7 +186,7 @@
 
   void set_menu_button(MenuButton* menu_button) { menu_button_ = menu_button; }
 
-  void OnMenuButtonClicked(MenuButton* source,
+  void OnMenuButtonClicked(Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override {
     pressed_lock_ = menu_button_->button_controller()->TakeLock();
@@ -316,13 +316,13 @@
   TestShowSiblingButtonListener() = default;
   ~TestShowSiblingButtonListener() override = default;
 
-  void OnMenuButtonClicked(MenuButton* source,
+  void OnMenuButtonClicked(Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override {
     // The MenuButton itself doesn't set the PRESSED state during Activate() or
     // OnMenuButtonClicked(). That should be handled by the MenuController or,
     // if no menu is shown, the listener.
-    EXPECT_EQ(Button::STATE_HOVERED, static_cast<MenuButton*>(source)->state());
+    EXPECT_EQ(Button::STATE_HOVERED, source->state());
   }
 
  private:
@@ -683,7 +683,7 @@
 
  private:
   // MenuButtonListener:
-  void OnMenuButtonClicked(MenuButton* source,
+  void OnMenuButtonClicked(Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override {
     menu_button_.reset();
diff --git a/ui/views/controls/scroll_view_unittest.cc b/ui/views/controls/scroll_view_unittest.cc
index a40ef51a..ea07f7f 100644
--- a/ui/views/controls/scroll_view_unittest.cc
+++ b/ui/views/controls/scroll_view_unittest.cc
@@ -744,10 +744,10 @@
   auto contents = std::make_unique<CustomView>();
   contents->SetPreferredSize(gfx::Size(500, 1000));
   auto* contents_ptr = scroll_view_->SetContents(std::move(contents));
-  FixedView* child = new FixedView;
+  auto child = std::make_unique<FixedView>();
   child->SetPreferredSize(gfx::Size(10, 10));
   child->SetPosition(gfx::Point(0, 405));
-  contents_ptr->AddChildView(child);
+  auto* child_ptr = contents_ptr->AddChildView(std::move(child));
 
   scroll_view_->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
   scroll_view_->Layout();
@@ -756,7 +756,7 @@
   // Set focus to the child control. This should cause the control to scroll to
   // y=405 height=10. Like the above test, this should make the y position of
   // the content at (405 + 10) - viewport_height (scroll region bottom aligned).
-  child->SetFocus();
+  child_ptr->SetFocus();
   const int viewport_height = test_api.contents_viewport()->height();
 
   // Expect there to be a horizontal scrollbar, making the viewport shorter.
@@ -906,8 +906,7 @@
   if (test_api.contents_viewport()->layer())
     return;
 
-  View* child = new View();
-  contents->AddChildView(child);
+  View* child = contents->AddChildView(std::make_unique<View>());
   child->SetPaintToLayer(ui::LAYER_TEXTURED);
 
   ASSERT_TRUE(test_api.contents_viewport()->layer());
@@ -922,8 +921,7 @@
   child->DestroyLayer();
   EXPECT_FALSE(test_api.contents_viewport()->layer());
 
-  View* child_child = new View();
-  child->AddChildView(child_child);
+  child->AddChildView(std::make_unique<View>());
   EXPECT_FALSE(test_api.contents_viewport()->layer());
   child->SetPaintToLayer(ui::LAYER_TEXTURED);
   EXPECT_TRUE(test_api.contents_viewport()->layer());
@@ -940,8 +938,7 @@
 
   scroll_view_->SetPaintToLayer();
 
-  View* child = new View();
-  contents->AddChildView(child);
+  View* child = contents->AddChildView(std::make_unique<View>());
   child->SetPaintToLayer(ui::LAYER_TEXTURED);
 
   EXPECT_FALSE(test_api.contents_viewport()->layer());
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc
index e16f8a9..6ced62f4 100644
--- a/ui/views/controls/textfield/textfield_unittest.cc
+++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -28,9 +28,9 @@
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/emoji/emoji_panel_helper.h"
 #include "ui/base/ime/constants.h"
+#include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/input_method_base.h"
 #include "ui/base/ime/input_method_delegate.h"
-#include "ui/base/ime/input_method_factory.h"
 #include "ui/base/ime/text_edit_commands.h"
 #include "ui/base/ime/text_input_client.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ui/views/examples/BUILD.gn b/ui/views/examples/BUILD.gn
index 4f311a7..b09a53d 100644
--- a/ui/views/examples/BUILD.gn
+++ b/ui/views/examples/BUILD.gn
@@ -121,6 +121,7 @@
     "//components/viz/host",
     "//components/viz/service",
     "//ui/base",
+    "//ui/base/ime/init",
     "//ui/compositor",
     "//ui/compositor:test_support",
     "//ui/gfx",
diff --git a/ui/views/examples/examples_main.cc b/ui/views/examples/examples_main.cc
index fe4d93c..f29aa2f 100644
--- a/ui/views/examples/examples_main.cc
+++ b/ui/views/examples/examples_main.cc
@@ -20,7 +20,7 @@
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_paths.h"
@@ -130,6 +130,9 @@
     display::Screen::SetScreenInstance(desktop_screen.get());
 #endif
 
+    // This app isn't a test and shouldn't timeout.
+    base::RunLoop::ScopedDisableRunTimeoutForTest disable_timeout;
+
     base::RunLoop run_loop;
     views::examples::ShowExamplesWindow(run_loop.QuitClosure());
 
diff --git a/ui/views/examples/menu_example.cc b/ui/views/examples/menu_example.cc
index 7a8c555..e88f2ee 100644
--- a/ui/views/examples/menu_example.cc
+++ b/ui/views/examples/menu_example.cc
@@ -64,7 +64,7 @@
 
  private:
   // MenuButtonListener:
-  void OnMenuButtonClicked(MenuButton* source,
+  void OnMenuButtonClicked(Button* source,
                            const gfx::Point& point,
                            const ui::Event* event) override;
 
@@ -174,7 +174,7 @@
 
 ExampleMenuButton::~ExampleMenuButton() = default;
 
-void ExampleMenuButton::OnMenuButtonClicked(MenuButton* source,
+void ExampleMenuButton::OnMenuButtonClicked(Button* source,
                                             const gfx::Point& point,
                                             const ui::Event* event) {
   menu_runner_ =
diff --git a/ui/views/mus/BUILD.gn b/ui/views/mus/BUILD.gn
index 7aa0968..28d22e8 100644
--- a/ui/views/mus/BUILD.gn
+++ b/ui/views/mus/BUILD.gn
@@ -64,6 +64,7 @@
     "//ui/accessibility",
     "//ui/accessibility/mojom",
     "//ui/aura",
+    "//ui/base/ime/init",
     "//ui/base/mojo:lib",
     "//ui/compositor",
     "//ui/display",
diff --git a/ui/views/mus/aura_init.cc b/ui/views/mus/aura_init.cc
index f7d65b6..a7f317e 100644
--- a/ui/views/mus/aura_init.cc
+++ b/ui/views/mus/aura_init.cc
@@ -12,7 +12,7 @@
 #include "build/build_config.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/aura/env.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_paths.h"
diff --git a/ui/views/test/scoped_views_test_helper.cc b/ui/views/test/scoped_views_test_helper.cc
index d67af1e8..5d141bf7 100644
--- a/ui/views/test/scoped_views_test_helper.cc
+++ b/ui/views/test/scoped_views_test_helper.cc
@@ -9,7 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/clipboard/test/test_clipboard.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/views/test/platform_test_helper.h"
 #include "ui/views/test/test_views_delegate.h"
 #include "ui/views/test/views_test_helper.h"
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h
index 06119b2..d962e212 100644
--- a/ui/views/widget/widget.h
+++ b/ui/views/widget/widget.h
@@ -20,6 +20,7 @@
 #include "ui/events/event_source.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
+#include "ui/native_theme/native_theme.h"
 #include "ui/native_theme/native_theme_observer.h"
 #include "ui/views/focus/focus_manager.h"
 #include "ui/views/widget/native_widget_delegate.h"
@@ -42,7 +43,6 @@
 class GestureRecognizer;
 class InputMethod;
 class Layer;
-class NativeTheme;
 class OSExchangeData;
 class ThemeProvider;
 }  // namespace ui
diff --git a/ui/views_content_client/BUILD.gn b/ui/views_content_client/BUILD.gn
index a20ef91d..77b0263 100644
--- a/ui/views_content_client/BUILD.gn
+++ b/ui/views_content_client/BUILD.gn
@@ -30,6 +30,7 @@
     "//content/shell:content_shell_lib",
     "//third_party/icu",
     "//ui/base",
+    "//ui/base/ime/init",
     "//ui/display",
     "//ui/events",
     "//ui/gfx",
diff --git a/ui/views_content_client/views_content_client_main_parts.cc b/ui/views_content_client/views_content_client_main_parts.cc
index 3f5be001..c1a83aa 100644
--- a/ui/views_content_client/views_content_client_main_parts.cc
+++ b/ui/views_content_client/views_content_client_main_parts.cc
@@ -10,7 +10,7 @@
 #include "build/build_config.h"
 #include "content/public/browser/context_factory.h"
 #include "content/shell/browser/shell_browser_context.h"
-#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/views/test/desktop_test_views_delegate.h"
 #include "ui/views_content_client/views_content_client.h"