diff --git a/BUILD.gn b/BUILD.gn
index 61b8940..0b73653 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1186,10 +1186,7 @@
       ]
     }
     if (enable_ipc_fuzzer && !is_component_build) {
-      deps += [
-        "//chrome/app:service_manifests",
-        "//tools/ipc_fuzzer:ipc_fuzzer_all",
-      ]
+      deps += [ "//tools/ipc_fuzzer:ipc_fuzzer_all" ]
     }
     if (!is_chromeos) {
       deps += [
diff --git a/DEPS b/DEPS
index 4335a8e..1d016ee 100644
--- a/DEPS
+++ b/DEPS
@@ -121,7 +121,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '212e9060ed298e8aa89e52080f8e80b033c95714',
+  'skia_revision': 'f6e963ef91c28b94bae45db7d2d30d6a0a307972',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -1199,7 +1199,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a2b35635aaef3e9301d69f77f9a0a3fd99291b08',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '35a9c6df44461580966b6f6d725db493ff764bce',
+    Var('webrtc_git') + '/src.git' + '@' + '7e0978c5e803809e273d6f8b48607917f63ccf05',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1230,7 +1230,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@85aaf9aabaf35ab7b2530d9c7ddb4cfacf481eee',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7234e488b92ea378bb2a86f25da39cb7b5941ec0',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java
index 499a0a0..3057d796 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java
@@ -31,8 +31,10 @@
 
     @Test
     @MediumTest
-    @CommandLineFlags.Add({"memlog=browser", "memlog-stack-mode=native-include-thread-names"})
-    public void testModeBrowser() throws Exception {
+    @CommandLineFlags.Add({"memlog=browser", "memlog-stack-mode=native-include-thread-names",
+            "memlog-sampling-rate=1"})
+    public void
+    testModeBrowser() throws Exception {
         HeapProfilingTestShim shim = new HeapProfilingTestShim();
         Assert.assertTrue(
                 shim.runTestForMode("browser", false, "native-include-thread-names", false, false));
diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc
index 49945e4..361de42 100644
--- a/ash/magnifier/magnification_controller.cc
+++ b/ash/magnifier/magnification_controller.cc
@@ -22,6 +22,7 @@
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
+#include "ui/base/ime/ime_bridge.h"
 #include "ui/base/ime/input_method.h"
 #include "ui/base/ime/text_input_client.h"
 #include "ui/compositor/dip_util.h"
@@ -83,9 +84,15 @@
 }
 
 ui::InputMethod* GetInputMethod(aura::Window* root_window) {
+  ui::IMEBridge* bridge = ui::IMEBridge::Get();
+  if (bridge && bridge->GetInputContextHandler())
+    return bridge->GetInputContextHandler()->GetInputMethod();
+
   if (root_window->GetHost())
     return root_window->GetHost()->GetInputMethod();
-  return nullptr;
+
+  // Needed by a handful of browser tests that use MockInputMethod.
+  return Shell::GetRootWindowForNewWindows()->GetHost()->GetInputMethod();
 }
 
 }  // namespace
@@ -121,6 +128,8 @@
   Shell::Get()->AddPreTargetHandler(this);
   root_window_->AddObserver(this);
   root_window_->GetHost()->GetEventSource()->AddEventRewriter(this);
+  if (ui::IMEBridge::Get())
+    ui::IMEBridge::Get()->AddObserver(this);
 
   point_of_interest_in_root_ = root_window_->bounds().CenterPoint();
 
@@ -130,9 +139,11 @@
 }
 
 MagnificationController::~MagnificationController() {
-  ui::InputMethod* input_method = GetInputMethod(root_window_);
-  if (input_method)
-    input_method->RemoveObserver(this);
+  if (input_method_)
+    input_method_->RemoveObserver(this);
+  input_method_ = nullptr;
+  if (ui::IMEBridge::Get())
+    ui::IMEBridge::Get()->RemoveObserver(this);
 
   root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this);
   root_window_->RemoveObserver(this);
@@ -141,11 +152,12 @@
 }
 
 void MagnificationController::SetEnabled(bool enabled) {
-  ui::InputMethod* input_method = GetInputMethod(root_window_);
   if (enabled) {
-    if (!is_enabled_ && input_method)
-      input_method->AddObserver(this);
-
+    if (!is_enabled_) {
+      input_method_ = GetInputMethod(root_window_);
+      if (input_method_)
+        input_method_->AddObserver(this);
+    }
     Shell* shell = Shell::Get();
     float scale =
         shell->accessibility_delegate()->GetSavedScreenMagnifierScale();
@@ -165,8 +177,9 @@
     if (!is_enabled_)
       return;
 
-    if (input_method)
-      input_method->RemoveObserver(this);
+    if (input_method_)
+      input_method_->RemoveObserver(this);
+    input_method_ = nullptr;
 
     RedrawKeepingMousePosition(kNonMagnifiedScale, true, false);
     is_enabled_ = enabled;
@@ -301,6 +314,18 @@
   return transform;
 }
 
+void MagnificationController::OnInputContextHandlerChanged() {
+  auto* new_input_method = GetInputMethod(root_window_);
+  if (!is_enabled_ || new_input_method == input_method_)
+    return;
+
+  if (input_method_)
+    input_method_->RemoveObserver(this);
+  input_method_ = new_input_method;
+  if (input_method_)
+    input_method_->AddObserver(this);
+}
+
 void MagnificationController::OnCaretBoundsChanged(
     const ui::TextInputClient* client) {
   // caret bounds in screen coordinates.
@@ -357,6 +382,13 @@
       this, &MagnificationController::OnMoveMagnifierTimer);
 }
 
+void MagnificationController::OnInputMethodDestroyed(
+    const ui::InputMethod* input_method) {
+  DCHECK_EQ(input_method, input_method_);
+  input_method_->RemoveObserver(this);
+  input_method_ = nullptr;
+}
+
 void MagnificationController::OnImplicitAnimationsCompleted() {
   if (!is_on_animation_)
     return;
diff --git a/ash/magnifier/magnification_controller.h b/ash/magnifier/magnification_controller.h
index eb1c4993..119d396 100644
--- a/ash/magnifier/magnification_controller.h
+++ b/ash/magnifier/magnification_controller.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/timer/timer.h"
 #include "ui/aura/window_observer.h"
+#include "ui/base/ime/ime_bridge_observer.h"
 #include "ui/base/ime/input_method_observer.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/events/event_handler.h"
@@ -47,6 +48,7 @@
 class ASH_EXPORT MagnificationController : public ui::EventHandler,
                                            public ui::ImplicitAnimationObserver,
                                            public aura::WindowObserver,
+                                           public ui::IMEBridgeObserver,
                                            public ui::InputMethodObserver,
                                            public ui::GestureConsumer,
                                            public ui::EventRewriter {
@@ -118,12 +120,16 @@
   // magnification is disabled, return an empty Transform.
   gfx::Transform GetMagnifierTransform() const;
 
+  // ui::IMEBridgeObserver:
+  void OnRequestSwitchEngine() override {}
+  void OnInputContextHandlerChanged() override;
+
   // ui::InputMethodObserver:
   void OnFocus() override {}
   void OnBlur() override {}
   void OnCaretBoundsChanged(const ui::TextInputClient* client) override;
   void OnTextInputStateChanged(const ui::TextInputClient* client) override {}
-  void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {}
+  void OnInputMethodDestroyed(const ui::InputMethod* input_method) override;
   void OnShowVirtualKeyboardIfEnabled() override {}
 
   // Returns the last mouse cursor (or last touched) location.
@@ -249,6 +255,9 @@
   // Target root window. This must not be NULL.
   aura::Window* root_window_;
 
+  // The currently active input method, observed for caret bounds changes.
+  ui::InputMethod* input_method_ = nullptr;
+
   // True if the magnified window is currently animating a change. Otherwise,
   // false.
   bool is_on_animation_ = false;
diff --git a/ash/shelf/shelf_constants.h b/ash/shelf/shelf_constants.h
index 4da9753..2f6eff0 100644
--- a/ash/shelf/shelf_constants.h
+++ b/ash/shelf/shelf_constants.h
@@ -37,25 +37,16 @@
 // Portion of the shelf that's within the screen bounds when auto-hidden.
 ASH_EXPORT constexpr int kHiddenShelfInScreenPortion = 3;
 
-// Animation duration for switching black shelf and dock background on and off.
-ASH_EXPORT constexpr int kTimeToSwitchBackgroundMs = 1000;
-
 // The default base color of the shelf to which different alpha values are
 // applied based on the desired shelf opacity level.
 ASH_EXPORT constexpr SkColor kShelfDefaultBaseColor = SK_ColorBLACK;
 
 // Size allocated for each app button on the shelf.
-ASH_EXPORT constexpr int kShelfButtonSize = 56;
+ASH_EXPORT constexpr int kShelfButtonSize = kShelfSize;
 
 // Size of the space between buttons on the shelf.
 ASH_EXPORT constexpr int kShelfButtonSpacing = 8;
 
-// Highlight color used for shelf button activated states.
-// TODO(bruthig|mohsen): Use of this color is temporary. Draw the active state
-// using the material design ripple animation.
-ASH_EXPORT constexpr SkColor kShelfButtonActivatedHighlightColor =
-    SkColorSetA(SK_ColorWHITE, 100);
-
 // Ink drop color for shelf items.
 constexpr SkColor kShelfInkDropBaseColor = SK_ColorWHITE;
 
@@ -81,18 +72,9 @@
 // The alpha value used to darken a colorized shelf when the shelf is opaque.
 constexpr int kShelfOpaqueColorDarkenAlpha = 178;
 
-// The width and height of the material design overflow button.
-constexpr int kOverflowButtonSize = 32;
-
-// The radius of the rounded corners of the overflow button.
-constexpr int kOverflowButtonCornerRadiusOldUi = 2;
-
 // The distance between the edge of the shelf and the status indicators.
 constexpr int kStatusIndicatorOffsetFromShelfEdge = 1;
 
-// The direction of the focus cycling.
-enum CycleDirection { CYCLE_FORWARD, CYCLE_BACKWARD };
-
 class ShelfConstants {
  public:
   // Size of the shelf when visible (height when the shelf is horizontal and
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index 8f5b37e8..ee49023 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -137,7 +137,7 @@
 class NestedMessagePumpAndroid;
 class SandboxHostLinux;
 class ScopedAllowWaitForDebugURL;
-class ServiceWorkerSubresourceLoader;
+class ServiceWorkerContextClient;
 class SessionStorageDatabase;
 class SoftwareOutputDeviceMus;
 class SynchronousCompositor;
@@ -369,7 +369,7 @@
   friend class base::GetAppOutputScopedAllowBaseSyncPrimitives;
   friend class content::BrowserMainLoop;
   friend class content::BrowserProcessSubThread;
-  friend class content::ServiceWorkerSubresourceLoader;
+  friend class content::ServiceWorkerContextClient;
   friend class content::SessionStorageDatabase;
   friend class functions::ExecScriptScopedAllowBaseSyncPrimitives;
   friend class internal::TaskTracker;
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 2b70e0d1..9e843f3 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -287,100 +287,16 @@
 # aix or one of the BSDs. If you need to check these, just check the
 # current_os value directly.
 
-if (current_os == "win" || current_os == "winuwp") {
-  is_android = false
-  is_chromeos = false
-  is_fuchsia = false
-  is_ios = false
-  is_linux = false
-  is_mac = false
-  is_nacl = false
-  is_posix = false
-  is_win = true
-} else if (current_os == "mac") {
-  is_android = false
-  is_chromeos = false
-  is_fuchsia = false
-  is_ios = false
-  is_linux = false
-  is_mac = true
-  is_nacl = false
-  is_posix = true
-  is_win = false
-} else if (current_os == "android") {
-  is_android = true
-  is_chromeos = false
-  is_fuchsia = false
-  is_ios = false
-  is_linux = false
-  is_mac = false
-  is_nacl = false
-  is_posix = true
-  is_win = false
-} else if (current_os == "chromeos") {
-  is_android = false
-  is_chromeos = true
-  is_fuchsia = false
-  is_ios = false
-  is_linux = true
-  is_mac = false
-  is_nacl = false
-  is_posix = true
-  is_win = false
-} else if (current_os == "nacl") {
-  # current_os == "nacl" will be passed by the nacl toolchain definition.
-  # It is not set by default or on the command line. We treat is as a
-  # Posix variant.
-  is_android = false
-  is_chromeos = false
-  is_fuchsia = false
-  is_ios = false
-  is_linux = false
-  is_mac = false
-  is_nacl = true
-  is_posix = true
-  is_win = false
-} else if (current_os == "fuchsia") {
-  is_android = false
-  is_chromeos = false
-  is_fuchsia = true
-  is_ios = false
-  is_linux = false
-  is_mac = false
-  is_nacl = false
-  is_posix = false
-  is_win = false
-} else if (current_os == "ios") {
-  is_android = false
-  is_chromeos = false
-  is_fuchsia = false
-  is_ios = true
-  is_linux = false
-  is_mac = false
-  is_nacl = false
-  is_posix = true
-  is_win = false
-} else if (current_os == "linux") {
-  is_android = false
-  is_chromeos = false
-  is_fuchsia = false
-  is_ios = false
-  is_linux = true
-  is_mac = false
-  is_nacl = false
-  is_posix = true
-  is_win = false
-} else if (current_os == "aix") {
-  is_android = false
-  is_chromeos = false
-  is_fuchsia = false
-  is_ios = false
-  is_linux = false
-  is_mac = false
-  is_nacl = false
-  is_posix = true
-  is_win = false
-}
+is_android = current_os == "android"
+is_chromeos = current_os == "chromeos"
+is_fuchsia = current_os == "fuchsia"
+is_ios = current_os == "ios"
+is_linux = current_os == "chromeos" || current_os == "linux"
+is_mac = current_os == "mac"
+is_nacl = current_os == "nacl"
+is_win = current_os == "win" || current_os == "winuwp"
+
+is_posix = !is_win && !is_fuchsia
 
 # =============================================================================
 # SOURCES FILTERS
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 07d8efa..97291b1 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -2230,10 +2230,7 @@
       # it all. This flag is incompatible with /PROFILE
       ldflags = [ "/DEBUG:FASTLINK" ]
     } else if (is_clang && use_lld && use_ghash) {
-      cflags += [
-        "-mllvm",
-        "-emit-codeview-ghash-section",
-      ]
+      cflags += [ "-gcodeview-ghash" ]
       ldflags = [ "/DEBUG:GHASH" ]
     } else {
       ldflags = [ "/DEBUG" ]
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 3889926..cf06dde 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0f03501be50bb12f79f2dfe16fda9fed57901dfe
\ No newline at end of file
+547d327493970d0cdd0f4f289c4b7222f34a24b6
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 436742d..eec2fd6 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-62991f299d80100ea7a239448aa52a7f53ef2178
\ No newline at end of file
+c49194362b1e6bd2684f7da62bf3d072d6702a91
\ No newline at end of file
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index 2ff0f55..dcbe126 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -123,9 +123,6 @@
       public_deps += [ ":reorder_imports" ]
       data_deps += [ ":reorder_imports" ]
     }
-    if (use_aura && (is_win || is_linux)) {
-      data_deps += [ "//chrome/app:service_manifests" ]
-    }
     if (is_chromeos) {
       data_deps += [ "//sandbox/linux:chrome_sandbox" ]
     }
@@ -1228,13 +1225,9 @@
     ]
 
     if (is_chrome_branded) {
-      framework_contents += [
-        "Default Apps",
-      ]
+      framework_contents += [ "Default Apps" ]
       if (enable_keystone_registration_framework) {
-        framework_contents += [
-          "Frameworks",  # For KeystoneRegistration.framework.
-        ]
+        framework_contents += [ "Frameworks" ]  # For KeystoneRegistration.framework.
       }
     }
 
diff --git a/chrome/VERSION b/chrome/VERSION
index ee836740..8da05cb 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=73
 MINOR=0
-BUILD=3652
+BUILD=3654
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
index 1941e76..3b7ad58 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -19,6 +19,7 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
 import org.chromium.components.signin.AccountManagerFacade;
+import org.chromium.components.signin.OAuth2TokenService;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.payments.mojom.PaymentOptions;
 
@@ -389,17 +390,17 @@
             return;
         }
 
-        AccountManagerFacade.get().getAuthToken(
-                mAccount, AUTH_TOKEN_TYPE, new AccountManagerFacade.GetAuthTokenCallback() {
+        OAuth2TokenService.getAccessToken(
+                mAccount, AUTH_TOKEN_TYPE, new OAuth2TokenService.GetAccessTokenCallback() {
                     @Override
-                    public void tokenAvailable(String token) {
+                    public void onGetTokenSuccess(String token) {
                         if (mUiControllerAndroid != 0) {
                             nativeOnAccessToken(mUiControllerAndroid, true, token);
                         }
                     }
 
                     @Override
-                    public void tokenUnavailable(boolean isTransientError) {
+                    public void onGetTokenFailure(boolean isTransientError) {
                         if (!isTransientError && mUiControllerAndroid != 0) {
                             nativeOnAccessToken(mUiControllerAndroid, false, "");
                         }
@@ -413,7 +414,7 @@
             return;
         }
 
-        AccountManagerFacade.get().invalidateAuthToken(accessToken);
+        OAuth2TokenService.invalidateAccessToken(accessToken);
     }
 
     @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/InvalidationGcmUpstreamSender.java b/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/InvalidationGcmUpstreamSender.java
index ac216a5..0ec0a21c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/InvalidationGcmUpstreamSender.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/services/gcm/InvalidationGcmUpstreamSender.java
@@ -20,7 +20,6 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.task.AsyncTask;
 import org.chromium.chrome.browser.init.ProcessInitializationHandler;
-import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.ChromeSigninController;
 import org.chromium.components.signin.OAuth2TokenService;
 import org.chromium.components.sync.SyncConstants;
@@ -68,11 +67,10 @@
         }
 
         // Attempt to retrieve a token for the user.
-        OAuth2TokenService.getOAuth2AccessToken(this, account,
-                SyncConstants.CHROME_SYNC_OAUTH2_SCOPE,
-                new AccountManagerFacade.GetAuthTokenCallback() {
+        OAuth2TokenService.getAccessToken(account, SyncConstants.CHROME_SYNC_OAUTH2_SCOPE,
+                new OAuth2TokenService.GetAccessTokenCallback() {
                     @Override
-                    public void tokenAvailable(final String token) {
+                    public void onGetTokenSuccess(final String token) {
                         new AsyncTask<Void>() {
                             @Override
                             protected Void doInBackground() {
@@ -84,7 +82,7 @@
                     }
 
                     @Override
-                    public void tokenUnavailable(boolean isTransientError) {
+                    public void onGetTokenFailure(boolean isTransientError) {
                         GcmUma.recordGcmUpstreamHistogram(ContextUtils.getApplicationContext(),
                                 GcmUma.UMA_UPSTREAM_TOKEN_REQUEST_FAILED);
                     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java
index adf4f2ff..f229514 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java
@@ -38,8 +38,10 @@
 
     @Test
     @MediumTest
-    @CommandLineFlags.Add({"memlog=browser", "memlog-stack-mode=native-include-thread-names"})
-    public void testModeBrowser() throws Exception {
+    @CommandLineFlags.Add({"memlog=browser", "memlog-stack-mode=native-include-thread-names",
+            "memlog-sampling-rate=1"})
+    public void
+    testModeBrowser() throws Exception {
         HeapProfilingTestShim shim = new HeapProfilingTestShim();
         Assert.assertTrue(
                 shim.runTestForMode("browser", false, "native-include-thread-names", false, false));
@@ -67,7 +69,8 @@
     @DisabledTest
     @Test
     @MediumTest
-    @CommandLineFlags.Add({"memlog=all-renderers", "memlog-stack-mode=pseudo"})
+    @CommandLineFlags.
+    Add({"memlog=all-renderers", "memlog-stack-mode=pseudo", "memlog-sampling-rate=1"})
     public void testModeRendererPseudo() throws Exception {
         HeapProfilingTestShim shim = new HeapProfilingTestShim();
         Assert.assertTrue(shim.runTestForMode("all-renderers", false, "pseudo", false, false));
@@ -75,7 +78,7 @@
 
     @Test
     @MediumTest
-    @CommandLineFlags.Add({"memlog=gpu", "memlog-stack-mode=pseudo"})
+    @CommandLineFlags.Add({"memlog=gpu", "memlog-stack-mode=pseudo", "memlog-sampling-rate=1"})
     public void testModeGpuPseudo() throws Exception {
         HeapProfilingTestShim shim = new HeapProfilingTestShim();
         Assert.assertTrue(shim.runTestForMode("gpu", false, "native", false, false));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java
index 453f130be..aaf02267 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java
@@ -128,8 +128,8 @@
                                               .build();
         mAccountManager.addAccountHolderBlocking(accountHolder);
 
-        String accessToken = OAuth2TokenService.getOAuth2AccessTokenWithTimeout(
-                mContext, account, scope, 5, TimeUnit.SECONDS);
+        String accessToken =
+                OAuth2TokenService.getAccessTokenWithTimeout(account, scope, 5, TimeUnit.SECONDS);
         Assert.assertEquals(expectedToken, accessToken);
     }
 }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 38552a0..6fa1d84 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-73.0.3651.0_rc-r1.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-73.0.3652.0_rc-r1.afdo.bz2
\ No newline at end of file
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index 016b0ba2..39bd9e5c 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -519,70 +519,3 @@
     ":chrome_content_utility_manifest_overlay",
   ]
 }
-
-if (use_aura || enable_ipc_fuzzer) {
-  # NOTE: These rules generate compiled versions of the content service
-  # manifests with Chrome's overlays applied. These are only used at run-time,
-  # and only when running Chrome inside the Mash environment. In production
-  # Chrome, the content manifests and Chrome's overlays are baked into browser
-  # resources and merged at runtime.
-
-  service_manifest("chrome_content_packaged_services_manifest") {
-    source_manifest = "//content/public/app:packaged_services_manifest"
-    overlays = [ ":chrome_content_packaged_services_manifest_overlay" ]
-  }
-
-  service_manifest("chrome_content_browser_manifest") {
-    source_manifest = "//content/public/app:browser_manifest"
-    overlays = [ ":chrome_content_browser_manifest_overlay" ]
-  }
-
-  service_manifest("chrome_test_browser_manifest") {
-    source_manifest = ":chrome_content_browser_manifest"
-    overlays = [ ":chrome_test_browser_overlay" ]
-  }
-
-  service_manifest("chrome_content_gpu_manifest") {
-    source_manifest = "//content/public/app:gpu_manifest"
-    overlays = [ ":chrome_content_gpu_manifest_overlay" ]
-  }
-
-  service_manifest("chrome_content_plugin_manifest") {
-    source_manifest = "//content/public/app:plugin_manifest"
-    overlays = [ ":chrome_content_plugin_manifest_overlay" ]
-  }
-
-  service_manifest("chrome_content_renderer_manifest") {
-    source_manifest = "//content/public/app:renderer_manifest"
-    overlays = [ ":chrome_content_renderer_manifest_overlay" ]
-  }
-
-  service_manifest("chrome_content_utility_manifest") {
-    source_manifest = "//content/public/app:utility_manifest"
-    overlays = [ ":chrome_content_utility_manifest_overlay" ]
-  }
-
-  group("service_manifests") {
-    deps = [
-      ":chrome_content_browser_manifest",
-      ":chrome_content_gpu_manifest",
-      ":chrome_content_plugin_manifest",
-      ":chrome_content_renderer_manifest",
-      ":chrome_content_utility_manifest",
-    ]
-  }
-
-  chrome_embedded_services = [
-    ":chrome_content_browser_manifest",
-    ":chrome_content_gpu_manifest",
-    ":chrome_content_plugin_manifest",
-    ":chrome_content_renderer_manifest",
-    ":chrome_content_utility_manifest",
-    ":chrome_renderer_manifest",
-  ]
-
-  catalog("catalog") {
-    embedded_services = chrome_embedded_services +
-                        [ ":chrome_content_packaged_services_manifest" ]
-  }
-}
diff --git a/chrome/app/android/chrome_jni_onload.cc b/chrome/app/android/chrome_jni_onload.cc
index 3479cff..95e227de 100644
--- a/chrome/app/android/chrome_jni_onload.cc
+++ b/chrome/app/android/chrome_jni_onload.cc
@@ -7,6 +7,7 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_registrar.h"
 #include "base/android/jni_utils.h"
+#include "base/stl_util.h"
 #include "chrome/app/android/chrome_android_initializer.h"
 #include "content/public/app/content_jni_onload.h"
 #include "device/vr/buildflags/buildflags.h"
@@ -35,7 +36,7 @@
   // Register manually when on the browser process.
   if (!base::android::IsSelectiveJniRegistrationEnabled(env)) {
     return RegisterNativeMethods(env, kChromeRegisteredMethods,
-                                 arraysize(kChromeRegisteredMethods));
+                                 base::size(kChromeRegisteredMethods));
   }
 #endif
   return true;
diff --git a/chrome/app/chrome_exe_main_win.cc b/chrome/app/chrome_exe_main_win.cc
index d39cace3fe..99765b78 100644
--- a/chrome/app/chrome_exe_main_win.cc
+++ b/chrome/app/chrome_exe_main_win.cc
@@ -53,7 +53,7 @@
 };
 
 bool IsFastStartSwitch(const std::string& command_line_switch) {
-  for (size_t i = 0; i < arraysize(kFastStartSwitches); ++i) {
+  for (size_t i = 0; i < base::size(kFastStartSwitches); ++i) {
     if (command_line_switch == kFastStartSwitches[i])
       return true;
   }
@@ -62,7 +62,7 @@
 
 bool ContainsNonFastStartFlag(const base::CommandLine& command_line) {
   const base::CommandLine::SwitchMap& switches = command_line.GetSwitches();
-  if (switches.size() > arraysize(kFastStartSwitches))
+  if (switches.size() > base::size(kFastStartSwitches))
     return true;
   for (base::CommandLine::SwitchMap::const_iterator it = switches.begin();
        it != switches.end(); ++it) {
@@ -94,11 +94,11 @@
   const base::char16 kPrefetchArgumentPrefix[] = L"/prefetch:";
 
   for (const auto& arg : command_line.argv()) {
-    if (arg.size() == arraysize(kPrefetchArgumentPrefix) &&
+    if (arg.size() == base::size(kPrefetchArgumentPrefix) &&
         base::StartsWith(arg, kPrefetchArgumentPrefix,
                          base::CompareCase::SENSITIVE)) {
-      return arg[arraysize(kPrefetchArgumentPrefix) - 1] >= L'1' &&
-             arg[arraysize(kPrefetchArgumentPrefix) - 1] <= L'8';
+      return arg[base::size(kPrefetchArgumentPrefix) - 1] >= L'1' &&
+             arg[base::size(kPrefetchArgumentPrefix) - 1] <= L'8';
     }
   }
   return false;
@@ -152,7 +152,7 @@
   // Retrieve the product & version details we need to report the crash
   // correctly.
   wchar_t exe_file[MAX_PATH] = {};
-  CHECK(::GetModuleFileName(nullptr, exe_file, arraysize(exe_file)));
+  CHECK(::GetModuleFileName(nullptr, exe_file, base::size(exe_file)));
 
   base::string16 product_name;
   base::string16 version;
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index 47907d1..9cbba58 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -13,11 +13,11 @@
 #include "base/files/file_path.h"
 #include "base/i18n/rtl.h"
 #include "base/lazy_instance.h"
-#include "base/macros.h"
 #include "base/path_service.h"
 #include "base/process/memory.h"
 #include "base/process/process.h"
 #include "base/process/process_handle.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -178,7 +178,7 @@
 const char* const ChromeMainDelegate::kNonWildcardDomainNonPortSchemes[] = {
     extensions::kExtensionScheme, chrome::kChromeSearchScheme};
 const size_t ChromeMainDelegate::kNonWildcardDomainNonPortSchemesSize =
-    arraysize(kNonWildcardDomainNonPortSchemes);
+    base::size(kNonWildcardDomainNonPortSchemes);
 
 namespace {
 
@@ -380,9 +380,9 @@
   wchar_t user_data_dir_buf[MAX_PATH], invalid_user_data_dir_buf[MAX_PATH];
 
   // In tests this may return false, implying the user data dir should be unset.
-  if (GetUserDataDirectoryThunk(user_data_dir_buf, arraysize(user_data_dir_buf),
-                                invalid_user_data_dir_buf,
-                                arraysize(invalid_user_data_dir_buf))) {
+  if (GetUserDataDirectoryThunk(
+          user_data_dir_buf, base::size(user_data_dir_buf),
+          invalid_user_data_dir_buf, base::size(invalid_user_data_dir_buf))) {
     base::FilePath user_data_dir(user_data_dir_buf);
     if (invalid_user_data_dir_buf[0] != 0) {
       chrome::SetInvalidSpecifiedUserDataDir(
@@ -660,8 +660,8 @@
       command_line.HasSwitch(switches::kDiagnosticsRecovery)) {
     base::CommandLine interim_command_line(command_line.GetProgram());
     const char* const kSwitchNames[] = {switches::kUserDataDir, };
-    interim_command_line.CopySwitchesFrom(
-        command_line, kSwitchNames, arraysize(kSwitchNames));
+    interim_command_line.CopySwitchesFrom(command_line, kSwitchNames,
+                                          base::size(kSwitchNames));
     interim_command_line.AppendSwitch(switches::kDiagnostics);
     interim_command_line.AppendSwitch(switches::kDiagnosticsRecovery);
 
@@ -890,7 +890,7 @@
       kAndroidChrome100PercentPakDescriptor,
       kAndroidUIResourcesPakDescriptor,
     };
-    for (size_t i = 0; i < arraysize(extra_pak_keys); ++i) {
+    for (size_t i = 0; i < base::size(extra_pak_keys); ++i) {
       pak_fd = global_descriptors->Get(extra_pak_keys[i]);
       pak_region = global_descriptors->GetRegion(extra_pak_keys[i]);
       ui::ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion(
@@ -996,7 +996,7 @@
 #endif
   };
 
-  for (size_t i = 0; i < arraysize(kMainFunctions); ++i) {
+  for (size_t i = 0; i < base::size(kMainFunctions); ++i) {
     if (process_type == kMainFunctions[i].name)
       return kMainFunctions[i].function(main_function_params);
   }
diff --git a/chrome/app/chrome_watcher_client_unittest_win.cc b/chrome/app/chrome_watcher_client_unittest_win.cc
index 05a43661..b6d5442 100644
--- a/chrome/app/chrome_watcher_client_unittest_win.cc
+++ b/chrome/app/chrome_watcher_client_unittest_win.cc
@@ -11,8 +11,8 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/process/process_handle.h"
+#include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -101,7 +101,7 @@
     // or one times before exit_event, never more.
     HANDLE handles[] = {exit_event.Get(), initialize_event.Get()};
     DWORD result =
-        ::WaitForMultipleObjects(arraysize(handles), handles, FALSE, INFINITE);
+        ::WaitForMultipleObjects(base::size(handles), handles, FALSE, INFINITE);
     switch (result) {
       case WAIT_OBJECT_0:
         // exit_event
diff --git a/chrome/app/chrome_watcher_client_win.cc b/chrome/app/chrome_watcher_client_win.cc
index ffe2e0f..9fb31ea 100644
--- a/chrome/app/chrome_watcher_client_win.cc
+++ b/chrome/app/chrome_watcher_client_win.cc
@@ -6,7 +6,7 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "components/browser_watcher/watcher_client_win.h"
 
 namespace {
@@ -75,8 +75,8 @@
   DCHECK(on_initialized_event_.IsValid());
 
   HANDLE handles[] = {on_initialized_event_.Get(), process_.Handle()};
-  DWORD result = ::WaitForMultipleObjects(arraysize(handles), handles,
-                                          FALSE, INFINITE);
+  DWORD result =
+      ::WaitForMultipleObjects(base::size(handles), handles, FALSE, INFINITE);
 
   switch (result) {
     case WAIT_OBJECT_0:
diff --git a/chrome/app/chrome_watcher_command_line_win.cc b/chrome/app/chrome_watcher_command_line_win.cc
index c6edb61f..050b4b1 100644
--- a/chrome/app/chrome_watcher_command_line_win.cc
+++ b/chrome/app/chrome_watcher_command_line_win.cc
@@ -12,6 +12,7 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/win/win_util.h"
 #include "chrome/common/chrome_switches.h"
@@ -163,7 +164,7 @@
   base::CommandLine current_command_line =
       *base::CommandLine::ForCurrentProcess();
   command_line.CopySwitchesFrom(current_command_line, kSwitchNames,
-                                arraysize(kSwitchNames));
+                                base::size(kSwitchNames));
 
   return command_line;
 }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index c8a9bdfd..47c0c5b4 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4590,10 +4590,23 @@
       allow_circular_includes_from += [ "android/vr:vr_android" ]
     }
 
+    if (is_win) {
+      # TODO(https://crbug.com/916322): Switch to a "is_desktop_vr" or
+      # "is_external_display_vr" build conditional since these files aren't
+      # inherently Windows-specific. At this time, desktop VR where the browser
+      # window shows alongside the head-mounted display is only supported on
+      # Windows, and that's the only situation where we need the UI host.
+      sources += [
+        "vr/ui_host/vr_ui_host_impl.cc",
+        "vr/ui_host/vr_ui_host_impl.h",
+      ]
+    }
+
     sources += [
       "component_updater/vr_assets_component_installer.cc",
       "component_updater/vr_assets_component_installer.h",
     ]
+
     deps += [ "//chrome/browser/vr:vr_common" ]
   }
 
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index f38bc3a..8d78a2d 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -16,7 +16,6 @@
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/i18n/base_i18n_switches.h"
-#include "base/macros.h"
 #include "base/memory/singleton.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/metrics_hashes.h"
@@ -629,11 +628,11 @@
 const FeatureEntry::FeatureVariation
     kContentSuggestionsCategoryOrderFeatureVariations[] = {
         {"(general)", kContentSuggestionsCategoryOrderFeatureVariationGeneral,
-         arraysize(kContentSuggestionsCategoryOrderFeatureVariationGeneral),
+         base::size(kContentSuggestionsCategoryOrderFeatureVariationGeneral),
          nullptr},
         {"(emerging markets oriented)",
          kContentSuggestionsCategoryOrderFeatureVariationEMOriented,
-         arraysize(kContentSuggestionsCategoryOrderFeatureVariationEMOriented),
+         base::size(kContentSuggestionsCategoryOrderFeatureVariationEMOriented),
          nullptr}};
 
 const FeatureEntry::FeatureParam
@@ -652,11 +651,12 @@
     kContentSuggestionsCategoryRankerFeatureVariations[] = {
         {"(constant)",
          kContentSuggestionsCategoryRankerFeatureVariationConstant,
-         arraysize(kContentSuggestionsCategoryRankerFeatureVariationConstant),
+         base::size(kContentSuggestionsCategoryRankerFeatureVariationConstant),
          nullptr},
         {"(click based)",
          kContentSuggestionsCategoryRankerFeatureVariationClickBased,
-         arraysize(kContentSuggestionsCategoryRankerFeatureVariationClickBased),
+         base::size(
+             kContentSuggestionsCategoryRankerFeatureVariationClickBased),
          nullptr}};
 #endif  // OS_ANDROID
 
@@ -669,7 +669,7 @@
     kContentSuggestionsNotificationsFeatureVariations[] = {
         {"(notify always, server side)", nullptr, 0, "3313312"},
         {"(notify always, client side)", kForceFetchedSuggestionsNotifications,
-         arraysize(kForceFetchedSuggestionsNotifications), nullptr}};
+         base::size(kForceFetchedSuggestionsNotifications), nullptr}};
 #endif  // OS_ANDROID
 
 #if defined(OS_ANDROID)
@@ -843,7 +843,7 @@
 // Ensure that all effective connection types returned by Network Quality
 // Estimator (NQE) are also exposed via flags.
 static_assert(net::EFFECTIVE_CONNECTION_TYPE_LAST + 2 ==
-                  arraysize(kForceEffectiveConnectionTypeChoices),
+                  base::size(kForceEffectiveConnectionTypeChoices),
               "ECT enum value is not handled.");
 static_assert(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN == 0,
               "ECT enum value is not handled.");
@@ -872,18 +872,19 @@
 const FeatureEntry::FeatureVariation
     kAutofillKeyboardAccessoryFeatureVariations[] = {
         {"Animate", kAutofillKeyboardAccessoryFeatureVariationAnimationDuration,
-         arraysize(kAutofillKeyboardAccessoryFeatureVariationAnimationDuration),
+         base::size(
+             kAutofillKeyboardAccessoryFeatureVariationAnimationDuration),
          nullptr},
         {"Limit label width",
          kAutofillKeyboardAccessoryFeatureVariationLimitLabelWidth,
-         arraysize(kAutofillKeyboardAccessoryFeatureVariationLimitLabelWidth),
+         base::size(kAutofillKeyboardAccessoryFeatureVariationLimitLabelWidth),
          nullptr},
         {"Show hint", kAutofillKeyboardAccessoryFeatureVariationShowHint,
-         arraysize(kAutofillKeyboardAccessoryFeatureVariationShowHint),
+         base::size(kAutofillKeyboardAccessoryFeatureVariationShowHint),
          nullptr},
         {"Animate with hint",
          kAutofillKeyboardAccessoryFeatureVariationAnimateWithHint,
-         arraysize(kAutofillKeyboardAccessoryFeatureVariationAnimateWithHint),
+         base::size(kAutofillKeyboardAccessoryFeatureVariationAnimateWithHint),
          nullptr}};
 #endif  // OS_ANDROID
 
@@ -942,19 +943,19 @@
 const FeatureEntry::FeatureVariation
     kOmniboxUIMaxAutocompleteMatchesVariations[] = {
         {"3 matches", kOmniboxUIMaxAutocompleteMatches3,
-         arraysize(kOmniboxUIMaxAutocompleteMatches3), nullptr},
+         base::size(kOmniboxUIMaxAutocompleteMatches3), nullptr},
         {"4 matches", kOmniboxUIMaxAutocompleteMatches4,
-         arraysize(kOmniboxUIMaxAutocompleteMatches4), nullptr},
+         base::size(kOmniboxUIMaxAutocompleteMatches4), nullptr},
         {"5 matches", kOmniboxUIMaxAutocompleteMatches5,
-         arraysize(kOmniboxUIMaxAutocompleteMatches5), nullptr},
+         base::size(kOmniboxUIMaxAutocompleteMatches5), nullptr},
         {"6 matches", kOmniboxUIMaxAutocompleteMatches6,
-         arraysize(kOmniboxUIMaxAutocompleteMatches6), nullptr},
+         base::size(kOmniboxUIMaxAutocompleteMatches6), nullptr},
         {"8 matches", kOmniboxUIMaxAutocompleteMatches8,
-         arraysize(kOmniboxUIMaxAutocompleteMatches8), nullptr},
+         base::size(kOmniboxUIMaxAutocompleteMatches8), nullptr},
         {"10 matches", kOmniboxUIMaxAutocompleteMatches10,
-         arraysize(kOmniboxUIMaxAutocompleteMatches10), nullptr},
+         base::size(kOmniboxUIMaxAutocompleteMatches10), nullptr},
         {"12 matches", kOmniboxUIMaxAutocompleteMatches12,
-         arraysize(kOmniboxUIMaxAutocompleteMatches12), nullptr}};
+         base::size(kOmniboxUIMaxAutocompleteMatches12), nullptr}};
 
 const FeatureEntry::Choice kAsyncImageDecodingChoices[] = {
     {flags_ui::kGenericExperimentChoiceDefault, "", ""},
@@ -1018,13 +1019,13 @@
 const FeatureEntry::FeatureVariation kWebXrRenderPathVariations[] = {
     {flag_descriptions::kWebXrRenderPathChoiceClientWaitDescription,
      kWebXrRenderPathChoiceClientWait,
-     arraysize(kWebXrRenderPathChoiceClientWait), nullptr},
+     base::size(kWebXrRenderPathChoiceClientWait), nullptr},
     {flag_descriptions::kWebXrRenderPathChoiceGpuFenceDescription,
-     kWebXrRenderPathChoiceGpuFence, arraysize(kWebXrRenderPathChoiceGpuFence),
+     kWebXrRenderPathChoiceGpuFence, base::size(kWebXrRenderPathChoiceGpuFence),
      nullptr},
     {flag_descriptions::kWebXrRenderPathChoiceSharedBufferDescription,
      kWebXrRenderPathChoiceSharedBuffer,
-     arraysize(kWebXrRenderPathChoiceSharedBuffer), nullptr}};
+     base::size(kWebXrRenderPathChoiceSharedBuffer), nullptr}};
 #endif  // defined(OS_ANDROID) && BUILDFLAG(ENABLE_VR)
 
 const FeatureEntry::FeatureParam kSimplifyHttpsIndicatorEvToSecure[] = {
@@ -1067,11 +1068,11 @@
     kTranslateForceTriggerOnEnglishVariations[] = {
         {"(Heuristic model without Ranker)",
          kTranslateForceTriggerOnEnglishHeuristic,
-         arraysize(kTranslateForceTriggerOnEnglishHeuristic), nullptr},
+         base::size(kTranslateForceTriggerOnEnglishHeuristic), nullptr},
         {"(Geo model without Ranker)", kTranslateForceTriggerOnEnglishGeo,
-         arraysize(kTranslateForceTriggerOnEnglishGeo), nullptr},
+         base::size(kTranslateForceTriggerOnEnglishGeo), nullptr},
         {"(Zero threshold)", kTranslateForceTriggerOnEnglishBackoff,
-         arraysize(kTranslateForceTriggerOnEnglishBackoff), nullptr}};
+         base::size(kTranslateForceTriggerOnEnglishBackoff), nullptr}};
 #endif  // defined(OS_ANDROID)
 
 #if !defined(OS_ANDROID)
@@ -1572,6 +1573,10 @@
      flag_descriptions::kAndroidMessagesIntegrationName,
      flag_descriptions::kAndroidMessagesIntegrationDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kAndroidMessagesIntegration)},
+    {"use_messages_google_com_domain",
+     flag_descriptions::kUseMessagesGoogleComDomainName,
+     flag_descriptions::kUseMessagesGoogleComDomainDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kUseMessagesGoogleComDomain)},
     {"enable_android_messages_prod_endpoint",
      flag_descriptions::kAndroidMessagesProdEndpointName,
      flag_descriptions::kAndroidMessagesProdEndpointDescription, kOsCrOS,
@@ -4322,7 +4327,7 @@
 class FlagsStateSingleton {
  public:
   FlagsStateSingleton()
-      : flags_state_(kFeatureEntries, arraysize(kFeatureEntries)) {}
+      : flags_state_(kFeatureEntries, base::size(kFeatureEntries)) {}
   ~FlagsStateSingleton() {}
 
   static FlagsStateSingleton* GetInstance() {
@@ -4519,7 +4524,7 @@
 const base::HistogramBase::Sample kBadSwitchFormatHistogramId = 0;
 
 const FeatureEntry* GetFeatureEntries(size_t* count) {
-  *count = arraysize(kFeatureEntries);
+  *count = base::size(kFeatureEntries);
   return kFeatureEntries;
 }
 
diff --git a/chrome/browser/android/chrome_backup_agent.cc b/chrome/browser/android/chrome_backup_agent.cc
index ba6b09e9..18f9760 100644
--- a/chrome/browser/android/chrome_backup_agent.cc
+++ b/chrome/browser/android/chrome_backup_agent.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "base/android/jni_array.h"
+#include "base/stl_util.h"
 #include "chrome/browser/android/chrome_backup_agent.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/pref_names.h"
@@ -56,7 +57,7 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& jcaller) {
   PrefService* prefs = ProfileManager::GetLastUsedProfile()->GetPrefs();
-  constexpr int pref_count = arraysize(backed_up_preferences_);
+  constexpr int pref_count = base::size(backed_up_preferences_);
   jboolean values[pref_count];
 
   for (int i = 0; i < pref_count; i++) {
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 3b7fd839..4b74826 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -10,8 +10,8 @@
 
 #include "base/android/jni_string.h"
 #include "base/feature_list.h"
-#include "base/macros.h"
 #include "base/metrics/field_trial_params.h"
+#include "base/stl_util.h"
 #include "chrome/common/chrome_features.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
@@ -185,7 +185,7 @@
 };
 
 const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
-  for (size_t i = 0; i < arraysize(kFeaturesExposedToJava); ++i) {
+  for (size_t i = 0; i < base::size(kFeaturesExposedToJava); ++i) {
     if (kFeaturesExposedToJava[i]->name == feature_name)
       return kFeaturesExposedToJava[i];
   }
diff --git a/chrome/browser/android/preferences/prefs_unittest.cc b/chrome/browser/android/preferences/prefs_unittest.cc
index 8d723d2..8a9064e 100644
--- a/chrome/browser/android/preferences/prefs_unittest.cc
+++ b/chrome/browser/android/preferences/prefs_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/android/preferences/prefs.h"
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "chrome/browser/android/preferences/pref_service_bridge.h"
 #include "chrome/common/pref_names.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -26,7 +26,7 @@
 
   // If one of these checks fails, most likely the Pref enum and
   // |kPrefExposedToJava| are out of sync.
-  EXPECT_EQ(Pref::PREF_NUM_PREFS, arraysize(kPrefsExposedToJava));
+  EXPECT_EQ(Pref::PREF_NUM_PREFS, base::size(kPrefsExposedToJava));
 
   EXPECT_EQ(prefs::kAllowDeletingBrowserHistory,
             GetPrefName(ALLOW_DELETING_BROWSER_HISTORY));
diff --git a/chrome/browser/android/signin/signin_manager_android_unittest.cc b/chrome/browser/android/signin/signin_manager_android_unittest.cc
index 007fc9b..9ccf491 100644
--- a/chrome/browser/android/signin/signin_manager_android_unittest.cc
+++ b/chrome/browser/android/signin/signin_manager_android_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/browsing_data/browsing_data_cache_storage_helper.h"
@@ -136,7 +137,7 @@
   for (const TestCase& test_case : kTestCases)
     helper->AddCacheStorage(GURL(test_case.worker_url));
 
-  ASSERT_EQ(arraysize(kTestCases), helper->GetCacheStorageCount());
+  ASSERT_EQ(base::size(kTestCases), helper->GetCacheStorageCount());
 
   // Delete service workers and wait for completion.
   base::RunLoop run_loop;
diff --git a/chrome/browser/app_mode/app_mode_utils.cc b/chrome/browser/app_mode/app_mode_utils.cc
index 738cb0c..083dca58 100644
--- a/chrome/browser/app_mode/app_mode_utils.cc
+++ b/chrome/browser/app_mode/app_mode_utils.cc
@@ -8,8 +8,8 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/optional.h"
+#include "base/stl_util.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/common/chrome_switches.h"
 
@@ -49,7 +49,7 @@
       IDC_ZOOM_MINUS,
   };
 
-  for (size_t i = 0; i < arraysize(kAllowed); ++i) {
+  for (size_t i = 0; i < base::size(kAllowed); ++i) {
     if (kAllowed[i] == command_id)
       return true;
   }
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac.cc b/chrome/browser/apps/app_shim/app_shim_host_mac.cc
index 8034b794..a1d2ffa 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_mac.cc
+++ b/chrome/browser/apps/app_shim/app_shim_host_mac.cc
@@ -25,15 +25,17 @@
 }  // namespace
 
 AppShimHost::AppShimHost(const std::string& app_id,
-                         const base::FilePath& profile_path)
+                         const base::FilePath& profile_path,
+                         bool uses_remote_views)
     : host_binding_(this),
       app_shim_request_(mojo::MakeRequest(&app_shim_)),
       app_id_(app_id),
       profile_path_(profile_path),
+      uses_remote_views_(uses_remote_views),
       weak_factory_(this) {
   // Create the interfaces used to host windows, so that browser windows may be
   // created before the host process finishes launching.
-  if (features::HostWindowsInAppShimProcess()) {
+  if (uses_remote_views_) {
     uint64_t host_id = g_next_host_id++;
 
     // Create the interface that will be used by views::NativeWidgetMac to
@@ -179,14 +181,20 @@
 }
 
 void AppShimHost::OnAppHide() {
+  if (uses_remote_views_)
+    return;
   app_shim_->Hide();
 }
 
 void AppShimHost::OnAppUnhideWithoutActivation() {
+  if (uses_remote_views_)
+    return;
   app_shim_->UnhideWithoutActivation();
 }
 
 void AppShimHost::OnAppRequestUserAttention(apps::AppShimAttentionType type) {
+  if (uses_remote_views_)
+    return;
   app_shim_->SetUserAttention(type);
 }
 
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac.h b/chrome/browser/apps/app_shim/app_shim_host_mac.h
index c6df6c7..cf93e79 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_mac.h
+++ b/chrome/browser/apps/app_shim/app_shim_host_mac.h
@@ -33,7 +33,11 @@
 // connected to the app shim is closed.
 class AppShimHost : public chrome::mojom::AppShimHost {
  public:
-  AppShimHost(const std::string& app_id, const base::FilePath& profile_path);
+  AppShimHost(const std::string& app_id,
+              const base::FilePath& profile_path,
+              bool uses_remote_views);
+
+  bool UsesRemoteViews() const { return uses_remote_views_; }
 
   // Returns true if an AppShimHostBootstrap has already connected to this
   // host.
@@ -106,6 +110,7 @@
 
   std::string app_id_;
   base::FilePath profile_path_;
+  const bool uses_remote_views_;
 
   // This class is only ever to be used on the UI thread.
   THREAD_CHECKER(thread_checker_);
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc b/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc
index 5f832d1..6093b44e 100644
--- a/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc
+++ b/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc
@@ -69,7 +69,8 @@
  public:
   TestingAppShimHost(const std::string& app_id,
                      const base::FilePath& profile_path)
-      : AppShimHost(app_id, profile_path), test_weak_factory_(this) {}
+      : AppShimHost(app_id, profile_path, false /* uses_remote_views */),
+        test_weak_factory_(this) {}
 
   base::WeakPtr<TestingAppShimHost> GetWeakPtr() {
     return test_weak_factory_.GetWeakPtr();
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc
index c3fceed..a75fd9c 100644
--- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc
+++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc
@@ -95,11 +95,6 @@
   if (browsers.empty())
     return false;
 
-  // If the NSWindows for the app are in the app shim process, then don't steal
-  // focus from the app shim.
-  if (features::HostWindowsInAppShimProcess())
-    return true;
-
   std::set<gfx::NativeWindow> native_windows;
   for (const Browser* browser : browsers)
     native_windows.insert(browser->window()->GetNativeWindow());
@@ -215,7 +210,8 @@
 AppShimHost* ExtensionAppShimHandler::Delegate::CreateHost(
     Profile* profile,
     const extensions::Extension* extension) {
-  return new AppShimHost(extension->id(), profile->GetPath());
+  return new AppShimHost(extension->id(), profile->GetPath(),
+                         extension->is_hosted_app());
 }
 
 void ExtensionAppShimHandler::Delegate::EnableExtension(
@@ -629,6 +625,9 @@
     AppShimHost* host,
     AppShimFocusType focus_type,
     const std::vector<base::FilePath>& files) {
+  if (host->UsesRemoteViews())
+    return;
+
   Profile* profile;
   const Extension* extension = MaybeGetExtensionOrCloseHost(host, &profile);
   if (!extension)
@@ -657,6 +656,9 @@
 }
 
 void ExtensionAppShimHandler::OnShimSetHidden(AppShimHost* host, bool hidden) {
+  if (host->UsesRemoteViews())
+    return;
+
   Profile* profile;
   const Extension* extension = MaybeGetExtensionOrCloseHost(host, &profile);
   if (!extension)
@@ -669,6 +671,9 @@
 }
 
 void ExtensionAppShimHandler::OnShimQuit(AppShimHost* host) {
+  if (host->UsesRemoteViews())
+    return;
+
   DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath()));
   Profile* profile = delegate_->ProfileForPath(host->GetProfilePath());
 
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
index e44e1087..2306b06 100644
--- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
+++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
@@ -212,7 +212,7 @@
   TestHost(const base::FilePath& profile_path,
            const std::string& app_id,
            TestingExtensionAppShimHandler* handler)
-      : AppShimHost(app_id, profile_path),
+      : AppShimHost(app_id, profile_path, false /* uses_remote_views */),
         handler_(handler),
         weak_factory_(this) {}
 
diff --git a/chrome/browser/apps/platform_apps/api/music_manager_private/device_id.cc b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id.cc
index 5352a0c..246768c 100644
--- a/chrome/browser/apps/platform_apps/api/music_manager_private/device_id.cc
+++ b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "content/public/browser/browser_thread.h"
@@ -164,7 +165,7 @@
     return false;
   }
 
-  for (size_t i = 0; i < arraysize(invalidAddresses); ++i) {
+  for (size_t i = 0; i < base::size(invalidAddresses); ++i) {
     size_t count = invalidAddresses[i].size;
     if (memcmp(invalidAddresses[i].address, bytes, count) == 0) {
       return false;
diff --git a/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_linux.cc b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_linux.cc
index aa33412..00020cf 100644
--- a/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_linux.cc
+++ b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_linux.cc
@@ -17,7 +17,7 @@
 #include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
@@ -70,7 +70,7 @@
 
   // Look for first device name matching an entry of |kDeviceNames|.
   std::string result;
-  for (size_t i = 0; i < arraysize(kDeviceNames); i++) {
+  for (size_t i = 0; i < base::size(kDeviceNames); i++) {
     DiskEntries::iterator it = disk_uuids.find(base::FilePath(kDeviceNames[i]));
     if (it != disk_uuids.end()) {
       DVLOG(1) << "Returning uuid: \"" << it->second.value()
@@ -162,7 +162,7 @@
   MacAddressProcessor processor(is_valid_mac_address);
   for (struct ifaddrs* ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
     bool keep_going = processor.ProcessInterface(
-        ifa, kNetDeviceNamePrefixes, arraysize(kNetDeviceNamePrefixes));
+        ifa, kNetDeviceNamePrefixes, base::size(kNetDeviceNamePrefixes));
     if (!keep_going)
       break;
   }
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
index fb40dc8..1170ff2 100644
--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
+++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -7,7 +7,7 @@
 #include <stddef.h>
 
 #include "base/bind.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
@@ -222,7 +222,7 @@
 #if !defined(OS_ANDROID)
   base::string16 settings(base::ASCIIToUTF16(chrome::kChromeUISettingsHost) +
                           base::ASCIIToUTF16("/"));
-  for (size_t i = 0; i < arraysize(kChromeSettingsSubPages); i++) {
+  for (size_t i = 0; i < base::size(kChromeSettingsSubPages); i++) {
     builtins.push_back(settings +
                        base::ASCIIToUTF16(kChromeSettingsSubPages[i]));
   }
diff --git a/chrome/browser/autocomplete/search_provider_unittest.cc b/chrome/browser/autocomplete/search_provider_unittest.cc
index 8fdf25e..123b182 100644
--- a/chrome/browser/autocomplete/search_provider_unittest.cc
+++ b/chrome/browser/autocomplete/search_provider_unittest.cc
@@ -10,9 +10,9 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
-#include "base/macros.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
@@ -737,7 +737,7 @@
     { "foo https://hostname/path",          true },
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     SCOPED_TRACE("for input=" + cases[i].input);
     QueryForInput(ASCIIToUTF16(cases[i].input), false, false);
     // Make sure the default provider's suggest service was or was not queried
@@ -1158,10 +1158,10 @@
   };
 
   // Test not in keyword mode.
-  RunTest(cases, arraysize(cases), false);
+  RunTest(cases, base::size(cases), false);
 
   // Test in keyword mode.  (Both modes should give the same result.)
-  RunTest(cases, arraysize(cases), true);
+  RunTest(cases, base::size(cases), true);
 }
 
 // Ensures command-line flags are reflected in the URLs the search provider
@@ -1194,7 +1194,7 @@
                    ASCIIToUTF16("k a")) } },
   };
 
-  RunTest(cases, arraysize(cases), false);
+  RunTest(cases, base::size(cases), false);
 }
 
 // Verifies Navsuggest results don't set a TemplateURL, which Instant relies on.
@@ -1266,7 +1266,7 @@
       { "akeyword-query", "a", "k a", "adefault.com", "k adefault-query" } }
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     // Send the query twice in order to have a synchronous pass after the first
     // response is received.  This is necessary because SearchProvider doesn't
     // allow an asynchronous response to change the default match.
@@ -1281,13 +1281,13 @@
         cases[i].default_provider_json + " and keyword_provider_json=" +
         cases[i].keyword_provider_json);
     const ACMatches& matches = provider_->matches();
-    ASSERT_LE(matches.size(), arraysize(cases[i].matches));
+    ASSERT_LE(matches.size(), base::size(cases[i].matches));
     size_t j = 0;
     // Ensure that the returned matches equal the expectations.
     for (; j < matches.size(); ++j)
       EXPECT_EQ(ASCIIToUTF16(cases[i].matches[j]), matches[j].contents);
     // Ensure that no expected matches are missing.
-    for (; j < arraysize(cases[i].matches); ++j)
+    for (; j < base::size(cases[i].matches); ++j)
       EXPECT_EQ(std::string(), cases[i].matches[j]);
   }
 }
@@ -1511,7 +1511,7 @@
       std::string() },
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     // Send the query twice in order to have a synchronous pass after the first
     // response is received.  This is necessary because SearchProvider doesn't
     // allow an asynchronous response to change the default match.
@@ -1521,7 +1521,7 @@
     }
 
     const std::string description = "for input with json=" + cases[i].json;
-    CheckMatches(description, arraysize(cases[i].matches), cases[i].matches,
+    CheckMatches(description, base::size(cases[i].matches), cases[i].matches,
                  provider_->matches());
   }
 }
@@ -1945,7 +1945,7 @@
     // clang-format on
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     // Send the query twice in order to have a synchronous pass after the first
     // response is received.  This is necessary because SearchProvider doesn't
     // allow an asynchronous response to change the default match.
@@ -1977,7 +1977,7 @@
     EXPECT_EQ(ASCIIToUTF16(cases[i].inline_autocompletion),
               it->inline_autocompletion);
 
-    ASSERT_LE(matches.size(), arraysize(cases[i].matches));
+    ASSERT_LE(matches.size(), base::size(cases[i].matches));
     size_t j = 0;
     // Ensure that the returned matches equal the expectations.
     for (; j < matches.size(); ++j) {
@@ -1989,7 +1989,7 @@
                 matches[j].allowed_to_be_default_match);
     }
     // Ensure that no expected matches are missing.
-    for (; j < arraysize(cases[i].matches); ++j) {
+    for (; j < base::size(cases[i].matches); ++j) {
       SCOPED_TRACE(" Case # " + base::NumberToString(i));
       EXPECT_EQ(kNotApplicable, cases[i].matches[j].contents);
     }
@@ -2192,7 +2192,7 @@
         kEmptyExpectedMatch } },
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     // First, send the query "a" and receive the JSON response |first_json|.
     ClearAllResults();
     QueryForInputAndWaitForFetcherResponses(
@@ -2201,14 +2201,14 @@
     // Verify that the matches after the asynchronous results are as expected.
     std::string description = "first asynchronous response for input with "
         "first_json=" + cases[i].first_json;
-    CheckMatches(description, arraysize(cases[i].first_async_matches),
+    CheckMatches(description, base::size(cases[i].first_async_matches),
                  cases[i].first_async_matches, provider_->matches());
 
     // Then, send the query "ab" and check the synchronous matches.
     description = "synchronous response after the first keystroke after input "
         "with first_json=" + cases[i].first_json;
     QueryForInput(ASCIIToUTF16("ab"), false, false);
-    CheckMatches(description, arraysize(cases[i].sync_matches),
+    CheckMatches(description, base::size(cases[i].sync_matches),
                  cases[i].sync_matches, provider_->matches());
 
     // Finally, get the provided JSON response, |second_json|, and verify the
@@ -2219,7 +2219,7 @@
     test_url_loader_factory_.AddResponse("http://defaultturl2/ab",
                                          cases[i].second_json);
     RunTillProviderDone();
-    CheckMatches(description, arraysize(cases[i].second_async_matches),
+    CheckMatches(description, base::size(cases[i].second_async_matches),
                  cases[i].second_async_matches, provider_->matches());
   }
 }
@@ -2251,7 +2251,7 @@
         kEmptyExpectedMatch } },
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     // First, send the query "1+2" and receive the JSON response |first_json|.
     ClearAllResults();
     QueryForInputAndWaitForFetcherResponses(
@@ -2260,14 +2260,14 @@
     // Verify that the matches after the asynchronous results are as expected.
     std::string description = "first asynchronous response for input with "
         "json=" + cases[i].json;
-    CheckMatches(description, arraysize(cases[i].async_matches),
+    CheckMatches(description, base::size(cases[i].async_matches),
                  cases[i].async_matches, provider_->matches());
 
     // Then, send the query "1+23" and check the synchronous matches.
     description = "synchronous response after the first keystroke after input "
         "with json=" + cases[i].json;
     QueryForInput(ASCIIToUTF16("1+23"), false, false);
-    CheckMatches(description, arraysize(cases[i].sync_matches),
+    CheckMatches(description, base::size(cases[i].sync_matches),
                  cases[i].sync_matches, provider_->matches());
   }
 }
@@ -2332,7 +2332,7 @@
       { "term", "a1", "a2", "term2", "a3", "a4" } }
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     QueryForInputAndWaitForFetcherResponses(
         cases[i].input, false, cases[i].json, std::string());
 
@@ -2340,7 +2340,7 @@
     const ACMatches& matches = provider_->matches();
 
     // Ensure no extra matches are present.
-    ASSERT_LE(matches.size(), arraysize(cases[i].matches));
+    ASSERT_LE(matches.size(), base::size(cases[i].matches));
 
     size_t j = 0;
     // Ensure that the returned matches equal the expectations.
@@ -2348,7 +2348,7 @@
       EXPECT_EQ(ASCIIToUTF16(cases[i].matches[j]),
                 matches[j].contents) << description;
     // Ensure that no expected matches are missing.
-    for (; j < arraysize(cases[i].matches); ++j)
+    for (; j < base::size(cases[i].matches); ++j)
       EXPECT_EQ(kNotApplicable, cases[i].matches[j]) <<
           "Case # " << i << " " << description;
   }
@@ -2452,7 +2452,7 @@
     // clang-format on
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     // Send the query twice in order to have a synchronous pass after the first
     // response is received.  This is necessary because SearchProvider doesn't
     // allow an asynchronous response to change the default match.
@@ -2464,7 +2464,7 @@
     SCOPED_TRACE("input=" + cases[i].input + " json=" + cases[i].json);
     size_t j = 0;
     const ACMatches& matches = provider_->matches();
-    ASSERT_LE(matches.size(), arraysize(cases[i].output));
+    ASSERT_LE(matches.size(), base::size(cases[i].output));
     // Ensure that the returned matches equal the expectations.
     for (; j < matches.size(); ++j) {
       EXPECT_EQ(ASCIIToUTF16(cases[i].output[j].match_contents),
@@ -2474,7 +2474,7 @@
                 matches[j].allowed_to_be_default_match);
     }
     // Ensure that no expected matches are missing.
-    for (; j < arraysize(cases[i].output); ++j) {
+    for (; j < base::size(cases[i].output); ++j) {
       EXPECT_EQ(kNotApplicable, cases[i].output[j].match_contents);
       EXPECT_EQ(AutocompleteMatchType::NUM_TYPES,
                 cases[i].output[j].match_type);
@@ -2568,7 +2568,7 @@
        "\"google:subtypeid\":[2, 4]}]",
        {{"ef", 2}, {"e.com", 4}}}};
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     QueryForInputAndWaitForFetcherResponses(
         ASCIIToUTF16(cases[i].input_text), false,
         cases[i].provider_response_json, std::string());
@@ -2576,7 +2576,7 @@
     // Check for the match and field trial triggered bits.
     const ACMatches& matches = provider_->matches();
     ASSERT_FALSE(matches.empty());
-    for (size_t j = 0; j < arraysize(cases[i].expected_matches); ++j) {
+    for (size_t j = 0; j < base::size(cases[i].expected_matches); ++j) {
       if (cases[i].expected_matches[j].contents == kNotApplicable)
         continue;
       AutocompleteMatch match;
@@ -2728,7 +2728,7 @@
                                "c.com/path/file.htm?q=x#foo",     true, false },
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     // First test regular mode.
     QueryForInput(ASCIIToUTF16(cases[i].input), false, false);
     SearchSuggestionParser::NavigationResult result(
@@ -2918,7 +2918,7 @@
       },
     },
   };
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     QueryForInputAndWaitForFetcherResponses(
         ASCIIToUTF16(cases[i].input_text), false, cases[i].response_json,
         std::string());
@@ -2928,7 +2928,7 @@
 
     SCOPED_TRACE("for input with json = " + cases[i].response_json);
 
-    ASSERT_LE(matches.size(), arraysize(cases[i].matches));
+    ASSERT_LE(matches.size(), base::size(cases[i].matches));
     size_t j = 0;
     // Ensure that the returned matches equal the expectations.
     for (; j < matches.size(); ++j) {
@@ -2945,7 +2945,7 @@
       EXPECT_EQ(match.type, matches[j].type);
     }
     // Ensure that no expected matches are missing.
-    for (; j < arraysize(cases[i].matches); ++j) {
+    for (; j < base::size(cases[i].matches); ++j) {
       SCOPED_TRACE(" and match index: " + base::NumberToString(j));
       EXPECT_EQ(cases[i].matches[j].contents, kNotApplicable);
       EXPECT_EQ(cases[i].matches[j].description, kNotApplicable);
@@ -3043,7 +3043,7 @@
            {"b", false, AutocompleteMatchType::SEARCH_SUGGEST, true}},
       }};
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     QueryForInputAndWaitForFetcherResponses(
         ASCIIToUTF16(cases[i].input_text),
         cases[i].prefer_keyword_provider_results,
@@ -3058,7 +3058,7 @@
     ASSERT_FALSE(matches.empty());
     EXPECT_GE(matches[0].relevance, 1300);
 
-    ASSERT_LE(matches.size(), arraysize(cases[i].matches));
+    ASSERT_LE(matches.size(), base::size(cases[i].matches));
     // Ensure that the returned matches equal the expectations.
     for (size_t j = 0; j < matches.size(); ++j) {
       SCOPED_TRACE(description);
@@ -3141,7 +3141,7 @@
     },
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     ClearAllResults();
     QueryForInputAndWaitForFetcherResponses(
         ASCIIToUTF16(cases[i].input_text), false,
@@ -3153,7 +3153,7 @@
     EXPECT_GE(matches[0].relevance, 1300);
 
     SCOPED_TRACE("for case: " + base::NumberToString(i));
-    ASSERT_LE(matches.size(), arraysize(cases[i].matches));
+    ASSERT_LE(matches.size(), base::size(cases[i].matches));
     size_t j = 0;
     // Ensure that the returned matches equal the expectations.
     for (; j < matches.size(); ++j) {
@@ -3162,7 +3162,7 @@
                 base::UTF16ToUTF8(matches[j].contents));
       EXPECT_EQ(cases[i].matches[j].type, matches[j].type);
     }
-    for (; j < arraysize(cases[i].matches); ++j) {
+    for (; j < base::size(cases[i].matches); ++j) {
       SCOPED_TRACE("and match: " + base::NumberToString(j));
       EXPECT_EQ(cases[i].matches[j].contents, kNotApplicable);
       EXPECT_EQ(cases[i].matches[j].type, AutocompleteMatchType::NUM_TYPES);
@@ -3249,7 +3249,7 @@
       // clang-format on
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     QueryForInputAndWaitForFetcherResponses(ASCIIToUTF16(cases[i].input_text),
                                             false, cases[i].response_json,
                                             std::string());
diff --git a/chrome/browser/autocomplete/shortcuts_provider_extension_unittest.cc b/chrome/browser/autocomplete/shortcuts_provider_extension_unittest.cc
index 4cb7b1b..0629215 100644
--- a/chrome/browser/autocomplete/shortcuts_provider_extension_unittest.cc
+++ b/chrome/browser/autocomplete/shortcuts_provider_extension_unittest.cc
@@ -9,9 +9,9 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h"
 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
@@ -77,7 +77,7 @@
   provider_ = new ShortcutsProvider(&client_);
   PopulateShortcutsBackendWithTestData(client_.GetShortcutsBackend(),
                                        shortcut_test_db,
-                                       arraysize(shortcut_test_db));
+                                       base::size(shortcut_test_db));
 }
 
 void ShortcutsProviderExtensionTest::TearDown() {
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.cc b/chrome/browser/autofill/android/personal_data_manager_android.cc
index 99ae989..e7062e5 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.cc
+++ b/chrome/browser/autofill/android/personal_data_manager_android.cc
@@ -13,6 +13,7 @@
 #include "base/android/jni_string.h"
 #include "base/command_line.h"
 #include "base/format_macros.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "chrome/browser/android/preferences/prefs.h"
@@ -473,7 +474,7 @@
 
   return ConvertUTF16ToJavaString(
       env, profile.ConstructInferredLabel(
-               kLabelFields, arraysize(kLabelFields), arraysize(kLabelFields),
+               kLabelFields, base::size(kLabelFields), base::size(kLabelFields),
                g_browser_process->GetApplicationLocale()));
 }
 
@@ -855,7 +856,7 @@
       ADDRESS_HOME_ZIP,     ADDRESS_HOME_SORTING_CODE,
       ADDRESS_HOME_COUNTRY,
   };
-  size_t kLabelFields_size = arraysize(kLabelFields);
+  size_t kLabelFields_size = base::size(kLabelFields);
   if (!include_country_in_label)
     --kLabelFields_size;
 
diff --git a/chrome/browser/browser_encoding_browsertest.cc b/chrome/browser/browser_encoding_browsertest.cc
index 5a9d951..9bfb242c 100644
--- a/chrome/browser/browser_encoding_browsertest.cc
+++ b/chrome/browser/browser_encoding_browsertest.cc
@@ -6,8 +6,8 @@
 
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
@@ -240,7 +240,7 @@
 
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
-  for (size_t i = 0; i < arraysize(kTestDatas); ++i) {
+  for (size_t i = 0; i < base::size(kTestDatas); ++i) {
     base::FilePath test_file_path(test_dir_path);
     test_file_path = test_file_path.AppendASCII(kTestDatas[i].test_file_name);
     GURL url =
diff --git a/chrome/browser/browser_keyevents_browsertest.cc b/chrome/browser/browser_keyevents_browsertest.cc
index 6bf93ad..f67c2d4 100644
--- a/chrome/browser/browser_keyevents_browsertest.cc
+++ b/chrome/browser/browser_keyevents_browsertest.cc
@@ -7,8 +7,8 @@
 #include <stddef.h>
 
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -371,7 +371,7 @@
   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
 
   int tab_index = browser()->tab_strip_model()->active_index();
-  for (size_t i = 0; i < arraysize(kTestNoInput); ++i) {
+  for (size_t i = 0; i < base::size(kTestNoInput); ++i) {
     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestNoInput[i]))
         << "kTestNoInput[" << i << "] failed:\n"
         << GetTestDataDescription(kTestNoInput[i]);
@@ -379,7 +379,7 @@
 
   // Input in normal text box.
   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A"));
-  for (size_t i = 0; i < arraysize(kTestWithInput); ++i) {
+  for (size_t i = 0; i < base::size(kTestWithInput); ++i) {
     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
         << "kTestWithInput[" << i << "] in text box failed:\n"
         << GetTestDataDescription(kTestWithInput[i]);
@@ -388,7 +388,7 @@
 
   // Input in password box.
   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"B"));
-  for (size_t i = 0; i < arraysize(kTestWithInput); ++i) {
+  for (size_t i = 0; i < base::size(kTestWithInput); ++i) {
     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
         << "kTestWithInput[" << i << "] in password box failed:\n"
         << GetTestDataDescription(kTestWithInput[i]);
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 8d78e7c..206c10ae 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -401,7 +401,7 @@
       <include name="IDR_OMNIBOX_COLUMN_WIDTHS_CSS" file="resources\omnibox\omnibox_column_widths.css" type="BINDATA" compress="gzip" />
       <include name="IDR_OMNIBOX_CSS" file="resources\omnibox\omnibox.css" type="BINDATA" compress="gzip" />
       <include name="IDR_OMNIBOX_ELEMENT_JS" file="resources\omnibox\omnibox_element.js" type="BINDATA" compress="gzip" />
-      <include name="IDR_OMNIBOX_INPUTS_JS" file="resources\omnibox\omnibox_inputs.js" type="BINDATA" compress="gzip" />
+      <include name="IDR_OMNIBOX_INPUT_JS" file="resources\omnibox\omnibox_input.js" type="BINDATA" compress="gzip" />
       <include name="IDR_OMNIBOX_OUTPUT_JS" file="resources\omnibox\omnibox_output.js" type="BINDATA" compress="gzip" />
       <include name="IDR_OMNIBOX_JS" file="resources\omnibox\omnibox.js" type="BINDATA" compress="gzip" />
       <include name="IDR_OMNIBOX_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\omnibox\omnibox.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
diff --git a/chrome/browser/browsing_data/browsing_data_file_system_helper.cc b/chrome/browser/browsing_data/browsing_data_file_system_helper.cc
index 05aaa2b..b02b198 100644
--- a/chrome/browser/browsing_data/browsing_data_file_system_helper.cc
+++ b/chrome/browser/browsing_data/browsing_data_file_system_helper.cc
@@ -9,8 +9,8 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/macros.h"
 #include "base/sequenced_task_runner.h"
+#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/browsing_data/browsing_data_helper.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -110,7 +110,7 @@
   std::list<FileSystemInfo> result;
   typedef std::map<GURL, FileSystemInfo> OriginInfoMap;
   OriginInfoMap file_system_info_map;
-  for (size_t i = 0; i < arraysize(types); ++i) {
+  for (size_t i = 0; i < base::size(types); ++i) {
     storage::FileSystemType type = types[i];
     storage::FileSystemQuotaUtil* quota_util =
         filesystem_context_->GetQuotaUtil(type);
diff --git a/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc
index 8cb58dd..61d443a 100644
--- a/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_util.h"
-#include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -238,7 +237,7 @@
       ADD_FAILURE() << info.origin.spec() << " isn't an origin we added.";
     }
   }
-  for (size_t i = 0; i < arraysize(test_hosts_found); i++) {
+  for (size_t i = 0; i < base::size(test_hosts_found); i++) {
     EXPECT_TRUE(test_hosts_found[i]);
   }
 }
diff --git a/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc b/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc
index 37f653ce..4f4f20da 100644
--- a/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc
@@ -14,9 +14,9 @@
 #include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/thread_test_helper.h"
 #include "base/threading/thread_restrictions.h"
@@ -63,7 +63,7 @@
     base::CreateDirectory(storage_path);
     static constexpr const base::FilePath::CharType* kFilesToCreate[] = {
         kTestFile0, kTestFile1, kTestFileInvalid, kTestFileExtension};
-    for (size_t i = 0; i < arraysize(kFilesToCreate); ++i) {
+    for (size_t i = 0; i < base::size(kFilesToCreate); ++i) {
       base::FilePath file_path = storage_path.Append(kFilesToCreate[i]);
       base::WriteFile(file_path, nullptr, 0);
     }
@@ -90,9 +90,9 @@
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     // There's no guarantee on the order, ensure these files are there.
     const char* const kTestHosts[] = {"www.chromium.org", "www.google.com"};
-    bool test_hosts_found[arraysize(kTestHosts)] = {false, false};
-    ASSERT_EQ(arraysize(kTestHosts), local_storage_info.size());
-    for (size_t i = 0; i < arraysize(kTestHosts); ++i) {
+    bool test_hosts_found[base::size(kTestHosts)] = {false, false};
+    ASSERT_EQ(base::size(kTestHosts), local_storage_info.size());
+    for (size_t i = 0; i < base::size(kTestHosts); ++i) {
       for (const auto& info : local_storage_info) {
         ASSERT_TRUE(info.origin_url.SchemeIs("http"));
         if (info.origin_url.host_piece() == kTestHosts[i]) {
@@ -101,7 +101,7 @@
         }
       }
     }
-    for (size_t i = 0; i < arraysize(kTestHosts); ++i) {
+    for (size_t i = 0; i < base::size(kTestHosts); ++i) {
       ASSERT_TRUE(test_hosts_found[i]) << kTestHosts[i];
     }
     base::RunLoop::QuitCurrentWhenIdleDeprecated();
diff --git a/chrome/browser/browsing_data/browsing_data_media_license_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_media_license_helper_unittest.cc
index 6f220ad..1a6fec0 100644
--- a/chrome/browser/browsing_data/browsing_data_media_license_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_media_license_helper_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_util.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
@@ -321,7 +320,7 @@
       ADD_FAILURE() << info.origin.spec() << " isn't an origin we added.";
     }
   }
-  for (size_t i = 0; i < arraysize(test_hosts_found); i++) {
+  for (size_t i = 0; i < base::size(test_hosts_found); i++) {
     EXPECT_TRUE(test_hosts_found[i]);
   }
 }
diff --git a/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc b/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc
index b3aee79..f3d56f8c 100644
--- a/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc
+++ b/chrome/browser/browsing_data/browsing_data_quota_helper_impl.cc
@@ -10,7 +10,7 @@
 #include "base/barrier_closure.h"
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/browsing_data/browsing_data_helper.h"
 #include "chrome/browser/profiles/profile.h"
@@ -71,7 +71,7 @@
   // hosts.
   PendingHosts* pending_hosts = new PendingHosts();
   base::RepeatingClosure completion = base::BarrierClosure(
-      arraysize(types),
+      base::size(types),
       base::BindOnce(&BrowsingDataQuotaHelperImpl::OnGetOriginsComplete,
                      weak_factory_.GetWeakPtr(), std::move(callback),
                      base::Owned(pending_hosts)));
diff --git a/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc
index 369ac754..7df68cdf 100644
--- a/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc
@@ -9,8 +9,8 @@
 
 #include "base/bind.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/browsing_data/browsing_data_quota_helper_impl.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -141,7 +141,7 @@
       {"http://example2.com/", StorageType::kTemporary, 1000},
   };
 
-  RegisterClient(kOrigins, arraysize(kOrigins));
+  RegisterClient(kOrigins, base::size(kOrigins));
   StartFetching();
   content::RunAllTasksUntilIdle();
   EXPECT_TRUE(fetching_completed());
@@ -170,7 +170,7 @@
        StorageType::kPersistent, 100000},
   };
 
-  RegisterClient(kOrigins, arraysize(kOrigins));
+  RegisterClient(kOrigins, base::size(kOrigins));
   StartFetching();
   content::RunAllTasksUntilIdle();
   EXPECT_TRUE(fetching_completed());
diff --git a/chrome/browser/browsing_data/site_data_size_collector_unittest.cc b/chrome/browser/browsing_data/site_data_size_collector_unittest.cc
index 167d3c0..d964bb0 100644
--- a/chrome/browser/browsing_data/site_data_size_collector_unittest.cc
+++ b/chrome/browser/browsing_data/site_data_size_collector_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_util.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "chrome/browser/browsing_data/mock_browsing_data_appcache_helper.h"
 #include "chrome/browser/browsing_data/mock_browsing_data_cache_storage_helper.h"
 #include "chrome/browser/browsing_data/mock_browsing_data_cookie_helper.h"
@@ -60,14 +61,14 @@
         new MockBrowsingDataFlashLSOHelper(profile_.get());
 
     base::WriteFile(profile_->GetPath().Append(chrome::kCookieFilename),
-                    kCookieFileData, arraysize(kCookieFileData));
+                    kCookieFileData, base::size(kCookieFileData));
     const base::FilePath flash_data_dir = profile_->GetPath().Append(
         content::kPepperDataDirname);
     base::CreateDirectory(flash_data_dir);
-    base::WriteFile(flash_data_dir.Append(kFlashDataFilename0),
-                    kFlashData0, arraysize(kFlashData0));
-    base::WriteFile(flash_data_dir.Append(kFlashDataFilename1),
-                    kFlashData1, arraysize(kFlashData1));
+    base::WriteFile(flash_data_dir.Append(kFlashDataFilename0), kFlashData0,
+                    base::size(kFlashData0));
+    base::WriteFile(flash_data_dir.Append(kFlashDataFilename1), kFlashData1,
+                    base::size(kFlashData1));
 
     fetched_size_ = -1;
   }
@@ -129,7 +130,7 @@
   mock_browsing_data_cookie_helper_->Notify();
   // Wait until reading files on blocking pool finishes.
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(static_cast<int64_t>(arraysize(kCookieFileData)), fetched_size_);
+  EXPECT_EQ(static_cast<int64_t>(base::size(kCookieFileData)), fetched_size_);
 }
 
 TEST_F(SiteDataSizeCollectorTest, FetchCookieWithoutEntry) {
@@ -246,7 +247,7 @@
   // Wait until reading files on blocking pool finishes.
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
-      static_cast<int64_t>(arraysize(kFlashData0) + arraysize(kFlashData1)),
+      static_cast<int64_t>(base::size(kFlashData0) + base::size(kFlashData1)),
       fetched_size_);
 }
 
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.cc b/chrome/browser/chrome_browser_field_trials_desktop.cc
index e40383e..690e6611 100644
--- a/chrome/browser/chrome_browser_field_trials_desktop.cc
+++ b/chrome/browser/chrome_browser_field_trials_desktop.cc
@@ -21,6 +21,7 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "base/time/time.h"
 #include "chrome/browser/prerender/prerender_field_trial.h"
@@ -151,7 +152,7 @@
         browser_watcher::StabilityRecordEvent::kGotTracker);
     // Record product, version, channel, special build and platform.
     wchar_t exe_file[MAX_PATH] = {};
-    CHECK(::GetModuleFileName(nullptr, exe_file, arraysize(exe_file)));
+    CHECK(::GetModuleFileName(nullptr, exe_file, base::size(exe_file)));
 
     base::string16 product_name;
     base::string16 version_number;
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index dd2fad9..c8823e98 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -301,6 +301,9 @@
 #if BUILDFLAG(ENABLE_VR)
 #include "chrome/browser/component_updater/vr_assets_component_installer.h"
 #include "chrome/browser/vr/service/vr_service_impl.h"
+#if defined(OS_WIN)
+#include "chrome/browser/vr/ui_host/vr_ui_host_impl.h"
+#endif
 #endif
 
 #if BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
@@ -1069,7 +1072,11 @@
 #if BUILDFLAG(ENABLE_VR)
   content::WebvrServiceProvider::SetWebvrServiceCallback(
       base::Bind(&vr::VRServiceImpl::Create));
-#endif
+
+#if defined(OS_WIN)
+  vr::VRUiHost::SetFactory(&vr::VRUiHostImpl::Create);
+#endif  // defined(OS_WIN)
+#endif  // BUILDFLAG(ENABLE_VR)
 
   // Enable Navigation Tracing only if a trace upload url is specified.
   if (parsed_command_line_.HasSwitch(switches::kEnableNavigationTracing) &&
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc
index 9103071..687c167 100644
--- a/chrome/browser/chrome_browser_main_win.cc
+++ b/chrome/browser/chrome_browser_main_win.cc
@@ -25,6 +25,7 @@
 #include "base/no_destructor.h"
 #include "base/path_service.h"
 #include "base/scoped_native_library.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
@@ -449,7 +450,7 @@
           ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR_DEPRECATED,
           ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR,
       };
-      for (size_t i = 0; i < arraysize(user_shortcut_locations); ++i) {
+      for (size_t i = 0; i < base::size(user_shortcut_locations); ++i) {
         if (!ShellUtil::RemoveShortcuts(user_shortcut_locations[i],
                                         ShellUtil::CURRENT_USER, chrome_exe)) {
           VLOG(1) << "Failed to delete shortcut at location "
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index fdbf81e..9a9898a2 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -17,11 +17,11 @@
 #include "base/i18n/base_i18n_switches.h"
 #include "base/i18n/character_encoding.h"
 #include "base/json/json_reader.h"
-#include "base/macros.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -1040,11 +1040,11 @@
     : chrome_feature_list_creator_(chrome_feature_list_creator),
       weak_factory_(this) {
 #if BUILDFLAG(ENABLE_PLUGINS)
-  for (size_t i = 0; i < arraysize(kPredefinedAllowedDevChannelOrigins); ++i)
+  for (size_t i = 0; i < base::size(kPredefinedAllowedDevChannelOrigins); ++i)
     allowed_dev_channel_origins_.insert(kPredefinedAllowedDevChannelOrigins[i]);
-  for (size_t i = 0; i < arraysize(kPredefinedAllowedFileHandleOrigins); ++i)
+  for (size_t i = 0; i < base::size(kPredefinedAllowedFileHandleOrigins); ++i)
     allowed_file_handle_origins_.insert(kPredefinedAllowedFileHandleOrigins[i]);
-  for (size_t i = 0; i < arraysize(kPredefinedAllowedSocketOrigins); ++i)
+  for (size_t i = 0; i < base::size(kPredefinedAllowedSocketOrigins); ++i)
     allowed_socket_origins_.insert(kPredefinedAllowedSocketOrigins[i]);
 
   extra_parts_.push_back(new ChromeContentBrowserClientPluginsPart);
@@ -1967,14 +1967,14 @@
     switches::kUserDataDir,  // Make logs go to the right file.
   };
   command_line->CopySwitchesFrom(browser_command_line, kCommonSwitchNames,
-                                 arraysize(kCommonSwitchNames));
+                                 base::size(kCommonSwitchNames));
 
   static const char* const kDinosaurEasterEggSwitches[] = {
       error_page::switches::kDisableDinosaurEasterEgg,
   };
   command_line->CopySwitchesFrom(browser_command_line,
                                  kDinosaurEasterEggSwitches,
-                                 arraysize(kDinosaurEasterEggSwitches));
+                                 base::size(kDinosaurEasterEggSwitches));
 
 #if defined(OS_CHROMEOS)
   // On Chrome OS need to pass primary user homedir (in multi-profiles session).
@@ -2143,7 +2143,7 @@
     };
 
     command_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
-                                   arraysize(kSwitchNames));
+                                   base::size(kSwitchNames));
   } else if (process_type == switches::kUtilityProcess) {
 #if BUILDFLAG(ENABLE_EXTENSIONS)
     static const char* const kSwitchNames[] = {
@@ -2154,7 +2154,7 @@
     };
 
     command_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
-                                   arraysize(kSwitchNames));
+                                   base::size(kSwitchNames));
 #endif
   } else if (process_type == service_manager::switches::kZygoteProcess) {
     static const char* const kSwitchNames[] = {
@@ -2171,7 +2171,7 @@
     };
 
     command_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
-                                   arraysize(kSwitchNames));
+                                   base::size(kSwitchNames));
   } else if (process_type == switches::kGpuProcess) {
     // If --ignore-gpu-blacklist is passed in, don't send in crash reports
     // because GPU is expected to be unreliable.
@@ -4400,9 +4400,8 @@
     static const char* const kWebRtcDevSwitchNames[] = {
       switches::kDisableWebRtcEncryption,
     };
-    to_command_line->CopySwitchesFrom(from_command_line,
-                                      kWebRtcDevSwitchNames,
-                                      arraysize(kWebRtcDevSwitchNames));
+    to_command_line->CopySwitchesFrom(from_command_line, kWebRtcDevSwitchNames,
+                                      base::size(kWebRtcDevSwitchNames));
   }
 }
 
diff --git a/chrome/browser/chrome_plugin_browsertest.cc b/chrome/browser/chrome_plugin_browsertest.cc
index 1311d3a..1c96884 100644
--- a/chrome/browser/chrome_plugin_browsertest.cc
+++ b/chrome/browser/chrome_plugin_browsertest.cc
@@ -10,10 +10,10 @@
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/files/file_util.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
 #include "base/process/process.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "build/build_config.h"
@@ -224,7 +224,7 @@
   };
 
   std::vector<content::WebPluginInfo> plugins = GetPlugins();
-  for (size_t i = 0; i < arraysize(expected); ++i) {
+  for (size_t i = 0; i < base::size(expected); ++i) {
     size_t j = 0;
     for (; j < plugins.size(); ++j) {
       if (plugins[j].name == base::ASCIIToUTF16(expected[i]))
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
index f072829..8ba6982 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
@@ -12,8 +12,8 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
 #include "base/threading/thread_restrictions.h"
@@ -949,7 +949,7 @@
       {"1234.1.1", false}, {"1234.1.3", false},
   };
 
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kTestCases); ++i) {
     scoped_refptr<extensions::Extension> app = MakeKioskApp(
         "App Name", "1.0", kAppId, kTestCases[i].required_platform_version);
     EXPECT_EQ(kTestCases[i].expected_compliant,
@@ -960,7 +960,7 @@
 
   // If an app is not auto launched with zero delay, it is always compliant.
   const char kNoneAutoLaucnhedAppId[] = "none_auto_launch_app_id";
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kTestCases); ++i) {
     scoped_refptr<extensions::Extension> app =
         MakeKioskApp("App Name", "1.0", kNoneAutoLaucnhedAppId,
                      kTestCases[i].required_platform_version);
diff --git a/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc b/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc
index 9ae6f134..47729a1 100644
--- a/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc
+++ b/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc
@@ -17,6 +17,7 @@
 #include "base/files/file_path_watcher.h"
 #include "base/memory/singleton.h"
 #include "base/sequence_checker.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
@@ -222,7 +223,7 @@
     ".xmf",    // FILE_TYPE_MID, audio/midi
 };
 const int kAndroidSupportedMediaExtensionsSize =
-    arraysize(kAndroidSupportedMediaExtensions);
+    base::size(kAndroidSupportedMediaExtensions);
 
 bool HasAndroidSupportedMediaExtension(const base::FilePath& path) {
   const std::string extension = base::ToLowerASCII(path.Extension());
diff --git a/chrome/browser/chromeos/attestation/fake_certificate.cc b/chrome/browser/chromeos/attestation/fake_certificate.cc
index 80e735b..b9bc4c33 100644
--- a/chrome/browser/chromeos/attestation/fake_certificate.cc
+++ b/chrome/browser/chromeos/attestation/fake_certificate.cc
@@ -6,7 +6,7 @@
 
 #include <stdint.h>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/time/time.h"
 #include "crypto/rsa_private_key.h"
 #include "net/cert/x509_certificate.h"
@@ -61,7 +61,7 @@
   }
   std::unique_ptr<crypto::RSAPrivateKey> test_key(
       crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(std::vector<uint8_t>(
-          &kTestKeyData[0], &kTestKeyData[arraysize(kTestKeyData)])));
+          &kTestKeyData[0], &kTestKeyData[base::size(kTestKeyData)])));
   if (!test_key.get()) {
     return false;
   }
diff --git a/chrome/browser/chromeos/customization/customization_document_browsertest.cc b/chrome/browser/chromeos/customization/customization_document_browsertest.cc
index 3f2d80e..8513557 100644
--- a/chrome/browser/chromeos/customization/customization_document_browsertest.cc
+++ b/chrome/browser/chromeos/customization/customization_document_browsertest.cc
@@ -6,7 +6,7 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread_restrictions.h"
@@ -75,7 +75,7 @@
 std::string GetExpectedLanguage(const std::string& required) {
   std::string expected = required;
 
-  for (size_t i = 0; i < arraysize(locale_aliases); ++i) {
+  for (size_t i = 0; i < base::size(locale_aliases); ++i) {
     if (required != locale_aliases[i].locale_alias)
       continue;
 
diff --git a/chrome/browser/chromeos/drive/download_handler.cc b/chrome/browser/chromeos/drive/download_handler.cc
index 19403ad..51c26ba 100644
--- a/chrome/browser/chromeos/drive/download_handler.cc
+++ b/chrome/browser/chromeos/drive/download_handler.cc
@@ -11,7 +11,7 @@
 
 #include "base/bind.h"
 #include "base/files/file_util.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/supports_user_data.h"
 #include "base/task/post_task.h"
@@ -125,7 +125,7 @@
 // 'default' fallback choice on the HTTP server. In such a case, we ignore the
 // type so that our logic can guess by its own while uploading to Drive.
 std::string FilterOutGenericMimeType(const std::string& mime_type) {
-  for (size_t i = 0; i < arraysize(kGenericMimeTypes); ++i) {
+  for (size_t i = 0; i < base::size(kGenericMimeTypes); ++i) {
     if (base::LowerCaseEqualsASCII(mime_type, kGenericMimeTypes[i]))
       return std::string();
   }
diff --git a/chrome/browser/chromeos/drive/file_system_util.cc b/chrome/browser/chromeos/drive/file_system_util.cc
index f8d423df..6d0bd518 100644
--- a/chrome/browser/chromeos/drive/file_system_util.cc
+++ b/chrome/browser/chromeos/drive/file_system_util.cc
@@ -17,7 +17,7 @@
 #include "base/i18n/icu_string_conversions.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/logging.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
@@ -101,7 +101,7 @@
   if (components[1] != FILE_PATH_LITERAL("special"))
     return base::FilePath();
   static const base::FilePath::CharType kPrefix[] = FILE_PATH_LITERAL("drive");
-  if (components[2].compare(0, arraysize(kPrefix) - 1, kPrefix) != 0)
+  if (components[2].compare(0, base::size(kPrefix) - 1, kPrefix) != 0)
     return base::FilePath();
 
   base::FilePath drive_path = GetDriveGrandRootPath();
diff --git a/chrome/browser/chromeos/extensions/default_app_order.cc b/chrome/browser/chromeos/extensions/default_app_order.cc
index 72bec8b..37373b4 100644
--- a/chrome/browser/chromeos/extensions/default_app_order.cc
+++ b/chrome/browser/chromeos/extensions/default_app_order.cc
@@ -12,8 +12,8 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/json/json_file_value_serializer.h"
-#include "base/macros.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
@@ -132,13 +132,13 @@
 
 // Gets built-in default app order.
 void GetDefault(std::vector<std::string>* app_ids) {
-  for (size_t i = 0; i < arraysize(kDefaultAppOrder); ++i)
+  for (size_t i = 0; i < base::size(kDefaultAppOrder); ++i)
     app_ids->push_back(std::string(kDefaultAppOrder[i]));
 }
 
 }  // namespace
 
-const size_t kDefaultAppOrderCount = arraysize(kDefaultAppOrder);
+const size_t kDefaultAppOrderCount = base::size(kDefaultAppOrder);
 
 ExternalLoader::ExternalLoader(bool async)
     : loaded_(base::WaitableEvent::ResetPolicy::MANUAL,
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
index d3d0524..11965ffb 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -13,7 +13,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_util.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
@@ -96,7 +96,7 @@
       "jndclpdbaamdhonoechobihbbiimdgai"   // Recovery tool prod
   };
 
-  for (size_t i = 0; i < arraysize(kRecoveryToolIds); ++i) {
+  for (size_t i = 0; i < base::size(kRecoveryToolIds); ++i) {
     const std::string extension_id = kRecoveryToolIds[i];
     if (extension_prefs->IsExtensionRunning(extension_id))
       return true;
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
index cd171e3e..74c97c6c 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
@@ -8,8 +8,8 @@
 #include <memory>
 
 #include "base/base64.h"
-#include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
 #include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
@@ -280,7 +280,7 @@
       }
     };
 
-    for (size_t i = 0; i < arraysize(kTestMountPoints); i++) {
+    for (size_t i = 0; i < base::size(kTestMountPoints); i++) {
       mount_points_.insert(DiskMountManager::MountPointMap::value_type(
           kTestMountPoints[i].mount_path,
           DiskMountManager::MountPointInfo(kTestMountPoints[i].source_path,
@@ -290,8 +290,8 @@
       ));
       int disk_info_index = kTestMountPoints[i].disk_info_index;
       if (kTestMountPoints[i].disk_info_index >= 0) {
-        EXPECT_GT(arraysize(kTestDisks), static_cast<size_t>(disk_info_index));
-        if (static_cast<size_t>(disk_info_index) >= arraysize(kTestDisks))
+        EXPECT_GT(base::size(kTestDisks), static_cast<size_t>(disk_info_index));
+        if (static_cast<size_t>(disk_info_index) >= base::size(kTestDisks))
           return;
 
         std::unique_ptr<Disk> disk =
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
index ced5d18d..dcc7b23 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
@@ -11,8 +11,8 @@
 
 #include "base/files/file_path.h"
 #include "base/location.h"
-#include "base/macros.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
 #include "chrome/browser/chromeos/drive/file_system_util.h"
@@ -448,7 +448,7 @@
     drive::util::GetDriveMountPointPath(profile),
     util::GetDownloadsFolderForProfile(profile),
   };
-  for (size_t i = 0; i < arraysize(paths); ++i) {
+  for (size_t i = 0; i < base::size(paths); ++i) {
     content::ChildProcessSecurityPolicy::GetInstance(
         )->GrantCreateReadWriteFile(render_view_process_id, paths[i]);
   }
diff --git a/chrome/browser/chromeos/extensions/gfx_utils.cc b/chrome/browser/chromeos/extensions/gfx_utils.cc
index 22c7cac6..349c09c 100644
--- a/chrome/browser/chromeos/extensions/gfx_utils.cc
+++ b/chrome/browser/chromeos/extensions/gfx_utils.cc
@@ -109,7 +109,7 @@
   using ExtensionToArcAppMap = std::unordered_map<std::string, std::string>;
 
   AppDualBadgeMap() {
-    for (size_t i = 0; i < arraysize(kDualBadgeMap); ++i) {
+    for (size_t i = 0; i < base::size(kDualBadgeMap); ++i) {
       arc_app_to_extensions_map_[kDualBadgeMap[i].arc_package_name].push_back(
           kDualBadgeMap[i].extension_id);
       extension_to_arc_app_map_[kDualBadgeMap[i].extension_id] =
diff --git a/chrome/browser/chromeos/extensions/input_method_api.cc b/chrome/browser/chromeos/extensions/input_method_api.cc
index 9741820..68d674d 100644
--- a/chrome/browser/chromeos/extensions/input_method_api.cc
+++ b/chrome/browser/chromeos/extensions/input_method_api.cc
@@ -324,8 +324,11 @@
   uint32_t param_before_length = (uint32_t)params->before_length;
   uint32_t param_after_length = (uint32_t)params->after_length;
 
-  auto ret = std::make_unique<base::DictionaryValue>();
   ui::SurroundingTextInfo info = input_context->GetSurroundingTextInfo();
+  if (!info.selection_range.IsValid())
+    return RespondNow(OneArgument(std::make_unique<base::Value>()));
+
+  auto ret = std::make_unique<base::DictionaryValue>();
   uint32_t selection_start = info.selection_range.start();
   uint32_t selection_end = info.selection_range.end();
   // Makes sure |selection_start| is less or equals to |selection_end|.
diff --git a/chrome/browser/chromeos/extensions/wallpaper_function_base.cc b/chrome/browser/chromeos/extensions/wallpaper_function_base.cc
index 8860ef7f..f5db433e 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_function_base.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_function_base.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/chromeos/extensions/wallpaper_function_base.h"
 
-#include "base/macros.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
 #include "base/synchronization/cancellation_flag.h"
 #include "base/task/lazy_task_runner.h"
 #include "base/task/task_traits.h"
@@ -31,7 +31,7 @@
   "TILE"
 };
 
-const int kWallpaperLayoutCount = arraysize(kWallpaperLayoutArrays);
+const int kWallpaperLayoutCount = base::size(kWallpaperLayoutArrays);
 
 base::LazySequencedTaskRunner g_blocking_task_runner =
     LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index bb32618..9de2c25 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -4,7 +4,7 @@
 
 #include <stddef.h>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
@@ -949,7 +949,7 @@
   // This is used for preparing all accounts in PRE_ test setup, and for testing
   // actual login behavior.
   void AddAllUsers() {
-    for (size_t i = 0; i < arraysize(kTestAccounts); ++i) {
+    for (size_t i = 0; i < base::size(kTestAccounts); ++i) {
       // The primary account was already set up in SetUpOnMainThread, so skip it
       // here.
       if (i == PRIMARY_ACCOUNT_INDEX)
diff --git a/chrome/browser/chromeos/file_manager/file_tasks.cc b/chrome/browser/chromeos/file_manager/file_tasks.cc
index fc6384b3..85769f4 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/file_tasks.cc
@@ -11,8 +11,8 @@
 
 #include "apps/launcher.h"
 #include "base/bind.h"
-#include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/chromeos/crostini/crostini_util.h"
@@ -132,7 +132,7 @@
       extension_misc::kQuickOfficeInternalExtensionId,
       extension_misc::kQuickOfficeExtensionId};
 
-  for (size_t i = 0; i < arraysize(kBuiltInApps); ++i) {
+  for (size_t i = 0; i < base::size(kBuiltInApps); ++i) {
     if (task.app_id == kBuiltInApps[i])
       return true;
   }
diff --git a/chrome/browser/chromeos/file_manager/open_with_browser.cc b/chrome/browser/chromeos/file_manager/open_with_browser.cc
index 6a85f71d..f7d61054 100644
--- a/chrome/browser/chromeos/file_manager/open_with_browser.cc
+++ b/chrome/browser/chromeos/file_manager/open_with_browser.cc
@@ -9,8 +9,8 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
@@ -58,7 +58,7 @@
 
 // Returns true if |file_path| is viewable in the browser (ex. HTML file).
 bool IsViewableInBrowser(const base::FilePath& file_path) {
-  for (size_t i = 0; i < arraysize(kFileExtensionsViewableInBrowser); i++) {
+  for (size_t i = 0; i < base::size(kFileExtensionsViewableInBrowser); i++) {
     if (file_path.MatchesExtension(kFileExtensionsViewableInBrowser[i]))
       return true;
   }
diff --git a/chrome/browser/chromeos/fileapi/file_system_backend.cc b/chrome/browser/chromeos/fileapi/file_system_backend.cc
index c6b07f74..66fa8b7c 100644
--- a/chrome/browser/chromeos/fileapi/file_system_backend.cc
+++ b/chrome/browser/chromeos/fileapi/file_system_backend.cc
@@ -11,6 +11,7 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/stl_util.h"
 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h"
 #include "chrome/browser/chromeos/fileapi/file_access_permissions.h"
 #include "chrome/browser/chromeos/fileapi/file_system_backend_delegate.h"
@@ -228,7 +229,7 @@
 
   const std::string& extension_id = url.origin().host();
   if (url.type() == storage::kFileSystemTypeRestrictedNativeLocal) {
-    for (size_t i = 0; i < arraysize(kOemAccessibleExtensions); ++i) {
+    for (size_t i = 0; i < base::size(kOemAccessibleExtensions); ++i) {
       if (extension_id == kOemAccessibleExtensions[i])
         return true;
     }
diff --git a/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc b/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc
index 21dc0e4..1c60ed9 100644
--- a/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc
+++ b/chrome/browser/chromeos/fileapi/file_system_backend_unittest.cc
@@ -9,7 +9,7 @@
 #include <set>
 
 #include "base/files/file_path.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "chrome/browser/chromeos/fileapi/file_system_backend_delegate.h"
 #include "chromeos/dbus/cros_disks_client.h"
 #include "extensions/common/constants.h"
@@ -237,7 +237,7 @@
     { FPL("/foo/xxx"), false, FPL("") },
   };
 
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kTestCases); ++i) {
     // Initialize virtual path with a value.
     base::FilePath virtual_path(FPL("/mount"));
     base::FilePath local_path(kTestCases[i].local_path);
diff --git a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
index 2a11d1a..55db4a68 100644
--- a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
@@ -11,8 +11,8 @@
 #include "base/files/file_util.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/system/sys_info.h"
 #include "base/task/post_task.h"
@@ -196,7 +196,7 @@
 
 // static
 bool ComponentExtensionIMEManagerImpl::IsIMEExtensionID(const std::string& id) {
-  for (size_t i = 0; i < arraysize(whitelisted_component_extension); ++i) {
+  for (size_t i = 0; i < base::size(whitelisted_component_extension); ++i) {
     if (base::LowerCaseEqualsASCII(id, whitelisted_component_extension[i].id))
       return true;
   }
@@ -309,7 +309,7 @@
 void ComponentExtensionIMEManagerImpl::ReadComponentExtensionsInfo(
     std::vector<ComponentExtensionIME>* out_imes) {
   DCHECK(out_imes);
-  for (size_t i = 0; i < arraysize(whitelisted_component_extension); ++i) {
+  for (size_t i = 0; i < base::size(whitelisted_component_extension); ++i) {
     ComponentExtensionIME component_ime;
     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
     component_ime.manifest =
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
index ae48e0d..19bfaa4 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
@@ -5,8 +5,8 @@
 #include <stddef.h>
 
 #include "base/bind_helpers.h"
-#include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
@@ -414,7 +414,7 @@
     { ui::VKEY_F9, "F9", "AudioVolumeDown" },
     { ui::VKEY_F10, "F10", "AudioVolumeUp" },
   };
-  for (size_t i = 0; i < arraysize(kMediaKeyCases); ++i) {
+  for (size_t i = 0; i < base::size(kMediaKeyCases); ++i) {
     SCOPED_TRACE(std::string("KeyDown, ") + kMediaKeyCases[i].code);
     KeyEventDoneCallback callback(false);
     const std::string expected_value =
diff --git a/chrome/browser/chromeos/input_method/textinput_browsertest.cc b/chrome/browser/chromeos/input_method/textinput_browsertest.cc
index 912afc6..c85c37b 100644
--- a/chrome/browser/chromeos/input_method/textinput_browsertest.cc
+++ b/chrome/browser/chromeos/input_method/textinput_browsertest.cc
@@ -4,7 +4,7 @@
 
 #include <stddef.h>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "chrome/browser/chromeos/input_method/textinput_test_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -256,7 +256,7 @@
     { "contenteditable_id", ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE },
   };  // The order should be same as tab order in all_input_node.html.
 
-  for (size_t i = 0; i < arraysize(expectations); ++i) {
+  for (size_t i = 0; i < base::size(expectations); ++i) {
     content::SimulateKeyPress(tab, ui::DomKey::TAB, ui::DomCode::TAB,
                               ui::VKEY_TAB, false, false, false, false);
 
@@ -264,7 +264,7 @@
     EXPECT_EQ(expectations[i].type, helper.GetTextInputType());
   }
 
-  for (size_t i = 0; i < arraysize(expectations); ++i) {
+  for (size_t i = 0; i < base::size(expectations); ++i) {
     helper.ClickElement(expectations[i].node_id, tab);
 
     helper.WaitForTextInputStateChanged(expectations[i].type);
diff --git a/chrome/browser/chromeos/locale_change_guard.cc b/chrome/browser/chromeos/locale_change_guard.cc
index 974b96e..94fe383c 100644
--- a/chrome/browser/chromeos/locale_change_guard.cc
+++ b/chrome/browser/chromeos/locale_change_guard.cc
@@ -8,7 +8,6 @@
 
 #include "ash/public/interfaces/constants.mojom.h"
 #include "base/bind.h"
-#include "base/macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -268,7 +267,7 @@
 
 // static
 size_t LocaleChangeGuard::GetSkipShowNotificationLanguagesSizeForTesting() {
-  return arraysize(kSkipShowNotificationLanguages);
+  return base::size(kSkipShowNotificationLanguages);
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
index 911a9a8..98660cc 100644
--- a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
@@ -12,9 +12,9 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
@@ -118,12 +118,12 @@
 
 std::vector<uint8_t> GetOwnerPublicKey() {
   return std::vector<uint8_t>(kOwnerPublicKey,
-                              kOwnerPublicKey + arraysize(kOwnerPublicKey));
+                              kOwnerPublicKey + base::size(kOwnerPublicKey));
 }
 
 bool CreateOwnerKeyInSlot(PK11SlotInfo* slot) {
   const std::vector<uint8_t> key(
-      kOwnerPrivateKey, kOwnerPrivateKey + arraysize(kOwnerPrivateKey));
+      kOwnerPrivateKey, kOwnerPrivateKey + base::size(kOwnerPrivateKey));
   return crypto::ImportNSSKeyFromPrivateKeyInfo(
              slot, key, true /* permanent */) != nullptr;
 }
diff --git a/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc b/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc
index 44f118e..0f026c7e 100644
--- a/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/auto_launched_kiosk_browsertest.cc
@@ -14,6 +14,7 @@
 #include "base/logging.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/app_mode/fake_cws.h"
@@ -131,7 +132,7 @@
     login_args_ = {{"login-manager", ""}};
 
     extra_args_ = {{switches::kPolicySwitchesBegin, ""}};
-    for (size_t i = 0; i < arraysize(kDefaultPolicySwitches); ++i) {
+    for (size_t i = 0; i < base::size(kDefaultPolicySwitches); ++i) {
       extra_args_.push_back(
           {kDefaultPolicySwitches[i].name, kDefaultPolicySwitches[i].value});
     }
@@ -470,7 +471,7 @@
 
   void ExpectCommandLineHasDefaultPolicySwitches(
       const base::CommandLine& cmd_line) {
-    for (size_t i = 0u; i < arraysize(kDefaultPolicySwitches); ++i) {
+    for (size_t i = 0u; i < base::size(kDefaultPolicySwitches); ++i) {
       EXPECT_TRUE(cmd_line.HasSwitch(kDefaultPolicySwitches[i].name))
           << "Missing flag " << kDefaultPolicySwitches[i].name;
       EXPECT_EQ(kDefaultPolicySwitches[i].value,
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index 443158fa..a6b7ea49 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -11,9 +11,9 @@
 #include "ash/public/cpp/ash_switches.h"
 #include "base/base_switches.h"
 #include "base/command_line.h"
-#include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/process/launch.h"
+#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/system/sys_info.h"
@@ -212,7 +212,7 @@
     wm::switches::kWindowAnimationsDisabled,
   };
   command_line->CopySwitchesFrom(base_command_line, kForwardSwitches,
-                                 arraysize(kForwardSwitches));
+                                 base::size(kForwardSwitches));
 
   if (start_url.is_valid())
     command_line->AppendArg(start_url.spec());
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_auth_attempt_unittest.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_auth_attempt_unittest.cc
index 2f83fa9..e296557 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_auth_attempt_unittest.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_auth_attempt_unittest.cc
@@ -7,7 +7,7 @@
 #include <stddef.h>
 
 #include "base/command_line.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "build/build_config.h"
 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
 #include "chromeos/components/proximity_auth/screenlock_bridge.h"
@@ -36,17 +36,17 @@
 
 std::string GetSecret() {
   return std::string(reinterpret_cast<const char*>(kSecret),
-                     arraysize(kSecret));
+                     base::size(kSecret));
 }
 
 std::string GetWrappedSecret() {
   return std::string(reinterpret_cast<const char*>(kWrappedSecret),
-                     arraysize(kWrappedSecret));
+                     base::size(kWrappedSecret));
 }
 
 std::string GetSessionKey() {
   return std::string(reinterpret_cast<const char*>(kSessionKey),
-                     arraysize(kSessionKey));
+                     base::size(kSessionKey));
 }
 
 // Fake lock handler to be used in these tests.
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_unittest.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_unittest.cc
index 441cd9d..c6d1442c 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_unittest.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_unittest.cc
@@ -5,9 +5,9 @@
 #include <cryptohi.h>
 
 #include "base/base64.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
@@ -418,14 +418,15 @@
 
 TEST_F(EasyUnlockTpmKeyManagerTest, PublicKeySetInPrefs) {
   SetLocalStatePublicKey(
-      test_account_id_, std::string(kTestPublicKey, arraysize(kTestPublicKey)));
+      test_account_id_,
+      std::string(kTestPublicKey, base::size(kTestPublicKey)));
 
   EXPECT_TRUE(user_key_manager()->PrepareTpmKey(
       false /* check_private_key */, base::Bind(&ExpectNotCalledCallback)));
 
   EXPECT_FALSE(user_key_manager()->GetPublicTpmKey(test_account_id_).empty());
   EXPECT_EQ(user_key_manager()->GetPublicTpmKey(test_account_id_),
-            std::string(kTestPublicKey, arraysize(kTestPublicKey)));
+            std::string(kTestPublicKey, base::size(kTestPublicKey)));
   EXPECT_EQ(user_key_manager()->GetPublicTpmKey(test_account_id_),
             signin_key_manager()->GetPublicTpmKey(test_account_id_));
 }
@@ -434,7 +435,8 @@
   ASSERT_TRUE(InitTestNssUser());
 
   SetLocalStatePublicKey(
-      test_account_id_, std::string(kTestPublicKey, arraysize(kTestPublicKey)));
+      test_account_id_,
+      std::string(kTestPublicKey, base::size(kTestPublicKey)));
 
   base::RunLoop run_loop;
   ASSERT_FALSE(user_key_manager()->PrepareTpmKey(true /* check_private_key */,
@@ -446,7 +448,7 @@
 
   EXPECT_FALSE(user_key_manager()->GetPublicTpmKey(test_account_id_).empty());
   EXPECT_NE(user_key_manager()->GetPublicTpmKey(test_account_id_),
-            std::string(kTestPublicKey, arraysize(kTestPublicKey)));
+            std::string(kTestPublicKey, base::size(kTestPublicKey)));
   EXPECT_EQ(user_key_manager()->GetPublicTpmKey(test_account_id_),
             signin_key_manager()->GetPublicTpmKey(test_account_id_));
 }
@@ -455,9 +457,10 @@
   ASSERT_TRUE(InitTestNssUser());
   ASSERT_TRUE(SetUpTestSystemSlot());
   VerifyKeyGenerationNotStartedAndFinalizeTestNssUser();
-  ASSERT_TRUE(ImportPrivateKey(kTestPrivateKey, arraysize(kTestPrivateKey)));
+  ASSERT_TRUE(ImportPrivateKey(kTestPrivateKey, base::size(kTestPrivateKey)));
   SetLocalStatePublicKey(
-      test_account_id_, std::string(kTestPublicKey, arraysize(kTestPublicKey)));
+      test_account_id_,
+      std::string(kTestPublicKey, base::size(kTestPublicKey)));
 
   int callback_count = 0;
   base::RunLoop run_loop;
@@ -473,7 +476,7 @@
   EXPECT_EQ(1, callback_count);
   EXPECT_FALSE(user_key_manager()->GetPublicTpmKey(test_account_id_).empty());
   EXPECT_EQ(user_key_manager()->GetPublicTpmKey(test_account_id_),
-            std::string(kTestPublicKey, arraysize(kTestPublicKey)));
+            std::string(kTestPublicKey, base::size(kTestPublicKey)));
   EXPECT_EQ(user_key_manager()->GetPublicTpmKey(test_account_id_),
             signin_key_manager()->GetPublicTpmKey(test_account_id_));
 
@@ -547,9 +550,10 @@
 
 TEST_F(EasyUnlockTpmKeyManagerTest, SignData) {
   ASSERT_TRUE(SetUpTestSystemSlot());
-  ASSERT_TRUE(ImportPrivateKey(kTestPrivateKey, arraysize(kTestPrivateKey)));
+  ASSERT_TRUE(ImportPrivateKey(kTestPrivateKey, base::size(kTestPrivateKey)));
   SetLocalStatePublicKey(
-      test_account_id_, std::string(kTestPublicKey, arraysize(kTestPublicKey)));
+      test_account_id_,
+      std::string(kTestPublicKey, base::size(kTestPublicKey)));
 
   base::RunLoop loop;
   std::string signed_data;
@@ -574,7 +578,8 @@
 
 TEST_F(EasyUnlockTpmKeyManagerTest, SignDataNoPrivateKeyPresent) {
   SetLocalStatePublicKey(
-      test_account_id_, std::string(kTestPublicKey, arraysize(kTestPublicKey)));
+      test_account_id_,
+      std::string(kTestPublicKey, base::size(kTestPublicKey)));
 
   base::RunLoop loop;
   std::string signed_data;
diff --git a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
index f8d4fbe5..bf62cfa 100644
--- a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
+++ b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
@@ -5,7 +5,6 @@
 #include "base/base64.h"
 #include "base/json/json_reader.h"
 #include "base/json/string_escape.h"
-#include "base/macros.h"
 #include "base/stl_util.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
@@ -834,7 +833,7 @@
       authpolicy::KerberosEncryptionTypes::ENC_TYPES_STRONG,
       std::vector<std::string>(
           kAdOrganizationlUnit,
-          kAdOrganizationlUnit + arraysize(kAdOrganizationlUnit)),
+          kAdOrganizationlUnit + base::size(kAdOrganizationlUnit)),
       kAdTestUser, kDMToken);
   SubmitActiveDirectoryCredentials("machine_name", kAdMachineDomainDN,
                                    "" /* encryption_types */, kAdTestUser,
diff --git a/chrome/browser/chromeos/login/login_ui_browsertest.cc b/chrome/browser/chromeos/login/login_ui_browsertest.cc
index 764a596..c2247d6 100644
--- a/chrome/browser/chromeos/login/login_ui_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_ui_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "base/stl_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
@@ -36,7 +37,7 @@
 class LoginUITest : public chromeos::LoginManagerTest {
  public:
   LoginUITest() : LoginManagerTest(false, true /* should_initialize_webui */) {
-    for (size_t i = 0; i < arraysize(kTestUsers); ++i) {
+    for (size_t i = 0; i < base::size(kTestUsers); ++i) {
       test_users_.emplace_back(AccountId::FromUserEmailGaiaId(
           kTestUsers[i].email, kTestUsers[i].gaia_id));
     }
diff --git a/chrome/browser/chromeos/login/oobe_localization_browsertest.cc b/chrome/browser/chromeos/login/oobe_localization_browsertest.cc
index 4e9a181f..c0a22b4 100644
--- a/chrome/browser/chromeos/login/oobe_localization_browsertest.cc
+++ b/chrome/browser/chromeos/login/oobe_localization_browsertest.cc
@@ -4,8 +4,8 @@
 
 #include <stddef.h>
 
-#include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/task_runner.h"
 #include "base/time/time.h"
@@ -431,6 +431,6 @@
     StructSequence,
     OobeLocalizationTest,
     testing::Range(&oobe_localization_test_parameters[0],
-                   &oobe_localization_test_parameters[arraysize(
+                   &oobe_localization_test_parameters[base::size(
                        oobe_localization_test_parameters)]));
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/oobe_screen.cc b/chrome/browser/chromeos/login/oobe_screen.cc
index bc3c33f..635a60fd 100644
--- a/chrome/browser/chromeos/login/oobe_screen.cc
+++ b/chrome/browser/chromeos/login/oobe_screen.cc
@@ -6,7 +6,6 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "chromeos/chromeos_switches.h"
@@ -68,7 +67,7 @@
 };
 
 static_assert(static_cast<size_t>(OobeScreen::SCREEN_UNKNOWN) ==
-                  arraysize(kScreenNames) - 1,
+                  base::size(kScreenNames) - 1,
               "Missing element in OobeScreen or kScreenNames");
 
 }  // namespace
@@ -79,7 +78,7 @@
 }
 
 OobeScreen GetOobeScreenFromName(const std::string& name) {
-  for (size_t i = 0; i < arraysize(kScreenNames); ++i) {
+  for (size_t i = 0; i < base::size(kScreenNames); ++i) {
     if (name == kScreenNames[i])
       return static_cast<OobeScreen>(i);
   }
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc b/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc
index 24b9fe6..b71ca157 100644
--- a/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc
+++ b/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc
@@ -7,8 +7,8 @@
 #include <memory>
 
 #include "base/command_line.h"
-#include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
 #include "chrome/browser/chromeos/login/screens/gaia_view.h"
@@ -147,7 +147,7 @@
   EXPECT_EQ(session_manager::SessionState::ACTIVE, manager->session_state());
   EXPECT_EQ(1u, manager->sessions().size());
 
-  for (size_t i = 1; i < arraysize(kTestUsers); ++i) {
+  for (size_t i = 1; i < base::size(kTestUsers); ++i) {
     // Verify that session state is LOGIN_SECONDARY during user adding.
     UserAddingScreen::Get()->Start();
     base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc b/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc
index e856e5c..07437d5 100644
--- a/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 #include "ash/public/cpp/ash_pref_names.h"
-#include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
 #include "chrome/browser/chromeos/login/lock/screen_locker_tester.h"
@@ -40,7 +40,7 @@
     } const kTestUsers[] = {{"test-user1@gmail.com", "1111111111"},
                             {"test-user2@gmail.com", "2222222222"},
                             {"test-user3@gmail.com", "3333333333"}};
-    for (size_t i = 0; i < arraysize(kTestUsers); ++i) {
+    for (size_t i = 0; i < base::size(kTestUsers); ++i) {
       test_users_.emplace_back(AccountId::FromUserEmailGaiaId(
           kTestUsers[i].email, kTestUsers[i].gaia_id));
     }
diff --git a/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc b/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc
index a6519e3..599da92 100644
--- a/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc
+++ b/chrome/browser/chromeos/login/users/default_user_image/default_user_images.cc
@@ -6,8 +6,8 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/rand_util.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
@@ -107,7 +107,7 @@
 };
 // clang-format on
 
-const int kDefaultImagesCount = arraysize(kDefaultImageResourceIDs);
+const int kDefaultImagesCount = base::size(kDefaultImageResourceIDs);
 
 const int kFirstDefaultImageIndex = 34;
 
@@ -170,7 +170,7 @@
 };
 // clang-format on
 
-const int kDefaultImageAuthorMaxID = arraysize(kDefaultImageAuthorIDs);
+const int kDefaultImageAuthorMaxID = base::size(kDefaultImageAuthorIDs);
 
 // clang-format off
 const int kDefaultImageWebsiteIDs[] = {
@@ -210,7 +210,7 @@
     IDS_LOGIN_DEFAULT_USER_WEBSITE_33,
 };
 
-const int kDefaultImageWebsiteMaxID = arraysize(kDefaultImageWebsiteIDs);
+const int kDefaultImageWebsiteMaxID = base::size(kDefaultImageWebsiteIDs);
 // clang-format on
 
 // IDs of default user image descriptions.
@@ -288,7 +288,8 @@
     IDS_LOGIN_DEFAULT_USER_DESC_70,
 };
 
-const int kDefaultImageDescriptionsMaxID = arraysize(kDefaultImageDescriptions);
+const int kDefaultImageDescriptionsMaxID =
+    base::size(kDefaultImageDescriptions);
 
 // Returns true if the string specified consists of the prefix and one of
 // the default images indices. Returns the index of the image in |image_id|
diff --git a/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc b/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc
index 5631232..95f07879 100644
--- a/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc
+++ b/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc
@@ -9,10 +9,10 @@
 #include <memory>
 
 #include "base/bind.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/chromeos/login/users/multi_profile_user_controller_delegate.h"
@@ -152,7 +152,7 @@
       : fake_user_manager_(new FakeChromeUserManager),
         user_manager_enabler_(base::WrapUnique(fake_user_manager_)),
         user_not_allowed_count_(0) {
-    for (size_t i = 0; i < arraysize(kUsers); ++i) {
+    for (size_t i = 0; i < base::size(kUsers); ++i) {
       test_users_.push_back(AccountId::FromUserEmail(kUsers[i]));
     }
   }
@@ -262,7 +262,7 @@
       MultiProfileUserController::kBehaviorPrimaryOnly,
       MultiProfileUserController::kBehaviorNotAllowed,
   };
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kTestCases); ++i) {
     SetCachedBehavior(0, kTestCases[i]);
     MultiProfileUserController::UserAllowedInSessionReason reason;
     EXPECT_TRUE(controller()->IsUserAllowedInSession(
@@ -293,7 +293,7 @@
       MultiProfileUserController::kBehaviorNotAllowed,
       MultiProfileUserController::kBehaviorUnrestricted,
   };
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kTestCases); ++i) {
     SetPrefBehavior(0, kTestCases[i]);
     EXPECT_EQ(kTestCases[i], GetCachedBehavior(0));
   }
@@ -325,7 +325,7 @@
 TEST_F(MultiProfileUserControllerTest, IsSecondaryAllowed) {
   LoginUser(0);
 
-  for (size_t i = 0; i < arraysize(kBehaviorTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kBehaviorTestCases); ++i) {
     SetPrefBehavior(0, kBehaviorTestCases[i].primary);
     SetCachedBehavior(1, kBehaviorTestCases[i].secondary);
     EXPECT_EQ(kBehaviorTestCases[i].expected_primary_policy,
@@ -344,7 +344,7 @@
   LoginUser(0);
   LoginUser(1);
 
-  for (size_t i = 0; i < arraysize(kBehaviorTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kBehaviorTestCases); ++i) {
     SetPrefBehavior(0, MultiProfileUserController::kBehaviorUnrestricted);
     SetPrefBehavior(1, MultiProfileUserController::kBehaviorUnrestricted);
     ResetCounts();
diff --git a/chrome/browser/chromeos/login/version_info_updater.cc b/chrome/browser/chromeos/login/version_info_updater.cc
index 5846ffb..1ec0834 100644
--- a/chrome/browser/chromeos/login/version_info_updater.cc
+++ b/chrome/browser/chromeos/login/version_info_updater.cc
@@ -8,7 +8,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/system/sys_info.h"
@@ -91,7 +91,7 @@
   // Watch for changes to the reporting flags.
   base::Closure callback = base::Bind(&VersionInfoUpdater::UpdateEnterpriseInfo,
                                       base::Unretained(this));
-  for (unsigned int i = 0; i < arraysize(kReportingFlags); ++i) {
+  for (unsigned int i = 0; i < base::size(kReportingFlags); ++i) {
     subscriptions_.push_back(
         cros_settings_->AddSettingsObserver(kReportingFlags[i], callback));
   }
diff --git a/chrome/browser/chromeos/network_change_manager_client_unittest.cc b/chrome/browser/chromeos/network_change_manager_client_unittest.cc
index c2ab2f1..ea0d0ed8 100644
--- a/chrome/browser/chromeos/network_change_manager_client_unittest.cc
+++ b/chrome/browser/chromeos/network_change_manager_client_unittest.cc
@@ -8,6 +8,7 @@
 
 #include <string>
 
+#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/network/network_handler.h"
@@ -96,7 +97,7 @@
       {shill::kTypeCellular, "unknown technology",
        NetworkChangeNotifier::CONNECTION_2G}};
 
-  for (size_t i = 0; i < arraysize(type_mappings); ++i) {
+  for (size_t i = 0; i < base::size(type_mappings); ++i) {
     NetworkChangeNotifier::ConnectionType type =
         NetworkChangeManagerClient::ConnectionTypeFromShill(
             type_mappings[i].shill_type, type_mappings[i].technology);
@@ -347,7 +348,7 @@
      false}};
 
 TEST_F(NetworkChangeManagerClientUpdateTest, UpdateDefaultNetwork) {
-  for (size_t i = 0; i < arraysize(test_cases); ++i) {
+  for (size_t i = 0; i < base::size(test_cases); ++i) {
     SCOPED_TRACE(test_cases[i].test_description);
     SetNotifierState(test_cases[i].initial_state);
     SetDefaultNetworkState(test_cases[i].default_network_state);
diff --git a/chrome/browser/chromeos/note_taking_helper.cc b/chrome/browser/chromeos/note_taking_helper.cc
index 00592c9..7c939c5 100644
--- a/chrome/browser/chromeos/note_taking_helper.cc
+++ b/chrome/browser/chromeos/note_taking_helper.cc
@@ -359,7 +359,7 @@
   }
   whitelisted_chrome_app_ids_.insert(whitelisted_chrome_app_ids_.end(),
                                      kExtensionIds,
-                                     kExtensionIds + arraysize(kExtensionIds));
+                                     kExtensionIds + base::size(kExtensionIds));
 
   // Track profiles so we can observe their extension registries.
   registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
diff --git a/chrome/browser/chromeos/policy/app_install_event_log_manager_unittest.cc b/chrome/browser/chromeos/policy/app_install_event_log_manager_unittest.cc
index c990f16..fb7ddc0 100644
--- a/chrome/browser/chromeos/policy/app_install_event_log_manager_unittest.cc
+++ b/chrome/browser/chromeos/policy/app_install_event_log_manager_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/sequenced_task_runner.h"
+#include "base/stl_util.h"
 #include "base/test/scoped_mock_time_message_loop_task_runner.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/test/test_simple_task_runner.h"
@@ -160,7 +161,7 @@
 
   void AddLogEntry(int app_index) {
     ASSERT_GE(app_index, 0);
-    ASSERT_LT(app_index, static_cast<int>(arraysize(kPackageNames)));
+    ASSERT_LT(app_index, static_cast<int>(base::size(kPackageNames)));
     const std::string package_name = kPackageNames[app_index];
     events_[package_name].push_back(event_);
     manager_->Add({kPackageNames[app_index]}, event_);
@@ -469,7 +470,7 @@
   FastForwardTo(offset);
   int i = 0;
   while (i <= kTotalSizeExpeditedUploadThreshold) {
-    for (int j = 0; j < static_cast<int>(arraysize(kPackageNames)); ++i, ++j) {
+    for (int j = 0; j < static_cast<int>(base::size(kPackageNames)); ++i, ++j) {
       AddLogEntry(j /* app_index */);
     }
   }
@@ -507,7 +508,7 @@
   const base::TimeDelta offset = base::TimeDelta::FromMinutes(20);
   FastForwardTo(offset);
   for (int i = 0; i <= kTotalSizeExpeditedUploadThreshold;
-       i += arraysize(kPackageNames)) {
+       i += base::size(kPackageNames)) {
     AddLogEntryForAllApps();
   }
 
diff --git a/chrome/browser/chromeos/policy/device_local_account.cc b/chrome/browser/chromeos/policy/device_local_account.cc
index 8f296087..c8064c2 100644
--- a/chrome/browser/chromeos/policy/device_local_account.cc
+++ b/chrome/browser/chromeos/policy/device_local_account.cc
@@ -11,7 +11,7 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
@@ -115,7 +115,7 @@
     return false;
 
   const std::string domain_prefix = domain.substr(
-      0, domain.size() - arraysize(kDeviceLocalAccountDomainSuffix) + 1);
+      0, domain.size() - base::size(kDeviceLocalAccountDomainSuffix) + 1);
 
   if (domain_prefix == kPublicAccountDomainPrefix) {
     if (type)
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
index 3ebe069b..03cca762 100644
--- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -25,12 +25,12 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/location.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -1006,7 +1006,7 @@
       SessionStartupPref::kPrefValueURLs);
   em::StringListPolicyProto* startup_urls_proto =
       device_local_account_policy_.payload().mutable_restoreonstartupurls();
-  for (size_t i = 0; i < arraysize(kStartupURLs); ++i)
+  for (size_t i = 0; i < base::size(kStartupURLs); ++i)
     startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]);
   UploadAndInstallDeviceLocalAccountPolicy();
   AddPublicSessionToDevicePolicy(kAccountId1);
@@ -1024,7 +1024,7 @@
 
   TabStripModel* tabs = browser->tab_strip_model();
   ASSERT_TRUE(tabs);
-  int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
+  int expected_tab_count = static_cast<int>(base::size(kStartupURLs));
   EXPECT_EQ(expected_tab_count, tabs->count());
   for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) {
     EXPECT_EQ(GURL(kStartupURLs[i]),
@@ -1773,7 +1773,7 @@
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, OneRecommendedLocale) {
   // Specify a recommended locale.
   SetRecommendedLocales(kSingleRecommendedLocale,
-                        arraysize(kSingleRecommendedLocale));
+                        base::size(kSingleRecommendedLocale));
   UploadAndInstallDeviceLocalAccountPolicy();
   AddPublicSessionToDevicePolicy(kAccountId1);
 
@@ -1802,7 +1802,7 @@
 
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, MultipleRecommendedLocales) {
   // Specify recommended locales.
-  SetRecommendedLocales(kRecommendedLocales1, arraysize(kRecommendedLocales1));
+  SetRecommendedLocales(kRecommendedLocales1, base::size(kRecommendedLocales1));
   UploadAndInstallDeviceLocalAccountPolicy();
   AddPublicSessionToDevicePolicy(kAccountId1);
   AddPublicSessionToDevicePolicy(kAccountId2);
@@ -1829,10 +1829,10 @@
   const base::ListValue* locales = NULL;
   ASSERT_TRUE(value_ptr);
   ASSERT_TRUE(value_ptr->GetAsList(&locales));
-  EXPECT_LT(arraysize(kRecommendedLocales1), locales->GetSize());
+  EXPECT_LT(base::size(kRecommendedLocales1), locales->GetSize());
 
   // Verify that the list starts with the recommended locales, in correct order.
-  for (size_t i = 0; i < arraysize(kRecommendedLocales1); ++i) {
+  for (size_t i = 0; i < base::size(kRecommendedLocales1); ++i) {
     std::string locale;
     EXPECT_TRUE(locales->GetString(i, &locale));
     EXPECT_EQ(kRecommendedLocales1[i], locale);
@@ -1841,9 +1841,9 @@
   // Verify that the recommended locales do not appear again in the remainder of
   // the list.
   std::set<std::string> recommended_locales;
-  for (size_t i = 0; i < arraysize(kRecommendedLocales1); ++i)
+  for (size_t i = 0; i < base::size(kRecommendedLocales1); ++i)
     recommended_locales.insert(kRecommendedLocales1[i]);
-  for (size_t i = arraysize(kRecommendedLocales1); i < locales->GetSize();
+  for (size_t i = base::size(kRecommendedLocales1); i < locales->GetSize();
        ++i) {
     std::string locale;
     EXPECT_TRUE(locales->GetString(i, &locale));
@@ -1863,7 +1863,7 @@
   EXPECT_EQ(kRecommendedLocales1[0], selected_locale);
 
   // Change the list of recommended locales.
-  SetRecommendedLocales(kRecommendedLocales2, arraysize(kRecommendedLocales2));
+  SetRecommendedLocales(kRecommendedLocales2, base::size(kRecommendedLocales2));
 
   // Also change the display name as it is easy to ensure that policy has been
   // updated by waiting for a display name change.
@@ -1887,8 +1887,8 @@
   locales = NULL;
   ASSERT_TRUE(value_ptr);
   ASSERT_TRUE(value_ptr->GetAsList(&locales));
-  EXPECT_LT(arraysize(kRecommendedLocales2), locales->GetSize());
-  for (size_t i = 0; i < arraysize(kRecommendedLocales2); ++i) {
+  EXPECT_LT(base::size(kRecommendedLocales2), locales->GetSize());
+  for (size_t i = 0; i < base::size(kRecommendedLocales2); ++i) {
     std::string locale;
     EXPECT_TRUE(locales->GetString(i, &locale));
     EXPECT_EQ(kRecommendedLocales2[i], locale);
@@ -1913,7 +1913,7 @@
           account_id_1_.Serialize().c_str(), kPublicSessionLocale)));
 
   // Change the list of recommended locales.
-  SetRecommendedLocales(kRecommendedLocales2, arraysize(kRecommendedLocales2));
+  SetRecommendedLocales(kRecommendedLocales2, base::size(kRecommendedLocales2));
   device_local_account_policy_.payload().mutable_userdisplayname()->set_value(
       kDisplayName1);
   UploadAndInstallDeviceLocalAccountPolicy();
@@ -2003,7 +2003,7 @@
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, InvalidRecommendedLocale) {
   // Specify an invalid recommended locale.
   SetRecommendedLocales(kInvalidRecommendedLocale,
-                        arraysize(kInvalidRecommendedLocale));
+                        base::size(kInvalidRecommendedLocale));
   UploadAndInstallDeviceLocalAccountPolicy();
   AddPublicSessionToDevicePolicy(kAccountId1);
 
@@ -2047,7 +2047,7 @@
   // Specify a locale that has real IMEs in addition to a keyboard layout one.
   const char* const kSingleLocaleWithIME[] = {"ja"};
   RunWithRecommendedLocale(kSingleLocaleWithIME,
-                           arraysize(kSingleLocaleWithIME));
+                           base::size(kSingleLocaleWithIME));
 
   EXPECT_GT(chromeos::input_method::InputMethodManager::Get()
                 ->GetActiveIMEState()
@@ -2059,7 +2059,7 @@
   // Specify a locale that has only keyboard layout.
   const char* const kSingleLocaleWithNoIME[] = {"de"};
   RunWithRecommendedLocale(kSingleLocaleWithNoIME,
-                           arraysize(kSingleLocaleWithNoIME));
+                           base::size(kSingleLocaleWithNoIME));
 
   EXPECT_EQ(1u, chromeos::input_method::InputMethodManager::Get()
                     ->GetActiveIMEState()
@@ -2086,7 +2086,7 @@
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest,
                        AutoLoginWithRecommendedLocales) {
   // Specify recommended locales.
-  SetRecommendedLocales(kRecommendedLocales1, arraysize(kRecommendedLocales1));
+  SetRecommendedLocales(kRecommendedLocales1, base::size(kRecommendedLocales1));
   UploadAndInstallDeviceLocalAccountPolicy();
   AddPublicSessionToDevicePolicy(kAccountId1);
   EnableAutoLogin();
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index 766d7433..b7a1ecf 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -11,7 +11,7 @@
 #include "base/callback.h"
 #include "base/json/json_reader.h"
 #include "base/logging.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/syslog_logging.h"
 #include "base/values.h"
@@ -101,7 +101,7 @@
       shill::kTypeBluetooth, shill::kTypeCellular,
   };
 
-  if (value < 0 || value >= static_cast<int>(arraysize(kConnectionTypes)))
+  if (value < 0 || value >= static_cast<int>(base::size(kConnectionTypes)))
     return nullptr;
 
   return std::make_unique<base::Value>(kConnectionTypes[value]);
diff --git a/chrome/browser/chromeos/policy/device_status_collector.cc b/chrome/browser/chromeos/policy/device_status_collector.cc
index 010df65..0887e7e 100644
--- a/chrome/browser/chromeos/policy/device_status_collector.cc
+++ b/chrome/browser/chromeos/policy/device_status_collector.cc
@@ -21,9 +21,9 @@
 #include "base/files/file_util.h"
 #include "base/format_macros.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/optional.h"
 #include "base/posix/eintr_wrapper.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -1473,14 +1473,14 @@
   for (device = device_list.begin(); device != device_list.end(); ++device) {
     // Determine the type enum constant for |device|.
     size_t type_idx = 0;
-    for (; type_idx < arraysize(kDeviceTypeMap); ++type_idx) {
+    for (; type_idx < base::size(kDeviceTypeMap); ++type_idx) {
       if ((*device)->type() == kDeviceTypeMap[type_idx].type_string)
         break;
     }
 
     // If the type isn't in |kDeviceTypeMap|, the interface is not relevant for
     // reporting. This filters out VPN devices.
-    if (type_idx >= arraysize(kDeviceTypeMap))
+    if (type_idx >= base::size(kDeviceTypeMap))
       continue;
 
     em::NetworkInterface* interface = status->add_network_interface();
@@ -1515,7 +1515,7 @@
     em::NetworkState::ConnectionState connection_state_enum =
         em::NetworkState::UNKNOWN;
     const std::string connection_state_string(state->connection_state());
-    for (size_t i = 0; i < arraysize(kConnectionStateMap); ++i) {
+    for (size_t i = 0; i < base::size(kConnectionStateMap); ++i) {
       if (connection_state_string == kConnectionStateMap[i].state_string) {
         connection_state_enum = kConnectionStateMap[i].state_constant;
         break;
diff --git a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
index 26105e9c..3cd5299 100644
--- a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
@@ -16,9 +16,9 @@
 #include "base/environment.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/system/sys_info.h"
 #include "base/test/scoped_feature_list.h"
@@ -1677,7 +1677,7 @@
 
   const char* kRequiredPlatformVersions[] = {"1234", "1234.0", "1234.0.0"};
 
-  for (size_t i = 0; i < arraysize(kRequiredPlatformVersions); ++i) {
+  for (size_t i = 0; i < base::size(kRequiredPlatformVersions); ++i) {
     MockAutoLaunchKioskAppWithRequiredPlatformVersion(
         fake_kiosk_device_local_account_, kRequiredPlatformVersions[i]);
 
@@ -1714,7 +1714,7 @@
           chromeos::UpdateEngineClient::UPDATE_STATUS_FINALIZING,
       };
 
-  for (size_t i = 0; i < arraysize(kUpdateEngineOps); ++i) {
+  for (size_t i = 0; i < base::size(kUpdateEngineOps); ++i) {
     update_status.status = kUpdateEngineOps[i];
     update_status.new_version = "1235.1.2";
     update_engine_client_->PushLastStatus(update_status);
@@ -2241,7 +2241,7 @@
         false,  // visible_only,
         0,      // no limit to number of results
         &state_list);
-    ASSERT_EQ(arraysize(kFakeNetworks), state_list.size());
+    ASSERT_EQ(base::size(kFakeNetworks), state_list.size());
   }
 
   void TearDown() override {
@@ -2281,7 +2281,7 @@
     EXPECT_EQ(count, device_status_.network_interface_size());
 
     // Now make sure network state list is correct.
-    EXPECT_EQ(arraysize(kFakeNetworks),
+    EXPECT_EQ(base::size(kFakeNetworks),
               static_cast<size_t>(device_status_.network_state_size()));
     for (const FakeNetworkState& state : kFakeNetworks) {
       bool found_match = false;
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc
index 86ed396..844d83b 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc
@@ -6,7 +6,7 @@
 #include <string>
 #include <utility>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -114,7 +114,7 @@
 
   TabStripModel* tabs = browser->tab_strip_model();
   ASSERT_TRUE(tabs);
-  const int expected_tab_count = static_cast<int>(arraysize(kStartupURLs));
+  const int expected_tab_count = static_cast<int>(base::size(kStartupURLs));
   EXPECT_EQ(expected_tab_count, tabs->count());
   for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) {
     EXPECT_EQ(GURL(kStartupURLs[i]),
diff --git a/chrome/browser/chromeos/power/power_metrics_reporter.cc b/chrome/browser/chromeos/power/power_metrics_reporter.cc
index 038af1c..ecaf386 100644
--- a/chrome/browser/chromeos/power/power_metrics_reporter.cc
+++ b/chrome/browser/chromeos/power/power_metrics_reporter.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/power/power_metrics_reporter.h"
 
 #include "base/metrics/histogram_functions.h"
+#include "base/stl_util.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
@@ -82,7 +83,7 @@
 void PowerMetricsReporter::RegisterLocalStatePrefs(
     PrefRegistrySimple* registry) {
   metrics::DailyEvent::RegisterPref(registry, prefs::kPowerMetricsDailySample);
-  for (size_t i = 0; i < arraysize(kDailyCounts); ++i)
+  for (size_t i = 0; i < base::size(kDailyCounts); ++i)
     registry->RegisterIntegerPref(kDailyCounts[i].pref_name, 0);
 }
 
@@ -95,7 +96,7 @@
           std::make_unique<metrics::DailyEvent>(pref_service_,
                                                 prefs::kPowerMetricsDailySample,
                                                 kDailyEventIntervalName)) {
-  for (size_t i = 0; i < arraysize(kDailyCounts); ++i) {
+  for (size_t i = 0; i < base::size(kDailyCounts); ++i) {
     daily_counts_[kDailyCounts[i].pref_name] =
         pref_service_->GetInteger(kDailyCounts[i].pref_name);
   }
@@ -143,14 +144,14 @@
     metrics::DailyEvent::IntervalType type) {
   // Don't send metrics on first run or if the clock is changed.
   if (type == metrics::DailyEvent::IntervalType::DAY_ELAPSED) {
-    for (size_t i = 0; i < arraysize(kDailyCounts); ++i) {
+    for (size_t i = 0; i < base::size(kDailyCounts); ++i) {
       base::UmaHistogramCounts100(kDailyCounts[i].metric_name,
                                   daily_counts_[kDailyCounts[i].pref_name]);
     }
   }
 
   // Reset all counts now that they've been reported.
-  for (size_t i = 0; i < arraysize(kDailyCounts); ++i) {
+  for (size_t i = 0; i < base::size(kDailyCounts); ++i) {
     const char* pref_name = kDailyCounts[i].pref_name;
     AddToCount(pref_name, -1 * daily_counts_[pref_name]);
   }
diff --git a/chrome/browser/chromeos/preferences_chromeos_browsertest.cc b/chrome/browser/chromeos/preferences_chromeos_browsertest.cc
index 1b3b7d4..f61672ab 100644
--- a/chrome/browser/chromeos/preferences_chromeos_browsertest.cc
+++ b/chrome/browser/chromeos/preferences_chromeos_browsertest.cc
@@ -7,7 +7,7 @@
 
 #include "ash/public/cpp/ash_switches.h"
 #include "base/command_line.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/input_method/input_method_manager_impl.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
@@ -41,7 +41,7 @@
       const char* gaia_id;
     } const kTestUsers[] = {{"test-user1@gmail.com", "1111111111"},
                             {"test-user2@gmail.com", "2222222222"}};
-    for (size_t i = 0; i < arraysize(kTestUsers); ++i) {
+    for (size_t i = 0; i < base::size(kTestUsers); ++i) {
       test_users_.push_back(AccountId::FromUserEmailGaiaId(
           kTestUsers[i].email, kTestUsers[i].gaia_id));
     }
diff --git a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
index 5b751f4..f817ecf 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
@@ -12,8 +12,8 @@
 #include "base/format_macros.h"
 #include "base/json/json_writer.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
@@ -378,7 +378,7 @@
   SetUpPrivateWiFi();
   // Create a ProxyConfigServiceImpl like for the system request context.
   SetUpProxyConfigService(nullptr /* no profile prefs */);
-  for (size_t i = 0; i < arraysize(tests); ++i) {
+  for (size_t i = 0; i < base::size(tests); ++i) {
     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
                                     tests[i].description.c_str()));
 
@@ -422,7 +422,7 @@
     { 8, 7, 6, },
     { 7, 6, 8, },
   };
-  for (size_t i = 0; i < arraysize(proxies); ++i) {
+  for (size_t i = 0; i < base::size(proxies); ++i) {
     const TestParams& managed_params = tests[proxies[i][0]];
     const TestParams& recommended_params = tests[proxies[i][1]];
     const TestParams& network_params = tests[proxies[i][2]];
diff --git a/chrome/browser/chromeos/proxy_cros_settings_parser.cc b/chrome/browser/chromeos/proxy_cros_settings_parser.cc
index f1e02aa..d5ce5f1 100644
--- a/chrome/browser/chromeos/proxy_cros_settings_parser.cc
+++ b/chrome/browser/chromeos/proxy_cros_settings_parser.cc
@@ -6,7 +6,7 @@
 
 #include <stdint.h>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
 #include "chromeos/network/proxy/ui_proxy_config.h"
@@ -103,7 +103,7 @@
 
 // We have to explicitly export this because the arraysize macro doesn't like
 // extern arrays as their size is not known on compile time.
-const size_t kProxySettingsCount = arraysize(kProxySettings);
+const size_t kProxySettingsCount = base::size(kProxySettings);
 
 bool IsProxyPref(const std::string& path) {
   return base::StartsWith(path, kProxyPrefsPrefix,
diff --git a/chrome/browser/chromeos/resource_reporter/resource_reporter_unittest.cc b/chrome/browser/chromeos/resource_reporter/resource_reporter_unittest.cc
index 086fb5f..96c21a0 100644
--- a/chrome/browser/chromeos/resource_reporter/resource_reporter_unittest.cc
+++ b/chrome/browser/chromeos/resource_reporter/resource_reporter_unittest.cc
@@ -10,9 +10,9 @@
 #include <string>
 #include <vector>
 
-#include "base/macros.h"
 #include "base/memory/fake_memory_pressure_monitor.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/system/sys_info.h"
 #include "base/timer/mock_timer.h"
@@ -55,7 +55,7 @@
     {12, "12", 87.0, 30 * k1KB, false},
 };
 
-constexpr size_t kTasksSize = arraysize(kTestTasks);
+constexpr size_t kTasksSize = base::size(kTestTasks);
 
 // A test implementation of the task manager that can be used to collect CPU and
 // memory usage so that they can be tested with the resource reporter.
diff --git a/chrome/browser/component_updater/file_type_policies_component_installer.cc b/chrome/browser/component_updater/file_type_policies_component_installer.cc
index d5ed6efd..48f96c4 100644
--- a/chrome/browser/component_updater/file_type_policies_component_installer.cc
+++ b/chrome/browser/component_updater/file_type_policies_component_installer.cc
@@ -13,9 +13,9 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "base/version.h"
 #include "chrome/common/safe_browsing/file_type_policies.h"
@@ -112,7 +112,7 @@
     std::vector<uint8_t>* hash) const {
   hash->assign(kFileTypePoliciesPublicKeySHA256,
                kFileTypePoliciesPublicKeySHA256 +
-                   arraysize(kFileTypePoliciesPublicKeySHA256));
+                   base::size(kFileTypePoliciesPublicKeySHA256));
 }
 
 std::string FileTypePoliciesComponentInstallerPolicy::GetName() const {
diff --git a/chrome/browser/component_updater/mei_preload_component_installer.cc b/chrome/browser/component_updater/mei_preload_component_installer.cc
index a36bda5..c196676 100644
--- a/chrome/browser/component_updater/mei_preload_component_installer.cc
+++ b/chrome/browser/component_updater/mei_preload_component_installer.cc
@@ -13,9 +13,9 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "base/version.h"
 #include "chrome/browser/media/media_engagement_preloaded_list.h"
@@ -114,7 +114,7 @@
     std::vector<uint8_t>* hash) const {
   hash->assign(
       kMeiPreloadPublicKeySHA256,
-      kMeiPreloadPublicKeySHA256 + arraysize(kMeiPreloadPublicKeySHA256));
+      kMeiPreloadPublicKeySHA256 + base::size(kMeiPreloadPublicKeySHA256));
 }
 
 std::string MediaEngagementPreloadComponentInstallerPolicy::GetName() const {
diff --git a/chrome/browser/component_updater/origin_trials_component_installer.cc b/chrome/browser/component_updater/origin_trials_component_installer.cc
index 73b8d43..ae36148 100644
--- a/chrome/browser/component_updater/origin_trials_component_installer.cc
+++ b/chrome/browser/component_updater/origin_trials_component_installer.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/common/chrome_switches.h"
@@ -128,7 +129,7 @@
   if (!hash)
     return;
   hash->assign(kOriginTrialSha2Hash,
-               kOriginTrialSha2Hash + arraysize(kOriginTrialSha2Hash));
+               kOriginTrialSha2Hash + base::size(kOriginTrialSha2Hash));
 }
 
 std::string OriginTrialsComponentInstallerPolicy::GetName() const {
diff --git a/chrome/browser/component_updater/pepper_flash_component_installer.cc b/chrome/browser/component_updater/pepper_flash_component_installer.cc
index dd4e981..35c38d6 100644
--- a/chrome/browser/component_updater/pepper_flash_component_installer.cc
+++ b/chrome/browser/component_updater/pepper_flash_component_installer.cc
@@ -81,7 +81,7 @@
     0x86, 0x8c, 0x86, 0x2c, 0x11, 0xb9, 0x40, 0xc5, 0x55, 0xaf, 0x08,
     0x63, 0x70, 0x54, 0xf9, 0x56, 0xd3, 0xe7, 0x88, 0xba, 0x8c};
 #endif  // defined(OS_CHROMEOS)
-static_assert(arraysize(kFlashSha2Hash) == crypto::kSHA256Length,
+static_assert(base::size(kFlashSha2Hash) == crypto::kSHA256Length,
               "Wrong hash length");
 
 #if defined(OS_CHROMEOS)
@@ -339,7 +339,7 @@
 }
 
 void FlashComponentInstallerPolicy::GetHash(std::vector<uint8_t>* hash) const {
-  hash->assign(kFlashSha2Hash, kFlashSha2Hash + arraysize(kFlashSha2Hash));
+  hash->assign(kFlashSha2Hash, kFlashSha2Hash + base::size(kFlashSha2Hash));
 }
 
 std::string FlashComponentInstallerPolicy::GetName() const {
diff --git a/chrome/browser/component_updater/recovery_component_installer.cc b/chrome/browser/component_updater/recovery_component_installer.cc
index c67f0ef..ecd7e95 100644
--- a/chrome/browser/component_updater/recovery_component_installer.cc
+++ b/chrome/browser/component_updater/recovery_component_installer.cc
@@ -29,6 +29,7 @@
 #include "base/process/kill.h"
 #include "base/process/launch.h"
 #include "base/process/process.h"
+#include "base/stl_util.h"
 #include "build/build_config.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -57,7 +58,7 @@
     0xdf, 0x39, 0x9a, 0x9b, 0x28, 0x3a, 0x9b, 0x0c, 0xbc, 0xc3, 0x4b,
     0x29, 0x12, 0xf3, 0x9e, 0x2c, 0x19, 0x7a, 0x71, 0x4b, 0x0a, 0x7c,
     0x80, 0x1c, 0xf6, 0x29, 0x7c, 0x0a, 0x5f, 0xea, 0x67, 0xb7};
-static_assert(arraysize(kRecoverySha2Hash) == crypto::kSHA256Length,
+static_assert(base::size(kRecoverySha2Hash) == crypto::kSHA256Length,
               "Wrong hash length");
 
 // File name of the recovery binary on different platforms.
diff --git a/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc b/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc
index 9665a94..fe3d6b53 100644
--- a/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc
+++ b/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
+#include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/ssl/ssl_error_assistant.h"
 #include "chrome/browser/ssl/ssl_error_handler.h"
@@ -121,7 +122,7 @@
     std::vector<uint8_t>* hash) const {
   hash->assign(kSslErrorAssistantPublicKeySHA256,
                kSslErrorAssistantPublicKeySHA256 +
-                   arraysize(kSslErrorAssistantPublicKeySHA256));
+                   base::size(kSslErrorAssistantPublicKeySHA256));
 }
 
 std::string SSLErrorAssistantComponentInstallerPolicy::GetName() const {
diff --git a/chrome/browser/component_updater/vr_assets_component_installer.cc b/chrome/browser/component_updater/vr_assets_component_installer.cc
index 38171f7..60d3786a 100644
--- a/chrome/browser/component_updater/vr_assets_component_installer.cc
+++ b/chrome/browser/component_updater/vr_assets_component_installer.cc
@@ -13,7 +13,6 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/path_service.h"
 #include "base/stl_util.h"
 #include "base/task/post_task.h"
@@ -185,7 +184,7 @@
 void VrAssetsComponentInstallerPolicy::GetHash(
     std::vector<uint8_t>* hash) const {
   hash->assign(kVrAssetsPublicKeySHA256,
-               kVrAssetsPublicKeySHA256 + arraysize(kVrAssetsPublicKeySHA256));
+               kVrAssetsPublicKeySHA256 + base::size(kVrAssetsPublicKeySHA256));
 }
 
 std::string VrAssetsComponentInstallerPolicy::GetName() const {
diff --git a/chrome/browser/component_updater/widevine_cdm_component_installer.cc b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
index a7398d4..f554dade 100644
--- a/chrome/browser/component_updater/widevine_cdm_component_installer.cc
+++ b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
@@ -18,9 +18,9 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/native_library.h"
+#include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
@@ -62,7 +62,7 @@
     0xe8, 0xce, 0xcf, 0x42, 0x06, 0xd0, 0x93, 0x49, 0x6d, 0xd9, 0x89,
     0xe1, 0x41, 0x04, 0x86, 0x4a, 0x8f, 0xbd, 0x86, 0x12, 0xb9, 0x58,
     0x9b, 0xfb, 0x4f, 0xbb, 0x1b, 0xa9, 0xd3, 0x85, 0x37, 0xef};
-static_assert(arraysize(kWidevineSha2Hash) == crypto::kSHA256Length,
+static_assert(base::size(kWidevineSha2Hash) == crypto::kSHA256Length,
               "Wrong hash length");
 
 // Name of the Widevine CDM OS in the component manifest.
@@ -492,7 +492,7 @@
 void WidevineCdmComponentInstallerPolicy::GetHash(
     std::vector<uint8_t>* hash) const {
   hash->assign(kWidevineSha2Hash,
-               kWidevineSha2Hash + arraysize(kWidevineSha2Hash));
+               kWidevineSha2Hash + base::size(kWidevineSha2Hash));
 }
 
 std::string WidevineCdmComponentInstallerPolicy::GetName() const {
diff --git a/chrome/browser/conflicts/module_info_util_win_unittest.cc b/chrome/browser/conflicts/module_info_util_win_unittest.cc
index 94568bd..7d596eb 100644
--- a/chrome/browser/conflicts/module_info_util_win_unittest.cc
+++ b/chrome/browser/conflicts/module_info_util_win_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/path_service.h"
 #include "base/scoped_native_library.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_environment_variable_override.h"
 #include "base/win/pe_image.h"
@@ -114,7 +115,7 @@
       std::make_pair(L"c:\\foo\\bar", L"%x%"),
   };
 
-  for (size_t i = 0; i < arraysize(kCollapsePathList); ++i) {
+  for (size_t i = 0; i < base::size(kCollapsePathList); ++i) {
     base::string16 test_case = kCollapsePathList[i].test_case;
     CollapseMatchingPrefixInPath(string_mapping, &test_case);
     EXPECT_EQ(kCollapsePathList[i].expected_result, test_case);
diff --git a/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.cc b/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.cc
index b0699ac..fe51f11 100644
--- a/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.cc
+++ b/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.cc
@@ -11,6 +11,7 @@
 #include "base/base64.h"
 #include "base/memory/ref_counted.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
@@ -90,7 +91,7 @@
       "data:application/x-ns-proxy-autoconfig;base64,";
   return base::StartsWith(pac_url, kPacURLPrefix,
                           base::CompareCase::SENSITIVE) &&
-         base::Base64Decode(pac_url.substr(arraysize(kPacURLPrefix) - 1),
+         base::Base64Decode(pac_url.substr(base::size(kPacURLPrefix) - 1),
                             pac_script);
 }
 
diff --git a/chrome/browser/devtools/device/android_device_info_query.cc b/chrome/browser/devtools/device/android_device_info_query.cc
index cae3802..53d6986 100644
--- a/chrome/browser/devtools/device/android_device_info_query.cc
+++ b/chrome/browser/devtools/device/android_device_info_query.cc
@@ -4,7 +4,7 @@
 
 #include <stddef.h>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -91,7 +91,7 @@
 };
 
 const BrowserDescriptor* FindBrowserDescriptor(const std::string& package) {
-  size_t count = arraysize(kBrowserDescriptors);
+  size_t count = base::size(kBrowserDescriptors);
   for (size_t i = 0; i < count; i++) {
     if (kBrowserDescriptors[i].package == package)
       return &kBrowserDescriptors[i];
@@ -101,7 +101,7 @@
 
 bool BrowserCompare(const AndroidDeviceManager::BrowserInfo& a,
                     const AndroidDeviceManager::BrowserInfo& b) {
-  size_t count = arraysize(kBrowserDescriptors);
+  size_t count = base::size(kBrowserDescriptors);
   for (size_t i = 0; i < count; i++) {
     bool isA = kBrowserDescriptors[i].display_name == a.display_name;
     bool isB = kBrowserDescriptors[i].display_name == b.display_name;
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index a98dfb83f..6faa82d0 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -13,13 +13,13 @@
 #include "base/compiler_specific.h"
 #include "base/files/file_path.h"
 #include "base/location.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/optional.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -155,7 +155,7 @@
   const char* args_array[] = {method, args...};
   std::ostringstream script;
   script << "uiTests.dispatchOnTestSuite([";
-  for (size_t i = 0; i < arraysize(args_array); ++i)
+  for (size_t i = 0; i < base::size(args_array); ++i)
     script << (i ? "," : "") << '\"' << args_array[i] << '\"';
   script << "])";
   ASSERT_TRUE(
diff --git a/chrome/browser/diagnostics/diagnostics_controller_unittest.cc b/chrome/browser/diagnostics/diagnostics_controller_unittest.cc
index 999f600a..2b92d120 100644
--- a/chrome/browser/diagnostics/diagnostics_controller_unittest.cc
+++ b/chrome/browser/diagnostics/diagnostics_controller_unittest.cc
@@ -10,8 +10,8 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "build/build_config.h"
 #include "chrome/browser/diagnostics/diagnostics_model.h"
 #include "chrome/browser/diagnostics/diagnostics_writer.h"
@@ -72,7 +72,7 @@
     // Just write some random characters into the file tInvaludUsero "corrupt"
     // it.
     const char bogus_data[] = "wwZ2uNYNuyUVzFbDm3DL";
-    base::WriteFile(path, bogus_data, arraysize(bogus_data));
+    base::WriteFile(path, bogus_data, base::size(bogus_data));
   }
 
   std::unique_ptr<DiagnosticsModel> model_;
diff --git a/chrome/browser/diagnostics/diagnostics_metrics.cc b/chrome/browser/diagnostics/diagnostics_metrics.cc
index 5b07755..3da9fd5 100644
--- a/chrome/browser/diagnostics/diagnostics_metrics.cc
+++ b/chrome/browser/diagnostics/diagnostics_metrics.cc
@@ -6,8 +6,8 @@
 
 #include <string>
 
-#include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
 #include "chrome/browser/diagnostics/diagnostics_test.h"
 
 namespace diagnostics {
@@ -55,7 +55,7 @@
     // Add new entries in the same order as DiagnosticsTestId.
 };
 
-static_assert(arraysize(kTestNameInfo) == DIAGNOSTICS_TEST_ID_COUNT,
+static_assert(base::size(kTestNameInfo) == DIAGNOSTICS_TEST_ID_COUNT,
               "diagnostics test info mismatch");
 
 const TestNameInfo* FindTestInfo(DiagnosticsTestId id) {
diff --git a/chrome/browser/diagnostics/diagnostics_writer.cc b/chrome/browser/diagnostics/diagnostics_writer.cc
index 2f62550..ffee058 100644
--- a/chrome/browser/diagnostics/diagnostics_writer.cc
+++ b/chrome/browser/diagnostics/diagnostics_writer.cc
@@ -10,7 +10,7 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -86,7 +86,7 @@
     SetColor(SimpleConsole::DEFAULT);
     Write(L"Press [enter] to continue\n");
     wchar_t buf[256];
-    DWORD read = arraysize(buf);
+    DWORD read = base::size(buf);
     ::ReadConsoleW(std_in_, buf, read, &read, NULL);
   }
 
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index d3c6d4b..816eed3 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -21,10 +21,10 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -1389,7 +1389,7 @@
     "image/jpeg",
     "image/bmp",
   };
-  for (size_t i = 0; i < arraysize(mime_types); ++i) {
+  for (size_t i = 0; i < base::size(mime_types); ++i) {
     const char* mime_type = mime_types[i];
     GURL url(
         embedded_test_server()->GetURL(std::string("/").append(mime_type)));
@@ -2707,7 +2707,7 @@
        "http://doesnotexist/shouldnotdownloadsuccessfully", DOWNLOAD_DIRECT,
        download::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, true, false}};
 
-  DownloadFilesCheckErrors(arraysize(download_info), download_info);
+  DownloadFilesCheckErrors(base::size(download_info), download_info);
 }
 
 #if defined(OS_MACOSX)
@@ -2812,7 +2812,7 @@
            download::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
        }}};
 
-  DownloadInsertFilesErrorCheckErrors(arraysize(error_info), error_info);
+  DownloadInsertFilesErrorCheckErrors(base::size(error_info), error_info);
 }
 
 IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadErrorReadonlyFolder) {
@@ -2824,7 +2824,7 @@
        // This passes because we switch to the My Documents folder.
        download::DOWNLOAD_INTERRUPT_REASON_NONE, true, true}};
 
-  DownloadFilesToReadonlyFolder(arraysize(download_info), download_info);
+  DownloadFilesToReadonlyFolder(base::size(download_info), download_info);
 }
 
 // Test that we show a dangerous downloads warning for a dangerous file
@@ -3204,7 +3204,7 @@
       GetDownloadDirectory(browser()).Append(FILE_PATH_LITERAL("origin"));
   ASSERT_TRUE(base::CreateDirectory(origin_directory));
 
-  for (size_t index = 0; index < arraysize(kCrazyFilenames); ++index) {
+  for (size_t index = 0; index < base::size(kCrazyFilenames); ++index) {
     SCOPED_TRACE(testing::Message() << "Index " << index);
     base::string16 crazy16;
     std::string crazy8;
diff --git a/chrome/browser/download/download_item_model_unittest.cc b/chrome/browser/download/download_item_model_unittest.cc
index bd201e3..4ba8da8 100644
--- a/chrome/browser/download/download_item_model_unittest.cc
+++ b/chrome/browser/download/download_item_model_unittest.cc
@@ -11,7 +11,7 @@
 
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -47,7 +47,7 @@
 #include "components/download/public/common/download_interrupt_reason_values.h"
 #undef INTERRUPT_REASON
 };
-const size_t kInterruptReasonCount = arraysize(kInterruptReasonCounter);
+const size_t kInterruptReasonCount = base::size(kInterruptReasonCounter);
 
 // Default target path for a mock download item in DownloadItemModelTest.
 const base::FilePath::CharType kDefaultTargetFilePath[] =
@@ -178,11 +178,11 @@
       {download::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN, "Failed - Shutdown"},
       {download::DOWNLOAD_INTERRUPT_REASON_CRASH, "Failed - Crash"},
   };
-  static_assert(kInterruptReasonCount == arraysize(kTestCases),
+  static_assert(kInterruptReasonCount == base::size(kTestCases),
                 "interrupt reason mismatch");
 
   SetupDownloadItemDefaults();
-  for (unsigned i = 0; i < arraysize(kTestCases); ++i) {
+  for (unsigned i = 0; i < base::size(kTestCases); ++i) {
     const TestCase& test_case = kTestCases[i];
     SetupInterruptedDownloadItem(test_case.reason);
     EXPECT_STREQ(test_case.expected_status,
@@ -258,7 +258,7 @@
       {download::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN, "foo.bar\nShutdown"},
       {download::DOWNLOAD_INTERRUPT_REASON_CRASH, "foo.bar\nCrash"},
   };
-  static_assert(kInterruptReasonCount == arraysize(kTestCases),
+  static_assert(kInterruptReasonCount == base::size(kTestCases),
                 "interrupt reason mismatch");
 
   // Large tooltip width. Should be large enough to accommodate the entire
@@ -273,7 +273,7 @@
       ui::ResourceBundle::GetSharedInstance().GetFontList(
           ui::ResourceBundle::BaseFont);
   SetupDownloadItemDefaults();
-  for (unsigned i = 0; i < arraysize(kTestCases); ++i) {
+  for (unsigned i = 0; i < base::size(kTestCases); ++i) {
     const TestCase& test_case = kTestCases[i];
     SetupInterruptedDownloadItem(test_case.reason);
 
@@ -348,7 +348,7 @@
 
   SetupDownloadItemDefaults();
 
-  for (unsigned i = 0; i < arraysize(kTestCases); i++) {
+  for (unsigned i = 0; i < base::size(kTestCases); i++) {
     const TestCase& test_case = kTestCases[i];
     Mock::VerifyAndClearExpectations(&item());
     Mock::VerifyAndClearExpectations(&model());
@@ -466,7 +466,7 @@
 
   SetupDownloadItemDefaults();
 
-  for (unsigned i = 0; i < arraysize(kTestCases); i++) {
+  for (unsigned i = 0; i < base::size(kTestCases); i++) {
     const TestCase& test_case = kTestCases[i];
     EXPECT_CALL(item(), GetOpenWhenComplete())
         .WillRepeatedly(Return(test_case.is_auto_open));
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc
index d4f13a8..3e41218 100644
--- a/chrome/browser/download/download_prefs.cc
+++ b/chrome/browser/download/download_prefs.cc
@@ -14,9 +14,9 @@
 #include "base/feature_list.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/no_destructor.h"
 #include "base/path_service.h"
+#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
@@ -129,7 +129,7 @@
       prefs::kSaveFileDefaultDirectory,
       prefs::kDownloadDefaultDirectory
   };
-  for (size_t i = 0; i < arraysize(path_pref); ++i) {
+  for (size_t i = 0; i < base::size(path_pref); ++i) {
     const base::FilePath current = prefs->GetFilePath(path_pref[i]);
     base::FilePath migrated;
     if (!current.empty() &&
diff --git a/chrome/browser/download/download_target_determiner_unittest.cc b/chrome/browser/download/download_target_determiner_unittest.cc
index 9f813a0a..d58f908 100644
--- a/chrome/browser/download/download_target_determiner_unittest.cc
+++ b/chrome/browser/download/download_target_determiner_unittest.cc
@@ -11,11 +11,11 @@
 #include "base/at_exit.h"
 #include "base/files/file_path.h"
 #include "base/location.h"
-#include "base/macros.h"
 #include "base/observer_list.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_path_override.h"
@@ -639,7 +639,7 @@
   ASSERT_EQ(DownloadFileType::ALLOW_ON_USER_GESTURE,
             safe_browsing::FileTypePolicies::GetInstance()->GetFileDangerLevel(
                 base::FilePath(FILE_PATH_LITERAL("foo.kindabad"))));
-  RunTestCasesWithActiveItem(kBasicTestCases, arraysize(kBasicTestCases));
+  RunTestCasesWithActiveItem(kBasicTestCases, base::size(kBasicTestCases));
 }
 
 TEST_F(DownloadTargetDeterminerTest, CancelSaveAs) {
@@ -656,7 +656,7 @@
       .WillByDefault(WithArg<3>(ScheduleCallback2(
           DownloadConfirmationResult::CANCELED, base::FilePath())));
   RunTestCasesWithActiveItem(kCancelSaveAsTestCases,
-                             arraysize(kCancelSaveAsTestCases));
+                             base::size(kCancelSaveAsTestCases));
 }
 
 // The SafeBrowsing check is performed early. Make sure that a download item
@@ -726,7 +726,7 @@
       .WillByDefault(WithArg<2>(
           ScheduleCallback(download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL)));
   RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
-                             arraysize(kSafeBrowsingTestCases));
+                             base::size(kSafeBrowsingTestCases));
 }
 
 // The SafeBrowsing check is performed early. Make sure that a download item
@@ -782,7 +782,7 @@
       .WillByDefault(WithArg<2>(ScheduleCallback(
           download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT)));
   RunTestCasesWithActiveItem(kSafeBrowsingTestCases,
-                             arraysize(kSafeBrowsingTestCases));
+                             base::size(kSafeBrowsingTestCases));
 }
 
 // Test whether the last saved directory is used for 'Save As' downloads.
@@ -844,7 +844,7 @@
                 RequestConfirmation(_, prompt_path,
                                     DownloadConfirmationReason::SAVE_AS, _));
     RunTestCasesWithActiveItem(kLastSavePathTestCasesPre,
-                               arraysize(kLastSavePathTestCasesPre));
+                               base::size(kLastSavePathTestCasesPre));
   }
 
   // Try with a non-empty last save path.
@@ -858,7 +858,7 @@
                 RequestConfirmation(_, prompt_path,
                                     DownloadConfirmationReason::SAVE_AS, _));
     RunTestCasesWithActiveItem(kLastSavePathTestCasesPost,
-                               arraysize(kLastSavePathTestCasesPost));
+                               base::size(kLastSavePathTestCasesPost));
   }
 
   // And again, but this time use a virtual directory.
@@ -875,7 +875,7 @@
         .WillOnce(WithArg<2>(ScheduleCallback(
             GetPathInDownloadDir(FILE_PATH_LITERAL("bar.txt")))));
     RunTestCasesWithActiveItem(kLastSavePathTestCasesVirtual,
-                               arraysize(kLastSavePathTestCasesVirtual));
+                               base::size(kLastSavePathTestCasesVirtual));
   }
 }
 
@@ -1090,7 +1090,7 @@
       _, GetPathInDownloadDir(FILE_PATH_LITERAL("virtual/foo.txt")), _))
       .WillOnce(WithArg<2>(ScheduleCallback(base::FilePath())));
   RunTestCasesWithActiveItem(kLocalPathFailedCases,
-                             arraysize(kLocalPathFailedCases));
+                             base::size(kLocalPathFailedCases));
 }
 
 // Downloads that have a danger level of ALLOW_ON_USER_GESTURE should be marked
@@ -1166,7 +1166,7 @@
   history_service->AddPage(url, time_of_visit, history::SOURCE_BROWSED);
 
   RunTestCasesWithActiveItem(kVisitedReferrerCases,
-                             arraysize(kVisitedReferrerCases));
+                             base::size(kVisitedReferrerCases));
 }
 
 TEST_F(DownloadTargetDeterminerTest, TransitionType) {
@@ -1465,7 +1465,7 @@
 
   SetPromptForDownload(true);
   RunTestCasesWithActiveItem(kPromptingTestCases,
-                             arraysize(kPromptingTestCases));
+                             base::size(kPromptingTestCases));
 }
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
@@ -1495,7 +1495,7 @@
   SetManagedDownloadPath(test_download_dir());
   ASSERT_TRUE(download_prefs()->IsDownloadPathManaged());
   RunTestCasesWithActiveItem(kManagedPathTestCases,
-                             arraysize(kManagedPathTestCases));
+                             base::size(kManagedPathTestCases));
 }
 
 // Test basic functionality supporting extensions that want to override download
@@ -1546,7 +1546,7 @@
   ON_CALL(*delegate(), NotifyExtensions(_, _, _))
       .WillByDefault(Invoke(&NotifyExtensionsOverridePath));
   RunTestCasesWithActiveItem(kNotifyExtensionsTestCases,
-                             arraysize(kNotifyExtensionsTestCases));
+                             base::size(kNotifyExtensionsTestCases));
 }
 
 // Test that filenames provided by extensions are passed into SafeBrowsing
@@ -1759,7 +1759,7 @@
   ASSERT_EQ(DownloadFileType::ALLOW_ON_USER_GESTURE,
             safe_browsing::FileTypePolicies::GetInstance()->GetFileDangerLevel(
                 base::FilePath(FILE_PATH_LITERAL("foo.kindabad"))));
-  for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kResumedTestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "Running test case " << i);
     const DownloadTestCase& test_case = kResumedTestCases[i];
     std::unique_ptr<download::MockDownloadItem> item =
@@ -1871,7 +1871,7 @@
   ASSERT_EQ(DownloadFileType::ALLOW_ON_USER_GESTURE,
             safe_browsing::FileTypePolicies::GetInstance()->GetFileDangerLevel(
                 base::FilePath(FILE_PATH_LITERAL("foo.kindabad"))));
-  for (size_t i = 0; i < arraysize(kResumedTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kResumedTestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "Running test case " << i);
     download_prefs()->SetSaveFilePath(test_download_dir());
     const DownloadTestCase& test_case = kResumedTestCases[i];
@@ -1981,7 +1981,7 @@
             safe_browsing::FileTypePolicies::GetInstance()->GetFileDangerLevel(
                 base::FilePath(FILE_PATH_LITERAL("foo.kindabad"))));
 
-  for (size_t i = 0; i < arraysize(kIntermediateNameTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kIntermediateNameTestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "Running test case " << i);
     const IntermediateNameTestCase& test_case = kIntermediateNameTestCases[i];
     std::unique_ptr<download::MockDownloadItem> item =
@@ -2088,7 +2088,7 @@
       .WillByDefault(WithArg<1>(
           ScheduleCallback("image/png")));
 
-  for (size_t i = 0; i < arraysize(kMIMETypeTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kMIMETypeTestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "Running test case " << i);
     const MIMETypeTestCase& test_case = kMIMETypeTestCases[i];
     std::unique_ptr<download::MockDownloadItem> item =
diff --git a/chrome/browser/download/notification/download_notification_interactive_uitest.cc b/chrome/browser/download/notification/download_notification_interactive_uitest.cc
index bdaa5510..f8ecc59 100644
--- a/chrome/browser/download/notification/download_notification_interactive_uitest.cc
+++ b/chrome/browser/download/notification/download_notification_interactive_uitest.cc
@@ -6,9 +6,9 @@
 #include <utility>
 
 #include "base/command_line.h"
-#include "base/macros.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
@@ -852,7 +852,7 @@
   // This is used for preparing all accounts in PRE_ test setup, and for testing
   // actual login behavior.
   void AddAllUsers() {
-    for (size_t i = 0; i < arraysize(kTestAccounts); ++i) {
+    for (size_t i = 0; i < base::size(kTestAccounts); ++i) {
       // The primary account was already set up in SetUpOnMainThread, so skip it
       // here.
       if (i == PRIMARY_ACCOUNT_INDEX)
diff --git a/chrome/browser/engagement/site_engagement_metrics.cc b/chrome/browser/engagement/site_engagement_metrics.cc
index ca8585a..9e343a1 100644
--- a/chrome/browser/engagement/site_engagement_metrics.cc
+++ b/chrome/browser/engagement/site_engagement_metrics.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/engagement/site_engagement_metrics.h"
 
 #include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/engagement/site_engagement_details.mojom.h"
 #include "chrome/browser/engagement/site_engagement_score.h"
@@ -84,7 +85,7 @@
     return;
 
   std::map<int, int> score_buckets;
-  for (size_t i = 0; i < arraysize(kEngagementBucketHistogramBuckets); ++i)
+  for (size_t i = 0; i < base::size(kEngagementBucketHistogramBuckets); ++i)
     score_buckets[kEngagementBucketHistogramBuckets[i]] = 0;
 
   const double threshold_0 = std::numeric_limits<double>::epsilon();;
@@ -149,7 +150,7 @@
 std::vector<std::string>
 SiteEngagementMetrics::GetEngagementBucketHistogramNames() {
   std::vector<std::string> histogram_names;
-  for (size_t i = 0; i < arraysize(kEngagementBucketHistogramBuckets); ++i) {
+  for (size_t i = 0; i < base::size(kEngagementBucketHistogramBuckets); ++i) {
     histogram_names.push_back(
         kEngagementBucketHistogramBase +
         base::IntToString(kEngagementBucketHistogramBuckets[i]));
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api.cc b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
index f88d63c..de28c14 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
@@ -443,7 +443,7 @@
   EventRouter::Get(browser_context_)->UnregisterObserver(this);
   registrar_.RemoveAll();
   if (observer_ && ui::IMEBridge::Get()) {
-    ui::IMEBridge::Get()->SetObserver(nullptr);
+    ui::IMEBridge::Get()->RemoveObserver(observer_.get());
   }
 }
 
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
index 7651920..35f3b6e 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
@@ -75,6 +75,7 @@
       return;
     ui::IMEBridge::Get()->SetCurrentEngineHandler(router->active_engine());
   }
+  void OnInputContextHandlerChanged() override {}
 };
 
 class ImeObserverNonChromeOS : public ui::ImeObserver {
@@ -150,7 +151,7 @@
   ui::IMEBridge::Initialize();
   if (!observer_) {
     observer_ = std::make_unique<ImeBridgeObserver>();
-    ui::IMEBridge::Get()->SetObserver(observer_.get());
+    ui::IMEBridge::Get()->AddObserver(observer_.get());
   }
 
   // Set the preference kPrefNeverActivatedSinceLoaded true to indicate
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index a18707b..b394162 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -2146,6 +2146,11 @@
     "expiry_milestone": 76
   },
   {
+    "name": "use_messages_google_com_domain",
+    "owners": [ "azeemarshad", "khorimoto" ],
+    "expiry_milestone": 76
+  },
+  {
     "name": "enable_android_messages_prod_endpoint",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index d8283eb..b2577bb8 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -53,6 +53,11 @@
 const char kAndroidMessagesIntegrationDescription[] =
     "Enables Chrome OS integration with Android messages.";
 
+const char kUseMessagesGoogleComDomainName[] = "Use messages.google.com domain";
+const char kUseMessagesGoogleComDomainDescription[] =
+    "Use the messages.google.com domain as part of the \"Messages\" "
+    "feature under \"Connected Devices\" settings.";
+
 const char kAndroidMessagesProdEndpointName[] =
     "Use Android Messages prod endpoint";
 const char kAndroidMessagesProdEndpointDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index b172b33..4dbe4ec 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -60,6 +60,9 @@
 extern const char kAndroidMessagesIntegrationName[];
 extern const char kAndroidMessagesIntegrationDescription[];
 
+extern const char kUseMessagesGoogleComDomainName[];
+extern const char kUseMessagesGoogleComDomainDescription[];
+
 extern const char kAndroidMessagesProdEndpointName[];
 extern const char kAndroidMessagesProdEndpointDescription[];
 
diff --git a/chrome/browser/profiling_host/memlog_browsertest.cc b/chrome/browser/profiling_host/memlog_browsertest.cc
index 9cd3aa8..fdafb0c8 100644
--- a/chrome/browser/profiling_host/memlog_browsertest.cc
+++ b/chrome/browser/profiling_host/memlog_browsertest.cc
@@ -54,6 +54,11 @@
         NOTREACHED();
       }
 
+      if (!GetParam().should_sample) {
+        command_line->AppendSwitchASCII(heap_profiling::kMemlogSamplingRate,
+                                        "1");
+      }
+
       if (GetParam().stack_mode == mojom::StackMode::PSEUDO) {
         command_line->AppendSwitchASCII(heap_profiling::kMemlogStackMode,
                                         heap_profiling::kMemlogStackModePseudo);
@@ -82,8 +87,9 @@
   LOG(INFO) << "Memlog mode: " << static_cast<int>(GetParam().mode);
   LOG(INFO) << "Memlog stack mode: " << static_cast<int>(GetParam().stack_mode);
   LOG(INFO) << "Started via command line flag: "
-            << static_cast<int>(
-                   GetParam().start_profiling_with_command_line_flag);
+            << GetParam().start_profiling_with_command_line_flag;
+  LOG(INFO) << "Should sample: " << GetParam().should_sample;
+  LOG(INFO) << "Sample everything: " << GetParam().sample_everything;
   TestDriver driver;
   TestDriver::Options options;
   options.mode = GetParam().mode;
diff --git a/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js b/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js
index 9b3efc3..78462fe 100644
--- a/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js
+++ b/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js
@@ -185,16 +185,36 @@
     }
 
     // Check various indicators that the node is actionable.
-    if (defaultActionVerb && defaultActionVerb !== 'none' &&
-        defaultActionVerb !== DefaultActionVerb.CLICK_ANCESTOR)
-      return true;
-
-    if (node.inputType)
-      return true;
-
     if (role === RoleType.BUTTON)
       return true;
 
+    if (node.inputType && node.inputType !== 'full-page')
+      return true;
+
+    if (defaultActionVerb &&
+        (defaultActionVerb === DefaultActionVerb.ACTIVATE ||
+         defaultActionVerb === DefaultActionVerb.CHECK ||
+         defaultActionVerb === DefaultActionVerb.OPEN ||
+         defaultActionVerb === DefaultActionVerb.PRESS ||
+         defaultActionVerb === DefaultActionVerb.SELECT ||
+         defaultActionVerb === DefaultActionVerb.UNCHECK)) {
+      return true;
+    }
+
+    if (role === RoleType.LIST_ITEM &&
+        defaultActionVerb === DefaultActionVerb.CLICK) {
+      return true;
+    }
+
+    // Focusable items should be surfaced as either groups or actionable.
+    // Current heuristic is to show as actionble any focusable item where no
+    // child is an interesting subtree.
+    if (state[StateType.FOCUSABLE]) {
+      return !(
+          node.children &&
+          node.children.some(SwitchAccessPredicate.isInterestingSubtree));
+    }
+
     return false;
   },
 
diff --git a/chrome/browser/resources/chromeos/switch_access/switch_access_predicate_test.extjs b/chrome/browser/resources/chromeos/switch_access/switch_access_predicate_test.extjs
index 0195bd78..c56e2b4 100644
--- a/chrome/browser/resources/chromeos/switch_access/switch_access_predicate_test.extjs
+++ b/chrome/browser/resources/chromeos/switch_access/switch_access_predicate_test.extjs
@@ -169,7 +169,8 @@
       '<a href="https://www.google.com/" aria-label="link1">link1</a>' +
       '<input type="text" aria-label="input1">input1</input>' +
       '<button>button3</button>' +
-      '<div aria-label="div1"><p>p1</p></div>'
+      '<div aria-label="listitem" role="listitem" onclick="2+2"></div>' +
+      '<div aria-label="div1"><p>p1</p></div>';
   this.runWithLoadedTree('data:text/html;charset=utf-8,' + treeString,
       function(desktop) {
         this.setDesktop(desktop);
@@ -201,6 +202,10 @@
         const button3 = this.getNodeByName('button3');
         assertTrue(SwitchAccessPredicate.isActionable(button3));
 
+        // List items with a default action of click are actionable.
+        const listitem = this.getNodeByName('listitem');
+        assertTrue(SwitchAccessPredicate.isActionable(listitem));
+
         // Divs are not generally actionable.
         const div1 = this.getNodeByName('div1');
         assertFalse(SwitchAccessPredicate.isActionable(div1));
@@ -212,6 +217,52 @@
   );
 });
 
+TEST_F('SwitchAccessPredicateTest', 'IsActionableFocusableElements', function()
+{
+  const treeString =
+      '<div aria-label="noChildren" tabindex="0"></div>' +
+      '<div aria-label="oneInterestingChild" tabindex="1">' +
+        '<div><div><div><button>button1</button></div></div></div>' +
+      '</div>' +
+      '<div aria-label="oneUninterestingChild" tabindex="2">' +
+        '<p>p1</p>' +
+      '</div>' +
+      '<div aria-label="interestingChildren" tabindex="3">' +
+        '<button>button2</button>' +
+        '<button>button3</button>' +
+      '</div>' +
+      '<div aria-label="uninterestingChildren" tabindex="4">' +
+        '<p>p2</p>' +
+        '<p>p3</p>' +
+      '</div>';
+  this.runWithLoadedTree('data:text/html;charset=utf-8,' + treeString,
+      function(desktop) {
+        this.setDesktop(desktop);
+
+        // Focusable element with no children should be actionable.
+        const noChildren = this.getNodeByName('noChildren');
+        assertTrue(SwitchAccessPredicate.isActionable(noChildren));
+
+        // Focusable elements with one or more interesting children should not
+        // be actionable.
+        const oneInterestingChild = this.getNodeByName('oneInterestingChild');
+        assertFalse(SwitchAccessPredicate.isActionable(oneInterestingChild));
+
+        const interestingChildren = this.getNodeByName('interestingChildren');
+        assertFalse(SwitchAccessPredicate.isActionable(interestingChildren));
+
+        // Focusable elements with children that are all uninteresting should
+        // be actionable.
+        const oneUninterestingChild =
+            this.getNodeByName('oneUninterestingChild');
+        assertTrue(SwitchAccessPredicate.isActionable(oneUninterestingChild));
+
+        const uninterestingChildren =
+            this.getNodeByName('uninterestingChildren');
+        assertTrue(SwitchAccessPredicate.isActionable(uninterestingChildren));
+      }
+  );
+});
 
 TEST_F('SwitchAccessPredicateTest', 'LeafPredicate', function() {
   this.runWithLoadedTree(testWebsite(),
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc
index a5e535c..b155f35 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc
@@ -14,6 +14,7 @@
 #include "base/files/file.h"
 #include "base/logging.h"
 #include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "base/time/time.h"
 #include "third_party/minizip/src/mz.h"
 #include "third_party/minizip/src/mz_strm.h"
@@ -526,5 +527,13 @@
   if (mz_zip_entry_is_open(zip_file_.get()) != MZ_OK)
     return true;
 
-  return mz_zip_entry_close(zip_file_.get()) == MZ_OK;
+  const int32_t error = mz_zip_entry_close(zip_file_.get());
+  // If the zip entry was not read in full, then closing the entry may cause a
+  // CRC error, because the whole file may not have been decompressed and
+  // checksummed.
+  const bool ok = (error == MZ_OK || error == MZ_CRC_ERROR);
+  if (!ok) {
+    set_error_message(base::StringPrintf("mz_zip_entry_close err = %d", error));
+  }
+  return ok;
 }
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc
index 534bb90a..4cf33cf5 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip_unittest.cc
@@ -224,6 +224,26 @@
   }
 }
 
+// Regression test for https://crbug.com/915960
+TEST_F(VolumeArchiveMinizipTest, ReadPartial) {
+  std::unique_ptr<TestVolumeReader> reader =
+      std::make_unique<TestVolumeReader>(GetTestZipPath("small_zip.zip"));
+  VolumeArchiveMinizip archive(std::move(reader));
+  ASSERT_TRUE(archive.Init(""));
+
+  for (auto it : kSmallZipFiles) {
+    EXPECT_TRUE(archive.SeekHeader(it.first));
+    if (it.second.is_directory)
+      continue;
+
+    // Read 1 byte.
+    const int32_t read_length = 1;
+    const char* buffer = nullptr;
+    int64_t read = archive.ReadData(0, read_length, &buffer);
+    EXPECT_EQ(read, read_length);
+  }
+}
+
 TEST_F(VolumeArchiveMinizipTest, Encrypted_PkCrypt) {
   std::unique_ptr<TestVolumeReader> reader =
       std::make_unique<TestVolumeReader>(GetTestZipPath("encrypted.zip"));
diff --git a/chrome/browser/resources/md_downloads/downloads.html b/chrome/browser/resources/md_downloads/downloads.html
index a308ca34..1a77afa 100644
--- a/chrome/browser/resources/md_downloads/downloads.html
+++ b/chrome/browser/resources/md_downloads/downloads.html
@@ -4,20 +4,26 @@
 <head>
   <meta charset="utf-8">
   <title>$i18n{title}</title>
-  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
   <style>
     html {
-      --downloads-card-margin: 24px;
-      --downloads-card-width: 680px;
+      --toolbar-height: 56px;
       background: rgb(248, 249, 250);
-
       /* Remove 300ms delay for 'click' event, when using touch interface. */
       touch-action: manipulation;
     }
 
-    .loading {
+    html[dark] {
+      background: rgb(32, 33, 36);  /* --google-grey-900 */
+    }
+
+    html[dark].loading {
+      border-top: 1px solid rgb(95, 99, 104);  /* --google-grey-refresh-700 */
+      margin-top: var(--toolbar-height);
+    }
+
+    html:not([dark]).loading {
       /* --google-blue-700 disguised. Replaced when downloads-toolbar loads. */
-      border-top: 56px solid rgb(51, 103, 214);
+      border-top: var(--toolbar-height) solid rgb(51, 103, 214);
     }
 
     html:not(.loading),
@@ -43,6 +49,8 @@
   <command id="undo-command" shortcut="Ctrl|z">
   <command id="find-command" shortcut="Ctrl|f">
 </if>
+  <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
+  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
   <link rel="import" href="chrome://resources/html/cr.html">
   <link rel="import" href="chrome://resources/html/polymer.html">
   <link rel="import" href="chrome://downloads/i18n_setup.html">
diff --git a/chrome/browser/resources/md_downloads/manager.html b/chrome/browser/resources/md_downloads/manager.html
index 42fdf30..6af77258 100644
--- a/chrome/browser/resources/md_downloads/manager.html
+++ b/chrome/browser/resources/md_downloads/manager.html
@@ -42,6 +42,12 @@
         opacity: var(--cr-container-shadow-max-opacity);
       }
 
+      downloads-item,
+      #downloadsList {
+        --downloads-card-margin: 24px;
+        --downloads-card-width: 680px;
+      }
+
       #downloadsList {
         min-width: calc(
           var(--downloads-card-width) + 2 * var(--downloads-card-margin));
diff --git a/chrome/browser/resources/omnibox/BUILD.gn b/chrome/browser/resources/omnibox/BUILD.gn
index a423f243..155099d 100644
--- a/chrome/browser/resources/omnibox/BUILD.gn
+++ b/chrome/browser/resources/omnibox/BUILD.gn
@@ -14,7 +14,7 @@
   deps = [
     "//ui/webui/resources/js:util",
     ":omnibox_element",
-    ":omnibox_inputs",
+    ":omnibox_input",
     ":omnibox_output",
   ]
   extra_deps = [ "//chrome/browser/ui/webui/omnibox:mojo_bindings_js" ]
@@ -28,7 +28,7 @@
 js_library("omnibox_element") {
 }
 
-js_library("omnibox_inputs") {
+js_library("omnibox_input") {
 }
 
 js_library("omnibox_output") {
diff --git a/chrome/browser/resources/omnibox/omnibox.css b/chrome/browser/resources/omnibox/omnibox.css
index b72f3f5..a7eedde 100644
--- a/chrome/browser/resources/omnibox/omnibox.css
+++ b/chrome/browser/resources/omnibox/omnibox.css
@@ -207,7 +207,7 @@
   border: 1px solid;
 }
 
-omnibox-inputs {
+omnibox-input {
   --action-color: rgb(66, 133, 244);
   --hover-color: #f2f2f2;
   --input-alignment-indentation: 9px;
diff --git a/chrome/browser/resources/omnibox/omnibox.html b/chrome/browser/resources/omnibox/omnibox.html
index 67695ec..c39d5db 100644
--- a/chrome/browser/resources/omnibox/omnibox.html
+++ b/chrome/browser/resources/omnibox/omnibox.html
@@ -10,13 +10,13 @@
   <script src="chrome://resources/js/util.js"></script>
   <script src="chrome/browser/ui/webui/omnibox/omnibox.mojom-lite.js"></script>
   <script src="omnibox_element.js"></script>
-  <script src="omnibox_inputs.js"></script>
+  <script src="omnibox_input.js"></script>
   <script src="omnibox_output.js"></script>
   <script src="omnibox.js"></script>
 </head>
 
 <body>
-  <template id="omnibox-inputs-template">
+  <template id="omnibox-input-template">
     <link rel="stylesheet" href="omnibox.css">
 
     <div class="top text">
@@ -150,7 +150,7 @@
     <p>host = <span class="host"></span>, has isTypedHost = <span class="is-typed-host"></span></p>
   </template>
 
-  <omnibox-inputs id="omnibox-inputs"></omnibox-inputs>
+  <omnibox-input id="omnibox-input"></omnibox-input>
   <omnibox-output id="omnibox-output"></omnibox-output>
 </body>
 </html>
diff --git a/chrome/browser/resources/omnibox/omnibox.js b/chrome/browser/resources/omnibox/omnibox.js
index 817f7d8..b1b18ea 100644
--- a/chrome/browser/resources/omnibox/omnibox.js
+++ b/chrome/browser/resources/omnibox/omnibox.js
@@ -44,17 +44,17 @@
 
   /** @type {!BrowserProxy} */
   const browserProxy = new BrowserProxy();
-  /** @type {!OmniboxInputs} */
-  let omniboxInputs;
+  /** @type {!OmniboxInput} */
+  let omniboxInput;
   /** @type {!omnibox_output.OmniboxOutput} */
   let omniboxOutput;
 
   document.addEventListener('DOMContentLoaded', () => {
-    omniboxInputs = /** @type {!OmniboxInputs} */ ($('omnibox-inputs'));
+    omniboxInput = /** @type {!OmniboxInput} */ ($('omnibox-input'));
     omniboxOutput =
         /** @type {!omnibox_output.OmniboxOutput} */ ($('omnibox-output'));
 
-    omniboxInputs.addEventListener('query-inputs-changed', event => {
+    omniboxInput.addEventListener('query-inputs-changed', event => {
       omniboxOutput.clearAutocompleteResponses();
       omniboxOutput.updateQueryInputs(event.detail);
       browserProxy.makeRequest(
@@ -67,13 +67,13 @@
           event.detail.currentUrl,
           event.detail.pageClassification);
     });
-    omniboxInputs.addEventListener(
+    omniboxInput.addEventListener(
         'display-inputs-changed',
         event => omniboxOutput.updateDisplayInputs(event.detail));
-    omniboxInputs.addEventListener(
+    omniboxInput.addEventListener(
         'filter-input-changed',
         event => omniboxOutput.updateFilterText(event.detail));
-    omniboxInputs.addEventListener('copy-request', event => {
+    omniboxInput.addEventListener('copy-request', event => {
       event.detail === 'text' ? omniboxOutput.copyDelegate.copyTextOutput() :
                                 omniboxOutput.copyDelegate.copyJsonOutput();
     });
diff --git a/chrome/browser/resources/omnibox/omnibox_inputs.js b/chrome/browser/resources/omnibox/omnibox_input.js
similarity index 94%
rename from chrome/browser/resources/omnibox/omnibox_inputs.js
rename to chrome/browser/resources/omnibox/omnibox_input.js
index 95eebd0..a877ffa 100644
--- a/chrome/browser/resources/omnibox/omnibox_inputs.js
+++ b/chrome/browser/resources/omnibox/omnibox_input.js
@@ -23,11 +23,11 @@
  */
 let DisplayInputs;
 
-class OmniboxInputs extends OmniboxElement {
+class OmniboxInput extends OmniboxElement {
   constructor() {
-    super('omnibox-inputs-template');
+    super('omnibox-input-template');
 
-    const displayInputs = OmniboxInputs.defaultDisplayInputs;
+    const displayInputs = OmniboxInput.defaultDisplayInputs;
     this.$$('show-incomplete-results').checked =
         displayInputs.showIncompleteResults;
     this.$$('show-details').checked = displayInputs.showDetails;
@@ -134,4 +134,4 @@
   }
 }
 
-customElements.define('omnibox-inputs', OmniboxInputs);
+customElements.define('omnibox-input', OmniboxInput);
diff --git a/chrome/browser/resources/omnibox/omnibox_output.js b/chrome/browser/resources/omnibox/omnibox_output.js
index 15bb3ed9..c599c85 100644
--- a/chrome/browser/resources/omnibox/omnibox_output.js
+++ b/chrome/browser/resources/omnibox/omnibox_output.js
@@ -23,7 +23,7 @@
       /** @private {!QueryInputs} */
       this.queryInputs_ = /** @type {!QueryInputs} */ ({});
       /** @private {!DisplayInputs} */
-      this.displayInputs_ = OmniboxInputs.defaultDisplayInputs;
+      this.displayInputs_ = OmniboxInput.defaultDisplayInputs;
       /** @private {string} */
       this.filterText_ = '';
     }
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-indicator/BUILD.gn b/chrome/browser/resources/pdf/elements/viewer-page-indicator/BUILD.gn
index 8da20c8..aa1906c 100644
--- a/chrome/browser/resources/pdf/elements/viewer-page-indicator/BUILD.gn
+++ b/chrome/browser/resources/pdf/elements/viewer-page-indicator/BUILD.gn
@@ -11,4 +11,8 @@
 }
 
 js_library("viewer-page-indicator") {
+  deps = [
+    "//ui/webui/resources/js:assert",
+    "//ui/webui/resources/js:util",
+  ]
 }
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.html b/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.html
index 19f05ee2..e815e1cb 100644
--- a/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.html
+++ b/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.html
@@ -1,20 +1,27 @@
+<link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/html/util.html">
 
 <dom-module id="viewer-page-indicator">
   <template>
     <style>
       :host {
+        display: flex;
         pointer-events: none;
         position: fixed;
         right: 0;
         transition: opacity 400ms ease-in-out;
       }
 
+      :host-context([dir=rtl]) {
+        left: 0;
+        right: auto;
+      }
+
       #text {
         background-color: rgba(0, 0, 0, 0.5);
         border-radius: 5px;
         color: white;
-        float: left;
         font-family: sans-serif;
         font-size: 12px;
         font-weight: bold;
@@ -24,19 +31,17 @@
         width: 62px;
       }
 
-      #triangle-right {
+      #triangle-end {
         border-bottom: 6px solid transparent;
-        border-left: 8px solid rgba(0, 0, 0, 0.5);
+        border-inline-start: 8px solid rgba(0, 0, 0, 0.5);
         border-top: 6px solid transparent;
-        display: inline;
-        float: left;
         height: 0;
         margin-top: 18px;
         width: 0;
       }
     </style>
     <div id="text">{{label}}</div>
-    <div id="triangle-right"></div>
+    <div id="triangle-end"></div>
   </template>
   <script src="viewer-page-indicator.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.js b/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.js
index bbf6e45a..4f0fdff 100644
--- a/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.js
+++ b/chrome/browser/resources/pdf/elements/viewer-page-indicator/viewer-page-indicator.js
@@ -37,12 +37,16 @@
         percent * (document.documentElement.clientHeight - this.offsetHeight) +
         'px';
     // <if expr="is_macosx">
-    // On the Mac, if overlay scrollbars are enabled, prevent them from
-    // overlapping the triangle.
+    // If overlay scrollbars are enabled, prevent them from overlapping the
+    // triangle. TODO(dbeam): various platforms can enable overlay scrolling,
+    // not just Mac. The scrollbars seem to have different widths/appearances on
+    // those platforms, though.
+    assert(document.documentElement.dir);
+    const endEdge = isRTL() ? 'left' : 'right';
     if (window.innerWidth == document.scrollingElement.scrollWidth)
-      this.style.right = '16px';
+      this.style[endEdge] = '16px';
     else
-      this.style.right = '0px';
+      this.style[endEdge] = '0px';
     // </if>
     this.style.opacity = 1;
     clearTimeout(this.timerId);
diff --git a/chrome/browser/resources/settings/controls/settings_slider.js b/chrome/browser/resources/settings/controls/settings_slider.js
index d34831e..4fe96ae4 100644
--- a/chrome/browser/resources/settings/controls/settings_slider.js
+++ b/chrome/browser/resources/settings/controls/settings_slider.js
@@ -4,7 +4,7 @@
 
 /**
  * @fileoverview
- * settings-slider wraps a paper-slider. It maps the slider's values from a
+ * settings-slider wraps a cr-slider. It maps the slider's values from a
  * linear UI range to a range of real values.  When |value| does not map exactly
  * to a tick mark, it interpolates to the nearest tick.
  */
@@ -27,9 +27,9 @@
     },
 
     /**
-     * A scale factor used to support fractional pref values since paper-slider
-     * only supports integers. This is not compatible with |ticks|,
-     * i.e. if |scale| is not 1 then |ticks| must be empty.
+     * A scale factor used to support fractional pref values. This is not
+     * compatible with |ticks|, i.e. if |scale| is not 1 then |ticks| must be
+     * empty.
      */
     scale: {
       type: Number,
diff --git a/chrome/browser/resources/settings/people_page/signout_dialog.html b/chrome/browser/resources/settings/people_page/signout_dialog.html
index 7dce40a..af7c0a5 100644
--- a/chrome/browser/resources/settings/people_page/signout_dialog.html
+++ b/chrome/browser/resources/settings/people_page/signout_dialog.html
@@ -28,6 +28,13 @@
         /* Override the cr-dialog footer padding. */
         padding: 16px 0;
       }
+
+      cr-dialog {
+        --cr-dialog-body: {
+          /* Add space for the link focus ring. See https://crbug.com/916939. */
+          padding-bottom: 2px;
+        };
+      }
     </style>
 
     <cr-dialog id="dialog" ignore-enter-key close-text="$i18n{close}">
diff --git a/chrome/browser/resources/settings/search_settings.js b/chrome/browser/resources/settings/search_settings.js
index 3a34994..cf62b20 100644
--- a/chrome/browser/resources/settings/search_settings.js
+++ b/chrome/browser/resources/settings/search_settings.js
@@ -33,6 +33,7 @@
     'CONTENT',
     'CR-ACTION-MENU',
     'CR-DIALOG',
+    'CR-SLIDER',
     'DIALOG',
     'IMG',
     'IRON-ICON',
@@ -40,7 +41,6 @@
     'PAPER-ICON-BUTTON',
     'PAPER-ICON-BUTTON-LIGHT',
     'PAPER-RIPPLE',
-    'PAPER-SLIDER',
     'PAPER-SPINNER-LITE',
     'SLOT',
     'STYLE',
diff --git a/chrome/browser/ui/ash/tablet_mode_client_test_util.cc b/chrome/browser/ui/ash/tablet_mode_client_test_util.cc
index acbae70..6f48cd0 100644
--- a/chrome/browser/ui/ash/tablet_mode_client_test_util.cc
+++ b/chrome/browser/ui/ash/tablet_mode_client_test_util.cc
@@ -10,6 +10,7 @@
 #include "content/public/common/service_manager_connection.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/test/mus/change_completion_waiter.h"
 
 namespace test {
 
@@ -57,6 +58,7 @@
 
   TestTabletModeClientObserver observer(enabled);
   observer.run_loop()->Run();
+  aura::test::WaitForAllChangesToComplete();
 
   ASSERT_EQ(enabled, TabletModeClient::Get()->tablet_mode_enabled());
 }
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
index 7e4d8209..6166bb2d 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
@@ -145,7 +145,10 @@
 class MockAppShimHost : public AppShimHost {
  public:
   MockAppShimHost()
-      : AppShimHost("app", base::FilePath("Profile")), weak_factory_(this) {}
+      : AppShimHost("app",
+                    base::FilePath("Profile"),
+                    false /* uses_remote_views */),
+        weak_factory_(this) {}
   ~MockAppShimHost() override {}
 
   MOCK_METHOD0(OnAppUnhideWithoutActivation, void());
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller.cc b/chrome/browser/ui/extensions/extension_action_view_controller.cc
index 3071796d..36bfa6b9 100644
--- a/chrome/browser/ui/extensions/extension_action_view_controller.cc
+++ b/chrome/browser/ui/extensions/extension_action_view_controller.cc
@@ -65,7 +65,7 @@
 }
 
 ExtensionActionViewController::~ExtensionActionViewController() {
-  DCHECK(!is_showing_popup());
+  DCHECK(!IsShowingPopup());
 }
 
 std::string ExtensionActionViewController::GetId() const {
@@ -177,8 +177,12 @@
   return tab_id.is_valid() ? extension_action_->HasPopup(tab_id.id()) : false;
 }
 
+bool ExtensionActionViewController::IsShowingPopup() const {
+  return popup_host_ != nullptr;
+}
+
 void ExtensionActionViewController::HidePopup() {
-  if (is_showing_popup()) {
+  if (IsShowingPopup()) {
     popup_host_->Close();
     // We need to do these actions synchronously (instead of closing and then
     // performing the rest of the cleanup in OnExtensionHostDestroyed()) because
@@ -214,8 +218,7 @@
 
 void ExtensionActionViewController::OnContextMenuClosed() {
   if (toolbar_actions_bar_ &&
-      toolbar_actions_bar_->popped_out_action() == this &&
-      !is_showing_popup()) {
+      toolbar_actions_bar_->popped_out_action() == this && !IsShowingPopup()) {
     toolbar_actions_bar_->UndoPopOut();
   }
 }
@@ -374,7 +377,7 @@
   if (!ExtensionIsValid())
     return false;
 
-  bool already_showing = is_showing_popup();
+  bool already_showing = IsShowingPopup();
 
   // Always hide the current popup, even if it's not owned by this extension.
   // Only one popup should be visible at a time.
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller.h b/chrome/browser/ui/extensions/extension_action_view_controller.h
index 9c8abfe..6c57212a 100644
--- a/chrome/browser/ui/extensions/extension_action_view_controller.h
+++ b/chrome/browser/ui/extensions/extension_action_view_controller.h
@@ -60,6 +60,7 @@
   bool IsEnabled(content::WebContents* web_contents) const override;
   bool WantsToRun(content::WebContents* web_contents) const override;
   bool HasPopup(content::WebContents* web_contents) const override;
+  bool IsShowingPopup() const override;
   void HidePopup() override;
   gfx::NativeView GetPopupNativeView() override;
   ui::MenuModel* GetContextMenu() override;
@@ -84,7 +85,6 @@
   ExtensionAction* extension_action() { return extension_action_; }
   const ExtensionAction* extension_action() const { return extension_action_; }
   ToolbarActionViewDelegate* view_delegate() { return view_delegate_; }
-  bool is_showing_popup() const { return popup_host_ != nullptr; }
 
   std::unique_ptr<IconWithBadgeImageSource> GetIconImageSourceForTesting(
       content::WebContents* web_contents,
diff --git a/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.h b/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.h
index e31b3754..4419037 100644
--- a/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.h
+++ b/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.h
@@ -24,6 +24,8 @@
 
   static MediaRouterDialogControllerImplBase* GetOrCreateForWebContents(
       content::WebContents* web_contents);
+  static MediaRouterDialogControllerImplBase* FromWebContents(
+      content::WebContents* web_contents);
 
   // Sets the action to notify when a dialog gets shown or hidden.
   void SetMediaRouterAction(const base::WeakPtr<MediaRouterAction>& action);
diff --git a/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc b/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc
index a57bd31..877a93b 100644
--- a/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc
+++ b/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc
@@ -373,14 +373,14 @@
 
   // Neither should yet be showing a popup.
   EXPECT_FALSE(browser_actions_bar()->HasPopup());
-  EXPECT_FALSE(first_controller->is_showing_popup());
-  EXPECT_FALSE(second_controller->is_showing_popup());
+  EXPECT_FALSE(first_controller->IsShowingPopup());
+  EXPECT_FALSE(second_controller->IsShowingPopup());
 
   // Click on the first extension's browser action. This should open a popup.
   browser_actions_bar()->Press(0);
   EXPECT_TRUE(browser_actions_bar()->HasPopup());
-  EXPECT_TRUE(first_controller->is_showing_popup());
-  EXPECT_FALSE(second_controller->is_showing_popup());
+  EXPECT_TRUE(first_controller->IsShowingPopup());
+  EXPECT_FALSE(second_controller->IsShowingPopup());
 
   {
     content::WindowedNotificationObserver observer(
@@ -394,8 +394,8 @@
     // notification.
     observer.Wait();
     EXPECT_TRUE(browser_actions_bar()->HasPopup());
-    EXPECT_FALSE(first_controller->is_showing_popup());
-    EXPECT_TRUE(second_controller->is_showing_popup());
+    EXPECT_FALSE(first_controller->IsShowingPopup());
+    EXPECT_TRUE(second_controller->IsShowingPopup());
   }
 
   {
@@ -407,8 +407,8 @@
     browser_actions_bar()->Press(1);
     observer.Wait();
     EXPECT_FALSE(browser_actions_bar()->HasPopup());
-    EXPECT_FALSE(first_controller->is_showing_popup());
-    EXPECT_FALSE(second_controller->is_showing_popup());
+    EXPECT_FALSE(first_controller->IsShowingPopup());
+    EXPECT_FALSE(second_controller->IsShowingPopup());
   }
 }
 
@@ -456,16 +456,16 @@
 
   // Neither should yet be showing a popup.
   EXPECT_FALSE(browser_actions_bar()->HasPopup());
-  EXPECT_FALSE(second_controller_main->is_showing_popup());
-  EXPECT_FALSE(second_controller_overflow->is_showing_popup());
+  EXPECT_FALSE(second_controller_main->IsShowingPopup());
+  EXPECT_FALSE(second_controller_overflow->IsShowingPopup());
 
   // Click on the first extension's browser action. This should open a popup.
   overflow_bar->Press(1);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(browser_actions_bar()->HasPopup());
   EXPECT_FALSE(overflow_bar->HasPopup());
-  EXPECT_TRUE(second_controller_main->is_showing_popup());
-  EXPECT_FALSE(second_controller_overflow->is_showing_popup());
+  EXPECT_TRUE(second_controller_main->IsShowingPopup());
+  EXPECT_FALSE(second_controller_overflow->IsShowingPopup());
 
   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
   EXPECT_EQ(1u, main_tab->GetIconCount());
@@ -486,8 +486,8 @@
 
   EXPECT_FALSE(browser_actions_bar()->HasPopup());
   EXPECT_FALSE(overflow_bar->HasPopup());
-  EXPECT_FALSE(second_controller_main->is_showing_popup());
-  EXPECT_FALSE(second_controller_overflow->is_showing_popup());
+  EXPECT_FALSE(second_controller_main->IsShowingPopup());
+  EXPECT_FALSE(second_controller_overflow->IsShowingPopup());
   EXPECT_EQ(0, browser_actions_bar()->VisibleBrowserActions());
   EXPECT_EQ(2, overflow_bar->VisibleBrowserActions());
   base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/ui/toolbar/media_router_action.cc b/chrome/browser/ui/toolbar/media_router_action.cc
index de34c95e..062a982 100644
--- a/chrome/browser/ui/toolbar/media_router_action.cc
+++ b/chrome/browser/ui/toolbar/media_router_action.cc
@@ -128,6 +128,11 @@
   return true;
 }
 
+bool MediaRouterAction::IsShowingPopup() const {
+  auto* controller = GetMediaRouterDialogController();
+  return controller && controller->IsShowingMediaRouterDialog();
+}
+
 void MediaRouterAction::HidePopup() {
   GetMediaRouterDialogController()->HideMediaRouterDialog();
 }
@@ -154,10 +159,9 @@
 }
 
 void MediaRouterAction::OnContextMenuClosed() {
-  if (toolbar_actions_bar_->popped_out_action() == this &&
-      !GetMediaRouterDialogController()->IsShowingMediaRouterDialog()) {
+  if (toolbar_actions_bar_->popped_out_action() == this && !IsShowingPopup())
     toolbar_actions_bar_->UndoPopOut();
-  }
+
   // We must destroy the context menu asynchronously to prevent it from being
   // destroyed before the command execution.
   // TODO(takumif): Using task sequence to order operations is fragile. Consider
@@ -171,7 +175,7 @@
 bool MediaRouterAction::ExecuteAction(bool by_user) {
   base::RecordAction(base::UserMetricsAction("MediaRouter_Icon_Click"));
 
-  if (GetMediaRouterDialogController()->IsShowingMediaRouterDialog()) {
+  if (IsShowingPopup()) {
     HidePopup();
     return false;
   }
@@ -270,7 +274,7 @@
   if (!delegate_->GetCurrentWebContents())
     return;
 
-  if (GetMediaRouterDialogController()->IsShowingMediaRouterDialog())
+  if (IsShowingPopup())
     OnDialogShown();
   else
     OnDialogHidden();
@@ -285,6 +289,14 @@
       web_contents);
 }
 
+const MediaRouterDialogControllerImplBase*
+MediaRouterAction::GetMediaRouterDialogController() const {
+  DCHECK(delegate_);
+  content::WebContents* web_contents = delegate_->GetCurrentWebContents();
+  DCHECK(web_contents);
+  return MediaRouterDialogControllerImplBase::FromWebContents(web_contents);
+}
+
 void MediaRouterAction::MaybeUpdateIcon() {
   const gfx::VectorIcon& new_icon = GetCurrentIcon();
 
diff --git a/chrome/browser/ui/toolbar/media_router_action.h b/chrome/browser/ui/toolbar/media_router_action.h
index 3e288a5f..481f5fc 100644
--- a/chrome/browser/ui/toolbar/media_router_action.h
+++ b/chrome/browser/ui/toolbar/media_router_action.h
@@ -56,6 +56,7 @@
   bool IsEnabled(content::WebContents* web_contents) const override;
   bool WantsToRun(content::WebContents* web_contents) const override;
   bool HasPopup(content::WebContents* web_contents) const override;
+  bool IsShowingPopup() const override;
   void HidePopup() override;
   gfx::NativeView GetPopupNativeView() override;
   ui::MenuModel* GetContextMenu() override;
@@ -107,6 +108,8 @@
   // Marked virtual for tests.
   virtual media_router::MediaRouterDialogControllerImplBase*
   GetMediaRouterDialogController();
+  virtual const media_router::MediaRouterDialogControllerImplBase*
+  GetMediaRouterDialogController() const;
 
   // Checks if the current icon of MediaRouterAction has changed. If so,
   // updates |current_icon_|.
diff --git a/chrome/browser/ui/toolbar/media_router_action_unittest.cc b/chrome/browser/ui/toolbar/media_router_action_unittest.cc
index 9862b41..2d543a10 100644
--- a/chrome/browser/ui/toolbar/media_router_action_unittest.cc
+++ b/chrome/browser/ui/toolbar/media_router_action_unittest.cc
@@ -73,8 +73,12 @@
 
  private:
   // MediaRouterAction:
-  MediaRouterDialogControllerWebUIImpl* GetMediaRouterDialogController()
-      override {
+  media_router::MediaRouterDialogControllerImplBase*
+  GetMediaRouterDialogController() override {
+    return controller_;
+  }
+  const media_router::MediaRouterDialogControllerImplBase*
+  GetMediaRouterDialogController() const override {
     return controller_;
   }
 
diff --git a/chrome/browser/ui/toolbar/test_toolbar_action_view_controller.cc b/chrome/browser/ui/toolbar/test_toolbar_action_view_controller.cc
index 29e4ed2..c0f0d0e 100644
--- a/chrome/browser/ui/toolbar/test_toolbar_action_view_controller.cc
+++ b/chrome/browser/ui/toolbar/test_toolbar_action_view_controller.cc
@@ -64,7 +64,12 @@
   return true;
 }
 
+bool TestToolbarActionViewController::IsShowingPopup() const {
+  return popup_showing_;
+}
+
 void TestToolbarActionViewController::HidePopup() {
+  popup_showing_ = false;
   delegate_->OnPopupClosed();
 }
 
@@ -90,6 +95,7 @@
 }
 
 void TestToolbarActionViewController::ShowPopup(bool by_user) {
+  popup_showing_ = true;
   delegate_->OnPopupShown(by_user);
 }
 
diff --git a/chrome/browser/ui/toolbar/test_toolbar_action_view_controller.h b/chrome/browser/ui/toolbar/test_toolbar_action_view_controller.h
index bac6dcb..db411eb 100644
--- a/chrome/browser/ui/toolbar/test_toolbar_action_view_controller.h
+++ b/chrome/browser/ui/toolbar/test_toolbar_action_view_controller.h
@@ -28,6 +28,7 @@
   bool IsEnabled(content::WebContents* web_contents) const override;
   bool WantsToRun(content::WebContents* web_contents) const override;
   bool HasPopup(content::WebContents* web_contents) const override;
+  bool IsShowingPopup() const override;
   void HidePopup() override;
   gfx::NativeView GetPopupNativeView() override;
   ui::MenuModel* GetContextMenu() override;
@@ -73,6 +74,9 @@
   // The number of times the action would have been executed.
   int execute_action_count_ = 0;
 
+  // True if a popup is (supposedly) currently showing.
+  bool popup_showing_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(TestToolbarActionViewController);
 };
 
diff --git a/chrome/browser/ui/toolbar/toolbar_action_view_controller.h b/chrome/browser/ui/toolbar/toolbar_action_view_controller.h
index ddbb797..dbc5cb8 100644
--- a/chrome/browser/ui/toolbar/toolbar_action_view_controller.h
+++ b/chrome/browser/ui/toolbar/toolbar_action_view_controller.h
@@ -64,6 +64,9 @@
   // Returns true if the action has a popup for the given |web_contents|.
   virtual bool HasPopup(content::WebContents* web_contents) const = 0;
 
+  // Returns whether there is currently a popup visible.
+  virtual bool IsShowingPopup() const = 0;
+
   // Hides the current popup, if one is visible.
   virtual void HidePopup() = 0;
 
diff --git a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
index 168bb5d5..1c7fa31 100644
--- a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
+++ b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
@@ -29,6 +29,15 @@
       web_contents);
 }
 
+// static
+MediaRouterDialogControllerImplBase*
+MediaRouterDialogControllerImplBase::FromWebContents(
+    content::WebContents* web_contents) {
+  if (ShouldUseViewsDialog())
+    return MediaRouterDialogControllerViews::FromWebContents(web_contents);
+  return MediaRouterDialogControllerWebUIImpl::FromWebContents(web_contents);
+}
+
 MediaRouterDialogControllerViews::~MediaRouterDialogControllerViews() {
   Reset();
   if (dialog_widget_) {
diff --git a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h
index 004353a..312404c 100644
--- a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h
+++ b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h
@@ -25,6 +25,8 @@
 
   static MediaRouterDialogControllerViews* GetOrCreateForWebContents(
       content::WebContents* web_contents);
+  using content::WebContentsUserData<
+      MediaRouterDialogControllerViews>::FromWebContents;
 
   // MediaRouterDialogController:
   void CreateMediaRouterDialog() override;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
index 83712ca..f7597a7 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -210,7 +210,7 @@
 }
 
 bool ToolbarActionView::OnMousePressed(const ui::MouseEvent& event) {
-  if (event.IsOnlyLeftMouseButton() && !pressed_lock_) {
+  if (event.IsOnlyLeftMouseButton() && !view_controller()->IsShowingPopup()) {
     // This event is likely to trigger the MenuButton action.
     // TODO(bruthig): The ACTION_PENDING triggering logic should be in
     // MenuButton::OnPressed() however there is a bug with the pressed state
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
index 5c4d6c7..4434490c 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
@@ -319,7 +319,7 @@
       static_cast<ExtensionActionViewController*>(
           toolbar_action_view->view_controller());
   EXPECT_EQ(view_controller, toolbar_actions_bar->popup_owner());
-  EXPECT_TRUE(view_controller->is_showing_popup());
+  EXPECT_TRUE(view_controller->IsShowingPopup());
 
   {
     // Click down on the action button; this should close the popup.
@@ -336,13 +336,13 @@
     observer.Wait();  // Wait for the popup to fully close.
   }
 
-  EXPECT_FALSE(view_controller->is_showing_popup());
+  EXPECT_FALSE(view_controller->IsShowingPopup());
   EXPECT_EQ(nullptr, toolbar_actions_bar->popup_owner());
 
   // Releasing the mouse shouldn't result in the popup being shown again.
   EXPECT_TRUE(
       ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, ui_controls::UP));
-  EXPECT_FALSE(view_controller->is_showing_popup());
+  EXPECT_FALSE(view_controller->IsShowingPopup());
   EXPECT_EQ(nullptr, toolbar_actions_bar->popup_owner());
 }
 
diff --git a/chrome/browser/ui/webui/media_router/media_router_dialog_controller_webui_impl.cc b/chrome/browser/ui/webui/media_router/media_router_dialog_controller_webui_impl.cc
index d431e44e..d1e53bd6 100644
--- a/chrome/browser/ui/webui/media_router/media_router_dialog_controller_webui_impl.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_dialog_controller_webui_impl.cc
@@ -114,6 +114,13 @@
   return MediaRouterDialogControllerWebUIImpl::GetOrCreateForWebContents(
       web_contents);
 }
+
+// static
+MediaRouterDialogControllerImplBase*
+MediaRouterDialogControllerImplBase::FromWebContents(
+    content::WebContents* web_contents) {
+  return MediaRouterDialogControllerWebUIImpl::FromWebContents(web_contents);
+}
 #endif  // !defined(TOOLKIT_VIEWS)
 
 class MediaRouterDialogControllerWebUIImpl::DialogWebContentsObserver
diff --git a/chrome/browser/ui/webui/media_router/media_router_dialog_controller_webui_impl.h b/chrome/browser/ui/webui/media_router/media_router_dialog_controller_webui_impl.h
index da01cb47..da50fd9 100644
--- a/chrome/browser/ui/webui/media_router/media_router_dialog_controller_webui_impl.h
+++ b/chrome/browser/ui/webui/media_router/media_router_dialog_controller_webui_impl.h
@@ -26,6 +26,8 @@
  public:
   static MediaRouterDialogControllerWebUIImpl* GetOrCreateForWebContents(
       content::WebContents* web_contents);
+  using content::WebContentsUserData<
+      MediaRouterDialogControllerWebUIImpl>::FromWebContents;
 
   ~MediaRouterDialogControllerWebUIImpl() override;
 
diff --git a/chrome/browser/ui/webui/omnibox/omnibox_ui.cc b/chrome/browser/ui/webui/omnibox/omnibox_ui.cc
index fa6ed72c..d29e8982 100644
--- a/chrome/browser/ui/webui/omnibox/omnibox_ui.cc
+++ b/chrome/browser/ui/webui/omnibox/omnibox_ui.cc
@@ -22,7 +22,7 @@
                           IDR_OMNIBOX_COLUMN_WIDTHS_CSS);
   source->AddResourcePath("omnibox.css", IDR_OMNIBOX_CSS);
   source->AddResourcePath("omnibox_element.js", IDR_OMNIBOX_ELEMENT_JS);
-  source->AddResourcePath("omnibox_inputs.js", IDR_OMNIBOX_INPUTS_JS);
+  source->AddResourcePath("omnibox_input.js", IDR_OMNIBOX_INPUT_JS);
   source->AddResourcePath("omnibox_output.js", IDR_OMNIBOX_OUTPUT_JS);
   source->AddResourcePath("omnibox.js", IDR_OMNIBOX_JS);
   source->AddResourcePath(
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn
index ad4f65f..ca41231 100644
--- a/chrome/browser/vr/BUILD.gn
+++ b/chrome/browser/vr/BUILD.gn
@@ -302,6 +302,8 @@
     sources += [
       "service/isolated_device_provider.cc",
       "service/isolated_device_provider.h",
+      "service/vr_ui_host.cc",
+      "service/vr_ui_host.h",
       "win/graphics_delegate_win.cc",
       "win/graphics_delegate_win.h",
       "win/input_delegate_win.cc",
@@ -310,8 +312,6 @@
       "win/scheduler_delegate_win.h",
       "win/vr_browser_renderer_thread_win.cc",
       "win/vr_browser_renderer_thread_win.h",
-      "win/vr_ui_host_impl.cc",
-      "win/vr_ui_host_impl.h",
     ]
 
     deps += [ "//services/ws/public/cpp/gpu" ]
diff --git a/chrome/browser/vr/service/isolated_device_provider.cc b/chrome/browser/vr/service/isolated_device_provider.cc
index a585df2..dccc2b1 100644
--- a/chrome/browser/vr/service/isolated_device_provider.cc
+++ b/chrome/browser/vr/service/isolated_device_provider.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/vr/service/isolated_device_provider.h"
 
-#include "chrome/browser/vr/win/vr_ui_host_impl.h"
+#include "chrome/browser/vr/service/vr_ui_host.h"
 #include "content/public/common/service_manager_connection.h"
 #include "device/vr/buildflags/buildflags.h"
 #include "device/vr/isolated_gamepad_data_fetcher.h"
@@ -49,29 +49,29 @@
     device::mojom::VRDisplayInfoPtr display_info) {
   device::mojom::XRDeviceId id = display_info->id;
   add_device_callback_.Run(id, display_info.Clone(), std::move(device));
-  VRUiHostImpl::AddCompositor(std::move(display_info),
-                              std::move(compositor_host));
-  registered_devices_.insert(id);
+
+  auto ui_host = (*VRUiHost::GetFactory())(std::move(display_info),
+                                           std::move(compositor_host));
+  ui_host_map_.insert(std::make_pair(id, std::move(ui_host)));
   device::IsolatedGamepadDataFetcher::Factory::AddGamepad(
       id, std::move(gamepad_factory));
 }
 
 void IsolatedVRDeviceProvider::OnDeviceRemoved(device::mojom::XRDeviceId id) {
   remove_device_callback_.Run(id);
-  registered_devices_.erase(id);
-  VRUiHostImpl::RemoveCompositor(id);
+  ui_host_map_.erase(id);
   device::IsolatedGamepadDataFetcher::Factory::RemoveGamepad(id);
 }
 
 void IsolatedVRDeviceProvider::OnServerError() {
   // An error occurred - any devices we have added are now disconnected and
   // should be removed.
-  for (auto id : registered_devices_) {
+  for (auto& entry : ui_host_map_) {
+    auto id = entry.first;
     remove_device_callback_.Run(id);
-    VRUiHostImpl::RemoveCompositor(id);
     device::IsolatedGamepadDataFetcher::Factory::RemoveGamepad(id);
   }
-  registered_devices_.clear();
+  ui_host_map_.clear();
 
   // At this point, XRRuntimeManager may be blocked waiting for us to return
   // that we've enumerated all runtimes/devices.  If we lost the connection to
@@ -90,10 +90,11 @@
 IsolatedVRDeviceProvider::IsolatedVRDeviceProvider() : binding_(this) {}
 
 IsolatedVRDeviceProvider::~IsolatedVRDeviceProvider() {
-  for (auto device_id : registered_devices_) {
+  for (auto& entry : ui_host_map_) {
+    auto device_id = entry.first;
     device::IsolatedGamepadDataFetcher::Factory::RemoveGamepad(device_id);
-    VRUiHostImpl::RemoveCompositor(device_id);
   }
+  // Default destructor handles renderer_host_map_ cleanup.
 }
 
 }  // namespace vr
diff --git a/chrome/browser/vr/service/isolated_device_provider.h b/chrome/browser/vr/service/isolated_device_provider.h
index f7137c1..aa767ae 100644
--- a/chrome/browser/vr/service/isolated_device_provider.h
+++ b/chrome/browser/vr/service/isolated_device_provider.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_VR_SERVICE_ISOLATED_DEVICE_PROVIDER_H_
 #define CHROME_BROWSER_VR_SERVICE_ISOLATED_DEVICE_PROVIDER_H_
 
+#include "base/containers/flat_map.h"
 #include "device/vr/public/mojom/isolated_xr_service.mojom.h"
 #include "device/vr/vr_device.h"
 #include "device/vr/vr_device_provider.h"
@@ -12,6 +13,8 @@
 
 namespace vr {
 
+class VRUiHost;
+
 class IsolatedVRDeviceProvider
     : public device::VRDeviceProvider,
       public device::mojom::IsolatedXRRuntimeProviderClient {
@@ -52,8 +55,11 @@
   base::RepeatingCallback<void(device::mojom::XRDeviceId)>
       remove_device_callback_;
   base::OnceClosure initialization_complete_;
-  std::set<device::mojom::XRDeviceId> registered_devices_;
   mojo::Binding<device::mojom::IsolatedXRRuntimeProviderClient> binding_;
+
+  using UiHostMap =
+      base::flat_map<device::mojom::XRDeviceId, std::unique_ptr<VRUiHost>>;
+  UiHostMap ui_host_map_;
 };
 
 }  // namespace vr
diff --git a/chrome/browser/vr/service/vr_ui_host.cc b/chrome/browser/vr/service/vr_ui_host.cc
new file mode 100644
index 0000000..648b8f2
--- /dev/null
+++ b/chrome/browser/vr/service/vr_ui_host.cc
@@ -0,0 +1,29 @@
+// 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/vr/service/vr_ui_host.h"
+
+namespace vr {
+
+namespace {
+VRUiHost::Factory* g_vr_ui_host_factory = nullptr;
+}
+
+// Needed for destructor chaining even for an abstract base class.
+VRUiHost::~VRUiHost() = default;
+
+// static
+void VRUiHost::SetFactory(VRUiHost::Factory* factory) {
+  DVLOG(1) << __func__;
+  g_vr_ui_host_factory = factory;
+}
+
+// static
+VRUiHost::Factory* VRUiHost::GetFactory() {
+  DVLOG(1) << __func__;
+  DCHECK(g_vr_ui_host_factory);
+  return g_vr_ui_host_factory;
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/service/vr_ui_host.h b/chrome/browser/vr/service/vr_ui_host.h
new file mode 100644
index 0000000..deb83f84
--- /dev/null
+++ b/chrome/browser/vr/service/vr_ui_host.h
@@ -0,0 +1,34 @@
+// 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_VR_SERVICE_VR_UI_HOST_H_
+#define CHROME_BROWSER_VR_SERVICE_VR_UI_HOST_H_
+
+#include "chrome/browser/vr/vr_export.h"
+#include "device/vr/public/mojom/isolated_xr_service.mojom.h"
+#include "device/vr/public/mojom/vr_service.mojom.h"
+
+namespace vr {
+
+// Abstract class to break a dependency loop between the "vr_common" component
+// when accessing "browser" component functionality such as the permission
+// manager. A concrete VRUiHostImpl object is injected through a factory method
+// registered from chrome_browser_main.cc. The concrete VRUiHost owns a thread
+// which draws browser UI such as permission prompts, and starts and stops that
+// thread as needed.
+class VR_EXPORT VRUiHost {
+ public:
+  virtual ~VRUiHost() = 0;
+
+  using Factory =
+      std::unique_ptr<VRUiHost>(device::mojom::VRDisplayInfoPtr info,
+                                device::mojom::XRCompositorHostPtr compositor);
+
+  static void SetFactory(Factory* factory);
+  static Factory* GetFactory();
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_SERVICE_VR_UI_HOST_H_
diff --git a/chrome/browser/vr/win/vr_ui_host_impl.cc b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc
similarity index 71%
rename from chrome/browser/vr/win/vr_ui_host_impl.cc
rename to chrome/browser/vr/ui_host/vr_ui_host_impl.cc
index 11c33a8..c8d108b 100644
--- a/chrome/browser/vr/win/vr_ui_host_impl.cc
+++ b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/vr/win/vr_ui_host_impl.h"
+#include "chrome/browser/vr/ui_host/vr_ui_host_impl.h"
+
 #include "chrome/browser/vr/service/browser_xr_runtime.h"
 #include "chrome/browser/vr/service/xr_runtime_manager.h"
 #include "chrome/browser/vr/win/vr_browser_renderer_thread_win.h"
 
 namespace vr {
 
-namespace {
-VRUiHostImpl* g_vr_ui_host = nullptr;
-}
-
 VRUiHostImpl::VRUiHostImpl(device::mojom::VRDisplayInfoPtr info,
                            device::mojom::XRCompositorHostPtr compositor)
     : compositor_(std::move(compositor)), info_(std::move(info)) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DVLOG(1) << __func__;
+
   BrowserXRRuntime* runtime =
       XRRuntimeManager::GetInstance()->GetRuntime(info_->id);
   if (runtime) {
@@ -24,12 +24,27 @@
 }
 
 VRUiHostImpl::~VRUiHostImpl() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DVLOG(1) << __func__;
+
   // We don't call BrowserXRRuntime::RemoveObserver, because if we are being
   // destroyed, it means the corresponding device has been removed from
   // XRRuntimeManager, and the BrowserXRRuntime has been destroyed.
+
+  StopUiRendering();
+}
+
+// static
+std::unique_ptr<VRUiHost> VRUiHostImpl::Create(
+    device::mojom::VRDisplayInfoPtr info,
+    device::mojom::XRCompositorHostPtr compositor) {
+  DVLOG(1) << __func__;
+  return std::make_unique<VRUiHostImpl>(std::move(info), std::move(compositor));
 }
 
 void VRUiHostImpl::SetWebXRWebContents(content::WebContents* contents) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
   // Eventually the contents will be used to poll for permissions, or determine
   // what overlays should show.
   if (contents)
@@ -40,30 +55,22 @@
 
 void VRUiHostImpl::SetVRDisplayInfo(
     device::mojom::VRDisplayInfoPtr display_info) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DVLOG(1) << __func__;
+
   info_ = std::move(display_info);
   if (ui_rendering_thread_) {
     ui_rendering_thread_->SetVRDisplayInfo(info_.Clone());
   }
 }
 
-void VRUiHostImpl::AddCompositor(
-    device::mojom::VRDisplayInfoPtr info,
-    device::mojom::XRCompositorHostPtr compositor) {
-  // We only expect one device to be enabled at a time.
-  DCHECK(!g_vr_ui_host);
-  g_vr_ui_host = new VRUiHostImpl(std::move(info), std::move(compositor));
-}
-
-void VRUiHostImpl::RemoveCompositor(device::mojom::XRDeviceId id) {
-  DCHECK(g_vr_ui_host);
-  g_vr_ui_host->StopUiRendering();
-  delete g_vr_ui_host;
-  g_vr_ui_host = nullptr;
-}
-
 void VRUiHostImpl::StartUiRendering() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DVLOG(1) << __func__;
+
 // Only used for testing currently.  To see an example overlay, enable the
-// following few lines.
+// following few lines. TODO(https://crbug.com/911734): show browser UI for
+// permission prompts in VR here.
 #if 0
   ui_rendering_thread_ = std::make_unique<VRBrowserRendererThreadWin>();
   ui_rendering_thread_->Start();
@@ -73,6 +80,9 @@
 }
 
 void VRUiHostImpl::StopUiRendering() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DVLOG(1) << __func__;
+
   ui_rendering_thread_ = nullptr;
 }
 
diff --git a/chrome/browser/vr/ui_host/vr_ui_host_impl.h b/chrome/browser/vr/ui_host/vr_ui_host_impl.h
new file mode 100644
index 0000000..8724f1f7
--- /dev/null
+++ b/chrome/browser/vr/ui_host/vr_ui_host_impl.h
@@ -0,0 +1,52 @@
+// 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_VR_UI_HOST_VR_UI_HOST_IMPL_H_
+#define CHROME_BROWSER_VR_UI_HOST_VR_UI_HOST_IMPL_H_
+
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+#include "chrome/browser/vr/service/browser_xr_runtime.h"
+#include "chrome/browser/vr/service/vr_ui_host.h"
+#include "content/public/browser/web_contents.h"
+
+namespace vr {
+
+class VRBrowserRendererThreadWin;
+
+// Concrete implementation of VRBrowserRendererHost, part of the "browser"
+// component. Used on the browser's main thread.
+class VRUiHostImpl : public VRUiHost, public BrowserXRRuntimeObserver {
+ public:
+  VRUiHostImpl(device::mojom::VRDisplayInfoPtr info,
+               device::mojom::XRCompositorHostPtr compositor);
+  ~VRUiHostImpl() override;
+
+  // Factory for use with VRUiHost::{Set,Get}Factory
+  static std::unique_ptr<VRUiHost> Create(
+      device::mojom::VRDisplayInfoPtr info,
+      device::mojom::XRCompositorHostPtr compositor);
+
+ private:
+  // BrowserXRRuntimeObserver implementation.
+  void SetWebXRWebContents(content::WebContents* contents) override;
+  void SetVRDisplayInfo(device::mojom::VRDisplayInfoPtr display_info) override;
+
+  // Internal methods used to start/stop the UI rendering thread that is used
+  // for drawing browser UI (such as permission prompts) for display in VR.
+  void StartUiRendering();
+  void StopUiRendering();
+
+  device::mojom::XRCompositorHostPtr compositor_;
+  std::unique_ptr<VRBrowserRendererThreadWin> ui_rendering_thread_;
+  device::mojom::VRDisplayInfoPtr info_;
+
+  THREAD_CHECKER(thread_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(VRUiHostImpl);
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_UI_HOST_VR_UI_HOST_IMPL_H_
diff --git a/chrome/browser/vr/win/vr_browser_renderer_thread_win.h b/chrome/browser/vr/win/vr_browser_renderer_thread_win.h
index b5b18d8d..a8c0eca 100644
--- a/chrome/browser/vr/win/vr_browser_renderer_thread_win.h
+++ b/chrome/browser/vr/win/vr_browser_renderer_thread_win.h
@@ -9,6 +9,7 @@
 #include "chrome/browser/vr/browser_renderer.h"
 #include "chrome/browser/vr/model/web_vr_model.h"
 #include "chrome/browser/vr/service/browser_xr_runtime.h"
+#include "chrome/browser/vr/vr_export.h"
 #include "content/public/browser/web_contents.h"
 #include "device/vr/public/mojom/isolated_xr_service.mojom.h"
 #include "device/vr/public/mojom/vr_service.mojom.h"
@@ -47,7 +48,7 @@
 
 #endif
 
-class VRBrowserRendererThreadWin : public MaybeThread {
+class VR_EXPORT VRBrowserRendererThreadWin : public MaybeThread {
  public:
   VRBrowserRendererThreadWin();
   ~VRBrowserRendererThreadWin() override;
diff --git a/chrome/browser/vr/win/vr_ui_host_impl.h b/chrome/browser/vr/win/vr_ui_host_impl.h
deleted file mode 100644
index 2973635..0000000
--- a/chrome/browser/vr/win/vr_ui_host_impl.h
+++ /dev/null
@@ -1,47 +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_VR_WIN_VR_UI_HOST_IMPL_H_
-#define CHROME_BROWSER_VR_WIN_VR_UI_HOST_IMPL_H_
-
-#include "base/threading/thread.h"
-#include "chrome/browser/vr/service/browser_xr_runtime.h"
-#include "content/public/browser/web_contents.h"
-#include "device/vr/public/mojom/isolated_xr_service.mojom.h"
-#include "device/vr/public/mojom/vr_service.mojom.h"
-
-namespace vr {
-
-class VRBrowserRendererThreadWin;
-
-class VRUiHostImpl : public BrowserXRRuntimeObserver {
- public:
-  // Called by IsolatedDeviceProvider when devices are added/removed.  These
-  // manage the lifetime of VRBrowserRendererHostWin instances.
-  static void AddCompositor(device::mojom::VRDisplayInfoPtr info,
-                            device::mojom::XRCompositorHostPtr compositor);
-  static void RemoveCompositor(device::mojom::XRDeviceId id);
-
- private:
-  VRUiHostImpl(device::mojom::VRDisplayInfoPtr info,
-               device::mojom::XRCompositorHostPtr compositor);
-  ~VRUiHostImpl() override;
-
-  // BrowserXRRuntimeObserver implementation.
-  void SetWebXRWebContents(content::WebContents* contents) override;
-  void SetVRDisplayInfo(device::mojom::VRDisplayInfoPtr display_info) override;
-
-  // Internal methods used to start/stop the UI rendering thread that is used
-  // for drawing browser UI (such as permission prompts) for display in VR.
-  void StartUiRendering();
-  void StopUiRendering();
-
-  device::mojom::XRCompositorHostPtr compositor_;
-  std::unique_ptr<VRBrowserRendererThreadWin> ui_rendering_thread_;
-  device::mojom::VRDisplayInfoPtr info_;
-};
-
-}  // namespace vr
-
-#endif  // CHROME_BROWSER_VR_WIN_VR_UI_HOST_IMPL_H_
diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc
index 7ad0232..44252ce 100644
--- a/chrome/service/service_utility_process_host.cc
+++ b/chrome/service/service_utility_process_host.cc
@@ -361,7 +361,7 @@
   // "content_utility". This is all set up here.
   service_manager_ = std::make_unique<service_manager::ServiceManager>(
       std::make_unique<NullServiceProcessLauncherFactory>(),
-      CreateServiceProcessCatalog(), nullptr);
+      CreateServiceProcessCatalog());
 
   service_manager::mojom::ServicePtr browser_proxy;
   service_manager_connection_ = content::ServiceManagerConnection::Create(
diff --git a/chrome/test/chromedriver/capabilities.cc b/chrome/test/chromedriver/capabilities.cc
index f3baddb2..73729a41 100644
--- a/chrome/test/chromedriver/capabilities.cc
+++ b/chrome/test/chromedriver/capabilities.cc
@@ -25,6 +25,7 @@
 #include "chrome/test/chromedriver/chrome/status.h"
 #include "chrome/test/chromedriver/logging.h"
 #include "chrome/test/chromedriver/session.h"
+#include "chrome/test/chromedriver/util.h"
 
 namespace {
 
@@ -222,22 +223,24 @@
   const base::DictionaryValue* timeouts;
   if (!option.GetAsDictionary(&timeouts))
     return Status(kInvalidArgument, "'timeouts' must be a JSON object");
-
-  std::map<std::string, Parser> parser_map;
-  parser_map["script"] =
-      base::BindRepeating(&ParseTimeDelta, &capabilities->script_timeout);
-  parser_map["pageLoad"] =
-      base::BindRepeating(&ParseTimeDelta, &capabilities->page_load_timeout);
-  parser_map["implicit"] = base::BindRepeating(
-      &ParseTimeDelta, &capabilities->implicit_wait_timeout);
-
   for (const auto& it : timeouts->DictItems()) {
-    if (parser_map.find(it.first) == parser_map.end())
+    int64_t timeout_ms_int64 = -1;
+    if (!GetOptionalSafeInt(timeouts, it.first, &timeout_ms_int64)
+        || timeout_ms_int64 < 0)
+      return Status(kInvalidArgument, "value must be a non-negative integer");
+    base::TimeDelta timeout =
+                          base::TimeDelta::FromMilliseconds(timeout_ms_int64);
+    const std::string& type = it.first;
+    if (type == "script") {
+      capabilities->script_timeout = timeout;
+    } else if (type == "pageLoad") {
+      capabilities->page_load_timeout = timeout;
+    } else if (type == "implicit") {
+      capabilities->implicit_wait_timeout = timeout;
+    } else {
       return Status(kInvalidArgument,
-                    "unrecognized 'timeouts' option: " + it.first);
-    Status status = parser_map[it.first].Run(it.second, capabilities);
-    if (status.IsError())
-      return Status(kInvalidArgument, "cannot parse " + it.first, status);
+                    "unrecognized 'timeouts' option: " + type);
+    }
   }
   return Status(kOk);
 }
diff --git a/chrome/test/chromedriver/session_commands.cc b/chrome/test/chromedriver/session_commands.cc
index dae051e..903f05c 100644
--- a/chrome/test/chromedriver/session_commands.cc
+++ b/chrome/test/chromedriver/session_commands.cc
@@ -133,11 +133,12 @@
   } else {
     caps->SetBoolean("setWindowRect", true);
   }
-  caps->SetInteger("timeouts.script", session->script_timeout.InMilliseconds());
-  caps->SetInteger("timeouts.pageLoad",
-                   session->page_load_timeout.InMilliseconds());
-  caps->SetInteger("timeouts.implicit",
-                   session->implicit_wait.InMilliseconds());
+  SetSafeInt(caps.get(), "timeouts.script",
+             session->script_timeout.InMilliseconds());
+  SetSafeInt(caps.get(), "timeouts.pageLoad",
+             session->page_load_timeout.InMilliseconds());
+  SetSafeInt(caps.get(), "timeouts.implicit",
+             session->implicit_wait.InMilliseconds());
   caps->SetBoolean("strictFileInteractability",
                     session->strict_file_interactability);
   caps->SetString(session->w3c_compliant ? "unhandledPromptBehavior"
@@ -715,10 +716,12 @@
                              const base::DictionaryValue& params,
                              std::unique_ptr<base::Value>* value) {
   for (const auto& setting : params.DictItems()) {
-    int timeout_ms;
-    if (!setting.second.GetAsInteger(&timeout_ms) || timeout_ms < 0)
+    int64_t timeout_ms_int64 = -1;
+    if (!GetOptionalSafeInt(&params, setting.first, &timeout_ms_int64) ||
+        timeout_ms_int64 < 0)
       return Status(kInvalidArgument, "value must be a non-negative integer");
-    base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(timeout_ms);
+    base::TimeDelta timeout =
+                    base::TimeDelta::FromMilliseconds(timeout_ms_int64);
     const std::string& type = setting.first;
     if (type == "script") {
       session->script_timeout = timeout;
@@ -750,9 +753,10 @@
                           const base::DictionaryValue& params,
                           std::unique_ptr<base::Value>* value) {
   base::DictionaryValue timeouts;
-  timeouts.SetInteger("script", session->script_timeout.InMilliseconds());
-  timeouts.SetInteger("pageLoad", session->page_load_timeout.InMilliseconds());
-  timeouts.SetInteger("implicit", session->implicit_wait.InMilliseconds());
+  SetSafeInt(&timeouts, "script", session->script_timeout.InMilliseconds());
+  SetSafeInt(&timeouts, "pageLoad",
+                        session->page_load_timeout.InMilliseconds());
+  SetSafeInt(&timeouts, "implicit", session->implicit_wait.InMilliseconds());
 
   value->reset(timeouts.DeepCopy());
   return Status(kOk);
diff --git a/chrome/test/chromedriver/util.cc b/chrome/test/chromedriver/util.cc
index ceb11338..4ff84c60 100644
--- a/chrome/test/chromedriver/util.cc
+++ b/chrome/test/chromedriver/util.cc
@@ -537,3 +537,13 @@
     *has_value = true;
   return true;
 }
+
+bool SetSafeInt(base::DictionaryValue* dict,
+                const base::StringPiece path,
+                int64_t in_value_64) {
+  int int_value = static_cast<int>(in_value_64);
+  if (in_value_64 == int_value)
+    return dict->SetInteger(path, in_value_64);
+  else
+    return dict->SetDouble(path, in_value_64);
+}
diff --git a/chrome/test/chromedriver/util.h b/chrome/test/chromedriver/util.h
index 31888d4..f36731c 100644
--- a/chrome/test/chromedriver/util.h
+++ b/chrome/test/chromedriver/util.h
@@ -88,4 +88,8 @@
                         int64_t* out_value,
                         bool* has_value = nullptr);
 
+bool SetSafeInt(base::DictionaryValue* dict,
+                const base::StringPiece path,
+                int64_t in_value_64);
+
 #endif  // CHROME_TEST_CHROMEDRIVER_UTIL_H_
diff --git a/chrome/test/data/webui/cr_focus_row_behavior_interactive_test.js b/chrome/test/data/webui/cr_focus_row_behavior_interactive_test.js
index abe4dbc..517401e 100644
--- a/chrome/test/data/webui/cr_focus_row_behavior_interactive_test.js
+++ b/chrome/test/data/webui/cr_focus_row_behavior_interactive_test.js
@@ -34,11 +34,6 @@
     PolymerTest.prototype.setUp.call(this);
     // We aren't loading the main document.
     this.accessibilityAuditConfig.ignoreSelectors('humanLangMissing', 'html');
-
-    // TODO(michaelpg): Re-enable after bringing in fix for
-    // https://github.com/PolymerElements/paper-slider/issues/131.
-    this.accessibilityAuditConfig.ignoreSelectors(
-        'badAriaAttributeValue', 'paper-slider');
   },
 };
 
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index 1bc6213..21c89ed 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -39,11 +39,6 @@
     // We aren't loading the main document.
     this.accessibilityAuditConfig.ignoreSelectors('humanLangMissing', 'html');
 
-    // TODO(michaelpg): Re-enable after bringing in fix for
-    // https://github.com/PolymerElements/paper-slider/issues/131.
-    this.accessibilityAuditConfig.ignoreSelectors(
-        'badAriaAttributeValue', 'paper-slider');
-
     settings.ensureLazyLoaded();
   },
 };
diff --git a/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js b/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js
index d3a26c2..9b588d1 100644
--- a/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js
+++ b/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js
@@ -34,11 +34,6 @@
     PolymerTest.prototype.setUp.call(this);
     // We aren't loading the main document.
     this.accessibilityAuditConfig.ignoreSelectors('humanLangMissing', 'html');
-
-    // TODO(michaelpg): Re-enable after bringing in fix for
-    // https://github.com/PolymerElements/paper-slider/issues/131.
-    this.accessibilityAuditConfig.ignoreSelectors(
-        'badAriaAttributeValue', 'paper-slider');
   },
 };
 
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js
index 5f766a2..94240e7 100644
--- a/chrome/test/data/webui/settings/device_page_tests.js
+++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -666,8 +666,7 @@
             expectEquals(500, keyboardPage.$$('#delaySlider').pref.value);
             expectEquals(500, keyboardPage.$$('#repeatRateSlider').pref.value);
 
-            // Test interaction with the settings-slider's underlying
-            // paper-slider.
+            // Test interaction with the settings-slider's underlying cr-slider.
             MockInteractions.pressAndReleaseKeyOn(
                 keyboardPage.$$('#delaySlider').$$('cr-slider'), 37 /* left */,
                 [], 'ArrowLeft');
diff --git a/chrome/test/data/webui/settings/search_settings_test.js b/chrome/test/data/webui/settings/search_settings_test.js
index 3d557ff..ee3ee262 100644
--- a/chrome/test/data/webui/settings/search_settings_test.js
+++ b/chrome/test/data/webui/settings/search_settings_test.js
@@ -108,6 +108,7 @@
       document.body.innerHTML = `<settings-section hidden-by-search>
              <cr-action-menu>${text}</cr-action-menu>
              <cr-dialog>${text}</cr-dialog>
+             <cr-slider>${text}</cr-slider>
              <dialog>${text}</dialog>
              <iron-icon>${text}</iron-icon>
              <iron-list>${text}</iron-list>
@@ -116,7 +117,6 @@
                <button>${text}</button>
              </paper-icon-button-light>
              <paper-ripple>${text}</paper-ripple>
-             <paper-slider>${text}</paper-slider>
              <paper-spinner-lite>${text}</paper-spinner-lite>
              <slot>${text}</slot>
              <content>${text}</content>
diff --git a/chrome/test/data/webui/settings/settings_slider_tests.js b/chrome/test/data/webui/settings/settings_slider_tests.js
index e4fc0d9..355b29a 100644
--- a/chrome/test/data/webui/settings/settings_slider_tests.js
+++ b/chrome/test/data/webui/settings/settings_slider_tests.js
@@ -8,7 +8,7 @@
   let slider;
 
   /**
-   * paper-slider instance wrapped by settings-slider.
+   * cr-slider instance wrapped by settings-slider.
    * @type {!CrSliderElement}
    */
   let crSlider;
diff --git a/chromecast/base/serializers_unittest.cc b/chromecast/base/serializers_unittest.cc
index 750e237..05f4a0d 100644
--- a/chromecast/base/serializers_unittest.cc
+++ b/chromecast/base/serializers_unittest.cc
@@ -57,13 +57,13 @@
 TEST(SerializeToJson, BadValue) {
   base::Value value(std::vector<char>(12));
   base::Optional<std::string> str = SerializeToJson(value);
-  EXPECT_EQ(base::nullopt, str);
+  EXPECT_FALSE(str.has_value());
 }
 
 TEST(SerializeToJson, EmptyValue) {
   base::DictionaryValue value;
   base::Optional<std::string> str = SerializeToJson(value);
-  ASSERT_NE(base::nullopt, str);
+  ASSERT_TRUE(str.has_value());
   EXPECT_EQ(kEmptyJsonString, *str);
 }
 
@@ -71,7 +71,7 @@
   base::DictionaryValue orig_value;
   orig_value.SetString(kTestKey, kTestValue);
   base::Optional<std::string> str = SerializeToJson(orig_value);
-  ASSERT_NE(nullptr, str);
+  ASSERT_TRUE(str.has_value());
 
   std::unique_ptr<base::Value> new_value = DeserializeFromJson(*str);
   ASSERT_NE(nullptr, new_value.get());
diff --git a/chromeos/chromeos_features.cc b/chromeos/chromeos_features.cc
index 43dfc86..e0b55d74 100644
--- a/chromeos/chromeos_features.cc
+++ b/chromeos/chromeos_features.cc
@@ -76,6 +76,11 @@
 const base::Feature kVideoPlayerNativeControls{
     "VideoPlayerNativeControls", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Use the messages.google.com domain as part of the "Messages" feature under
+// "Connected Devices" settings.
+const base::Feature kUseMessagesGoogleComDomain{
+    "UseMessagesGoogleComDomain", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables or disables user activity prediction for power management on
 // Chrome OS.
 // Defined here rather than in //chrome alongside other related features so that
diff --git a/chromeos/chromeos_features.h b/chromeos/chromeos_features.h
index 970f304..0f8506a 100644
--- a/chromeos/chromeos_features.h
+++ b/chromeos/chromeos_features.h
@@ -31,6 +31,7 @@
 CHROMEOS_EXPORT extern const base::Feature kImeServiceConnectable;
 CHROMEOS_EXPORT extern const base::Feature kInstantTethering;
 CHROMEOS_EXPORT extern const base::Feature kVideoPlayerNativeControls;
+CHROMEOS_EXPORT extern const base::Feature kUseMessagesGoogleComDomain;
 CHROMEOS_EXPORT extern const base::Feature kUserActivityPrediction;
 
 }  // namespace features
diff --git a/components/arc/arc_session_impl.cc b/components/arc/arc_session_impl.cc
index bf6dd34..8b73051 100644
--- a/components/arc/arc_session_impl.cc
+++ b/components/arc/arc_session_impl.cc
@@ -510,8 +510,6 @@
         upgrade_params_.demo_session_apps_path.value());
   }
 
-  request.set_create_socket_in_chrome(true);
-
   client_->UpgradeArc(
       request,
       base::BindOnce(&ArcSessionImpl::OnUpgraded, weak_factory_.GetWeakPtr(),
diff --git a/components/invalidation/impl/android/DEPS b/components/invalidation/impl/android/DEPS
index 5fb592e..d2207df 100644
--- a/components/invalidation/impl/android/DEPS
+++ b/components/invalidation/impl/android/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
+  "+components/signin",
   "+components/sync",
 ]
diff --git a/components/invalidation/impl/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java b/components/invalidation/impl/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java
index 7ed5b78..d871bd7 100644
--- a/components/invalidation/impl/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java
+++ b/components/invalidation/impl/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java
@@ -29,8 +29,8 @@
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
-import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.ChromeSigninController;
+import org.chromium.components.signin.OAuth2TokenService;
 import org.chromium.components.sync.AndroidSyncSettings;
 import org.chromium.components.sync.ModelTypeHelper;
 import org.chromium.components.sync.SyncConstants;
@@ -257,16 +257,17 @@
         ThreadUtils.runOnUiThread(() -> {
             // Attempt to retrieve a token for the user. This method will also invalidate
             // invalidAuthToken if it is non-null.
-            AccountManagerFacade.get().getNewAuthToken(account, invalidAuthToken,
-                    getOAuth2ScopeWithType(), new AccountManagerFacade.GetAuthTokenCallback() {
+            OAuth2TokenService.getNewAccessToken(account, invalidAuthToken,
+                    SyncConstants.CHROME_SYNC_OAUTH2_SCOPE,
+                    new OAuth2TokenService.GetAccessTokenCallback() {
                         @Override
-                        public void tokenAvailable(String token) {
+                        public void onGetTokenSuccess(String token) {
                             setAuthToken(InvalidationClientService.this.getApplicationContext(),
-                                    pendingIntent, token, getOAuth2ScopeWithType());
+                                    pendingIntent, token, SyncConstants.CHROME_SYNC_OAUTH2_SCOPE);
                         }
 
                         @Override
-                        public void tokenUnavailable(boolean isTransientError) {}
+                        public void onGetTokenFailure(boolean isTransientError) {}
                     });
         });
     }
@@ -536,10 +537,6 @@
         return sClientId;
     }
 
-    private static String getOAuth2ScopeWithType() {
-        return "oauth2:" + SyncConstants.CHROME_SYNC_OAUTH2_SCOPE;
-    }
-
     private static void setClientId(byte[] clientId) {
         sClientId = clientId;
     }
diff --git a/components/omnibox/browser/clipboard_url_provider.cc b/components/omnibox/browser/clipboard_url_provider.cc
index 86d41a6..110ea4e 100644
--- a/components/omnibox/browser/clipboard_url_provider.cc
+++ b/components/omnibox/browser/clipboard_url_provider.cc
@@ -10,12 +10,14 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/omnibox/browser/autocomplete_input.h"
 #include "components/omnibox/browser/autocomplete_provider_client.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/verbatim_match.h"
 #include "components/open_from_clipboard/clipboard_recent_content.h"
+#include "components/search_engines/template_url_service.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/url_formatter.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -42,19 +44,15 @@
   if (!input.from_omnibox_focus())
     return;
 
-  GURL url;
-  // The clipboard does not contain a URL worth suggesting.
-  if (!clipboard_content_->GetRecentURLFromClipboard(&url)) {
-    current_url_suggested_ = GURL();
-    current_url_suggested_times_ = 0;
+  base::Optional<AutocompleteMatch> optional_match = CreateURLMatch(input);
+  if (!optional_match) {
+    optional_match = CreateTextMatch(input);
+  }
+  // The clipboard does not contain any suggestions
+  if (!optional_match) {
     return;
   }
-  // The URL on the page is the same as the URL in the clipboard.  Don't
-  // bother suggesting it.
-  if (url == input.current_url())
-    return;
 
-  DCHECK(url.is_valid());
   // If the omnibox is not empty, add a default match.
   // This match will be opened when the user presses "Enter".
   if (!input.text().empty()) {
@@ -71,6 +69,29 @@
                         !matches_.empty());
   UMA_HISTOGRAM_LONG_TIMES_100("Omnibox.ClipboardSuggestionShownAge",
                                clipboard_content_->GetClipboardContentAge());
+
+  matches_.emplace_back(std::move(optional_match).value());
+}
+
+base::Optional<AutocompleteMatch> ClipboardURLProvider::CreateURLMatch(
+    const AutocompleteInput& input) {
+  // The clipboard does not contain a URL worth suggesting.
+  base::Optional<GURL> optional_gurl =
+      clipboard_content_->GetRecentURLFromClipboard();
+  if (!optional_gurl) {
+    current_url_suggested_ = GURL();
+    current_url_suggested_times_ = 0;
+    return base::nullopt;
+  }
+  GURL url = std::move(optional_gurl).value();
+
+  // The URL on the page is the same as the URL in the clipboard.  Don't
+  // bother suggesting it.
+  if (url == input.current_url())
+    return base::nullopt;
+
+  DCHECK(url.is_valid());
+
   // Record the number of times the currently-offered URL has been suggested.
   // This only works over this run of Chrome; if the URL was in the clipboard
   // on a previous run, those offerings will not be counted.
@@ -101,7 +122,47 @@
       base::string16::npos, 0, match.description.length(),
       ACMatchClassification::NONE, &match.description_class);
 
-  matches_.push_back(match);
+  return match;
+}
+
+base::Optional<AutocompleteMatch> ClipboardURLProvider::CreateTextMatch(
+    const AutocompleteInput& input) {
+  // Only try text match if feature is enabled
+  if (!base::FeatureList::IsEnabled(omnibox::kCopiedTextBehavior)) {
+    return base::nullopt;
+  }
+
+  base::Optional<base::string16> optional_text =
+      clipboard_content_->GetRecentTextFromClipboard();
+  if (!optional_text) {
+    return base::nullopt;
+  }
+  base::string16 text = std::move(optional_text).value();
+
+  DCHECK(!text.empty());
+
+  // Add the clipboard match. The relevance is 800 to beat ZeroSuggest results.
+  AutocompleteMatch match(this, 800, false, AutocompleteMatchType::CLIPBOARD);
+  TemplateURLService* url_service = client_->GetTemplateURLService();
+  const TemplateURL* default_url = url_service->GetDefaultSearchProvider();
+  DCHECK(!default_url->url().empty());
+  DCHECK(default_url->url_ref().IsValid(url_service->search_terms_data()));
+  TemplateURLRef::SearchTermsArgs search_args(text);
+  GURL result(default_url->url_ref().ReplaceSearchTerms(
+      search_args, url_service->search_terms_data()));
+  match.destination_url = result;
+  match.contents.assign(l10n_util::GetStringFUTF16(
+      IDS_COPIED_TEXT_FROM_CLIPBOARD, AutocompleteMatch::SanitizeString(text)));
+  AutocompleteMatch::ClassifyLocationInString(
+      base::string16::npos, 0, match.contents.length(),
+      ACMatchClassification::DIM, &match.contents_class);
+
+  match.description.assign(l10n_util::GetStringUTF16(IDS_TEXT_FROM_CLIPBOARD));
+  AutocompleteMatch::ClassifyLocationInString(
+      base::string16::npos, 0, match.description.length(),
+      ACMatchClassification::NONE, &match.description_class);
+
+  return match;
 }
 
 void ClipboardURLProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
diff --git a/components/omnibox/browser/clipboard_url_provider.h b/components/omnibox/browser/clipboard_url_provider.h
index 0b54d3e4..aa9bd30 100644
--- a/components/omnibox/browser/clipboard_url_provider.h
+++ b/components/omnibox/browser/clipboard_url_provider.h
@@ -27,6 +27,13 @@
  private:
   ~ClipboardURLProvider() override;
 
+  // If there is a url copied to the clipboard, use it to create a match.
+  base::Optional<AutocompleteMatch> CreateURLMatch(
+      const AutocompleteInput& input);
+  // If there is text copied to the clipboard, use it to create a match.
+  base::Optional<AutocompleteMatch> CreateTextMatch(
+      const AutocompleteInput& input);
+
   AutocompleteProviderClient* client_;
   ClipboardRecentContent* clipboard_content_;
 
diff --git a/components/omnibox/browser/clipboard_url_provider_unittest.cc b/components/omnibox/browser/clipboard_url_provider_unittest.cc
index becd43b..ca40830 100644
--- a/components/omnibox/browser/clipboard_url_provider_unittest.cc
+++ b/components/omnibox/browser/clipboard_url_provider_unittest.cc
@@ -9,10 +9,14 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "components/omnibox/browser/autocomplete_input.h"
 #include "components/omnibox/browser/mock_autocomplete_provider_client.h"
 #include "components/omnibox/browser/test_scheme_classifier.h"
 #include "components/open_from_clipboard/fake_clipboard_recent_content.h"
+#include "components/search_engines/template_url_service.h"
+#include "components/search_engines/template_url_service_client.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -21,6 +25,8 @@
 
 const char kCurrentURL[] = "http://example.com/current";
 const char kClipboardURL[] = "http://example.com/clipboard";
+const char kClipboardText[] = "Search for me";
+const char kClipboardTitleText[] = "\"Search for me\"";
 
 class ClipboardURLProviderTest : public testing::Test {
  public:
@@ -37,8 +43,11 @@
   void ClearClipboard() { clipboard_content_.SuppressClipboardContent(); }
 
   void SetClipboardUrl(const GURL& url) {
-    clipboard_content_.SetClipboardContent(url,
-                                           base::TimeDelta::FromMinutes(10));
+    clipboard_content_.SetClipboardURL(url, base::TimeDelta::FromMinutes(10));
+  }
+
+  void SetClipboardText(const base::string16& text) {
+    clipboard_content_.SetClipboardText(text, base::TimeDelta::FromMinutes(10));
   }
 
   AutocompleteInput CreateAutocompleteInput(bool from_omnibox_focus) {
@@ -79,4 +88,17 @@
   EXPECT_EQ(GURL(kClipboardURL), provider_->matches().back().destination_url);
 }
 
+TEST_F(ClipboardURLProviderTest, MatchesText) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(omnibox::kCopiedTextBehavior);
+  auto template_url_service = std::make_unique<TemplateURLService>(
+      /*initializers=*/nullptr, /*count=*/0);
+  client_->set_template_url_service(std::move(template_url_service));
+  SetClipboardText(base::UTF8ToUTF16(kClipboardText));
+  provider_->Start(CreateAutocompleteInput(true), false);
+  ASSERT_GE(provider_->matches().size(), 1U);
+  EXPECT_EQ(base::UTF8ToUTF16(kClipboardTitleText),
+            provider_->matches().back().contents);
+}
+
 }  // namespace
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index 442afe9..209f8c91 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -224,6 +224,16 @@
 const base::Feature kOmniboxPopupShortcutIconsInZeroState{
     "OmniboxPopupShortcutIconsInZeroState", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Feature to differentiate between a copied url and copied text
+const base::Feature kCopiedTextBehavior {
+  "CopiedTextBehavior",
+#if defined(OS_IOS)
+      base::FEATURE_ENABLED_BY_DEFAULT
+#else
+      base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
+
 }  // namespace omnibox
 
 namespace {
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h
index fedf8c6..4b762b9 100644
--- a/components/omnibox/browser/omnibox_field_trial.h
+++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -49,6 +49,7 @@
 extern const base::Feature kSpeculativeServiceWorkerStartOnQueryInput;
 extern const base::Feature kDocumentProvider;
 extern const base::Feature kOmniboxPopupShortcutIconsInZeroState;
+extern const base::Feature kCopiedTextBehavior;
 
 }  // namespace omnibox
 
diff --git a/components/omnibox_strings.grdp b/components/omnibox_strings.grdp
index 067f34b..fcd446f7 100644
--- a/components/omnibox_strings.grdp
+++ b/components/omnibox_strings.grdp
@@ -10,6 +10,12 @@
   <message name="IDS_LINK_FROM_CLIPBOARD" desc="The label in the omnibox dropdown explaining that the link has been extracted from the user's clipboard. [Length: 21em]">
     Link you copied
   </message>
+  <message name="IDS_TEXT_FROM_CLIPBOARD" desc="The label in the omnibox dropdown explaining that the text has been extracted from the user's clipboard.">
+    Text you copied
+  </message>
+  <message name="IDS_COPIED_TEXT_FROM_CLIPBOARD" desc="The actual text the user copied, surrounded by quotation marks.">
+    &quot;<ph name="TEXT">$1<ex>search string</ex></ph>&quot;
+  </message>
   <message name="IDS_SECURE_CONNECTION_EV" desc="Short text shown in the location bar when the connection is secure with an EV cert.">
     <ph name="ORGANIZATION">$1<ex>Paypal Inc.</ex></ph> [<ph name="COUNTRY">$2<ex>US</ex></ph>]
   </message>
diff --git a/components/open_from_clipboard/clipboard_recent_content.h b/components/open_from_clipboard/clipboard_recent_content.h
index 6d11890..48063e8 100644
--- a/components/open_from_clipboard/clipboard_recent_content.h
+++ b/components/open_from_clipboard/clipboard_recent_content.h
@@ -28,10 +28,13 @@
   // Sets the global instance of ClipboardRecentContent singleton.
   static void SetInstance(std::unique_ptr<ClipboardRecentContent> new_instance);
 
-  // Returns true if the clipboard contains a recent URL that is appropriate to
-  // be suggested and has not been supressed, and copies it in |url|.
-  // Otherwise, returns false. |url| must not be null.
-  virtual bool GetRecentURLFromClipboard(GURL* url) = 0;
+  // Returns clipboard content as URL, if it has a compatible type,
+  // is recent enough and has not been suppressed.
+  virtual base::Optional<GURL> GetRecentURLFromClipboard() = 0;
+
+  // Returns clipboard content as text, if it has a compatible type,
+  // is recent enough and has not been suppressed.
+  virtual base::Optional<base::string16> GetRecentTextFromClipboard() = 0;
 
   // Returns how old the content of the clipboard is.
   virtual base::TimeDelta GetClipboardContentAge() const = 0;
diff --git a/components/open_from_clipboard/clipboard_recent_content_generic.cc b/components/open_from_clipboard/clipboard_recent_content_generic.cc
index 70b36916..0877cbb 100644
--- a/components/open_from_clipboard/clipboard_recent_content_generic.cc
+++ b/components/open_from_clipboard/clipboard_recent_content_generic.cc
@@ -22,9 +22,10 @@
 
 ClipboardRecentContentGeneric::ClipboardRecentContentGeneric() {}
 
-bool ClipboardRecentContentGeneric::GetRecentURLFromClipboard(GURL* url) {
+base::Optional<GURL>
+ClipboardRecentContentGeneric::GetRecentURLFromClipboard() {
   if (GetClipboardContentAge() > MaximumAgeOfClipboard())
-    return false;
+    return base::nullopt;
 
   // Get and clean up the clipboard before processing.
   std::string gurl_string;
@@ -34,15 +35,15 @@
                             &gurl_string);
 
   // Interpret the clipboard as a URL if possible.
-  DCHECK(url);
+  GURL url;
   // If there is mid-string whitespace, don't attempt to interpret the string
   // as a URL.  (Otherwise gurl will happily try to convert
   // "http://example.com extra words" into "http://example.com%20extra%20words",
   // which is not likely to be a useful or intended destination.)
   if (gurl_string.find_first_of(base::kWhitespaceASCII) != std::string::npos)
-    return false;
+    return base::nullopt;
   if (!gurl_string.empty()) {
-    *url = GURL(gurl_string);
+    url = GURL(gurl_string);
   } else {
     // Fall back to unicode / UTF16, as some URLs may use international domain
     // names, not punycode.
@@ -52,11 +53,19 @@
                          &gurl_string16);
     if (gurl_string16.find_first_of(base::kWhitespaceUTF16) !=
         std::string::npos)
-      return false;
+      return base::nullopt;
     if (!gurl_string16.empty())
-      *url = GURL(gurl_string16);
+      url = GURL(gurl_string16);
   }
-  return url->is_valid() && IsAppropriateSuggestion(*url);
+  if (!url.is_valid() || !IsAppropriateSuggestion(url)) {
+    return base::nullopt;
+  }
+  return url;
+}
+
+base::Optional<base::string16>
+ClipboardRecentContentGeneric::GetRecentTextFromClipboard() {
+  return base::nullopt;
 }
 
 base::TimeDelta ClipboardRecentContentGeneric::GetClipboardContentAge() const {
diff --git a/components/open_from_clipboard/clipboard_recent_content_generic.h b/components/open_from_clipboard/clipboard_recent_content_generic.h
index 4a5d4a4..38422d7 100644
--- a/components/open_from_clipboard/clipboard_recent_content_generic.h
+++ b/components/open_from_clipboard/clipboard_recent_content_generic.h
@@ -22,7 +22,8 @@
   explicit ClipboardRecentContentGeneric();
 
   // ClipboardRecentContent implementation.
-  bool GetRecentURLFromClipboard(GURL* url) override;
+  base::Optional<GURL> GetRecentURLFromClipboard() override;
+  base::Optional<base::string16> GetRecentTextFromClipboard() override;
   base::TimeDelta GetClipboardContentAge() const override;
   void SuppressClipboardContent() override;
 
diff --git a/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc b/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc
index e03deef..425537b 100644
--- a/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc
+++ b/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc
@@ -68,9 +68,8 @@
                                test_data[i].clipboard.length());
     test_clipboard_->SetLastModifiedTime(now -
                                          base::TimeDelta::FromSeconds(10));
-    GURL url;
     EXPECT_EQ(test_data[i].expected_get_recent_url_value,
-              recent_content.GetRecentURLFromClipboard(&url))
+              recent_content.GetRecentURLFromClipboard().has_value())
         << "for input " << test_data[i].clipboard;
   }
 }
@@ -81,11 +80,10 @@
   std::string text = "http://example.com/";
   test_clipboard_->WriteText(text.data(), text.length());
   test_clipboard_->SetLastModifiedTime(now - base::TimeDelta::FromSeconds(10));
-  GURL url;
-  EXPECT_TRUE(recent_content.GetRecentURLFromClipboard(&url));
+  EXPECT_TRUE(recent_content.GetRecentURLFromClipboard().has_value());
   // If the last modified time is days ago, the URL shouldn't be suggested.
   test_clipboard_->SetLastModifiedTime(now - base::TimeDelta::FromDays(2));
-  EXPECT_FALSE(recent_content.GetRecentURLFromClipboard(&url));
+  EXPECT_FALSE(recent_content.GetRecentURLFromClipboard().has_value());
 }
 
 TEST_F(ClipboardRecentContentGenericTest, GetClipboardContentAge) {
@@ -108,16 +106,15 @@
   std::string text = "http://example.com/";
   test_clipboard_->WriteText(text.data(), text.length());
   test_clipboard_->SetLastModifiedTime(now - base::TimeDelta::FromSeconds(10));
-  GURL url;
-  EXPECT_TRUE(recent_content.GetRecentURLFromClipboard(&url));
+  EXPECT_TRUE(recent_content.GetRecentURLFromClipboard().has_value());
 
   // After suppressing it, it shouldn't be suggested.
   recent_content.SuppressClipboardContent();
-  EXPECT_FALSE(recent_content.GetRecentURLFromClipboard(&url));
+  EXPECT_FALSE(recent_content.GetRecentURLFromClipboard().has_value());
 
   // If the clipboard changes, even if to the same thing again, the content
   // should be suggested again.
   test_clipboard_->WriteText(text.data(), text.length());
   test_clipboard_->SetLastModifiedTime(now);
-  EXPECT_TRUE(recent_content.GetRecentURLFromClipboard(&url));
+  EXPECT_TRUE(recent_content.GetRecentURLFromClipboard().has_value());
 }
diff --git a/components/open_from_clipboard/clipboard_recent_content_impl_ios.h b/components/open_from_clipboard/clipboard_recent_content_impl_ios.h
index 9507df0..da54ba1 100644
--- a/components/open_from_clipboard/clipboard_recent_content_impl_ios.h
+++ b/components/open_from_clipboard/clipboard_recent_content_impl_ios.h
@@ -35,6 +35,10 @@
 // been supressed. Otherwise, returns nil.
 - (NSURL*)recentURLFromClipboard;
 
+// Returns the copied string if the clipboard contains a recent string that has
+// not been suppresed. Otherwise, returns nil.
+- (NSString*)recentTextFromClipboard;
+
 // Returns how old the content of the clipboard is.
 - (NSTimeInterval)clipboardContentAge;
 
diff --git a/components/open_from_clipboard/clipboard_recent_content_impl_ios.mm b/components/open_from_clipboard/clipboard_recent_content_impl_ios.mm
index f5b5696..f8353ea 100644
--- a/components/open_from_clipboard/clipboard_recent_content_impl_ios.mm
+++ b/components/open_from_clipboard/clipboard_recent_content_impl_ios.mm
@@ -158,6 +158,14 @@
   return [self URLFromPasteboard];
 }
 
+- (NSString*)recentTextFromClipboard {
+  [self updateIfNeeded];
+  if ([self clipboardContentAge] > self.maximumAgeOfClipboard) {
+    return nil;
+  }
+  return [UIPasteboard generalPasteboard].string;
+}
+
 - (NSTimeInterval)clipboardContentAge {
   return -[self.lastPasteboardChangeDate timeIntervalSinceNow];
 }
@@ -185,9 +193,7 @@
 }
 
 - (NSURL*)URLFromPasteboard {
-  NSString* clipboardString = [UIPasteboard generalPasteboard].string;
-
-  NSURL* url = [NSURL URLWithString:clipboardString];
+  NSURL* url = [UIPasteboard generalPasteboard].URL;
   if (![self.authorizedSchemes containsObject:url.scheme]) {
     return nil;
   }
diff --git a/components/open_from_clipboard/clipboard_recent_content_ios.h b/components/open_from_clipboard/clipboard_recent_content_ios.h
index abbf5101..dadc619 100644
--- a/components/open_from_clipboard/clipboard_recent_content_ios.h
+++ b/components/open_from_clipboard/clipboard_recent_content_ios.h
@@ -38,7 +38,8 @@
   ~ClipboardRecentContentIOS() override;
 
   // ClipboardRecentContent implementation.
-  bool GetRecentURLFromClipboard(GURL* url) override;
+  base::Optional<GURL> GetRecentURLFromClipboard() override;
+  base::Optional<base::string16> GetRecentTextFromClipboard() override;
   base::TimeDelta GetClipboardContentAge() const override;
   void SuppressClipboardContent() override;
 
diff --git a/components/open_from_clipboard/clipboard_recent_content_ios.mm b/components/open_from_clipboard/clipboard_recent_content_ios.mm
index 49cb850..ac6d132 100644
--- a/components/open_from_clipboard/clipboard_recent_content_ios.mm
+++ b/components/open_from_clipboard/clipboard_recent_content_ios.mm
@@ -69,15 +69,24 @@
   implementation_.reset(implementation);
 }
 
-bool ClipboardRecentContentIOS::GetRecentURLFromClipboard(GURL* url) {
-  DCHECK(url);
+base::Optional<GURL> ClipboardRecentContentIOS::GetRecentURLFromClipboard() {
   NSURL* url_from_pasteboard = [implementation_ recentURLFromClipboard];
   GURL converted_url = net::GURLWithNSURL(url_from_pasteboard);
-  if (converted_url.is_valid()) {
-    *url = std::move(converted_url);
-    return true;
+  if (!converted_url.is_valid()) {
+    return base::nullopt;
   }
-  return false;
+
+  return converted_url;
+}
+
+base::Optional<base::string16>
+ClipboardRecentContentIOS::GetRecentTextFromClipboard() {
+  NSString* text_from_pasteboard = [implementation_ recentTextFromClipboard];
+  if (!text_from_pasteboard) {
+    return base::nullopt;
+  }
+
+  return base::SysNSStringToUTF16(text_from_pasteboard);
 }
 
 ClipboardRecentContentIOS::~ClipboardRecentContentIOS() {}
diff --git a/components/open_from_clipboard/clipboard_recent_content_ios_unittest.mm b/components/open_from_clipboard/clipboard_recent_content_ios_unittest.mm
index 95a3d1ec..d11f6a9 100644
--- a/components/open_from_clipboard/clipboard_recent_content_ios_unittest.mm
+++ b/components/open_from_clipboard/clipboard_recent_content_ios_unittest.mm
@@ -10,6 +10,7 @@
 #include <memory>
 
 #include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #import "components/open_from_clipboard/clipboard_recent_content_impl_ios.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
@@ -132,107 +133,131 @@
   std::unique_ptr<ClipboardRecentContentIOSWithFakeUptime> clipboard_content_;
   ClipboardRecentContentImplIOSWithFakeUptime*
       clipboard_content_implementation_;
+
+  void VerifyClipboardURLExists(const char* expected_url) {
+    base::Optional<GURL> optional_gurl =
+        clipboard_content_->GetRecentURLFromClipboard();
+    EXPECT_TRUE(optional_gurl.has_value());
+    EXPECT_STREQ(expected_url, optional_gurl.value().spec().c_str());
+  }
+
+  void VerifyClipboardURLDoesNotExist() {
+    EXPECT_FALSE(clipboard_content_->GetRecentURLFromClipboard().has_value());
+  }
+
+  void VerifyClipboardTextExists(const char* expected_text) {
+    base::Optional<base::string16> optional_text =
+        clipboard_content_->GetRecentTextFromClipboard();
+    EXPECT_TRUE(optional_text.has_value());
+    EXPECT_STREQ(expected_text,
+                 base::UTF16ToUTF8(optional_text.value()).c_str());
+  }
+
+  void VerifyClipboardTextDoesNotExist() {
+    EXPECT_FALSE(clipboard_content_->GetRecentTextFromClipboard().has_value());
+  }
 };
 
 TEST_F(ClipboardRecentContentIOSTest, SchemeFiltering) {
-  GURL gurl;
-
   // Test unrecognized URL.
   SetPasteboardContent(kUnrecognizedURL);
-  EXPECT_FALSE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
+  VerifyClipboardURLDoesNotExist();
 
   // Test recognized URL.
   SetPasteboardContent(kRecognizedURL);
-  EXPECT_TRUE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
-  EXPECT_STREQ(kRecognizedURL, gurl.spec().c_str());
+  VerifyClipboardURLExists(kRecognizedURL);
 
   // Test URL with app specific scheme.
   SetPasteboardContent(kAppSpecificURL);
-  EXPECT_TRUE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
-  EXPECT_STREQ(kAppSpecificURL, gurl.spec().c_str());
+  VerifyClipboardURLExists(kAppSpecificURL);
 
   // Test URL without app specific scheme.
   ResetClipboardRecentContent(std::string(), base::TimeDelta::FromDays(10));
 
   SetPasteboardContent(kAppSpecificURL);
-  EXPECT_FALSE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
+  VerifyClipboardURLDoesNotExist();
 }
 
 TEST_F(ClipboardRecentContentIOSTest, PasteboardURLObsolescence) {
-  GURL gurl;
   SetPasteboardContent(kRecognizedURL);
 
   // Test that recent pasteboard data is provided.
-  EXPECT_TRUE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
-  EXPECT_STREQ(kRecognizedURL, gurl.spec().c_str());
+  VerifyClipboardURLExists(kRecognizedURL);
+  VerifyClipboardTextExists(kRecognizedURL);
 
   // Test that old pasteboard data is not provided.
   SetStoredPasteboardChangeDate(
       [NSDate dateWithTimeIntervalSinceNow:-kLongerThanMaxAge]);
-  EXPECT_FALSE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
+  VerifyClipboardURLDoesNotExist();
+  VerifyClipboardTextDoesNotExist();
 
   // Tests that if chrome is relaunched, old pasteboard data is still
   // not provided.
   ResetClipboardRecentContent(kAppSpecificScheme,
                               base::TimeDelta::FromDays(10));
-  EXPECT_FALSE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
+  VerifyClipboardURLDoesNotExist();
+  VerifyClipboardTextDoesNotExist();
 
   SimulateDeviceRestart();
   // Tests that if the device is restarted, old pasteboard data is still
   // not provided.
-  EXPECT_FALSE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
+  VerifyClipboardURLDoesNotExist();
+  VerifyClipboardTextDoesNotExist();
 }
 
 TEST_F(ClipboardRecentContentIOSTest, SupressedPasteboard) {
-  GURL gurl;
   SetPasteboardContent(kRecognizedURL);
 
   // Test that recent pasteboard data is provided.
-  EXPECT_TRUE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
+  VerifyClipboardURLExists(kRecognizedURL);
+  VerifyClipboardTextExists(kRecognizedURL);
 
   // Suppress the content of the pasteboard.
   clipboard_content_->SuppressClipboardContent();
 
   // Check that the pasteboard content is suppressed.
-  EXPECT_FALSE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
+  VerifyClipboardURLDoesNotExist();
+  VerifyClipboardTextDoesNotExist();
 
   // Create a new clipboard content to test persistence.
   ResetClipboardRecentContent(kAppSpecificScheme,
                               base::TimeDelta::FromDays(10));
 
   // Check that the pasteboard content is still suppressed.
-  EXPECT_FALSE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
+  VerifyClipboardURLDoesNotExist();
+  VerifyClipboardTextDoesNotExist();
 
   // Check that even if the device is restarted, pasteboard content is
   // still suppressed.
   SimulateDeviceRestart();
-  EXPECT_FALSE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
+  VerifyClipboardURLDoesNotExist();
+  VerifyClipboardTextDoesNotExist();
 
   // Check that if the pasteboard changes, the new content is not
   // supressed anymore.
   SetPasteboardContent(kRecognizedURL2);
-  EXPECT_TRUE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
+  VerifyClipboardURLExists(kRecognizedURL2);
+  VerifyClipboardTextExists(kRecognizedURL2);
 }
 
 // Checks that if user copies something other than a string we don't cache the
 // string in pasteboard.
 TEST_F(ClipboardRecentContentIOSTest, AddingNonStringRemovesCachedString) {
-  GURL gurl;
   SetPasteboardContent(kRecognizedURL);
 
-  // Test that recent pasteboard data is provided.
-  EXPECT_TRUE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
-  EXPECT_STREQ(kRecognizedURL, gurl.spec().c_str());
+  // Test that recent pasteboard data is provided as text and url.
+  VerifyClipboardURLExists(kRecognizedURL);
+  VerifyClipboardTextExists(kRecognizedURL);
 
   // Overwrite pasteboard with an image.
-  base::scoped_nsobject<UIImage> image([[UIImage alloc] init]);
   SetPasteboardImage(TestUIImage());
 
-  // Pasteboard should appear empty.
-  EXPECT_FALSE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
+  // Url and text pasteboard should appear empty.
+  VerifyClipboardURLDoesNotExist();
+  VerifyClipboardTextDoesNotExist();
 
   // Tests that if URL is added again, pasteboard provides it normally.
   SetPasteboardContent(kRecognizedURL);
-  EXPECT_TRUE(clipboard_content_->GetRecentURLFromClipboard(&gurl));
-  EXPECT_STREQ(kRecognizedURL, gurl.spec().c_str());
+  VerifyClipboardURLExists(kRecognizedURL);
+  VerifyClipboardTextExists(kRecognizedURL);
 }
diff --git a/components/open_from_clipboard/fake_clipboard_recent_content.cc b/components/open_from_clipboard/fake_clipboard_recent_content.cc
index 87e5627..7a531ce4 100644
--- a/components/open_from_clipboard/fake_clipboard_recent_content.cc
+++ b/components/open_from_clipboard/fake_clipboard_recent_content.cc
@@ -9,15 +9,19 @@
 
 FakeClipboardRecentContent::~FakeClipboardRecentContent() {}
 
-bool FakeClipboardRecentContent::GetRecentURLFromClipboard(GURL* url) {
+base::Optional<GURL> FakeClipboardRecentContent::GetRecentURLFromClipboard() {
   if (suppress_content_)
-    return false;
+    return base::nullopt;
 
-  if (!clipboard_content_.is_valid())
-    return false;
+  return clipboard_url_content_;
+}
 
-  *url = clipboard_content_;
-  return true;
+base::Optional<base::string16>
+FakeClipboardRecentContent::GetRecentTextFromClipboard() {
+  if (suppress_content_)
+    return base::nullopt;
+
+  return clipboard_text_content_;
 }
 
 base::TimeDelta FakeClipboardRecentContent::GetClipboardContentAge() const {
@@ -28,10 +32,19 @@
   suppress_content_ = true;
 }
 
-void FakeClipboardRecentContent::SetClipboardContent(
-    const GURL& url,
-    base::TimeDelta content_age) {
-  clipboard_content_ = url;
+void FakeClipboardRecentContent::SetClipboardURL(const GURL& url,
+                                                 base::TimeDelta content_age) {
+  DCHECK(url.is_valid());
+  clipboard_url_content_ = url;
+  clipboard_text_content_ = base::nullopt;
+  content_age_ = content_age;
+  suppress_content_ = false;
+}
+
+void FakeClipboardRecentContent::SetClipboardText(const base::string16& text,
+                                                  base::TimeDelta content_age) {
+  clipboard_url_content_ = base::nullopt;
+  clipboard_text_content_ = text;
   content_age_ = content_age;
   suppress_content_ = false;
 }
diff --git a/components/open_from_clipboard/fake_clipboard_recent_content.h b/components/open_from_clipboard/fake_clipboard_recent_content.h
index 05c8a3fd..c1170dc 100644
--- a/components/open_from_clipboard/fake_clipboard_recent_content.h
+++ b/components/open_from_clipboard/fake_clipboard_recent_content.h
@@ -18,15 +18,20 @@
   ~FakeClipboardRecentContent() override;
 
   // ClipboardRecentContent implementation.
-  bool GetRecentURLFromClipboard(GURL* url) override;
+  base::Optional<GURL> GetRecentURLFromClipboard() override;
+  base::Optional<base::string16> GetRecentTextFromClipboard() override;
   base::TimeDelta GetClipboardContentAge() const override;
   void SuppressClipboardContent() override;
 
-  // Sets the URL and clipboard content age.
-  void SetClipboardContent(const GURL& url, base::TimeDelta content_age);
+  // Sets the URL and clipboard content age. This clears the text
+  void SetClipboardURL(const GURL& url, base::TimeDelta content_age);
+  // Sets the text and clipboard content age. This clears the url.
+  void SetClipboardText(const base::string16& text,
+                        base::TimeDelta content_age);
 
  private:
-  GURL clipboard_content_;
+  base::Optional<GURL> clipboard_url_content_;
+  base::Optional<base::string16> clipboard_text_content_;
   base::TimeDelta content_age_;
   bool suppress_content_;
 
diff --git a/components/previews/content/previews_decider_impl.cc b/components/previews/content/previews_decider_impl.cc
index 715ee4a..48e7483 100644
--- a/components/previews/content/previews_decider_impl.cc
+++ b/components/previews/content/previews_decider_impl.cc
@@ -48,6 +48,9 @@
 void LogTriggeredPreviewEffectiveConnectionType(
     net::EffectiveConnectionType navigation_ect,
     PreviewsType type) {
+  UMA_HISTOGRAM_ENUMERATION("Previews.Triggered.EffectiveConnectionType",
+                            navigation_ect,
+                            net::EFFECTIVE_CONNECTION_TYPE_LAST);
   int32_t max_limit = static_cast<int32_t>(net::EFFECTIVE_CONNECTION_TYPE_LAST);
   base::LinearHistogram::FactoryGet(
       base::StringPrintf("Previews.Triggered.EffectiveConnectionType.%s",
@@ -406,6 +409,9 @@
       return false;
     }
   }
+
+  LogTriggeredPreviewEffectiveConnectionType(previews_data->navigation_ect(),
+                                             type);
   return true;
 }
 
@@ -509,10 +515,6 @@
   }
   passed_reasons->push_back(
       PreviewsEligibilityReason::NETWORK_NOT_SLOW_FOR_SESSION);
-
-  LogTriggeredPreviewEffectiveConnectionType(previews_data->navigation_ect(),
-                                             type);
-
   return PreviewsEligibilityReason::ALLOWED;
 }
 
diff --git a/components/previews/content/previews_decider_impl_unittest.cc b/components/previews/content/previews_decider_impl_unittest.cc
index 5c0cb84..d6fed74 100644
--- a/components/previews/content/previews_decider_impl_unittest.cc
+++ b/components/previews/content/previews_decider_impl_unittest.cc
@@ -937,6 +937,9 @@
 
     // Triggered ECT logged.
     histogram_tester.ExpectUniqueSample(
+        "Previews.Triggered.EffectiveConnectionType",
+        static_cast<int>(net::EFFECTIVE_CONNECTION_TYPE_2G), 1);
+    histogram_tester.ExpectUniqueSample(
         "Previews.Triggered.EffectiveConnectionType.NoScript",
         static_cast<int>(net::EFFECTIVE_CONNECTION_TYPE_2G), 1);
   }
@@ -1192,6 +1195,9 @@
 
     // Triggered ECT logged.
     histogram_tester.ExpectUniqueSample(
+        "Previews.Triggered.EffectiveConnectionType",
+        static_cast<int>(net::EFFECTIVE_CONNECTION_TYPE_2G), 1);
+    histogram_tester.ExpectUniqueSample(
         "Previews.Triggered.EffectiveConnectionType.ResourceLoadingHints",
         static_cast<int>(net::EFFECTIVE_CONNECTION_TYPE_2G), 1);
   }
diff --git a/components/services/heap_profiling/public/cpp/settings.cc b/components/services/heap_profiling/public/cpp/settings.cc
index 7b08ff8..933146d 100644
--- a/components/services/heap_profiling/public/cpp/settings.cc
+++ b/components/services/heap_profiling/public/cpp/settings.cc
@@ -25,8 +25,8 @@
 const char kOOPHeapProfilingFeatureSampling[] = "sampling";
 const char kOOPHeapProfilingFeatureSamplingRate[] = "sampling-rate";
 
-const uint32_t kDefaultSamplingRate = 10000;
-const bool kDefaultShouldSample = false;
+const uint32_t kDefaultSamplingRate = 100000;
+const bool kDefaultShouldSample = true;
 
 bool RecordAllAllocationsForStartup() {
   const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java
index 5f4cc8d..3feda0e 100644
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java
@@ -20,6 +20,7 @@
 import android.support.annotation.AnyThread;
 import android.support.annotation.MainThread;
 import android.support.annotation.Nullable;
+import android.support.annotation.WorkerThread;
 
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
@@ -30,7 +31,6 @@
 import org.chromium.base.metrics.CachedMetrics;
 import org.chromium.base.task.AsyncTask;
 import org.chromium.components.signin.util.PatternMatcher;
-import org.chromium.net.NetworkChangeNotifier;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -39,8 +39,6 @@
 import java.util.Locale;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Pattern;
 
@@ -100,26 +98,6 @@
     private final ArrayList<Runnable> mCallbacksWaitingForPendingUpdates = new ArrayList<>();
 
     /**
-     * A simple callback for getAuthToken.
-     */
-    public interface GetAuthTokenCallback {
-        /**
-         * Invoked on the UI thread if a token is provided by the AccountManager.
-         *
-         * @param token Auth token, guaranteed not to be null.
-         */
-        void tokenAvailable(String token);
-
-        /**
-         * Invoked on the UI thread if no token is available.
-         *
-         * @param isTransientError Indicates if the error is transient (network timeout or
-         * unavailable, etc) or persistent (bad credentials, permission denied, etc).
-         */
-        void tokenUnavailable(boolean isTransientError);
-    }
-
-    /**
      * @param delegate the AccountManagerDelegate to use as a backend
      */
     private AccountManagerFacade(AccountManagerDelegate delegate) {
@@ -451,64 +429,30 @@
     }
 
     /**
-     * Gets the auth token and returns the response asynchronously.
-     * This should be called when we have a foreground activity that needs an auth token.
-     * If encountered an IO error, it will attempt to retry when the network is back.
-     *
-     * - Assumes that the account is a valid account.
+     * Synchronously gets an OAuth2 access token. May return a cached version, use
+     * {@link #invalidateAccessToken} to invalidate a token in the cache.
+     * @param account The {@link Account} for which the token is requested.
+     * @param scope OAuth2 scope for which the requested token should be valid.
+     * @return The OAuth2 access token as a string.
      */
-    @MainThread
-    public void getAuthToken(final Account account, final String authTokenType,
-            final GetAuthTokenCallback callback) {
-        ConnectionRetry.runAuthTask(new AuthTask<String>() {
-            @Override
-            public String run() throws AuthException {
-                return mDelegate.getAuthToken(account, authTokenType);
-            }
-            @Override
-            public void onSuccess(String token) {
-                callback.tokenAvailable(token);
-            }
-            @Override
-            public void onFailure(boolean isTransientError) {
-                callback.tokenUnavailable(isTransientError);
-            }
-        });
+    @WorkerThread
+    String getAccessToken(Account account, String scope) throws AuthException {
+        assert account != null;
+        assert scope != null;
+        // TODO(bsazonov): Rename delegate's getAuthToken to getAccessToken.
+        return mDelegate.getAuthToken(account, scope);
     }
 
     /**
-     * Invalidates the old token (if non-null/non-empty) and asynchronously generates a new one.
-     *
-     * - Assumes that the account is a valid account.
+     * Synchronously clears an OAuth2 access token from the cache. Use {@link #getAccessToken}
+     * to issue a new token after invalidating the old one.
+     * @param accessToken The access token to invalidate.
      */
-    @MainThread
-    public void getNewAuthToken(Account account, String authToken, String authTokenType,
-            GetAuthTokenCallback callback) {
-        invalidateAuthToken(authToken);
-        getAuthToken(account, authTokenType, callback);
-    }
-
-    /**
-     * Clear an auth token from the local cache with respect to the ApplicationContext.
-     */
-    @MainThread
-    public void invalidateAuthToken(final String authToken) {
-        if (authToken == null || authToken.isEmpty()) {
-            return;
-        }
-        ConnectionRetry.runAuthTask(new AuthTask<Boolean>() {
-            @Override
-            public Boolean run() throws AuthException {
-                mDelegate.invalidateAuthToken(authToken);
-                return true;
-            }
-            @Override
-            public void onSuccess(Boolean result) {}
-            @Override
-            public void onFailure(boolean isTransientError) {
-                Log.e(TAG, "Failed to invalidate auth token: " + authToken);
-            }
-        });
+    @WorkerThread
+    void invalidateAccessToken(String accessToken) throws AuthException {
+        assert accessToken != null;
+        // TODO(bsazonov): Rename delegate's invalidateAuthToken to invalidateAccessToken.
+        mDelegate.invalidateAuthToken(accessToken);
     }
 
     // Incorrectly infers that this is called on a worker thread because of AsyncTask doInBackground
@@ -763,83 +707,4 @@
             decrementUpdateCounter();
         }
     }
-
-    private interface AuthTask<T> {
-        T run() throws AuthException;
-        void onSuccess(T result);
-        void onFailure(boolean isTransientError);
-    }
-
-    /**
-     * A helper class to encapsulate network connection retry logic for AuthTasks.
-     *
-     * The task will be run on the background thread. If it encounters a transient error, it will
-     * wait for a network change and retry up to MAX_TRIES times.
-     */
-    private static class ConnectionRetry<T>
-            implements NetworkChangeNotifier.ConnectionTypeObserver {
-        private static final int MAX_TRIES = 3;
-
-        private final AuthTask<T> mAuthTask;
-        private final AtomicInteger mNumTries;
-        private final AtomicBoolean mIsTransientError;
-
-        public static <T> void runAuthTask(AuthTask<T> authTask) {
-            new ConnectionRetry<>(authTask).attempt();
-        }
-
-        private ConnectionRetry(AuthTask<T> authTask) {
-            mAuthTask = authTask;
-            mNumTries = new AtomicInteger(0);
-            mIsTransientError = new AtomicBoolean(false);
-        }
-
-        /**
-         * Tries running the {@link AuthTask} in the background. This object is never registered
-         * as a {@link NetworkChangeNotifier.ConnectionTypeObserver} when this method is called.
-         */
-        private void attempt() {
-            ThreadUtils.assertOnUiThread();
-            // Clear any transient error.
-            mIsTransientError.set(false);
-            new AsyncTask<T>() {
-                @Override
-                public T doInBackground() {
-                    try {
-                        return mAuthTask.run();
-                    } catch (AuthException ex) {
-                        Log.w(TAG, "Failed to perform auth task: %s", ex.stringifyCausalChain());
-                        Log.d(TAG, "Exception details:", ex);
-                        mIsTransientError.set(ex.isTransientError());
-                    }
-                    return null;
-                }
-                @Override
-                public void onPostExecute(T result) {
-                    if (result != null) {
-                        mAuthTask.onSuccess(result);
-                    } else if (!mIsTransientError.get() || mNumTries.incrementAndGet() >= MAX_TRIES
-                            || !NetworkChangeNotifier.isInitialized()) {
-                        // Permanent error, ran out of tries, or we can't listen for network
-                        // change events; give up.
-                        mAuthTask.onFailure(mIsTransientError.get());
-                    } else {
-                        // Transient error with tries left; register for another attempt.
-                        NetworkChangeNotifier.addConnectionTypeObserver(ConnectionRetry.this);
-                    }
-                }
-            }
-                    .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
-        }
-
-        @Override
-        public void onConnectionTypeChanged(int connectionType) {
-            assert mNumTries.get() < MAX_TRIES;
-            if (NetworkChangeNotifier.isOnline()) {
-                // The network is back; stop listening and try again.
-                NetworkChangeNotifier.removeConnectionTypeObserver(this);
-                attempt();
-            }
-        }
-    }
 }
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
index 0b52d30..c1f25744 100644
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/OAuth2TokenService.java
@@ -5,8 +5,9 @@
 package org.chromium.components.signin;
 
 import android.accounts.Account;
-import android.content.Context;
 import android.support.annotation.MainThread;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
@@ -15,6 +16,8 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.task.AsyncTask;
+import org.chromium.net.NetworkChangeNotifier;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -22,6 +25,8 @@
 import java.util.Set;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
@@ -39,6 +44,26 @@
     public static final String STORED_ACCOUNTS_KEY = "google.services.stored_accounts";
 
     /**
+     * A simple callback for getAccessToken.
+     */
+    public interface GetAccessTokenCallback {
+        /**
+         * Invoked on the UI thread if a token is provided by the AccountManager.
+         *
+         * @param token Access token, guaranteed not to be null.
+         */
+        void onGetTokenSuccess(String token);
+
+        /**
+         * Invoked on the UI thread if no token is available.
+         *
+         * @param isTransientError Indicates if the error is transient (network timeout or
+         * unavailable, etc) or persistent (bad credentials, permission denied, etc).
+         */
+        void onGetTokenFailure(boolean isTransientError);
+    }
+
+    /**
      * Classes that want to listen for refresh token availability should
      * implement this interface and register with {@link #addObserver}.
      */
@@ -126,13 +151,13 @@
 
     /**
      * Called by native to retrieve OAuth2 tokens.
-     *  @param username The native username (full address).
+     * @param username The native username (email address).
      * @param scope The scope to get an auth token for (without Android-style 'oauth2:' prefix).
      * @param nativeCallback The pointer to the native callback that should be run upon completion.
      */
     @MainThread
     @CalledByNative
-    public static void getOAuth2AuthToken(
+    private static void getAccessTokenFromNative(
             String username, String scope, final long nativeCallback) {
         Account account = getAccountOrNullFromUsername(username);
         if (account == null) {
@@ -140,34 +165,96 @@
             return;
         }
         String oauth2Scope = OAUTH2_SCOPE_PREFIX + scope;
+        getAccessToken(account, oauth2Scope, new GetAccessTokenCallback() {
+            @Override
+            public void onGetTokenSuccess(String token) {
+                nativeOAuth2TokenFetched(token, false, nativeCallback);
+            }
 
-        AccountManagerFacade accountManagerFacade = AccountManagerFacade.get();
-        accountManagerFacade.getAuthToken(
-                account, oauth2Scope, new AccountManagerFacade.GetAuthTokenCallback() {
-                    @Override
-                    public void tokenAvailable(String token) {
-                        nativeOAuth2TokenFetched(token, false, nativeCallback);
-                    }
-
-                    @Override
-                    public void tokenUnavailable(boolean isTransientError) {
-                        nativeOAuth2TokenFetched(null, isTransientError, nativeCallback);
-                    }
-                });
+            @Override
+            public void onGetTokenFailure(boolean isTransientError) {
+                nativeOAuth2TokenFetched(null, isTransientError, nativeCallback);
+            }
+        });
     }
 
     /**
-     * Call this method to retrieve an OAuth2 access token for the given account and scope.
-     *
+     * Call this method to retrieve an OAuth2 access token for the given account and scope. Please
+     * note that this method expects a scope with 'oauth2:' prefix.
      * @param account the account to get the access token for.
-     * @param scope The scope to get an auth token for (without Android-style 'oauth2:' prefix).
+     * @param scope The scope to get an auth token for (with Android-style 'oauth2:' prefix).
      * @param callback called on successful and unsuccessful fetching of auth token.
      */
     @MainThread
-    public static void getOAuth2AccessToken(Context context, Account account, String scope,
-            AccountManagerFacade.GetAuthTokenCallback callback) {
-        String oauth2Scope = OAUTH2_SCOPE_PREFIX + scope;
-        AccountManagerFacade.get().getAuthToken(account, oauth2Scope, callback);
+    public static void getAccessToken(
+            Account account, String scope, GetAccessTokenCallback callback) {
+        ConnectionRetry.runAuthTask(new AuthTask<String>() {
+            @Override
+            public String run() throws AuthException {
+                return AccountManagerFacade.get().getAccessToken(account, scope);
+            }
+            @Override
+            public void onSuccess(String token) {
+                callback.onGetTokenSuccess(token);
+            }
+            @Override
+            public void onFailure(boolean isTransientError) {
+                callback.onGetTokenFailure(isTransientError);
+            }
+        });
+    }
+
+    /**
+     * Called by native to invalidate an OAuth2 token. Please note that the token is invalidated
+     * asynchronously.
+     */
+    @MainThread
+    @CalledByNative
+    public static void invalidateAccessToken(String accessToken) {
+        if (TextUtils.isEmpty(accessToken)) {
+            return;
+        }
+        ConnectionRetry.runAuthTask(new AuthTask<Boolean>() {
+            @Override
+            public Boolean run() throws AuthException {
+                AccountManagerFacade.get().invalidateAccessToken(accessToken);
+                return true;
+            }
+            @Override
+            public void onSuccess(Boolean result) {}
+            @Override
+            public void onFailure(boolean isTransientError) {
+                Log.e(TAG, "Failed to invalidate auth token: " + accessToken);
+            }
+        });
+    }
+
+    /**
+     * Invalidates the old token (if non-null/non-empty) and asynchronously generates a new one.
+     * @param account the account to get the access token for.
+     * @param oldToken The old token to be invalidated or null.
+     * @param scope The scope to get an auth token for (with Android-style 'oauth2:' prefix).
+     * @param callback called on successful and unsuccessful fetching of auth token.
+     */
+    public static void getNewAccessToken(Account account, @Nullable String oldToken, String scope,
+            GetAccessTokenCallback callback) {
+        ConnectionRetry.runAuthTask(new AuthTask<String>() {
+            @Override
+            public String run() throws AuthException {
+                if (!TextUtils.isEmpty(oldToken)) {
+                    AccountManagerFacade.get().invalidateAccessToken(oldToken);
+                }
+                return AccountManagerFacade.get().getAccessToken(account, scope);
+            }
+            @Override
+            public void onSuccess(String token) {
+                callback.onGetTokenSuccess(token);
+            }
+            @Override
+            public void onFailure(boolean isTransientError) {
+                callback.onGetTokenFailure(isTransientError);
+            }
+        });
     }
 
     /**
@@ -182,25 +269,24 @@
      * @param unit the unit for |timeout|.
      */
     @VisibleForTesting
-    public static String getOAuth2AccessTokenWithTimeout(
-            Context context, Account account, String scope, long timeout, TimeUnit unit) {
+    public static String getAccessTokenWithTimeout(
+            Account account, String scope, long timeout, TimeUnit unit) {
         assert !ThreadUtils.runningOnUiThread();
         final AtomicReference<String> result = new AtomicReference<>();
         final Semaphore semaphore = new Semaphore(0);
-        getOAuth2AccessToken(
-                context, account, scope, new AccountManagerFacade.GetAuthTokenCallback() {
-                    @Override
-                    public void tokenAvailable(String token) {
-                        result.set(token);
-                        semaphore.release();
-                    }
+        getAccessToken(account, scope, new GetAccessTokenCallback() {
+            @Override
+            public void onGetTokenSuccess(String token) {
+                result.set(token);
+                semaphore.release();
+            }
 
-                    @Override
-                    public void tokenUnavailable(boolean isTransientError) {
-                        result.set(null);
-                        semaphore.release();
-                    }
-                });
+            @Override
+            public void onGetTokenFailure(boolean isTransientError) {
+                result.set(null);
+                semaphore.release();
+            }
+        });
         try {
             if (semaphore.tryAcquire(timeout, unit)) {
                 return result.get();
@@ -232,16 +318,6 @@
     }
 
     /**
-     * Called by native to invalidate an OAuth2 token.
-     */
-    @CalledByNative
-    public static void invalidateOAuth2AuthToken(String accessToken) {
-        if (accessToken != null) {
-            AccountManagerFacade.get().invalidateAuthToken(accessToken);
-        }
-    }
-
-    /**
      * Continue pending accounts validation after system accounts have been seeded into
      * AccountTrackerService.
      */
@@ -339,6 +415,84 @@
                 .apply();
     }
 
+    private interface AuthTask<T> {
+        T run() throws AuthException;
+        void onSuccess(T result);
+        void onFailure(boolean isTransientError);
+    }
+
+    /**
+     * A helper class to encapsulate network connection retry logic for AuthTasks.
+     *
+     * The task will be run on the background thread. If it encounters a transient error, it will
+     * wait for a network change and retry up to MAX_TRIES times.
+     */
+    private static class ConnectionRetry<T>
+            implements NetworkChangeNotifier.ConnectionTypeObserver {
+        private static final int MAX_TRIES = 3;
+
+        private final AuthTask<T> mAuthTask;
+        private final AtomicInteger mNumTries;
+        private final AtomicBoolean mIsTransientError;
+
+        public static <T> void runAuthTask(AuthTask<T> authTask) {
+            new ConnectionRetry<>(authTask).attempt();
+        }
+
+        private ConnectionRetry(AuthTask<T> authTask) {
+            mAuthTask = authTask;
+            mNumTries = new AtomicInteger(0);
+            mIsTransientError = new AtomicBoolean(false);
+        }
+
+        /**
+         * Tries running the {@link AuthTask} in the background. This object is never registered
+         * as a {@link NetworkChangeNotifier.ConnectionTypeObserver} when this method is called.
+         */
+        private void attempt() {
+            ThreadUtils.assertOnUiThread();
+            // Clear any transient error.
+            mIsTransientError.set(false);
+            new AsyncTask<T>() {
+                @Override
+                public T doInBackground() {
+                    try {
+                        return mAuthTask.run();
+                    } catch (AuthException ex) {
+                        Log.w(TAG, "Failed to perform auth task: %s", ex.stringifyCausalChain());
+                        Log.d(TAG, "Exception details:", ex);
+                        mIsTransientError.set(ex.isTransientError());
+                    }
+                    return null;
+                }
+                @Override
+                public void onPostExecute(T result) {
+                    if (result != null) {
+                        mAuthTask.onSuccess(result);
+                    } else if (!mIsTransientError.get() || mNumTries.incrementAndGet() >= MAX_TRIES
+                            || !NetworkChangeNotifier.isInitialized()) {
+                        // Permanent error, ran out of tries, or we can't listen for network
+                        // change events; give up.
+                        mAuthTask.onFailure(mIsTransientError.get());
+                    } else {
+                        // Transient error with tries left; register for another attempt.
+                        NetworkChangeNotifier.addConnectionTypeObserver(ConnectionRetry.this);
+                    }
+                }
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        }
+
+        @Override
+        public void onConnectionTypeChanged(int connectionType) {
+            assert mNumTries.get() < MAX_TRIES;
+            if (NetworkChangeNotifier.isOnline()) {
+                // The network is back; stop listening and try again.
+                NetworkChangeNotifier.removeConnectionTypeObserver(this);
+                attempt();
+            }
+        }
+    }
+
     private static native void nativeOAuth2TokenFetched(
             String authToken, boolean isTransientError, long nativeCallback);
     private native void nativeValidateAccounts(long nativeOAuth2TokenServiceDelegateAndroid,
diff --git a/components/signin/core/browser/oauth2_token_service_delegate_android.cc b/components/signin/core/browser/oauth2_token_service_delegate_android.cc
index dcc990b..0d872ed 100644
--- a/components/signin/core/browser/oauth2_token_service_delegate_android.cc
+++ b/components/signin/core/browser/oauth2_token_service_delegate_android.cc
@@ -87,7 +87,7 @@
                      weak_factory_.GetWeakPtr())));
 
   // Call into Java to get a new token.
-  Java_OAuth2TokenService_getOAuth2AuthToken(
+  Java_OAuth2TokenService_getAccessTokenFromNative(
       env, j_username, j_scope,
       reinterpret_cast<intptr_t>(heap_callback.release()));
 }
@@ -264,7 +264,7 @@
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jstring> j_access_token =
       ConvertUTF8ToJavaString(env, access_token);
-  Java_OAuth2TokenService_invalidateOAuth2AuthToken(env, j_access_token);
+  Java_OAuth2TokenService_invalidateAccessToken(env, j_access_token);
 }
 
 void OAuth2TokenServiceDelegateAndroid::ValidateAccounts(
diff --git a/components/sync/android/java/src/org/chromium/components/sync/SyncConstants.java b/components/sync/android/java/src/org/chromium/components/sync/SyncConstants.java
index 6b639dfa8..38df034 100644
--- a/components/sync/android/java/src/org/chromium/components/sync/SyncConstants.java
+++ b/components/sync/android/java/src/org/chromium/components/sync/SyncConstants.java
@@ -8,7 +8,7 @@
 public final class SyncConstants {
     // This should always have the same value as GaiaConstants::kChromeSyncOAuth2Scope.
     public static final String CHROME_SYNC_OAUTH2_SCOPE =
-            "https://www.googleapis.com/auth/chromesync";
+            "oauth2:https://www.googleapis.com/auth/chromesync";
 
     // This should always have the same value as TabNodePool::kInvalidTabNodeID.
     public static final int INVALID_TAB_NODE_ID = -1;
diff --git a/content/BUILD.gn b/content/BUILD.gn
index 0ca39d7..bce6285 100644
--- a/content/BUILD.gn
+++ b/content/BUILD.gn
@@ -2,9 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//tools/grit/grit_rule.gni")
 import("//build/config/nacl/config.gni")
 import("//ppapi/buildflags/buildflags.gni")
+import("//tools/grit/grit_rule.gni")
 
 # Applied by targets internal to content.
 config("content_implementation") {
@@ -128,7 +128,6 @@
     "//content/public/app:plugin_manifest",
     "//content/public/app:renderer_manifest",
     "//content/public/app:utility_manifest",
-    "//services/catalog:manifest",
   ]
 }
 
diff --git a/content/app/content_service_manager_main_delegate.cc b/content/app/content_service_manager_main_delegate.cc
index fc86a74..3a6bc4e 100644
--- a/content/app/content_service_manager_main_delegate.cc
+++ b/content/app/content_service_manager_main_delegate.cc
@@ -74,9 +74,9 @@
     config->is_broker_process = true;
 }
 
-std::unique_ptr<base::Value>
-ContentServiceManagerMainDelegate::CreateServiceCatalog() {
-  return nullptr;
+std::vector<service_manager::Manifest>
+ContentServiceManagerMainDelegate::GetServiceManifests() {
+  return std::vector<service_manager::Manifest>();
 }
 
 bool ContentServiceManagerMainDelegate::ShouldLaunchAsServiceProcess(
diff --git a/content/app/content_service_manager_main_delegate.h b/content/app/content_service_manager_main_delegate.h
index 6f32f97..864f2a5 100644
--- a/content/app/content_service_manager_main_delegate.h
+++ b/content/app/content_service_manager_main_delegate.h
@@ -30,7 +30,7 @@
   void ShutDownEmbedderProcess() override;
   service_manager::ProcessType OverrideProcessType() override;
   void OverrideMojoConfiguration(mojo::core::Configuration* config) override;
-  std::unique_ptr<base::Value> CreateServiceCatalog() override;
+  std::vector<service_manager::Manifest> GetServiceManifests() override;
   bool ShouldLaunchAsServiceProcess(
       const service_manager::Identity& identity) override;
   void AdjustServiceProcessCommandLine(
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc
index bd16e1b..6b7f72e 100644
--- a/content/browser/child_process_launcher.cc
+++ b/content/browser/child_process_launcher.cc
@@ -149,7 +149,7 @@
 // static
 void ChildProcessLauncher::SetRegisteredFilesForService(
     const std::string& service_name,
-    catalog::RequiredFileMap required_files) {
+    std::map<std::string, base::FilePath> required_files) {
   ChildProcessLauncherHelper::SetRegisteredFilesForService(
       service_name, std::move(required_files));
 }
diff --git a/content/browser/child_process_launcher.h b/content/browser/child_process_launcher.h
index 26f1376..415d916d 100644
--- a/content/browser/child_process_launcher.h
+++ b/content/browser/child_process_launcher.h
@@ -210,7 +210,7 @@
   // for the service |service_name|.
   static void SetRegisteredFilesForService(
       const std::string& service_name,
-      catalog::RequiredFileMap required_files);
+      std::map<std::string, base::FilePath> required_files);
 
   // Resets all files registered by |SetRegisteredFilesForService|. Used to
   // support multiple shell context creation in unit_tests.
diff --git a/content/browser/child_process_launcher_helper.h b/content/browser/child_process_launcher_helper.h
index 4dbac12..9b93e1f 100644
--- a/content/browser/child_process_launcher_helper.h
+++ b/content/browser/child_process_launcher_helper.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_CHILD_PROCESS_LAUNCHER_HELPER_H_
 #define CONTENT_BROWSER_CHILD_PROCESS_LAUNCHER_HELPER_H_
 
+#include <map>
 #include <memory>
 
 #include "base/macros.h"
@@ -17,7 +18,6 @@
 #include "content/public/common/result_codes.h"
 #include "mojo/public/cpp/platform/platform_channel.h"
 #include "mojo/public/cpp/system/invitation.h"
-#include "services/catalog/public/cpp/manifest_parsing_util.h"
 #include "services/service_manager/zygote/common/zygote_buildflags.h"
 
 #if !defined(OS_FUCHSIA)
@@ -182,7 +182,7 @@
 
   static void SetRegisteredFilesForService(
       const std::string& service_name,
-      catalog::RequiredFileMap required_files);
+      std::map<std::string, base::FilePath> required_files);
 
   static void ResetRegisteredFilesForTesting();
 
diff --git a/content/browser/child_process_launcher_helper_android.cc b/content/browser/child_process_launcher_helper_android.cc
index caacdf8..04bfd4a 100644
--- a/content/browser/child_process_launcher_helper_android.cc
+++ b/content/browser/child_process_launcher_helper_android.cc
@@ -234,7 +234,7 @@
 // static
 void ChildProcessLauncherHelper::SetRegisteredFilesForService(
     const std::string& service_name,
-    catalog::RequiredFileMap required_files) {
+    std::map<std::string, base::FilePath> required_files) {
   SetFilesToShareForServicePosix(service_name, std::move(required_files));
 }
 
diff --git a/content/browser/child_process_launcher_helper_fuchsia.cc b/content/browser/child_process_launcher_helper_fuchsia.cc
index bd84693..06e1067 100644
--- a/content/browser/child_process_launcher_helper_fuchsia.cc
+++ b/content/browser/child_process_launcher_helper_fuchsia.cc
@@ -40,7 +40,7 @@
 // static
 void ChildProcessLauncherHelper::SetRegisteredFilesForService(
     const std::string& service_name,
-    catalog::RequiredFileMap required_files) {
+    std::map<std::string, base::FilePath> required_files) {
   // TODO(fuchsia): Implement this. (crbug.com/707031)
   NOTIMPLEMENTED();
 }
diff --git a/content/browser/child_process_launcher_helper_linux.cc b/content/browser/child_process_launcher_helper_linux.cc
index c981f7f..c715a86d0 100644
--- a/content/browser/child_process_launcher_helper_linux.cc
+++ b/content/browser/child_process_launcher_helper_linux.cc
@@ -164,7 +164,7 @@
 // static
 void ChildProcessLauncherHelper::SetRegisteredFilesForService(
     const std::string& service_name,
-    catalog::RequiredFileMap required_files) {
+    std::map<std::string, base::FilePath> required_files) {
   SetFilesToShareForServicePosix(service_name, std::move(required_files));
 }
 
diff --git a/content/browser/child_process_launcher_helper_mac.cc b/content/browser/child_process_launcher_helper_mac.cc
index de7b7ff..d240f93 100644
--- a/content/browser/child_process_launcher_helper_mac.cc
+++ b/content/browser/child_process_launcher_helper_mac.cc
@@ -254,7 +254,7 @@
 // static
 void ChildProcessLauncherHelper::SetRegisteredFilesForService(
     const std::string& service_name,
-    catalog::RequiredFileMap required_files) {
+    std::map<std::string, base::FilePath> required_files) {
   // No file passing from the manifest on Mac yet.
   DCHECK(required_files.empty());
 }
diff --git a/content/browser/child_process_launcher_helper_posix.cc b/content/browser/child_process_launcher_helper_posix.cc
index 15a9977..2ca43941 100644
--- a/content/browser/child_process_launcher_helper_posix.cc
+++ b/content/browser/child_process_launcher_helper_posix.cc
@@ -16,7 +16,6 @@
 #include "content/public/common/content_descriptors.h"
 #include "content/public/common/content_switches.h"
 #include "mojo/public/cpp/platform/platform_channel_endpoint.h"
-#include "services/catalog/public/cpp/manifest_parsing_util.h"
 #include "services/service_manager/embedder/shared_file_util.h"
 #include "services/service_manager/embedder/switches.h"
 
@@ -26,7 +25,7 @@
 namespace {
 
 using RequiredFilesByServiceMap =
-    std::map<std::string, catalog::RequiredFileMap>;
+    std::map<std::string, std::map<std::string, base::FilePath>>;
 
 RequiredFilesByServiceMap& GetRequiredFilesByServiceMap() {
   static auto* required_files_by_service = new RequiredFilesByServiceMap();
@@ -113,7 +112,8 @@
   const std::string& service_name = service_name_iter->second;
   auto files_iter = GetRequiredFilesByServiceMap().find(service_name);
   if (files_iter != GetRequiredFilesByServiceMap().end()) {
-    const catalog::RequiredFileMap& required_files_map = files_iter->second;
+    const std::map<std::string, base::FilePath>& required_files_map =
+        files_iter->second;
     base::GlobalDescriptors::Key key = kContentDynamicDescriptorStart;
     service_manager::SharedFileSwitchValueBuilder file_switch_value_builder;
     for (const auto& key_path_iter : required_files_map) {
@@ -137,8 +137,9 @@
   return files_to_register;
 }
 
-void SetFilesToShareForServicePosix(const std::string& service_name,
-                                    catalog::RequiredFileMap required_files) {
+void SetFilesToShareForServicePosix(
+    const std::string& service_name,
+    std::map<std::string, base::FilePath> required_files) {
   if (required_files.empty())
     return;
 
diff --git a/content/browser/child_process_launcher_helper_posix.h b/content/browser/child_process_launcher_helper_posix.h
index 956c6d3a..9622650 100644
--- a/content/browser/child_process_launcher_helper_posix.h
+++ b/content/browser/child_process_launcher_helper_posix.h
@@ -5,11 +5,11 @@
 #ifndef CONTENT_BROWSER_CHILD_PROCESS_LAUNCHER_HELPER_POSIX_H_
 #define CONTENT_BROWSER_CHILD_PROCESS_LAUNCHER_HELPER_POSIX_H_
 
+#include <map>
 #include <memory>
 
 #include "base/files/file.h"
 #include "base/files/memory_mapped_file.h"
-#include "services/catalog/public/cpp/manifest_parsing_util.h"
 
 namespace base {
 class CommandLine;
@@ -38,8 +38,9 @@
 
 // Called by the service manager to register the files that should be mapped for
 // a service in the child process.
-void SetFilesToShareForServicePosix(const std::string& service_name,
-                                    catalog::RequiredFileMap required_files);
+void SetFilesToShareForServicePosix(
+    const std::string& service_name,
+    std::map<std::string, base::FilePath> required_files);
 
 // Called from unit_tests in order to reset all previously registered files.
 void ResetFilesToShareForTestingPosix();
diff --git a/content/browser/child_process_launcher_helper_win.cc b/content/browser/child_process_launcher_helper_win.cc
index 4deb943..4aa0c71 100644
--- a/content/browser/child_process_launcher_helper_win.cc
+++ b/content/browser/child_process_launcher_helper_win.cc
@@ -121,7 +121,7 @@
 // static
 void ChildProcessLauncherHelper::SetRegisteredFilesForService(
     const std::string& service_name,
-    catalog::RequiredFileMap required_files) {
+    std::map<std::string, base::FilePath> required_files) {
   // No file passing from the manifest on Windows yet.
   DCHECK(required_files.empty());
 }
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc
index 5689802..93bd9c02 100644
--- a/content/browser/devtools/devtools_instrumentation.cc
+++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -202,10 +202,11 @@
   if (!agent_host)
     return false;
   bool had_interceptors = false;
-  for (auto* handler : HandlerType::ForAgentHost(agent_host)) {
+  const auto& handlers = HandlerType::ForAgentHost(agent_host);
+  for (auto it = handlers.rbegin(); it != handlers.rend(); ++it) {
     had_interceptors =
-        handler->MaybeCreateProxyForInterception(
-            rfh, is_navigation, is_download, target_factory_request) ||
+        (*it)->MaybeCreateProxyForInterception(rfh, is_navigation, is_download,
+                                               target_factory_request) ||
         had_interceptors;
   }
   return had_interceptors;
@@ -231,6 +232,7 @@
       MaybeCreateProxyForInterception<protocol::NetworkHandler>(
           frame_agent_host, rfh, is_navigation, is_download,
           target_factory_request);
+
   had_interceptors = MaybeCreateProxyForInterception<protocol::FetchHandler>(
                          frame_agent_host, rfh, is_navigation, is_download,
                          target_factory_request) ||
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 364fe0d..df12172 100644
--- a/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -2344,6 +2344,8 @@
       FrameOwnerProperties(), blink::FrameOwnerElementType::kIframe);
   TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
       contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
+  RenderFrameHostManager* subframe_rfhm =
+      subframe->frame_tree_node()->render_manager();
   const GURL subframe_url("http://foo1/subframe");
 
   // Compute the sequence number assigned by Blink.
@@ -2355,6 +2357,7 @@
     params.nav_entry_id = 0;
     params.did_create_new_entry = false;
     params.url = subframe_url;
+    params.origin = url::Origin::Create(subframe_url);
     params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
     params.should_update_history = false;
     params.gesture = NavigationGestureUser;
@@ -2382,6 +2385,7 @@
   params.nav_entry_id = 0;
   params.did_create_new_entry = true;
   params.url = url2;
+  params.origin = url::Origin::Create(url2);
   params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
   params.should_update_history = false;
   params.gesture = NavigationGestureUser;
@@ -2394,6 +2398,12 @@
   // This should generate a new entry.
   subframe->SendRendererInitiatedNavigationRequest(url2, false);
   subframe->PrepareForCommit();
+  // If the navigation is cross-process, the commit comes from the speculative
+  // RenderFrame.
+  if (subframe_rfhm->speculative_frame_host()) {
+    subframe = static_cast<TestRenderFrameHost*>(
+        subframe_rfhm->speculative_frame_host());
+  }
   subframe->SendNavigateWithParams(&params, false);
   NavigationEntryImpl* entry2 = controller.GetLastCommittedEntry();
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
@@ -2411,6 +2421,7 @@
   params.nav_entry_id = 0;
   params.did_create_new_entry = true;
   params.url = url3;
+  params.origin = url::Origin::Create(url3);
   params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
   params.item_sequence_number = item_sequence_number3;
   params.document_sequence_number = document_sequence_number3;
@@ -2418,6 +2429,10 @@
     url3, item_sequence_number3, document_sequence_number3);
   subframe->SendRendererInitiatedNavigationRequest(url3, false);
   subframe->PrepareForCommit();
+  if (subframe_rfhm->speculative_frame_host()) {
+    subframe = static_cast<TestRenderFrameHost*>(
+        subframe_rfhm->speculative_frame_host());
+  }
   subframe->SendNavigateWithParams(&params, false);
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
@@ -2434,12 +2449,17 @@
   params.nav_entry_id = entry2->GetUniqueID();
   params.did_create_new_entry = false;
   params.url = url2;
+  params.origin = url::Origin::Create(url2);
   params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
   params.page_state = PageState::CreateForTestingWithSequenceNumbers(
     url2, item_sequence_number2, document_sequence_number2);
   params.item_sequence_number = item_sequence_number2;
   params.document_sequence_number = document_sequence_number2;
   subframe->PrepareForCommit();
+  if (subframe_rfhm->speculative_frame_host()) {
+    subframe = static_cast<TestRenderFrameHost*>(
+        subframe_rfhm->speculative_frame_host());
+  }
   subframe->SendNavigateWithParams(&params, false);
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
@@ -2454,12 +2474,17 @@
   params.nav_entry_id = entry1->GetUniqueID();
   params.did_create_new_entry = false;
   params.url = subframe_url;
+  params.origin = url::Origin::Create(subframe_url);
   params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
   params.page_state = PageState::CreateForTestingWithSequenceNumbers(
     subframe_url, item_sequence_number1, document_sequence_number1);
   params.item_sequence_number = item_sequence_number1;
   params.document_sequence_number = document_sequence_number1;
   subframe->PrepareForCommit();
+  if (subframe_rfhm->speculative_frame_host()) {
+    subframe = static_cast<TestRenderFrameHost*>(
+        subframe_rfhm->speculative_frame_host());
+  }
   subframe->SendNavigateWithParams(&params, false);
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
@@ -2510,6 +2535,7 @@
   self_params.did_create_new_entry = true;
   self_params.should_replace_current_entry = true;
   self_params.url = url1;
+  self_params.origin = url::Origin::Create(url1);
   self_params.transition = ui::PAGE_TRANSITION_LINK;
   self_params.should_update_history = false;
   self_params.gesture = NavigationGestureUser;
@@ -2537,6 +2563,7 @@
   params.nav_entry_id = 0;
   params.did_create_new_entry = true;
   params.url = url2;
+  params.origin = url::Origin::Create(url2);
   params.transition = ui::PAGE_TRANSITION_LINK;
   params.should_update_history = false;
   params.gesture = NavigationGestureUser;
@@ -2598,13 +2625,17 @@
   params.nav_entry_id = 0;
   params.did_create_new_entry = true;
   params.url = url3;
+  params.origin = url::Origin::Create(url3);
   params.item_sequence_number = 0;
   params.document_sequence_number = 0;
   params.page_state = PageState::CreateFromURL(url3);
   navigation_entry_committed_counter_ = 0;
   main_test_rfh()->SendRendererInitiatedNavigationRequest(url3, false);
   main_test_rfh()->PrepareForCommit();
-  main_test_rfh()->SendNavigateWithParams(&params, false);
+  TestRenderFrameHost* navigating_rfh = contents()->GetPendingMainFrame()
+                                            ? contents()->GetPendingMainFrame()
+                                            : main_test_rfh();
+  navigating_rfh->SendNavigateWithParams(&params, false);
   EXPECT_EQ(1U, navigation_entry_committed_counter_);
   navigation_entry_committed_counter_ = 0;
   EXPECT_FALSE(observer.is_same_document());
@@ -2677,6 +2708,7 @@
     params.did_create_new_entry = false;
     params.should_replace_current_entry = true;
     params.url = url;
+    params.origin = url::Origin::Create(url);
     params.transition = ui::PAGE_TRANSITION_LINK;
     params.redirects.push_back(url);
     params.should_update_history = true;
@@ -4795,6 +4827,7 @@
   params.nav_entry_id = 0;
   params.did_create_new_entry = true;
   params.url = url;
+  params.origin = url::Origin::Create(url);
   params.transition = ui::PAGE_TRANSITION_FORM_SUBMIT;
   params.gesture = NavigationGestureUser;
   params.page_state = PageState::CreateFromURL(url);
@@ -4809,6 +4842,7 @@
   params.nav_entry_id = 0;
   params.did_create_new_entry = false;
   params.url = replace_url;
+  params.origin = url::Origin::Create(replace_url);
   params.transition = ui::PAGE_TRANSITION_LINK;
   params.gesture = NavigationGestureUser;
   params.page_state = PageState::CreateFromURL(replace_url);
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 6146413..a20be5d 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -114,7 +114,6 @@
 #include "content/common/render_message_filter.mojom.h"
 #include "content/common/renderer.mojom.h"
 #include "content/common/swapped_out_messages.h"
-#include "content/common/url_loader_factory_bundle.mojom.h"
 #include "content/common/widget.mojom.h"
 #include "content/public/browser/ax_event_notification_details.h"
 #include "content/public/browser/browser_accessibility_state.h"
@@ -179,6 +178,7 @@
 #include "third_party/blink/public/common/feature_policy/feature_policy.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/frame/frame_policy.h"
+#include "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
 #include "third_party/blink/public/mojom/usb/web_usb_service.mojom.h"
 #include "third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.h"
@@ -453,10 +453,10 @@
   return connection->GetConnector();
 }
 
-std::unique_ptr<URLLoaderFactoryBundleInfo> CloneFactoryBundle(
-    scoped_refptr<URLLoaderFactoryBundle> bundle) {
-  return base::WrapUnique(
-      static_cast<URLLoaderFactoryBundleInfo*>(bundle->Clone().release()));
+std::unique_ptr<blink::URLLoaderFactoryBundleInfo> CloneFactoryBundle(
+    scoped_refptr<blink::URLLoaderFactoryBundle> bundle) {
+  return base::WrapUnique(static_cast<blink::URLLoaderFactoryBundleInfo*>(
+      bundle->Clone().release()));
 }
 
 }  // namespace
@@ -1169,8 +1169,9 @@
   //    bundle before).
   if (push_to_renderer_now && insertion_took_place &&
       has_committed_any_navigation_) {
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories =
-        std::make_unique<URLLoaderFactoryBundleInfo>();
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factories =
+            std::make_unique<blink::URLLoaderFactoryBundleInfo>();
     subresource_loader_factories->initiator_specific_factory_infos() =
         CreateInitiatorSpecificURLLoaderFactories(request_initiators);
     GetNavigationControl()->UpdateSubresourceLoaderFactories(
@@ -1182,10 +1183,10 @@
   return static_cast<int>(active_sandbox_flags_) & static_cast<int>(flags);
 }
 
-URLLoaderFactoryBundleInfo::OriginMap
+blink::URLLoaderFactoryBundleInfo::OriginMap
 RenderFrameHostImpl::CreateInitiatorSpecificURLLoaderFactories(
     const base::flat_set<url::Origin>& initiator_origins) {
-  URLLoaderFactoryBundleInfo::OriginMap result;
+  blink::URLLoaderFactoryBundleInfo::OriginMap result;
   for (const url::Origin& initiator : initiator_origins) {
     network::mojom::URLLoaderFactoryPtrInfo factory_info;
     CreateNetworkServiceDefaultFactoryAndObserve(
@@ -4535,12 +4536,13 @@
   const bool is_same_document =
       FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type);
 
-  std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories;
+  std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+      subresource_loader_factories;
   if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
       (!is_same_document || is_first_navigation)) {
     recreate_default_url_loader_factory_after_network_service_crash_ = false;
     subresource_loader_factories =
-        std::make_unique<URLLoaderFactoryBundleInfo>();
+        std::make_unique<blink::URLLoaderFactoryBundleInfo>();
     BrowserContext* browser_context = GetSiteInstance()->GetBrowserContext();
     // NOTE: On Network Service navigations, we want to ensure that a frame is
     // given everything it will need to load any accessible subresources. We
@@ -4696,11 +4698,12 @@
       }
     }
 
-    std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_prefetch;
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        factory_bundle_for_prefetch;
     network::mojom::URLLoaderFactoryPtr prefetch_loader_factory;
     if (subresource_loader_factories) {
       // Clone the factory bundle for prefetch.
-      auto bundle = base::MakeRefCounted<URLLoaderFactoryBundle>(
+      auto bundle = base::MakeRefCounted<blink::URLLoaderFactoryBundle>(
           std::move(subresource_loader_factories));
       subresource_loader_factories = CloneFactoryBundle(bundle);
       factory_bundle_for_prefetch = CloneFactoryBundle(bundle);
@@ -4709,7 +4712,7 @@
                (!is_same_document || is_first_navigation)) {
       DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
       factory_bundle_for_prefetch =
-          std::make_unique<URLLoaderFactoryBundleInfo>();
+          std::make_unique<blink::URLLoaderFactoryBundleInfo>();
       network::mojom::URLLoaderFactoryPtrInfo factory_info;
       CreateNetworkServiceDefaultFactoryInternal(
           url::Origin(), mojo::MakeRequest(&factory_info));
@@ -4811,15 +4814,18 @@
   // later on.
   url::Origin origin = url::Origin();
 
-  std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories;
+  std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+      subresource_loader_factories;
   if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
     network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
     bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve(
         origin, mojo::MakeRequest(&default_factory_info));
-    subresource_loader_factories = std::make_unique<URLLoaderFactoryBundleInfo>(
-        std::move(default_factory_info),
-        URLLoaderFactoryBundleInfo::SchemeMap(),
-        URLLoaderFactoryBundleInfo::OriginMap(), bypass_redirect_checks);
+    subresource_loader_factories =
+        std::make_unique<blink::URLLoaderFactoryBundleInfo>(
+            std::move(default_factory_info),
+            blink::URLLoaderFactoryBundleInfo::SchemeMap(),
+            blink::URLLoaderFactoryBundleInfo::OriginMap(),
+            bypass_redirect_checks);
   }
 
   auto find_request = navigation_requests_.find(navigation_id);
@@ -5327,13 +5333,14 @@
         last_committed_origin_, mojo::MakeRequest(&default_factory_info));
   }
 
-  std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories =
-      std::make_unique<URLLoaderFactoryBundleInfo>(
-          std::move(default_factory_info),
-          URLLoaderFactoryBundleInfo::SchemeMap(),
-          CreateInitiatorSpecificURLLoaderFactories(
-              initiators_requiring_separate_url_loader_factory_),
-          bypass_redirect_checks);
+  std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+      subresource_loader_factories =
+          std::make_unique<blink::URLLoaderFactoryBundleInfo>(
+              std::move(default_factory_info),
+              blink::URLLoaderFactoryBundleInfo::SchemeMap(),
+              CreateInitiatorSpecificURLLoaderFactories(
+                  initiators_requiring_separate_url_loader_factory_),
+              bypass_redirect_checks);
   GetNavigationControl()->UpdateSubresourceLoaderFactories(
       std::move(subresource_loader_factories));
 }
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 2e569a00..c8e2710 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1335,7 +1335,7 @@
 
   // Creates initiator-specific URLLoaderFactory objects for
   // |initiator_origins|.
-  URLLoaderFactoryBundleInfo::OriginMap
+  blink::URLLoaderFactoryBundleInfo::OriginMap
   CreateInitiatorSpecificURLLoaderFactories(
       const base::flat_set<url::Origin>& initiator_origins);
 
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index 2f04466..2685bf0 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -142,8 +142,9 @@
 }
 
 void IndexedDBDispatcherHost::AddBinding(
-    blink::mojom::IDBFactoryRequest request) {
-  bindings_.AddBinding(this, std::move(request));
+    blink::mojom::IDBFactoryRequest request,
+    const url::Origin& origin) {
+  bindings_.AddBinding(this, std::move(request), {origin});
 }
 
 void IndexedDBDispatcherHost::AddDatabaseBinding(
@@ -169,57 +170,60 @@
 }
 
 void IndexedDBDispatcherHost::GetDatabaseInfo(
-    blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
-    const url::Origin& origin) {
+    blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!IsValidOrigin(origin)) {
+  const auto& context = bindings_.dispatch_context();
+  if (!IsValidOrigin(context.origin)) {
     mojo::ReportBadMessage(kInvalidOrigin);
     return;
   }
 
-  scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
-      this->AsWeakPtr(), origin, std::move(callbacks_info), IDBTaskRunner()));
+  scoped_refptr<IndexedDBCallbacks> callbacks(
+      new IndexedDBCallbacks(this->AsWeakPtr(), context.origin,
+                             std::move(callbacks_info), IDBTaskRunner()));
   IDBTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(&IDBSequenceHelper::GetDatabaseInfoOnIDBThread,
                                 base::Unretained(idb_helper_),
-                                std::move(callbacks), origin));
+                                std::move(callbacks), context.origin));
 }
 
 void IndexedDBDispatcherHost::GetDatabaseNames(
-    blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
-    const url::Origin& origin) {
+    blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!IsValidOrigin(origin)) {
+  const auto& context = bindings_.dispatch_context();
+  if (!IsValidOrigin(context.origin)) {
     mojo::ReportBadMessage(kInvalidOrigin);
     return;
   }
 
-  scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
-      this->AsWeakPtr(), origin, std::move(callbacks_info), IDBTaskRunner()));
+  scoped_refptr<IndexedDBCallbacks> callbacks(
+      new IndexedDBCallbacks(this->AsWeakPtr(), context.origin,
+                             std::move(callbacks_info), IDBTaskRunner()));
   IDBTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(&IDBSequenceHelper::GetDatabaseNamesOnIDBThread,
                                 base::Unretained(idb_helper_),
-                                std::move(callbacks), origin));
+                                std::move(callbacks), context.origin));
 }
 
 void IndexedDBDispatcherHost::Open(
     blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
     blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo database_callbacks_info,
-    const url::Origin& origin,
     const base::string16& name,
     int64_t version,
     int64_t transaction_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!IsValidOrigin(origin)) {
+  const auto& context = bindings_.dispatch_context();
+  if (!IsValidOrigin(context.origin)) {
     mojo::ReportBadMessage(kInvalidOrigin);
     return;
   }
 
-  scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
-      this->AsWeakPtr(), origin, std::move(callbacks_info), IDBTaskRunner()));
+  scoped_refptr<IndexedDBCallbacks> callbacks(
+      new IndexedDBCallbacks(this->AsWeakPtr(), context.origin,
+                             std::move(callbacks_info), IDBTaskRunner()));
   scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks(
       new IndexedDBDatabaseCallbacks(indexed_db_context_,
                                      std::move(database_callbacks_info)));
@@ -227,37 +231,38 @@
       FROM_HERE,
       base::BindOnce(&IDBSequenceHelper::OpenOnIDBThread,
                      base::Unretained(idb_helper_), std::move(callbacks),
-                     std::move(database_callbacks), origin, name, version,
-                     transaction_id));
+                     std::move(database_callbacks), context.origin, name,
+                     version, transaction_id));
 }
 
 void IndexedDBDispatcherHost::DeleteDatabase(
     blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
-    const url::Origin& origin,
     const base::string16& name,
     bool force_close) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!IsValidOrigin(origin)) {
+  const auto& context = bindings_.dispatch_context();
+  if (!IsValidOrigin(context.origin)) {
     mojo::ReportBadMessage(kInvalidOrigin);
     return;
   }
 
-  scoped_refptr<IndexedDBCallbacks> callbacks(new IndexedDBCallbacks(
-      this->AsWeakPtr(), origin, std::move(callbacks_info), IDBTaskRunner()));
+  scoped_refptr<IndexedDBCallbacks> callbacks(
+      new IndexedDBCallbacks(this->AsWeakPtr(), context.origin,
+                             std::move(callbacks_info), IDBTaskRunner()));
   IDBTaskRunner()->PostTask(
       FROM_HERE,
       base::BindOnce(&IDBSequenceHelper::DeleteDatabaseOnIDBThread,
                      base::Unretained(idb_helper_), std::move(callbacks),
-                     origin, name, force_close));
+                     context.origin, name, force_close));
 }
 
 void IndexedDBDispatcherHost::AbortTransactionsAndCompactDatabase(
-    const url::Origin& origin,
     AbortTransactionsAndCompactDatabaseCallback mojo_callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!IsValidOrigin(origin)) {
+  const auto& context = bindings_.dispatch_context();
+  if (!IsValidOrigin(context.origin)) {
     mojo::ReportBadMessage(kInvalidOrigin);
     return;
   }
@@ -269,15 +274,16 @@
       FROM_HERE,
       base::BindOnce(
           &IDBSequenceHelper::AbortTransactionsAndCompactDatabaseOnIDBThread,
-          base::Unretained(idb_helper_), std::move(callback_on_io), origin));
+          base::Unretained(idb_helper_), std::move(callback_on_io),
+          context.origin));
 }
 
 void IndexedDBDispatcherHost::AbortTransactionsForDatabase(
-    const url::Origin& origin,
     AbortTransactionsForDatabaseCallback mojo_callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!IsValidOrigin(origin)) {
+  const auto& context = bindings_.dispatch_context();
+  if (!IsValidOrigin(context.origin)) {
     mojo::ReportBadMessage(kInvalidOrigin);
     return;
   }
@@ -289,7 +295,8 @@
       FROM_HERE,
       base::BindOnce(
           &IDBSequenceHelper::AbortTransactionsForDatabaseOnIDBThread,
-          base::Unretained(idb_helper_), std::move(callback_on_io), origin));
+          base::Unretained(idb_helper_), std::move(callback_on_io),
+          context.origin));
 }
 
 void IndexedDBDispatcherHost::InvalidateWeakPtrsAndClearBindings() {
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.h b/content/browser/indexed_db/indexed_db_dispatcher_host.h
index af46f84..f147d36 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -47,7 +47,8 @@
       scoped_refptr<IndexedDBContextImpl> indexed_db_context,
       scoped_refptr<ChromeBlobStorageContext> blob_storage_context);
 
-  void AddBinding(blink::mojom::IDBFactoryRequest request);
+  void AddBinding(blink::mojom::IDBFactoryRequest request,
+                  const url::Origin& origin);
 
   void AddDatabaseBinding(std::unique_ptr<blink::mojom::IDBDatabase> database,
                           blink::mojom::IDBDatabaseAssociatedRequest request);
@@ -83,28 +84,22 @@
 
   // blink::mojom::IDBFactory implementation:
   void GetDatabaseInfo(
-      blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
-      const url::Origin& origin) override;
+      blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) override;
   void GetDatabaseNames(
-      blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
-      const url::Origin& origin) override;
+      blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info) override;
   void Open(blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
             blink::mojom::IDBDatabaseCallbacksAssociatedPtrInfo
                 database_callbacks_info,
-            const url::Origin& origin,
             const base::string16& name,
             int64_t version,
             int64_t transaction_id) override;
   void DeleteDatabase(
       blink::mojom::IDBCallbacksAssociatedPtrInfo callbacks_info,
-      const url::Origin& origin,
       const base::string16& name,
       bool force_close) override;
   void AbortTransactionsAndCompactDatabase(
-      const url::Origin& origin,
       AbortTransactionsAndCompactDatabaseCallback callback) override;
   void AbortTransactionsForDatabase(
-      const url::Origin& origin,
       AbortTransactionsForDatabaseCallback callback) override;
 
   void InvalidateWeakPtrsAndClearBindings();
@@ -117,7 +112,12 @@
   // Used to set file permissions for blob storage.
   const int ipc_process_id_;
 
-  mojo::BindingSet<blink::mojom::IDBFactory> bindings_;
+  // State for each client held in |bindings_|.
+  struct BindingState {
+    url::Origin origin;
+  };
+
+  mojo::BindingSet<blink::mojom::IDBFactory, BindingState> bindings_;
 
   mojo::StrongAssociatedBindingSet<blink::mojom::IDBDatabase>
       database_bindings_;
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
index b19ae42..193e3a5 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -112,8 +112,8 @@
 
   void Open(IDBFactory* factory) {
     factory->Open(open_callbacks->CreateInterfacePtrAndBind(),
-                  connection_callbacks->CreateInterfacePtrAndBind(), origin,
-                  db_name, version, upgrade_txn_id);
+                  connection_callbacks->CreateInterfacePtrAndBind(), db_name,
+                  version, upgrade_txn_id);
   }
 
   url::Origin origin;
@@ -190,7 +190,8 @@
   }
 
   void SetUp() override {
-    host_->AddBinding(::mojo::MakeRequest(&idb_mojo_factory_));
+    host_->AddBinding(::mojo::MakeRequest(&idb_mojo_factory_),
+                      {url::Origin::Create(GURL(kOrigin))});
   }
 
  protected:
@@ -489,7 +490,6 @@
     ::testing::InSequence dummy;
     base::RunLoop loop;
     base::Closure quit_closure = base::BarrierClosure(3, loop.QuitClosure());
-    const url::Origin origin = url::Origin::Create(GURL(kOrigin));
 
     EXPECT_CALL(*connection.connection_callbacks, Complete(kTransactionId))
         .Times(1)
@@ -501,9 +501,8 @@
         .WillOnce(RunClosure(quit_closure));
 
     connection.database->Commit(kTransactionId);
-    idb_mojo_factory_->AbortTransactionsAndCompactDatabase(
-        origin, base::BindOnce(&StatusCallback, std::move(quit_closure),
-                               &callback_result));
+    idb_mojo_factory_->AbortTransactionsAndCompactDatabase(base::BindOnce(
+        &StatusCallback, std::move(quit_closure), &callback_result));
 
     loop.Run();
   }
@@ -549,7 +548,6 @@
     ::testing::InSequence dummy;
     base::RunLoop loop;
     base::Closure quit_closure = base::BarrierClosure(4, loop.QuitClosure());
-    const url::Origin origin = url::Origin::Create(GURL(kOrigin));
 
     EXPECT_CALL(
         *connection.connection_callbacks,
@@ -568,9 +566,8 @@
     connection.database->CreateObjectStore(kTransactionId, kObjectStoreId,
                                            base::UTF8ToUTF16(kObjectStoreName),
                                            blink::IndexedDBKeyPath(), false);
-    idb_mojo_factory_->AbortTransactionsAndCompactDatabase(
-        origin, base::BindOnce(&StatusCallback, std::move(quit_closure),
-                               &callback_result));
+    idb_mojo_factory_->AbortTransactionsAndCompactDatabase(base::BindOnce(
+        &StatusCallback, std::move(quit_closure), &callback_result));
 
     loop.Run();
   }
@@ -614,7 +611,6 @@
     ::testing::InSequence dummy;
     base::RunLoop loop;
     base::Closure quit_closure = base::BarrierClosure(4, loop.QuitClosure());
-    const url::Origin origin = url::Origin::Create(GURL(kOrigin));
 
     EXPECT_CALL(
         *connection.connection_callbacks,
@@ -630,9 +626,8 @@
         .WillOnce(RunClosure(quit_closure));
 
     ASSERT_TRUE(connection.database.is_bound());
-    idb_mojo_factory_->AbortTransactionsAndCompactDatabase(
-        origin, base::BindOnce(&StatusCallback, std::move(quit_closure),
-                               &callback_result));
+    idb_mojo_factory_->AbortTransactionsAndCompactDatabase(base::BindOnce(
+        &StatusCallback, std::move(quit_closure), &callback_result));
 
     loop.Run();
   }
@@ -677,7 +672,6 @@
     ::testing::InSequence dummy;
     base::RunLoop loop;
     base::Closure quit_closure = base::BarrierClosure(4, loop.QuitClosure());
-    const url::Origin origin = url::Origin::Create(GURL(kOrigin));
 
     EXPECT_CALL(*connection.connection_callbacks, Complete(kTransactionId))
         .Times(1)
@@ -692,9 +686,8 @@
         .WillOnce(RunClosure(quit_closure));
 
     connection.database->Commit(kTransactionId);
-    idb_mojo_factory_->AbortTransactionsForDatabase(
-        origin, base::BindOnce(&StatusCallback, std::move(quit_closure),
-                               &callback_result));
+    idb_mojo_factory_->AbortTransactionsForDatabase(base::BindOnce(
+        &StatusCallback, std::move(quit_closure), &callback_result));
 
     loop.Run();
   }
@@ -740,7 +733,6 @@
     ::testing::InSequence dummy;
     base::RunLoop loop;
     base::Closure quit_closure = base::BarrierClosure(4, loop.QuitClosure());
-    const url::Origin origin = url::Origin::Create(GURL(kOrigin));
 
     EXPECT_CALL(
         *connection.connection_callbacks,
@@ -759,9 +751,8 @@
     connection.database->CreateObjectStore(kTransactionId, kObjectStoreId,
                                            base::UTF8ToUTF16(kObjectStoreName),
                                            blink::IndexedDBKeyPath(), false);
-    idb_mojo_factory_->AbortTransactionsForDatabase(
-        origin, base::BindOnce(&StatusCallback, std::move(quit_closure),
-                               &callback_result));
+    idb_mojo_factory_->AbortTransactionsForDatabase(base::BindOnce(
+        &StatusCallback, std::move(quit_closure), &callback_result));
 
     loop.Run();
   }
@@ -805,7 +796,6 @@
     ::testing::InSequence dummy;
     base::RunLoop loop;
     base::Closure quit_closure = base::BarrierClosure(4, loop.QuitClosure());
-    const url::Origin origin = url::Origin::Create(GURL(kOrigin));
 
     EXPECT_CALL(
         *connection.connection_callbacks,
@@ -821,9 +811,8 @@
         .WillOnce(RunClosure(quit_closure));
 
     ASSERT_TRUE(connection.database.is_bound());
-    idb_mojo_factory_->AbortTransactionsForDatabase(
-        origin, base::BindOnce(&StatusCallback, std::move(quit_closure),
-                               &callback_result));
+    idb_mojo_factory_->AbortTransactionsForDatabase(base::BindOnce(
+        &StatusCallback, std::move(quit_closure), &callback_result));
 
     loop.Run();
   }
diff --git a/content/browser/loader/loader_browsertest.cc b/content/browser/loader/loader_browsertest.cc
index 43c6799..cfe0b98 100644
--- a/content/browser/loader/loader_browsertest.cc
+++ b/content/browser/loader/loader_browsertest.cc
@@ -1084,11 +1084,6 @@
 // bypass cookies SameSite=Strict protections by navigating a new window twice.
 IN_PROC_BROWSER_TEST_F(LoaderBrowserTest,
                        CookieSameSiteStrictOpenNewNamedWindowTwice) {
-  // TODO(lukasza): https://crbug.com/417518: Get tests working with
-  // --site-per-process.
-  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
-    return;
-
   ASSERT_TRUE(embedded_test_server()->Start());
 
   // 1) Add cookies for 'a.com', one of them with the "SameSite=Strict" option.
diff --git a/content/browser/loader/prefetch_url_loader_service.h b/content/browser/loader/prefetch_url_loader_service.h
index 2fafbff..514b6fee 100644
--- a/content/browser/loader/prefetch_url_loader_service.h
+++ b/content/browser/loader/prefetch_url_loader_service.h
@@ -10,10 +10,10 @@
 #include "base/memory/ref_counted.h"
 #include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h"
 #include "content/common/content_export.h"
-#include "content/common/url_loader_factory_bundle.h"
 #include "content/public/browser/browser_thread.h"
 #include "mojo/public/cpp/bindings/strong_binding_set.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
 
 namespace net {
 class URLRequestContextGetter;
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 7fd819b..d0fe048 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2041,6 +2041,20 @@
                      origin));
 }
 
+void RenderProcessHostImpl::BindIndexedDB(
+    blink::mojom::IDBFactoryRequest request,
+    const url::Origin& origin) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  // Send the binding to IO thread to let IndexedDB handle Mojo IPC on the IO
+  // thread.
+  base::PostTaskWithTraits(
+      FROM_HERE, {BrowserThread::IO},
+      base::BindOnce(&IndexedDBDispatcherHost::AddBinding,
+                     base::Unretained(indexed_db_factory_.get()),
+                     std::move(request), origin));
+}
+
 void RenderProcessHostImpl::BindFileSystemManager(
     blink::mojom::FileSystemManagerRequest request) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -2185,10 +2199,6 @@
   }
 
   registry->AddInterface(
-      base::BindRepeating(&IndexedDBDispatcherHost::AddBinding,
-                          base::Unretained(indexed_db_factory_.get())));
-
-  registry->AddInterface(
       base::Bind(
           &WebDatabaseHostImpl::Create, GetID(),
           base::WrapRefCounted(storage_partition_impl_->GetDatabaseTracker())),
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 01d3339..d23793bf 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -233,6 +233,8 @@
   void LockToOrigin(const GURL& lock_url) override;
   void BindCacheStorage(blink::mojom::CacheStorageRequest request,
                         const url::Origin& origin) override;
+  void BindIndexedDB(blink::mojom::IDBFactoryRequest request,
+                     const url::Origin& origin) override;
   void CleanupCorbExceptionForPluginUponDestruction() override;
 
   mojom::RouteProvider* GetRemoteRouteProvider();
diff --git a/content/browser/renderer_interface_binders.cc b/content/browser/renderer_interface_binders.cc
index 976328a7..87ecafb 100644
--- a/content/browser/renderer_interface_binders.cc
+++ b/content/browser/renderer_interface_binders.cc
@@ -150,6 +150,12 @@
         static_cast<RenderProcessHostImpl*>(host)->BindCacheStorage(
             std::move(request), origin);
       }));
+  parameterized_binder_registry_.AddInterface(base::BindRepeating(
+      [](blink::mojom::IDBFactoryRequest request, RenderProcessHost* host,
+         const url::Origin& origin) {
+        static_cast<RenderProcessHostImpl*>(host)->BindIndexedDB(
+            std::move(request), origin);
+      }));
   // TODO(https://crbug.com/873661): Pass origin to FileSystemMananger.
   parameterized_binder_registry_.AddInterface(base::BindRepeating(
       [](blink::mojom::FileSystemManagerRequest request,
diff --git a/content/browser/service_manager/service_manager_context.cc b/content/browser/service_manager/service_manager_context.cc
index 0f8d4ba4..5d5630c 100644
--- a/content/browser/service_manager/service_manager_context.cc
+++ b/content/browser/service_manager/service_manager_context.cc
@@ -56,8 +56,6 @@
 #include "mojo/public/cpp/system/invitation.h"
 #include "services/audio/public/mojom/constants.mojom.h"
 #include "services/audio/service_factory.h"
-#include "services/catalog/public/cpp/manifest_parsing_util.h"
-#include "services/catalog/public/mojom/constants.mojom.h"
 #include "services/data_decoder/public/mojom/constants.mojom.h"
 #include "services/device/device_service.h"
 #include "services/device/public/mojom/constants.mojom.h"
@@ -73,7 +71,6 @@
 #include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
 #include "services/resource_coordinator/resource_coordinator_service.h"
 #include "services/service_manager/connect_params.h"
-#include "services/service_manager/embedder/manifest_utils.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/constants.h"
 #include "services/service_manager/public/cpp/manifest.h"
@@ -564,7 +561,6 @@
         {mojom::kPluginServiceName, IDR_MOJO_CONTENT_PLUGIN_MANIFEST},
         {mojom::kRendererServiceName, IDR_MOJO_CONTENT_RENDERER_MANIFEST},
         {mojom::kUtilityServiceName, IDR_MOJO_CONTENT_UTILITY_MANIFEST},
-        {catalog::mojom::kServiceName, IDR_MOJO_CATALOG_MANIFEST},
     };
     std::vector<service_manager::Manifest> manifests;
     for (const auto& manifest_info : kManifestInfo) {
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index 0d650700..b5ff23c 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -26,7 +26,6 @@
 #include "content/common/content_switches_internal.h"
 #include "content/common/renderer.mojom.h"
 #include "content/common/service_worker/service_worker_types.h"
-#include "content/common/url_loader_factory_bundle.mojom.h"
 #include "content/common/url_schemes.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
@@ -40,6 +39,7 @@
 #include "services/network/public/cpp/features.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/service_worker/service_worker_utils.h"
+#include "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
 #include "third_party/blink/public/web/web_console_message.h"
 #include "url/gurl.h"
@@ -100,10 +100,10 @@
 // it may also include scheme-specific factories that don't go to network.
 //
 // The network factory does not support reconnection to the network service.
-std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle(
+std::unique_ptr<blink::URLLoaderFactoryBundleInfo> CreateFactoryBundle(
     RenderProcessHost* rph,
     const url::Origin& origin) {
-  auto factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
+  auto factory_bundle = std::make_unique<blink::URLLoaderFactoryBundleInfo>();
   network::mojom::URLLoaderFactoryRequest default_factory_request =
       mojo::MakeRequest(&factory_bundle->default_factory_info());
   network::mojom::TrustedURLLoaderHeaderClientPtrInfo default_header_client;
@@ -162,9 +162,9 @@
     std::unique_ptr<ServiceWorkerProcessManager::AllocatedProcessInfo>,
     std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy>,
     std::unique_ptr<
-        URLLoaderFactoryBundleInfo> /* factory_bundle_for_browser */,
+        blink::URLLoaderFactoryBundleInfo> /* factory_bundle_for_browser */,
     std::unique_ptr<
-        URLLoaderFactoryBundleInfo> /* factory_bundle_for_renderer */,
+        blink::URLLoaderFactoryBundleInfo> /* factory_bundle_for_renderer */,
     blink::mojom::CacheStoragePtrInfo)>;
 
 // Allocates a renderer process for starting a worker and does setup like
@@ -187,8 +187,9 @@
   auto process_info =
       std::make_unique<ServiceWorkerProcessManager::AllocatedProcessInfo>();
   std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy> devtools_proxy;
-  std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser;
-  std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_renderer;
+  std::unique_ptr<blink::URLLoaderFactoryBundleInfo> factory_bundle_for_browser;
+  std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+      factory_bundle_for_renderer;
 
   if (!process_manager) {
     base::PostTaskWithTraits(
@@ -543,8 +544,10 @@
       std::unique_ptr<ServiceWorkerProcessManager::AllocatedProcessInfo>
           process_info,
       std::unique_ptr<EmbeddedWorkerInstance::DevToolsProxy> devtools_proxy,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_renderer,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+          factory_bundle_for_browser,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+          factory_bundle_for_renderer,
       blink::mojom::CacheStoragePtrInfo cache_storage) {
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
@@ -594,8 +597,9 @@
     scoped_refptr<network::SharedURLLoaderFactory> factory_for_new_scripts;
     if (blink::ServiceWorkerUtils::IsServicificationEnabled()) {
       DCHECK(factory_bundle_for_browser);
-      factory_for_new_scripts = base::MakeRefCounted<URLLoaderFactoryBundle>(
-          std::move(factory_bundle_for_browser));
+      factory_for_new_scripts =
+          base::MakeRefCounted<blink::URLLoaderFactoryBundle>(
+              std::move(factory_bundle_for_browser));
 
       // Send the factory bundle for subresource loading from the service worker
       // (i.e. fetch()).
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index 2caa589..4304d89 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -14,6 +14,7 @@
 #include "base/task/post_task.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
+#include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/devtools/service_worker_devtools_agent_host.h"
 #include "content/browser/devtools/service_worker_devtools_manager.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -300,6 +301,23 @@
       "policies (or a combination of both) limits the scope of these requests."
 )");
 
+// A copy of RenderFrameHostImpl's GrantFileAccess since there's not a great
+// central place to put this.
+//
+// Abuse is prevented, because the files listed in ResourceRequestBody are
+// validated earlier by navigation or ResourceDispatcherHost machinery before
+// ServiceWorkerFetchDispatcher is used to send the request to a service worker.
+void GrantFileAccessToProcess(int process_id,
+                              const std::vector<base::FilePath>& file_paths) {
+  ChildProcessSecurityPolicyImpl* policy =
+      ChildProcessSecurityPolicyImpl::GetInstance();
+
+  for (const auto& file : file_paths) {
+    if (!policy->CanReadFile(process_id, file))
+      policy->GrantReadFile(process_id, file);
+  }
+}
+
 }  // namespace
 
 // ResponseCallback is owned by the callback that is passed to
@@ -498,6 +516,13 @@
   DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status())
       << "Worker stopped too soon after it was started.";
 
+  // Grant the service worker's process access to files in the request body.
+  if (request_->body) {
+    const scoped_refptr<network::ResourceRequestBody>& body = *request_->body;
+    GrantFileAccessToProcess(version_->embedded_worker()->process_id(),
+                             body->GetReferencedFiles());
+  }
+
   // Run callback to say that the fetch event will be dispatched.
   DCHECK(prepare_callback_);
   std::move(prepare_callback_).Run();
diff --git a/content/browser/service_worker/service_worker_file_upload_browsertest.cc b/content/browser/service_worker/service_worker_file_upload_browsertest.cc
new file mode 100644
index 0000000..3f5e0ca
--- /dev/null
+++ b/content/browser/service_worker/service_worker_file_upload_browsertest.cc
@@ -0,0 +1,166 @@
+// 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 "base/bind.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/json/json_reader.h"
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_content_browser_client.h"
+#include "content/test/content_browser_test_utils_internal.h"
+#include "net/base/escape.h"
+#include "net/base/url_util.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/ssl/ssl_server_config.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "third_party/blink/public/common/features.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+enum class ServicifiedFeatures { kNone, kServiceWorker };
+}
+
+// Tests POST requests that include a file and are intercepted by a service
+// worker. This is a browser test rather than a web test because as
+// https://crbug.com/786510 describes, http tests involving file uploads usually
+// need to be in the http/tests/local directory, which does tricks with origins
+// that can break when Site Isolation is enabled.
+class ServiceWorkerFileUploadTest
+    : public ContentBrowserTest,
+      public ::testing::WithParamInterface<ServicifiedFeatures> {
+ public:
+  ServiceWorkerFileUploadTest() = default;
+
+  void SetUp() override {
+    ServicifiedFeatures param = GetParam();
+    switch (param) {
+      case ServicifiedFeatures::kNone:
+        scoped_feature_list_.InitAndDisableFeature(
+            blink::features::kServiceWorkerServicification);
+        break;
+      case ServicifiedFeatures::kServiceWorker:
+        scoped_feature_list_.InitAndEnableFeature(
+            blink::features::kServiceWorkerServicification);
+        break;
+    }
+
+    ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+
+    ContentBrowserTest::SetUp();
+  }
+
+  void SetUpOnMainThread() override {
+    // Make all hosts resolve to 127.0.0.1 so the same embedded test server can
+    // be used for cross-origin URLs.
+    host_resolver()->AddRule("*", "127.0.0.1");
+    embedded_test_server()->StartAcceptingConnections();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFileUploadTest);
+};
+
+// Tests using Request.formData() from a service worker for a navigation
+// request due to a form submission to a cross-origin target. Regression
+// test for https://crbug.com/916070.
+IN_PROC_BROWSER_TEST_P(ServiceWorkerFileUploadTest, AsFormData) {
+  // Install the service worker.
+  EXPECT_TRUE(NavigateToURL(shell(),
+                            embedded_test_server()->GetURL(
+                                "/service_worker/create_service_worker.html")));
+  EXPECT_EQ("DONE", EvalJs(shell(), "register('file_upload_worker.js');"));
+
+  // Generate a cross-origin URL for the page with a file upload form.
+  GURL top_frame_url =
+      embedded_test_server()->GetURL("/service_worker/form.html");
+  GURL::Replacements replacements;
+  replacements.SetHostStr("cross-origin.example.com");
+  top_frame_url = top_frame_url.ReplaceComponents(replacements);
+
+  // Also add "target=" query parameter so the page submits the form back to the
+  // original origin with the service worker.
+  GURL target_url = embedded_test_server()->GetURL("/service_worker/upload");
+  top_frame_url =
+      net::AppendQueryParameter(top_frame_url, "target", target_url.spec());
+
+  // Navigate to the cross-origin page with a file upload form.
+  EXPECT_TRUE(NavigateToURL(shell(), top_frame_url));
+
+  // Prepare a file for the upload form.
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  base::ScopedTempDir temp_dir;
+  base::FilePath file_path;
+  std::string file_content("come on baby america");
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &file_path));
+  ASSERT_LT(
+      0, base::WriteFile(file_path, file_content.data(), file_content.size()));
+
+  // Fill out the form to refer to the test file.
+  base::RunLoop run_loop;
+  auto delegate =
+      std::make_unique<FileChooserDelegate>(file_path, run_loop.QuitClosure());
+  shell()->web_contents()->SetDelegate(delegate.get());
+  EXPECT_TRUE(ExecJs(shell(), "fileInput.click();"));
+  run_loop.Run();
+
+  // Submit the form.
+  TestNavigationObserver form_post_observer(shell()->web_contents(), 1);
+  EXPECT_TRUE(ExecJs(shell(), "form.submit();"));
+  form_post_observer.Wait();
+
+  // Extract the body payload. It is JSON describing the uploaded form content.
+  EvalJsResult result = EvalJs(shell()->web_contents()->GetMainFrame(),
+                               "document.body.textContent");
+  ASSERT_TRUE(result.error.empty());
+  std::unique_ptr<base::DictionaryValue> dict = base::DictionaryValue::From(
+      base::JSONReader::Read(result.ExtractString()));
+  ASSERT_TRUE(dict) << "not json: " << result.ExtractString();
+  auto* entries_value = dict->FindKeyOfType("entries", base::Value::Type::LIST);
+  ASSERT_TRUE(entries_value);
+  // There was one entry uploaded so far.
+  const base::Value::ListStorage& entries = entries_value->GetList();
+  ASSERT_EQ(1u, entries.size());
+
+  // Test the first entry of the form data.
+
+  // The key should be "file" (the <input type="file"> element's name).
+  const auto* key0 = entries[0].FindKeyOfType("key", base::Value::Type::STRING);
+  ASSERT_TRUE(key0);
+  EXPECT_EQ("file", key0->GetString());
+
+  // The value should describe the uploaded file.
+  const auto* value0 =
+      entries[0].FindKeyOfType("value", base::Value::Type::DICTIONARY);
+  ASSERT_TRUE(value0);
+  // "type" is "file" since the value was a File object.
+  auto* value0_type = value0->FindKeyOfType("type", base::Value::Type::STRING);
+  EXPECT_EQ("file", value0_type->GetString());
+  // "name" is the filename (File.name)
+  auto* value0_name = value0->FindKeyOfType("name", base::Value::Type::STRING);
+  EXPECT_EQ(file_path.BaseName().MaybeAsASCII(), value0_name->GetString());
+  // "size" is the file size (File.size)
+  auto* value0_size = value0->FindKeyOfType("size", base::Value::Type::INTEGER);
+  ASSERT_GE(value0_size->GetInt(), 0);
+  EXPECT_EQ(file_content.size(),
+            base::checked_cast<size_t>(value0_size->GetInt()));
+}
+
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+                        ServiceWorkerFileUploadTest,
+                        ::testing::Values(ServicifiedFeatures::kNone,
+                                          ServicifiedFeatures::kServiceWorker));
+
+}  // namespace content
diff --git a/content/browser/worker_host/mock_shared_worker.cc b/content/browser/worker_host/mock_shared_worker.cc
index a2a0241..d951dd0 100644
--- a/content/browser/worker_host/mock_shared_worker.cc
+++ b/content/browser/worker_host/mock_shared_worker.cc
@@ -4,9 +4,9 @@
 
 #include "content/browser/worker_host/mock_shared_worker.h"
 
-#include "content/common/url_loader_factory_bundle.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -109,7 +109,8 @@
     network::mojom::URLLoaderFactoryAssociatedPtrInfo
         main_script_loader_factory,
     blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factories,
     blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
     blink::mojom::SharedWorkerHostPtr host,
     blink::mojom::SharedWorkerRequest request,
diff --git a/content/browser/worker_host/mock_shared_worker.h b/content/browser/worker_host/mock_shared_worker.h
index b2c61903..0c8b4bbf 100644
--- a/content/browser/worker_host/mock_shared_worker.h
+++ b/content/browser/worker_host/mock_shared_worker.h
@@ -21,8 +21,11 @@
 
 class GURL;
 
-namespace content {
+namespace blink {
 class URLLoaderFactoryBundleInfo;
+}  // namespace blink
+
+namespace content {
 
 class MockSharedWorker : public blink::mojom::SharedWorker {
  public:
@@ -78,7 +81,8 @@
       network::mojom::URLLoaderFactoryAssociatedPtrInfo
           main_script_loader_factory,
       blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+          subresource_loader_factories,
       blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
       blink::mojom::SharedWorkerHostPtr host,
       blink::mojom::SharedWorkerRequest request,
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc
index 6d33485..2f193894 100644
--- a/content/browser/worker_host/shared_worker_host.cc
+++ b/content/browser/worker_host/shared_worker_host.cc
@@ -19,7 +19,6 @@
 #include "content/browser/worker_host/shared_worker_instance.h"
 #include "content/browser/worker_host/shared_worker_service_impl.h"
 #include "content/common/navigation_subresource_loader_params.h"
-#include "content/common/url_loader_factory_bundle.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
@@ -29,6 +28,7 @@
 #include "content/public/common/renderer_preference_watcher.mojom.h"
 #include "services/network/public/cpp/features.h"
 #include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
 #include "third_party/blink/public/common/service_worker/service_worker_utils.h"
 #include "third_party/blink/public/platform/web_feature.mojom.h"
@@ -146,7 +146,8 @@
     network::mojom::URLLoaderFactoryAssociatedPtrInfo
         main_script_loader_factory,
     blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factories,
     base::Optional<SubresourceLoaderParams> subresource_loader_params) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   AdvanceTo(Phase::kStarted);
diff --git a/content/browser/worker_host/shared_worker_host.h b/content/browser/worker_host/shared_worker_host.h
index 6f9c690..8c45294 100644
--- a/content/browser/worker_host/shared_worker_host.h
+++ b/content/browser/worker_host/shared_worker_host.h
@@ -32,6 +32,7 @@
 
 namespace blink {
 class MessagePortChannel;
+class URLLoaderFactoryBundleInfo;
 }
 
 namespace content {
@@ -40,7 +41,6 @@
 class SharedWorkerContentSettingsProxyImpl;
 class SharedWorkerInstance;
 class SharedWorkerServiceImpl;
-class URLLoaderFactoryBundleInfo;
 struct SubresourceLoaderParams;
 
 // The SharedWorkerHost is the interface that represents the browser side of
@@ -96,7 +96,8 @@
       network::mojom::URLLoaderFactoryAssociatedPtrInfo
           main_script_loader_factory,
       blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+          subresource_loader_factories,
       base::Optional<SubresourceLoaderParams> subresource_loader_params);
 
   void AllowFileSystem(const GURL& url,
diff --git a/content/browser/worker_host/shared_worker_host_unittest.cc b/content/browser/worker_host/shared_worker_host_unittest.cc
index a7e7ccb..c2f5c433 100644
--- a/content/browser/worker_host/shared_worker_host_unittest.cc
+++ b/content/browser/worker_host/shared_worker_host_unittest.cc
@@ -78,7 +78,8 @@
     network::mojom::URLLoaderFactoryAssociatedPtrInfo
         main_script_loader_factory;
     blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params;
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories;
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factories;
     base::Optional<SubresourceLoaderParams> subresource_loader_params;
 
     // Set up various mocks based on NetworkService/S13nServiceWorker
@@ -91,7 +92,8 @@
           &provider_info);
 
       main_script_load_params = blink::mojom::WorkerMainScriptLoadParams::New();
-      subresource_loader_factories.reset(new URLLoaderFactoryBundleInfo());
+      subresource_loader_factories.reset(
+          new blink::URLLoaderFactoryBundleInfo());
       subresource_loader_params = SubresourceLoaderParams();
 
       network::mojom::URLLoaderFactoryPtr loader_factory_ptr;
@@ -116,10 +118,10 @@
       mojo::MakeStrongBinding(
           std::make_unique<NotImplementedNetworkURLLoaderFactory>(),
           mojo::MakeRequest(&default_factory_ptr));
-      subresource_loader_factories.reset(new URLLoaderFactoryBundleInfo(
+      subresource_loader_factories.reset(new blink::URLLoaderFactoryBundleInfo(
           default_factory_ptr.PassInterface(),
-          URLLoaderFactoryBundleInfo::SchemeMap(),
-          URLLoaderFactoryBundleInfo::OriginMap(),
+          blink::URLLoaderFactoryBundleInfo::SchemeMap(),
+          blink::URLLoaderFactoryBundleInfo::OriginMap(),
           true /* bypass_redirect_checks */));
     }
 
diff --git a/content/browser/worker_host/shared_worker_service_impl.cc b/content/browser/worker_host/shared_worker_service_impl.cc
index ac7ea6a2..fe9aef92 100644
--- a/content/browser/worker_host/shared_worker_service_impl.cc
+++ b/content/browser/worker_host/shared_worker_service_impl.cc
@@ -241,7 +241,8 @@
         service_worker_provider_info,
     network::mojom::URLLoaderFactoryAssociatedPtrInfo
         main_script_loader_factory,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factories,
     blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
     base::Optional<SubresourceLoaderParams> subresource_loader_params,
     bool success) {
@@ -276,7 +277,8 @@
         service_worker_provider_info,
     network::mojom::URLLoaderFactoryAssociatedPtrInfo
         main_script_loader_factory,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factories,
     blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
     base::Optional<SubresourceLoaderParams> subresource_loader_params) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/content/browser/worker_host/shared_worker_service_impl.h b/content/browser/worker_host/shared_worker_service_impl.h
index 60467df..8fb18c1 100644
--- a/content/browser/worker_host/shared_worker_service_impl.h
+++ b/content/browser/worker_host/shared_worker_service_impl.h
@@ -91,7 +91,8 @@
           service_worker_provider_info,
       network::mojom::URLLoaderFactoryAssociatedPtrInfo
           main_script_loader_factory,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+          subresource_loader_factories,
       blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
       base::Optional<SubresourceLoaderParams> subresource_loader_params,
       bool success);
@@ -106,7 +107,8 @@
           service_worker_provider_info,
       network::mojom::URLLoaderFactoryAssociatedPtrInfo
           main_script_loader_factory,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+          subresource_loader_factories,
       blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
       base::Optional<SubresourceLoaderParams> subresource_loader_params);
 
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.cc b/content/browser/worker_host/worker_script_fetch_initiator.cc
index 6e46fdf..2f4be80 100644
--- a/content/browser/worker_host/worker_script_fetch_initiator.cc
+++ b/content/browser/worker_host/worker_script_fetch_initiator.cc
@@ -23,7 +23,6 @@
 #include "content/browser/worker_host/worker_script_loader_factory.h"
 #include "content/common/content_constants_internal.h"
 #include "content/common/navigation_subresource_loader_params.h"
-#include "content/common/url_loader_factory_bundle.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
@@ -38,6 +37,7 @@
 #include "services/network/loader_util.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/blink/public/common/loader//url_loader_factory_bundle.h"
 #include "third_party/blink/public/common/service_worker/service_worker_utils.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
 #include "url/origin.h"
@@ -68,12 +68,12 @@
   // chrome-extension:// URLs. One factory bundle is consumed by the browser
   // for WorkerScriptLoaderFactory, and one is sent to the renderer for
   // subresource loading.
-  std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser =
-      CreateFactoryBundle(process_id, storage_partition,
-                          constructor_uses_file_url);
-  std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories =
-      CreateFactoryBundle(process_id, storage_partition,
-                          constructor_uses_file_url);
+  std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+      factory_bundle_for_browser = CreateFactoryBundle(
+          process_id, storage_partition, constructor_uses_file_url);
+  std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+      subresource_loader_factories = CreateFactoryBundle(
+          process_id, storage_partition, constructor_uses_file_url);
 
   // NetworkService (PlzWorker):
   // Create a resource request for initiating shared worker script fetch from
@@ -106,7 +106,7 @@
           std::move(callback)));
 }
 
-std::unique_ptr<URLLoaderFactoryBundleInfo>
+std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
 WorkerScriptFetchInitiator::CreateFactoryBundle(
     int process_id,
     StoragePartitionImpl* storage_partition,
@@ -120,7 +120,7 @@
       ->RegisterNonNetworkSubresourceURLLoaderFactories(
           process_id, MSG_ROUTING_NONE, &non_network_factories);
 
-  auto factory_bundle = std::make_unique<URLLoaderFactoryBundleInfo>();
+  auto factory_bundle = std::make_unique<blink::URLLoaderFactoryBundleInfo>();
   for (auto& pair : non_network_factories) {
     const std::string& scheme = pair.first;
     std::unique_ptr<network::mojom::URLLoaderFactory> factory =
@@ -221,8 +221,10 @@
     int process_id,
     std::unique_ptr<network::ResourceRequest> resource_request,
     scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_browser_info,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        factory_bundle_for_browser_info,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factories,
     scoped_refptr<ServiceWorkerContextWrapper> context,
     AppCacheNavigationHandleCore* appcache_handle_core,
     std::unique_ptr<network::SharedURLLoaderFactoryInfo>
@@ -261,7 +263,7 @@
       factory_bundle_for_browser_info->default_factory_info() =
           network_factory_ptr.PassInterface();
     }
-    url_loader_factory = base::MakeRefCounted<URLLoaderFactoryBundle>(
+    url_loader_factory = base::MakeRefCounted<blink::URLLoaderFactoryBundle>(
         std::move(factory_bundle_for_browser_info));
   }
 
@@ -319,7 +321,8 @@
         service_worker_provider_info,
     network::mojom::URLLoaderFactoryAssociatedPtrInfo
         main_script_loader_factory,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factories,
     blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
     base::Optional<SubresourceLoaderParams> subresource_loader_params,
     bool success) {
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.h b/content/browser/worker_host/worker_script_fetch_initiator.h
index de63130c..c1cbedb 100644
--- a/content/browser/worker_host/worker_script_fetch_initiator.h
+++ b/content/browser/worker_host/worker_script_fetch_initiator.h
@@ -18,6 +18,10 @@
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
 #include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h"
 
+namespace blink {
+class URLLoaderFactoryBundleInfo;
+}  // namespace blink
+
 namespace network {
 class SharedURLLoaderFactory;
 class SharedURLLoaderFactoryInfo;
@@ -29,7 +33,6 @@
 class BrowserContext;
 class ServiceWorkerContextWrapper;
 class StoragePartitionImpl;
-class URLLoaderFactoryBundleInfo;
 class URLLoaderFactoryGetter;
 struct SubresourceLoaderParams;
 
@@ -41,7 +44,7 @@
   using CompletionCallback = base::OnceCallback<void(
       blink::mojom::ServiceWorkerProviderInfoForSharedWorkerPtr,
       network::mojom::URLLoaderFactoryAssociatedPtrInfo,
-      std::unique_ptr<URLLoaderFactoryBundleInfo>,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>,
       blink::mojom::WorkerMainScriptLoadParamsPtr,
       base::Optional<SubresourceLoaderParams>,
       bool)>;
@@ -60,7 +63,7 @@
       CompletionCallback callback);
 
  private:
-  static std::unique_ptr<URLLoaderFactoryBundleInfo> CreateFactoryBundle(
+  static std::unique_ptr<blink::URLLoaderFactoryBundleInfo> CreateFactoryBundle(
       int process_id,
       StoragePartitionImpl* storage_partition,
       bool file_support);
@@ -71,9 +74,10 @@
       int process_id,
       std::unique_ptr<network::ResourceRequest> resource_request,
       scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter,
-      std::unique_ptr<URLLoaderFactoryBundleInfo>
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
           factory_bundle_for_browser_info,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+          subresource_loader_factories,
       scoped_refptr<ServiceWorkerContextWrapper> context,
       AppCacheNavigationHandleCore* appcache_handle_core,
       std::unique_ptr<network::SharedURLLoaderFactoryInfo>
@@ -85,7 +89,8 @@
           service_worker_provider_info,
       network::mojom::URLLoaderFactoryAssociatedPtrInfo
           main_script_loader_factory,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+          subresource_loader_factories,
       blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
       base::Optional<SubresourceLoaderParams> subresource_loader_params,
       bool success);
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index f98081f..d6df7633 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -255,8 +255,6 @@
     "throttling_url_loader.h",
     "unique_name_helper.cc",
     "unique_name_helper.h",
-    "url_loader_factory_bundle.cc",
-    "url_loader_factory_bundle.h",
     "url_schemes.cc",
     "url_schemes.h",
     "user_agent.cc",
@@ -510,7 +508,6 @@
     "renderer_host.mojom",
     "service_worker/embedded_worker.mojom",
     "shared_worker/shared_worker_factory.mojom",
-    "url_loader_factory_bundle.mojom",
     "widget.mojom",
   ]
 
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 53d7ae2..d2161a7 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -6,7 +6,6 @@
 
 import "content/common/navigation_client.mojom";
 import "content/common/navigation_params.mojom";
-import "content/common/url_loader_factory_bundle.mojom";
 import "content/public/common/resource_type.mojom";
 import "content/public/common/resource_load_info.mojom";
 import "content/public/common/transferrable_url_loader.mojom";
@@ -20,6 +19,7 @@
 import "third_party/blink/public/mojom/blob/blob_url_store.mojom";
 import "third_party/blink/public/mojom/feature_policy/feature_policy.mojom";
 import "third_party/blink/public/mojom/frame/navigation_initiator.mojom";
+import "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom";
 import "third_party/blink/public/mojom/referrer.mojom";
 import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom";
 import "third_party/blink/public/web/commit_result.mojom";
@@ -105,7 +105,7 @@
       CommonNavigationParams common_params,
       RequestNavigationParams request_params,
       network.mojom.URLLoaderClientEndpoints? url_loader_client_endpoints,
-      URLLoaderFactoryBundle? subresource_loader_factories,
+      blink.mojom.URLLoaderFactoryBundle? subresource_loader_factories,
       array<TransferrableURLLoader>? subresource_overrides,
       blink.mojom.ControllerServiceWorkerInfo? controller_service_worker_info,
       network.mojom.URLLoaderFactory? prefetch_loader_factory,
@@ -127,7 +127,7 @@
       bool has_stale_copy_in_cache,
       int32 error_code,
       string? error_page_content,
-      URLLoaderFactoryBundle? subresource_loader_factories)
+      blink.mojom.URLLoaderFactoryBundle? subresource_loader_factories)
       => (blink.mojom.CommitResult commit_result);
 
   // Tells the renderer that a same-document navigation should be committed.
@@ -151,7 +151,7 @@
   // The new bundle contains replacement factories for a subset of the
   // receiver's existing bundle.
   UpdateSubresourceLoaderFactories(
-      URLLoaderFactoryBundle subresource_loader_factories);
+      blink.mojom.URLLoaderFactoryBundle subresource_loader_factories);
 
   // Returns a DevToolsAgent interface for this frame, used for
   // remote debugging. See DevToolsAgent for details.
diff --git a/content/common/navigation_client.mojom b/content/common/navigation_client.mojom
index 14ee7ad..68fcecb 100644
--- a/content/common/navigation_client.mojom
+++ b/content/common/navigation_client.mojom
@@ -6,10 +6,10 @@
 
 import "services/network/public/mojom/url_loader.mojom";
 import "services/network/public/mojom/url_loader_factory.mojom";
-import "content/common/url_loader_factory_bundle.mojom";
 import "content/public/common/transferrable_url_loader.mojom";
 import "mojo/public/mojom/base/unguessable_token.mojom";
 import "url/mojom/url.mojom";
+import "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom";
 import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom";
 import "third_party/blink/public/web/commit_result.mojom";
 
@@ -57,7 +57,7 @@
       CommonNavigationParams common_params,
       RequestNavigationParams request_params,
       network.mojom.URLLoaderClientEndpoints? url_loader_client_endpoints,
-      URLLoaderFactoryBundle? subresource_loader_factories,
+      blink.mojom.URLLoaderFactoryBundle? subresource_loader_factories,
       array<TransferrableURLLoader>? subresource_overrides,
       blink.mojom.ControllerServiceWorkerInfo? controller_service_worker_info,
       network.mojom.URLLoaderFactory? prefetch_loader_factory,
@@ -79,7 +79,7 @@
       bool has_stale_copy_in_cache,
       int32 error_code,
       string? error_page_content,
-      URLLoaderFactoryBundle? subresource_loader_factories)
+      blink.mojom.URLLoaderFactoryBundle? subresource_loader_factories)
       => (blink.mojom.CommitResult commit_result);
 };
 
diff --git a/content/common/service_worker/embedded_worker.mojom b/content/common/service_worker/embedded_worker.mojom
index 99c5a02c..4270b107 100644
--- a/content/common/service_worker/embedded_worker.mojom
+++ b/content/common/service_worker/embedded_worker.mojom
@@ -5,13 +5,13 @@
 module content.mojom;
 
 import "content/common/native_types.mojom";
-import "content/common/url_loader_factory_bundle.mojom";
 import "content/public/common/renderer_preference_watcher.mojom";
 import "content/public/common/renderer_preferences.mojom";
 import "mojo/public/mojom/base/string16.mojom";
 import "mojo/public/mojom/base/time.mojom";
 import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/service_manager/public/mojom/interface_provider.mojom";
+import "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom";
 import "third_party/blink/public/mojom/script/script_type.mojom";
 import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker.mojom";
@@ -79,7 +79,7 @@
   // S13nServiceWorker: Used to load subresources in the service worker.
   // This allows the service worker to load chrome-extension:// URLs which
   // the renderer's default loader factory can't load.
-  URLLoaderFactoryBundle? subresource_loader_factories;
+  blink.mojom.URLLoaderFactoryBundle? subresource_loader_factories;
 };
 
 // Holds timing information about the start worker sequence for UMA.
diff --git a/content/common/shared_worker/shared_worker_factory.mojom b/content/common/shared_worker/shared_worker_factory.mojom
index 71f1e16..5abf76e 100644
--- a/content/common/shared_worker/shared_worker_factory.mojom
+++ b/content/common/shared_worker/shared_worker_factory.mojom
@@ -4,12 +4,12 @@
 
 module content.mojom;
 
-import "content/common/url_loader_factory_bundle.mojom";
 import "content/public/common/renderer_preference_watcher.mojom";
 import "content/public/common/renderer_preferences.mojom";
 import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/network/public/mojom/url_loader_factory.mojom";
 import "services/service_manager/public/mojom/interface_provider.mojom";
+import "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom";
 import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom";
 import "third_party/blink/public/mojom/worker/shared_worker.mojom";
@@ -79,7 +79,7 @@
       // subresources where applicable. For example, this allows the shared
       // worker to load chrome-extension:// URLs which the renderer's default
       // loader factory can't load.
-      URLLoaderFactoryBundle? subresource_loader_factories,
+      blink.mojom.URLLoaderFactoryBundle? subresource_loader_factories,
 
       // NetworkService (PlzWorker):
       // Used for setting ServiceWorkerContainer#controller. This is null when
diff --git a/content/common/typemaps.gni b/content/common/typemaps.gni
index 6a814a0..54abf7f6 100644
--- a/content/common/typemaps.gni
+++ b/content/common/typemaps.gni
@@ -13,6 +13,5 @@
   "//content/common/navigation_params.typemap",
   "//content/common/push_messaging.typemap",
   "//content/common/render_frame_metadata.typemap",
-  "//content/common/url_loader_factory_bundle.typemap",
   "//content/common/web_preferences.typemap",
 ]
diff --git a/content/common/url_loader_factory_bundle.typemap b/content/common/url_loader_factory_bundle.typemap
deleted file mode 100644
index 1689e50..0000000
--- a/content/common/url_loader_factory_bundle.typemap
+++ /dev/null
@@ -1,13 +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.
-
-mojom = "//content/common/url_loader_factory_bundle.mojom"
-public_headers = [ "//content/common/url_loader_factory_bundle.h" ]
-traits_headers =
-    [ "//content/common/url_loader_factory_bundle_struct_traits.h" ]
-sources = [
-  "//content/common/url_loader_factory_bundle_struct_traits.cc",
-]
-
-type_mappings = [ "content.mojom.URLLoaderFactoryBundle=std::unique_ptr<content::URLLoaderFactoryBundleInfo>[move_only,nullable_is_same_type]" ]
diff --git a/content/common/url_loader_factory_bundle_struct_traits.h b/content/common/url_loader_factory_bundle_struct_traits.h
deleted file mode 100644
index 487ffb2..0000000
--- a/content/common/url_loader_factory_bundle_struct_traits.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_STRUCT_TRAITS_H_
-#define CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_STRUCT_TRAITS_H_
-
-#include <memory>
-
-#include "content/common/url_loader_factory_bundle.h"
-#include "content/common/url_loader_factory_bundle.mojom-shared.h"
-#include "mojo/public/cpp/bindings/struct_traits.h"
-
-namespace mojo {
-
-template <>
-struct StructTraits<content::mojom::URLLoaderFactoryBundleDataView,
-                    std::unique_ptr<content::URLLoaderFactoryBundleInfo>> {
-  using BundleInfoType = std::unique_ptr<content::URLLoaderFactoryBundleInfo>;
-
-  static bool IsNull(const BundleInfoType& bundle) { return !bundle; }
-
-  static void SetToNull(BundleInfoType* bundle) { bundle->reset(); }
-
-  static network::mojom::URLLoaderFactoryPtrInfo default_factory(
-      BundleInfoType& bundle);
-
-  static network::mojom::URLLoaderFactoryPtrInfo appcache_factory(
-      BundleInfoType& bundle);
-
-  static content::URLLoaderFactoryBundleInfo::SchemeMap
-  scheme_specific_factories(BundleInfoType& bundle);
-
-  static content::URLLoaderFactoryBundleInfo::OriginMap
-  initiator_specific_factories(BundleInfoType& bundle);
-
-  static bool bypass_redirect_checks(BundleInfoType& bundle);
-
-  static bool Read(content::mojom::URLLoaderFactoryBundleDataView data,
-                   BundleInfoType* out_bundle);
-};
-
-}  // namespace mojo
-
-#endif  // CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_STRUCT_TRAITS_H_
diff --git a/content/content_resources.grd b/content/content_resources.grd
index 6578475..44307b2 100644
--- a/content/content_resources.grd
+++ b/content/content_resources.grd
@@ -26,7 +26,6 @@
       <include name="IDR_INDEXED_DB_INTERNALS_CSS" file="browser/resources/indexed_db/indexeddb_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
       <include name="IDR_MEDIA_INTERNALS_HTML" file="browser/resources/media/media_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
       <include name="IDR_MEDIA_INTERNALS_JS" file="browser/resources/media/media_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
-      <include name="IDR_MOJO_CATALOG_MANIFEST" file="../services/catalog/manifest.json" type="BINDATA" />
       <include name="IDR_MOJO_CONTENT_BROWSER_MANIFEST" file="${root_gen_dir}/content/public/app/browser_manifest.json" use_base_dir="false" type="BINDATA" />
       <include name="IDR_MOJO_CONTENT_GPU_MANIFEST" file="${root_gen_dir}/content/public/app/gpu_manifest.json" use_base_dir="false" type="BINDATA" />
       <include name="IDR_MOJO_CONTENT_PACKAGED_SERVICES_MANIFEST" file="${root_gen_dir}/content/public/app/packaged_services_manifest.json" use_base_dir="false" type="BINDATA" />
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index 2a5692b..ebfeba7e 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -45,7 +45,6 @@
           "blink.mojom.EmbeddedFrameSinkProvider",
           "blink.mojom.FileUtilitiesHost",
           "blink.mojom.FileSystemManager",
-          "blink.mojom.IDBFactory",
           "blink.mojom.Hyphenation",
           "blink.mojom.MimeRegistry",
           "blink.mojom.PluginRegistry",
@@ -172,10 +171,11 @@
           "blink.mojom.DedicatedWorkerFactory",
           "blink.mojom.FileChooser",
           "blink.mojom.FileSystemManager",
-          "blink.mojom.LockManager",
           "blink.mojom.GeolocationService",
+          "blink.mojom.IDBFactory",
           "blink.mojom.InsecureInputService",
           "blink.mojom.KeyboardLockService",
+          "blink.mojom.LockManager",
           "blink.mojom.MediaDevicesDispatcherHost",
           "blink.mojom.MediaSessionService",
           "blink.mojom.NotificationService",
@@ -238,6 +238,7 @@
           "blink.mojom.CacheStorage",
           "blink.mojom.DedicatedWorkerFactory",
           "blink.mojom.FileSystemManager",
+          "blink.mojom.IDBFactory",
           "blink.mojom.LockManager",
           "blink.mojom.NotificationService",
           "blink.mojom.PermissionService",
@@ -257,6 +258,7 @@
           "blink.mojom.BackgroundFetchService",
           "blink.mojom.CacheStorage",
           "blink.mojom.CookieStore",
+          "blink.mojom.IDBFactory",
           "blink.mojom.LockManager",
           "blink.mojom.NotificationService",
           "blink.mojom.PermissionService",
@@ -275,6 +277,7 @@
         "renderer": [
           "blink.mojom.CacheStorage",
           "blink.mojom.FileSystemManager",
+          "blink.mojom.IDBFactory",
           "blink.mojom.LockManager",
           "blink.mojom.NotificationService",
           "blink.mojom.PermissionService",
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h
index 3cb06a7..518b757d 100644
--- a/content/public/browser/render_process_host.h
+++ b/content/public/browser/render_process_host.h
@@ -27,6 +27,7 @@
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
 #include "ui/gfx/native_widget_types.h"
 
 #if defined(OS_ANDROID)
@@ -464,6 +465,12 @@
   virtual void BindCacheStorage(blink::mojom::CacheStorageRequest request,
                                 const url::Origin& origin) = 0;
 
+  // Binds |request| to the IndexedDBDispatcherHost instance. The binding is
+  // sent to the IO thread. This is for internal use only, and is only exposed
+  // here to support MockRenderProcessHost usage in tests.
+  virtual void BindIndexedDB(blink::mojom::IDBFactoryRequest request,
+                             const url::Origin& origin) = 0;
+
   // Returns the current number of active views in this process.  Excludes
   // any RenderViewHosts that are swapped out.
   size_t GetActiveViewCount();
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc
index c049ee0..528345d5a 100644
--- a/content/public/test/mock_render_process_host.cc
+++ b/content/public/test/mock_render_process_host.cc
@@ -450,6 +450,12 @@
   cache_storage_request_ = std::move(request);
 }
 
+void MockRenderProcessHost::BindIndexedDB(
+    blink::mojom::IDBFactoryRequest request,
+    const url::Origin& origin) {
+  idb_factory_request_ = std::move(request);
+}
+
 void MockRenderProcessHost::CleanupCorbExceptionForPluginUponDestruction() {}
 
 void MockRenderProcessHost::FilterURL(bool empty_allowed, GURL* url) {
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h
index 2669ea4..6a344e4 100644
--- a/content/public/test/mock_render_process_host.h
+++ b/content/public/test/mock_render_process_host.h
@@ -160,6 +160,8 @@
   void LockToOrigin(const GURL& lock_url) override;
   void BindCacheStorage(blink::mojom::CacheStorageRequest request,
                         const url::Origin& origin) override;
+  void BindIndexedDB(blink::mojom::IDBFactoryRequest request,
+                     const url::Origin& origin) override;
   void CleanupCorbExceptionForPluginUponDestruction() override;
 
   // IPC::Sender via RenderProcessHost.
@@ -230,6 +232,7 @@
   bool is_renderer_locked_to_site_ = false;
   network::mojom::URLLoaderFactory* url_loader_factory_;
   blink::mojom::CacheStorageRequest cache_storage_request_;
+  blink::mojom::IDBFactoryRequest idb_factory_request_;
   base::WeakPtrFactory<MockRenderProcessHost> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(MockRenderProcessHost);
diff --git a/content/renderer/loader/child_url_loader_factory_bundle.h b/content/renderer/loader/child_url_loader_factory_bundle.h
index c4cfffc..2a26ba3 100644
--- a/content/renderer/loader/child_url_loader_factory_bundle.h
+++ b/content/renderer/loader/child_url_loader_factory_bundle.h
@@ -13,9 +13,9 @@
 #include "base/optional.h"
 #include "content/common/content_export.h"
 #include "content/common/possibly_associated_interface_ptr.h"
-#include "content/common/url_loader_factory_bundle.h"
 #include "content/public/common/transferrable_url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
 
 namespace content {
 
@@ -28,7 +28,7 @@
 // flag is enabled. TODO(crbug/803776): deprecate this once SXG specific code is
 // moved into Network Service unless we see huge memory benefit for doing this.
 class CONTENT_EXPORT ChildURLLoaderFactoryBundleInfo
-    : public URLLoaderFactoryBundleInfo {
+    : public blink::URLLoaderFactoryBundleInfo {
  public:
   using PossiblyAssociatedURLLoaderFactoryPtrInfo =
       PossiblyAssociatedInterfacePtrInfo<network::mojom::URLLoaderFactory>;
@@ -68,7 +68,7 @@
 // Besides, it also supports using callbacks to lazily initialize the direct
 // network loader factory.
 class CONTENT_EXPORT ChildURLLoaderFactoryBundle
-    : public URLLoaderFactoryBundle {
+    : public blink::URLLoaderFactoryBundle {
  public:
   using PossiblyAssociatedURLLoaderFactoryPtr =
       PossiblyAssociatedInterfacePtr<network::mojom::URLLoaderFactory>;
diff --git a/content/renderer/loader/tracked_child_url_loader_factory_bundle.cc b/content/renderer/loader/tracked_child_url_loader_factory_bundle.cc
index 30f7ff89..cc9e9792 100644
--- a/content/renderer/loader/tracked_child_url_loader_factory_bundle.cc
+++ b/content/renderer/loader/tracked_child_url_loader_factory_bundle.cc
@@ -174,12 +174,12 @@
 }
 
 void HostChildURLLoaderFactoryBundle::UpdateThisAndAllClones(
-    std::unique_ptr<URLLoaderFactoryBundleInfo> info) {
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo> info) {
   DCHECK(RenderThread::Get()) << "Should run on the main renderer thread";
   DCHECK(observer_list_);
 
   auto partial_bundle = base::MakeRefCounted<ChildURLLoaderFactoryBundle>();
-  static_cast<URLLoaderFactoryBundle*>(partial_bundle.get())
+  static_cast<blink::URLLoaderFactoryBundle*>(partial_bundle.get())
       ->Update(std::move(info));
 
   for (const auto& iter : *observer_list_) {
diff --git a/content/renderer/loader/tracked_child_url_loader_factory_bundle.h b/content/renderer/loader/tracked_child_url_loader_factory_bundle.h
index 16a6d21f..a7b15b9 100644
--- a/content/renderer/loader/tracked_child_url_loader_factory_bundle.h
+++ b/content/renderer/loader/tracked_child_url_loader_factory_bundle.h
@@ -128,7 +128,8 @@
   // Update this bundle with |info|, and post cloned |info| to tracked bundles.
   // Note: We don't need to worry about |direct_network_factory_| since it's
   // only used by |RendererBlinkPlatformImpl| and doesn't rely on this codepath.
-  void UpdateThisAndAllClones(std::unique_ptr<URLLoaderFactoryBundleInfo> info);
+  void UpdateThisAndAllClones(
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo> info);
 
  private:
   friend class TrackedChildURLLoaderFactoryBundle;
diff --git a/content/renderer/navigation_client.cc b/content/renderer/navigation_client.cc
index 3dfdd6f3..649ad2a 100644
--- a/content/renderer/navigation_client.cc
+++ b/content/renderer/navigation_client.cc
@@ -18,7 +18,7 @@
     const CommonNavigationParams& common_params,
     const RequestNavigationParams& request_params,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
     base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>>
         subresource_overrides,
     blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info,
@@ -45,7 +45,7 @@
     bool has_stale_copy_in_cache,
     int error_code,
     const base::Optional<std::string>& error_page_content,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
     CommitFailedNavigationCallback callback) {
   ResetDisconnectionHandler();
   render_frame_->CommitFailedNavigation(
diff --git a/content/renderer/navigation_client.h b/content/renderer/navigation_client.h
index 325a399..1499207 100644
--- a/content/renderer/navigation_client.h
+++ b/content/renderer/navigation_client.h
@@ -23,7 +23,7 @@
       const CommonNavigationParams& common_params,
       const RequestNavigationParams& request_params,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
       base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>>
           subresource_overrides,
       blink::mojom::ControllerServiceWorkerInfoPtr
@@ -37,7 +37,7 @@
       bool has_stale_copy_in_cache,
       int error_code,
       const base::Optional<std::string>& error_page_content,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
       CommitFailedNavigationCallback callback) override;
 
   void Bind(mojom::NavigationClientAssociatedRequest request);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 934203f..cd54805e 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -3199,7 +3199,8 @@
     const CommonNavigationParams& common_params,
     const RequestNavigationParams& request_params,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factories,
     base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>>
         subresource_overrides,
     blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info,
@@ -3338,7 +3339,8 @@
     bool has_stale_copy_in_cache,
     int error_code,
     const base::Optional<std::string>& error_page_content,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factories,
     CommitFailedNavigationCallback callback) {
   TRACE_EVENT1("navigation,benchmark,rail",
                "RenderFrameImpl::CommitFailedNavigation", "id", routing_id_);
@@ -3584,7 +3586,7 @@
 }
 
 void RenderFrameImpl::UpdateSubresourceLoaderFactories(
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders) {
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders) {
   DCHECK(loader_factories_);
   DCHECK(loader_factories_->IsHostChildURLLoaderFactoryBundle());
   static_cast<HostChildURLLoaderFactoryBundle*>(loader_factories_.get())
@@ -6522,7 +6524,7 @@
 }
 
 void RenderFrameImpl::SetupLoaderFactoryBundle(
-    std::unique_ptr<URLLoaderFactoryBundleInfo> info,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo> info,
     base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>>
         subresource_overrides,
     network::mojom::URLLoaderFactoryPtr prefetch_loader_factory) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 58a4401..976b8d3 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -542,7 +542,7 @@
       const CommonNavigationParams& common_params,
       const RequestNavigationParams& request_params,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
       base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>>
           subresource_overrides,
       blink::mojom::ControllerServiceWorkerInfoPtr
@@ -556,7 +556,7 @@
       bool has_stale_copy_in_cache,
       int error_code,
       const base::Optional<std::string>& error_page_content,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
       CommitFailedNavigationCallback callback) override;
   void CommitSameDocumentNavigation(
       const CommonNavigationParams& common_params,
@@ -564,7 +564,8 @@
       CommitSameDocumentNavigationCallback callback) override;
   void HandleRendererDebugURL(const GURL& url) override;
   void UpdateSubresourceLoaderFactories(
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders) override;
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders)
+      override;
   void BindDevToolsAgent(
       blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
       blink::mojom::DevToolsAgentAssociatedRequest request) override;
@@ -1108,7 +1109,7 @@
   ChildURLLoaderFactoryBundle* GetLoaderFactoryBundle();
 
   void SetupLoaderFactoryBundle(
-      std::unique_ptr<URLLoaderFactoryBundleInfo> info,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo> info,
       base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>>
           subresource_overrides,
       network::mojom::URLLoaderFactoryPtr prefetch_loader_factory);
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 15fc330..bd533c2 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -231,67 +231,6 @@
   return WebURLRequest::Priority::kVeryLow;
 }
 
-void ToWebServiceWorkerRequestForFetchEvent(
-    blink::mojom::FetchAPIRequestPtr request,
-    std::vector<blink::mojom::BlobPtrInfo> blob_ptrs,
-    const std::string& client_id,
-    blink::WebServiceWorkerRequest* web_request) {
-  DCHECK(web_request);
-  web_request->SetURL(blink::WebURL(request->url));
-  web_request->SetMethod(blink::WebString::FromUTF8(request->method));
-  for (const auto& pair : request->headers) {
-    if (!GetContentClient()
-             ->renderer()
-             ->IsExcludedHeaderForServiceWorkerFetchEvent(pair.first)) {
-      web_request->SetHeader(blink::WebString::FromUTF8(pair.first),
-                             blink::WebString::FromUTF8(pair.second));
-    }
-  }
-
-  // Non-S13nServiceWorker: The body is provided as a blob.
-  if (request->blob) {
-    DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
-    web_request->SetBlob(blink::WebString::FromASCII(request->blob->uuid),
-                         request->blob->size, request->blob->blob.PassHandle());
-  }
-  // S13nServiceWorker: The body is provided in |request->body|.
-  else if (request->body.has_value()) {
-    DCHECK(request->body.value());
-    DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
-    // |blob_ptrs| should be empty when Network Service is enabled.
-    DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService) ||
-           blob_ptrs.empty());
-    blink::WebHTTPBody body = GetWebHTTPBodyForRequestBodyWithBlobPtrs(
-        *(request->body.value()), std::move(blob_ptrs));
-    body.SetUniqueBoundary();
-    web_request->SetBody(body);
-  }
-
-  if (request->referrer) {
-    web_request->SetReferrer(
-        blink::WebString::FromUTF8(request->referrer->url.spec()),
-        request->referrer->policy);
-  }
-  web_request->SetMode(request->mode);
-  web_request->SetIsMainResourceLoad(request->is_main_resource_load);
-  web_request->SetCredentialsMode(request->credentials_mode);
-  web_request->SetCacheMode(request->cache_mode);
-  web_request->SetRedirectMode(request->redirect_mode);
-  web_request->SetRequestContext(request->request_context_type);
-  web_request->SetFrameType(request->frame_type);
-  web_request->SetClientId(blink::WebString::FromUTF8(client_id));
-  web_request->SetIsReload(request->is_reload);
-  if (request->integrity) {
-    web_request->SetIntegrity(blink::WebString::FromUTF8(*request->integrity));
-  }
-  web_request->SetPriority(
-      ConvertNetPriorityToWebKitPriority(request->priority));
-  web_request->SetKeepalive(request->keepalive);
-  web_request->SetIsHistoryNavigation(request->is_history_navigation);
-  if (request->fetch_window_id)
-    web_request->SetWindowId(*request->fetch_window_id);
-}
-
 // Finds an event callback keyed by |event_id| from |map|, and runs the callback
 // with |args|. Returns true if the callback was found and called, otherwise
 // returns false.
@@ -570,7 +509,7 @@
     std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client,
     mojom::EmbeddedWorkerStartTimingPtr start_timing,
     mojom::RendererPreferenceWatcherRequest preference_watcher_request,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
     scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
     : embedded_worker_id_(embedded_worker_id),
       service_worker_version_id_(service_worker_version_id),
@@ -1362,6 +1301,71 @@
   proxy_->DispatchPaymentRequestEvent(event_id, webEventData);
 }
 
+void ServiceWorkerContextClient::ToWebServiceWorkerRequestForFetchEvent(
+    blink::mojom::FetchAPIRequestPtr request,
+    const std::string& client_id,
+    blink::WebServiceWorkerRequest* web_request) {
+  DCHECK(web_request);
+  web_request->SetURL(blink::WebURL(request->url));
+  web_request->SetMethod(blink::WebString::FromUTF8(request->method));
+  for (const auto& pair : request->headers) {
+    if (!GetContentClient()
+             ->renderer()
+             ->IsExcludedHeaderForServiceWorkerFetchEvent(pair.first)) {
+      web_request->SetHeader(blink::WebString::FromUTF8(pair.first),
+                             blink::WebString::FromUTF8(pair.second));
+    }
+  }
+
+  // Non-S13nServiceWorker: The body is provided as a blob.
+  if (request->blob) {
+    DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
+    web_request->SetBlob(blink::WebString::FromASCII(request->blob->uuid),
+                         request->blob->size, request->blob->blob.PassHandle());
+  }
+  // S13nServiceWorker: The body is provided in |request->body|.
+  else if (request->body.has_value()) {
+    DCHECK(request->body.value());
+    DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+    std::vector<blink::mojom::BlobPtrInfo> blob_ptrs;
+    if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+      // We need this as GetBlobFromUUID is a sync IPC.
+      // TODO(kinuko): Remove the friend for ScopedAllowBaseSyncPrimitives
+      // in //base as well when we remove this code.
+      base::ScopedAllowBaseSyncPrimitives allow_sync_primitives;
+      blob_ptrs = GetBlobPtrsForRequestBody(*(request->body.value()));
+    }
+    blink::WebHTTPBody body = GetWebHTTPBodyForRequestBodyWithBlobPtrs(
+        *(request->body.value()), std::move(blob_ptrs));
+    body.SetUniqueBoundary();
+    web_request->SetBody(body);
+  }
+
+  if (request->referrer) {
+    web_request->SetReferrer(
+        blink::WebString::FromUTF8(request->referrer->url.spec()),
+        request->referrer->policy);
+  }
+  web_request->SetMode(request->mode);
+  web_request->SetIsMainResourceLoad(request->is_main_resource_load);
+  web_request->SetCredentialsMode(request->credentials_mode);
+  web_request->SetCacheMode(request->cache_mode);
+  web_request->SetRedirectMode(request->redirect_mode);
+  web_request->SetRequestContext(request->request_context_type);
+  web_request->SetFrameType(request->frame_type);
+  web_request->SetClientId(blink::WebString::FromUTF8(client_id));
+  web_request->SetIsReload(request->is_reload);
+  if (request->integrity) {
+    web_request->SetIntegrity(blink::WebString::FromUTF8(*request->integrity));
+  }
+  web_request->SetPriority(
+      ConvertNetPriorityToWebKitPriority(request->priority));
+  web_request->SetKeepalive(request->keepalive);
+  web_request->SetIsHistoryNavigation(request->is_history_navigation);
+  if (request->fetch_window_id)
+    web_request->SetWindowId(*request->fetch_window_id);
+}
+
 void ServiceWorkerContextClient::SendWorkerStarted(
     blink::mojom::ServiceWorkerStartStatus status) {
   DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
@@ -1603,9 +1607,8 @@
 
   // Dispatch the event to the service worker execution context.
   blink::WebServiceWorkerRequest web_request;
-  ToWebServiceWorkerRequestForFetchEvent(
-      std::move(params->request), std::move(params->request_body_blob_ptrs),
-      params->client_id, &web_request);
+  ToWebServiceWorkerRequestForFetchEvent(std::move(params->request),
+                                         params->client_id, &web_request);
   proxy_->DispatchFetchEvent(event_id, web_request, navigation_preload_sent);
 }
 
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
index 024654f..a4a6987e 100644
--- a/content/renderer/service_worker/service_worker_context_client.h
+++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -96,7 +96,7 @@
       std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client,
       mojom::EmbeddedWorkerStartTimingPtr start_timing,
       mojom::RendererPreferenceWatcherRequest preference_watcher_request,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
       scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
   ~ServiceWorkerContextClient() override;
 
@@ -226,6 +226,11 @@
                            DispatchOrQueueFetchEvent_NotRequestedTermination);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextClientTest, TaskInServiceWorker);
 
+  static void ToWebServiceWorkerRequestForFetchEvent(
+      blink::mojom::FetchAPIRequestPtr request,
+      const std::string& client_id,
+      blink::WebServiceWorkerRequest* web_request);
+
   // Get routing_id for sending message to the ServiceWorkerVersion
   // in the browser process.
   int GetRoutingID() const { return embedded_worker_id_; }
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.cc b/content/renderer/service_worker/service_worker_subresource_loader.cc
index fdad598..68df0916a 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -282,19 +282,8 @@
   params->request = blink::mojom::FetchAPIRequest::From(resource_request_);
   params->client_id = controller_connector_->client_id();
 
-  // S13nServiceWorker without NetworkService:
-  // BlobPtr for each blob data element in the request body needs to be created
-  // before dispatching the fetch event for keeping the blob alive.
-  if (resource_request_.request_body &&
-      !base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    // We need this as GetBlobFromUUID is a sync IPC.
-    // TODO(kinuko): Remove the friend for ScopedAllowBaseSyncPrimitives
-    // in //base as well when we remove this code.
-    base::ScopedAllowBaseSyncPrimitives allow_sync_primitives;
-    params->request_body_blob_ptrs =
-        GetBlobPtrsForRequestBody(*resource_request_.request_body);
-  }
-
+  // TODO(falken): Grant the controller service worker's process access to files
+  // in the body, like ServiceWorkerFetchDispatcher::DispatchFetchEvent() does.
   controller->DispatchFetchEvent(
       std::move(params), std::move(response_callback_ptr),
       base::BindOnce(&ServiceWorkerSubresourceLoader::OnFetchEventFinished,
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index e582f04a..adf241f 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -11,7 +11,6 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/common/possibly_associated_wrapper_shared_url_loader_factory.h"
-#include "content/common/url_loader_factory_bundle.h"
 #include "content/public/common/appcache_info.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
@@ -34,6 +33,7 @@
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
 #include "third_party/blink/public/common/privacy_preferences.h"
 #include "third_party/blink/public/common/service_worker/service_worker_utils.h"
@@ -219,7 +219,7 @@
     network::mojom::URLLoaderFactoryAssociatedPtrInfo
         main_script_loader_factory,
     blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo> factory_bundle,
     blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
     blink::mojom::SharedWorkerHostPtr host,
     blink::mojom::SharedWorkerRequest request,
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.h b/content/renderer/shared_worker/embedded_shared_worker_stub.h
index 1fe9384..01ec7c8a 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.h
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.h
@@ -37,12 +37,12 @@
 
 namespace blink {
 class MessagePortChannel;
+class URLLoaderFactoryBundleInfo;
 }
 
 namespace content {
 
 class HostChildURLLoaderFactoryBundle;
-class URLLoaderFactoryBundleInfo;
 class WebApplicationCacheHostImpl;
 struct NavigationResponseOverrideParameters;
 
@@ -71,7 +71,8 @@
       network::mojom::URLLoaderFactoryAssociatedPtrInfo
           main_script_loader_factory,
       blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+          subresource_loader_factories,
       blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
       blink::mojom::SharedWorkerHostPtr host,
       blink::mojom::SharedWorkerRequest request,
diff --git a/content/renderer/shared_worker/shared_worker_factory_impl.cc b/content/renderer/shared_worker/shared_worker_factory_impl.cc
index 4d1a05a..ac9acbc 100644
--- a/content/renderer/shared_worker/shared_worker_factory_impl.cc
+++ b/content/renderer/shared_worker/shared_worker_factory_impl.cc
@@ -5,9 +5,9 @@
 #include "content/renderer/shared_worker/shared_worker_factory_impl.h"
 
 #include "base/memory/ptr_util.h"
-#include "content/common/url_loader_factory_bundle.h"
 #include "content/renderer/shared_worker/embedded_shared_worker_stub.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
 
 namespace content {
 
@@ -33,7 +33,8 @@
     network::mojom::URLLoaderFactoryAssociatedPtrInfo
         main_script_loader_factory,
     blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+        subresource_loader_factories,
     blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
     blink::mojom::SharedWorkerHostPtr host,
     blink::mojom::SharedWorkerRequest request,
diff --git a/content/renderer/shared_worker/shared_worker_factory_impl.h b/content/renderer/shared_worker/shared_worker_factory_impl.h
index 21947c8f..6ca3c74b 100644
--- a/content/renderer/shared_worker/shared_worker_factory_impl.h
+++ b/content/renderer/shared_worker/shared_worker_factory_impl.h
@@ -10,8 +10,11 @@
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
 
-namespace content {
+namespace blink {
 class URLLoaderFactoryBundleInfo;
+}  // namespace blink
+
+namespace content {
 
 class SharedWorkerFactoryImpl : public mojom::SharedWorkerFactory {
  public:
@@ -34,7 +37,8 @@
       network::mojom::URLLoaderFactoryAssociatedPtrInfo
           main_script_loader_factory,
       blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+          subresource_loader_factories,
       blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
       blink::mojom::SharedWorkerHostPtr host,
       blink::mojom::SharedWorkerRequest request,
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 53c2118..f38448a 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -869,6 +869,7 @@
     "../browser/service_manager/service_manager_context_browsertest.cc",
     "../browser/service_worker/service_worker_browsertest.cc",
     "../browser/service_worker/service_worker_clients_api_browsertest.cc",
+    "../browser/service_worker/service_worker_file_upload_browsertest.cc",
     "../browser/service_worker/service_worker_tls_browsertest.cc",
     "../browser/session_history_browsertest.cc",
     "../browser/shape_detection/shape_detection_browsertest.cc",
diff --git a/content/test/data/service_worker/file_upload_worker.js b/content/test/data/service_worker/file_upload_worker.js
new file mode 100644
index 0000000..bc288f0
--- /dev/null
+++ b/content/test/data/service_worker/file_upload_worker.js
@@ -0,0 +1,42 @@
+// 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.
+
+// Service worker for the file upload test. It responds to a POST submission
+// with an HTML document whose body describes the received form data in JSON.
+
+function describeValue(value) {
+  const result = {};
+  if (value instanceof File) {
+    return {type: 'file', size: value.size, name: value.name};
+  } else if (value instanceof Blob) {
+    return {type: 'blob', size: value.size};
+  } else {
+    return {type: 'string', data: value};
+  }
+}
+
+async function generateResponse(request) {
+  const formData = await request.formData();
+  const result = {};
+  result.entries = [];
+  for (var pair of formData.entries()) {
+    result.entries.push({key: pair[0], value: describeValue(pair[1])});
+  }
+  const resultString = JSON.stringify(result);
+  const body = String.raw`
+    <!doctype html>
+    <html>
+    <title>form submitted</title>
+    <body>${resultString}</body>
+    </html>
+  `;
+  const headers = {'content-type': 'text/html'};
+  return new Response(body, {headers});
+}
+
+self.addEventListener('fetch', event => {
+  if (event.request.method != 'POST')
+    return;
+  event.respondWith(generateResponse(event.request));
+});
diff --git a/content/test/data/service_worker/form.html b/content/test/data/service_worker/form.html
new file mode 100644
index 0000000..472f769
--- /dev/null
+++ b/content/test/data/service_worker/form.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- This page has a form that submits to the "target" param of the search part
+     of this page's URL. For example if this page's URL is
+     "form.html?target=//example.com/upload", the form submits to
+     //example.com/upload.
+-->
+<meta charset="utf-8">
+<head>
+<title>form</title>
+</head>
+<form id="form" method="POST" enctype="multipart/form-data">
+<input id="file" type="file" name="file">
+</form>
+<script>
+const fileInput = document.querySelector('#file');
+const form = document.querySelector('#form');
+
+// Set the form to submit to the |target| param.
+const documentUrl = new URL(window.location);
+form.action = documentUrl.searchParams.get('target');
+</script>
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py
index 19c7696..0604571 100644
--- a/content/test/gpu/gpu_tests/pixel_test_pages.py
+++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -950,7 +950,7 @@
       'filter_effects.html',
       base_name + '_CSSFilterEffects',
       test_rect=[0, 0, 300, 300],
-      revision=8),
+      revision=9),
     PixelTestPage(
       'filter_effects.html',
       base_name + '_CSSFilterEffects_NoOverlays',
diff --git a/content/test/mock_navigation_client_impl.cc b/content/test/mock_navigation_client_impl.cc
index d3de500..1043925 100644
--- a/content/test/mock_navigation_client_impl.cc
+++ b/content/test/mock_navigation_client_impl.cc
@@ -20,7 +20,7 @@
     const CommonNavigationParams& common_params,
     const RequestNavigationParams& request_params,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
     base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>>
         subresource_overrides,
     blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info,
@@ -34,7 +34,7 @@
     bool has_stale_copy_in_cache,
     int error_code,
     const base::Optional<std::string>& error_page_content,
-    std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+    std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
     CommitFailedNavigationCallback callback) {}
 
 }  // namespace content
diff --git a/content/test/mock_navigation_client_impl.h b/content/test/mock_navigation_client_impl.h
index 20af7425..638b9b7 100644
--- a/content/test/mock_navigation_client_impl.h
+++ b/content/test/mock_navigation_client_impl.h
@@ -22,7 +22,7 @@
       const CommonNavigationParams& common_params,
       const RequestNavigationParams& request_params,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
       base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>>
           subresource_overrides,
       blink::mojom::ControllerServiceWorkerInfoPtr
@@ -36,7 +36,7 @@
       bool has_stale_copy_in_cache,
       int error_code,
       const base::Optional<std::string>& error_page_content,
-      std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders,
+      std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders,
       CommitFailedNavigationCallback callback) override;
 
  private:
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index a72c282..f456f0c 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -161,7 +161,7 @@
   CommitNavigation(
       head, common_params, request_params,
       network::mojom::URLLoaderClientEndpointsPtr(),
-      std::make_unique<URLLoaderFactoryBundleInfo>(), base::nullopt,
+      std::make_unique<blink::URLLoaderFactoryBundleInfo>(), base::nullopt,
       blink::mojom::ControllerServiceWorkerInfoPtr(),
       network::mojom::URLLoaderFactoryPtr(), base::UnguessableToken::Create(),
       CommitNavigationCallback());
diff --git a/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc b/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
index 785092e0..c36dc61 100644
--- a/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/format_macros.h"
+#include "base/macros.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
diff --git a/extensions/browser/event_router_unittest.cc b/extensions/browser/event_router_unittest.cc
index 1d28464..6342f2c 100644
--- a/extensions/browser/event_router_unittest.cc
+++ b/extensions/browser/event_router_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
+#include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/values.h"
diff --git a/extensions/common/features/simple_feature_unittest.cc b/extensions/common/features/simple_feature_unittest.cc
index 0f719e81..eff9dbef 100644
--- a/extensions/common/features/simple_feature_unittest.cc
+++ b/extensions/common/features/simple_feature_unittest.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/command_line.h"
+#include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/scoped_command_line.h"
diff --git a/extensions/renderer/bindings/api_binding_js_util_unittest.cc b/extensions/renderer/bindings/api_binding_js_util_unittest.cc
index 80d91d2..dbd4646 100644
--- a/extensions/renderer/bindings/api_binding_js_util_unittest.cc
+++ b/extensions/renderer/bindings/api_binding_js_util_unittest.cc
@@ -5,6 +5,7 @@
 #include "extensions/renderer/bindings/api_binding_js_util.h"
 
 #include "base/bind.h"
+#include "base/macros.h"
 #include "base/optional.h"
 #include "base/stl_util.h"
 #include "extensions/renderer/bindings/api_binding_test_util.h"
diff --git a/extensions/renderer/bindings/api_binding_unittest.cc b/extensions/renderer/bindings/api_binding_unittest.cc
index d0c304b..fb377da 100644
--- a/extensions/renderer/bindings/api_binding_unittest.cc
+++ b/extensions/renderer/bindings/api_binding_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
diff --git a/extensions/renderer/bindings/api_event_handler_unittest.cc b/extensions/renderer/bindings/api_event_handler_unittest.cc
index ea1852b..b16d93e 100644
--- a/extensions/renderer/bindings/api_event_handler_unittest.cc
+++ b/extensions/renderer/bindings/api_event_handler_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
+#include "base/macros.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
diff --git a/extensions/renderer/bindings/argument_spec_unittest.cc b/extensions/renderer/bindings/argument_spec_unittest.cc
index 9b4dd8ac..6622d7d 100644
--- a/extensions/renderer/bindings/argument_spec_unittest.cc
+++ b/extensions/renderer/bindings/argument_spec_unittest.cc
@@ -5,6 +5,7 @@
 #include "extensions/renderer/bindings/argument_spec.h"
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/values.h"
 #include "extensions/renderer/bindings/api_binding_test_util.h"
diff --git a/extensions/renderer/bindings/declarative_event_unittest.cc b/extensions/renderer/bindings/declarative_event_unittest.cc
index f541a1d..97aa9675 100644
--- a/extensions/renderer/bindings/declarative_event_unittest.cc
+++ b/extensions/renderer/bindings/declarative_event_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
diff --git a/extensions/renderer/bindings/event_emitter_unittest.cc b/extensions/renderer/bindings/event_emitter_unittest.cc
index 645e9e5..f7cc5525 100644
--- a/extensions/renderer/bindings/event_emitter_unittest.cc
+++ b/extensions/renderer/bindings/event_emitter_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/values.h"
 #include "extensions/renderer/bindings/api_binding_test.h"
diff --git a/extensions/renderer/gin_port_unittest.cc b/extensions/renderer/gin_port_unittest.cc
index 2fe0a631..24ebce1 100644
--- a/extensions/renderer/gin_port_unittest.cc
+++ b/extensions/renderer/gin_port_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/macros.h"
 #include "base/optional.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
diff --git a/extensions/renderer/native_extension_bindings_system_unittest.cc b/extensions/renderer/native_extension_bindings_system_unittest.cc
index 02661d1..c2f0937 100644
--- a/extensions/renderer/native_extension_bindings_system_unittest.cc
+++ b/extensions/renderer/native_extension_bindings_system_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "extensions/renderer/native_extension_bindings_system_test_base.h"
 
+#include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/bind_test_util.h"
diff --git a/extensions/renderer/native_renderer_messaging_service_unittest.cc b/extensions/renderer/native_renderer_messaging_service_unittest.cc
index 69a9fa6..bd66eb3 100644
--- a/extensions/renderer/native_renderer_messaging_service_unittest.cc
+++ b/extensions/renderer/native_renderer_messaging_service_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/macros.h"
 #include "base/stl_util.h"
 #include "components/crx_file/id_util.h"
 #include "content/public/common/child_process_host.h"
diff --git a/extensions/renderer/one_time_message_handler_unittest.cc b/extensions/renderer/one_time_message_handler_unittest.cc
index 0a34a84..d4442e2 100644
--- a/extensions/renderer/one_time_message_handler_unittest.cc
+++ b/extensions/renderer/one_time_message_handler_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
diff --git a/extensions/renderer/render_frame_observer_natives.cc b/extensions/renderer/render_frame_observer_natives.cc
index b69bdfe..918c283 100644
--- a/extensions/renderer/render_frame_observer_natives.cc
+++ b/extensions/renderer/render_frame_observer_natives.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index b88a5139..80a50114 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -714,60 +714,21 @@
       <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_AUTOCOMPLETE_SEARCHES_AND_URLS_TEXT" desc="Feature title in the settings for the user to enable/disable, to have autocomplete searches and URLs. Text related to 'Sends searches from the address bar and search box, and some cookies to your default search engine' [iOS only]">
         Autocomplete Searches and URLs
       </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_AUTOFILL_TEXT" desc="Feature in the settings for the user to enable/disable, to sync autofill data between devices. [iOS only]">
-        Autofill
-      </message>
       <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_BETTER_SEARCH_AND_BROWSING_DETAIL" desc="Detail text for a feature in the settings for the user to enable/disable, to make searches andn browsing better. Related to 'Make searches and browsing better'. [iOS only]">
         Sends URLs of pages you visit to Google
       </message>
       <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_BETTER_SEARCH_AND_BROWSING_TEXT" desc="Title for a feature in the settings for the user to enable/disable, to make searches andn browsing better. Related to 'Sends URLs of pages you visit to Google'. [iOS only]">
         Make searches and browsing better
       </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_BOOKMARKS_TEXT" desc="Feature in the settings for the user to enable/disable, to sync Bookmarks between devices. [iOS only]">
-        Bookmarks
-      </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_ENCRYPTION_TEXT" desc="Opens the encryption settings screen. [iOS only]">
-        Encryption
-      </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_GOOGLE_ACTIVITY_CONTROL_DETAIL" desc="Detail text to open the Google activity screen. Related to 'Google activity controls'. [iOS only]">
-        Control how your browsing history is used to personalize Search, ads, and more
-      </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_GOOGLE_ACTIVITY_CONTROL_TEXT" desc="Title to open the Google activity screen. Related to 'Control how your browsing history is used to personalize Search, ads, and more'. [iOS only]">
-        Google activity controls
-      </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_HISTORY_TEXT" desc="Feature in the settings for the user to enable/disable, to sync browsing history between devices. [iOS only]">
-        History
-      </message>
       <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_IMPROVE_CHROME_DETAIL" desc="Feature detail text in the settings for the user enable or disable. Related with 'Help improve Chrome's features and performance' feature. [iOS only]">
         Automatically sends usage statistics and crash reports to Google
       </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_MANAGED_SYNC_DATA_TEXT" desc="Opens the sync data screen for the user to manage their synced data. [iOS only]">
-        Manage Synced Data…
-      </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_OPENTABS_TEXT" desc="Feature in the settings for the user to enable/disable, to sync passwords between devices. [iOS only]">
-        Open tabs
-      </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_PASSWORD_TEXT" desc="Feature in the settings for the user to enable/disable, to sync passwords between devices. [iOS only]">
-        Passwords
-      </message>
       <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_PRELOAD_PAGES_DETAIL" desc="Detail text for a feature in the settings for the user to enable/disable, to preload pages. Related to 'Preload pages for faster browsing and searching'. [iOS only]">
         Uses cookies to remember your preferences, even if you don't visit those pages
       </message>
       <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_PRELOAD_PAGES_TEXT" desc="Title for a feature in the settings for the user to enable/disable, to preload pages. Related to 'Uses cookies to remember your preferences, even if you don't visit those pages'. [iOS only]">
         Preload pages for faster browsing and searching
       </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_READING_LIST_TEXT" desc="Feature in the settings for the user to enable/disable, to sync reading list links between devices. [iOS only]">
-        Reading List
-      </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_AUTOCOMPLETE_WALLET" desc="Label for the checkbox that controls the Autofill/Payments integration feature. 'Google Pay' should not be translated as it is the product name. [iOS only]">
-        Payment methods and addresses using Google Pay
-      </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_SETTINGS_TEXT" desc="Feature in the settings for the user to enable/disable, to sync settings data between devices. [iOS only]">
-        Settings
-      </message>
-      <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_SYNC_EVERYTHING" desc="Feature in the settings for the user enable or disable all the Google sync features. [iOS only]">
-        Use sync and all services
-      </message>
       <message name="IDS_IOS_GOOGLE_SERVICES_SETTINGS_TITLE" desc="Title for the view in the Settings for enabling/disabling Sync and all the Google services. [Length: 26em] [iOS only]">
         Sync and Google Services
       </message>
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm
index e720bd33..36acc0d 100644
--- a/ios/chrome/browser/about_flags.mm
+++ b/ios/chrome/browser/about_flags.mm
@@ -484,7 +484,7 @@
      FEATURE_VALUE_TYPE(kSearchCopiedImage)},
     {"copied-text-behavior", flag_descriptions::kCopiedTextBehaviorName,
      flag_descriptions::kCopiedTextBehaviorName, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(kCopiedTextBehavior)},
+     FEATURE_VALUE_TYPE(omnibox::kCopiedTextBehavior)},
 };
 
 // Add all switches from experimental flags to |command_line|.
diff --git a/ios/chrome/browser/snapshots/snapshot_tab_helper.h b/ios/chrome/browser/snapshots/snapshot_tab_helper.h
index 99749ad..21eacd62 100644
--- a/ios/chrome/browser/snapshots/snapshot_tab_helper.h
+++ b/ios/chrome/browser/snapshots/snapshot_tab_helper.h
@@ -21,7 +21,8 @@
 @protocol SnapshotGeneratorDelegate;
 
 // SnapshotTabHelper allows capturing and retrival for web page snapshots.
-class SnapshotTabHelper : public web::WebStateObserver,
+class SnapshotTabHelper : public infobars::InfoBarManager::Observer,
+                          public web::WebStateObserver,
                           public web::WebStateUserData<SnapshotTabHelper> {
  public:
   ~SnapshotTabHelper() override;
@@ -87,13 +88,24 @@
       web::PageLoadCompletionStatus load_completion_status) override;
   void WebStateDestroyed(web::WebState* web_state) override;
 
+  // infobars::InfoBarManager::Observer implementation.
+  void OnInfoBarAdded(infobars::InfoBar* infobar) override;
+  void OnInfoBarRemoved(infobars::InfoBar* infobar, bool animate) override;
+  void OnInfoBarReplaced(infobars::InfoBar* old_infobar,
+                         infobars::InfoBar* new_infobar) override;
+  void OnManagerShuttingDown(infobars::InfoBarManager* manager) override;
+
   web::WebState* web_state_ = nullptr;
   SnapshotGenerator* snapshot_generator_ = nil;
+  infobars::InfoBarManager* infobar_manager_ = nullptr;
 
   // Manages this object as an observer of |web_state_|.
   ScopedObserver<web::WebState, web::WebStateObserver> web_state_observer_;
 
-  std::unique_ptr<infobars::InfoBarManager::Observer> infobar_observer_;
+  // Manages this object as an observer of infobars.
+  ScopedObserver<infobars::InfoBarManager, infobars::InfoBarManager::Observer>
+      infobar_observer_;
+
   bool ignore_next_load_ = false;
 
   // Used to ensure |UpdateSnapshotWithCallback()| is not run when this object
diff --git a/ios/chrome/browser/snapshots/snapshot_tab_helper.mm b/ios/chrome/browser/snapshots/snapshot_tab_helper.mm
index d478e3c5..4202425 100644
--- a/ios/chrome/browser/snapshots/snapshot_tab_helper.mm
+++ b/ios/chrome/browser/snapshots/snapshot_tab_helper.mm
@@ -5,10 +5,8 @@
 #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
 
 #include "base/bind.h"
-#include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/task/post_task.h"
-#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
 #import "ios/chrome/browser/snapshots/snapshot_generator.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
@@ -19,80 +17,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-
-// SnapshotInfobarObserver watches an InfobarManager for InfoBar insertions,
-// removals or replacements and updates the page snapshot in response.
-class SnapshotInfobarObserver : public infobars::InfoBarManager::Observer {
- public:
-  SnapshotInfobarObserver(SnapshotTabHelper* owner,
-                          infobars::InfoBarManager* manager);
-  ~SnapshotInfobarObserver() override;
-
-  // infobars::InfoBarManager::Observer implementation.
-  void OnInfoBarAdded(infobars::InfoBar* infobar) override;
-  void OnInfoBarRemoved(infobars::InfoBar* infobar, bool animate) override;
-  void OnInfoBarReplaced(infobars::InfoBar* old_infobar,
-                         infobars::InfoBar* new_infobar) override;
-  void OnManagerShuttingDown(infobars::InfoBarManager* manager) override;
-
- private:
-  void OnInfoBarChanges();
-
-  SnapshotTabHelper* owner_ = nullptr;
-  infobars::InfoBarManager* manager_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(SnapshotInfobarObserver);
-};
-
-SnapshotInfobarObserver::SnapshotInfobarObserver(
-    SnapshotTabHelper* owner,
-    infobars::InfoBarManager* manager)
-    : owner_(owner), manager_(manager) {
-  DCHECK(owner_);
-  DCHECK(manager_);
-  manager_->AddObserver(this);
-}
-
-SnapshotInfobarObserver::~SnapshotInfobarObserver() {
-  if (manager_) {
-    manager_->RemoveObserver(this);
-    manager_ = nullptr;
-  }
-}
-
-void SnapshotInfobarObserver::OnInfoBarAdded(infobars::InfoBar* infobar) {
-  OnInfoBarChanges();
-}
-
-void SnapshotInfobarObserver::OnInfoBarRemoved(infobars::InfoBar* infobar,
-                                               bool animate) {
-  OnInfoBarChanges();
-}
-
-void SnapshotInfobarObserver::OnInfoBarReplaced(
-    infobars::InfoBar* old_infobar,
-    infobars::InfoBar* new_infobar) {
-  OnInfoBarChanges();
-}
-
-void SnapshotInfobarObserver::OnInfoBarChanges() {
-  // Update the page snapshot on any infobar change.
-  owner_->UpdateSnapshot();
-}
-
-void SnapshotInfobarObserver::OnManagerShuttingDown(
-    infobars::InfoBarManager* manager) {
-  // The InfoBarManager delete itself when the WebState is destroyed, so
-  // the observer needs to unregister itself when OnManagerShuttingDown
-  // is invoked.
-  DCHECK_EQ(manager_, manager);
-  manager_->RemoveObserver(this);
-  manager_ = nullptr;
-}
-
-}  // namespace;
-
 SnapshotTabHelper::~SnapshotTabHelper() {
   DCHECK(!web_state_);
 }
@@ -167,18 +91,17 @@
                                      NSString* session_id)
     : web_state_(web_state),
       web_state_observer_(this),
+      infobar_observer_(this),
       weak_ptr_factory_(this) {
   snapshot_generator_ = [[SnapshotGenerator alloc] initWithWebState:web_state_
                                                   snapshotSessionId:session_id];
+  web_state_observer_.Add(web_state_);
 
   // Supports missing InfoBarManager to make testing easier.
-  if (infobars::InfoBarManager* infobar_manager =
-          InfoBarManagerImpl::FromWebState(web_state_)) {
-    infobar_observer_ =
-        std::make_unique<SnapshotInfobarObserver>(this, infobar_manager);
+  infobar_manager_ = InfoBarManagerImpl::FromWebState(web_state_);
+  if (infobar_manager_) {
+    infobar_observer_.Add(infobar_manager_);
   }
-
-  web_state_observer_.Add(web_state_);
 }
 
 void SnapshotTabHelper::DidStartLoading(web::WebState* web_state) {
@@ -209,3 +132,24 @@
   web_state_observer_.Remove(web_state);
   web_state_ = nullptr;
 }
+
+void SnapshotTabHelper::OnInfoBarAdded(infobars::InfoBar* infobar) {
+  UpdateSnapshotWithCallback(nil);
+}
+
+void SnapshotTabHelper::OnInfoBarRemoved(infobars::InfoBar* infobar,
+                                         bool animate) {
+  UpdateSnapshotWithCallback(nil);
+}
+
+void SnapshotTabHelper::OnInfoBarReplaced(infobars::InfoBar* old_infobar,
+                                          infobars::InfoBar* new_infobar) {
+  UpdateSnapshotWithCallback(nil);
+}
+
+void SnapshotTabHelper::OnManagerShuttingDown(
+    infobars::InfoBarManager* manager) {
+  DCHECK_EQ(infobar_manager_, manager);
+  infobar_observer_.Remove(manager);
+  infobar_manager_ = nullptr;
+}
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
index 7affd02..3ecdc96 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
@@ -120,6 +120,9 @@
     return;
   }
 
+  if (CGSizeEqualToSize(self.collectionView.contentSize, CGSizeZero))
+    [self.collectionView layoutIfNeeded];
+
   CGFloat pinnedOffsetY = [self.headerController pinnedOffsetY];
   self.collectionShiftingOffset =
       MAX(0, pinnedOffsetY - self.collectionView.contentOffset.y);
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
index 789516a0..5030ffd 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.mm
@@ -236,14 +236,13 @@
   // Ignore if:
   // - explicitly requested via IgnoreRemainderOfCurrentScroll(),
   // - the scroll is a bounce-up animation at the top,
-  // - the scroll is attempting to scroll past the bottom of the page,
   // - the scroll is attempting to scroll content up when it already fits.
   bool scrolling_content_down = y_content_offset_ - from_offset < 0.0;
   bool scrolling_past_top = y_content_offset_ <= -top_inset_;
   bool content_fits = content_height_ <= scroll_view_height_ - top_inset_;
   if (ignoring_current_scroll_ ||
       (scrolling_past_top && !scrolling_content_down) ||
-      is_scrolled_to_bottom() || (content_fits && !scrolling_content_down)) {
+      (content_fits && !scrolling_content_down)) {
     return ScrollAction::kIgnore;
   }
 
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
index f9e1824..427a4f76 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
@@ -6,6 +6,7 @@
 
 #include "base/ios/ios_util.h"
 #include "base/metrics/user_metrics.h"
+#include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/ui/commands/activity_service_commands.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
@@ -429,7 +430,7 @@
     // when it's the first time setting the first responder.
     dispatch_async(dispatch_get_main_queue(), ^{
       UIMenuController* menu = [UIMenuController sharedMenuController];
-      if (base::FeatureList::IsEnabled(kCopiedTextBehavior)) {
+      if (base::FeatureList::IsEnabled(omnibox::kCopiedTextBehavior)) {
         UIMenuItem* visitCopiedLink = [[UIMenuItem alloc]
             initWithTitle:l10n_util::GetNSString(IDS_IOS_VISIT_COPIED_LINK)
                    action:@selector(visitCopiedLink:)];
@@ -458,15 +459,15 @@
   UIPasteboard* pasteboard = UIPasteboard.generalPasteboard;
   // remove along with flag kCopiedTextBehavior
   if (action == @selector(pasteAndGo:)) {
-    DCHECK(!base::FeatureList::IsEnabled(kCopiedTextBehavior));
+    DCHECK(!base::FeatureList::IsEnabled(omnibox::kCopiedTextBehavior));
     return UIPasteboard.generalPasteboard.string.length > 0;
   }
   if (action == @selector(visitCopiedLink:)) {
-    DCHECK(base::FeatureList::IsEnabled(kCopiedTextBehavior));
+    DCHECK(base::FeatureList::IsEnabled(omnibox::kCopiedTextBehavior));
     return pasteboard.hasURLs;
   }
   if (action == @selector(searchCopiedText:)) {
-    DCHECK(base::FeatureList::IsEnabled(kCopiedTextBehavior));
+    DCHECK(base::FeatureList::IsEnabled(omnibox::kCopiedTextBehavior));
     return !pasteboard.hasURLs && pasteboard.hasStrings;
   }
   return NO;
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
index 514d8a8..061c21d 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/ui/omnibox/omnibox_view_controller.h"
 
+#include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/ui/commands/load_query_commands.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_container_view.h"
@@ -78,7 +79,7 @@
 
   // Add Paste and Go option to the editing menu
   UIMenuController* menu = [UIMenuController sharedMenuController];
-  if (base::FeatureList::IsEnabled(kCopiedTextBehavior)) {
+  if (base::FeatureList::IsEnabled(omnibox::kCopiedTextBehavior)) {
     UIMenuItem* visitCopiedLink = [[UIMenuItem alloc]
         initWithTitle:l10n_util::GetNSString(IDS_IOS_VISIT_COPIED_LINK)
                action:@selector(visitCopiedLink:)];
@@ -243,15 +244,15 @@
   UIPasteboard* pasteboard = UIPasteboard.generalPasteboard;
   // remove with flag kCopiedTextBehavior
   if (action == @selector(pasteAndGo:)) {
-    DCHECK(!base::FeatureList::IsEnabled(kCopiedTextBehavior));
+    DCHECK(!base::FeatureList::IsEnabled(omnibox::kCopiedTextBehavior));
     return UIPasteboard.generalPasteboard.string.length > 0;
   }
   if (action == @selector(visitCopiedLink:)) {
-    DCHECK(base::FeatureList::IsEnabled(kCopiedTextBehavior));
+    DCHECK(base::FeatureList::IsEnabled(omnibox::kCopiedTextBehavior));
     return pasteboard.hasURLs;
   }
   if (action == @selector(searchCopiedText:)) {
-    DCHECK(base::FeatureList::IsEnabled(kCopiedTextBehavior));
+    DCHECK(base::FeatureList::IsEnabled(omnibox::kCopiedTextBehavior));
     return !pasteboard.hasURLs && pasteboard.hasStrings;
   }
   return NO;
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
index e9c642b..6bdae30 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
@@ -901,25 +901,28 @@
 }
 
 void OmniboxViewIOS::EndEditing() {
-  CloseOmniboxPopup();
-  model()->OnWillKillFocus();
-  model()->OnKillFocus();
-  if ([field_ isPreEditing])
-    [field_ exitPreEditState];
+  if (model()->has_focus()) {
+    CloseOmniboxPopup();
 
-  UpdateRightDecorations();
+    model()->OnWillKillFocus();
+    model()->OnKillFocus();
+    if ([field_ isPreEditing])
+      [field_ exitPreEditState];
 
-  // The controller looks at the current pre-edit state, so the call to
-  // OnKillFocus() must come after exiting pre-edit.
-  controller_->OnKillFocus();
+    UpdateRightDecorations();
 
-  // Blow away any in-progress edits.
-  RevertAll();
-  DCHECK(![field_ hasAutocompleteText]);
+    // The controller looks at the current pre-edit state, so the call to
+    // OnKillFocus() must come after exiting pre-edit.
+    controller_->OnKillFocus();
 
-  if (!omnibox_interacted_while_focused_) {
-    RecordAction(
-        UserMetricsAction("Mobile_FocusedDefocusedOmnibox_WithNoAction"));
+    // Blow away any in-progress edits.
+    RevertAll();
+    DCHECK(![field_ hasAutocompleteText]);
+
+    if (!omnibox_interacted_while_focused_) {
+      RecordAction(
+          UserMetricsAction("Mobile_FocusedDefocusedOmnibox_WithNoAction"));
+    }
   }
 }
 
diff --git a/ios/chrome/browser/ui/popup_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/BUILD.gn
index 4d53ec1b..5a6460a 100644
--- a/ios/chrome/browser/ui/popup_menu/BUILD.gn
+++ b/ios/chrome/browser/ui/popup_menu/BUILD.gn
@@ -40,6 +40,8 @@
     "//base",
     "//components/bookmarks/browser",
     "//components/feature_engagement/public",
+    "//components/omnibox/browser:browser",
+    "//components/open_from_clipboard",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
     "//ios/chrome/browser/bookmarks",
@@ -48,7 +50,6 @@
     "//ios/chrome/browser/find_in_page",
     "//ios/chrome/browser/reading_list",
     "//ios/chrome/browser/ui",
-    "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/activity_services",
     "//ios/chrome/browser/ui/bookmarks",
     "//ios/chrome/browser/ui/bubble",
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
index 88eeb75..a40114d49 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.mm
@@ -4,9 +4,13 @@
 
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_action_handler.h"
 
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/omnibox/browser/omnibox_field_trial.h"
+#include "components/open_from_clipboard/clipboard_recent_content.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
 #import "ios/chrome/browser/ui/commands/load_query_commands.h"
@@ -14,7 +18,6 @@
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_action_handler_commands.h"
 #import "ios/chrome/browser/ui/popup_menu/public/cells/popup_menu_item.h"
 #import "ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller.h"
-#include "ios/chrome/browser/ui/ui_feature_flags.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -129,9 +132,16 @@
     case PopupMenuActionPasteAndGo: {
       RecordAction(UserMetricsAction("MobileMenuPasteAndGo"));
       NSString* query;
-      if (base::FeatureList::IsEnabled(kCopiedTextBehavior)) {
-        query = [UIPasteboard generalPasteboard].URL.absoluteString
-                    ?: [UIPasteboard generalPasteboard].string;
+      if (base::FeatureList::IsEnabled(omnibox::kCopiedTextBehavior)) {
+        ClipboardRecentContent* clipboardRecentContent =
+            ClipboardRecentContent::GetInstance();
+        if (base::Optional<GURL> optional_url =
+                clipboardRecentContent->GetRecentURLFromClipboard()) {
+          query = base::SysUTF8ToNSString(optional_url.value().spec());
+        } else if (base::Optional<base::string16> optional_text =
+                       clipboardRecentContent->GetRecentTextFromClipboard()) {
+          query = base::SysUTF16ToNSString(optional_text.value());
+        }
       } else {
         query = [UIPasteboard generalPasteboard].string;
       }
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
index 86899cf..46cc130 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
@@ -10,6 +10,8 @@
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/feature_engagement/public/feature_constants.h"
 #include "components/feature_engagement/public/tracker.h"
+#include "components/omnibox/browser/omnibox_field_trial.h"
+#include "components/open_from_clipboard/clipboard_recent_content.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
 #import "ios/chrome/browser/find_in_page/find_tab_helper.h"
 #import "ios/chrome/browser/ui/activity_services/canonical_url_retriever.h"
@@ -24,7 +26,6 @@
 #import "ios/chrome/browser/ui/popup_menu/public/popup_menu_consumer.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_menu_notification_delegate.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_menu_notifier.h"
-#include "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #import "ios/chrome/browser/web_state_list/web_state_list.h"
 #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
@@ -585,11 +586,13 @@
 - (void)createSearchMenuItems {
   NSMutableArray* items = [NSMutableArray array];
 
-  if (base::FeatureList::IsEnabled(kCopiedTextBehavior)) {
+  if (base::FeatureList::IsEnabled(omnibox::kCopiedTextBehavior)) {
+    ClipboardRecentContent* clipboardRecentContent =
+        ClipboardRecentContent::GetInstance();
     NSNumber* titleID = nil;
-    if ([UIPasteboard generalPasteboard].hasURLs) {
+    if (clipboardRecentContent->GetRecentURLFromClipboard()) {
       titleID = [NSNumber numberWithInt:IDS_IOS_TOOLS_MENU_VISIT_COPIED_LINK];
-    } else if ([UIPasteboard generalPasteboard].hasStrings) {
+    } else if (clipboardRecentContent->GetRecentTextFromClipboard()) {
       titleID = [NSNumber numberWithInt:IDS_IOS_TOOLS_MENU_SEARCH_COPIED_TEXT];
     }
 
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index 38c352ea..46d33a3 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -7,8 +7,8 @@
   sources = [
     "about_chrome_table_view_controller.h",
     "about_chrome_table_view_controller.mm",
-    "accounts_collection_view_controller.h",
-    "accounts_collection_view_controller.mm",
+    "accounts_table_view_controller.h",
+    "accounts_table_view_controller.mm",
     "alpha_animated_collection_view_flow_layout.h",
     "alpha_animated_collection_view_flow_layout.mm",
     "autofill_credit_card_edit_table_view_controller.h",
@@ -373,7 +373,7 @@
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
-    "accounts_collection_egtest.mm",
+    "accounts_table_egtest.mm",
     "autofill_credit_card_settings_egtest.mm",
     "autofill_profile_settings_egtest.mm",
     "block_popups_egtest.mm",
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.h b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.h
deleted file mode 100644
index a1312a9..0000000
--- a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.h
+++ /dev/null
@@ -1,48 +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 IOS_CHROME_BROWSER_UI_SETTINGS_ACCOUNTS_COLLECTION_VIEW_CONTROLLER_H_
-#define IOS_CHROME_BROWSER_UI_SETTINGS_ACCOUNTS_COLLECTION_VIEW_CONTROLLER_H_
-
-#import "ios/chrome/browser/sync/sync_observer_bridge.h"
-#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
-#import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h"
-
-// The accessibility identifier of the view controller's view.
-extern NSString* const kSettingsAccountsId;
-// The accessibility identifier of the header of the accounts list.
-extern NSString* const kSettingsHeaderId;
-// The accessibility identifier of the add account cell.
-extern NSString* const kSettingsAccountsAddAccountCellId;
-// The accessibility identifier of the signout cell.
-extern NSString* const kSettingsAccountsSignoutCellId;
-// The accessibility identifier of the sync account cell.
-extern NSString* const kSettingsAccountsSyncCellId;
-
-@protocol ApplicationCommands;
-@protocol ApplicationSettingsCommands;
-namespace ios {
-class ChromeBrowserState;
-}  // namespace ios
-
-// Collection View that handles the settings for accounts when the user is
-// signed in
-// to Chrome.
-@interface AccountsCollectionViewController
-    : SettingsRootCollectionViewController<SettingsControllerProtocol>
-
-// |browserState| must not be nil.
-// If |closeSettingsOnAddAccount| is YES, then this account table view
-// controller will close the setting screen when an account is added.
-- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
-           closeSettingsOnAddAccount:(BOOL)closeSettingsOnAddAccount
-    NS_DESIGNATED_INITIALIZER;
-
-- (instancetype)initWithLayout:(UICollectionViewLayout*)layout
-                         style:(CollectionViewControllerStyle)style
-    NS_UNAVAILABLE;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_ACCOUNTS_COLLECTION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm b/ios/chrome/browser/ui/settings/accounts_table_egtest.mm
similarity index 97%
rename from ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
rename to ios/chrome/browser/ui/settings/accounts_table_egtest.mm
index 688f38b..38f520f 100644
--- a/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
+++ b/ios/chrome/browser/ui/settings/accounts_table_egtest.mm
@@ -15,7 +15,7 @@
 #import "ios/chrome/browser/signin/authentication_service.h"
 #import "ios/chrome/browser/signin/authentication_service_factory.h"
 #include "ios/chrome/browser/sync/profile_sync_service_factory.h"
-#import "ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.h"
+#import "ios/chrome/browser/ui/authentication/cells/account_control_item.h"
 #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h"
 #import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -249,10 +249,9 @@
   // Check that account sync button displays the expected detail text label and
   // an image.
   GREYPerformBlock block = ^BOOL(id element, NSError* __strong* errorOrNil) {
-    GREYAssertTrue([element isKindOfClass:[LegacyAccountControlCell class]],
-                   @"Should be LegacyAccountControlCell type");
-    LegacyAccountControlCell* cell =
-        static_cast<LegacyAccountControlCell*>(element);
+    GREYAssertTrue([element isKindOfClass:[AccountControlCell class]],
+                   @"Should be AccountControlCell type");
+    AccountControlCell* cell = static_cast<AccountControlCell*>(element);
     return
         [cell.detailTextLabel.text isEqualToString:expectedDetailTextLabel] &&
         cell.imageView.image != nil;
diff --git a/ios/chrome/browser/ui/settings/accounts_table_view_controller.h b/ios/chrome/browser/ui/settings/accounts_table_view_controller.h
new file mode 100644
index 0000000..04f429c
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/accounts_table_view_controller.h
@@ -0,0 +1,45 @@
+// 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 IOS_CHROME_BROWSER_UI_SETTINGS_ACCOUNTS_TABLE_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_ACCOUNTS_TABLE_VIEW_CONTROLLER_H_
+
+#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
+#import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h"
+
+// The accessibility identifier of the view controller's view.
+extern NSString* const kSettingsAccountsTableViewId;
+// The accessibility identifier of the add account cell.
+extern NSString* const kSettingsAccountsTableViewAddAccountCellId;
+// The accessibility identifier of the signout cell.
+extern NSString* const kSettingsAccountsTableViewSignoutCellId;
+// The accessibility identifier of the sync account cell.
+extern NSString* const kSettingsAccountsTableViewSyncCellId;
+
+@protocol ApplicationCommands;
+@protocol ApplicationSettingsCommands;
+namespace ios {
+class ChromeBrowserState;
+}  // namespace ios
+
+// TableView that handles the settings for accounts when the user is signed in
+// to Chrome.
+@interface AccountsTableViewController
+    : SettingsRootTableViewController <SettingsControllerProtocol>
+
+// |browserState| must not be nil.
+// If |closeSettingsOnAddAccount| is YES, then this account table view
+// controller will close the setting screen when an account is added.
+- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
+           closeSettingsOnAddAccount:(BOOL)closeSettingsOnAddAccount
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)initWithTableViewStyle:(UITableViewStyle)style
+                           appBarStyle:
+                               (ChromeTableViewControllerStyle)appBarStyle
+    NS_UNAVAILABLE;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_ACCOUNTS_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm b/ios/chrome/browser/ui/settings/accounts_table_view_controller.mm
similarity index 76%
rename from ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm
rename to ios/chrome/browser/ui/settings/accounts_table_view_controller.mm
index f6ec8dc..83ad1cb 100644
--- a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/accounts_table_view_controller.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
+#import "ios/chrome/browser/ui/settings/accounts_table_view_controller.h"
 
 #import "base/mac/foundation_util.h"
 #include "base/metrics/user_metrics.h"
@@ -26,21 +26,19 @@
 #include "ios/chrome/browser/sync/sync_setup_service.h"
 #include "ios/chrome/browser/sync/sync_setup_service_factory.h"
 #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
-#import "ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.h"
+#import "ios/chrome/browser/ui/authentication/cells/account_control_item.h"
+#import "ios/chrome/browser/ui/authentication/cells/table_view_account_item.h"
 #import "ios/chrome/browser/ui/authentication/resized_avatar_cache.h"
-#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
-#import "ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.h"
-#import "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_style.h"
-#import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
 #import "ios/chrome/browser/ui/icons/chrome_icon.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_text_item.h"
-#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
 #import "ios/chrome/browser/ui/settings/sync_settings_collection_view_controller.h"
 #import "ios/chrome/browser/ui/settings/sync_utils/sync_util.h"
 #import "ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.h"
+#import "ios/chrome/browser/ui/table_view/table_view_model.h"
 #include "ios/chrome/grit/ios_chromium_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/public/provider/chrome/browser/chrome_browser_provider.h"
@@ -56,13 +54,13 @@
 #error "This file requires ARC support."
 #endif
 
-NSString* const kSettingsAccountsId = @"kSettingsAccountsId";
-NSString* const kSettingsHeaderId = @"kSettingsHeaderId";
-NSString* const kSettingsAccountsAddAccountCellId =
-    @"kSettingsAccountsAddAccountCellId";
-NSString* const kSettingsAccountsSignoutCellId =
-    @"kSettingsAccountsSignoutCellId";
-NSString* const kSettingsAccountsSyncCellId = @"kSettingsAccountsSyncCellId";
+NSString* const kSettingsAccountsTableViewId = @"kSettingsAccountsTableViewId";
+NSString* const kSettingsAccountsTableViewAddAccountCellId =
+    @"kSettingsAccountsTableViewAddAccountCellId";
+NSString* const kSettingsAccountsTableViewSignoutCellId =
+    @"kSettingsAccountsTableViewSignoutCellId";
+NSString* const kSettingsAccountsTableViewSyncCellId =
+    @"kSettingsAccountsTableViewSyncCellId";
 
 namespace {
 
@@ -83,7 +81,7 @@
 
 }  // namespace
 
-@interface AccountsCollectionViewController ()<
+@interface AccountsTableViewController () <
     ChromeIdentityServiceObserver,
     ChromeIdentityBrowserOpener,
     OAuth2TokenServiceObserverBridgeDelegate,
@@ -105,7 +103,7 @@
   std::unique_ptr<ChromeIdentityServiceObserverBridge> _identityServiceObserver;
 
   // Enable lookup of item corresponding to a given identity GAIA ID string.
-  NSDictionary<NSString*, CollectionViewItem*>* _identityMap;
+  NSDictionary<NSString*, TableViewItem*>* _identityMap;
 }
 
 // The SigninInteractionCoordinator that presents Sign In UI for the Accounts
@@ -119,7 +117,7 @@
 
 @end
 
-@implementation AccountsCollectionViewController
+@implementation AccountsTableViewController
 
 @synthesize dispatcher = _dispatcher;
 @synthesize signinInteractionCoordinator = _signinInteractionCoordinator;
@@ -128,9 +126,9 @@
            closeSettingsOnAddAccount:(BOOL)closeSettingsOnAddAccount {
   DCHECK(browserState);
   DCHECK(!browserState->IsOffTheRecord());
-  UICollectionViewLayout* layout = [[MDCCollectionViewFlowLayout alloc] init];
   self =
-      [super initWithLayout:layout style:CollectionViewControllerStyleAppBar];
+      [super initWithTableViewStyle:UITableViewStyleGrouped
+                        appBarStyle:ChromeTableViewControllerStyleWithAppBar];
   if (self) {
     _browserState = browserState;
     _closeSettingsOnAddAccount = closeSettingsOnAddAccount;
@@ -154,18 +152,21 @@
            selector:@selector(didFinishSwitchAccount)
                name:kSwitchAccountDidFinishNotification
              object:nil];
-    self.collectionViewAccessibilityIdentifier = kSettingsAccountsId;
     _avatarCache = [[ResizedAvatarCache alloc] init];
     _identityServiceObserver.reset(
         new ChromeIdentityServiceObserverBridge(self));
-    // TODO(crbug.com/764578): -loadModel should not be called from
-    // initializer. A possible fix is to move this call to -viewDidLoad.
-    [self loadModel];
   }
 
   return self;
 }
 
+- (void)viewDidLoad {
+  [super viewDidLoad];
+  self.tableView.accessibilityIdentifier = kSettingsAccountsTableViewId;
+
+  [self loadModel];
+}
+
 - (void)stopBrowserStateServiceObservers {
   _tokenServiceObserver.reset();
   _syncObserver.reset();
@@ -179,13 +180,13 @@
   [self stopBrowserStateServiceObservers];
 }
 
-#pragma mark - SettingsRootCollectionViewController
+#pragma mark - SettingsRootTableViewController
 
 - (void)reloadData {
-  if (![self authService]->IsAuthenticated()) {
-    // This accounts collection view will be popped or dismissed when the user
+  if (![self authService] -> IsAuthenticated()) {
+    // This accounts table view will be popped or dismissed when the user
     // is signed out. Avoid reloading it in that case as that would lead to an
-    // empty collection view.
+    // empty table view.
     return;
   }
   [super reloadData];
@@ -194,7 +195,7 @@
 - (void)loadModel {
   // Update the title with the name with the currently signed-in account.
   ChromeIdentity* authenticatedIdentity =
-      [self authService]->GetAuthenticatedIdentity();
+      [self authService] -> GetAuthenticatedIdentity();
   NSString* title = nil;
   if (authenticatedIdentity) {
     title = [authenticatedIdentity userFullName];
@@ -206,12 +207,12 @@
 
   [super loadModel];
 
-  if (![self authService]->IsAuthenticated())
+  if (![self authService] -> IsAuthenticated())
     return;
 
-  CollectionViewModel* model = self.collectionViewModel;
+  TableViewModel* model = self.tableViewModel;
 
-  NSMutableDictionary<NSString*, CollectionViewItem*>* mutableIdentityMap =
+  NSMutableDictionary<NSString*, TableViewItem*>* mutableIdentityMap =
       [[NSMutableDictionary alloc] init];
 
   // Account cells.
@@ -227,7 +228,7 @@
     ChromeIdentity* identity = ios::GetChromeBrowserProvider()
                                    ->GetChromeIdentityService()
                                    ->GetIdentityWithGaiaID(account.gaia);
-    CollectionViewItem* item = [self accountItem:identity];
+    TableViewItem* item = [self accountItem:identity];
     [model addItem:item toSectionWithIdentifier:SectionIdentifierAccounts];
 
     [mutableIdentityMap setObject:item forKey:identity.gaiaID];
@@ -256,56 +257,51 @@
 
 #pragma mark - Model objects
 
-- (CollectionViewItem*)header {
-  SettingsTextItem* header =
-      [[SettingsTextItem alloc] initWithType:ItemTypeHeader];
+- (TableViewTextHeaderFooterItem*)header {
+  TableViewTextHeaderFooterItem* header =
+      [[TableViewTextHeaderFooterItem alloc] initWithType:ItemTypeHeader];
   header.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_DESCRIPTION);
-  header.accessibilityIdentifier = kSettingsHeaderId;
-  header.textColor = [[MDCPalette greyPalette] tint500];
   return header;
 }
 
-- (CollectionViewItem*)accountItem:(ChromeIdentity*)identity {
-  CollectionViewAccountItem* item =
-      [[CollectionViewAccountItem alloc] initWithType:ItemTypeAccount];
-  item.cellStyle = CollectionViewCellStyle::kUIKit;
+- (TableViewItem*)accountItem:(ChromeIdentity*)identity {
+  TableViewAccountItem* item =
+      [[TableViewAccountItem alloc] initWithType:ItemTypeAccount];
   [self updateAccountItem:item withIdentity:identity];
   return item;
 }
 
-- (void)updateAccountItem:(CollectionViewAccountItem*)item
+- (void)updateAccountItem:(TableViewAccountItem*)item
              withIdentity:(ChromeIdentity*)identity {
   item.image = [_avatarCache resizedAvatarForIdentity:identity];
   item.text = identity.userEmail;
   item.chromeIdentity = identity;
-  item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator;
+  item.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
 }
 
-- (CollectionViewItem*)addAccountItem {
-  CollectionViewAccountItem* item =
-      [[CollectionViewAccountItem alloc] initWithType:ItemTypeAddAccount];
-  item.cellStyle = CollectionViewCellStyle::kUIKit;
+- (TableViewItem*)addAccountItem {
+  TableViewAccountItem* item =
+      [[TableViewAccountItem alloc] initWithType:ItemTypeAddAccount];
   item.text =
       l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_ADD_ACCOUNT_BUTTON);
-  item.accessibilityIdentifier = kSettingsAccountsAddAccountCellId;
+  item.accessibilityIdentifier = kSettingsAccountsTableViewAddAccountCellId;
   item.image = [UIImage imageNamed:@"settings_accounts_add_account"];
   return item;
 }
 
-- (CollectionViewItem*)syncItem {
-  LegacyAccountControlItem* item =
-      [[LegacyAccountControlItem alloc] initWithType:ItemTypeSync];
-  item.cellStyle = CollectionViewCellStyle::kUIKit;
+- (TableViewItem*)syncItem {
+  AccountControlItem* item =
+      [[AccountControlItem alloc] initWithType:ItemTypeSync];
   item.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_SYNC_TITLE);
-  item.accessibilityIdentifier = kSettingsAccountsSyncCellId;
+  item.accessibilityIdentifier = kSettingsAccountsTableViewSyncCellId;
   [self updateSyncItem:item];
-  item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator;
+  item.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
   return item;
 }
 
 // Updates the sync item according to the sync status (in progress, sync error,
 // mdm error, sync disabled or sync enabled).
-- (void)updateSyncItem:(LegacyAccountControlItem*)syncItem {
+- (void)updateSyncItem:(AccountControlItem*)syncItem {
   SyncSetupService* syncSetupService =
       SyncSetupServiceFactory::GetForBrowserState(_browserState);
   if (!syncSetupService->HasFinishedInitialSetup()) {
@@ -316,7 +312,7 @@
     return;
   }
 
-  ChromeIdentity* identity = [self authService]->GetAuthenticatedIdentity();
+  ChromeIdentity* identity = [self authService] -> GetAuthenticatedIdentity();
   if (!IsTransientSyncError(syncSetupService->GetSyncServiceState())) {
     // Sync error.
     syncItem.shouldDisplayError = YES;
@@ -325,7 +321,7 @@
     DCHECK(errorMessage);
     syncItem.image = [UIImage imageNamed:@"settings_error"];
     syncItem.detailText = errorMessage;
-  } else if ([self authService]->HasCachedMDMErrorForIdentity(identity)) {
+  } else if ([self authService] -> HasCachedMDMErrorForIdentity(identity)) {
     // MDM error.
     syncItem.shouldDisplayError = YES;
     syncItem.image = [UIImage imageNamed:@"settings_error"];
@@ -347,23 +343,22 @@
   }
 }
 
-- (CollectionViewItem*)googleActivityControlsItem {
-  LegacyAccountControlItem* item = [[LegacyAccountControlItem alloc]
-      initWithType:ItemTypeGoogleActivityControls];
-  item.cellStyle = CollectionViewCellStyle::kUIKit;
+- (TableViewItem*)googleActivityControlsItem {
+  AccountControlItem* item =
+      [[AccountControlItem alloc] initWithType:ItemTypeGoogleActivityControls];
   item.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_GOOGLE_TITLE);
   item.detailText =
       l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_GOOGLE_DESCRIPTION);
   item.image = ios::GetChromeBrowserProvider()
                    ->GetBrandedImageProvider()
                    ->GetAccountsListActivityControlsImage();
-  item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator;
+  item.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
   return item;
 }
 
-- (CollectionViewItem*)signOutItem {
-  SettingsTextItem* item =
-      [[SettingsTextItem alloc] initWithType:ItemTypeSignOut];
+- (TableViewItem*)signOutItem {
+  TableViewDetailTextItem* item =
+      [[TableViewDetailTextItem alloc] initWithType:ItemTypeSignOut];
   if (unified_consent::IsUnifiedConsentFeatureEnabled()) {
     item.text =
         l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_SIGN_OUT_TURN_OFF_SYNC);
@@ -371,24 +366,23 @@
     item.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_SIGNOUT);
   }
   item.accessibilityTraits |= UIAccessibilityTraitButton;
-  item.accessibilityIdentifier = kSettingsAccountsSignoutCellId;
+  item.accessibilityIdentifier = kSettingsAccountsTableViewSignoutCellId;
   return item;
 }
 
-#pragma mark - UICollectionViewDelegate
+#pragma mark - UITableViewDelegate
 
-- (void)collectionView:(UICollectionView*)collectionView
-    didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
-  [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
+- (void)tableView:(UITableView*)tableView
+    didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
+  [super tableView:tableView didSelectRowAtIndexPath:indexPath];
 
-  NSInteger itemType =
-      [self.collectionViewModel itemTypeForIndexPath:indexPath];
+  NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];
 
   switch (itemType) {
     case ItemTypeAccount: {
-      CollectionViewAccountItem* item =
-          base::mac::ObjCCastStrict<CollectionViewAccountItem>(
-              [self.collectionViewModel itemAtIndexPath:indexPath]);
+      TableViewAccountItem* item =
+          base::mac::ObjCCastStrict<TableViewAccountItem>(
+              [self.tableViewModel itemAtIndexPath:indexPath]);
       DCHECK(item.chromeIdentity);
       [self showAccountDetails:item.chromeIdentity];
       break;
@@ -408,45 +402,30 @@
     default:
       break;
   }
-}
 
-#pragma mark - MDCCollectionViewStylingDelegate
-
-- (CGFloat)collectionView:(UICollectionView*)collectionView
-    cellHeightAtIndexPath:(NSIndexPath*)indexPath {
-  CollectionViewItem* item =
-      [self.collectionViewModel itemAtIndexPath:indexPath];
-  if (item.type == ItemTypeGoogleActivityControls ||
-      item.type == ItemTypeSync) {
-    return [MDCCollectionViewCell
-        cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds)
-                           forItem:item];
-  } else if (item.type == ItemTypeSignOut) {
-    return MDCCellDefaultOneLineHeight;
-  }
-  return MDCCellDefaultTwoLineHeight;
+  [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
 }
 
 #pragma mark - SyncObserverModelBridge
 
 - (void)onSyncStateChanged {
-  if (![self authService]->IsAuthenticated()) {
+  if (![self authService] -> IsAuthenticated()) {
     // Ignore sync state changed notification if signed out.
     return;
   }
 
   NSIndexPath* index =
-      [self.collectionViewModel indexPathForItemType:ItemTypeSync
-                                   sectionIdentifier:SectionIdentifierSync];
+      [self.tableViewModel indexPathForItemType:ItemTypeSync
+                              sectionIdentifier:SectionIdentifierSync];
 
-  CollectionViewModel* model = self.collectionViewModel;
+  TableViewModel* model = self.tableViewModel;
   if ([model numberOfSections] > index.section &&
       [model numberOfItemsInSection:index.section] > index.row) {
-    LegacyAccountControlItem* item =
-        base::mac::ObjCCastStrict<LegacyAccountControlItem>(
-            [model itemAtIndexPath:index]);
+    AccountControlItem* item = base::mac::ObjCCastStrict<AccountControlItem>(
+        [model itemAtIndexPath:index]);
     [self updateSyncItem:item];
-    [self.collectionView reloadItemsAtIndexPaths:@[ index ]];
+    [self.tableView reloadRowsAtIndexPaths:@[ index ]
+                          withRowAnimation:UITableViewRowAnimationAutomatic];
   }
 }
 
@@ -455,7 +434,7 @@
 - (void)onEndBatchChanges {
   [self reloadData];
   [self popViewIfSignedOut];
-  if (![self authService]->IsAuthenticated() && _settingsDetails) {
+  if (![self authService] -> IsAuthenticated() && _settingsDetails) {
     [_settingsDetails dismissViewControllerAnimated:YES completion:nil];
     _settingsDetails = nil;
   }
@@ -467,8 +446,9 @@
   if ([_alertCoordinator isVisible])
     return;
 
-  if ([self authService]->ShowMDMErrorDialogForIdentity(
-          [self authService]->GetAuthenticatedIdentity())) {
+  if ([self authService]
+      -> ShowMDMErrorDialogForIdentity(
+          [self authService] -> GetAuthenticatedIdentity())) {
     // If there is an MDM error for the synced identity, show it instead.
     return;
   }
@@ -490,7 +470,7 @@
       ios::GetChromeBrowserProvider()
           ->GetChromeIdentityService()
           ->CreateWebAndAppSettingDetailsController(
-              [self authService]->GetAuthenticatedIdentity(), self);
+              [self authService] -> GetAuthenticatedIdentity(), self);
   UIImage* closeIcon = [ChromeIcon closeIcon];
   SEL action = @selector(closeGoogleActivitySettings:);
   [settingsDetails.topViewController navigationItem].leftBarButtonItem =
@@ -524,7 +504,7 @@
   // |_authenticationOperationInProgress| is reset when the signin operation is
   // completed.
   _authenticationOperationInProgress = YES;
-  __weak AccountsCollectionViewController* weakSelf = self;
+  __weak AccountsTableViewController* weakSelf = self;
   [self.signinInteractionCoordinator
       addAccountWithAccessPoint:signin_metrics::AccessPoint::
                                     ACCESS_POINT_SETTINGS
@@ -573,7 +553,7 @@
       l10n_util::GetNSString(IDS_IOS_DISCONNECT_DIALOG_INFO_MOBILE);
   NSString* continueButtonTitle =
       l10n_util::GetNSString(IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE);
-  if ([self authService]->IsAuthenticatedIdentityManaged()) {
+  if ([self authService] -> IsAuthenticatedIdentityManaged()) {
     std::string hosted_domain =
         IdentityManagerFactory::GetForBrowserState(_browserState)
             ->GetPrimaryAccountInfo()
@@ -608,7 +588,7 @@
   [_alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL)
                                action:nil
                                 style:UIAlertActionStyleCancel];
-  __weak AccountsCollectionViewController* weakSelf = self;
+  __weak AccountsTableViewController* weakSelf = self;
   [_alertCoordinator addItemWithTitle:continueButtonTitle
                                action:^{
                                  [weakSelf handleDisconnect];
@@ -633,7 +613,7 @@
 }
 
 // Sets |_authenticationOperationInProgress| to NO and pops this accounts
-// collection view controller if the user is signed out.
+// table view controller if the user is signed out.
 - (void)handleAuthenticationOperationDidFinish {
   DCHECK(_authenticationOperationInProgress);
   _authenticationOperationInProgress = NO;
@@ -641,7 +621,7 @@
 }
 
 - (void)popViewIfSignedOut {
-  if ([self authService]->IsAuthenticated()) {
+  if ([self authService] -> IsAuthenticated()) {
     return;
   }
   if (_authenticationOperationInProgress) {
@@ -694,15 +674,15 @@
 #pragma mark - ChromeIdentityServiceObserver
 
 - (void)profileUpdate:(ChromeIdentity*)identity {
-  CollectionViewAccountItem* item =
-      base::mac::ObjCCastStrict<CollectionViewAccountItem>(
-          [_identityMap objectForKey:identity.gaiaID]);
+  TableViewAccountItem* item = base::mac::ObjCCastStrict<TableViewAccountItem>(
+      [_identityMap objectForKey:identity.gaiaID]);
   if (!item) {
     return;
   }
   [self updateAccountItem:item withIdentity:identity];
-  NSIndexPath* indexPath = [self.collectionViewModel indexPathForItem:item];
-  [self.collectionView reloadItemsAtIndexPaths:@[ indexPath ]];
+  NSIndexPath* indexPath = [self.tableViewModel indexPathForItem:item];
+  [self.tableView reloadRowsAtIndexPaths:@[ indexPath ]
+                        withRowAnimation:UITableViewRowAnimationAutomatic];
 }
 
 - (void)chromeIdentityServiceWillBeDestroyed {
diff --git a/ios/chrome/browser/ui/settings/cells/BUILD.gn b/ios/chrome/browser/ui/settings/cells/BUILD.gn
index d1f55a4b..c30184c 100644
--- a/ios/chrome/browser/ui/settings/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/cells/BUILD.gn
@@ -20,8 +20,6 @@
     "copied_to_chrome_item.mm",
     "encryption_item.h",
     "encryption_item.mm",
-    "import_data_multiline_detail_item.h",
-    "import_data_multiline_detail_item.mm",
     "passphrase_error_item.h",
     "passphrase_error_item.mm",
     "password_details_item.h",
@@ -32,6 +30,8 @@
     "settings_detail_item.mm",
     "settings_image_detail_text_item.h",
     "settings_image_detail_text_item.mm",
+    "settings_multiline_detail_item.h",
+    "settings_multiline_detail_item.mm",
     "settings_search_item.h",
     "settings_search_item.mm",
     "settings_switch_cell.h",
@@ -82,9 +82,9 @@
     "clear_browsing_data_item_unittest.mm",
     "copied_to_chrome_item_unittest.mm",
     "encryption_item_unittest.mm",
-    "import_data_multiline_detail_item_unittest.mm",
     "passphrase_error_item_unittest.mm",
     "password_details_item_unittest.mm",
+    "settings_multiline_detail_item_unittest.mm",
     "text_and_error_item_unittest.mm",
     "version_item_unittest.mm",
   ]
diff --git a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h b/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h
deleted file mode 100644
index 4f317ed..0000000
--- a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_IMPORT_DATA_MULTILINE_DETAIL_ITEM_H_
-#define IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_IMPORT_DATA_MULTILINE_DETAIL_ITEM_H_
-
-#import <UIKit/UIKit.h>
-
-#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h"
-
-// ImportDataMultilineDetailItem is a model class that uses
-// ImportDataMultilineDetailCell.
-@interface ImportDataMultilineDetailItem : TableViewItem
-
-// The main text string.
-@property(nonatomic, copy) NSString* text;
-
-// The detail text string.
-@property(nonatomic, copy) NSString* detailText;
-
-@end
-
-// ImportDataMultilineDetailCell implements an UITableViewCell
-// subclass containing two text labels: a "main" label and a "detail" label.
-// The two labels are laid out on top of each other and can span on multiple
-// lines. This is to be used with a ImportDataMultilineDetailItem.
-@interface ImportDataMultilineDetailCell : UITableViewCell
-
-// UILabels corresponding to |text| and |detailText| from the item.
-@property(nonatomic, readonly, strong) UILabel* textLabel;
-@property(nonatomic, readonly, strong) UILabel* detailTextLabel;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_IMPORT_DATA_MULTILINE_DETAIL_ITEM_H_
diff --git a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item_unittest.mm b/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item_unittest.mm
deleted file mode 100644
index f4f5532..0000000
--- a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item_unittest.mm
+++ /dev/null
@@ -1,56 +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.
-
-#import "ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h"
-
-#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-
-using ImportDataMultilineDetailItemTest = PlatformTest;
-
-// Tests that the text and detail text are honoured after a call to
-// |configureCell:|.
-TEST_F(ImportDataMultilineDetailItemTest, ConfigureCell) {
-  ImportDataMultilineDetailItem* item =
-      [[ImportDataMultilineDetailItem alloc] initWithType:0];
-  NSString* text = @"Test Text";
-  NSString* detailText =
-      @"Test Detail Text that can span multiple lines. For "
-      @"example, this line probably fits on three or four "
-      @"lines.";
-
-  item.text = text;
-  item.detailText = detailText;
-
-  id cell = [[[item cellClass] alloc] init];
-  ASSERT_TRUE([cell isMemberOfClass:[ImportDataMultilineDetailCell class]]);
-
-  ImportDataMultilineDetailCell* multilineDetailCell =
-      static_cast<ImportDataMultilineDetailCell*>(cell);
-  EXPECT_FALSE(multilineDetailCell.textLabel.text);
-  EXPECT_FALSE(multilineDetailCell.detailTextLabel.text);
-
-  [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]];
-  EXPECT_NSEQ(text, multilineDetailCell.textLabel.text);
-  EXPECT_NSEQ(detailText, multilineDetailCell.detailTextLabel.text);
-}
-
-// Tests that the text label of an ImportDataMultilineDetailCell only has one
-// line but the detail text label spans multiple lines.
-TEST_F(ImportDataMultilineDetailItemTest, MultipleLines) {
-  ImportDataMultilineDetailCell* cell =
-      [[ImportDataMultilineDetailCell alloc] init];
-  EXPECT_EQ(0, cell.textLabel.numberOfLines);
-  EXPECT_EQ(0, cell.detailTextLabel.numberOfLines);
-}
-
-}  // namespace
diff --git a/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.h b/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.h
new file mode 100644
index 0000000..5f07090
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.h
@@ -0,0 +1,36 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_SETTINGS_MULTILINE_DETAIL_ITEM_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_SETTINGS_MULTILINE_DETAIL_ITEM_H_
+
+#import <UIKit/UIKit.h>
+
+#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h"
+
+// SettingsMultilineDetailItem is a model class that uses
+// SettingsMultilineDetailCell.
+@interface SettingsMultilineDetailItem : TableViewItem
+
+// The main text string.
+@property(nonatomic, copy) NSString* text;
+
+// The detail text string.
+@property(nonatomic, copy) NSString* detailText;
+
+@end
+
+// SettingsMultilineDetailCell implements an UITableViewCell
+// subclass containing two text labels: a "main" label and a "detail" label.
+// The two labels are laid out on top of each other and can span on multiple
+// lines. This is to be used with a SettingsMultilineDetailItem.
+@interface SettingsMultilineDetailCell : UITableViewCell
+
+// UILabels corresponding to |text| and |detailText| from the item.
+@property(nonatomic, readonly, strong) UILabel* textLabel;
+@property(nonatomic, readonly, strong) UILabel* detailTextLabel;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_SETTINGS_MULTILINE_DETAIL_ITEM_H_
diff --git a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.mm b/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.mm
similarity index 92%
rename from ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.mm
rename to ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.mm
index 1be8dee..2488f97 100644
--- a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.mm
+++ b/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h"
+#import "ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.h"
 
 #import "ios/chrome/browser/ui/settings/cells/settings_cells_constants.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
@@ -13,7 +13,7 @@
 #error "This file requires ARC support."
 #endif
 
-@implementation ImportDataMultilineDetailItem
+@implementation SettingsMultilineDetailItem
 
 @synthesize text = _text;
 @synthesize detailText = _detailText;
@@ -21,14 +21,14 @@
 - (instancetype)initWithType:(NSInteger)type {
   self = [super initWithType:type];
   if (self) {
-    self.cellClass = [ImportDataMultilineDetailCell class];
+    self.cellClass = [SettingsMultilineDetailCell class];
   }
   return self;
 }
 
 #pragma mark CollectionViewItem
 
-- (void)configureCell:(ImportDataMultilineDetailCell*)cell
+- (void)configureCell:(SettingsMultilineDetailCell*)cell
            withStyler:(ChromeTableViewStyler*)styler {
   [super configureCell:cell withStyler:styler];
   cell.textLabel.text = self.text;
@@ -37,7 +37,7 @@
 
 @end
 
-@implementation ImportDataMultilineDetailCell
+@implementation SettingsMultilineDetailCell
 
 @synthesize textLabel = _textLabel;
 @synthesize detailTextLabel = _detailTextLabel;
diff --git a/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item_unittest.mm b/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item_unittest.mm
new file mode 100644
index 0000000..a7ec1d3
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item_unittest.mm
@@ -0,0 +1,55 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.h"
+
+#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+using SettingsMultilineDetailItemTest = PlatformTest;
+
+// Tests that the text and detail text are honoured after a call to
+// |configureCell:|.
+TEST_F(SettingsMultilineDetailItemTest, ConfigureCell) {
+  SettingsMultilineDetailItem* item =
+      [[SettingsMultilineDetailItem alloc] initWithType:0];
+  NSString* text = @"Test Text";
+  NSString* detailText = @"Test Detail Text that can span multiple lines. For "
+                         @"example, this line probably fits on three or four "
+                         @"lines.";
+
+  item.text = text;
+  item.detailText = detailText;
+
+  id cell = [[[item cellClass] alloc] init];
+  ASSERT_TRUE([cell isMemberOfClass:[SettingsMultilineDetailCell class]]);
+
+  SettingsMultilineDetailCell* multilineDetailCell =
+      static_cast<SettingsMultilineDetailCell*>(cell);
+  EXPECT_FALSE(multilineDetailCell.textLabel.text);
+  EXPECT_FALSE(multilineDetailCell.detailTextLabel.text);
+
+  [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]];
+  EXPECT_NSEQ(text, multilineDetailCell.textLabel.text);
+  EXPECT_NSEQ(detailText, multilineDetailCell.detailTextLabel.text);
+}
+
+// Tests that the text label of an SettingsMultilineDetailCell only has one
+// line but the detail text label spans multiple lines.
+TEST_F(SettingsMultilineDetailItemTest, MultipleLines) {
+  SettingsMultilineDetailCell* cell =
+      [[SettingsMultilineDetailCell alloc] init];
+  EXPECT_EQ(0, cell.textLabel.numberOfLines);
+  EXPECT_EQ(0, cell.detailTextLabel.numberOfLines);
+}
+
+}  // namespace
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm b/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm
index 9675484..9c0bc49e 100644
--- a/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm
+++ b/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm
@@ -5,10 +5,6 @@
 #import "ios/chrome/browser/ui/settings/google_services_settings_coordinator.h"
 
 #include "base/mac/foundation_util.h"
-#include "base/metrics/user_metrics.h"
-#include "base/metrics/user_metrics_action.h"
-#include "components/browser_sync/profile_sync_service.h"
-#include "components/google/core/common/google_util.h"
 #include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
@@ -18,18 +14,10 @@
 #include "ios/chrome/browser/sync/sync_setup_service_factory.h"
 #import "ios/chrome/browser/ui/authentication/authentication_flow.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
-#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
-#import "ios/chrome/browser/ui/commands/show_signin_command.h"
-#import "ios/chrome/browser/ui/icons/chrome_icon.h"
 #import "ios/chrome/browser/ui/settings/google_services_settings_local_commands.h"
 #import "ios/chrome/browser/ui/settings/google_services_settings_mediator.h"
 #import "ios/chrome/browser/ui/settings/google_services_settings_view_controller.h"
-#import "ios/chrome/browser/ui/settings/sync_encryption_passphrase_table_view_controller.h"
-#import "ios/chrome/browser/ui/settings/sync_encryption_table_view_controller.h"
 #include "ios/chrome/browser/unified_consent/unified_consent_service_factory.h"
-#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
-#import "ios/public/provider/chrome/browser/signin/chrome_identity_browser_opener.h"
-#include "ios/public/provider/chrome/browser/signin/chrome_identity_service.h"
 #include "net/base/mac/url_conversions.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -37,7 +25,6 @@
 #endif
 
 @interface GoogleServicesSettingsCoordinator ()<
-    ChromeIdentityBrowserOpener,
     GoogleServicesSettingsLocalCommands,
     GoogleServicesSettingsViewControllerPresentationDelegate>
 
@@ -55,12 +42,6 @@
 
 @implementation GoogleServicesSettingsCoordinator
 
-@synthesize viewController = _viewController;
-@synthesize delegate = _delegate;
-@synthesize dispatcher = _dispatcher;
-@synthesize mediator = _mediator;
-@synthesize authenticationFlow = _authenticationFlow;
-
 - (void)start {
   UICollectionViewLayout* layout = [[MDCCollectionViewFlowLayout alloc] init];
   GoogleServicesSettingsViewController* viewController =
@@ -72,14 +53,11 @@
   self.viewController = viewController;
   SyncSetupService* syncSetupService =
       SyncSetupServiceFactory::GetForBrowserState(self.browserState);
-  browser_sync::ProfileSyncService* syncService =
-      ProfileSyncServiceFactory::GetForBrowserState(self.browserState);
   unified_consent::UnifiedConsentService* unifiedConsentService =
       UnifiedConsentServiceFactory::GetForBrowserState(self.browserState);
   self.mediator = [[GoogleServicesSettingsMediator alloc]
       initWithUserPrefService:self.browserState->GetPrefs()
              localPrefService:GetApplicationContext()->GetLocalState()
-                  syncService:syncService
              syncSetupService:syncSetupService
         unifiedConsentService:unifiedConsentService];
   self.mediator.consumer = viewController;
@@ -146,51 +124,6 @@
       showSyncPassphraseSettingsFromViewController:self.viewController];
 }
 
-- (void)openGoogleActivityControlsDialog {
-  base::RecordAction(base::UserMetricsAction(
-      "Signin_AccountSettings_GoogleActivityControlsClicked"));
-  UINavigationController* settingsDetails =
-      ios::GetChromeBrowserProvider()
-          ->GetChromeIdentityService()
-          ->CreateWebAndAppSettingDetailsController(
-              self.authService->GetAuthenticatedIdentity(), self);
-  UIImage* closeIcon = [ChromeIcon closeIcon];
-  SEL action = @selector(closeGoogleActivitySettings:);
-  [settingsDetails.topViewController navigationItem].leftBarButtonItem =
-      [ChromeIcon templateBarButtonItemWithImage:closeIcon
-                                          target:self
-                                          action:action];
-  [self.navigationController presentViewController:settingsDetails
-                                          animated:YES
-                                        completion:nil];
-}
-
-- (void)openEncryptionDialog {
-  browser_sync::ProfileSyncService* syncService =
-      ProfileSyncServiceFactory::GetForBrowserState(self.browserState);
-  UIViewController<SettingsRootViewControlling>* controllerToPush;
-  // If there was a sync error, prompt the user to enter the passphrase.
-  // Otherwise, show the full encryption options.
-  if (syncService->IsPassphraseRequired()) {
-    controllerToPush = [[SyncEncryptionPassphraseTableViewController alloc]
-        initWithBrowserState:self.browserState];
-  } else {
-    controllerToPush = [[SyncEncryptionTableViewController alloc]
-        initWithBrowserState:self.browserState];
-  }
-  controllerToPush.dispatcher = self.dispatcher;
-  [self.navigationController pushViewController:controllerToPush animated:YES];
-}
-
-- (void)openManageSyncedDataWebPage {
-  GURL learnMoreUrl = google_util::AppendGoogleLocaleParam(
-      GURL(kSyncGoogleDashboardURL),
-      GetApplicationContext()->GetApplicationLocale());
-  OpenNewTabCommand* command =
-      [OpenNewTabCommand commandWithURLFromChrome:learnMoreUrl];
-  [self.dispatcher closeSettingsUIAndOpenURL:command];
-}
-
 #pragma mark - GoogleServicesSettingsViewControllerPresentationDelegate
 
 - (void)googleServicesSettingsViewControllerDidRemove:
@@ -199,14 +132,4 @@
   [self.delegate googleServicesSettingsCoordinatorDidRemove:self];
 }
 
-#pragma mark - ChromeIdentityBrowserOpener
-
-- (void)openURL:(NSURL*)URL
-              view:(UIView*)view
-    viewController:(UIViewController*)viewController {
-  OpenNewTabCommand* command =
-      [OpenNewTabCommand commandWithURLFromChrome:net::GURLWithNSURL(URL)];
-  [self.dispatcher closeSettingsUIAndOpenURL:command];
-}
-
 @end
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm b/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm
index 6dc864d..a7ff41253 100644
--- a/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm
@@ -55,64 +55,12 @@
       performAction:grey_tap()];
 }
 
-// Tests the Google Services settings, when the user is not logged in.
-// The personalized section is expect to be collapsed and the non-personalized
-// section is expected to be expanded.
-- (void)testOpeningServicesWhileSignedOut {
+// Tests the Google Services settings.
+- (void)testOpeningServices {
   [self openGoogleServicesSettings];
-  [self assertPersonalizedServices];
   [self assertNonPersonalizedServices];
 }
 
-// Tests the Google Services settings, when the user is logged in without user
-// consent.
-// The "Sync Everything" section is expected to be visible.
-// The personalized section and the non-personalized section are expected to be
-// expanded.
-- (void)testOpeningServicesWhileSignedIn {
-  [SigninEarlGreyUI signinWithIdentity:[SigninEarlGreyUtils fakeIdentity1]];
-  [self openGoogleServicesSettings];
-  [self assertSyncEverythingSection];
-  [self assertPersonalizedServices];
-  [self assertNonPersonalizedServices];
-}
-
-// Tests the Google Services settings, when the user is logged in with user
-// consent.
-// The "Sync Everything" section is expected to be visible.
-// The personalized section and the non-personalized section are expected to be
-// collapsed.
-- (void)testOpeningServicesWhileSignedInAndConsentGiven {
-  [SigninEarlGreyUI signinWithIdentity:[SigninEarlGreyUtils fakeIdentity1]];
-  [self openGoogleServicesSettings];
-  [self assertSyncEverythingSection];
-  [self assertPersonalizedServices];
-  [self assertNonPersonalizedServices];
-}
-
-// Tests the "Manage synced data" cell does nothing when the user is not signed
-// in.
-- (void)testOpenManageSyncedDataWebPage {
-  [self openGoogleServicesSettings];
-  [[self cellElementInteractionWithTitleID:
-             IDS_IOS_GOOGLE_SERVICES_SETTINGS_MANAGED_SYNC_DATA_TEXT
-                              detailTextID:0] performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:self.scrollViewMatcher]
-      assertWithMatcher:grey_notNil()];
-}
-
-// Tests the "Manage synced data" cell closes the settings, and opens the web
-// page, while the user is signed in without user consent.
-- (void)testOpenManageSyncedDataWebPageWhileSignedIn {
-  [SigninEarlGreyUI signinWithIdentity:[SigninEarlGreyUtils fakeIdentity1]];
-  [self openGoogleServicesSettings];
-  [[self cellElementInteractionWithTitleID:
-             IDS_IOS_GOOGLE_SERVICES_SETTINGS_MANAGED_SYNC_DATA_TEXT
-                              detailTextID:0] performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:self.scrollViewMatcher]
-      assertWithMatcher:grey_nil()];
-}
-
 #pragma mark - Helpers
 
 // Opens the Google services settings.
@@ -177,59 +125,6 @@
       assertWithMatcher:grey_notNil()];
 }
 
-// Asserts that the switch is enabled/disabled inside a cell with |titleID| and
-// |detailTextID|.
-- (void)assertSwitchCellWithTitleID:(int)titleID
-                       detailTextID:(int)detailTextID
-                            enabled:(BOOL)enabled {
-  id<GREYMatcher> cellMatcher =
-      [self cellMatcherWithTitleID:titleID detailTextID:detailTextID];
-  id<GREYMatcher> enabledMatcher = grey_enabled();
-  if (!enabled) {
-    enabledMatcher = grey_not(grey_enabled());
-  }
-  id<GREYMatcher> switchMatcher =
-      grey_allOf(enabledMatcher, grey_kindOfClass([UISwitch class]),
-                 grey_ancestor(cellMatcher), nil);
-  GREYElementInteraction* element =
-      [self elementInteractionWithGreyMatcher:switchMatcher];
-  [element assertWithMatcher:grey_notNil()];
-}
-
-// Asserts that the sync everthing section cell is visible.
-- (void)assertSyncEverythingSection {
-  [self assertCellWithTitleID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_SYNC_EVERYTHING
-                 detailTextID:0];
-}
-
-// Asserts that the personalized service section is visible.
-- (void)assertPersonalizedServices {
-  [self assertCellWithTitleID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_BOOKMARKS_TEXT
-                 detailTextID:0];
-  [self assertCellWithTitleID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_HISTORY_TEXT
-                 detailTextID:0];
-  [self assertCellWithTitleID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_PASSWORD_TEXT
-                 detailTextID:0];
-  [self assertCellWithTitleID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_OPENTABS_TEXT
-                 detailTextID:0];
-  [self assertCellWithTitleID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_AUTOFILL_TEXT
-                 detailTextID:0];
-  [self assertCellWithTitleID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_SETTINGS_TEXT
-                 detailTextID:0];
-  [self assertCellWithTitleID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_READING_LIST_TEXT
-                 detailTextID:0];
-  [self
-      assertCellWithTitleID:
-          IDS_IOS_GOOGLE_SERVICES_SETTINGS_GOOGLE_ACTIVITY_CONTROL_TEXT
-               detailTextID:
-                   IDS_IOS_GOOGLE_SERVICES_SETTINGS_GOOGLE_ACTIVITY_CONTROL_DETAIL];
-  [self assertCellWithTitleID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_ENCRYPTION_TEXT
-                 detailTextID:0];
-  [self assertCellWithTitleID:
-            IDS_IOS_GOOGLE_SERVICES_SETTINGS_MANAGED_SYNC_DATA_TEXT
-                 detailTextID:0];
-}
-
 // Asserts that the non-personalized service section is visible.
 - (void)assertNonPersonalizedServices {
   [self
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_local_commands.h b/ios/chrome/browser/ui/settings/google_services_settings_local_commands.h
index c4aff838..fd30a07 100644
--- a/ios/chrome/browser/ui/settings/google_services_settings_local_commands.h
+++ b/ios/chrome/browser/ui/settings/google_services_settings_local_commands.h
@@ -17,15 +17,6 @@
 // Opens the passphrase dialog.
 - (void)openPassphraseDialog;
 
-// Opens the "Google Activity Controls" dialog.
-- (void)openGoogleActivityControlsDialog;
-
-// Opens the "Encryption" dialog.
-- (void)openEncryptionDialog;
-
-// Opens the "Manage Synced Data" web page.
-- (void)openManageSyncedDataWebPage;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_SETTINGS_LOCAL_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_mediator.h b/ios/chrome/browser/ui/settings/google_services_settings_mediator.h
index f4e69f9b..f931223f 100644
--- a/ios/chrome/browser/ui/settings/google_services_settings_mediator.h
+++ b/ios/chrome/browser/ui/settings/google_services_settings_mediator.h
@@ -17,9 +17,6 @@
 class PrefService;
 class SyncSetupService;
 
-namespace browser_sync {
-class ProfileSyncService;
-}  // namespace browser_sync
 namespace unified_consent {
 class UnifiedConsentService;
 }  // namespace unified_consent
@@ -40,7 +37,6 @@
 - (instancetype)
 initWithUserPrefService:(PrefService*)userPrefService
        localPrefService:(PrefService*)localPrefService
-            syncService:(browser_sync::ProfileSyncService*)syncService
        syncSetupService:(SyncSetupService*)syncSetupService
   unifiedConsentService:
       (unified_consent::UnifiedConsentService*)unifiedConsentService
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm
index 9f21238a..adc3dd6 100644
--- a/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm
+++ b/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm
@@ -7,20 +7,12 @@
 #include "base/auto_reset.h"
 #include "base/mac/foundation_util.h"
 #include "components/autofill/core/common/autofill_prefs.h"
-#include "components/browser_sync/profile_sync_service.h"
 #include "components/metrics/metrics_pref_names.h"
-#import "components/prefs/ios/pref_observer_bridge.h"
-#include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
 #include "components/unified_consent/pref_names.h"
-#include "components/unified_consent/unified_consent_service.h"
 #include "ios/chrome/browser/pref_names.h"
 #import "ios/chrome/browser/signin/authentication_service.h"
 #import "ios/chrome/browser/signin/authentication_service_factory.h"
-#include "ios/chrome/browser/sync/sync_observer_bridge.h"
-#include "ios/chrome/browser/sync/sync_setup_service.h"
-#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
-#import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h"
 #import "ios/chrome/browser/ui/settings/cells/legacy/legacy_sync_switch_item.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h"
 #import "ios/chrome/browser/ui/settings/sync_utils/sync_util.h"
@@ -44,8 +36,6 @@
 // List of sections.
 typedef NS_ENUM(NSInteger, SectionIdentifier) {
   SyncFeedbackSectionIdentifier = kSectionIdentifierEnumZero,
-  SyncEverythingSectionIdentifier,
-  PersonalizedSectionIdentifier,
   NonPersonalizedSectionIdentifier,
 };
 
@@ -53,20 +43,6 @@
 typedef NS_ENUM(NSInteger, ItemType) {
   // SyncErrorSectionIdentifier,
   SyncErrorItemType = kItemTypeEnumZero,
-  // SyncEverythingSectionIdentifier section.
-  SyncEverythingItemType,
-  // PersonalizedSectionIdentifier section.
-  SyncBookmarksItemType,
-  SyncHistoryItemType,
-  SyncPasswordsItemType,
-  SyncOpenTabsItemType,
-  SyncAutofillItemType,
-  SyncSettingsItemType,
-  SyncReadingListItemType,
-  AutocompleteWalletItemType,
-  SyncGoogleActivityControlsItemType,
-  EncryptionItemType,
-  ManageSyncedDataItemType,
   // NonPersonalizedSectionIdentifier section.
   AutocompleteSearchesAndURLsItemType,
   PreloadPagesItemType,
@@ -76,10 +52,7 @@
 
 }  // namespace
 
-@interface GoogleServicesSettingsMediator ()<BooleanObserver,
-                                             SyncObserverModelBridge> {
-  std::unique_ptr<SyncObserverBridge> _syncObserver;
-}
+@interface GoogleServicesSettingsMediator () <BooleanObserver>
 
 // Unified consent service.
 @property(nonatomic, assign)
@@ -114,16 +87,11 @@
 @property(nonatomic, strong, readonly)
     PrefBackedBoolean* anonymizedDataCollectionPreference;
 
-// YES if the switch for |syncEverythingItem| is currently animating from one
-// state to another.
-@property(nonatomic, assign) BOOL syncEverythingSwitchBeingAnimated;
 // YES if at least one switch in the personalized section is currently animating
 // from one state to another.
 @property(nonatomic, assign) BOOL personalizedSectionBeingAnimated;
 // Item to display the sync error.
 @property(nonatomic, strong) SettingsImageDetailTextItem* syncErrorItem;
-// Item for "Sync Everything" section.
-@property(nonatomic, strong, readonly) LegacySyncSwitchItem* syncEverythingItem;
 // All the items for the personalized section.
 @property(nonatomic, strong, readonly) ItemArray personalizedItems;
 // Item for the autocomplete wallet feature.
@@ -136,26 +104,6 @@
 
 @implementation GoogleServicesSettingsMediator
 
-@synthesize unifiedConsentService = _unifiedConsentService;
-@synthesize consumer = _consumer;
-@synthesize authService = _authService;
-@synthesize syncSetupService = _syncSetupService;
-@synthesize autocompleteWalletPreference = _autocompleteWalletPreference;
-@synthesize autocompleteSearchPreference = _autocompleteSearchPreference;
-@synthesize preloadPagesPreference = _preloadPagesPreference;
-@synthesize preloadPagesWifiOnlyPreference = _preloadPagesWifiOnlyPreference;
-@synthesize sendDataUsagePreference = _sendDataUsagePreference;
-@synthesize sendDataUsageWifiOnlyPreference = _sendDataUsageWifiOnlyPreference;
-@synthesize anonymizedDataCollectionPreference =
-    _anonymizedDataCollectionPreference;
-@synthesize syncEverythingSwitchBeingAnimated =
-    _syncEverythingSwitchBeingAnimated;
-@synthesize personalizedSectionBeingAnimated =
-    _personalizedSectionBeingAnimated;
-@synthesize syncErrorItem = _syncErrorItem;
-@synthesize syncEverythingItem = _syncEverythingItem;
-@synthesize personalizedItems = _personalizedItems;
-@synthesize autocompleteWalletItem = _autocompleteWalletItem;
 @synthesize nonPersonalizedItems = _nonPersonalizedItems;
 
 #pragma mark - Load model
@@ -163,7 +111,6 @@
 - (instancetype)
 initWithUserPrefService:(PrefService*)userPrefService
        localPrefService:(PrefService*)localPrefService
-            syncService:(browser_sync::ProfileSyncService*)syncService
        syncSetupService:(SyncSetupService*)syncSetupService
   unifiedConsentService:
       (unified_consent::UnifiedConsentService*)unifiedConsentService {
@@ -171,12 +118,10 @@
   if (self) {
     DCHECK(userPrefService);
     DCHECK(localPrefService);
-    DCHECK(syncService);
     DCHECK(syncSetupService);
     DCHECK(unifiedConsentService);
     _syncSetupService = syncSetupService;
     _unifiedConsentService = unifiedConsentService;
-    _syncObserver.reset(new SyncObserverBridge(self, syncService));
     _autocompleteWalletPreference = [[PrefBackedBoolean alloc]
         initWithPrefService:userPrefService
                    prefName:autofill::prefs::kAutofillWalletImportEnabled];
@@ -208,24 +153,6 @@
   return self;
 }
 
-// Loads SyncEverythingSectionIdentifier section.
-- (void)loadSyncEverythingSection {
-  CollectionViewModel* model = self.consumer.collectionViewModel;
-  [model addSectionWithIdentifier:SyncEverythingSectionIdentifier];
-  [model addItem:self.syncEverythingItem
-      toSectionWithIdentifier:SyncEverythingSectionIdentifier];
-}
-
-// Loads PersonalizedSectionIdentifier section.
-- (void)loadPersonalizedSection {
-  CollectionViewModel* model = self.consumer.collectionViewModel;
-  [model addSectionWithIdentifier:PersonalizedSectionIdentifier];
-  for (CollectionViewItem* item in self.personalizedItems) {
-    [model addItem:item toSectionWithIdentifier:PersonalizedSectionIdentifier];
-  }
-  [self updatePersonalizedSection];
-}
-
 // Loads NonPersonalizedSectionIdentifier section.
 - (void)loadNonPersonalizedSection {
   CollectionViewModel* model = self.consumer.collectionViewModel;
@@ -260,112 +187,6 @@
   return _syncErrorItem;
 }
 
-- (CollectionViewItem*)syncEverythingItem {
-  if (!_syncEverythingItem) {
-    _syncEverythingItem = [self
-        switchItemWithItemType:SyncEverythingItemType
-                  textStringID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_SYNC_EVERYTHING
-                detailStringID:0
-                     commandID:
-                         GoogleServicesSettingsCommandIDToggleSyncEverything
-                      dataType:0];
-  }
-  return _syncEverythingItem;
-}
-
-- (ItemArray)personalizedItems {
-  if (!_personalizedItems) {
-    LegacySyncSwitchItem* syncBookmarksItem = [self
-        switchItemWithItemType:SyncBookmarksItemType
-                  textStringID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_BOOKMARKS_TEXT
-                detailStringID:0
-                     commandID:GoogleServicesSettingsCommandIDToggleDataTypeSync
-                      dataType:SyncSetupService::kSyncBookmarks];
-    LegacySyncSwitchItem* syncHistoryItem = [self
-        switchItemWithItemType:SyncHistoryItemType
-                  textStringID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_HISTORY_TEXT
-                detailStringID:0
-                     commandID:GoogleServicesSettingsCommandIDToggleDataTypeSync
-                      dataType:SyncSetupService::kSyncOmniboxHistory];
-    LegacySyncSwitchItem* syncPasswordsItem = [self
-        switchItemWithItemType:SyncPasswordsItemType
-                  textStringID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_PASSWORD_TEXT
-                detailStringID:0
-                     commandID:GoogleServicesSettingsCommandIDToggleDataTypeSync
-                      dataType:SyncSetupService::kSyncPasswords];
-    LegacySyncSwitchItem* syncOpenTabsItem = [self
-        switchItemWithItemType:SyncOpenTabsItemType
-                  textStringID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_OPENTABS_TEXT
-                detailStringID:0
-                     commandID:GoogleServicesSettingsCommandIDToggleDataTypeSync
-                      dataType:SyncSetupService::kSyncOpenTabs];
-    LegacySyncSwitchItem* syncAutofillItem = [self
-        switchItemWithItemType:SyncAutofillItemType
-                  textStringID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_AUTOFILL_TEXT
-                detailStringID:0
-                     commandID:GoogleServicesSettingsCommandIDToggleDataTypeSync
-                      dataType:SyncSetupService::kSyncAutofill];
-    LegacySyncSwitchItem* syncSettingsItem = [self
-        switchItemWithItemType:SyncAutofillItemType
-                  textStringID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_SETTINGS_TEXT
-                detailStringID:0
-                     commandID:GoogleServicesSettingsCommandIDToggleDataTypeSync
-                      dataType:SyncSetupService::kSyncPreferences];
-    LegacySyncSwitchItem* syncReadingListItem = [self
-        switchItemWithItemType:SyncReadingListItemType
-                  textStringID:
-                      IDS_IOS_GOOGLE_SERVICES_SETTINGS_READING_LIST_TEXT
-                detailStringID:0
-                     commandID:GoogleServicesSettingsCommandIDToggleDataTypeSync
-                      dataType:SyncSetupService::kSyncReadingList];
-    CollectionViewTextItem* syncGoogleActivityControlsItem = [self
-        textItemWithItemType:SyncGoogleActivityControlsItemType
-                textStringID:
-                    IDS_IOS_GOOGLE_SERVICES_SETTINGS_GOOGLE_ACTIVITY_CONTROL_TEXT
-              detailStringID:
-                  IDS_IOS_GOOGLE_SERVICES_SETTINGS_GOOGLE_ACTIVITY_CONTROL_DETAIL
-               accessoryType:MDCCollectionViewCellAccessoryDisclosureIndicator
-                   commandID:
-                       GoogleServicesSettingsCommandIDOpenGoogleActivityControlsDialog];
-    CollectionViewTextItem* encryptionItem = [self
-        textItemWithItemType:EncryptionItemType
-                textStringID:IDS_IOS_GOOGLE_SERVICES_SETTINGS_ENCRYPTION_TEXT
-              detailStringID:0
-               accessoryType:MDCCollectionViewCellAccessoryDisclosureIndicator
-                   commandID:
-                       GoogleServicesSettingsCommandIDOpenEncryptionDialog];
-    CollectionViewTextItem* manageSyncedDataItem = [self
-        textItemWithItemType:ManageSyncedDataItemType
-                textStringID:
-                    IDS_IOS_GOOGLE_SERVICES_SETTINGS_MANAGED_SYNC_DATA_TEXT
-              detailStringID:0
-               accessoryType:MDCCollectionViewCellAccessoryNone
-                   commandID:
-                       GoogleServicesSettingsCommandIDOpenManageSyncedDataWebPage];
-    _personalizedItems = @[
-      syncBookmarksItem, syncHistoryItem, syncPasswordsItem, syncOpenTabsItem,
-      syncAutofillItem, syncSettingsItem, syncReadingListItem,
-      self.autocompleteWalletItem, syncGoogleActivityControlsItem,
-      encryptionItem, manageSyncedDataItem
-    ];
-  }
-  return _personalizedItems;
-}
-
-- (LegacySyncSwitchItem*)autocompleteWalletItem {
-  if (!_autocompleteWalletItem) {
-    _autocompleteWalletItem = [self
-        switchItemWithItemType:AutocompleteWalletItemType
-                  textStringID:
-                      IDS_IOS_GOOGLE_SERVICES_SETTINGS_AUTOCOMPLETE_WALLET
-                detailStringID:0
-                     commandID:
-                         GoogleServicesSettingsCommandIDAutocompleteWalletService
-                      dataType:0];
-  }
-  return _autocompleteWalletItem;
-}
-
 - (ItemArray)nonPersonalizedItems {
   if (!_nonPersonalizedItems) {
     LegacySyncSwitchItem* autocompleteSearchesAndURLsItem = [self
@@ -430,23 +251,6 @@
   return switchItem;
 }
 
-// Creates a CollectionViewTextItem instance.
-- (CollectionViewTextItem*)
-textItemWithItemType:(NSInteger)itemType
-        textStringID:(int)textStringID
-      detailStringID:(int)detailStringID
-       accessoryType:(MDCCollectionViewCellAccessoryType)accessoryType
-           commandID:(NSInteger)commandID {
-  CollectionViewTextItem* textItem =
-      [[CollectionViewTextItem alloc] initWithType:itemType];
-  textItem.text = GetNSString(textStringID);
-  textItem.accessoryType = accessoryType;
-  if (detailStringID)
-    textItem.detailText = GetNSString(detailStringID);
-  textItem.commandID = commandID;
-  return textItem;
-}
-
 // Reloads the sync feedback section. If |notifyConsummer| is YES, the consomer
 // is notified to add or remove the sync error section.
 - (void)updateSyncErrorSectionAndNotifyConsumer:(BOOL)notifyConsummer {
@@ -510,51 +314,13 @@
   }
 }
 
-// Updates the personalized section according to the user consent.
-- (void)updatePersonalizedSection {
-  BOOL enabled = self.isAuthenticated;
-  [self updateSectionWithItems:self.personalizedItems
-             switchItemEnabled:enabled
-               textItemEnabled:self.isAuthenticated];
-  syncer::ModelType autofillModelType =
-      _syncSetupService->GetModelType(SyncSetupService::kSyncAutofill);
-  BOOL isAutofillOn = _syncSetupService->IsDataTypePreferred(autofillModelType);
-  self.autocompleteWalletItem.enabled = enabled && isAutofillOn;
-  if (!isAutofillOn) {
-    // Autocomplete wallet item should be disabled when autofill is off.
-    self.autocompleteWalletItem.on = false;
-  }
-}
-
 // Updates the non-personalized section according to the user consent.
 - (void)updateNonPersonalizedSection {
-  BOOL enabled = YES;
-  [self updateSectionWithItems:self.nonPersonalizedItems
-             switchItemEnabled:enabled
-               textItemEnabled:enabled];
-}
-
-// Updates |items| using |switchItemEnabled| and |textItemEnabled|.
-- (void)updateSectionWithItems:(ItemArray)items
-             switchItemEnabled:(BOOL)switchItemEnabled
-               textItemEnabled:(BOOL)textItemEnabled {
-  for (CollectionViewItem* item in items) {
+  for (CollectionViewItem* item in self.nonPersonalizedItems) {
     if ([item isKindOfClass:[LegacySyncSwitchItem class]]) {
       LegacySyncSwitchItem* switchItem =
           base::mac::ObjCCast<LegacySyncSwitchItem>(item);
       switch (switchItem.commandID) {
-        case GoogleServicesSettingsCommandIDToggleDataTypeSync: {
-          SyncSetupService::SyncableDatatype dataType =
-              static_cast<SyncSetupService::SyncableDatatype>(
-                  switchItem.dataType);
-          syncer::ModelType modelType =
-              self.syncSetupService->GetModelType(dataType);
-          switchItem.on = self.syncSetupService->IsDataTypePreferred(modelType);
-          break;
-        }
-        case GoogleServicesSettingsCommandIDAutocompleteWalletService:
-          switchItem.on = self.autocompleteWalletPreference.value;
-          break;
         case GoogleServicesSettingsCommandIDToggleAutocompleteSearchesService:
           switchItem.on = self.autocompleteSearchPreference.value;
           break;
@@ -567,17 +333,7 @@
         case GoogleServicesSettingsCommandIDToggleBetterSearchAndBrowsingService:
           switchItem.on = self.anonymizedDataCollectionPreference.value;
           break;
-        case GoogleServicesSettingsCommandIDOpenGoogleActivityControlsDialog:
-        case GoogleServicesSettingsCommandIDOpenEncryptionDialog:
-        case GoogleServicesSettingsCommandIDOpenManageSyncedDataWebPage:
-          NOTREACHED();
-          break;
       }
-      switchItem.enabled = switchItemEnabled;
-    } else if ([item isKindOfClass:[CollectionViewTextItem class]]) {
-      CollectionViewTextItem* textItem =
-          base::mac::ObjCCast<CollectionViewTextItem>(item);
-      textItem.enabled = textItemEnabled;
     } else {
       NOTREACHED();
     }
@@ -589,30 +345,12 @@
 - (void)googleServicesSettingsViewControllerLoadModel:
     (GoogleServicesSettingsViewController*)controller {
   DCHECK_EQ(self.consumer, controller);
-  if (self.isAuthenticated)
-    [self loadSyncEverythingSection];
-  [self loadPersonalizedSection];
   [self loadNonPersonalizedSection];
   [self updateSyncErrorSectionAndNotifyConsumer:NO];
 }
 
 #pragma mark - GoogleServicesSettingsServiceDelegate
 
-- (void)toggleSyncEverythingWithValue:(BOOL)value {
-  if (!value)
-    return;
-  // Mark the switch has being animated to avoid being reloaded.
-  base::AutoReset<BOOL> autoReset(&_syncEverythingSwitchBeingAnimated, YES);
-}
-
-- (void)toggleSyncDataSync:(NSInteger)dataTypeInt withValue:(BOOL)value {
-  base::AutoReset<BOOL> autoReset(&_personalizedSectionBeingAnimated, YES);
-  SyncSetupService::SyncableDatatype dataType =
-      static_cast<SyncSetupService::SyncableDatatype>(dataTypeInt);
-  syncer::ModelType modelType = self.syncSetupService->GetModelType(dataType);
-  self.syncSetupService->SetDataTypeEnabled(modelType, value);
-}
-
 - (void)toggleAutocompleteWalletServiceWithValue:(BOOL)value {
   self.autocompleteWalletPreference.value = value;
 }
@@ -641,28 +379,6 @@
   self.anonymizedDataCollectionPreference.value = value;
 }
 
-#pragma mark - SyncObserverModelBridge
-
-- (void)onSyncStateChanged {
-  [self updatePersonalizedSection];
-  // TODO(crbug.com/899791): Should reloads only the updated items (instead of
-  // reload the full section), and get ride of
-  // |self.personalizedSectionBeingAnimated|. This will get a smoother animation
-  // for "Autocomplete wall" switch switch when being tapped by the user.
-  if (!self.personalizedSectionBeingAnimated) {
-    CollectionViewModel* model = self.consumer.collectionViewModel;
-    NSMutableIndexSet* sectionIndexToReload = [NSMutableIndexSet indexSet];
-    [sectionIndexToReload addIndex:[model sectionForSectionIdentifier:
-                                              PersonalizedSectionIdentifier]];
-    [self.consumer reloadSections:sectionIndexToReload];
-  } else {
-    // |self.autocompleteWalletItem| needs to be reloaded in case the autofill
-    // data type changed state.
-    [self.consumer reloadItem:self.autocompleteWalletItem];
-  }
-  [self updateSyncErrorSectionAndNotifyConsumer:YES];
-}
-
 #pragma mark - BooleanObserver
 
 - (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_service_delegate.h b/ios/chrome/browser/ui/settings/google_services_settings_service_delegate.h
index 5e3837c..ae7b3f7 100644
--- a/ios/chrome/browser/ui/settings/google_services_settings_service_delegate.h
+++ b/ios/chrome/browser/ui/settings/google_services_settings_service_delegate.h
@@ -20,21 +20,6 @@
   // SyncSetupService::kSyncServiceNeedsPassphrase.
   GoogleServicesSettingsCommandIDShowPassphraseDialog,
 
-  // Enabble/disable all the Google services.
-  GoogleServicesSettingsCommandIDToggleSyncEverything,
-
-  // Personalized section.
-  // Enable/disabble bookmark sync.
-  GoogleServicesSettingsCommandIDToggleDataTypeSync,
-  // Enable/disable autocomplete wallet for Google Pay.
-  GoogleServicesSettingsCommandIDAutocompleteWalletService,
-  // Opens the Google activity controls dialog.
-  GoogleServicesSettingsCommandIDOpenGoogleActivityControlsDialog,
-  // Opens the encryption dialog.
-  GoogleServicesSettingsCommandIDOpenEncryptionDialog,
-  // Opens manage synced data web page.
-  GoogleServicesSettingsCommandIDOpenManageSyncedDataWebPage,
-
   // Non-personalized section.
   // Enable/disabble autocomplete searches service.
   GoogleServicesSettingsCommandIDToggleAutocompleteSearchesService,
@@ -49,16 +34,6 @@
 // Protocol to handle Google services settings commands.
 @protocol GoogleServicesSettingsServiceDelegate<NSObject>
 
-// Called when GoogleServicesSettingsCommandIDToggleSyncEverything is triggered.
-- (void)toggleSyncEverythingWithValue:(BOOL)value;
-
-// Personalized section.
-// Called when GoogleServicesSettingsCommandIDToggleDataTypeSync is triggered.
-- (void)toggleSyncDataSync:(NSInteger)dataType withValue:(BOOL)value;
-// Called when GoogleServicesSettingsCommandIDAutocompleteWalletService is
-// triggered.
-- (void)toggleAutocompleteWalletServiceWithValue:(BOOL)value;
-
 // Non-personalized section.
 // Called when GoogleServicesSettingsCommandIDToggleAutocompleteSearchesService
 // is triggered.
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_view_controller.mm b/ios/chrome/browser/ui/settings/google_services_settings_view_controller.mm
index 0189159..5199d83 100644
--- a/ios/chrome/browser/ui/settings/google_services_settings_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/google_services_settings_view_controller.mm
@@ -6,8 +6,6 @@
 
 #include "base/mac/foundation_util.h"
 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
-#import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h"
-#import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h"
 #import "ios/chrome/browser/ui/settings/cells/legacy/legacy_sync_switch_item.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h"
 #import "ios/chrome/browser/ui/settings/google_services_settings_local_commands.h"
@@ -30,11 +28,6 @@
 
 @implementation GoogleServicesSettingsViewController
 
-@synthesize presentationDelegate = _presentationDelegate;
-@synthesize modelDelegate = _modelDelegate;
-@synthesize serviceDelegate = _serviceDelegate;
-@synthesize localDispatcher = _localDispatcher;
-
 - (instancetype)initWithLayout:(UICollectionViewLayout*)layout
                          style:(CollectionViewControllerStyle)style {
   self = [super initWithLayout:layout style:style];
@@ -67,16 +60,6 @@
   GoogleServicesSettingsCommandID commandID =
       static_cast<GoogleServicesSettingsCommandID>(syncSwitchItem.commandID);
   switch (commandID) {
-    case GoogleServicesSettingsCommandIDToggleSyncEverything:
-      [self.serviceDelegate toggleSyncEverythingWithValue:isOn];
-      break;
-    case GoogleServicesSettingsCommandIDToggleDataTypeSync:
-      [self.serviceDelegate toggleSyncDataSync:syncSwitchItem.dataType
-                                     withValue:isOn];
-      break;
-    case GoogleServicesSettingsCommandIDAutocompleteWalletService:
-      [self.serviceDelegate toggleAutocompleteWalletServiceWithValue:isOn];
-      break;
     case GoogleServicesSettingsCommandIDToggleAutocompleteSearchesService:
       [self.serviceDelegate toggleAutocompleteSearchesServiceWithValue:isOn];
       break;
@@ -93,9 +76,6 @@
     case GoogleServicesSettingsReauthDialogAsSyncIsInAuthError:
     case GoogleServicesSettingsCommandIDShowPassphraseDialog:
     case GoogleServicesSettingsCommandIDNoOp:
-    case GoogleServicesSettingsCommandIDOpenGoogleActivityControlsDialog:
-    case GoogleServicesSettingsCommandIDOpenEncryptionDialog:
-    case GoogleServicesSettingsCommandIDOpenManageSyncedDataWebPage:
       // Command ID not related with switch action.
       NOTREACHED();
       break;
@@ -202,10 +182,6 @@
     return NO;
   } else if ([item isKindOfClass:[SettingsImageDetailTextItem class]]) {
     return YES;
-  } else if ([item isKindOfClass:[CollectionViewTextItem class]]) {
-    CollectionViewTextItem* textItem =
-        base::mac::ObjCCast<CollectionViewTextItem>(item);
-    return textItem.enabled;
   }
   // The highlight of an item should be explicitly defined. If the item can be
   // highlighted, then a command ID should be defined in
@@ -222,12 +198,7 @@
       [self.collectionViewModel itemAtIndexPath:indexPath];
   GoogleServicesSettingsCommandID commandID =
       GoogleServicesSettingsCommandIDNoOp;
-  if ([item isKindOfClass:[CollectionViewTextItem class]]) {
-    CollectionViewTextItem* textItem =
-        base::mac::ObjCCast<CollectionViewTextItem>(item);
-    commandID =
-        static_cast<GoogleServicesSettingsCommandID>(textItem.commandID);
-  } else if ([item isKindOfClass:[SettingsImageDetailTextItem class]]) {
+  if ([item isKindOfClass:[SettingsImageDetailTextItem class]]) {
     SettingsImageDetailTextItem* imageDetailTextItem =
         base::mac::ObjCCast<SettingsImageDetailTextItem>(item);
     commandID = static_cast<GoogleServicesSettingsCommandID>(
@@ -246,19 +217,7 @@
     case GoogleServicesSettingsCommandIDShowPassphraseDialog:
       [self.localDispatcher openPassphraseDialog];
       break;
-    case GoogleServicesSettingsCommandIDOpenGoogleActivityControlsDialog:
-      [self.localDispatcher openGoogleActivityControlsDialog];
-      break;
-    case GoogleServicesSettingsCommandIDOpenEncryptionDialog:
-      [self.localDispatcher openEncryptionDialog];
-      break;
-    case GoogleServicesSettingsCommandIDOpenManageSyncedDataWebPage:
-      [self.localDispatcher openManageSyncedDataWebPage];
-      break;
     case GoogleServicesSettingsCommandIDNoOp:
-    case GoogleServicesSettingsCommandIDToggleSyncEverything:
-    case GoogleServicesSettingsCommandIDToggleDataTypeSync:
-    case GoogleServicesSettingsCommandIDAutocompleteWalletService:
     case GoogleServicesSettingsCommandIDToggleAutocompleteSearchesService:
     case GoogleServicesSettingsCommandIDTogglePreloadPagesService:
     case GoogleServicesSettingsCommandIDToggleImproveChromeService:
diff --git a/ios/chrome/browser/ui/settings/import_data_table_view_controller.mm b/ios/chrome/browser/ui/settings/import_data_table_view_controller.mm
index f21db7d0..44be3f3 100644
--- a/ios/chrome/browser/ui/settings/import_data_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/import_data_table_view_controller.mm
@@ -7,7 +7,7 @@
 #include "base/logging.h"
 #import "base/mac/foundation_util.h"
 #include "base/strings/sys_string_conversions.h"
-#import "ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h"
+#import "ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h"
 #import "ios/chrome/browser/ui/table_view/table_view_model.h"
 #include "ios/chrome/grit/ios_chromium_strings.h"
@@ -45,8 +45,8 @@
   NSString* _toEmail;
   BOOL _isSignedIn;
   ShouldClearData _shouldClearData;
-  ImportDataMultilineDetailItem* _importDataItem;
-  ImportDataMultilineDetailItem* _keepDataSeparateItem;
+  SettingsMultilineDetailItem* _importDataItem;
+  SettingsMultilineDetailItem* _keepDataSeparateItem;
 }
 
 #pragma mark - Initialization
@@ -127,8 +127,8 @@
   return item;
 }
 
-- (ImportDataMultilineDetailItem*)importDataItem {
-  ImportDataMultilineDetailItem* item = [[ImportDataMultilineDetailItem alloc]
+- (SettingsMultilineDetailItem*)importDataItem {
+  SettingsMultilineDetailItem* item = [[SettingsMultilineDetailItem alloc]
       initWithType:ItemTypeOptionImportData];
   item.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_IMPORT_DATA_IMPORT_TITLE);
   item.detailText =
@@ -140,8 +140,8 @@
   return item;
 }
 
-- (ImportDataMultilineDetailItem*)keepDataSeparateItem {
-  ImportDataMultilineDetailItem* item = [[ImportDataMultilineDetailItem alloc]
+- (SettingsMultilineDetailItem*)keepDataSeparateItem {
+  SettingsMultilineDetailItem* item = [[SettingsMultilineDetailItem alloc]
       initWithType:ItemTypeOptionKeepDataSeparate];
   item.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_IMPORT_DATA_KEEP_TITLE);
   if (_isSignedIn) {
diff --git a/ios/chrome/browser/ui/settings/import_data_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/import_data_table_view_controller_unittest.mm
index 70ba2e9..3fb7a8c 100644
--- a/ios/chrome/browser/ui/settings/import_data_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/import_data_table_view_controller_unittest.mm
@@ -7,7 +7,7 @@
 #include "base/mac/foundation_util.h"
 #include "base/strings/sys_string_conversions.h"
 #import "ios/chrome/browser/ui/settings/cells/card_multiline_item.h"
-#import "ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h"
+#import "ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.h"
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h"
 #import "ios/chrome/browser/ui/table_view/table_view_model.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -125,12 +125,12 @@
   NSIndexPath* importIndexPath = [NSIndexPath indexPathForItem:0 inSection:1];
   NSIndexPath* keepSeparateIndexPath = [NSIndexPath indexPathForItem:1
                                                            inSection:1];
-  ImportDataMultilineDetailItem* importItem =
-      base::mac::ObjCCastStrict<ImportDataMultilineDetailItem>(
+  SettingsMultilineDetailItem* importItem =
+      base::mac::ObjCCastStrict<SettingsMultilineDetailItem>(
           [import_data_controller.tableViewModel
               itemAtIndexPath:importIndexPath]);
-  ImportDataMultilineDetailItem* keepSeparateItem =
-      base::mac::ObjCCastStrict<ImportDataMultilineDetailItem>(
+  SettingsMultilineDetailItem* keepSeparateItem =
+      base::mac::ObjCCastStrict<SettingsMultilineDetailItem>(
           [import_data_controller.tableViewModel
               itemAtIndexPath:keepSeparateIndexPath]);
 
diff --git a/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm b/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm
index 2cc3374..09567da 100644
--- a/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm
@@ -33,7 +33,6 @@
 #import "ios/chrome/browser/ui/settings/cells/account_signin_item.h"
 #import "ios/chrome/browser/ui/settings/cells/card_multiline_item.h"
 #import "ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.h"
-#import "ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h"
 #import "ios/chrome/browser/ui/settings/cells/legacy/legacy_autofill_data_item.h"
 #import "ios/chrome/browser/ui/settings/cells/legacy/legacy_settings_detail_item.h"
 #import "ios/chrome/browser/ui/settings/cells/legacy/legacy_settings_switch_item.h"
@@ -41,6 +40,7 @@
 #import "ios/chrome/browser/ui/settings/cells/passphrase_error_item.h"
 #import "ios/chrome/browser/ui/settings/cells/password_details_item.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h"
+#import "ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_search_item.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_text_item.h"
 #import "ios/chrome/browser/ui/settings/cells/text_and_error_item.h"
diff --git a/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm b/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm
index b60c244..93fa46f 100644
--- a/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm
@@ -22,7 +22,7 @@
 #include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/experimental_flags.h"
 #include "ios/chrome/browser/pref_names.h"
-#import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
+#import "ios/chrome/browser/ui/settings/accounts_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_cells_constants.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_detail_item.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_switch_cell.h"
diff --git a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
index 3b6c72dc..c56794b 100644
--- a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
@@ -43,7 +43,7 @@
 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/commands/settings_main_page_commands.h"
 #import "ios/chrome/browser/ui/settings/about_chrome_table_view_controller.h"
-#import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
+#import "ios/chrome/browser/ui/settings/accounts_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/autofill_profile_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/bandwidth_management_table_view_controller.h"
@@ -824,7 +824,7 @@
                         completion:nil];
       break;
     case ItemTypeAccount:
-      controller = [[AccountsCollectionViewController alloc]
+      controller = [[AccountsTableViewController alloc]
                initWithBrowserState:_browserState
           closeSettingsOnAddAccount:NO];
       break;
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.h b/ios/chrome/browser/ui/settings/settings_navigation_controller.h
index a72b401d..c11dca01 100644
--- a/ios/chrome/browser/ui/settings/settings_navigation_controller.h
+++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.h
@@ -55,7 +55,7 @@
                                      (id<SettingsNavigationControllerDelegate>)
                                          delegate;
 
-// Creates a new AccountsCollectionViewController and the chrome around it.
+// Creates a new AccountsTableViewController and the chrome around it.
 // |browserState| is used to personalize some settings aspects and should not be
 // nil. |delegate| may be nil.
 + (SettingsNavigationController*)
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
index e7a656b..a0effec 100644
--- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -13,7 +13,7 @@
 #import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h"
 #import "ios/chrome/browser/ui/material_components/app_bar_view_controller_presenting.h"
 #import "ios/chrome/browser/ui/material_components/utils.h"
-#import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
+#import "ios/chrome/browser/ui/settings/accounts_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/autofill_profile_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/google_services_settings_coordinator.h"
@@ -131,9 +131,9 @@
 + (SettingsNavigationController*)
 newAccountsController:(ios::ChromeBrowserState*)browserState
              delegate:(id<SettingsNavigationControllerDelegate>)delegate {
-  AccountsCollectionViewController* controller = [
-      [AccountsCollectionViewController alloc] initWithBrowserState:browserState
-                                          closeSettingsOnAddAccount:YES];
+  AccountsTableViewController* controller =
+      [[AccountsTableViewController alloc] initWithBrowserState:browserState
+                                      closeSettingsOnAddAccount:YES];
   controller.dispatcher = [delegate dispatcherForSettings];
   SettingsNavigationController* nc = [[SettingsNavigationController alloc]
       initWithRootViewController:controller
@@ -498,10 +498,9 @@
 // TODO(crbug.com/779791) : Do not pass |baseViewController| through dispatcher.
 - (void)showAccountsSettingsFromViewController:
     (UIViewController*)baseViewController {
-  AccountsCollectionViewController* controller =
-      [[AccountsCollectionViewController alloc]
-               initWithBrowserState:mainBrowserState_
-          closeSettingsOnAddAccount:NO];
+  AccountsTableViewController* controller = [[AccountsTableViewController alloc]
+           initWithBrowserState:mainBrowserState_
+      closeSettingsOnAddAccount:NO];
   controller.dispatcher = [delegate_ dispatcherForSettings];
   [self pushViewController:controller animated:YES];
 }
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc
index 8e188d2e..ed0a595 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.cc
+++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -18,6 +18,3 @@
 
 const base::Feature kSearchCopiedImage{"SearchCopiedImage",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
-
-const base::Feature kCopiedTextBehavior{"CopiedTextBehavior",
-                                        base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/ui/ui_feature_flags.h b/ios/chrome/browser/ui/ui_feature_flags.h
index e420898..a56a4001 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.h
+++ b/ios/chrome/browser/ui/ui_feature_flags.h
@@ -24,7 +24,4 @@
 // Feature to allow user to search for a copied image.
 extern const base::Feature kSearchCopiedImage;
 
-// Feature to differentiate between a copied url and copied text
-extern const base::Feature kCopiedTextBehavior;
-
 #endif  // IOS_CHROME_BROWSER_UI_UI_FEATURE_FLAGS_H_
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
index 94afa63f..c52889e 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
@@ -8,7 +8,7 @@
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/ui/history/history_ui_constants.h"
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h"
-#import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
+#import "ios/chrome/browser/ui/settings/accounts_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/clear_browsing_data_ui_constants.h"
 #import "ios/chrome/browser/ui/settings/privacy_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h"
@@ -150,7 +150,7 @@
 + (void)tapAccountsMenuButton:(id<GREYMatcher>)buttonMatcher {
   [[[EarlGrey selectElementWithMatcher:buttonMatcher]
          usingSearchAction:ScrollDown()
-      onElementWithMatcher:grey_accessibilityID(kSettingsAccountsId)]
+      onElementWithMatcher:grey_accessibilityID(kSettingsAccountsTableViewId)]
       performAction:grey_tap()];
 }
 
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm
index 11a9649c3..2193082 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.mm
+++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -23,7 +23,7 @@
 #import "ios/chrome/browser/ui/payments/payment_request_picker_view_controller.h"
 #import "ios/chrome/browser/ui/payments/payment_request_view_controller.h"
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h"
-#import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
+#import "ios/chrome/browser/ui/settings/accounts_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/cells/clear_browsing_data_constants.h"
 #import "ios/chrome/browser/ui/settings/cells/legacy/legacy_settings_switch_item.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_switch_cell.h"
@@ -336,11 +336,11 @@
 }
 
 id<GREYMatcher> AddAccountButton() {
-  return grey_accessibilityID(kSettingsAccountsAddAccountCellId);
+  return grey_accessibilityID(kSettingsAccountsTableViewAddAccountCellId);
 }
 
 id<GREYMatcher> SignOutAccountsButton() {
-  return grey_accessibilityID(kSettingsAccountsSignoutCellId);
+  return grey_accessibilityID(kSettingsAccountsTableViewSignoutCellId);
 }
 
 id<GREYMatcher> ClearBrowsingDataCell() {
@@ -392,7 +392,7 @@
 }
 
 id<GREYMatcher> SettingsAccountsCollectionView() {
-  return grey_accessibilityID(kSettingsAccountsId);
+  return grey_accessibilityID(kSettingsAccountsTableViewId);
 }
 
 id<GREYMatcher> SettingsImportDataImportButton() {
@@ -408,7 +408,7 @@
 }
 
 id<GREYMatcher> AccountsSyncButton() {
-  return grey_allOf(grey_accessibilityID(kSettingsAccountsSyncCellId),
+  return grey_allOf(grey_accessibilityID(kSettingsAccountsTableViewSyncCellId),
                     grey_sufficientlyVisible(), nil);
 }
 
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 4ba52f6..6e5b9fa5 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -51,7 +51,6 @@
     "//services/network:network_service",
     "//services/network/public/mojom",
     "//services/service_manager",
-    "//services/service_manager/embedder",
     "//services/service_manager/public/cpp",
   ]
 
diff --git a/ios/web/service_manager_context.mm b/ios/web/service_manager_context.mm
index 3f10f2b9..df31e85 100644
--- a/ios/web/service_manager_context.mm
+++ b/ios/web/service_manager_context.mm
@@ -26,10 +26,8 @@
 #include "ios/web/public/web_task_traits.h"
 #include "ios/web/public/web_thread.h"
 #include "ios/web/service_manager_connection_impl.h"
-#include "services/catalog/public/cpp/manifest_parsing_util.h"
 #include "services/catalog/public/mojom/constants.mojom.h"
 #include "services/service_manager/connect_params.h"
-#include "services/service_manager/embedder/manifest_utils.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/constants.h"
 #include "services/service_manager/public/cpp/manifest.h"
diff --git a/ipc/message_filter_router.cc b/ipc/message_filter_router.cc
index f56279e..344b83ca 100644
--- a/ipc/message_filter_router.cc
+++ b/ipc/message_filter_router.cc
@@ -7,7 +7,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_message_utils.h"
 #include "ipc/message_filter.h"
@@ -72,7 +72,7 @@
   if (RemoveFilterImpl(global_filters_, filter))
     return;
 
-  for (size_t i = 0; i < arraysize(message_class_filters_); ++i)
+  for (size_t i = 0; i < base::size(message_class_filters_); ++i)
     RemoveFilterImpl(message_class_filters_[i], filter);
 }
 
@@ -89,7 +89,7 @@
 
 void MessageFilterRouter::Clear() {
   global_filters_.clear();
-  for (size_t i = 0; i < arraysize(message_class_filters_); ++i)
+  for (size_t i = 0; i < base::size(message_class_filters_); ++i)
     message_class_filters_[i].clear();
 }
 
diff --git a/ipc/sync_socket_unittest.cc b/ipc/sync_socket_unittest.cc
index f9db649a..2f116a0 100644
--- a/ipc/sync_socket_unittest.cc
+++ b/ipc/sync_socket_unittest.cc
@@ -12,9 +12,9 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/threading/thread.h"
 #include "build/build_config.h"
 #include "ipc/ipc_test_base.h"
@@ -51,7 +51,7 @@
 namespace {
 
 const char kHelloString[] = "Hello, SyncSocket Client";
-const size_t kHelloStringLength = arraysize(kHelloString);
+const size_t kHelloStringLength = base::size(kHelloString);
 
 // The SyncSocket server listener class processes two sorts of
 // messages from the client.
@@ -226,7 +226,7 @@
   size_t received = 1U;  // Initialize to an unexpected value.
   worker.task_runner()->PostTask(
       FROM_HERE,
-      base::Bind(&BlockingRead, &pair[0], &buf[0], arraysize(buf), &received));
+      base::Bind(&BlockingRead, &pair[0], &buf[0], base::size(buf), &received));
 
   // Wait for the worker thread to say hello.
   char hello[kHelloStringLength] = {0};
diff --git a/mash/BUILD.gn b/mash/BUILD.gn
index b9aa26a..d1773fbf 100644
--- a/mash/BUILD.gn
+++ b/mash/BUILD.gn
@@ -13,7 +13,6 @@
   testonly = true
 
   deps = [
-    ":mash_catalog",
     "//components/services/leveldb",
     "//mash/catalog_viewer",
     "//mash/example",
@@ -36,16 +35,14 @@
   standalone_services = [
     "//components/services/leveldb:manifest",
     "//mash/catalog_viewer:manifest",
+    "//mash/example/views_examples:manifest",
+    "//mash/example/window_type_launcher:manifest",
     "//mash/session:manifest",
     "//mash/task_viewer:manifest",
     "//services/ws/ime/test_ime_driver:manifest",
     "//services/viz:manifest",
   ]
 
-  executable_overrides = [ "content_packaged_services:@EXE_DIR/chrome" ]
-
-  catalog_deps = [ "//mash/example:catalog" ]
-
   if (is_chromeos) {
     standalone_services += [
       "//ash:manifest",
@@ -65,13 +62,8 @@
   }
 }
 
-copy("mash_catalog") {
+catalog_cpp_source("mash_catalog_source") {
   testonly = true
-  sources = get_target_outputs(":catalog")
-  outputs = [
-    "$root_out_dir/mash_catalog.json",
-  ]
-  deps = [
-    ":catalog",
-  ]
+  catalog = ":catalog"
+  generated_function_name = "CreateMashCatalog"
 }
diff --git a/mash/example/BUILD.gn b/mash/example/BUILD.gn
index a210a3c..1e772aae 100644
--- a/mash/example/BUILD.gn
+++ b/mash/example/BUILD.gn
@@ -18,10 +18,3 @@
     deps += [ "//ash:ash_service" ]
   }
 }
-
-catalog("catalog") {
-  standalone_services = [
-    "//mash/example/views_examples:manifest",
-    "//mash/example/window_type_launcher:manifest",
-  ]
-}
diff --git a/mash/runner/BUILD.gn b/mash/runner/BUILD.gn
index 4cb3030c..a82a207 100644
--- a/mash/runner/BUILD.gn
+++ b/mash/runner/BUILD.gn
@@ -13,13 +13,10 @@
     "//base",
     "//base:i18n",
     "//base/test:test_support",
+    "//mash:mash_catalog_source",
     "//mojo/core/embedder",
     "//services/service_manager",
     "//services/service_manager/runner:init",
     "//services/service_manager/standalone",
   ]
-
-  data_deps = [
-    "//mash:mash_catalog",
-  ]
 }
diff --git a/mash/runner/main.cc b/mash/runner/main.cc
index 68e56a3..e08d303 100644
--- a/mash/runner/main.cc
+++ b/mash/runner/main.cc
@@ -25,19 +25,13 @@
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread.h"
 #include "build/build_config.h"
+#include "mash/mash_catalog_source.h"
 #include "mojo/core/embedder/embedder.h"
 #include "mojo/core/embedder/scoped_ipc_support.h"
 #include "services/service_manager/runner/init.h"
 #include "services/service_manager/standalone/context.h"
 #include "services/service_manager/switches.h"
 
-namespace {
-
-const base::FilePath::CharType kMashCatalogFilename[] =
-    FILE_PATH_LITERAL("mash_catalog.json");
-
-}  // namespace
-
 int main(int argc, char** argv) {
   base::CommandLine::Init(argc, argv);
 
@@ -54,19 +48,11 @@
 #endif
   base::PlatformThread::SetName("service_manager");
 
-  std::string catalog_contents;
-  base::FilePath exe_path;
-  base::PathService::Get(base::DIR_EXE, &exe_path);
-  base::FilePath catalog_path = exe_path.Append(kMashCatalogFilename);
-  bool result = base::ReadFileToString(catalog_path, &catalog_contents);
-  DCHECK(result);
-  std::unique_ptr<base::Value> manifest_value =
-      base::JSONReader::Read(catalog_contents);
-  DCHECK(manifest_value);
-
 #if defined(OS_WIN) && defined(COMPONENT_BUILD)
   // In Windows component builds, ensure that loaded service binaries always
   // search this exe's dir for DLLs.
+  base::FilePath exe_path;
+  base::PathService::Get(base::DIR_EXE, &exe_path);
   SetDllDirectory(exe_path.value().c_str());
 #endif
 
@@ -86,7 +72,7 @@
 
   base::test::ScopedTaskEnvironment scoped_task_environment;
   service_manager::Context service_manager_context(nullptr,
-                                                   std::move(manifest_value));
+                                                   CreateMashCatalog());
   base::RunLoop loop;
   scoped_task_environment.GetMainThreadTaskRunner()->PostTask(
       FROM_HERE,
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index a2d24d47..7d18871 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -83,7 +83,12 @@
     "gpu_video_decode_accelerator_factory.h",
     "gpu_video_encode_accelerator_factory.cc",
     "gpu_video_encode_accelerator_factory.h",
+    "image_processor.cc",
     "image_processor.h",
+    "image_processor_factory.cc",
+    "image_processor_factory.h",
+    "libyuv_image_processor.cc",
+    "libyuv_image_processor.h",
     "platform_video_frame.cc",
     "platform_video_frame.h",
   ]
@@ -227,6 +232,7 @@
       "v4l2/v4l2_vp9_accelerator.cc",
       "v4l2/v4l2_vp9_accelerator.h",
     ]
+
     libs = [
       "EGL",
       "GLESv2",
diff --git a/media/gpu/image_processor.cc b/media/gpu/image_processor.cc
new file mode 100644
index 0000000..1f5c409
--- /dev/null
+++ b/media/gpu/image_processor.cc
@@ -0,0 +1,19 @@
+// 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/image_processor.h"
+
+namespace media {
+
+ImageProcessor::PortConfig::PortConfig(
+    const VideoFrameLayout& layout,
+    const gfx::Size& visible_size,
+    const std::vector<VideoFrame::StorageType>& preferred_storage_types)
+    : layout(layout),
+      visible_size(visible_size),
+      preferred_storage_types(preferred_storage_types) {}
+
+ImageProcessor::PortConfig::~PortConfig() {}
+
+}  // namespace media
diff --git a/media/gpu/image_processor.h b/media/gpu/image_processor.h
index 81bf062..feefd75 100644
--- a/media/gpu/image_processor.h
+++ b/media/gpu/image_processor.h
@@ -10,7 +10,9 @@
 #include "base/callback_forward.h"
 #include "base/files/scoped_file.h"
 #include "base/memory/ref_counted.h"
+#include "build/build_config.h"
 #include "media/base/video_frame.h"
+#include "media/base/video_frame_layout.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace media {
@@ -21,35 +23,35 @@
 // in a format different from what the rest of the pipeline expects.
 //
 // This class exposes the interface that an image processor should implement.
+// The threading model of ImageProcessor:
+// Process(), Reset(), and callbacks: FrameReadyCB, ErrorCB, should be run in
+// the same thread that creates ImageProcessor.
 class ImageProcessor {
  public:
   // OutputMode is used as intermediate stage. The ultimate goal is to make
   // ImageProcessor's clients all use IMPORT output mode.
-  // TODO(907767): Remove this once ImageProcessor always works as IMPORT mode
-  // for output.
+  // TODO(crbug.com/907767): Remove this once ImageProcessor always works as
+  // IMPORT mode for output.
   enum class OutputMode {
     ALLOCATE,
     IMPORT
   };
 
-  // Returns input allocated size required by the processor to be fed with.
-  virtual gfx::Size input_allocated_size() const = 0;
+  // Encapsulates ImageProcessor input / output configurations.
+  struct PortConfig {
+    PortConfig() = delete;
+    PortConfig(
+        const VideoFrameLayout& layout,
+        const gfx::Size& visible_size,
+        const std::vector<VideoFrame::StorageType>& preferred_storage_types);
+    ~PortConfig();
 
-  // Returns output allocated size required by the processor.
-  virtual gfx::Size output_allocated_size() const = 0;
+    const VideoFrameLayout layout;
+    const gfx::Size visible_size;
+    const std::vector<VideoFrame::StorageType> preferred_storage_types;
+  };
 
-  // Returns input storage type.
-  virtual VideoFrame::StorageType input_storage_type() const = 0;
-
-  // Returns output storage type.
-  virtual VideoFrame::StorageType output_storage_type() const = 0;
-
-  // Returns output mode.
-  virtual OutputMode output_mode() const = 0;
-
-  // Callback to be used to return the index of a processed image to the
-  // client. After the client is done with the frame, call Process with the
-  // index to return the output buffer to the image processor.
+  // Callback to be used to return a processed image to the client.
   // FrameReadyCB shall be executed on the thread that creates ImageProcessor.
   // ImageProcessor has to bind its weak pointer to the task to execute
   // FrameReadyCB so that the task will not be called after ImageProcessor
@@ -66,6 +68,22 @@
   // lifetime of or outlive ImageProcessor.
   using ErrorCB = base::RepeatingClosure;
 
+  // Returns input allocated size required by the processor to be fed with.
+  virtual gfx::Size input_allocated_size() const = 0;
+
+  // Returns output allocated size required by the processor.
+  virtual gfx::Size output_allocated_size() const = 0;
+
+  // Returns input storage type.
+  virtual VideoFrame::StorageType input_storage_type() const = 0;
+
+  // Returns output storage type.
+  virtual VideoFrame::StorageType output_storage_type() const = 0;
+
+  // Returns output mode.
+  virtual OutputMode output_mode() const = 0;
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
   // Called by client to process |frame|. The resulting processed frame will be
   // stored in |output_buffer_index| output buffer and notified via |cb|. The
   // processor will drop all its references to |frame| after it finishes
@@ -73,13 +91,31 @@
   // should pass non-empty |output_dmabuf_fds| and the processed frame will be
   // stored in those buffers. If the number of |output_dmabuf_fds| is not
   // expected, this function will return false.
+  // Process() must be called on the same thread that creates ImageProcessor.
+  //
+  // Note: because base::ScopedFD is defined under OS_POXIS or OS_FUCHSIA, we
+  // define this function under the same build config. It doesn't affect its
+  // current users as they are all under the same build config.
+  // TODO(crbug.com/907767): Remove this once ImageProcessor always works as
+  // IMPORT mode for output.
   virtual bool Process(scoped_refptr<VideoFrame> frame,
                        int output_buffer_index,
                        std::vector<base::ScopedFD> output_dmabuf_fds,
                        FrameReadyCB cb) = 0;
+#endif
+
+  // Called by client to process |input_frame| and store in |output_frame|. This
+  // can only be used when output mode is IMPORT. The processor will drop all
+  // its references to |input_frame| and |output_frame| after it finishes
+  // accessing it.
+  // Process() must be called on the same thread that creates ImageProcessor.
+  virtual bool Process(scoped_refptr<VideoFrame> input_frame,
+                       scoped_refptr<VideoFrame> output_frame,
+                       FrameReadyCB cb) = 0;
 
   // Reset all processing frames. After this method returns, no more callbacks
   // will be invoked. ImageProcessor is ready to process more frames.
+  // Reset() must be called on the same thread that creates ImageProcessor.
   virtual bool Reset() = 0;
 
   virtual ~ImageProcessor() = default;
diff --git a/media/gpu/image_processor_factory.cc b/media/gpu/image_processor_factory.cc
new file mode 100644
index 0000000..ba259c2
--- /dev/null
+++ b/media/gpu/image_processor_factory.cc
@@ -0,0 +1,46 @@
+// 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/image_processor_factory.h"
+
+#include <stddef.h>
+
+#include "base/callback.h"
+#include "media/gpu/buildflags.h"
+#include "media/gpu/libyuv_image_processor.h"
+
+#if BUILDFLAG(USE_V4L2_CODEC)
+#include "media/gpu/v4l2/v4l2_device.h"
+#include "media/gpu/v4l2/v4l2_image_processor.h"
+#endif  // BUILDFLAG(USE_V4L2_CODEC)
+
+namespace media {
+
+// static
+std::unique_ptr<ImageProcessor> ImageProcessorFactory::Create(
+    const ImageProcessor::PortConfig& input_config,
+    const ImageProcessor::PortConfig& output_config,
+    const std::vector<ImageProcessor::OutputMode>& preferred_output_modes,
+    size_t num_buffers,
+    ImageProcessor::ErrorCB error_cb) {
+  std::unique_ptr<ImageProcessor> image_processor;
+#if BUILDFLAG(USE_V4L2_CODEC)
+  for (auto output_mode : preferred_output_modes) {
+    image_processor = V4L2ImageProcessor::Create(
+        V4L2Device::Create(), input_config, output_config, output_mode,
+        num_buffers, error_cb);
+    if (image_processor)
+      return image_processor;
+  }
+#endif  // BUILDFLAG(USE_V4L2_CODEC)
+  for (auto output_mode : preferred_output_modes) {
+    image_processor = LibYUVImageProcessor::Create(input_config, output_config,
+                                                   output_mode, error_cb);
+    if (image_processor)
+      return image_processor;
+  }
+  return nullptr;
+}
+
+}  // namespace media
diff --git a/media/gpu/image_processor_factory.h b/media/gpu/image_processor_factory.h
new file mode 100644
index 0000000..31f165d
--- /dev/null
+++ b/media/gpu/image_processor_factory.h
@@ -0,0 +1,56 @@
+// 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_IMAGE_PROCESSOR_FACTORY_H_
+#define MEDIA_GPU_IMAGE_PROCESSOR_FACTORY_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "media/gpu/image_processor.h"
+#include "media/gpu/media_gpu_export.h"
+
+namespace media {
+
+class MEDIA_GPU_EXPORT ImageProcessorFactory {
+ public:
+  // Factory method to create ImageProcessor.
+  // Given input and output PortConfig, it tries to find out the most suitable
+  // ImageProcessor to be used for the current platform.
+  //
+  // For |preferred_output_modes|, it tries instantiate an ImageProcessor class
+  // with an output mode in sequence. With ImageProcessor subclass and output
+  // mode selected, the subclass' factory method will pick the first supported
+  // input and output storage type from input and output PortConfig,
+  // respectively. It has an assumption that the selection of output mode is
+  // independent from the selection of output storage type.
+  //
+  // TODO(crbug.com/907767): Remove |preferred_output_modes| once ImageProcessor
+  // only accepts IMPORT output mode.
+  //
+  // Args:
+  //   input_config: input PortConfig.
+  //   output_config: output PortConfig.
+  //   preferred_output_modes: list of preferred output modes.
+  //   num_buffers: number of input and output buffers.
+  //   error_cb: Callback when error occurs.
+  //
+  // Returns:
+  //   Most suitable ImageProcessor instance. nullptr if no ImageProcessor
+  //   is available for given parameters on current platform.
+  static std::unique_ptr<ImageProcessor> Create(
+      const ImageProcessor::PortConfig& input_config,
+      const ImageProcessor::PortConfig& output_config,
+      const std::vector<ImageProcessor::OutputMode>& preferred_output_modes,
+      size_t num_buffers,
+      ImageProcessor::ErrorCB error_cb);
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ImageProcessorFactory);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_IMAGE_PROCESSOR_FACTORY_H_
diff --git a/media/gpu/libyuv_image_processor.cc b/media/gpu/libyuv_image_processor.cc
new file mode 100644
index 0000000..d4470dfba
--- /dev/null
+++ b/media/gpu/libyuv_image_processor.cc
@@ -0,0 +1,232 @@
+// 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/libyuv_image_processor.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "media/gpu/macros.h"
+#include "third_party/libyuv/include/libyuv/convert_from.h"
+
+namespace media {
+
+LibYUVImageProcessor::LibYUVImageProcessor(
+    const VideoFrameLayout& input_layout,
+    const gfx::Size& input_visible_size,
+    VideoFrame::StorageType input_storage_type,
+    const VideoFrameLayout& output_layout,
+    const gfx::Size& output_visible_size,
+    VideoFrame::StorageType output_storage_type,
+    ErrorCB error_cb)
+    : input_layout_(input_layout),
+      input_visible_rect_(input_visible_size),
+      input_storage_type_(input_storage_type),
+      output_layout_(output_layout),
+      output_visible_rect_(output_visible_size),
+      output_storage_type_(output_storage_type),
+      error_cb_(error_cb),
+      client_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      process_thread_("LibYUVImageProcessorThread"),
+      weak_this_factory_(this) {
+  weak_this_ = weak_this_factory_.GetWeakPtr();
+}
+
+LibYUVImageProcessor::~LibYUVImageProcessor() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  weak_this_factory_.InvalidateWeakPtrs();
+  process_thread_.Stop();
+}
+
+// static
+std::unique_ptr<LibYUVImageProcessor> LibYUVImageProcessor::Create(
+    const ImageProcessor::PortConfig& input_config,
+    const ImageProcessor::PortConfig& output_config,
+    const ImageProcessor::OutputMode output_mode,
+    ErrorCB error_cb) {
+  VLOGF(2);
+
+  if (!IsFormatSupported(input_config.layout.format(),
+                         output_config.layout.format())) {
+    VLOGF(2) << "Conversion from " << input_config.layout.format() << " to "
+             << output_config.layout.format() << " is not supported";
+    return nullptr;
+  }
+
+  // LibYUVImageProcessor supports only memory-based video frame for input.
+  VideoFrame::StorageType input_storage_type = VideoFrame::STORAGE_UNKNOWN;
+  for (auto input_type : input_config.preferred_storage_types) {
+    if (VideoFrame::IsStorageTypeMappable(input_type)) {
+      input_storage_type = input_type;
+      break;
+    }
+  }
+  if (input_storage_type == VideoFrame::STORAGE_UNKNOWN) {
+    VLOGF(2) << "Unsupported input storage type";
+    return nullptr;
+  }
+
+  // LibYUVImageProcessor supports only memory-based video frame for output.
+  VideoFrame::StorageType output_storage_type = VideoFrame::STORAGE_UNKNOWN;
+  for (auto output_type : output_config.preferred_storage_types) {
+    if (VideoFrame::IsStorageTypeMappable(output_type)) {
+      output_storage_type = output_type;
+      break;
+    }
+  }
+  if (output_storage_type == VideoFrame::STORAGE_UNKNOWN) {
+    VLOGF(2) << "Unsupported output storage type";
+    return nullptr;
+  }
+
+  if (output_mode != OutputMode::IMPORT) {
+    VLOGF(2) << "Only support OutputMode::IMPORT";
+    return nullptr;
+  }
+
+  auto processor = base::WrapUnique(new LibYUVImageProcessor(
+      input_config.layout, input_config.visible_size, input_storage_type,
+      output_config.layout, output_config.visible_size, output_storage_type,
+      std::move(error_cb)));
+  if (!processor->process_thread_.Start()) {
+    VLOGF(1) << "Failed to start processing thread";
+    return nullptr;
+  }
+
+  VLOGF(2) << "LibYUVImageProcessor created for converting from "
+           << input_config.layout << " to " << output_config.layout;
+  return processor;
+}
+
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+bool LibYUVImageProcessor::Process(
+    scoped_refptr<VideoFrame> frame,
+    int output_buffer_index,
+    std::vector<base::ScopedFD> output_dmabuf_fds,
+    FrameReadyCB cb) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  NOTIMPLEMENTED();
+  return false;
+}
+#endif
+
+bool LibYUVImageProcessor::Process(scoped_refptr<VideoFrame> input_frame,
+                                   scoped_refptr<VideoFrame> output_frame,
+                                   FrameReadyCB cb) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DVLOGF(4);
+  DCHECK_EQ(input_frame->layout().format(), input_layout_.format());
+  DCHECK(input_frame->layout().coded_size() == input_layout_.coded_size());
+  DCHECK_EQ(output_frame->layout().format(), output_layout_.format());
+  DCHECK(output_frame->layout().coded_size() == output_layout_.coded_size());
+  DCHECK(VideoFrame::IsStorageTypeMappable(input_frame->storage_type()));
+  DCHECK(VideoFrame::IsStorageTypeMappable(output_frame->storage_type()));
+  process_thread_.task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(&LibYUVImageProcessor::ProcessTask,
+                                base::Unretained(this), std::move(input_frame),
+                                std::move(output_frame), std::move(cb)));
+  return true;
+}
+
+void LibYUVImageProcessor::ProcessTask(scoped_refptr<VideoFrame> input_frame,
+                                       scoped_refptr<VideoFrame> output_frame,
+                                       FrameReadyCB cb) {
+  DCHECK(process_thread_.task_runner()->BelongsToCurrentThread());
+  DVLOGF(4);
+  int result = libyuv::I420ToNV12(input_frame->data(VideoFrame::kYPlane),
+                                  input_frame->stride(VideoFrame::kYPlane),
+                                  input_frame->data(VideoFrame::kUPlane),
+                                  input_frame->stride(VideoFrame::kUPlane),
+                                  input_frame->data(VideoFrame::kVPlane),
+                                  input_frame->stride(VideoFrame::kVPlane),
+                                  output_frame->data(VideoFrame::kYPlane),
+                                  output_frame->stride(VideoFrame::kYPlane),
+                                  output_frame->data(VideoFrame::kUVPlane),
+                                  output_frame->stride(VideoFrame::kUVPlane),
+                                  output_frame->visible_rect().width(),
+                                  output_frame->visible_rect().height());
+  if (result != 0) {
+    VLOGF(1) << "libyuv::I420ToNV12 returns non-zero code: " << result;
+    NotifyError();
+  }
+  client_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&LibYUVImageProcessor::FrameReady, weak_this_,
+                                std::move(cb), std::move(output_frame)));
+}
+
+void LibYUVImageProcessor::FrameReady(FrameReadyCB cb,
+                                      scoped_refptr<VideoFrame> frame) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  std::move(cb).Run(std::move(frame));
+}
+
+bool LibYUVImageProcessor::Reset() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  weak_this_factory_.InvalidateWeakPtrs();
+  process_thread_.Stop();
+
+  weak_this_ = weak_this_factory_.GetWeakPtr();
+  if (!process_thread_.Start()) {
+    VLOGF(1) << "process_thread_ failed to start";
+    return false;
+  }
+  return true;
+}
+
+gfx::Size LibYUVImageProcessor::input_allocated_size() const {
+  return input_layout_.coded_size();
+}
+
+gfx::Size LibYUVImageProcessor::output_allocated_size() const {
+  return output_layout_.coded_size();
+}
+
+VideoFrame::StorageType LibYUVImageProcessor::input_storage_type() const {
+  return input_storage_type_;
+}
+
+VideoFrame::StorageType LibYUVImageProcessor::output_storage_type() const {
+  return output_storage_type_;
+}
+
+ImageProcessor::OutputMode LibYUVImageProcessor::output_mode() const {
+  return OutputMode::IMPORT;
+}
+
+void LibYUVImageProcessor::NotifyError() {
+  VLOGF(1);
+  DCHECK(!client_task_runner_->BelongsToCurrentThread());
+  client_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&LibYUVImageProcessor::NotifyErrorOnClientThread,
+                     weak_this_));
+}
+
+void LibYUVImageProcessor::NotifyErrorOnClientThread() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  error_cb_.Run();
+}
+
+// static
+bool LibYUVImageProcessor::IsFormatSupported(VideoPixelFormat input_format,
+                                             VideoPixelFormat output_format) {
+  if (input_format == PIXEL_FORMAT_I420) {
+    if (output_format == PIXEL_FORMAT_NV12) {
+      return true;
+    } else {
+      VLOGF(2) << "Unsupported output format: " << output_format
+               << " for converting input format: " << input_format;
+      return false;
+    }
+  } else {
+    VLOGF(2) << "Unsupported input format: " << input_format;
+    return false;
+  }
+}
+
+}  // namespace media
diff --git a/media/gpu/libyuv_image_processor.h b/media/gpu/libyuv_image_processor.h
new file mode 100644
index 0000000..a51be70
--- /dev/null
+++ b/media/gpu/libyuv_image_processor.h
@@ -0,0 +1,130 @@
+// 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_LIBYUV_IMAGE_PROCESSOR_H_
+#define MEDIA_GPU_LIBYUV_IMAGE_PROCESSOR_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_checker.h"
+#include "build/build_config.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_frame_layout.h"
+#include "media/base/video_types.h"
+#include "media/gpu/image_processor.h"
+#include "media/gpu/media_gpu_export.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}  // namespace base
+
+namespace media {
+
+// A software image processor which uses libyuv to perform format conversion.
+// It expects input VideoFrame is mapped into CPU space, and output VideoFrame
+// is allocated in user space.
+class MEDIA_GPU_EXPORT LibYUVImageProcessor : public ImageProcessor {
+ public:
+  // ImageProcessor override
+  ~LibYUVImageProcessor() override;
+  gfx::Size input_allocated_size() const override;
+  gfx::Size output_allocated_size() const override;
+  VideoFrame::StorageType input_storage_type() const override;
+  VideoFrame::StorageType output_storage_type() const override;
+  OutputMode output_mode() const override;
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+  bool Process(scoped_refptr<VideoFrame> frame,
+               int output_buffer_index,
+               std::vector<base::ScopedFD> output_dmabuf_fds,
+               FrameReadyCB cb) override;
+#endif
+  bool Process(scoped_refptr<VideoFrame> input_frame,
+               scoped_refptr<VideoFrame> output_frame,
+               FrameReadyCB cb) override;
+  bool Reset() override;
+
+  // Factory method to create LibYUVImageProcessor to convert video format
+  // specified in input_config and output_config. Provided |error_cb| will be
+  // posted to the same thread Create() is called if an error occurs after
+  // initialization.
+  // Returns nullptr if it fails to create LibYUVImageProcessor.
+  static std::unique_ptr<LibYUVImageProcessor> Create(
+      const ImageProcessor::PortConfig& input_config,
+      const ImageProcessor::PortConfig& output_config,
+      const ImageProcessor::OutputMode output_mode,
+      ErrorCB error_cb);
+
+ private:
+  LibYUVImageProcessor(const VideoFrameLayout& input_layout,
+                       const gfx::Size& input_visible_size,
+                       VideoFrame::StorageType input_storage_type,
+                       const VideoFrameLayout& output_layout,
+                       const gfx::Size& output_visible_size,
+                       VideoFrame::StorageType output_storage_type,
+                       ErrorCB error_cb);
+
+  void ProcessTask(scoped_refptr<VideoFrame> input_frame,
+                   scoped_refptr<VideoFrame> output_frame,
+                   FrameReadyCB cb);
+
+  // A processed frame is ready.
+  void FrameReady(FrameReadyCB cb, scoped_refptr<VideoFrame> frame);
+
+  // Posts error on |client_task_runner_| thread. This must be called in a
+  // thread |client_task_runner_| doesn't belong to.
+  void NotifyError();
+  // Invokes |error_cb_|. This must be called in |client_task_runner_|'s thread.
+  void NotifyErrorOnClientThread();
+
+  static bool IsFormatSupported(VideoPixelFormat input_format,
+                                VideoPixelFormat output_format);
+
+  const VideoFrameLayout input_layout_;
+  const gfx::Rect input_visible_rect_;
+  VideoFrame::StorageType input_storage_type_;
+  const VideoFrameLayout output_layout_;
+  const gfx::Rect output_visible_rect_;
+  VideoFrame::StorageType output_storage_type_;
+
+  // Error callback to the client.
+  ErrorCB error_cb_;
+
+  // A task runner belongs to a thread where LibYUVImageProcessor is created.
+  const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner_;
+
+  // Thread to process frame format conversion.
+  base::Thread process_thread_;
+
+  // Checker for the thread |client_task_runner_| belongs to.
+  THREAD_CHECKER(thread_checker_);
+
+  // Emits weak pointer to |this| for tasks from |processor_thread_| to the
+  // thread that creates LibYUVImageProcessor. So the tasks are cancelled if
+  // |this| is invalidated, which leads to avoid calling FrameReadyCB and
+  // ErrorCB of the invalidated client (e.g. V4L2VideoEncodeAccelerator).
+  // On the other hand, since |process_thread_| is the member of this class, it
+  // is guaranteed this instance is alive when a task on the thread is executed.
+  // Therefore, base::Unretained(this) is safe for |processor_thread_| tasks
+  // posted from |client_task_runner_|'s thread.
+  // NOTE: |weak_this_| must always be dereferenced and invalidated on the
+  // thread that creates LibYUVImageProcessor.
+  base::WeakPtr<LibYUVImageProcessor> weak_this_;
+
+  // The WeakPtrFactory for |weak_this_|.
+  base::WeakPtrFactory<LibYUVImageProcessor> weak_this_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(LibYUVImageProcessor);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_LIBYUV_IMAGE_PROCESSOR_H_
diff --git a/media/gpu/v4l2/v4l2_image_processor.cc b/media/gpu/v4l2/v4l2_image_processor.cc
index 0b5e89c3..27cea3d 100644
--- a/media/gpu/v4l2/v4l2_image_processor.cc
+++ b/media/gpu/v4l2/v4l2_image_processor.cc
@@ -4,7 +4,6 @@
 
 #include <errno.h>
 #include <fcntl.h>
-#include <linux/videodev2.h>
 #include <poll.h>
 #include <string.h>
 #include <sys/eventfd.h>
@@ -144,19 +143,43 @@
 // static
 std::unique_ptr<V4L2ImageProcessor> V4L2ImageProcessor::Create(
     scoped_refptr<V4L2Device> device,
-    VideoFrame::StorageType input_storage_type,
-    VideoFrame::StorageType output_storage_type,
-    OutputMode output_mode,
-    const VideoFrameLayout& input_layout,
-    const VideoFrameLayout& output_layout,
-    gfx::Size input_visible_size,
-    gfx::Size output_visible_size,
+    const ImageProcessor::PortConfig& input_config,
+    const ImageProcessor::PortConfig& output_config,
+    const ImageProcessor::OutputMode output_mode,
     size_t num_buffers,
     ErrorCB error_cb) {
   VLOGF(2);
   DCHECK_GT(num_buffers, 0u);
   if (!device) {
-    VLOGF(1) << "Failed creating V4L2Device";
+    VLOGF(2) << "Failed creating V4L2Device";
+    return nullptr;
+  }
+
+  // V4L2ImageProcessor supports either DmaBuf-backed or memory-based video
+  // frame for input.
+  VideoFrame::StorageType input_storage_type = VideoFrame::STORAGE_UNKNOWN;
+  for (auto input_type : input_config.preferred_storage_types) {
+    if (input_type == VideoFrame::STORAGE_DMABUFS ||
+        VideoFrame::IsStorageTypeMappable(input_type)) {
+      input_storage_type = input_type;
+      break;
+    }
+  }
+  if (input_storage_type == VideoFrame::STORAGE_UNKNOWN) {
+    VLOGF(2) << "Unsupported input storage type";
+    return nullptr;
+  }
+
+  // V4L2ImageProcessor only supports DmaBuf-backed video frame for output.
+  VideoFrame::StorageType output_storage_type = VideoFrame::STORAGE_UNKNOWN;
+  for (auto output_type : output_config.preferred_storage_types) {
+    if (output_type == VideoFrame::STORAGE_DMABUFS) {
+      output_storage_type = output_type;
+      break;
+    }
+  }
+  if (output_storage_type == VideoFrame::STORAGE_UNKNOWN) {
+    VLOGF(2) << "Unsupported output storage type";
     return nullptr;
   }
 
@@ -167,12 +190,6 @@
     return nullptr;
   }
 
-  // Note that for v4l2 IP, output storage type must be STORAGE_DMABUFS.
-  // And output_memory_type depends on its output mode.
-  if (output_storage_type != VideoFrame::STORAGE_DMABUFS) {
-    VLOGF(1) << "Unsupported output storage type: " << output_storage_type;
-    return nullptr;
-  }
   const v4l2_memory output_memory_type =
       output_mode == ImageProcessor::OutputMode::ALLOCATE ? V4L2_MEMORY_MMAP
                                                           : V4L2_MEMORY_DMABUF;
@@ -181,6 +198,8 @@
     VLOGF(1) << "V4L2ImageProcessor not supported in this platform";
     return nullptr;
   }
+
+  const VideoFrameLayout& input_layout = input_config.layout;
   const uint32_t input_format_fourcc =
       V4L2Device::VideoFrameLayoutToV4L2PixFmt(input_layout);
   if (!input_format_fourcc) {
@@ -216,14 +235,15 @@
   DCHECK_LE(negotiated_input_layout->num_buffers(),
             static_cast<size_t>(VIDEO_MAX_PLANES));
   if (!gfx::Rect(negotiated_input_layout->coded_size())
-      .Contains(gfx::Rect(input_visible_size))) {
+           .Contains(gfx::Rect(input_config.visible_size))) {
     VLOGF(1) << "Negotiated input allocated size: "
              << negotiated_input_layout->coded_size().ToString()
              << " should contain visible size: "
-             << input_visible_size.ToString();
+             << input_config.visible_size.ToString();
     return nullptr;
   }
 
+  const VideoFrameLayout& output_layout = output_config.layout;
   const uint32_t output_format_fourcc =
       V4L2Device::VideoFrameLayoutToV4L2PixFmt(output_layout);
   if (!output_format_fourcc) {
@@ -256,20 +276,20 @@
   DCHECK_LE(negotiated_output_layout->num_buffers(),
             static_cast<size_t>(VIDEO_MAX_PLANES));
   if (!gfx::Rect(negotiated_output_layout->coded_size())
-      .Contains(gfx::Rect(output_layout.coded_size()))) {
+           .Contains(gfx::Rect(output_layout.coded_size()))) {
     VLOGF(1) << "Negotiated output allocated size: "
              << negotiated_output_layout->coded_size().ToString()
              << " should contain original output allocated size: "
              << output_layout.coded_size().ToString();
     return nullptr;
-
   }
 
   auto processor = base::WrapUnique(new V4L2ImageProcessor(
       std::move(device), input_storage_type, output_storage_type,
       input_memory_type, output_memory_type, output_mode,
-      *negotiated_input_layout, *negotiated_output_layout, input_visible_size,
-      output_visible_size, num_buffers, std::move(error_cb)));
+      *negotiated_input_layout, *negotiated_output_layout,
+      input_config.visible_size, output_config.visible_size, num_buffers,
+      std::move(error_cb)));
   if (!processor->Initialize()) {
     VLOGF(1) << "Failed to initialize V4L2ImageProcessor";
     return nullptr;
@@ -437,6 +457,13 @@
   return true;
 }
 
+bool V4L2ImageProcessor::Process(scoped_refptr<VideoFrame> input_frame,
+                                 scoped_refptr<VideoFrame> output_frame,
+                                 FrameReadyCB cb) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
 void V4L2ImageProcessor::ProcessTask(std::unique_ptr<JobRecord> job_record) {
   DVLOGF(4) << "Reusing output buffer, index="
             << job_record->output_buffer_index;
diff --git a/media/gpu/v4l2/v4l2_image_processor.h b/media/gpu/v4l2/v4l2_image_processor.h
index cf89bb4..4b6d09e 100644
--- a/media/gpu/v4l2/v4l2_image_processor.h
+++ b/media/gpu/v4l2/v4l2_image_processor.h
@@ -13,9 +13,11 @@
 
 #include <linux/videodev2.h>
 
+#include "base/callback_forward.h"
 #include "base/containers/queue.h"
+#include "base/files/scoped_file.h"
 #include "base/macros.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread.h"
 #include "media/base/video_frame.h"
@@ -23,6 +25,7 @@
 #include "media/gpu/image_processor.h"
 #include "media/gpu/media_gpu_export.h"
 #include "media/gpu/v4l2/v4l2_device.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace media {
 
@@ -42,9 +45,11 @@
                int output_buffer_index,
                std::vector<base::ScopedFD> output_dmabuf_fds,
                FrameReadyCB cb) override;
+  bool Process(scoped_refptr<VideoFrame> input_frame,
+               scoped_refptr<VideoFrame> output_frame,
+               FrameReadyCB cb) override;
   bool Reset() override;
 
-
   // Returns true if image processing is supported on this platform.
   static bool IsSupported();
 
@@ -64,21 +69,19 @@
                               size_t* num_planes);
 
   // Factory method to create V4L2ImageProcessor to convert from
-  // input_format to output_format. Caller shall provide input and output
-  // storage type as well as output mode. The number of input buffers and output
+  // input_config to output_config. The number of input buffers and output
   // buffers will be |num_buffers|. Provided |error_cb| will be posted to the
   // same thread Create() is called if an error occurs after initialization.
   // Returns nullptr if V4L2ImageProcessor fails to create.
   // Note: output_mode will be removed once all its clients use import mode.
+  // TODO(crbug.com/917798): remove |device| parameter once
+  //     V4L2VideoDecodeAccelerator no longer creates and uses
+  //     |image_processor_device_| before V4L2ImageProcessor is created.
   static std::unique_ptr<V4L2ImageProcessor> Create(
       scoped_refptr<V4L2Device> device,
-      VideoFrame::StorageType input_storage_type,
-      VideoFrame::StorageType output_storage_type,
-      OutputMode output_mode,
-      const VideoFrameLayout& input_layout,
-      const VideoFrameLayout& output_layout,
-      gfx::Size input_visible_size,
-      gfx::Size output_visible_size,
+      const ImageProcessor::PortConfig& input_config,
+      const ImageProcessor::PortConfig& output_config,
+      const ImageProcessor::OutputMode output_mode,
       size_t num_buffers,
       ErrorCB error_cb);
 
@@ -146,8 +149,7 @@
   // Posts error on |client_task_runner_| thread. This must be called in a
   // thread |client_task_runner_| doesn't belong to.
   void NotifyError();
-  // Invokes ErrorCB given by factory method. This must be called in
-  // |client_task_runner_|'s thread.
+  // Invokes |erro_cb_|. This must be called in |client_task_runner_|'s thread.
   void NotifyErrorOnClientThread();
 
   void ProcessTask(std::unique_ptr<JobRecord> job_record);
@@ -180,8 +182,7 @@
   const VideoFrame::StorageType output_storage_type_;
   const OutputMode output_mode_;
 
-  // The task runner which belongs to the thread where V4L2ImageProcessor is
-  // created.
+  // A task runner belongs to a thread where V4L2ImageProcessor is created.
   const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner_;
 
   // V4L2 device in use.
@@ -218,17 +219,19 @@
   // Error callback to the client.
   ErrorCB error_cb_;
 
-  // WeakPtr<> pointing to |this| for use in posting tasks from the device
-  // worker threads back to the the thread where V4L2ImageProcessor is created.
-  // Because the worker threads are members of this class, any task running on
-  // those threads is guaranteed that this object is still alive.  As a result,
-  // tasks posted from |client_task_runner_|'s thread to the device thread
-  // should use base::Unretained(this), and tasks posted the other way should
-  // use |weak_this_|.
+  // Emits weak pointer to |this| for tasks from |processor_thread_| to the
+  // thread that creates V4L2ImageProcessor. So the tasks are cancelled if
+  // |this| is invalidated, which leads to avoid calling FrameReadyCB and
+  // ErrorCB of the invalidated client (e.g. V4L2VideoEncodeAccelerator).
+  // On the other hand, since |device_thread_| is the member of this class, it
+  // is guaranteed this instance is alive when a task on the thread is executed.
+  // Therefore, base::Unretained(this) is safe for |device_thread_| tasks
+  // posted from |client_task_runner_|'s thread.
+  // NOTE: |weak_this_| must always be dereferenced and invalidated on the
+  // thread that creates V4L2ImageProcessor.
   base::WeakPtr<V4L2ImageProcessor> weak_this_;
 
-  // Weak factory for producing weak pointers on the |client_task_runner_|'s
-  // thread.
+  // The WeakPtrFactory for |weak_this_|.
   base::WeakPtrFactory<V4L2ImageProcessor> weak_this_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(V4L2ImageProcessor);
diff --git a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
index d8543ad..719f495 100644
--- a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
@@ -29,6 +29,7 @@
 #include "media/base/unaligned_shared_memory.h"
 #include "media/base/video_frame_layout.h"
 #include "media/base/video_types.h"
+#include "media/gpu/image_processor_factory.h"
 #include "media/gpu/macros.h"
 #include "media/gpu/v4l2/v4l2_image_processor.h"
 #include "media/video/h264_parser.h"
@@ -2392,15 +2393,19 @@
     return false;
   }
 
-  // Unretained(this) is safe in creating ErrorCB because |image_processor_|
-  // is destructed by Destroy(), which posts DestroyTask() to |decoder_thread_|,
-  // which is the same thread ErrorCB being called. In DestroyTask(), it
-  // destructs |image_processor_| so no more ErrorCB is invoked after
-  // DestroyTask() is called.
+  // Unretained(this) is safe in creating ErrorCB because
+  // V4L2VideoDecodeAccelerator instance outlives |image_processor_| and
+  // ImageProcessor invalidates posted ErrorCB when its Reset() or destructor is
+  // called.
+  // TODO(crbug.com/917798): Use ImageProcessorFactory::Create() once we remove
+  //     |image_processor_device_| from V4L2VideoDecodeAccelerator.
   image_processor_ = V4L2ImageProcessor::Create(
-      image_processor_device_, VideoFrame::STORAGE_DMABUFS,
-      VideoFrame::STORAGE_DMABUFS, image_processor_output_mode, *input_layout,
-      *output_layout, visible_size_, visible_size_, output_buffer_map_.size(),
+      image_processor_device_,
+      ImageProcessor::PortConfig(*input_layout, visible_size_,
+                                 {VideoFrame::STORAGE_DMABUFS}),
+      ImageProcessor::PortConfig(*output_layout, visible_size_,
+                                 {VideoFrame::STORAGE_DMABUFS}),
+      image_processor_output_mode, output_buffer_map_.size(),
       base::BindRepeating(&V4L2VideoDecodeAccelerator::ImageProcessorError,
                           base::Unretained(this)));
 
@@ -2455,12 +2460,9 @@
       return false;
   }
   // Unretained(this) is safe in creating FrameReadyCB because
-  // |image_processor_| is destructed by Destroy(), which posts DestroyTask() to
-  // |decoder_thread_|, which is the same thread ErrorCB being called. In
-  // DestroyTask(), it destructs |image_processor_| so no more ErrorCB is
-  // invoked after DestroyTask() is called. Unretained is safe because |this|
-  // owns image processor and there will be no callbacks after processor
-  // destroys.
+  // V4L2VideoDecodeAccelerator instance outlives |image_processor_| and
+  // ImageProcessor invalidates posted FrameReadyCB when its Reset() or
+  // destructor is called.
   image_processor_->Process(
       input_frame, output_buffer_index, std::move(output_fds),
       base::BindOnce(&V4L2VideoDecodeAccelerator::FrameProcessed,
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
index 8f8a018..281fd9c9 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -12,6 +12,7 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 
+#include <numeric>
 #include <utility>
 
 #include "base/callback.h"
@@ -28,8 +29,8 @@
 #include "media/base/video_frame_layout.h"
 #include "media/base/video_types.h"
 #include "media/gpu/gpu_video_encode_accelerator_helpers.h"
+#include "media/gpu/image_processor_factory.h"
 #include "media/gpu/macros.h"
-#include "media/gpu/v4l2/v4l2_image_processor.h"
 #include "media/video/h264_parser.h"
 
 #define NOTIFY_ERROR(x)                      \
@@ -201,11 +202,6 @@
              << "by the HW. Will try to convert to "
              << device_input_layout_->format();
 
-    if (!V4L2ImageProcessor::IsSupported()) {
-      VLOGF(1) << "Image processor not available";
-      return false;
-    }
-
     // It is necessary to set strides and buffers even with dummy values,
     // because VideoFrameLayout::num_buffers() specifies v4l2 pix format
     // associated with |config.input_format| is multi-planar.
@@ -223,19 +219,24 @@
     // Convert from |config.input_format| to |device_input_layout_->format()|,
     // keeping the size at |visible_size_| and requiring the output buffers to
     // be of at least |device_input_layout_->coded_size()|.
-    // Unretained(this) is safe in creating ErrorCB because |image_processor_|
-    // is destructed by Destroy() and Destroy() is posted in child_task_runner_,
-    // which is the same thread ErrorCB being called. So after Destroy() is
-    // called, no more ErrorCB will be invoked.
-    // |input_storage_type| can be STORAGE_SHMEM and
-    // STORAGE_MOJO_SHARED_BUFFER. However, it doesn't matter
-    // VideoFrame::STORAGE_OWNED_MEMORY is specified for |input_storage_type|
-    // here, as long as VideoFrame on Process()'s data can be accessed by
-    // VideoFrame::data().
-    image_processor_ = V4L2ImageProcessor::Create(
-        V4L2Device::Create(), VideoFrame::STORAGE_OWNED_MEMORY,
-        VideoFrame::STORAGE_DMABUFS, ImageProcessor::OutputMode::ALLOCATE,
-        *input_layout, *device_input_layout_, visible_size_, visible_size_,
+    // Unretained(this) is safe in creating ErrorCB because
+    // V4L2VideoEncodeAccelerator instance outlives |image_processor_| and
+    // ImageProcessor invalidates posted ErrorCB when its Reset() or destructor
+    // is called.
+    // |input_storage_type| can be STORAGE_SHMEM and STORAGE_MOJO_SHARED_BUFFER.
+    // However, it doesn't matter VideoFrame::STORAGE_OWNED_MEMORY is specified
+    // for |input_storage_type| here, as long as VideoFrame on Process()'s data
+    // can be accessed by VideoFrame::data().
+    image_processor_ = ImageProcessorFactory::Create(
+        ImageProcessor::PortConfig(*input_layout, visible_size_,
+                                   {VideoFrame::STORAGE_OWNED_MEMORY}),
+        ImageProcessor::PortConfig(
+            *device_input_layout_, visible_size_,
+            {VideoFrame::STORAGE_DMABUFS, VideoFrame::STORAGE_OWNED_MEMORY}),
+        // Try OutputMode::ALLOCATE first because we want v4l2IP chooses
+        // ALLOCATE mode. For libyuvIP, it accepts only IMPORT.
+        {ImageProcessor::OutputMode::ALLOCATE,
+         ImageProcessor::OutputMode::IMPORT},
         kImageProcBufferCount,
         base::BindRepeating(&V4L2VideoEncodeAccelerator::ImageProcessorError,
                             base::Unretained(this)));
@@ -259,29 +260,24 @@
       return false;
     }
 
-    for (int i = 0; i < kImageProcBufferCount; i++)
-      free_image_processor_output_buffers_.push_back(i);
+    // Initialize |free_image_processor_output_buffer_indices_|.
+    free_image_processor_output_buffer_indices_.resize(kImageProcBufferCount);
+    std::iota(free_image_processor_output_buffer_indices_.begin(),
+              free_image_processor_output_buffer_indices_.end(), 0);
+
+    if (!AllocateImageProcessorOutputBuffers())
+      return false;
   }
 
+  if (!InitInputMemoryType(config))
+    return false;
+
   if (!InitControls(config))
     return false;
 
   if (!CreateOutputBuffers())
     return false;
 
-  if (!image_processor_) {
-    switch (config.storage_type.value_or(Config::StorageType::kShmem)) {
-      case Config::StorageType::kShmem:
-        input_memory_type_ = V4L2_MEMORY_USERPTR;
-        break;
-      case Config::StorageType::kDmabuf:
-        input_memory_type_ = V4L2_MEMORY_DMABUF;
-        break;
-    }
-  } else {
-    input_memory_type_ = V4L2_MEMORY_DMABUF;
-  }
-
   if (!encoder_thread_.Start()) {
     VLOGF(1) << "encoder thread failed to start";
     return false;
@@ -303,6 +299,61 @@
   return true;
 }
 
+bool V4L2VideoEncodeAccelerator::AllocateImageProcessorOutputBuffers() {
+  DCHECK(image_processor_);
+  // Allocate VideoFrames for image processor output if its mode is IMPORT.
+  if (image_processor_->output_mode() != ImageProcessor::OutputMode::IMPORT) {
+    return true;
+  }
+
+  image_processor_output_buffers_.resize(kImageProcBufferCount);
+  const auto output_storage_type = image_processor_->output_storage_type();
+  for (size_t i = 0; i < kImageProcBufferCount; i++) {
+    switch (output_storage_type) {
+      case VideoFrame::STORAGE_OWNED_MEMORY:
+        image_processor_output_buffers_[i] = VideoFrame::CreateFrameWithLayout(
+            *device_input_layout_, gfx::Rect(visible_size_), visible_size_,
+            base::TimeDelta(), true);
+        if (!image_processor_output_buffers_[i]) {
+          VLOG(1) << "Failed to create VideoFrame";
+          return false;
+        }
+        break;
+      // TODO(crbug.com/910590): Support VideoFrame::STORAGE_DMABUFS.
+      default:
+        VLOGF(1) << "Unsupported output storage type of image processor: "
+                 << output_storage_type;
+        return false;
+    }
+  }
+  return true;
+}
+
+bool V4L2VideoEncodeAccelerator::InitInputMemoryType(const Config& config) {
+  if (image_processor_) {
+    const auto storage_type = image_processor_->output_storage_type();
+    if (storage_type == VideoFrame::STORAGE_DMABUFS) {
+      input_memory_type_ = V4L2_MEMORY_DMABUF;
+    } else if (VideoFrame::IsStorageTypeMappable(storage_type)) {
+      input_memory_type_ = V4L2_MEMORY_USERPTR;
+    } else {
+      VLOGF(1) << "Unsupported image processor's output StorageType: "
+               << storage_type;
+      return false;
+    }
+  } else {
+    switch (config.storage_type.value_or(Config::StorageType::kShmem)) {
+      case Config::StorageType::kShmem:
+        input_memory_type_ = V4L2_MEMORY_USERPTR;
+        break;
+      case Config::StorageType::kDmabuf:
+        input_memory_type_ = V4L2_MEMORY_DMABUF;
+        break;
+    }
+  }
+  return true;
+}
+
 void V4L2VideoEncodeAccelerator::ImageProcessorError() {
   VLOGF(1) << "Image processor error";
   NOTIFY_ERROR(kPlatformFailureError);
@@ -314,20 +365,41 @@
   DCHECK(child_task_runner_->BelongsToCurrentThread());
 
   if (image_processor_) {
-    if (free_image_processor_output_buffers_.size() > 0) {
-      int output_buffer_index = free_image_processor_output_buffers_.back();
-      free_image_processor_output_buffers_.pop_back();
-      // Unretained(this) is safe in creating FrameReadyCB because
-      // |image_processor_| is destructed by Destroy() and Destroy() is posted
-      // in child_task_runner_, which is the same thread FrameReadyCB being
-      // called. So after Destroy() is called, no more FrameReadyCB will be
-      // invoked.
-      if (!image_processor_->Process(
-              frame, output_buffer_index, std::vector<base::ScopedFD>(),
-              base::BindOnce(&V4L2VideoEncodeAccelerator::FrameProcessed,
-                             base::Unretained(this), force_keyframe,
-                             frame->timestamp(), output_buffer_index))) {
-        NOTIFY_ERROR(kPlatformFailureError);
+    if (!free_image_processor_output_buffer_indices_.empty()) {
+      // Create a VideoFrame by wrapping an instance from
+      // |image_processor_output_buffers_|. The new VideoFrame has its own life
+      // cycle but shares underlying payload from the VideoFrame being wrapped.
+      // When the VideoEncodeAccelerator finish processing ImageProcessor's
+      // output frame, the frame is no longer referenced, hence trigger
+      // destruction observer to recycle the frame.
+      const size_t output_buffer_index =
+          free_image_processor_output_buffer_indices_.back();
+      free_image_processor_output_buffer_indices_.pop_back();
+      if (image_processor_->output_mode() ==
+          ImageProcessor::OutputMode::IMPORT) {
+        const auto& buf = image_processor_output_buffers_[output_buffer_index];
+        auto output_frame = VideoFrame::WrapVideoFrame(
+            buf, buf->format(), buf->visible_rect(), buf->natural_size());
+
+        // Unretained(this) is safe in creating FrameReadyCB because
+        // V4L2VideoEncodeAccelerator instance outlives |image_processor_| and
+        // ImageProcessor invalidates posted FrameReadyCB when its Reset() or
+        // destructor is called.
+        if (!image_processor_->Process(
+                frame, std::move(output_frame),
+                base::BindOnce(&V4L2VideoEncodeAccelerator::FrameProcessed,
+                               base::Unretained(this), force_keyframe,
+                               frame->timestamp(), output_buffer_index))) {
+          NOTIFY_ERROR(kPlatformFailureError);
+        }
+      } else {
+        if (!image_processor_->Process(
+                frame, output_buffer_index, std::vector<base::ScopedFD>(),
+                base::BindOnce(&V4L2VideoEncodeAccelerator::FrameProcessed,
+                               base::Unretained(this), force_keyframe,
+                               frame->timestamp(), output_buffer_index))) {
+          NOTIFY_ERROR(kPlatformFailureError);
+        }
       }
     } else {
       image_processor_input_queue_.emplace(frame, force_keyframe);
@@ -426,7 +498,7 @@
 
   if (flush_callback_ || encoder_state_ != kEncoding) {
     VLOGF(1) << "Flush failed: there is a pending flush, "
-             << "or VEA is not in kEncoding state";
+             << "or VideoEncodeAccelerator is not in kEncoding state";
     NOTIFY_ERROR(kIllegalStateError);
     child_task_runner_->PostTask(
         FROM_HERE, base::BindOnce(std::move(flush_callback), false));
@@ -473,7 +545,7 @@
     int output_buffer_index) {
   DCHECK(child_task_runner_->BelongsToCurrentThread());
   DVLOGF(4) << "output_buffer_index=" << output_buffer_index;
-  free_image_processor_output_buffers_.push_back(output_buffer_index);
+  free_image_processor_output_buffer_indices_.push_back(output_buffer_index);
   if (!image_processor_input_queue_.empty()) {
     InputFrameInfo frame_info = image_processor_input_queue_.front();
     image_processor_input_queue_.pop();
@@ -868,7 +940,7 @@
 
     switch (input_memory_type_) {
       case V4L2_MEMORY_USERPTR:
-        // Use buffer_size VEA HW requested by S_FMT.
+        // Use buffer_size VideoEncodeAccelerator HW requested by S_FMT.
         qbuf.m.planes[i].length = device_input_layout_->buffer_sizes()[i];
         qbuf.m.planes[i].m.userptr =
             reinterpret_cast<unsigned long>(frame->data(i));
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.h b/media/gpu/v4l2/v4l2_video_encode_accelerator.h
index 4d24233..658c941 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.h
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.h
@@ -213,6 +213,10 @@
   // false otherwise.
   bool IsCtrlExposed(uint32_t ctrl_id);
 
+  // Allocates video frames for image processor's output buffers.
+  // Returns false if there's something wrong.
+  bool AllocateImageProcessorOutputBuffers();
+
   // Recycle output buffer of image processor with |output_buffer_index|.
   void ReuseImageProcessorOutputBuffer(int output_buffer_index);
 
@@ -224,6 +228,9 @@
                               size_t bitstream_size,
                               std::unique_ptr<BitstreamBufferRef> buffer_ref);
 
+  // Initializes input_memory_type_.
+  bool InitInputMemoryType(const Config& config);
+
   // Our original calling task runner for the child thread.
   const scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_;
 
@@ -294,14 +301,18 @@
 
   // Image processor, if one is in use.
   std::unique_ptr<ImageProcessor> image_processor_;
+  // Video frames for image processor output / VideoEncodeAccelerator input.
+  // Only accessed on child thread.
+  std::vector<scoped_refptr<VideoFrame>> image_processor_output_buffers_;
   // Indexes of free image processor output buffers. Only accessed on child
   // thread.
-  std::vector<int> free_image_processor_output_buffers_;
+  std::vector<size_t> free_image_processor_output_buffer_indices_;
   // Video frames ready to be processed. Only accessed on child thread.
   base::queue<InputFrameInfo> image_processor_input_queue_;
 
-  // This thread services tasks posted from the VEA API entry points by the
-  // child thread and device service callbacks posted from the device thread.
+  // This thread services tasks posted from the VideoEncodeAccelerator API entry
+  // points by the child thread and device service callbacks posted from the
+  // device thread.
   base::Thread encoder_thread_;
 
   // The device polling thread handles notifications of V4L2 device changes.
diff --git a/media/learning/common/learning_task.cc b/media/learning/common/learning_task.cc
index acc339b..07cc407 100644
--- a/media/learning/common/learning_task.cc
+++ b/media/learning/common/learning_task.cc
@@ -8,7 +8,19 @@
 namespace learning {
 
 LearningTask::LearningTask() = default;
+
+LearningTask::LearningTask(
+    const std::string& name,
+    Model model,
+    std::initializer_list<ValueDescription> feature_init_list,
+    ValueDescription target_description)
+    : name(name),
+      model(model),
+      feature_descriptions(std::move(feature_init_list)),
+      target_description(target_description) {}
+
 LearningTask::LearningTask(const LearningTask&) = default;
+
 LearningTask::~LearningTask() = default;
 
 }  // namespace learning
diff --git a/media/learning/impl/BUILD.gn b/media/learning/impl/BUILD.gn
index 5227bb23..777da95 100644
--- a/media/learning/impl/BUILD.gn
+++ b/media/learning/impl/BUILD.gn
@@ -13,6 +13,8 @@
     "learning_task_controller_impl.cc",
     "learning_task_controller_impl.h",
     "model.h",
+    "one_hot.cc",
+    "one_hot.h",
     "random_forest.cc",
     "random_forest.h",
     "random_forest_trainer.cc",
@@ -45,6 +47,7 @@
     "fisher_iris_dataset.h",
     "learning_session_impl_unittest.cc",
     "learning_task_controller_impl_unittest.cc",
+    "one_hot_unittest.cc",
     "random_forest_trainer_unittest.cc",
     "random_number_generator_unittest.cc",
     "random_tree_trainer_unittest.cc",
diff --git a/media/learning/impl/one_hot.cc b/media/learning/impl/one_hot.cc
new file mode 100644
index 0000000..1b16c02
--- /dev/null
+++ b/media/learning/impl/one_hot.cc
@@ -0,0 +1,119 @@
+// 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/learning/impl/one_hot.h"
+
+#include <set>
+
+namespace media {
+namespace learning {
+
+OneHotConverter::OneHotConverter(const LearningTask& task,
+                                 const TrainingData& training_data)
+    : converted_task_(task) {
+  converted_task_.feature_descriptions.clear();
+
+  // store
+  converters_.resize(task.feature_descriptions.size());
+
+  for (size_t i = 0; i < task.feature_descriptions.size(); i++) {
+    const LearningTask::ValueDescription& feature =
+        task.feature_descriptions[i];
+
+    // If this is already a numeric feature, then we will copy it since
+    // converters[i] will be unset.
+    if (feature.ordering == LearningTask::Ordering::kNumeric) {
+      converted_task_.feature_descriptions.push_back(feature);
+      continue;
+    }
+
+    ProcessOneFeature(i, feature, training_data);
+  }
+}
+
+OneHotConverter::~OneHotConverter() = default;
+
+TrainingData OneHotConverter::Convert(const TrainingData& training_data) const {
+  TrainingData converted_training_data;
+  for (auto& example : training_data) {
+    TrainingExample converted_example(example);
+    converted_example.features = Convert(example.features);
+    converted_training_data.push_back(converted_example);
+  }
+
+  return converted_training_data;
+}
+
+FeatureVector OneHotConverter::Convert(
+    const FeatureVector& feature_vector) const {
+  FeatureVector converted_feature_vector;
+  converted_feature_vector.reserve(converted_task_.feature_descriptions.size());
+  for (size_t i = 0; i < converters_.size(); i++) {
+    auto& converter = converters_[i];
+    if (!converter) {
+      // There's no conversion needed for this feature, since it was numeric.
+      converted_feature_vector.push_back(feature_vector[i]);
+      continue;
+    }
+
+    // Convert this feature to a one-hot vector.
+    const size_t vector_size = converter->size();
+
+    // Start with a zero-hot vector.  Is that a thing?
+    for (size_t v = 0; v < vector_size; v++)
+      converted_feature_vector.push_back(FeatureValue(0));
+
+    // Set the appropriate entry to 1, if any.  Otherwise, this is a
+    // previously unseen value and all of them should be zero.
+    auto iter = converter->find(feature_vector[i]);
+    if (iter != converter->end())
+      converted_feature_vector[iter->second] = FeatureValue(1);
+  }
+
+  return converted_feature_vector;
+}
+
+void OneHotConverter::ProcessOneFeature(
+    size_t index,
+    const LearningTask::ValueDescription& original_description,
+    const TrainingData& training_data) {
+  // Collect all the distinct values for |index|.
+  std::set<Value> values;
+  for (auto& example : training_data)
+    values.insert(example.features[index]);
+
+  // We let the set's ordering be the one-hot value.  It doesn't really matter
+  // as long as we don't change it once we pick it.
+  ValueVectorIndexMap value_map;
+  // Vector index that should be set to one for each distinct value.  This will
+  // start at the next feature in the adjusted task.
+  size_t next_vector_index = converted_task_.feature_descriptions.size();
+
+  // Add one feature for each value, and construct a map from value to the
+  // feature index that should be 1 when the feature takes that value.
+  for (auto& value : values) {
+    LearningTask::ValueDescription adjusted_description = original_description;
+    adjusted_description.ordering = LearningTask::Ordering::kNumeric;
+    converted_task_.feature_descriptions.push_back(adjusted_description);
+    // |value| will converted into a 1 in the |next_vector_index|-th feature.
+    value_map[value] = next_vector_index++;
+  }
+
+  // Record |values| for the |index|-th original feature.
+  converters_[index] = std::move(value_map);
+}
+
+ConvertingModel::ConvertingModel(std::unique_ptr<OneHotConverter> converter,
+                                 std::unique_ptr<Model> model)
+    : converter_(std::move(converter)), model_(std::move(model)) {}
+ConvertingModel::~ConvertingModel() = default;
+
+TargetDistribution ConvertingModel::PredictDistribution(
+    const FeatureVector& instance) {
+  FeatureVector converted_instance = converter_->Convert(instance);
+  return model_->PredictDistribution(converted_instance);
+}
+
+}  // namespace learning
+}  // namespace media
diff --git a/media/learning/impl/one_hot.h b/media/learning/impl/one_hot.h
new file mode 100644
index 0000000..897efcf
--- /dev/null
+++ b/media/learning/impl/one_hot.h
@@ -0,0 +1,83 @@
+// 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_LEARNING_IMPL_ONE_HOT_H_
+#define MEDIA_LEARNING_IMPL_ONE_HOT_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "media/learning/common/learning_task.h"
+#include "media/learning/common/training_example.h"
+#include "media/learning/common/value.h"
+#include "media/learning/impl/model.h"
+
+namespace media {
+namespace learning {
+
+// Converter class that memorizes a mapping from nominal features to numeric
+// features with a one-hot encoding.
+class COMPONENT_EXPORT(LEARNING_IMPL) OneHotConverter {
+ public:
+  // Build a one-hot converter for all nominal features |task|, using the values
+  // found in |training_data|.
+  OneHotConverter(const LearningTask& task, const TrainingData& training_data);
+  ~OneHotConverter();
+
+  // Return the LearningTask that has only nominal features.
+  const LearningTask& converted_task() const { return converted_task_; }
+
+  // Convert |training_data| to be a one-hot model.
+  TrainingData Convert(const TrainingData& training_data) const;
+
+  // Convert |feature_vector| to match the one-hot model.
+  FeatureVector Convert(const FeatureVector& feature_vector) const;
+
+ private:
+  // Build a converter for original feature |index|.
+  void ProcessOneFeature(
+      size_t index,
+      const LearningTask::ValueDescription& original_description,
+      const TrainingData& training_data);
+
+  // Learning task with the feature descriptions adjusted for the one-hot model.
+  LearningTask converted_task_;
+
+  // [value] == vector index that should be 1 in the one-hot vector.
+  using ValueVectorIndexMap = std::map<Value, size_t>;
+
+  // [original task feature index] = optional converter for it.  If the feature
+  // was kNumeric to begin with, then there will be no converter.
+  std::vector<base::Optional<ValueVectorIndexMap>> converters_;
+
+  DISALLOW_COPY_AND_ASSIGN(OneHotConverter);
+};
+
+// Model that uses |Converter| to convert instances before sending them to the
+// underlying model.
+class COMPONENT_EXPORT(LEARNING_IMPL) ConvertingModel : public Model {
+ public:
+  ConvertingModel(std::unique_ptr<OneHotConverter> converter,
+                  std::unique_ptr<Model> model);
+  ~ConvertingModel() override;
+
+  // Model
+  TargetDistribution PredictDistribution(
+      const FeatureVector& instance) override;
+
+ private:
+  std::unique_ptr<OneHotConverter> converter_;
+  std::unique_ptr<Model> model_;
+
+  DISALLOW_COPY_AND_ASSIGN(ConvertingModel);
+};
+
+}  // namespace learning
+}  // namespace media
+
+#endif  // MEDIA_LEARNING_IMPL_ONE_HOT_H_
diff --git a/media/learning/impl/one_hot_unittest.cc b/media/learning/impl/one_hot_unittest.cc
new file mode 100644
index 0000000..3584696
--- /dev/null
+++ b/media/learning/impl/one_hot_unittest.cc
@@ -0,0 +1,118 @@
+// 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/learning/impl/one_hot.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+namespace learning {
+
+class OneHotTest : public testing::Test {
+ public:
+  OneHotTest() {}
+};
+
+TEST_F(OneHotTest, EmptyLearningTaskWorks) {
+  LearningTask empty_task("EmptyTask", LearningTask::Model::kRandomForest, {},
+                          LearningTask::ValueDescription({"target"}));
+  TrainingData empty_training_data;
+  OneHotConverter one_hot(empty_task, empty_training_data);
+  EXPECT_EQ(one_hot.converted_task().feature_descriptions.size(), 0u);
+}
+
+TEST_F(OneHotTest, SimpleConversionWorks) {
+  LearningTask task("SimpleTask", LearningTask::Model::kRandomForest,
+                    {{"feature1", LearningTask::Ordering::kUnordered}},
+                    LearningTask::ValueDescription({"target"}));
+  TrainingData training_data;
+  training_data.push_back({{FeatureValue("abc")}, TargetValue(0)});
+  training_data.push_back({{FeatureValue("def")}, TargetValue(1)});
+  training_data.push_back({{FeatureValue("ghi")}, TargetValue(2)});
+  // Push a duplicate as the last one.
+  training_data.push_back({{FeatureValue("def")}, TargetValue(3)});
+  OneHotConverter one_hot(task, training_data);
+  // There should be one feature for each distinct value in features[0].
+  const size_t adjusted_feature_size = 3u;
+  EXPECT_EQ(one_hot.converted_task().feature_descriptions.size(),
+            adjusted_feature_size);
+  EXPECT_EQ(one_hot.converted_task().feature_descriptions[0].ordering,
+            LearningTask::Ordering::kNumeric);
+  EXPECT_EQ(one_hot.converted_task().feature_descriptions[1].ordering,
+            LearningTask::Ordering::kNumeric);
+  EXPECT_EQ(one_hot.converted_task().feature_descriptions[2].ordering,
+            LearningTask::Ordering::kNumeric);
+
+  TrainingData converted_training_data = one_hot.Convert(training_data);
+  EXPECT_EQ(converted_training_data.size(), training_data.size());
+  // Exactly one feature should be 1.
+  for (size_t i = 0; i < converted_training_data.size(); i++) {
+    EXPECT_EQ(converted_training_data[i].features[0].value() +
+                  converted_training_data[i].features[1].value() +
+                  converted_training_data[i].features[2].value(),
+              1);
+  }
+
+  // Each of the first three training examples should have distinct vectors.
+  for (size_t f = 0; f < adjusted_feature_size; f++) {
+    int num_ones = 0;
+    // 3u is the number of distinct examples.  [3] is a duplicate.
+    for (size_t i = 0; i < 3u; i++)
+      num_ones += converted_training_data[i].features[f].value();
+    EXPECT_EQ(num_ones, 1);
+  }
+
+  // The features of examples 1 and 3 should be the same.
+  for (size_t f = 0; f < adjusted_feature_size; f++) {
+    EXPECT_EQ(converted_training_data[1].features[f],
+              converted_training_data[3].features[f]);
+  }
+
+  // Converting each feature vector should result in the same one as before.
+  for (size_t f = 0; f < adjusted_feature_size; f++) {
+    FeatureVector converted_feature_vector =
+        one_hot.Convert(training_data[f].features);
+    EXPECT_EQ(converted_feature_vector, converted_training_data[f].features);
+  }
+}
+
+TEST_F(OneHotTest, NumericsAreNotConverted) {
+  LearningTask task("SimpleTask", LearningTask::Model::kRandomForest,
+                    {{"feature1", LearningTask::Ordering::kNumeric}},
+                    LearningTask::ValueDescription({"target"}));
+  OneHotConverter one_hot(task, TrainingData());
+  EXPECT_EQ(one_hot.converted_task().feature_descriptions.size(), 1u);
+  EXPECT_EQ(one_hot.converted_task().feature_descriptions[0].ordering,
+            LearningTask::Ordering::kNumeric);
+
+  TrainingData training_data;
+  training_data.push_back({{FeatureValue(5)}, TargetValue(0)});
+  TrainingData converted_training_data = one_hot.Convert(training_data);
+  EXPECT_EQ(converted_training_data[0], training_data[0]);
+
+  FeatureVector converted_feature_vector =
+      one_hot.Convert(training_data[0].features);
+  EXPECT_EQ(converted_feature_vector, training_data[0].features);
+}
+
+TEST_F(OneHotTest, UnknownValuesAreZeroHot) {
+  LearningTask task("SimpleTask", LearningTask::Model::kRandomForest,
+                    {{"feature1", LearningTask::Ordering::kUnordered}},
+                    LearningTask::ValueDescription({"target"}));
+  TrainingData training_data;
+  training_data.push_back({{FeatureValue("abc")}, TargetValue(0)});
+  training_data.push_back({{FeatureValue("def")}, TargetValue(1)});
+  training_data.push_back({{FeatureValue("ghi")}, TargetValue(2)});
+  OneHotConverter one_hot(task, training_data);
+
+  // Send in an unknown value, and see if it becomes {0, 0, 0}.
+  FeatureVector converted_feature_vector =
+      one_hot.Convert(FeatureVector({FeatureValue("jkl")}));
+  EXPECT_EQ(converted_feature_vector.size(), 3u);
+  for (size_t i = 0; i < converted_feature_vector.size(); i++)
+    EXPECT_EQ(converted_feature_vector[i], FeatureValue(0));
+}
+
+}  // namespace learning
+}  // namespace media
diff --git a/media/midi/midi_manager.cc b/media/midi/midi_manager.cc
index 6de6c776..0029928 100644
--- a/media/midi/midi_manager.cc
+++ b/media/midi/midi_manager.cc
@@ -64,6 +64,8 @@
 
 MidiManager::~MidiManager() {
   base::AutoLock auto_lock(lock_);
+  DCHECK(pending_clients_.empty() && clients_.empty());
+
   if (session_thread_runner_) {
     DCHECK(session_thread_runner_->BelongsToCurrentThread());
     session_thread_runner_ = nullptr;
@@ -79,12 +81,6 @@
                  : (data_received_ ? SendReceiveUsage::RECEIVED
                                    : SendReceiveUsage::NO_USE),
       static_cast<Sample>(SendReceiveUsage::MAX) + 1);
-
-  // Detach all clients so that they do not call MidiManager methods any more.
-  for (auto* client : pending_clients_)
-    client->Detach();
-  for (auto* client : clients_)
-    client->Detach();
 }
 
 #if !defined(OS_MACOSX) && !defined(OS_WIN) && \
@@ -182,6 +178,16 @@
   NOTREACHED();
 }
 
+void MidiManager::EndAllSessions() {
+  base::AutoLock lock(lock_);
+  for (auto* client : pending_clients_)
+    client->Detach();
+  for (auto* client : clients_)
+    client->Detach();
+  pending_clients_.clear();
+  clients_.clear();
+}
+
 void MidiManager::StartInitialization() {
   CompleteInitialization(Result::NOT_SUPPORTED);
 }
@@ -286,6 +292,7 @@
 }
 
 size_t MidiManager::GetPendingClientCountForTesting() {
+  base::AutoLock auto_lock(lock_);
   return pending_clients_.size();
 }
 
diff --git a/media/midi/midi_manager.h b/media/midi/midi_manager.h
index fab53ef..facb5f3 100644
--- a/media/midi/midi_manager.h
+++ b/media/midi/midi_manager.h
@@ -118,6 +118,10 @@
                                     const std::vector<uint8_t>& data,
                                     base::TimeTicks timestamp);
 
+  // This method ends all sessions by detaching and removing all registered
+  // clients. This method can be called from any thread.
+  void EndAllSessions();
+
  protected:
   friend class MidiManagerUsb;
 
@@ -179,7 +183,7 @@
   mojom::Result result_ = mojom::Result::NOT_INITIALIZED;
 
   // Keeps track of all clients who are waiting for CompleteStartSession().
-  std::set<MidiManagerClient*> pending_clients_;
+  std::set<MidiManagerClient*> pending_clients_ GUARDED_BY(lock_);
 
   // Keeps track of all clients who wish to receive MIDI data.
   std::set<MidiManagerClient*> clients_ GUARDED_BY(lock_);
diff --git a/media/midi/midi_service.cc b/media/midi/midi_service.cc
index a602337c..e624e82 100644
--- a/media/midi/midi_service.cc
+++ b/media/midi/midi_service.cc
@@ -42,6 +42,7 @@
 void MidiService::Shutdown() {
   base::AutoLock lock(lock_);
   if (manager_) {
+    manager_->EndAllSessions();
     DCHECK(manager_destructor_runner_);
     manager_destructor_runner_->DeleteSoon(FROM_HERE, std::move(manager_));
     manager_destructor_runner_ = nullptr;
diff --git a/media/mojo/common/media_type_converters_unittest.cc b/media/mojo/common/media_type_converters_unittest.cc
index 336b549a..1074c3b 100644
--- a/media/mojo/common/media_type_converters_unittest.cc
+++ b/media/mojo/common/media_type_converters_unittest.cc
@@ -9,7 +9,7 @@
 #include <string.h>
 #include <memory>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "media/base/audio_buffer.h"
 #include "media/base/audio_decoder_config.h"
 #include "media/base/decoder_buffer.h"
@@ -61,8 +61,8 @@
 TEST(MediaTypeConvertersTest, ConvertDecoderBuffer_Normal) {
   const uint8_t kData[] = "hello, world";
   const uint8_t kSideData[] = "sideshow bob";
-  const size_t kDataSize = arraysize(kData);
-  const size_t kSideDataSize = arraysize(kSideData);
+  const size_t kDataSize = base::size(kData);
+  const size_t kSideDataSize = base::size(kSideData);
 
   // Original.
   scoped_refptr<DecoderBuffer> buffer(DecoderBuffer::CopyFrom(
@@ -108,7 +108,7 @@
 
 TEST(MediaTypeConvertersTest, ConvertDecoderBuffer_KeyFrame) {
   const uint8_t kData[] = "hello, world";
-  const size_t kDataSize = arraysize(kData);
+  const size_t kDataSize = base::size(kData);
 
   // Original.
   scoped_refptr<DecoderBuffer> buffer(DecoderBuffer::CopyFrom(
@@ -129,7 +129,7 @@
 
 TEST(MediaTypeConvertersTest, ConvertDecoderBuffer_CencEncryptedBuffer) {
   const uint8_t kData[] = "hello, world";
-  const size_t kDataSize = arraysize(kData);
+  const size_t kDataSize = base::size(kData);
   const char kKeyId[] = "00112233445566778899aabbccddeeff";
   const char kIv[] = "0123456789abcdef";
 
@@ -165,7 +165,7 @@
 
 TEST(MediaTypeConvertersTest, ConvertDecoderBuffer_CbcsEncryptedBuffer) {
   const uint8_t kData[] = "hello, world";
-  const size_t kDataSize = arraysize(kData);
+  const size_t kDataSize = base::size(kData);
   const char kKeyId[] = "00112233445566778899aabbccddeeff";
   const char kIv[] = "0123456789abcdef";
 
diff --git a/media/mojo/interfaces/audio_decoder_config_struct_traits_unittest.cc b/media/mojo/interfaces/audio_decoder_config_struct_traits_unittest.cc
index 00c81d51..6bf0f8e 100644
--- a/media/mojo/interfaces/audio_decoder_config_struct_traits_unittest.cc
+++ b/media/mojo/interfaces/audio_decoder_config_struct_traits_unittest.cc
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "media/base/audio_decoder_config.h"
 #include "media/base/media_util.h"
 #include "mojo/public/cpp/base/time_mojom_traits.h"
@@ -17,7 +17,7 @@
 TEST(AudioDecoderConfigStructTraitsTest, ConvertAudioDecoderConfig_Normal) {
   const uint8_t kExtraData[] = "input extra data";
   const std::vector<uint8_t> kExtraDataVector(
-      &kExtraData[0], &kExtraData[0] + arraysize(kExtraData));
+      &kExtraData[0], &kExtraData[0] + base::size(kExtraData));
 
   AudioDecoderConfig input;
   input.Initialize(kCodecAAC, kSampleFormatU8, CHANNEL_LAYOUT_SURROUND, 48000,
diff --git a/media/mojo/interfaces/video_decoder_config_struct_traits_unittest.cc b/media/mojo/interfaces/video_decoder_config_struct_traits_unittest.cc
index fde934c5..d028eb5 100644
--- a/media/mojo/interfaces/video_decoder_config_struct_traits_unittest.cc
+++ b/media/mojo/interfaces/video_decoder_config_struct_traits_unittest.cc
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "media/base/media_util.h"
 #include "media/base/video_decoder_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -24,7 +24,7 @@
 TEST(VideoDecoderConfigStructTraitsTest, ConvertVideoDecoderConfig_Normal) {
   const uint8_t kExtraData[] = "config extra data";
   const std::vector<uint8_t> kExtraDataVector(
-      &kExtraData[0], &kExtraData[0] + arraysize(kExtraData));
+      &kExtraData[0], &kExtraData[0] + base::size(kExtraData));
   VideoDecoderConfig input(kCodecVP8, VP8PROFILE_ANY, PIXEL_FORMAT_I420,
                            VideoColorSpace(), VIDEO_ROTATION_0, kCodedSize,
                            kVisibleRect, kNaturalSize, kExtraDataVector,
diff --git a/mojo/core/data_pipe_unittest.cc b/mojo/core/data_pipe_unittest.cc
index b2f32a4..0ce3f1e 100644
--- a/mojo/core/data_pipe_unittest.cc
+++ b/mojo/core/data_pipe_unittest.cc
@@ -10,9 +10,9 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "build/build_config.h"
 #include "mojo/core/embedder/embedder.h"
 #include "mojo/core/test/mojo_test_base.h"
@@ -168,7 +168,7 @@
   int32_t elements[10] = {};
   uint32_t num_bytes = 0;
 
-  num_bytes = static_cast<uint32_t>(arraysize(elements) * sizeof(elements[0]));
+  num_bytes = static_cast<uint32_t>(base::size(elements) * sizeof(elements[0]));
 
   elements[0] = 123;
   elements[1] = 456;
@@ -211,7 +211,7 @@
        100,                              // |element_num_bytes|.
        0}                                // |capacity_num_bytes|.
   };
-  for (size_t i = 0; i < arraysize(test_options); i++) {
+  for (size_t i = 0; i < base::size(test_options); i++) {
     MojoHandle producer_handle, consumer_handle;
     MojoCreateDataPipeOptions* options = i ? &test_options[i] : nullptr;
     ASSERT_EQ(MOJO_RESULT_OK,
@@ -236,7 +236,7 @@
   uint32_t num_bytes = 0;
 
   // Try reading; nothing there yet.
-  num_bytes = static_cast<uint32_t>(arraysize(elements) * sizeof(elements[0]));
+  num_bytes = static_cast<uint32_t>(base::size(elements) * sizeof(elements[0]));
   ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadData(elements, &num_bytes));
 
   // Query; nothing there yet.
@@ -874,7 +874,7 @@
   // Try writing more than the total capacity of the pipe.
   uint32_t num_bytes = 20u * sizeof(int32_t);
   int32_t buffer[100];
-  Seq(0, arraysize(buffer), buffer);
+  Seq(0, base::size(buffer), buffer);
   ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, WriteData(buffer, &num_bytes, true));
 
   // Should still be empty.
@@ -884,7 +884,7 @@
 
   // Write some data.
   num_bytes = 5u * sizeof(int32_t);
-  Seq(100, arraysize(buffer), buffer);
+  Seq(100, base::size(buffer), buffer);
   ASSERT_EQ(MOJO_RESULT_OK, WriteData(buffer, &num_bytes, true));
   ASSERT_EQ(5u * sizeof(int32_t), num_bytes);
 
@@ -910,7 +910,7 @@
   // Try writing more than the available capacity of the pipe, but less than the
   // total capacity.
   num_bytes = 6u * sizeof(int32_t);
-  Seq(200, arraysize(buffer), buffer);
+  Seq(200, base::size(buffer), buffer);
   ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE, WriteData(buffer, &num_bytes, true));
 
   // Try reading too much.
@@ -927,13 +927,13 @@
 
   // Just a little.
   num_bytes = 2u * sizeof(int32_t);
-  Seq(300, arraysize(buffer), buffer);
+  Seq(300, base::size(buffer), buffer);
   ASSERT_EQ(MOJO_RESULT_OK, WriteData(buffer, &num_bytes, true));
   ASSERT_EQ(2u * sizeof(int32_t), num_bytes);
 
   // Just right.
   num_bytes = 3u * sizeof(int32_t);
-  Seq(400, arraysize(buffer), buffer);
+  Seq(400, base::size(buffer), buffer);
   ASSERT_EQ(MOJO_RESULT_OK, WriteData(buffer, &num_bytes, true));
   ASSERT_EQ(3u * sizeof(int32_t), num_bytes);
 
@@ -1029,7 +1029,7 @@
 // this.)
 TEST_F(DataPipeTest, WrapAround) {
   unsigned char test_data[1000];
-  for (size_t i = 0; i < arraysize(test_data); i++)
+  for (size_t i = 0; i < base::size(test_data); i++)
     test_data[i] = static_cast<unsigned char>(i);
 
   const MojoCreateDataPipeOptions options = {
@@ -1106,7 +1106,7 @@
 
   // Read as much as possible. We should read 100 bytes.
   num_bytes =
-      static_cast<uint32_t>(arraysize(read_buffer) * sizeof(read_buffer[0]));
+      static_cast<uint32_t>(base::size(read_buffer) * sizeof(read_buffer[0]));
   memset(read_buffer, 0, num_bytes);
   ASSERT_EQ(MOJO_RESULT_OK, ReadData(read_buffer, &num_bytes));
   ASSERT_EQ(100u, num_bytes);
diff --git a/mojo/core/multiprocess_message_pipe_unittest.cc b/mojo/core/multiprocess_message_pipe_unittest.cc
index 0b26502d..c6f1141 100644
--- a/mojo/core/multiprocess_message_pipe_unittest.cc
+++ b/mojo/core/multiprocess_message_pipe_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/string_split.h"
 #include "build/build_config.h"
 #include "mojo/core/handle_signals_state.h"
@@ -270,7 +271,7 @@
   std::string read_buffer(100, '\0');
   uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
   MojoHandle handles[10];
-  uint32_t num_handlers = arraysize(handles);  // Maximum number to receive
+  uint32_t num_handlers = base::size(handles);  // Maximum number to receive
   CHECK_EQ(MojoReadMessage(h, &read_buffer[0], &num_bytes, &handles[0],
                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE),
            MOJO_RESULT_OK);
@@ -350,7 +351,7 @@
     handles[0] = duplicated_shared_buffer;
     ASSERT_EQ(MOJO_RESULT_OK,
               MojoWriteMessage(h, &go1[0], static_cast<uint32_t>(go1.size()),
-                               &handles[0], arraysize(handles),
+                               &handles[0], base::size(handles),
                                MOJO_WRITE_MESSAGE_FLAG_NONE));
 
     // Wait for a message from the child.
@@ -407,7 +408,7 @@
   std::string read_buffer(100, '\0');
   uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
   MojoHandle handles[255];  // Maximum number to receive.
-  uint32_t num_handlers = arraysize(handles);
+  uint32_t num_handlers = base::size(handles);
 
   CHECK_EQ(MojoReadMessage(h, &read_buffer[0], &num_bytes, &handles[0],
                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE),
@@ -503,7 +504,7 @@
 
   // It should have a message pipe.
   MojoHandle handles[10];
-  uint32_t num_handlers = arraysize(handles);
+  uint32_t num_handlers = base::size(handles);
   CHECK_EQ(MojoReadMessage(h, nullptr, nullptr, &handles[0], &num_handlers,
                            MOJO_READ_MESSAGE_FLAG_NONE),
            MOJO_RESULT_OK);
@@ -619,7 +620,7 @@
 
   // It should have a message pipe.
   MojoHandle handles[10];
-  uint32_t num_handlers = arraysize(handles);
+  uint32_t num_handlers = base::size(handles);
   CHECK_EQ(MojoReadMessage(h, nullptr, nullptr, &handles[0], &num_handlers,
                            MOJO_READ_MESSAGE_FLAG_NONE),
            MOJO_RESULT_OK);
diff --git a/mojo/core/shared_buffer_dispatcher_unittest.cc b/mojo/core/shared_buffer_dispatcher_unittest.cc
index 22cbb44..b245b78 100644
--- a/mojo/core/shared_buffer_dispatcher_unittest.cc
+++ b/mojo/core/shared_buffer_dispatcher_unittest.cc
@@ -9,10 +9,10 @@
 
 #include <limits>
 
-#include "base/macros.h"
 #include "base/memory/platform_shared_memory_region.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/writable_shared_memory_region.h"
+#include "base/stl_util.h"
 #include "mojo/core/dispatcher.h"
 #include "mojo/core/platform_shared_memory_mapping.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -65,7 +65,7 @@
   // Different flags.
   MojoCreateSharedBufferFlags flags_values[] = {
       MOJO_CREATE_SHARED_BUFFER_FLAG_NONE};
-  for (size_t i = 0; i < arraysize(flags_values); i++) {
+  for (size_t i = 0; i < base::size(flags_values); i++) {
     const MojoCreateSharedBufferFlags flags = flags_values[i];
 
     // Different capacities (size 1).
diff --git a/mojo/public/cpp/base/ref_counted_memory_unittest.cc b/mojo/public/cpp/base/ref_counted_memory_unittest.cc
index a3c757a..72f12eb 100644
--- a/mojo/public/cpp/base/ref_counted_memory_unittest.cc
+++ b/mojo/public/cpp/base/ref_counted_memory_unittest.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/stl_util.h"
 #include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
 #include "mojo/public/cpp/base/ref_counted_memory_mojom_traits.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
@@ -14,7 +15,7 @@
   uint8_t data[] = {'a', 'b', 'c', 'd', 'e'};
 
   scoped_refptr<base::RefCountedMemory> in =
-      new base::RefCountedStaticMemory(&data, arraysize(data));
+      new base::RefCountedStaticMemory(&data, base::size(data));
 
   scoped_refptr<base::RefCountedMemory> out;
   ASSERT_TRUE(
@@ -28,7 +29,7 @@
   // Stuff real data in out to ensure it gets overwritten with a null.
   uint8_t data[] = {'a', 'b', 'c', 'd', 'e'};
   scoped_refptr<base::RefCountedMemory> out =
-      new base::RefCountedStaticMemory(&data, arraysize(data));
+      new base::RefCountedStaticMemory(&data, base::size(data));
 
   scoped_refptr<base::RefCountedMemory> in;
   ASSERT_TRUE(
diff --git a/mojo/public/cpp/bindings/tests/connector_unittest.cc b/mojo/public/cpp/bindings/tests/connector_unittest.cc
index 68f51fc..605e3ea 100644
--- a/mojo/public/cpp/bindings/tests/connector_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/connector_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/callback_helpers.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/message.h"
@@ -196,7 +197,7 @@
                        base::ThreadTaskRunnerHandle::Get());
 
   const char* kText[] = {"hello", "world"};
-  for (size_t i = 0; i < arraysize(kText); ++i) {
+  for (size_t i = 0; i < base::size(kText); ++i) {
     Message message = CreateMessage(kText[i]);
     connector0.Accept(&message);
   }
@@ -204,7 +205,7 @@
   MessageAccumulator accumulator;
   connector1.set_incoming_receiver(&accumulator);
 
-  for (size_t i = 0; i < arraysize(kText); ++i) {
+  for (size_t i = 0; i < base::size(kText); ++i) {
     if (accumulator.IsEmpty()) {
       base::RunLoop run_loop;
       accumulator.set_closure(run_loop.QuitClosure());
@@ -228,7 +229,7 @@
                        base::ThreadTaskRunnerHandle::Get());
 
   const char* kText[] = {"hello", "world"};
-  for (size_t i = 0; i < arraysize(kText); ++i) {
+  for (size_t i = 0; i < base::size(kText); ++i) {
     Message message = CreateMessage(kText[i]);
     connector0.Accept(&message);
   }
@@ -378,7 +379,7 @@
                        base::ThreadTaskRunnerHandle::Get());
 
   const char* kText[] = {"hello", "world"};
-  for (size_t i = 0; i < arraysize(kText); ++i) {
+  for (size_t i = 0; i < base::size(kText); ++i) {
     Message message = CreateMessage(kText[i]);
     connector0.Accept(&message);
   }
@@ -386,7 +387,7 @@
   ReentrantMessageAccumulator accumulator(&connector1);
   connector1.set_incoming_receiver(&accumulator);
 
-  for (size_t i = 0; i < arraysize(kText); ++i) {
+  for (size_t i = 0; i < base::size(kText); ++i) {
     if (accumulator.IsEmpty()) {
       base::RunLoop run_loop;
       accumulator.set_closure(run_loop.QuitClosure());
diff --git a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
index 3a79010..f7417c8 100644
--- a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
@@ -3,9 +3,9 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
-#include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
 #include "mojo/public/cpp/bindings/lib/serialization.h"
@@ -219,7 +219,7 @@
   // arrs[1] is null.
   arrs[2] = ConstructStringArray();
 
-  for (size_t i = 0; i < arraysize(arrs); ++i) {
+  for (size_t i = 0; i < base::size(arrs); ++i) {
     base::RunLoop loop;
     // Test that a base::Optional<WTF::Vector<WTF::String>> is unchanged after
     // the following conversion:
@@ -245,7 +245,7 @@
   // maps[1] is null.
   maps[2] = ConstructStringMap();
 
-  for (size_t i = 0; i < arraysize(maps); ++i) {
+  for (size_t i = 0; i < base::size(maps); ++i) {
     base::RunLoop loop;
     // Test that a base::Optional<WTF::HashMap<WTF::String, WTF::String>> is
     // unchanged after the following conversion:
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module-shared.cc.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module-shared.cc.tmpl
index 6004c52..357d850 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/module-shared.cc.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/module-shared.cc.tmpl
@@ -12,6 +12,7 @@
 #include <utility>
 
 #include "base/logging.h"
+#include "base/stl_util.h"  // for base::size()
 #include "mojo/public/cpp/bindings/lib/validate_params.h"
 #include "mojo/public/cpp/bindings/lib/validation_context.h"
 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
index 1638962..c564e79 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
@@ -25,9 +25,9 @@
   };
 
   if (object->header_.version <=
-          kVersionSizes[arraysize(kVersionSizes) - 1].version) {
+          kVersionSizes[base::size(kVersionSizes) - 1].version) {
     // Scan in reverse order to optimize for more recent versions.
-    for (int i = arraysize(kVersionSizes) - 1; i >= 0; --i) {
+    for (int i = base::size(kVersionSizes) - 1; i >= 0; --i) {
       if (object->header_.version >= kVersionSizes[i].version) {
         if (object->header_.num_bytes == kVersionSizes[i].num_bytes)
           break;
@@ -39,7 +39,7 @@
       }
     }
   } else if (object->header_.num_bytes <
-                 kVersionSizes[arraysize(kVersionSizes) - 1].num_bytes) {
+                 kVersionSizes[base::size(kVersionSizes) - 1].num_bytes) {
     ReportValidationError(
         validation_context,
         mojo::internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index f161668..b9fefb5 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -1027,7 +1027,7 @@
   }
 
   bool can_open_next;
-  if (!quic::GetQuicReloadableFlag(quic_use_common_stream_check) &&
+  if (!GetQuicReloadableFlag(quic_use_common_stream_check) &&
       connection()->transport_version() != quic::QUIC_VERSION_99) {
     can_open_next = (GetNumOpenOutgoingStreams() <
                      stream_id_manager().max_open_outgoing_streams());
@@ -1063,7 +1063,7 @@
     DVLOG(1) << "Encryption not active so no outgoing stream created.";
     return false;
   }
-  if (!quic::GetQuicReloadableFlag(quic_use_common_stream_check) &&
+  if (!GetQuicReloadableFlag(quic_use_common_stream_check) &&
       connection()->transport_version() != quic::QUIC_VERSION_99) {
     if (GetNumOpenOutgoingStreams() >=
         stream_id_manager().max_open_outgoing_streams()) {
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 82e6f00..1887136f 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -2284,7 +2284,7 @@
 
   // Fire the retransmission alarm, from this point, connection will idle
   // timeout after 4 seconds.
-  if (!quic::GetQuicReloadableFlag(
+  if (!GetQuicReloadableFlag(
           quic_fix_time_of_first_packet_sent_after_receiving)) {
     quic_task_runner_->RunNextTask();
   }
@@ -2415,7 +2415,7 @@
 
   // Fire the retransmission alarm, after which connection will idle
   // timeout after 4 seconds.
-  if (!quic::GetQuicReloadableFlag(
+  if (!GetQuicReloadableFlag(
           quic_fix_time_of_first_packet_sent_after_receiving)) {
     quic_task_runner_->RunNextTask();
   }
@@ -2550,7 +2550,7 @@
 
   // Pump the message loop to get the request started.
   base::RunLoop().RunUntilIdle();
-  if (!quic::GetQuicReloadableFlag(
+  if (!GetQuicReloadableFlag(
           quic_fix_time_of_first_packet_sent_after_receiving)) {
     quic_task_runner_->RunNextTask();
   }
@@ -3397,7 +3397,7 @@
                        11, quic::QuicUtils::GetHeadersStreamId(version_), false,
                        false, settings_offset, settings_data));
 
-  if (quic::GetQuicReloadableFlag(
+  if (GetQuicReloadableFlag(
           quic_fix_time_of_first_packet_sent_after_receiving)) {
     quic_data.AddWrite(
         SYNCHRONOUS,
diff --git a/net/third_party/quic/platform/impl/quic_flags_impl.h b/net/third_party/quic/platform/impl/quic_flags_impl.h
index ca35f586..38f0145 100644
--- a/net/third_party/quic/platform/impl/quic_flags_impl.h
+++ b/net/third_party/quic/platform/impl/quic_flags_impl.h
@@ -24,7 +24,6 @@
 #undef QUIC_FLAG
 
 // API compatibility with new-style flags.
-namespace quic {
 
 inline bool GetQuicFlagImpl(bool flag) {
   return flag;
@@ -70,6 +69,8 @@
   *f = v;
 }
 
+namespace quic {
+
 // ------------------------------------------------------------------------
 // DEFINE_QUIC_COMMAND_LINE_FLAG implementation.
 // ------------------------------------------------------------------------
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.cc b/sandbox/linux/bpf_dsl/policy_compiler.cc
index 7ce517a5..3473048 100644
--- a/sandbox/linux/bpf_dsl/policy_compiler.cc
+++ b/sandbox/linux/bpf_dsl/policy_compiler.cc
@@ -12,7 +12,7 @@
 #include <limits>
 
 #include "base/logging.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h"
 #include "sandbox/linux/bpf_dsl/codegen.h"
@@ -454,7 +454,7 @@
 }
 
 bool PolicyCompiler::IsRequiredForUnsafeTrap(int sysno) {
-  for (size_t i = 0; i < arraysize(kSyscallsRequiredForUnsafeTraps); ++i) {
+  for (size_t i = 0; i < base::size(kSyscallsRequiredForUnsafeTraps); ++i) {
     if (sysno == kSyscallsRequiredForUnsafeTraps[i]) {
       return true;
     }
diff --git a/sandbox/linux/bpf_dsl/syscall_set_unittest.cc b/sandbox/linux/bpf_dsl/syscall_set_unittest.cc
index 5069e8e..942ac745 100644
--- a/sandbox/linux/bpf_dsl/syscall_set_unittest.cc
+++ b/sandbox/linux/bpf_dsl/syscall_set_unittest.cc
@@ -7,7 +7,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "sandbox/linux/bpf_dsl/linux_syscall_ranges.h"
 #include "sandbox/linux/tests/unit_tests.h"
 
@@ -86,12 +86,12 @@
     size_t i = 0;
     for (uint32_t sysnum : set) {
       if (!SyscallSet::IsValid(sysnum)) {
-        SANDBOX_ASSERT(i < arraysize(kExpected));
+        SANDBOX_ASSERT(i < base::size(kExpected));
         SANDBOX_ASSERT(kExpected[i] == sysnum);
         ++i;
       }
     }
-    SANDBOX_ASSERT(i == arraysize(kExpected));
+    SANDBOX_ASSERT(i == base::size(kExpected));
   }
 }
 
diff --git a/sandbox/linux/bpf_dsl/test_trap_registry_unittest.cc b/sandbox/linux/bpf_dsl/test_trap_registry_unittest.cc
index 04a620d8..6f0f71f 100644
--- a/sandbox/linux/bpf_dsl/test_trap_registry_unittest.cc
+++ b/sandbox/linux/bpf_dsl/test_trap_registry_unittest.cc
@@ -6,7 +6,7 @@
 
 #include <stddef.h>
 
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace sandbox {
@@ -37,7 +37,7 @@
 
   // Add traps twice to test that IDs are reused correctly.
   for (int i = 0; i < 2; ++i) {
-    for (size_t j = 0; j < arraysize(funcs); ++j) {
+    for (size_t j = 0; j < base::size(funcs); ++j) {
       // Trap IDs start at 1.
       EXPECT_EQ(j + 1, traps.Add(funcs[j].fnc, funcs[j].aux, true));
     }
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
index 1515d528..5adc1a7a 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
@@ -14,6 +14,7 @@
 #include "base/debug/crash_logging.h"
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
+#include "base/stl_util.h"
 #include "build/build_config.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
@@ -180,7 +181,7 @@
   memset(crash_key, '\0', crash_key_length);
 
   size_t offset = 0;
-  for (size_t i = 0; i < arraysize(values); ++i) {
+  for (size_t i = 0; i < base::size(values); ++i) {
     const char* strings[2] = { prefixes[i], values[i] };
     for (auto* string : strings) {
       size_t string_len = strlen(string);
diff --git a/sandbox/linux/seccomp-bpf/syscall_unittest.cc b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
index e96f51b..2b776d2 100644
--- a/sandbox/linux/seccomp-bpf/syscall_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/syscall_unittest.cc
@@ -16,9 +16,9 @@
 
 #include <vector>
 
-#include "base/macros.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/process_metrics.h"
+#include "base/stl_util.h"
 #include "build/build_config.h"
 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
 #include "sandbox/linux/bpf_dsl/policy.h"
@@ -96,8 +96,8 @@
   // |aux| is our BPF_AUX pointer.
   std::vector<uint64_t>* const seen_syscall_args =
       static_cast<std::vector<uint64_t>*>(aux);
-  BPF_ASSERT(arraysize(args.args) == 6);
-  seen_syscall_args->assign(args.args, args.args + arraysize(args.args));
+  BPF_ASSERT(base::size(args.args) == 6);
+  seen_syscall_args->assign(args.args, args.args + base::size(args.args));
   return -ENOMEM;
 }
 
@@ -134,7 +134,7 @@
   // implementation details of kernel BPF filters and we will need to document
   // the expected behavior very clearly.
   int syscall_args[6];
-  for (size_t i = 0; i < arraysize(syscall_args); ++i) {
+  for (size_t i = 0; i < base::size(syscall_args); ++i) {
     syscall_args[i] = kExpectedValue + i;
   }
 
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc
index ad0714a7..ee0fa017 100644
--- a/sandbox/linux/services/credentials.cc
+++ b/sandbox/linux/services/credentials.cc
@@ -21,9 +21,9 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/launch.h"
+#include "base/stl_util.h"
 #include "build/build_config.h"
 #include "sandbox/linux/services/namespace_utils.h"
 #include "sandbox/linux/services/proc_util.h"
@@ -228,7 +228,7 @@
 
   PCHECK(sys_capget(&hdr, data) == 0);
 
-  for (size_t i = 0; i < arraysize(data); ++i) {
+  for (size_t i = 0; i < base::size(data); ++i) {
     if (data[i].effective || data[i].permitted || data[i].inheritable) {
       return true;
     }
diff --git a/sandbox/linux/services/namespace_sandbox.cc b/sandbox/linux/services/namespace_sandbox.cc
index 53d530c..eb91e525 100644
--- a/sandbox/linux/services/namespace_sandbox.cc
+++ b/sandbox/linux/services/namespace_sandbox.cc
@@ -19,10 +19,10 @@
 #include "base/environment.h"
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/launch.h"
 #include "base/process/process.h"
+#include "base/stl_util.h"
 #include "build/build_config.h"
 #include "sandbox/linux/services/credentials.h"
 #include "sandbox/linux/services/namespace_utils.h"
@@ -78,7 +78,7 @@
   // Return a special exit code so that the process is detected as terminated by
   // a signal.
   const size_t sig_idx = static_cast<size_t>(sig);
-  if (sig_idx < arraysize(g_signal_exit_codes)) {
+  if (sig_idx < base::size(g_signal_exit_codes)) {
     _exit(g_signal_exit_codes[sig_idx]);
   }
 
@@ -265,7 +265,7 @@
   }
 
   const size_t sig_idx = static_cast<size_t>(sig);
-  CHECK_LT(sig_idx, arraysize(g_signal_exit_codes));
+  CHECK_LT(sig_idx, base::size(g_signal_exit_codes));
 
   DCHECK_GE(exit_code, 0);
   DCHECK_LT(exit_code, 256);
diff --git a/sandbox/linux/suid/client/setuid_sandbox_host.cc b/sandbox/linux/suid/client/setuid_sandbox_host.cc
index 6096c3bc..784f6073 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_host.cc
+++ b/sandbox/linux/suid/client/setuid_sandbox_host.cc
@@ -20,11 +20,11 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/path_service.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/launch.h"
 #include "base/process/process_metrics.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "sandbox/linux/suid/common/sandbox.h"
 #include "sandbox/linux/suid/common/suid_unsafe_environment_variables.h"
@@ -51,7 +51,7 @@
       kSandboxNETNSEnvironmentVarName,
   };
 
-  for (size_t i = 0; i < arraysize(environment_vars); ++i) {
+  for (size_t i = 0; i < base::size(environment_vars); ++i) {
     // Setting values in EnvironmentMap to an empty-string will make
     // sure that they get unset from the environment via AlterEnvironment().
     (*env_map)[environment_vars[i]] = base::NativeEnvironmentString();
diff --git a/sandbox/linux/syscall_broker/broker_process_unittest.cc b/sandbox/linux/syscall_broker/broker_process_unittest.cc
index 553b02a..a4fc812 100644
--- a/sandbox/linux/syscall_broker/broker_process_unittest.cc
+++ b/sandbox/linux/syscall_broker/broker_process_unittest.cc
@@ -24,7 +24,6 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/posix/unix_domain_socket.h"
 #include "base/stl_util.h"
@@ -537,7 +536,7 @@
 
   // Save one FD to send to the broker later, and close the others.
   base::ScopedFD message_fd(available_fds[0]);
-  for (size_t i = 1; i < arraysize(available_fds); i++) {
+  for (size_t i = 1; i < base::size(available_fds); i++) {
     SANDBOX_ASSERT(0 == IGNORE_EINTR(close(available_fds[i])));
   }
 
@@ -546,9 +545,8 @@
   // descriptors a process can have: it only limits the highest value that can
   // be assigned to newly-created descriptors allocated by the process.)
   const rlim_t fd_limit =
-      1 +
-      *std::max_element(available_fds,
-                        available_fds + arraysize(available_fds));
+      1 + *std::max_element(available_fds,
+                            available_fds + base::size(available_fds));
 
   struct rlimit rlim;
   SANDBOX_ASSERT(0 == getrlimit(RLIMIT_NOFILE, &rlim));
diff --git a/sandbox/mac/seatbelt_extension_unittest.cc b/sandbox/mac/seatbelt_extension_unittest.cc
index c9e52306..6b1744f 100644
--- a/sandbox/mac/seatbelt_extension_unittest.cc
+++ b/sandbox/mac/seatbelt_extension_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/stl_util.h"
 #include "base/test/multiprocess_test.h"
 #include "base/test/test_timeouts.h"
 #include "sandbox/mac/sandbox_compiler.h"
@@ -26,7 +27,7 @@
     "(allow file-read* (extension \"com.apple.app-sandbox.read\"))";
 
 const char kTestData[] = "hello world";
-constexpr int kTestDataLen = arraysize(kTestData);
+constexpr int kTestDataLen = base::size(kTestData);
 
 const char kSwitchFile[] = "test-file";
 const char kSwitchExtension[] = "test-extension";
diff --git a/sandbox/win/src/filesystem_policy.cc b/sandbox/win/src/filesystem_policy.cc
index a21a0c3a..5f482b64 100644
--- a/sandbox/win/src/filesystem_policy.cc
+++ b/sandbox/win/src/filesystem_policy.cc
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "base/logging.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/win/scoped_handle.h"
 #include "base/win/windows_version.h"
 #include "sandbox/win/src/ipc_tags.h"
@@ -415,7 +415,7 @@
 
   // NT prefix escaped for rule matcher
   const wchar_t kNTPrefixEscaped[] = L"\\/?/?\\";
-  const int kNTPrefixEscapedLen = arraysize(kNTPrefixEscaped) - 1;
+  const int kNTPrefixEscapedLen = base::size(kNTPrefixEscaped) - 1;
 
   if (0 != mod_name.compare(0, kNTPrefixLen, kNTPrefix)) {
     if (0 != mod_name.compare(0, kNTPrefixEscapedLen, kNTPrefixEscaped)) {
diff --git a/sandbox/win/src/ipc_leak_test.cc b/sandbox/win/src/ipc_leak_test.cc
index 30f2211..66d0b4da 100644
--- a/sandbox/win/src/ipc_leak_test.cc
+++ b/sandbox/win/src/ipc_leak_test.cc
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 
 #include "base/process/process_metrics.h"
+#include "base/stl_util.h"
 #include "base/win/win_util.h"
 #include "sandbox/win/src/crosscall_client.h"
 #include "sandbox/win/src/filesystem_interception.h"
@@ -335,7 +336,7 @@
                    {TESTIPC_NTOPENKEY, "TESTIPC_NTOPENKEY", nullptr},
                    {TESTIPC_NTCREATEKEY, "TESTIPC_NTCREATEEY", nullptr}};
 
-  static_assert(arraysize(test_data) == TESTIPC_LAST, "Not enough tests.");
+  static_assert(base::size(test_data) == TESTIPC_LAST, "Not enough tests.");
   for (auto test : test_data) {
     TestRunner runner;
     EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_REGISTRY,
diff --git a/sandbox/win/src/win_utils.cc b/sandbox/win/src/win_utils.cc
index 1ef7b79..135d40e 100644
--- a/sandbox/win/src/win_utils.cc
+++ b/sandbox/win/src/win_utils.cc
@@ -12,8 +12,8 @@
 #include <memory>
 #include <vector>
 
-#include "base/macros.h"
 #include "base/numerics/safe_math.h"
+#include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/win/pe_image.h"
@@ -26,7 +26,7 @@
 const size_t kDriveLetterLen = 3;
 
 constexpr wchar_t kNTDotPrefix[] = L"\\\\.\\";
-const size_t kNTDotPrefixLen = arraysize(kNTDotPrefix) - 1;
+const size_t kNTDotPrefixLen = base::size(kNTDotPrefix) - 1;
 
 // Holds the information about a known registry key.
 struct KnownReservedKey {
@@ -103,7 +103,7 @@
 // "\Device\HarddiskVolumeX" in |path|.
 size_t PassHarddiskVolume(const base::string16& path) {
   static constexpr wchar_t pattern[] = L"\\Device\\HarddiskVolume";
-  const size_t patternLen = arraysize(pattern) - 1;
+  const size_t patternLen = base::size(pattern) - 1;
 
   // First, check for |pattern|.
   if ((path.size() < patternLen) || (!EqualPath(path, pattern, patternLen)))
@@ -156,14 +156,14 @@
     start = sandbox::kNTPrefixLen;
 
   const wchar_t kPipe[] = L"pipe\\";
-  if (path.size() < start + arraysize(kPipe) - 1)
+  if (path.size() < start + base::size(kPipe) - 1)
     return false;
 
-  return EqualPath(path, start, kPipe, arraysize(kPipe) - 1);
+  return EqualPath(path, start, kPipe, base::size(kPipe) - 1);
 }
 
 HKEY GetReservedKeyFromName(const base::string16& name) {
-  for (size_t i = 0; i < arraysize(kKnownKey); ++i) {
+  for (size_t i = 0; i < base::size(kKnownKey); ++i) {
     if (name == kKnownKey[i].name)
       return kKnownKey[i].key;
   }
@@ -172,7 +172,7 @@
 }
 
 bool ResolveRegistryName(base::string16 name, base::string16* resolved_name) {
-  for (size_t i = 0; i < arraysize(kKnownKey); ++i) {
+  for (size_t i = 0; i < base::size(kKnownKey); ++i) {
     if (name.find(kKnownKey[i].name) == 0) {
       HKEY key;
       DWORD disposition;
diff --git a/sandbox/win/src/win_utils.h b/sandbox/win/src/win_utils.h
index 84d6883..f69ddf7 100644
--- a/sandbox/win/src/win_utils.h
+++ b/sandbox/win/src/win_utils.h
@@ -10,6 +10,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "sandbox/win/src/nt_internals.h"
 
@@ -17,10 +18,10 @@
 
 // Prefix for path used by NT calls.
 const wchar_t kNTPrefix[] = L"\\??\\";
-const size_t kNTPrefixLen = arraysize(kNTPrefix) - 1;
+const size_t kNTPrefixLen = base::size(kNTPrefix) - 1;
 
 const wchar_t kNTDevicePrefix[] = L"\\Device\\";
-const size_t kNTDevicePrefixLen = arraysize(kNTDevicePrefix) - 1;
+const size_t kNTDevicePrefixLen = base::size(kNTDevicePrefix) - 1;
 
 // Automatically acquires and releases a lock when the object is
 // is destroyed.
diff --git a/services/audio/BUILD.gn b/services/audio/BUILD.gn
index 575bcab..f6012237 100644
--- a/services/audio/BUILD.gn
+++ b/services/audio/BUILD.gn
@@ -223,6 +223,7 @@
   service_manifest("standalone_unittest_manifest") {
     name = "audio_unittests"
     source = "test/service_unittest_manifest.json"
+    generated_namespace = "standalone_audio_unittest"
   }
 
   catalog("standalone_unittest_catalog") {
diff --git a/services/catalog/BUILD.gn b/services/catalog/BUILD.gn
index c35b58a..07cfd90 100644
--- a/services/catalog/BUILD.gn
+++ b/services/catalog/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//services/service_manager/public/service_manifest.gni")
 import("//testing/test.gni")
 
 group("catalog") {
@@ -31,7 +30,6 @@
     "entry_cache.h",
     "instance.cc",
     "instance.h",
-    "manifest_provider.h",
     "service_options.h",
   ]
 
@@ -55,24 +53,3 @@
 
   defines = [ "IS_CATALOG_IMPL" ]
 }
-
-service_manifest("manifest") {
-  name = "catalog"
-  source = "manifest.json"
-}
-
-source_set("unittests") {
-  testonly = true
-  sources = [
-    "entry_unittest.cc",
-  ]
-  data = [
-    "//services/catalog/test_data/",
-  ]
-  deps = [
-    ":lib",
-    "//base",
-    "//services/service_manager/public/cpp",
-    "//testing/gtest",
-  ]
-}
diff --git a/services/catalog/catalog.cc b/services/catalog/catalog.cc
index 6931cf8..2d1d21ff 100644
--- a/services/catalog/catalog.cc
+++ b/services/catalog/catalog.cc
@@ -32,87 +32,11 @@
 
 namespace {
 
-const char kCatalogServicesKey[] = "services";
-const char kCatalogServiceEmbeddedKey[] = "embedded";
-const char kCatalogServiceExecutableKey[] = "executable";
-const char kCatalogServiceManifestKey[] = "manifest";
-
 std::vector<service_manager::Manifest>& GetDefaultManifests() {
   static base::NoDestructor<std::vector<service_manager::Manifest>> manifests;
   return *manifests;
 }
 
-void LoadCatalogManifestIntoCache(const base::Value* root, EntryCache* cache) {
-  DCHECK(root);
-  const base::DictionaryValue* catalog = nullptr;
-  if (!root->GetAsDictionary(&catalog)) {
-    LOG(ERROR) << "Catalog manifest is not a dictionary value.";
-    return;
-  }
-  DCHECK(catalog);
-
-  const base::DictionaryValue* services = nullptr;
-  if (!catalog->GetDictionary(kCatalogServicesKey, &services)) {
-    LOG(ERROR) << "Catalog manifest \"services\" is not a dictionary value.";
-    return;
-  }
-
-  for (base::DictionaryValue::Iterator it(*services); !it.IsAtEnd();
-       it.Advance()) {
-    const base::DictionaryValue* service_entry = nullptr;
-    if (!it.value().GetAsDictionary(&service_entry)) {
-      LOG(ERROR) << "Catalog service entry for \"" << it.key()
-                 << "\" is not a dictionary value.";
-      continue;
-    }
-
-    bool is_embedded = false;
-    service_entry->GetBoolean(kCatalogServiceEmbeddedKey, &is_embedded);
-
-    base::FilePath executable_path;
-    std::string executable_path_string;
-    if (service_entry->GetString(kCatalogServiceExecutableKey,
-                                 &executable_path_string)) {
-      base::FilePath exe_dir;
-      CHECK(base::PathService::Get(base::DIR_EXE, &exe_dir));
-#if defined(OS_WIN)
-      executable_path_string += ".exe";
-      base::ReplaceFirstSubstringAfterOffset(
-          &executable_path_string, 0, "@EXE_DIR",
-          base::UTF16ToUTF8(exe_dir.value()));
-      executable_path =
-          base::FilePath(base::UTF8ToUTF16(executable_path_string));
-#else
-      base::ReplaceFirstSubstringAfterOffset(
-          &executable_path_string, 0, "@EXE_DIR", exe_dir.value());
-      executable_path = base::FilePath(executable_path_string);
-#endif
-    }
-
-    const base::DictionaryValue* manifest = nullptr;
-    if (!service_entry->GetDictionary(kCatalogServiceManifestKey, &manifest)) {
-      LOG(ERROR) << "Catalog entry for \"" << it.key() << "\" has an invalid "
-                 << "\"manifest\" value.";
-      continue;
-    }
-
-    DCHECK(!(is_embedded && !executable_path.empty()));
-
-    if (is_embedded)
-      executable_path = base::CommandLine::ForCurrentProcess()->GetProgram();
-
-    auto entry = Entry::Deserialize(*manifest);
-    if (entry) {
-      if (!executable_path.empty())
-        entry->set_path(std::move(executable_path));
-      bool added = cache->AddRootEntry(std::move(entry));
-      DCHECK(added);
-    } else {
-      LOG(ERROR) << "Failed to read manifest entry for \"" << it.key() << "\".";
-    }
-  }
-}
-
 }  // namespace
 
 // Wraps state needed for servicing directory requests on a separate thread.
@@ -143,13 +67,8 @@
   DISALLOW_COPY_AND_ASSIGN(DirectoryThreadState);
 };
 
-Catalog::Catalog(std::unique_ptr<base::Value> catalog_contents,
-                 const std::vector<service_manager::Manifest>& manifests,
-                 ManifestProvider* service_manifest_provider)
-    : service_manifest_provider_(service_manifest_provider) {
-  if (catalog_contents) {
-    LoadCatalogManifestIntoCache(catalog_contents.get(), &system_cache_);
-  } else if (!manifests.empty()) {
+Catalog::Catalog(const std::vector<service_manager::Manifest>& manifests) {
+  if (!manifests.empty()) {
     for (const auto& manifest : manifests)
       system_cache_.AddRootEntryFromManifest(manifest);
   } else {
@@ -181,9 +100,8 @@
   if (it != instances_.end())
     return it->second.get();
 
-  auto result = instances_.emplace(
-      instance_group,
-      std::make_unique<Instance>(&system_cache_, service_manifest_provider_));
+  auto result = instances_.emplace(instance_group,
+                                   std::make_unique<Instance>(&system_cache_));
   return result.first->second.get();
 }
 
diff --git a/services/catalog/catalog.h b/services/catalog/catalog.h
index daa3a42..728dd5a 100644
--- a/services/catalog/catalog.h
+++ b/services/catalog/catalog.h
@@ -26,23 +26,18 @@
 
 namespace base {
 class SequencedTaskRunner;
-class Value;
 }
 
 namespace catalog {
 
 class Instance;
-class ManifestProvider;
 
 // Creates and owns an instance of the catalog. Exposes a ServicePtr that
 // can be passed to the service manager, potentially in a different process.
 class COMPONENT_EXPORT(CATALOG) Catalog : public service_manager::Service {
  public:
-  // Constructs a catalog over a set of Manifests and optionally a
-  // ManifestProvider for dynamic manifest lookup.
-  explicit Catalog(std::unique_ptr<base::Value> catalog_contents,
-                   const std::vector<service_manager::Manifest>& manifests,
-                   ManifestProvider* service_manifest_provider = nullptr);
+  // Constructs a catalog over a set of Manifests to use for lookup.
+  explicit Catalog(const std::vector<service_manager::Manifest>& manifests);
   ~Catalog() override;
 
   void BindServiceRequest(service_manager::mojom::ServiceRequest request);
@@ -79,7 +74,6 @@
       const service_manager::BindSourceInfo&>
       registry_;
 
-  ManifestProvider* service_manifest_provider_;
   EntryCache system_cache_;
   std::map<base::Token, std::unique_ptr<Instance>> instances_;
 
diff --git a/services/catalog/entry.cc b/services/catalog/entry.cc
index f3884de..c1d438d 100644
--- a/services/catalog/entry.cc
+++ b/services/catalog/entry.cc
@@ -5,113 +5,10 @@
 #include "services/catalog/entry.h"
 
 #include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "services/catalog/public/cpp/manifest_parsing_util.h"
 #include "services/catalog/store.h"
 #include "services/service_manager/public/mojom/interface_provider_spec.mojom.h"
 
 namespace catalog {
-namespace {
-
-#if defined(OS_WIN)
-const char kServiceExecutableExtension[] = ".service.exe";
-#else
-const char kServiceExecutableExtension[] = ".service";
-#endif
-
-bool ReadStringSet(const base::ListValue& list_value,
-                   std::set<std::string>* string_set) {
-  DCHECK(string_set);
-  for (const auto& value_value : list_value) {
-    std::string value;
-    if (!value_value.GetAsString(&value)) {
-      LOG(ERROR) << "Entry::Deserialize: list member must be a string";
-      return false;
-    }
-    string_set->insert(std::move(value));
-  }
-  return true;
-}
-
-bool ReadStringSetFromValue(const base::Value& value,
-                            std::set<std::string>* string_set) {
-  const base::ListValue* list_value = nullptr;
-  if (!value.GetAsList(&list_value)) {
-    LOG(ERROR) << "Entry::Deserialize: Value must be a list.";
-    return false;
-  }
-  return ReadStringSet(*list_value, string_set);
-}
-
-// If |key| refers to a dictionary value within |value|, |*out| is set to that
-// DictionaryValue. Returns true if either |key| is not present or the
-// corresponding value is a dictionary.
-bool GetDictionaryValue(const base::DictionaryValue& value,
-                        base::StringPiece key,
-                        const base::DictionaryValue** out) {
-  const base::Value* entry_value = nullptr;
-  return !value.Get(key, &entry_value) || entry_value->GetAsDictionary(out);
-}
-
-bool BuildInterfaceProviderSpec(
-    const base::DictionaryValue& value,
-    service_manager::InterfaceProviderSpec* interface_provider_specs) {
-  DCHECK(interface_provider_specs);
-  const base::DictionaryValue* provides_value = nullptr;
-  if (!GetDictionaryValue(value, Store::kInterfaceProviderSpecs_ProvidesKey,
-                          &provides_value)) {
-    LOG(ERROR) << "Entry::Deserialize: "
-               << Store::kInterfaceProviderSpecs_ProvidesKey
-               << " must be a dictionary.";
-    return false;
-  }
-  if (provides_value) {
-    base::DictionaryValue::Iterator it(*provides_value);
-    for(; !it.IsAtEnd(); it.Advance()) {
-      service_manager::InterfaceSet interfaces;
-      if (!ReadStringSetFromValue(it.value(), &interfaces)) {
-        LOG(ERROR) << "Entry::Deserialize: Invalid interface list in provided "
-                   << " capabilities dictionary";
-        return false;
-      }
-      interface_provider_specs->provides[it.key()] = std::move(interfaces);
-    }
-  }
-
-  const base::DictionaryValue* requires_value = nullptr;
-  if (!GetDictionaryValue(value, Store::kInterfaceProviderSpecs_RequiresKey,
-                          &requires_value)) {
-    LOG(ERROR) << "Entry::Deserialize: "
-               << Store::kInterfaceProviderSpecs_RequiresKey
-               << " must be a dictionary.";
-    return false;
-  }
-  if (requires_value) {
-    base::DictionaryValue::Iterator it(*requires_value);
-    for (; !it.IsAtEnd(); it.Advance()) {
-      service_manager::CapabilitySet capabilities;
-      const base::ListValue* entry_value = nullptr;
-      if (!it.value().GetAsList(&entry_value)) {
-        LOG(ERROR) << "Entry::Deserialize: "
-                   << Store::kInterfaceProviderSpecs_RequiresKey
-                   << " entry must be a list.";
-        return false;
-      }
-      if (!ReadStringSet(*entry_value, &capabilities)) {
-        LOG(ERROR) << "Entry::Deserialize: Invalid capabilities list in "
-                   << "requires dictionary.";
-        return false;
-      }
-
-      interface_provider_specs->requires[it.key()] = std::move(capabilities);
-    }
-  }
-  return true;
-}
-
-}  // namespace
 
 Entry::Entry() {}
 Entry::Entry(const std::string& name)
@@ -119,147 +16,6 @@
       display_name_(name) {}
 Entry::~Entry() {}
 
-// static
-std::unique_ptr<Entry> Entry::Deserialize(const base::Value& manifest_root) {
-  const base::DictionaryValue* dictionary_value = nullptr;
-  if (!manifest_root.GetAsDictionary(&dictionary_value))
-    return nullptr;
-  const base::DictionaryValue& value = *dictionary_value;
-
-  auto entry = std::make_unique<Entry>();
-
-  // Name.
-  std::string name;
-  if (!value.GetString(Store::kNameKey, &name)) {
-    LOG(ERROR) << "Entry::Deserialize: dictionary has no "
-               << Store::kNameKey << " key";
-    return nullptr;
-  }
-  if (name.empty()) {
-    LOG(ERROR) << "Entry::Deserialize: empty service name.";
-    return nullptr;
-  }
-  entry->set_name(std::move(name));
-
-  // By default we assume a standalone service executable. The catalog may
-  // override this layer based on configuration external to the service's own
-  // manifest.
-  base::FilePath service_exe_root;
-  CHECK(base::PathService::Get(base::DIR_ASSETS, &service_exe_root));
-  entry->set_path(service_exe_root.AppendASCII(entry->name() +
-                                               kServiceExecutableExtension));
-
-  // Human-readable name.
-  std::string display_name;
-  if (!value.GetString(Store::kDisplayNameKey, &display_name)) {
-    LOG(ERROR) << "Entry::Deserialize: dictionary has no "
-               << Store::kDisplayNameKey << " key";
-    return nullptr;
-  }
-  entry->set_display_name(std::move(display_name));
-
-  // Sandbox type, optional.
-  std::string sandbox_type;
-  if (value.GetString(Store::kSandboxTypeKey, &sandbox_type))
-    entry->set_sandbox_type(std::move(sandbox_type));
-
-  // Options, optional.
-  if (const base::Value* options = value.FindKey(Store::kOptionsKey)) {
-    ServiceOptions options_struct;
-
-    if (const base::Value* instance_sharing_value =
-            options->FindKey("instance_sharing")) {
-      const std::string& instance_sharing = instance_sharing_value->GetString();
-      if (instance_sharing == "none") {
-        options_struct.instance_sharing =
-            ServiceOptions::InstanceSharingType::NONE;
-      } else if (instance_sharing == "singleton") {
-        options_struct.instance_sharing =
-            ServiceOptions::InstanceSharingType::SINGLETON;
-      } else if (instance_sharing == "shared_instance_across_users" ||
-                 instance_sharing == "shared_across_instance_groups") {
-        options_struct.instance_sharing =
-            ServiceOptions::InstanceSharingType::SHARED_ACROSS_INSTANCE_GROUPS;
-      } else {
-        LOG(ERROR) << "Entry::Deserialize invalid instance sharing type: "
-                   << instance_sharing;
-      }
-    }
-
-    if (const base::Value* can_connect_to_instances_in_any_group =
-            options->FindKey("can_connect_to_other_services_as_any_user")) {
-      options_struct.can_connect_to_instances_in_any_group =
-          can_connect_to_instances_in_any_group->GetBool();
-    }
-
-    if (const base::Value*
-            can_connect_to_other_services_with_any_instance_name_value =
-                options->FindKey(
-                    "can_connect_to_other_services_with_any_instance_name")) {
-      options_struct.can_connect_to_other_services_with_any_instance_name =
-          can_connect_to_other_services_with_any_instance_name_value->GetBool();
-    }
-
-    if (const base::Value* can_create_other_service_instances_value =
-            options->FindKey("can_create_other_service_instances")) {
-      options_struct.can_create_other_service_instances =
-          can_create_other_service_instances_value->GetBool();
-    }
-
-    entry->AddOptions(std::move(options_struct));
-  }
-
-  // InterfaceProvider specs.
-  const base::DictionaryValue* interface_provider_specs = nullptr;
-  if (!value.GetDictionary(Store::kInterfaceProviderSpecsKey,
-                           &interface_provider_specs)) {
-    LOG(ERROR) << "Entry::Deserialize: dictionary has no "
-               << Store::kInterfaceProviderSpecsKey << " key";
-    return nullptr;
-  }
-
-  base::DictionaryValue::Iterator it(*interface_provider_specs);
-  for (; !it.IsAtEnd(); it.Advance()) {
-    const base::DictionaryValue* spec_value = nullptr;
-    if (!interface_provider_specs->GetDictionary(it.key(), &spec_value)) {
-      LOG(ERROR) << "Entry::Deserialize: value of InterfaceProvider map for "
-                 << "key: " << it.key() << " not a dictionary.";
-      return nullptr;
-    }
-
-    service_manager::InterfaceProviderSpec spec;
-    if (!BuildInterfaceProviderSpec(*spec_value, &spec)) {
-      LOG(ERROR) << "Entry::Deserialize: failed to build InterfaceProvider "
-                 << "spec for key: " << it.key();
-      return nullptr;
-    }
-    entry->AddInterfaceProviderSpec(it.key(), std::move(spec));
-  }
-
-  // Required files.
-  base::Optional<RequiredFileMap> required_files =
-      catalog::RetrieveRequiredFiles(value);
-  DCHECK(required_files);
-  for (auto& iter : *required_files) {
-    entry->AddRequiredFilePath(iter.first, std::move(iter.second));
-  }
-
-  const base::ListValue* services = nullptr;
-  if (value.GetList(Store::kServicesKey, &services)) {
-    for (size_t i = 0; i < services->GetSize(); ++i) {
-      const base::DictionaryValue* service = nullptr;
-      services->GetDictionary(i, &service);
-      std::unique_ptr<Entry> child = Entry::Deserialize(*service);
-      if (child) {
-        child->set_parent(entry.get());
-        entry->children().emplace_back(std::move(child));
-      }
-    }
-  }
-
-  return entry;
-}
-
 bool Entry::ProvidesCapability(const std::string& capability) const {
   auto it = interface_provider_specs_.find(
       service_manager::mojom::kServiceManager_ConnectorSpec);
diff --git a/services/catalog/entry.h b/services/catalog/entry.h
index 86a29e3..46de570 100644
--- a/services/catalog/entry.h
+++ b/services/catalog/entry.h
@@ -16,10 +16,6 @@
 #include "services/catalog/service_options.h"
 #include "services/service_manager/public/cpp/interface_provider_spec.h"
 
-namespace base {
-class Value;
-}
-
 namespace catalog {
 
 // Static information about a service package known to the Catalog.
@@ -29,8 +25,6 @@
   explicit Entry(const std::string& name);
   ~Entry();
 
-  static std::unique_ptr<Entry> Deserialize(const base::Value& manifest_root);
-
   bool ProvidesCapability(const std::string& capability) const;
 
   bool operator==(const Entry& other) const;
diff --git a/services/catalog/entry_unittest.cc b/services/catalog/entry_unittest.cc
deleted file mode 100644
index f89668b4..0000000
--- a/services/catalog/entry_unittest.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/catalog/entry.h"
-
-#include "base/files/file_path.h"
-#include "base/json/json_file_value_serializer.h"
-#include "base/macros.h"
-#include "base/path_service.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "services/service_manager/public/cpp/interface_provider_spec.h"
-#include "services/service_manager/public/mojom/interface_provider_spec.mojom.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace catalog {
-
-class EntryTest : public testing::Test {
- public:
-  EntryTest() {}
-  ~EntryTest() override {}
-
- protected:
-  std::unique_ptr<Entry> ReadEntry(const std::string& manifest,
-                                   std::unique_ptr<base::Value>* out_value) {
-    std::unique_ptr<base::Value> value = ReadManifest(manifest);
-    base::DictionaryValue* dictionary = nullptr;
-    CHECK(value->GetAsDictionary(&dictionary));
-    if (out_value)
-      *out_value = std::move(value);
-    return Entry::Deserialize(*dictionary);
-  }
-
-  std::unique_ptr<base::Value> ReadManifest(const std::string& manifest) {
-    base::FilePath manifest_path;
-    base::PathService::Get(base::DIR_SOURCE_ROOT, &manifest_path);
-    manifest_path =
-        manifest_path.AppendASCII("services/catalog/test_data/" + manifest);
-
-    JSONFileValueDeserializer deserializer(manifest_path);
-    int error = 0;
-    std::string message;
-    // TODO(beng): probably want to do more detailed error checking. This should
-    //             be done when figuring out if to unblock connection
-    //             completion.
-    return deserializer.Deserialize(&error, &message);
-  }
-
- private:
-  void SetUp() override {}
-  void TearDown() override {}
-
-  DISALLOW_COPY_AND_ASSIGN(EntryTest);
-};
-
-TEST_F(EntryTest, Simple) {
-  std::unique_ptr<Entry> entry = ReadEntry("simple", nullptr);
-  EXPECT_EQ("foo", entry->name());
-  EXPECT_EQ("Foo", entry->display_name());
-  EXPECT_EQ("none", entry->sandbox_type());
-}
-
-TEST_F(EntryTest, Instance) {
-  std::unique_ptr<Entry> entry = ReadEntry("instance", nullptr);
-  EXPECT_EQ("foo", entry->name());
-  EXPECT_EQ("Foo", entry->display_name());
-  EXPECT_EQ("", entry->sandbox_type());
-}
-
-TEST_F(EntryTest, Options) {
-  std::unique_ptr<Entry> entry = ReadEntry("options", nullptr);
-  EXPECT_EQ("foo", entry->name());
-  EXPECT_EQ("Foo", entry->display_name());
-
-  EXPECT_EQ(ServiceOptions::InstanceSharingType::SINGLETON,
-            entry->options().instance_sharing);
-  EXPECT_TRUE(entry->options().can_connect_to_instances_in_any_group);
-  EXPECT_TRUE(
-      entry->options().can_connect_to_other_services_with_any_instance_name);
-  EXPECT_TRUE(entry->options().can_create_other_service_instances);
-
-  EXPECT_EQ("", entry->sandbox_type());
-}
-
-TEST_F(EntryTest, ConnectionSpec) {
-  std::unique_ptr<Entry> entry = ReadEntry("connection_spec", nullptr);
-
-  EXPECT_EQ("foo", entry->name());
-  EXPECT_EQ("Foo", entry->display_name());
-  service_manager::InterfaceProviderSpec spec;
-  service_manager::CapabilitySet capabilities;
-  capabilities.insert("bar:bar");
-  spec.requires["bar"] = capabilities;
-  service_manager::InterfaceProviderSpecMap specs;
-  specs[service_manager::mojom::kServiceManager_ConnectorSpec] = spec;
-  EXPECT_EQ(specs, entry->interface_provider_specs());
-}
-
-TEST_F(EntryTest, RequiredFiles) {
-  std::unique_ptr<Entry> entry = ReadEntry("required_files", nullptr);
-  EXPECT_EQ("foo", entry->name());
-  EXPECT_EQ("Foo", entry->display_name());
-  auto required_files = entry->required_file_paths();
-  EXPECT_EQ(2U, required_files.size());
-  auto iter = required_files.find("all_platforms");
-  ASSERT_NE(required_files.end(), iter);
-  bool checked_platform_specific_file = false;
-#if defined(OS_WIN)
-  EXPECT_EQ(base::FilePath(L"/all/platforms/windows"), iter->second);
-  iter = required_files.find("windows_only");
-  ASSERT_NE(required_files.end(), iter);
-  EXPECT_EQ(base::FilePath(L"/windows/only"), iter->second);
-  checked_platform_specific_file = true;
-#elif defined(OS_FUCHSIA)
-  EXPECT_EQ(base::FilePath("/all/platforms/fuchsia"), iter->second);
-  iter = required_files.find("fuchsia_only");
-  ASSERT_NE(required_files.end(), iter);
-  EXPECT_EQ(base::FilePath("/fuchsia/only"), iter->second);
-  checked_platform_specific_file = true;
-#elif defined(OS_LINUX)
-  EXPECT_EQ(base::FilePath("/all/platforms/linux"), iter->second);
-  iter = required_files.find("linux_only");
-  ASSERT_NE(required_files.end(), iter);
-  EXPECT_EQ(base::FilePath("/linux/only"), iter->second);
-  checked_platform_specific_file = true;
-#elif defined(OS_MACOSX)
-  EXPECT_EQ(base::FilePath("/all/platforms/macosx"), iter->second);
-  iter = required_files.find("macosx_only");
-  ASSERT_NE(required_files.end(), iter);
-  EXPECT_EQ(base::FilePath("/macosx/only"), iter->second);
-  checked_platform_specific_file = true;
-#elif defined(OS_ANDROID)
-  EXPECT_EQ(base::FilePath("/all/platforms/android"), iter->second);
-  iter = required_files.find("android_only");
-  ASSERT_NE(required_files.end(), iter);
-  EXPECT_EQ(base::FilePath("/android/only"), iter->second);
-  checked_platform_specific_file = true;
-#endif
-  EXPECT_TRUE(checked_platform_specific_file);
-}
-
-TEST_F(EntryTest, Malformed) {
-  std::unique_ptr<base::Value> value = ReadManifest("malformed");
-  EXPECT_FALSE(value.get());
-}
-
-
-}  // namespace catalog
diff --git a/services/catalog/instance.cc b/services/catalog/instance.cc
index 7dcbb76..8cc1422 100644
--- a/services/catalog/instance.cc
+++ b/services/catalog/instance.cc
@@ -10,7 +10,6 @@
 #include "base/values.h"
 #include "services/catalog/entry.h"
 #include "services/catalog/entry_cache.h"
-#include "services/catalog/manifest_provider.h"
 
 namespace catalog {
 namespace {
@@ -24,12 +23,9 @@
 
 }  // namespace
 
-Instance::Instance(EntryCache* system_cache,
-                   ManifestProvider* service_manifest_provider)
-    : system_cache_(system_cache),
-      service_manifest_provider_(service_manifest_provider) {}
+Instance::Instance(EntryCache* system_cache) : system_cache_(system_cache) {}
 
-Instance::~Instance() {}
+Instance::~Instance() = default;
 
 void Instance::BindCatalog(mojom::CatalogRequest request) {
   catalog_bindings_.AddBinding(this, std::move(request));
@@ -41,25 +37,8 @@
   if (cached_entry)
     return cached_entry;
 
-  std::unique_ptr<base::Value> new_manifest;
-  if (service_manifest_provider_)
-    new_manifest = service_manifest_provider_->GetManifest(service_name);
-
-  if (!new_manifest) {
-    LOG(ERROR) << "Unable to locate service manifest for " << service_name;
-    return nullptr;
-  }
-
-  auto new_entry = Entry::Deserialize(*new_manifest);
-  if (!new_entry) {
-    LOG(ERROR) << "Malformed manifest for " << service_name;
-    return nullptr;
-  }
-
-  cached_entry = const_cast<const Entry*>(new_entry.get());
-  bool added = system_cache_->AddRootEntry(std::move(new_entry));
-  DCHECK(added);
-  return cached_entry;
+  LOG(ERROR) << "Unable to locate service manifest for " << service_name;
+  return nullptr;
 }
 
 void Instance::GetEntries(const base::Optional<std::vector<std::string>>& names,
diff --git a/services/catalog/instance.h b/services/catalog/instance.h
index ad7d05c..14faa9d 100644
--- a/services/catalog/instance.h
+++ b/services/catalog/instance.h
@@ -17,14 +17,11 @@
 namespace catalog {
 
 class EntryCache;
-class ManifestProvider;
 
 class COMPONENT_EXPORT(CATALOG) Instance : public mojom::Catalog {
  public:
-  // Neither |system_cache| nor |service_manifest_provider| is owned.
-  // |service_manifest_provider| may be null
-  Instance(EntryCache* system_cache,
-           ManifestProvider* service_manifest_provider);
+  // |system_cache| is not owned.
+  explicit Instance(EntryCache* system_cache);
   ~Instance() override;
 
   void BindCatalog(mojom::CatalogRequest request);
@@ -46,10 +43,6 @@
   // TODO(beng): eventually add per-user applications.
   EntryCache* const system_cache_;
 
-  // A runtime interface the embedder can use to provide dynamic manifest data
-  // to be queried on-demand if something can't be found in |system_cache_|.
-  ManifestProvider* const service_manifest_provider_;
-
   DISALLOW_COPY_AND_ASSIGN(Instance);
 };
 
diff --git a/services/catalog/manifest.json b/services/catalog/manifest.json
deleted file mode 100644
index 0a5c2d2..0000000
--- a/services/catalog/manifest.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-  "name": "catalog",
-  "display_name": "Application Resolver",
-  "options" : {
-    "instance_sharing" : "shared_instance_across_users"
-  },
-  "interface_provider_specs": {
-    // NOTE: This manifest is for documentation purposes only. Relevant
-    // capability spec is defined inline in the ServiceManager implementation.
-    //
-    // TODO(rockot): Fix this. We can bake this file into ServiceManager at
-    // build time or something. Same with service:service_manager.
-    "service_manager:connector": {
-      "provides": {
-        "directory": [ "filesystem.mojom.Directory" ],
-        "control": [ "catalog.mojom.CatalogControl" ]
-      }
-    }
-  }
-}
diff --git a/services/catalog/manifest_provider.h b/services/catalog/manifest_provider.h
deleted file mode 100644
index f1caa22..0000000
--- a/services/catalog/manifest_provider.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_CATALOG_MANIFEST_PROVIDER_H_
-#define SERVICES_CATALOG_MANIFEST_PROVIDER_H_
-
-#include <string>
-
-#include "base/component_export.h"
-
-namespace base {
-class Value;
-}
-
-namespace catalog {
-
-// An interface which can be implemented by a catalog embedder to override
-// manifest fetching behavior.
-class COMPONENT_EXPORT(CATALOG) ManifestProvider {
- public:
-  virtual ~ManifestProvider() {}
-
-  // Retrieves the raw contents of the manifest for application named |name|.
-  // Returns true if |name| is known and |*manifest_contents| is populated.
-  // returns false otherwise.
-  virtual std::unique_ptr<base::Value> GetManifest(const std::string& name) = 0;
-};
-
-}  // namespace catalog
-
-#endif  // SERVICES_CATALOG_MANIFEST_PROVIDER_H_
diff --git a/services/catalog/public/cpp/BUILD.gn b/services/catalog/public/cpp/BUILD.gn
index 7eb6bda..1b61a04 100644
--- a/services/catalog/public/cpp/BUILD.gn
+++ b/services/catalog/public/cpp/BUILD.gn
@@ -4,8 +4,6 @@
 
 source_set("cpp") {
   sources = [
-    "manifest_parsing_util.cc",
-    "manifest_parsing_util.h",
     "resource_loader.cc",
     "resource_loader.h",
   ]
diff --git a/services/catalog/public/cpp/manifest_parsing_util.cc b/services/catalog/public/cpp/manifest_parsing_util.cc
deleted file mode 100644
index 4a19ec6..0000000
--- a/services/catalog/public/cpp/manifest_parsing_util.cc
+++ /dev/null
@@ -1,111 +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 "services/catalog/public/cpp/manifest_parsing_util.h"
-
-#include "base/values.h"
-#include "build/build_config.h"
-#include "services/catalog/store.h"
-
-namespace catalog {
-
-namespace {
-
-bool IsValidPlatformName(const std::string& name) {
-  return name == Store::kRequiredFilesKey_PlatformValue_Windows ||
-         name == Store::kRequiredFilesKey_PlatformValue_Linux ||
-         name == Store::kRequiredFilesKey_PlatformValue_MacOSX ||
-         name == Store::kRequiredFilesKey_PlatformValue_Android ||
-         name == Store::kRequiredFilesKey_PlatformValue_Fuchsia;
-}
-
-bool IsCurrentPlatform(const std::string& name) {
-#if defined(OS_WIN)
-  return name == Store::kRequiredFilesKey_PlatformValue_Windows;
-#elif defined(OS_LINUX)
-  return name == Store::kRequiredFilesKey_PlatformValue_Linux;
-#elif defined(OS_MACOSX)
-  return name == Store::kRequiredFilesKey_PlatformValue_MacOSX;
-#elif defined(OS_ANDROID)
-  return name == Store::kRequiredFilesKey_PlatformValue_Android;
-#elif defined(OS_FUCHSIA)
-  return name == Store::kRequiredFilesKey_PlatformValue_Fuchsia;
-#else
-#error This architecture is not supported.
-#endif
-}
-
-}  // namespace
-
-base::Optional<RequiredFileMap> RetrieveRequiredFiles(
-    const base::Value& manifest_value) {
-  const base::DictionaryValue* manifest_dictionary = nullptr;
-  if (!manifest_value.GetAsDictionary(&manifest_dictionary)) {
-    DLOG(ERROR) << "Entry::Deserialize: manifest node is not a dictionary.";
-    return base::nullopt;
-  }
-
-  RequiredFileMap required_files;
-  if (!manifest_dictionary->HasKey(Store::kRequiredFilesKey))
-    return {required_files};
-
-  const base::DictionaryValue* required_files_value = nullptr;
-  if (!manifest_dictionary->GetDictionary(Store::kRequiredFilesKey,
-                                          &required_files_value)) {
-    DLOG(ERROR) << "Entry::Deserialize: RequiredFiles not a dictionary.";
-    return base::nullopt;
-  }
-
-  base::DictionaryValue::Iterator it(*required_files_value);
-  for (; !it.IsAtEnd(); it.Advance()) {
-    const std::string& entry_name = it.key();
-    const base::ListValue* all_platform_values = nullptr;
-    if (!it.value().GetAsList(&all_platform_values)) {
-      DLOG(ERROR) << "Entry::Deserialize: value of RequiredFiles for key: "
-                  << entry_name << " not a list.";
-      return base::nullopt;
-    }
-
-    for (size_t i = 0; i < all_platform_values->GetSize(); i++) {
-      const base::DictionaryValue* file_descriptor_value = nullptr;
-      if (!all_platform_values->GetDictionary(i, &file_descriptor_value)) {
-        DLOG(ERROR) << "Entry::Deserialize: value of entry at index " << i
-                    << " of RequiredFiles for key: " << entry_name
-                    << " not a dictionary.";
-        return base::nullopt;
-      }
-      std::string platform;
-      if (file_descriptor_value->GetString(Store::kRequiredFilesKey_PlatformKey,
-                                           &platform)) {
-        if (!IsValidPlatformName(platform)) {
-          DLOG(ERROR) << "Entry::Deserialize: value of platform for "
-                      << "required file entry entry is invalid " << platform;
-          return base::nullopt;
-        }
-      }
-      if (!IsCurrentPlatform(platform)) {
-        continue;
-      }
-      base::FilePath::StringType path;
-      if (!file_descriptor_value->GetString(Store::kRequiredFilesKey_PathKey,
-                                            &path)) {
-        DLOG(ERROR) << "Entry::Deserialize: value of RequiredFiles entry for "
-                    << "key: " << entry_name
-                    << " missing: " << Store::kRequiredFilesKey_PathKey
-                    << " value.";
-        return base::nullopt;
-      }
-      if (required_files.count(entry_name) > 0) {
-        DLOG(ERROR) << "Entry::Deserialize: value of RequiredFiles entry for "
-                    << "key: " << entry_name << " has more than one value for "
-                    << "platform: " << platform;
-        return base::nullopt;
-      }
-      required_files[entry_name] = base::FilePath(path);
-    }
-  }
-  return base::make_optional(std::move(required_files));
-}
-
-}  // namespace content
diff --git a/services/catalog/public/cpp/manifest_parsing_util.h b/services/catalog/public/cpp/manifest_parsing_util.h
deleted file mode 100644
index f76c156..0000000
--- a/services/catalog/public/cpp/manifest_parsing_util.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_CATALOG_PUBLIC_CPP_MANIFEST_PARSING_UTIL_H_
-#define SERVICES_CATALOG_PUBLIC_CPP_MANIFEST_PARSING_UTIL_H_
-
-#include <map>
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/optional.h"
-
-namespace base {
-class Value;
-}
-
-// TODO(jcivelli): http://crbug.com/687250 Remove this file and inline
-//                 PopulateRequiredFiles() in Entry::Deserialize.
-namespace catalog {
-
-using RequiredFileMap = std::map<std::string, base::FilePath>;
-
-base::Optional<RequiredFileMap> RetrieveRequiredFiles(
-    const base::Value& manifest);
-
-}  // namespace content
-
-#endif  // SERVICES_CATALOG_PUBLIC_CPP_MANIFEST_PARSING_UTIL_H_
diff --git a/services/catalog/public/tools/catalog.cc.tmpl b/services/catalog/public/tools/catalog.cc.tmpl
index 06327c5..85ebc0c 100644
--- a/services/catalog/public/tools/catalog.cc.tmpl
+++ b/services/catalog/public/tools/catalog.cc.tmpl
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// This is a generated file. Please see the "catalog_cpp_source" template in
-// src/services/catalog/public/tools/catalog.gni for more details.
+// This is a generated file. Please see the "service_manifest" template in
+// src/services/service_manager/public/service_manifest.gni for more details.
 
 #include "{{path}}.h"
 
@@ -13,8 +13,15 @@
 #include "base/no_destructor.h"
 #include "build/build_config.h"
 #include "services/service_manager/public/cpp/manifest_builder.h"
+{%  for info in packaged_services %}
+#include "{{info.header}}"
+{%- endfor %}
+{%  for info in overlays %}
+#include "{{info.header}}"
+{%- endfor %}
 
-{%- macro generate_manifest_builder(manifest) -%}
+{%- macro generate_manifest_builder(manifest, packaged_services=[],
+                                    overlays=[]) -%}
 service_manager::ManifestBuilder()
     .WithServiceName("{{manifest['name']}}")
 {%-   if 'display_name' in manifest %}
@@ -102,21 +109,36 @@
     .PackageService(
         {{generate_manifest_builder(packaged_service_manifest)|indent(8)}})
 {%-  endfor %}
+{%-  for info in packaged_services %}
+    .PackageService({{info.namespace}}::GetManifest())
+{%-  endfor %}
     .Build()
+{%-  for info in overlays %}
+        .Amend({{info.namespace}}::GetManifest())
+{%-  endfor %}
 {%- endmacro %}
 
 {% for namespace in namespaces %}
 namespace {{namespace}} {
 {%- endfor %}
 
-const std::vector<service_manager::Manifest>& {{function_name}}() {
-  static base::NoDestructor<std::vector<service_manager::Manifest>> catalog{ {
-{%- for entry in catalog['services'].itervalues() %}
-      {{generate_manifest_builder(entry['manifest'])|indent(6)}}
-{%- if not loop.last %},{% endif %}
-{%- endfor %} } };
-  return *catalog;
+{%  if root_manifest %}
+const service_manager::Manifest& {{function_name}}() {
+  static base::NoDestructor<service_manager::Manifest> manifest{
+      {{generate_manifest_builder(root_manifest,
+            packaged_services=packaged_services, overlays=overlays)
+            |indent(6)}} };
+  return *manifest;
 }
+{%  else %}
+const std::vector<service_manager::Manifest>& {{function_name}}() {
+  static base::NoDestructor<std::vector<service_manager::Manifest>> manifests{ {
+{%- for info in packaged_services %}
+      {{info.namespace}}::GetManifest(){%- if not loop.last %},{%- endif %}
+{%- endfor -%} }};
+  return *manifests;
+}
+{%  endif %}
 
 {%- for namespace in namespaces|reverse %}
 }  // namespace {{namespace}}
diff --git a/services/catalog/public/tools/catalog.gni b/services/catalog/public/tools/catalog.gni
index 212d28c..ca11a734 100644
--- a/services/catalog/public/tools/catalog.gni
+++ b/services/catalog/public/tools/catalog.gni
@@ -4,173 +4,53 @@
 
 import("//build/config/dcheck_always_on.gni")
 
-# Generates a static catalog manifest to be loaded at runtime. This manifest
-# contains the union of all individual service manifests specified by the
-# template parameters.
+# Generates code to produce a list service_manager::Manifest objects given a set
+# of service_manager targets to include in the list.
 #
-# The output of a catalog rule is always a file named:
+# This is a temporary helper to transition away from JSON manifests. The catalog
+# target always has a companion catalog_cpp_source target, which yields a
+# source_set defining the generated function.
 #
-#     ${target_gen_dir}/${target_name}.json
-#
-# A Service Manager embedder uses a catalog manifest as its singular source of
-# truth regarding available services in the system.
-#
-# Parameters:
-#
-#   embedded_services (optional)
-#       A list of service manifest targets whose outputs correspond to services
-#       embedded by the Service Manager embedder's binary. Outputs of targets
-#       listed here will be embedded in the catalog within its
-#       "embedded_services" list.
-#
-#   standalone_services (optional)
-#       A list of service manifest targets whose outputs correspond to services
-#       with standalone binaries which must be available to the Service Manager
-#       at runtime. Outputs of targets listed here will be embedded in the
-#       catalog within its "standalone_services" list.
-#
-#       Typically a standalone service binary is expected to live next to
-#       the Service Manager embedder's binary, with the name
-#       "${service_name}.service", with an additional ".exe" suffix on Windows.
-#       Binaries following this naming scheme are typically output by
-#       service_executable targets. See
-#       //services/service_manager/public/cpp/service_executable.gni.
-#
-#    executable_overrides (optional)
-#       A list of overrides to apply in catalog metadata for individual
-#       services. An override string must be of the form
-#
-#           "<service_name>:<executable_path>"
-#
-#       The special token @EXE_DIR may be used in |executable_path| to denote
-#       a path relative to the Service Manager embedder's binary, substituted
-#       at runtime. For example:
-#
-#           "content_browser:@EXE_DIR/chrome"
-#
-#       would indicate to the Service Manager embedder that the
-#       "content_browser" service can be started by running the "chrome"
-#       executable in the embedder's own directory.
-#
-#       This overrides the default binary name expectation described in
-#       |standalone_services| above.
-#
-#    catalog_deps (optional)
-#       A list of other catalog targets whose outputs will be included within
-#       this catalog. Targets in this list
-#
+# No new uses of these targets should be introduced.
 template("catalog") {
-  output_filename = "$target_gen_dir/${target_name}.json"
-  action(target_name) {
+  group(target_name) {
     testonly = defined(invoker.testonly) && invoker.testonly
-
-    script = "//services/catalog/public/tools/generate_manifest.py"
-
-    inputs = []
-    outputs = [
-      output_filename,
-    ]
-
-    args = [ "--output=" + rebase_path(output_filename, root_build_dir) ]
-
-    if (is_debug || dcheck_always_on) {
-      args += [ "--pretty" ]
-    }
-
-    deps = []
-    if (defined(invoker.deps)) {
-      deps += invoker.deps
-    }
-
-    if (defined(invoker.embedded_services)) {
-      args += [ "--embedded-services" ]
-      foreach(manifest_target, invoker.embedded_services) {
-        manifest_target_dir = get_label_info(manifest_target, "target_gen_dir")
-        manifest_target_name = get_label_info(manifest_target, "name")
-        manifest_filename = "$manifest_target_dir/${manifest_target_name}.json"
-
-        inputs += [ "$manifest_filename" ]
-        deps += [ manifest_target ]
-        args += [ rebase_path(manifest_filename, root_build_dir) ]
-
-        # Ensure that each entry does in fact reference a service manifest rule.
-        label_no_toolchain =
-            get_label_info(manifest_target, "label_no_toolchain")
-        toolchain = get_label_info(manifest_target, "toolchain")
-        deps += [ "${label_no_toolchain}__is_service_manifest(${toolchain})" ]
-      }
-    }
-
-    if (defined(invoker.standalone_services)) {
-      args += [ "--standalone-services" ]
-      foreach(manifest_target, invoker.standalone_services) {
-        manifest_target_dir = get_label_info(manifest_target, "target_gen_dir")
-        manifest_target_name = get_label_info(manifest_target, "name")
-        manifest_filename = "$manifest_target_dir/${manifest_target_name}.json"
-
-        inputs += [ "$manifest_filename" ]
-        deps += [ manifest_target ]
-        args += [ rebase_path(manifest_filename, root_build_dir) ]
-
-        # Ensure that each entry does in fact reference a service manifest rule.
-        label_no_toolchain =
-            get_label_info(manifest_target, "label_no_toolchain")
-        toolchain = get_label_info(manifest_target, "toolchain")
-        deps += [ "${label_no_toolchain}__is_service_manifest(${toolchain})" ]
-      }
-    }
-
-    if (defined(invoker.executable_overrides)) {
-      args +=
-          [ "--override-service-executables" ] + invoker.executable_overrides
-    }
-
-    if (defined(invoker.catalog_deps)) {
-      args += [ "--include-catalogs" ]
-      foreach(catalog_target, invoker.catalog_deps) {
-        catalog_target_dir = get_label_info(catalog_target, "target_gen_dir")
-        catalog_target_name = get_label_info(catalog_target, "name")
-        catalog_filename = "$catalog_target_dir/${catalog_target_name}.json"
-
-        inputs += [ "$catalog_filename" ]
-        deps += [ catalog_target ]
-        args += [ rebase_path(catalog_filename, root_build_dir) ]
-      }
-    }
   }
+
+  # NOTE: There is no longer a practical difference between embedded and
+  # standalone services in terms of manifest data. Some targets use one or the
+  # other or both.
+  submanifests = []
+  if (defined(invoker.embedded_services)) {
+    submanifests += invoker.embedded_services
+  }
+  if (defined(invoker.standalone_services)) {
+    submanifests += invoker.standalone_services
+  }
+
+  write_file("$target_gen_dir/${target_name}.submanifests", submanifests)
 }
 
-# Generates a source_set target which defines a single string constant
-# containing the contents of a compiled catalog manifest.
-#
-# Parameters:
-#
-#   catalog
-#       The catalog target whose output should be stringified.
-#
-#   generated_function_name
-#       The fully qualified symbol name of the C++ string constant to define in
-#       the generate source_set.
-#
 template("catalog_cpp_source") {
   assert(defined(invoker.catalog), "catalog is required")
   assert(defined(invoker.generated_function_name),
          "generated_function_name is required")
 
+  generator_target_name = "${target_name}__generator"
+  generated_filename_base = "${target_gen_dir}/${target_name}"
+
   catalog_target = invoker.catalog
   catalog_target_dir = get_label_info(catalog_target, "target_gen_dir")
   catalog_target_name = get_label_info(catalog_target, "name")
-  catalog_filename = "$catalog_target_dir/${catalog_target_name}.json"
 
-  generator_target_name = "${target_name}__generator"
-  generated_filename_base = "${target_gen_dir}/${target_name}"
+  submanifests =
+      read_file("$catalog_target_dir/${catalog_target_name}.submanifests",
+                "list lines")
 
   action(generator_target_name) {
     testonly = defined(invoker.testonly) && invoker.testonly
     script = "//services/catalog/public/tools/sourcify_manifest.py"
     inputs = [
-      catalog_filename,
-
       "//services/catalog/public/tools/catalog.cc.tmpl",
       "//services/catalog/public/tools/catalog.h.tmpl",
     ]
@@ -178,28 +58,42 @@
       "${generated_filename_base}.cc",
       "${generated_filename_base}.h",
     ]
+
+    submanifest_info = []
+    foreach(submanifest, submanifests) {
+      manifest_dir = get_label_info(submanifest, "target_gen_dir")
+      manifest_target_name = get_label_info(submanifest, "name")
+      manifest_namespace_input =
+          "$manifest_dir/${manifest_target_name}.namespace"
+      manifest_namespace_path =
+          rebase_path(manifest_namespace_input, root_build_dir)
+      manifest_header_base =
+          rebase_path(manifest_dir, root_gen_dir) + "/${manifest_target_name}"
+      submanifest_info +=
+          [ "packaged@$manifest_namespace_path@$manifest_header_base" ]
+    }
+
+    submanifest_info_file =
+        "$target_gen_dir/${invoker.target_name}.submanifest_info"
+    write_file(submanifest_info_file, submanifest_info)
+
     args = [
-      "--input=" + rebase_path(catalog_filename, root_build_dir),
+      "--submanifest-info=" +
+          rebase_path(submanifest_info_file, root_build_dir),
       "--output-filename-base=" +
           rebase_path(generated_filename_base, root_build_dir),
       "--output-function-name=" + invoker.generated_function_name,
       "--module-path=" + rebase_path(generated_filename_base, root_gen_dir),
     ]
-    if (is_debug || dcheck_always_on) {
-      args += [ "--pretty" ]
-    }
-    deps = [
-      catalog_target,
-    ]
   }
 
   source_set(target_name) {
     testonly = defined(invoker.testonly) && invoker.testonly
     sources = get_target_outputs(":$generator_target_name")
     deps = [
-      ":$generator_target_name",
-      "//base",
-      "//services/service_manager/public/cpp",
-    ]
+             ":$generator_target_name",
+             "//base",
+             "//services/service_manager/public/cpp",
+           ] + submanifests
   }
 }
diff --git a/services/catalog/public/tools/catalog.h.tmpl b/services/catalog/public/tools/catalog.h.tmpl
index 402a877b..aed4b1d 100644
--- a/services/catalog/public/tools/catalog.h.tmpl
+++ b/services/catalog/public/tools/catalog.h.tmpl
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// This is a generated file. Please see the "catalog_cpp_source" template in
-// src/services/catalog/public/tools/catalog.gni for more details.
+// This is a generated file. Please see the "service_manifest" template in
+// src/services/service_manager/public/service_manifest.gni for more details.
+
 {%- set header_guard = "%s_H_"|format(path)|upper|replace("/", "_")|
         replace(".", "_")|replace("-", "_") %}
 
@@ -18,7 +19,11 @@
 namespace {{namespace}} {
 {%- endfor %}
 
+{% if root_manifest -%}
+const service_manager::Manifest& {{function_name}}();
+{% else -%}
 const std::vector<service_manager::Manifest>& {{function_name}}();
+{%- endif %}
 
 {% for namespace in namespaces|reverse %}
 }  // namespace {{namespace}}
diff --git a/services/catalog/public/tools/sourcify_manifest.py b/services/catalog/public/tools/sourcify_manifest.py
index 1bcfc6ae..acfc971d 100755
--- a/services/catalog/public/tools/sourcify_manifest.py
+++ b/services/catalog/public/tools/sourcify_manifest.py
@@ -18,10 +18,20 @@
     "build", "android", "gyp"))
 from util import build_utils
 
+
 _H_FILE_TEMPLATE = "catalog.h.tmpl"
 _CC_FILE_TEMPLATE = "catalog.cc.tmpl"
 
 
+eater_relative = "../../../../../tools/json_comment_eater"
+eater_relative = os.path.join(os.path.abspath(__file__), eater_relative)
+sys.path.insert(0, os.path.normpath(eater_relative))
+try:
+  import json_comment_eater
+finally:
+  sys.path.pop(0)
+
+
 # Disable lint check for finding modules:
 # pylint: disable=F0401
 
@@ -44,49 +54,38 @@
 
 
 def ApplyTemplate(path_to_template, output_path, global_vars, **kwargs):
-  def make_ascii(maybe_unicode):
-    if type(maybe_unicode) is str:
-      return maybe_unicode
-    assert type(maybe_unicode) is unicode
-    return maybe_unicode.encode("ascii", "ignore")
-
   with build_utils.AtomicOutput(output_path) as output_file:
     jinja_env = jinja2.Environment(
         loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
         keep_trailing_newline=True, **kwargs)
     jinja_env.globals.update(global_vars)
-    jinja_env.filters.update({
-      "is_dict": lambda x : type(x) is dict,
-      "is_list": lambda x : type(x) is list,
-      "is_number": lambda x : type(x) is int or type(x) is float,
-      "is_bool": lambda x: type(x) is bool,
-      "is_string": lambda x: type(x) is str,
-      "is_unicode": lambda x: type(x) is unicode,
-      "make_ascii": make_ascii,
-    })
     output_file.write(jinja_env.get_template(path_to_template).render())
 
 
 def main():
   parser = argparse.ArgumentParser(
       description="Generates a C++ constant containing a catalog manifest.")
-  parser.add_argument("--input")
+  parser.add_argument("--root-manifest")
+  parser.add_argument("--submanifest-info")
   parser.add_argument("--output-filename-base")
   parser.add_argument("--output-function-name")
   parser.add_argument("--module-path")
   args, _ = parser.parse_known_args()
 
-  if args.input is None:
-    raise Exception("--input is required")
+  if args.submanifest_info is None:
+    raise Exception("--submanifest-info required")
   if args.output_filename_base is None:
     raise Exception("--output-filename-base is required")
   if args.output_function_name is None:
     raise Exception("--output-function-name is required")
   if args.module_path is None:
-    raise Exception("--module-path is required")
+    args.module_path = args.output_filename_base
 
-  with open(args.input, "r") as input_file:
-    catalog = json.load(input_file)
+  if args.root_manifest:
+    with open(args.root_manifest, "r") as input_file:
+      root_manifest = json.loads(json_comment_eater.Nom(input_file.read()))
+  else:
+    root_manifest = None
 
   qualified_function_name = args.output_function_name.split("::")
   namespaces = qualified_function_name[0:-1]
@@ -95,8 +94,23 @@
   def raise_error(error, value):
     raise Exception(error)
 
+  overlays = []
+  packaged_services = []
+  with open(args.submanifest_info, "r") as info_file:
+    for line in info_file.readlines():
+      submanifest_type, namespace_file, header_base = line.strip().split("@", 3)
+      with open(namespace_file, "r") as namespace_file:
+        namespace = namespace_file.readline().strip()
+      info = { "namespace": namespace, "header": header_base + ".h" }
+      if submanifest_type == "overlay":
+        overlays.append(info)
+      else:
+        packaged_services.append(info)
+
   global_vars = {
-    "catalog": catalog,
+    "root_manifest": root_manifest,
+    "overlays": overlays,
+    "packaged_services": packaged_services,
     "function_name": function_name,
     "namespaces": namespaces,
     "path": args.module_path,
diff --git a/services/catalog/test_data/connection_spec b/services/catalog/test_data/connection_spec
deleted file mode 100644
index 80da172..0000000
--- a/services/catalog/test_data/connection_spec
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name": "foo",
-  "display_name": "Foo",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "requires": {
-        "bar": [ "bar:bar" ]
-      }
-    }
-  }
-}
diff --git a/services/catalog/test_data/instance b/services/catalog/test_data/instance
deleted file mode 100644
index 3fa31be..0000000
--- a/services/catalog/test_data/instance
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "name": "foo",
-  "display_name": "Foo",
-  "interface_provider_specs": { }
-}
diff --git a/services/catalog/test_data/malformed b/services/catalog/test_data/malformed
deleted file mode 100644
index 28a269c..0000000
--- a/services/catalog/test_data/malformed
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "name": "foo",
-  "display_name": "Foo",
diff --git a/services/catalog/test_data/options b/services/catalog/test_data/options
deleted file mode 100644
index 203a4e6..0000000
--- a/services/catalog/test_data/options
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name": "foo",
-  "display_name": "Foo",
-  "options": {
-    "instance_sharing": "singleton",
-    "can_connect_to_other_services_as_any_user": true,
-    "can_connect_to_other_services_with_any_instance_name": true,
-    "can_create_other_service_instances": true
-  },
-  "interface_provider_specs": { }
-}
diff --git a/services/catalog/test_data/required_files b/services/catalog/test_data/required_files
deleted file mode 100644
index 2e45d97e..0000000
--- a/services/catalog/test_data/required_files
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "name": "foo",
-  "display_name": "Foo",
-  "interface_provider_specs": { },
-  "required_files": {
-    "all_platforms": [
-      { "path": "/all/platforms/fuchsia", "platform": "fuchsia" },
-      { "path": "/all/platforms/linux", "platform": "linux" },
-      { "path": "/all/platforms/windows", "platform": "windows" },
-      { "path": "/all/platforms/macosx", "platform": "macosx" },
-      { "path": "/all/platforms/android", "platform": "android" }
-    ],
-    "fuchsia_only": [{ "path": "/fuchsia/only", "platform": "fuchsia" }],
-    "linux_only": [{ "path": "/linux/only", "platform": "linux" }],
-    "windows_only": [{ "path" : "/windows/only", "platform": "windows" }],
-    "macosx_only": [{ "path" : "/macosx/only", "platform": "macosx" }],
-    "android_only": [{ "path" : "/android/only", "platform": "android" }]
-  }
-}
diff --git a/services/catalog/test_data/serialization b/services/catalog/test_data/serialization
deleted file mode 100644
index 10fe188..0000000
--- a/services/catalog/test_data/serialization
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "name": "foo",
-  "display_name": "Foo",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "provides": {
-        "foo": [ "mojo::Bar", "mojo::Baz" ],
-        "bar": [ "mojo::Bork" ]
-      },
-      "requires": {
-        "bar": [ "a", "b" ]
-      }
-    }
-  }
-}
diff --git a/services/catalog/test_data/simple b/services/catalog/test_data/simple
deleted file mode 100644
index 04cd6fe..0000000
--- a/services/catalog/test_data/simple
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "name": "foo",
-  "display_name": "Foo",
-  "sandbox_type": "none",
-  "interface_provider_specs": { }
-}
diff --git a/services/service_manager/BUILD.gn b/services/service_manager/BUILD.gn
index efd375a..e55963d 100644
--- a/services/service_manager/BUILD.gn
+++ b/services/service_manager/BUILD.gn
@@ -28,8 +28,6 @@
     "connect_params.h",
     "service_manager.cc",
     "service_manager.h",
-    "service_overrides.cc",
-    "service_overrides.h",
     "switches.cc",
     "switches.h",
   ]
diff --git a/services/service_manager/background/background_service_manager.cc b/services/service_manager/background/background_service_manager.cc
index c887ea7..6e718c4 100644
--- a/services/service_manager/background/background_service_manager.cc
+++ b/services/service_manager/background/background_service_manager.cc
@@ -26,26 +26,13 @@
 
 BackgroundServiceManager::BackgroundServiceManager(
     ServiceProcessLauncherDelegate* launcher_delegate,
-    std::unique_ptr<base::Value> catalog_contents)
-    : background_thread_("service_manager") {
-  background_thread_.Start();
-  background_thread_.task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&BackgroundServiceManager::InitializeOnBackgroundThread,
-                     base::Unretained(this), launcher_delegate,
-                     std::move(catalog_contents), std::vector<Manifest>()));
-}
-
-BackgroundServiceManager::BackgroundServiceManager(
-    ServiceProcessLauncherDelegate* launcher_delegate,
     const std::vector<Manifest>& manifests)
     : background_thread_("service_manager") {
   background_thread_.Start();
   background_thread_.task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&BackgroundServiceManager::InitializeOnBackgroundThread,
-                     base::Unretained(this), launcher_delegate, nullptr,
-                     manifests));
+                     base::Unretained(this), launcher_delegate, manifests));
 }
 
 BackgroundServiceManager::~BackgroundServiceManager() {
@@ -74,14 +61,8 @@
 
 void BackgroundServiceManager::InitializeOnBackgroundThread(
     ServiceProcessLauncherDelegate* launcher_delegate,
-    std::unique_ptr<base::Value> catalog_contents,
     const std::vector<Manifest>& manifests) {
-  if (!manifests.empty()) {
-    context_ = std::make_unique<Context>(launcher_delegate, manifests);
-  } else {
-    context_ = std::make_unique<Context>(launcher_delegate,
-                                         std::move(catalog_contents));
-  }
+  context_ = std::make_unique<Context>(launcher_delegate, manifests);
 }
 
 void BackgroundServiceManager::ShutDownOnBackgroundThread(
diff --git a/services/service_manager/background/background_service_manager.h b/services/service_manager/background/background_service_manager.h
index d614f5b..8260d0c 100644
--- a/services/service_manager/background/background_service_manager.h
+++ b/services/service_manager/background/background_service_manager.h
@@ -10,7 +10,6 @@
 
 #include "base/macros.h"
 #include "base/threading/thread.h"
-#include "base/values.h"
 #include "build/build_config.h"
 #include "services/service_manager/public/cpp/manifest.h"
 #include "services/service_manager/public/mojom/connector.mojom.h"
@@ -32,8 +31,6 @@
 class BackgroundServiceManager {
  public:
   BackgroundServiceManager(ServiceProcessLauncherDelegate* launcher_delegate,
-                           std::unique_ptr<base::Value> catalog_contents);
-  BackgroundServiceManager(ServiceProcessLauncherDelegate* launcher_delegate,
                            const std::vector<Manifest>& manifests);
   ~BackgroundServiceManager();
 
@@ -50,7 +47,6 @@
  private:
   void InitializeOnBackgroundThread(
       ServiceProcessLauncherDelegate* launcher_delegate,
-      std::unique_ptr<base::Value> catalog_contents,
       const std::vector<Manifest>& manifests);
   void ShutDownOnBackgroundThread(base::WaitableEvent* done_event);
   void RegisterServiceOnBackgroundThread(
diff --git a/services/service_manager/embedder/BUILD.gn b/services/service_manager/embedder/BUILD.gn
index df6fb926..feeac1e2 100644
--- a/services/service_manager/embedder/BUILD.gn
+++ b/services/service_manager/embedder/BUILD.gn
@@ -2,19 +2,12 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("embedder") {
-  public = [
-    "manifest_utils.h",
-  ]
-
-  sources = [
-    "manifest_utils.cc",
-  ]
-
-  # iOS embeds the Service Manager but does not use service_manager::Main() (and
-  # cannot use or even build it as-is).
-  if (!is_ios) {
-    public += [
+if (!is_ios) {
+  # iOS embeds the Service Manager but does not use anything in this library.
+  # This avoids having an empty component library target, which can otherwise be
+  # problematic.
+  component("embedder") {
+    public = [
       "main.h",
       "main_delegate.h",
       "process_type.h",
@@ -22,60 +15,52 @@
       "set_process_title_linux.h",
       "shared_file_util.h",
     ]
-    sources += [
+
+    sources = [
       "main.cc",
       "main_delegate.cc",
       "set_process_title.cc",
       "set_process_title_linux.cc",
       "shared_file_util.cc",
     ]
-  }
 
-  if (is_mac) {
-    sources += [
-      "mac_init.h",
-      "mac_init.mm",
-    ]
+    if (is_mac) {
+      sources += [
+        "mac_init.h",
+        "mac_init.mm",
+      ]
 
-    libs = [ "Foundation.framework" ]
-  }
+      libs = [ "Foundation.framework" ]
+    }
 
-  deps = [
-    "//base:base_static",
-    "//base:i18n",
-  ]
-
-  public_deps = [
-    ":embedder_result_codes",
-    "//base",
-    "//services/service_manager/public/cpp",
-    "//services/service_manager/public/mojom",
-  ]
-
-  if (!is_ios) {
-    # deps of ServiceManager::Main and related functionality.
-    deps += [
+    deps = [
+      "//base:base_static",
+      "//base:i18n",
       "//base/allocator:buildflags",
       "//components/tracing:startup_tracing",
     ]
 
+    public_deps = [
+      ":embedder_result_codes",
+      ":embedder_switches",
+      "//base",
+      "//mojo/core/embedder",
+      "//services/service_manager/background:lib",
+      "//services/service_manager/public/cpp",
+      "//services/service_manager/public/cpp/service_executable:support",
+      "//services/service_manager/public/mojom",
+      "//services/service_manager/runner:init",
+      "//services/service_manager/runner/common",
+    ]
+
     if (!is_nacl) {
       # NaCl stuff should not depend on skia as it would require platform and
       # cpu properties set.
       deps += [ "//ui/base" ]
     }
 
-    public_deps += [
-      ":embedder_switches",
-      "//mojo/core/embedder",
-      "//services/service_manager/background:lib",
-      "//services/service_manager/public/cpp/service_executable:support",
-      "//services/service_manager/runner:init",
-      "//services/service_manager/runner/common",
-    ]
+    defines = [ "IS_SERVICE_MANAGER_EMBEDDER_IMPL" ]
   }
-
-  defines = [ "IS_SERVICE_MANAGER_EMBEDDER_IMPL" ]
 }
 
 component("embedder_switches") {
@@ -94,18 +79,3 @@
     "result_codes.h",
   ]
 }
-
-source_set("unittests") {
-  testonly = true
-
-  sources = [
-    "manifest_utils_unittest.cc",
-  ]
-
-  deps = [
-    ":embedder",
-    "//base",
-    "//base/test:test_support",
-    "//testing/gtest",
-  ]
-}
diff --git a/services/service_manager/embedder/main.cc b/services/service_manager/embedder/main.cc
index 938469b..06e6247 100644
--- a/services/service_manager/embedder/main.cc
+++ b/services/service_manager/embedder/main.cc
@@ -235,7 +235,7 @@
   ServiceProcessLauncherDelegateImpl service_process_launcher_delegate(
       delegate);
   service_manager::BackgroundServiceManager background_service_manager(
-      &service_process_launcher_delegate, delegate->CreateServiceCatalog());
+      &service_process_launcher_delegate, delegate->GetServiceManifests());
 
   base::RunLoop run_loop;
   delegate->OnServiceManagerInitialized(run_loop.QuitClosure(),
diff --git a/services/service_manager/embedder/main_delegate.cc b/services/service_manager/embedder/main_delegate.cc
index 1501a97..ea4c1d7 100644
--- a/services/service_manager/embedder/main_delegate.cc
+++ b/services/service_manager/embedder/main_delegate.cc
@@ -27,8 +27,8 @@
 void MainDelegate::OverrideMojoConfiguration(
     mojo::core::Configuration* config) {}
 
-std::unique_ptr<base::Value> MainDelegate::CreateServiceCatalog() {
-  return nullptr;
+std::vector<Manifest> MainDelegate::GetServiceManifests() {
+  return std::vector<Manifest>();
 }
 
 bool MainDelegate::ShouldLaunchAsServiceProcess(const Identity& identity) {
diff --git a/services/service_manager/embedder/main_delegate.h b/services/service_manager/embedder/main_delegate.h
index d373d708..ba3589a5 100644
--- a/services/service_manager/embedder/main_delegate.h
+++ b/services/service_manager/embedder/main_delegate.h
@@ -6,6 +6,7 @@
 #define SERVICES_SERVICE_MANAGER_EMBEDDER_MAIN_DELEGATE_H_
 
 #include <memory>
+#include <vector>
 
 #include "base/callback_forward.h"
 #include "base/component_export.h"
@@ -15,12 +16,12 @@
 #include "services/service_manager/background/background_service_manager.h"
 #include "services/service_manager/embedder/process_type.h"
 #include "services/service_manager/public/cpp/identity.h"
+#include "services/service_manager/public/cpp/manifest.h"
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
 
 namespace base {
 class CommandLine;
-class Value;
 namespace mac {
 class ScopedNSAutoreleasePool;
 }
@@ -73,9 +74,10 @@
   // Allows the embedder to override the process-wide Mojop configuration.
   virtual void OverrideMojoConfiguration(mojo::core::Configuration* config);
 
-  // Create the service catalog to be used by the Service Manager. May return
-  // null to use the default (empty) catalog, if you're into that.
-  virtual std::unique_ptr<base::Value> CreateServiceCatalog();
+  // Gets the list of service manifests with which to initialize the Service
+  // Manager. This list must describe the complete set of usable services in
+  // the system and remains fixed for the lifetime of the Service Manager.
+  virtual std::vector<Manifest> GetServiceManifests();
 
   // Indicates whether a process started by the service manager for a given
   // target service identity should be run as a real service process (|true|)
diff --git a/services/service_manager/embedder/manifest_utils.cc b/services/service_manager/embedder/manifest_utils.cc
deleted file mode 100644
index a43c152..0000000
--- a/services/service_manager/embedder/manifest_utils.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/service_manager/embedder/manifest_utils.h"
-
-
-namespace service_manager {
-
-namespace {
-
-// Similar to base::DictionaryValue::MergeDictionary(), except concatenates
-// ListValue contents.
-// This is explicitly not part of base::DictionaryValue at brettw's request.
-void MergeDictionary(base::DictionaryValue* target,
-                     const base::DictionaryValue* source) {
-  for (base::DictionaryValue::Iterator it(*source); !it.IsAtEnd();
-       it.Advance()) {
-    const base::Value* merge_value = &it.value();
-    // Check whether we have to merge dictionaries.
-    if (merge_value->is_dict()) {
-      base::DictionaryValue* sub_dict;
-      if (target->GetDictionaryWithoutPathExpansion(it.key(), &sub_dict)) {
-        MergeDictionary(sub_dict,
-                        static_cast<const base::DictionaryValue*>(merge_value));
-        continue;
-      }
-    }
-    if (merge_value->is_list()) {
-      const base::ListValue* merge_list = nullptr;
-      if (merge_value->GetAsList(&merge_list)) {
-        base::ListValue* target_list = nullptr;
-        if (target->GetListWithoutPathExpansion(it.key(), &target_list)) {
-          for (size_t i = 0; i < merge_list->GetSize(); ++i) {
-            const base::Value* element = nullptr;
-            CHECK(merge_list->Get(i, &element));
-            target_list->Append(element->CreateDeepCopy());
-          }
-          continue;
-        }
-      }
-    }
-    // All other cases: Make a copy and hook it up.
-    target->SetKey(it.key(), merge_value->Clone());
-  }
-}
-
-}  // namespace
-
-void MergeManifestWithOverlay(base::Value* manifest, base::Value* overlay) {
-  if (!overlay)
-    return;
-
-  base::DictionaryValue* manifest_dictionary = nullptr;
-  bool result = manifest->GetAsDictionary(&manifest_dictionary);
-  DCHECK(result);
-  base::DictionaryValue* overlay_dictionary = nullptr;
-  result = overlay->GetAsDictionary(&overlay_dictionary);
-  DCHECK(result);
-  MergeDictionary(manifest_dictionary, overlay_dictionary);
-}
-
-}  // namespace service_manager
diff --git a/services/service_manager/embedder/manifest_utils.h b/services/service_manager/embedder/manifest_utils.h
deleted file mode 100644
index a6af881..0000000
--- a/services/service_manager/embedder/manifest_utils.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_SERVICE_MANAGER_EMBEDDER_MANIFEST_UTILS_H_
-#define SERVICES_SERVICE_MANAGER_EMBEDDER_MANIFEST_UTILS_H_
-
-#include "base/component_export.h"
-#include "base/values.h"
-
-namespace service_manager {
-
-// Merges |overlay| (if not null) into |manifest|.
-// Uses a strategy similar to base::DictionaryValue::MergeDictionary(), except
-// concatenates ListValue contents.
-void COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER)
-    MergeManifestWithOverlay(base::Value* manifest, base::Value* overlay);
-}  // namespace service_manager
-
-#endif  // SERVICES_SERVICE_MANAGER_EMBEDDER_MANIFEST_UTILS_H_
diff --git a/services/service_manager/embedder/manifest_utils_unittest.cc b/services/service_manager/embedder/manifest_utils_unittest.cc
deleted file mode 100644
index 9d8e46ac..0000000
--- a/services/service_manager/embedder/manifest_utils_unittest.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/service_manager/embedder/manifest_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace service_manager {
-
-TEST(MergeManifestWithOverlayTest, Merge) {
-  // |manifest| & |overlay| have three properties, "string", "list" and
-  // "dictionary", which are then merged.
-  base::DictionaryValue manifest;
-  manifest.SetString("string", "Hello, ");
-  std::unique_ptr<base::DictionaryValue> dict_value_original(
-      std::make_unique<base::DictionaryValue>());
-  dict_value_original->SetString("key1", "original");
-  dict_value_original->SetString("key3", "original");
-  manifest.Set("dictionary", std::move(dict_value_original));
-  std::unique_ptr<base::ListValue> list(std::make_unique<base::ListValue>());
-  list->AppendString("A");
-  list->AppendString("B");
-  manifest.Set("list", std::move(list));
-
-  base::DictionaryValue overlay;
-  overlay.SetString("string", "World!");
-  std::unique_ptr<base::DictionaryValue> dict_value_replacement(
-      std::make_unique<base::DictionaryValue>());
-  dict_value_replacement->SetString("key1", "new");
-  dict_value_replacement->SetString("key2", "new");
-  overlay.Set("dictionary", std::move(dict_value_replacement));
-  list = std::make_unique<base::ListValue>();
-  list->AppendString("C");
-  overlay.Set("list", std::move(list));
-
-  MergeManifestWithOverlay(&manifest, &overlay);
-
-  // Simple string value should have been clobbered.
-  std::string out_string;
-  EXPECT_TRUE(manifest.GetString("string", &out_string));
-  EXPECT_EQ(out_string, "World!");
-
-  // Dictionary should have been merged, with key1 being clobbered, key2 added
-  // and key3 preserved.
-  base::DictionaryValue* out_dictionary = nullptr;
-  EXPECT_TRUE(manifest.GetDictionary("dictionary", &out_dictionary));
-  EXPECT_EQ(3u, out_dictionary->size());
-  std::string value1, value2, value3;
-  EXPECT_TRUE(out_dictionary->GetString("key1", &value1));
-  EXPECT_TRUE(out_dictionary->GetString("key2", &value2));
-  EXPECT_TRUE(out_dictionary->GetString("key3", &value3));
-  EXPECT_EQ(value1, "new");
-  EXPECT_EQ(value2, "new");
-  EXPECT_EQ(value3, "original");
-
-  // List should have been merged, with the items from overlay appended to the
-  // items from manifest.
-  base::ListValue* out_list = nullptr;
-  EXPECT_TRUE(manifest.GetList("list", &out_list));
-  EXPECT_EQ(3u, out_list->GetSize());
-  std::string a, b, c;
-  EXPECT_TRUE(out_list->GetString(0, &a));
-  EXPECT_TRUE(out_list->GetString(1, &b));
-  EXPECT_TRUE(out_list->GetString(2, &c));
-  EXPECT_EQ("A", a);
-  EXPECT_EQ("B", b);
-  EXPECT_EQ("C", c);
-}
-
-}  // namespace service_manager
diff --git a/services/service_manager/public/cpp/manifest.cc b/services/service_manager/public/cpp/manifest.cc
index e018583d..464ad43 100644
--- a/services/service_manager/public/cpp/manifest.cc
+++ b/services/service_manager/public/cpp/manifest.cc
@@ -230,7 +230,7 @@
   return manifest;
 }
 
-void Manifest::Amend(Manifest other) {
+Manifest& Manifest::Amend(Manifest other) {
   for (auto& other_capability : other.exposed_capabilities) {
     auto it = std::find_if(
         exposed_capabilities.begin(), exposed_capabilities.end(),
@@ -272,6 +272,8 @@
     packaged_services.emplace_back(std::move(manifest));
   for (auto& file_info : other.preloaded_files)
     preloaded_files.emplace_back(std::move(file_info));
+
+  return *this;
 }
 
 }  // namespace service_manager
diff --git a/services/service_manager/public/cpp/manifest.h b/services/service_manager/public/cpp/manifest.h
index 684a60e..12294aa 100644
--- a/services/service_manager/public/cpp/manifest.h
+++ b/services/service_manager/public/cpp/manifest.h
@@ -267,7 +267,7 @@
   // Amends this Manifest with a subset of |other|. Namely, exposed and required
   // capabilities, exposed and required interface filter capabilities, packaged
   // services, and preloaded files are all added from |other| if present.
-  void Amend(Manifest other);
+  Manifest& Amend(Manifest other);
 
   std::string service_name;
   DisplayName display_name;
diff --git a/services/service_manager/public/service_manifest.gni b/services/service_manager/public/service_manifest.gni
index 1bf9463..b797200e 100644
--- a/services/service_manager/public/service_manifest.gni
+++ b/services/service_manager/public/service_manifest.gni
@@ -4,65 +4,129 @@
 
 import("//build/config/dcheck_always_on.gni")
 
-# Used to produce a Service Manifest for a Service.
+# Generates code to produce a compiled service_manager::Manifest from a JSON
+# description at build time.
 #
-# Service manifests may be subsequently aggregated into one or more catalog
-# manifests (see //services/catalog/public/tools/catalog.gni). A catalog
-# manifest provides the Service Manager at runtime with a static service layout
-# configuration to dictate which services are supported by the runtime
-# environment as well as how individual services may be launched and
-# interconnected.
+# This is a temporary helper for the transition away from JSON manifests. Do not
+# introduce new service_manifest targets.
 #
-# Note that this target may be used to produce partial manifests, and partial
-# manifests may be aggregated by using one service_manifest target as the
-# |source_manifest| of another (see below.)
+# This template yields a source_set target which defines a symbol named
+# "${name}::GetManifest()" where ${name} is the service name given in the
+# target.
 #
-# Parameters:
-#
-#   source (optional**)
-#       The manifest template for this service. Must be the name of a valid JSON
-#       file.
-#
-#   source_manifest (optional**)
-#       The manifest template for this service. Must be the name of another
-#       service_manifest target.
-#
-#       ** NOTE: Either |source| OR |source_manifest| MUST be specified.
-#
-#   name (optional)
-#       The name of the service whose manifest is to be generated. A script
-#       validates that the value of this parameter matches the name set in the
-#       source manifest and raises an error if it does not match.
-#
-#   overlays (optional)
-#       A list of other manifest targets whose outputs should be overlayed onto
-#       the source manifest before emitting the final output. Overlays are
-#       applied in-order as the last step of output generation, after any
-#       |packaged_services| manifests are embedded.
-#
-#   packaged_services (optional)
-#       A list of other manifest targets whose outputs should be packaged
-#       within this output manifest, specifically within a toplevel "services"
-#       list.
-#
-#   testonly (optional)
-#
-# Outputs:
-#
-#   An instantiation of this template produces a meta manifest from the source
-#   template and the output manifests of all its |overlay| and
-#   |packaged_services|dependencies. The output file is always
-#   "$target_gen_dir/${target_name}.json".
-#
+# All service_manifest targets should be replaced with in-tree C++ sources.
 template("service_manifest") {
-  assert(
-      defined(invoker.source) || defined(invoker.source_manifest),
-      "\"source\" or \"source_manifest\" must be defined for the $target_name target")
-  assert(
-      !defined(invoker.source) || !defined(invoker.source_manifest),
-      "Only one of \"source\" or \"source_manifest\" must be defined for the $target_name target")
+  assert(defined(invoker.source),
+         "\"source\" must be defined for the $target_name target")
 
-  action(target_name) {
+  generator_target_name = "${target_name}__generator"
+  generated_sources = [
+    "$target_gen_dir/${target_name}.cc",
+    "$target_gen_dir/${target_name}.h",
+  ]
+
+  # We prefer to use |name| for the generated function's namespace if a
+  # |generated_namespace| isn't explicitly defined. It turns out that we also
+  # have a few targets which don't specify a |name| though; they all have unique
+  # target names, so we fall back on that if necessary. The important detail is
+  # that all generated GetManifest() functions should live in their own
+  # namespace, and with the current (and final) set of service_manifest targets
+  # in the tree, these rules accomplish that.
+  if (defined(invoker.generated_namespace)) {
+    output_namespace = invoker.generated_namespace
+  } else if (defined(invoker.name)) {
+    output_namespace = invoker.name
+  } else {
+    output_namespace = invoker.target_name
+  }
+
+  write_file("$target_gen_dir/${target_name}.namespace", output_namespace)
+
+  source_set(target_name) {
+    testonly = defined(invoker.testonly) && invoker.testonly
+    sources = generated_sources
+    public_deps = [
+      ":$generator_target_name",
+    ]
+
+    deps = []
+    if (defined(invoker.packaged_services)) {
+      deps += invoker.packaged_services
+    }
+    if (defined(invoker.overlays)) {
+      deps += invoker.overlays
+    }
+  }
+
+  collator_target_name = "${target_name}__collator"
+
+  action(generator_target_name) {
+    testonly = defined(invoker.testonly) && invoker.testonly
+    script = "//services/catalog/public/tools/sourcify_manifest.py"
+
+    inputs = [
+      "//services/catalog/public/tools/catalog.cc.tmpl",
+      "//services/catalog/public/tools/catalog.h.tmpl",
+      invoker.source,
+    ]
+    outputs = generated_sources
+
+    submanifest_info = []
+    if (defined(invoker.packaged_services)) {
+      foreach(submanifest, invoker.packaged_services) {
+        manifest_dir = get_label_info(submanifest, "target_gen_dir")
+        manifest_target_name = get_label_info(submanifest, "name")
+        manifest_namespace_input =
+            "$manifest_dir/${manifest_target_name}.namespace"
+        manifest_namespace_path =
+            rebase_path(manifest_namespace_input, root_build_dir)
+        manifest_header_base =
+            rebase_path(manifest_dir, root_gen_dir) + "/${manifest_target_name}"
+        submanifest_info +=
+            [ "packaged@$manifest_namespace_path@$manifest_header_base" ]
+      }
+    }
+    if (defined(invoker.overlays)) {
+      foreach(submanifest, invoker.overlays) {
+        manifest_dir = get_label_info(submanifest, "target_gen_dir")
+        manifest_target_name = get_label_info(submanifest, "name")
+        manifest_namespace_input =
+            "$manifest_dir/${manifest_target_name}.namespace"
+        manifest_namespace_path =
+            rebase_path(manifest_namespace_input, root_build_dir)
+        manifest_header_base =
+            rebase_path(manifest_dir, root_gen_dir) + "/${manifest_target_name}"
+        submanifest_info +=
+            [ "overlay@$manifest_namespace_path@$manifest_header_base" ]
+      }
+    }
+
+    submanifest_info_file =
+        "${target_gen_dir}/${invoker.target_name}.submanifest_info"
+    write_file(submanifest_info_file, submanifest_info)
+
+    args = [
+      "--root-manifest=" + rebase_path(invoker.source, root_build_dir),
+      "--submanifest-info=" +
+          rebase_path(submanifest_info_file, root_build_dir),
+      "--output-function-name=${output_namespace}::GetManifest",
+      "--output-filename-base=" +
+          rebase_path("$target_gen_dir/${invoker.target_name}", root_build_dir),
+      "--module-path=" +
+          rebase_path("$target_gen_dir/${invoker.target_name}", root_gen_dir),
+    ]
+
+    # We inherit a public dependency on the collator because service_manifest
+    # dependents still expect to use its generated JSON output. We don't
+    # actually depend on the collated JSON at all here, since packaged services
+    # and overlays are added in the generated C++ code by referring to other
+    # generated C++ code.
+    public_deps = [
+      ":$collator_target_name",
+    ]
+  }
+
+  action(collator_target_name) {
     testonly = defined(invoker.testonly) && invoker.testonly
 
     script =
@@ -73,25 +137,16 @@
       deps += invoker.deps
     }
 
-    if (defined(invoker.source)) {
-      source = invoker.source
-    } else {
-      source_target_dir =
-          get_label_info(invoker.source_manifest, "target_gen_dir")
-      source_target_name = get_label_info(invoker.source_manifest, "name")
-      source = "$source_target_dir/${source_target_name}.json"
-      deps += [ invoker.source_manifest ]
-    }
     inputs = [
-      source,
+      invoker.source,
     ]
 
-    output = "$target_gen_dir/${target_name}.json"
+    output = "$target_gen_dir/${invoker.target_name}.json"
     outputs = [
       output,
     ]
 
-    rebase_parent = rebase_path(source, root_build_dir)
+    rebase_parent = rebase_path(invoker.source, root_build_dir)
     rebase_output = rebase_path(output, root_build_dir)
 
     args = [
diff --git a/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc b/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
index b545d681..21675d1 100644
--- a/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
+++ b/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
@@ -177,9 +177,8 @@
     options->paths_to_clone.push_back(base::FilePath("/config/ssl"));
 
   if (config.features & kProvideVulkanResources) {
-    // /system/lib is used to load Vulkan libraries. /dev/class/gpu and
-    // /config/vulkan/icd.d are to used configure and access the GPU.
-    options->paths_to_clone.push_back(base::FilePath("/system/lib"));
+    // /dev/class/gpu and /config/vulkan/icd.d are to used configure and
+    // access the GPU.
     options->paths_to_clone.push_back(base::FilePath("/dev/class/gpu"));
     const auto vulkan_icd_path = base::FilePath("/config/vulkan/icd.d");
     if (base::PathExists(vulkan_icd_path))
diff --git a/services/service_manager/service_manager.cc b/services/service_manager/service_manager.cc
index a169c130..c42fa2a 100644
--- a/services/service_manager/service_manager.cc
+++ b/services/service_manager/service_manager.cc
@@ -946,24 +946,42 @@
 
 ServiceManager::ServiceManager(std::unique_ptr<ServiceProcessLauncherFactory>
                                    service_process_launcher_factory,
-                               const std::vector<Manifest>& manifests,
-                               catalog::ManifestProvider* manifest_provider)
-    : catalog_(nullptr, manifests, manifest_provider),
+                               const std::vector<Manifest>& manifests)
+    : catalog_(manifests),
       identity_to_instance_(std::make_unique<IdentityToInstanceMap>()),
       service_process_launcher_factory_(
           std::move(service_process_launcher_factory)) {
-  InitBuiltinServices();
-}
+  InterfaceProviderSpec spec;
+  spec.provides[kCapability_ServiceManager].insert(
+      "service_manager.mojom.ServiceManager");
+  spec.requires["*"].insert("service_manager:service_factory");
+  InterfaceProviderSpecMap specs;
+  specs[mojom::kServiceManager_ConnectorSpec] = std::move(spec);
 
-ServiceManager::ServiceManager(std::unique_ptr<ServiceProcessLauncherFactory>
-                                   service_process_launcher_factory,
-                               std::unique_ptr<base::Value> catalog_contents,
-                               catalog::ManifestProvider* manifest_provider)
-    : catalog_(std::move(catalog_contents), {}, manifest_provider),
-      identity_to_instance_(std::make_unique<IdentityToInstanceMap>()),
-      service_process_launcher_factory_(
-          std::move(service_process_launcher_factory)) {
-  InitBuiltinServices();
+  service_manager_instance_ = CreateInstance(
+      GetServiceManagerInstanceIdentity(), InstanceType::kSingleton,
+      std::move(specs), catalog::ServiceOptions());
+
+  mojom::ServicePtr service;
+  service_binding_.Bind(mojo::MakeRequest(&service));
+  service_manager_instance_->StartWithService(std::move(service));
+
+  InterfaceProviderSpec catalog_spec;
+  catalog_spec.provides["directory"].insert("filesystem.mojom.Directory");
+  catalog_spec.provides["catalog:catalog"].insert("catalog.mojom.Catalog");
+  catalog_spec.provides["control"].insert("catalog.mojom.CatalogControl");
+  InterfaceProviderSpecMap catalog_specs;
+  catalog_specs[mojom::kServiceManager_ConnectorSpec] = std::move(catalog_spec);
+
+  Identity id{catalog::mojom::kServiceName, kSystemInstanceGroup, base::Token{},
+              base::Token::CreateRandom()};
+  Instance* instance =
+      CreateInstance(id, InstanceType::kSingleton, std::move(catalog_specs),
+                     catalog::ServiceOptions());
+
+  mojom::ServicePtr catalog_service;
+  catalog_.BindServiceRequest(mojo::MakeRequest(&catalog_service));
+  instance->StartWithService(std::move(catalog_service));
 }
 
 ServiceManager::~ServiceManager() {
@@ -1218,43 +1236,6 @@
   Connect(std::move(params));
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// ServiceManager, private:
-
-void ServiceManager::InitBuiltinServices() {
-  InterfaceProviderSpec spec;
-  spec.provides[kCapability_ServiceManager].insert(
-      "service_manager.mojom.ServiceManager");
-  spec.requires["*"].insert("service_manager:service_factory");
-  InterfaceProviderSpecMap specs;
-  specs[mojom::kServiceManager_ConnectorSpec] = std::move(spec);
-
-  service_manager_instance_ = CreateInstance(
-      GetServiceManagerInstanceIdentity(), InstanceType::kSingleton,
-      std::move(specs), catalog::ServiceOptions());
-
-  mojom::ServicePtr service;
-  service_binding_.Bind(mojo::MakeRequest(&service));
-  service_manager_instance_->StartWithService(std::move(service));
-
-  InterfaceProviderSpec catalog_spec;
-  catalog_spec.provides["directory"].insert("filesystem.mojom.Directory");
-  catalog_spec.provides["catalog:catalog"].insert("catalog.mojom.Catalog");
-  catalog_spec.provides["control"].insert("catalog.mojom.CatalogControl");
-  InterfaceProviderSpecMap catalog_specs;
-  catalog_specs[mojom::kServiceManager_ConnectorSpec] = std::move(catalog_spec);
-
-  Identity id{catalog::mojom::kServiceName, kSystemInstanceGroup, base::Token{},
-              base::Token::CreateRandom()};
-  Instance* instance =
-      CreateInstance(id, InstanceType::kSingleton, std::move(catalog_specs),
-                     catalog::ServiceOptions());
-
-  mojom::ServicePtr catalog_service;
-  catalog_.BindServiceRequest(mojo::MakeRequest(&catalog_service));
-  instance->StartWithService(std::move(catalog_service));
-}
-
 void ServiceManager::OnInstanceError(Instance* instance) {
   // We never clean up the ServiceManager's own instance.
   if (instance == service_manager_instance_)
diff --git a/services/service_manager/service_manager.h b/services/service_manager/service_manager.h
index 2a046f9..8bf2428 100644
--- a/services/service_manager/service_manager.h
+++ b/services/service_manager/service_manager.h
@@ -12,7 +12,6 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/process/process.h"
-#include "base/values.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/interface_ptr_set.h"
 #include "services/catalog/catalog.h"
@@ -29,11 +28,6 @@
 #include "services/service_manager/public/mojom/service_factory.mojom.h"
 #include "services/service_manager/public/mojom/service_manager.mojom.h"
 #include "services/service_manager/runner/host/service_process_launcher_factory.h"
-#include "services/service_manager/service_overrides.h"
-
-namespace catalog {
-class ManifestProvider;
-}
 
 namespace service_manager {
 
@@ -50,25 +44,9 @@
   // |service_process_launcher_factory| is an instance of an object capable of
   // vending implementations of ServiceProcessLauncher, e.g. for out-of-process
   // execution.
-  explicit ServiceManager(
-      std::unique_ptr<ServiceProcessLauncherFactory>
-          service_process_launcher_factory,
-      const std::vector<Manifest>& manifests,
-      catalog::ManifestProvider* manifest_provider = nullptr);
-
-  // |service_process_launcher_factory| is an instance of an object capable of
-  // vending implementations of ServiceProcessLauncher, e.g. for out-of-process
-  // execution.
-  //
-  // |catalog_contents|, if not null, will be used to prepoulate the service
-  // manager catalog with a fixed data set. |manifest_provider|, if not null,
-  // will be consulted for dynamic manifest resolution if a manifest is not
-  // found within the catalog; if used, |manifest_provider| is not owned and
-  // must outlive this ServiceManager.
-  ServiceManager(std::unique_ptr<ServiceProcessLauncherFactory>
-                     service_process_launcher_factory,
-                 std::unique_ptr<base::Value> catalog_contents,
-                 catalog::ManifestProvider* manifest_provider);
+  explicit ServiceManager(std::unique_ptr<ServiceProcessLauncherFactory>
+                              service_process_launcher_factory,
+                          const std::vector<Manifest>& manifests);
   ~ServiceManager() override;
 
   // Provide a callback to be notified whenever an instance is destroyed.
@@ -128,8 +106,6 @@
     kSingleton,
   };
 
-  void InitBuiltinServices();
-
   // Called when |instance| encounters an error. Deletes |instance|.
   void OnInstanceError(Instance* instance);
 
diff --git a/services/service_manager/service_overrides.cc b/services/service_manager/service_overrides.cc
deleted file mode 100644
index 2dfa8b5..0000000
--- a/services/service_manager/service_overrides.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/service_manager/service_overrides.h"
-
-#include "base/base_paths.h"
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-
-namespace service_manager {
-
-namespace {
-
-const char kExecutablePathKey[] = "executable_path";
-const char kPackageNameKey[] = "package_name";
-
-}  // namespace
-
-ServiceOverrides::Entry::Entry() {}
-
-ServiceOverrides::Entry::~Entry() {}
-
-ServiceOverrides::ServiceOverrides(std::unique_ptr<base::Value> overrides) {
-  const base::DictionaryValue* services;
-  if (!overrides->GetAsDictionary(&services)) {
-    LOG(ERROR) << "Expected top-level dictionary.";
-    return;
-  }
-
-  base::DictionaryValue::Iterator service_iter(*services);
-  for (; !service_iter.IsAtEnd(); service_iter.Advance()) {
-    Entry& new_entry = entries_[service_iter.key()];
-
-    const base::DictionaryValue* value;
-    if (!service_iter.value().GetAsDictionary(&value)) {
-      LOG(ERROR) << "Expected service entry to be a dictionary.";
-      return;
-    }
-
-    std::string executable_path_value;
-    if (value->GetString(kExecutablePathKey, &executable_path_value)) {
-      base::FilePath exe_dir;
-      CHECK(base::PathService::Get(base::DIR_EXE, &exe_dir));
-#if defined(OS_WIN)
-      executable_path_value += ".exe";
-      base::ReplaceFirstSubstringAfterOffset(
-          &executable_path_value, 0, "@EXE_DIR",
-          base::UTF16ToUTF8(exe_dir.value()));
-      new_entry.executable_path =
-          base::FilePath(base::UTF8ToUTF16(executable_path_value));
-#else
-      base::ReplaceFirstSubstringAfterOffset(
-          &executable_path_value, 0, "@EXE_DIR",
-          exe_dir.value());
-      new_entry.executable_path = base::FilePath(executable_path_value);
-#endif
-    }
-
-    value->GetString(kPackageNameKey, &new_entry.package_name);
-  }
-}
-
-ServiceOverrides::~ServiceOverrides() {}
-
-bool ServiceOverrides::GetExecutablePathOverride(
-    const std::string& service_name,
-    base::FilePath* path) const {
-  auto iter = entries_.find(service_name);
-  if (iter == entries_.end() || iter->second.executable_path.empty())
-    return false;
-
-  *path = iter->second.executable_path;
-  return true;
-}
-
-}  // namespace service_manager
diff --git a/services/service_manager/service_overrides.h b/services/service_manager/service_overrides.h
deleted file mode 100644
index 1478ef7..0000000
--- a/services/service_manager/service_overrides.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_SERVICE_MANAGER_SERVICE_OVERRIDES_H_
-#define SERVICES_SERVICE_MANAGER_SERVICE_OVERRIDES_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/values.h"
-
-namespace service_manager {
-
-class ServiceOverrides {
- public:
-  struct Entry {
-    Entry();
-    ~Entry();
-
-    base::FilePath executable_path;
-    std::string package_name;
-  };
-
-  explicit ServiceOverrides(std::unique_ptr<base::Value> overrides);
-  ~ServiceOverrides();
-
-  bool GetExecutablePathOverride(const std::string& service_name,
-                                 base::FilePath* path) const;
-
-  const std::map<std::string, Entry>& entries() const { return entries_; }
-
- private:
-  std::map<std::string, Entry> entries_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceOverrides);
-};
-
-}  // namespace service_manager
-
-#endif  // SERVICES_SERVICE_MANAGER_SERVICE_OVERRIDES_H_
diff --git a/services/service_manager/standalone/context.cc b/services/service_manager/standalone/context.cc
index b7908da..12594f8 100644
--- a/services/service_manager/standalone/context.cc
+++ b/services/service_manager/standalone/context.cc
@@ -70,21 +70,7 @@
 
 Context::Context(
     ServiceProcessLauncherDelegate* service_process_launcher_delegate,
-    const std::vector<Manifest>& manifests)
-    : Context(service_process_launcher_delegate, nullptr, manifests) {}
-
-Context::Context(
-    ServiceProcessLauncherDelegate* service_process_launcher_delegate,
-    std::unique_ptr<base::Value> catalog_contents)
-    : Context(service_process_launcher_delegate,
-              std::move(catalog_contents),
-              std::vector<Manifest>()) {}
-
-Context::Context(
-    ServiceProcessLauncherDelegate* service_process_launcher_delegate,
-    std::unique_ptr<base::Value> catalog_contents,
-    const std::vector<Manifest>& manifests)
-    : main_entry_time_(base::Time::Now()) {
+    const std::vector<Manifest>& manifests) {
   TRACE_EVENT0("service_manager", "Context::Context");
 
   std::unique_ptr<ServiceProcessLauncherFactory>
@@ -97,14 +83,8 @@
       std::make_unique<ServiceProcessLauncherFactoryImpl>(
           service_process_launcher_delegate);
 #endif
-  if (!manifests.empty()) {
-    service_manager_ = std::make_unique<ServiceManager>(
-        std::move(service_process_launcher_factory), manifests, nullptr);
-  } else {
-    service_manager_ = std::make_unique<ServiceManager>(
-        std::move(service_process_launcher_factory),
-        std::move(catalog_contents), nullptr);
-  }
+  service_manager_ = std::make_unique<ServiceManager>(
+      std::move(service_process_launcher_factory), manifests);
 }
 
 Context::~Context() = default;
diff --git a/services/service_manager/standalone/context.h b/services/service_manager/standalone/context.h
index 2fc0c97aa..234a9aa 100644
--- a/services/service_manager/standalone/context.h
+++ b/services/service_manager/standalone/context.h
@@ -11,7 +11,6 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/time/time.h"
-#include "base/values.h"
 #include "services/service_manager/public/cpp/manifest.h"
 #include "services/service_manager/runner/host/service_process_launcher_delegate.h"
 
@@ -24,11 +23,6 @@
  public:
   Context(ServiceProcessLauncherDelegate* launcher_delegate,
           const std::vector<Manifest>& manifests);
-  Context(ServiceProcessLauncherDelegate* launcher_delegate,
-          std::unique_ptr<base::Value> catalog_contents);
-  Context(ServiceProcessLauncherDelegate* launcher_delegate,
-          std::unique_ptr<base::Value> catalog_contents,
-          const std::vector<Manifest>& manifests);
   ~Context();
 
   // Run the application specified on the command line, and run |on_quit| when
diff --git a/services/service_manager/tests/BUILD.gn b/services/service_manager/tests/BUILD.gn
index b3cc60a..db89a4b 100644
--- a/services/service_manager/tests/BUILD.gn
+++ b/services/service_manager/tests/BUILD.gn
@@ -26,11 +26,9 @@
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
     "//services/catalog:lib",
-    "//services/catalog:unittests",
     "//services/service_manager",
     "//services/service_manager/background:lib",
     "//services/service_manager/background/tests:unittests",
-    "//services/service_manager/embedder:unittests",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/cpp:unittests",
     "//services/service_manager/public/cpp/test:test_support",
diff --git a/services/service_manager/tests/service_manager/service_manager_listener_unittest.cc b/services/service_manager/tests/service_manager/service_manager_listener_unittest.cc
index e922c84..6927e6c8 100644
--- a/services/service_manager/tests/service_manager/service_manager_listener_unittest.cc
+++ b/services/service_manager/tests/service_manager/service_manager_listener_unittest.cc
@@ -103,7 +103,8 @@
 class ServiceManagerListenerTest : public testing::Test, public Service {
  public:
   ServiceManagerListenerTest()
-      : service_manager_(nullptr, GetTestManifests(), nullptr) {}
+      : service_manager_(nullptr, GetTestManifests()) {}
+
   ~ServiceManagerListenerTest() override = default;
 
   Connector* connector() { return service_binding_.GetConnector(); }
diff --git a/sql/BUILD.gn b/sql/BUILD.gn
index 0a220ec..3cfe156 100644
--- a/sql/BUILD.gn
+++ b/sql/BUILD.gn
@@ -20,7 +20,6 @@
     "meta_table.h",
     "recovery.cc",
     "recovery.h",
-    "sql_export.h",
     "sql_features.cc",
     "sql_features.h",
     "sql_memory_dump_provider.cc",
@@ -35,7 +34,7 @@
     "vfs_wrapper.h",
   ]
 
-  defines = [ "SQL_IMPLEMENTATION" ]
+  defines = [ "IS_SQL_IMPL" ]
 
   deps = [
     "//base",
diff --git a/sql/database.h b/sql/database.h
index e4f38ab..f4b6b29 100644
--- a/sql/database.h
+++ b/sql/database.h
@@ -15,6 +15,7 @@
 
 #include "base/callback.h"
 #include "base/compiler_specific.h"
+#include "base/component_export.h"
 #include "base/containers/flat_map.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
@@ -24,7 +25,6 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/time/tick_clock.h"
 #include "sql/internal_api_token.h"
-#include "sql/sql_export.h"
 #include "sql/statement_id.h"
 
 struct sqlite3;
@@ -64,7 +64,7 @@
 // TODO(pwnall): This should be renamed to Database. Class instances are
 // typically named "db_" / "db", and the class' equivalents in other systems
 // used by Chrome are named LevelDB::DB and blink::IDBDatabase.
-class SQL_EXPORT Database {
+class COMPONENT_EXPORT(SQL) Database {
  private:
   class StatementRef;  // Forward declaration, see real one below.
 
@@ -583,7 +583,8 @@
   //
   // The Database may revoke a StatementRef in some error cases, so callers
   // should always check validity before using.
-  class SQL_EXPORT StatementRef : public base::RefCounted<StatementRef> {
+  class COMPONENT_EXPORT(SQL) StatementRef
+      : public base::RefCounted<StatementRef> {
    public:
     REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
 
diff --git a/sql/error_delegate_util.h b/sql/error_delegate_util.h
index 4213321..b0c2ec78 100644
--- a/sql/error_delegate_util.h
+++ b/sql/error_delegate_util.h
@@ -7,14 +7,14 @@
 
 #include <string>
 
+#include "base/component_export.h"
 #include "base/files/file_path.h"
-#include "sql/sql_export.h"
 
 namespace sql {
 
 // Returns true if it is highly unlikely that the database can recover from
 // |error|.
-SQL_EXPORT bool IsErrorCatastrophic(int error);
+COMPONENT_EXPORT(SQL) bool IsErrorCatastrophic(int error);
 
 // Gets diagnostic info of the given |corrupted_file_path| that can be appended
 // to a corrupt database diagnostics info. The file info are not localized as
@@ -22,7 +22,8 @@
 // Also the full file path is not appended as it might contain some PII. Instead
 // only the last two components of the path are appended to distinguish between
 // default and user profiles.
-SQL_EXPORT std::string GetCorruptFileDiagnosticsInfo(
+COMPONENT_EXPORT(SQL)
+std::string GetCorruptFileDiagnosticsInfo(
     const base::FilePath& corrupted_file_path);
 
 }  // namespace sql
diff --git a/sql/initialization.h b/sql/initialization.h
index 98a625a..01eca433 100644
--- a/sql/initialization.h
+++ b/sql/initialization.h
@@ -5,7 +5,7 @@
 #ifndef SQL_INITIALIZATION_H_
 #define SQL_INITIALIZATION_H_
 
-#include "sql/sql_export.h"
+#include "base/component_export.h"
 
 namespace sql {
 
@@ -16,7 +16,7 @@
 //
 // The function is exposed for other components that use SQLite indirectly, such
 // as Blink.
-SQL_EXPORT void EnsureSqliteInitialized();
+COMPONENT_EXPORT(SQL) void EnsureSqliteInitialized();
 
 }  // namespace sql
 
diff --git a/sql/meta_table.h b/sql/meta_table.h
index 0ce66de..9b4acfe 100644
--- a/sql/meta_table.h
+++ b/sql/meta_table.h
@@ -8,8 +8,8 @@
 #include <stdint.h>
 #include <string>
 
+#include "base/component_export.h"
 #include "base/macros.h"
-#include "sql/sql_export.h"
 
 namespace sql {
 
@@ -22,7 +22,7 @@
 // * Helper methods to assist in database schema version control.
 // * Historical data on past attempts to mmap the database to make it possible
 //   to avoid unconditionally retrying to load broken databases.
-class SQL_EXPORT MetaTable {
+class COMPONENT_EXPORT(SQL) MetaTable {
  public:
   MetaTable();
   ~MetaTable();
diff --git a/sql/recovery.h b/sql/recovery.h
index 69dd092..aaaf780 100644
--- a/sql/recovery.h
+++ b/sql/recovery.h
@@ -9,6 +9,7 @@
 
 #include <memory>
 
+#include "base/component_export.h"
 #include "base/macros.h"
 #include "sql/database.h"
 
@@ -62,7 +63,7 @@
 // If Recovered() is not called, then RazeAndClose() is called on
 // orig_db.
 
-class SQL_EXPORT Recovery {
+class COMPONENT_EXPORT(SQL) Recovery {
  public:
   ~Recovery();
 
diff --git a/sql/sql_export.h b/sql/sql_export.h
deleted file mode 100644
index 165120c..0000000
--- a/sql/sql_export.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SQL_SQL_EXPORT_H_
-#define SQL_SQL_EXPORT_H_
-
-#if defined(COMPONENT_BUILD)
-#if defined(WIN32)
-
-#if defined(SQL_IMPLEMENTATION)
-#define SQL_EXPORT __declspec(dllexport)
-#else
-#define SQL_EXPORT __declspec(dllimport)
-#endif  // defined(SQL_IMPLEMENTATION)
-
-#else // defined(WIN32)
-#if defined(SQL_IMPLEMENTATION)
-#define SQL_EXPORT __attribute__((visibility("default")))
-#else
-#define SQL_EXPORT
-#endif
-#endif
-
-#else // defined(COMPONENT_BUILD)
-#define SQL_EXPORT
-#endif
-
-#endif  // SQL_SQL_EXPORT_H_
diff --git a/sql/sql_features.h b/sql/sql_features.h
index 4b0c947..1969727 100644
--- a/sql/sql_features.h
+++ b/sql/sql_features.h
@@ -5,14 +5,14 @@
 #ifndef SQL_SQL_FEATURES_H_
 #define SQL_SQL_FEATURES_H_
 
+#include "base/component_export.h"
 #include "base/feature_list.h"
-#include "sql/sql_export.h"
 
 namespace sql {
 
 namespace features {
 
-SQL_EXPORT extern const base::Feature kSqlTempStoreMemory;
+COMPONENT_EXPORT(SQL) extern const base::Feature kSqlTempStoreMemory;
 
 }  // namespace features
 
diff --git a/sql/sql_memory_dump_provider.h b/sql/sql_memory_dump_provider.h
index f6213bf..57e88c6 100644
--- a/sql/sql_memory_dump_provider.h
+++ b/sql/sql_memory_dump_provider.h
@@ -5,16 +5,16 @@
 #ifndef SQL_SQL_MEMORY_DUMP_PROVIDER_H
 #define SQL_SQL_MEMORY_DUMP_PROVIDER_H
 
+#include "base/component_export.h"
 #include "base/macros.h"
 #include "base/memory/singleton.h"
 #include "base/trace_event/memory_dump_provider.h"
-#include "sql/sql_export.h"
 
 namespace sql {
 
 // Adds process-wide memory usage statistics about sqlite to chrome://tracing.
 // sql::Database::OnMemoryDump adds per-connection memory statistics.
-class SQL_EXPORT SqlMemoryDumpProvider
+class COMPONENT_EXPORT(SQL) SqlMemoryDumpProvider
     : public base::trace_event::MemoryDumpProvider {
  public:
   static SqlMemoryDumpProvider* GetInstance();
diff --git a/sql/statement.h b/sql/statement.h
index cdef13f..ade63a59 100644
--- a/sql/statement.h
+++ b/sql/statement.h
@@ -9,12 +9,12 @@
 #include <string>
 #include <vector>
 
+#include "base/component_export.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/sequence_checker.h"
 #include "base/strings/string16.h"
 #include "sql/database.h"
-#include "sql/sql_export.h"
 
 namespace sql {
 
@@ -43,7 +43,7 @@
 // Step() and Run() just return true to signal success. If you want to handle
 // specific errors such as database corruption, install an error handler in
 // in the connection object using set_error_delegate().
-class SQL_EXPORT Statement {
+class COMPONENT_EXPORT(SQL) Statement {
  public:
   // Creates an uninitialized statement. The statement will be invalid until
   // you initialize it via Assign.
diff --git a/sql/statement_id.h b/sql/statement_id.h
index f52b725d..ee5a90e 100644
--- a/sql/statement_id.h
+++ b/sql/statement_id.h
@@ -7,7 +7,7 @@
 
 #include <cstddef>
 
-#include "sql/sql_export.h"
+#include "base/component_export.h"
 
 namespace sql {
 
@@ -18,7 +18,7 @@
 //
 // StatementID instances should be constructed by using the SQL_FROM_HERE
 // macro, which produces an unique ID based on the source file name and line.
-class SQL_EXPORT StatementID {
+class COMPONENT_EXPORT(SQL) StatementID {
  public:
   // Creates an ID representing a line in the source tree.
   //
diff --git a/sql/transaction.h b/sql/transaction.h
index 3c01a1e6..0b9af69f 100644
--- a/sql/transaction.h
+++ b/sql/transaction.h
@@ -5,14 +5,14 @@
 #ifndef SQL_TRANSACTION_H_
 #define SQL_TRANSACTION_H_
 
+#include "base/component_export.h"
 #include "base/macros.h"
-#include "sql/sql_export.h"
 
 namespace sql {
 
 class Database;
 
-class SQL_EXPORT Transaction {
+class COMPONENT_EXPORT(SQL) Transaction {
  public:
   // Creates the scoped transaction object. You MUST call Begin() to begin the
   // transaction. If you have begun a transaction and not committed it, the
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index 1043b7c..6faaf09f 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -38,6 +38,8 @@
     "indexeddb/indexeddb_key_path.cc",
     "indexeddb/indexeddb_key_range.cc",
     "indexeddb/indexeddb_metadata.cc",
+    "loader/url_loader_factory_bundle.cc",
+    "loader/url_loader_factory_bundle_mojom_traits.cc",
     "manifest/manifest.cc",
     "manifest/manifest_icon_selector.cc",
     "messaging/cloneable_message.cc",
diff --git a/third_party/blink/common/loader/OWNERS b/third_party/blink/common/loader/OWNERS
new file mode 100644
index 0000000..e4c226c
--- /dev/null
+++ b/third_party/blink/common/loader/OWNERS
@@ -0,0 +1,5 @@
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+
+# TEAM: loading-dev@chromium.org
+# COMPONENT: Blink>Loader
diff --git a/content/common/url_loader_factory_bundle.cc b/third_party/blink/common/loader/url_loader_factory_bundle.cc
similarity index 95%
rename from content/common/url_loader_factory_bundle.cc
rename to third_party/blink/common/loader/url_loader_factory_bundle.cc
index ca25256..acab90d 100644
--- a/content/common/url_loader_factory_bundle.cc
+++ b/third_party/blink/common/loader/url_loader_factory_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 "content/common/url_loader_factory_bundle.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
 
 #include <utility>
 
@@ -10,7 +10,7 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "url/gurl.h"
 
-namespace content {
+namespace blink {
 
 namespace {
 
@@ -112,7 +112,7 @@
   if (default_factory_)
     default_factory_->Clone(mojo::MakeRequest(&default_factory_info));
 
-  auto info = std::make_unique<URLLoaderFactoryBundleInfo>(
+  auto info = std::make_unique<blink::URLLoaderFactoryBundleInfo>(
       std::move(default_factory_info),
       ClonePtrMapToPtrInfoMap(scheme_specific_factories_),
       ClonePtrMapToPtrInfoMap(initiator_specific_factories_),
@@ -141,4 +141,4 @@
   bypass_redirect_checks_ = info->bypass_redirect_checks();
 }
 
-}  // namespace content
+}  // namespace blink
diff --git a/content/common/url_loader_factory_bundle_struct_traits.cc b/third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.cc
similarity index 73%
rename from content/common/url_loader_factory_bundle_struct_traits.cc
rename to third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.cc
index 9ce8963..645d5d4 100644
--- a/content/common/url_loader_factory_bundle_struct_traits.cc
+++ b/third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.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/common/url_loader_factory_bundle_struct_traits.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h"
 
 #include <memory>
 #include <utility>
@@ -11,9 +11,8 @@
 
 namespace mojo {
 
-using Traits =
-    StructTraits<content::mojom::URLLoaderFactoryBundleDataView,
-                 std::unique_ptr<content::URLLoaderFactoryBundleInfo>>;
+using Traits = StructTraits<blink::mojom::URLLoaderFactoryBundleDataView,
+                            std::unique_ptr<blink::URLLoaderFactoryBundleInfo>>;
 
 // static
 network::mojom::URLLoaderFactoryPtrInfo Traits::default_factory(
@@ -28,13 +27,13 @@
 }
 
 // static
-content::URLLoaderFactoryBundleInfo::SchemeMap
-Traits::scheme_specific_factories(BundleInfoType& bundle) {
+blink::URLLoaderFactoryBundleInfo::SchemeMap Traits::scheme_specific_factories(
+    BundleInfoType& bundle) {
   return std::move(bundle->scheme_specific_factory_infos());
 }
 
 // static
-content::URLLoaderFactoryBundleInfo::OriginMap
+blink::URLLoaderFactoryBundleInfo::OriginMap
 Traits::initiator_specific_factories(BundleInfoType& bundle) {
   return std::move(bundle->initiator_specific_factory_infos());
 }
@@ -45,9 +44,9 @@
 }
 
 // static
-bool Traits::Read(content::mojom::URLLoaderFactoryBundleDataView data,
+bool Traits::Read(blink::mojom::URLLoaderFactoryBundleDataView data,
                   BundleInfoType* out_bundle) {
-  *out_bundle = std::make_unique<content::URLLoaderFactoryBundleInfo>();
+  *out_bundle = std::make_unique<blink::URLLoaderFactoryBundleInfo>();
 
   (*out_bundle)->default_factory_info() =
       data.TakeDefaultFactory<network::mojom::URLLoaderFactoryPtrInfo>();
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index da86287..254b251 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -60,6 +60,8 @@
     "indexeddb/indexeddb_key_range.h",
     "indexeddb/indexeddb_metadata.h",
     "indexeddb/web_idb_types.h",
+    "loader/url_loader_factory_bundle.h",
+    "loader/url_loader_factory_bundle_mojom_traits.h",
     "manifest/manifest.h",
     "manifest/manifest_icon_selector.h",
     "manifest/web_display_mode.h",
@@ -89,6 +91,7 @@
   ]
 
   public_deps = [
+    "//services/network/public/cpp:cpp",
     "//skia",
     "//third_party/blink/public/mojom:mojom_modules_headers",
   ]
diff --git a/third_party/blink/public/common/DEPS b/third_party/blink/public/common/DEPS
index c28e08f..79d91368 100644
--- a/third_party/blink/public/common/DEPS
+++ b/third_party/blink/public/common/DEPS
@@ -10,6 +10,8 @@
     "+build",
     "+net",
     "+mojo",
+    "+services/network/public/cpp/shared_url_loader_factory.h",
+    "+services/network/public/mojom/url_loader_factory.mojom.h",
     "+skia/public/interfaces",
     "+third_party/blink/public/common",
     "+third_party/blink/public/mojom",
diff --git a/third_party/blink/public/common/loader/OWNERS b/third_party/blink/public/common/loader/OWNERS
new file mode 100644
index 0000000..10f8abc
--- /dev/null
+++ b/third_party/blink/public/common/loader/OWNERS
@@ -0,0 +1,7 @@
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *.typemap=set noparent
+per-file *.typemap=file://ipc/SECURITY_OWNERS
+
+# TEAM: loading-dev@chromium.org
+# COMPONENT: Blink>Loader
diff --git a/content/common/url_loader_factory_bundle.h b/third_party/blink/public/common/loader/url_loader_factory_bundle.h
similarity index 92%
rename from content/common/url_loader_factory_bundle.h
rename to third_party/blink/public/common/loader/url_loader_factory_bundle.h
index b864edc..eb70586 100644
--- a/content/common/url_loader_factory_bundle.h
+++ b/third_party/blink/public/common/loader/url_loader_factory_bundle.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_H_
-#define CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_URL_LOADER_FACTORY_BUNDLE_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_URL_LOADER_FACTORY_BUNDLE_H_
 
 #include <map>
 #include <memory>
@@ -11,20 +11,20 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "content/common/content_export.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/blink/public/common/common_export.h"
 #include "url/origin.h"
 
 namespace network {
 struct ResourceRequest;
 };
 
-namespace content {
+namespace blink {
 
 // Holds the internal state of a URLLoaderFactoryBundle in a form that is safe
 // to pass across sequences.
-class CONTENT_EXPORT URLLoaderFactoryBundleInfo
+class BLINK_COMMON_EXPORT URLLoaderFactoryBundleInfo
     : public network::SharedURLLoaderFactoryInfo {
  public:
   // Map from URL scheme to URLLoaderFactoryPtrInfo for handling URL requests
@@ -82,7 +82,7 @@
 
 // Encapsulates a collection of URLLoaderFactoryPtrs which can be usd to acquire
 // loaders for various types of resource requests.
-class CONTENT_EXPORT URLLoaderFactoryBundle
+class BLINK_COMMON_EXPORT URLLoaderFactoryBundle
     : public network::SharedURLLoaderFactory {
  public:
   URLLoaderFactoryBundle();
@@ -154,6 +154,6 @@
   bool bypass_redirect_checks_ = false;
 };
 
-}  // namespace content
+}  // namespace blink
 
-#endif  // CONTENT_COMMON_URL_LOADER_FACTORY_BUNDLE_H_
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_URL_LOADER_FACTORY_BUNDLE_H_
diff --git a/third_party/blink/public/common/loader/url_loader_factory_bundle.typemap b/third_party/blink/public/common/loader/url_loader_factory_bundle.typemap
new file mode 100644
index 0000000..41c980d
--- /dev/null
+++ b/third_party/blink/public/common/loader/url_loader_factory_bundle.typemap
@@ -0,0 +1,11 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom =
+    "//third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom"
+public_headers =
+    [ "//third_party/blink/public/common/loader/url_loader_factory_bundle.h" ]
+traits_headers = [ "//third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h" ]
+
+type_mappings = [ "blink.mojom.URLLoaderFactoryBundle=std::unique_ptr<blink::URLLoaderFactoryBundleInfo>[move_only,nullable_is_same_type]" ]
diff --git a/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h b/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h
new file mode 100644
index 0000000..4727643f
--- /dev/null
+++ b/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h
@@ -0,0 +1,47 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_URL_LOADER_FACTORY_BUNDLE_MOJOM_TRAITS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_URL_LOADER_FACTORY_BUNDLE_MOJOM_TRAITS_H_
+
+#include <memory>
+
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
+#include "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct BLINK_COMMON_EXPORT
+    StructTraits<blink::mojom::URLLoaderFactoryBundleDataView,
+                 std::unique_ptr<blink::URLLoaderFactoryBundleInfo>> {
+  using BundleInfoType = std::unique_ptr<blink::URLLoaderFactoryBundleInfo>;
+
+  static bool IsNull(const BundleInfoType& bundle) { return !bundle; }
+
+  static void SetToNull(BundleInfoType* bundle) { bundle->reset(); }
+
+  static network::mojom::URLLoaderFactoryPtrInfo default_factory(
+      BundleInfoType& bundle);
+
+  static network::mojom::URLLoaderFactoryPtrInfo appcache_factory(
+      BundleInfoType& bundle);
+
+  static blink::URLLoaderFactoryBundleInfo::SchemeMap scheme_specific_factories(
+      BundleInfoType& bundle);
+
+  static blink::URLLoaderFactoryBundleInfo::OriginMap
+  initiator_specific_factories(BundleInfoType& bundle);
+
+  static bool bypass_redirect_checks(BundleInfoType& bundle);
+
+  static bool Read(blink::mojom::URLLoaderFactoryBundleDataView data,
+                   BundleInfoType* out_bundle);
+};
+
+}  // namespace mojo
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_URL_LOADER_FACTORY_BUNDLE_MOJOM_TRAITS_H_
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index bb85261..6ad4e1f 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -43,6 +43,7 @@
     "loader/navigation_predictor.mojom",
     "loader/pause_subresource_loading_handle.mojom",
     "loader/previews_resource_loading_hints.mojom",
+    "loader/url_loader_factory_bundle.mojom",
     "manifest/display_mode.mojom",
     "manifest/manifest.mojom",
     "manifest/manifest_manager.mojom",
diff --git a/third_party/blink/public/mojom/indexeddb/indexeddb.mojom b/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
index 3c847d38..474407bf 100644
--- a/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
+++ b/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
@@ -370,17 +370,15 @@
 };
 
 interface IDBFactory {
-  GetDatabaseInfo(associated IDBCallbacks callbacks, url.mojom.Origin origin);
-  GetDatabaseNames(associated IDBCallbacks callbacks, url.mojom.Origin origin);
+  GetDatabaseInfo(associated IDBCallbacks callbacks);
+  GetDatabaseNames(associated IDBCallbacks callbacks);
   Open(associated IDBCallbacks callbacks,
        associated IDBDatabaseCallbacks database_callbacks,
-       url.mojom.Origin origin,
        mojo_base.mojom.String16 name,
        int64 version,
        int64 transaction_id);
-  DeleteDatabase(associated IDBCallbacks callbacks, url.mojom.Origin origin,
+  DeleteDatabase(associated IDBCallbacks callbacks,
                  mojo_base.mojom.String16 name, bool force_close);
-  AbortTransactionsAndCompactDatabase(url.mojom.Origin origin) =>
-                                     (IDBStatus status);
-  AbortTransactionsForDatabase(url.mojom.Origin origin) => (IDBStatus status);
+  AbortTransactionsAndCompactDatabase() => (IDBStatus status);
+  AbortTransactionsForDatabase() => (IDBStatus status);
 };
diff --git a/content/common/url_loader_factory_bundle.mojom b/third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom
similarity index 94%
rename from content/common/url_loader_factory_bundle.mojom
rename to third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom
index d3e1ec7d..24ac0fc 100644
--- a/content/common/url_loader_factory_bundle.mojom
+++ b/third_party/blink/public/mojom/loader/url_loader_factory_bundle.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.
 
-module content.mojom;
+module blink.mojom;
 
 import "services/network/public/mojom/url_loader_factory.mojom";
 import "url/mojom/origin.mojom";
@@ -12,7 +12,7 @@
 // This supports a scenario where URLLoaderFactoryBundle contains only
 // the factories that need to be updated (and allows leaving out factories
 // that should not be updated/cloberred).
-// See also content::URLLoaderFactoryBundle::Update.
+// See also blink::URLLoaderFactoryBundle::Update.
 struct URLLoaderFactoryBundle {
   // The default factory to be used when no others apply.
   // This must be non-null for a navigation commit when NetworkService is
diff --git a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
index 1fc679a..a251d2b 100644
--- a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
+++ b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
@@ -20,24 +20,6 @@
   // FetchEvent#request.
   FetchAPIRequest request;
 
-  // The following fields are used to create FetchEvent#request#body, depending
-  // on whether S13nServiceWorker/NetworkService are enabled.
-
-  // (A) S13nServiceWorker with NetworkService on:
-  // All information about the request body is provided in |request.body|, and
-  // |request.blob| is null.
-
-  // (B) S13nServiceWorker with NetworkService off:
-  // All information about the request body except for BlobPtrs is provided in
-  // |request.body|. These BlobPtrs need to be passed separately.
-  // Once the NetworkService is enabled, this will be no longer used since all
-  // Blobs are passed as data pipes which can live in |request.body|.
-  array<Blob> request_body_blob_ptrs;
-
-  // (C) non-S13nServiceWorker:
-  // All information to create the request body is packed into |request.blob|,
-  // and |request.body| is null.
-
   // FetchEvent#clientId.
   string client_id;
   // FetchEvent#preloadResponse.
diff --git a/third_party/blink/public/public_typemaps.gni b/third_party/blink/public/public_typemaps.gni
index 267d2a4..edc0f16 100644
--- a/third_party/blink/public/public_typemaps.gni
+++ b/third_party/blink/public/public_typemaps.gni
@@ -6,6 +6,7 @@
 typemaps = [
   "//third_party/blink/public/common/fetch/fetch_api_request_headers.typemap",
   "//third_party/blink/public/common/indexeddb/indexed_db_default.typemap",
+  "//third_party/blink/public/common/loader/url_loader_factory_bundle.typemap",
   "//third_party/blink/public/common/manifest/display_mode.typemap",
   "//third_party/blink/public/common/manifest/manifest.typemap",
   "//third_party/blink/public/common/notifications/notification_types.typemap",
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 ba3fa273..875829fa 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
@@ -245,6 +245,11 @@
 
   EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
   budget.DidPerformPhase(DisplayLockBudget::Phase::kLayout);
+  EXPECT_TRUE(budget.NeedsLifecycleUpdates());
+
+  budget.WillStartLifecycleUpdate();
+  EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+  budget.DidPerformPhase(DisplayLockBudget::Phase::kPrePaint);
 
   // Note that since the layout was indicated as done (from the budget
   // perspective), it will no longer need updates even though the true layout is
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index d5b2c06..d1bd473 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -706,6 +706,7 @@
 
     fetcher_ = frame_->Loader().GetDocumentLoader()->Fetcher();
     To<FrameFetchContext>(fetcher_->Context()).ProvideDocumentToContext(this);
+    fetcher_->SetConsoleLogger(this);
 
     // TODO(dcheng): Why does this need to check that DOMWindow is non-null?
     CustomElementRegistry* registry =
@@ -714,7 +715,7 @@
     if (registry && registration_context_)
       registry->Entangle(registration_context_);
   } else if (imports_controller_) {
-    fetcher_ = FrameFetchContext::CreateFetcherFromDocument(this);
+    fetcher_ = FrameFetchContext::CreateFetcherForImportedDocument(this);
   } else {
     fetcher_ = MakeGarbageCollected<ResourceFetcher>(nullptr);
   }
@@ -2299,7 +2300,7 @@
 
   PropagateStyleToViewport();
   View()->UpdateCountersAfterStyleChange();
-  GetLayoutView()->RecalcOverflow();
+  GetLayoutView()->RecalcLayoutOverflow();
 
   DCHECK(!NeedsStyleRecalc());
   DCHECK(!ChildNeedsStyleRecalc());
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.cc b/third_party/blink/renderer/core/execution_context/execution_context.cc
index 44e16cf1..ca30ead 100644
--- a/third_party/blink/renderer/core/execution_context/execution_context.cc
+++ b/third_party/blink/renderer/core/execution_context/execution_context.cc
@@ -259,6 +259,7 @@
   visitor->Trace(pending_exceptions_);
   visitor->Trace(csp_delegate_);
   ContextLifecycleNotifier::Trace(visitor);
+  ConsoleLoggerImplBase::Trace(visitor);
   Supplementable<ExecutionContext>::Trace(visitor);
 }
 
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.h b/third_party/blink/renderer/core/execution_context/execution_context.h
index 68afe9e..b76faa8 100644
--- a/third_party/blink/renderer/core/execution_context/execution_context.h
+++ b/third_party/blink/renderer/core/execution_context/execution_context.h
@@ -38,6 +38,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/context_lifecycle_notifier.h"
 #include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/loader/console_logger_impl_base.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/loader/fetch/https_state.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
@@ -53,7 +54,6 @@
 
 namespace blink {
 
-class ConsoleMessage;
 class ContentSecurityPolicy;
 class ContentSecurityPolicyDelegate;
 class CoreProbeSink;
@@ -103,7 +103,8 @@
 // by an extension developer, but these share an ExecutionContext (the document)
 // in common.
 class CORE_EXPORT ExecutionContext : public ContextLifecycleNotifier,
-                                     public Supplementable<ExecutionContext> {
+                                     public Supplementable<ExecutionContext>,
+                                     public ConsoleLoggerImplBase {
   MERGE_GARBAGE_COLLECTED_MIXINS();
 
  public:
@@ -171,7 +172,6 @@
 
   void DispatchErrorEvent(ErrorEvent*, SanitizeScriptErrors);
 
-  virtual void AddConsoleMessage(ConsoleMessage*) = 0;
   virtual void ExceptionThrown(ErrorEvent*) = 0;
 
   PublicURLManager& GetPublicURLManager();
diff --git a/third_party/blink/renderer/core/frame/frame_console.cc b/third_party/blink/renderer/core/frame/frame_console.cc
index 48b3e48..bfe16e6c 100644
--- a/third_party/blink/renderer/core/frame/frame_console.cc
+++ b/third_party/blink/renderer/core/frame/frame_console.cc
@@ -146,6 +146,7 @@
 
 void FrameConsole::Trace(blink::Visitor* visitor) {
   visitor->Trace(frame_);
+  ConsoleLoggerImplBase::Trace(visitor);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/frame_console.h b/third_party/blink/renderer/core/frame/frame_console.h
index d8061d2..71722a5 100644
--- a/third_party/blink/renderer/core/frame/frame_console.h
+++ b/third_party/blink/renderer/core/frame/frame_console.h
@@ -31,6 +31,7 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/inspector/console_types.h"
+#include "third_party/blink/renderer/core/loader/console_logger_impl_base.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -49,7 +50,10 @@
 // around ChromeClient calls and the way that Blink core/ can add messages to
 // the console.
 class CORE_EXPORT FrameConsole final
-    : public GarbageCollectedFinalized<FrameConsole> {
+    : public GarbageCollectedFinalized<FrameConsole>,
+      public ConsoleLoggerImplBase {
+  USING_GARBAGE_COLLECTED_MIXIN(FrameConsole);
+
  public:
   static FrameConsole* Create(LocalFrame& frame) {
     return MakeGarbageCollected<FrameConsole>(frame);
@@ -57,6 +61,10 @@
 
   explicit FrameConsole(LocalFrame&);
 
+  // ConsoleLoggerImplBase implementation.
+  void AddConsoleMessage(ConsoleMessage* message) override {
+    AddMessage(message);
+  }
   void AddMessage(ConsoleMessage*);
 
   bool AddMessageToStorage(ConsoleMessage*);
@@ -73,7 +81,7 @@
                       unsigned long request_identifier,
                       const ResourceError&);
 
-  void Trace(blink::Visitor*);
+  void Trace(blink::Visitor*) override;
 
  private:
   Member<LocalFrame> frame_;
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 664ceba41..7224e37f 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -249,7 +249,12 @@
       paint_frame_count_(0),
       unique_id_(NewUniqueObjectId()),
       jank_tracker_(std::make_unique<JankTracker>(this)),
-      paint_timing_detector_(MakeGarbageCollected<PaintTimingDetector>(this)) {
+      paint_timing_detector_(MakeGarbageCollected<PaintTimingDetector>(this))
+#if DCHECK_IS_ON()
+      ,
+      is_updating_descendant_dependent_flags_(false)
+#endif
+{
   // Propagate the marginwidth/height and scrolling modes to the view.
   if (frame_->Owner() &&
       frame_->Owner()->ScrollingMode() == kScrollbarAlwaysOff)
@@ -623,21 +628,10 @@
 
 void LocalFrameView::LayoutFromRootObject(LayoutObject& root) {
   LayoutState layout_state(root);
-  if (!root.IsBoxModelObject()) {
+  if (!root.IsBoxModelObject())
     root.UpdateLayout();
-  } else {
-    // Laying out the root may change its visual overflow. If so, that
-    // visual overflow needs to propagate to its containing block.
-    LayoutBoxModelObject& box_object = ToLayoutBoxModelObject(root);
-    LayoutRect previous_visual_overflow_rect = box_object.VisualOverflowRect();
-    box_object.UpdateLayout();
-    if (box_object.VisualOverflowRect() != previous_visual_overflow_rect) {
-      // TODO(chrishtr): this can probably just set the dirty bit for
-      // visual overflow, not layout overflow.
-      box_object.SetNeedsOverflowRecalc();
-      GetLayoutView()->RecalcOverflow();
-    }
-  }
+  else
+    ToLayoutBoxModelObject(root).UpdateLayout();
 }
 
 void LocalFrameView::PrepareLayoutAnalyzer() {
@@ -2128,9 +2122,6 @@
 
 // TODO(schenney): Pass a LifecycleUpdateReason in here
 bool LocalFrameView::UpdateLifecycleToCompositingInputsClean() {
-  // When CAP is enabled, the standard compositing lifecycle steps do not
-  // exist; compositing is done after paint instead.
-  DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
   return GetFrame().LocalFrameRoot().View()->UpdateLifecyclePhases(
       DocumentLifecycle::kCompositingInputsClean,
       DocumentLifecycle::LifecycleUpdateReason::kOther);
@@ -2478,10 +2469,16 @@
                              LocalFrameUkmAggregator::kCompositing);
     layout_view->Compositor()->UpdateIfNeededRecursive(target_state);
   } else {
+#if DCHECK_IS_ON()
+    SetIsUpdatingDescendantDependentFlags(true);
+#endif
     ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
       frame_view.GetLayoutView()->Layer()->UpdateDescendantDependentFlags();
       frame_view.GetLayoutView()->CommitPendingSelection();
     });
+#if DCHECK_IS_ON()
+    SetIsUpdatingDescendantDependentFlags(false);
+#endif
   }
 
   // We may be in kCompositingInputsClean clean, which does not need to notify
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h
index 35a2c9d..2e5adf3 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.h
+++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -704,6 +704,15 @@
   // Return the UKM aggregator for this frame, creating it if necessary.
   LocalFrameUkmAggregator& EnsureUkmAggregator();
 
+#if DCHECK_IS_ON()
+  void SetIsUpdatingDescendantDependentFlags(bool val) {
+    is_updating_descendant_dependent_flags_ = val;
+  }
+  bool IsUpdatingDescendantDependentFlags() const {
+    return is_updating_descendant_dependent_flags_;
+  }
+#endif
+
   void RegisterForLifecycleNotifications(LifecycleNotificationObserver*);
   void UnregisterFromLifecycleNotifications(LifecycleNotificationObserver*);
 
@@ -999,6 +1008,10 @@
 
   HeapHashSet<WeakMember<LifecycleNotificationObserver>> lifecycle_observers_;
 
+#if DCHECK_IS_ON()
+  bool is_updating_descendant_dependent_flags_;
+#endif
+
   FRIEND_TEST_ALL_PREFIXES(WebViewTest, DeviceEmulationResetScrollbars);
 };
 
diff --git a/third_party/blink/renderer/core/layout/custom/layout_custom.cc b/third_party/blink/renderer/core/layout/custom/layout_custom.cc
index 5c62e93d..611c30a 100644
--- a/third_party/blink/renderer/core/layout/custom/layout_custom.cc
+++ b/third_party/blink/renderer/core/layout/custom/layout_custom.cc
@@ -266,7 +266,7 @@
       relayout_children = true;
 
     LayoutPositionedObjects(relayout_children || IsDocumentElement());
-    ComputeOverflow(old_client_after_edge);
+    ComputeLayoutOverflow(old_client_after_edge);
   }
 
   UpdateAfterLayout();
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc
index 4ac4e23..5b31788 100644
--- a/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -519,25 +519,20 @@
     AddLayoutOverflowFromBlockChildren();
 }
 
-void LayoutBlock::ComputeOverflow(LayoutUnit old_client_after_edge,
-                                  bool recompute_floats) {
+void LayoutBlock::ComputeVisualOverflow(bool) {
   LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
-  ClearAllOverflows();
-  ComputeLayoutOverflow(old_client_after_edge, recompute_floats);
-  ComputeVisualOverflow(previous_visual_overflow_rect, recompute_floats);
-}
-
-void LayoutBlock::ComputeVisualOverflow(
-    const LayoutRect& previous_visual_overflow_rect,
-    bool) {
+  ClearVisualOverflow();
   AddVisualOverflowFromChildren();
 
   AddVisualEffectOverflow();
   AddVisualOverflowFromTheme();
 
   if (VisualOverflowRect() != previous_visual_overflow_rect) {
-    if (Layer())
-      Layer()->SetNeedsCompositingInputsUpdate();
+    if (Layer()) {
+      Layer()->SetNeedsCompositingInputsUpdate(
+          PaintLayer::DoesNotNeedDescendantDependentUpdate);
+    }
+    SetShouldCheckForPaintInvalidation();
     GetFrameView()->SetIntersectionObservationState(LocalFrameView::kDesired);
   }
 }
@@ -545,6 +540,8 @@
 DISABLE_CFI_PERF
 void LayoutBlock::ComputeLayoutOverflow(LayoutUnit old_client_after_edge,
                                         bool) {
+  ClearSelfNeedsLayoutOverflowRecalc();
+  ClearLayoutOverflow();
   AddLayoutOverflowFromChildren();
   AddLayoutOverflowFromPositionedObjects();
 
@@ -583,7 +580,6 @@
     if (child->IsLayoutBlockFlow() &&
         ToLayoutBlockFlow(child)->ContainsInlineWithOutlineAndContinuation())
       ToLayoutBlockFlow(child)->AddVisualOverflowFromInlineChildren();
-
     AddVisualOverflowFromChild(*child);
   }
 }
@@ -744,7 +740,7 @@
     // bottom edge before we clamp our height. Since this information isn't
     // available during simplifiedLayout, we cache the value in m_overflow.
     LayoutUnit old_client_after_edge = LayoutClientAfterEdge();
-    ComputeOverflow(old_client_after_edge, true);
+    ComputeLayoutOverflow(old_client_after_edge, true);
   }
 
   UpdateAfterLayout();
@@ -2101,77 +2097,147 @@
   cached_constraint_space_.reset(new NGConstraintSpace(space));
 }
 
-bool LayoutBlock::RecalcNormalFlowChildOverflowIfNeeded(
+bool LayoutBlock::RecalcNormalFlowChildLayoutOverflowIfNeeded(
     LayoutObject* layout_object) {
   if (layout_object->IsOutOfFlowPositioned())
     return false;
-  return layout_object->RecalcOverflow();
+  return layout_object->RecalcLayoutOverflow();
 }
 
-bool LayoutBlock::RecalcChildOverflow() {
-  DCHECK(!IsTable());
-  DCHECK(ChildNeedsOverflowRecalc());
-  ClearChildNeedsLayoutOverflowRecalc();
-  ClearChildNeedsVisualOverflowRecalc();
+bool LayoutBlock::RecalcNormalFlowChildVisualOverflowIfNeeded(
+    LayoutObject* layout_object) {
+  if (layout_object->IsOutOfFlowPositioned() ||
+      (layout_object->HasLayer() &&
+       ToLayoutBoxModelObject(layout_object)->HasSelfPaintingLayer()))
+    return false;
+  return layout_object->RecalcVisualOverflow();
+}
 
-  bool children_overflow_changed = false;
+bool LayoutBlock::RecalcChildLayoutOverflow() {
+  DCHECK(!IsTable());
+  DCHECK(ChildNeedsLayoutOverflowRecalc());
+  ClearChildNeedsLayoutOverflowRecalc();
+
+  bool children_layout_overflow_changed = false;
 
   if (ChildrenInline()) {
     SECURITY_DCHECK(IsLayoutBlockFlow());
-    children_overflow_changed =
-        ToLayoutBlockFlow(this)->RecalcInlineChildrenOverflow();
+    children_layout_overflow_changed =
+        ToLayoutBlockFlow(this)->RecalcInlineChildrenLayoutOverflow();
   } else {
     for (LayoutBox* box = FirstChildBox(); box; box = box->NextSiblingBox()) {
-      if (RecalcNormalFlowChildOverflowIfNeeded(box))
-        children_overflow_changed = true;
+      if (RecalcNormalFlowChildLayoutOverflowIfNeeded(box))
+        children_layout_overflow_changed = true;
     }
   }
 
-  return RecalcPositionedDescendantsOverflow() || children_overflow_changed;
+  return RecalcPositionedDescendantsLayoutOverflow() ||
+         children_layout_overflow_changed;
 }
 
-bool LayoutBlock::RecalcPositionedDescendantsOverflow() {
-  bool children_overflow_changed = false;
+bool LayoutBlock::RecalcChildVisualOverflow() {
+  DCHECK(!IsTable());
+  DCHECK(ChildNeedsVisualOverflowRecalc());
+  ClearChildNeedsVisualOverflowRecalc();
+
+  bool children_visual_overflow_changed = false;
+
+  if (ChildrenInline()) {
+    SECURITY_DCHECK(IsLayoutBlockFlow());
+    children_visual_overflow_changed =
+        ToLayoutBlockFlow(this)->RecalcInlineChildrenVisualOverflow();
+  } else {
+    for (LayoutBox* box = FirstChildBox(); box; box = box->NextSiblingBox()) {
+      if (RecalcNormalFlowChildVisualOverflowIfNeeded(box))
+        children_visual_overflow_changed = true;
+    }
+  }
+
+  return RecalcPositionedDescendantsVisualOverflow() ||
+         children_visual_overflow_changed;
+}
+
+bool LayoutBlock::RecalcPositionedDescendantsLayoutOverflow() {
+  bool children_layout_overflow_changed = false;
 
   TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects();
   if (!positioned_descendants)
-    return children_overflow_changed;
+    return children_layout_overflow_changed;
 
   for (auto* box : *positioned_descendants) {
-    if (box->RecalcOverflow())
-      children_overflow_changed = true;
+    if (box->RecalcLayoutOverflow())
+      children_layout_overflow_changed = true;
   }
-  return children_overflow_changed;
+  return children_layout_overflow_changed;
 }
 
-bool LayoutBlock::RecalcOverflow() {
-  bool children_overflow_changed = false;
-  if (ChildNeedsOverflowRecalc())
-    children_overflow_changed = RecalcChildOverflow();
+bool LayoutBlock::RecalcPositionedDescendantsVisualOverflow() {
+  bool children_visual_overflow_changed = false;
 
-  bool self_needs_overflow_recalc = SelfNeedsOverflowRecalc();
-  if (!self_needs_overflow_recalc && !children_overflow_changed)
+  TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects();
+  if (!positioned_descendants)
+    return children_visual_overflow_changed;
+
+  for (auto* box : *positioned_descendants) {
+    if (box->HasLayer() && box->HasSelfPaintingLayer())
+      continue;
+    if (box->RecalcVisualOverflow())
+      children_visual_overflow_changed = true;
+  }
+  return children_visual_overflow_changed;
+}
+
+bool LayoutBlock::RecalcLayoutOverflow() {
+  bool children_layout_overflow_changed = false;
+  if (ChildNeedsLayoutOverflowRecalc())
+    children_layout_overflow_changed = RecalcChildLayoutOverflow();
+
+  bool self_needs_overflow_recalc = SelfNeedsLayoutOverflowRecalc();
+  if (!self_needs_overflow_recalc && !children_layout_overflow_changed)
     return false;
 
-  return RecalcSelfOverflow();
+  return RecalcSelfLayoutOverflow();
 }
 
-bool LayoutBlock::RecalcSelfOverflow() {
-  bool self_needs_overflow_recalc = SelfNeedsOverflowRecalc();
-  ClearSelfNeedsLayoutOverflowRecalc();
+bool LayoutBlock::RecalcVisualOverflow() {
+  if (!NeedsVisualOverflowRecalc())
+    return false;
+  bool visual_overflow_changed = false;
+  if (ChildNeedsVisualOverflowRecalc())
+    visual_overflow_changed = RecalcChildVisualOverflow();
+
+  if (SelfNeedsVisualOverflowRecalc())
+    visual_overflow_changed = true;
+
+  if (RecalcSelfVisualOverflow())
+    visual_overflow_changed = true;
+
+  ClearChildNeedsVisualOverflowRecalc();
   ClearSelfNeedsVisualOverflowRecalc();
+
+  return visual_overflow_changed;
+}
+
+bool LayoutBlock::RecalcSelfLayoutOverflow() {
+  bool self_needs_layout_overflow_recalc = SelfNeedsLayoutOverflowRecalc();
   // If the current block needs layout, overflow will be recalculated during
   // layout time anyway. We can safely exit here.
   if (NeedsLayout())
     return false;
 
   LayoutUnit old_client_after_edge = LayoutClientAfterEdge();
-  ComputeOverflow(old_client_after_edge, true);
-
+  ComputeLayoutOverflow(old_client_after_edge, true);
   if (HasOverflowClip())
     Layer()->GetScrollableArea()->UpdateAfterOverflowRecalc();
 
-  return !HasOverflowClip() || self_needs_overflow_recalc;
+  return !HasOverflowClip() || self_needs_layout_overflow_recalc;
+}
+
+bool LayoutBlock::RecalcSelfVisualOverflow() {
+  ComputeVisualOverflow(true);
+  // TODO(chrishtr): what does it have to do with HasOverflowClip()? Why
+  // not just return true if the visual overflow actually changed?
+  return !HasOverflowClip();
 }
 
 // Called when a positioned object moves but doesn't necessarily change size.
diff --git a/third_party/blink/renderer/core/layout/layout_block.h b/third_party/blink/renderer/core/layout/layout_block.h
index fd8380b..466e053b 100644
--- a/third_party/blink/renderer/core/layout/layout_block.h
+++ b/third_party/blink/renderer/core/layout/layout_block.h
@@ -324,13 +324,18 @@
   void SetCachedConstraintSpace(const NGConstraintSpace& space);
 
  protected:
-  bool RecalcNormalFlowChildOverflowIfNeeded(LayoutObject*);
-  bool RecalcPositionedDescendantsOverflow();
-  bool RecalcSelfOverflow();
+  bool RecalcNormalFlowChildLayoutOverflowIfNeeded(LayoutObject*);
+  bool RecalcNormalFlowChildVisualOverflowIfNeeded(LayoutObject*);
+  bool RecalcPositionedDescendantsLayoutOverflow();
+  bool RecalcPositionedDescendantsVisualOverflow();
+  bool RecalcSelfLayoutOverflow();
+  bool RecalcSelfVisualOverflow();
 
  public:
-  bool RecalcChildOverflow();
-  bool RecalcOverflow() override;
+  bool RecalcChildLayoutOverflow();
+  bool RecalcChildVisualOverflow();
+  bool RecalcLayoutOverflow() override;
+  bool RecalcVisualOverflow() override;
 
   // An example explaining layout tree structure about first-line style:
   // <style>
@@ -395,9 +400,6 @@
                              const LayoutPoint& paint_offset) const;
   void UpdateAfterLayout() override;
 
-  void ComputeOverflow(LayoutUnit old_client_after_edge,
-                       bool recompute_floats = false);
-
  protected:
   virtual void AdjustInlineDirectionLineBounds(
       unsigned /* expansionOpportunityCount */,
@@ -455,10 +457,9 @@
  protected:
   void AddVisualOverflowFromTheme();
   virtual void ComputeVisualOverflow(
-      const LayoutRect& previous_visual_overflow_rect,
       bool recompute_floats);
   virtual void ComputeLayoutOverflow(LayoutUnit old_client_after_edge,
-                                     bool recompute_floats);
+                                     bool recompute_floats = false);
 
   virtual void AddLayoutOverflowFromChildren();
   void AddVisualOverflowFromChildren();
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc
index 49d412f5..daa3145 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -525,7 +525,7 @@
   LayoutPositionedObjects(relayout_children, behavior);
 
   // Add overflow from children.
-  ComputeOverflow(unconstrained_client_after_edge);
+  ComputeLayoutOverflow(unconstrained_client_after_edge, false);
 
   descendants_with_floats_marked_for_layout_ = false;
 
@@ -2570,8 +2570,9 @@
     NGPhysicalOffset) {}
 
 void LayoutBlockFlow::ComputeVisualOverflow(
-    const LayoutRect& previous_visual_overflow_rect,
     bool recompute_floats) {
+  LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
+  ClearVisualOverflow();
   AddVisualOverflowFromChildren();
 
   AddVisualEffectOverflow();
@@ -2580,10 +2581,12 @@
   if (recompute_floats || CreatesNewFormattingContext() ||
       HasSelfPaintingLayer())
     AddVisualOverflowFromFloats();
-
   if (VisualOverflowRect() != previous_visual_overflow_rect) {
-    if (Layer())
-      Layer()->SetNeedsCompositingInputsUpdate();
+    if (Layer()) {
+      Layer()->SetNeedsCompositingInputsUpdate(
+          PaintLayer::DoesNotNeedDescendantDependentUpdate);
+    }
+    SetShouldCheckForPaintInvalidation();
     GetFrameView()->SetIntersectionObservationState(LocalFrameView::kDesired);
   }
 }
@@ -4659,15 +4662,17 @@
   }
 }
 
-bool LayoutBlockFlow::RecalcInlineChildrenOverflow() {
+bool LayoutBlockFlow::RecalcInlineChildrenLayoutOverflow() {
   DCHECK(ChildrenInline());
-  bool children_overflow_changed = false;
+  bool children_layout_overflow_changed = false;
   ListHashSet<RootInlineBox*> line_boxes;
   for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.AtEnd();
        walker.Advance()) {
     LayoutObject* layout_object = walker.Current().GetLayoutObject();
-    if (RecalcNormalFlowChildOverflowIfNeeded(layout_object)) {
-      children_overflow_changed = true;
+    if (RecalcNormalFlowChildLayoutOverflowIfNeeded(layout_object)) {
+      children_layout_overflow_changed = true;
+      // TODO(chrishtr): should this be IsBox()? Non-blocks can be
+      // inline and have line box wrappers.
       if (layout_object->IsLayoutBlock()) {
         if (InlineBox* inline_box_wrapper =
                 ToLayoutBlock(layout_object)->InlineBoxWrapper())
@@ -4685,7 +4690,35 @@
     box->ClearKnownToHaveNoOverflow();
     box->ComputeOverflow(box->LineTop(), box->LineBottom(), text_box_data_map);
   }
-  return children_overflow_changed;
+  return children_layout_overflow_changed;
+}
+
+bool LayoutBlockFlow::RecalcInlineChildrenVisualOverflow() {
+  DCHECK(ChildrenInline());
+  bool children_visual_overflow_changed = false;
+  ListHashSet<RootInlineBox*> line_boxes;
+  for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.AtEnd();
+       walker.Advance()) {
+    LayoutObject* layout_object = walker.Current().GetLayoutObject();
+    if (RecalcNormalFlowChildVisualOverflowIfNeeded(layout_object)) {
+      children_visual_overflow_changed = true;
+      if (layout_object->IsBox()) {
+        if (InlineBox* inline_box_wrapper =
+                ToLayoutBox(layout_object)->InlineBoxWrapper())
+          line_boxes.insert(&inline_box_wrapper->Root());
+      }
+    }
+  }
+
+  // Child inline boxes' self visual overflow is already computed at the same
+  // time as layout overflow. But we need to add replaced children visual rects.
+  for (ListHashSet<RootInlineBox*>::const_iterator it = line_boxes.begin();
+       it != line_boxes.end(); ++it) {
+    RootInlineBox* box = *it;
+    box->AddReplacedChildrenVisualOverflow(box->LineTop(), box->LineBottom());
+  }
+
+  return children_visual_overflow_changed;
 }
 
 PositionWithAffinity LayoutBlockFlow::PositionForPoint(
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.h b/third_party/blink/renderer/core/layout/layout_block_flow.h
index b34a822..f754999c 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.h
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.h
@@ -111,9 +111,9 @@
 
   void UpdateBlockLayout(bool relayout_children) override;
 
-  void ComputeVisualOverflow(const LayoutRect&, bool recompute_floats) override;
+  void ComputeVisualOverflow(bool recompute_floats) override;
   void ComputeLayoutOverflow(LayoutUnit old_client_after_edge,
-                             bool recompute_floats) override;
+                             bool recompute_floats = false) override;
 
   void DeleteLineBoxTree();
 
@@ -424,7 +424,8 @@
   void SetShouldDoFullPaintInvalidationForFirstLine();
 
   void SimplifiedNormalFlowInlineLayout();
-  bool RecalcInlineChildrenOverflow();
+  bool RecalcInlineChildrenLayoutOverflow();
+  bool RecalcInlineChildrenVisualOverflow();
 
   PositionWithAffinity PositionForPoint(const LayoutPoint&) const override;
 
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index c7362db..00c0181a 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -5386,7 +5386,7 @@
     return;
 
   if (!HasSelfVisualOverflow() && ContentsVisualOverflowRect().IsEmpty()) {
-    ClearAllOverflows();
+    overflow_.reset();
     return;
   }
 
@@ -5398,7 +5398,7 @@
     return;
 
   if (!HasLayoutOverflow()) {
-    ClearAllOverflows();
+    overflow_.reset();
     return;
   }
 
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h
index f86db2d..865da50 100644
--- a/third_party/blink/renderer/core/layout/layout_box.h
+++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -551,7 +551,6 @@
   void SetLayoutClientAfterEdge(LayoutUnit client_after_edge);
   LayoutUnit LayoutClientAfterEdge() const;
 
-  void ClearAllOverflows() { overflow_.reset(); }
   void ClearLayoutOverflow();
   void ClearVisualOverflow();
 
diff --git a/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc
index 228b90af..4a945a8f 100644
--- a/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc
@@ -457,7 +457,7 @@
 
     LayoutPositionedObjects(relayout_children || IsDocumentElement());
 
-    ComputeOverflow(old_client_after_edge);
+    ComputeLayoutOverflow(old_client_after_edge);
   }
 
   UpdateAfterLayout();
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_object.cc b/third_party/blink/renderer/core/layout/layout_embedded_object.cc
index a6aef27e..9061a8c8 100644
--- a/third_party/blink/renderer/core/layout/layout_embedded_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_embedded_object.cc
@@ -92,8 +92,7 @@
   UpdateLogicalWidth();
   UpdateLogicalHeight();
 
-  ClearAllOverflows();
-  AddVisualEffectOverflow();
+  ClearLayoutOverflow();
 
   UpdateAfterLayout();
 
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
index 8b3de628..a0aa402 100644
--- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -353,7 +353,7 @@
 
     // FIXME: css3/flexbox/repaint-rtl-column.html seems to issue paint
     // invalidations for more overflow than it needs to.
-    ComputeOverflow(ClientLogicalBottomAfterRepositioning());
+    ComputeLayoutOverflow(ClientLogicalBottomAfterRepositioning());
   }
 
   // We have to reset this, because changes to our ancestors' style can affect
diff --git a/third_party/blink/renderer/core/layout/layout_grid.cc b/third_party/blink/renderer/core/layout/layout_grid.cc
index 71b72542..65c4f931 100644
--- a/third_party/blink/renderer/core/layout/layout_grid.cc
+++ b/third_party/blink/renderer/core/layout/layout_grid.cc
@@ -374,7 +374,7 @@
 
     LayoutPositionedObjects(relayout_children || IsDocumentElement());
 
-    ComputeOverflow(old_client_after_edge);
+    ComputeLayoutOverflow(old_client_after_edge);
   }
 
   UpdateAfterLayout();
diff --git a/third_party/blink/renderer/core/layout/layout_iframe.cc b/third_party/blink/renderer/core/layout/layout_iframe.cc
index e4a1f0e..ca2683d 100644
--- a/third_party/blink/renderer/core/layout/layout_iframe.cc
+++ b/third_party/blink/renderer/core/layout/layout_iframe.cc
@@ -54,8 +54,7 @@
   // No kids to layout as a replaced element.
   UpdateLogicalHeight();
 
-  ClearAllOverflows();
-  AddVisualEffectOverflow();
+  ClearLayoutOverflow();
   UpdateAfterLayout();
 
   ClearNeedsLayout();
diff --git a/third_party/blink/renderer/core/layout/layout_list_item.cc b/third_party/blink/renderer/core/layout/layout_list_item.cc
index cb6d617..dc5c2ff 100644
--- a/third_party/blink/renderer/core/layout/layout_list_item.cc
+++ b/third_party/blink/renderer/core/layout/layout_list_item.cc
@@ -287,9 +287,29 @@
   return false;
 }
 
-void LayoutListItem::ComputeVisualOverflow(
-    const LayoutRect& previous_visual_overflow_rect,
-    bool recompute_floats) {
+bool LayoutListItem::RecalcVisualOverflow() {
+  if (!NeedsVisualOverflowRecalc())
+    return false;
+  bool visual_overflow_changed = false;
+  if (ChildNeedsVisualOverflowRecalc())
+    visual_overflow_changed = RecalcChildVisualOverflow();
+  // UpdateOverflow may override the visual overflow rect for inline boxes.
+
+  if (SelfNeedsVisualOverflowRecalc())
+    visual_overflow_changed = true;
+  if (RecalcSelfVisualOverflow())
+    visual_overflow_changed = true;
+
+  ClearChildNeedsVisualOverflowRecalc();
+  ClearSelfNeedsVisualOverflowRecalc();
+
+  return visual_overflow_changed;
+}
+
+void LayoutListItem::ComputeVisualOverflow(bool recompute_floats) {
+  LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
+  ClearVisualOverflow();
+
   AddVisualOverflowFromChildren();
 
   AddVisualEffectOverflow();
@@ -300,20 +320,18 @@
     AddVisualOverflowFromFloats();
 
   if (VisualOverflowRect() != previous_visual_overflow_rect) {
-    if (Layer())
-      Layer()->SetNeedsCompositingInputsUpdate();
+    if (Layer()) {
+      Layer()->SetNeedsCompositingInputsUpdate(
+          PaintLayer::DoesNotNeedDescendantDependentUpdate);
+    }
+    SetShouldCheckForPaintInvalidation();
     GetFrameView()->SetIntersectionObservationState(LocalFrameView::kDesired);
   }
 }
 
-void LayoutListItem::AddVisualOverflowFromChildren() {
-  LayoutBlockFlow::AddVisualOverflowFromChildren();
-  UpdateOverflow(Visual);
-}
-
 void LayoutListItem::AddLayoutOverflowFromChildren() {
   LayoutBlockFlow::AddLayoutOverflowFromChildren();
-  UpdateOverflow(Layout);
+  UpdateOverflow();
 }
 
 // Align marker_inline_box in block direction according to line_box_root's
@@ -387,7 +405,7 @@
   }
 }
 
-void LayoutListItem::UpdateOverflow(OverflowType overflow_type) {
+void LayoutListItem::UpdateOverflow() {
   if (!marker_ || !marker_->Parent() || !marker_->Parent()->IsBox() ||
       marker_->IsInside() || !marker_->InlineBoxWrapper())
     return;
@@ -428,39 +446,39 @@
                                           kDoNotIndentText, LayoutUnit()));
     marker_logical_left = marker_line_offset - line_offset - PaddingStart() -
                           BorderStart() + marker_->MarginStart();
+
     marker_inline_box->MoveInInlineDirection(marker_logical_left -
                                              marker_old_logical_left);
+
     for (InlineFlowBox* box = marker_inline_box->Parent(); box;
          box = box->Parent()) {
-      if (overflow_type == Visual) {
-        LayoutRect new_logical_visual_overflow_rect =
-            box->LogicalVisualOverflowRect(line_top, line_bottom);
-        if (marker_logical_left < new_logical_visual_overflow_rect.X() &&
-            !hit_self_painting_layer) {
-          new_logical_visual_overflow_rect.SetWidth(
-              new_logical_visual_overflow_rect.MaxX() - marker_logical_left);
-          new_logical_visual_overflow_rect.SetX(marker_logical_left);
-          if (box == root)
-            adjust_overflow = true;
-        }
-        box->OverrideVisualOverflowFromLogicalRect(
-            new_logical_visual_overflow_rect, line_top, line_bottom);
-
-        if (box->BoxModelObject().HasSelfPaintingLayer())
-          hit_self_painting_layer = true;
-      } else {
-        LayoutRect new_logical_layout_overflow_rect =
-            box->LogicalLayoutOverflowRect(line_top, line_bottom);
-        if (marker_logical_left < new_logical_layout_overflow_rect.X()) {
-          new_logical_layout_overflow_rect.SetWidth(
-              new_logical_layout_overflow_rect.MaxX() - marker_logical_left);
-          new_logical_layout_overflow_rect.SetX(marker_logical_left);
-          if (box == root)
-            adjust_overflow = true;
-        }
-        box->OverrideLayoutOverflowFromLogicalRect(
-            new_logical_layout_overflow_rect, line_top, line_bottom);
+      box->AddReplacedChildrenVisualOverflow(line_top, line_bottom);
+      LayoutRect new_logical_visual_overflow_rect =
+          box->LogicalVisualOverflowRect(line_top, line_bottom);
+      if (marker_logical_left < new_logical_visual_overflow_rect.X() &&
+          !hit_self_painting_layer) {
+        new_logical_visual_overflow_rect.SetWidth(
+            new_logical_visual_overflow_rect.MaxX() - marker_logical_left);
+        new_logical_visual_overflow_rect.SetX(marker_logical_left);
+        if (box == root)
+          adjust_overflow = true;
       }
+      box->OverrideVisualOverflowFromLogicalRect(
+          new_logical_visual_overflow_rect, line_top, line_bottom);
+
+      if (box->BoxModelObject().HasSelfPaintingLayer())
+        hit_self_painting_layer = true;
+      LayoutRect new_logical_layout_overflow_rect =
+          box->LogicalLayoutOverflowRect(line_top, line_bottom);
+      if (marker_logical_left < new_logical_layout_overflow_rect.X()) {
+        new_logical_layout_overflow_rect.SetWidth(
+            new_logical_layout_overflow_rect.MaxX() - marker_logical_left);
+        new_logical_layout_overflow_rect.SetX(marker_logical_left);
+        if (box == root)
+          adjust_overflow = true;
+      }
+      box->OverrideLayoutOverflowFromLogicalRect(
+          new_logical_layout_overflow_rect, line_top, line_bottom);
     }
   } else {
     LayoutUnit marker_line_offset =
@@ -469,41 +487,41 @@
                                            kDoNotIndentText, LayoutUnit()));
     marker_logical_left = marker_line_offset - line_offset + PaddingStart() +
                           BorderStart() + marker_->MarginEnd();
+
     marker_inline_box->MoveInInlineDirection(marker_logical_left -
                                              marker_old_logical_left);
+
     for (InlineFlowBox* box = marker_inline_box->Parent(); box;
          box = box->Parent()) {
-      if (overflow_type == Visual) {
-        LayoutRect new_logical_visual_overflow_rect =
-            box->LogicalVisualOverflowRect(line_top, line_bottom);
-        if (marker_logical_left + marker_->LogicalWidth() >
-                new_logical_visual_overflow_rect.MaxX() &&
-            !hit_self_painting_layer) {
-          new_logical_visual_overflow_rect.SetWidth(
-              marker_logical_left + marker_->LogicalWidth() -
-              new_logical_visual_overflow_rect.X());
-          if (box == root)
-            adjust_overflow = true;
-        }
-        box->OverrideVisualOverflowFromLogicalRect(
-            new_logical_visual_overflow_rect, line_top, line_bottom);
-
-        if (box->BoxModelObject().HasSelfPaintingLayer())
-          hit_self_painting_layer = true;
-      } else {
-        LayoutRect new_logical_layout_overflow_rect =
-            box->LogicalLayoutOverflowRect(line_top, line_bottom);
-        if (marker_logical_left + marker_->LogicalWidth() >
-            new_logical_layout_overflow_rect.MaxX()) {
-          new_logical_layout_overflow_rect.SetWidth(
-              marker_logical_left + marker_->LogicalWidth() -
-              new_logical_layout_overflow_rect.X());
-          if (box == root)
-            adjust_overflow = true;
-        }
-        box->OverrideLayoutOverflowFromLogicalRect(
-            new_logical_layout_overflow_rect, line_top, line_bottom);
+      box->AddReplacedChildrenVisualOverflow(line_top, line_bottom);
+      LayoutRect new_logical_visual_overflow_rect =
+          box->LogicalVisualOverflowRect(line_top, line_bottom);
+      if (marker_logical_left + marker_->LogicalWidth() >
+              new_logical_visual_overflow_rect.MaxX() &&
+          !hit_self_painting_layer) {
+        new_logical_visual_overflow_rect.SetWidth(
+            marker_logical_left + marker_->LogicalWidth() -
+            new_logical_visual_overflow_rect.X());
+        if (box == root)
+          adjust_overflow = true;
       }
+      box->OverrideVisualOverflowFromLogicalRect(
+          new_logical_visual_overflow_rect, line_top, line_bottom);
+
+      if (box->BoxModelObject().HasSelfPaintingLayer())
+        hit_self_painting_layer = true;
+      LayoutRect new_logical_layout_overflow_rect =
+          box->LogicalLayoutOverflowRect(line_top, line_bottom);
+      if (marker_logical_left + marker_->LogicalWidth() >
+          new_logical_layout_overflow_rect.MaxX()) {
+        new_logical_layout_overflow_rect.SetWidth(
+            marker_logical_left + marker_->LogicalWidth() -
+            new_logical_layout_overflow_rect.X());
+        if (box == root)
+          adjust_overflow = true;
+      }
+      box->OverrideLayoutOverflowFromLogicalRect(
+          new_logical_layout_overflow_rect, line_top, line_bottom);
     }
   }
 
@@ -517,28 +535,25 @@
         marker_->Size());
     if (!StyleRef().IsHorizontalWritingMode())
       marker_rect = marker_rect.TransposedRect();
-    LayoutBox* o = marker_;
+    LayoutBox* object = marker_;
 
-    if (overflow_type == Visual) {
-      do {
-        o = o->ParentBox();
-        if (o->IsLayoutBlock())
-          ToLayoutBlock(o)->AddContentsVisualOverflow(marker_rect);
-        if (o->HasOverflowClip() || o->HasSelfPaintingLayer())
-          break;
-        marker_rect.MoveBy(-o->Location());
-      } while (o != this);
-    } else {
-      do {
-        o = o->ParentBox();
-        if (o->IsLayoutBlock()) {
-          ToLayoutBlock(o)->AddLayoutOverflow(marker_rect);
-        }
-        if (o->HasOverflowClip())
-          break;
-        marker_rect.MoveBy(-o->Location());
-      } while (o != this);
-    }
+    bool found_self_painting_layer = false;
+    do {
+      object = object->ParentBox();
+      if (object->IsLayoutBlock()) {
+        if (!found_self_painting_layer)
+          ToLayoutBlock(object)->AddContentsVisualOverflow(marker_rect);
+        ToLayoutBlock(object)->AddLayoutOverflow(marker_rect);
+      }
+
+      if (object->HasOverflowClip())
+        break;
+
+      if (object->HasSelfPaintingLayer())
+        found_self_painting_layer = true;
+
+      marker_rect.MoveBy(-object->Location());
+    } while (object != this);
   }
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_list_item.h b/third_party/blink/renderer/core/layout/layout_list_item.h
index e0d7736..c35aa165d 100644
--- a/third_party/blink/renderer/core/layout/layout_list_item.h
+++ b/third_party/blink/renderer/core/layout/layout_list_item.h
@@ -48,6 +48,8 @@
 
   const char* GetName() const override { return "LayoutListItem"; }
 
+  bool RecalcVisualOverflow() override;
+
  private:
   bool IsOfType(LayoutObjectType type) const override {
     return type == kLayoutObjectListItem || LayoutBlockFlow::IsOfType(type);
@@ -65,14 +67,12 @@
   // Returns true if we re-attached and updated the location of the marker.
   bool UpdateMarkerLocation();
 
-  enum OverflowType { Layout, Visual };
-  void UpdateOverflow(OverflowType);
+  void UpdateOverflow();
 
   void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
 
-  void ComputeVisualOverflow(const LayoutRect&, bool recompute_floats) final;
+  void ComputeVisualOverflow(bool recompute_floats) final;
 
-  void AddVisualOverflowFromChildren();
   void AddLayoutOverflowFromChildren() override;
 
   void AlignMarkerInBlockDirection();
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_set.cc b/third_party/blink/renderer/core/layout/layout_multi_column_set.cc
index 0adaeba0..3e47b40 100644
--- a/third_party/blink/renderer/core/layout/layout_multi_column_set.cc
+++ b/third_party/blink/renderer/core/layout/layout_multi_column_set.cc
@@ -522,8 +522,9 @@
 }
 
 void LayoutMultiColumnSet::ComputeVisualOverflow(
-    const LayoutRect& previous_visual_overflow_rect,
     bool recompute_floats) {
+  LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
+  ClearVisualOverflow();
   AddVisualOverflowFromChildren();
 
   AddVisualEffectOverflow();
@@ -534,8 +535,11 @@
     AddVisualOverflowFromFloats();
 
   if (VisualOverflowRect() != previous_visual_overflow_rect) {
-    if (Layer())
-      Layer()->SetNeedsCompositingInputsUpdate();
+    if (Layer()) {
+      Layer()->SetNeedsCompositingInputsUpdate(
+          PaintLayer::DoesNotNeedDescendantDependentUpdate);
+    }
+    SetShouldCheckForPaintInvalidation();
     GetFrameView()->SetIntersectionObservationState(LocalFrameView::kDesired);
   }
 }
@@ -685,7 +689,7 @@
   DCHECK_EQ(fragmentainer_groups_.size(), 1U);
   auto& group = fragmentainer_groups_[0];
   group.UpdateFromNG(LogicalHeight());
-  ComputeOverflow(LogicalHeight());
+  ComputeLayoutOverflow(LogicalHeight());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_set.h b/third_party/blink/renderer/core/layout/layout_multi_column_set.h
index 8e66f98..26348fe3 100644
--- a/third_party/blink/renderer/core/layout/layout_multi_column_set.h
+++ b/third_party/blink/renderer/core/layout/layout_multi_column_set.h
@@ -255,7 +255,7 @@
   void PaintObject(const PaintInfo&,
                    const LayoutPoint& paint_offset) const override;
 
-  void ComputeVisualOverflow(const LayoutRect&, bool recompute_floats) final;
+  void ComputeVisualOverflow(bool recompute_floats) final;
 
   void AddVisualOverflowFromChildren();
   void AddLayoutOverflowFromChildren() override;
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
index 52eddf6..e50c236 100644
--- a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
+++ b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
@@ -94,6 +94,16 @@
   return layout_object_in_flow_thread_->NeedsPreferredWidthsRecalculation();
 }
 
+bool LayoutMultiColumnSpannerPlaceholder::RecalcVisualOverflow() {
+  LayoutRect old_contents_overflow = ContentsVisualOverflowRect();
+  bool visual_overflow_changed = LayoutBox::RecalcVisualOverflow();
+  ClearVisualOverflow();
+  AddContentsVisualOverflow(
+      layout_object_in_flow_thread_->VisualOverflowRect());
+  return visual_overflow_changed ||
+         old_contents_overflow != ContentsVisualOverflowRect();
+}
+
 LayoutUnit LayoutMultiColumnSpannerPlaceholder::MinPreferredLogicalWidth()
     const {
   return layout_object_in_flow_thread_->MinPreferredLogicalWidth();
@@ -123,9 +133,7 @@
 
   // Take the overflow from the spanner, so that it gets propagated to the
   // multicol container and beyond.
-  ClearAllOverflows();
-  AddContentsVisualOverflow(
-      layout_object_in_flow_thread_->VisualOverflowRect());
+  ClearLayoutOverflow();
   AddLayoutOverflow(layout_object_in_flow_thread_->LayoutOverflowRect());
 
   ClearNeedsLayout();
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h
index b1705d5..021bb9d 100644
--- a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h
+++ b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h
@@ -55,6 +55,7 @@
   void InsertedIntoTree() override;
   void WillBeRemovedFromTree() override;
   bool NeedsPreferredWidthsRecalculation() const override;
+  bool RecalcVisualOverflow() override;
   LayoutUnit MinPreferredLogicalWidth() const override;
   LayoutUnit MaxPreferredLogicalWidth() const override;
   void UpdateLayout() override;
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index 3fee9b9..6cc8df6 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1414,16 +1414,34 @@
   return *layout_view;
 }
 
-bool LayoutObject::RecalcOverflow() {
-  if (!ChildNeedsOverflowRecalc())
+bool LayoutObject::RecalcLayoutOverflow() {
+  if (!ChildNeedsLayoutOverflowRecalc())
     return false;
-  bool children_overflow_changed = false;
+  ClearChildNeedsLayoutOverflowRecalc();
+  bool children_layout_overflow_changed = false;
   for (LayoutObject* current = SlowFirstChild(); current;
        current = current->NextSibling()) {
-    if (current->RecalcOverflow())
-      children_overflow_changed = true;
+    if (current->RecalcLayoutOverflow())
+      children_layout_overflow_changed = true;
   }
-  return children_overflow_changed;
+  return children_layout_overflow_changed;
+}
+
+bool LayoutObject::RecalcVisualOverflow() {
+  if (!NeedsVisualOverflowRecalc())
+    return false;
+  bool visual_overflow_changed = SelfNeedsVisualOverflowRecalc();
+  for (LayoutObject* current = SlowFirstChild(); current;
+       current = current->NextSibling()) {
+    if (current->HasLayer() &&
+        ToLayoutBoxModelObject(current)->HasSelfPaintingLayer())
+      continue;
+    if (current->RecalcVisualOverflow())
+      visual_overflow_changed = true;
+  }
+  ClearChildNeedsVisualOverflowRecalc();
+  ClearSelfNeedsVisualOverflowRecalc();
+  return visual_overflow_changed;
 }
 
 const LayoutBoxModelObject* LayoutObject::EnclosingCompositedContainer() const {
@@ -1976,6 +1994,11 @@
 
 void LayoutObject::MarkContainerChainForOverflowRecalcIfNeeded() {
   LayoutObject* object = this;
+  bool found_layer = false;
+  if (HasLayer()) {
+    ToLayoutBoxModelObject(this)->Layer()->SetNeedsCompositingInputsUpdate();
+    found_layer = true;
+  }
   do {
     // Cell and row need to propagate the flag to their containing section and
     // row as their containing block is the table wrapper.
@@ -1986,12 +2009,21 @@
     if (object) {
       object->SetChildNeedsLayoutOverflowRecalc();
       object->SetChildNeedsVisualOverflowRecalc();
+
+      if (object->HasLayer() && !found_layer) {
+        ToLayoutBoxModelObject(object)
+            ->Layer()
+            ->SetNeedsCompositingInputsUpdate();
+        found_layer = true;
+      }
     }
+
   } while (object);
 }
 
 void LayoutObject::SetNeedsOverflowRecalc() {
-  bool needed_recalc = NeedsLayoutOverflowRecalc();
+  bool needed_recalc =
+      NeedsLayoutOverflowRecalc() && NeedsVisualOverflowRecalc();
   SetSelfNeedsLayoutOverflowRecalc();
   SetSelfNeedsVisualOverflowRecalc();
   SetShouldCheckForPaintInvalidation();
@@ -2301,7 +2333,8 @@
       MarkContainerChainForLayout();
 
     // Ditto.
-    if (NeedsOverflowRecalc() &&
+    // TODO(chrishtr): review this. Why are we checking Needs* at all?
+    if ((NeedsLayoutOverflowRecalc() || NeedsVisualOverflowRecalc()) &&
         old_style->GetPosition() != style_->GetPosition())
       MarkContainerChainForOverflowRecalcIfNeeded();
 
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 15f2573..214553c 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -915,18 +915,6 @@
     return bitfields_.PreferredLogicalWidthsDirty();
   }
 
-  bool NeedsOverflowRecalc() const {
-    return SelfNeedsOverflowRecalc() || ChildNeedsOverflowRecalc();
-  }
-  bool SelfNeedsOverflowRecalc() const {
-    return bitfields_.SelfNeedsLayoutOverflowRecalc() ||
-           bitfields_.SelfNeedsVisualOverflowRecalc();
-  }
-  bool ChildNeedsOverflowRecalc() const {
-    return bitfields_.ChildNeedsLayoutOverflowRecalc() ||
-           bitfields_.ChildNeedsVisualOverflowRecalc();
-  }
-
   bool NeedsLayoutOverflowRecalc() const {
     return bitfields_.SelfNeedsLayoutOverflowRecalc() ||
            bitfields_.ChildNeedsLayoutOverflowRecalc();
@@ -1262,7 +1250,8 @@
 
   virtual void Paint(const PaintInfo&) const;
 
-  virtual bool RecalcOverflow();
+  virtual bool RecalcLayoutOverflow();
+  virtual bool RecalcVisualOverflow();
 
   // Subclasses must reimplement this method to compute the size and position
   // of this object and all its descendants.
@@ -2993,6 +2982,7 @@
 #endif
   bool already_needed_layout = bitfields_.SelfNeedsLayout();
   SetSelfNeedsLayout(true);
+  SetNeedsOverflowRecalc();
   MarkContainerNeedsCollectInlines();
   if (!already_needed_layout) {
     TRACE_EVENT_INSTANT1(
@@ -3039,6 +3029,7 @@
   DCHECK(!IsSetNeedsLayoutForbidden());
 #endif
   bool already_needed_layout = NormalChildNeedsLayout();
+  SetNeedsOverflowRecalc();
   SetNormalChildNeedsLayout(true);
   MarkContainerNeedsCollectInlines();
   // FIXME: Replace MarkOnlyThis with the SubtreeLayoutScope code path and
@@ -3050,6 +3041,7 @@
 
 inline void LayoutObject::SetNeedsPositionedMovementLayout() {
   bool already_needed_layout = NeedsPositionedMovementLayout();
+  SetNeedsOverflowRecalc();
   SetNeedsPositionedMovementLayout(true);
 #if DCHECK_IS_ON()
   DCHECK(!IsSetNeedsLayoutForbidden());
diff --git a/third_party/blink/renderer/core/layout/layout_object_child_list.cc b/third_party/blink/renderer/core/layout/layout_object_child_list.cc
index a520da7..bd2c737 100644
--- a/third_party/blink/renderer/core/layout/layout_object_child_list.cc
+++ b/third_party/blink/renderer/core/layout/layout_object_child_list.cc
@@ -217,6 +217,9 @@
       PaintInvalidationReason::kAppeared);
   new_child->AddSubtreePaintPropertyUpdateReason(
       SubtreePaintPropertyUpdateReason::kContainerChainMayChange);
+  new_child->SetChildNeedsLayoutOverflowRecalc();
+  new_child->SetChildNeedsVisualOverflowRecalc();
+
   if (!owner->NormalChildNeedsLayout()) {
     owner->SetChildNeedsLayout();  // We may supply the static position for an
                                    // absolute positioned child.
diff --git a/third_party/blink/renderer/core/layout/layout_replaced.cc b/third_party/blink/renderer/core/layout/layout_replaced.cc
index c8767ffe..6bcc049 100644
--- a/third_party/blink/renderer/core/layout/layout_replaced.cc
+++ b/third_party/blink/renderer/core/layout/layout_replaced.cc
@@ -99,8 +99,7 @@
   UpdateLogicalWidth();
   UpdateLogicalHeight();
 
-  ClearAllOverflows();
-  AddVisualEffectOverflow();
+  ClearLayoutOverflow();
   UpdateAfterLayout();
 
   ClearNeedsLayout();
@@ -153,6 +152,21 @@
          layout_object->IsVideo();
 }
 
+bool LayoutReplaced::RecalcVisualOverflow() {
+  if (!NeedsVisualOverflowRecalc())
+    return false;
+  LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
+  bool visual_overflow_changed = SelfNeedsVisualOverflowRecalc();
+
+  if (LayoutObject::RecalcVisualOverflow())
+    visual_overflow_changed = true;
+
+  ClearVisualOverflow();
+  AddVisualEffectOverflow();
+  return visual_overflow_changed ||
+         previous_visual_overflow_rect != VisualOverflowRect();
+}
+
 void LayoutReplaced::ComputeIntrinsicSizingInfoForReplacedContent(
     IntrinsicSizingInfo& intrinsic_sizing_info) const {
   if (ShouldApplySizeContainment()) {
diff --git a/third_party/blink/renderer/core/layout/layout_replaced.h b/third_party/blink/renderer/core/layout/layout_replaced.h
index 62be25f..0f043ae 100644
--- a/third_party/blink/renderer/core/layout/layout_replaced.h
+++ b/third_party/blink/renderer/core/layout/layout_replaced.h
@@ -71,6 +71,8 @@
 
   bool NeedsPreferredWidthsRecalculation() const override;
 
+  bool RecalcVisualOverflow() override;
+
   // These values are specified to be 300 and 150 pixels in the CSS 2.1 spec.
   // http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width
   static const int kDefaultWidth;
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_run.cc b/third_party/blink/renderer/core/layout/layout_ruby_run.cc
index 699e128..bba4c5c 100644
--- a/third_party/blink/renderer/core/layout/layout_ruby_run.cc
+++ b/third_party/blink/renderer/core/layout/layout_ruby_run.cc
@@ -261,7 +261,7 @@
   }
 
   // Update our overflow to account for the new LayoutRubyText position.
-  ComputeOverflow(ClientLogicalBottom());
+  ComputeLayoutOverflow(ClientLogicalBottom());
 }
 
 void LayoutRubyRun::GetOverhang(bool first_line,
diff --git a/third_party/blink/renderer/core/layout/layout_table.cc b/third_party/blink/renderer/core/layout/layout_table.cc
index 8c02463..ed351279d 100644
--- a/third_party/blink/renderer/core/layout/layout_table.cc
+++ b/third_party/blink/renderer/core/layout/layout_table.cc
@@ -568,32 +568,57 @@
        section = SectionBelow(section)) {
     section->LayoutIfNeeded();
     section->LayoutRows();
-    section->ComputeOverflowFromDescendants();
+    section->ComputeLayoutOverflowFromDescendants();
     section->UpdateAfterLayout();
-    section->AddVisualEffectOverflow();
   }
 }
 
-bool LayoutTable::RecalcOverflow() {
-  RecalcSelfOverflow();
+bool LayoutTable::RecalcLayoutOverflow() {
+  RecalcSelfLayoutOverflow();
 
-  if (!ChildNeedsOverflowRecalc())
+  if (!ChildNeedsLayoutOverflowRecalc())
     return false;
   ClearChildNeedsLayoutOverflowRecalc();
-  ClearChildNeedsVisualOverflowRecalc();
 
   // If the table sections we keep pointers to have gone away then the table
   // will be rebuilt and overflow will get recalculated anyway so return early.
   if (NeedsSectionRecalc())
     return false;
 
-  bool children_overflow_changed = false;
+  bool children_layout_overflow_changed = false;
   for (LayoutTableSection* section = TopSection(); section;
        section = SectionBelow(section)) {
-    children_overflow_changed =
-        section->RecalcOverflow() || children_overflow_changed;
+    children_layout_overflow_changed =
+        section->RecalcLayoutOverflow() || children_layout_overflow_changed;
   }
-  return RecalcPositionedDescendantsOverflow() || children_overflow_changed;
+  return RecalcPositionedDescendantsLayoutOverflow() ||
+         children_layout_overflow_changed;
+}
+
+bool LayoutTable::RecalcVisualOverflow() {
+  if (!NeedsVisualOverflowRecalc())
+    return false;
+  bool visual_overflow_changed = false;
+  if (ChildNeedsVisualOverflowRecalc()) {
+    for (auto* caption : captions_)
+      caption->RecalcVisualOverflow();
+
+    for (LayoutTableSection* section = TopSection(); section;
+         section = SectionBelow(section)) {
+      if (section->RecalcVisualOverflow())
+        visual_overflow_changed = true;
+    }
+    if (RecalcPositionedDescendantsVisualOverflow())
+      visual_overflow_changed = true;
+  }
+  if (SelfNeedsVisualOverflowRecalc())
+    visual_overflow_changed = true;
+  ClearChildNeedsVisualOverflowRecalc();
+  ClearSelfNeedsVisualOverflowRecalc();
+
+  if (RecalcSelfVisualOverflow())
+    visual_overflow_changed = true;
+  return visual_overflow_changed;
 }
 
 void LayoutTable::UpdateLayout() {
@@ -794,7 +819,6 @@
       SetLogicalHeight(LogicalHeight() + section->LogicalHeight());
 
       section->UpdateAfterLayout();
-      section->AddVisualEffectOverflow();
 
       section = SectionBelow(section);
     }
@@ -815,7 +839,7 @@
                              old_logical_height != LogicalHeight();
     LayoutPositionedObjects(dimension_changed);
 
-    ComputeOverflow(ClientLogicalBottom());
+    ComputeLayoutOverflow(ClientLogicalBottom());
     UpdateAfterLayout();
 
     if (state.IsPaginated() && IsPageLogicalHeightKnown()) {
@@ -909,17 +933,19 @@
   }
 }
 
-void LayoutTable::ComputeVisualOverflow(
-    const LayoutRect& previous_visual_overflow_rect,
-    bool recompute_floats) {
+void LayoutTable::ComputeVisualOverflow(bool) {
+  LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
   AddVisualOverflowFromChildren();
 
   AddVisualEffectOverflow();
   AddVisualOverflowFromTheme();
 
   if (VisualOverflowRect() != previous_visual_overflow_rect) {
-    if (Layer())
-      Layer()->SetNeedsCompositingInputsUpdate();
+    if (Layer()) {
+      Layer()->SetNeedsCompositingInputsUpdate(
+          PaintLayer::DoesNotNeedDescendantDependentUpdate);
+    }
+    SetShouldCheckForPaintInvalidation();
     GetFrameView()->SetIntersectionObservationState(LocalFrameView::kDesired);
   }
 }
diff --git a/third_party/blink/renderer/core/layout/layout_table.h b/third_party/blink/renderer/core/layout/layout_table.h
index 7a61ab8..f73d0eeb 100644
--- a/third_party/blink/renderer/core/layout/layout_table.h
+++ b/third_party/blink/renderer/core/layout/layout_table.h
@@ -426,7 +426,10 @@
  protected:
   void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
   void SimplifiedNormalFlowLayout() override;
-  bool RecalcOverflow() override;
+
+  bool RecalcLayoutOverflow() final;
+  bool RecalcVisualOverflow() final;
+
   void EnsureIsReadyForPaintInvalidation() override;
   void InvalidatePaint(const PaintInvalidatorContext&) const override;
   bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const override;
@@ -474,7 +477,7 @@
       OverlayScrollbarClipBehavior =
           kIgnorePlatformOverlayScrollbarSize) const override;
 
-  void ComputeVisualOverflow(const LayoutRect&, bool recompute_floats) final;
+  void ComputeVisualOverflow(bool recompute_floats) final;
 
   void AddVisualOverflowFromChildren();
   void AddLayoutOverflowFromChildren() override;
diff --git a/third_party/blink/renderer/core/layout/layout_table_cell.cc b/third_party/blink/renderer/core/layout/layout_table_cell.cc
index dfc18cd..6223d46 100644
--- a/third_party/blink/renderer/core/layout/layout_table_cell.cc
+++ b/third_party/blink/renderer/core/layout/layout_table_cell.cc
@@ -383,10 +383,8 @@
 }
 
 void LayoutTableCell::ComputeVisualOverflow(
-    const LayoutRect& previous_visual_overflow_rect,
     bool recompute_floats) {
-  LayoutBlockFlow::ComputeVisualOverflow(previous_visual_overflow_rect,
-                                         recompute_floats);
+  LayoutBlockFlow::ComputeVisualOverflow(recompute_floats);
 
   UpdateCollapsedBorderValues();
   if (!collapsed_border_values_)
diff --git a/third_party/blink/renderer/core/layout/layout_table_cell.h b/third_party/blink/renderer/core/layout/layout_table_cell.h
index 52baeef..927ffeb 100644
--- a/third_party/blink/renderer/core/layout/layout_table_cell.h
+++ b/third_party/blink/renderer/core/layout/layout_table_cell.h
@@ -341,7 +341,7 @@
     return is_spanning_collapsed_column_;
   }
 
-  void ComputeVisualOverflow(const LayoutRect&, bool recompute_floats) override;
+  void ComputeVisualOverflow(bool recompute_floats) override;
 
  protected:
   void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
diff --git a/third_party/blink/renderer/core/layout/layout_table_row.cc b/third_party/blink/renderer/core/layout/layout_table_row.cc
index 183d09d4..6bb0c11 100644
--- a/third_party/blink/renderer/core/layout/layout_table_row.cc
+++ b/third_party/blink/renderer/core/layout/layout_table_row.cc
@@ -205,8 +205,7 @@
       Section()->UpdateFragmentationInfoForChild(*cell);
   }
 
-  ClearAllOverflows();
-  AddVisualEffectOverflow();
+  ClearLayoutOverflow();
   // We do not call addOverflowFromCell here. The cell are laid out to be
   // measured above and will be sized correctly in a follow-up phase.
 
@@ -287,17 +286,59 @@
   return new_row;
 }
 
-void LayoutTableRow::ComputeOverflow() {
-  const auto& old_visual_rect = SelfVisualOverflowRect();
-  ClearAllOverflows();
-  AddVisualEffectOverflow();
+void LayoutTableRow::ComputeLayoutOverflow() {
+  ClearLayoutOverflow();
   for (LayoutTableCell* cell = FirstCell(); cell; cell = cell->NextCell())
-    AddOverflowFromCell(cell);
-  if (old_visual_rect != SelfVisualOverflowRect())
-    SetShouldCheckForPaintInvalidation();
+    AddLayoutOverflowFromCell(cell);
 }
 
-void LayoutTableRow::AddOverflowFromCell(const LayoutTableCell* cell) {
+bool LayoutTableRow::RecalcVisualOverflow() {
+  if (!NeedsVisualOverflowRecalc())
+    return false;
+  bool visual_overflow_changed = SelfNeedsVisualOverflowRecalc();
+  unsigned n_cols = Section()->NumCols(RowIndex());
+  for (unsigned c = 0; c < n_cols; c++) {
+    auto* cell = Section()->OriginatingCellAt(RowIndex(), c);
+    if (!cell)
+      continue;
+    if (cell->RecalcVisualOverflow())
+      visual_overflow_changed = true;
+  }
+  ClearChildNeedsVisualOverflowRecalc();
+  ClearSelfNeedsVisualOverflowRecalc();
+  if (!visual_overflow_changed)
+    return false;
+  return ComputeVisualOverflow();
+}
+
+bool LayoutTableRow::ComputeVisualOverflow() {
+  const auto& old_visual_rect = VisualOverflowRect();
+  ClearVisualOverflow();
+  AddVisualEffectOverflow();
+
+  for (LayoutTableCell* cell = FirstCell(); cell; cell = cell->NextCell())
+    AddVisualOverflowFromCell(cell);
+  if (old_visual_rect != VisualOverflowRect()) {
+    SetShouldCheckForPaintInvalidation();
+    return true;
+  }
+  return false;
+}
+
+void LayoutTableRow::AddLayoutOverflowFromCell(const LayoutTableCell* cell) {
+  LayoutRect cell_layout_overflow_rect =
+      cell->LayoutOverflowRectForPropagation(this);
+
+  // The cell and the row share the section's coordinate system. However
+  // the visual overflow should be determined in the coordinate system of
+  // the row, that's why we shift the rects by cell_row_offset below.
+  LayoutSize cell_row_offset = cell->Location() - Location();
+
+  cell_layout_overflow_rect.Move(cell_row_offset);
+  AddLayoutOverflow(cell_layout_overflow_rect);
+}
+
+void LayoutTableRow::AddVisualOverflowFromCell(const LayoutTableCell* cell) {
   // Table row paints its background behind cells. If the cell spans multiple
   // rows, the row's visual rect should be expanded to cover the cell.
   // Here don't check background existence to avoid requirement to invalidate
@@ -332,11 +373,6 @@
       cell->VisualOverflowRectForPropagation();
   cell_visual_overflow_rect.Move(cell_row_offset);
   AddContentsVisualOverflow(cell_visual_overflow_rect);
-
-  LayoutRect cell_layout_overflow_rect =
-      cell->LayoutOverflowRectForPropagation(this);
-  cell_layout_overflow_rect.Move(cell_row_offset);
-  AddLayoutOverflow(cell_layout_overflow_rect);
 }
 
 bool LayoutTableRow::PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const {
diff --git a/third_party/blink/renderer/core/layout/layout_table_row.h b/third_party/blink/renderer/core/layout/layout_table_row.h
index f70334f4..8a252e8 100644
--- a/third_party/blink/renderer/core/layout/layout_table_row.h
+++ b/third_party/blink/renderer/core/layout/layout_table_row.h
@@ -106,7 +106,9 @@
 
   PaginationBreakability GetPaginationBreakability() const final;
 
-  void ComputeOverflow();
+  void ComputeLayoutOverflow();
+
+  bool RecalcVisualOverflow() override;
 
   const char* GetName() const override { return "LayoutTableRow"; }
 
@@ -123,7 +125,9 @@
   bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const override;
 
  private:
-  void AddOverflowFromCell(const LayoutTableCell*);
+  bool ComputeVisualOverflow();
+  void AddLayoutOverflowFromCell(const LayoutTableCell*);
+  void AddVisualOverflowFromCell(const LayoutTableCell*);
 
   bool IsOfType(LayoutObjectType type) const override {
     return type == kLayoutObjectTableRow ||
diff --git a/third_party/blink/renderer/core/layout/layout_table_section.cc b/third_party/blink/renderer/core/layout/layout_table_section.cc
index 71454fa..2071ed1 100644
--- a/third_party/blink/renderer/core/layout/layout_table_section.cc
+++ b/third_party/blink/renderer/core/layout/layout_table_section.cc
@@ -36,6 +36,7 @@
 #include "third_party/blink/renderer/core/layout/layout_table_row.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/subtree_layout_scope.h"
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/table_section_painter.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -1273,14 +1274,14 @@
       }
     }
     if (row)
-      row->ComputeOverflow();
+      row->ComputeLayoutOverflow();
   }
 
   DCHECK(!NeedsLayout());
 
   SetLogicalHeight(LayoutUnit(row_pos_[total_rows]));
 
-  ComputeOverflowFromDescendants();
+  ComputeLayoutOverflowFromDescendants();
 }
 
 void LayoutTableSection::UpdateLogicalWidthForCollapsedCells(
@@ -1316,7 +1317,7 @@
         if (collapsed_width != 0)
           cell->SetIsSpanningCollapsedColumn(true);
         // Recompute overflow in case overflow clipping is necessary.
-        cell->ComputeOverflow(cell->ClientLogicalBottom());
+        cell->ComputeLayoutOverflow(cell->ClientLogicalBottom(), false);
         DCHECK_GE(cell->LogicalWidth(), 0);
       }
     }
@@ -1358,23 +1359,13 @@
   return pagination_strut.Ceil();
 }
 
-void LayoutTableSection::ComputeOverflowFromDescendants() {
+void LayoutTableSection::ComputeVisualOverflowFromDescendants() {
   auto old_self_visual_overflow_rect = SelfVisualOverflowRect();
-  ClearAllOverflows();
-  overflowing_cells_.clear();
+  ClearVisualOverflow();
+
+  visually_overflowing_cells_.clear();
   force_full_paint_ = false;
 
-  ComputeVisualOverflowFromDescendants();
-
-  // Overflow rect contributes to the visual rect, so if it has changed then we
-  // need to signal a possible paint invalidation.
-  if (old_self_visual_overflow_rect != SelfVisualOverflowRect())
-    SetShouldCheckForPaintInvalidation();
-
-  ComputeLayoutOverflowFromDescendants();
-}
-
-void LayoutTableSection::ComputeVisualOverflowFromDescendants() {
   // These 2 variables are used to balance the memory consumption vs the paint
   // time on big sections with overflowing cells:
   // 1. For small sections, don't track overflowing cells because for them the
@@ -1397,7 +1388,6 @@
 #if DCHECK_IS_ON()
   bool has_overflowing_cell = false;
 #endif
-
   for (auto* row = FirstRow(); row; row = row->NextRow()) {
     AddVisualOverflowFromChild(*row);
 
@@ -1421,56 +1411,81 @@
 #if DCHECK_IS_ON()
       has_overflowing_cell = true;
 #endif
-      if (overflowing_cells_.size() >= max_overflowing_cell_count) {
+      if (visually_overflowing_cells_.size() >= max_overflowing_cell_count) {
         force_full_paint_ = true;
         // The full paint path does not make any use of the overflowing cells
         // info, so don't hold on to the memory.
-        overflowing_cells_.clear();
+        visually_overflowing_cells_.clear();
         continue;
       }
 
-      overflowing_cells_.insert(cell);
+      visually_overflowing_cells_.insert(cell);
     }
   }
 
 #if DCHECK_IS_ON()
-  DCHECK_EQ(has_overflowing_cell, HasOverflowingCell());
+  DCHECK_EQ(has_overflowing_cell, HasVisuallyOverflowingCell());
 #endif
+
+  // Overflow rect contributes to the visual rect, so if it has changed then we
+  // need to signal a possible paint invalidation.
+  if (old_self_visual_overflow_rect != SelfVisualOverflowRect())
+    SetShouldCheckForPaintInvalidation();
 }
 
 void LayoutTableSection::ComputeLayoutOverflowFromDescendants() {
+  ClearLayoutOverflow();
   for (auto* row = FirstRow(); row; row = row->NextRow())
     AddLayoutOverflowFromChild(*row);
 }
 
-bool LayoutTableSection::RecalcOverflow() {
-  if (!ChildNeedsOverflowRecalc())
+bool LayoutTableSection::RecalcLayoutOverflow() {
+  if (!ChildNeedsLayoutOverflowRecalc())
     return false;
   ClearChildNeedsLayoutOverflowRecalc();
-  ClearChildNeedsVisualOverflowRecalc();
   unsigned total_rows = grid_.size();
-  bool children_overflow_changed = false;
+  bool children_layout_overflow_changed = false;
   for (unsigned r = 0; r < total_rows; r++) {
     LayoutTableRow* row_layouter = RowLayoutObjectAt(r);
-    if (!row_layouter || !row_layouter->ChildNeedsOverflowRecalc())
+    if (!row_layouter || !row_layouter->ChildNeedsLayoutOverflowRecalc())
       continue;
     row_layouter->ClearChildNeedsLayoutOverflowRecalc();
-    row_layouter->ClearChildNeedsVisualOverflowRecalc();
-    bool row_children_overflow_changed = false;
+    bool row_children_layout_overflow_changed = false;
     unsigned n_cols = NumCols(r);
     for (unsigned c = 0; c < n_cols; c++) {
       auto* cell = OriginatingCellAt(r, c);
       if (!cell)
         continue;
-      row_children_overflow_changed |= cell->RecalcOverflow();
+      row_children_layout_overflow_changed |= cell->RecalcLayoutOverflow();
     }
-    if (row_children_overflow_changed)
-      row_layouter->ComputeOverflow();
-    children_overflow_changed |= row_children_overflow_changed;
+    if (row_children_layout_overflow_changed)
+      row_layouter->ComputeLayoutOverflow();
+    children_layout_overflow_changed |= row_children_layout_overflow_changed;
   }
-  if (children_overflow_changed)
-    ComputeOverflowFromDescendants();
-  return children_overflow_changed;
+  if (children_layout_overflow_changed)
+    ComputeLayoutOverflowFromDescendants();
+
+  return children_layout_overflow_changed;
+}
+
+bool LayoutTableSection::RecalcVisualOverflow() {
+  if (!ChildNeedsVisualOverflowRecalc())
+    return false;
+  ClearChildNeedsVisualOverflowRecalc();
+  unsigned total_rows = grid_.size();
+  bool children_visual_overflow_changed = false;
+  for (unsigned r = 0; r < total_rows; r++) {
+    LayoutTableRow* row_layouter = RowLayoutObjectAt(r);
+    if (!row_layouter || (row_layouter->HasLayer() &&
+                          row_layouter->Layer()->IsSelfPaintingLayer()))
+      continue;
+    if (row_layouter->RecalcVisualOverflow())
+      children_visual_overflow_changed = true;
+  }
+  if (children_visual_overflow_changed)
+    ComputeVisualOverflowFromDescendants();
+  AddVisualEffectOverflow();
+  return children_visual_overflow_changed;
 }
 
 void LayoutTableSection::MarkAllCellsWidthsDirtyAndOrNeedsLayout(
@@ -1806,7 +1821,7 @@
       !location_in_container.Intersects(OverflowClipRect(adjusted_location)))
     return false;
 
-  if (HasOverflowingCell()) {
+  if (HasVisuallyOverflowingCell()) {
     for (LayoutTableRow* row = LastRow(); row; row = row->PreviousRow()) {
       // FIXME: We have to skip over inline flows, since they can show up inside
       // table rows at the moment (a demoted inline <form> for example). If we
diff --git a/third_party/blink/renderer/core/layout/layout_table_section.h b/third_party/blink/renderer/core/layout/layout_table_section.h
index 364313c..d8c2390 100644
--- a/third_party/blink/renderer/core/layout/layout_table_section.h
+++ b/third_party/blink/renderer/core/layout/layout_table_section.h
@@ -120,8 +120,8 @@
   int VBorderSpacingBeforeFirstRow() const;
   int CalcRowLogicalHeight();
   void LayoutRows();
-  void ComputeOverflowFromDescendants();
-  bool RecalcOverflow() override;
+  bool RecalcLayoutOverflow() final;
+  bool RecalcVisualOverflow() final;
 
   void MarkAllCellsWidthsDirtyAndOrNeedsLayout(LayoutTable::WhatToMarkAllCells);
 
@@ -237,11 +237,11 @@
                                       CellSpan& rows,
                                       CellSpan& columns) const;
 
-  const HashSet<const LayoutTableCell*>& OverflowingCells() const {
-    return overflowing_cells_;
+  const HashSet<const LayoutTableCell*>& VisuallyOverflowingCells() const {
+    return visually_overflowing_cells_;
   }
-  bool HasOverflowingCell() const {
-    return overflowing_cells_.size() || force_full_paint_;
+  bool HasVisuallyOverflowingCell() const {
+    return visually_overflowing_cells_.size() || force_full_paint_;
   }
   bool HasMultipleCellLevels() const { return has_multiple_cell_levels_; }
 
@@ -291,6 +291,9 @@
   void UpdateLogicalWidthForCollapsedCells(
       const Vector<int>& col_collapsed_width);
 
+  void ComputeVisualOverflowFromDescendants();
+  void ComputeLayoutOverflowFromDescendants();
+
  protected:
   void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
   bool NodeAtPoint(HitTestResult&,
@@ -299,9 +302,6 @@
                    HitTestAction) override;
 
  private:
-  void ComputeVisualOverflowFromDescendants();
-  void ComputeLayoutOverflowFromDescendants();
-
   bool IsOfType(LayoutObjectType type) const override {
     return type == kLayoutObjectTableSection || LayoutBox::IsOfType(type);
   }
@@ -450,8 +450,8 @@
 
   // This HashSet holds the overflowing cells for the partial paint path. If we
   // have too many overflowing cells, it will be empty and force_full_paint_
-  // will be set to save memory. See ComputeOverflowFromDescendants().
-  HashSet<const LayoutTableCell*> overflowing_cells_;
+  // will be set to save memory. See ComputeVisualOverflowFromDescendants().
+  HashSet<const LayoutTableCell*> visually_overflowing_cells_;
   bool force_full_paint_;
 
   // This boolean tracks if we have cells overlapping due to rowspan / colspan
diff --git a/third_party/blink/renderer/core/layout/layout_table_section_test.cc b/third_party/blink/renderer/core/layout/layout_table_section_test.cc
index a06ed4f..9b40a63 100644
--- a/third_party/blink/renderer/core/layout/layout_table_section_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_table_section_test.cc
@@ -332,7 +332,7 @@
 
   LayoutRect paint_rect(50, 50, 50, 50);
   auto* small_section = CreateSection(20, 20);
-  EXPECT_FALSE(small_section->HasOverflowingCell());
+  EXPECT_FALSE(small_section->HasVisuallyOverflowingCell());
   CellSpan rows;
   CellSpan columns;
   small_section->DirtiedRowsAndEffectiveColumns(paint_rect, rows, columns);
@@ -340,7 +340,7 @@
   EXPECT_NE(small_section->FullTableEffectiveColumnSpan(), columns);
 
   auto* big_section = CreateSection(80, 80);
-  EXPECT_FALSE(big_section->HasOverflowingCell());
+  EXPECT_FALSE(big_section->HasVisuallyOverflowingCell());
   big_section->DirtiedRowsAndEffectiveColumns(paint_rect, rows, columns);
   EXPECT_NE(big_section->FullSectionRowSpan(), rows);
   EXPECT_NE(big_section->FullTableEffectiveColumnSpan(), columns);
@@ -350,15 +350,15 @@
   UpdateAllLifecyclePhasesForTest();
 
   // Small sections with overflowing cells always use the full paint path.
-  EXPECT_TRUE(small_section->HasOverflowingCell());
-  EXPECT_EQ(0u, small_section->OverflowingCells().size());
+  EXPECT_TRUE(small_section->HasVisuallyOverflowingCell());
+  EXPECT_EQ(0u, small_section->VisuallyOverflowingCells().size());
   small_section->DirtiedRowsAndEffectiveColumns(paint_rect, rows, columns);
   EXPECT_EQ(small_section->FullSectionRowSpan(), rows);
   EXPECT_EQ(small_section->FullTableEffectiveColumnSpan(), columns);
 
   // Big sections with small number of overflowing cells use partial paint path.
-  EXPECT_TRUE(big_section->HasOverflowingCell());
-  EXPECT_EQ(80u, big_section->OverflowingCells().size());
+  EXPECT_TRUE(big_section->HasVisuallyOverflowingCell());
+  EXPECT_EQ(80u, big_section->VisuallyOverflowingCells().size());
   big_section->DirtiedRowsAndEffectiveColumns(paint_rect, rows, columns);
   EXPECT_NE(big_section->FullSectionRowSpan(), rows);
   EXPECT_NE(big_section->FullTableEffectiveColumnSpan(), columns);
@@ -370,16 +370,16 @@
   UpdateAllLifecyclePhasesForTest();
 
   // Small sections with overflowing cells always use the full paint path.
-  EXPECT_TRUE(small_section->HasOverflowingCell());
-  EXPECT_EQ(0u, small_section->OverflowingCells().size());
+  EXPECT_TRUE(small_section->HasVisuallyOverflowingCell());
+  EXPECT_EQ(0u, small_section->VisuallyOverflowingCells().size());
   small_section->DirtiedRowsAndEffectiveColumns(paint_rect, rows, columns);
   EXPECT_EQ(small_section->FullSectionRowSpan(), rows);
   EXPECT_EQ(small_section->FullTableEffectiveColumnSpan(), columns);
 
   // Big sections with too many overflowing cells are forced to use the full
   // paint path.
-  EXPECT_TRUE(big_section->HasOverflowingCell());
-  EXPECT_EQ(0u, big_section->OverflowingCells().size());
+  EXPECT_TRUE(big_section->HasVisuallyOverflowingCell());
+  EXPECT_EQ(0u, big_section->VisuallyOverflowingCells().size());
   big_section->DirtiedRowsAndEffectiveColumns(paint_rect, rows, columns);
   EXPECT_EQ(big_section->FullSectionRowSpan(), rows);
   EXPECT_EQ(big_section->FullTableEffectiveColumnSpan(), columns);
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc
index 6f0ff01d..1bf767b5 100644
--- a/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -1780,6 +1780,17 @@
     SetText(std::move(text_to_transform), true);
 }
 
+bool LayoutText::RecalcVisualOverflow() {
+  if (!NeedsVisualOverflowRecalc())
+    return false;
+  ClearSelfNeedsVisualOverflowRecalc();
+  ClearChildNeedsVisualOverflowRecalc();
+  // The actual visual overflow of text is computed during layout,
+  // because of complications to do with glyph caches, so return true
+  // always if recalc is needed for now.
+  return true;
+}
+
 static inline bool IsInlineFlowOrEmptyText(const LayoutObject* o) {
   if (o->IsLayoutInline())
     return true;
diff --git a/third_party/blink/renderer/core/layout/layout_text.h b/third_party/blink/renderer/core/layout/layout_text.h
index cfefdc2..221ff37 100644
--- a/third_party/blink/renderer/core/layout/layout_text.h
+++ b/third_party/blink/renderer/core/layout/layout_text.h
@@ -204,6 +204,8 @@
 
   virtual void TransformText();
 
+  bool RecalcVisualOverflow() override;
+
   LayoutRect LocalSelectionRect() const final;
   LayoutRect LocalCaretRect(
       const InlineBox*,
diff --git a/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc b/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc
index 0c66899..375d0a3 100644
--- a/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc
+++ b/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc
@@ -129,8 +129,10 @@
     // The placeholder gets layout last, after the parent text control and its
     // other children, so in order to get the correct overflow from the
     // placeholder we need to recompute it now.
-    if (needed_layout)
-      ComputeOverflow(ClientLogicalBottom());
+    if (needed_layout) {
+      SetNeedsOverflowRecalc();
+      ComputeLayoutOverflow(ClientLogicalBottom());
+    }
   }
 }
 
@@ -317,8 +319,8 @@
 }
 
 void LayoutTextControlSingleLine::ComputeVisualOverflow(
-    const LayoutRect& previous_visual_overflow_rect,
     bool recompute_floats) {
+  LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
   AddVisualOverflowFromChildren();
 
   AddVisualEffectOverflow();
@@ -329,8 +331,11 @@
     AddVisualOverflowFromFloats();
 
   if (VisualOverflowRect() != previous_visual_overflow_rect) {
-    if (Layer())
-      Layer()->SetNeedsCompositingInputsUpdate();
+    if (Layer()) {
+      Layer()->SetNeedsCompositingInputsUpdate(
+          PaintLayer::DoesNotNeedDescendantDependentUpdate);
+    }
+    SetShouldCheckForPaintInvalidation();
     GetFrameView()->SetIntersectionObservationState(LocalFrameView::kDesired);
   }
 }
diff --git a/third_party/blink/renderer/core/layout/layout_text_control_single_line.h b/third_party/blink/renderer/core/layout/layout_text_control_single_line.h
index 66c2a232..9685eadb 100644
--- a/third_party/blink/renderer/core/layout/layout_text_control_single_line.h
+++ b/third_party/blink/renderer/core/layout/layout_text_control_single_line.h
@@ -78,7 +78,7 @@
       LayoutUnit line_height,
       LayoutUnit non_content_height) const override;
 
-  void ComputeVisualOverflow(const LayoutRect&, bool recompute_floats) override;
+  void ComputeVisualOverflow(bool recompute_floats) override;
 
   // If the INPUT content height is smaller than the font height, the
   // inner-editor element overflows the INPUT box intentionally, however it
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc
index 21975a8..163b6ac 100644
--- a/third_party/blink/renderer/core/layout/layout_view.cc
+++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -859,10 +859,10 @@
     SetHasBoxDecorationBackground(true);
 }
 
-bool LayoutView::RecalcOverflow() {
-  if (!NeedsOverflowRecalc())
+bool LayoutView::RecalcLayoutOverflow() {
+  if (!NeedsLayoutOverflowRecalc())
     return false;
-  bool result = LayoutBlockFlow::RecalcOverflow();
+  bool result = LayoutBlockFlow::RecalcLayoutOverflow();
   if (result) {
     // Changing overflow should notify scrolling coordinator to ensures that it
     // updates non-fast scroll rects even if there is no layout.
diff --git a/third_party/blink/renderer/core/layout/layout_view.h b/third_party/blink/renderer/core/layout/layout_view.h
index 6353404..ac72bdf 100644
--- a/third_party/blink/renderer/core/layout/layout_view.h
+++ b/third_party/blink/renderer/core/layout/layout_view.h
@@ -252,7 +252,7 @@
   // (which is responsible for painting the tickmarks).
   void InvalidatePaintForTickmarks();
 
-  bool RecalcOverflow() override;
+  bool RecalcLayoutOverflow() final;
 
   // The visible background area, in the local coordinates. The view background
   // will be painted in this rect. It's also the positioning area of fixed-
diff --git a/third_party/blink/renderer/core/layout/line/inline_flow_box.cc b/third_party/blink/renderer/core/layout/line/inline_flow_box.cc
index 5185f3b..e53c009 100644
--- a/third_party/blink/renderer/core/layout/line/inline_flow_box.cc
+++ b/third_party/blink/renderer/core/layout/line/inline_flow_box.cc
@@ -918,15 +918,18 @@
   }
 }
 
-void InlineFlowBox::OverrideVisualOverflowFromLogicalRect(
+bool InlineFlowBox::OverrideVisualOverflowFromLogicalRect(
     const LayoutRect& logical_visual_overflow,
     LayoutUnit line_top,
     LayoutUnit line_bottom) {
   // If we are setting an overflow, then we can't pretend not to have an
   // overflow.
   ClearKnownToHaveNoOverflow();
+  LayoutRect old_visual_overflow_rect =
+      VisualOverflowRect(line_top, line_bottom);
   SetVisualOverflowFromLogicalRect(logical_visual_overflow, line_top,
                                    line_bottom);
+  return VisualOverflowRect(line_top, line_bottom) != old_visual_overflow_rect;
 }
 
 void InlineFlowBox::OverrideLayoutOverflowFromLogicalRect(
@@ -1121,24 +1124,11 @@
     text_box->SetLogicalOverflowRect(logical_visual_overflow);
 }
 
-inline void InlineFlowBox::AddReplacedChildOverflow(
+inline void InlineFlowBox::AddReplacedChildLayoutOverflow(
     const InlineBox* inline_box,
-    LayoutRect& logical_layout_overflow,
-    LayoutRect& logical_visual_overflow) {
+    LayoutRect& logical_layout_overflow) {
   LineLayoutBox box = LineLayoutBox(inline_box->GetLineLayoutItem());
 
-  // Visual overflow only propagates if the box doesn't have a self-painting
-  // layer. This rectangle does not include transforms or relative positioning
-  // (since those objects always have self-painting layers), but it does need to
-  // be adjusted for writing-mode differences.
-  if (!box.HasSelfPaintingLayer()) {
-    LayoutRect child_logical_visual_overflow =
-        box.LogicalVisualOverflowRectForPropagation();
-    child_logical_visual_overflow.Move(inline_box->LogicalLeft(),
-                                       inline_box->LogicalTop());
-    logical_visual_overflow.Unite(child_logical_visual_overflow);
-  }
-
   // Layout overflow internal to the child box only propagates if the child box
   // doesn't have overflow clip set. Otherwise the child border box propagates
   // as layout overflow. This rectangle must include transforms and relative
@@ -1150,6 +1140,34 @@
   logical_layout_overflow.Unite(child_logical_layout_overflow);
 }
 
+void InlineFlowBox::AddReplacedChildrenVisualOverflow(LayoutUnit line_top,
+                                                      LayoutUnit line_bottom) {
+  LayoutRect logical_visual_overflow =
+      VisualOverflowRect(line_top, line_bottom);
+  for (InlineBox* curr = FirstChild(); curr; curr = curr->NextOnLine()) {
+    const LineLayoutItem& item = curr->GetLineLayoutItem();
+    if (item.IsOutOfFlowPositioned() || item.IsText() || item.IsLayoutInline())
+      continue;
+
+    LineLayoutBox box = LineLayoutBox(curr->GetLineLayoutItem());
+
+    // Visual overflow only propagates if the box doesn't have a self-painting
+    // layer. This rectangle does not include transforms or relative positioning
+    // (since those objects always have self-painting layers), but it does need
+    // to be adjusted for writing-mode differences.
+    if (!box.HasSelfPaintingLayer()) {
+      LayoutRect child_logical_visual_overflow =
+          box.LogicalVisualOverflowRectForPropagation();
+      child_logical_visual_overflow.Move(curr->LogicalLeft(),
+                                         curr->LogicalTop());
+      logical_visual_overflow.Unite(child_logical_visual_overflow);
+      ClearKnownToHaveNoOverflow();
+    }
+  }
+  SetVisualOverflowFromLogicalRect(logical_visual_overflow, line_top,
+                                   line_bottom);
+}
+
 static void ComputeGlyphOverflow(
     InlineTextBox* text,
     const LineLayoutText& layout_text,
@@ -1250,8 +1268,7 @@
         logical_layout_overflow =
             LogicalFrameRectIncludingLineHeight(line_top, line_bottom);
       }
-      AddReplacedChildOverflow(curr, logical_layout_overflow,
-                               logical_visual_overflow);
+      AddReplacedChildLayoutOverflow(curr, logical_layout_overflow);
     }
   }
 
diff --git a/third_party/blink/renderer/core/layout/line/inline_flow_box.h b/third_party/blink/renderer/core/layout/line/inline_flow_box.h
index 6c14c1f..c6b7c33 100644
--- a/third_party/blink/renderer/core/layout/line/inline_flow_box.h
+++ b/third_party/blink/renderer/core/layout/line/inline_flow_box.h
@@ -246,9 +246,16 @@
   LayoutUnit ComputeUnderAnnotationAdjustment(
       LayoutUnit allowed_position) const;
 
+  // Computes all layout overflow, plus visual overflow not due to replaced
+  // children. Visual overflow due to replaced children is computed during
+  // the RecalcVisualOverflow tree walk. Other visual overflow is computed
+  // during layout for performance reasons.
   void ComputeOverflow(LayoutUnit line_top,
                        LayoutUnit line_bottom,
                        GlyphOverflowAndFallbackFontsMap&);
+  // Adds visual flow to the current visual overflow for replaced children.
+  void AddReplacedChildrenVisualOverflow(LayoutUnit line_top,
+                                         LayoutUnit line_bottom);
 
   void RemoveChild(InlineBox* child, MarkLineBoxes);
 
@@ -378,7 +385,7 @@
     is_first_after_page_break_ = is_first_after_page_break;
   }
 
-  void OverrideVisualOverflowFromLogicalRect(
+  bool OverrideVisualOverflowFromLogicalRect(
       const LayoutRect& logical_visual_overflow,
       LayoutUnit line_top,
       LayoutUnit line_bottom);
@@ -419,9 +426,8 @@
   void AddTextBoxVisualOverflow(InlineTextBox*,
                                 GlyphOverflowAndFallbackFontsMap&,
                                 LayoutRect& logical_visual_overflow);
-  void AddReplacedChildOverflow(const InlineBox*,
-                                LayoutRect& logical_layout_overflow,
-                                LayoutRect& logical_visual_overflow);
+  void AddReplacedChildLayoutOverflow(const InlineBox*,
+                                      LayoutRect& logical_layout_overflow);
   bool HasEmphasisMarkBefore(const InlineTextBox*) const;
   bool HasEmphasisMarkOver(const InlineTextBox*) const;
   bool HasEmphasisMarkUnder(const InlineTextBox*) const;
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
index 833ab23..75a9129 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
@@ -73,14 +73,18 @@
 
 template <typename Base>
 void LayoutNGMixin<Base>::ComputeVisualOverflow(
-    const LayoutRect& previous_visual_overflow_rect,
     bool recompute_floats) {
-  Base::ComputeVisualOverflow(previous_visual_overflow_rect, recompute_floats);
+  LayoutRect previous_visual_overflow_rect = Base::VisualOverflowRect();
+  Base::ClearVisualOverflow();
+  Base::ComputeVisualOverflow(recompute_floats);
   AddVisualOverflowFromChildren();
 
   if (Base::VisualOverflowRect() != previous_visual_overflow_rect) {
-    if (Base::Layer())
-      Base::Layer()->SetNeedsCompositingInputsUpdate();
+    if (Base::Layer()) {
+      Base::Layer()->SetNeedsCompositingInputsUpdate(
+          PaintLayer::DoesNotNeedDescendantDependentUpdate);
+    }
+    Base::SetShouldCheckForPaintInvalidation();
     Base::GetFrameView()->SetIntersectionObservationState(
         LocalFrameView::kDesired);
   }
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
index b554011..502ac6d3 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
@@ -83,7 +83,7 @@
  protected:
   bool IsOfType(LayoutObject::LayoutObjectType) const override;
 
-  void ComputeVisualOverflow(const LayoutRect&, bool recompute_floats) final;
+  void ComputeVisualOverflow(bool recompute_floats) final;
 
   void AddVisualOverflowFromChildren();
   void AddLayoutOverflowFromChildren() final;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index eb1c95f..6467db21 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -595,8 +595,9 @@
 
     // |ComputeOverflow()| below calls |AddVisualOverflowFromChildren()|, which
     // computes visual overflow from |RootInlineBox| if |ChildrenInline()|
-    block->ComputeOverflow(intrinsic_block_size - borders.block_end -
-                           scrollbars.block_end);
+    block->SetNeedsOverflowRecalc();
+    block->ComputeLayoutOverflow(intrinsic_block_size - borders.block_end -
+                                 scrollbars.block_end);
   }
 
   box_->UpdateAfterLayout();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
index 20f09c4..61c5f6f 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
@@ -210,11 +210,7 @@
   }
 
   const auto& old_overflow_rect = VisualOverflowRect();
-  ClearAllOverflows();
-  AddVisualEffectOverflow();
-
-  if (!ShouldApplyViewportClip())
-    AddContentsVisualOverflow(ComputeContentsVisualOverflow());
+  ClearLayoutOverflow();
 
   // The scale of one or more of the SVG elements may have changed, content
   // (the entire SVG) could have moved or new content may have been exposed, so
@@ -245,11 +241,19 @@
          StyleRef().OverflowX() == EOverflow::kScroll || IsDocumentElement();
 }
 
-LayoutRect LayoutSVGRoot::VisualOverflowRect() const {
-  LayoutRect rect = LayoutReplaced::SelfVisualOverflowRect();
-  if (!ShouldApplyViewportClip())
-    rect.Unite(ContentsVisualOverflowRect());
-  return rect;
+bool LayoutSVGRoot::RecalcVisualOverflow() {
+  if (!NeedsVisualOverflowRecalc())
+    return false;
+  bool visual_overflow_changed = LayoutReplaced::RecalcVisualOverflow();
+  UpdateCachedBoundaries();
+  if (!ShouldApplyViewportClip()) {
+    LayoutRect old_contents_overflow = ContentsVisualOverflowRect();
+    AddContentsVisualOverflow(ComputeContentsVisualOverflow());
+    visual_overflow_changed =
+        visual_overflow_changed ||
+        old_contents_overflow != ContentsVisualOverflowRect();
+  }
+  return visual_overflow_changed;
 }
 
 LayoutRect LayoutSVGRoot::ComputeContentsVisualOverflow() const {
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.h b/third_party/blink/renderer/core/layout/svg/layout_svg_root.h
index 338bc72..1ffe8140 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.h
@@ -85,7 +85,7 @@
 
   bool ShouldApplyViewportClip() const;
 
-  LayoutRect VisualOverflowRect() const override;
+  bool RecalcVisualOverflow() override;
 
   bool HasNonIsolatedBlendingDescendants() const final;
 
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc
index e72add9..859ac47 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc
@@ -283,9 +283,7 @@
     update_parent_boundaries = true;
   }
 
-  ClearAllOverflows();
-  AddSelfVisualOverflow(LayoutRect(new_boundaries));
-  AddVisualEffectOverflow();
+  ClearLayoutOverflow();
 
   // Invalidate all resources of this client if our layout changed.
   if (EverHadLayout() && SelfNeedsLayout())
@@ -302,6 +300,15 @@
   ClearNeedsLayout();
 }
 
+bool LayoutSVGText::RecalcVisualOverflow() {
+  LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
+  bool visual_overflow_changed = LayoutObject::RecalcVisualOverflow();
+  AddSelfVisualOverflow(LayoutRect(ObjectBoundingBox()));
+  AddVisualEffectOverflow();
+  return visual_overflow_changed ||
+         previous_visual_overflow_rect != VisualOverflowRect();
+}
+
 RootInlineBox* LayoutSVGText::CreateRootInlineBox() {
   RootInlineBox* box = new SVGRootInlineBox(LineLayoutItem(this));
   box->SetHasVirtualLogicalHeight();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text.h b/third_party/blink/renderer/core/layout/svg/layout_svg_text.h
index ce40fa6..bff7bfa 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_text.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text.h
@@ -62,6 +62,8 @@
   void SubtreeChildWillBeRemoved();
   void SubtreeTextDidChange();
 
+  bool RecalcVisualOverflow() override;
+
   const char* GetName() const override { return "LayoutSVGText"; }
 
  private:
diff --git a/third_party/blink/renderer/core/loader/BUILD.gn b/third_party/blink/renderer/core/loader/BUILD.gn
index 7deab887..a98388e 100644
--- a/third_party/blink/renderer/core/loader/BUILD.gn
+++ b/third_party/blink/renderer/core/loader/BUILD.gn
@@ -12,6 +12,8 @@
     "appcache/application_cache_host.h",
     "base_fetch_context.cc",
     "base_fetch_context.h",
+    "console_logger_impl_base.cc",
+    "console_logger_impl_base.h",
     "cookie_jar.cc",
     "cookie_jar.h",
     "document_load_timing.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 99a2a6f..5d9731ca 100644
--- a/third_party/blink/renderer/core/loader/base_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -89,21 +89,6 @@
   return "";
 }
 
-MessageSource ConvertLogSourceToMessageSource(FetchContext::LogSource source) {
-  // When LogSource is extended, this switch statement should be modified to
-  // convert LogSource to blink::MessageSource.
-  switch (source) {
-    case FetchContext::kJSSource:
-      return kJSMessageSource;
-    case FetchContext::kSecuritySource:
-      return kSecurityMessageSource;
-    case FetchContext::kOtherSource:
-      return kOtherMessageSource;
-  }
-  NOTREACHED();
-  return kOtherMessageSource;
-}
-
 }  // namespace
 
 BaseFetchContext::BaseFetchContext(
@@ -201,24 +186,6 @@
   return blocked_reason;
 }
 
-void BaseFetchContext::AddInfoConsoleMessage(const String& message,
-                                             LogSource source) const {
-  AddConsoleMessage(ConsoleMessage::Create(
-      ConvertLogSourceToMessageSource(source), kInfoMessageLevel, message));
-}
-
-void BaseFetchContext::AddWarningConsoleMessage(const String& message,
-                                                LogSource source) const {
-  AddConsoleMessage(ConsoleMessage::Create(
-      ConvertLogSourceToMessageSource(source), kWarningMessageLevel, message));
-}
-
-void BaseFetchContext::AddErrorConsoleMessage(const String& message,
-                                              LogSource source) const {
-  AddConsoleMessage(ConsoleMessage::Create(
-      ConvertLogSourceToMessageSource(source), kErrorMessageLevel, message));
-}
-
 bool BaseFetchContext::IsAdResource(
     const KURL& resource_url,
     ResourceType type,
@@ -318,8 +285,9 @@
   if (request_mode != network::mojom::FetchRequestMode::kNavigate &&
       !origin->CanDisplay(url)) {
     if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
-      AddErrorConsoleMessage(
-          "Not allowed to load local resource: " + url.GetString(), kJSSource);
+      AddConsoleMessage(ConsoleMessage::Create(
+          kJSMessageSource, kErrorMessageLevel,
+          "Not allowed to load local resource: " + url.GetString()));
     }
     RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::requestResource URL was not "
                                  "allowed by SecurityOrigin::CanDisplay";
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.h b/third_party/blink/renderer/core/loader/base_fetch_context.h
index 07c0174..011d716 100644
--- a/third_party/blink/renderer/core/loader/base_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/base_fetch_context.h
@@ -56,9 +56,6 @@
   virtual std::unique_ptr<WebSocketHandshakeThrottle>
   CreateWebSocketHandshakeThrottle() = 0;
 
-  void AddInfoConsoleMessage(const String&, LogSource) const override;
-  void AddWarningConsoleMessage(const String&, LogSource) const override;
-  void AddErrorConsoleMessage(const String&, LogSource) const override;
   bool IsAdResource(const KURL&,
                     ResourceType,
                     mojom::RequestContextType) const override;
@@ -94,6 +91,7 @@
   virtual base::Optional<mojom::IPAddressSpace> GetAddressSpace() const = 0;
   virtual const ContentSecurityPolicy* GetContentSecurityPolicy() const = 0;
 
+  // TODO(yhirano): Remove this.
   virtual void AddConsoleMessage(ConsoleMessage*) const = 0;
 
  private:
diff --git a/third_party/blink/renderer/core/loader/console_logger_impl_base.cc b/third_party/blink/renderer/core/loader/console_logger_impl_base.cc
new file mode 100644
index 0000000..decf906
--- /dev/null
+++ b/third_party/blink/renderer/core/loader/console_logger_impl_base.cc
@@ -0,0 +1,46 @@
+// 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 "third_party/blink/renderer/core/loader/console_logger_impl_base.h"
+
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
+
+namespace blink {
+
+ConsoleLoggerImplBase::ConsoleLoggerImplBase() = default;
+ConsoleLoggerImplBase::~ConsoleLoggerImplBase() = default;
+
+void ConsoleLoggerImplBase::AddInfoMessage(Source source,
+                                           const String& message) {
+  AddConsoleMessage(ConsoleMessage::Create(GetMessageSourceFromSource(source),
+                                           kInfoMessageLevel, message));
+}
+
+void ConsoleLoggerImplBase::AddWarningMessage(Source source,
+                                              const String& message) {
+  AddConsoleMessage(ConsoleMessage::Create(GetMessageSourceFromSource(source),
+                                           kWarningMessageLevel, message));
+}
+
+void ConsoleLoggerImplBase::AddErrorMessage(Source source,
+                                            const String& message) {
+  AddConsoleMessage(ConsoleMessage::Create(GetMessageSourceFromSource(source),
+                                           kErrorMessageLevel, message));
+}
+
+MessageSource ConsoleLoggerImplBase::GetMessageSourceFromSource(Source source) {
+  switch (source) {
+    case Source::kScript:
+      return kJSMessageSource;
+    case Source::kSecurity:
+      return kSecurityMessageSource;
+    case Source::kOther:
+      return kOtherMessageSource;
+  }
+  NOTREACHED();
+  return kOtherMessageSource;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/console_logger_impl_base.h b/third_party/blink/renderer/core/loader/console_logger_impl_base.h
new file mode 100644
index 0000000..ea67327b
--- /dev/null
+++ b/third_party/blink/renderer/core/loader/console_logger_impl_base.h
@@ -0,0 +1,36 @@
+// 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_LOADER_CONSOLE_LOGGER_IMPL_BASE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_CONSOLE_LOGGER_IMPL_BASE_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/inspector/console_types.h"
+#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
+
+namespace blink {
+
+class ConsoleMessage;
+
+// A bridge class which translates an Add(Info|Warning|Error)Message call to
+// an AddMessage call.
+class CORE_EXPORT ConsoleLoggerImplBase : public ConsoleLogger {
+ public:
+  ConsoleLoggerImplBase();
+  ~ConsoleLoggerImplBase() override;
+
+  // ConsoleLogger implementation.
+  void AddInfoMessage(Source source, const String& message) override;
+  void AddWarningMessage(Source source, const String& message) override;
+  void AddErrorMessage(Source source, const String& message) override;
+
+  virtual void AddConsoleMessage(ConsoleMessage*) = 0;
+
+ private:
+  static MessageSource GetMessageSourceFromSource(Source);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_CONSOLE_LOGGER_IMPL_BASE_H_
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 9905daf..52a2d33 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -117,7 +117,7 @@
     std::unique_ptr<WebNavigationParams> navigation_params)
     : request_(navigation_params->request.ToResourceRequest()),
       frame_(frame),
-      fetcher_(FrameFetchContext::CreateFetcherFromDocumentLoader(this)),
+      fetcher_(FrameFetchContext::CreateFetcher(this)),
       original_url_(request_.Url()),
       original_referrer_(request_.HttpReferrer()),
       load_type_(navigation_params->frame_load_type),
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 fa26441..eec8749 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -304,25 +304,43 @@
   }
 };
 
-ResourceFetcher* FrameFetchContext::CreateFetcher(DocumentLoader* loader,
-                                                  Document* document) {
-  FrameFetchContext* context =
-      MakeGarbageCollected<FrameFetchContext>(loader, document);
-  return MakeGarbageCollected<ResourceFetcher>(context);
+ResourceFetcher* FrameFetchContext::CreateFetcher(DocumentLoader* loader) {
+  DCHECK(loader);
+  FrameFetchContext* context = MakeGarbageCollected<FrameFetchContext>(loader);
+  ConsoleLogger* logger = &context->GetFrame()->Console();
+  return MakeGarbageCollected<ResourceFetcher>(context, logger);
 }
 
-FrameFetchContext::FrameFetchContext(DocumentLoader* loader, Document* document)
+ResourceFetcher* FrameFetchContext::CreateFetcherForImportedDocument(
+    Document* document) {
+  DCHECK(document);
+  FrameFetchContext* context =
+      MakeGarbageCollected<FrameFetchContext>(document);
+  // |document| is detached.
+  DCHECK(!document->GetFrame());
+  ConsoleLogger* logger = &context->GetFrame()->Console();
+  return MakeGarbageCollected<ResourceFetcher>(context, logger);
+}
+
+FrameFetchContext::FrameFetchContext(DocumentLoader* loader)
     : BaseFetchContext(
-          document
-              ? document->GetTaskRunner(blink::TaskType::kNetworking)
-              : loader->GetFrame()->GetTaskRunner(blink::TaskType::kNetworking),
-          document
-              ? *MakeGarbageCollected<FetchClientSettingsObjectImpl>(*document)
-              : CreateFetchClientSettingsObjectForNavigation()),
+          loader->GetFrame()->GetTaskRunner(blink::TaskType::kNetworking),
+          CreateFetchClientSettingsObjectForNavigation()),
       document_loader_(loader),
+      save_data_enabled_(GetNetworkStateNotifier().SaveDataEnabled() &&
+                         !GetSettings()->GetDataSaverHoldbackWebApi()) {
+  DCHECK(loader);
+  DCHECK(GetFrame());
+}
+
+FrameFetchContext::FrameFetchContext(Document* document)
+    : BaseFetchContext(
+          document->GetTaskRunner(blink::TaskType::kNetworking),
+          *MakeGarbageCollected<FetchClientSettingsObjectImpl>(*document)),
       document_(document),
       save_data_enabled_(GetNetworkStateNotifier().SaveDataEnabled() &&
                          !GetSettings()->GetDataSaverHoldbackWebApi()) {
+  DCHECK(document);
   DCHECK(GetFrame());
 }
 
@@ -602,9 +620,8 @@
 
 void FrameFetchContext::DispatchDidReceiveResponse(
     unsigned long identifier,
+    const ResourceRequest& request,
     const ResourceResponse& response,
-    network::mojom::RequestContextFrameType frame_type,
-    mojom::RequestContextType request_context,
     Resource* resource,
     ResourceResponseType response_type) {
   if (IsDetached())
@@ -620,6 +637,9 @@
                                           MasterDocumentLoader());
 
   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())
@@ -662,7 +682,8 @@
 
   if (response.HasMajorCertificateErrors()) {
     MixedContentChecker::HandleCertificateError(GetFrame(), response,
-                                                frame_type, request_context);
+                                                request.GetFrameType(),
+                                                request.GetRequestContext());
   }
 
   if (response.IsLegacySymantecCert()) {
@@ -781,17 +802,6 @@
   }
 }
 
-void FrameFetchContext::DispatchDidLoadResourceFromMemoryCache(
-    unsigned long identifier,
-    const ResourceRequest& resource_request,
-    const ResourceResponse& resource_response) {
-  if (IsDetached())
-    return;
-
-  GetLocalFrameClient()->DispatchDidLoadResourceFromMemoryCache(
-      resource_request, resource_response);
-}
-
 bool FrameFetchContext::ShouldLoadNewResource(ResourceType type) const {
   if (!document_loader_)
     return true;
@@ -1557,9 +1567,9 @@
     ResourceRequest::RedirectStatus redirect_status) const {
   if (document_ && document_->IsFreezingInProgress() &&
       !resource_request.GetKeepalive()) {
-    AddErrorConsoleMessage(
-        "Only fetch keepalive is allowed during onfreeze: " + url.GetString(),
-        kJSSource);
+    AddConsoleMessage(ConsoleMessage::Create(
+        kJSMessageSource, kErrorMessageLevel,
+        "Only fetch keepalive is allowed during onfreeze: " + url.GetString()));
     return ResourceRequestBlockedReason::kOther;
   }
   return BaseFetchContext::CanRequest(type, resource_request, url, options,
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 f5ef48ac..ad43a51 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -64,19 +64,15 @@
 
 class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
  public:
-  static ResourceFetcher* CreateFetcherFromDocumentLoader(
-      DocumentLoader* loader) {
-    return CreateFetcher(loader, nullptr);
-  }
+  static ResourceFetcher* CreateFetcher(DocumentLoader* loader);
   // Used for creating a FrameFetchContext for an imported Document.
   // |document_loader_| will be set to nullptr.
-  static ResourceFetcher* CreateFetcherFromDocument(Document* document) {
-    return CreateFetcher(nullptr, document);
-  }
+  static ResourceFetcher* CreateFetcherForImportedDocument(Document* document);
 
   void ProvideDocumentToContext(Document*);
 
-  FrameFetchContext(DocumentLoader*, Document*);
+  explicit FrameFetchContext(DocumentLoader*);
+  explicit FrameFetchContext(Document*);
   ~FrameFetchContext() override;
 
   bool IsFrameFetchContext() const override { return true; }
@@ -104,13 +100,9 @@
       const ResourceResponse& redirect_response,
       ResourceType,
       const FetchInitiatorInfo& = FetchInitiatorInfo()) override;
-  void DispatchDidLoadResourceFromMemoryCache(unsigned long identifier,
-                                              const ResourceRequest&,
-                                              const ResourceResponse&) override;
   void DispatchDidReceiveResponse(unsigned long identifier,
+                                  const ResourceRequest&,
                                   const ResourceResponse&,
-                                  network::mojom::RequestContextFrameType,
-                                  mojom::RequestContextType,
                                   Resource*,
                                   ResourceResponseType) override;
   void DispatchDidReceiveData(unsigned long identifier,
@@ -184,12 +176,11 @@
   void DispatchNetworkQuiet() override;
 
  private:
+  class FrameConsoleLogger;
   friend class FrameFetchContextTest;
 
   struct FrozenState;
 
-  static ResourceFetcher* CreateFetcher(DocumentLoader*, Document*);
-
   // Convenient accessors below can be used to transparently access the
   // relevant document loader or frame in either cases without null-checks.
   //
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 4283713..632ec5a 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
@@ -1093,7 +1093,7 @@
 // Tests that the embedder gets correct notification when a resource is loaded
 // from the memory cache.
 TEST_F(FrameFetchContextMockedLocalFrameClientTest,
-       DispatchDidLoadResourceFromMemoryCache) {
+       LoadResourceFromMemoryCache) {
   ResourceRequest resource_request(url);
   resource_request.SetRequestContext(mojom::RequestContextType::IMAGE);
   resource_request.SetFetchCredentialsMode(
@@ -1109,8 +1109,9 @@
               testing::Property(&ResourceRequest::GetRequestContext,
                                 mojom::RequestContextType::IMAGE)),
           testing::Property(&ResourceResponse::IsNull, true)));
-  fetch_context->DispatchDidLoadResourceFromMemoryCache(
-      CreateUniqueIdentifier(), resource_request, resource->GetResponse());
+  fetch_context->DispatchDidReceiveResponse(
+      CreateUniqueIdentifier(), resource_request, resource->GetResponse(),
+      resource, FetchContext::ResourceResponseType::kFromMemoryCache);
 }
 
 // Tests that when a resource with certificate errors is loaded from the memory
@@ -1126,8 +1127,9 @@
   Resource* resource = MockResource::Create(resource_request);
   resource->SetResponse(response);
   EXPECT_CALL(*client, DidDisplayContentWithCertificateErrors());
-  fetch_context->DispatchDidLoadResourceFromMemoryCache(
-      CreateUniqueIdentifier(), resource_request, resource->GetResponse());
+  fetch_context->DispatchDidReceiveResponse(
+      CreateUniqueIdentifier(), resource_request, resource->GetResponse(),
+      resource, FetchContext::ResourceResponseType::kFromMemoryCache);
 }
 
 TEST_F(FrameFetchContextSubresourceFilterTest, Filter) {
@@ -1251,18 +1253,6 @@
   // Should not crash.
 }
 
-TEST_F(FrameFetchContextTest,
-       DispatchDidLoadResourceFromMemoryCacheWhenDetached) {
-  ResourceRequest request(KURL("https://www.example.com/"));
-  ResourceResponse response;
-  FetchInitiatorInfo initiator_info;
-
-  dummy_page_holder = nullptr;
-
-  fetch_context->DispatchDidLoadResourceFromMemoryCache(8, request, response);
-  // Should not crash.
-}
-
 TEST_F(FrameFetchContextTest, DispatchDidReceiveResponseWhenDetached) {
   ResourceRequest request(KURL("https://www.example.com/"));
   request.SetFetchCredentialsMode(network::mojom::FetchCredentialsMode::kOmit);
@@ -1272,8 +1262,7 @@
   dummy_page_holder = nullptr;
 
   fetch_context->DispatchDidReceiveResponse(
-      3, response, network::mojom::RequestContextFrameType::kTopLevel,
-      mojom::RequestContextType::FETCH, resource,
+      3, request, response, resource,
       FetchContext::ResourceResponseType::kNotFromMemoryCache);
   // Should not crash.
 }
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 cbdaaae..23c45a1 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -265,15 +265,15 @@
 
 void WorkerFetchContext::DispatchDidReceiveResponse(
     unsigned long identifier,
+    const ResourceRequest& request,
     const ResourceResponse& response,
-    network::mojom::RequestContextFrameType frame_type,
-    mojom::RequestContextType request_context,
     Resource* resource,
     ResourceResponseType) {
   if (response.HasMajorCertificateErrors()) {
     WebMixedContentContextType context_type =
         WebMixedContent::ContextTypeFromRequestContext(
-            request_context, false /* strictMixedContentCheckingForPlugin */);
+            request.GetRequestContext(),
+            false /* strictMixedContentCheckingForPlugin */);
     if (context_type == WebMixedContentContextType::kBlockable) {
       web_context_->DidRunContentWithCertificateErrors();
     } else {
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 fc6d8ed..def6e12 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.h
@@ -84,9 +84,8 @@
                                ResourceType,
                                const FetchInitiatorInfo&) override;
   void DispatchDidReceiveResponse(unsigned long identifier,
+                                  const ResourceRequest&,
                                   const ResourceResponse&,
-                                  network::mojom::RequestContextFrameType,
-                                  mojom::RequestContextType,
                                   Resource*,
                                   ResourceResponseType) override;
   void DispatchDidReceiveData(unsigned long identifier,
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 e4296ac..1278853 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
@@ -57,7 +57,7 @@
     target.setAttribute(
         html_names::kStyleAttr,
         target.getAttribute(html_names::kStyleAttr) + "; width: 200px");
-    GetDocument().View()->UpdateLifecycleToLayoutClean();
+    GetDocument().View()->UpdateLifecycleToCompositingInputsClean();
     // Simulate that PaintInvalidator updates visual rect.
     box.GetMutableForPainting().SetVisualRect(
         LayoutRect(visual_rect.Location(), box.Size()));
diff --git a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
index 406899b..b70e07d 100644
--- a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
+++ b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
@@ -232,7 +232,13 @@
   // InCompositingUpdate.
   EnableCompositingModeIfNeeded();
 
+#if DCHECK_IS_ON()
+  view->SetIsUpdatingDescendantDependentFlags(true);
+#endif
   RootLayer()->UpdateDescendantDependentFlags();
+#if DCHECK_IS_ON()
+  view->SetIsUpdatingDescendantDependentFlags(false);
+#endif
 
   layout_view_.CommitPendingSelection();
 
@@ -300,6 +306,10 @@
   pending_update_type_ = std::max(pending_update_type_, update_type);
   if (Page* page = GetPage())
     page->Animator().ScheduleVisualUpdate(layout_view_.GetFrame());
+
+  if (layout_view_.DocumentBeingDestroyed())
+    return;
+
   Lifecycle().EnsureStateAtMost(DocumentLifecycle::kLayoutClean);
 }
 
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index c77553c3..7b8260cf 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -450,7 +450,7 @@
 
   if (had3d_transform != Has3DTransform()) {
     SetNeedsCompositingInputsUpdateInternal();
-    MarkAncestorChainForDescendantDependentFlagsUpdate();
+    MarkAncestorChainForFlagsUpdate();
   }
 
   if (LocalFrameView* frame_view = GetLayoutObject().GetDocument().View())
@@ -636,18 +636,27 @@
 }
 
 void PaintLayer::DirtyVisibleContentStatus() {
-  MarkAncestorChainForDescendantDependentFlagsUpdate();
+  MarkAncestorChainForFlagsUpdate();
   // Non-self-painting layers paint into their ancestor layer, and count as part
   // of the "visible contents" of the parent, so we need to dirty it.
   if (!IsSelfPaintingLayer())
     Parent()->DirtyVisibleContentStatus();
 }
 
-void PaintLayer::MarkAncestorChainForDescendantDependentFlagsUpdate() {
+void PaintLayer::MarkAncestorChainForFlagsUpdate(
+    DescendantDependentFlagsUpdateFlag flag) {
+#if DCHECK_IS_ON()
+  DCHECK(flag == DoesNotNeedDescendantDependentUpdate ||
+         !layout_object_.GetDocument()
+              .View()
+              ->IsUpdatingDescendantDependentFlags());
+#endif
   for (PaintLayer* layer = this; layer; layer = layer->Parent()) {
-    if (layer->needs_descendant_dependent_flags_update_)
+    if (layer->needs_descendant_dependent_flags_update_ &&
+        layer->GetLayoutObject().NeedsPaintPropertyUpdate())
       break;
-    layer->needs_descendant_dependent_flags_update_ = true;
+    if (flag == NeedsDescendantDependentUpdate)
+      layer->needs_descendant_dependent_flags_update_ = true;
     layer->GetLayoutObject().SetNeedsPaintPropertyUpdate();
   }
 }
@@ -724,6 +733,9 @@
         static_cast<bool>(has_non_isolated_descendant_with_blend_mode_))
       GetLayoutObject().SetNeedsPaintPropertyUpdate();
     needs_descendant_dependent_flags_update_ = false;
+
+    if (GetLayoutObject().NeedsVisualOverflowRecalc() && IsSelfPaintingLayer())
+      GetLayoutObject().RecalcVisualOverflow();
   }
 
   bool previously_has_visible_content = has_visible_content_;
@@ -1052,14 +1064,15 @@
   return nullptr;
 }
 
-void PaintLayer::SetNeedsCompositingInputsUpdate() {
+void PaintLayer::SetNeedsCompositingInputsUpdate(
+    DescendantDependentFlagsUpdateFlag flag) {
   SetNeedsCompositingInputsUpdateInternal();
 
   // TODO(chrishtr): These are a bit of a heavy hammer, because not all
   // things which require compositing inputs update require a descendant-
   // dependent flags update. Reduce call sites after CAP launch allows
   /// removal of CompositingInputsUpdater.
-  MarkAncestorChainForDescendantDependentFlagsUpdate();
+  MarkAncestorChainForFlagsUpdate(flag);
 }
 
 void PaintLayer::SetNeedsCompositingInputsUpdateInternal() {
@@ -1314,7 +1327,7 @@
     // building up generated content layers. This is ok, since the lists will
     // start off dirty in that case anyway.
     PaintLayerStackingNode::DirtyStackingContextZOrderLists(child);
-    MarkAncestorChainForDescendantDependentFlagsUpdate();
+    MarkAncestorChainForFlagsUpdate();
   }
 
   // Non-self-painting children paint into this layer, so the visible contents
@@ -1322,7 +1335,7 @@
   if (!child->IsSelfPaintingLayer())
     DirtyVisibleContentStatus();
 
-  MarkAncestorChainForDescendantDependentFlagsUpdate();
+  MarkAncestorChainForFlagsUpdate();
 
   // Need to force requirements update, due to change of stacking order.
   SetNeedsCompositingRequirementsUpdate();
@@ -1368,7 +1381,7 @@
     old_child->RemoveAncestorOverflowLayer(old_child->AncestorOverflowLayer());
 
   if (old_child->has_visible_content_ || old_child->has_visible_descendant_)
-    MarkAncestorChainForDescendantDependentFlagsUpdate();
+    MarkAncestorChainForFlagsUpdate();
 
   if (old_child->EnclosingPaginationLayer())
     old_child->ClearPaginationRecursive();
@@ -1388,7 +1401,7 @@
 
   if (old_style && old_style->IsStacked()) {
     PaintLayerStackingNode::DirtyStackingContextZOrderLists(this);
-    MarkAncestorChainForDescendantDependentFlagsUpdate();
+    MarkAncestorChainForFlagsUpdate();
   }
 
   bool did_set_paint_invalidation = false;
@@ -2914,7 +2927,7 @@
   MarkCompositingContainerChainForNeedsRepaint();
 
   if (PaintLayer* parent = Parent()) {
-    parent->MarkAncestorChainForDescendantDependentFlagsUpdate();
+    parent->MarkAncestorChainForFlagsUpdate();
 
     if (PaintLayer* enclosing_self_painting_layer =
             parent->EnclosingSelfPaintingLayer()) {
@@ -3081,7 +3094,7 @@
   }
 
   if (PaintLayerStackingNode::StyleDidChange(this, old_style))
-    MarkAncestorChainForDescendantDependentFlagsUpdate();
+    MarkAncestorChainForFlagsUpdate();
 
   if (RequiresScrollableArea()) {
     DCHECK(scrollable_area_);
@@ -3130,7 +3143,7 @@
 
   // HasNonContainedAbsolutePositionDescendant depends on position changes.
   if (!old_style || old_style->GetPosition() != new_style.GetPosition())
-    MarkAncestorChainForDescendantDependentFlagsUpdate();
+    MarkAncestorChainForFlagsUpdate();
 
   UpdateTransform(old_style, new_style);
   UpdateFilters(old_style, new_style);
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h
index 39c668c..64cea82 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.h
+++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -756,7 +756,16 @@
     bool is_under_video = false;
   };
 
-  void SetNeedsCompositingInputsUpdate();
+  // Indicates whether the descendant-dependent tree walk bit should also
+  // be set.
+  enum DescendantDependentFlagsUpdateFlag {
+    NeedsDescendantDependentUpdate,
+    DoesNotNeedDescendantDependentUpdate
+  };
+  void SetNeedsCompositingInputsUpdate(
+      DescendantDependentFlagsUpdateFlag = NeedsDescendantDependentUpdate);
+  // Use this internal method only for cases during the descendant-dependent
+  // tree walk.
   bool ChildNeedsCompositingInputsUpdate() const {
     return child_needs_compositing_inputs_update_;
   }
@@ -1173,7 +1182,10 @@
   bool RequiresScrollableArea() const;
   void UpdateScrollableArea();
 
-  void MarkAncestorChainForDescendantDependentFlagsUpdate();
+  // Marks the ancestor chain for paint property update, and if
+  // the flag is set, the descendant-dependent tree walk as well.
+  void MarkAncestorChainForFlagsUpdate(
+      DescendantDependentFlagsUpdateFlag = NeedsDescendantDependentUpdate);
 
   bool AttemptDirectCompositingUpdate(const StyleDifference&,
                                       const ComputedStyle* old_style);
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter.cc b/third_party/blink/renderer/core/paint/paint_layer_painter.cc
index ea5450f..fddbe89 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_painter.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_painter.cc
@@ -74,13 +74,11 @@
     if (style.Opacity())
       return false;
 
-    const auto* effect = paint_layer_.GetLayoutObject()
-                             .FirstFragment()
-                             .PaintProperties()
-                             ->Effect();
-    if (effect && effect->RequiresCompositingForAnimation()) {
+    const auto* properties =
+        paint_layer_.GetLayoutObject().FirstFragment().PaintProperties();
+    if (properties && properties->Effect() &&
+        properties->Effect()->RequiresCompositingForAnimation())
       return false;
-    }
   }
 
   // 0.0004f < 1/2048. With 10-bit color channels (only available on the
@@ -708,6 +706,7 @@
     return result;
   if (!paint_layer_.StackingNode())
     return result;
+
 #if DCHECK_IS_ON()
   LayerListMutationDetector mutation_checker(paint_layer_.StackingNode());
 #endif
@@ -717,7 +716,6 @@
   PaintLayer* child = iterator.Next();
   if (!child)
     return result;
-
   for (; child; child = iterator.Next()) {
     // If this Layer should paint into its own backing or a grouped backing,
     // that will be done via CompositedLayerMapping::PaintContents() and
@@ -818,7 +816,6 @@
                            ? fragment.fragment_data->LogicalTopInFlowThread()
                            : LayoutUnit(),
                        suppress_painting_descendants);
-
   paint_layer_.GetLayoutObject().Paint(paint_info);
 }
 
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index af910efe..56f0fbf 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -1479,7 +1479,6 @@
             viewport_container.LocalToSVGParentTransform().Inverse().MapRect(
                 viewport_container.Viewport()));
       }
-
       const ClipPaintPropertyNode* existing = properties_->OverflowClip();
       bool equal_ignoring_hit_test_rects =
           !!existing &&
diff --git a/third_party/blink/renderer/core/paint/table_painter_test.cc b/third_party/blink/renderer/core/paint/table_painter_test.cc
index 200f2ac..a31fb6f 100644
--- a/third_party/blink/renderer/core/paint/table_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/table_painter_test.cc
@@ -183,7 +183,6 @@
   )HTML");
 
   auto& cell = *ToLayoutTableCell(GetLayoutObjectByElementId("cell"));
-
   InvalidateAll(RootPaintController());
   GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
   // Intersects the overflowing part of cell but not border box.
diff --git a/third_party/blink/renderer/core/paint/table_section_painter.cc b/third_party/blink/renderer/core/paint/table_section_painter.cc
index 78f6d28..bd02fbf 100644
--- a/third_party/blink/renderer/core/paint/table_section_painter.cc
+++ b/third_party/blink/renderer/core/paint/table_section_painter.cc
@@ -202,15 +202,16 @@
       dirtied_columns.Start() >= dirtied_columns.End())
     return;
 
-  const auto& overflowing_cells = layout_table_section_.OverflowingCells();
-  if (overflowing_cells.IsEmpty()) {
+  const auto& visually_overflowing_cells =
+      layout_table_section_.VisuallyOverflowingCells();
+  if (visually_overflowing_cells.IsEmpty()) {
     // This path is for 2 cases:
     // 1. Normal partial paint, without overflowing cells;
     // 2. Full paint, for small sections or big sections with many overflowing
     //    cells.
     // The difference between the normal partial paint and full paint is that
     // whether dirtied_rows and dirtied_columns cover the whole section.
-    DCHECK(!layout_table_section_.HasOverflowingCell() ||
+    DCHECK(!layout_table_section_.HasVisuallyOverflowingCell() ||
            (dirtied_rows == layout_table_section_.FullSectionRowSpan() &&
             dirtied_columns ==
                 layout_table_section_.FullTableEffectiveColumnSpan()));
@@ -235,7 +236,7 @@
     // This is the "partial paint path" for overflowing cells referred in
     // LayoutTableSection::ComputeOverflowFromDescendants().
     Vector<const LayoutTableCell*> cells;
-    CopyToVector(overflowing_cells, cells);
+    CopyToVector(visually_overflowing_cells, cells);
 
     HashSet<const LayoutTableCell*> spanning_cells;
     for (unsigned r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) {
@@ -250,7 +251,7 @@
       for (unsigned c = dirtied_columns.Start();
            c < n_cols && c < dirtied_columns.End(); c++) {
         if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) {
-          if (!overflowing_cells.Contains(cell))
+          if (!visually_overflowing_cells.Contains(cell))
             cells.push_back(cell);
         }
       }
diff --git a/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc b/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc
index 1b3c09f..b55a502 100644
--- a/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc
+++ b/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc
@@ -286,13 +286,27 @@
   // ran.
   frame_element->setAttribute(kWidthAttr, "50");
   CompositeFrame();
-  EXPECT_EQ(DocumentLifecycle::kPaintClean,
-            frame_document->Lifecycle().GetState());
 
-  // A hit test will not force a complete lifecycle update.
-  WebView().HitTestResultAt(gfx::Point());
-  EXPECT_EQ(DocumentLifecycle::kPaintClean,
-            frame_document->Lifecycle().GetState());
+  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+    EXPECT_EQ(DocumentLifecycle::kPaintClean,
+              frame_document->Lifecycle().GetState());
+
+    // A hit test will not force a complete lifecycle update.
+    WebView().HitTestResultAt(gfx::Point());
+    EXPECT_EQ(DocumentLifecycle::kPaintClean,
+              frame_document->Lifecycle().GetState());
+  } else {
+    // Resets to kLayoutClean due to a call to SetNeedsCompositingInputsUpdate.
+    // TODO(chrishtr): fix this test by manually resetting to
+    // kVisualUpdatePending before call to CompositeFrame.
+    EXPECT_EQ(DocumentLifecycle::kLayoutClean,
+              frame_document->Lifecycle().GetState());
+
+    // A hit test will not force a complete lifecycle update.
+    WebView().HitTestResultAt(gfx::Point());
+    EXPECT_EQ(DocumentLifecycle::kLayoutClean,
+              frame_document->Lifecycle().GetState());
+  }
 }
 
 TEST_P(FrameThrottlingTest, UnthrottlingFrameSchedulesAnimation) {
diff --git a/third_party/blink/renderer/core/script/classic_pending_script.cc b/third_party/blink/renderer/core/script/classic_pending_script.cc
index bb708c0..2fc22472 100644
--- a/third_party/blink/renderer/core/script/classic_pending_script.cc
+++ b/third_party/blink/renderer/core/script/classic_pending_script.cc
@@ -331,9 +331,10 @@
   DCHECK(GetResource()->IsLoaded());
   ScriptResource* resource = ToScriptResource(GetResource());
 
+  auto* fetcher = GetElement()->GetDocument().ContextDocument()->Fetcher();
   // If the MIME check fails, which is considered as load failure.
   if (!AllowedByNosniff::MimeTypeAsScript(
-          GetElement()->GetDocument().ContextDocument()->Fetcher()->Context(),
+          fetcher->Context(), fetcher->GetConsoleLogger(),
           resource->GetResponse(), AllowedByNosniff::MimeTypeCheck::kLax,
           false)) {
     return nullptr;
diff --git a/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc b/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
index 833466a..03b5004 100644
--- a/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
+++ b/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
@@ -177,7 +177,8 @@
     return;
   }
   if (!AllowedByNosniff::MimeTypeAsScript(
-          fetch_client_settings_object_fetcher_->Context(), response,
+          fetch_client_settings_object_fetcher_->Context(),
+          fetch_client_settings_object_fetcher_->GetConsoleLogger(), response,
           fetch_client_settings_object_fetcher_->Context()
               .GetFetchClientSettingsObject()
               ->MimeTypeCheckForClassicWorkerScript(),
@@ -189,8 +190,8 @@
   if (is_top_level_script_) {
     String error = CheckSameOriginEnforcement(url_, response);
     if (!error.IsNull()) {
-      fetch_client_settings_object_fetcher_->Context().AddErrorConsoleMessage(
-          error, FetchContext::kSecuritySource);
+      fetch_client_settings_object_fetcher_->GetConsoleLogger()
+          ->AddErrorMessage(ConsoleLogger::Source::kSecurity, error);
       NotifyError();
       return;
     }
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 740540f5..09d67dc 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
@@ -139,8 +139,9 @@
                 *this, web_worker_fetch_context_, subresource_filter_,
                 *fetch_client_settings_object)
           : nullptr;
-  ResourceFetcher* resource_fetcher =
-      MakeGarbageCollected<ResourceFetcher>(fetch_context);
+  ConsoleLogger* console_logger = this;
+  auto* resource_fetcher =
+      MakeGarbageCollected<ResourceFetcher>(fetch_context, console_logger);
   if (IsContextPaused())
     resource_fetcher->SetDefersLoading(true);
   resource_fetchers_.insert(resource_fetcher);
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
index 8a738487..e594ea1 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
@@ -31,11 +31,11 @@
 #include <memory>
 #include <utility>
 
+#include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
 #include "third_party/blink/public/platform/interface_provider.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -189,10 +189,14 @@
   return true;
 }
 
-WebIDBFactory* IDBFactory::GetFactory() {
+WebIDBFactory* IDBFactory::GetFactory(ExecutionContext* execution_context) {
   if (!web_idb_factory_) {
     mojom::blink::IDBFactoryPtrInfo web_idb_factory_host_info;
-    Platform::Current()->GetInterfaceProvider()->GetInterface(
+    service_manager::InterfaceProvider* interface_provider =
+        execution_context->GetInterfaceProvider();
+    if (!interface_provider)
+      return nullptr;
+    interface_provider->GetInterface(
         mojo::MakeRequest(&web_idb_factory_host_info));
     web_idb_factory_ = std::make_unique<WebIDBFactoryImpl>(
         std::move(web_idb_factory_host_info));
@@ -213,12 +217,16 @@
     return resolver->Promise();
   }
 
-  GetFactory()->GetDatabaseInfo(
+  ExecutionContext* execution_context = ExecutionContext::From(script_state);
+  WebIDBFactory* factory = GetFactory(execution_context);
+  if (!factory) {
+    exception_state.ThrowSecurityError("An internal error occurred.");
+    resolver->Reject();
+    return resolver->Promise();
+  }
+  factory->GetDatabaseInfo(
       WebIDBGetDBNamesCallbacksImpl::Create(resolver).release(),
-      WebSecurityOrigin(
-          ExecutionContext::From(script_state)->GetSecurityOrigin()),
-      ExecutionContext::From(script_state)
-          ->GetTaskRunner(TaskType::kInternalIndexedDB));
+      execution_context->GetTaskRunner(TaskType::kInternalIndexedDB));
   ScriptPromise promise = resolver->Promise();
   return promise;
 }
@@ -252,12 +260,15 @@
     return request;
   }
 
-  GetFactory()->GetDatabaseNames(
+  ExecutionContext* execution_context = ExecutionContext::From(script_state);
+  WebIDBFactory* factory = GetFactory(execution_context);
+  if (!factory) {
+    exception_state.ThrowSecurityError("An internal error occurred.");
+    return nullptr;
+  }
+  factory->GetDatabaseNames(
       request->CreateWebCallbacks().release(),
-      WebSecurityOrigin(
-          ExecutionContext::From(script_state)->GetSecurityOrigin()),
-      ExecutionContext::From(script_state)
-          ->GetTaskRunner(TaskType::kInternalIndexedDB));
+      execution_context->GetTaskRunner(TaskType::kInternalIndexedDB));
   return request;
 }
 
@@ -307,13 +318,16 @@
     return request;
   }
 
-  GetFactory()->Open(
-      name, version, transaction_id, request->CreateWebCallbacks().release(),
-      database_callbacks->CreateWebCallbacks().release(),
-      WebSecurityOrigin(
-          ExecutionContext::From(script_state)->GetSecurityOrigin()),
-      ExecutionContext::From(script_state)
-          ->GetTaskRunner(TaskType::kInternalIndexedDB));
+  ExecutionContext* execution_context = ExecutionContext::From(script_state);
+  WebIDBFactory* factory = GetFactory(execution_context);
+  if (!factory) {
+    exception_state.ThrowSecurityError("An internal error occurred.");
+    return nullptr;
+  }
+  factory->Open(name, version, transaction_id,
+                request->CreateWebCallbacks().release(),
+                database_callbacks->CreateWebCallbacks().release(),
+                execution_context->GetTaskRunner(TaskType::kInternalIndexedDB));
   return request;
 }
 
@@ -373,13 +387,15 @@
     return request;
   }
 
-  GetFactory()->DeleteDatabase(
-      name, request->CreateWebCallbacks().release(),
-      WebSecurityOrigin(
-          ExecutionContext::From(script_state)->GetSecurityOrigin()),
-      force_close,
-      ExecutionContext::From(script_state)
-          ->GetTaskRunner(TaskType::kInternalIndexedDB));
+  ExecutionContext* execution_context = ExecutionContext::From(script_state);
+  WebIDBFactory* factory = GetFactory(execution_context);
+  if (!factory) {
+    exception_state.ThrowSecurityError("An internal error occurred.");
+    return nullptr;
+  }
+  factory->DeleteDatabase(
+      name, request->CreateWebCallbacks().release(), force_close,
+      execution_context->GetTaskRunner(TaskType::kInternalIndexedDB));
   return request;
 }
 
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory.h b/third_party/blink/renderer/modules/indexeddb/idb_factory.h
index 68b8234..4648549 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_factory.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_factory.h
@@ -78,7 +78,7 @@
   ScriptPromise GetDatabaseInfo(ScriptState*, ExceptionState&);
 
  private:
-  WebIDBFactory* GetFactory();
+  WebIDBFactory* GetFactory(ExecutionContext* execution_context);
 
   IDBOpenDBRequest* OpenInternal(ScriptState*,
                                  const String& name,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc b/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc
index 67e96ba..bd69c07 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc
@@ -65,7 +65,7 @@
       SecurityOrigin::Create(KURL("https://example.com")));
   std::unique_ptr<MockWebIDBFactory> web_factory = MockWebIDBFactory::Create();
   std::unique_ptr<WebIDBCallbacks> callbacks;
-  EXPECT_CALL(*web_factory, GetDatabaseInfo(testing::_, testing::_, testing::_))
+  EXPECT_CALL(*web_factory, GetDatabaseInfo(testing::_, testing::_))
       .Times(1)
       .WillOnce(SaveUniquePointer<0>(&callbacks));
   IDBFactory* factory = IDBFactory::CreateForTest(std::move(web_factory));
@@ -100,7 +100,7 @@
       SecurityOrigin::Create(KURL("https://example.com")));
   std::unique_ptr<MockWebIDBFactory> web_factory = MockWebIDBFactory::Create();
   std::unique_ptr<WebIDBCallbacks> callbacks;
-  EXPECT_CALL(*web_factory, GetDatabaseInfo(testing::_, testing::_, testing::_))
+  EXPECT_CALL(*web_factory, GetDatabaseInfo(testing::_, testing::_))
       .Times(1)
       .WillOnce(SaveUniquePointer<0>(&callbacks));
   IDBFactory* factory = IDBFactory::CreateForTest(std::move(web_factory));
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h
index 21166b9..37cbc7c 100644
--- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h
+++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_factory.h
@@ -9,7 +9,6 @@
 #include <memory>
 
 #include "base/single_thread_task_runner.h"
-#include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/renderer/modules/indexeddb/web_idb_factory.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 
@@ -25,7 +24,6 @@
 
 class WebIDBCallbacks;
 class WebIDBDatabaseCallbacks;
-class WebSecurityOrigin;
 
 class MockWebIDBFactory : public testing::StrictMock<blink::WebIDBFactory> {
  public:
@@ -33,26 +31,22 @@
 
   static std::unique_ptr<MockWebIDBFactory> Create();
 
-  MOCK_METHOD3(GetDatabaseInfo,
+  MOCK_METHOD2(GetDatabaseInfo,
                void(WebIDBCallbacks*,
-                    const WebSecurityOrigin&,
                     scoped_refptr<base::SingleThreadTaskRunner>));
-  MOCK_METHOD3(GetDatabaseNames,
+  MOCK_METHOD2(GetDatabaseNames,
                void(WebIDBCallbacks*,
-                    const WebSecurityOrigin&,
                     scoped_refptr<base::SingleThreadTaskRunner>));
-  MOCK_METHOD7(Open,
+  MOCK_METHOD6(Open,
                void(const WTF::String& name,
                     long long version,
                     long long transaction_id,
                     WebIDBCallbacks*,
                     WebIDBDatabaseCallbacks*,
-                    const WebSecurityOrigin&,
                     scoped_refptr<base::SingleThreadTaskRunner>));
-  MOCK_METHOD5(DeleteDatabase,
+  MOCK_METHOD4(DeleteDatabase,
                void(const WTF::String& name,
                     WebIDBCallbacks*,
-                    const WebSecurityOrigin&,
                     bool force_close,
                     scoped_refptr<base::SingleThreadTaskRunner>));
 
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_factory.h b/third_party/blink/renderer/modules/indexeddb/web_idb_factory.h
index a02875b..2252937 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_factory.h
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_factory.h
@@ -44,29 +44,24 @@
 
 class WebIDBCallbacks;
 class WebIDBDatabaseCallbacks;
-class WebSecurityOrigin;
 
 class MODULES_EXPORT WebIDBFactory {
  public:
   virtual ~WebIDBFactory() = default;
 
   virtual void GetDatabaseInfo(WebIDBCallbacks*,
-                               const WebSecurityOrigin&,
                                scoped_refptr<base::SingleThreadTaskRunner>) = 0;
   virtual void GetDatabaseNames(
       WebIDBCallbacks*,
-      const WebSecurityOrigin&,
       scoped_refptr<base::SingleThreadTaskRunner>) = 0;
   virtual void Open(const WTF::String& name,
                     long long version,
                     long long transaction_id,
                     WebIDBCallbacks*,
                     WebIDBDatabaseCallbacks*,
-                    const WebSecurityOrigin&,
                     scoped_refptr<base::SingleThreadTaskRunner>) = 0;
   virtual void DeleteDatabase(const WTF::String& name,
                               WebIDBCallbacks*,
-                              const WebSecurityOrigin&,
                               bool force_close,
                               scoped_refptr<base::SingleThreadTaskRunner>) = 0;
 };
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc
index a1442a50..d40c9531 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc
@@ -6,7 +6,6 @@
 
 #include "base/memory/ptr_util.h"
 #include "mojo/public/cpp/bindings/strong_associated_binding.h"
-#include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h"
 #include "third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -21,24 +20,20 @@
 
 void WebIDBFactoryImpl::GetDatabaseInfo(
     WebIDBCallbacks* callbacks,
-    const WebSecurityOrigin& origin,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
       base::WrapUnique(callbacks), IndexedDBCallbacksImpl::kNoTransaction,
       nullptr);
-  factory_->GetDatabaseInfo(GetCallbacksProxy(std::move(callbacks_impl)),
-                            origin);
+  factory_->GetDatabaseInfo(GetCallbacksProxy(std::move(callbacks_impl)));
 }
 
 void WebIDBFactoryImpl::GetDatabaseNames(
     WebIDBCallbacks* callbacks,
-    const WebSecurityOrigin& origin,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
       base::WrapUnique(callbacks), IndexedDBCallbacksImpl::kNoTransaction,
       nullptr);
-  factory_->GetDatabaseNames(GetCallbacksProxy(std::move(callbacks_impl)),
-                             origin);
+  factory_->GetDatabaseNames(GetCallbacksProxy(std::move(callbacks_impl)));
 }
 
 void WebIDBFactoryImpl::Open(
@@ -47,7 +42,6 @@
     long long transaction_id,
     WebIDBCallbacks* callbacks,
     WebIDBDatabaseCallbacks* database_callbacks,
-    const WebSecurityOrigin& origin,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
       base::WrapUnique(callbacks), transaction_id, nullptr);
@@ -57,21 +51,20 @@
   DCHECK(!name.IsNull());
   factory_->Open(GetCallbacksProxy(std::move(callbacks_impl)),
                  GetDatabaseCallbacksProxy(std::move(database_callbacks_impl)),
-                 origin, name, version, transaction_id);
+                 name, version, transaction_id);
 }
 
 void WebIDBFactoryImpl::DeleteDatabase(
     const String& name,
     WebIDBCallbacks* callbacks,
-    const WebSecurityOrigin& origin,
     bool force_close,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>(
       base::WrapUnique(callbacks), IndexedDBCallbacksImpl::kNoTransaction,
       nullptr);
   DCHECK(!name.IsNull());
-  factory_->DeleteDatabase(GetCallbacksProxy(std::move(callbacks_impl)), origin,
-                           name, force_close);
+  factory_->DeleteDatabase(GetCallbacksProxy(std::move(callbacks_impl)), name,
+                           force_close);
 }
 
 mojom::blink::IDBCallbacksAssociatedPtrInfo
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h b/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h
index cd093901..2b05d6c3 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h
@@ -18,7 +18,6 @@
 }
 
 namespace blink {
-class WebSecurityOrigin;
 
 class WebIDBFactoryImpl : public blink::WebIDBFactory {
  public:
@@ -28,23 +27,19 @@
   // See WebIDBFactory.h for documentation on these functions.
   void GetDatabaseInfo(
       blink::WebIDBCallbacks* callbacks,
-      const blink::WebSecurityOrigin& origin,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
   void GetDatabaseNames(
       blink::WebIDBCallbacks* callbacks,
-      const blink::WebSecurityOrigin& origin,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
   void Open(const WTF::String& name,
             long long version,
             long long transaction_id,
             blink::WebIDBCallbacks* callbacks,
             blink::WebIDBDatabaseCallbacks* databaseCallbacks,
-            const blink::WebSecurityOrigin& origin,
             scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
   void DeleteDatabase(
       const WTF::String& name,
       blink::WebIDBCallbacks* callbacks,
-      const blink::WebSecurityOrigin& origin,
       bool force_close,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) override;
 
diff --git a/third_party/blink/renderer/platform/heap/heap_compact.cc b/third_party/blink/renderer/platform/heap/heap_compact.cc
index 53eb750..6e3559e4 100644
--- a/third_party/blink/renderer/platform/heap/heap_compact.cc
+++ b/third_party/blink/renderer/platform/heap/heap_compact.cc
@@ -368,14 +368,10 @@
     return force_compaction_gc_;
   }
 
-  // TODO(keishi): Should be enable after fixing the crashes.
-  if (marking_type == BlinkGC::kIncrementalMarking)
-    return false;
-
-  // TODO(harukamt): Add kIncrementalIdleGC and kIncrementalV8FollowupGC when we
-  // enable heap compaction for incremental marking.
   if (reason != BlinkGC::GCReason::kIdleGC &&
       reason != BlinkGC::GCReason::kPreciseGC &&
+      reason != BlinkGC::GCReason::kIncrementalIdleGC &&
+      reason != BlinkGC::GCReason::kIncrementalV8FollowupGC &&
       reason != BlinkGC::GCReason::kForcedGC)
     return false;
 
diff --git a/third_party/blink/renderer/platform/loader/BUILD.gn b/third_party/blink/renderer/platform/loader/BUILD.gn
index c9ac86e..f4e0c9e 100644
--- a/third_party/blink/renderer/platform/loader/BUILD.gn
+++ b/third_party/blink/renderer/platform/loader/BUILD.gn
@@ -27,6 +27,7 @@
     "fetch/cached_metadata_handler.h",
     "fetch/client_hints_preferences.cc",
     "fetch/client_hints_preferences.h",
+    "fetch/console_logger.h",
     "fetch/fetch_client_settings_object.h",
     "fetch/fetch_client_settings_object_snapshot.cc",
     "fetch/fetch_client_settings_object_snapshot.h",
diff --git a/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc b/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc
index 7a147ad..dcc87ed 100644
--- a/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc
+++ b/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/platform/loader/allowed_by_nosniff.h"
 
+#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
 #include "third_party/blink/renderer/platform/network/http_names.h"
@@ -130,6 +131,7 @@
 }  // namespace
 
 bool AllowedByNosniff::MimeTypeAsScript(FetchContext& context,
+                                        ConsoleLogger* console_logger,
                                         const ResourceResponse& response,
                                         MimeTypeCheck mime_type_check_mode,
                                         bool is_worker_global_scope) {
@@ -150,12 +152,12 @@
   if (!(ParseContentTypeOptionsHeader(response.HttpHeaderField(
             http_names::kXContentTypeOptions)) != kContentTypeOptionsNosniff ||
         MIMETypeRegistry::IsSupportedJavaScriptMIMEType(mime_type))) {
-    context.AddErrorConsoleMessage(
+    console_logger->AddErrorMessage(
+        ConsoleLogger::Source::kSecurity,
         "Refused to execute script from '" +
             response.CurrentRequestUrl().ElidedString() +
             "' because its MIME type ('" + mime_type +
-            "') is not executable, and strict MIME type checking is enabled.",
-        FetchContext::kSecuritySource);
+            "') is not executable, and strict MIME type checking is enabled.");
     return false;
   }
 
@@ -190,11 +192,11 @@
   if (!allow || warn) {
     const char* msg =
         allow ? "Deprecated: Future versions will refuse" : "Refused";
-    context.AddErrorConsoleMessage(
+    console_logger->AddErrorMessage(
+        ConsoleLogger::Source::kSecurity,
         String() + msg + " to execute script from '" +
             response.CurrentRequestUrl().ElidedString() +
-            "' because its MIME type ('" + mime_type + "') is not executable.",
-        FetchContext::kSecuritySource);
+            "' because its MIME type ('" + mime_type + "') is not executable.");
   }
   return allow;
 }
diff --git a/third_party/blink/renderer/platform/loader/allowed_by_nosniff.h b/third_party/blink/renderer/platform/loader/allowed_by_nosniff.h
index 2e9e029..c73a8ed 100644
--- a/third_party/blink/renderer/platform/loader/allowed_by_nosniff.h
+++ b/third_party/blink/renderer/platform/loader/allowed_by_nosniff.h
@@ -9,6 +9,7 @@
 
 namespace blink {
 
+class ConsoleLogger;
 class FetchContext;
 class ResourceResponse;
 
@@ -17,6 +18,7 @@
   enum class MimeTypeCheck { kStrict, kLax };
 
   static bool MimeTypeAsScript(FetchContext&,
+                               ConsoleLogger*,
                                const ResourceResponse&,
                                MimeTypeCheck mime_type_check_mode,
                                bool is_worker_global_scope);
diff --git a/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc b/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc
index e8fd293..ee99b5e5 100644
--- a/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc
+++ b/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc
@@ -6,6 +6,7 @@
 
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
 #include "third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -33,7 +34,16 @@
         std::move(security_origin));
   }
   MOCK_CONST_METHOD1(CountUsage, void(mojom::WebFeature));
-  MOCK_CONST_METHOD2(AddErrorConsoleMessage, void(const String&, LogSource));
+};
+
+class MockConsoleLogger : public GarbageCollectedFinalized<MockConsoleLogger>,
+                          public ConsoleLogger {
+  USING_GARBAGE_COLLECTED_MIXIN(MockConsoleLogger);
+
+ public:
+  MOCK_METHOD2(AddInfoMessage, void(Source, const String&));
+  MOCK_METHOD2(AddWarningMessage, void(Source, const String&));
+  MOCK_METHOD2(AddErrorMessage, void(Source, const String&));
 };
 
 }  // namespace
@@ -94,6 +104,8 @@
     const KURL url("https://bla.com/");
     auto* context =
         CountUsageMockFetchContext::Create(SecurityOrigin::Create(url));
+    Persistent<MockConsoleLogger> logger =
+        MakeGarbageCollected<MockConsoleLogger>();
     ResourceResponse response(url);
     response.SetHTTPHeaderField("Content-Type", testcase.mimetype);
 
@@ -103,18 +115,18 @@
     RuntimeEnabledFeatures::SetWorkerNosniffWarnEnabled(false);
     EXPECT_CALL(*context, CountUsage(_)).Times(::testing::AnyNumber());
     if (!testcase.allowed)
-      EXPECT_CALL(*context, AddErrorConsoleMessage(_, _));
+      EXPECT_CALL(*logger, AddErrorMessage(_, _));
     EXPECT_EQ(testcase.allowed,
-              AllowedByNosniff::MimeTypeAsScript(*context, response,
+              AllowedByNosniff::MimeTypeAsScript(*context, logger, response,
                                                  MimeTypeCheck::kLax, false));
     ::testing::Mock::VerifyAndClear(context);
 
     EXPECT_CALL(*context, CountUsage(_)).Times(::testing::AnyNumber());
     if (!testcase.allowed)
-      EXPECT_CALL(*context, AddErrorConsoleMessage(_, _));
+      EXPECT_CALL(*logger, AddErrorMessage(_, _));
     EXPECT_EQ(testcase.allowed,
               AllowedByNosniff::MimeTypeAsScript(
-                  *context, response, MimeTypeCheck::kStrict, false));
+                  *context, logger, response, MimeTypeCheck::kStrict, false));
     ::testing::Mock::VerifyAndClear(context);
 
     // Nosniff worker blocked: Workers follow the 'strict_allow' setting.
@@ -124,18 +136,18 @@
 
     EXPECT_CALL(*context, CountUsage(_)).Times(::testing::AnyNumber());
     if (!testcase.allowed)
-      EXPECT_CALL(*context, AddErrorConsoleMessage(_, _));
+      EXPECT_CALL(*logger, AddErrorMessage(_, _));
     EXPECT_EQ(testcase.allowed,
-              AllowedByNosniff::MimeTypeAsScript(*context, response,
+              AllowedByNosniff::MimeTypeAsScript(*context, logger, response,
                                                  MimeTypeCheck::kLax, false));
     ::testing::Mock::VerifyAndClear(context);
 
     EXPECT_CALL(*context, CountUsage(_)).Times(::testing::AnyNumber());
     if (!testcase.strict_allowed)
-      EXPECT_CALL(*context, AddErrorConsoleMessage(_, _));
+      EXPECT_CALL(*logger, AddErrorMessage(_, _));
     EXPECT_EQ(testcase.strict_allowed,
               AllowedByNosniff::MimeTypeAsScript(
-                  *context, response, MimeTypeCheck::kStrict, false));
+                  *context, logger, response, MimeTypeCheck::kStrict, false));
     ::testing::Mock::VerifyAndClear(context);
 
     // Nosniff 'legacy', but with warnings. The allowed setting follows the
@@ -145,18 +157,18 @@
 
     EXPECT_CALL(*context, CountUsage(_)).Times(::testing::AnyNumber());
     if (!testcase.allowed)
-      EXPECT_CALL(*context, AddErrorConsoleMessage(_, _));
+      EXPECT_CALL(*logger, AddErrorMessage(_, _));
     EXPECT_EQ(testcase.allowed,
-              AllowedByNosniff::MimeTypeAsScript(*context, response,
+              AllowedByNosniff::MimeTypeAsScript(*context, logger, response,
                                                  MimeTypeCheck::kLax, false));
     ::testing::Mock::VerifyAndClear(context);
 
     EXPECT_CALL(*context, CountUsage(_)).Times(::testing::AnyNumber());
     if (!testcase.strict_allowed)
-      EXPECT_CALL(*context, AddErrorConsoleMessage(_, _));
+      EXPECT_CALL(*logger, AddErrorMessage(_, _));
     EXPECT_EQ(testcase.allowed,
               AllowedByNosniff::MimeTypeAsScript(
-                  *context, response, MimeTypeCheck::kStrict, false));
+                  *context, logger, response, MimeTypeCheck::kStrict, false));
     ::testing::Mock::VerifyAndClear(context);
   }
 }
@@ -199,14 +211,16 @@
                                     << "\n  webfeature: " << testcase.expected);
     auto* context = CountUsageMockFetchContext::Create(
         SecurityOrigin::Create(KURL(testcase.origin)));
+    Persistent<MockConsoleLogger> logger =
+        MakeGarbageCollected<MockConsoleLogger>();
     ResourceResponse response(KURL(testcase.url));
     response.SetHTTPHeaderField("Content-Type", testcase.mimetype);
 
     EXPECT_CALL(*context, CountUsage(testcase.expected));
     EXPECT_CALL(*context, CountUsage(::testing::Ne(testcase.expected)))
         .Times(::testing::AnyNumber());
-    AllowedByNosniff::MimeTypeAsScript(*context, response, MimeTypeCheck::kLax,
-                                       false);
+    AllowedByNosniff::MimeTypeAsScript(*context, logger, response,
+                                       MimeTypeCheck::kLax, false);
     ::testing::Mock::VerifyAndClear(context);
   }
 }
@@ -238,15 +252,16 @@
 
   for (auto& testcase : data) {
     auto* context = CountUsageMockFetchContext::Create(nullptr);
-    EXPECT_CALL(*context, AddErrorConsoleMessage(_, _))
-        .Times(::testing::AnyNumber());
+    Persistent<MockConsoleLogger> logger =
+        MakeGarbageCollected<MockConsoleLogger>();
+    EXPECT_CALL(*logger, AddErrorMessage(_, _)).Times(::testing::AnyNumber());
     SCOPED_TRACE(testing::Message() << "\n  url: " << testcase.url
                                     << "\n  allowed: " << testcase.allowed);
     ResourceResponse response(KURL(testcase.url));
     response.SetHTTPHeaderField("Content-Type", "invalid");
     response.SetHTTPHeaderField("X-Content-Type-Options", "nosniff");
     EXPECT_EQ(testcase.allowed,
-              AllowedByNosniff::MimeTypeAsScript(*context, response,
+              AllowedByNosniff::MimeTypeAsScript(*context, logger, response,
                                                  MimeTypeCheck::kLax, false));
   }
 }
diff --git a/third_party/blink/renderer/platform/loader/fetch/console_logger.h b/third_party/blink/renderer/platform/loader/fetch/console_logger.h
new file mode 100644
index 0000000..680acc9
--- /dev/null
+++ b/third_party/blink/renderer/platform/loader/fetch/console_logger.h
@@ -0,0 +1,54 @@
+// 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_PLATFORM_LOADER_FETCH_CONSOLE_LOGGER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_CONSOLE_LOGGER_H_
+
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+// A pure virtual interface for console logging.
+class PLATFORM_EXPORT ConsoleLogger : public GarbageCollectedMixin {
+ public:
+  // This enum corresponds to blink::MessageSource. Expand this enum when
+  // needed.
+  enum class Source {
+    kScript,
+    kSecurity,
+    kOther,
+  };
+
+  ConsoleLogger() = default;
+  virtual ~ConsoleLogger() = default;
+
+  // Add a message with "info" level.
+  virtual void AddInfoMessage(Source source, const String& message) = 0;
+
+  // Add a message with "warning" level.
+  virtual void AddWarningMessage(Source source, const String& message) = 0;
+
+  // Add a message with "error" level.
+  virtual void AddErrorMessage(Source source, const String& message) = 0;
+};
+
+class PLATFORM_EXPORT NullConsoleLogger final
+    : public GarbageCollected<NullConsoleLogger>,
+      public ConsoleLogger {
+  USING_GARBAGE_COLLECTED_MIXIN(NullConsoleLogger);
+
+ public:
+  NullConsoleLogger() = default;
+  ~NullConsoleLogger() override = default;
+
+  void AddInfoMessage(Source source, const String&) override {}
+  void AddWarningMessage(Source source, const String&) override {}
+  void AddErrorMessage(Source source, const String&) override {}
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_CONSOLE_LOGGER_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 42f935a..a2e54d2 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
@@ -99,18 +99,11 @@
                                            ResourceType,
                                            const FetchInitiatorInfo&) {}
 
-void FetchContext::DispatchDidLoadResourceFromMemoryCache(
-    unsigned long,
-    const ResourceRequest&,
-    const ResourceResponse&) {}
-
-void FetchContext::DispatchDidReceiveResponse(
-    unsigned long,
-    const ResourceResponse&,
-    network::mojom::RequestContextFrameType FrameType,
-    mojom::RequestContextType,
-    Resource*,
-    ResourceResponseType) {}
+void FetchContext::DispatchDidReceiveResponse(unsigned long,
+                                              const ResourceRequest&,
+                                              const ResourceResponse&,
+                                              Resource*,
+                                              ResourceResponseType) {}
 
 void FetchContext::DispatchDidReceiveData(unsigned long, const char*, size_t) {}
 
@@ -142,12 +135,6 @@
 
 void FetchContext::AddResourceTiming(const ResourceTimingInfo&) {}
 
-void FetchContext::AddInfoConsoleMessage(const String&, LogSource) const {}
-
-void FetchContext::AddWarningConsoleMessage(const String&, LogSource) const {}
-
-void FetchContext::AddErrorConsoleMessage(const String&, LogSource) const {}
-
 const SecurityOrigin* FetchContext::GetSecurityOrigin() const {
   return GetFetchClientSettingsObject()->GetSecurityOrigin();
 }
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 fd6abc5..e80a076a 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -88,18 +88,6 @@
   FetchContext(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
                FetchClientSettingsObject&);
 
-  // This enum corresponds to blink::MessageSource. We have this not to
-  // introduce any dependency to core/.
-  //
-  // Currently only kJSMessageSource, kSecurityMessageSource and
-  // kOtherMessageSource are used, but not to impress readers that
-  // AddConsoleMessage() call from FetchContext() should always use them,
-  // which is not true, we ask users of the Add.*ConsoleMessage() methods
-  // to explicitly specify the MessageSource to use.
-  //
-  // Extend this when needed.
-  enum LogSource { kJSSource, kSecuritySource, kOtherSource };
-
   static FetchContext& NullInstance(
       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
 
@@ -139,17 +127,16 @@
       const ResourceResponse& redirect_response,
       ResourceType,
       const FetchInitiatorInfo& = FetchInitiatorInfo());
-  virtual void DispatchDidLoadResourceFromMemoryCache(unsigned long identifier,
-                                                      const ResourceRequest&,
-                                                      const ResourceResponse&);
   enum class ResourceResponseType { kNotFromMemoryCache, kFromMemoryCache };
-  virtual void DispatchDidReceiveResponse(
-      unsigned long identifier,
-      const ResourceResponse&,
-      network::mojom::RequestContextFrameType,
-      mojom::RequestContextType,
-      Resource*,
-      ResourceResponseType);
+  // |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(unsigned long identifier,
+                                          const ResourceRequest& request,
+                                          const ResourceResponse& response,
+                                          Resource* resource,
+                                          ResourceResponseType);
   virtual void DispatchDidReceiveData(unsigned long identifier,
                                       const char* data,
                                       size_t data_length);
@@ -212,10 +199,6 @@
     return false;
   }
 
-  virtual void AddInfoConsoleMessage(const String&, LogSource) const;
-  virtual void AddWarningConsoleMessage(const String&, LogSource) const;
-  virtual void AddErrorConsoleMessage(const String&, LogSource) const;
-
   virtual void CountUsage(mojom::WebFeature) const = 0;
   virtual void CountDeprecation(mojom::WebFeature) const = 0;
 
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 cbd7ccc..7b6de04f 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -44,6 +44,7 @@
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
 #include "third_party/blink/renderer/platform/loader/cors/cors.h"
+#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
 #include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
@@ -371,7 +372,12 @@
 }
 
 ResourceFetcher::ResourceFetcher(FetchContext* new_context)
+    : ResourceFetcher(new_context, MakeGarbageCollected<NullConsoleLogger>()) {}
+
+ResourceFetcher::ResourceFetcher(FetchContext* new_context,
+                                 ConsoleLogger* console_logger)
     : context_(new_context),
+      console_logger_(console_logger),
       scheduler_(ResourceLoadScheduler::Create(&Context())),
       archive_(Context().IsMainFrame() ? nullptr : Context().Archive()),
       resource_timing_report_timer_(
@@ -383,6 +389,7 @@
       allow_stale_resources_(false),
       image_fetched_(false),
       stale_while_revalidate_enabled_(false) {
+  DCHECK(console_logger);
   InstanceCounters::IncrementCounter(InstanceCounters::kResourceFetcherCounter);
   if (IsMainThread())
     MainThreadFetchersSet().insert(this);
@@ -460,22 +467,14 @@
 void ResourceFetcher::DidLoadResourceFromMemoryCache(
     unsigned long identifier,
     Resource* resource,
-    const ResourceRequest& original_resource_request) {
-  ResourceRequest resource_request(resource->Url());
-  resource_request.SetFrameType(original_resource_request.GetFrameType());
-  resource_request.SetRequestContext(
-      original_resource_request.GetRequestContext());
-  if (original_resource_request.IsAdResource())
-    resource_request.SetIsAdResource();
+    const ResourceRequest& original_request) {
+  ResourceRequest request = original_request;
 
-  Context().DispatchDidLoadResourceFromMemoryCache(identifier, resource_request,
-                                                   resource->GetResponse());
   Context().DispatchWillSendRequest(
-      identifier, resource_request, ResourceResponse() /* redirects */,
+      identifier, request, ResourceResponse() /* redirects */,
       resource->GetType(), resource->Options().initiator_info);
   Context().DispatchDidReceiveResponse(
-      identifier, resource->GetResponse(), resource_request.GetFrameType(),
-      resource_request.GetRequestContext(), resource,
+      identifier, request, resource->GetResponse(), resource,
       FetchContext::ResourceResponseType::kFromMemoryCache);
 
   if (resource->EncodedSize() > 0) {
@@ -1187,8 +1186,8 @@
       builder.Append("due to different image placeholder policies.");
       break;
   }
-  Context().AddWarningConsoleMessage(builder.ToString(),
-                                     FetchContext::kOtherSource);
+  console_logger_->AddWarningMessage(ConsoleLogger::Source::kOther,
+                                     builder.ToString());
 }
 
 void ResourceFetcher::InsertAsPreloadIfNecessary(Resource* resource,
@@ -1473,6 +1472,7 @@
   scheduler_->Shutdown();
   ClearPreloads(ResourceFetcher::kClearAllPreloads);
   context_ = Context().Detach();
+  console_logger_ = MakeGarbageCollected<NullConsoleLogger>();
 
   // Make sure the only requests still going are keepalive requests.
   // Callers of ClearContext() should be calling StopFetching() prior
@@ -1549,19 +1549,19 @@
 ArchiveResource* ResourceFetcher::CreateArchive(Resource* resource) {
   // Only the top-frame can load MHTML.
   if (!Context().IsMainFrame()) {
-    Context().AddErrorConsoleMessage(
+    console_logger_->AddErrorMessage(
+        ConsoleLogger::Source::kScript,
         "Attempted to load a multipart archive into an subframe: " +
-            resource->Url().GetString(),
-        FetchContext::kJSSource);
+            resource->Url().GetString());
     return nullptr;
   }
 
   archive_ = MHTMLArchive::Create(resource->Url(), resource->ResourceBuffer());
   if (!archive_) {
     // Log if attempting to load an invalid archive resource.
-    Context().AddErrorConsoleMessage(
-        "Malformed multipart archive: " + resource->Url().GetString(),
-        FetchContext::kJSSource);
+    console_logger_->AddErrorMessage(
+        ConsoleLogger::Source::kScript,
+        "Malformed multipart archive: " + resource->Url().GetString());
     return nullptr;
   }
 
@@ -1963,6 +1963,7 @@
 
 void ResourceFetcher::Trace(blink::Visitor* visitor) {
   visitor->Trace(context_);
+  visitor->Trace(console_logger_);
   visitor->Trace(scheduler_);
   visitor->Trace(archive_);
   visitor->Trace(loaders_);
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 7865062f..42b277f3 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -50,6 +50,7 @@
 namespace blink {
 
 class ArchiveResource;
+class ConsoleLogger;
 class MHTMLArchive;
 class KURL;
 class Resource;
@@ -75,6 +76,7 @@
 
  public:
   ResourceFetcher(FetchContext*);
+  ResourceFetcher(FetchContext*, ConsoleLogger*);
   virtual ~ResourceFetcher();
   virtual void Trace(blink::Visitor*);
 
@@ -107,6 +109,11 @@
 
   FetchContext& Context() const;
   void ClearContext();
+  ConsoleLogger* GetConsoleLogger() { return console_logger_; }
+  void SetConsoleLogger(ConsoleLogger* console_logger) {
+    DCHECK(console_logger);
+    console_logger_ = console_logger;
+  }
 
   int BlockingRequestCount() const;
   int NonblockingRequestCount() const;
@@ -286,6 +293,7 @@
   void RevalidateStaleResource(Resource* stale_resource);
 
   Member<FetchContext> context_;
+  Member<ConsoleLogger> console_logger_;
   Member<ResourceLoadScheduler> scheduler_;
 
   DocumentResourceMap cached_resources_map_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc
index 83d42a3..7e0c48c 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc
@@ -10,6 +10,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/scheduler/public/aggregated_metric_reporter.h"
@@ -414,6 +415,7 @@
                                     ThrottleOption option,
                                     ResourceLoadPriority priority,
                                     int intra_priority,
+                                    ConsoleLogger* console_logger,
                                     ResourceLoadScheduler::ClientId* id) {
   *id = GenerateClientId();
   if (is_shutdown_)
@@ -442,13 +444,13 @@
       pending_request_map_.find(client_id) != pending_request_map_.end()) {
     // Note that this doesn't show the message when a frame is stopped (vs.
     // this DOES when throttled).
-    context_->AddInfoConsoleMessage(
+    console_logger->AddInfoMessage(
+        ConsoleLogger::Source::kOther,
         "Active resource loading counts reached a per-frame limit while the "
         "tab was in background. Network requests will be delayed until a "
         "previous loading finishes, or the tab is brought to the foreground. "
         "See https://www.chromestatus.com/feature/5527160148197376 for more "
-        "details",
-        FetchContext::kOtherSource);
+        "details");
     omit_console_log_ = true;
   }
 }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h
index 7f327a2..7ad4814 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h
@@ -17,6 +17,7 @@
 
 namespace blink {
 
+class ConsoleLogger;
 class FetchContext;
 
 // Client interface to use the throttling/scheduling functionality that
@@ -172,6 +173,7 @@
                ThrottleOption,
                ResourceLoadPriority,
                int intra_priority,
+               ConsoleLogger* console_logger,
                ClientId*);
 
   // Updates the priority information of the given client. This function may
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
index 09ccb75..8d3942e 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
@@ -6,6 +6,7 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
 #include "third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
@@ -92,7 +93,7 @@
   ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client1, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id1);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id1);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
   EXPECT_FALSE(client1->WasRun());
 
@@ -102,7 +103,7 @@
   ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client2, ThrottleOption::kStoppable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id2);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id2);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
   EXPECT_FALSE(client2->WasRun());
 
@@ -112,7 +113,7 @@
   ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client3, ThrottleOption::kCanNotBeStoppedOrThrottled,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id3);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id3);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
   EXPECT_TRUE(client3->WasRun());
 
@@ -140,7 +141,7 @@
   ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client1, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id1);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id1);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
   EXPECT_FALSE(client1->WasRun());
 
@@ -150,7 +151,7 @@
   ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client2, ThrottleOption::kStoppable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id2);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id2);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
   EXPECT_TRUE(client2->WasRun());
 
@@ -160,7 +161,7 @@
   ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client3, ThrottleOption::kCanNotBeStoppedOrThrottled,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id3);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id3);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
   EXPECT_TRUE(client3->WasRun());
 
@@ -184,7 +185,7 @@
   ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client1, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id1);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id1);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
   EXPECT_TRUE(client1->WasRun());
 
@@ -193,7 +194,7 @@
   ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client2, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id2);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id2);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
   EXPECT_FALSE(client2->WasRun());
 
@@ -202,7 +203,7 @@
   ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client3, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id3);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id3);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
   EXPECT_FALSE(client3->WasRun());
 
@@ -210,7 +211,7 @@
   ResourceLoadScheduler::ClientId id4 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client4, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id4);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id4);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id4);
   EXPECT_FALSE(client4->WasRun());
 
@@ -236,7 +237,7 @@
   ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client1, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id1);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id1);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
   EXPECT_TRUE(client1->WasRun());
 
@@ -244,7 +245,7 @@
   ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client2, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id2);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id2);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
   EXPECT_FALSE(client2->WasRun());
 
@@ -252,7 +253,7 @@
   ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client3, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id3);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id3);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
   EXPECT_FALSE(client3->WasRun());
 
@@ -273,7 +274,7 @@
   ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client1, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id1);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id1);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
   EXPECT_TRUE(client1->WasRun());
 
@@ -281,7 +282,7 @@
   ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client2, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id2);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id2);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
   EXPECT_FALSE(client2->WasRun());
 
@@ -289,7 +290,7 @@
   ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client3, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kMedium, 0 /* intra_priority */,
-                       &id3);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id3);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
   EXPECT_FALSE(client3->WasRun());
 
@@ -318,28 +319,28 @@
   ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client1, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kLowest, 10 /* intra_priority */,
-                       &id1);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id1);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
 
   MockClient* client2 = MakeGarbageCollected<MockClient>();
   ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client2, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kLow, 1 /* intra_priority */,
-                       &id2);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id2);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
 
   MockClient* client3 = MakeGarbageCollected<MockClient>();
   ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client3, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kLow, 3 /* intra_priority */,
-                       &id3);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id3);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
 
   MockClient* client4 = MakeGarbageCollected<MockClient>();
   ResourceLoadScheduler::ClientId id4 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client4, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kHigh, 0 /* intra_priority */,
-                       &id4);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id4);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id4);
 
   EXPECT_FALSE(client1->WasRun());
@@ -393,13 +394,13 @@
   ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client1, ThrottleOption::kStoppable,
                        ResourceLoadPriority::kLowest, 10 /* intra_priority */,
-                       &id1);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id1);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
 
   ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client2, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kHigh, 1 /* intra_priority */,
-                       &id2);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id2);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
 
   EXPECT_FALSE(client1->WasRun());
@@ -434,21 +435,21 @@
   ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client1, ThrottleOption::kStoppable,
                        ResourceLoadPriority::kLowest, 10 /* intra_priority */,
-                       &id1);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id1);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
 
   MockClient* client2 = MakeGarbageCollected<MockClient>();
   ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client2, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kHigh, 1 /* intra_priority */,
-                       &id2);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id2);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
 
   MockClient* client3 = MakeGarbageCollected<MockClient>();
   ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client3, ThrottleOption::kStoppable,
                        ResourceLoadPriority::kLowest, 10 /* intra_priority */,
-                       &id3);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id3);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
 
   EXPECT_FALSE(client1->WasRun());
@@ -485,21 +486,21 @@
   ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client1, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kLowest, 0 /* intra_priority */,
-                       &id1);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id1);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
 
   MockClient* client2 = MakeGarbageCollected<MockClient>();
   ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client2, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kLow, 5 /* intra_priority */,
-                       &id2);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id2);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
 
   MockClient* client3 = MakeGarbageCollected<MockClient>();
   ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client3, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kLow, 10 /* intra_priority */,
-                       &id3);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id3);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
 
   EXPECT_FALSE(client1->WasRun());
@@ -538,28 +539,28 @@
   ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client1, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kLowest, 0 /* intra_priority */,
-                       &id1);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id1);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
 
   MockClient* client2 = MakeGarbageCollected<MockClient>();
   ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client2, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kLowest, 0 /* intra_priority */,
-                       &id2);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id2);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
 
   MockClient* client3 = MakeGarbageCollected<MockClient>();
   ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client3, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kLowest, 0 /* intra_priority */,
-                       &id3);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id3);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
 
   MockClient* client4 = MakeGarbageCollected<MockClient>();
   ResourceLoadScheduler::ClientId id4 = ResourceLoadScheduler::kInvalidClientId;
   Scheduler()->Request(client4, ThrottleOption::kThrottleable,
                        ResourceLoadPriority::kLowest, 0 /* intra_priority */,
-                       &id4);
+                       MakeGarbageCollected<NullConsoleLogger>(), &id4);
   EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id4);
 
   Scheduler()->SetPriority(id2, ResourceLoadPriority::kLow, 0);
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 3b26ad9e..01b0324 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -46,6 +46,7 @@
 #include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
 #include "third_party/blink/renderer/platform/loader/cors/cors.h"
 #include "third_party/blink/renderer/platform/loader/cors/cors_error_string.h"
+#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
@@ -415,7 +416,8 @@
         ResourceLoadScheduler::ThrottleOption::kCanNotBeStoppedOrThrottled;
   }
   scheduler_->Request(this, throttle_option, request.Priority(),
-                      request.IntraPriorityValue(), &scheduler_client_id_);
+                      request.IntraPriorityValue(), GetConsoleLogger(),
+                      &scheduler_client_id_);
 }
 
 void ResourceLoader::Run() {
@@ -922,8 +924,7 @@
 
   // FrameType never changes during the lifetime of a request.
   Context().DispatchDidReceiveResponse(
-      resource_->Identifier(), response_to_pass, initial_request.GetFrameType(),
-      request_context, resource_,
+      resource_->Identifier(), initial_request, response_to_pass, resource_,
       FetchContext::ResourceResponseType::kNotFromMemoryCache);
 
   // When streaming, unpause virtual time early to prevent deadlocking
@@ -1070,12 +1071,12 @@
     return;
   }
   if (error.CorsErrorStatus()) {
-    Context().AddErrorConsoleMessage(
+    GetConsoleLogger()->AddErrorMessage(
+        ConsoleLogger::Source::kScript,
         cors::GetErrorString(
             *error.CorsErrorStatus(), resource_->GetResourceRequest().Url(),
             resource_->LastResourceRequest().Url(), *resource_->GetOrigin(),
-            resource_->GetType(), resource_->Options().initiator_info.name),
-        FetchContext::kJSSource);
+            resource_->GetType(), resource_->Options().initiator_info.name));
   }
 
   Release(ResourceLoadScheduler::ReleaseOption::kReleaseAndSchedule,
@@ -1232,9 +1233,13 @@
   }
 }
 
+ConsoleLogger* ResourceLoader::GetConsoleLogger() {
+  return fetcher_->GetConsoleLogger();
+}
+
 base::Optional<ResourceRequestBlockedReason>
 ResourceLoader::CheckResponseNosniff(mojom::RequestContextType request_context,
-                                     const ResourceResponse& response) const {
+                                     const ResourceResponse& response) {
   bool sniffing_allowed =
       ParseContentTypeOptionsHeader(response.HttpHeaderField(
           http_names::kXContentTypeOptions)) != kContentTypeOptionsNosniff;
@@ -1244,13 +1249,13 @@
   String mime_type = response.HttpContentType();
   if (request_context == mojom::RequestContextType::STYLE &&
       !MIMETypeRegistry::IsSupportedStyleSheetMIMEType(mime_type)) {
-    Context().AddErrorConsoleMessage(
+    GetConsoleLogger()->AddErrorMessage(
+        ConsoleLogger::Source::kSecurity,
         "Refused to apply style from '" +
             response.CurrentRequestUrl().ElidedString() +
             "' because its MIME type ('" + mime_type + "') " +
             "is not a supported stylesheet MIME type, and strict MIME checking "
-            "is enabled.",
-        FetchContext::kSecuritySource);
+            "is enabled.");
     return ResourceRequestBlockedReason::kContentType;
   }
   // TODO(mkwst): Move the 'nosniff' bit of 'AllowedByNosniff::MimeTypeAsScript'
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
index c49cf21..02b5f64 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
@@ -47,6 +47,7 @@
 
 namespace blink {
 
+class ConsoleLogger;
 class FetchContext;
 class ResourceError;
 class ResourceFetcher;
@@ -182,10 +183,11 @@
   void FinishedCreatingBlob(const scoped_refptr<BlobDataHandle>&);
 
   bool GetCorsFlag() const { return resource_->Options().cors_flag; }
+  ConsoleLogger* GetConsoleLogger();
 
   base::Optional<ResourceRequestBlockedReason> CheckResponseNosniff(
       mojom::RequestContextType,
-      const ResourceResponse&) const;
+      const ResourceResponse&);
 
   bool ShouldCheckCorsInResourceLoader() const;
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.cc b/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
index 388a37f..5ad7c46 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
@@ -427,10 +427,6 @@
   ct_policy_compliance_ = compliance;
 }
 
-bool ResourceResponse::IsOpaqueResponseFromServiceWorker() const {
-  return IsCorsCrossOrigin() && WasFetchedViaServiceWorker();
-}
-
 AtomicString ResourceResponse::ConnectionInfoString() const {
   std::string connection_info_string =
       net::HttpResponseInfo::ConnectionInfoToString(connection_info_);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.h b/third_party/blink/renderer/platform/loader/fetch/resource_response.h
index f825c87..d35e413 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_response.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.h
@@ -151,8 +151,8 @@
   // https://fetch.spec.whatwg.org/#concept-request-current-url
   //
   // Beware that this might not be the same the response URL, so it is usually
-  // incorrect to use this in security checks. Use FetchResponseType() to
-  // determine origin sameness.
+  // incorrect to use this in security checks. Use GetType() to determine origin
+  // sameness.
   //
   // Specifically, if a service worker responded to the request for this
   // resource, it may have fetched an entirely different URL and responded with
@@ -174,6 +174,9 @@
 
   // The response URL of this resource. Corresponds to:
   // https://fetch.spec.whatwg.org/#concept-response-url
+  //
+  // This returns the same URL as CurrentRequestUrl() unless a service worker
+  // responded to the request. See the comments for that function.
   KURL ResponseUrl() const;
 
   const AtomicString& MimeType() const;
@@ -310,7 +313,6 @@
   void SetType(network::mojom::FetchResponseType value) {
     response_type_ = value;
   }
-  bool IsOpaqueResponseFromServiceWorker() const;
   // https://html.spec.whatwg.org/#cors-same-origin
   bool IsCorsSameOrigin() const {
     return network::cors::IsCorsSameOriginResponseType(response_type_);
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
index 78ac91b..efd48d8 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -6,7 +6,6 @@
 Bug(none) editing/input [ Skip ]
 Bug(none) external/wpt [ Skip ]
 Bug(none) http/tests/devtools [ Skip ]
-Bug(none) media/ [ Skip ]
 Bug(none) printing/ [ Skip ]
 Bug(none) scrollbars/ [ Skip ]
 Bug(none) scrollingcoordinator/ [ Skip ]
@@ -14,6 +13,7 @@
 Bug(none) transforms/ [ Skip ]
 
 Bug(none) virtual/android/ [ Skip ]
+Bug(none) virtual/bidi-caret-affinity/ [ Skip ]
 Bug(none) virtual/exotic-color-space/ [ Skip ]
 Bug(none) virtual/gpu/ [ Skip ]
 Bug(none) virtual/gpu-rasterization/ [ Skip ]
@@ -199,6 +199,7 @@
 Bug(none) inspector-protocol/dom/dom-setInspectModeEnabled.js [ Crash ]
 Bug(none) inspector-protocol/layers/paint-profiler.js [ Failure ]
 Bug(none) inspector-protocol/layers/get-layers.js [ Timeout ]
+crbug.com/912357 media/video-object-fit.html [ Failure ]
 Bug(none) paint/pagination/pagination-change-clip-crash.html [ Failure ]
 Bug(none) virtual/sampling-heap-profiler/inspector-protocol/memory/sampling-native-profile-blink-gc.js [ Failure ]
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index aa04cf8..749d13b 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1821,7 +1821,6 @@
 ### True failures start from here
 
 ### virtual/bidi-caret-affinity/editing/selection/
-crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/caret-bidi-first-and-last-letters.html [ Failure ]
 crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/css-pseudo-element.html [ Failure ]
 crbug.com/894651 virtual/bidi-caret-affinity/editing/selection/select-bidi-run.html [ Failure ]
 
@@ -5750,7 +5749,7 @@
 crbug.com/914441 external/wpt/user-timing/mark-measure-feature-detection.html [ Failure ]
 
 # The below is only supported with network service.
-crbug.com/896924 http/tests/inspector-protocol/network/interception-multiclient.js [ Skip ]
+crbug.com/896924 http/tests/inspector-protocol/network/interception-multiclient.js [ Timeout Failure ]
 crbug.com/899303 http/tests/inspector-protocol/fetch/fetch-basic.js [ Timeout ]
 crbug.com/899303 http/tests/inspector-protocol/fetch/fetch-renderer.js [ Timeout ]
 
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https.html
index 1f523e5..0617ac11 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-interfaces.https.html
@@ -10,7 +10,7 @@
 'use strict';
 
 function doTest(idl, dom) {
-  var idl_array = new IdlArray();
+  const idl_array = new IdlArray();
   idl_array.add_untested_idls('interface Navigator {};');
   idl_array.add_untested_idls('interface EventTarget {};');
   idl_array.add_untested_idls('dictionary PermissionDescriptor {};');
@@ -25,7 +25,7 @@
 };
 
 function fetchText(url) {
-  return fetch(url).then((response) => response.text());
+  return fetch(url).then(response => response.text());
 }
 
 promise_test(() => {
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html
index 3126655..8d7cf99e 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html
@@ -5,7 +5,7 @@
 <script src="/resources/testharnessreport.js"></script>
 <script>
 
-test(function() {
+test(() => {
   assert_not_equals(navigator.clipboard, undefined);
   assert_true(navigator.clipboard instanceof Clipboard);
   assert_equals(navigator.clipboard, navigator.clipboard);
@@ -13,23 +13,23 @@
 
 /* clipboard.write() */
 
-promise_test(function() {
-  var dt = new DataTransfer();
+promise_test(() => {
+  const dt = new DataTransfer();
   dt.items.add("Howdy", "text/plain");
   return navigator.clipboard.write(dt);
 }, "navigator.clipboard.write(DataTransfer) succeeds");
 
-promise_test(function(t) {
+promise_test(t => {
   return promise_rejects(t, new TypeError(),
                          navigator.clipboard.write());
 }, "navigator.clipboard.write() fails (expect DataTransfer)");
 
-promise_test(function(t) {
+promise_test(t => {
   return promise_rejects(t, new TypeError(),
                          navigator.clipboard.write(null));
 }, "navigator.clipboard.write(null) fails (expect DataTransfer)");
 
-promise_test(function(t) {
+promise_test(t => {
   return promise_rejects(t, new TypeError(),
                          navigator.clipboard.write("Bad string"));
 }, "navigator.clipboard.write(DOMString) fails (expect DataTransfer)");
@@ -37,11 +37,11 @@
 
 /* clipboard.writeText() */
 
-promise_test(function() {
+promise_test(() => {
   return navigator.clipboard.writeText("New clipboard text");
 }, "navigator.clipboard.writeText(DOMString) succeeds");
 
-promise_test(function(t) {
+promise_test(t => {
   return promise_rejects(t, new TypeError(),
                          navigator.clipboard.writeText());
 }, "navigator.clipboard.writeText() fails (expect DOMString)");
@@ -49,9 +49,9 @@
 
 /* clipboard.read() */
 
-promise_test(function() {
+promise_test(() => {
   return navigator.clipboard.read()
-    .then(function(result) {
+    .then(result => {
       assert_true(result instanceof DataTransfer);
     });
 }, "navigator.clipboard.read() succeeds");
@@ -59,9 +59,9 @@
 
 /* clipboard.readText() */
 
-promise_test(function() {
+promise_test(() => {
   return navigator.clipboard.readText()
-    .then(function(result) {
+    .then(result => {
       assert_equals(typeof result, "string");
     });
 }, "navigator.clipboard.readText() succeeds");
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-dttext-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-dttext-manual.https.html
index 75cf3a3..2930b471 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-dttext-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-dttext-manual.https.html
@@ -4,7 +4,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
-promise_test(async (t) => {
+promise_test(async t => {
   const input = "Clipboard write (dt/text) -> read (dt/text) test data";
   const dt = new DataTransfer();
   dt.items.add(input, "text/plain");
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-text-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-text-manual.https.html
index 3e68f9a5..1b178696 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-text-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-text-manual.https.html
@@ -4,7 +4,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
-promise_test(async (t) => {
+promise_test(async t => {
   const input = "Clipboard write (dt/text) -> readText test data";
   const dt = new DataTransfer();
   dt.items.add(input, "text/plain");
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-dttext-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-dttext-manual.https.html
index 232e144..9f524b9 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-dttext-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-dttext-manual.https.html
@@ -4,7 +4,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
-promise_test(async (t) => {
+promise_test(async t => {
   const input = "Clipboard writeText -> read (dt/text) test data";
 
   await navigator.clipboard.writeText(input);
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html
index 783683e..3a3922e 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html
@@ -4,7 +4,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
-promise_test(async (t) => {
+promise_test(async t => {
   const input = "Clipboard writeText -> readText test data";
 
   await navigator.clipboard.writeText(input);
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/clipboard-events-synthetic.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/clipboard-events-synthetic.html
index 00f32ae..fa40d8c 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/clipboard-events-synthetic.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/clipboard-events-synthetic.html
@@ -9,20 +9,20 @@
 <script>
 const EVENTS = [ 'copy', 'cut', 'paste' ];
 
-EVENTS.forEach(name => {
-  function testEvent(name, init, composed_flag_expectation, name) {
-    async_test(function(test) {
-      document.addEventListener(name, test.step_func_done((e) => {
-        assert_false(e.isTrusted, `synthetic ${name} event is untrusted`);
-        assert_equals(e.composed, composed_flag_expectation,
-                      `composed flag should be ${composed_flag_expectation}`);
-      }));
-      let event = new ClipboardEvent(name, init);
-      document.dispatchEvent(event);
-    }, name);
-  }
+function testEvent(eventName, init, composed_flag_expectation, testName) {
+  async_test(test => {
+    document.addEventListener(eventName, test.step_func_done(e => {
+      assert_false(e.isTrusted, `synthetic ${eventName} event is untrusted`);
+      assert_equals(e.composed, composed_flag_expectation,
+                    `composed flag should be ${composed_flag_expectation}`);
+    }));
+    const event = new ClipboardEvent(eventName, init);
+    document.dispatchEvent(event);
+  }, testName);
+}
 
-  testEvent(name, { bubbles: true, cancellable: true}, false,
+EVENTS.forEach(name => {
+  testEvent(name, { bubbles: true, cancellable: true }, false,
             `Unspecified synthetic ${name} event should not be composed.`);
   testEvent(name, { bubbles: true, cancelable: true, composed: true }, true,
             `Synthetic ${name} event can be explicitly composed.`);
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/linebox/line-height-129.xht b/third_party/blink/web_tests/external/wpt/css/CSS2/linebox/line-height-129.xht
index b4250b88..78f90fb 100644
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/linebox/line-height-129.xht
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/linebox/line-height-129.xht
@@ -41,7 +41,7 @@
 
   <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 
-  <div><img src="support/green_box.png" alt="Image download support must be enabled" /></div>
+  <div id="target"><img src="support/green_box.png" alt="Image download support must be enabled" /></div>
 
  </body>
 </html>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/media/video-zoom-controls-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/media/video-zoom-controls-expected.png
new file mode 100644
index 0000000..0bdfbb3
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/media/video-zoom-controls-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/paint/invalidation/box/invalidate-box-shadow-currentColor.html b/third_party/blink/web_tests/paint/invalidation/box/invalidate-box-shadow-currentColor.html
index 1f49ab4..b329e3b 100644
--- a/third_party/blink/web_tests/paint/invalidation/box/invalidate-box-shadow-currentColor.html
+++ b/third_party/blink/web_tests/paint/invalidation/box/invalidate-box-shadow-currentColor.html
@@ -14,4 +14,4 @@
     target.style.color = 'green';
 }
 window.onload = runRepaintAndPixelTest;
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/blink/web_tests/paint/invalidation/table/border-collapse-change-collapse-to-separate.html b/third_party/blink/web_tests/paint/invalidation/table/border-collapse-change-collapse-to-separate.html
index fd698901..8a09e35 100644
--- a/third_party/blink/web_tests/paint/invalidation/table/border-collapse-change-collapse-to-separate.html
+++ b/third_party/blink/web_tests/paint/invalidation/table/border-collapse-change-collapse-to-separate.html
@@ -11,4 +11,4 @@
     <td style="border: solid 2px yellow; width: 100px; height: 100px;"></td>
     <td style="border: solid 3px blue; width: 100px; height: 100px;"></td>
   </tr>
-</table>
\ No newline at end of file
+</table>
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.png b/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.png
index abc3b025..7487e84 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.png
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt
index c38f8e727d..31b9093f 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt
@@ -34,7 +34,7 @@
         },
         {
           "object": "LayoutTextControl TEXTAREA id='editor'",
-          "rect": [9, 11, 124, 13],
+          "rect": [9, 11, 139, 13],
           "reason": "chunk appeared"
         }
       ]
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/offset-change-wrong-invalidation-with-float-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/offset-change-wrong-invalidation-with-float-expected.txt
index b25c390..ec9a727 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/offset-change-wrong-invalidation-with-float-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/offset-change-wrong-invalidation-with-float-expected.txt
@@ -27,7 +27,7 @@
     {
       "name": "LayoutListItem (floating) LI id='watches'",
       "position": [31, 42],
-      "bounds": [24, 18]
+      "bounds": [7, 18]
     },
     {
       "name": "LayoutInline (relative positioned) SPAN id='placeholder'",
@@ -38,7 +38,7 @@
     {
       "name": "LayoutListItem (relative positioned) (floating) LI id='menu'",
       "position": [31, 42],
-      "bounds": [17, 18],
+      "bounds": [7, 18],
       "paintInvalidations": [
         {
           "object": "LayoutListMarker (anonymous)",
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/offset-change-wrong-invalidation-with-float-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/offset-change-wrong-invalidation-with-float-expected.txt
index aa9f41c6..b013a4b 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/offset-change-wrong-invalidation-with-float-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/offset-change-wrong-invalidation-with-float-expected.txt
@@ -27,7 +27,7 @@
     {
       "name": "LayoutListItem (floating) LI id='watches'",
       "position": [30, 44],
-      "bounds": [25, 19]
+      "bounds": [7, 19]
     },
     {
       "name": "LayoutInline (relative positioned) SPAN id='placeholder'",
@@ -38,7 +38,7 @@
     {
       "name": "LayoutListItem (relative positioned) (floating) LI id='menu'",
       "position": [30, 44],
-      "bounds": [18, 19],
+      "bounds": [7, 19],
       "paintInvalidations": [
         {
           "object": "LayoutListMarker (anonymous)",
diff --git a/third_party/polymer/README.chromium b/third_party/polymer/README.chromium
index 4ad09c1..f6d300f 100644
--- a/third_party/polymer/README.chromium
+++ b/third_party/polymer/README.chromium
@@ -40,8 +40,6 @@
   Polymer's <paper-ripple>.
 - Removed CSS properties that are not needed in Chromium using
   css_strip_prefixes.py script.
-- For paper-slider, added mixin for the pin text and removed custom focus change
-  handler code which was hiding ripples for pointer interactions.
 - Bundled and minified Polymer 2 with minify_polymer.py, since Polymer 2 repo
   does not distribute minified files (unlike Polymer 1).
 - Note that the Polymer 2 bundle does not include dir-mixin.html which is
diff --git a/third_party/polymer/v1_0/bower.json b/third_party/polymer/v1_0/bower.json
index f5e36eff..9a4fbe2 100644
--- a/third_party/polymer/v1_0/bower.json
+++ b/third_party/polymer/v1_0/bower.json
@@ -37,7 +37,6 @@
     "paper-input": "PolymerElements/paper-input#2.2.2",
     "paper-progress": "PolymerElements/paper-progress#2.0.1",
     "paper-ripple": "PolymerElements/paper-ripple#2.0.1",
-    "paper-slider": "PolymerElements/paper-slider#2.0.2",
     "paper-spinner": "PolymerElements/paper-spinner#2.0.0",
     "paper-styles": "PolymerElements/paper-styles#2.1.0",
     "paper-tabs": "PolymerElements/paper-tabs#2.0.0",
diff --git a/third_party/polymer/v1_0/chromium.patch b/third_party/polymer/v1_0/chromium.patch
index 3e4c74f..71b0017 100644
--- a/third_party/polymer/v1_0/chromium.patch
+++ b/third_party/polymer/v1_0/chromium.patch
@@ -121,67 +121,6 @@
 \ No newline at end of file
 +</body></html>
 \ No newline at end of file
-diff --git a/components-chromium/paper-slider/paper-slider.html b/components-chromium/paper-slider/paper-slider.html
-index 233808adc822..4117f3590a61 100644
---- a/components-chromium/paper-slider/paper-slider.html
-+++ b/components-chromium/paper-slider/paper-slider.html
-@@ -12,7 +12,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
- <link rel="import" href="../iron-form-element-behavior/iron-form-element-behavior.html">
- <link rel="import" href="../iron-range-behavior/iron-range-behavior.html">
- <link rel="import" href="../paper-behaviors/paper-inky-focus-behavior.html">
--<link rel="import" href="../paper-input/paper-input.html">
- <link rel="import" href="../paper-progress/paper-progress.html">
- <link rel="import" href="../paper-styles/color.html">
- 
-@@ -279,6 +278,7 @@ Custom property | Description | Default
- 
-       .pin.expand > .slider-knob > .slider-knob-inner::after {
-         transform: scale(1) translate(0, -17px);
-+        @apply --paper-slider-pin-text;
-       }
- 
-       /* paper-input */
-@@ -330,11 +330,6 @@ Custom property | Description | Default
-           <div class="slider-knob-inner" value$="[[immediateValue]]"></div>
-       </div>
-     </div>
--
--    <template is="dom-if" if="[[editable]]">
--      <paper-input id="input" type="number" step="[[step]]" min="[[min]]" max="[[max]]" class="slider-input" disabled$="[[disabled]]" value="[[immediateValue]]" on-change="_changeValue" on-keydown="_inputKeyDown" no-label-float="">
--      </paper-input>
--    </template>
-   </template>
- 
-   </dom-module>
-diff --git a/components-chromium/paper-slider/paper-slider-extracted.js b/components-chromium/paper-slider/paper-slider-extracted.js
-index 2e63d3731be1..217c7ff1414c 100644
---- a/components-chromium/paper-slider/paper-slider-extracted.js
-+++ b/components-chromium/paper-slider/paper-slider-extracted.js
-@@ -385,24 +385,6 @@ Polymer({
-         this._rippleContainer = this.$.sliderKnob;
-         return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this);
-       },
--
--      // Hide the ripple when user is not interacting with keyboard.
--      // This behavior is different from other ripple-y controls, but is
--      // according to spec: https://www.google.com/design/spec/components/sliders.html
--      _focusedChanged: function(receivedFocusFromKeyboard) {
--        if (receivedFocusFromKeyboard) {
--          this.ensureRipple();
--        }
--        if (this.hasRipple()) {
--          // note, ripple must be un-hidden prior to setting `holdDown`
--          if (receivedFocusFromKeyboard) {
--            this._ripple.style.display = '';
--          } else {
--            this._ripple.style.display = 'none';
--          }
--          this._ripple.holdDown = receivedFocusFromKeyboard;
--        }
--      }
-     });
- 
-     /**
 diff --git a/components-chromium/paper-input/paper-input-container.html b/components-chromium/paper-input/paper-input-container.html
 index 55714942c93c..46fb9adf6a04 100644
 --- a/components-chromium/paper-input/paper-input-container.html
@@ -189,7 +128,7 @@
 @@ -254,8 +254,8 @@ This element is `display:block` by default, but you can set the `inline` attribu
          @apply --paper-input-container-label-floating;
        }
- 
+
 -      :host(:dir(rtl)) .input-content.label-is-floating ::slotted(label),
 -      :host(:dir(rtl)) .input-content.label-is-floating ::slotted(.paper-input-label) {
 +      :host-context([dir="rtl"]) .input-content.label-is-floating ::slotted(label),
@@ -218,6 +157,6 @@
       */
 -    const legacyElementBase = Polymer.DirMixin(Polymer.GestureEventListeners(Polymer.ElementMixin(base)));
 +    const legacyElementBase = Polymer.GestureEventListeners(Polymer.ElementMixin(base));
- 
+
      /**
       * Map of simple names to touch action names
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/BUILD.gn b/third_party/polymer/v1_0/components-chromium/paper-slider/BUILD.gn
deleted file mode 100644
index 2868066..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-slider/BUILD.gn
+++ /dev/null
@@ -1,17 +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.
-#
-# NOTE: Created with generate_gn.py, please do not edit.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_library("paper-slider-extracted") {
-  deps = [
-    "../iron-a11y-keys-behavior:iron-a11y-keys-behavior-extracted",
-    "../iron-form-element-behavior:iron-form-element-behavior-extracted",
-    "../iron-range-behavior:iron-range-behavior-extracted",
-    "../paper-behaviors:paper-inky-focus-behavior-extracted",
-    "../paper-progress:paper-progress-extracted",
-  ]
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/bower.json b/third_party/polymer/v1_0/components-chromium/paper-slider/bower.json
deleted file mode 100644
index 90650495..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-slider/bower.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "name": "paper-slider",
-  "version": "2.0.2",
-  "description": "A material design-style slider",
-  "license": "http://polymer.github.io/LICENSE.txt",
-  "authors": "The Polymer Authors",
-  "keywords": [
-    "web-components",
-    "polymer",
-    "slider",
-    "control"
-  ],
-  "main": "paper-slider.html",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/PolymerElements/paper-slider.git"
-  },
-  "ignore": [],
-  "dependencies": {
-    "polymer": "Polymer/polymer#1.9 - 2",
-    "paper-input": "PolymerElements/paper-input#1 - 2",
-    "paper-progress": "PolymerElements/paper-progress#1 - 2",
-    "iron-flex-layout": "PolymerElements/iron-flex-layout#1 - 2",
-    "paper-styles": "PolymerElements/paper-styles#1 - 2",
-    "iron-behaviors": "PolymerElements/iron-behaviors#1 - 2",
-    "paper-behaviors": "PolymerElements/paper-behaviors#1 - 2",
-    "iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#1 - 2",
-    "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#1 - 2"
-  },
-  "devDependencies": {
-    "iron-component-page": "PolymerElements/iron-component-page#1 - 2",
-    "iron-demo-helpers": "polymerelements/iron-demo-helpers#1 - 2",
-    "iron-test-helpers": "polymerelements/iron-test-helpers#1 - 2",
-    "test-fixture": "PolymerElements/test-fixture#^3.0.0-rc.1",
-    "web-component-tester": "^6.0.0",
-    "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0"
-  },
-  "variants": {
-    "1.x": {
-      "dependencies": {
-        "polymer": "Polymer/polymer#^1.9",
-        "paper-input": "PolymerElements/paper-input#^1.0.0",
-        "paper-progress": "PolymerElements/paper-progress#^1.0.0",
-        "iron-flex-layout": "PolymerElements/iron-flex-layout#^1.0.0",
-        "paper-styles": "PolymerElements/paper-styles#^1.0.0",
-        "iron-behaviors": "PolymerElements/iron-behaviors#^1.0.0",
-        "paper-behaviors": "PolymerElements/paper-behaviors#^1.0.0",
-        "iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#^1.0.0",
-        "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#^1.0.0"
-      },
-      "devDependencies": {
-        "iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
-        "iron-demo-helpers": "polymerelements/iron-demo-helpers#^1.0.0",
-        "test-fixture": "PolymerElements/test-fixture#^1.0.0",
-        "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0",
-        "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0",
-        "web-component-tester": "Polymer/web-component-tester#^4.0.0"
-      },
-      "resolutions": {
-        "webcomponentsjs": "^0.7"
-      }
-    }
-  },
-  "resolutions": {
-    "webcomponentsjs": "^1.0.0"
-  }
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider-extracted.js
deleted file mode 100644
index 217c7ff1..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider-extracted.js
+++ /dev/null
@@ -1,414 +0,0 @@
-Polymer({
-      is: 'paper-slider',
-
-      behaviors: [
-        Polymer.IronA11yKeysBehavior,
-        Polymer.IronFormElementBehavior,
-        Polymer.PaperInkyFocusBehavior,
-        Polymer.IronRangeBehavior
-      ],
-
-      properties: {
-        /**
-         * If true, the slider thumb snaps to tick marks evenly spaced based
-         * on the `step` property value.
-         */
-        snaps: {
-          type: Boolean,
-          value: false,
-          notify: true
-        },
-
-        /**
-         * If true, a pin with numeric value label is shown when the slider thumb
-         * is pressed. Use for settings for which users need to know the exact
-         * value of the setting.
-         */
-        pin: {
-          type: Boolean,
-          value: false,
-          notify: true
-        },
-
-        /**
-         * The number that represents the current secondary progress.
-         */
-        secondaryProgress: {
-          type: Number,
-          value: 0,
-          notify: true,
-          observer: '_secondaryProgressChanged'
-        },
-
-        /**
-         * If true, an input is shown and user can use it to set the slider value.
-         */
-        editable: {
-          type: Boolean,
-          value: false
-        },
-
-        /**
-         * The immediate value of the slider.  This value is updated while the user
-         * is dragging the slider.
-         */
-        immediateValue: {
-          type: Number,
-          value: 0,
-          readOnly: true,
-          notify: true
-        },
-
-        /**
-         * The maximum number of markers
-         */
-        maxMarkers: {
-          type: Number,
-          value: 0,
-          notify: true
-        },
-
-        /**
-         * If true, the knob is expanded
-         */
-        expand: {
-          type: Boolean,
-          value: false,
-          readOnly: true
-        },
-
-        /**
-         * True when the user is dragging the slider.
-         */
-        dragging: {
-          type: Boolean,
-          value: false,
-          readOnly: true
-        },
-
-        transiting: {
-          type: Boolean,
-          value: false,
-          readOnly: true
-        },
-
-        markers: {
-          type: Array,
-          readOnly: true,
-          value: function() {
-              return [];
-          }
-        },
-      },
-
-      observers: [
-        '_updateKnob(value, min, max, snaps, step)',
-        '_valueChanged(value)',
-        '_immediateValueChanged(immediateValue)',
-        '_updateMarkers(maxMarkers, min, max, snaps)'
-      ],
-
-      hostAttributes: {
-        role: 'slider',
-        tabindex: 0
-      },
-
-      keyBindings: {
-        'left': '_leftKey',
-        'right': '_rightKey',
-        'down pagedown home': '_decrementKey',
-        'up pageup end': '_incrementKey'
-      },
-
-      /**
-       * Increases value by `step` but not above `max`.
-       * @method increment
-       */
-      increment: function() {
-        this.value = this._clampValue(this.value + this.step);
-      },
-
-      /**
-       * Decreases value by `step` but not below `min`.
-       * @method decrement
-       */
-      decrement: function() {
-        this.value = this._clampValue(this.value - this.step);
-      },
-
-      _updateKnob: function(value, min, max, snaps, step) {
-        this.setAttribute('aria-valuemin', min);
-        this.setAttribute('aria-valuemax', max);
-        this.setAttribute('aria-valuenow', value);
-
-        this._positionKnob(this._calcRatio(value) * 100);
-      },
-
-      _valueChanged: function() {
-        this.fire('value-change', {composed: true});
-      },
-
-      _immediateValueChanged: function() {
-        if (this.dragging) {
-          this.fire('immediate-value-change', {composed: true});
-        } else {
-          this.value = this.immediateValue;
-        }
-      },
-
-      _secondaryProgressChanged: function() {
-        this.secondaryProgress = this._clampValue(this.secondaryProgress);
-      },
-
-      _expandKnob: function() {
-        this._setExpand(true);
-      },
-
-      _resetKnob: function() {
-        this.cancelDebouncer('expandKnob');
-        this._setExpand(false);
-      },
-
-      _positionKnob: function(ratio) {
-        this._setImmediateValue(this._calcStep(this._calcKnobPosition(ratio)));
-        this._setRatio(this._calcRatio(this.immediateValue) * 100);
-
-        this.$.sliderKnob.style.left = this.ratio + '%';
-        if (this.dragging) {
-          this._knobstartx = (this.ratio * this._w) / 100;
-          this.translate3d(0, 0, 0, this.$.sliderKnob);
-        }
-      },
-
-      _calcKnobPosition: function(ratio) {
-        return (this.max - this.min) * ratio / 100 + this.min;
-      },
-
-      _onTrack: function(event) {
-        event.stopPropagation();
-        switch (event.detail.state) {
-          case 'start':
-            this._trackStart(event);
-            break;
-          case 'track':
-            this._trackX(event);
-            break;
-          case 'end':
-            this._trackEnd();
-            break;
-        }
-      },
-
-      _trackStart: function(event) {
-        this._setTransiting(false);
-        this._w = this.$.sliderBar.offsetWidth;
-        this._x = this.ratio * this._w / 100;
-        this._startx = this._x;
-        this._knobstartx = this._startx;
-        this._minx = - this._startx;
-        this._maxx = this._w - this._startx;
-        this.$.sliderKnob.classList.add('dragging');
-        this._setDragging(true);
-      },
-
-      _trackX: function(event) {
-        if (!this.dragging) {
-          this._trackStart(event);
-        }
-
-        var direction = this._isRTL ? -1 : 1;
-        var dx = Math.min(
-            this._maxx, Math.max(this._minx, event.detail.dx * direction));
-        this._x = this._startx + dx;
-
-        var immediateValue = this._calcStep(this._calcKnobPosition(this._x / this._w * 100));
-        this._setImmediateValue(immediateValue);
-
-        // update knob's position
-        var translateX = ((this._calcRatio(this.immediateValue) * this._w) - this._knobstartx);
-        this.translate3d(translateX + 'px', 0, 0, this.$.sliderKnob);
-      },
-
-      _trackEnd: function() {
-        var s = this.$.sliderKnob.style;
-
-        this.$.sliderKnob.classList.remove('dragging');
-        this._setDragging(false);
-        this._resetKnob();
-        this.value = this.immediateValue;
-
-        s.transform = s.webkitTransform = '';
-
-        this.fire('change', {composed: true});
-      },
-
-      _knobdown: function(event) {
-        this._expandKnob();
-
-        // cancel selection
-        event.preventDefault();
-
-        // set the focus manually because we will called prevent default
-        this.focus();
-      },
-
-      _bardown: function(event) {
-        this._w = this.$.sliderBar.offsetWidth;
-        var rect = this.$.sliderBar.getBoundingClientRect();
-        var ratio = (event.detail.x - rect.left) / this._w * 100;
-        if (this._isRTL) {
-          ratio = 100 - ratio;
-        }
-        var prevRatio = this.ratio;
-
-        this._setTransiting(true);
-
-        this._positionKnob(ratio);
-
-        this.debounce('expandKnob', this._expandKnob, 60);
-
-        // if the ratio doesn't change, sliderKnob's animation won't start
-        // and `_knobTransitionEnd` won't be called
-        // Therefore, we need to manually update the `transiting` state
-
-        if (prevRatio === this.ratio) {
-          this._setTransiting(false);
-        }
-
-        this.async(function() {
-          this.fire('change', {composed: true});
-        });
-
-        // cancel selection
-        event.preventDefault();
-
-        // set the focus manually because we will called prevent default
-        this.focus();
-      },
-
-      _knobTransitionEnd: function(event) {
-        if (event.target === this.$.sliderKnob) {
-          this._setTransiting(false);
-        }
-      },
-
-      _updateMarkers: function(maxMarkers, min, max, snaps) {
-        if (!snaps) {
-          this._setMarkers([]);
-        }
-        var steps = Math.round((max - min) / this.step);
-        if (steps > maxMarkers) {
-          steps = maxMarkers;
-        }
-        if (steps < 0 || !isFinite(steps)) {
-          steps = 0;
-        }
-        this._setMarkers(new Array(steps));
-      },
-
-      _mergeClasses: function(classes) {
-        return Object.keys(classes).filter(
-          function(className) {
-            return classes[className];
-          }).join(' ');
-      },
-
-      _getClassNames: function() {
-        return this._mergeClasses({
-          disabled: this.disabled,
-          pin: this.pin,
-          snaps: this.snaps,
-          ring: this.immediateValue <= this.min,
-          expand: this.expand,
-          dragging: this.dragging,
-          transiting: this.transiting,
-          editable: this.editable
-        });
-      },
-
-      get _isRTL() {
-        if (this.__isRTL === undefined) {
-          this.__isRTL = window.getComputedStyle(this)['direction'] === 'rtl';
-        }
-        return this.__isRTL;
-      },
-
-      _leftKey: function(event) {
-        if (this._isRTL)
-          this._incrementKey(event);
-        else
-          this._decrementKey(event);
-      },
-
-      _rightKey: function(event) {
-        if (this._isRTL)
-          this._decrementKey(event);
-        else
-          this._incrementKey(event);
-      },
-
-      _incrementKey: function(event) {
-        if (!this.disabled) {
-          if (event.detail.key === 'end') {
-            this.value = this.max;
-          } else {
-            this.increment();
-          }
-          this.fire('change');
-          event.preventDefault();
-        }
-      },
-
-      _decrementKey: function(event) {
-        if (!this.disabled) {
-          if (event.detail.key === 'home') {
-            this.value = this.min;
-          } else {
-            this.decrement();
-          }
-          this.fire('change');
-          event.preventDefault();
-        }
-      },
-
-      _changeValue: function(event) {
-        this.value = event.target.value;
-        this.fire('change', {composed: true});
-      },
-
-      _inputKeyDown: function(event) {
-        event.stopPropagation();
-      },
-
-      // create the element ripple inside the `sliderKnob`
-      _createRipple: function() {
-        this._rippleContainer = this.$.sliderKnob;
-        return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this);
-      },
-    });
-
-    /**
-     * Fired when the slider's value changes.
-     *
-     * @event value-change
-     */
-
-    /**
-     * Fired when the slider's immediateValue changes. Only occurs while the
-     * user is dragging.
-     *
-     * To detect changes to immediateValue that happen for any input (i.e.
-     * dragging, tapping, clicking, etc.) listen for immediate-value-changed
-     * instead.
-     *
-     * @event immediate-value-change
-     */
-
-    /**
-     * Fired when the slider's value changes due to user interaction.
-     *
-     * Changes to the slider's value due to changes in an underlying
-     * bound variable will not trigger this event.
-     *
-     * @event change
-     */
\ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html b/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html
deleted file mode 100644
index 42f2bee..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html
+++ /dev/null
@@ -1,336 +0,0 @@
-<!--
-@license
-Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
-This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
-The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
-The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
-Code distributed by Google as part of the polymer project is also
-subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
---><html><head><link rel="import" href="../polymer/polymer.html">
-<link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
-<link rel="import" href="../iron-flex-layout/iron-flex-layout.html">
-<link rel="import" href="../iron-form-element-behavior/iron-form-element-behavior.html">
-<link rel="import" href="../iron-range-behavior/iron-range-behavior.html">
-<link rel="import" href="../paper-behaviors/paper-inky-focus-behavior.html">
-<link rel="import" href="../paper-progress/paper-progress.html">
-<link rel="import" href="../paper-styles/color.html">
-
-<!--
-Material design: [Sliders](https://www.google.com/design/spec/components/sliders.html)
-
-`paper-slider` allows user to select a value from a range of values by
-moving the slider thumb.  The interactive nature of the slider makes it a
-great choice for settings that reflect intensity levels, such as volume,
-brightness, or color saturation.
-
-Example:
-
-    <paper-slider></paper-slider>
-
-Use `min` and `max` to specify the slider range.  Default is 0 to 100.
-
-Example:
-
-    <paper-slider min="10" max="200" value="110"></paper-slider>
-
-### Styling
-
-The following custom properties and mixins are available for styling:
-
-Custom property | Description | Default
-----------------|-------------|----------
-`--paper-slider-container-color` | The background color of the bar | `--paper-grey-400`
-`--paper-slider-bar-color` | The background color of the slider | `transparent`
-`--paper-slider-active-color` | The progress bar color | `--google-blue-700`
-`--paper-slider-secondary-color` | The secondary progress bar color | `--google-blue-300`
-`--paper-slider-knob-color` | The knob color | `--google-blue-700`
-`--paper-slider-disabled-knob-color` | The disabled knob color | `--paper-grey-400`
-`--paper-slider-pin-color` | The pin color | `--google-blue-700`
-`--paper-slider-font-color` | The pin's text color | `#fff`
-`--paper-slider-markers-color` | The snaps markers color | `#000`
-`--paper-slider-disabled-active-color` | The disabled progress bar color | `--paper-grey-400`
-`--paper-slider-disabled-secondary-color` | The disabled secondary progress bar color | `--paper-grey-400`
-`--paper-slider-knob-start-color` | The fill color of the knob at the far left | `transparent`
-`--paper-slider-knob-start-border-color` | The border color of the knob at the far left | `--paper-grey-400`
-`--paper-slider-pin-start-color` | The color of the pin at the far left | `--paper-grey-400`
-`--paper-slider-height` | Height of the progress bar | `2px`
-`--paper-slider-input` | Mixin applied to the input in editable mode | `{}`
-
-@group Paper Elements
-@element paper-slider
-@demo demo/index.html
-@hero hero.svg
--->
-
-</head><body><dom-module id="paper-slider">
-  <template strip-whitespace="">
-    <style>
-      :host {
-        @apply --layout;
-        @apply --layout-justified;
-        @apply --layout-center;
-        width: 200px;
-        cursor: default;
-        user-select: none;
-        -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-        --paper-progress-active-color: var(--paper-slider-active-color, var(--google-blue-700));
-        --paper-progress-secondary-color: var(--paper-slider-secondary-color, var(--google-blue-300));
-        --paper-progress-disabled-active-color: var(--paper-slider-disabled-active-color, var(--paper-grey-400));
-        --paper-progress-disabled-secondary-color: var(--paper-slider-disabled-secondary-color, var(--paper-grey-400));
-        --calculated-paper-slider-height: var(--paper-slider-height, 2px);
-      }
-
-      /* focus shows the ripple */
-      :host(:focus) {
-        outline: none;
-      }
-
-      /** 
-       * NOTE(keanulee): Though :host-context is not universally supported, some pages
-       * still rely on paper-slider being flipped when dir="rtl" is set on body. For full
-       * compatability, dir="rtl" must be explicitly set on paper-slider.
-       */
-      :host-context([dir="rtl"]) #sliderContainer {
-        transform: scaleX(-1);
-      }
-
-      /** 
-       * NOTE(keanulee): This is separate from the rule above because :host-context may
-       * not be recognized.
-       */
-      :host([dir="rtl"]) #sliderContainer {
-        transform: scaleX(-1);
-      }
-
-      /** 
-       * NOTE(keanulee): Needed to override the :host-context rule (where supported)
-       * to support LTR sliders in RTL pages.
-       */
-      :host([dir="ltr"]) #sliderContainer {
-        transform: scaleX(1);
-      }
-
-      #sliderContainer {
-        position: relative;
-        width: 100%;
-        height: calc(30px + var(--calculated-paper-slider-height));
-        margin-left: calc(15px + var(--calculated-paper-slider-height)/2);
-        margin-right: calc(15px + var(--calculated-paper-slider-height)/2);
-      }
-
-      #sliderContainer:focus {
-        outline: 0;
-      }
-
-      #sliderContainer.editable {
-        margin-top: 12px;
-        margin-bottom: 12px;
-      }
-
-      .bar-container {
-        position: absolute;
-        top: 0;
-        bottom: 0;
-        left: 0;
-        right: 0;
-        overflow: hidden;
-      }
-
-      .ring > .bar-container {
-        left: calc(5px + var(--calculated-paper-slider-height)/2);
-        transition: left 0.18s ease;
-      }
-
-      .ring.expand.dragging > .bar-container {
-        transition: none;
-      }
-
-      .ring.expand:not(.pin) > .bar-container {
-        left: calc(8px + var(--calculated-paper-slider-height)/2);
-      }
-
-      #sliderBar {
-        padding: 15px 0;
-        width: 100%;
-        background-color: var(--paper-slider-bar-color, transparent);
-        --paper-progress-container-color: var(--paper-slider-container-color, var(--paper-grey-400));
-        --paper-progress-height: var(--calculated-paper-slider-height);
-      }
-
-      .slider-markers {
-        position: absolute;
-        top: calc(14px + var(--paper-slider-height,2px)/2);
-        height: var(--calculated-paper-slider-height);
-        left: 0;
-        right: -1px;
-        box-sizing: border-box;
-        pointer-events: none;
-        @apply --layout-horizontal;
-      }
-
-      .slider-marker {
-        @apply --layout-flex;
-      }
-      .slider-markers::after,
-      .slider-marker::after {
-        content: "";
-        display: block;
-        margin-left: -1px;
-        width: 2px;
-        height: var(--calculated-paper-slider-height);
-        border-radius: 50%;
-        background-color: var(--paper-slider-markers-color, #000);
-      }
-
-      .slider-knob {
-        position: absolute;
-        left: 0;
-        top: 0;
-        margin-left: calc(-15px - var(--calculated-paper-slider-height)/2);
-        width: calc(30px + var(--calculated-paper-slider-height));
-        height: calc(30px + var(--calculated-paper-slider-height));
-      }
-
-      .transiting > .slider-knob {
-        transition: left 0.08s ease;
-      }
-
-      .slider-knob:focus {
-        outline: none;
-      }
-
-      .slider-knob.dragging {
-        transition: none;
-      }
-
-      .snaps > .slider-knob.dragging {
-        transition: transform 0.08s ease;
-      }
-
-      .slider-knob-inner {
-        margin: 10px;
-        width: calc(100% - 20px);
-        height: calc(100% - 20px);
-        background-color: var(--paper-slider-knob-color, var(--google-blue-700));
-        border: 2px solid var(--paper-slider-knob-color, var(--google-blue-700));
-        border-radius: 50%;
-
-        box-sizing: border-box;
-
-        transition-property: transform, background-color, border;
-        transition-duration: 0.18s;
-        transition-timing-function: ease;
-      }
-
-      .expand:not(.pin) > .slider-knob > .slider-knob-inner {
-        transform: scale(1.5);
-      }
-
-      .ring > .slider-knob > .slider-knob-inner {
-        background-color: var(--paper-slider-knob-start-color, transparent);
-        border: 2px solid var(--paper-slider-knob-start-border-color, var(--paper-grey-400));
-      }
-
-      .slider-knob-inner::before {
-        background-color: var(--paper-slider-pin-color, var(--google-blue-700));
-      }
-
-      .pin > .slider-knob > .slider-knob-inner::before {
-        content: "";
-        position: absolute;
-        top: 0;
-        left: 50%;
-        margin-left: -13px;
-        width: 26px;
-        height: 26px;
-        border-radius: 50% 50% 50% 0;
-
-        transform: rotate(-45deg) scale(0) translate(0);
-      }
-
-      .slider-knob-inner::before,
-      .slider-knob-inner::after {
-        transition: transform .18s ease, background-color .18s ease;
-      }
-
-      .pin.ring > .slider-knob > .slider-knob-inner::before {
-        background-color: var(--paper-slider-pin-start-color, var(--paper-grey-400));
-      }
-
-      .pin.expand > .slider-knob > .slider-knob-inner::before {
-        transform: rotate(-45deg) scale(1) translate(17px, -17px);
-      }
-
-      .pin > .slider-knob > .slider-knob-inner::after {
-        content: attr(value);
-        position: absolute;
-        top: 0;
-        left: 50%;
-        margin-left: -16px;
-        width: 32px;
-        height: 26px;
-        text-align: center;
-        color: var(--paper-slider-font-color, #fff);
-        font-size: 10px;
-
-        transform: scale(0) translate(0);
-      }
-
-      .pin.expand > .slider-knob > .slider-knob-inner::after {
-        transform: scale(1) translate(0, -17px);
-        @apply --paper-slider-pin-text;
-      }
-
-      /* paper-input */
-      .slider-input {
-        width: 50px;
-        overflow: hidden;
-        --paper-input-container-input: {
-          text-align: center;
-        };
-        @apply --paper-slider-input;
-      }
-
-      /* disabled state */
-      #sliderContainer.disabled {
-        pointer-events: none;
-      }
-
-      .disabled > .slider-knob > .slider-knob-inner {
-        background-color: var(--paper-slider-disabled-knob-color, var(--paper-grey-400));
-        border: 2px solid var(--paper-slider-disabled-knob-color, var(--paper-grey-400));
-        transform: scale3d(0.75, 0.75, 1);
-      }
-
-      .disabled.ring > .slider-knob > .slider-knob-inner {
-        background-color: var(--paper-slider-knob-start-color, transparent);
-        border: 2px solid var(--paper-slider-knob-start-border-color, var(--paper-grey-400));
-      }
-
-      paper-ripple {
-        color: var(--paper-slider-knob-color, var(--google-blue-700));
-      }
-    </style>
-
-    <div id="sliderContainer" class$="[[_getClassNames(disabled, pin, snaps, immediateValue, min, expand, dragging, transiting, editable)]]">
-      <div class="bar-container">
-        <paper-progress disabled$="[[disabled]]" id="sliderBar" aria-hidden="true" min="[[min]]" max="[[max]]" step="[[step]]" value="[[immediateValue]]" secondary-progress="[[secondaryProgress]]" on-down="_bardown" on-up="_resetKnob" on-track="_onTrack">
-        </paper-progress>
-      </div>
-
-      <template is="dom-if" if="[[snaps]]">
-        <div class="slider-markers">
-          <template is="dom-repeat" items="[[markers]]">
-            <div class="slider-marker"></div>
-          </template>
-        </div>
-      </template>
-
-      <div id="sliderKnob" class="slider-knob" on-down="_knobdown" on-up="_resetKnob" on-track="_onTrack" on-transitionend="_knobTransitionEnd">
-          <div class="slider-knob-inner" value$="[[immediateValue]]"></div>
-      </div>
-    </div>
-  </template>
-
-  </dom-module>
-<script src="paper-slider-extracted.js"></script></body></html>
\ No newline at end of file
diff --git a/third_party/polymer/v1_0/components_summary.txt b/third_party/polymer/v1_0/components_summary.txt
index 1e72dbf..161a74e9 100644
--- a/third_party/polymer/v1_0/components_summary.txt
+++ b/third_party/polymer/v1_0/components_summary.txt
@@ -208,12 +208,6 @@
 Revision: d0884e8508263e680fd9ee6c11b52c74a416f27f
 Tree link: https://github.com/PolymerElements/paper-ripple/tree/v2.0.1
 
-Name: paper-slider
-Repository: https://github.com/PolymerElements/paper-slider.git
-Tree: v2.0.2
-Revision: 2abcf4052ce04ad450b06f6800f11055cb26ce5b
-Tree link: https://github.com/PolymerElements/paper-slider/tree/v2.0.2
-
 Name: paper-spinner
 Repository: https://github.com/PolymerElements/paper-spinner.git
 Tree: v2.0.0
diff --git a/tools/clang/plugins/tests/enum_max_value.flags b/tools/clang/plugins/tests/enum_max_value.flags
deleted file mode 100644
index 4df8e75..0000000
--- a/tools/clang/plugins/tests/enum_max_value.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xclang -plugin-arg-find-bad-constructs -Xclang check-enum-max-value
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index af06f01..56ad330 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -12941,6 +12941,8 @@
   <int value="17" label="Password entry: Pairing added"/>
   <int value="18" label="Password entry: No screenlock state handler"/>
   <int value="19" label="Password entry: Phone locked and tx power too high"/>
+  <int value="20" label="Password entry: Forced re-auth"/>
+  <int value="21" label="Password entry: Required for login"/>
 </enum>
 
 <enum name="EasyUnlockBluetoothType">
@@ -30336,6 +30338,7 @@
   <int value="-1711283256"
       label="AutofillSaveCardSignInAfterLocalSave:enabled"/>
   <int value="-1710772665" label="disable-my-files-navigation"/>
+  <int value="-1704472714" label="UseMessagesGoogleComDomain:disabled"/>
   <int value="-1703709912" label="enable-new-ntp"/>
   <int value="-1703308540" label="disable-webaudio"/>
   <int value="-1701123067" label="ShowManagedUi:enabled"/>
@@ -32203,6 +32206,7 @@
       label="AutofillLocalCardMigrationShowFeedback:enabled"/>
   <int value="1636962093" label="disable-material-design-ntp"/>
   <int value="1638927687" label="AutofillRichMetadataQueries:disabled"/>
+  <int value="1639190590" label="UseMessagesGoogleComDomain:enabled"/>
   <int value="1639314588" label="LookalikeUrlNavigationSuggestions:disabled"/>
   <int value="1640386037" label="ContextualSuggestionsSlimPeekUI:disabled"/>
   <int value="1646498561" label="OfflineBookmarks:disabled"/>
@@ -53568,10 +53572,6 @@
   <int value="66" label=".gslides"/>
 </enum>
 
-<enum name="ViewsTextServicesContextMenuItem">
-  <int value="0" label="EMOJI"/>
-</enum>
-
 <enum name="VirtualKeyboardContainerType">
   <int value="0" label="FULL_WIDTH"/>
   <int value="1" label="FLOATING"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 9a921f5..ead567c 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -16828,11 +16828,12 @@
   </summary>
 </histogram>
 
-<histogram name="ContextMenu.ViewsTextServices.Used"
-    enum="ViewsTextServicesContextMenuItem" expires_after="2019-06-01">
+<histogram name="ContextMenu.ViewsTextServices.Emoji" enum="Boolean"
+    expires_after="2019-06-01">
   <owner>shend@chromium.org</owner>
   <summary>
-    Number of times each item in the views text services context menu is used.
+    Number of times the emoji item in the views text services context menu is
+    used.
   </summary>
 </histogram>
 
diff --git a/ui/base/ime/ime_bridge.cc b/ui/base/ime/ime_bridge.cc
index f196d8a..5db2a8e4 100644
--- a/ui/base/ime/ime_bridge.cc
+++ b/ui/base/ime/ime_bridge.cc
@@ -9,6 +9,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/singleton.h"
+#include "base/observer_list.h"
 #include "build/build_config.h"
 
 namespace ui {
@@ -18,28 +19,12 @@
 // An implementation of IMEBridge.
 class IMEBridgeImpl : public IMEBridge {
  public:
-#if defined(OS_CHROMEOS)
   IMEBridgeImpl()
-      : input_context_handler_(nullptr),
-        engine_handler_(nullptr),
-        observer_(nullptr),
-        current_input_context_(ui::TEXT_INPUT_TYPE_NONE,
-                               ui::TEXT_INPUT_MODE_DEFAULT,
-                               0,
-                               ui::TextInputClient::FOCUS_REASON_NONE,
-                               false /* should_do_learning */),
-        candidate_window_handler_(nullptr) {}
-#else
-  IMEBridgeImpl()
-      : input_context_handler_(nullptr),
-        engine_handler_(nullptr),
-        observer_(nullptr),
-        current_input_context_(ui::TEXT_INPUT_TYPE_NONE,
+      : current_input_context_(ui::TEXT_INPUT_TYPE_NONE,
                                ui::TEXT_INPUT_MODE_DEFAULT,
                                0,
                                ui::TextInputClient::FOCUS_REASON_NONE,
                                false /* should_do_learning */) {}
-#endif
 
   ~IMEBridgeImpl() override {}
 
@@ -52,6 +37,8 @@
   void SetInputContextHandler(
       IMEInputContextHandlerInterface* handler) override {
     input_context_handler_ = handler;
+    for (auto& observer : observers_)
+      observer.OnInputContextHandlerChanged();
   }
 
   // IMEBridge override.
@@ -77,14 +64,19 @@
   }
 
   // IMEBridge override.
-  void SetObserver(ui::IMEBridgeObserver* observer) override {
-    observer_ = observer;
+  void AddObserver(ui::IMEBridgeObserver* observer) override {
+    observers_.AddObserver(observer);
+  }
+
+  // IMEBridge override.
+  void RemoveObserver(ui::IMEBridgeObserver* observer) override {
+    observers_.RemoveObserver(observer);
   }
 
   // IMEBridge override.
   void MaybeSwitchEngine() override {
-    if (observer_)
-      observer_->OnRequestSwitchEngine();
+    for (auto& observer : observers_)
+      observer.OnRequestSwitchEngine();
   }
 
 #if defined(OS_CHROMEOS)
@@ -102,13 +94,14 @@
 #endif
 
  private:
-  IMEInputContextHandlerInterface* input_context_handler_;
-  IMEEngineHandlerInterface* engine_handler_;
-  IMEBridgeObserver* observer_;
+  IMEInputContextHandlerInterface* input_context_handler_ = nullptr;
+  IMEEngineHandlerInterface* engine_handler_ = nullptr;
+  base::ObserverList<IMEBridgeObserver> observers_;
   IMEEngineHandlerInterface::InputContext current_input_context_;
 
 #if defined(OS_CHROMEOS)
-  chromeos::IMECandidateWindowHandlerInterface* candidate_window_handler_;
+  chromeos::IMECandidateWindowHandlerInterface* candidate_window_handler_ =
+      nullptr;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(IMEBridgeImpl);
diff --git a/ui/base/ime/ime_bridge.h b/ui/base/ime/ime_bridge.h
index e18c03a..0a807f6870 100644
--- a/ui/base/ime/ime_bridge.h
+++ b/ui/base/ime/ime_bridge.h
@@ -64,8 +64,9 @@
   virtual const IMEEngineHandlerInterface::InputContext&
   GetCurrentInputContext() const = 0;
 
-  // Sets the observer that observes the switching engine event.
-  virtual void SetObserver(ui::IMEBridgeObserver* observer) = 0;
+  // Add or remove observers of events such as switching engines, etc.
+  virtual void AddObserver(ui::IMEBridgeObserver* observer) = 0;
+  virtual void RemoveObserver(ui::IMEBridgeObserver* observer) = 0;
 
   // Switches the engine handler upon top level window focus change.
   virtual void MaybeSwitchEngine() = 0;
diff --git a/ui/base/ime/ime_bridge_observer.h b/ui/base/ime/ime_bridge_observer.h
index a21c5f8..74dd8e9 100644
--- a/ui/base/ime/ime_bridge_observer.h
+++ b/ui/base/ime/ime_bridge_observer.h
@@ -5,17 +5,19 @@
 #ifndef UI_BASE_IME_IME_BRIDGE_OBSERVER_H_
 #define UI_BASE_IME_IME_BRIDGE_OBSERVER_H_
 
+#include "base/observer_list_types.h"
 #include "ui/base/ime/ui_base_ime_export.h"
 
 namespace ui {
 
-// A interface to .
-class UI_BASE_IME_EXPORT IMEBridgeObserver {
+// A interface to observe changes in the IMEBridge.
+class UI_BASE_IME_EXPORT IMEBridgeObserver : public base::CheckedObserver {
  public:
-  virtual ~IMEBridgeObserver() {}
-
   // Called when requesting to switch the engine handler from ui::InputMethod.
   virtual void OnRequestSwitchEngine() = 0;
+
+  // Called when the input context handler has changed, a signal of IME change.
+  virtual void OnInputContextHandlerChanged() = 0;
 };
 
 }  // namespace ui
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index 5ba2110..a6e56275 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -15,8 +15,8 @@
   enable_swiftshader = (is_win || is_linux || (is_mac && use_egl) ||
                         is_chromeos || is_fuchsia) &&
                        (target_cpu == "x86" || target_cpu == "x64" ||
-                        target_cpu == "arm64" || target_cpu == "mipsel" ||
-                        target_cpu == "mips64el")
+                        target_cpu == "arm" || target_cpu == "arm64" ||
+                        target_cpu == "mipsel" || target_cpu == "mips64el")
 }
 
 use_glx = use_x11 || ozone_platform_x11
diff --git a/ui/views/controls/views_text_services_context_menu_base.cc b/ui/views/controls/views_text_services_context_menu_base.cc
index 1cdb872..ae5da49 100644
--- a/ui/views/controls/views_text_services_context_menu_base.cc
+++ b/ui/views/controls/views_text_services_context_menu_base.cc
@@ -19,11 +19,8 @@
 
 namespace {
 
-const char kViewsTextServicesContextMenuHistogram[] =
-    "ContextMenu.ViewsTextServices.Used";
-
-// Do not change the values in this enum as they are used by UMA.
-enum class Command { kEmoji = 0, kMaxValue = kEmoji };
+const char kViewsTextServicesContextMenuEmoji[] =
+    "ContextMenu.ViewsTextServices.Emoji";
 
 }  // namespace
 
@@ -83,8 +80,7 @@
 void ViewsTextServicesContextMenuBase::ExecuteCommand(int command_id) {
   if (command_id == IDS_CONTENT_CONTEXT_EMOJI) {
     ui::ShowEmojiPanel();
-    UMA_HISTOGRAM_ENUMERATION(kViewsTextServicesContextMenuHistogram,
-                              Command::kEmoji);
+    UMA_HISTOGRAM_BOOLEAN(kViewsTextServicesContextMenuEmoji, true);
   }
 }
 
diff --git a/ui/views/mus/views_mus_test_suite.cc b/ui/views/mus/views_mus_test_suite.cc
index befc9bd2..7ed39f43 100644
--- a/ui/views/mus/views_mus_test_suite.cc
+++ b/ui/views/mus/views_mus_test_suite.cc
@@ -54,7 +54,6 @@
   ServiceManagerConnection()
       : thread_("Persistent service_manager connections"),
         default_service_binding_(&default_service_) {
-    catalog::Catalog::SetDefaultCatalogManifest(CreateViewsMusTestsCatalog());
     base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                              base::WaitableEvent::InitialState::NOT_SIGNALED);
     base::Thread::Options options;
@@ -106,8 +105,8 @@
 
   void SetUpConnectionsOnBackgroundThread(base::WaitableEvent* wait) {
     background_service_manager_ =
-        std::make_unique<service_manager::BackgroundServiceManager>(nullptr,
-                                                                    nullptr);
+        std::make_unique<service_manager::BackgroundServiceManager>(
+            nullptr, CreateViewsMusTestsCatalog());
     service_manager::mojom::ServicePtr service;
     default_service_binding_.Bind(mojo::MakeRequest(&service));
     background_service_manager_->RegisterService(
diff --git a/ui/webui/resources/polymer_resources.grdp b/ui/webui/resources/polymer_resources.grdp
index 46acab2..7681d79 100644
--- a/ui/webui/resources/polymer_resources.grdp
+++ b/ui/webui/resources/polymer_resources.grdp
@@ -492,14 +492,6 @@
              file="../../../third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple.html"
              type="chrome_html"
              compress="gzip" />
-  <structure name="IDR_POLYMER_1_0_PAPER_SLIDER_PAPER_SLIDER_EXTRACTED_JS"
-             file="../../../third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider-extracted.js"
-             type="chrome_html"
-             compress="gzip" />
-  <structure name="IDR_POLYMER_1_0_PAPER_SLIDER_PAPER_SLIDER_HTML"
-             file="../../../third_party/polymer/v1_0/components-chromium/paper-slider/paper-slider.html"
-             type="chrome_html"
-             compress="gzip" />
   <structure name="IDR_POLYMER_1_0_PAPER_SPINNER_PAPER_SPINNER_BEHAVIOR_EXTRACTED_JS"
              file="../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-behavior-extracted.js"
              type="chrome_html"