diff --git a/DEPS b/DEPS
index 78386ce7b..b22ee5c9 100644
--- a/DEPS
+++ b/DEPS
@@ -188,7 +188,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': '10b7541a1edc4c856937346e162086b368107752',
+  'skia_revision': '359d16da1108ceae989ddcb0d3bcec723d529fc2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -200,7 +200,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'e2de2c1c54736b994a071801457e7916293d7ee5',
+  'angle_revision': '98a51fde05e84d714af995bb2f98ce629f79d161',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -208,7 +208,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '0c55cdde36c8c9fe1869e8ac275be0550f24a1ab',
+  'pdfium_revision': '6bd8e303c90e42e026c7442caaa477f725150b7b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -259,7 +259,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '82ed9d9bb1f0ca8c39ee03e2b6420803216813c7',
+  'devtools_frontend_revision': '54c234edfb33306bee588c1ed105bd4aafe25691',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -295,7 +295,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '7a1af5878594cec2992a1bb00565b4c712490239',
+  'spv_tools_revision': 'fc0dc3a9c734f798f85a8433cbd99306dbe82825',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -311,7 +311,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'b231c7fb717d13dc5b15f4ab34527cff198fd17b',
+  'dawn_revision': 'bae16b4df9d7383834745a5d31f8d4b0d745a455',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -881,7 +881,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'd9391fdb176da469e56f3a9d490cff8c89833262',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'd912aa91339c5563ee8a9cfbd362c6c252d58188',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -937,7 +937,7 @@
     Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'bf190c43e5c7cc81751867c917a81bc2920be079',
 
   'src/third_party/glslang/src':
-    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '27e915ed4f208cf0913425c79b1e62ffe80a6299',
+    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '90f1d6ab58653c2b5ad327567e7a2841385894c6',
 
   'src/third_party/google_toolbox_for_mac/src': {
       'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'),
@@ -1230,7 +1230,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c047dd609ca72e220715da0648251c4bdcf02931',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '3e560e727fb86450d7c9463d6e97d92881aa1679',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1308,7 +1308,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': 'I_sHBnheTA3cmFAjzkyUAhsmhpWXu82YLidstkjgsvIC'
+              'version': 'OQ8c-S6dNd0LdVeElhAYBgsHeiiM4xyJ8E6hy3pRIUMC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1458,7 +1458,7 @@
   },
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'a1163749fd80709f30f54a95a475b5958b98cab7',
+    Var('webrtc_git') + '/src.git' + '@' + '4b5792cc4a19502e46e46a257945c27bf2205055',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1530,7 +1530,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0f437404b0ed414cea17d177b923a714749497ec',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a72bd10ae6378aad06f3ddc7ef3bb13e04699f49',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/icon_helper.cc b/android_webview/browser/icon_helper.cc
index 6e0323014..e2d0a77f 100644
--- a/android_webview/browser/icon_helper.cc
+++ b/android_webview/browser/icon_helper.cc
@@ -21,6 +21,12 @@
 
 namespace android_webview {
 
+namespace {
+
+const int kLargestIconSize = 192;
+
+}  // namespace
+
 IconHelper::IconHelper(WebContents* web_contents)
     : WebContentsObserver(web_contents),
       listener_(NULL),
@@ -76,10 +82,10 @@
         }
         web_contents()->DownloadImage(
             candidate->icon_url,
-            true,   // Is a favicon
-            0,      // No preferred size
-            0,      // No maximum size
-            false,  // Normal cache policy
+            true,              // Is a favicon
+            0,                 // No preferred size
+            kLargestIconSize,  // Max bitmap size
+            false,             // Normal cache policy
             base::BindOnce(&IconHelper::DownloadFaviconCallback,
                            base::Unretained(this)));
         break;
diff --git a/ash/ambient/backdrop/ambient_backend_controller_impl.cc b/ash/ambient/backdrop/ambient_backend_controller_impl.cc
index 7942fcc8b..b4895df1 100644
--- a/ash/ambient/backdrop/ambient_backend_controller_impl.cc
+++ b/ash/ambient/backdrop/ambient_backend_controller_impl.cc
@@ -352,13 +352,10 @@
     return;
   }
 
-  // Comment this to land the public first.
-  // TODO: Will uncomment when the internal code landed.
-  BackdropClientConfig::Request request;
-  //  BackdropClientConfig::Request request =
-  //      backdrop_client_config_.CreateFetchPersonalAlbumsRequest(
-  //          banner_width, banner_height, num_albums, resume_token, gaia_id,
-  //          access_token);
+  BackdropClientConfig::Request request =
+      backdrop_client_config_.CreateFetchPersonalAlbumsRequest(
+          banner_width, banner_height, num_albums, resume_token, gaia_id,
+          access_token);
   std::unique_ptr<network::ResourceRequest> resource_request =
       CreateResourceRequest(request);
   auto backdrop_url_loader = std::make_unique<BackdropURLLoader>();
@@ -380,12 +377,9 @@
   // Parse the |PersonalAlbumsResponse| out from the response string.
   // Note that the |personal_albums| can be a dummy instance if the parsing has
   // failed.
-  // Comment this to land the public first.
-  // TODO: Will uncomment when the internal code landed.
-  ash::PersonalAlbums personal_albums;
-  //  ash::PersonalAlbums personal_albums =
-  //      BackdropClientConfig::ParsePersonalAlbumsResponse(*response);
-  std::move(callback).Run(personal_albums);
+  ash::PersonalAlbums personal_albums =
+      BackdropClientConfig::ParsePersonalAlbumsResponse(*response);
+  std::move(callback).Run(std::move(personal_albums));
 }
 
 }  // namespace ash
diff --git a/ash/login/login_screen_test_api.cc b/ash/login/login_screen_test_api.cc
index 8d7bed94..ed35e9d 100644
--- a/ash/login/login_screen_test_api.cc
+++ b/ash/login/login_screen_test_api.cc
@@ -425,6 +425,16 @@
   return expanded_test.advanced_view()->GetVisible();
 }
 
+bool LoginScreenTestApi::IsPublicSessionWarningShown() {
+  LockScreen::TestApi lock_screen_test(LockScreen::Get());
+  LockContentsView::TestApi lock_contents_test(
+      lock_screen_test.contents_view());
+  LoginExpandedPublicAccountView::TestApi expanded_test(
+      lock_contents_test.expanded_view());
+  return expanded_test.monitoring_warning_icon() &&
+         expanded_test.monitoring_warning_label();
+}
+
 // static
 void LoginScreenTestApi::ClickPublicExpandedAdvancedViewButton() {
   LockScreen::TestApi lock_screen_test(LockScreen::Get());
diff --git a/ash/public/cpp/ambient/ambient_backend_controller.h b/ash/public/cpp/ambient/ambient_backend_controller.h
index e93adee..535a0f3 100644
--- a/ash/public/cpp/ambient/ambient_backend_controller.h
+++ b/ash/public/cpp/ambient/ambient_backend_controller.h
@@ -81,7 +81,7 @@
       base::OnceCallback<void(const base::Optional<AmbientSettings>& settings)>;
   using UpdateSettingsCallback = base::OnceCallback<void(bool success)>;
   using OnPersonalAlbumsFetchedCallback =
-      base::OnceCallback<void(const PersonalAlbums&)>;
+      base::OnceCallback<void(PersonalAlbums)>;
 
   static AmbientBackendController* Get();
 
diff --git a/ash/public/cpp/login_screen_test_api.h b/ash/public/cpp/login_screen_test_api.h
index 594c4cc..c75a5ab 100644
--- a/ash/public/cpp/login_screen_test_api.h
+++ b/ash/public/cpp/login_screen_test_api.h
@@ -56,6 +56,7 @@
   static bool HidePublicSessionExpandedPod();
   static bool IsPublicSessionExpanded();
   static bool IsExpandedPublicSessionAdvanced();
+  static bool IsPublicSessionWarningShown();
   static void ClickPublicExpandedAdvancedViewButton();
   static void ClickPublicExpandedSubmitButton();
   static void SetPublicSessionLocale(const std::string& locale);
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index a6617c5..3d90fa09 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20200629.2.4
+0.20200630.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index a6617c5..3d90fa09 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20200629.2.4
+0.20200630.1.1
diff --git a/cc/layers/heads_up_display_layer.cc b/cc/layers/heads_up_display_layer.cc
index 42755c0..085c362 100644
--- a/cc/layers/heads_up_display_layer.cc
+++ b/cc/layers/heads_up_display_layer.cc
@@ -41,7 +41,7 @@
     bounds = device_viewport_in_layout_pixels;
   } else {
     // If the HUD is not displaying full-viewport rects (e.g., it is showing the
-    // FPS meter), use a fixed size.
+    // Frame Rendering Stats), use a fixed size.
     constexpr int kDefaultHUDSize = 256;
     bounds.SetSize(kDefaultHUDSize, kDefaultHUDSize);
   }
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index b539a5d..2fabc34 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -664,7 +664,7 @@
       SkRect::MakeXYWH(left + kPadding, text_bounds.bottom() + 2 * kPadding,
                        kGraphWidth, kGraphHeight);
 
-  // Draw the fps meter.
+  // Draw the frame rendering stats.
   const std::string title("Frames");
   const std::string value_text = base::StringPrintf("%d %%", throughput_value_);
   const std::string dropped_frames_text =
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 6501061..d51815d 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -357,6 +357,7 @@
     "//components/browser_ui/android/bottomsheet:factory_java",
     "//components/browser_ui/android/bottomsheet:java",
     "//components/browser_ui/android/bottomsheet:manager_java",
+    "//components/browser_ui/banners/android:java",
     "//components/browser_ui/client_certificate/android:java",
     "//components/browser_ui/http_auth/android:java",
     "//components/browser_ui/media/android:java",
diff --git a/chrome/android/DEPS b/chrome/android/DEPS
index 569e621..d1c1e8a 100644
--- a/chrome/android/DEPS
+++ b/chrome/android/DEPS
@@ -13,6 +13,7 @@
   "+chrome/browser/util/android/java",
   "+chrome/browser/xsurface/android",
   "+components/browser_ui/android/bottomsheet",
+  "+components/browser_ui/banners/android",
   "+components/browser_ui/media/android",
   "+components/browser_ui/modaldialog/android",
   "+components/browser_ui/share/android",
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index 147331c..ad20a85 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -749,7 +749,6 @@
   "java/res/drawable/infobar_download_complete_animation.xml",
   "java/res/drawable/infobar_downloading_fill_animation.xml",
   "java/res/drawable/infobar_downloading_sweep_animation.xml",
-  "java/res/drawable/infobar_wrapper_bg.xml",
   "java/res/drawable/item_chooser_row_background.xml",
   "java/res/drawable/logo_avatar_anonymous.xml",
   "java/res/drawable/logo_partly_cloudy.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index f1f8582..57f909b8 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -133,7 +133,6 @@
   "java/src/org/chromium/chrome/browser/banners/AppBannerManager.java",
   "java/src/org/chromium/chrome/browser/banners/AppData.java",
   "java/src/org/chromium/chrome/browser/banners/AppDetailsDelegate.java",
-  "java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkAddActivity.java",
@@ -818,7 +817,6 @@
   "java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java",
   "java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java",
   "java/src/org/chromium/chrome/browser/infobar/InfoBarContainerView.java",
-  "java/src/org/chromium/chrome/browser/infobar/InfoBarWrapper.java",
   "java/src/org/chromium/chrome/browser/infobar/InstallableAmbientBadgeInfoBar.java",
   "java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBar.java",
   "java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBarDelegate.java",
@@ -1424,6 +1422,7 @@
   "java/src/org/chromium/chrome/browser/signin/SyncPromoView.java",
   "java/src/org/chromium/chrome/browser/signin/UnifiedConsentServiceBridge.java",
   "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java",
+  "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java",
   "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetProperties.java",
   "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java",
   "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java",
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
index a76f7688..93915b3 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -412,12 +412,11 @@
         } else if (mOverviewModeState == OverviewModeState.SHOWN_TABSWITCHER) {
             mPropertyModel.set(IS_SHOWING_STACK_TAB_SWITCHER, mShowStackTabSwitcher);
 
-            setExploreSurfaceVisibility(false);
             setTabCarouselVisibility(false);
             setMVTilesVisibility(false);
             setFakeBoxVisibility(false);
             setSecondaryTasksSurfaceVisibility(true);
-
+            setExploreSurfaceVisibility(false);
         } else if (mOverviewModeState == OverviewModeState.SHOWN_TABSWITCHER_TWO_PANES) {
             // Show Explore Surface if last visible pane explore.
             setExploreSurfaceVisibility(
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
index f3a1813..6dcd9ed 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
@@ -25,6 +25,7 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.os.Build;
+import android.support.test.filters.MediumTest;
 import android.text.TextUtils;
 import android.util.Base64;
 import android.view.View;
@@ -94,6 +95,7 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -410,6 +412,52 @@
                 startSurfaceToolbarCoordinator.getIncognitoSwitchCoordinatorForTesting());
     }
 
+    /**
+     * Tests that clicking the "more_tabs" button won't make Omnibox get focused when single tab is
+     * shown on the StartSurface.
+     */
+    @Test
+    @MediumTest
+    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
+    // clang-format off
+    @EnableFeatures({ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<Study,",
+            ChromeFeatureList.START_SURFACE_ANDROID + "<Study"})
+    @CommandLineFlags.Add({"force-fieldtrials=Study/Group", IMMEDIATE_RETURN_PARAMS +
+            "/start_surface_variation/single/show_last_active_tab_only/true"})
+    public void startSurfaceMoreTabsButtonTest() throws IOException {
+        // clang-format on
+        createTabStateFile(new int[] {0});
+        createThumbnailBitmapAndWriteToFile(0);
+        TabAttributeCache.setTitleForTesting(0, "Google");
+
+        startMainActivityFromLauncher();
+        Assert.assertFalse(mActivityTestRule.getActivity().isTablet());
+        Assert.assertTrue(CachedFeatureFlags.isEnabled(ChromeFeatureList.INSTANT_START));
+        Assert.assertEquals("single", StartSurfaceConfiguration.START_SURFACE_VARIATION.getValue());
+        Assert.assertTrue(ReturnToChromeExperimentsUtil.shouldShowTabSwitcher(-1));
+        Assert.assertTrue(StartSurfaceConfiguration.START_SURFACE_LAST_ACTIVE_TAB_ONLY.getValue());
+        Assert.assertFalse(
+                StartSurfaceConfiguration.START_SURFACE_SHOW_STACK_TAB_SWITCHER.getValue());
+
+        mActivityTestRule.waitForActivityNativeInitializationComplete();
+
+        // Note that onView(R.id.more_tabs).perform(click()) can not be used since it requires 90
+        // percent of the view's area is displayed to the users. However, this view has negative
+        // margin which makes the percentage is less than 90.
+        // TODO(crbug.com/1025296): Investigate whether this would be a problem for real users.
+        try {
+            TestThreadUtils.runOnUiThreadBlocking(()
+                                                          -> mActivityTestRule.getActivity()
+                                                                     .findViewById(R.id.more_tabs)
+                                                                     .performClick());
+        } catch (ExecutionException e) {
+            Assert.fail("Failed to tap 'more tabs' " + e.toString());
+        }
+
+        onViewWaiting(withId(R.id.tab_list_view));
+        Assert.assertFalse(mActivityTestRule.getActivity().findViewById(R.id.url_bar).isFocused());
+    }
+
     @Test
     @SmallTest
     @Restriction({UiRestriction.RESTRICTION_TYPE_TABLET})
diff --git a/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml b/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml
index e4ef206..e2caa49a 100644
--- a/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml
+++ b/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml
@@ -39,9 +39,30 @@
         style="@style/HorizontalDivider" />
 
     <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/account_picker_item"
+        android:id="@+id/account_picker_account_list"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_margin="16dp"
+        android:visibility="gone"
         tools:listitem="@layout/account_chooser_dialog_item" />
+
+    <include
+        android:id="@+id/account_picker_selected_account"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="16dp"
+        layout="@layout/account_picker_row" />
+
+    <org.chromium.ui.widget.ButtonCompat
+        android:id="@+id/account_picker_continue_as_button"
+        style="@style/FilledButton.Flat"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="24dp"
+        android:layout_marginEnd="24dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="20dp"
+        android:ellipsize="end"
+        android:singleLine="true"
+        android:text="@string/signin_promo_continue_as" />
 </LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java
index cdc58a95..29cfd4b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java
@@ -170,7 +170,7 @@
     public boolean onScroll(
             float startX, float distanceX, float distanceY, float endX, float endY) {
         // onScroll needs handling only after the state moves away from |NONE|.
-        if (mState == GestureState.NONE) return true;
+        if (mState == GestureState.NONE || mActionDelegate == null) return true;
 
         if (mState == GestureState.STARTED) {
             if (shouldTriggerUi(startX, distanceX, distanceY)) {
@@ -342,12 +342,17 @@
         // The animation view is attached/detached on-demand to minimize overlap
         // with composited SurfaceView content.
         cancelDetachLayoutRunnable();
-        if (mSideSlideLayout.getParent() == null) mParentView.addView(mSideSlideLayout);
+        if (isLayoutDetached()) mParentView.addView(mSideSlideLayout);
     }
 
     private void detachLayoutIfNecessary() {
         if (mSideSlideLayout == null) return;
         cancelDetachLayoutRunnable();
-        if (mSideSlideLayout.getParent() != null) mParentView.removeView(mSideSlideLayout);
+        if (!isLayoutDetached()) mParentView.removeView(mSideSlideLayout);
+    }
+
+    @VisibleForTesting
+    boolean isLayoutDetached() {
+        return mSideSlideLayout == null || mSideSlideLayout.getParent() == null;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java
index 07825ba..c713a38 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java
@@ -155,6 +155,19 @@
 
         // The absolute offset has to take into account that the circle starts at an offset
         mTotalDragDistance = RAW_SWIPE_LIMIT_DP * getResources().getDisplayMetrics().density;
+
+        mAnimateToStartPosition.setAnimationListener(new AnimationListener() {
+            @Override
+            public void onAnimationStart(Animation animation) {}
+
+            @Override
+            public void onAnimationRepeat(Animation animation) {}
+
+            @Override
+            public void onAnimationEnd(Animation animation) {
+                reset();
+            }
+        });
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AdsBlockedInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AdsBlockedInfoBar.java
index ddbdd7d..e9cbea5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AdsBlockedInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AdsBlockedInfoBar.java
@@ -15,7 +15,7 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarControlLayout;
 import org.chromium.components.infobars.InfoBarLayout;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillCreditCardFillingInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillCreditCardFillingInfoBar.java
index ddb8b8b..0749663f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillCreditCardFillingInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillCreditCardFillingInfoBar.java
@@ -8,7 +8,7 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBarControlLayout;
 import org.chromium.components.infobars.InfoBarLayout;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillSaveCardInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillSaveCardInfoBar.java
index 8527bea..cc3fce5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillSaveCardInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutofillSaveCardInfoBar.java
@@ -14,7 +14,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBarControlLayout;
 import org.chromium.components.infobars.InfoBarLayout;
 import org.chromium.ui.UiUtils;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java
index 7af46800..409f235 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java
@@ -17,8 +17,8 @@
 import org.chromium.chrome.browser.about_settings.AboutSettingsBridge;
 import org.chromium.chrome.browser.datareduction.DataReductionPromoUtils;
 import org.chromium.chrome.browser.omaha.VersionNumberGetter;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
 import org.chromium.components.embedder_support.util.UrlConstants;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBarControlLayout;
 import org.chromium.components.infobars.InfoBarLayout;
 import org.chromium.content_public.browser.WebContents;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java
index 1443b913..8544a43 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java
@@ -23,8 +23,8 @@
 import org.chromium.chrome.browser.download.DownloadManagerService;
 import org.chromium.chrome.browser.download.DownloadOpenSource;
 import org.chromium.chrome.browser.download.DownloadUtils;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
 import org.chromium.components.download.DownloadCollectionBridge;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarLayout;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/GeneratedPasswordSavedInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/GeneratedPasswordSavedInfoBar.java
index 3cf365f8..3449820b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/GeneratedPasswordSavedInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/GeneratedPasswordSavedInfoBar.java
@@ -8,7 +8,7 @@
 import android.text.Spanned;
 
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBarControlLayout;
 import org.chromium.components.infobars.InfoBarLayout;
 import org.chromium.ui.text.NoUnderlineClickableSpan;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java
index eaa0184..6a566937 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java
@@ -21,6 +21,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarAnimationListener;
 import org.chromium.components.infobars.InfoBarUiItem;
+import org.chromium.components.infobars.InfoBarWrapper;
 import org.chromium.ui.widget.OptimizedFrameLayout;
 
 import java.util.ArrayList;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerView.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerView.java
index b64fd776..a1620c8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerView.java
@@ -15,9 +15,9 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.chrome.browser.banners.SwipableOverlayView;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsUtils;
+import org.chromium.components.browser_ui.banners.SwipableOverlayView;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarUiItem;
 import org.chromium.ui.display.DisplayAndroid;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarWrapper.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarWrapper.java
deleted file mode 100644
index 8638f22..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarWrapper.java
+++ /dev/null
@@ -1,47 +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.
-
-package org.chromium.chrome.browser.infobar;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.view.Gravity;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import org.chromium.chrome.R;
-import org.chromium.components.infobars.InfoBarUiItem;
-
-/**
- * Layout that holds an infobar's contents and provides a background color and a top shadow.
- */
-class InfoBarWrapper extends FrameLayout {
-    private final InfoBarUiItem mItem;
-
-    /**
-     * Constructor for inflating from Java.
-     */
-    InfoBarWrapper(Context context, InfoBarUiItem item) {
-        super(context);
-        mItem = item;
-        Resources res = context.getResources();
-        int peekingHeight = res.getDimensionPixelSize(R.dimen.infobar_peeking_height);
-        int shadowHeight = res.getDimensionPixelSize(R.dimen.infobar_shadow_height);
-        setMinimumHeight(peekingHeight + shadowHeight);
-
-        // setBackgroundResource() changes the padding, so call setPadding() second.
-        setBackgroundResource(R.drawable.infobar_wrapper_bg);
-        setPadding(0, shadowHeight, 0, 0);
-    }
-
-    InfoBarUiItem getItem() {
-        return mItem;
-    }
-
-    @Override
-    public void onViewAdded(View child) {
-        child.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT,
-                Gravity.TOP));
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBar.java
index 5b4ea43a..5d47ea4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBar.java
@@ -11,8 +11,8 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.instantapps.InstantAppsBannerData;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
 import org.chromium.components.browser_ui.widget.DualControlLayout;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarLayout;
 import org.chromium.components.url_formatter.SchemeDisplay;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/KnownInterceptionDisclosureInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/KnownInterceptionDisclosureInfoBar.java
index 73f989a..68bfce54 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/KnownInterceptionDisclosureInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/KnownInterceptionDisclosureInfoBar.java
@@ -9,7 +9,7 @@
 import androidx.annotation.ColorRes;
 
 import org.chromium.base.annotations.CalledByNative;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBarLayout;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java
index e482e6ae..a395fb6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java
@@ -13,9 +13,9 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
 import org.chromium.components.browser_ui.site_settings.SingleCategorySettings;
 import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBarCompactLayout;
 import org.chromium.components.infobars.InfoBarLayout;
 import org.chromium.components.permissions.AndroidPermissionRequester;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsInfoBar.java
index a56203b..992fcc2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsInfoBar.java
@@ -6,7 +6,7 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarLayout;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsLitePageInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsLitePageInfoBar.java
index fc65edf..59c60694 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsLitePageInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsLitePageInfoBar.java
@@ -11,7 +11,7 @@
 import org.chromium.chrome.browser.datareduction.settings.DataReductionPreferenceFragment;
 import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SafetyTipInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SafetyTipInfoBar.java
index df476511..32fa31f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SafetyTipInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SafetyTipInfoBar.java
@@ -9,7 +9,7 @@
 import androidx.annotation.ColorRes;
 
 import org.chromium.base.annotations.CalledByNative;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBarLayout;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SavePasswordInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SavePasswordInfoBar.java
index eec3ed9..769e77d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SavePasswordInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SavePasswordInfoBar.java
@@ -8,7 +8,7 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarControlLayout;
 import org.chromium.components.infobars.InfoBarLayout;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java
index 40628c5..6b2f066 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java
@@ -24,7 +24,7 @@
 import org.chromium.chrome.browser.sync.settings.SyncAndServicesSettings;
 import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils;
 import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils.SyncError;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarLayout;
 import org.chromium.content_public.browser.WebContents;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java
index a83afd6..182f0ba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/UpdatePasswordInfoBar.java
@@ -9,7 +9,7 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarControlLayout;
 import org.chromium.components.infobars.InfoBarControlLayout.InfoBarArrayAdapter;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java
index 9b7018a..9c80299 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java
@@ -239,7 +239,8 @@
         if (mSearchQuery == null) {
             createSavePasswordsSwitch();
             createAutoSignInCheckbox();
-            if (ChromeFeatureList.isEnabled(ChromeFeatureList.PASSWORD_CHECK)) {
+            if (ChromeFeatureList.isEnabled(ChromeFeatureList.PASSWORD_CHECK)
+                    && PasswordUIView.hasAccountForLeakCheckRequest()) {
                 createCheckPasswords();
             }
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java
index 314d8afd..2d15377 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java
@@ -11,13 +11,13 @@
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
 import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver;
-import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
 
 /**
  * Coordinator of the account picker bottom sheet used in web signin flow.
  */
 public class AccountPickerBottomSheetCoordinator {
+    private final AccountPickerBottomSheetMediator mAccountPickerBottomSheetMediator;
     private final AccountPickerCoordinator mAccountPickerCoordinator;
     private final BottomSheetController mBottomSheetController;
     private final BottomSheetObserver mBottomSheetObserver = new EmptyBottomSheetObserver() {
@@ -32,18 +32,20 @@
 
     /**
      * Constructs the AccountPickerBottomSheetCoordinator and shows the
-     * bottomsheet on the screen.
+     * bottom sheet on the screen.
      */
     @MainThread
     public AccountPickerBottomSheetCoordinator(Context context,
             BottomSheetController bottomSheetController,
-            AccountPickerCoordinator.Listener accountPickerListener) {
+            AccountPickerDelegate accountPickerDelegate) {
         AccountPickerBottomSheetView view = new AccountPickerBottomSheetView(context);
+        mAccountPickerBottomSheetMediator =
+                new AccountPickerBottomSheetMediator(context, accountPickerDelegate);
         mAccountPickerCoordinator = new AccountPickerCoordinator(
-                view.getAccountPickerItemView(), accountPickerListener, null);
+                view.getAccountListView(), mAccountPickerBottomSheetMediator, null);
         mBottomSheetController = bottomSheetController;
-        PropertyModel model = AccountPickerBottomSheetProperties.createModel();
-        PropertyModelChangeProcessor.create(model, view, AccountPickerBottomSheetViewBinder::bind);
+        PropertyModelChangeProcessor.create(mAccountPickerBottomSheetMediator.getModel(), view,
+                AccountPickerBottomSheetViewBinder::bind);
         mBottomSheetController.addObserver(mBottomSheetObserver);
         mBottomSheetController.requestShowContent(view, true);
     }
@@ -54,6 +56,8 @@
     @MainThread
     private void destroy() {
         mAccountPickerCoordinator.destroy();
+        mAccountPickerBottomSheetMediator.destroy();
+
         mBottomSheetController.removeObserver(mBottomSheetObserver);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java
new file mode 100644
index 0000000..7b77013c
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java
@@ -0,0 +1,117 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.signin.account_picker;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.text.TextUtils;
+
+import androidx.annotation.Nullable;
+
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.signin.ProfileDataCache;
+import org.chromium.components.signin.AccountManagerFacadeProvider;
+import org.chromium.ui.modelutil.PropertyModel;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Mediator of the account picker bottom sheet in web sign-in flow.
+ */
+class AccountPickerBottomSheetMediator implements AccountPickerCoordinator.Listener {
+    private final AccountPickerDelegate mAccountPickerDelegate;
+    private final ProfileDataCache mProfileDataCache;
+    private final PropertyModel mModel;
+
+    private final ProfileDataCache.Observer mProfileDataSourceObserver =
+            this::updateSelectedAccountData;
+    private @Nullable String mSelectedAccountName = null;
+
+    AccountPickerBottomSheetMediator(Context context, AccountPickerDelegate accountPickerDelegate) {
+        mAccountPickerDelegate = accountPickerDelegate;
+        mProfileDataCache = new ProfileDataCache(
+                context, context.getResources().getDimensionPixelSize(R.dimen.user_picture_size));
+
+        mModel = AccountPickerBottomSheetProperties.createModel(
+                this::onSelectedAccountClicked, this::onContinueAsClicked);
+        mProfileDataCache.addObserver(mProfileDataSourceObserver);
+        // TODO(https://crbug.com/1096977): Add an observer to listen to accounts
+        // change in AccountManagerFacade, in case from zero to more accounts or
+        // the selected account disappeared.
+        List<Account> accounts = AccountManagerFacadeProvider.getInstance().tryGetGoogleAccounts();
+        if (!accounts.isEmpty()) {
+            setSelectedAccountName(accounts.get(0).name);
+        }
+    }
+
+    /**
+     * Notifies that the user has selected an account.
+     *
+     * @param accountName The email of the selected account.
+     * @param isDefaultAccount Whether the selected account is the first in the account list.
+     */
+    @Override
+    public void onAccountSelected(String accountName, boolean isDefaultAccount) {
+        // Click on one account in the account list when the account list is expanded
+        // will collapse it to the selected account
+        mModel.set(AccountPickerBottomSheetProperties.IS_ACCOUNT_LIST_EXPANDED, false);
+        setSelectedAccountName(accountName);
+    }
+
+    /**
+     * Notifies when the user clicked the "add account" button.
+     */
+    @Override
+    public void addAccount() {
+        mAccountPickerDelegate.addAccount();
+    }
+
+    PropertyModel getModel() {
+        return mModel;
+    }
+
+    void destroy() {
+        mProfileDataCache.removeObserver(mProfileDataSourceObserver);
+    }
+
+    private void setSelectedAccountName(String accountName) {
+        mSelectedAccountName = accountName;
+        mProfileDataCache.update(Collections.singletonList(mSelectedAccountName));
+        updateSelectedAccountData(mSelectedAccountName);
+    }
+
+    /**
+     * Implements {@link ProfileDataCache.Observer}.
+     */
+    private void updateSelectedAccountData(String accountName) {
+        if (TextUtils.equals(mSelectedAccountName, accountName)) {
+            mModel.set(AccountPickerBottomSheetProperties.SELECTED_ACCOUNT_DATA,
+                    mProfileDataCache.getProfileDataOrDefault(accountName));
+        }
+    }
+
+    /**
+     * Callback for the PropertyKey
+     * {@link AccountPickerBottomSheetProperties#ON_SELECTED_ACCOUNT_CLICKED}.
+     */
+    private void onSelectedAccountClicked() {
+        // Clicking on the selected account when the account list is collapsed will expand the
+        // account list and make the account list visible
+        mModel.set(AccountPickerBottomSheetProperties.IS_ACCOUNT_LIST_EXPANDED, true);
+    }
+
+    /**
+     * Callback for the PropertyKey
+     * {@link AccountPickerBottomSheetProperties#ON_CONTINUE_AS_CLICKED}.
+     */
+    private void onContinueAsClicked() {
+        if (mSelectedAccountName == null) {
+            addAccount();
+        } else {
+            mAccountPickerDelegate.signIn(mSelectedAccountName);
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetProperties.java
index 3f4f1ca..6f03b13 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetProperties.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetProperties.java
@@ -4,18 +4,46 @@
 
 package org.chromium.chrome.browser.signin.account_picker;
 
+import org.chromium.chrome.browser.signin.DisplayableProfileData;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey;
+import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
+import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
 
 /**
- * Properties of account picker bottomsheet.
- *
- * TODO(http://crbug.com/1081253): Implement the bottomsheet properties.
+ * Properties of account picker bottom sheet.
  */
 class AccountPickerBottomSheetProperties {
-    static final PropertyKey[] ALL_KEYS = new PropertyKey[] {};
+    // PropertyKeys for the selected account view when the account list is collapsed.
+    // The selected account view is replaced by account list view when the
+    // account list is expanded.
+    static final ReadableObjectPropertyKey<Runnable> ON_SELECTED_ACCOUNT_CLICKED =
+            new ReadableObjectPropertyKey<>("on_selected_account_clicked");
+    static final WritableObjectPropertyKey<DisplayableProfileData> SELECTED_ACCOUNT_DATA =
+            new WritableObjectPropertyKey<>("selected_account_data");
 
-    static PropertyModel createModel() {
-        return new PropertyModel.Builder(ALL_KEYS).build();
+    // PropertyKey for the button |Continue as ...|
+    // The button is visible during all the lifecycle of the bottom sheet
+    static final ReadableObjectPropertyKey<Runnable> ON_CONTINUE_AS_CLICKED =
+            new ReadableObjectPropertyKey<>("on_continue_as_clicked");
+
+    // PropertyKey indicates if the account list is expanded
+    static final WritableBooleanPropertyKey IS_ACCOUNT_LIST_EXPANDED =
+            new WritableBooleanPropertyKey("is_account_list_expanded");
+
+    static final PropertyKey[] ALL_KEYS = new PropertyKey[] {ON_SELECTED_ACCOUNT_CLICKED,
+            SELECTED_ACCOUNT_DATA, ON_CONTINUE_AS_CLICKED, IS_ACCOUNT_LIST_EXPANDED};
+
+    static PropertyModel createModel(
+            Runnable onSelectedAccountClicked, Runnable onContinueAsClicked) {
+        return new PropertyModel.Builder(ALL_KEYS)
+                .with(ON_SELECTED_ACCOUNT_CLICKED, onSelectedAccountClicked)
+                .with(SELECTED_ACCOUNT_DATA, null)
+                .with(ON_CONTINUE_AS_CLICKED, onContinueAsClicked)
+                .with(IS_ACCOUNT_LIST_EXPANDED, false)
+                .build();
     }
+
+    private AccountPickerBottomSheetProperties() {}
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java
index 514f904..5010f80 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java
@@ -7,33 +7,103 @@
 import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.widget.ImageView;
 
 import androidx.annotation.Nullable;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.signin.DisplayableProfileData;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
+import org.chromium.ui.widget.ButtonCompat;
 
 /**
  * This class is the AccountPickerBottomsheet view for the web sign-in flow.
+ *
+ * The bottom sheet shows a single account with a |Continue as ...| button by default, clicking
+ * on the account will expand the bottom sheet to an account list together with other sign-in
+ * options like "Add account" and "Go incognito mode".
  */
 class AccountPickerBottomSheetView implements BottomSheetContent {
     private final Context mContext;
     private final View mContentView;
-    private final RecyclerView mAccountPickerItemView;
+    private final RecyclerView mAccountListView;
+    private final View mSelectedAccountView;
+    private final ButtonCompat mContinueAsButton;
 
     AccountPickerBottomSheetView(Context context) {
         mContext = context;
         mContentView = LayoutInflater.from(mContext).inflate(
                 R.layout.account_picker_bottom_sheet_view, null);
-        mAccountPickerItemView = mContentView.findViewById(R.id.account_picker_item);
-        mAccountPickerItemView.setLayoutManager(new LinearLayoutManager(
-                mAccountPickerItemView.getContext(), LinearLayoutManager.VERTICAL, false));
+        mAccountListView = mContentView.findViewById(R.id.account_picker_account_list);
+        mAccountListView.setLayoutManager(new LinearLayoutManager(
+                mAccountListView.getContext(), LinearLayoutManager.VERTICAL, false));
+        mSelectedAccountView = mContentView.findViewById(R.id.account_picker_selected_account);
+        mContinueAsButton = mContentView.findViewById(R.id.account_picker_continue_as_button);
     }
 
-    RecyclerView getAccountPickerItemView() {
-        return mAccountPickerItemView;
+    /**
+     * The account list view is visible when the account list is expanded.
+     */
+    RecyclerView getAccountListView() {
+        return mAccountListView;
+    }
+
+    /**
+     * The selected account is visible when the account list is collapsed.
+     */
+    View getSelectedAccountView() {
+        return mSelectedAccountView;
+    }
+
+    /**
+     * The |Continue As| button on the bottom sheet.
+     */
+    ButtonCompat getContinueAsButton() {
+        return mContinueAsButton;
+    }
+
+    /**
+     * Expands the account list.
+     */
+    void expandAccountList() {
+        mSelectedAccountView.setVisibility(View.GONE);
+        mContinueAsButton.setVisibility(View.GONE);
+        mAccountListView.setVisibility(View.VISIBLE);
+    }
+
+    /**
+     * Collapses the account list.
+     * If there is a non null selected account, the account list will collapse to that account,
+     * otherwise, the account list will just collapse the remaining.
+     *
+     * @param isSelectedAccountNonNull Flag indicates if the selected profile data exists
+     *                                 in model.
+     */
+    void collapseAccountList(boolean isSelectedAccountNonNull) {
+        mAccountListView.setVisibility(View.GONE);
+        mSelectedAccountView.setVisibility(isSelectedAccountNonNull ? View.VISIBLE : View.GONE);
+        mContinueAsButton.setVisibility(View.VISIBLE);
+    }
+
+    /**
+     * Updates the view of the collapsed account list.
+     */
+    void updateCollapsedAccountList(DisplayableProfileData accountProfileData) {
+        if (accountProfileData == null) {
+            mContinueAsButton.setText(R.string.signin_add_account);
+        } else {
+            ExistingAccountRowViewBinder.bindAccountView(accountProfileData, mSelectedAccountView);
+
+            ImageView rowEndImage = mSelectedAccountView.findViewById(R.id.account_selection_mark);
+            rowEndImage.setImageResource(R.drawable.ic_expand_more_black_24dp);
+            rowEndImage.setColorFilter(R.color.default_icon_color);
+
+            String continueAsButtonText = mContext.getString(R.string.signin_promo_continue_as,
+                    accountProfileData.getGivenNameOrFullNameOrEmail());
+            mContinueAsButton.setText(continueAsButtonText);
+        }
     }
 
     @Override
@@ -49,7 +119,7 @@
 
     @Override
     public int getVerticalScrollOffset() {
-        return mAccountPickerItemView.computeVerticalScrollOffset();
+        return mAccountListView.computeVerticalScrollOffset();
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java
index 7ae469e3..767bbda 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java
@@ -4,15 +4,38 @@
 
 package org.chromium.chrome.browser.signin.account_picker;
 
+import org.chromium.chrome.browser.signin.DisplayableProfileData;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
 /**
  * Stateless AccountPickerBottomSheet view binder.
- *
- * TODO(http://crbug.com/1081253): Implement the bottomsheet view binder.
  */
 class AccountPickerBottomSheetViewBinder {
     static void bind(
-            PropertyModel model, AccountPickerBottomSheetView view, PropertyKey propertyKey) {}
+            PropertyModel model, AccountPickerBottomSheetView view, PropertyKey propertyKey) {
+        if (propertyKey == AccountPickerBottomSheetProperties.ON_SELECTED_ACCOUNT_CLICKED) {
+            view.getSelectedAccountView().setOnClickListener(v -> {
+                model.get(AccountPickerBottomSheetProperties.ON_SELECTED_ACCOUNT_CLICKED).run();
+            });
+        } else if (propertyKey == AccountPickerBottomSheetProperties.IS_ACCOUNT_LIST_EXPANDED) {
+            if (model.get(AccountPickerBottomSheetProperties.IS_ACCOUNT_LIST_EXPANDED)) {
+                view.expandAccountList();
+            } else {
+                boolean isSelectedAccountNonNull =
+                        model.get(AccountPickerBottomSheetProperties.SELECTED_ACCOUNT_DATA) != null;
+                view.collapseAccountList(isSelectedAccountNonNull);
+            }
+        } else if (propertyKey == AccountPickerBottomSheetProperties.SELECTED_ACCOUNT_DATA) {
+            DisplayableProfileData profileData =
+                    model.get(AccountPickerBottomSheetProperties.SELECTED_ACCOUNT_DATA);
+            view.updateCollapsedAccountList(profileData);
+        } else if (propertyKey == AccountPickerBottomSheetProperties.ON_CONTINUE_AS_CLICKED) {
+            view.getContinueAsButton().setOnClickListener(v -> {
+                model.get(AccountPickerBottomSheetProperties.ON_CONTINUE_AS_CLICKED).run();
+            });
+        }
+    }
+
+    private AccountPickerBottomSheetViewBinder() {}
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
index b1adea2..dac4fc40 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
@@ -27,7 +27,7 @@
  * It is responsible for the sign-in and adding account functions needed for the
  * web sign-in flow.
  */
-public class AccountPickerDelegate implements AccountPickerCoordinator.Listener {
+public class AccountPickerDelegate {
     private final ChromeActivity mChromeActivity;
     private final Tab mTab;
     private final String mContinueUrl;
@@ -39,13 +39,9 @@
         mContinueUrl = continueUrl;
     }
     /**
-     * Notifies that the user has selected an account.
-     *
-     * @param accountName The email of the selected account.
-     * @param isDefaultAccount Whether the selected account is the first in the account list.
+     * Signs the user into the account of the given accountName.
      */
-    @Override
-    public void onAccountSelected(String accountName, boolean isDefaultAccount) {
+    public void signIn(String accountName) {
         Account account = AccountUtils.findAccountByName(
                 AccountManagerFacadeProvider.getInstance().tryGetGoogleAccounts(), accountName);
         IdentityServicesProvider.get().getSigninManager().signIn(
@@ -70,7 +66,6 @@
     /**
      * Notifies when the user clicked the "add account" button.
      */
-    @Override
     public void addAccount() {
         // TODO(https//crbug.com/1097031): We should select the added account
         // and collapse the account chooser after the account is actually added.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/ExistingAccountRowViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/ExistingAccountRowViewBinder.java
index 820c2f0..9a826fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/ExistingAccountRowViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/ExistingAccountRowViewBinder.java
@@ -42,22 +42,7 @@
                     -> model.get(ExistingAccountRowProperties.ON_CLICK_LISTENER)
                                .onResult(profileData));
         } else if (propertyKey == ExistingAccountRowProperties.PROFILE_DATA) {
-            ImageView accountImage = view.findViewById(R.id.account_image);
-            accountImage.setImageDrawable(profileData.getImage());
-
-            TextView accountTextPrimary = view.findViewById(R.id.account_text_primary);
-            TextView accountTextSecondary = view.findViewById(R.id.account_text_secondary);
-
-            String fullName = profileData.getFullName();
-            if (!TextUtils.isEmpty(fullName)) {
-                accountTextPrimary.setText(fullName);
-                accountTextSecondary.setText(profileData.getAccountName());
-                accountTextSecondary.setVisibility(View.VISIBLE);
-            } else {
-                // Full name is not available, show the email in the primary TextView.
-                accountTextPrimary.setText(profileData.getAccountName());
-                accountTextSecondary.setVisibility(View.GONE);
-            }
+            bindAccountView(profileData, view);
         } else if (propertyKey == ExistingAccountRowProperties.IS_SELECTED_ACCOUNT) {
             ImageView selectionMark = view.findViewById(R.id.account_selection_mark);
             selectionMark.setVisibility(model.get(ExistingAccountRowProperties.IS_SELECTED_ACCOUNT)
@@ -68,4 +53,29 @@
                     "Cannot update the view for propertyKey: " + propertyKey);
         }
     }
+
+    /**
+     * Binds the view with the given profile data.
+     *
+     * @param profileData profile data needs to bind.
+     * @param view A view object inflated from @layout/account_picker_row.
+     */
+    static void bindAccountView(DisplayableProfileData profileData, View view) {
+        ImageView accountImage = view.findViewById(R.id.account_image);
+        accountImage.setImageDrawable(profileData.getImage());
+
+        TextView accountTextPrimary = view.findViewById(R.id.account_text_primary);
+        TextView accountTextSecondary = view.findViewById(R.id.account_text_secondary);
+
+        String fullName = profileData.getFullName();
+        if (!TextUtils.isEmpty(fullName)) {
+            accountTextPrimary.setText(fullName);
+            accountTextSecondary.setText(profileData.getAccountName());
+            accountTextSecondary.setVisibility(View.VISIBLE);
+        } else {
+            // Full name is not available, show the email in the primary TextView.
+            accountTextPrimary.setText(profileData.getAccountName());
+            accountTextSecondary.setVisibility(View.GONE);
+        }
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sms/SmsReceiverInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/sms/SmsReceiverInfoBar.java
index 0a82868..27e9eb26 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sms/SmsReceiverInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sms/SmsReceiverInfoBar.java
@@ -14,7 +14,7 @@
 import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ui.messages.infobar.ConfirmInfoBar;
+import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBarControlLayout;
 import org.chromium.components.infobars.InfoBarLayout;
 import org.chromium.ui.KeyboardVisibilityDelegate;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
index 1ebbff09..147b6ad7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
@@ -6,7 +6,6 @@
 
 import android.app.Activity;
 import android.graphics.Point;
-import android.os.Handler;
 import android.support.test.InstrumentationRegistry;
 import android.util.DisplayMetrics;
 
@@ -23,22 +22,26 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
+import org.chromium.chrome.browser.compositor.layouts.OverviewModeController;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.tabbed_mode.TabbedRootUiCoordinator;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.components.embedder_support.util.UrlConstants;
+import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.content_public.common.ContentUrlConstants;
 import org.chromium.net.test.EmbeddedTestServer;
+import org.chromium.ui.base.PageTransition;
 
 /**
  * Tests {@link NavigationHandler} navigating back/forward using overscroll history navigation.
- * TODO(jinsukkim): Add more tests (right swipe, tab switcher, etc).
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.
@@ -94,18 +97,34 @@
     private void swipeFromEdge(boolean leftEdge) {
         Point size = new Point();
         mActivityTestRule.getActivity().getWindowManager().getDefaultDisplay().getSize(size);
-
-        // Swipe from an edge toward the middle of the screen.
-        final int eventCounts = 100;
         final float startx = leftEdge ? mEdgeWidthPx / 2 : size.x - mEdgeWidthPx / 2;
-        final float y = size.y / 2;
-        final float step = (size.x / 2 - startx) / eventCounts;
+        final float endx = size.x / 2;
+        final float yMiddle = size.y / 2;
+        swipe(leftEdge, startx, endx, yMiddle);
+    }
+
+    // Make an edge swipe too short to trigger the navigation.
+    private void shortSwipeFromEdge(boolean leftEdge) {
+        Point size = new Point();
+        mActivityTestRule.getActivity().getWindowManager().getDefaultDisplay().getSize(size);
+        final float startx = leftEdge ? 0 : size.x;
+        final float endx = leftEdge ? mEdgeWidthPx : size.x - mEdgeWidthPx;
+        final float yMiddle = size.y / 2;
+        swipe(leftEdge, startx, endx, yMiddle);
+    }
+
+    private void swipe(boolean leftEdge, float startx, float endx, float y) {
+        // # of pixels (of reasonally small value) which a finger moves across
+        // per one motion event.
+        final float distancePx = 6.0f;
+        final float step = Math.signum(endx - startx) * distancePx;
+        final int eventCounts = (int) ((endx - startx) / step);
 
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mNavigationHandler.onDown();
-            float endx = startx + step;
-            for (int i = 0; i < eventCounts; i++, endx += step) {
-                mNavigationHandler.onScroll(startx, -step, 0, endx, y);
+            float nextx = startx + step;
+            for (int i = 0; i < eventCounts; i++, nextx += step) {
+                mNavigationHandler.onScroll(startx, -step, 0, nextx, y);
             }
             mNavigationHandler.release(true);
         });
@@ -113,6 +132,16 @@
 
     @Test
     @SmallTest
+    public void testShortSwipeDoesNotTriggerNavigation() {
+        mActivityTestRule.loadUrl(UrlConstants.NTP_URL);
+        shortSwipeFromEdge(LEFT_EDGE);
+        CriteriaHelper.pollUiThread(mNavigationHandler::isLayoutDetached);
+        Assert.assertEquals("Current page should not change", UrlConstants.NTP_URL,
+                currentTab().getUrlString());
+    }
+
+    @Test
+    @SmallTest
     public void testCloseChromeAtHistoryStackHead() {
         loadNewTabPage();
         final Activity activity = mActivityTestRule.getActivity();
@@ -125,6 +154,16 @@
 
     @Test
     @SmallTest
+    public void testLayoutGetsDetachedAfterUse() {
+        mActivityTestRule.loadUrl(UrlConstants.NTP_URL);
+        mActivityTestRule.loadUrl(UrlConstants.RECENT_TABS_URL);
+        swipeFromEdge(LEFT_EDGE);
+        CriteriaHelper.pollUiThread(mNavigationHandler::isLayoutDetached,
+                "Navigation Layout should be detached after use");
+    }
+
+    @Test
+    @SmallTest
     public void testSwipeNavigateOnNativePage() {
         mActivityTestRule.loadUrl(UrlConstants.NTP_URL);
         mActivityTestRule.loadUrl(UrlConstants.RECENT_TABS_URL);
@@ -141,11 +180,53 @@
         mActivityTestRule.loadUrl(ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
 
         assertNavigateOnSwipeFrom(LEFT_EDGE, mTestServer.getURL(RENDERED_PAGE));
-        // clang-format off
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            new Handler().postDelayed(() -> assertNavigateOnSwipeFrom(
-                    RIGHT_EDGE, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL), PAGELOAD_TIMEOUT_MS);
+        assertNavigateOnSwipeFrom(RIGHT_EDGE, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
+    }
+
+    @Test
+    @SmallTest
+    public void testLeftEdgeSwipeClosesTabLaunchedFromLink() {
+        Tab oldTab = currentTab();
+        TabCreator tabCreator = mActivityTestRule.getActivity().getTabCreator(false);
+        Tab newTab = TestThreadUtils.runOnUiThreadBlockingNoException(() -> {
+            return tabCreator.createNewTab(
+                    new LoadUrlParams(UrlConstants.RECENT_TABS_URL, PageTransition.LINK),
+                    TabLaunchType.FROM_LINK, oldTab);
         });
-        // clang-format on
+        Assert.assertEquals(newTab, currentTab());
+        swipeFromEdge(LEFT_EDGE);
+
+        // Assert that the new tab was closed and the old tab is the current tab again.
+        CriteriaHelper.pollUiThread(Criteria.equals(false, newTab::isInitialized));
+        Assert.assertEquals(oldTab, currentTab());
+        Assert.assertEquals("Chrome should remain in foreground", ActivityState.RESUMED,
+                ApplicationStatus.getStateForActivity(mActivityTestRule.getActivity()));
+    }
+
+    @Test
+    @SmallTest
+    public void testEdgeSwipeIsNoopInTabSwitcher() {
+        mActivityTestRule.loadUrl(UrlConstants.NTP_URL);
+        mActivityTestRule.loadUrl(UrlConstants.RECENT_TABS_URL);
+        setTabSwitcherModeAndWait(true);
+        swipeFromEdge(LEFT_EDGE);
+        Assert.assertTrue("Chrome should stay in tab switcher",
+                mActivityTestRule.getActivity().isInOverviewMode());
+        setTabSwitcherModeAndWait(false);
+        Assert.assertEquals("Current page should not change", UrlConstants.RECENT_TABS_URL,
+                currentTab().getUrlString());
+    }
+
+    /**
+     * Enter or exit the tab switcher with animations and wait for the scene to change.
+     * @param inSwitcher Whether to enter or exit the tab switcher.
+     */
+    private void setTabSwitcherModeAndWait(boolean inSwitcher) {
+        OverviewModeController controller = mActivityTestRule.getActivity().getLayoutManager();
+        if (inSwitcher) {
+            TestThreadUtils.runOnUiThreadBlocking(() -> controller.showOverview(false));
+        } else {
+            TestThreadUtils.runOnUiThreadBlocking(() -> controller.hideOverview(false));
+        }
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
index 8ac3822..f491bb40 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
@@ -721,13 +721,15 @@
     }
 
     /**
-     * Check that the check passwords preference is shown when the corresponding feature is enabled.
+     * Check that the check passwords preference is shown when the corresponding feature is enabled
+     * and the user is signed in.
      */
     @Test
     @SmallTest
     @Feature({"Preferences"})
     @EnableFeatures(ChromeFeatureList.PASSWORD_CHECK)
-    public void testCheckPasswordsEnabled() {
+    public void testCheckPasswordsEnabledSignedIn() {
+        mBrowserTestRule.addAndSignInTestAccount();
         final SettingsActivity settingsActivity = mSettingsActivityTestRule.startSettingsActivity();
 
         TestThreadUtils.runOnUiThreadBlocking(() -> {
@@ -739,6 +741,23 @@
 
     /**
      * Check that the check passwords preference is not shown when the corresponding feature is
+     * enabled but the user is not signed in.
+     */
+    @Test
+    @SmallTest
+    @Feature({"Preferences"})
+    @EnableFeatures(ChromeFeatureList.PASSWORD_CHECK)
+    public void testCheckPasswordsEnabledNotSignedIn() {
+        final SettingsActivity settingsActivity = mSettingsActivityTestRule.startSettingsActivity();
+
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            PasswordSettings passwordPrefs = mSettingsActivityTestRule.getFragment();
+            Assert.assertNull(passwordPrefs.findPreference(PasswordSettings.PREF_CHECK_PASSWORDS));
+        });
+    }
+
+    /**
+     * Check that the check passwords preference is not shown when the corresponding feature is
      * disabled.
      */
     @Test
@@ -746,6 +765,7 @@
     @Feature({"Preferences"})
     @DisableFeatures(ChromeFeatureList.PASSWORD_CHECK)
     public void testCheckPasswordsDisabled() {
+        mBrowserTestRule.addAndSignInTestAccount();
         final SettingsActivity settingsActivity = mSettingsActivityTestRule.startSettingsActivity();
 
         TestThreadUtils.runOnUiThreadBlocking(() -> {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
index c96231f..535c4c3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
@@ -6,15 +6,26 @@
 
 import static androidx.test.espresso.Espresso.onView;
 import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.action.ViewActions.pressBack;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
 import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE;
 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
+import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
 import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.core.AllOf.allOf;
 import static org.mockito.Mockito.verify;
 import static org.mockito.MockitoAnnotations.initMocks;
 
+import android.support.test.InstrumentationRegistry;
+
 import androidx.test.filters.MediumTest;
 
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -27,17 +38,20 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetCoordinator;
-import org.chromium.chrome.browser.signin.account_picker.AccountPickerCoordinator;
+import org.chromium.chrome.browser.signin.account_picker.AccountPickerDelegate;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
+import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.ProfileDataSource;
+import org.chromium.components.signin.test.util.FakeAccountManagerFacade;
 import org.chromium.components.signin.test.util.FakeProfileDataSource;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 /**
- * Tests account picker bottomsheet of the web signin flow.
+ * Tests account picker bottom sheet of the web signin flow.
  *
  * TODO(https://crbug.com/1090356): Add render tests for bottomsheet.
  */
@@ -45,6 +59,17 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Features.EnableFeatures({ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY})
 public class AccountPickerBottomSheetTest {
+    private static class CustomFakeProfileDataSource extends FakeProfileDataSource {
+        int getNumberOfObservers() {
+            return mObservers.size();
+        }
+    }
+
+    private static final String FULL_NAME1 = "Test Account1";
+    private static final String GIVEN_NAME1 = "Account1";
+    private static final String ACCOUNT_NAME1 = "test.account1@gmail.com";
+    private static final String ACCOUNT_NAME2 = "test.account2@gmail.com";
+
     @Rule
     public final Features.InstrumentationProcessor mProcessor =
             new Features.InstrumentationProcessor();
@@ -52,8 +77,11 @@
     private final ChromeTabbedActivityTestRule mActivityTestRule =
             new ChromeTabbedActivityTestRule();
 
+    private final CustomFakeProfileDataSource mFakeProfileDataSource =
+            new CustomFakeProfileDataSource();
+
     private final AccountManagerTestRule mAccountManagerTestRule =
-            new AccountManagerTestRule(new FakeProfileDataSource());
+            new AccountManagerTestRule(mFakeProfileDataSource);
 
     // Destroys the mock AccountManagerFacade in the end as ChromeActivity may needs
     // to unregister observers in the stub.
@@ -62,60 +90,176 @@
             RuleChain.outerRule(mAccountManagerTestRule).around(mActivityTestRule);
 
     @Mock
-    private AccountPickerCoordinator.Listener mAccountPickerListenerMock;
-
-    private final String mFullName1 = "Test Account1";
-    private final String mAccountName1 = "test.account1@gmail.com";
-    private final String mAccountName2 = "test.account2@gmail.com";
-    private AccountPickerBottomSheetCoordinator mAccountPickerBottomSheetCoordinator;
+    private AccountPickerDelegate mAccountPickerDelegateMock;
 
     @Before
     public void setUp() {
         initMocks(this);
-        addAccount(mAccountName1, mFullName1);
-        addAccount(mAccountName2, "");
+        addAccount(ACCOUNT_NAME1, FULL_NAME1, GIVEN_NAME1);
+        addAccount(ACCOUNT_NAME2, null, null);
         mActivityTestRule.startMainActivityOnBlankPage();
-        TestThreadUtils.runOnUiThreadBlocking(this::buildAndShowAccountPickerBottomSheet);
     }
 
     private void buildAndShowAccountPickerBottomSheet() {
-        mAccountPickerBottomSheetCoordinator =
-                new AccountPickerBottomSheetCoordinator(mActivityTestRule.getActivity(),
-                        mActivityTestRule.getActivity().getBottomSheetController(),
-                        mAccountPickerListenerMock);
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            AccountPickerBottomSheetCoordinator accountPickerBottomSheetCoordinator =
+                    new AccountPickerBottomSheetCoordinator(mActivityTestRule.getActivity(),
+                            mActivityTestRule.getActivity().getBottomSheetController(),
+                            mAccountPickerDelegateMock);
+        });
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
 
     @Test
     @MediumTest
-    public void testTitle() {
+    public void testCollapsedSheetWithAccount() {
+        buildAndShowAccountPickerBottomSheet();
         onView(withText(R.string.signin_account_picker_dialog_title)).check(matches(isDisplayed()));
+        onView(withText(ACCOUNT_NAME1)).check(matches(isDisplayed()));
+        onView(withText(FULL_NAME1)).check(matches(isDisplayed()));
+        String continueAsText = mActivityTestRule.getActivity().getString(
+                R.string.signin_promo_continue_as, GIVEN_NAME1);
+        onView(withText(continueAsText)).check(matches(isDisplayed()));
+        onView(withText(ACCOUNT_NAME2)).check(doesNotExist());
+        onView(withId(R.id.account_picker_account_list)).check(matches(not(isDisplayed())));
     }
 
     @Test
     @MediumTest
-    public void testAddAccount() {
+    public void testExpandedSheet() {
+        buildAndShowAccountPickerBottomSheet();
+        onView(withText(FULL_NAME1)).perform(click());
+        // Check expanded bottom sheet
+        onView(allOf(withText(ACCOUNT_NAME1), withEffectiveVisibility(VISIBLE)))
+                .check(matches(isDisplayed()));
+        onView(allOf(withText(FULL_NAME1), withEffectiveVisibility(VISIBLE)))
+                .check(matches(isDisplayed()));
+        onView(withText(ACCOUNT_NAME2)).check(matches(isDisplayed()));
+        onView(withText(R.string.signin_add_account)).check(matches(isDisplayed()));
+
+        onView(withId(R.id.account_picker_selected_account)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.account_picker_continue_as_button)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    @MediumTest
+    public void testCollapsedSheetWithZeroAccount() {
+        // As we have already added accounts in our current AccountManagerFacade mock
+        // Here since we want to test a zero account case, we would like to set up
+        // a new AccountManagerFacade mock with no account in it. The mock will be
+        // torn down in the end of the test in AccountManagerTestRule.
+        AccountManagerFacadeProvider.setInstanceForTests(
+                new FakeAccountManagerFacade(mFakeProfileDataSource));
+        buildAndShowAccountPickerBottomSheet();
+        onView(withText(ACCOUNT_NAME1)).check(doesNotExist());
+        onView(withText(ACCOUNT_NAME2)).check(doesNotExist());
+        onView(withId(R.id.account_picker_account_list)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.account_picker_selected_account)).check(matches(not(isDisplayed())));
         onView(withText(R.string.signin_add_account)).perform(click());
-        verify(mAccountPickerListenerMock).addAccount();
+        verify(mAccountPickerDelegateMock).addAccount();
     }
 
     @Test
     @MediumTest
-    public void testSelectDefaultAccount() {
-        onView(withText(mAccountName1)).check(matches(isDisplayed()));
-        onView(withText(mFullName1)).perform(click());
-        verify(mAccountPickerListenerMock).onAccountSelected(mAccountName1, true);
+    public void testDismissCollapsedSheet() {
+        buildAndShowAccountPickerBottomSheet();
+        onView(withText(ACCOUNT_NAME1)).check(matches(isDisplayed()));
+        BottomSheetController controller =
+                mActivityTestRule.getActivity().getBottomSheetController();
+        Assert.assertTrue(controller.isSheetOpen());
+        Assert.assertEquals(2, mFakeProfileDataSource.getNumberOfObservers());
+        onView(isRoot()).perform(pressBack());
+        Assert.assertFalse(controller.isSheetOpen());
+        Assert.assertEquals(0, mFakeProfileDataSource.getNumberOfObservers());
     }
 
     @Test
     @MediumTest
-    public void testSelectNonDefaultAccount() {
-        onView(withText(mAccountName2)).perform(click());
-        verify(mAccountPickerListenerMock).onAccountSelected(mAccountName2, false);
+    public void testDismissExpandedSheet() {
+        buildAndShowAccountPickerBottomSheet();
+        onView(withText(FULL_NAME1)).perform(click());
+        BottomSheetController controller =
+                mActivityTestRule.getActivity().getBottomSheetController();
+        Assert.assertTrue(controller.isSheetOpen());
+        Assert.assertEquals(2, mFakeProfileDataSource.getNumberOfObservers());
+        onView(isRoot()).perform(pressBack());
+        Assert.assertFalse(controller.isSheetOpen());
+        Assert.assertEquals(0, mFakeProfileDataSource.getNumberOfObservers());
     }
 
-    private void addAccount(String accountName, String fullName) {
+    @Test
+    @MediumTest
+    public void testProfileDataUpdateInExpandedSheet() {
+        buildAndShowAccountPickerBottomSheet();
+        onView(withText(FULL_NAME1)).perform(click());
+        String newFullName = "New Full Name1";
+        String newGivenName = "New Given Name1";
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mFakeProfileDataSource.setProfileData(ACCOUNT_NAME1,
+                    new ProfileDataSource.ProfileData(
+                            ACCOUNT_NAME1, null, newFullName, newGivenName));
+        });
+        onView(allOf(withText(newFullName), withEffectiveVisibility(VISIBLE)))
+                .check(matches(isDisplayed()));
+        // Check that profile data update when the bottom sheet is expanded won't
+        // toggle out any hidden part.
+        onView(withId(R.id.account_picker_selected_account)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.account_picker_continue_as_button)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    @MediumTest
+    public void testSignInDefaultAccountOnCollapsedSheet() {
+        buildAndShowAccountPickerBottomSheet();
+        String continueAsText = mActivityTestRule.getActivity().getString(
+                R.string.signin_promo_continue_as, GIVEN_NAME1);
+        onView(withText(continueAsText)).perform(click());
+        verify(mAccountPickerDelegateMock).signIn(ACCOUNT_NAME1);
+    }
+
+    @Test
+    @MediumTest
+    public void testSignInAnotherAccount() {
+        buildAndShowAccountPickerBottomSheet();
+        onView(withText(FULL_NAME1)).perform(click());
+        onView(withText(ACCOUNT_NAME2)).perform(click());
+        String continueAsText = mActivityTestRule.getActivity().getString(
+                R.string.signin_promo_continue_as, ACCOUNT_NAME2);
+        onView(withText(continueAsText)).perform(click());
+        verify(mAccountPickerDelegateMock).signIn(ACCOUNT_NAME2);
+    }
+
+    @Test
+    @MediumTest
+    public void testAddAccountOnExpandedSheet() {
+        buildAndShowAccountPickerBottomSheet();
+        onView(withText(FULL_NAME1)).perform(click());
+        onView(withText(R.string.signin_add_account)).perform(click());
+        verify(mAccountPickerDelegateMock).addAccount();
+    }
+
+    @Test
+    @MediumTest
+    public void testSelectAnotherAccountOnExpandedSheet() {
+        buildAndShowAccountPickerBottomSheet();
+        onView(withText(FULL_NAME1)).perform(click());
+        onView(withText(ACCOUNT_NAME2)).perform(click());
+
+        onView(allOf(withText(ACCOUNT_NAME2), withEffectiveVisibility(VISIBLE)))
+                .check(matches(isDisplayed()));
+        String continueAsText = mActivityTestRule.getActivity().getString(
+                R.string.signin_promo_continue_as, ACCOUNT_NAME2);
+        onView(withText(continueAsText)).check(matches(isDisplayed()));
+
+        onView(allOf(withText(ACCOUNT_NAME1), withEffectiveVisibility(VISIBLE)))
+                .check(doesNotExist());
+        onView(allOf(withText(FULL_NAME1), withEffectiveVisibility(VISIBLE))).check(doesNotExist());
+        onView(withId(R.id.account_picker_account_list)).check(matches(not(isDisplayed())));
+    }
+
+    private void addAccount(String accountName, String fullName, String givenName) {
         ProfileDataSource.ProfileData profileData =
-                new ProfileDataSource.ProfileData(accountName, null, fullName, null);
+                new ProfileDataSource.ProfileData(accountName, null, fullName, givenName);
         mAccountManagerTestRule.addAccount(accountName, profileData);
     }
 }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 578006e6..b6fd599 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-86.0.4185.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-86.0.4186.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 13b5d8e..9629e94 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1286,8 +1286,6 @@
     "prerender/prerender_manager.h",
     "prerender/prerender_manager_factory.cc",
     "prerender/prerender_manager_factory.h",
-    "prerender/prerender_message_filter.cc",
-    "prerender/prerender_message_filter.h",
     "prerender/prerender_processor_impl.cc",
     "prerender/prerender_processor_impl.h",
     "prerender/prerender_tab_helper.cc",
@@ -5855,6 +5853,7 @@
   }
   if (is_chromeos) {
     deps += [
+      "//chrome/browser/resources/chromeos/account_manager/components:web_components",
       "//chrome/browser/resources/chromeos/crostini_installer:polymer3_elements",
       "//chrome/browser/resources/chromeos/crostini_upgrader:polymer3_elements",
       "//chrome/browser/resources/chromeos/edu_login:polymer3_elements",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 41ebdda9..4d874d5 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1928,6 +1928,12 @@
      nullptr}};
 #endif  // defined(OS_ANDROID)
 
+#if defined(OS_CHROMEOS)
+constexpr char kAssistantBetterOnboardingInternalName[] =
+    "enable-assistant-better-onboarding";
+constexpr char kAssistantTimersV2InternalName[] = "enable-assistant-timers-v2";
+#endif  // OS_CHROMEOS
+
 // RECORDING USER METRICS FOR FLAGS:
 // -----------------------------------------------------------------------------
 // The first line of the entry is the internal name.
@@ -4399,6 +4405,16 @@
      FEATURE_VALUE_TYPE(
          chromeos::assistant::features::kEnableOnDeviceAssistant)},
 
+    {kAssistantBetterOnboardingInternalName,
+     flag_descriptions::kEnableAssistantBetterOnboardingName,
+     flag_descriptions::kEnableAssistantBetterOnboardingDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(
+         chromeos::assistant::features::kAssistantBetterOnboarding)},
+
+    {kAssistantTimersV2InternalName,
+     flag_descriptions::kEnableAssistantTimersV2Name,
+     flag_descriptions::kEnableAssistantTimersV2Description, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::assistant::features::kAssistantTimersV2)},
 #endif  // defined(OS_CHROMEOS)
 
 #if BUILDFLAG(ENABLE_CLICK_TO_CALL)
@@ -5422,6 +5438,10 @@
     {"help-app-release-notes", flag_descriptions::kHelpAppReleaseNotesName,
      flag_descriptions::kHelpAppReleaseNotesDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kHelpAppReleaseNotes)},
+    {"help-app-search-service-integration",
+     flag_descriptions::kHelpAppSearchServiceIntegrationName,
+     flag_descriptions::kHelpAppSearchServiceIntegrationDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kHelpAppSearchServiceIntegration)},
     {"media-app", flag_descriptions::kMediaAppName,
      flag_descriptions::kMediaAppDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kMediaApp)},
@@ -5832,6 +5852,14 @@
       channel != version_info::Channel::UNKNOWN) {
     return true;
   }
+
+  // The following flags are only available to teamfooders.
+  if (!strcmp(kAssistantBetterOnboardingInternalName, entry.internal_name) ||
+      !strcmp(kAssistantTimersV2InternalName, entry.internal_name)) {
+    constexpr base::Feature kTeamfoodFlags{"TeamfoodFlags",
+                                           base::FEATURE_DISABLED_BY_DEFAULT};
+    return !base::FeatureList::IsEnabled(kTeamfoodFlags);
+  }
 #endif  // defined(OS_CHROMEOS)
 
   // data-reduction-proxy-lo-fi and enable-data-reduction-proxy-lite-page
diff --git a/chrome/browser/apps/app_service/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon_factory.cc
index e98b050..cb55488e 100644
--- a/chrome/browser/apps/app_service/app_icon_factory.cc
+++ b/chrome/browser/apps/app_service/app_icon_factory.cc
@@ -209,36 +209,6 @@
       std::move(compressed_data_callback));
 }
 
-// Encode the ImageSkia to the compressed PNG data with the image's 1.0f scale
-// factor representation. Return the encoded PNG data.
-//
-// This function should not be called on the UI thread.
-std::vector<uint8_t> EncodeImage(const gfx::ImageSkia image) {
-  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
-                                                base::BlockingType::MAY_BLOCK);
-
-  std::vector<uint8_t> image_data;
-
-  const gfx::ImageSkiaRep& image_skia_rep = image.GetRepresentation(1.0f);
-  if (image_skia_rep.scale() != 1.0f) {
-    return image_data;
-  }
-
-  const SkBitmap& bitmap = image_skia_rep.GetBitmap();
-  if (bitmap.drawsNothing()) {
-    return image_data;
-  }
-
-  base::AssertLongCPUWorkAllowed();
-  constexpr bool discard_transparency = false;
-  bool success = gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, discard_transparency,
-                                                   &image_data);
-  if (!success) {
-    return std::vector<uint8_t>();
-  }
-  return image_data;
-}
-
 // This pipeline is meant to:
 // * Simplify loading icons, as things like effects and type are common
 //   to all loading.
@@ -362,19 +332,20 @@
           return;
         }
         FALLTHROUGH;
-      case apps::mojom::IconType::kUncompressed: {
-        // For uncompressed icon, apply the resize and pad effect.
-        icon_effects_ = static_cast<apps::IconEffects>(
-            icon_effects_ | apps::IconEffects::kResizeAndPad);
+      case apps::mojom::IconType::kUncompressed:
+        if (icon_type_ == apps::mojom::IconType::kUncompressed) {
+          // For uncompressed icon, apply the resize and pad effect.
+          icon_effects_ = static_cast<apps::IconEffects>(
+              icon_effects_ | apps::IconEffects::kResizeAndPad);
 
-        // For uncompressed icon, clear the standard icon effects: kBackground
-        // and kMask.
-        icon_effects_ = static_cast<apps::IconEffects>(
-            icon_effects_ & ~apps::IconEffects::kCrOsStandardBackground);
-        icon_effects_ = static_cast<apps::IconEffects>(
-            icon_effects_ & ~apps::IconEffects::kCrOsStandardMask);
+          // For uncompressed icon, clear the standard icon effects: kBackground
+          // and kMask.
+          icon_effects_ = static_cast<apps::IconEffects>(
+              icon_effects_ & ~apps::IconEffects::kCrOsStandardBackground);
+          icon_effects_ = static_cast<apps::IconEffects>(
+              icon_effects_ & ~apps::IconEffects::kCrOsStandardMask);
+        }
         FALLTHROUGH;
-      }
       case apps::mojom::IconType::kStandard:
         // If |icon_effects| are requested, we must always load the
         // uncompressed image to apply the icon effects, and then re-encode the
@@ -553,7 +524,7 @@
   processed_image.MakeThreadSafe();
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
-      base::BindOnce(&EncodeImage, processed_image),
+      base::BindOnce(&apps::EncodeImageToPngBytes, processed_image),
       base::BindOnce(&IconLoadingPipeline::CompleteWithCompressed,
                      base::WrapRefCounted(this)));
 }
@@ -649,6 +620,32 @@
 
 namespace apps {
 
+std::vector<uint8_t> EncodeImageToPngBytes(const gfx::ImageSkia image) {
+  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                base::BlockingType::MAY_BLOCK);
+
+  std::vector<uint8_t> image_data;
+
+  const gfx::ImageSkiaRep& image_skia_rep = image.GetRepresentation(1.0f);
+  if (image_skia_rep.scale() != 1.0f) {
+    return image_data;
+  }
+
+  const SkBitmap& bitmap = image_skia_rep.GetBitmap();
+  if (bitmap.drawsNothing()) {
+    return image_data;
+  }
+
+  base::AssertLongCPUWorkAllowed();
+  constexpr bool discard_transparency = false;
+  bool success = gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, discard_transparency,
+                                                   &image_data);
+  if (!success) {
+    return std::vector<uint8_t>();
+  }
+  return image_data;
+}
+
 void ApplyIconEffects(IconEffects icon_effects,
                       int size_hint_in_dip,
                       gfx::ImageSkia* image_skia) {
diff --git a/chrome/browser/apps/app_service/app_icon_factory.h b/chrome/browser/apps/app_service/app_icon_factory.h
index e5394e7d..1968d5f 100644
--- a/chrome/browser/apps/app_service/app_icon_factory.h
+++ b/chrome/browser/apps/app_service/app_icon_factory.h
@@ -44,6 +44,11 @@
   kCrOsStandardMask = 0x80,  // Apply the mask to the standard icon.
 };
 
+// Encode the ImageSkia to the compressed PNG data with the image's 1.0f scale
+// factor representation. Return the encoded PNG data.
+// This function should not be called on the UI thread.
+std::vector<uint8_t> EncodeImageToPngBytes(const gfx::ImageSkia image);
+
 // Modifies |image_skia| to apply icon post-processing effects like badging and
 // desaturation to gray.
 void ApplyIconEffects(IconEffects icon_effects,
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc
index fd28637..f0c96ba1 100644
--- a/chrome/browser/apps/app_service/arc_apps.cc
+++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -14,6 +14,8 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
 #include "base/stl_util.h"
+#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/arc_apps_factory.h"
@@ -48,6 +50,19 @@
 
 namespace {
 
+void CompleteWithCompressed(apps::mojom::Publisher::LoadIconCallback callback,
+                            std::vector<uint8_t> data) {
+  if (data.empty()) {
+    std::move(callback).Run(apps::mojom::IconValue::New());
+    return;
+  }
+  apps::mojom::IconValuePtr iv = apps::mojom::IconValue::New();
+  iv->icon_type = apps::mojom::IconType::kCompressed;
+  iv->compressed = std::move(data);
+  iv->is_placeholder_icon = false;
+  std::move(callback).Run(std::move(iv));
+}
+
 void OnArcAppIconCompletelyLoaded(
     apps::mojom::IconType icon_type,
     int32_t size_hint_in_dip,
@@ -64,23 +79,26 @@
   iv->is_placeholder_icon = false;
 
   switch (icon_type) {
-    case apps::mojom::IconType::kCompressed: {
-      auto& compressed_images = icon->compressed_images();
-      auto iter =
-          compressed_images.find(apps_util::GetPrimaryDisplayUIScaleFactor());
-      if (iter == compressed_images.end()) {
-        std::move(callback).Run(apps::mojom::IconValue::New());
-        return;
+    case apps::mojom::IconType::kCompressed:
+      if (!base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
+        auto& compressed_images = icon->compressed_images();
+        auto iter =
+            compressed_images.find(apps_util::GetPrimaryDisplayUIScaleFactor());
+        if (iter == compressed_images.end()) {
+          std::move(callback).Run(apps::mojom::IconValue::New());
+          return;
+        }
+        const std::string& data = iter->second;
+        iv->compressed = std::vector<uint8_t>(data.begin(), data.end());
+        if (icon_effects != apps::IconEffects::kNone) {
+          // TODO(crbug.com/988321): decompress the image, apply icon effects
+          // then re-compress.
+        }
+        break;
       }
-      const std::string& data = iter->second;
-      iv->compressed = std::vector<uint8_t>(data.begin(), data.end());
-      if (icon_effects != apps::IconEffects::kNone) {
-        // TODO(crbug.com/988321): decompress the image, apply icon effects then
-        // re-compress.
-      }
-      break;
-    }
+      FALLTHROUGH;
     case apps::mojom::IconType::kUncompressed:
+      FALLTHROUGH;
     case apps::mojom::IconType::kStandard: {
       if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
         iv->uncompressed = gfx::ImageSkiaOperations::CreateSuperimposedImage(
@@ -99,6 +117,15 @@
       break;
   }
 
+  if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon) &&
+      icon_type == apps::mojom::IconType::kCompressed) {
+    iv->uncompressed.MakeThreadSafe();
+    base::ThreadPool::PostTaskAndReplyWithResult(
+        FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+        base::BindOnce(&apps::EncodeImageToPngBytes, iv->uncompressed),
+        base::BindOnce(&CompleteWithCompressed, std::move(callback)));
+    return;
+  }
   std::move(callback).Run(std::move(iv));
 }
 
diff --git a/chrome/browser/apps/app_service/arc_icon_once_loader.cc b/chrome/browser/apps/app_service/arc_icon_once_loader.cc
index 13b91a1..ea080c3d 100644
--- a/chrome/browser/apps/app_service/arc_icon_once_loader.cc
+++ b/chrome/browser/apps/app_service/arc_icon_once_loader.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/apps/app_service/arc_icon_once_loader.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_icon.h"
+#include "chrome/common/chrome_features.h"
 
 namespace apps {
 
@@ -73,10 +74,16 @@
   switch (icon_type_) {
     case apps::mojom::IconType::kUnknown:
     case apps::mojom::IconType::kUncompressed:
-      icon_type = ArcAppIcon::IconType::kUncompressed;
+      icon_type =
+          base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)
+              ? ArcAppIcon::IconType::kAdaptive
+              : ArcAppIcon::IconType::kUncompressed;
       break;
     case apps::mojom::IconType::kCompressed:
-      icon_type = ArcAppIcon::IconType::kCompressed;
+      icon_type =
+          base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)
+              ? ArcAppIcon::IconType::kAdaptive
+              : ArcAppIcon::IconType::kCompressed;
       break;
     case apps::mojom::IconType::kStandard:
       icon_type = ArcAppIcon::IconType::kAdaptive;
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index f8dfa35..e75e668 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -226,7 +226,8 @@
         <include name="IDR_EDU_LOGIN_EDU_LOGIN_SIGNIN_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\edu_login\edu_login_signin.js" use_base_dir="false" type ="BINDATA" />
         <include name="IDR_FAMILY_LINK_LOGO_SVG" file="resources\chromeos\family_link_logo.svg" type="BINDATA" />
 
-        <!-- Chrome OS Account Manager welcome screen resources -->
+        <!-- Chrome OS Account Manager resources -->
+        <include name="IDR_ACCOUNT_MANAGER_COMPONENTS_ERROR_SCREEN_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\account_manager\components\error_screen.js" use_base_dir="false" type ="BINDATA"/>
         <include name="IDR_ACCOUNT_MANAGER_SHARED_CSS" file="resources\chromeos\account_manager\account_manager_shared.css" type="BINDATA" />
         <include name="IDR_ACCOUNT_MANAGER_WELCOME_HTML" file="resources\chromeos\account_manager\account_manager_welcome.html" allowexternalscript="true" type="BINDATA" preprocess="true"/>
         <include name="IDR_ACCOUNT_MANAGER_WELCOME_JS" file="resources\chromeos\account_manager\account_manager_welcome.js" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 70027c7..e6d590ba 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -2052,7 +2052,7 @@
 TEST_F(ChromeBrowsingDataRemoverDelegateTest,
        RemoveCompromisedCredentialsByTimeOnly) {
   RemovePasswordsTester tester(GetProfile());
-  base::Callback<bool(const GURL&)> empty_filter;
+  base::RepeatingCallback<bool(const GURL&)> empty_filter;
 
   EXPECT_CALL(*tester.store(), RemoveCompromisedCredentialsByUrlAndTimeImpl(
                                    ProbablySameFilter(empty_filter),
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 7b22c977..e0a08a6b 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -96,7 +96,6 @@
 #include "chrome/browser/prerender/isolated/isolated_prerender_url_loader_interceptor.h"
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_manager_factory.h"
-#include "chrome/browser/prerender/prerender_message_filter.h"
 #include "chrome/browser/prerender/prerender_util.h"
 #include "chrome/browser/previews/previews_content_util.h"
 #include "chrome/browser/previews/previews_service.h"
@@ -1506,7 +1505,6 @@
 #if BUILDFLAG(ENABLE_PRINTING)
   host->AddFilter(new printing::PrintingMessageFilter(id, profile));
 #endif
-  host->AddFilter(new prerender::PrerenderMessageFilter(id));
 
   WebRtcLoggingController::AttachToRenderProcessHost(
       host, g_browser_process->webrtc_log_uploader());
diff --git a/chrome/browser/chromeos/arc/session/arc_session_manager.cc b/chrome/browser/chromeos/arc/session/arc_session_manager.cc
index 66eb260..908926b 100644
--- a/chrome/browser/chromeos/arc/session/arc_session_manager.cc
+++ b/chrome/browser/chromeos/arc/session/arc_session_manager.cc
@@ -154,6 +154,32 @@
   return true;
 }
 
+// Defines the conditions that require UI to present eventual error conditions
+// to the end user.
+//
+// Don't show UI for ARC Kiosk because the only one UI in kiosk mode must
+// be the kiosk app. In case of error the UI will be useless as well, because
+// in typical use case there will be no one nearby the kiosk device, who can
+// do some action to solve the problem be means of UI.
+// Same considerations apply for MGS sessions in Demo Mode.
+// All other managed sessions will be attended by a user and require an error
+// UI.
+bool ShouldUseErrorDialog() {
+  if (!g_ui_enabled)
+    return false;
+
+  if (IsArcOptInVerificationDisabled())
+    return false;
+
+  if (IsArcKioskMode())
+    return false;
+
+  if (chromeos::DemoSession::IsDeviceInDemoMode())
+    return false;
+
+  return true;
+}
+
 void ResetStabilityMetrics() {
   // TODO(shaochuan): Make this an event observable by StabilityMetricsManager
   // and eliminate this null check.
@@ -538,13 +564,7 @@
   // ARC support Chrome app is rarely used (only opt-in and re-auth flow).
   // So, it may be better to initialize it lazily.
   // TODO(hidehiko): Revisit to think about lazy initialization.
-  //
-  // Don't show UI for ARC Kiosk because the only one UI in kiosk mode must
-  // be the kiosk app. In case of error the UI will be useless as well, because
-  // in typical use case there will be no one nearby the kiosk device, who can
-  // do some action to solve the problem be means of UI.
-  if (g_ui_enabled && !IsArcOptInVerificationDisabled() &&
-      !IsRobotOrOfflineDemoAccountMode()) {
+  if (ShouldUseErrorDialog()) {
     DCHECK(!support_host_);
     support_host_ = std::make_unique<ArcSupportHost>(profile_);
     support_host_->SetErrorDelegate(this);
@@ -1020,11 +1040,6 @@
   switch (result) {
     case policy::AndroidManagementClient::Result::UNMANAGED:
       VLOG(1) << "Starting ARC for first sign in.";
-      sign_in_start_time_ = base::TimeTicks::Now();
-      arc_sign_in_timer_.Start(
-          FROM_HERE, GetArcSignInTimeout(),
-          base::BindOnce(&ArcSessionManager::OnArcSignInTimeout,
-                         weak_ptr_factory_.GetWeakPtr()));
       StartArc();
       // Since opt-in is an explicit user (or admin) action, relax the
       // cgroups restriction now.
@@ -1091,6 +1106,8 @@
       << state_;
   state_ = State::ACTIVE;
 
+  MaybeStartTimer();
+
   // ARC must be started only if no pending data removal request exists.
   DCHECK(!profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested));
 
@@ -1210,6 +1227,22 @@
   RequestEnableImpl();
 }
 
+// Starts a timer to check if provisioning takes too loong.
+// The timer will not be set if this device was previously provisioned
+// successfully.
+void ArcSessionManager::MaybeStartTimer() {
+  if (IsArcProvisioned(profile_)) {
+    return;
+  }
+
+  VLOG(1) << "Setup provisioning timer";
+  sign_in_start_time_ = base::TimeTicks::Now();
+  arc_sign_in_timer_.Start(
+      FROM_HERE, GetArcSignInTimeout(),
+      base::BindOnce(&ArcSessionManager::OnArcSignInTimeout,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
 void ArcSessionManager::OnWindowClosed() {
   CancelAuthCode();
 }
diff --git a/chrome/browser/chromeos/arc/session/arc_session_manager.h b/chrome/browser/chromeos/arc/session/arc_session_manager.h
index 20abfeae0e..454f0eb 100644
--- a/chrome/browser/chromeos/arc/session/arc_session_manager.h
+++ b/chrome/browser/chromeos/arc/session/arc_session_manager.h
@@ -374,6 +374,11 @@
   // is fixed.
   void MaybeReenableArc();
 
+  // Starts a timer to check if provisioning takes too long.
+  // The timer will not be set if this device was previously provisioned
+  // successfully.
+  void MaybeStartTimer();
+
   // Requests the support host (if it exists) to show the error, and notifies
   // the observers.
   void ShowArcSupportHostError(ArcSupportHost::Error error,
diff --git a/chrome/browser/chromeos/arc/session/arc_session_manager_unittest.cc b/chrome/browser/chromeos/arc/session/arc_session_manager_unittest.cc
index 013b2c97..02d143a8 100644
--- a/chrome/browser/chromeos/arc/session/arc_session_manager_unittest.cc
+++ b/chrome/browser/chromeos/arc/session/arc_session_manager_unittest.cc
@@ -325,9 +325,10 @@
   arc_session_manager()->OnTermsOfServiceNegotiatedForTesting(true);
   ASSERT_EQ(ArcSessionManager::State::CHECKING_ANDROID_MANAGEMENT,
             arc_session_manager()->state());
+  EXPECT_TRUE(arc_session_manager()->sign_in_start_time().is_null());
   arc_session_manager()->StartArcForTesting();
 
-  EXPECT_TRUE(arc_session_manager()->sign_in_start_time().is_null());
+  EXPECT_FALSE(arc_session_manager()->sign_in_start_time().is_null());
   EXPECT_FALSE(arc_session_manager()->arc_start_time().is_null());
 
   ASSERT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state());
@@ -509,7 +510,9 @@
   arc_session_manager()->OnTermsOfServiceNegotiatedForTesting(true);
   ASSERT_EQ(ArcSessionManager::State::CHECKING_ANDROID_MANAGEMENT,
             arc_session_manager()->state());
+  EXPECT_TRUE(arc_session_manager()->sign_in_start_time().is_null());
   arc_session_manager()->StartArcForTesting();
+  EXPECT_FALSE(arc_session_manager()->sign_in_start_time().is_null());
   EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state());
 
   // Here, provisining is not yet completed, so kArcSignedIn should be false.
@@ -521,7 +524,6 @@
   arc_session_manager()->OnProvisioningFinished(ProvisioningResult::SUCCESS);
   EXPECT_TRUE(prefs->GetBoolean(prefs::kArcSignedIn));
   EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state());
-  EXPECT_TRUE(arc_session_manager()->sign_in_start_time().is_null());
   EXPECT_TRUE(arc_session_manager()->IsPlaystoreLaunchRequestedForTesting());
 }
 
diff --git a/chrome/browser/chromeos/crostini/crostini_stability_monitor.h b/chrome/browser/chromeos/crostini/crostini_stability_monitor.h
index ee69abb..090a243 100644
--- a/chrome/browser/chromeos/crostini/crostini_stability_monitor.h
+++ b/chrome/browser/chromeos/crostini/crostini_stability_monitor.h
@@ -19,14 +19,27 @@
 
 // These values are logged to UMA. Entries should not be renumbered and numeric
 // values should never be reused. Please keep in sync with
-// CrostiniFailureClasses in src/tools/metrics/histograms/enums.xml.
+// CrostiniFailureClasses in src/tools/metrics/histograms/enums.xml and the copy
+// in src/platform2/vm_tools/cicerone/crash_listener_impl.cc
 enum class FailureClasses {
   ConciergeStopped = 0,
   CiceroneStopped = 1,
   SeneschalStopped = 2,
   ChunneldStopped = 3,
   VmStopped = 4,
-  kMaxValue = VmStopped,
+  VmSyslogStopped = 5,
+  VshdStopped = 6,
+  LxcFsStopped = 7,
+  TremplinStopped = 8,
+  NdproxydStopped = 9,
+  McastdStopped = 10,
+  LxdStopped = 11,
+  GarconStopped = 12,
+  SommelierStopped = 13,
+  SommelierXStopped = 14,
+  CrosSftpStopped = 15,
+  CrosNotificationdStopped = 16,
+  kMaxValue = CrosNotificationdStopped,
 };
 
 class CrostiniStabilityMonitor : chromeos::ConciergeClient::Observer,
diff --git a/chrome/browser/chromeos/dbus/plugin_vm_service_provider.cc b/chrome/browser/chromeos/dbus/plugin_vm_service_provider.cc
index 3e160f6..3788a8e1 100644
--- a/chrome/browser/chromeos/dbus/plugin_vm_service_provider.cc
+++ b/chrome/browser/chromeos/dbus/plugin_vm_service_provider.cc
@@ -10,16 +10,19 @@
 #include "base/bind.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h"
 #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
-#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #include "chrome/browser/ui/webui/settings/chromeos/app_management/app_management_uma.h"
 #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chromeos/dbus/plugin_vm_service/plugin_vm_service.pb.h"
+#include "components/prefs/pref_service.h"
+#include "components/user_manager/user_manager.h"
 #include "dbus/message.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
@@ -30,6 +33,14 @@
 constexpr char kShowSettingsPageDetails[] = "pluginVm/details";
 constexpr char kShowSettingsPageSharedPaths[] = "pluginVm/sharedPaths";
 
+namespace {
+Profile* GetPrimaryProfile() {
+  const user_manager::User* primary_user =
+      user_manager::UserManager::Get()->GetPrimaryUser();
+  return chromeos::ProfileHelper::Get()->GetProfileByUser(primary_user);
+}
+}  // namespace
+
 namespace chromeos {
 
 PluginVmServiceProvider::PluginVmServiceProvider() {}
@@ -56,6 +67,12 @@
                           weak_ptr_factory_.GetWeakPtr()),
       base::BindRepeating(&PluginVmServiceProvider::OnExported,
                           weak_ptr_factory_.GetWeakPtr()));
+  exported_object->ExportMethod(
+      kPluginVmServiceInterface, kPluginVmServiceGetPermissionsMethod,
+      base::BindRepeating(&PluginVmServiceProvider::GetPermissions,
+                          weak_ptr_factory_.GetWeakPtr()),
+      base::BindRepeating(&PluginVmServiceProvider::OnExported,
+                          weak_ptr_factory_.GetWeakPtr()));
 }
 
 void PluginVmServiceProvider::OnExported(const std::string& interface_name,
@@ -101,14 +118,15 @@
     return;
   }
 
-  Profile* profile = ProfileManager::GetPrimaryUserProfile();
+  Profile* primary_profile = GetPrimaryProfile();
   if (request.subpage_path() == kShowSettingsPageDetails) {
     chrome::ShowAppManagementPage(
-        profile, plugin_vm::kPluginVmShelfAppId,
+        primary_profile, plugin_vm::kPluginVmShelfAppId,
         AppManagementEntryPoint::kDBusServicePluginVm);
   } else if (request.subpage_path() == kShowSettingsPageSharedPaths) {
     chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
-        profile, chromeos::settings::mojom::kPluginVmSharedPathsSubpagePath);
+        primary_profile,
+        chromeos::settings::mojom::kPluginVmSharedPathsSubpagePath);
   } else {
     constexpr char error_message[] = "Invalid subpage_path";
     LOG(ERROR) << error_message;
@@ -127,8 +145,22 @@
   std::unique_ptr<dbus::Response> response =
       dbus::Response::FromMethodCall(method_call);
   plugin_vm_service::GetAppLicenseUserIdResponse payload;
-  payload.set_user_id(plugin_vm::GetPluginVmUserIdForProfile(
-      ProfileManager::GetPrimaryUserProfile()));
+  payload.set_user_id(
+      plugin_vm::GetPluginVmUserIdForProfile(GetPrimaryProfile()));
+  dbus::MessageWriter writer(response.get());
+  writer.AppendProtoAsArrayOfBytes(payload);
+  std::move(response_sender).Run(std::move(response));
+}
+
+void PluginVmServiceProvider::GetPermissions(
+    dbus::MethodCall* method_call,
+    dbus::ExportedObject::ResponseSender response_sender) {
+  std::unique_ptr<dbus::Response> response =
+      dbus::Response::FromMethodCall(method_call);
+  plugin_vm_service::GetPermissionsResponse payload;
+  payload.set_data_collection_enabled(
+      GetPrimaryProfile()->GetPrefs()->GetBoolean(
+          plugin_vm::prefs::kPluginVmDataCollectionAllowed));
   dbus::MessageWriter writer(response.get());
   writer.AppendProtoAsArrayOfBytes(payload);
   std::move(response_sender).Run(std::move(response));
diff --git a/chrome/browser/chromeos/dbus/plugin_vm_service_provider.h b/chrome/browser/chromeos/dbus/plugin_vm_service_provider.h
index 027629e2..231453c 100644
--- a/chrome/browser/chromeos/dbus/plugin_vm_service_provider.h
+++ b/chrome/browser/chromeos/dbus/plugin_vm_service_provider.h
@@ -33,13 +33,22 @@
 //  string device_id = 2; // If it is available, this contains the
 //                        // directory API ID, if not, this contains
 //                        // the empty string.
+// })
 //
 // ShowSettingsPage:
 // % dbus-send --system --type=method_call --print-reply
-//     --dest=org.chromium.PluginVmService /org/chromium/PluginVmService
-//     org.chromium.PluginVmServiceInterface.ShowSettingsPage
-//     array:byte:0x0a,0x10,0x70,0x6c,0x75,0x67,0x69,0x6e,0x56,0x6d,0x2f,0x64,
-//     0x65,0x74,0x61,0x69,0x6c,0x73
+// --dest=org.chromium.PluginVmService /org/chromium/PluginVmService
+// org.chromium.PluginVmServiceInterface.ShowSettingsPage
+// array:byte:0x0a,0x10,0x70,0x6c,0x75,0x67,0x69,0x6e,0x56,0x6d,0x2f,0x64,0x65,
+// 0x74,0x61,0x69,0x6c,0x73
+//
+// GetPermissions:
+// % dbus-send --system --type=method_call --print-reply
+// --dest=org.chromium.PluginVmService /org/chromium/PluginVmService
+// org.chromium.PluginVmServiceInterface.GetPermissions
+//
+// % (returns message GetPermissionsResponse {
+//  bool data_collection_enabled = 1; // Data collection enablement status.
 // })
 //
 // GetUserId:
@@ -51,6 +60,7 @@
 //  string plugin_vm_user_id = 1; // If available, this contains the PluginVm
 //                                // user id, if not, this contains the
 //                                // empty string.
+// })
 class PluginVmServiceProvider
     : public CrosDBusService::ServiceProviderInterface {
  public:
@@ -61,7 +71,7 @@
   void Start(scoped_refptr<dbus::ExportedObject> exported_object) override;
 
  private:
-  // Called from ExportedObject when GetLicenseDataResponse() is exported as a
+  // Called from ExportedObject when one of the service methods is exported as a
   // D-Bus method or failed to be exported.
   void OnExported(const std::string& interface_name,
                   const std::string& method_name,
@@ -83,6 +93,12 @@
   void GetUserId(dbus::MethodCall* method_call,
                  dbus::ExportedObject::ResponseSender response_sender);
 
+  // Called from PluginVm process to retrieve permissions info. Embeds a
+  // |plugin_vm_service::GetPermissionsResponse| in the payload for the
+  // response.
+  void GetPermissions(dbus::MethodCall* method_call,
+                      dbus::ExportedObject::ResponseSender response_sender);
+
   // Keep this last so that all weak pointers will be invalidated at the
   // beginning of destruction.
   base::WeakPtrFactory<PluginVmServiceProvider> weak_ptr_factory_{this};
diff --git a/chrome/browser/chromeos/extensions/default_app_order.cc b/chrome/browser/chromeos/extensions/default_app_order.cc
index fbf245b..6b11aff 100644
--- a/chrome/browser/chromeos/extensions/default_app_order.cc
+++ b/chrome/browser/chromeos/extensions/default_app_order.cc
@@ -54,11 +54,12 @@
     arc::kGoogleCalendarAppId,
     extension_misc::kYoutubeAppId,
     arc::kYoutubeAppId,
+    arc::kYoutubeMusicAppId,                 // Youtube Music ARC app
+    default_web_apps::kYoutubeMusicAppId,    // Youtube Music Web app
     arc::kPlayMoviesAppId,                   // Play Movies & TV ARC app
     extension_misc::kGooglePlayMoviesAppId,  // Play Movies & TV Chrome app
     arc::kPlayMusicAppId,                    // Play Music ARC app
     extension_misc::kGooglePlayMusicAppId,   // Play Music Chrome app
-    default_web_apps::kYoutubeMusicAppId,
     arc::kPlayGamesAppId,
     arc::kPlayBooksAppId,                   // Play Books ARC app
     extension_misc::kGooglePlayBooksAppId,  // Play Books Chrome app
diff --git a/chrome/browser/chromeos/local_search_service/index.cc b/chrome/browser/chromeos/local_search_service/index.cc
index 1daf343..4ab359b 100644
--- a/chrome/browser/chromeos/local_search_service/index.cc
+++ b/chrome/browser/chromeos/local_search_service/index.cc
@@ -14,9 +14,13 @@
 
 namespace {
 
-void LogSearchResultsStats(const std::string& histogram_prefix,
-                           ResponseStatus status,
-                           size_t num_results) {
+// Only logs metrics if |histogram_prefix| is not empty.
+void MaybeLogSearchResultsStats(const std::string& histogram_prefix,
+                                ResponseStatus status,
+                                size_t num_results) {
+  if (histogram_prefix.empty())
+    return;
+
   base::UmaHistogramEnumeration(histogram_prefix + ".ResponseStatus", status);
   if (status == ResponseStatus::kSuccess) {
     // Only logs number of results if search is a success.
@@ -25,6 +29,15 @@
   }
 }
 
+// Only logs metrics if |histogram_prefix| is not empty.
+void MaybeLogIndexIdAndBackendType(const std::string& histogram_prefix,
+                                   Backend backend) {
+  if (histogram_prefix.empty())
+    return;
+
+  base::UmaHistogramEnumeration(histogram_prefix + ".Backend", backend);
+}
+
 std::string IndexIdBasedHistogramPrefix(IndexId index_id) {
   const std::string prefix = "LocalSearchService.";
   switch (index_id) {
@@ -37,7 +50,10 @@
 
 }  // namespace
 
-Index::Index(IndexId index_id) : index_id_(index_id) {
+Index::Index(IndexId index_id, Backend backend) : index_id_(index_id) {
+  // TODO(jiameng): currently only support linear map.
+  DCHECK_EQ(backend, Backend::kLinearMap);
+
   histogram_prefix_ = IndexIdBasedHistogramPrefix(*index_id_);
   linear_map_search_ = std::make_unique<LinearMapSearch>();
   if (!g_browser_process || !g_browser_process->local_state()) {
@@ -48,6 +64,8 @@
       std::make_unique<SearchMetricsReporter>(g_browser_process->local_state());
   DCHECK(reporter_);
   reporter_->SetIndexId(*index_id_);
+
+  MaybeLogIndexIdAndBackendType(histogram_prefix_, backend);
 }
 
 Index::~Index() = default;
@@ -73,8 +91,8 @@
                            std::vector<Result>* results) {
   DCHECK(linear_map_search_);
   ResponseStatus status = linear_map_search_->Find(query, max_results, results);
-  if (!histogram_prefix_.empty())
-    LogSearchResultsStats(histogram_prefix_, status, results->size());
+  MaybeLogSearchResultsStats(histogram_prefix_, status, results->size());
+
   if (reporter_)
     reporter_->OnSearchPerformed();
 
diff --git a/chrome/browser/chromeos/local_search_service/index.h b/chrome/browser/chromeos/local_search_service/index.h
index 949732c..77eebb7 100644
--- a/chrome/browser/chromeos/local_search_service/index.h
+++ b/chrome/browser/chromeos/local_search_service/index.h
@@ -26,7 +26,7 @@
 // backends that provide actual data storage/indexing/search functions.
 class Index {
  public:
-  explicit Index(IndexId index_id);
+  Index(IndexId index_id, Backend backend);
   ~Index();
 
   Index(const Index&) = delete;
diff --git a/chrome/browser/chromeos/local_search_service/index_unittest.cc b/chrome/browser/chromeos/local_search_service/index_unittest.cc
index 41da2e5c..04bfdaa 100644
--- a/chrome/browser/chromeos/local_search_service/index_unittest.cc
+++ b/chrome/browser/chromeos/local_search_service/index_unittest.cc
@@ -27,10 +27,8 @@
 void CheckSearchParams(const SearchParams& actual,
                        const SearchParams& expected) {
   EXPECT_DOUBLE_EQ(actual.relevance_threshold, expected.relevance_threshold);
-  EXPECT_DOUBLE_EQ(actual.partial_match_penalty_rate,
-                   expected.partial_match_penalty_rate);
-  EXPECT_EQ(actual.use_prefix_only, expected.use_prefix_only);
-  EXPECT_EQ(actual.use_edit_distance, expected.use_edit_distance);
+  EXPECT_DOUBLE_EQ(actual.prefix_threshold, expected.prefix_threshold);
+  EXPECT_DOUBLE_EQ(actual.fuzzy_threshold, expected.fuzzy_threshold);
 }
 
 void FindAndCheckResults(Index* index,
@@ -72,7 +70,8 @@
 
 class IndexTest : public testing::Test {
   void SetUp() override {
-    index_ = std::make_unique<Index>(IndexId::kCrosSettings);
+    index_ =
+        std::make_unique<Index>(IndexId::kCrosSettings, Backend::kLinearMap);
   }
 
  protected:
@@ -92,10 +91,8 @@
     SearchParams search_params;
     const SearchParams default_params;
     search_params.relevance_threshold = default_params.relevance_threshold / 2;
-    search_params.partial_match_penalty_rate =
-        default_params.partial_match_penalty_rate / 2;
-    search_params.use_prefix_only = !default_params.use_prefix_only;
-    search_params.use_edit_distance = !default_params.use_edit_distance;
+    search_params.prefix_threshold = default_params.prefix_threshold / 2;
+    search_params.fuzzy_threshold = default_params.fuzzy_threshold / 2;
 
     index_->SetSearchParams(search_params);
 
diff --git a/chrome/browser/chromeos/local_search_service/linear_map_search.cc b/chrome/browser/chromeos/local_search_service/linear_map_search.cc
index 7002cb11..bed5fe1 100644
--- a/chrome/browser/chromeos/local_search_service/linear_map_search.cc
+++ b/chrome/browser/chromeos/local_search_service/linear_map_search.cc
@@ -35,9 +35,6 @@
 bool IsItemRelevant(const TokenizedString& query,
                     const std::vector<TokenizedStringWithId>& search_tags,
                     double relevance_threshold,
-                    bool use_prefix_only,
-                    bool use_edit_distance,
-                    double partial_match_penalty_rate,
                     double* relevance_score,
                     Positions* positions) {
   DCHECK(relevance_score);
@@ -49,8 +46,10 @@
   for (const auto& tag : search_tags) {
     FuzzyTokenizedStringMatch match;
     if (match.IsRelevant(query, *(tag.second), relevance_threshold,
-                         use_prefix_only, true /* use_weighted_ratio */,
-                         use_edit_distance, partial_match_penalty_rate, 0.1)) {
+                         false /* use_prefix_only */,
+                         true /* use_weighted_ratio */,
+                         false /* use_edit_distance */,
+                         0.9 /* partial_match_penalty_rate */, 0.1)) {
       *relevance_score = match.relevance();
       Position position;
       position.content_id = tag.first;
@@ -137,11 +136,9 @@
   for (const auto& item : data_) {
     double relevance_score = 0.0;
     Positions positions;
-    if (IsItemRelevant(
-            tokenized_query, item.second, search_params_.relevance_threshold,
-            search_params_.use_prefix_only, search_params_.use_edit_distance,
-            search_params_.partial_match_penalty_rate, &relevance_score,
-            &positions)) {
+    if (IsItemRelevant(tokenized_query, item.second,
+                       search_params_.relevance_threshold, &relevance_score,
+                       &positions)) {
       Result result;
       result.id = item.first;
       result.score = relevance_score;
diff --git a/chrome/browser/chromeos/local_search_service/local_search_service.cc b/chrome/browser/chromeos/local_search_service/local_search_service.cc
index f04b61a..f68e426cc 100644
--- a/chrome/browser/chromeos/local_search_service/local_search_service.cc
+++ b/chrome/browser/chromeos/local_search_service/local_search_service.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "chrome/browser/chromeos/local_search_service/index.h"
-#include "chrome/browser/chromeos/local_search_service/shared_structs.h"
 
 namespace local_search_service {
 
@@ -15,10 +14,11 @@
 
 LocalSearchService::~LocalSearchService() = default;
 
-Index* LocalSearchService::GetIndex(IndexId index_id) {
+Index* LocalSearchService::GetIndex(IndexId index_id, Backend backend) {
   auto it = indices_.find(index_id);
   if (it == indices_.end()) {
-    it = indices_.emplace(index_id, std::make_unique<Index>(index_id)).first;
+    it = indices_.emplace(index_id, std::make_unique<Index>(index_id, backend))
+             .first;
   }
   DCHECK(it != indices_.end());
   DCHECK(it->second);
diff --git a/chrome/browser/chromeos/local_search_service/local_search_service.h b/chrome/browser/chromeos/local_search_service/local_search_service.h
index dc1caa0..d5912328 100644
--- a/chrome/browser/chromeos/local_search_service/local_search_service.h
+++ b/chrome/browser/chromeos/local_search_service/local_search_service.h
@@ -9,12 +9,12 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "chrome/browser/chromeos/local_search_service/shared_structs.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace local_search_service {
 
 class Index;
-enum class IndexId;
 
 // LocalSearchService creates and owns content-specific Indices. Clients can
 // call it |GetIndex| method to get an Index for a given index id.
@@ -25,7 +25,7 @@
   LocalSearchService(const LocalSearchService&) = delete;
   LocalSearchService& operator=(const LocalSearchService&) = delete;
 
-  Index* GetIndex(IndexId index_id);
+  Index* GetIndex(IndexId index_id, Backend backend = Backend::kLinearMap);
 
  private:
   std::map<IndexId, std::unique_ptr<Index>> indices_;
diff --git a/chrome/browser/chromeos/local_search_service/proxy/BUILD.gn b/chrome/browser/chromeos/local_search_service/proxy/BUILD.gn
index e980728..f3883946 100644
--- a/chrome/browser/chromeos/local_search_service/proxy/BUILD.gn
+++ b/chrome/browser/chromeos/local_search_service/proxy/BUILD.gn
@@ -43,6 +43,10 @@
           mojom = "local_search_service.mojom.ResponseStatus"
           cpp = "::local_search_service::ResponseStatus"
         },
+        {
+          mojom = "local_search_service.mojom.Backend"
+          cpp = "::local_search_service::Backend"
+        },
       ]
       traits_headers = [ "//chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits.h" ]
       traits_sources = [ "//chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits.cc" ]
diff --git a/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.cc b/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.cc
index 4ddc802..de9aead 100644
--- a/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.cc
+++ b/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.cc
@@ -19,10 +19,11 @@
 
 void LocalSearchServiceProxy::GetIndex(
     IndexId index_id,
+    Backend backend,
     mojo::PendingReceiver<mojom::IndexProxy> index_receiver) {
   auto it = indices_.find(index_id);
   if (it == indices_.end()) {
-    Index* index = service_->GetIndex(index_id);
+    Index* index = service_->GetIndex(index_id, backend);
     it = indices_.emplace(index_id, std::make_unique<IndexProxy>(index)).first;
   }
   it->second->BindReceiver(std::move(index_receiver));
diff --git a/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.h b/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.h
index f68c790..f60a461 100644
--- a/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.h
+++ b/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.h
@@ -29,6 +29,7 @@
   // mojom::LocalSearchServiceProxy:
   void GetIndex(
       IndexId index_id,
+      Backend backend,
       mojo::PendingReceiver<mojom::IndexProxy> index_receiver) override;
 
   void BindReceiver(
diff --git a/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.mojom b/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.mojom
index 3c954c7..dbe6983 100644
--- a/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.mojom
+++ b/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy.mojom
@@ -12,6 +12,11 @@
   // Add new client IDs here.
 };
 
+enum Backend {
+  kLinearMap = 0,
+  kInvertedIndex = 1
+};
+
 // LocalSearchServiceProxy creates and owns content-specific IndexProxies.
 // Clients can call |GetIndex| to get an IndexProxy for a given index id.
 interface LocalSearchServiceProxy {
@@ -21,7 +26,8 @@
   // Note, there should be one primary client that is the owner of the data and
   // can read/write the data to the Index. The other clients should only use
   // the Index for query search.
-  GetIndex(IndexId index_id, pending_receiver<IndexProxy> index_receiver);
+  GetIndex(IndexId index_id, Backend backend,
+      pending_receiver<IndexProxy> index_receiver);
 };
 
 // A proxy to a local search service Index.
@@ -47,4 +53,3 @@
   Find(mojo_base.mojom.String16 query, uint32 max_results)
       => (ResponseStatus status, array<Result>? results);
 };
-
diff --git a/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy_unittest.cc b/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy_unittest.cc
index abd2897..ec76004b 100644
--- a/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy_unittest.cc
+++ b/chrome/browser/chromeos/local_search_service/proxy/local_search_service_proxy_unittest.cc
@@ -33,7 +33,7 @@
 
 TEST_F(LocalSearchServiceProxyTest, GetIndex) {
   mojo::Remote<mojom::IndexProxy> index_remote;
-  service_remote_->GetIndex(IndexId::kCrosSettings,
+  service_remote_->GetIndex(IndexId::kCrosSettings, Backend::kLinearMap,
                             index_remote.BindNewPipeAndPassReceiver());
   base::RunLoop().RunUntilIdle();
 
diff --git a/chrome/browser/chromeos/local_search_service/proxy/types.mojom b/chrome/browser/chromeos/local_search_service/proxy/types.mojom
index a806873..336d252 100644
--- a/chrome/browser/chromeos/local_search_service/proxy/types.mojom
+++ b/chrome/browser/chromeos/local_search_service/proxy/types.mojom
@@ -10,6 +10,7 @@
   // An identifier for the content in Data.
   string id;
   mojo_base.mojom.String16 content;
+  double weight = 1.0;
 };
 
 struct Data {
@@ -26,9 +27,8 @@
 
 struct SearchParams {
   double relevance_threshold = 0.32;
-  double partial_match_penalty_rate = 0.9;
-  bool use_prefix_only = false;
-  bool use_edit_distance = false;
+  double prefix_threshold = 0.6;
+  double fuzzy_threshold = 0.6;
 };
 
 struct Position {
@@ -68,4 +68,3 @@
   // Index is empty (i.e. no data).
   kEmptyIndex
 };
-
diff --git a/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits.cc b/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits.cc
index efd07f6..a7fb9514 100644
--- a/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits.cc
+++ b/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits.cc
@@ -34,6 +34,38 @@
 }
 
 // static
+local_search_service::mojom::Backend
+EnumTraits<local_search_service::mojom::Backend,
+           local_search_service::Backend>::ToMojom(local_search_service::Backend
+                                                       input) {
+  switch (input) {
+    case local_search_service::Backend::kLinearMap:
+      return local_search_service::mojom::Backend::kLinearMap;
+    case local_search_service::Backend::kInvertedIndex:
+      return local_search_service::mojom::Backend::kInvertedIndex;
+  }
+  NOTREACHED();
+  return local_search_service::mojom::Backend::kLinearMap;
+}
+
+// static
+bool EnumTraits<local_search_service::mojom::Backend,
+                local_search_service::Backend>::
+    FromMojom(local_search_service::mojom::Backend input,
+              local_search_service::Backend* output) {
+  switch (input) {
+    case local_search_service::mojom::Backend::kLinearMap:
+      *output = local_search_service::Backend::kLinearMap;
+      return true;
+    case local_search_service::mojom::Backend::kInvertedIndex:
+      *output = local_search_service::Backend::kInvertedIndex;
+      return true;
+  }
+  NOTREACHED();
+  return false;
+}
+
+// static
 bool StructTraits<local_search_service::mojom::ContentDataView,
                   local_search_service::Content>::
     Read(local_search_service::mojom::ContentDataView data,
@@ -43,7 +75,7 @@
   if (!data.ReadId(&id) || !data.ReadContent(&content))
     return false;
 
-  *out = local_search_service::Content(id, content);
+  *out = local_search_service::Content(id, content, data.weight());
   return true;
 }
 
@@ -68,9 +100,8 @@
          local_search_service::SearchParams* out) {
   *out = local_search_service::SearchParams();
   out->relevance_threshold = data.relevance_threshold();
-  out->partial_match_penalty_rate = data.partial_match_penalty_rate();
-  out->use_prefix_only = data.use_prefix_only();
-  out->use_edit_distance = data.use_edit_distance();
+  out->prefix_threshold = data.prefix_threshold();
+  out->fuzzy_threshold = data.fuzzy_threshold();
   return true;
 }
 
diff --git a/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits.h b/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits.h
index 4eec955..f82f2bf 100644
--- a/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits.h
+++ b/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits.h
@@ -26,6 +26,15 @@
 };
 
 template <>
+struct EnumTraits<local_search_service::mojom::Backend,
+                  local_search_service::Backend> {
+  static local_search_service::mojom::Backend ToMojom(
+      local_search_service::Backend input);
+  static bool FromMojom(local_search_service::mojom::Backend input,
+                        local_search_service::Backend* output);
+};
+
+template <>
 struct StructTraits<local_search_service::mojom::ContentDataView,
                     local_search_service::Content> {
  public:
@@ -33,6 +42,9 @@
   static base::string16 content(const local_search_service::Content& c) {
     return c.content;
   }
+  static double weight(const local_search_service::Content& c) {
+    return c.weight;
+  }
 
   static bool Read(local_search_service::mojom::ContentDataView data,
                    local_search_service::Content* out);
@@ -60,15 +72,11 @@
       const local_search_service::SearchParams& s) {
     return s.relevance_threshold;
   }
-  static double partial_match_penalty_rate(
-      const local_search_service::SearchParams& s) {
-    return s.partial_match_penalty_rate;
+  static double prefix_threshold(const local_search_service::SearchParams& s) {
+    return s.prefix_threshold;
   }
-  static bool use_prefix_only(const local_search_service::SearchParams& s) {
-    return s.use_prefix_only;
-  }
-  static bool use_edit_distance(const local_search_service::SearchParams& s) {
-    return s.use_edit_distance;
+  static double fuzzy_threshold(const local_search_service::SearchParams& s) {
+    return s.fuzzy_threshold;
   }
 
   static bool Read(local_search_service::mojom::SearchParamsDataView data,
diff --git a/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits_unittest.cc b/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits_unittest.cc
index f887049..ab993dd 100644
--- a/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits_unittest.cc
+++ b/chrome/browser/chromeos/local_search_service/proxy/types_mojom_traits_unittest.cc
@@ -13,18 +13,20 @@
 namespace local_search_service {
 
 TEST(LocalSearchMojomTraitsTest, ContentTraits) {
-  Content input("id", base::UTF8ToUTF16("content"));
+  Content input("id", base::UTF8ToUTF16("content"), 0.3);
   Content output;
 
   ASSERT_TRUE(
       mojo::test::SerializeAndDeserialize<mojom::Content>(&input, &output));
   EXPECT_EQ(input.id, output.id);
   EXPECT_EQ(input.content, output.content);
+  EXPECT_EQ(input.weight, output.weight);
 }
 
 TEST(LocalSearchMojomTraitsTest, DataTraits) {
-  std::vector<Content> contents{Content("id1", base::UTF8ToUTF16("contents1")),
-                                Content("id2", base::UTF8ToUTF16("contents2"))};
+  std::vector<Content> contents{
+      Content("id1", base::UTF8ToUTF16("contents1"), 0.1),
+      Content("id2", base::UTF8ToUTF16("contents2"), 0.2)};
   Data input("id", contents);
   Data output;
 
@@ -33,21 +35,21 @@
   EXPECT_EQ(input.id, output.id);
   EXPECT_EQ(input.contents[0].id, output.contents[0].id);
   EXPECT_EQ(input.contents[0].content, output.contents[0].content);
+  EXPECT_EQ(input.contents[0].weight, output.contents[0].weight);
   EXPECT_EQ(input.contents[1].id, output.contents[1].id);
   EXPECT_EQ(input.contents[1].content, output.contents[1].content);
+  EXPECT_EQ(input.contents[1].weight, output.contents[1].weight);
 }
 
 TEST(LocalSearchMojomTraitsTest, SearchParamsTraits) {
-  SearchParams input{0.1, 0.2, true, false};
+  SearchParams input{0.1, 0.2, 0.3};
   SearchParams output;
 
   ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::SearchParams>(
       &input, &output));
   EXPECT_EQ(input.relevance_threshold, output.relevance_threshold);
-  EXPECT_EQ(input.partial_match_penalty_rate,
-            output.partial_match_penalty_rate);
-  EXPECT_EQ(input.use_prefix_only, output.use_prefix_only);
-  EXPECT_EQ(input.use_edit_distance, output.use_edit_distance);
+  EXPECT_EQ(input.prefix_threshold, output.prefix_threshold);
+  EXPECT_EQ(input.fuzzy_threshold, output.fuzzy_threshold);
 }
 
 TEST(LocalSearchMojomTraitsTest, PositionTraits) {
diff --git a/chrome/browser/chromeos/local_search_service/shared_structs.cc b/chrome/browser/chromeos/local_search_service/shared_structs.cc
index 42079e4..0f9d071e 100644
--- a/chrome/browser/chromeos/local_search_service/shared_structs.cc
+++ b/chrome/browser/chromeos/local_search_service/shared_structs.cc
@@ -15,11 +15,13 @@
 
 namespace local_search_service {
 
-Content::Content(const std::string& id, const base::string16& content)
-    : id(id), content(content) {}
-Content::Content() = default;
-Content::Content(const Content& content) = default;
-Content::~Content() = default;
+local_search_service::Content::Content(const std::string& id,
+                                       const base::string16& content,
+                                       double weight)
+    : id(id), content(content), weight(weight) {}
+local_search_service::Content::Content() = default;
+local_search_service::Content::Content(const Content& content) = default;
+local_search_service::Content::~Content() = default;
 
 Data::Data(const std::string& id, const std::vector<Content>& contents)
     : id(id), contents(contents) {}
diff --git a/chrome/browser/chromeos/local_search_service/shared_structs.h b/chrome/browser/chromeos/local_search_service/shared_structs.h
index 0e6282e3..8f4885c 100644
--- a/chrome/browser/chromeos/local_search_service/shared_structs.h
+++ b/chrome/browser/chromeos/local_search_service/shared_structs.h
@@ -12,13 +12,33 @@
 
 namespace local_search_service {
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum class IndexId { kCrosSettings = 0, kMaxValue = kCrosSettings };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class Backend {
+  kLinearMap = 0,
+  kInvertedIndex = 1,
+  kMaxValue = kInvertedIndex
+};
+
 struct Content {
   // An identifier for the content in Data.
   std::string id;
   base::string16 content;
-  Content(const std::string& id, const base::string16& content);
+  // |weight| represents how important this Content is and is used in
+  // calculating overall matching score of its enclosing Data item. When a query
+  // matches a Data item it is matching some Content of the Data. If the
+  // matching Content has a larger weight, the overall matching score will be
+  // higher. The range is in [0,1].
+  // TODO(jiameng): it will be used by kInvertedIndex only. We may consider
+  // extending to kLinearMap.
+  double weight = 1.0;
+  Content(const std::string& id,
+          const base::string16& content,
+          double weight = 1.0);
   Content();
   Content(const Content& content);
   ~Content();
@@ -42,10 +62,19 @@
 };
 
 struct SearchParams {
+  // |relevance_threshold| will be applicable if the backend is kLinearMap.
+  // Relevance score will be calculated as a combination of prefix and fuzzy
+  // matching. A Data item is relevant if the overall relevance score is above
+  // this threshold. The threshold should be in [0,1].
   double relevance_threshold = 0.32;
-  double partial_match_penalty_rate = 0.9;
-  bool use_prefix_only = false;
-  bool use_edit_distance = false;
+  // |prefix_threshold| and |fuzzy_threshold| will be applicable if the backend
+  // is kInvertedIndex. When a query term is matched against a Data item, it
+  // will be considered relevant if either its prefix score is above
+  // |prefix_threshold| or fuzzy score is above |fuzzy_threshold|. Both of these
+  // thresholds should be in [0,1].
+  // TODO(jiameng): revise default values.
+  double prefix_threshold = 0.6;
+  double fuzzy_threshold = 0.6;
 };
 
 struct Position {
diff --git a/chrome/browser/chromeos/login/arc_terms_of_service_browsertest.cc b/chrome/browser/chromeos/login/arc_terms_of_service_browsertest.cc
index c90a3979..9c58f32 100644
--- a/chrome/browser/chromeos/login/arc_terms_of_service_browsertest.cc
+++ b/chrome/browser/chromeos/login/arc_terms_of_service_browsertest.cc
@@ -212,7 +212,7 @@
 
   void LoginAsRegularUser() {
     SetUpExitCallback();
-    login_manager_mixin_.LoginAsNewReguarUser();
+    login_manager_mixin_.LoginAsNewRegularUser();
     OobeScreenExitWaiter(GaiaView::kScreenId).Wait();
   }
 
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc b/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc
index 538bc36..7b66f3d 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc
@@ -248,14 +248,7 @@
 };
 
 // Simple manual enrollment.
-// TODO(https://crbug.com/1031275): Slow on MSAN and debug builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_ManualEnrollment DISABLED_ManualEnrollment
-#else
-#define MAYBE_ManualEnrollment ManualEnrollment
-#endif
-IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_ManualEnrollment) {
+IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, ManualEnrollment) {
   TriggerEnrollmentAndSignInSuccessfully();
 
   enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess);
@@ -264,16 +257,8 @@
 }
 
 // Simple manual enrollment with device attributes prompt.
-// TODO(https://crbug.com/1031275): Slow on MSAN and debug builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_ManualEnrollmentWithDeviceAttributes \
-  DISABLED_ManualEnrollmentWithDeviceAttributes
-#else
-#define MAYBE_ManualEnrollmentWithDeviceAttributes \
-  ManualEnrollmentWithDeviceAttributes
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_ManualEnrollmentWithDeviceAttributes) {
+                       ManualEnrollmentWithDeviceAttributes) {
   policy_server_.SetUpdateDeviceAttributesPermission(true);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -290,14 +275,8 @@
 // device_management_service.cc
 
 // Error during enrollment : 402 - missing licenses.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorNoLicenses DISABLED_EnrollmentErrorNoLicenses
-#else
-#define MAYBE_EnrollmentErrorNoLicenses EnrollmentErrorNoLicenses
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorNoLicenses) {
+                       EnrollmentErrorNoLicenses) {
   policy_server_.SetExpectedDeviceEnrollmentError(402);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -311,16 +290,8 @@
 }
 
 // Error during enrollment : 403 - management not allowed.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorManagementNotAllowed \
-  DISABLED_EnrollmentErrorManagementNotAllowed
-#else
-#define MAYBE_EnrollmentErrorManagementNotAllowed \
-  EnrollmentErrorManagementNotAllowed
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorManagementNotAllowed) {
+                       EnrollmentErrorManagementNotAllowed) {
   policy_server_.SetExpectedDeviceEnrollmentError(403);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -334,16 +305,8 @@
 }
 
 // Error during enrollment : 405 - invalid device serial.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorInvalidDeviceSerial \
-  DISABLED_EnrollmentErrorInvalidDeviceSerial
-#else
-#define MAYBE_EnrollmentErrorInvalidDeviceSerial \
-  EnrollmentErrorInvalidDeviceSerial
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorInvalidDeviceSerial) {
+                       EnrollmentErrorInvalidDeviceSerial) {
   policy_server_.SetExpectedDeviceEnrollmentError(405);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -359,15 +322,8 @@
 }
 
 // Error during enrollment : 406 - domain mismatch
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorDomainMismatch \
-  DISABLED_EnrollmentErrorDomainMismatch
-#else
-#define MAYBE_EnrollmentErrorDomainMismatch EnrollmentErrorDomainMismatch
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorDomainMismatch) {
+                       EnrollmentErrorDomainMismatch) {
   policy_server_.SetExpectedDeviceEnrollmentError(406);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -381,15 +337,8 @@
 }
 
 // Error during enrollment : 409 - Device ID is already in use
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorDeviceIDConflict \
-  DISABLED_EnrollmentErrorDeviceIDConflict
-#else
-#define MAYBE_EnrollmentErrorDeviceIDConflict EnrollmentErrorDeviceIDConflict
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorDeviceIDConflict) {
+                       EnrollmentErrorDeviceIDConflict) {
   policy_server_.SetExpectedDeviceEnrollmentError(409);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -404,16 +353,8 @@
 }
 
 // Error during enrollment : 412 - Activation is pending
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorActivationIsPending \
-  DISABLED_EnrollmentErrorActivationIsPending
-#else
-#define MAYBE_EnrollmentErrorActivationIsPending \
-  EnrollmentErrorActivationIsPending
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorActivationIsPending) {
+                       EnrollmentErrorActivationIsPending) {
   policy_server_.SetExpectedDeviceEnrollmentError(412);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -427,18 +368,8 @@
 }
 
 // Error during enrollment : 417 - Consumer account with packaged license.
-// Disable due to flaky crash/timeout on MSAN. https://crbug.com/1028650
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorConsumerAccountWithPackagedLicense \
-  DISABLED_EnrollmentErrorConsumerAccountWithPackagedLicense
-#else
-#define MAYBE_EnrollmentErrorConsumerAccountWithPackagedLicense \
-  EnrollmentErrorConsumerAccountWithPackagedLicense
-#endif
-IN_PROC_BROWSER_TEST_F(
-    EnrollmentLocalPolicyServerBase,
-    MAYBE_EnrollmentErrorConsumerAccountWithPackagedLicense) {
+IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
+                       EnrollmentErrorConsumerAccountWithPackagedLicense) {
   policy_server_.SetExpectedDeviceEnrollmentError(417);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -453,14 +384,8 @@
 }
 
 // Error during enrollment : 500 - Consumer account with packaged license.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorServerError DISABLED_EnrollmentErrorServerError
-#else
-#define MAYBE_EnrollmentErrorServerError EnrollmentErrorServerError
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorServerError) {
+                       EnrollmentErrorServerError) {
   policy_server_.SetExpectedDeviceEnrollmentError(500);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -474,17 +399,8 @@
 }
 
 // Error during enrollment : 905 - Ineligible enterprise account.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorEnterpriseAccountIsNotEligibleToEnroll \
-  DISABLED_EnrollmentErrorEnterpriseAccountIsNotEligibleToEnroll
-#else
-#define MAYBE_EnrollmentErrorEnterpriseAccountIsNotEligibleToEnroll \
-  EnrollmentErrorEnterpriseAccountIsNotEligibleToEnroll
-#endif
-IN_PROC_BROWSER_TEST_F(
-    EnrollmentLocalPolicyServerBase,
-    MAYBE_EnrollmentErrorEnterpriseAccountIsNotEligibleToEnroll) {
+IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
+                       EnrollmentErrorEnterpriseAccountIsNotEligibleToEnroll) {
   policy_server_.SetExpectedDeviceEnrollmentError(905);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -514,14 +430,8 @@
 }
 
 // Error during enrollment : Strange HTTP response from server.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorServerIsDrunk DISABLED_EnrollmentErrorServerIsDrunk
-#else
-#define MAYBE_EnrollmentErrorServerIsDrunk EnrollmentErrorServerIsDrunk
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorServerIsDrunk) {
+                       EnrollmentErrorServerIsDrunk) {
   policy_server_.SetExpectedDeviceEnrollmentError(12345);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -535,16 +445,8 @@
 }
 
 // Error during enrollment : Can not update device attributes
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorUploadingDeviceAttributes \
-  DISABLED_EnrollmentErrorUploadingDeviceAttributes
-#else
-#define MAYBE_EnrollmentErrorUploadingDeviceAttributes \
-  EnrollmentErrorUploadingDeviceAttributes
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorUploadingDeviceAttributes) {
+                       EnrollmentErrorUploadingDeviceAttributes) {
   policy_server_.SetUpdateDeviceAttributesPermission(true);
   policy_server_.SetExpectedDeviceAttributeUpdateError(500);
 
@@ -564,16 +466,8 @@
 }
 
 // Error during enrollment : Error fetching policy : 500 server error.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorFetchingPolicyTransient \
-  DISABLED_EnrollmentErrorFetchingPolicyTransient
-#else
-#define MAYBE_EnrollmentErrorFetchingPolicyTransient \
-  EnrollmentErrorFetchingPolicyTransient
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorFetchingPolicyTransient) {
+                       EnrollmentErrorFetchingPolicyTransient) {
   policy_server_.SetExpectedPolicyFetchError(500);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -587,16 +481,8 @@
 }
 
 // Error during enrollment : Error fetching policy : 902 - policy not found.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorFetchingPolicyNotFound \
-  DISABLED_EnrollmentErrorFetchingPolicyNotFound
-#else
-#define MAYBE_EnrollmentErrorFetchingPolicyNotFound \
-  EnrollmentErrorFetchingPolicyNotFound
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorFetchingPolicyNotFound) {
+                       EnrollmentErrorFetchingPolicyNotFound) {
   policy_server_.SetExpectedPolicyFetchError(902);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -611,16 +497,8 @@
 }
 
 // Error during enrollment : Error fetching policy : 903 - deprovisioned.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentErrorFetchingPolicyDeprovisioned \
-  DISABLED_EnrollmentErrorFetchingPolicyDeprovisioned
-#else
-#define MAYBE_EnrollmentErrorFetchingPolicyDeprovisioned \
-  EnrollmentErrorFetchingPolicyDeprovisioned
-#endif
 IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase,
-                       MAYBE_EnrollmentErrorFetchingPolicyDeprovisioned) {
+                       EnrollmentErrorFetchingPolicyDeprovisioned) {
   policy_server_.SetExpectedPolicyFetchError(903);
 
   TriggerEnrollmentAndSignInSuccessfully();
@@ -634,27 +512,13 @@
 }
 
 // No state keys on the server. Auto enrollment check should proceed to login.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_AutoEnrollmentCheck DISABLED_AutoEnrollmentCheck
-#else
-#define MAYBE_AutoEnrollmentCheck AutoEnrollmentCheck
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer,
-                       MAYBE_AutoEnrollmentCheck) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, AutoEnrollmentCheck) {
   host()->StartWizard(AutoEnrollmentCheckScreenView::kScreenId);
   OobeScreenWaiter(GaiaView::kScreenId).Wait();
 }
 
 // State keys are present but restore mode is not requested.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_ReenrollmentNone DISABLED_ReenrollmentNone
-#else
-#define MAYBE_ReenrollmentNone ReenrollmentNone
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer,
-                       MAYBE_ReenrollmentNone) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, ReenrollmentNone) {
   EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse(
       state_keys_broker(),
       enterprise_management::DeviceStateRetrievalResponse::RESTORE_MODE_NONE,
@@ -664,14 +528,7 @@
 }
 
 // Reenrollment requested. User can skip.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_ReenrollmentRequested DISABLED_ReenrollmentRequested
-#else
-#define MAYBE_ReenrollmentRequested ReenrollmentRequested
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer,
-                       MAYBE_ReenrollmentRequested) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, ReenrollmentRequested) {
   EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse(
       state_keys_broker(),
       enterprise_management::DeviceStateRetrievalResponse::
@@ -684,14 +541,7 @@
 }
 
 // Reenrollment forced. User can not skip.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_ReenrollmentForced DISABLED_ReenrollmentForced
-#else
-#define MAYBE_ReenrollmentForced ReenrollmentForced
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer,
-                       MAYBE_ReenrollmentForced) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, ReenrollmentForced) {
   EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse(
       state_keys_broker(),
       enterprise_management::DeviceStateRetrievalResponse::
@@ -705,13 +555,7 @@
 }
 
 // Device is disabled.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_DeviceDisabled DISABLED_DeviceDisabled
-#else
-#define MAYBE_DeviceDisabled DeviceDisabled
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, MAYBE_DeviceDisabled) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, DeviceDisabled) {
   EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse(
       state_keys_broker(),
       enterprise_management::DeviceStateRetrievalResponse::
@@ -722,13 +566,7 @@
 }
 
 // Attestation enrollment.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_Attestation DISABLED_Attestation
-#else
-#define MAYBE_Attestation Attestation
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, MAYBE_Attestation) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, Attestation) {
   policy_server_.SetFakeAttestationFlow();
   EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse(
       state_keys_broker(),
@@ -743,13 +581,7 @@
 }
 
 // FRE explicitly required in VPD, but the state keys are missing.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_FREExplicitlyRequired DISABLED_FREExplicitlyRequired
-#else
-#define MAYBE_FREExplicitlyRequired FREExplicitlyRequired
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentNoStateKeys, MAYBE_FREExplicitlyRequired) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentNoStateKeys, FREExplicitlyRequired) {
   SetFRERequiredKey("1");
   host()->StartWizard(AutoEnrollmentCheckScreenView::kScreenId);
   OobeScreenWaiter(AutoEnrollmentCheckScreenView::kScreenId).Wait();
@@ -760,27 +592,14 @@
 
 // FRE not explicitly required and the state keys are missing. Should proceed to
 // normal signin.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_NotRequired DISABLED_NotRequired
-#else
-#define MAYBE_NotRequired NotRequired
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentNoStateKeys, MAYBE_NotRequired) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentNoStateKeys, NotRequired) {
   host()->StartWizard(AutoEnrollmentCheckScreenView::kScreenId);
   OobeScreenWaiter(GaiaView::kScreenId).Wait();
 }
 
 // FRE explicitly not required in VPD, so it should not even contact the policy
 // server.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_ExplicitlyNotRequired DISABLED_ExplicitlyNotRequired
-#else
-#define MAYBE_ExplicitlyNotRequired ExplicitlyNotRequired
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics,
-                       MAYBE_ExplicitlyNotRequired) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, ExplicitlyNotRequired) {
   SetFRERequiredKey("0");
 
   // Should be ignored.
@@ -795,14 +614,7 @@
 }
 
 // FRE is not required when VPD is valid and activate date is not there.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_MachineNotActivated DISABLED_MachineNotActivated
-#else
-#define MAYBE_MachineNotActivated MachineNotActivated
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics,
-                       MAYBE_MachineNotActivated) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, MachineNotActivated) {
   // Should be ignored.
   EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse(
       state_keys_broker(),
@@ -815,13 +627,7 @@
 }
 
 // FRE is required when VPD is valid and activate date is there.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_MachineActivated DISABLED_MachineActivated
-#else
-#define MAYBE_MachineActivated MachineActivated
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, MAYBE_MachineActivated) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, MachineActivated) {
   SetActivateDate("1970-01");
 
   EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse(
@@ -835,13 +641,7 @@
 }
 
 // FRE is required when VPD in invalid state.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_CorruptedVPD DISABLED_CorruptedVPD
-#else
-#define MAYBE_CorruptedVPD CorruptedVPD
-#endif
-IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, MAYBE_CorruptedVPD) {
+IN_PROC_BROWSER_TEST_F(AutoEnrollmentWithStatistics, CorruptedVPD) {
   SetVPDCorrupted();
 
   EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse(
@@ -875,13 +675,7 @@
   DISALLOW_COPY_AND_ASSIGN(EnrollmentRecoveryTest);
 };
 
-// TODO(https://crbug.com/995784): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_Success DISABLED_Success
-#else
-#define MAYBE_Success Success
-#endif
-IN_PROC_BROWSER_TEST_F(EnrollmentRecoveryTest, MAYBE_Success) {
+IN_PROC_BROWSER_TEST_F(EnrollmentRecoveryTest, Success) {
   test::SkipToEnrollmentOnRecovery();
 
   ASSERT_TRUE(StartupUtils::IsDeviceRegistered());
@@ -906,13 +700,7 @@
           .empty());
 }
 
-// TODO(https://crbug.com/995784): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_DifferentDomain DISABLED_DifferentDomain
-#else
-#define MAYBE_DifferentDomain DifferentDomain
-#endif
-IN_PROC_BROWSER_TEST_F(EnrollmentRecoveryTest, MAYBE_DifferentDomain) {
+IN_PROC_BROWSER_TEST_F(EnrollmentRecoveryTest, DifferentDomain) {
   test::SkipToEnrollmentOnRecovery();
 
   ASSERT_TRUE(StartupUtils::IsDeviceRegistered());
@@ -925,13 +713,7 @@
   enrollment_ui_.RetryAfterError();
 }
 
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_EnrollmentForced DISABLED_EnrollmentForced
-#else
-#define MAYBE_EnrollmentForced EnrollmentForced
-#endif
-IN_PROC_BROWSER_TEST_F(InitialEnrollmentTest, MAYBE_EnrollmentForced) {
+IN_PROC_BROWSER_TEST_F(InitialEnrollmentTest, EnrollmentForced) {
   auto initial_enrollment =
       enterprise_management::DeviceInitialEnrollmentStateResponse::
           INITIAL_ENROLLMENT_MODE_ENROLLMENT_ENFORCED;
@@ -958,15 +740,7 @@
 
 // Zero touch with attestation authentication fail. Attestation fails because we
 // send empty cert request. Should switch to interactive authentication.
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_ZeroTouchForcedAttestationFail \
-  DISABLED_ZeroTouchForcedAttestationFail
-#else
-#define MAYBE_ZeroTouchForcedAttestationFail ZeroTouchForcedAttestationFail
-#endif
-IN_PROC_BROWSER_TEST_F(InitialEnrollmentTest,
-                       MAYBE_ZeroTouchForcedAttestationFail) {
+IN_PROC_BROWSER_TEST_F(InitialEnrollmentTest, ZeroTouchForcedAttestationFail) {
   auto initial_enrollment =
       enterprise_management::DeviceInitialEnrollmentStateResponse::
           INITIAL_ENROLLMENT_MODE_ZERO_TOUCH_ENFORCED;
@@ -1001,16 +775,8 @@
   EXPECT_TRUE(InstallAttributes::Get()->IsEnterpriseManaged());
 }
 
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_ZeroTouchForcedAttestationSuccess \
-  DISABLED_ZeroTouchForcedAttestationSuccess
-#else
-#define MAYBE_ZeroTouchForcedAttestationSuccess \
-  ZeroTouchForcedAttestationSuccess
-#endif
 IN_PROC_BROWSER_TEST_F(InitialEnrollmentTest,
-                       MAYBE_ZeroTouchForcedAttestationSuccess) {
+                       ZeroTouchForcedAttestationSuccess) {
   policy_server_.SetupZeroTouchForcedEnrollment();
 
   host()->StartWizard(AutoEnrollmentCheckScreenView::kScreenId);
@@ -1035,13 +801,7 @@
   DISALLOW_COPY_AND_ASSIGN(OobeGuestButtonPolicy);
 };
 
-// TODO(https://crbug.com/1031275): Slow on MSAN builds.
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_VisibilityAfterEnrollment DISABLED_VisibilityAfterEnrollment
-#else
-#define MAYBE_VisibilityAfterEnrollment VisibilityAfterEnrollment
-#endif
-IN_PROC_BROWSER_TEST_P(OobeGuestButtonPolicy, MAYBE_VisibilityAfterEnrollment) {
+IN_PROC_BROWSER_TEST_P(OobeGuestButtonPolicy, VisibilityAfterEnrollment) {
   TriggerEnrollmentAndSignInSuccessfully();
   enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess);
   ConfirmAndWaitLoginScreen();
diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc
index 4647072..f558be0 100644
--- a/chrome/browser/chromeos/login/login_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_browsertest.cc
@@ -168,12 +168,7 @@
   offline_gaia_test_mixin_.PrepareOfflineGaiaLogin();
 }
 
-#if defined(OS_LINUX) && defined(MEMORY_SANITIZER)
-#define MAYBE_GaiaAuthOffline DISABLED_GaiaAuthOffline
-#else
-#define MAYBE_GaiaAuthOffline GaiaAuthOffline
-#endif
-IN_PROC_BROWSER_TEST_F(LoginOfflineTest, MAYBE_GaiaAuthOffline) {
+IN_PROC_BROWSER_TEST_F(LoginOfflineTest, GaiaAuthOffline) {
   offline_gaia_test_mixin_.GoOffline();
   offline_gaia_test_mixin_.InitOfflineLogin(test_account_id_,
                                             LoginManagerTest::kPassword);
diff --git a/chrome/browser/chromeos/login/login_utils_browsertest.cc b/chrome/browser/chromeos/login/login_utils_browsertest.cc
index a6cbeed..9bf3771 100644
--- a/chrome/browser/chromeos/login/login_utils_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_utils_browsertest.cc
@@ -69,7 +69,7 @@
     UserSessionInitializer::Get()->set_init_rlz_impl_closure_for_testing(
         loop.QuitClosure());
 
-    login_manager_.LoginAsNewReguarUser();
+    login_manager_.LoginAsNewRegularUser();
     login_manager_.WaitForActiveSession();
 
     loop.Run();
diff --git a/chrome/browser/chromeos/login/screens/app_downloading_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/app_downloading_screen_browsertest.cc
index c06dceb..7122455 100644
--- a/chrome/browser/chromeos/login/screens/app_downloading_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/app_downloading_screen_browsertest.cc
@@ -52,7 +52,7 @@
   }
 
   void Login() {
-    login_manager_.LoginAsNewReguarUser();
+    login_manager_.LoginAsNewRegularUser();
     OobeScreenExitWaiter(GaiaView::kScreenId).Wait();
   }
 
diff --git a/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen_browsertest.cc
index c222cf37..e158c94 100644
--- a/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen_browsertest.cc
@@ -332,7 +332,7 @@
   }
 
   void ShowAssistantOptInFlowScreen() {
-    login_manager_.LoginAsNewReguarUser();
+    login_manager_.LoginAsNewRegularUser();
     OobeScreenExitWaiter(GaiaView::kScreenId).Wait();
     if (!screen_exited_) {
       LoginDisplayHost::default_host()->StartWizard(
diff --git a/chrome/browser/chromeos/login/screens/discover_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/discover_screen_browsertest.cc
index 144cb55..c379b5049 100644
--- a/chrome/browser/chromeos/login/screens/discover_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/discover_screen_browsertest.cc
@@ -43,7 +43,7 @@
   }
 
   void ShowDiscoverScreen() {
-    login_manager_mixin_.LoginAsNewReguarUser();
+    login_manager_mixin_.LoginAsNewRegularUser();
     OobeScreenExitWaiter(GaiaView::kScreenId).Wait();
     if (!screen_exited_) {
       LoginDisplayHost::default_host()->StartWizard(
diff --git a/chrome/browser/chromeos/login/screens/marketing_opt_in_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/marketing_opt_in_screen_browsertest.cc
index e637a5c9..fb345bf 100644
--- a/chrome/browser/chromeos/login/screens/marketing_opt_in_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/marketing_opt_in_screen_browsertest.cc
@@ -179,7 +179,7 @@
       &MarketingOptInScreenTest::HandleScreenExit, base::Unretained(this)));
 
   OobeBaseTest::SetUpOnMainThread();
-  login_manager_mixin_.LoginAsNewReguarUser();
+  login_manager_mixin_.LoginAsNewRegularUser();
   OobeScreenExitWaiter(GaiaView::kScreenId).Wait();
   ProfileManager::GetActiveUserProfile()->GetPrefs()->SetBoolean(
       ash::prefs::kGestureEducationNotificationShown, true);
diff --git a/chrome/browser/chromeos/login/screens/recommend_apps_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/recommend_apps_screen_browsertest.cc
index 9545f680..25d9ebea 100644
--- a/chrome/browser/chromeos/login/screens/recommend_apps_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/recommend_apps_screen_browsertest.cc
@@ -141,7 +141,7 @@
   }
 
   void ShowRecommendAppsScreen() {
-    login_manager_.LoginAsNewReguarUser();
+    login_manager_.LoginAsNewRegularUser();
     OobeScreenExitWaiter(GaiaView::kScreenId).Wait();
     LoginDisplayHost::default_host()->StartWizard(
         RecommendAppsScreenView::kScreenId);
diff --git a/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc b/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc
index 2933953..7452b2a 100644
--- a/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc
@@ -190,7 +190,7 @@
   }
 
   void LoginToSyncConsentScreen() {
-    login_manager_mixin_.LoginAsNewReguarUser();
+    login_manager_mixin_.LoginAsNewRegularUser();
     OobeScreenExitWaiter(GaiaView::kScreenId).Wait();
     // No need to explicitly show the screen as it is the first one after login.
   }
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen.cc b/chrome/browser/chromeos/login/screens/welcome_screen.cc
index 0881ed3..5dfc457d 100644
--- a/chrome/browser/chromeos/login/screens/welcome_screen.cc
+++ b/chrome/browser/chromeos/login/screens/welcome_screen.cc
@@ -10,9 +10,11 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/stl_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
+#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
 #include "chrome/browser/chromeos/base/locale_util.h"
 #include "chrome/browser/chromeos/customization/customization_document.h"
 #include "chrome/browser/chromeos/login/oobe_screen.h"
@@ -30,14 +32,97 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
 
+namespace chromeos {
 namespace {
 
 constexpr char kUserActionContinueButtonClicked[] = "continue";
+constexpr const char kUserActionEnableSpokenFeedback[] =
+    "accessibility-spoken-feedback-enable";
+constexpr const char kUserActionDisableSpokenFeedback[] =
+    "accessibility-spoken-feedback-disable";
+constexpr const char kUserActionEnableLargeCursor[] =
+    "accessibility-large-cursor-enable";
+constexpr const char kUserActionDisableLargeCursor[] =
+    "accessibility-large-cursor-disable";
+constexpr const char kUserActionEnableHighContrast[] =
+    "accessibility-high-contrast-enable";
+constexpr const char kUserActionDisableHighContrast[] =
+    "accessibility-high-contrast-disable";
+constexpr const char kUserActionEnableScreenMagnifier[] =
+    "accessibility-screen-magnifier-enable";
+constexpr const char kUserActionDisableScreenMagnifier[] =
+    "accessibility-screen-magnifier-disable";
+constexpr const char kUserActionEnableSelectToSpeak[] =
+    "accessibility-select-to-speak-enable";
+constexpr const char kUserActionDisableSelectToSpeak[] =
+    "accessibility-select-to-speak-disable";
+constexpr const char kUserActionEnableDockedMagnifier[] =
+    "accessibility-docked-magnifier-enable";
+constexpr const char kUserActionDisableDockedMagnifier[] =
+    "accessibility-docked-magnifier-disable";
+constexpr const char kUserActionEnableVirtualKeyboard[] =
+    "accessibility-virtual-keyboard-enable";
+constexpr const char kUserActionDisableVirtualKeyboard[] =
+    "accessibility-virtual-keyboard-disable";
+
+struct WelcomeScreenA11yUserAction {
+  const char* name_;
+  WelcomeScreen::A11yUserAction uma_name_;
+};
+
+const WelcomeScreenA11yUserAction actions[] = {
+    {kUserActionEnableSpokenFeedback,
+     WelcomeScreen::A11yUserAction::kEnableSpokenFeedback},
+    {kUserActionDisableSpokenFeedback,
+     WelcomeScreen::A11yUserAction::kDisableSpokenFeedback},
+    {kUserActionEnableLargeCursor,
+     WelcomeScreen::A11yUserAction::kEnableLargeCursor},
+    {kUserActionDisableLargeCursor,
+     WelcomeScreen::A11yUserAction::kDisableLargeCursor},
+    {kUserActionEnableHighContrast,
+     WelcomeScreen::A11yUserAction::kEnableHighContrast},
+    {kUserActionDisableHighContrast,
+     WelcomeScreen::A11yUserAction::kDisableHighContrast},
+    {kUserActionEnableScreenMagnifier,
+     WelcomeScreen::A11yUserAction::kEnableScreenMagnifier},
+    {kUserActionDisableScreenMagnifier,
+     WelcomeScreen::A11yUserAction::kDisableScreenMagnifier},
+    {kUserActionEnableSelectToSpeak,
+     WelcomeScreen::A11yUserAction::kEnableSelectToSpeak},
+    {kUserActionDisableSelectToSpeak,
+     WelcomeScreen::A11yUserAction::kDisableSelectToSpeak},
+    {kUserActionEnableDockedMagnifier,
+     WelcomeScreen::A11yUserAction::kEnableDockedMagnifier},
+    {kUserActionDisableDockedMagnifier,
+     WelcomeScreen::A11yUserAction::kDisableDockedMagnifier},
+    {kUserActionEnableVirtualKeyboard,
+     WelcomeScreen::A11yUserAction::kEnableVirtualKeyboard},
+    {kUserActionDisableVirtualKeyboard,
+     WelcomeScreen::A11yUserAction::kDisableVirtualKeyboard},
+};
+
+bool IsA11yUserAction(const std::string& action_id) {
+  for (const auto& el : actions) {
+    if (action_id == el.name_) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void RecordA11yUserAction(const std::string& action_id) {
+  for (const auto& el : actions) {
+    if (action_id == el.name_) {
+      base::UmaHistogramEnumeration("OOBE.WelcomeScreen.A11yUserActions",
+                                    el.uma_name_);
+      return;
+    }
+  }
+  NOTREACHED() << "Unexpected action id: " << action_id;
+}
 
 }  // namespace
 
-namespace chromeos {
-
 ///////////////////////////////////////////////////////////////////////////////
 // WelcomeScreen, public:
 
@@ -203,6 +288,43 @@
 void WelcomeScreen::OnUserAction(const std::string& action_id) {
   if (action_id == kUserActionContinueButtonClicked) {
     OnContinueButtonPressed();
+    return;
+  }
+  if (IsA11yUserAction(action_id)) {
+    RecordA11yUserAction(action_id);
+    if (action_id == kUserActionEnableSpokenFeedback) {
+      AccessibilityManager::Get()->EnableSpokenFeedback(true);
+    } else if (action_id == kUserActionDisableSpokenFeedback) {
+      AccessibilityManager::Get()->EnableSpokenFeedback(false);
+    } else if (action_id == kUserActionEnableLargeCursor) {
+      AccessibilityManager::Get()->EnableLargeCursor(true);
+    } else if (action_id == kUserActionDisableLargeCursor) {
+      AccessibilityManager::Get()->EnableLargeCursor(false);
+    } else if (action_id == kUserActionEnableHighContrast) {
+      AccessibilityManager::Get()->EnableHighContrast(true);
+    } else if (action_id == kUserActionDisableHighContrast) {
+      AccessibilityManager::Get()->EnableHighContrast(false);
+    } else if (action_id == kUserActionEnableScreenMagnifier) {
+      DCHECK(MagnificationManager::Get());
+      MagnificationManager::Get()->SetMagnifierEnabled(true);
+    } else if (action_id == kUserActionDisableScreenMagnifier) {
+      DCHECK(MagnificationManager::Get());
+      MagnificationManager::Get()->SetMagnifierEnabled(false);
+    } else if (action_id == kUserActionEnableSelectToSpeak) {
+      AccessibilityManager::Get()->SetSelectToSpeakEnabled(true);
+    } else if (action_id == kUserActionDisableSelectToSpeak) {
+      AccessibilityManager::Get()->SetSelectToSpeakEnabled(false);
+    } else if (action_id == kUserActionEnableDockedMagnifier) {
+      DCHECK(MagnificationManager::Get());
+      MagnificationManager::Get()->SetDockedMagnifierEnabled(true);
+    } else if (action_id == kUserActionDisableDockedMagnifier) {
+      DCHECK(MagnificationManager::Get());
+      MagnificationManager::Get()->SetDockedMagnifierEnabled(false);
+    } else if (action_id == kUserActionEnableVirtualKeyboard) {
+      AccessibilityManager::Get()->EnableVirtualKeyboard(true);
+    } else if (action_id == kUserActionDisableVirtualKeyboard) {
+      AccessibilityManager::Get()->EnableVirtualKeyboard(false);
+    }
   } else {
     BaseScreen::OnUserAction(action_id);
   }
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen.h b/chrome/browser/chromeos/login/screens/welcome_screen.h
index 18cf413..14152bc 100644
--- a/chrome/browser/chromeos/login/screens/welcome_screen.h
+++ b/chrome/browser/chromeos/login/screens/welcome_screen.h
@@ -30,6 +30,28 @@
 class WelcomeScreen : public BaseScreen,
                       public input_method::InputMethodManager::Observer {
  public:
+  // This enum is tied directly to a UMA enum defined in
+  // //tools/metrics/histograms/enums.xml, and should always reflect it (do not
+  // change one without changing the other).  Entries should be never modified
+  // or deleted.  Only additions possible.
+  enum class A11yUserAction {
+    kEnableSpokenFeedback = 0,
+    kDisableSpokenFeedback = 1,
+    kEnableLargeCursor = 2,
+    kDisableLargeCursor = 3,
+    kEnableHighContrast = 4,
+    kDisableHighContrast = 5,
+    kEnableScreenMagnifier = 6,
+    kDisableScreenMagnifier = 7,
+    kEnableSelectToSpeak = 8,
+    kDisableSelectToSpeak = 9,
+    kEnableDockedMagnifier = 10,
+    kDisableDockedMagnifier = 11,
+    kEnableVirtualKeyboard = 12,
+    kDisableVirtualKeyboard = 13,
+    kMaxValue = kDisableVirtualKeyboard
+  };
+
   class Observer {
    public:
     virtual ~Observer() {}
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/welcome_screen_browsertest.cc
index fc6a503..468a7db 100644
--- a/chrome/browser/chromeos/login/screens/welcome_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/welcome_screen_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include <memory>
 
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_path_override.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
@@ -98,6 +99,9 @@
   void WaitForScreenExit() {
     OobeScreenExitWaiter(WelcomeView::kScreenId).Wait();
   }
+
+  base::HistogramTester histogram_tester_;
+
  private:
   std::unique_ptr<base::ScopedPathOverride> path_override_;
   base::ScopedTempDir data_dir_;
@@ -243,9 +247,17 @@
   ASSERT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
   ToggleAccessibilityFeature("accessibility-spoken-feedback", true);
   ASSERT_TRUE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kEnableSpokenFeedback, 1);
 
   ToggleAccessibilityFeature("accessibility-spoken-feedback", false);
   ASSERT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kDisableSpokenFeedback, 1);
+
+  histogram_tester_.ExpectTotalCount("OOBE.WelcomeScreen.A11yUserActions", 2);
 }
 
 IN_PROC_BROWSER_TEST_F(WelcomeScreenBrowserTest,
@@ -257,9 +269,17 @@
   ASSERT_FALSE(AccessibilityManager::Get()->IsLargeCursorEnabled());
   ToggleAccessibilityFeature("accessibility-large-cursor", true);
   ASSERT_TRUE(AccessibilityManager::Get()->IsLargeCursorEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kEnableLargeCursor, 1);
 
   ToggleAccessibilityFeature("accessibility-large-cursor", false);
   ASSERT_FALSE(AccessibilityManager::Get()->IsLargeCursorEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kDisableLargeCursor, 1);
+
+  histogram_tester_.ExpectTotalCount("OOBE.WelcomeScreen.A11yUserActions", 2);
 }
 
 IN_PROC_BROWSER_TEST_F(WelcomeScreenBrowserTest,
@@ -271,9 +291,17 @@
   ASSERT_FALSE(AccessibilityManager::Get()->IsHighContrastEnabled());
   ToggleAccessibilityFeature("accessibility-high-contrast", true);
   ASSERT_TRUE(AccessibilityManager::Get()->IsHighContrastEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kEnableHighContrast, 1);
 
   ToggleAccessibilityFeature("accessibility-high-contrast", false);
   ASSERT_FALSE(AccessibilityManager::Get()->IsHighContrastEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kDisableHighContrast, 1);
+
+  histogram_tester_.ExpectTotalCount("OOBE.WelcomeScreen.A11yUserActions", 2);
 }
 
 IN_PROC_BROWSER_TEST_F(WelcomeScreenBrowserTest,
@@ -285,9 +313,17 @@
   ASSERT_FALSE(AccessibilityManager::Get()->IsSelectToSpeakEnabled());
   ToggleAccessibilityFeature("accessibility-select-to-speak", true);
   ASSERT_TRUE(AccessibilityManager::Get()->IsSelectToSpeakEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kEnableSelectToSpeak, 1);
 
   ToggleAccessibilityFeature("accessibility-select-to-speak", false);
   ASSERT_FALSE(AccessibilityManager::Get()->IsSelectToSpeakEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kDisableSelectToSpeak, 1);
+
+  histogram_tester_.ExpectTotalCount("OOBE.WelcomeScreen.A11yUserActions", 2);
 }
 
 IN_PROC_BROWSER_TEST_F(WelcomeScreenBrowserTest,
@@ -299,9 +335,17 @@
   ASSERT_FALSE(MagnificationManager::Get()->IsMagnifierEnabled());
   ToggleAccessibilityFeature("accessibility-screen-magnifier", true);
   ASSERT_TRUE(MagnificationManager::Get()->IsMagnifierEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kEnableScreenMagnifier, 1);
 
   ToggleAccessibilityFeature("accessibility-screen-magnifier", false);
   ASSERT_FALSE(MagnificationManager::Get()->IsMagnifierEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kDisableScreenMagnifier, 1);
+
+  histogram_tester_.ExpectTotalCount("OOBE.WelcomeScreen.A11yUserActions", 2);
 }
 
 IN_PROC_BROWSER_TEST_F(WelcomeScreenBrowserTest,
@@ -313,9 +357,17 @@
   ASSERT_FALSE(MagnificationManager::Get()->IsDockedMagnifierEnabled());
   ToggleAccessibilityFeature("accessibility-docked-magnifier", true);
   ASSERT_TRUE(MagnificationManager::Get()->IsDockedMagnifierEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kEnableDockedMagnifier, 1);
 
   ToggleAccessibilityFeature("accessibility-docked-magnifier", false);
   ASSERT_FALSE(MagnificationManager::Get()->IsDockedMagnifierEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kDisableDockedMagnifier, 1);
+
+  histogram_tester_.ExpectTotalCount("OOBE.WelcomeScreen.A11yUserActions", 2);
 }
 
 IN_PROC_BROWSER_TEST_F(WelcomeScreenBrowserTest, PRE_SelectedLanguage) {
@@ -347,9 +399,17 @@
   ASSERT_FALSE(AccessibilityManager::Get()->IsVirtualKeyboardEnabled());
   ToggleAccessibilityFeature("accessibility-virtual-keyboard", true);
   ASSERT_TRUE(AccessibilityManager::Get()->IsVirtualKeyboardEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kEnableVirtualKeyboard, 1);
 
   ToggleAccessibilityFeature("accessibility-virtual-keyboard", false);
   ASSERT_FALSE(AccessibilityManager::Get()->IsVirtualKeyboardEnabled());
+  histogram_tester_.ExpectBucketCount(
+      "OOBE.WelcomeScreen.A11yUserActions",
+      WelcomeScreen::A11yUserAction::kDisableVirtualKeyboard, 1);
+
+  histogram_tester_.ExpectTotalCount("OOBE.WelcomeScreen.A11yUserActions", 2);
 }
 
 IN_PROC_BROWSER_TEST_F(WelcomeScreenSystemDevModeBrowserTest,
diff --git a/chrome/browser/chromeos/login/test/login_manager_mixin.cc b/chrome/browser/chromeos/login/test/login_manager_mixin.cc
index fbba070..3004750 100644
--- a/chrome/browser/chromeos/login/test/login_manager_mixin.cc
+++ b/chrome/browser/chromeos/login/test/login_manager_mixin.cc
@@ -183,7 +183,7 @@
       user_context, std::make_unique<StubAuthenticatorBuilder>(user_context));
 }
 
-void LoginManagerMixin::LoginAsNewReguarUser() {
+void LoginManagerMixin::LoginAsNewRegularUser() {
   ASSERT_FALSE(session_manager::SessionManager::Get()->IsSessionStarted());
   const std::string email = "test_user" + std::string(kGmailDomain);
   const std::string gaia_id = "111111111";
diff --git a/chrome/browser/chromeos/login/test/login_manager_mixin.h b/chrome/browser/chromeos/login/test/login_manager_mixin.h
index 17ca76b..a354579 100644
--- a/chrome/browser/chromeos/login/test/login_manager_mixin.h
+++ b/chrome/browser/chromeos/login/test/login_manager_mixin.h
@@ -121,7 +121,7 @@
 
   // Logs in as a regular user with default user context. Should be used for
   // proceeding into the session from the login screen.
-  void LoginAsNewReguarUser();
+  void LoginAsNewRegularUser();
 
  private:
   UserList initial_users_;
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_manager_impl.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_manager_impl.cc
index d76c4517..0dbdb7c2 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_manager_impl.cc
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_manager_impl.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/plugin_vm/plugin_vm_manager_impl.h"
 
+#include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/browser_process.h"
@@ -124,7 +125,12 @@
   // 3) Call ListVms to get the state of the VM.
   // 4) Start the VM if necessary.
   // 5) Show the UI.
-  InstallPluginVmDlc();
+  InstallDlcAndUpdateVmState(
+      base::BindOnce(&PluginVmManagerImpl::OnListVmsForLaunch,
+                     weak_ptr_factory_.GetWeakPtr()),
+      base::BindOnce(&PluginVmManagerImpl::LaunchFailed,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     PluginVmLaunchResult::kError));
 }
 
 void PluginVmManagerImpl::AddVmStartingObserver(
@@ -163,15 +169,20 @@
   uninstaller_notification_ =
       std::make_unique<PluginVmUninstallerNotification>(profile_);
   // Uninstalling Plugin Vm goes through the following steps:
-  // 1) Start the Plugin Vm Dispatcher (no-op if already running)
-  // 2) Call ListVms to get the state of the VM
-  // 3) Stop the VM if necessary
-  // 4) Uninstall the VM
+  // 1) Ensure DLC is installed (otherwise we will not be able to start the
+  //    dispatcher). Potentially, we can check and skip to 5) if it is not
+  //    installed, but it is probably easier to just always go through the same
+  //    flow.
+  // 2) Start the Plugin Vm Dispatcher (no-op if already running)
+  // 3) Call ListVms to get the state of the VM
+  // 4) Stop the VM if necessary
+  // 5) Uninstall the VM
   // It does not stop the dispatcher, as it will be stopped upon next shutdown
-  UpdateVmState(base::BindOnce(&PluginVmManagerImpl::OnListVmsForUninstall,
-                               weak_ptr_factory_.GetWeakPtr()),
-                base::BindOnce(&PluginVmManagerImpl::UninstallFailed,
-                               weak_ptr_factory_.GetWeakPtr()));
+  InstallDlcAndUpdateVmState(
+      base::BindOnce(&PluginVmManagerImpl::OnListVmsForUninstall,
+                     weak_ptr_factory_.GetWeakPtr()),
+      base::BindOnce(&PluginVmManagerImpl::UninstallFailed,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 uint64_t PluginVmManagerImpl::seneschal_server_handle() const {
@@ -254,6 +265,32 @@
   return vm_state_;
 }
 
+void PluginVmManagerImpl::InstallDlcAndUpdateVmState(
+    base::OnceCallback<void(bool default_vm_exists)> success_callback,
+    base::OnceClosure error_callback) {
+  chromeos::DlcserviceClient::Get()->Install(
+      "pita",
+      base::BindOnce(&PluginVmManagerImpl::OnInstallPluginVmDlc,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     std::move(success_callback), std::move(error_callback)),
+      chromeos::DlcserviceClient::IgnoreProgress);
+}
+
+void PluginVmManagerImpl::OnInstallPluginVmDlc(
+    base::OnceCallback<void(bool default_vm_exists)> success_callback,
+    base::OnceClosure error_callback,
+    const chromeos::DlcserviceClient::InstallResult& install_result) {
+  if (install_result.error == dlcservice::kErrorNone) {
+    UpdateVmState(std::move(success_callback), std::move(error_callback));
+  } else {
+    // TODO(kimjae): Unify the dlcservice error handler with
+    // PluginVmInstaller.
+    LOG(ERROR) << "Couldn't install PluginVM DLC after import: "
+               << install_result.error;
+    std::move(error_callback).Run();
+  }
+}
+
 void PluginVmManagerImpl::OnStartDispatcher(
     base::OnceCallback<void(bool)> success_callback,
     base::OnceClosure error_callback,
@@ -301,30 +338,6 @@
   }
 }
 
-void PluginVmManagerImpl::InstallPluginVmDlc() {
-  chromeos::DlcserviceClient::Get()->Install(
-      "pita",
-      base::BindOnce(&PluginVmManagerImpl::OnInstallPluginVmDlc,
-                     weak_ptr_factory_.GetWeakPtr()),
-      chromeos::DlcserviceClient::IgnoreProgress);
-}
-
-void PluginVmManagerImpl::OnInstallPluginVmDlc(
-    const chromeos::DlcserviceClient::InstallResult& install_result) {
-  if (install_result.error == dlcservice::kErrorNone) {
-    UpdateVmState(base::BindOnce(&PluginVmManagerImpl::OnListVmsForLaunch,
-                                 weak_ptr_factory_.GetWeakPtr()),
-                  base::BindOnce(&PluginVmManagerImpl::LaunchFailed,
-                                 weak_ptr_factory_.GetWeakPtr(),
-                                 PluginVmLaunchResult::kError));
-  } else {
-    // TODO(kimjae): Unify the dlcservice error handler with
-    // PluginVmInstaller.
-    LOG(ERROR) << "Couldn't intall PluginVM DLC after import: "
-               << install_result.error;
-    LaunchFailed();
-  }
-}
 
 void PluginVmManagerImpl::OnListVmsForLaunch(bool default_vm_exists) {
   if (!default_vm_exists) {
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_manager_impl.h b/chrome/browser/chromeos/plugin_vm/plugin_vm_manager_impl.h
index 49600001..fdfad5e 100644
--- a/chrome/browser/chromeos/plugin_vm/plugin_vm_manager_impl.h
+++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_manager_impl.h
@@ -65,6 +65,13 @@
   }
 
  private:
+  void InstallDlcAndUpdateVmState(
+      base::OnceCallback<void(bool default_vm_exists)> success_callback,
+      base::OnceClosure error_callback);
+  void OnInstallPluginVmDlc(
+      base::OnceCallback<void(bool default_vm_exists)> success_callback,
+      base::OnceClosure error_callback,
+      const chromeos::DlcserviceClient::InstallResult& install_result);
   void OnStartDispatcher(
       base::OnceCallback<void(bool default_vm_exists)> success_callback,
       base::OnceClosure error_callback,
@@ -77,9 +84,6 @@
   // The flow to launch a Plugin Vm. We'll probably want to add additional
   // abstraction around starting the services in the future but this is
   // sufficient for now.
-  void InstallPluginVmDlc();
-  void OnInstallPluginVmDlc(
-      const chromeos::DlcserviceClient::InstallResult& install_result);
   void OnListVmsForLaunch(bool default_vm_exists);
   void StartVm();
   void OnStartVm(
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
index 1575ac81..9f221e1 100644
--- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -2222,6 +2222,52 @@
             *policy_service->GetPolicies(ns).GetValue("string"));
 }
 
+IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, LoginWarningShown) {
+  UploadAndInstallDeviceLocalAccountPolicy();
+  AddPublicSessionToDevicePolicy(kAccountId1);
+
+  WaitForPolicy();
+
+  ExpandPublicSessionPod(false);
+
+  // Click the link that switches the pod to its advanced form. Verify that the
+  // pod switches from basic to advanced.
+  ash::LoginScreenTestApi::ClickPublicExpandedAdvancedViewButton();
+  ASSERT_TRUE(ash::LoginScreenTestApi::IsExpandedPublicSessionAdvanced());
+  ASSERT_TRUE(ash::LoginScreenTestApi::IsPublicSessionWarningShown());
+}
+
+class DeviceLocalAccountWarnings : public DeviceLocalAccountTest {
+  void SetUpInProcessBrowserTestFixture() override {
+    DeviceLocalAccountTest::SetUpInProcessBrowserTestFixture();
+    SetManagedSessionsWarningDisabled();
+  }
+
+  void SetManagedSessionsWarningDisabled() {
+    em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
+    em::ManagedGuestSessionPrivacyWarningsProto* managed_sessions_warnings =
+        proto.mutable_managed_guest_session_privacy_warnings();
+    managed_sessions_warnings->set_enabled(false);
+    RefreshDevicePolicy();
+    ASSERT_TRUE(local_policy_mixin_.UpdateDevicePolicy(proto));
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(DeviceLocalAccountWarnings, NoLoginWarningShown) {
+  UploadAndInstallDeviceLocalAccountPolicy();
+  AddPublicSessionToDevicePolicy(kAccountId1);
+
+  WaitForPolicy();
+
+  ExpandPublicSessionPod(false);
+
+  // Click the link that switches the pod to its advanced form. Verify that the
+  // pod switches from basic to advanced.
+  ash::LoginScreenTestApi::ClickPublicExpandedAdvancedViewButton();
+  ASSERT_TRUE(ash::LoginScreenTestApi::IsExpandedPublicSessionAdvanced());
+  ASSERT_FALSE(ash::LoginScreenTestApi::IsPublicSessionWarningShown());
+}
+
 class ManagedSessionsTest : public DeviceLocalAccountTest {
  protected:
   class CertsObserver : public chromeos::PolicyCertificateProvider::Observer {
diff --git a/chrome/browser/chromeos/web_applications/chrome_help_app_ui_delegate.cc b/chrome/browser/chromeos/web_applications/chrome_help_app_ui_delegate.cc
index 99811ad6..cd842cb 100644
--- a/chrome/browser/chromeos/web_applications/chrome_help_app_ui_delegate.cc
+++ b/chrome/browser/chromeos/web_applications/chrome_help_app_ui_delegate.cc
@@ -68,6 +68,9 @@
   source->AddBoolean(
       "HelpAppReleaseNotes",
       base::FeatureList::IsEnabled(chromeos::features::kHelpAppReleaseNotes));
+  source->AddBoolean("HelpAppSearchServiceIntegration",
+                     base::FeatureList::IsEnabled(
+                         chromeos::features::kHelpAppSearchServiceIntegration));
 
   Profile* profile = Profile::FromWebUI(web_ui_);
   PrefService* pref_service = profile->GetPrefs();
diff --git a/chrome/browser/extensions/DEPS b/chrome/browser/extensions/DEPS
index 0f2e5f4..cb789af 100644
--- a/chrome/browser/extensions/DEPS
+++ b/chrome/browser/extensions/DEPS
@@ -29,11 +29,6 @@
   "test_extension_system.cc": [
     "+services/data_decoder",
   ],
-  "cross_origin_read_blocking_browsertest.cc": [
-    # Mostly for helping the test verify UMA values from
-    # network::CrossOriginReadBlocking::Action enum.
-    "+services/network/cross_origin_read_blocking.h"
-  ],
   "webstore_private_apitest.cc" : [
     # TODO(crbug/1095814): Remove this layering violation.
     "+chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.h",
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index f7de2ed..cf7f05c 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/nearby_sharing/nearby_sharing_prefs.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/safe_browsing/generated_safe_browsing_pref.h"
 #include "chrome/common/pref_names.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
@@ -260,6 +261,8 @@
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
   (*s_whitelist)[::prefs::kSafeBrowsingScoutReportingEnabled] =
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
+  (*s_whitelist)[::safe_browsing::kGeneratedSafeBrowsingPref] =
+      settings_api::PrefType::PREF_TYPE_NUMBER;
 
   // Sync and personalization page.
   (*s_whitelist)[::prefs::kSearchSuggestEnabled] =
diff --git a/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc b/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc
index c4f85738..ffa791a2 100644
--- a/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc
+++ b/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc
@@ -57,7 +57,7 @@
 #include "net/test/embedded_test_server/controllable_http_response.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
-#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/mojom/network_context.mojom-shared.h"
 #include "services/network/public/mojom/trust_tokens.mojom-shared.h"
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 7947d8cf..8206d8b 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1205,6 +1205,11 @@
     "expiry_milestone": 88
   },
   {
+    "name": "enable-assistant-better-onboarding",
+    "owners": ["croissant-eng"],
+    "expiry_milestone": 88
+  },
+  {
     "name": "enable-assistant-dsp",
     "owners": [ "croissant-eng" ],
     "expiry_milestone": 88
@@ -1235,6 +1240,11 @@
     "expiry_milestone": 88
   },
   {
+    "name": "enable-assistant-timers-v2",
+    "owners": ["croissant-eng"],
+    "expiry_milestone": 88
+  },
+  {
     "name": "enable-async-dns",
     "owners": [ "ericorth", "net-dev" ],
     "expiry_milestone": 81
@@ -2819,6 +2829,11 @@
     "expiry_milestone": 90
   },
   {
+    "name": "help-app-search-service-integration",
+    "owners": [ "//chromeos/components/help_app_ui/OWNERS" ],
+    "expiry_milestone": 90
+  },
+  {
     "name": "homepage-promo-card",
     "owners": [ "wenyufu", "chrome-android-app@chromium.org" ],
     "expiry_milestone": 90
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 850c1d0c..8af6965 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3525,6 +3525,11 @@
 const char kEnableAssistantAppSupportDescription[] =
     "Enable the Assistant App Support feature";
 
+const char kEnableAssistantBetterOnboardingName[] =
+    "Enable Assistant Better Onboarding";
+const char kEnableAssistantBetterOnboardingDescription[] =
+    "Enables the Assistant better onboarding experience.";
+
 const char kEnableAssistantLauncherIntegrationName[] =
     "Assistant & Launcher integration";
 const char kEnableAssistantLauncherIntegrationDescription[] =
@@ -3544,6 +3549,10 @@
 const char kEnableAssistantRoutinesName[] = "Assistant Routines";
 const char kEnableAssistantRoutinesDescription[] = "Enable Assistant Routines.";
 
+const char kEnableAssistantTimersV2Name[] = "Enable Assistant Timers V2";
+const char kEnableAssistantTimersV2Description[] =
+    "Enables v2 of Assistant timers.";
+
 const char kEnableBackgroundBlurName[] = "Enable background blur.";
 const char kEnableBackgroundBlurDescription[] =
     "Enables background blur for the Launcher, Shelf, Unified System Tray etc.";
@@ -3773,6 +3782,12 @@
 const char kHelpAppReleaseNotesDescription[] =
     "Enables release notes in the help app";
 
+const char kHelpAppSearchServiceIntegrationName[] =
+    "Help App search service integration";
+const char kHelpAppSearchServiceIntegrationDescription[] =
+    "Enables the integration between the help app and the local search"
+    " service. Includes using the search service for in app search.";
+
 const char kHideArcMediaNotificationsName[] = "Hide ARC media notifications";
 const char kHideArcMediaNotificationsDescription[] =
     "Hides media notifications for ARC apps. Requires "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 8c219ed..428a4c3 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -2044,6 +2044,9 @@
 extern const char kEnableAssistantAppSupportName[];
 extern const char kEnableAssistantAppSupportDescription[];
 
+extern const char kEnableAssistantBetterOnboardingName[];
+extern const char kEnableAssistantBetterOnboardingDescription[];
+
 extern const char kEnableAssistantLauncherIntegrationName[];
 extern const char kEnableAssistantLauncherIntegrationDescription[];
 
@@ -2056,6 +2059,9 @@
 extern const char kEnableAssistantRoutinesName[];
 extern const char kEnableAssistantRoutinesDescription[];
 
+extern const char kEnableAssistantTimersV2Name[];
+extern const char kEnableAssistantTimersV2Description[];
+
 extern const char kEnableBackgroundBlurName[];
 extern const char kEnableBackgroundBlurDescription[];
 
@@ -2204,6 +2210,9 @@
 extern const char kHelpAppReleaseNotesName[];
 extern const char kHelpAppReleaseNotesDescription[];
 
+extern const char kHelpAppSearchServiceIntegrationName[];
+extern const char kHelpAppSearchServiceIntegrationDescription[];
+
 extern const char kHideArcMediaNotificationsName[];
 extern const char kHideArcMediaNotificationsDescription[];
 
diff --git a/chrome/browser/media/webrtc/camera_pan_tilt_zoom_permission_context.cc b/chrome/browser/media/webrtc/camera_pan_tilt_zoom_permission_context.cc
index a2a152cc..471775e 100644
--- a/chrome/browser/media/webrtc/camera_pan_tilt_zoom_permission_context.cc
+++ b/chrome/browser/media/webrtc/camera_pan_tilt_zoom_permission_context.cc
@@ -134,10 +134,8 @@
   const std::vector<blink::MediaStreamDevice> devices =
       MediaCaptureDevicesDispatcher::GetInstance()->GetVideoCaptureDevices();
   for (const blink::MediaStreamDevice& device : devices) {
-    if (device.pan_tilt_zoom_supported.has_value() &&
-        device.pan_tilt_zoom_supported.value()) {
+    if (device.pan_tilt_zoom_supported)
       return true;
-    }
   }
   return false;
 }
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc
index 835c1d7..845aa13 100644
--- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc
+++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_factory.cc
@@ -69,7 +69,8 @@
 }
 
 bool SiteDataCacheFacadeFactory::ServiceIsNULLWhileTesting() const {
-  return false;
+  // Tests that want to use this factory will have to explicitly enable it.
+  return true;
 }
 
 }  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc
index 5451e88..359e1ff 100644
--- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc
+++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc
@@ -113,8 +113,8 @@
 
   void TearDown() override {
     use_in_memory_db_for_testing_.reset();
-    profile_.reset();
     facade_factory_.reset();
+    profile_.reset();
     testing::TestWithPerformanceManager::TearDown();
   }
 
@@ -142,8 +142,6 @@
     return mock_cache_raw;
   }
 
-  SiteDataCacheFacadeFactory* facade_factory() { return facade_factory_.get(); }
-
  private:
   std::unique_ptr<TestingProfile> profile_;
   std::unique_ptr<SiteDataCacheFacadeFactory> facade_factory_;
@@ -153,12 +151,12 @@
 TEST_F(SiteDataCacheFacadeTest, IsDataCacheRecordingForTesting) {
   bool cache_is_recording = false;
 
-  auto* facade = facade_factory()->GetForProfile(profile());
-  facade->WaitUntilCacheInitializedForTesting();
+  SiteDataCacheFacade data_cache_facade(profile());
+  data_cache_facade.WaitUntilCacheInitializedForTesting();
   {
     base::RunLoop run_loop;
     auto quit_closure = run_loop.QuitClosure();
-    facade->IsDataCacheRecordingForTesting(
+    data_cache_facade.IsDataCacheRecordingForTesting(
         base::BindLambdaForTesting([&](bool is_recording) {
           cache_is_recording = is_recording;
           std::move(quit_closure).Run();
@@ -167,12 +165,12 @@
   }
   EXPECT_TRUE(cache_is_recording);
 
-  auto* off_record_data_cache_facade =
-      facade_factory()->GetForProfile(profile()->GetPrimaryOTRProfile());
+  SiteDataCacheFacade off_record_data_cache_facade(
+      profile()->GetPrimaryOTRProfile());
   {
     base::RunLoop run_loop;
     auto quit_closure = run_loop.QuitClosure();
-    off_record_data_cache_facade->IsDataCacheRecordingForTesting(
+    off_record_data_cache_facade.IsDataCacheRecordingForTesting(
         base::BindLambdaForTesting([&](bool is_recording) {
           cache_is_recording = is_recording;
           quit_closure.Run();
@@ -196,13 +194,13 @@
       {TestOrigin2().GetURL(), {0, base::Time::Now()}},
   });
 
-  auto* facade = facade_factory()->GetForProfile(profile());
-  facade->WaitUntilCacheInitializedForTesting();
+  SiteDataCacheFacade data_cache_facade(profile());
+  data_cache_facade.WaitUntilCacheInitializedForTesting();
 
   auto* mock_cache_raw = SetUpMockCache();
   mock_cache_raw->SetClearSiteDataForOriginsExpectations(
       {TestOrigin(), TestOrigin2()});
-  facade->OnURLsDeleted(nullptr, deletion_info);
+  data_cache_facade.OnURLsDeleted(nullptr, deletion_info);
   mock_cache_raw->WaitForExpectations();
 }
 
@@ -219,26 +217,27 @@
       {TestOrigin2().GetURL(), {3, base::Time::Now()}},
   });
 
-  auto* facade = facade_factory()->GetForProfile(profile());
-  facade->WaitUntilCacheInitializedForTesting();
+  SiteDataCacheFacade data_cache_facade(profile());
+  data_cache_facade.WaitUntilCacheInitializedForTesting();
 
   auto* mock_cache_raw = SetUpMockCache();
   // |TestOrigin2()| shouldn't be removed as there's still some references to it
   // in the history.
   mock_cache_raw->SetClearSiteDataForOriginsExpectations({TestOrigin()});
-  facade->OnURLsDeleted(nullptr, deletion_info);
+  data_cache_facade.OnURLsDeleted(nullptr, deletion_info);
   mock_cache_raw->WaitForExpectations();
 }
 
 // Verify that origins are removed from the data cache (in memory and on disk)
 // when the history is completely cleared.
 TEST_F(SiteDataCacheFacadeTest, OnURLsDeleted_Full) {
-  auto* facade = facade_factory()->GetForProfile(profile());
-  facade->WaitUntilCacheInitializedForTesting();
+  SiteDataCacheFacade data_cache_facade(profile());
+  data_cache_facade.WaitUntilCacheInitializedForTesting();
 
   auto* mock_cache_raw = SetUpMockCache();
   mock_cache_raw->SetClearAllSiteDataExpectations();
-  facade->OnURLsDeleted(nullptr, history::DeletionInfo::ForAllHistory());
+  data_cache_facade.OnURLsDeleted(nullptr,
+                                  history::DeletionInfo::ForAllHistory());
   mock_cache_raw->WaitForExpectations();
 }
 
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index 1bc96bd..5714ad42d 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -30,7 +30,6 @@
 #include "chrome/common/prerender_util.h"
 #include "components/history/core/browser/history_types.h"
 #include "components/prerender/common/prerender_final_status.h"
-#include "components/prerender/common/prerender_messages.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_handle.h"
@@ -650,10 +649,14 @@
   NotifyPrerenderStop();
 }
 
-void PrerenderContents::CancelPrerenderForUnsupportedScheme(const GURL& url) {
+void PrerenderContents::CancelPrerenderForUnsupportedScheme() {
   Destroy(FINAL_STATUS_UNSUPPORTED_SCHEME);
 }
 
+void PrerenderContents::CancelPrerenderForNoStatePrefetch() {
+  Destroy(FINAL_STATUS_NOSTATE_PREFETCH_FINISHED);
+}
+
 void PrerenderContents::AddPrerenderCancelerReceiver(
     mojo::PendingReceiver<prerender::mojom::PrerenderCanceler> receiver) {
   prerender_canceler_receiver_set_.Add(this, std::move(receiver));
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h
index 3d2241a..15cde43 100644
--- a/chrome/browser/prerender/prerender_contents.h
+++ b/chrome/browser/prerender/prerender_contents.h
@@ -293,7 +293,8 @@
       std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump);
 
   // prerender::mojom::PrerenderCanceler:
-  void CancelPrerenderForUnsupportedScheme(const GURL& url) override;
+  void CancelPrerenderForUnsupportedScheme() override;
+  void CancelPrerenderForNoStatePrefetch() override;
 
   mojo::ReceiverSet<prerender::mojom::PrerenderCanceler>
       prerender_canceler_receiver_set_;
diff --git a/chrome/browser/prerender/prerender_message_filter.cc b/chrome/browser/prerender/prerender_message_filter.cc
deleted file mode 100644
index 33faf9e..0000000
--- a/chrome/browser/prerender/prerender_message_filter.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/prerender/prerender_message_filter.h"
-
-#include "chrome/browser/prerender/prerender_contents.h"
-#include "chrome/browser/prerender/prerender_manager.h"
-#include "chrome/browser/prerender/prerender_manager_factory.h"
-#include "components/prerender/common/prerender_final_status.h"
-#include "components/prerender/common/prerender_messages.h"
-#include "content/public/browser/render_process_host.h"
-
-namespace prerender {
-
-PrerenderMessageFilter::PrerenderMessageFilter(int render_process_id)
-    : BrowserMessageFilter(PrerenderMsgStart),
-      render_process_id_(render_process_id) {}
-
-PrerenderMessageFilter::~PrerenderMessageFilter() = default;
-
-bool PrerenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(PrerenderMessageFilter, message)
-    IPC_MESSAGE_HANDLER(PrerenderHostMsg_PrefetchFinished, OnPrefetchFinished)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-
-  return handled;
-}
-
-void PrerenderMessageFilter::OverrideThreadForMessage(
-    const IPC::Message& message, content::BrowserThread::ID* thread) {
-  if (message.type() == PrerenderHostMsg_PrefetchFinished::ID)
-    *thread = content::BrowserThread::UI;
-}
-
-void PrerenderMessageFilter::OnPrefetchFinished() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  content::RenderProcessHost* render_process_host =
-      content::RenderProcessHost::FromID(render_process_id_);
-  if (!render_process_host)
-    return;
-
-  PrerenderManager* prerender_manager =
-      PrerenderManagerFactory::GetForBrowserContext(
-          render_process_host->GetBrowserContext());
-  if (!prerender_manager)
-    return;
-
-  // Kill the process doing the prefetch. Only one prefetch per renderer is
-  // possible, also prefetches are not shared with other renderer processes.
-  PrerenderContents* prerender_contents =
-      prerender_manager->GetPrerenderContentsForProcess(render_process_id_);
-  if (prerender_contents)
-    prerender_contents->Destroy(FINAL_STATUS_NOSTATE_PREFETCH_FINISHED);
-}
-
-}  // namespace prerender
-
diff --git a/chrome/browser/prerender/prerender_message_filter.h b/chrome/browser/prerender/prerender_message_filter.h
deleted file mode 100644
index 368fdd8..0000000
--- a/chrome/browser/prerender/prerender_message_filter.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_MESSAGE_FILTER_H_
-#define CHROME_BROWSER_PRERENDER_PRERENDER_MESSAGE_FILTER_H_
-
-#include <memory>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "content/public/browser/browser_thread.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-
-namespace IPC {
-class Message;
-}
-
-namespace prerender {
-
-class PrerenderMessageFilter : public content::BrowserMessageFilter {
- public:
-  explicit PrerenderMessageFilter(int render_process_id);
-
- private:
-  friend struct content::BrowserThread::DeleteOnThread<
-      content::BrowserThread::UI>;
-  friend class base::DeleteHelper<PrerenderMessageFilter>;
-
-  ~PrerenderMessageFilter() override;
-
-  // Overridden from content::BrowserMessageFilter.
-  bool OnMessageReceived(const IPC::Message& message) override;
-  void OverrideThreadForMessage(const IPC::Message& message,
-                                content::BrowserThread::ID* thread) override;
-
-  void OnPrefetchFinished();
-
-  const int render_process_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(PrerenderMessageFilter);
-};
-
-}  // namespace prerender
-
-#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_MESSAGE_FILTER_H_
-
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index 1c5b68d0..8b937632 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -58,7 +58,6 @@
 #include "chrome/browser/prefs/pref_metrics_service.h"
 #include "chrome/browser/prerender/prerender_link_manager_factory.h"
 #include "chrome/browser/prerender/prerender_manager_factory.h"
-#include "chrome/browser/prerender/prerender_message_filter.h"
 #include "chrome/browser/profiles/gaia_info_update_service_factory.h"
 #include "chrome/browser/profiles/renderer_updater_factory.h"
 #include "chrome/browser/safe_browsing/certificate_reporting_service_factory.h"
diff --git a/chrome/browser/reputation/safety_tip_infobar.cc b/chrome/browser/reputation/safety_tip_infobar.cc
index a5178535..5416b6e 100644
--- a/chrome/browser/reputation/safety_tip_infobar.cc
+++ b/chrome/browser/reputation/safety_tip_infobar.cc
@@ -26,7 +26,7 @@
 
 SafetyTipInfoBar::SafetyTipInfoBar(
     std::unique_ptr<SafetyTipInfoBarDelegate> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 ScopedJavaLocalRef<jobject> SafetyTipInfoBar::CreateRenderInfoBar(JNIEnv* env) {
   ScopedJavaLocalRef<jstring> ok_button_text =
diff --git a/chrome/browser/reputation/safety_tip_infobar.h b/chrome/browser/reputation/safety_tip_infobar.h
index e990832..ab462bb 100644
--- a/chrome/browser/reputation/safety_tip_infobar.h
+++ b/chrome/browser/reputation/safety_tip_infobar.h
@@ -7,13 +7,13 @@
 
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
 class SafetyTipInfoBarDelegate;
 
 // SafetyTipInfoBar is a thin vineer over ConfirmInfoBar that adds a discrete
 // description (instead of just having a title).
-class SafetyTipInfoBar : public ConfirmInfoBar {
+class SafetyTipInfoBar : public ChromeConfirmInfoBar {
  public:
   static std::unique_ptr<infobars::InfoBar> CreateInfoBar(
       std::unique_ptr<SafetyTipInfoBarDelegate> delegate);
diff --git a/chrome/browser/resources/chromeos/BUILD.gn b/chrome/browser/resources/chromeos/BUILD.gn
index 675d9ee..8daeca9 100644
--- a/chrome/browser/resources/chromeos/BUILD.gn
+++ b/chrome/browser/resources/chromeos/BUILD.gn
@@ -39,6 +39,7 @@
     "accessibility/braille_ime:closure_compile",
     "accessibility/select_to_speak:closure_compile",
     "accessibility/switch_access:closure_compile",
+    "account_manager/components:closure_compile",
     "add_supervision:closure_compile",
     "bluetooth_pairing_dialog:closure_compile",
     "crostini_installer:closure_compile",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
index f4848686..09e2bee 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
@@ -1023,7 +1023,7 @@
       }
       let word = '';
       for (let z = 0; z < wordStarts.length; ++z) {
-        if (wordStarts[z] <= index && wordEnds[z] >= index) {
+        if (wordStarts[z] <= index && wordEnds[z] > index) {
           word = text.substring(wordStarts[z], wordEnds[z]);
           break;
         }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/cursors.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/cursors.js
index 75d4e124..0529f6b 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/cursors.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/cursors.js
@@ -362,7 +362,7 @@
             }
             let start, end;
             for (let i = 0; i < wordStarts.length; i++) {
-              if (newIndex >= wordStarts[i] && newIndex <= wordEnds[i]) {
+              if (newIndex >= wordStarts[i] && newIndex < wordEnds[i]) {
                 start = wordStarts[i];
                 end = wordEnds[i];
                 break;
@@ -384,10 +384,12 @@
             }
             // Go to the next word stop in the same piece of text.
             for (let i = 0; i < wordStarts.length; i++) {
-              if (newIndex >= wordStarts[i] && newIndex <= wordEnds[i]) {
-                const nextIndex = dir == Dir.FORWARD ? i + 1 : i - 1;
-                start = wordStarts[nextIndex];
-                break;
+              if ((dir == Dir.FORWARD && newIndex < wordStarts[i]) ||
+                  (dir == Dir.BACKWARD && newIndex >= wordEnds[i])) {
+                start = wordStarts[i];
+                if (dir == Dir.FORWARD) {
+                  break;
+                }
               }
             }
             if (goog.isDef(start)) {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/locale_output_helper_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/locale_output_helper_test.js
index 76bb52e..baaa6662e 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/locale_output_helper_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/locale_output_helper_test.js
@@ -487,12 +487,18 @@
         .call(doCmd('nextWord'))
         .expectSpeechWithLocale('fr', `l'apres`)
         .call(doCmd('nextWord'))
+        .expectSpeechWithLocale('fr', `-`)
+        .call(doCmd('nextWord'))
         .expectSpeechWithLocale('fr', `midi`)
         .call(doCmd('nextWord'))
+        .expectSpeechWithLocale('fr', `,`)
+        .call(doCmd('nextWord'))
         .expectSpeechWithLocale('fr', `je`)
         .call(doCmd('nextWord'))
         .expectSpeechWithLocale('fr', `dejeune`)
         .call(doCmd('nextWord'))
+        .expectSpeechWithLocale('fr', `.`)
+        .call(doCmd('nextWord'))
         .expectSpeechWithLocale('en', `English: Hello`)
         .call(doCmd('nextWord'))
         .expectSpeechWithLocale('en', `it's`)
@@ -507,9 +513,13 @@
         .call(doCmd('nextWord'))
         .expectSpeechWithLocale('en', `you`)
         .call(doCmd('nextWord'))
+        .expectSpeechWithLocale('en', `.`)
+        .call(doCmd('nextWord'))
         .expectSpeechWithLocale('fr', `français: Comment`)
         .call(doCmd('previousWord'))
-        .expectSpeechWithLocale('en', `English: you`)
+        .expectSpeechWithLocale('en', `English: .`)
+        .call(doCmd('previousWord'))
+        .expectSpeechWithLocale('en', `you`)
         .replay();
   });
 });
diff --git a/chrome/browser/resources/chromeos/account_manager/components/BUILD.gn b/chrome/browser/resources/chromeos/account_manager/components/BUILD.gn
new file mode 100644
index 0000000..7172392
--- /dev/null
+++ b/chrome/browser/resources/chromeos/account_manager/components/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/html_to_js.gni")
+
+js_type_check("closure_compile") {
+  is_polymer3 = true
+  deps = [ ":error_screen" ]
+}
+
+js_library("error_screen") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+}
+
+html_to_js("web_components") {
+  js_files = [ "error_screen.js" ]
+}
diff --git a/chrome/browser/resources/chromeos/account_manager/components/error_screen.html b/chrome/browser/resources/chromeos/account_manager/components/error_screen.html
new file mode 100644
index 0000000..ec16e08
--- /dev/null
+++ b/chrome/browser/resources/chromeos/account_manager/components/error_screen.html
@@ -0,0 +1,40 @@
+<style>
+  /* TODO(anastasiian): move shared font styles to a separate file. */
+  h1 {
+    font-size: 2em;
+    font-weight: normal;
+    margin-bottom: 16px;
+    margin-top: 28px;
+  }
+
+  p {
+    line-height: 1.5;
+    white-space: pre-line;
+  }
+
+  a {
+    color: var(--google-blue-700);
+    text-decoration: none;
+  }
+
+  iron-icon.error-icon {
+    color: var(--google-blue-600);
+  }
+
+  .container {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+  }
+
+  .body-container {
+    flex-grow: 1;
+  }
+</style>
+<div class="container">
+  <iron-icon icon="cr:error-outline" class="error-icon"></iron-icon>
+  <h1>[[errorTitle]]</h1>
+  <div class="body-container">
+    <slot name="body"></slot>
+  </div>
+</div>
diff --git a/chrome/browser/resources/chromeos/account_manager/components/error_screen.js b/chrome/browser/resources/chromeos/account_manager/components/error_screen.js
new file mode 100644
index 0000000..17f2b6e
--- /dev/null
+++ b/chrome/browser/resources/chromeos/account_manager/components/error_screen.js
@@ -0,0 +1,25 @@
+// Copyright 2020 The Chromium 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 'chrome://resources/cr_elements/shared_vars_css.m.js';
+import 'chrome://resources/cr_elements/icons.m.js';
+
+import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+/**
+ * @fileoverview Polymer element for displaying error screens with error icon,
+ * title and body text.
+ */
+
+Polymer({
+  is: 'account-manager-error-screen',
+
+  _template: html`{__html_template__}`,
+
+  properties: {
+    errorTitle: {
+      type: String,
+      value: '',
+    },
+  },
+});
diff --git a/chrome/browser/resources/chromeos/login/oobe_adb_sideloading_screen.js b/chrome/browser/resources/chromeos/login/oobe_adb_sideloading_screen.js
index c1c8ef8..a9c06d2 100644
--- a/chrome/browser/resources/chromeos/login/oobe_adb_sideloading_screen.js
+++ b/chrome/browser/resources/chromeos/login/oobe_adb_sideloading_screen.js
@@ -47,7 +47,6 @@
 
   ready() {
     this.initializeLoginScreen('EnableAdbSideloadingScreen', {
-      noAnimatedTransition: true,
       resetAllowed: true,
     });
   },
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen.css b/chrome/browser/resources/chromeos/login/oobe_screen.css
index a2d3810..36aad8d 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen.css
+++ b/chrome/browser/resources/chromeos/login/oobe_screen.css
@@ -15,30 +15,14 @@
   user-select: none;
 }
 
-.step.animated:not(.faded) {
-  transition: transform 200ms ease-in-out,
-              opacity 200ms ease-in-out,
-              visibility 200ms ease-in-out;
-}
-
 .step.hidden {
   visibility: hidden;
 }
 
-.faded,
-.left,
-.right {
+.faded {
   opacity: 0;
 }
 
-.step.right {
-  transform: translateX(50px);
-}
-
-.step.left {
-  transform: translateX(-50px)
-}
-
 .step.fullscreen {
   height: 100%;
   left: 0;
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_assistant_optin_flow.html b/chrome/browser/resources/chromeos/login/oobe_screen_assistant_optin_flow.html
index 80cc25e0..d7ce125 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_assistant_optin_flow.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_assistant_optin_flow.html
@@ -2,7 +2,7 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<div class="step faded hidden" id="assistant-optin-flow"
+<div class="step hidden" id="assistant-optin-flow"
     role="group" hidden>
   <assistant-optin-flow id="assistant-optin-flow-card"></assistant-optin-flow>
 </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.html b/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.html
index c66fd77a..3990cab 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.html
@@ -1,4 +1,4 @@
-<div class="step right hidden animated" id="auto-enrollment-check" role="group"
+<div class="step hidden" id="auto-enrollment-check" role="group"
      i18n-values="aria-label:autoEnrollmentCheckScreenHeader" hidden>
   <div class="step-contents">
     <div id="auto-enrollment-check-progress" aria-live="polite">
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_enable_debugging.html b/chrome/browser/resources/chromeos/login/oobe_screen_enable_debugging.html
index c6a43d9..7d80e5a9 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_enable_debugging.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_enable_debugging.html
@@ -1,4 +1,4 @@
-<div class="step faded hidden" id="debugging" role="group" hidden
+<div class="step hidden" id="debugging" role="group" hidden
      i18n-values="aria-label:enableDebuggingScreenAccessibleTitle">
   <div class="step-contents" aria-live="polite" aria-atomic="true">
     <div id="enable-debugging-icon"></div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_eula.html b/chrome/browser/resources/chromeos/login/oobe_screen_eula.html
index aa1edefd..d4794f3 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_eula.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_eula.html
@@ -1,4 +1,4 @@
-<div class="step right hidden animated" id="eula" role="group"
+<div class="step hidden" id="eula" role="group"
      i18n-values="aria-label:eulaScreenAccessibleTitle" hidden>
   <oobe-eula-md id="oobe-eula-md"></oobe-eula-md>
 </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.html b/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.html
index 1c5174bf..8d780983 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.html
@@ -2,8 +2,8 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<div class="step faded hidden" id="supervision-transition"
+<div class="step  hidden" id="supervision-transition"
     role="group" hidden>
   <supervision-transition-md id="supervision-transition-md">
   </supervision-transition-md>
-</div>
\ No newline at end of file
+</div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.html b/chrome/browser/resources/chromeos/login/oobe_welcome.html
index be535f8e..12e5fc6 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.html
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.html
@@ -118,9 +118,8 @@
       </hd-iron-icon>
       <div slot="footer" class="layout vertical scroll">
         <oobe-a11y-option id="accessibility-spoken-feedback"
-        checked="[[a11yStatus.spokenFeedbackEnabled]]"
+            checked="[[a11yStatus.spokenFeedbackEnabled]]"
             on-change="onA11yOptionChanged_"
-            chrome-message="enableSpokenFeedback"
             label-for-aria="[[i18nDynamic(locale, 'spokenFeedbackOption')]]"
             class="focus-on-show">
           <span slot="title">
@@ -135,7 +134,7 @@
         </oobe-a11y-option>
         <oobe-a11y-option id="accessibility-large-cursor"
             checked="[[a11yStatus.largeCursorEnabled]]"
-            on-change="onA11yOptionChanged_" chrome-message="enableLargeCursor"
+            on-change="onA11yOptionChanged_"
             label-for-aria="[[i18nDynamic(locale, 'largeCursorOption')]]">
           <span slot="title">
             [[i18nDynamic(locale, 'largeCursorOption')]]
@@ -149,7 +148,7 @@
         </oobe-a11y-option>
         <oobe-a11y-option id="accessibility-high-contrast"
             checked="[[a11yStatus.highContrastEnabled]]"
-            on-change="onA11yOptionChanged_" chrome-message="enableHighContrast"
+            on-change="onA11yOptionChanged_"
             label-for-aria="[[i18nDynamic(locale, 'highContrastOption')]]">
           <span slot="title">
             [[i18nDynamic(locale, 'highContrastOption')]]
@@ -164,7 +163,6 @@
         <oobe-a11y-option id="accessibility-screen-magnifier"
             checked="[[a11yStatus.screenMagnifierEnabled]]"
             on-change="onA11yOptionChanged_"
-            chrome-message="enableScreenMagnifier"
             label-for-aria="[[i18nDynamic(locale, 'screenMagnifierOption')]]">
           <span slot="title">
             [[i18nDynamic(locale, 'screenMagnifierOption')]]
@@ -179,7 +177,6 @@
         <oobe-a11y-option id="accessibility-select-to-speak"
             checked="[[a11yStatus.selectToSpeakEnabled]]"
             on-change="onA11yOptionChanged_"
-            chrome-message="enableSelectToSpeak"
             label-for-aria="[[i18nDynamic(locale, 'selectToSpeakOption')]]"
             id="selectToSpeakOobeOption">
           <span slot="title">
@@ -195,7 +192,6 @@
         <oobe-a11y-option id="accessibility-docked-magnifier"
             checked="[[a11yStatus.dockedMagnifierEnabled]]"
             on-change="onA11yOptionChanged_"
-            chrome-message="enableDockedMagnifier"
             label-for-aria="[[i18nDynamic(locale, 'dockedMagnifierOption')]]">
           <span slot="title">
             [[i18nDynamic(locale, 'dockedMagnifierOption')]]
@@ -210,7 +206,6 @@
         <oobe-a11y-option id="accessibility-virtual-keyboard"
             checked="[[a11yStatus.virtualKeyboardEnabled]]"
             on-change="onA11yOptionChanged_"
-            chrome-message="enableVirtualKeyboard"
             label-for-aria="[[i18nDynamic(locale, 'virtualKeyboardOption')]]">
           <span slot="title">
             [[i18nDynamic(locale, 'virtualKeyboardOption')]]
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.js b/chrome/browser/resources/chromeos/login/oobe_welcome.js
index 8042c77..eaa2bfcc 100644
--- a/chrome/browser/resources/chromeos/login/oobe_welcome.js
+++ b/chrome/browser/resources/chromeos/login/oobe_welcome.js
@@ -95,7 +95,6 @@
       resetAllowed: true,
       enableDebuggingAllowed: true,
       enterDemoModeAllowed: true,
-      noAnimatedTransition: true,
       postponeEnrollmentAllowed: true,
     });
     this.updateLocalizedContent();
@@ -434,8 +433,11 @@
   onA11yOptionChanged_(event) {
     var a11ytarget = /** @type {{chromeMessage: string, checked: boolean}} */ (
         event.currentTarget);
-    chrome.send(
-        'WelcomeScreen.' + a11ytarget.chromeMessage, [a11ytarget.checked]);
+    if (a11ytarget.checked) {
+      this.userActed(a11ytarget.id + '-enable');
+    } else {
+      this.userActed(a11ytarget.id + '-disable');
+    }
   },
 
   /** ******************** Timezone section ******************* */
diff --git a/chrome/browser/resources/chromeos/login/screen_update_required.html b/chrome/browser/resources/chromeos/login/screen_update_required.html
index 9003d1eb..ed3aef5 100644
--- a/chrome/browser/resources/chromeos/login/screen_update_required.html
+++ b/chrome/browser/resources/chromeos/login/screen_update_required.html
@@ -2,7 +2,7 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<div class="step faded" id="update-required" hidden>
+<div class="step hidden" id="update-required" hidden>
     <update-required-card id="update-required-card">
     </update-required-card>
 </div>
diff --git a/chrome/browser/resources/chromeos/login/structure/screens_common.html b/chrome/browser/resources/chromeos/login/structure/screens_common.html
index ca8ae1adf..ee03ce0 100644
--- a/chrome/browser/resources/chromeos/login/structure/screens_common.html
+++ b/chrome/browser/resources/chromeos/login/structure/screens_common.html
@@ -13,9 +13,9 @@
 <include src="../../../../../../ui/login/account_picker/chromeos_screen_account_picker.html">
 <include src="../screen_error_message.html">
 <include src="../screen_arc_terms_of_service.html">
-<gaia-signin id="gaia-signin" class="step right hidden" hidden>
+<gaia-signin id="gaia-signin" class="step hidden" hidden>
 </gaia-signin>
-<tpm-error-message id="tpm-error-message" class="step faded hidden">
+<tpm-error-message id="tpm-error-message" class="step hidden">
 </tpm-error-message>
 <wrong-hwid id="wrong-hwid" class="step hidden"></wrong-hwid>
 <include src="../screen_app_launch_splash.html">
@@ -25,9 +25,9 @@
 <device-disabled id="device-disabled" class="step hidden">
 </device-disabled>
 <include src="../screen_sync_consent.html">
-<fingerprint-setup id="fingerprint-setup" class="step right hidden" hidden>
+<fingerprint-setup id="fingerprint-setup" class="step hidden" hidden>
 </fingerprint-setup>
-<recommend-apps id="recommend-apps" class="step right hidden" hidden>
+<recommend-apps id="recommend-apps" class="step hidden" hidden>
 </recommend-apps>
 <include src="../screen_app_downloading.html">
 <include src="../screen_discover.html">
diff --git a/chrome/browser/resources/chromeos/login/structure/screens_login.html b/chrome/browser/resources/chromeos/login/structure/screens_login.html
index ce4f8d3f..02992cfa 100644
--- a/chrome/browser/resources/chromeos/login/structure/screens_login.html
+++ b/chrome/browser/resources/chromeos/login/structure/screens_login.html
@@ -3,14 +3,14 @@
      found in the LICENSE file. -->
 
 <!-- Login-specific screens -->
-<terms-of-service id="terms-of-service" class="step right hidden">
+<terms-of-service id="terms-of-service" class="step hidden">
 </terms-of-service>
 <include src="../oobe_screen_supervision_transition.html">
 <gaia-password-changed id="gaia-password-changed"
-    class="step faded hidden" hidden>
+    class="step hidden" hidden>
 </gaia-password-changed>
 <active-directory-password-change id="ad-password-change"
-    class="step faded hidden migrate" hidden>
+    class="step hidden migrate" hidden>
 </active-directory-password-change>
 <include src="../screen_encryption_migration.html">
 <include src="../screen_update_required.html">
diff --git a/chrome/browser/resources/chromeos/login/structure/screens_oobe.html b/chrome/browser/resources/chromeos/login/structure/screens_oobe.html
index 08bf6004..8a3be0f9 100644
--- a/chrome/browser/resources/chromeos/login/structure/screens_oobe.html
+++ b/chrome/browser/resources/chromeos/login/structure/screens_oobe.html
@@ -7,14 +7,14 @@
 <!-- Due to implementation details Welcome screen have to be first -->
 <oobe-welcome-md id="connect" class="step hidden" hidden>
 </oobe-welcome-md>
-<hid-detection id="hid-detection" class="step right hidden">
+<hid-detection id="hid-detection" class="step hidden">
 </hid-detection>
 <include src="../oobe_screen_enable_debugging.html">
 <include src="../oobe_screen_demo_setup.html">
-<oobe-network id="network-selection" class="step hidden animated" hidden>
+<oobe-network id="network-selection" class="step hidden" hidden>
 </oobe-network>
 <include src="../oobe_screen_eula.html">
-<oobe-update id="oobe-update" class="step right hidden animated" hidden>
+<oobe-update id="oobe-update" class="step hidden" hidden>
 </oobe-update>
 <include src="../oobe_screen_auto_enrollment_check.html">
 <include src="../oobe_screen_demo_preferences.html">
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index a0a669d3..8a1ab3c 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -254,7 +254,6 @@
     "autofill_page:autofill_section",
     "autofill_page:payments_section",
     "privacy_page:cookies_page",
-    "privacy_page:safe_browsing_browser_proxy",
     "privacy_page:security_page",
     "site_settings:local_data_browser_proxy",
     "site_settings:protocol_handlers",
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn
index 3e19c60..71795b2 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn
@@ -8,31 +8,54 @@
   deps = [
     ":ambient_mode_browser_proxy",
     ":ambient_mode_page",
+    ":ambient_mode_photos_page",
+    ":constants",
   ]
 }
 
 js_library("ambient_mode_browser_proxy") {
-  deps = [ "//ui/webui/resources/js:cr" ]
+  deps = [
+    ":constants",
+    "//ui/webui/resources/js:cr",
+  ]
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
 
 js_library("ambient_mode_page") {
   deps = [
     ":ambient_mode_browser_proxy",
+    ":constants",
+    "..:os_route",
+    "../..:router",
     "../../prefs:prefs_behavior",
     "//ui/webui/resources/js:cr",
     "//ui/webui/resources/js:i18n_behavior",
-    "//ui/webui/resources/js:load_time_data",
     "//ui/webui/resources/js:web_ui_listener_behavior",
   ]
 }
 
+js_library("ambient_mode_photos_page") {
+  deps = [
+    ":ambient_mode_browser_proxy",
+    ":constants",
+    "..:os_route",
+    "../..:router",
+    "//ui/webui/resources/js:cr",
+    "//ui/webui/resources/js:i18n_behavior",
+    "//ui/webui/resources/js:web_ui_listener_behavior",
+  ]
+}
+
+js_library("constants") {
+}
+
 # TODO: Uncomment as the Polymer3 migration makes progress.
 #js_type_check("closure_compile_module") {
 #  is_polymer3 = true
 #  deps = [
 #    ":ambient_mode_browser_proxy.m",
-#    ":ambient_mode_page.m"
+#    ":ambient_mode_page.m",
+#    ":ambient_mode_photos_page.m",
 #  ]
 #}
 
@@ -52,11 +75,20 @@
   extra_deps = [ ":ambient_mode_page_module" ]
 }
 
+js_library("ambient_mode_photos_page.m") {
+  sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.m.js" ]
+  deps = [
+    # TODO: Fill those in.
+  ]
+  extra_deps = [ ":ambient_mode_photos_page_module" ]
+}
+
 import("//tools/polymer/polymer.gni")
 
 group("polymer3_elements") {
   public_deps = [
     ":ambient_mode_page_module",
+    ":ambient_mode_photos_page_module",
     ":modulize",
   ]
 }
@@ -67,8 +99,17 @@
   html_type = "dom-module"
 }
 
+polymer_modulizer("ambient_mode_photos_page") {
+  js_file = "ambient_mode_photos_page.js"
+  html_file = "ambient_mode_photos_page.html"
+  html_type = "dom-module"
+}
+
 import("//ui/webui/resources/tools/js_modulizer.gni")
 
 js_modulizer("modulize") {
-  input_files = [ "ambient_mode_browser_proxy.js" ]
+  input_files = [
+    "ambient_mode_browser_proxy.js",
+    "constants.js",
+  ]
 }
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js
index 4a2ccaf2..23a944b 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js
@@ -16,8 +16,27 @@
      */
     onAmbientModePageReady() {}
 
-    /** Updates the selected topic source to server. */
-    onTopicSourceSelectedChanged(selected) {}
+    /**
+     * Updates the selected topic source to server.
+     * @param {!AmbientModeTopicSource} topicSource the selected topic source.
+     */
+    setSelectedTopicSource(topicSource) {}
+
+    /**
+     * Retrieves the personal album and art categories from server. As a
+     * response, the C++ sends the 'photos-containers-changed' WebUIListener
+     * event.
+     * @param {!AmbientModeTopicSource} topicSource the topic source for which
+     *     the containers requested
+     * for.
+     */
+    requestPhotosContainers(topicSource) {}
+
+    /**
+     * Updates the selected personal albums or art categories to server.
+     * @param {!Array<string>} containers the selected albums or categeries.
+     */
+    setSelectedPhotosContainers(containers) {}
   }
 
   /** @implements {settings.AmbientModeBrowserProxy} */
@@ -28,8 +47,18 @@
     }
 
     /** @override */
-    onTopicSourceSelectedChanged(selected) {
-      chrome.send('onTopicSourceSelectedChanged', [selected]);
+    setSelectedTopicSource(topicSource) {
+      chrome.send('setSelectedTopicSource', [topicSource]);
+    }
+
+    /** @override */
+    requestPhotosContainers(topicSource) {
+      chrome.send('requestPhotosContainers', [topicSource]);
+    }
+
+    /** @override */
+    setSelectedPhotosContainers(containers) {
+      chrome.send('setSelectedPhotosContainers', containers);
     }
   }
 
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.html
index 38c8cf8..e11f702d 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.html
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.html
@@ -5,6 +5,9 @@
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="constants.html">
+<link rel="import" href="../os_route.html">
+<link rel="import" href="../../router.html">
 <link rel="import" href="../../controls/settings_radio_group.html">
 <link rel="import" href="../../controls/settings_toggle_button.html">
 <link rel="import" href="../../settings_shared_css.html">
@@ -33,19 +36,22 @@
       <label id="topicSourceDescription" class="cr-padded-text">
           $i18n{ambientModeTopicSourceTitle}
       </label>
+
+      <!-- TODO(b/159746638): Implement a new UI to pick topic source and open
+      subpage. -->
       <div class="list-frame">
         <!-- Disable the radio buttons before the selection is fetched from
         server. -->
         <cr-radio-group id="topicSourceRadioGroup"
             aria-labelledby="topicSourceDescription"
-            selected="[[topicSourceSelected_]]"
-            on-selected-changed="onTopicSourceSelectedChanged_"
-            disabled="[[!isValidTopicSource_(topicSourceSelected_)]]">
-          <cr-radio-button name="[[topicSource_.GOOGLE_PHOTOS]]"
+            selected="[[selectedTopicSource_]]"
+            on-click="onTopicSourceClicked_"
+            disabled="[[!isValidTopicSource_(selectedTopicSource_)]]">
+          <cr-radio-button name="[[AmbientModeTopicSource.GOOGLE_PHOTOS]]"
               class="list-item underbar"
               label="$i18n{ambientModeTopicSourceGooglePhotos}">
           </cr-radio-button>
-          <cr-radio-button name="[[topicSource_.ART_GALLERY]]"
+          <cr-radio-button name="[[AmbientModeTopicSource.ART_GALLERY]]"
               class="list-item underbar"
               label="$i18n{ambientModeTopicSourceArtGallery}">
           </cr-radio-button>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js
index 9734718..c9f3127c 100644
--- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js
@@ -12,29 +12,28 @@
   behaviors: [I18nBehavior, PrefsBehavior, WebUIListenerBehavior],
 
   properties: {
+    /** Preferences state. */
     prefs: Object,
 
     /**
-     * Enum values for topicSourceRadioGroup.
-     * Values need to stay in sync with the enum |ash::AmbientModeTopicSource|.
-     * @private {!Object<string, number>}
+     * Used to refer to the enum values in the HTML.
+     * @private {!Object}
      */
-    topicSource_: {
+    AmbientModeTopicSource: {
       type: Object,
-      value: {
-        UNKNOWN: -1,
-        GOOGLE_PHOTOS: 0,
-        ART_GALLERY: 1,
-      },
-      readOnly: true,
+      value: AmbientModeTopicSource,
     },
 
-    /** @private */
-    topicSourceSelected_: {
-      type: String,
-      value() {
-        return this.topicSource_.UNKNOWN;
-      },
+    /** @private {!AmbientModeTopicSource} */
+    selectedTopicSource_: {
+      type: AmbientModeTopicSource,
+      value: AmbientModeTopicSource.UNKNOWN,
+    },
+
+    /** @private {!AmbientModeTopicSource} */
+    previousTopicSource_: {
+      type: AmbientModeTopicSource,
+      value: AmbientModeTopicSource.UNKNOWN,
     },
   },
 
@@ -49,7 +48,8 @@
   /** @override */
   ready() {
     this.addWebUIListener('topic-source-changed', (topicSource) => {
-      this.topicSourceSelected_ = topicSource;
+      this.selectedTopicSource_ = topicSource;
+      this.previousTopicSource_ = topicSource;
     });
 
     this.browserProxy_.onAmbientModePageReady();
@@ -65,9 +65,23 @@
   },
 
   /** @private */
-  onTopicSourceSelectedChanged_() {
-    return this.browserProxy_.onTopicSourceSelectedChanged(
-        this.$$('#topicSourceRadioGroup').selected);
+  onTopicSourceClicked_() {
+    const selectedTopicSource = this.$$('#topicSourceRadioGroup').selected;
+    if (selectedTopicSource === '0') {
+      this.selectedTopicSource_ = AmbientModeTopicSource.GOOGLE_PHOTOS;
+    } else if (selectedTopicSource === '1') {
+      this.selectedTopicSource_ = AmbientModeTopicSource.ART_GALLERY;
+    }
+
+    if (this.selectedTopicSource_ !== this.previousTopicSource_) {
+      this.previousTopicSource_ = this.selectedTopicSource_;
+      this.browserProxy_.setSelectedTopicSource(this.selectedTopicSource_);
+    }
+
+    const params = new URLSearchParams();
+    params.append('topicSource', JSON.stringify(this.selectedTopicSource_));
+    settings.Router.getInstance().navigateTo(
+        settings.routes.AMBIENT_MODE_PHOTOS, params);
   },
 
   /**
@@ -76,6 +90,6 @@
    * @private
    */
   isValidTopicSource_(topicSource) {
-    return this.topicSourceSelected_ !== this.topicSource_.UNKNOWN;
+    return topicSource !== AmbientModeTopicSource.UNKNOWN;
   },
 });
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.html
new file mode 100644
index 0000000..052943e
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.html
@@ -0,0 +1,35 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="ambient_mode_browser_proxy.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="constants.html">
+<link rel="import" href="../os_route.html">
+<link rel="import" href="../../router.html">
+<link rel="import" href="../../settings_shared_css.html">
+
+<dom-module id="settings-ambient-mode-photos-page">
+  <template>
+    <style include="settings-shared">
+    </style>
+
+    <div class="cr-row first">
+      <h2 class="flex">
+        [[getDescription_(topicSource_)]]
+      </h2>
+    </div>
+    <iron-list id="containers" class="list-frame" items="[[photosContainers_]]">
+      <template>
+        <cr-checkbox class="list-item"
+            checked="[[item.checked]]"
+            on-change="onCheckboxChange_"
+            label="[[item.title]]">
+          [[item.title]]
+        </cr-checkbox>
+      </template>
+    </iron-list>
+    </div>
+  </template>
+  <script src="ambient_mode_photos_page.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.js
new file mode 100644
index 0000000..d019114
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_photos_page.js
@@ -0,0 +1,109 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview 'settings-ambient-mode-photos-page' is the settings page to
+ * select personal albums in Google Photos or categories in Art gallary.
+ */
+Polymer({
+  is: 'settings-ambient-mode-photos-page',
+
+  behaviors:
+      [I18nBehavior, settings.RouteObserverBehavior, WebUIListenerBehavior],
+
+  properties: {
+    /** @private {!AmbientModeTopicSource} */
+    topicSource_: {
+      type: AmbientModeTopicSource,
+      value() {
+        return AmbientModeTopicSource.UNKNOWN;
+      },
+    },
+
+    /** @private {Array<Object>} */
+    photosContainers_: Array,
+  },
+
+  /** @private {?settings.AmbientModeBrowserProxy} */
+  browserProxy_: null,
+
+  /** @override */
+  created() {
+    this.browserProxy_ = settings.AmbientModeBrowserProxyImpl.getInstance();
+  },
+
+  /** @override */
+  ready() {
+    this.addWebUIListener(
+        'photos-containers-changed', (AmbientModeSettings) => {
+          // This page has been reused by other topic source since the last time
+          // requesting the containers. Do not update on this stale event.
+          if (AmbientModeSettings.topicSource !== this.topicSource_) {
+            return;
+          }
+          this.photosContainers_ = AmbientModeSettings.topicContainers;
+        });
+  },
+
+  /**
+   * RouteObserverBehavior
+   * @param {!settings.Route} currentRoute
+   * @protected
+   */
+  currentRouteChanged(currentRoute) {
+    if (currentRoute !== settings.routes.AMBIENT_MODE_PHOTOS) {
+      return;
+    }
+
+    const topicSourceParam =
+        settings.Router.getInstance().getQueryParameters().get('topicSource');
+    const topicSourceInt = parseInt(topicSourceParam, 10);
+
+    if (isNaN(topicSourceInt)) {
+      assertNotReached();
+      return;
+    }
+
+    this.topicSource_ = /** @type {!AmbientModeTopicSource} */ (topicSourceInt);
+    if (this.topicSource_ === AmbientModeTopicSource.GOOGLE_PHOTOS) {
+      this.parentNode.pageTitle =
+          this.i18n('ambientModeTopicSourceGooglePhotos');
+    } else if (this.topicSource_ === AmbientModeTopicSource.ART_GALLERY) {
+      this.parentNode.pageTitle = this.i18n('ambientModeTopicSourceArtGallery');
+    } else {
+      assertNotReached();
+      return;
+    }
+
+    this.photosContainers_ = [];
+    this.browserProxy_.requestPhotosContainers(this.topicSource_);
+  },
+
+  /**
+   * @param {number} topicSource
+   * @return {string}
+   * @private
+   */
+  getDescription_(topicSource) {
+    // TODO(b/159766700): Finialize the strings and i18n.
+    if (topicSource === AmbientModeTopicSource.GOOGLE_PHOTOS) {
+      return 'A slideshow of selected memories will be created';
+    } else {
+      return 'Curated images and artwork';
+    }
+  },
+
+  /** @private */
+  onCheckboxChange_() {
+    const checkboxes = this.$$('#containers').querySelectorAll('cr-checkbox');
+    const containers = [];
+    checkboxes.forEach((checkbox) => {
+      if (checkbox.checked && !checkbox.hidden) {
+        containers.push(checkbox.label);
+      }
+    });
+    this.browserProxy_.setSelectedPhotosContainers(containers);
+  }
+
+});
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.html
new file mode 100644
index 0000000..2b6bc6b
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.html
@@ -0,0 +1 @@
+<script src="constants.js"></script>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.js
new file mode 100644
index 0000000..4bd440b
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.js
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Enumeration of the topic source, i.e. where the photos come from.
+ * Values need to stay in sync with the enum |ash::AmbientModeTopicSource|.
+ * @enum {number}
+ */
+/* #export */ const AmbientModeTopicSource = {
+  UNKNOWN: -1,
+  GOOGLE_PHOTOS: 0,
+  ART_GALLERY: 1,
+};
+
+/**
+ * Settings containing topic source and the photos containers.
+ *
+ * @typedef {{
+ *   topicSource: !AmbientModeTopicSource,
+ *   topicContainers: !Array,
+ * }}
+ */
+/* #export */ let AmbientModeSettings;
diff --git a/chrome/browser/resources/settings/chromeos/os_route.js b/chrome/browser/resources/settings/chromeos/os_route.js
index 482e6c67..b8e6976e 100644
--- a/chrome/browser/resources/settings/chromeos/os_route.js
+++ b/chrome/browser/resources/settings/chromeos/os_route.js
@@ -149,6 +149,9 @@
       r.AMBIENT_MODE = createSubpage(
           r.PERSONALIZATION, mojom.AMBIENT_MODE_SUBPAGE_PATH,
           Subpage.kAmbientMode);
+      r.AMBIENT_MODE_PHOTOS = createSubpage(
+          r.AMBIENT_MODE, mojom.AMBIENT_MODE_PHOTOS_SUBPAGE_PATH,
+          Subpage.kAmbientModePhotos);
     }
 
     // Search and Assistant section.
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_routes.js b/chrome/browser/resources/settings/chromeos/os_settings_routes.js
index 8fab7f1..07297fe 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_routes.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_routes.js
@@ -13,6 +13,8 @@
  *   ACCOUNTS: !settings.Route,
  *   ACCOUNT_MANAGER: !settings.Route,
  *   ADVANCED: !settings.Route,
+ *   AMBIENT_MODE: !settings.Route,
+ *   AMBIENT_MODE_PHOTOS: !settings.Route,
  *   APP_MANAGEMENT: !settings.Route,
  *   APP_MANAGEMENT_DETAIL: !settings.Route,
  *   APP_MANAGEMENT_PLUGIN_VM_SHARED_PATHS: !settings.Route,
diff --git a/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.html b/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.html
index 21df30a..7aeaed6 100644
--- a/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.html
+++ b/chrome/browser/resources/settings/chromeos/personalization_page/personalization_page.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="../ambient_mode_page/ambient_mode_page.html">
+<link rel="import" href="../ambient_mode_page/ambient_mode_photos_page.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="change_picture.html">
@@ -65,6 +66,14 @@
             </settings-ambient-mode-page>
           </settings-subpage>
         </template>
+
+        <template is="dom-if" route-path="/ambientMode/photos">
+          <settings-subpage>
+            <settings-ambient-mode-photos-page>
+            </settings-ambient-mode-photos-page>
+          </settings-subpage>
+        </template>
+
       </template>
     </settings-animated-pages>
   </template>
diff --git a/chrome/browser/resources/settings/controls/settings_radio_group.js b/chrome/browser/resources/settings/controls/settings_radio_group.js
index d15a91f..473f343 100644
--- a/chrome/browser/resources/settings/controls/settings_radio_group.js
+++ b/chrome/browser/resources/settings/controls/settings_radio_group.js
@@ -20,6 +20,16 @@
   properties: {
     groupAriaLabel: String,
 
+    /**
+     * If true, do not automatically set the preference value. This allows the
+     * container to confirm the change first then call either sendPrefChange
+     * or resetToPrefValue accordingly.
+     */
+    noSetPref: {
+      type: Boolean,
+      value: false,
+    },
+
     selected: String,
 
     selectableElements: {
@@ -33,24 +43,31 @@
   },
 
   observers: [
-    'prefChanged_(pref.*)',
+    'resetToPrefValue(pref.*)',
   ],
 
-  /** @private */
-  prefChanged_() {
+  /** Reset the selected value to match the current pref value. */
+  resetToPrefValue() {
     const pref = /** @type {!chrome.settingsPrivate.PrefObject} */ (this.pref);
     this.selected = Settings.PrefUtil.prefToString(pref);
   },
 
-  /** @private */
-  onSelectedChanged_() {
+  /** Update the pref to the current selected value. */
+  sendPrefChange() {
     if (!this.pref) {
       return;
     }
-    this.selected = this.$$('cr-radio-group').selected;
     this.set(
         'pref.value',
         Settings.PrefUtil.stringToPrefValue(this.selected, this.pref));
+  },
+
+  /** @private */
+  onSelectedChanged_() {
+    this.selected = this.$$('cr-radio-group').selected;
+    if (!this.noSetPref) {
+      this.sendPrefChange();
+    }
     this.fire('change');
   },
 });
diff --git a/chrome/browser/resources/settings/lazy_load.js b/chrome/browser/resources/settings/lazy_load.js
index 5eba5f7..ce038675 100644
--- a/chrome/browser/resources/settings/lazy_load.js
+++ b/chrome/browser/resources/settings/lazy_load.js
@@ -74,12 +74,12 @@
 export {ImportDataBrowserProxyImpl, ImportDataStatus} from './people_page/import_data_browser_proxy.js';
 export {ManageProfileBrowserProxyImpl, ProfileShortcutStatus} from './people_page/manage_profile_browser_proxy.js';
 // </if>
-export {SafeBrowsingBrowserProxy, SafeBrowsingBrowserProxyImpl, SafeBrowsingRadioManagedState} from './privacy_page/safe_browsing_browser_proxy.js';
 export {BioEnrollDialogPage} from './privacy_page/security_keys_bio_enroll_dialog.js';
 export {Ctap2Status, SampleStatus, SecurityKeysBioEnrollProxyImpl, SecurityKeysCredentialBrowserProxyImpl, SecurityKeysPINBrowserProxyImpl, SecurityKeysResetBrowserProxyImpl} from './privacy_page/security_keys_browser_proxy.js';
 export {CredentialManagementDialogPage} from './privacy_page/security_keys_credential_management_dialog.js';
 export {ResetDialogPage} from './privacy_page/security_keys_reset_dialog.js';
 export {SetPINDialogPage} from './privacy_page/security_keys_set_pin_dialog.js';
+export {SafeBrowsingSetting} from './privacy_page/security_page.js';
 // <if expr="chromeos">
 export {AndroidInfoBrowserProxyImpl} from './site_settings/android_info_browser_proxy.js';
 // </if>
diff --git a/chrome/browser/resources/settings/os_settings_resources.grd b/chrome/browser/resources/settings/os_settings_resources.grd
index 3c93fcf..3eea67fd 100644
--- a/chrome/browser/resources/settings/os_settings_resources.grd
+++ b/chrome/browser/resources/settings/os_settings_resources.grd
@@ -69,18 +69,30 @@
       <structure name="IDR_OS_SETTINGS_A11Y_PAGE_HTML"
                  file="chromeos/os_a11y_page/os_a11y_page.html"
                  compress="false" type="chrome_html" />
-      <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_PAGE_JS"
+      <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_JS"
                  file="chromeos/ambient_mode_page/ambient_mode_page.js"
                  compress="false" type="chrome_html" />
-      <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_PAGE_HTML"
+      <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_HTML"
                  file="chromeos/ambient_mode_page/ambient_mode_page.html"
                  compress="false" type="chrome_html" />
-      <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_BROWSER_PROXY_JS"
+      <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PHOTOS_PAGE_JS"
+                 file="chromeos/ambient_mode_page/ambient_mode_photos_page.js"
+                 compress="false" type="chrome_html" />
+      <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PHOTOS_PAGE_HTML"
+                 file="chromeos/ambient_mode_page/ambient_mode_photos_page.html"
+                 compress="false" type="chrome_html" />
+      <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_BROWSER_PROXY_JS"
                  file="chromeos/ambient_mode_page/ambient_mode_browser_proxy.js"
                  compress="false" type="chrome_html" />
-      <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_BROWSER_PROXY_HTML"
+      <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_BROWSER_PROXY_HTML"
                  file="chromeos/ambient_mode_page/ambient_mode_browser_proxy.html"
                  compress="false" type="chrome_html" />
+      <structure name="IDR_OS_SETTINGS_AMBIENT_CONSTANTS_JS"
+                 file="chromeos/ambient_mode_page/constants.js"
+                 compress="false" type="chrome_html" />
+      <structure name="IDR_OS_SETTINGS_AMBIENT_CONSTANTS_HTML"
+                 file="chromeos/ambient_mode_page/constants.html"
+                 compress="false" type="chrome_html" />
       <structure name="IDR_OS_SETTINGS_APPS_PAGE_JS"
                  file="chromeos/os_apps_page/os_apps_page.js"
                  compress="false" type="chrome_html" />
diff --git a/chrome/browser/resources/settings/privacy_page/BUILD.gn b/chrome/browser/resources/settings/privacy_page/BUILD.gn
index c8b89afc..c73a7c4 100644
--- a/chrome/browser/resources/settings/privacy_page/BUILD.gn
+++ b/chrome/browser/resources/settings/privacy_page/BUILD.gn
@@ -49,7 +49,6 @@
     ":personalization_options.m",
     ":privacy_page",
     ":privacy_page_browser_proxy.m",
-    ":safe_browsing_browser_proxy",
     ":secure_dns",
     ":secure_dns_input",
     ":security_keys_bio_enroll_dialog",
@@ -177,13 +176,6 @@
   extra_deps = [ ":modulize" ]
 }
 
-js_library("safe_browsing_browser_proxy") {
-  deps = [
-    "../site_settings:site_settings_prefs_browser_proxy",
-    "//ui/webui/resources/js:cr.m",
-  ]
-}
-
 js_library("security_keys_bio_enroll_dialog") {
   deps = [
     ":security_keys_browser_proxy",
@@ -249,7 +241,6 @@
   deps = [
     ":disable_safebrowsing_dialog",
     ":privacy_page_browser_proxy.m",
-    ":safe_browsing_browser_proxy",
     "..:i18n_setup",
     "..:metrics_browser_proxy",
     "..:route",
diff --git a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.html b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.html
index fc617b3..14bc311 100644
--- a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.html
+++ b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.html
@@ -7,7 +7,6 @@
         opacity: 1;
       }
 
-      cr-policy-indicator,
       cr-policy-pref-indicator,
       :host([disabled]) cr-expand-button {
         pointer-events: auto;
@@ -80,17 +79,9 @@
         </div>
         <template is="dom-if" if="[[pref]]">
           <cr-policy-pref-indicator pref="[[pref]]" icon-aria-label="[[label]]"
-            associated-value="[[name]]">
+              associated-value="[[name]]">
           </cr-policy-pref-indicator>
         </template>
-        <template is="dom-if"
-            if="[[shouldShowPolicyIndicator_(pref, policyIndicatorType)]]">
-          <cr-policy-indicator id="policyIndicator"
-              on-click="onIndicatorClick_"
-              on-aria-label="[[label]]"
-              indicator-type="[[policyIndicatorType]]">
-          </cr-policy-indicator>
-        </template>
         <div hidden$="[[noCollapse]]" class="separator"></div>
         <cr-expand-button hidden$="[[noCollapse]]" expanded="{{expanded}}">
         </cr-expand-button>
diff --git a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.js b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.js
index 8b77b4a..ff4616b 100644
--- a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.js
+++ b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.js
@@ -4,12 +4,10 @@
 
 import 'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.m.js';
 import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_style_css.m.js';
-import 'chrome://resources/cr_elements/policy/cr_policy_indicator.m.js';
 import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
 import '../settings_shared_css.m.js';
 
 import {CrRadioButtonBehavior} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_behavior.m.js';
-import {CrPolicyIndicatorType} from 'chrome://resources/cr_elements/policy/cr_policy_indicator_behavior.m.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 Polymer({
@@ -28,15 +26,6 @@
       value: false,
     },
 
-    /**
-     * Which indicator type to show (or NONE).
-     * @type {CrPolicyIndicatorType}
-     */
-    policyIndicatorType: {
-      type: String,
-      value: CrPolicyIndicatorType.NONE,
-    },
-
     noCollapse: Boolean,
 
     label: String,
@@ -69,16 +58,6 @@
     this.expanded = this.checked;
   },
 
-  /**
-   * @param {!Event} e
-   * @private
-   */
-  onIndicatorClick_(e) {
-    // Prevent interacting with the indicator changing anything when disabled.
-    e.preventDefault();
-    e.stopPropagation();
-  },
-
   /** @private */
   onPrefChanged_() {
     // If the preference has been set, and is managed, this control should be
@@ -90,9 +69,4 @@
         !(!!this.pref.userSelectableValues &&
           this.pref.userSelectableValues.includes(this.name));
   },
-
-  /** @private */
-  shouldShowPolicyIndicator_() {
-    return !this.pref;
-  },
 });
diff --git a/chrome/browser/resources/settings/privacy_page/safe_browsing_browser_proxy.html b/chrome/browser/resources/settings/privacy_page/safe_browsing_browser_proxy.html
deleted file mode 100644
index 98abda79..0000000
--- a/chrome/browser/resources/settings/privacy_page/safe_browsing_browser_proxy.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator_behavior.html">
-<script src="safe_browsing_browser_proxy.js"></script>
diff --git a/chrome/browser/resources/settings/privacy_page/safe_browsing_browser_proxy.js b/chrome/browser/resources/settings/privacy_page/safe_browsing_browser_proxy.js
deleted file mode 100644
index 2e7daf7..0000000
--- a/chrome/browser/resources/settings/privacy_page/safe_browsing_browser_proxy.js
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/** @fileoverview Handles Safe Browsing settings updates */
-
-// clang-format on
-import {CrPolicyIndicatorType} from 'chrome://resources/cr_elements/policy/cr_policy_indicator_behavior.m.js';
-import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js';
-
-// clang-format off
-
-  /**
-   * Stores information about the management state of a control, i.e. whether
-   * it is disabled and what indicator should be shown (including
-   * CrPolicyIndicatorType::NONE)
-   * @typedef {{disabled: boolean,
-   *            indicator: !CrPolicyIndicatorType}}
-   */
-  export let ManagedState;
-
-  /**
-   * Represents the management state of the Safe Browsing radio buttons.
-   * @typedef {{enhanced: !ManagedState,
-   *            standard: !ManagedState,
-   *            disabled: !ManagedState }}
-   */
-  export let SafeBrowsingRadioManagedState;
-
-  /** @interface */
-  export class SafeBrowsingBrowserProxy {
-    /**
-     * Gets the current Safe Browsing radio controls managed state.
-     * @return {!Promise<!SafeBrowsingRadioManagedState>}
-     */
-    getSafeBrowsingRadioManagedState() {}
-
-    /**
-     * Ensures that Safe Browsing Enhanced preference is in a consistent
-     * state for the currently enabled features.
-     * TODO(crbug.com/1074499) Remove this logic when Enhanced protection is
-     * considered stable.
-     */
-     validateSafeBrowsingEnhanced() {}
-  }
-
-  /** @implements {SafeBrowsingBrowserProxy} */
-  export class SafeBrowsingBrowserProxyImpl {
-    /** @override */
-    getSafeBrowsingRadioManagedState() {
-      return sendWithPromise('getSafeBrowsingRadioManagedState');
-    }
-
-    /** @override */
-    validateSafeBrowsingEnhanced() {
-      chrome.send('validateSafeBrowsingEnhanced');
-    }
-  }
-
-  addSingletonGetter(SafeBrowsingBrowserProxyImpl);
-
diff --git a/chrome/browser/resources/settings/privacy_page/security_page.html b/chrome/browser/resources/settings/privacy_page/security_page.html
index 9f7e235..b228c2e 100644
--- a/chrome/browser/resources/settings/privacy_page/security_page.html
+++ b/chrome/browser/resources/settings/privacy_page/security_page.html
@@ -61,18 +61,16 @@
     </picture>
     <div id="safeBrowsingSection">
       <h2>$i18n{safeBrowsingSectionLabel}</h2>
-      <cr-radio-group id="safeBrowsingRadio"
-          selected="[[selectSafeBrowsingRadio_]]"
+      <settings-radio-group id="safeBrowsingRadioGroup" no-set-pref
+          pref="{{prefs.generated.safe_browsing}}"
           selectable-elements="cr-radio-button, settings-collapse-radio-button"
-          on-selected-changed="onSafeBrowsingRadioChange_">
-        <settings-collapse-radio-button name="[[safeBrowsingEnum_.ENHANCED]]"
-            id="safeBrowsingEnhanced"
+          on-change="onSafeBrowsingRadioChange_">
+        <settings-collapse-radio-button id="safeBrowsingEnhanced"
+            name="[[safeBrowsingSettingEnum_.ENHANCED]]"
+            pref="[[prefs.generated.safe_browsing]]"
             label="$i18n{safeBrowsingEnhanced}"
             sub-label="$i18n{safeBrowsingEnhancedDesc}"
-            hidden="[[!safeBrowsingEnhancedEnabled_]]"
-            disabled="[[safeBrowsingRadioManagedState_.enhanced.disabled]]"
-            policy-indicator-type=
-                "[[safeBrowsingRadioManagedState_.enhanced.indicator]]">
+            hidden="[[!safeBrowsingEnhancedEnabled_]]">
           <div slot="collapse">
             <div class="bullet-line">
               <iron-icon icon="cr:security"></iron-icon>
@@ -106,14 +104,12 @@
             </div>
           </div>
         </settings-collapse-radio-button>
-        <settings-collapse-radio-button name="[[safeBrowsingEnum_.STANDARD]]"
-            id="safeBrowsingStandard"
+        <settings-collapse-radio-button id="safeBrowsingStandard"
+            name="[[safeBrowsingSettingEnum_.STANDARD]]"
+            pref="[[prefs.generated.safe_browsing]]"
             label="$i18n{safeBrowsingStandard}"
             sub-label="$i18n{safeBrowsingStandardDesc}"
-            info-opened="{{infoOpened_}}"
-            disabled="[[safeBrowsingRadioManagedState_.standard.disabled]]"
-            policy-indicator-type=
-                "[[safeBrowsingRadioManagedState_.standard.indicator]]">
+            info-opened="{{infoOpened_}}">
           <div slot="collapse">
             <div class="bullet-line">
               <iron-icon icon="cr:security"></iron-icon>
@@ -134,8 +130,8 @@
                 label="$i18n{safeBrowsingStandardReportingLabel}"
                 sub-label="$i18n{safeBrowsingEnableExtendedReportingDesc}"
                 on-change="onSafeBrowsingExtendedReportingChange_"
-                disabled="[[
-                    getDisabledExtendedSafeBrowsing_(prefs.safebrowsing.*)]]">
+                disabled="[[getDisabledExtendedSafeBrowsing_(
+                              prefs.generated.safe_browsing.*)]]">
             </settings-toggle-button>
             <settings-passwords-leak-detection-toggle id="passwordsLeakToggle"
                 class="collapsable"
@@ -144,13 +140,11 @@
             </settings-passwords-leak-detection-toggle>
           </div>
         </settings-collapse-radio-button>
-        <settings-collapse-radio-button name="[[safeBrowsingEnum_.DISABLED]]"
-            id="safeBrowsingDisabled" no-collapse
+        <settings-collapse-radio-button id="safeBrowsingDisabled" no-collapse
+            name="[[safeBrowsingSettingEnum_.DISABLED]]"
+            pref="[[prefs.generated.safe_browsing]]"
             label="$i18n{safeBrowsingNone}"
-            sub-label="$i18n{safeBrowsingNoneDesc}"
-            disabled="[[safeBrowsingRadioManagedState_.disabled.disabled]]"
-            policy-indicator-type=
-                "[[safeBrowsingRadioManagedState_.disabled.indicator]]">
+            sub-label="$i18n{safeBrowsingNoneDesc}">
         </settings-collapse-radio-button>
       </cr-radio-group>
     </div>
diff --git a/chrome/browser/resources/settings/privacy_page/security_page.js b/chrome/browser/resources/settings/privacy_page/security_page.js
index 9184974..3c41016c 100644
--- a/chrome/browser/resources/settings/privacy_page/security_page.js
+++ b/chrome/browser/resources/settings/privacy_page/security_page.js
@@ -27,16 +27,17 @@
 import {Router} from '../router.m.js';
 
 import {PrivacyPageBrowserProxy, PrivacyPageBrowserProxyImpl} from './privacy_page_browser_proxy.m.js';
-import {SafeBrowsingBrowserProxy, SafeBrowsingBrowserProxyImpl, SafeBrowsingRadioManagedState} from './safe_browsing_browser_proxy.js';
 
 /**
- * Enumeration of all safe browsing modes.
- * @enum {string}
+ * Enumeration of all safe browsing modes. Must be kept in sync with the enum
+ * of the same name located in:
+ * chrome/browser/safe_browsing/generated_safe_browsing_pref.h
+ * @enum {number}
  */
-const SafeBrowsing = {
-  ENHANCED: 'enhanced',
-  STANDARD: 'standard',
-  DISABLED: 'disabled',
+export const SafeBrowsingSetting = {
+  ENHANCED: 0,
+  STANDARD: 1,
+  DISABLED: 2,
 };
 
 Polymer({
@@ -76,15 +77,9 @@
      * Valid safe browsing states.
      * @private
      */
-    safeBrowsingEnum_: {
+    safeBrowsingSettingEnum_: {
       type: Object,
-      value: SafeBrowsing,
-    },
-
-    /** @private */
-    selectSafeBrowsingRadio_: {
-      type: String,
-      computed: 'computeSelectSafeBrowsingRadio_(prefs.safebrowsing.*)',
+      value: SafeBrowsingSetting,
     },
 
     /** @private */
@@ -96,9 +91,6 @@
       },
     },
 
-    /** @private {!SafeBrowsingRadioManagedState} */
-    safeBrowsingRadioManagedState_: Object,
-
     /** @private */
     enableSecurityKeysSubpage_: {
       type: Boolean,
@@ -118,10 +110,6 @@
     showDisableSafebrowsingDialog_: Boolean,
   },
 
-  observers: [
-    'onSafeBrowsingPrefChange_(prefs.safebrowsing.*)',
-  ],
-
   /*
    * @param {!Map<string, string>} newConfig
    * @param {?Map<string, string>} oldConfig
@@ -144,21 +132,6 @@
     }
   },
 
-  /**
-   * @return {string}
-   * @private
-   */
-  computeSelectSafeBrowsingRadio_() {
-    if (this.prefs === undefined) {
-      return SafeBrowsing.STANDARD;
-    }
-    if (!this.getPref('safebrowsing.enabled').value) {
-      return SafeBrowsing.DISABLED;
-    }
-    return this.getPref('safebrowsing.enhanced').value ? SafeBrowsing.ENHANCED :
-                                                         SafeBrowsing.STANDARD;
-  },
-
   /** @private {PrivacyPageBrowserProxy} */
   browserProxy_: null,
 
@@ -172,26 +145,18 @@
     this.metricsBrowserProxy_ = MetricsBrowserProxyImpl.getInstance();
   },
 
-  /** @override */
-  attached() {
-    SafeBrowsingBrowserProxyImpl.getInstance().validateSafeBrowsingEnhanced();
-  },
-
   /**
-   * Updates the various underlying cookie prefs based on the newly selected
-   * radio button.
-   * @param {!CustomEvent<{value: string}>} event
+   * Possibly displays the Safe Browsing disable dialog based on the users
+   * selection.
    * @private
    */
-  onSafeBrowsingRadioChange_: function(event) {
-    if (event.detail.value === SafeBrowsing.ENHANCED) {
-      this.setPrefValue('safebrowsing.enabled', true);
-      this.setPrefValue('safebrowsing.enhanced', true);
-    } else if (event.detail.value === SafeBrowsing.STANDARD) {
-      this.setPrefValue('safebrowsing.enabled', true);
-      this.setPrefValue('safebrowsing.enhanced', false);
-    } else {  // disabled state
+  onSafeBrowsingRadioChange_: function() {
+    const selected =
+        Number.parseInt(this.$.safeBrowsingRadioGroup.selected, 10);
+    if (selected === SafeBrowsingSetting.DISABLED) {
       this.showDisableSafebrowsingDialog_ = true;
+    } else {
+      this.$.safeBrowsingRadioGroup.sendPrefChange();
     }
   },
 
@@ -200,16 +165,8 @@
    * @private
    */
   getDisabledExtendedSafeBrowsing_() {
-    return !this.getPref('safebrowsing.enabled').value ||
-        !!this.getPref('safebrowsing.enhanced').value;
-  },
-
-  /** @private */
-  async onSafeBrowsingPrefChange_() {
-    // Retrieve and update safe browsing radio managed state.
-    this.safeBrowsingRadioManagedState_ =
-        await SafeBrowsingBrowserProxyImpl.getInstance()
-            .getSafeBrowsingRadioManagedState();
+    return this.getPref('generated.safe_browsing').value !==
+        SafeBrowsingSetting.STANDARD;
   },
 
   /** @private */
@@ -250,15 +207,13 @@
     // Check if the dialog was confirmed before closing it.
     if (/** @type {!SettingsDisableSafebrowsingDialogElement} */
         (this.$$('settings-disable-safebrowsing-dialog')).wasConfirmed()) {
-      this.setPrefValue('safebrowsing.enabled', false);
-      this.setPrefValue('safebrowsing.enhanced', false);
+      this.$.safeBrowsingRadioGroup.sendPrefChange();
+    } else {
+      this.$.safeBrowsingRadioGroup.resetToPrefValue();
     }
 
     this.showDisableSafebrowsingDialog_ = false;
 
-    // Have the correct radio button highlighted.
-    this.$.safeBrowsingRadio.selected = this.selectSafeBrowsingRadio_;
-
     // Set focus back to the no protection button regardless of user interaction
     // with the dialog, as it was the entry point to the dialog.
     focusWithoutInk(assert(this.$.safeBrowsingDisabled));
diff --git a/chrome/browser/resources/settings/settings_resources_v3.grdp b/chrome/browser/resources/settings/settings_resources_v3.grdp
index 8f2325ae..2f5f8e4 100644
--- a/chrome/browser/resources/settings/settings_resources_v3.grdp
+++ b/chrome/browser/resources/settings/settings_resources_v3.grdp
@@ -511,9 +511,6 @@
            use_base_dir="false"
            preprocess="true"
            compress="false" type="BINDATA" />
-  <include name="IDR_SETTINGS_PRIVACY_PAGE_SAFE_BROWSING_BROWSER_PROXY_JS"
-           file="privacy_page/safe_browsing_browser_proxy.js"
-           compress="false" type="BINDATA" />
   <include name="IDR_SETTINGS_PRIVACY_PAGE_SECURE_DNS_JS"
            file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/secure_dns.js"
            use_base_dir="false"
diff --git a/chrome/browser/resources/settings/settings_routes.js b/chrome/browser/resources/settings/settings_routes.js
index 85669a7..560c9a0 100644
--- a/chrome/browser/resources/settings/settings_routes.js
+++ b/chrome/browser/resources/settings/settings_routes.js
@@ -12,7 +12,6 @@
  *   ACCESSIBILITY: !Route,
  *   ADVANCED: !Route,
  *   ADDRESSES: !Route,
- *   AMBIENT_MODE: !Route,
  *   APPEARANCE: !Route,
  *   AUTOFILL: !Route,
  *   BASIC: !Route,
diff --git a/chrome/browser/ssl/known_interception_disclosure_infobar.cc b/chrome/browser/ssl/known_interception_disclosure_infobar.cc
index b4d87e2..ea47c753 100644
--- a/chrome/browser/ssl/known_interception_disclosure_infobar.cc
+++ b/chrome/browser/ssl/known_interception_disclosure_infobar.cc
@@ -27,7 +27,7 @@
 
 KnownInterceptionDisclosureInfoBar::KnownInterceptionDisclosureInfoBar(
     std::unique_ptr<KnownInterceptionDisclosureInfoBarDelegate> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 ScopedJavaLocalRef<jobject>
 KnownInterceptionDisclosureInfoBar::CreateRenderInfoBar(JNIEnv* env) {
diff --git a/chrome/browser/ssl/known_interception_disclosure_infobar.h b/chrome/browser/ssl/known_interception_disclosure_infobar.h
index a7c5d63..1264885 100644
--- a/chrome/browser/ssl/known_interception_disclosure_infobar.h
+++ b/chrome/browser/ssl/known_interception_disclosure_infobar.h
@@ -10,14 +10,14 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/android/scoped_java_ref.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 #include "components/infobars/core/infobar.h"
 
 class KnownInterceptionDisclosureInfoBarDelegate;
 
 // KnownInterceptionDisclosureInfoBar is a thin veneer over ConfirmInfoBar that
 // adds a discrete description (instead of just having a title).
-class KnownInterceptionDisclosureInfoBar : public ConfirmInfoBar {
+class KnownInterceptionDisclosureInfoBar : public ChromeConfirmInfoBar {
  public:
   static std::unique_ptr<infobars::InfoBar> CreateInfoBar(
       std::unique_ptr<KnownInterceptionDisclosureInfoBarDelegate> delegate);
diff --git a/chrome/browser/sync/glue/DEPS b/chrome/browser/sync/glue/DEPS
index b5630c54..583f39d 100644
--- a/chrome/browser/sync/glue/DEPS
+++ b/chrome/browser/sync/glue/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
   "-components/sync/engine",
   "-components/sync/sessions",
-  "-components/sync/syncable",
 ]
diff --git a/chrome/browser/sync/test/integration/sessions_helper.h b/chrome/browser/sync/test/integration/sessions_helper.h
index 3250243..fbd0fe4 100644
--- a/chrome/browser/sync/test/integration/sessions_helper.h
+++ b/chrome/browser/sync/test/integration/sessions_helper.h
@@ -15,7 +15,6 @@
 #include "chrome/browser/sync/test/integration/multi_client_status_change_checker.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "components/sessions/core/session_types.h"
-#include "components/sync/syncable/nigori_util.h"
 #include "components/sync_sessions/synced_session.h"
 
 class GURL;
diff --git a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
deleted file mode 100644
index 487d279..0000000
--- a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/bind_helpers.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "chrome/browser/sync/test/integration/bookmarks_helper.h"
-#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
-#include "chrome/browser/sync/test/integration/sync_test.h"
-#include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
-#include "components/sync/driver/profile_sync_service.h"
-#include "components/sync/model/model_type_store_service.h"
-#include "components/sync/syncable/directory.h"
-#include "content/public/test/browser_test.h"
-#include "sql/test/test_helpers.h"
-#include "url/gurl.h"
-
-using base::FileEnumerator;
-using base::FilePath;
-
-namespace {
-
-// USS ModelTypeStore uses the same folder as the Directory. However, all of its
-// content is in a sub-folder. By not asking for recursive files, this function
-// will avoid seeing any of those, and return iff Directory database files still
-// exist.
-bool FolderContainsFiles(const FilePath& folder) {
-  base::ScopedAllowBlockingForTesting allow_blocking;
-  if (base::DirectoryExists(folder)) {
-    return !FileEnumerator(folder, false, FileEnumerator::FILES).Next().empty();
-  } else {
-    return false;
-  }
-}
-
-class SingleClientDirectorySyncTest : public SyncTest {
- public:
-  SingleClientDirectorySyncTest() : SyncTest(SINGLE_CLIENT) {}
-  ~SingleClientDirectorySyncTest() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SingleClientDirectorySyncTest);
-};
-
-// A status change checker that waits for an unrecoverable sync error to occur.
-class SyncUnrecoverableErrorChecker : public SingleClientStatusChangeChecker {
- public:
-  explicit SyncUnrecoverableErrorChecker(syncer::ProfileSyncService* service)
-      : SingleClientStatusChangeChecker(service) {}
-
-  bool IsExitConditionSatisfied(std::ostream* os) override {
-    *os << "Waiting for a Sync Unrecoverable Error";
-    return service()->HasUnrecoverableError();
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(SingleClientDirectorySyncTest,
-                       StopThenDisableDeletesDirectory) {
-  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
-  syncer::ProfileSyncService* sync_service = GetSyncService(0);
-  FilePath directory_path = sync_service->GetSyncClientForTest()
-                                ->GetSyncDataPath();
-  ASSERT_TRUE(FolderContainsFiles(directory_path));
-  sync_service->StopAndClear();
-
-  // Wait for StartupController::StartUp()'s tasks to finish.
-  base::RunLoop run_loop;
-  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                run_loop.QuitClosure());
-  run_loop.Run();
-  // Wait for the directory deletion to finish.
-  sync_service->FlushBackendTaskRunnerForTest();
-  EXPECT_FALSE(FolderContainsFiles(directory_path));
-}
-
-}  // namespace
diff --git a/chrome/browser/sync/test/integration/typed_urls_helper.cc b/chrome/browser/sync/test/integration/typed_urls_helper.cc
index 3959109..5728959 100644
--- a/chrome/browser/sync/test/integration/typed_urls_helper.cc
+++ b/chrome/browser/sync/test/integration/typed_urls_helper.cc
@@ -26,9 +26,6 @@
 #include "components/history/core/browser/history_database.h"
 #include "components/history/core/browser/history_db_task.h"
 #include "components/history/core/browser/history_service.h"
-#include "components/sync/syncable/read_node.h"
-#include "components/sync/syncable/read_transaction.h"
-#include "components/sync/syncable/user_share.h"
 
 using sync_datatype_helper::test;
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 0be6967..4c2969691 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -681,8 +681,8 @@
       "android/infobars/autofill_credit_card_filling_infobar.h",
       "android/infobars/autofill_save_card_infobar.cc",
       "android/infobars/autofill_save_card_infobar.h",
-      "android/infobars/confirm_infobar.cc",
-      "android/infobars/confirm_infobar.h",
+      "android/infobars/chrome_confirm_infobar.cc",
+      "android/infobars/chrome_confirm_infobar.h",
       "android/infobars/data_reduction_promo_infobar.cc",
       "android/infobars/data_reduction_promo_infobar.h",
       "android/infobars/download_progress_infobar.cc",
@@ -1388,8 +1388,6 @@
       "webui/settings/recent_site_settings_helper.h",
       "webui/settings/reset_settings_handler.cc",
       "webui/settings/reset_settings_handler.h",
-      "webui/settings/safe_browsing_handler.cc",
-      "webui/settings/safe_browsing_handler.h",
       "webui/settings/safety_check_handler.cc",
       "webui/settings/safety_check_handler.h",
       "webui/settings/search_engines_handler.cc",
diff --git a/chrome/browser/ui/android/infobars/ads_blocked_infobar.cc b/chrome/browser/ui/android/infobars/ads_blocked_infobar.cc
index 0dfc70f..ddfac96 100644
--- a/chrome/browser/ui/android/infobars/ads_blocked_infobar.cc
+++ b/chrome/browser/ui/android/infobars/ads_blocked_infobar.cc
@@ -14,7 +14,7 @@
 
 AdsBlockedInfoBar::AdsBlockedInfoBar(
     std::unique_ptr<AdsBlockedInfobarDelegate> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 AdsBlockedInfoBar::~AdsBlockedInfoBar() {}
 
diff --git a/chrome/browser/ui/android/infobars/ads_blocked_infobar.h b/chrome/browser/ui/android/infobars/ads_blocked_infobar.h
index b4b44ee..382e7bc9 100644
--- a/chrome/browser/ui/android/infobars/ads_blocked_infobar.h
+++ b/chrome/browser/ui/android/infobars/ads_blocked_infobar.h
@@ -7,9 +7,9 @@
 
 #include "base/macros.h"
 #include "chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
-class AdsBlockedInfoBar : public ConfirmInfoBar {
+class AdsBlockedInfoBar : public ChromeConfirmInfoBar {
  public:
   explicit AdsBlockedInfoBar(
       std::unique_ptr<AdsBlockedInfobarDelegate> delegate);
diff --git a/chrome/browser/ui/android/infobars/autofill_credit_card_filling_infobar.cc b/chrome/browser/ui/android/infobars/autofill_credit_card_filling_infobar.cc
index 20a226f..6d7c424d 100644
--- a/chrome/browser/ui/android/infobars/autofill_credit_card_filling_infobar.cc
+++ b/chrome/browser/ui/android/infobars/autofill_credit_card_filling_infobar.cc
@@ -21,7 +21,7 @@
 AutofillCreditCardFillingInfoBar::AutofillCreditCardFillingInfoBar(
     std::unique_ptr<autofill::AutofillCreditCardFillingInfoBarDelegateMobile>
         delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 AutofillCreditCardFillingInfoBar::~AutofillCreditCardFillingInfoBar() {}
 
diff --git a/chrome/browser/ui/android/infobars/autofill_credit_card_filling_infobar.h b/chrome/browser/ui/android/infobars/autofill_credit_card_filling_infobar.h
index 8a2a8d3..39b80774 100644
--- a/chrome/browser/ui/android/infobars/autofill_credit_card_filling_infobar.h
+++ b/chrome/browser/ui/android/infobars/autofill_credit_card_filling_infobar.h
@@ -10,7 +10,7 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
 namespace autofill {
 class AutofillCreditCardFillingInfoBarDelegateMobile;
@@ -20,7 +20,7 @@
 // proposes to autofill user data into the detected credit card form in the
 // page. Upon accepting the infobar, the form is filled automatically. If
 // the infobar is dismissed, nothing happens.
-class AutofillCreditCardFillingInfoBar : public ConfirmInfoBar {
+class AutofillCreditCardFillingInfoBar : public ChromeConfirmInfoBar {
  public:
   explicit AutofillCreditCardFillingInfoBar(
       std::unique_ptr<autofill::AutofillCreditCardFillingInfoBarDelegateMobile>
diff --git a/chrome/browser/ui/android/infobars/autofill_save_card_infobar.cc b/chrome/browser/ui/android/infobars/autofill_save_card_infobar.cc
index 5603ef9b..e43d83fc 100644
--- a/chrome/browser/ui/android/infobars/autofill_save_card_infobar.cc
+++ b/chrome/browser/ui/android/infobars/autofill_save_card_infobar.cc
@@ -32,7 +32,7 @@
 
 AutofillSaveCardInfoBar::AutofillSaveCardInfoBar(
     std::unique_ptr<autofill::AutofillSaveCardInfoBarDelegateMobile> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 AutofillSaveCardInfoBar::~AutofillSaveCardInfoBar() {}
 
diff --git a/chrome/browser/ui/android/infobars/autofill_save_card_infobar.h b/chrome/browser/ui/android/infobars/autofill_save_card_infobar.h
index b176165..97c2d05 100644
--- a/chrome/browser/ui/android/infobars/autofill_save_card_infobar.h
+++ b/chrome/browser/ui/android/infobars/autofill_save_card_infobar.h
@@ -10,14 +10,14 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
 namespace autofill {
 class AutofillSaveCardInfoBarDelegateMobile;
 }
 
 // Android implementation of the infobar for saving credit card information.
-class AutofillSaveCardInfoBar : public ConfirmInfoBar {
+class AutofillSaveCardInfoBar : public ChromeConfirmInfoBar {
  public:
   explicit AutofillSaveCardInfoBar(
       std::unique_ptr<autofill::AutofillSaveCardInfoBarDelegateMobile>
diff --git a/chrome/browser/ui/android/infobars/chrome_confirm_infobar.cc b/chrome/browser/ui/android/infobars/chrome_confirm_infobar.cc
new file mode 100644
index 0000000..e910f471
--- /dev/null
+++ b/chrome/browser/ui/android/infobars/chrome_confirm_infobar.cc
@@ -0,0 +1,42 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "chrome/browser/android/resource_mapper.h"
+#include "chrome/browser/android/tab_android.h"
+#include "chrome/browser/infobars/infobar_service.h"
+#include "content/public/browser/web_contents.h"
+
+// InfoBarService -------------------------------------------------------------
+
+std::unique_ptr<infobars::InfoBar> InfoBarService::CreateConfirmInfoBar(
+    std::unique_ptr<ConfirmInfoBarDelegate> delegate) {
+  return std::make_unique<ChromeConfirmInfoBar>(std::move(delegate));
+}
+
+// ChromeConfirmInfoBar
+// -------------------------------------------------------------
+
+ChromeConfirmInfoBar::ChromeConfirmInfoBar(
+    std::unique_ptr<ConfirmInfoBarDelegate> delegate)
+    : ConfirmInfoBar(
+          std::move(delegate),
+          base::BindRepeating(&ResourceMapper::MapToJavaDrawableId)) {}
+
+ChromeConfirmInfoBar::~ChromeConfirmInfoBar() {}
+
+TabAndroid* ChromeConfirmInfoBar::GetTab() {
+  content::WebContents* web_contents =
+      InfoBarService::WebContentsFromInfoBar(this);
+  DCHECK(web_contents);
+
+  TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
+  DCHECK(tab);
+  return tab;
+}
diff --git a/chrome/browser/ui/android/infobars/chrome_confirm_infobar.h b/chrome/browser/ui/android/infobars/chrome_confirm_infobar.h
new file mode 100644
index 0000000..12b777e
--- /dev/null
+++ b/chrome/browser/ui/android/infobars/chrome_confirm_infobar.h
@@ -0,0 +1,27 @@
+// Copyright 2020 The Chromium 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_UI_ANDROID_INFOBARS_CHROME_CONFIRM_INFOBAR_H_
+#define CHROME_BROWSER_UI_ANDROID_INFOBARS_CHROME_CONFIRM_INFOBAR_H_
+
+#include "components/infobars/android/confirm_infobar.h"
+
+class TabAndroid;
+
+// Chrome-specific convenience specialization of ConfirmInfoBar that supplies
+// Chrome-level parameters.
+class ChromeConfirmInfoBar : public ConfirmInfoBar {
+ public:
+  explicit ChromeConfirmInfoBar(
+      std::unique_ptr<ConfirmInfoBarDelegate> delegate);
+  ~ChromeConfirmInfoBar() override;
+
+  ChromeConfirmInfoBar(const ChromeConfirmInfoBar&) = delete;
+  ChromeConfirmInfoBar& operator=(const ChromeConfirmInfoBar&) = delete;
+
+ protected:
+  TabAndroid* GetTab();
+};
+
+#endif  // CHROME_BROWSER_UI_ANDROID_INFOBARS_CHROME_CONFIRM_INFOBAR_H_
diff --git a/chrome/browser/ui/android/infobars/confirm_infobar.cc b/chrome/browser/ui/android/infobars/confirm_infobar.cc
deleted file mode 100644
index 24a204f..0000000
--- a/chrome/browser/ui/android/infobars/confirm_infobar.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/android/jni_string.h"
-#include "base/bind.h"
-#include "chrome/browser/android/resource_mapper.h"
-#include "chrome/browser/android/tab_android.h"
-#include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/browser/ui/messages/android/jni_headers/ConfirmInfoBar_jni.h"
-#include "components/infobars/core/confirm_infobar_delegate.h"
-#include "content/public/browser/web_contents.h"
-#include "ui/android/window_android.h"
-#include "ui/gfx/android/java_bitmap.h"
-#include "ui/gfx/image/image.h"
-
-using base::android::JavaParamRef;
-using base::android::ScopedJavaLocalRef;
-
-// InfoBarService -------------------------------------------------------------
-
-std::unique_ptr<infobars::InfoBar> InfoBarService::CreateConfirmInfoBar(
-    std::unique_ptr<ConfirmInfoBarDelegate> delegate) {
-  return std::make_unique<ConfirmInfoBar>(std::move(delegate));
-}
-
-
-// ConfirmInfoBar -------------------------------------------------------------
-
-ConfirmInfoBar::ConfirmInfoBar(std::unique_ptr<ConfirmInfoBarDelegate> delegate)
-    : InfoBarAndroid(
-          std::move(delegate),
-          base::BindRepeating(&ResourceMapper::MapToJavaDrawableId)) {}
-
-ConfirmInfoBar::~ConfirmInfoBar() {
-}
-
-base::string16 ConfirmInfoBar::GetTextFor(
-    ConfirmInfoBarDelegate::InfoBarButton button) {
-  ConfirmInfoBarDelegate* delegate = GetDelegate();
-  return (delegate->GetButtons() & button) ?
-      delegate->GetButtonLabel(button) : base::string16();
-}
-
-ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() {
-  return delegate()->AsConfirmInfoBarDelegate();
-}
-
-TabAndroid* ConfirmInfoBar::GetTab() {
-  content::WebContents* web_contents =
-      InfoBarService::WebContentsFromInfoBar(this);
-  DCHECK(web_contents);
-
-  TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
-  DCHECK(tab);
-  return tab;
-}
-
-ScopedJavaLocalRef<jobject> ConfirmInfoBar::CreateRenderInfoBar(JNIEnv* env) {
-  ScopedJavaLocalRef<jstring> ok_button_text =
-      base::android::ConvertUTF16ToJavaString(
-          env, GetTextFor(ConfirmInfoBarDelegate::BUTTON_OK));
-  ScopedJavaLocalRef<jstring> cancel_button_text =
-      base::android::ConvertUTF16ToJavaString(
-          env, GetTextFor(ConfirmInfoBarDelegate::BUTTON_CANCEL));
-  ConfirmInfoBarDelegate* delegate = GetDelegate();
-  ScopedJavaLocalRef<jstring> message_text =
-      base::android::ConvertUTF16ToJavaString(env, delegate->GetMessageText());
-  ScopedJavaLocalRef<jstring> link_text =
-      base::android::ConvertUTF16ToJavaString(env, delegate->GetLinkText());
-
-  ScopedJavaLocalRef<jobject> java_bitmap;
-  if (delegate->GetIconId() == infobars::InfoBarDelegate::kNoIconID &&
-      !delegate->GetIcon().IsEmpty()) {
-    java_bitmap = gfx::ConvertToJavaBitmap(delegate->GetIcon().ToSkBitmap());
-  }
-
-  return Java_ConfirmInfoBar_create(env, GetJavaIconId(), java_bitmap,
-                                    message_text, link_text, ok_button_text,
-                                    cancel_button_text);
-}
-
-void ConfirmInfoBar::OnLinkClicked(JNIEnv* env,
-                                   const JavaParamRef<jobject>& obj) {
-  if (!owner())
-      return; // We're closing; don't call anything, it might access the owner.
-
-  if (GetDelegate()->LinkClicked(WindowOpenDisposition::NEW_FOREGROUND_TAB))
-    RemoveSelf();
-}
-
-void ConfirmInfoBar::ProcessButton(int action) {
-  if (!owner())
-    return; // We're closing; don't call anything, it might access the owner.
-
-  DCHECK((action == InfoBarAndroid::ACTION_OK) ||
-      (action == InfoBarAndroid::ACTION_CANCEL));
-  ConfirmInfoBarDelegate* delegate = GetDelegate();
-  if ((action == InfoBarAndroid::ACTION_OK) ?
-      delegate->Accept() : delegate->Cancel())
-    RemoveSelf();
-}
diff --git a/chrome/browser/ui/android/infobars/data_reduction_promo_infobar.cc b/chrome/browser/ui/android/infobars/data_reduction_promo_infobar.cc
index f33c9fe4..b075219 100644
--- a/chrome/browser/ui/android/infobars/data_reduction_promo_infobar.cc
+++ b/chrome/browser/ui/android/infobars/data_reduction_promo_infobar.cc
@@ -17,7 +17,7 @@
 
 DataReductionPromoInfoBar::DataReductionPromoInfoBar(
     std::unique_ptr<DataReductionPromoInfoBarDelegateAndroid> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 DataReductionPromoInfoBar::~DataReductionPromoInfoBar() {
 }
diff --git a/chrome/browser/ui/android/infobars/data_reduction_promo_infobar.h b/chrome/browser/ui/android/infobars/data_reduction_promo_infobar.h
index 86aea741..95aba3bc 100644
--- a/chrome/browser/ui/android/infobars/data_reduction_promo_infobar.h
+++ b/chrome/browser/ui/android/infobars/data_reduction_promo_infobar.h
@@ -7,9 +7,9 @@
 
 #include "base/macros.h"
 #include "chrome/browser/data_reduction_proxy/data_reduction_promo_infobar_delegate_android.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
-class DataReductionPromoInfoBar : public ConfirmInfoBar {
+class DataReductionPromoInfoBar : public ChromeConfirmInfoBar {
  public:
   explicit DataReductionPromoInfoBar(
       std::unique_ptr<DataReductionPromoInfoBarDelegateAndroid> delegate);
diff --git a/chrome/browser/ui/android/infobars/duplicate_download_infobar.cc b/chrome/browser/ui/android/infobars/duplicate_download_infobar.cc
index 4b81d442..c3288f7 100644
--- a/chrome/browser/ui/android/infobars/duplicate_download_infobar.cc
+++ b/chrome/browser/ui/android/infobars/duplicate_download_infobar.cc
@@ -25,7 +25,7 @@
 
 DuplicateDownloadInfoBar::DuplicateDownloadInfoBar(
     std::unique_ptr<DuplicateDownloadInfoBarDelegate> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 base::android::ScopedJavaLocalRef<jobject>
 DuplicateDownloadInfoBar::CreateRenderInfoBar(JNIEnv* env) {
diff --git a/chrome/browser/ui/android/infobars/duplicate_download_infobar.h b/chrome/browser/ui/android/infobars/duplicate_download_infobar.h
index 42f5eec..45f9ab1 100644
--- a/chrome/browser/ui/android/infobars/duplicate_download_infobar.h
+++ b/chrome/browser/ui/android/infobars/duplicate_download_infobar.h
@@ -7,7 +7,7 @@
 
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
 namespace android {
 class DuplicateDownloadInfoBarDelegate;
@@ -15,7 +15,7 @@
 
 // A native-side implementation of an infobar to ask whether to continue
 // downloading if target file already exists.
-class DuplicateDownloadInfoBar : public ConfirmInfoBar {
+class DuplicateDownloadInfoBar : public ChromeConfirmInfoBar {
  public:
   static std::unique_ptr<infobars::InfoBar> CreateInfoBar(
       std::unique_ptr<android::DuplicateDownloadInfoBarDelegate> delegate);
diff --git a/chrome/browser/ui/android/infobars/grouped_permission_infobar.cc b/chrome/browser/ui/android/infobars/grouped_permission_infobar.cc
index 0afebf9..60f8d3b4 100644
--- a/chrome/browser/ui/android/infobars/grouped_permission_infobar.cc
+++ b/chrome/browser/ui/android/infobars/grouped_permission_infobar.cc
@@ -64,7 +64,7 @@
 
 GroupedPermissionInfoBar::GroupedPermissionInfoBar(
     std::unique_ptr<GroupedPermissionInfoBarDelegate> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 GroupedPermissionInfoBar::~GroupedPermissionInfoBar() {}
 
diff --git a/chrome/browser/ui/android/infobars/grouped_permission_infobar.h b/chrome/browser/ui/android/infobars/grouped_permission_infobar.h
index 2b8c1b001..0397ad7 100644
--- a/chrome/browser/ui/android/infobars/grouped_permission_infobar.h
+++ b/chrome/browser/ui/android/infobars/grouped_permission_infobar.h
@@ -5,13 +5,13 @@
 #ifndef CHROME_BROWSER_UI_ANDROID_INFOBARS_GROUPED_PERMISSION_INFOBAR_H_
 #define CHROME_BROWSER_UI_ANDROID_INFOBARS_GROUPED_PERMISSION_INFOBAR_H_
 
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
 class GroupedPermissionInfoBarDelegate;
 
 // TODO(andypaicu): rename this to PermissionInfoBar, grouped permissions are
 // not a thing anymore.
-class GroupedPermissionInfoBar : public ConfirmInfoBar {
+class GroupedPermissionInfoBar : public ChromeConfirmInfoBar {
  public:
   explicit GroupedPermissionInfoBar(
       std::unique_ptr<GroupedPermissionInfoBarDelegate> delegate);
diff --git a/chrome/browser/ui/android/infobars/instant_apps_infobar.cc b/chrome/browser/ui/android/infobars/instant_apps_infobar.cc
index db4b24b..44b6572 100644
--- a/chrome/browser/ui/android/infobars/instant_apps_infobar.cc
+++ b/chrome/browser/ui/android/infobars/instant_apps_infobar.cc
@@ -12,7 +12,7 @@
 
 InstantAppsInfoBar::InstantAppsInfoBar(
     std::unique_ptr<InstantAppsInfoBarDelegate> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 InstantAppsInfoBar::~InstantAppsInfoBar() {}
 
diff --git a/chrome/browser/ui/android/infobars/instant_apps_infobar.h b/chrome/browser/ui/android/infobars/instant_apps_infobar.h
index 4c9dc88..623ce445 100644
--- a/chrome/browser/ui/android/infobars/instant_apps_infobar.h
+++ b/chrome/browser/ui/android/infobars/instant_apps_infobar.h
@@ -8,9 +8,9 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
 #include "chrome/browser/android/instantapps/instant_apps_infobar_delegate.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
-class InstantAppsInfoBar : public ConfirmInfoBar {
+class InstantAppsInfoBar : public ChromeConfirmInfoBar {
  public:
   InstantAppsInfoBar(
       std::unique_ptr<InstantAppsInfoBarDelegate> delegate);
diff --git a/chrome/browser/ui/android/infobars/previews_lite_page_infobar.cc b/chrome/browser/ui/android/infobars/previews_lite_page_infobar.cc
index 6ad7800..8f3f1c6 100644
--- a/chrome/browser/ui/android/infobars/previews_lite_page_infobar.cc
+++ b/chrome/browser/ui/android/infobars/previews_lite_page_infobar.cc
@@ -12,7 +12,7 @@
 
 PreviewsLitePageInfoBar::PreviewsLitePageInfoBar(
     std::unique_ptr<PreviewsLitePageInfoBarDelegate> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 PreviewsLitePageInfoBar::~PreviewsLitePageInfoBar() {}
 
diff --git a/chrome/browser/ui/android/infobars/previews_lite_page_infobar.h b/chrome/browser/ui/android/infobars/previews_lite_page_infobar.h
index 224f8b0..175ba4e 100644
--- a/chrome/browser/ui/android/infobars/previews_lite_page_infobar.h
+++ b/chrome/browser/ui/android/infobars/previews_lite_page_infobar.h
@@ -10,11 +10,11 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
 #include "chrome/browser/previews/previews_lite_page_infobar_delegate.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
 // This InfoBar notifies the user that Data Saver now also applies to HTTPS
 // pages.
-class PreviewsLitePageInfoBar : public ConfirmInfoBar {
+class PreviewsLitePageInfoBar : public ChromeConfirmInfoBar {
  public:
   explicit PreviewsLitePageInfoBar(
       std::unique_ptr<PreviewsLitePageInfoBarDelegate> delegate);
diff --git a/chrome/browser/ui/android/infobars/save_password_infobar.cc b/chrome/browser/ui/android/infobars/save_password_infobar.cc
index 64b569e..2fb8624 100644
--- a/chrome/browser/ui/android/infobars/save_password_infobar.cc
+++ b/chrome/browser/ui/android/infobars/save_password_infobar.cc
@@ -17,7 +17,7 @@
 
 SavePasswordInfoBar::SavePasswordInfoBar(
     std::unique_ptr<SavePasswordInfoBarDelegate> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 SavePasswordInfoBar::~SavePasswordInfoBar() {}
 
diff --git a/chrome/browser/ui/android/infobars/save_password_infobar.h b/chrome/browser/ui/android/infobars/save_password_infobar.h
index 371f4f58..4dc2d16 100644
--- a/chrome/browser/ui/android/infobars/save_password_infobar.h
+++ b/chrome/browser/ui/android/infobars/save_password_infobar.h
@@ -7,12 +7,12 @@
 
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
 class SavePasswordInfoBarDelegate;
 
 // The infobar to be used with SavePasswordInfoBarDelegate.
-class SavePasswordInfoBar : public ConfirmInfoBar {
+class SavePasswordInfoBar : public ChromeConfirmInfoBar {
  public:
   explicit SavePasswordInfoBar(
       std::unique_ptr<SavePasswordInfoBarDelegate> delegate);
diff --git a/chrome/browser/ui/android/infobars/sync_error_infobar.cc b/chrome/browser/ui/android/infobars/sync_error_infobar.cc
index 998f478..e114b278 100644
--- a/chrome/browser/ui/android/infobars/sync_error_infobar.cc
+++ b/chrome/browser/ui/android/infobars/sync_error_infobar.cc
@@ -6,7 +6,7 @@
 
 SyncErrorInfoBar::SyncErrorInfoBar(
     std::unique_ptr<SyncErrorInfoBarDelegateAndroid> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 SyncErrorInfoBar::~SyncErrorInfoBar() {}
 
diff --git a/chrome/browser/ui/android/infobars/sync_error_infobar.h b/chrome/browser/ui/android/infobars/sync_error_infobar.h
index 965058d..61c82c5 100644
--- a/chrome/browser/ui/android/infobars/sync_error_infobar.h
+++ b/chrome/browser/ui/android/infobars/sync_error_infobar.h
@@ -8,9 +8,9 @@
 #include "base/android/jni_android.h"
 #include "base/macros.h"
 #include "chrome/browser/sync/sync_error_infobar_delegate_android.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
-class SyncErrorInfoBar : public ConfirmInfoBar {
+class SyncErrorInfoBar : public ChromeConfirmInfoBar {
  public:
   explicit SyncErrorInfoBar(
       std::unique_ptr<SyncErrorInfoBarDelegateAndroid> delegate);
diff --git a/chrome/browser/ui/android/infobars/update_password_infobar.cc b/chrome/browser/ui/android/infobars/update_password_infobar.cc
index fe595d3..11fc90b 100644
--- a/chrome/browser/ui/android/infobars/update_password_infobar.cc
+++ b/chrome/browser/ui/android/infobars/update_password_infobar.cc
@@ -19,7 +19,7 @@
 
 UpdatePasswordInfoBar::UpdatePasswordInfoBar(
     std::unique_ptr<UpdatePasswordInfoBarDelegate> delegate)
-    : ConfirmInfoBar(std::move(delegate)) {}
+    : ChromeConfirmInfoBar(std::move(delegate)) {}
 
 UpdatePasswordInfoBar::~UpdatePasswordInfoBar() {}
 
diff --git a/chrome/browser/ui/android/infobars/update_password_infobar.h b/chrome/browser/ui/android/infobars/update_password_infobar.h
index 98f62e30..340720f 100644
--- a/chrome/browser/ui/android/infobars/update_password_infobar.h
+++ b/chrome/browser/ui/android/infobars/update_password_infobar.h
@@ -7,12 +7,12 @@
 
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
 class UpdatePasswordInfoBarDelegate;
 
 // The infobar to be used with UpdatePasswordInfoBarDelegate.
-class UpdatePasswordInfoBar : public ConfirmInfoBar {
+class UpdatePasswordInfoBar : public ChromeConfirmInfoBar {
  public:
   explicit UpdatePasswordInfoBar(
       std::unique_ptr<UpdatePasswordInfoBarDelegate> delegate);
diff --git a/chrome/browser/ui/android/sms/sms_infobar.cc b/chrome/browser/ui/android/sms/sms_infobar.cc
index e7bf50c..354c9c8 100644
--- a/chrome/browser/ui/android/sms/sms_infobar.cc
+++ b/chrome/browser/ui/android/sms/sms_infobar.cc
@@ -32,7 +32,7 @@
 
 SmsInfoBar::SmsInfoBar(content::WebContents* web_contents,
                        std::unique_ptr<SmsInfoBarDelegate> delegate)
-    : ConfirmInfoBar(std::move(delegate)), web_contents_(web_contents) {}
+    : ChromeConfirmInfoBar(std::move(delegate)), web_contents_(web_contents) {}
 
 SmsInfoBar::~SmsInfoBar() = default;
 
diff --git a/chrome/browser/ui/android/sms/sms_infobar.h b/chrome/browser/ui/android/sms/sms_infobar.h
index 61a92d35..435c4de 100644
--- a/chrome/browser/ui/android/sms/sms_infobar.h
+++ b/chrome/browser/ui/android/sms/sms_infobar.h
@@ -9,7 +9,7 @@
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
-#include "chrome/browser/ui/android/infobars/confirm_infobar.h"
+#include "chrome/browser/ui/android/infobars/chrome_confirm_infobar.h"
 
 namespace content {
 class WebContents;
@@ -21,7 +21,7 @@
 
 class SmsInfoBarDelegate;
 
-class SmsInfoBar : public ConfirmInfoBar {
+class SmsInfoBar : public ChromeConfirmInfoBar {
  public:
   SmsInfoBar(content::WebContents* web_contents,
              std::unique_ptr<SmsInfoBarDelegate> delegate);
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
index 2fe9ce7f..f31ebef 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -234,6 +234,7 @@
 const char kPlayStoreAppId[] = "cnbgggchhmkkdmeppjobngjoejnihlei";
 const char kSettingsAppId[] = "mconboelelhjpkbdhhiijkgcimoangdj";
 const char kYoutubeAppId[] = "aniolghapcdkoolpkffememnhpphmjkl";
+const char kYoutubeMusicAppId[] = "hpdkdmlckojaocbedhffglopeafcgggc";
 
 bool ShouldShowInLauncher(const std::string& app_id) {
   for (auto* const id : kAppIdsHiddenInLauncher) {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.h b/chrome/browser/ui/app_list/arc/arc_app_utils.h
index 3400a56..5f07e25 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_utils.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_utils.h
@@ -47,6 +47,7 @@
 extern const char kPlayStoreAppId[];
 extern const char kSettingsAppId[];
 extern const char kYoutubeAppId[];
+extern const char kYoutubeMusicAppId[];
 
 // Represents unparsed intent.
 class Intent {
diff --git a/chrome/browser/ui/messages/android/BUILD.gn b/chrome/browser/ui/messages/android/BUILD.gn
index 6b64e85..1212f481 100644
--- a/chrome/browser/ui/messages/android/BUILD.gn
+++ b/chrome/browser/ui/messages/android/BUILD.gn
@@ -23,7 +23,6 @@
 
 android_library("java") {
   sources = [
-    "java/src/org/chromium/chrome/browser/ui/messages/infobar/ConfirmInfoBar.java",
     "java/src/org/chromium/chrome/browser/ui/messages/infobar/SimpleConfirmInfoBarBuilder.java",
     "java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java",
     "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollection.java",
@@ -52,10 +51,7 @@
 }
 
 generate_jni("jni_headers") {
-  sources = [
-    "java/src/org/chromium/chrome/browser/ui/messages/infobar/ConfirmInfoBar.java",
-    "java/src/org/chromium/chrome/browser/ui/messages/infobar/SimpleConfirmInfoBarBuilder.java",
-  ]
+  sources = [ "java/src/org/chromium/chrome/browser/ui/messages/infobar/SimpleConfirmInfoBarBuilder.java" ]
 }
 
 java_library("junit") {
diff --git a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc
index 38efaf95..ed55532d 100644
--- a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc
@@ -181,21 +181,6 @@
               &WelcomeScreenHandler::HandleSetInputMethodId);
   AddCallback("WelcomeScreen.setTimezoneId",
               &WelcomeScreenHandler::HandleSetTimezoneId);
-
-  AddCallback("WelcomeScreen.enableHighContrast",
-              &WelcomeScreenHandler::HandleEnableHighContrast);
-  AddCallback("WelcomeScreen.enableLargeCursor",
-              &WelcomeScreenHandler::HandleEnableLargeCursor);
-  AddCallback("WelcomeScreen.enableVirtualKeyboard",
-              &WelcomeScreenHandler::HandleEnableVirtualKeyboard);
-  AddCallback("WelcomeScreen.enableScreenMagnifier",
-              &WelcomeScreenHandler::HandleEnableScreenMagnifier);
-  AddCallback("WelcomeScreen.enableSpokenFeedback",
-              &WelcomeScreenHandler::HandleEnableSpokenFeedback);
-  AddCallback("WelcomeScreen.enableSelectToSpeak",
-              &WelcomeScreenHandler::HandleEnableSelectToSpeak);
-  AddCallback("WelcomeScreen.enableDockedMagnifier",
-              &WelcomeScreenHandler::HandleEnableDockedMagnifier);
 }
 
 void WelcomeScreenHandler::GetAdditionalParameters(
@@ -282,44 +267,6 @@
     screen_->SetTimezone(timezone_id);
 }
 
-void WelcomeScreenHandler::HandleEnableHighContrast(bool enabled) {
-  AccessibilityManager::Get()->EnableHighContrast(enabled);
-}
-
-void WelcomeScreenHandler::HandleEnableLargeCursor(bool enabled) {
-  AccessibilityManager::Get()->EnableLargeCursor(enabled);
-}
-
-void WelcomeScreenHandler::HandleEnableVirtualKeyboard(bool enabled) {
-  AccessibilityManager::Get()->EnableVirtualKeyboard(enabled);
-}
-
-void WelcomeScreenHandler::HandleEnableScreenMagnifier(bool enabled) {
-  DCHECK(MagnificationManager::Get());
-  MagnificationManager::Get()->SetMagnifierEnabled(enabled);
-}
-
-void WelcomeScreenHandler::HandleEnableSpokenFeedback(bool /* enabled */) {
-  // Checkbox is initialized on page init and updates when spoken feedback
-  // setting is changed so just toggle spoken feedback here.
-  AccessibilityManager::Get()->EnableSpokenFeedback(
-      !AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
-}
-
-void WelcomeScreenHandler::HandleEnableSelectToSpeak(bool /* enabled */) {
-  // Checkbox is initialized on page init and updates when Select to Speak
-  // setting is changed so just toggle Select to Speak here.
-  AccessibilityManager::Get()->SetSelectToSpeakEnabled(
-      !AccessibilityManager::Get()->IsSelectToSpeakEnabled());
-}
-
-void WelcomeScreenHandler::HandleEnableDockedMagnifier(bool enabled) {
-  // Checkbox is initialized on page init and updates when the docked magnifier
-  // setting is changed so just toggle Select to Speak here.
-  DCHECK(MagnificationManager::Get());
-  MagnificationManager::Get()->SetDockedMagnifierEnabled(enabled);
-}
-
 void WelcomeScreenHandler::OnAccessibilityStatusChanged(
     const AccessibilityStatusEventDetails& details) {
   if (details.notification_type == ACCESSIBILITY_MANAGER_SHUTDOWN)
diff --git a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc
index 67ae990c..fd4f14a6 100644
--- a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc
@@ -7,12 +7,31 @@
 #include "ash/public/cpp/ambient/ambient_backend_controller.h"
 #include "ash/public/cpp/ambient/common/ambient_settings.h"
 #include "base/bind.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 
 namespace chromeos {
 namespace settings {
 
+namespace {
+
+// Width and height of the preview image for personal album.
+constexpr int kBannerWidth = 512;
+constexpr int kBannderHeight = 512;
+
+ash::AmbientModeTopicSource ExtractTopicSource(const base::ListValue* args) {
+  CHECK_EQ(args->GetSize(), 1U);
+  ash::AmbientModeTopicSource topic_source =
+      static_cast<ash::AmbientModeTopicSource>(args->GetList()[0].GetInt());
+  // Check the |topic_source| has valid value.
+  CHECK_GE(topic_source, ash::AmbientModeTopicSource::kMinValue);
+  CHECK_LE(topic_source, ash::AmbientModeTopicSource::kMaxValue);
+  return topic_source;
+}
+
+}  // namespace
+
 AmbientModeHandler::AmbientModeHandler() = default;
 
 AmbientModeHandler::~AmbientModeHandler() = default;
@@ -24,13 +43,27 @@
                           base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
-      "onTopicSourceSelectedChanged",
-      base::BindRepeating(&AmbientModeHandler::HandleTopicSourceSelectedChanged,
+      "setSelectedTopicSource",
+      base::BindRepeating(&AmbientModeHandler::HandleSetSelectedTopicSource,
                           base::Unretained(this)));
+
+  web_ui()->RegisterMessageCallback(
+      "requestPhotosContainers",
+      base::BindRepeating(&AmbientModeHandler::RequestPhotosContainers,
+                          base::Unretained(this)));
+
+  web_ui()->RegisterMessageCallback(
+      "setSelectedPhotosContainers",
+      base::BindRepeating(
+          &AmbientModeHandler::HandleSetSelectedPhotosContainers,
+          base::Unretained(this)));
 }
 
 void AmbientModeHandler::OnJavascriptAllowed() {
   GetSettings();
+
+  // Prefetch albums.
+  FetchPersonalAlbums();
 }
 
 void AmbientModeHandler::OnJavascriptDisallowed() {
@@ -41,21 +74,63 @@
   CHECK(args);
   CHECK(args->empty());
 
+  init_from_ambient_mode_page_ = true;
   AllowJavascript();
 }
 
-void AmbientModeHandler::HandleTopicSourceSelectedChanged(
-    const base::ListValue* args) {
-  CHECK_EQ(args->GetSize(), 1U);
-  int topic_source;
-  CHECK(base::StringToInt(args->GetList()[0].GetString(), &topic_source));
-  // Check the |topic_source| has valid value.
-  CHECK_GE(topic_source,
-           static_cast<int>(ash::AmbientModeTopicSource::kMinValue));
-  CHECK_LE(topic_source,
-           static_cast<int>(ash::AmbientModeTopicSource::kMaxValue));
+void AmbientModeHandler::RequestPhotosContainers(const base::ListValue* args) {
+  // TODO(b/159747583): Handle deep linking to ambientMode/photos page.
+  // For now it will not load the page contents if visited directly.
+  if (!init_from_ambient_mode_page_)
+    return;
 
-  UpdateSettings(static_cast<ash::AmbientModeTopicSource>(topic_source));
+  ash::AmbientModeTopicSource topic_source = ExtractTopicSource(args);
+  DCHECK_EQ(topic_source, settings_->topic_source);
+
+  if (topic_source == ash::AmbientModeTopicSource::kGooglePhotos) {
+    FetchPersonalAlbums();
+  }
+  SendPhotosContainers();
+}
+
+void AmbientModeHandler::HandleSetSelectedTopicSource(
+    const base::ListValue* args) {
+  ash::AmbientModeTopicSource topic_source = ExtractTopicSource(args);
+  settings_->topic_source = topic_source;
+  UpdateSettings();
+}
+
+void AmbientModeHandler::HandleSetSelectedPhotosContainers(
+    const base::ListValue* args) {
+  switch (settings_->topic_source) {
+    case ash::AmbientModeTopicSource::kGooglePhotos:
+      // For Google Photos, we will populate the |selected_album_ids| with IDs
+      // of selected albums.
+      settings_->selected_album_ids.clear();
+      for (const auto& value : args->GetList()) {
+        std::string name = value.GetString();
+        auto it = std::find_if(
+            personal_albums_.albums.begin(), personal_albums_.albums.end(),
+            [name](const auto& album) { return album.album_name == name; });
+        CHECK(it != personal_albums_.albums.end());
+        settings_->selected_album_ids.emplace_back(it->album_id);
+      }
+      break;
+    case ash::AmbientModeTopicSource::kArtGallery:
+      // For Art gallery, we set the corresponding setting to be enabled or not
+      // based on the selections.
+      for (auto& art_setting : settings_->art_settings) {
+        std::string title = art_setting.title;
+        auto it = std::find_if(
+            args->GetList().begin(), args->GetList().end(),
+            [title](const auto& value) { return value.GetString() == title; });
+        const bool checked = it != args->GetList().end();
+        art_setting.enabled = checked;
+      }
+      break;
+  }
+
+  UpdateSettings();
 }
 
 void AmbientModeHandler::GetSettings() {
@@ -81,18 +156,46 @@
                     base::Value(static_cast<int>(settings_->topic_source)));
 }
 
-void AmbientModeHandler::UpdateSettings(
-    ash::AmbientModeTopicSource topic_source) {
+void AmbientModeHandler::SendPhotosContainers() {
   DCHECK(settings_);
-  settings_->topic_source = topic_source;
-  ash::AmbientBackendController::Get()->UpdateSettings(
-      *settings_, base::BindOnce(&AmbientModeHandler::OnUpdateSettings,
-                                 weak_factory_.GetWeakPtr(), topic_source));
+
+  base::Value dictionary(base::Value::Type::DICTIONARY);
+  base::Value containers(base::Value::Type::LIST);
+  switch (settings_->topic_source) {
+    case ash::AmbientModeTopicSource::kGooglePhotos:
+      for (const auto& album : personal_albums_.albums) {
+        base::Value value(base::Value::Type::DICTIONARY);
+        value.SetKey("title", base::Value(album.album_name));
+        value.SetKey("checked",
+                     base::Value(base::Contains(settings_->selected_album_ids,
+                                                album.album_id)));
+        containers.Append(std::move(value));
+      }
+      break;
+    case ash::AmbientModeTopicSource::kArtGallery:
+      for (const auto& setting : settings_->art_settings) {
+        base::Value value(base::Value::Type::DICTIONARY);
+        value.SetKey("title", base::Value(setting.title));
+        value.SetKey("checked", base::Value(setting.enabled));
+        containers.Append(std::move(value));
+      }
+      break;
+  }
+
+  dictionary.SetKey("topicSource",
+                    base::Value(static_cast<int>(settings_->topic_source)));
+  dictionary.SetKey("topicContainers", std::move(containers));
+  FireWebUIListener("photos-containers-changed", std::move(dictionary));
 }
 
-void AmbientModeHandler::OnUpdateSettings(
-    ash::AmbientModeTopicSource topic_source,
-    bool success) {
+void AmbientModeHandler::UpdateSettings() {
+  DCHECK(settings_);
+  ash::AmbientBackendController::Get()->UpdateSettings(
+      *settings_, base::BindOnce(&AmbientModeHandler::OnUpdateSettings,
+                                 weak_factory_.GetWeakPtr()));
+}
+
+void AmbientModeHandler::OnUpdateSettings(bool success) {
   if (success)
     return;
 
@@ -100,5 +203,31 @@
   // when user confirms in the error message dialog.
 }
 
+void AmbientModeHandler::FetchPersonalAlbums() {
+  // TODO: Add a helper function to get all the albums.
+  ash::AmbientBackendController::Get()->FetchPersonalAlbums(
+      kBannerWidth, kBannderHeight, /*num_albums=*/100, /*resume_token=*/"",
+      base::BindOnce(&AmbientModeHandler::OnPersonalAlbumsFetched,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void AmbientModeHandler::OnPersonalAlbumsFetched(
+    ash::PersonalAlbums personal_albums) {
+  personal_albums_ = std::move(personal_albums);
+
+  // If the |topic_source| is not |kGooglePhotos|, no need to refresh the
+  // photos subpage.
+  // |settings_| could be null because we call GetSettings() and
+  // FetchPersonalAlbums() in OnJavascriptAllowed(). |settings_| is populated by
+  // OnGetSettings(), which could be called later. The purpose to call
+  // FetchPersonalAlbums() is to prefetch albums, which takes several seconds,
+  // This improves the experience when we click into the ambientMode/photos page
+  // to show the albums list faster.
+  if (settings_ &&
+      settings_->topic_source == ash::AmbientModeTopicSource::kGooglePhotos) {
+    SendPhotosContainers();
+  }
+}
+
 }  // namespace settings
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h
index 973e1fc..ac0c6441 100644
--- a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h
@@ -41,8 +41,15 @@
   // WebUI call to signal js side is ready.
   void HandleInitialized(const base::ListValue* args);
 
+  // WebUI call to request photos containers, e.g. personal albums or art
+  // categories.
+  void RequestPhotosContainers(const base::ListValue* args);
+
   // WebUI call to sync topic source with server.
-  void HandleTopicSourceSelectedChanged(const base::ListValue* args);
+  void HandleSetSelectedTopicSource(const base::ListValue* args);
+
+  // WebUI call to sync photos containers with server.
+  void HandleSetSelectedPhotosContainers(const base::ListValue* args);
 
   // Retrieve the initial settings from server.
   void GetSettings();
@@ -54,15 +61,27 @@
   // settings is retrieved.
   void SendTopicSource();
 
-  // Update the selected topic source to server.
-  void UpdateSettings(ash::AmbientModeTopicSource topic_source);
+  // Send the "photos-containers-changed" WebUIListener event when the personal
+  // albums are retrieved.
+  void SendPhotosContainers();
+
+  // Update the local |settings_| to server.
+  void UpdateSettings();
 
   // Called when the settings is updated.
-  // |topic_source| is the value to retry if the update was failed.
-  void OnUpdateSettings(ash::AmbientModeTopicSource topic_source, bool success);
+  void OnUpdateSettings(bool success);
+
+  void FetchPersonalAlbums();
+
+  void OnPersonalAlbumsFetched(ash::PersonalAlbums personal_albums);
+
+  // Whether the Javascript is inited from the ambientMode page.
+  bool init_from_ambient_mode_page_ = false;
 
   base::Optional<ash::AmbientSettings> settings_;
 
+  ash::PersonalAlbums personal_albums_;
+
   base::WeakPtrFactory<AmbientModeHandler> weak_factory_{this};
 };
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom b/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
index 7cae045..ecb574c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
+++ b/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
@@ -74,6 +74,7 @@
   // Personalization section.
   kChangePicture = 500,
   kAmbientMode = 501,
+  kAmbientModePhotos= 502,
 
   // Search and Assistant section.
   kAssistant = 600,
@@ -171,6 +172,7 @@
 const string kPersonalizationSectionPath = "personalization";
 const string kChangePictureSubpagePath = "changePicture";
 const string kAmbientModeSubpagePath = "ambientMode";
+const string kAmbientModePhotosSubpagePath = "ambientMode/photos";
 
 // Search and Assistant section.
 const string kSearchAndAssistantSectionPath = "osSearch";
diff --git a/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom b/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom
index 1b30b87..1933926 100644
--- a/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom
+++ b/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom
@@ -117,6 +117,7 @@
   kAmbientModeOnOff = 501,
   kAmbientModeSource = 502,
   kChangeDeviceAccountImage = 503,
+  kAmbientModeUpdatePhotosContainers = 504,
 
   // Search and Assistant section.
   kPreferredSearchEngine = 600,
diff --git a/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc b/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc
index 4e991d0..dfbbaf1 100644
--- a/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc
@@ -60,6 +60,7 @@
   return *tags;
 }
 
+// TODO(b/159766700): Add search concepts for |kAmbientModePhotosSubpagePath|.
 const std::vector<SearchConcept>& GetAmbientModeSearchConcepts() {
   static const base::NoDestructor<std::vector<SearchConcept>> tags({
       {IDS_OS_SETTINGS_TAG_AMBIENT_MODE,
@@ -237,6 +238,19 @@
   };
   RegisterNestedSettingBulk(mojom::Subpage::kAmbientMode, kAmbientModeSettings,
                             generator);
+
+  // Note: The subpage name in the UI is updated dynamically based on the topic
+  // source.
+  // TODO(b/159766700): Create a string for the page title and strings for the
+  // search.
+  generator->RegisterNestedSubpage(
+      IDS_OS_SETTINGS_AMBIENT_MODE_TITLE, mojom::Subpage::kAmbientModePhotos,
+      mojom::Subpage::kAmbientMode, mojom::SearchResultIcon::kWallpaper,
+      mojom::SearchResultDefaultRank::kMedium,
+      mojom::kAmbientModePhotosSubpagePath);
+  generator->RegisterNestedSetting(
+      mojom::Setting::kAmbientModeUpdatePhotosContainers,
+      mojom::Subpage::kAmbientModePhotos);
 }
 
 void PersonalizationSection::OnAmbientModeEnabledStateChanged() {
diff --git a/chrome/browser/ui/webui/settings/safe_browsing_handler.cc b/chrome/browser/ui/webui/settings/safe_browsing_handler.cc
deleted file mode 100644
index 7403e56..0000000
--- a/chrome/browser/ui/webui/settings/safe_browsing_handler.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/settings/safe_browsing_handler.h"
-
-#include "components/prefs/pref_change_registrar.h"
-#include "components/prefs/pref_service.h"
-#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
-#include "components/safe_browsing/core/features.h"
-
-namespace settings {
-
-SafeBrowsingHandler::SafeBrowsingHandler(Profile* profile)
-    : profile_(profile) {}
-SafeBrowsingHandler::~SafeBrowsingHandler() = default;
-
-void SafeBrowsingHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback(
-      "getSafeBrowsingRadioManagedState",
-      base::BindRepeating(
-          &SafeBrowsingHandler::HandleGetSafeBrowsingRadioManagedState,
-          base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(
-      "validateSafeBrowsingEnhanced",
-      base::BindRepeating(
-          &SafeBrowsingHandler::HandleValidateSafeBrowsingEnhanced,
-          base::Unretained(this)));
-}
-
-void SafeBrowsingHandler::HandleGetSafeBrowsingRadioManagedState(
-    const base::ListValue* args) {
-  AllowJavascript();
-  CHECK_EQ(1U, args->GetList().size());
-  std::string callback_id = args->GetList()[0].GetString();
-
-  auto state = GetSafeBrowsingRadioManagedState(profile_);
-
-  base::Value result(base::Value::Type::DICTIONARY);
-  // TODO(crbug.com/1063265): Move managed state functions out of site_settings.
-  result.SetKey(kSafeBrowsingEnhanced,
-                site_settings::GetValueForManagedState(state.enhanced));
-  result.SetKey(kSafeBrowsingStandard,
-                site_settings::GetValueForManagedState(state.standard));
-  result.SetKey(kSafeBrowsingDisabled,
-                site_settings::GetValueForManagedState(state.disabled));
-
-  ResolveJavascriptCallback(base::Value(callback_id), result);
-}
-
-void SafeBrowsingHandler::HandleValidateSafeBrowsingEnhanced(
-    const base::ListValue* args) {
-  // TODO(crbug.com/1074499) Remove this logic when Enhanced protection is
-  // considered stable.
-  if (!base::FeatureList::IsEnabled(safe_browsing::kEnhancedProtection))
-    profile_->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnhanced, false);
-}
-
-SafeBrowsingRadioManagedState
-SafeBrowsingHandler::GetSafeBrowsingRadioManagedState(Profile* profile) {
-  // Create a default managed state that is updated based on preferences.
-  SafeBrowsingRadioManagedState managed_state;
-
-  // Computing the effective Safe Browsing managed state requires inspecting
-  // three different preferences. It is possible that these may be in
-  // temporarily conflicting managed states. The enabled preference is always
-  // taken as the canonical source of management.
-  const PrefService::Preference* enabled_pref =
-      profile->GetPrefs()->FindPreference(prefs::kSafeBrowsingEnabled);
-  const bool enabled_enforced = !enabled_pref->IsUserModifiable();
-  const bool enabled_recommended =
-      (enabled_pref && enabled_pref->GetRecommendedValue());
-  const bool enabled_recommended_on =
-      enabled_recommended && enabled_pref->GetRecommendedValue()->GetBool();
-  const auto enabled_policy_indicator =
-      site_settings::GetPolicyIndicatorFromPref(enabled_pref);
-
-  // The enhanced preference may have a recommended setting. This only takes
-  // effect if the enabled preference also has a recommended setting.
-  const PrefService::Preference* enhanced_pref =
-      profile->GetPrefs()->FindPreference(prefs::kSafeBrowsingEnhanced);
-  const bool enhanced_recommended_on =
-      enhanced_pref->GetRecommendedValue() &&
-      enhanced_pref->GetRecommendedValue()->GetBool();
-
-  // A forcefully disabled reporting preference will disallow enhanced from
-  // being selected and thus it must also be considered.
-  const PrefService::Preference* reporting_pref =
-      profile->GetPrefs()->FindPreference(
-          prefs::kSafeBrowsingScoutReportingEnabled);
-  const bool reporting_on = reporting_pref->GetValue()->GetBool();
-  const bool reporting_enforced = !reporting_pref->IsUserModifiable();
-  const auto reporting_policy_indicator =
-      site_settings::GetPolicyIndicatorFromPref(reporting_pref);
-
-  if (!enabled_enforced && !enabled_recommended && !reporting_enforced) {
-    // No relevant policies are applied, return the default state.
-    return managed_state;
-  }
-  if (enabled_enforced) {
-    // All radio controls are managed.
-    managed_state.enhanced.disabled = true;
-    managed_state.enhanced.indicator = enabled_policy_indicator;
-    managed_state.standard.disabled = true;
-    managed_state.standard.indicator = enabled_policy_indicator;
-    managed_state.disabled.disabled = true;
-    managed_state.disabled.indicator = enabled_policy_indicator;
-    return managed_state;
-  }
-  if (enabled_recommended) {
-    if (enhanced_recommended_on) {
-      managed_state.enhanced.indicator = enabled_policy_indicator;
-    } else if (enabled_recommended_on) {
-      managed_state.standard.indicator = enabled_policy_indicator;
-    } else {
-      managed_state.disabled.indicator = enabled_policy_indicator;
-    }
-    return managed_state;
-  }
-  if (reporting_enforced && !reporting_on) {
-    // Disable enhanced protection when reporting has been enforced off.
-    managed_state.enhanced.disabled = true;
-    managed_state.enhanced.indicator = reporting_policy_indicator;
-    return managed_state;
-  }
-
-  return managed_state;
-}
-
-}  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/safe_browsing_handler.h b/chrome/browser/ui/webui/settings/safe_browsing_handler.h
deleted file mode 100644
index a92e70ad..0000000
--- a/chrome/browser/ui/webui/settings/safe_browsing_handler.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2020 The Chromium 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_UI_WEBUI_SETTINGS_SAFE_BROWSING_HANDLER_H_
-#define CHROME_BROWSER_UI_WEBUI_SETTINGS_SAFE_BROWSING_HANDLER_H_
-
-#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
-#include "chrome/browser/ui/webui/settings/site_settings_helper.h"
-
-#include "chrome/browser/profiles/profile.h"
-
-namespace settings {
-
-constexpr char kSafeBrowsingEnhanced[] = "enhanced";
-constexpr char kSafeBrowsingStandard[] = "standard";
-constexpr char kSafeBrowsingDisabled[] = "disabled";
-
-struct SafeBrowsingRadioManagedState {
-  site_settings::ManagedState enhanced;
-  site_settings::ManagedState standard;
-  site_settings::ManagedState disabled;
-};
-
-// Settings page UI handler that provides representation of Safe Browsing
-// settings.
-class SafeBrowsingHandler : public SettingsPageUIHandler {
- public:
-  explicit SafeBrowsingHandler(Profile* profile);
-  ~SafeBrowsingHandler() override;
-
-  // WebUIMessageHandler implementation.
-  void RegisterMessages() override;
-
-  // Calculate and return the current Safe Browsing radio buttons.
-  void HandleGetSafeBrowsingRadioManagedState(const base::ListValue* args);
-
-  // Confirm that the current Safe Browsing Enhanced preference is appropriate
-  // for the currently enabled features, updating it if required.
-  void HandleValidateSafeBrowsingEnhanced(const base::ListValue* args);
-
- private:
-  friend class SafeBrowsingHandlerTest;
-  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingHandlerTest, GenerateRadioManagedState);
-  FRIEND_TEST_ALL_PREFIXES(SafeBrowsingHandlerTest, ProvideRadioManagedState);
-
-  // SettingsPageUIHandler implementation.
-  void OnJavascriptAllowed() override {}
-  void OnJavascriptDisallowed() override {}
-
-  // Calculate the current Safe Browsing control state for the provided profile.
-  static SafeBrowsingRadioManagedState GetSafeBrowsingRadioManagedState(
-      Profile* profile);
-
-  Profile* profile_;
-
-  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingHandler);
-};
-
-}  // namespace settings
-
-#endif  // CHROME_BROWSER_UI_WEBUI_SETTINGS_SAFE_BROWSING_HANDLER_H_
diff --git a/chrome/browser/ui/webui/settings/safe_browsing_handler_unittest.cc b/chrome/browser/ui/webui/settings/safe_browsing_handler_unittest.cc
deleted file mode 100644
index 3065bc2..0000000
--- a/chrome/browser/ui/webui/settings/safe_browsing_handler_unittest.cc
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/settings/safe_browsing_handler.h"
-
-#include <memory>
-#include <string>
-
-#include "base/test/scoped_feature_list.h"
-#include "base/values.h"
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "chrome/test/base/testing_profile.h"
-#include "components/prefs/pref_service.h"
-#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
-#include "components/safe_browsing/core/features.h"
-#include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/test_web_ui.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace settings {
-
-class SafeBrowsingHandlerTest : public testing::Test {
- public:
-  void SetUp() override {
-    handler_ = std::make_unique<SafeBrowsingHandler>(profile());
-    handler()->set_web_ui(web_ui());
-    handler()->AllowJavascript();
-    web_ui()->ClearTrackedCalls();
-  }
-
-  TestingProfile* profile() { return &profile_; }
-  content::TestWebUI* web_ui() { return &web_ui_; }
-  SafeBrowsingHandler* handler() { return handler_.get(); }
-
- private:
-  content::BrowserTaskEnvironment task_environment_;
-  std::unique_ptr<SafeBrowsingHandler> handler_;
-  TestingProfile profile_;
-  content::TestWebUI web_ui_;
-};
-
-// All of the possible managed states for a boolean preference that can be
-// both enforced and recommended.
-// TODO(crbug.com/1063265): Remove duplication with site_settings_helper.
-enum class PrefSetting {
-  kEnforcedOff,
-  kEnforcedOn,
-  kRecommendedOff,
-  kRecommendedOn,
-  kNotSet,
-};
-
-// Possible preference sources supported by TestingPrefService.
-// TODO(crbug.com/1063265): Remove duplication with site_settings_helper.
-enum class PrefSource {
-  kExtension,
-  kDevicePolicy,
-  kRecommended,
-  kNone,
-};
-
-void AssertRadioManagedStateEqual(const SafeBrowsingRadioManagedState& a,
-                                  const SafeBrowsingRadioManagedState& b) {
-  ASSERT_EQ(a.enhanced.disabled, b.enhanced.disabled);
-  ASSERT_EQ(a.enhanced.indicator, b.enhanced.indicator);
-  ASSERT_EQ(a.standard.disabled, b.standard.disabled);
-  ASSERT_EQ(a.standard.indicator, b.standard.indicator);
-  ASSERT_EQ(a.disabled.disabled, b.disabled.disabled);
-  ASSERT_EQ(a.disabled.indicator, b.disabled.indicator);
-}
-
-struct RadioManagedStateTestCase {
-  PrefSetting safe_browsing_enhanced;
-  PrefSetting safe_browsing_enabled;
-  PrefSetting safe_browsing_reporting;
-  PrefSource preference_source;
-  SafeBrowsingRadioManagedState expected_result;
-};
-
-const std::vector<RadioManagedStateTestCase> test_cases = {
-    {PrefSetting::kNotSet,
-     PrefSetting::kNotSet,
-     PrefSetting::kNotSet,
-     PrefSource::kNone,
-     {{false, site_settings::PolicyIndicatorType::kNone},
-      {false, site_settings::PolicyIndicatorType::kNone},
-      {false, site_settings::PolicyIndicatorType::kNone}}},
-    {PrefSetting::kEnforcedOn,
-     PrefSetting::kEnforcedOn,
-     PrefSetting::kNotSet,
-     PrefSource::kExtension,
-     {{true, site_settings::PolicyIndicatorType::kExtension},
-      {true, site_settings::PolicyIndicatorType::kExtension},
-      {true, site_settings::PolicyIndicatorType::kExtension}}},
-    {PrefSetting::kEnforcedOff,
-     PrefSetting::kEnforcedOff,
-     PrefSetting::kNotSet,
-     PrefSource::kDevicePolicy,
-     {{true, site_settings::PolicyIndicatorType::kDevicePolicy},
-      {true, site_settings::PolicyIndicatorType::kDevicePolicy},
-      {true, site_settings::PolicyIndicatorType::kDevicePolicy}}},
-    {PrefSetting::kEnforcedOff,
-     PrefSetting::kEnforcedOn,
-     PrefSetting::kNotSet,
-     PrefSource::kExtension,
-     {{true, site_settings::PolicyIndicatorType::kExtension},
-      {true, site_settings::PolicyIndicatorType::kExtension},
-      {true, site_settings::PolicyIndicatorType::kExtension}}},
-    {PrefSetting::kRecommendedOn,
-     PrefSetting::kRecommendedOn,
-     PrefSetting::kNotSet,
-     PrefSource::kRecommended,
-     {{false, site_settings::PolicyIndicatorType::kRecommended},
-      {false, site_settings::PolicyIndicatorType::kNone},
-      {false, site_settings::PolicyIndicatorType::kNone}}},
-    {PrefSetting::kRecommendedOff,
-     PrefSetting::kRecommendedOn,
-     PrefSetting::kNotSet,
-     PrefSource::kRecommended,
-     {{false, site_settings::PolicyIndicatorType::kNone},
-      {false, site_settings::PolicyIndicatorType::kRecommended},
-      {false, site_settings::PolicyIndicatorType::kNone}}},
-    {PrefSetting::kRecommendedOff,
-     PrefSetting::kRecommendedOff,
-     PrefSetting::kNotSet,
-     PrefSource::kRecommended,
-     {{false, site_settings::PolicyIndicatorType::kNone},
-      {false, site_settings::PolicyIndicatorType::kNone},
-      {false, site_settings::PolicyIndicatorType::kRecommended}}},
-    {PrefSetting::kNotSet,
-     PrefSetting::kNotSet,
-     PrefSetting::kEnforcedOff,
-     PrefSource::kDevicePolicy,
-     {{true, site_settings::PolicyIndicatorType::kDevicePolicy},
-      {false, site_settings::PolicyIndicatorType::kNone},
-      {false, site_settings::PolicyIndicatorType::kNone}}}};
-
-void SetupTestConditions(TestingProfile* profile,
-                         const RadioManagedStateTestCase& test_case) {
-  sync_preferences::TestingPrefServiceSyncable* prefs =
-      profile->GetTestingPrefService();
-  const std::map<const char*, PrefSetting> pref_to_setting = {
-      {prefs::kSafeBrowsingEnhanced, test_case.safe_browsing_enhanced},
-      {prefs::kSafeBrowsingEnabled, test_case.safe_browsing_enabled},
-      {prefs::kSafeBrowsingScoutReportingEnabled,
-       test_case.safe_browsing_reporting}};
-
-  for (const auto& pref_setting : pref_to_setting) {
-    if (pref_setting.second == PrefSetting::kNotSet) {
-      continue;
-    }
-    auto pref_value = std::make_unique<base::Value>(
-        pref_setting.second == PrefSetting::kRecommendedOn ||
-        pref_setting.second == PrefSetting::kEnforcedOn);
-    if (test_case.preference_source == PrefSource::kExtension) {
-      prefs->SetExtensionPref(pref_setting.first, std::move(pref_value));
-    } else if (test_case.preference_source == PrefSource::kDevicePolicy) {
-      prefs->SetManagedPref(pref_setting.first, std::move(pref_value));
-    } else if (test_case.preference_source == PrefSource::kRecommended) {
-      prefs->SetRecommendedPref(pref_setting.first, std::move(pref_value));
-    }
-  }
-}
-
-TEST_F(SafeBrowsingHandlerTest, GenerateRadioManagedState) {
-  int count = 0;
-  for (const auto& test_case : test_cases) {
-    TestingProfile profile;
-    SCOPED_TRACE(base::StringPrintf("Test case %d", count++));
-    SetupTestConditions(&profile, test_case);
-    AssertRadioManagedStateEqual(
-        handler()->GetSafeBrowsingRadioManagedState(&profile),
-        test_case.expected_result);
-  }
-}
-
-TEST_F(SafeBrowsingHandlerTest, ProvideRadioManagedState) {
-  // Test that the handler correctly wraps the generated result.
-  const std::string kNone = "none";
-  const std::string kDevicePolicy = "devicePolicy";
-  const std::string kCallbackId = "callback";
-  const std::vector<std::string> kRadioNames = {"enhanced", "standard",
-                                                "disabled"};
-
-  // Check that the default radio state is handled correctly.
-  base::ListValue get_args;
-  get_args.AppendString(kCallbackId);
-  handler()->HandleGetSafeBrowsingRadioManagedState(&get_args);
-  {
-    const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
-    EXPECT_EQ("cr.webUIResponse", data.function_name());
-    EXPECT_EQ(kCallbackId, data.arg1()->GetString());
-    ASSERT_TRUE(data.arg2()->GetBool());
-    for (const auto& control_name : kRadioNames) {
-      auto* control_state = data.arg3()->FindPath(control_name);
-      ASSERT_FALSE(control_state->FindKey("disabled")->GetBool());
-      ASSERT_EQ(kNone, control_state->FindKey("indicator")->GetString());
-    }
-  }
-
-  // Create a fully managed state and check it is returned correctly.
-  sync_preferences::TestingPrefServiceSyncable* pref_service =
-      profile()->GetTestingPrefService();
-  pref_service->SetManagedPref(prefs::kSafeBrowsingEnhanced,
-                               std::make_unique<base::Value>(true));
-  pref_service->SetManagedPref(prefs::kSafeBrowsingEnabled,
-                               std::make_unique<base::Value>(true));
-
-  handler()->HandleGetSafeBrowsingRadioManagedState(&get_args);
-  {
-    const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
-    EXPECT_EQ("cr.webUIResponse", data.function_name());
-    EXPECT_EQ(kCallbackId, data.arg1()->GetString());
-    ASSERT_TRUE(data.arg2()->GetBool());
-    for (const auto& control_name : kRadioNames) {
-      auto* control_state = data.arg3()->FindPath(control_name);
-      ASSERT_TRUE(control_state->FindKey("disabled")->GetBool());
-      ASSERT_EQ(kDevicePolicy,
-                control_state->FindKey("indicator")->GetString());
-    }
-  }
-}
-
-TEST_F(SafeBrowsingHandlerTest, ValidateSafeBrowsingPrefs) {
-  base::ListValue args;
-  base::test::ScopedFeatureList scoped_feature_list_;
-  sync_preferences::TestingPrefServiceSyncable* pref_service =
-      profile()->GetTestingPrefService();
-
-  pref_service->SetBoolean(prefs::kSafeBrowsingEnhanced, true);
-
-  // Ensure the preference is not changed when the Enhanced feature is enabled.
-  scoped_feature_list_.InitWithFeatures({safe_browsing::kEnhancedProtection},
-                                        {});
-  handler()->HandleValidateSafeBrowsingEnhanced(&args);
-  EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnhanced));
-  scoped_feature_list_.Reset();
-
-  // Ensure the preference is disabled when the Enhanced feature is disabled.
-  scoped_feature_list_.InitWithFeatures({},
-                                        {safe_browsing::kEnhancedProtection});
-  handler()->HandleValidateSafeBrowsingEnhanced(&args);
-  EXPECT_FALSE(pref_service->GetBoolean(prefs::kSafeBrowsingEnhanced));
-}
-
-}  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc
index 9e29823..278369c 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -43,7 +43,6 @@
 #include "chrome/browser/ui/webui/settings/profile_info_handler.h"
 #include "chrome/browser/ui/webui/settings/protocol_handlers_handler.h"
 #include "chrome/browser/ui/webui/settings/reset_settings_handler.h"
-#include "chrome/browser/ui/webui/settings/safe_browsing_handler.h"
 #include "chrome/browser/ui/webui/settings/safety_check_handler.h"
 #include "chrome/browser/ui/webui/settings/search_engines_handler.h"
 #include "chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h"
@@ -205,7 +204,6 @@
   AddSettingsPageUIHandler(std::make_unique<PeopleHandler>(profile));
   AddSettingsPageUIHandler(std::make_unique<ProfileInfoHandler>(profile));
   AddSettingsPageUIHandler(std::make_unique<ProtocolHandlersHandler>());
-  AddSettingsPageUIHandler(std::make_unique<SafeBrowsingHandler>(profile));
   AddSettingsPageUIHandler(std::make_unique<SearchEnginesHandler>(profile));
   AddSettingsPageUIHandler(std::make_unique<SecureDnsHandler>());
   AddSettingsPageUIHandler(std::make_unique<SiteSettingsHandler>(
diff --git a/chrome/browser/ui/webui/signin/inline_login_ui.cc b/chrome/browser/ui/webui/signin/inline_login_ui.cc
index c00843b7b..a87edf5 100644
--- a/chrome/browser/ui/webui/signin/inline_login_ui.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_ui.cc
@@ -114,6 +114,7 @@
     {"inline_login.js", IDR_INLINE_LOGIN_JS},
     {"gaia_auth_host.js", IDR_GAIA_AUTH_AUTHENTICATOR_JS},
 #if defined(OS_CHROMEOS)
+    {"error_screen.js", IDR_ACCOUNT_MANAGER_COMPONENTS_ERROR_SCREEN_JS},
     {"edu", IDR_EDU_LOGIN_EDU_LOGIN_HTML},
     {"app.js", IDR_EDU_LOGIN_EDU_LOGIN_JS},
     {"edu_login_button.js", IDR_EDU_LOGIN_EDU_LOGIN_BUTTON_JS},
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_icon_manager.cc b/chrome/browser/web_applications/extensions/bookmark_app_icon_manager.cc
index 9ab6508..ffc2466 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_icon_manager.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_icon_manager.cc
@@ -239,7 +239,7 @@
       FROM_HERE,
       {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
        base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
-      base::BindOnce(ReadShortcutsMenuIconsBlocking, img_reps),
+      base::BindOnce(ReadShortcutsMenuIconsBlocking, std::move(img_reps)),
       std::move(callback));
 }
 
diff --git a/chrome/browser/web_applications/os_integration_manager.cc b/chrome/browser/web_applications/os_integration_manager.cc
index 532a11f3..a98306b 100644
--- a/chrome/browser/web_applications/os_integration_manager.cc
+++ b/chrome/browser/web_applications/os_integration_manager.cc
@@ -7,10 +7,8 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/feature_list.h"
 #include "chrome/browser/web_applications/components/app_shortcut_manager.h"
 #include "chrome/browser/web_applications/components/file_handler_manager.h"
-#include "chrome/common/chrome_features.h"
 
 namespace web_app {
 
diff --git a/chrome/browser/web_applications/proto/web_app.proto b/chrome/browser/web_applications/proto/web_app.proto
index a7622bc..b3b830b 100644
--- a/chrome/browser/web_applications/proto/web_app.proto
+++ b/chrome/browser/web_applications/proto/web_app.proto
@@ -49,6 +49,18 @@
   required bool is_disabled = 4;
 }
 
+// Properties for a WebApp's shortcuts menu item.
+message WebAppShortcutsMenuItemInfoProto {
+  required string name = 1;
+  required string url = 2;
+  repeated sync_pb.WebAppIconInfo shortcut_icon_infos = 3;
+}
+
+// List of icon sizes downloaded to disk for a shortcuts menu item.
+message DownloadedShortcutsMenuIconSizesProto {
+  repeated int32 icon_sizes = 1;
+}
+
 // Full WebApp object data. See detailed comments in
 // chrome/browser/web_applications/web_app.h. Note on database identities:
 // app_id is a hash of launch_url. app_id is the client tag for sync system.
@@ -106,4 +118,10 @@
   repeated WebAppProtocolHandler protocol_handlers = 17;
 
   required bool is_generated_icon = 18;
+
+  // A list of Shortcuts Menu items specified in the Web App Manifest.
+  repeated WebAppShortcutsMenuItemInfoProto shortcut_infos = 19;
+  // A list of icon sizes we successfully downloaded to store on disk.
+  repeated DownloadedShortcutsMenuIconSizesProto
+      downloaded_shortcuts_menu_icons_sizes = 20;
 }
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h
index 71c4f5f..b623289b 100644
--- a/chrome/browser/web_applications/web_app.h
+++ b/chrome/browser/web_applications/web_app.h
@@ -213,8 +213,6 @@
   std::vector<WebApplicationIconInfo> icon_infos_;
   std::vector<SquareSizePx> downloaded_icon_sizes_;
   bool is_generated_icon_ = false;
-  // TODO(https://crbug.com/1069312): Serialize shortcut_infos_ and
-  // downloaded_shortcuts_menu_icons_sizes_ fields in WebAppDatabase.
   std::vector<WebApplicationShortcutsMenuItemInfo> shortcut_infos_;
   std::vector<std::vector<SquareSizePx>> downloaded_shortcuts_menu_icons_sizes_;
   apps::FileHandlers file_handlers_;
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc
index 6b17c38..e2601ab 100644
--- a/chrome/browser/web_applications/web_app_database.cc
+++ b/chrome/browser/web_applications/web_app_database.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
 #include "chrome/browser/web_applications/components/web_app_utils.h"
 #include "chrome/browser/web_applications/web_app.h"
@@ -198,6 +199,31 @@
     }
   }
 
+  for (const WebApplicationShortcutsMenuItemInfo& shortcut_info :
+       web_app.shortcut_infos()) {
+    WebAppShortcutsMenuItemInfoProto* shortcut_info_proto =
+        local_data->add_shortcut_infos();
+    shortcut_info_proto->set_name(base::UTF16ToUTF8(shortcut_info.name));
+    shortcut_info_proto->set_url(shortcut_info.url.spec());
+    for (const WebApplicationShortcutsMenuItemInfo::Icon& icon_info :
+         shortcut_info.shortcut_icon_infos) {
+      sync_pb::WebAppIconInfo* shortcut_icon_info_proto =
+          shortcut_info_proto->add_shortcut_icon_infos();
+      DCHECK(!icon_info.url.is_empty());
+      shortcut_icon_info_proto->set_url(icon_info.url.spec());
+      shortcut_icon_info_proto->set_size_in_px(icon_info.square_size_px);
+    }
+  }
+
+  for (const std::vector<SquareSizePx>& icon_sizes :
+       web_app.downloaded_shortcuts_menu_icons_sizes()) {
+    DownloadedShortcutsMenuIconSizesProto* icon_sizes_proto =
+        local_data->add_downloaded_shortcuts_menu_icons_sizes();
+    for (const SquareSizePx& icon_size : icon_sizes) {
+      icon_sizes_proto->add_icon_sizes(icon_size);
+    }
+  }
+
   for (const auto& additional_search_term : web_app.additional_search_terms()) {
     // Additional search terms should be sanitized before being added here.
     DCHECK(!additional_search_term.empty());
@@ -394,6 +420,36 @@
   }
   web_app->SetFileHandlers(std::move(file_handlers));
 
+  std::vector<WebApplicationShortcutsMenuItemInfo> shortcut_infos;
+  for (const auto& shortcut_info_proto : local_data.shortcut_infos()) {
+    WebApplicationShortcutsMenuItemInfo shortcut_info;
+    shortcut_info.name = base::UTF8ToUTF16(shortcut_info_proto.name());
+    shortcut_info.url = GURL(shortcut_info_proto.url());
+    for (const auto& icon_info_proto :
+         shortcut_info_proto.shortcut_icon_infos()) {
+      WebApplicationShortcutsMenuItemInfo::Icon shortcut_icon_info;
+      shortcut_icon_info.square_size_px = icon_info_proto.size_in_px();
+      shortcut_icon_info.url = GURL(icon_info_proto.url());
+      shortcut_info.shortcut_icon_infos.emplace_back(
+          std::move(shortcut_icon_info));
+    }
+    shortcut_infos.emplace_back(std::move(shortcut_info));
+  }
+  web_app->SetShortcutInfos(std::move(shortcut_infos));
+
+  std::vector<std::vector<SquareSizePx>> shortcuts_menu_icons_sizes;
+  for (const auto& shortcuts_icon_sizes_proto :
+       local_data.downloaded_shortcuts_menu_icons_sizes()) {
+    std::vector<SquareSizePx> shortcuts_menu_icon_sizes;
+    for (const auto& icon_size : shortcuts_icon_sizes_proto.icon_sizes()) {
+      shortcuts_menu_icon_sizes.emplace_back(icon_size);
+    }
+    shortcuts_menu_icons_sizes.emplace_back(
+        std::move(shortcuts_menu_icon_sizes));
+  }
+  web_app->SetDownloadedShortcutsMenuIconsSizes(
+      std::move(shortcuts_menu_icons_sizes));
+
   std::vector<std::string> additional_search_terms;
   for (const std::string& additional_search_term :
        local_data.additional_search_terms()) {
diff --git a/chrome/browser/web_applications/web_app_database_unittest.cc b/chrome/browser/web_applications/web_app_database_unittest.cc
index 0e38739..890ef078 100644
--- a/chrome/browser/web_applications/web_app_database_unittest.cc
+++ b/chrome/browser/web_applications/web_app_database_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/test/bind_test_util.h"
 #include "base/time/time.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
@@ -33,6 +34,12 @@
 
 namespace web_app {
 
+namespace {
+
+const int kIconSize = 64;
+
+}  // namespace
+
 class WebAppDatabaseTest : public WebAppTest {
  public:
   void SetUp() override {
@@ -89,6 +96,43 @@
     return protocol_handlers;
   }
 
+  static std::vector<WebApplicationShortcutsMenuItemInfo> CreateShortcutInfos(
+      const std::string& base_url,
+      int suffix) {
+    std::vector<WebApplicationShortcutsMenuItemInfo> shortcut_infos;
+    for (unsigned int i = 0; i < 3; ++i) {
+      std::string suffix_str =
+          base::NumberToString(suffix) + base::NumberToString(i);
+      WebApplicationShortcutsMenuItemInfo shortcut_info;
+      shortcut_info.url = GURL(base_url + "/shortcut" + suffix_str);
+      shortcut_info.name = base::UTF8ToUTF16("shortcut" + suffix_str);
+      for (unsigned int j = 0; j < i; ++j) {
+        std::string icon_suffix_str = suffix_str + base::NumberToString(j);
+        WebApplicationShortcutsMenuItemInfo::Icon shortcut_icon;
+        shortcut_icon.url =
+            GURL(base_url + "/shortcuts/icon" + icon_suffix_str);
+        shortcut_icon.square_size_px = kIconSize * (i + j);
+        shortcut_info.shortcut_icon_infos.emplace_back(
+            std::move(shortcut_icon));
+      }
+      shortcut_infos.emplace_back(std::move(shortcut_info));
+    }
+    return shortcut_infos;
+  }
+
+  static std::vector<std::vector<SquareSizePx>>
+  CreateDownloadedShortcutsMenuIconsSizes() {
+    std::vector<std::vector<SquareSizePx>> results;
+    for (unsigned int i = 0; i < 3; ++i) {
+      std::vector<SquareSizePx> result;
+      for (unsigned int j = 0; j < i; ++j) {
+        result.emplace_back(kIconSize * (i + j));
+      }
+      results.emplace_back(std::move(result));
+    }
+    return results;
+  }
+
   static std::unique_ptr<WebApp> CreateWebApp(const std::string& base_url,
                                               int suffix) {
     const auto launch_url = base_url + base::NumberToString(suffix);
@@ -161,6 +205,10 @@
     }
     app->SetAdditionalSearchTerms(std::move(additional_search_terms));
 
+    app->SetShortcutInfos(CreateShortcutInfos(base_url, suffix));
+    app->SetDownloadedShortcutsMenuIconsSizes(
+        CreateDownloadedShortcutsMenuIconsSizes());
+
     if (IsChromeOs()) {
       auto chromeos_data = base::make_optional<WebAppChromeOsData>();
       chromeos_data->show_in_launcher = suffix & 0b0001;
@@ -375,6 +423,8 @@
   EXPECT_TRUE(app->protocol_handlers().empty());
   EXPECT_TRUE(app->last_launch_time().is_null());
   EXPECT_TRUE(app->install_time().is_null());
+  EXPECT_TRUE(app->shortcut_infos().empty());
+  EXPECT_TRUE(app->downloaded_shortcuts_menu_icons_sizes().empty());
   controller().RegisterApp(std::move(app));
 
   Registry registry = database_factory().ReadRegistry();
@@ -423,6 +473,8 @@
   EXPECT_TRUE(app_copy->file_handlers().empty());
   EXPECT_TRUE(app_copy->additional_search_terms().empty());
   EXPECT_TRUE(app_copy->protocol_handlers().empty());
+  EXPECT_TRUE(app_copy->shortcut_infos().empty());
+  EXPECT_TRUE(app_copy->downloaded_shortcuts_menu_icons_sizes().empty());
 }
 
 TEST_F(WebAppDatabaseTest, WebAppWithManyIcons) {
diff --git a/chrome/browser/web_applications/web_app_migration_manager.cc b/chrome/browser/web_applications/web_app_migration_manager.cc
index 9b67a70..81771ae 100644
--- a/chrome/browser/web_applications/web_app_migration_manager.cc
+++ b/chrome/browser/web_applications/web_app_migration_manager.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/threading/sequenced_task_runner_handle.h"
@@ -23,6 +24,7 @@
 #include "chrome/browser/web_applications/web_app_database_factory.h"
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
+#include "chrome/common/chrome_features.h"
 #include "components/services/app_service/public/cpp/file_handler.h"
 #include "components/sync/model/metadata_batch.h"
 #include "components/sync/model/metadata_change_list.h"
@@ -119,18 +121,41 @@
     MigrateNextBookmarkAppIcons();
     return;
   }
-  // TODO(https://crbug.com/1069316): Support jump lists migration here: Convert
-  // old extension's representation to new web app representation (project BMO).
+
   web_app_icon_manager_->WriteData(
       app_id, std::move(icon_bitmaps),
       base::BindOnce(&WebAppMigrationManager::OnWebAppIconsWritten,
+                     weak_ptr_factory_.GetWeakPtr(), app_id));
+}
+
+void WebAppMigrationManager::OnWebAppIconsWritten(const AppId& app_id,
+                                                  bool success) {
+  if (!success)
+    DLOG(ERROR) << "Write web app icons failed.";
+  if (base::FeatureList::IsEnabled(
+          features::kDesktopPWAsAppIconShortcutsMenu)) {
+    bookmark_app_icon_manager_.ReadAllShortcutsMenuIcons(
+        app_id,
+        base::BindOnce(
+            &WebAppMigrationManager::OnBookmarkAppShortcutsMenuIconsRead,
+            weak_ptr_factory_.GetWeakPtr(), app_id));
+  } else {
+    MigrateNextBookmarkAppIcons();
+  }
+}
+
+void WebAppMigrationManager::OnBookmarkAppShortcutsMenuIconsRead(
+    const AppId& app_id,
+    ShortcutsMenuIconsBitmaps shortcuts_menu_icons_bitmaps) {
+  web_app_icon_manager_->WriteShortcutsMenuIconsData(
+      app_id, std::move(shortcuts_menu_icons_bitmaps),
+      base::BindOnce(&WebAppMigrationManager::OnWebAppShortcutsMenuIconsWritten,
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
-void WebAppMigrationManager::OnWebAppIconsWritten(bool success) {
+void WebAppMigrationManager::OnWebAppShortcutsMenuIconsWritten(bool success) {
   if (!success)
-    DLOG(ERROR) << "Write web app icons failed.";
-
+    DLOG(ERROR) << "Write web app shortcuts menu icons failed.";
   MigrateNextBookmarkAppIcons();
 }
 
@@ -213,6 +238,15 @@
   web_app->SetDownloadedIconSizes(
       bookmark_app_registrar_.GetAppDownloadedIconSizes(app_id));
 
+  if (base::FeatureList::IsEnabled(
+          features::kDesktopPWAsAppIconShortcutsMenu)) {
+    web_app->SetShortcutInfos(
+        bookmark_app_registrar_.GetAppShortcutInfos(app_id));
+    web_app->SetDownloadedShortcutsMenuIconsSizes(
+        bookmark_app_registrar_.GetAppDownloadedShortcutsMenuIconsSizes(
+            app_id));
+  }
+
   web_app->SetUserPageOrdinal(
       bookmark_app_registrar_.GetUserPageOrdinal(app_id));
   web_app->SetUserLaunchOrdinal(
diff --git a/chrome/browser/web_applications/web_app_migration_manager.h b/chrome/browser/web_applications/web_app_migration_manager.h
index 83e73a0..83ab8a86 100644
--- a/chrome/browser/web_applications/web_app_migration_manager.h
+++ b/chrome/browser/web_applications/web_app_migration_manager.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_MIGRATION_MANAGER_H_
 #define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_MIGRATION_MANAGER_H_
 
+#include <map>
 #include <memory>
 #include <vector>
 
@@ -54,7 +55,11 @@
   void MigrateNextBookmarkAppIcons();
   void OnBookmarkAppIconsRead(const AppId& app_id,
                               std::map<SquareSizePx, SkBitmap> icon_bitmaps);
-  void OnWebAppIconsWritten(bool success);
+  void OnWebAppIconsWritten(const AppId& app_id, bool success);
+  void OnBookmarkAppShortcutsMenuIconsRead(
+      const AppId& app_id,
+      ShortcutsMenuIconsBitmaps shortcuts_menu_icons_bitmaps);
+  void OnWebAppShortcutsMenuIconsWritten(bool success);
 
   void MigrateBookmarkAppInstallSource(const AppId& app_id, WebApp* web_app);
   bool CanMigrateBookmarkApp(const AppId& app_id) const;
diff --git a/chrome/browser/web_applications/web_app_migration_manager_browsertest.cc b/chrome/browser/web_applications/web_app_migration_manager_browsertest.cc
index 5323bda..13f521e 100644
--- a/chrome/browser/web_applications/web_app_migration_manager_browsertest.cc
+++ b/chrome/browser/web_applications/web_app_migration_manager_browsertest.cc
@@ -64,6 +64,13 @@
 constexpr char kHiddenAppStartUrl[] =
     "https://www.google.com/chromebook/whatsnew/embedded/";
 
+constexpr char kManifestWithShortcutsMenuInstallUrl[] =
+    "https://example.org/manifest_test_page.html"
+    "?manifest=manifest_with_shortcuts.json";
+
+constexpr char kManifestWithShortcutsMenuStartUrl[] =
+    "https://example.org/start";
+
 // Performs blocking IO operations.
 base::FilePath GetDataFilePath(const base::FilePath& relative_path,
                                bool* path_exists) {
@@ -345,4 +352,105 @@
 // install source to cover
 // WebAppMigrationManager::MigrateBookmarkAppInstallSource() logic.
 
+class WebAppMigrationManagerBrowserTestWithShortcutsMenu
+    : public WebAppMigrationManagerBrowserTest {
+ public:
+  WebAppMigrationManagerBrowserTestWithShortcutsMenu() {
+    scoped_feature_list_.InitAndEnableFeature(
+        features::kDesktopPWAsAppIconShortcutsMenu);
+  }
+
+  void ReadAndVerifyDownloadedShortcutsMenuIcons(
+      const AppId& app_id,
+      std::vector<std::vector<SquareSizePx>> shortcuts_menu_icons_sizes) {
+    EXPECT_EQ(
+        provider().registrar().GetAppDownloadedShortcutsMenuIconsSizes(app_id),
+        shortcuts_menu_icons_sizes);
+
+    base::RunLoop run_loop;
+    provider().icon_manager().ReadAllShortcutsMenuIcons(
+        app_id,
+        base::BindLambdaForTesting(
+            [&](ShortcutsMenuIconsBitmaps shortcuts_menu_icons_bitmaps) {
+              EXPECT_EQ(2u, shortcuts_menu_icons_bitmaps.size());
+              for (size_t i = 0; i < shortcuts_menu_icons_bitmaps.size(); ++i) {
+                EXPECT_EQ(shortcuts_menu_icons_sizes[i].size(),
+                          shortcuts_menu_icons_bitmaps[i].size());
+                const std::vector<SquareSizePx>& icon_sizes =
+                    shortcuts_menu_icons_sizes[i];
+                const std::map<SquareSizePx, SkBitmap>& icon_maps =
+                    shortcuts_menu_icons_bitmaps[i];
+                for (const auto& icon_map : icon_maps) {
+                  const SquareSizePx& size_px = icon_map.first;
+                  EXPECT_TRUE(base::Contains(icon_sizes, size_px));
+
+                  const SkBitmap& bitmap = icon_map.second;
+                  EXPECT_FALSE(bitmap.empty());
+                  EXPECT_EQ(size_px, bitmap.width());
+                  EXPECT_EQ(size_px, bitmap.height());
+                }
+              }
+              run_loop.Quit();
+            }));
+    run_loop.Run();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(WebAppMigrationManagerBrowserTestWithShortcutsMenu,
+                       PRE_DatabaseMigration_ManifestWithShortcutsMenu) {
+  ui_test_utils::NavigateToURL(browser(),
+                               GURL{kManifestWithShortcutsMenuInstallUrl});
+  AppId app_id = InstallWebAppAsUserViaOmnibox();
+  EXPECT_EQ(GenerateAppIdFromURL(GURL{kManifestWithShortcutsMenuStartUrl}),
+            app_id);
+
+  EXPECT_TRUE(provider().registrar().AsBookmarkAppRegistrar());
+  EXPECT_FALSE(provider().registrar().AsWebAppRegistrar());
+
+  EXPECT_TRUE(provider().registrar().IsInstalled(app_id));
+
+  std::vector<WebApplicationShortcutsMenuItemInfo> shortcut_infos =
+      provider().registrar().GetAppShortcutInfos(app_id);
+  EXPECT_EQ(shortcut_infos.size(), 2u);
+  EXPECT_EQ(shortcut_infos[0].name, base::UTF8ToUTF16("shortcut1"));
+  EXPECT_EQ(shortcut_infos[0].shortcut_icon_infos.size(), 1u);
+  EXPECT_EQ(shortcut_infos[1].name, base::UTF8ToUTF16("shortcut2"));
+  EXPECT_EQ(shortcut_infos[1].shortcut_icon_infos.size(), 2u);
+
+  const std::vector<std::vector<SquareSizePx>> shortcuts_menu_icons_sizes = {
+      {48}, {96, 144}};
+  ReadAndVerifyDownloadedShortcutsMenuIcons(app_id, shortcuts_menu_icons_sizes);
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppMigrationManagerBrowserTestWithShortcutsMenu,
+                       DatabaseMigration_ManifestWithShortcutsMenu) {
+  AwaitRegistryReady();
+
+  AppId app_id = GenerateAppIdFromURL(GURL{kManifestWithShortcutsMenuStartUrl});
+  EXPECT_TRUE(provider().registrar().IsInstalled(app_id));
+
+  EXPECT_FALSE(provider().registrar().AsBookmarkAppRegistrar());
+  WebAppRegistrar* registrar = provider().registrar().AsWebAppRegistrar();
+  ASSERT_TRUE(registrar);
+
+  const WebApp* web_app = registrar->GetAppById(app_id);
+  ASSERT_TRUE(web_app);
+
+  EXPECT_EQ("Manifest test app with Shortcuts", web_app->name());
+  EXPECT_EQ(DisplayMode::kStandalone, web_app->display_mode());
+
+  EXPECT_EQ(web_app->shortcut_infos().size(), 2u);
+  EXPECT_EQ(web_app->shortcut_infos()[0].name, base::UTF8ToUTF16("shortcut1"));
+  EXPECT_EQ(web_app->shortcut_infos()[0].shortcut_icon_infos.size(), 1u);
+  EXPECT_EQ(web_app->shortcut_infos()[1].name, base::UTF8ToUTF16("shortcut2"));
+  EXPECT_EQ(web_app->shortcut_infos()[1].shortcut_icon_infos.size(), 2u);
+
+  const std::vector<std::vector<SquareSizePx>> shortcuts_menu_icons_sizes = {
+      {48}, {96, 144}};
+  ReadAndVerifyDownloadedShortcutsMenuIcons(app_id, shortcuts_menu_icons_sizes);
+}
+
 }  // namespace web_app
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index f87b79d..d3979a6 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1593475028-63728bbaf9d72e013a403087ba2956d3e5f5a26b.profdata
+chrome-mac-master-1593518062-9a8bcf79d9703750826ab2cdd2c19e0799442665.profdata
diff --git a/chrome/common/common_message_generator.h b/chrome/common/common_message_generator.h
index 8e1f8513..a7b3d79 100644
--- a/chrome/common/common_message_generator.h
+++ b/chrome/common/common_message_generator.h
@@ -6,12 +6,6 @@
 
 #include "chrome/common/search/instant_mojom_traits.h"
 #include "services/network/public/cpp/p2p_param_traits.h"
-#undef COMPONENTS_PRERENDER_COMMON_PRERENDER_MESSAGES_H_
-#include "components/prerender/common/prerender_messages.h"
-#ifndef COMPONENTS_PRERENDER_COMMON_PRERENDER_MESSAGES_H_
-#error \
-    "Failed to include header components/prerender/common/prerender_messages.h"
-#endif
 #undef CHROME_COMMON_RENDER_MESSAGES_H_
 #include "chrome/common/render_messages.h"
 #ifndef CHROME_COMMON_RENDER_MESSAGES_H_
diff --git a/chrome/common/conflicts/module_watcher_win_unittest.cc b/chrome/common/conflicts/module_watcher_win_unittest.cc
index 8de1eb13..bdc0646 100644
--- a/chrome/common/conflicts/module_watcher_win_unittest.cc
+++ b/chrome/common/conflicts/module_watcher_win_unittest.cc
@@ -58,8 +58,8 @@
   void RunUntilIdle() { task_environment_.RunUntilIdle(); }
 
   std::unique_ptr<ModuleWatcher> Create() {
-    return ModuleWatcher::Create(
-        base::Bind(&ModuleWatcherTest::OnModuleEvent, base::Unretained(this)));
+    return ModuleWatcher::Create(base::BindRepeating(
+        &ModuleWatcherTest::OnModuleEvent, base::Unretained(this)));
   }
 
   base::test::TaskEnvironment task_environment_;
diff --git a/chrome/common/prerender_url_loader_throttle.cc b/chrome/common/prerender_url_loader_throttle.cc
index 8c010275..ab30fba 100644
--- a/chrome/common/prerender_url_loader_throttle.cc
+++ b/chrome/common/prerender_url_loader_throttle.cc
@@ -24,10 +24,9 @@
 const char kPurposeHeaderValue[] = "prefetch";
 
 void CallCancelPrerenderForUnsupportedScheme(
-    mojo::PendingRemote<prerender::mojom::PrerenderCanceler> canceler,
-    const GURL& url) {
+    mojo::PendingRemote<prerender::mojom::PrerenderCanceler> canceler) {
   mojo::Remote<prerender::mojom::PrerenderCanceler>(std::move(canceler))
-      ->CancelPrerenderForUnsupportedScheme(url);
+      ->CancelPrerenderForUnsupportedScheme();
 }
 
 // Returns true if the response has a "no-store" cache control header.
@@ -96,7 +95,7 @@
     // WillRedirectRequest() and PrerenderContents::CheckURL(). See
     // http://crbug.com/673771.
     delegate_->CancelWithError(net::ERR_ABORTED);
-    CallCancelPrerenderForUnsupportedScheme(std::move(canceler_), request->url);
+    CallCancelPrerenderForUnsupportedScheme(std::move(canceler_));
     return;
   }
 
@@ -154,8 +153,7 @@
   // Abort any prerenders with requests which redirect to invalid schemes.
   if (!DoesURLHaveValidScheme(redirect_info->new_url)) {
     delegate_->CancelWithError(net::ERR_ABORTED);
-    CallCancelPrerenderForUnsupportedScheme(std::move(canceler_),
-                                            redirect_info->new_url);
+    CallCancelPrerenderForUnsupportedScheme(std::move(canceler_));
   } else if (follow_only_when_prerender_shown_header == "1" &&
              resource_type_ != blink::mojom::ResourceType::kMainFrame) {
     // Only defer redirects with the Follow-Only-When-Prerender-Shown
diff --git a/chrome/common/web_application_info.h b/chrome/common/web_application_info.h
index fdea93e..4f9111c9 100644
--- a/chrome/common/web_application_info.h
+++ b/chrome/common/web_application_info.h
@@ -140,6 +140,8 @@
   std::vector<std::string> additional_search_terms;
 
   // Set of shortcut infos populated using shortcuts specified in the manifest.
+  //
+  // TODO(https://crbug.com/1100751): Rename this to shortcuts_menu_item_infos.
   std::vector<WebApplicationShortcutsMenuItemInfo> shortcut_infos;
 
   // Vector of shortcut icon bitmaps keyed by their square size. The index of a
diff --git a/chrome/installer/mini_installer/BUILD.gn b/chrome/installer/mini_installer/BUILD.gn
index a04d7f3..571727c 100644
--- a/chrome/installer/mini_installer/BUILD.gn
+++ b/chrome/installer/mini_installer/BUILD.gn
@@ -7,6 +7,7 @@
 import("//build/config/ui.gni")
 import("//chrome/process_version_rc_template.gni")
 import("//components/nacl/features.gni")
+import("//third_party/ffmpeg/ffmpeg_options.gni")
 import("//third_party/icu/config.gni")
 import("//tools/v8_context_snapshot/v8_context_snapshot.gni")
 import("//ui/base/ui_features.gni")
@@ -192,6 +193,10 @@
       args += [ "--component_build=1" ]
     }
 
+    if (is_component_ffmpeg) {
+      args += [ "--component_ffmpeg_build=1" ]
+    }
+
     if (skip_archive_compression) {
       args += [ "--skip_archive_compression" ]
     } else {
diff --git a/chrome/installer/mini_installer/chrome.release b/chrome/installer/mini_installer/chrome.release
index f86e95ba..abfb1fa 100644
--- a/chrome/installer/mini_installer/chrome.release
+++ b/chrome/installer/mini_installer/chrome.release
@@ -65,6 +65,9 @@
 [HIDPI]
 chrome_200_percent.pak: %(VersionDir)s\
 
+[FFMPEG]
+ffmpeg.dll: %(VersionDir)s\
+
 [TOUCH]
 
 [GOOGLE_CHROME]
diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc
index 0aff91c2..971fe93 100644
--- a/chrome/renderer/chrome_render_frame_observer.cc
+++ b/chrome/renderer/chrome_render_frame_observer.cc
@@ -29,7 +29,6 @@
 #include "chrome/renderer/web_apps.h"
 #include "components/crash/core/common/crash_key.h"
 #include "components/offline_pages/buildflags/buildflags.h"
-#include "components/prerender/common/prerender_messages.h"
 #include "components/translate/content/renderer/translate_agent.h"
 #include "components/translate/core/common/translate_util.h"
 #include "components/web_cache/renderer/web_cache_impl.h"
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.cc b/chrome/renderer/plugins/chrome_plugin_placeholder.cc
index ff8e525..ae3ad0e 100644
--- a/chrome/renderer/plugins/chrome_plugin_placeholder.cc
+++ b/chrome/renderer/plugins/chrome_plugin_placeholder.cc
@@ -24,7 +24,6 @@
 #include "chrome/renderer/plugins/plugin_uma.h"
 #include "chrome/renderer/prerender/prerender_observer_list.h"
 #include "components/content_settings/renderer/content_settings_agent_impl.h"
-#include "components/prerender/common/prerender_messages.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/untrustworthy_context_menu_params.h"
diff --git a/chrome/renderer/prerender/prerender_helper.cc b/chrome/renderer/prerender/prerender_helper.cc
index 438a7f9..e1e6912 100644
--- a/chrome/renderer/prerender/prerender_helper.cc
+++ b/chrome/renderer/prerender/prerender_helper.cc
@@ -7,7 +7,6 @@
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
 #include "chrome/common/prerender_url_loader_throttle.h"
-#include "components/prerender/common/prerender_messages.h"
 #include "content/public/renderer/document_state.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_thread.h"
@@ -134,8 +133,11 @@
   DCHECK(prefetch_count_ == 0 && prefetch_finished_);
   UMA_HISTOGRAM_MEDIUM_TIMES("Prerender.NoStatePrefetchRendererParseTime",
                              parsed_time_ - start_time_);
-  // TODO(darin): Perhaps this should be a routed message (frame level).
-  content::RenderThread::Get()->Send(new PrerenderHostMsg_PrefetchFinished());
+
+  mojo::Remote<prerender::mojom::PrerenderCanceler> canceler;
+  render_frame()->GetBrowserInterfaceBroker()->GetInterface(
+      canceler.BindNewPipeAndPassReceiver());
+  canceler->CancelPrerenderForNoStatePrefetch();
 }
 
 }  // namespace prerender
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 26c3a161..6c79ff3 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4272,7 +4272,6 @@
       "../browser/ui/webui/settings/profile_info_handler_unittest.cc",
       "../browser/ui/webui/settings/recent_site_settings_helper_unittest.cc",
       "../browser/ui/webui/settings/reset_settings_handler_unittest.cc",
-      "../browser/ui/webui/settings/safe_browsing_handler_unittest.cc",
       "../browser/ui/webui/settings/safety_check_handler_unittest.cc",
       "../browser/ui/webui/settings/settings_cookies_view_handler_unittest.cc",
       "../browser/ui/webui/settings/settings_manage_profile_handler_unittest.cc",
@@ -6446,7 +6445,6 @@
       "../browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc",
       "../browser/sync/test/integration/single_client_device_info_sync_test.cc",
       "../browser/sync/test/integration/single_client_dictionary_sync_test.cc",
-      "../browser/sync/test/integration/single_client_directory_sync_test.cc",
       "../browser/sync/test/integration/single_client_extension_apps_sync_test.cc",
       "../browser/sync/test/integration/single_client_extensions_sync_test.cc",
       "../browser/sync/test/integration/single_client_history_delete_directives_sync_test.cc",
diff --git a/chrome/test/data/banners/manifest_with_shortcuts.json b/chrome/test/data/banners/manifest_with_shortcuts.json
new file mode 100644
index 0000000..4e6ad6f8
--- /dev/null
+++ b/chrome/test/data/banners/manifest_with_shortcuts.json
@@ -0,0 +1,45 @@
+{
+  "name": "Manifest test app with Shortcuts",
+  "icons": [
+    {
+      "src": "image-512px.png",
+      "sizes": "512x512",
+      "type": "image/png"
+    }
+  ],
+  "start_url": "https://example.org/start",
+  "scope": "/",
+  "display": "standalone",
+  "orientation": "landscape",
+  "shortcuts": [
+    {
+      "name": "shortcut1",
+      "short_name": "short_name1",
+      "url": "launch_url",
+      "icons": [
+        {
+          "src": "launcher-icon-1x.png",
+          "sizes": "48x48",
+          "type": "image/png"
+        }
+      ]
+    },
+    {
+      "name": "shortcut2",
+      "short_name": "short_name2",
+      "url": "launch_url",
+      "icons": [
+        {
+          "src": "launcher-icon-2x.png",
+          "sizes": "96x96",
+          "type": "image/png"
+        },
+        {
+          "src": "launcher-icon-3x.png",
+          "sizes": "144x144",
+          "type": "image/png"
+        }
+      ]
+    }
+  ]
+}
diff --git a/chrome/test/data/webrtc/webrtc_pan_tilt_zoom_test.html b/chrome/test/data/webrtc/webrtc_pan_tilt_zoom_test.html
index 8fbd9b6..d0a3f8b 100644
--- a/chrome/test/data/webrtc/webrtc_pan_tilt_zoom_test.html
+++ b/chrome/test/data/webrtc/webrtc_pan_tilt_zoom_test.html
@@ -45,23 +45,13 @@
     }
   }
 
-  async function getTrackSetting(settingName) {
-    // |videoTrack|s settings retrieval is a process kicked right after
-    // creation, we introduce a small delay to allow for those to be collected.
-    // TODO(mcasas): this shouldn't be needed, https://crbug.com/711524.
-    await waitForImageCapture;
-
+  function getTrackSetting(settingName) {
     const videoTrack = stream.getVideoTracks()[0];
     const settings = videoTrack.getSettings();
     returnToTest(settings[settingName]);
   }
 
-  async function checkConstraints(expectedConstraints) {
-    // |videoTrack|s constraints retrieval is a process kicked right after
-    // creation, we introduce a small delay to allow for those to be collected.
-    // TODO(mcasas): this shouldn't be needed, https://crbug.com/711524.
-    await waitForImageCapture;
-
+  function checkConstraints(expectedConstraints) {
     const videoTrack = stream.getVideoTracks()[0];
     const constraints = videoTrack.getConstraints();
 
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn
index 31979662..6f630ec 100644
--- a/chrome/test/data/webui/settings/BUILD.gn
+++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -188,7 +188,6 @@
 
     #":test_profile_info_browser_proxy",
     #":test_reset_browser_proxy",
-    ":test_safe_browsing_browser_proxy",
     ":test_search_engines_browser_proxy.m",
     ":test_site_settings_prefs_browser_proxy",
     ":test_sync_browser_proxy.m",
@@ -311,13 +310,6 @@
   ]
 }
 
-js_library("test_safe_browsing_browser_proxy") {
-  deps = [
-    "..:test_browser_proxy.m",
-    "//chrome/browser/resources/settings:lazy_load",
-  ]
-}
-
 js_library("search_page_test") {
   deps = [
     ":test_search_engines_browser_proxy.m",
@@ -331,7 +323,6 @@
   deps = [
     ":test_metrics_browser_proxy",
     ":test_privacy_page_browser_proxy",
-    ":test_safe_browsing_browser_proxy",
     ":test_sync_browser_proxy.m",
     "..:chai_assert",
     "..:test_util.m",
diff --git a/chrome/test/data/webui/settings/collapse_radio_button_tests.js b/chrome/test/data/webui/settings/collapse_radio_button_tests.js
index 53d9fe1..ef6db66 100644
--- a/chrome/test/data/webui/settings/collapse_radio_button_tests.js
+++ b/chrome/test/data/webui/settings/collapse_radio_button_tests.js
@@ -5,7 +5,6 @@
 // clang-format off
 import 'chrome://settings/lazy_load.js';
 
-import {CrPolicyIndicatorType} from 'chrome://resources/cr_elements/policy/cr_policy_indicator_behavior.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {isChildVisible} from 'chrome://test/test_util.m.js';
 
@@ -90,17 +89,6 @@
     assertTrue(collapse.opened);
   });
 
-  test('displayPolicyIndicator', function() {
-    assertFalse(isChildVisible(collapseRadioButton, '#policyIndicator'));
-    assertEquals(
-        collapseRadioButton.policyIndicatorType, CrPolicyIndicatorType.NONE);
-
-    collapseRadioButton.policyIndicatorType =
-        CrPolicyIndicatorType.DEVICE_POLICY;
-    flush();
-    assertTrue(isChildVisible(collapseRadioButton, '#policyIndicator'));
-  });
-
   test('respectPreferenceState', function() {
     const togglePrefValue = 'pref_value';
     collapseRadioButton.name = togglePrefValue;
@@ -136,25 +124,4 @@
     assertTrue(isChildVisible(collapseRadioButton, 'cr-policy-pref-indicator'));
     assertFalse(collapseRadioButton.disabled);
   });
-
-  test('singlePolicyIndicator', function() {
-    assertFalse(isChildVisible(collapseRadioButton, '#policyIndicator'));
-    assertFalse(
-        isChildVisible(collapseRadioButton, 'cr-policy-pref-indicator'));
-
-    collapseRadioButton.policyIndicatorType =
-        CrPolicyIndicatorType.DEVICE_POLICY;
-    flush();
-    assertTrue(isChildVisible(collapseRadioButton, '#policyIndicator'));
-    assertFalse(
-        isChildVisible(collapseRadioButton, 'cr-policy-pref-indicator'));
-
-    collapseRadioButton.pref = {
-      enforcement: chrome.settingsPrivate.Enforcement.ENFORCED,
-      controlledBy: chrome.settingsPrivate.ControlledBy.DEVICE_POLICY,
-    };
-    flush();
-    assertFalse(isChildVisible(collapseRadioButton, '#policyIndicator'));
-    assertTrue(isChildVisible(collapseRadioButton, 'cr-policy-pref-indicator'));
-  });
 });
diff --git a/chrome/test/data/webui/settings/security_page_test.js b/chrome/test/data/webui/settings/security_page_test.js
index 4e3ebbd..80ff37b 100644
--- a/chrome/test/data/webui/settings/security_page_test.js
+++ b/chrome/test/data/webui/settings/security_page_test.js
@@ -3,11 +3,10 @@
 // found in the LICENSE file.
 
 // clang-format off
-import {CrPolicyIndicatorType} from 'chrome://resources/cr_elements/policy/cr_policy_indicator_behavior.m.js';
 import {isMac, isWindows} from 'chrome://resources/js/cr.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {SafeBrowsingBrowserProxyImpl} from 'chrome://settings/lazy_load.js';
+import {SafeBrowsingSetting} from 'chrome://settings/lazy_load.js';
 import {MetricsBrowserProxyImpl, PrivacyElementInteractions,PrivacyPageBrowserProxyImpl, Router, routes, SecureDnsMode, SyncBrowserProxyImpl} from 'chrome://settings/settings.js';
 
 import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js';
@@ -15,7 +14,6 @@
 
 import {TestMetricsBrowserProxy} from './test_metrics_browser_proxy.js';
 import {TestPrivacyPageBrowserProxy} from './test_privacy_page_browser_proxy.js';
-import {TestSafeBrowsingBrowserProxy} from './test_safe_browsing_browser_proxy.js';
 import {TestSyncBrowserProxy} from './test_sync_browser_proxy.m.js';
 
 // clang-format on
@@ -30,9 +28,6 @@
   /** @type {!TestPrivacyPageBrowserProxy} */
   let testPrivacyBrowserProxy;
 
-  /** @type {!TestSafeBrowsingBrowserProxy} */
-  let testSafeBrowsingBrowserProxy;
-
   /** @type {!SettingsSecurityPageElement} */
   let page;
 
@@ -49,13 +44,11 @@
     PrivacyPageBrowserProxyImpl.instance_ = testPrivacyBrowserProxy;
     syncBrowserProxy = new TestSyncBrowserProxy();
     SyncBrowserProxyImpl.instance_ = syncBrowserProxy;
-    testSafeBrowsingBrowserProxy = new TestSafeBrowsingBrowserProxy();
-    SafeBrowsingBrowserProxyImpl.instance_ = testSafeBrowsingBrowserProxy;
     document.body.innerHTML = '';
     page = /** @type {!SettingsSecurityPageElement} */ (
         document.createElement('settings-security-page'));
     page.prefs = {
-      profile: {password_manager_leak_detection: {value: true}},
+      profile: {password_manager_leak_detection: {value: false}},
       signin: {
         allowed_on_next_startup:
             {type: chrome.settingsPrivate.PrefType.BOOLEAN, value: true}
@@ -65,6 +58,12 @@
         scout_reporting_enabled: {value: true},
         enhanced: {value: false}
       },
+      generated: {
+        safe_browsing: {
+          type: chrome.settingsPrivate.PrefType.NUMBER,
+          value: SafeBrowsingSetting.STANDARD,
+        },
+      },
       dns_over_https:
           {mode: {value: SecureDnsMode.AUTOMATIC}, templates: {value: ''}},
     };
@@ -107,34 +106,34 @@
 
   test('safeBrowsingReportingToggle', function() {
     page.$$('#safeBrowsingStandard').click();
+    assertEquals(
+        SafeBrowsingSetting.STANDARD, page.prefs.generated.safe_browsing.value);
+
     const safeBrowsingReportingToggle = page.$$('#safeBrowsingReportingToggle');
-    assertTrue(
-        page.prefs.safebrowsing.enabled.value &&
-        !page.prefs.safebrowsing.enhanced.value);
     assertFalse(safeBrowsingReportingToggle.disabled);
     assertTrue(safeBrowsingReportingToggle.checked);
+
     // This could also be set to disabled, anything other than standard.
     page.$$('#safeBrowsingEnhanced').click();
+    assertEquals(
+        SafeBrowsingSetting.ENHANCED, page.prefs.generated.safe_browsing.value);
     flush();
-
-    assertFalse(
-        page.prefs.safebrowsing.enabled.value &&
-        !page.prefs.safebrowsing.enhanced.value);
     assertTrue(safeBrowsingReportingToggle.disabled);
     assertTrue(safeBrowsingReportingToggle.checked);
     assertTrue(page.prefs.safebrowsing.scout_reporting_enabled.value);
-    page.$$('#safeBrowsingStandard').click();
-    flush();
 
-    assertTrue(
-        page.prefs.safebrowsing.enabled.value &&
-        !page.prefs.safebrowsing.enhanced.value);
+    page.$$('#safeBrowsingStandard').click();
+    assertEquals(
+        SafeBrowsingSetting.STANDARD, page.prefs.generated.safe_browsing.value);
+    flush();
     assertFalse(safeBrowsingReportingToggle.disabled);
     assertTrue(safeBrowsingReportingToggle.checked);
   });
 
   test('DisableSafebrowsingDialog_Confirm', async function() {
     page.$$('#safeBrowsingStandard').click();
+    assertEquals(
+        SafeBrowsingSetting.STANDARD, page.prefs.generated.safe_browsing.value);
     flush();
 
     page.$$('#safeBrowsingDisabled').click();
@@ -153,13 +152,14 @@
     assertFalse(page.$$('#safeBrowsingEnhanced').checked);
     assertFalse(page.$$('#safeBrowsingStandard').checked);
     assertTrue(page.$$('#safeBrowsingDisabled').checked);
-
-    assertFalse(page.prefs.safebrowsing.enabled.value);
-    assertFalse(page.prefs.safebrowsing.enhanced.value);
+    assertEquals(
+        SafeBrowsingSetting.DISABLED, page.prefs.generated.safe_browsing.value);
   });
 
   test('DisableSafebrowsingDialog_CancelFromEnhanced', async function() {
     page.$$('#safeBrowsingEnhanced').click();
+    assertEquals(
+        SafeBrowsingSetting.ENHANCED, page.prefs.generated.safe_browsing.value);
     flush();
 
     page.$$('#safeBrowsingDisabled').click();
@@ -178,13 +178,14 @@
     assertTrue(page.$$('#safeBrowsingEnhanced').checked);
     assertFalse(page.$$('#safeBrowsingStandard').checked);
     assertFalse(page.$$('#safeBrowsingDisabled').checked);
-
-    assertTrue(page.prefs.safebrowsing.enabled.value);
-    assertTrue(page.prefs.safebrowsing.enhanced.value);
+    assertEquals(
+        SafeBrowsingSetting.ENHANCED, page.prefs.generated.safe_browsing.value);
   });
 
   test('DisableSafebrowsingDialog_CancelFromStandard', async function() {
     page.$$('#safeBrowsingStandard').click();
+    assertEquals(
+        SafeBrowsingSetting.STANDARD, page.prefs.generated.safe_browsing.value);
     flush();
 
     page.$$('#safeBrowsingDisabled').click();
@@ -203,9 +204,8 @@
     assertFalse(page.$$('#safeBrowsingEnhanced').checked);
     assertTrue(page.$$('#safeBrowsingStandard').checked);
     assertFalse(page.$$('#safeBrowsingDisabled').checked);
-
-    assertTrue(page.prefs.safebrowsing.enabled.value);
-    assertFalse(page.prefs.safebrowsing.enhanced.value);
+    assertEquals(
+        SafeBrowsingSetting.STANDARD, page.prefs.generated.safe_browsing.value);
   });
 
   test('noControlSafeBrowsingReportingInEnhanced', function() {
@@ -301,98 +301,6 @@
     assertTrue(
         page.prefs.profile.password_manager_leak_detection.value === previous);
   });
-
-  test('SafeBrowsingRadio_PreferenceUpdate', function() {
-    const enhancedRadio = page.$$('#safeBrowsingEnhanced');
-    const standardRadio = page.$$('#safeBrowsingStandard');
-    const disabledRadio = page.$$('#safeBrowsingDisabled');
-
-    // Set an enhanced protection preference state and ensure the radio buttons
-    // correctly reflect this.
-    page.set('prefs.safebrowsing.enabled.value', true);
-    page.set('prefs.safebrowsing.enhanced.value', true);
-    flush();
-    assertTrue(enhancedRadio.checked);
-    assertFalse(standardRadio.checked);
-    assertFalse(disabledRadio.checked);
-
-    // As above but for an enabled protection state.
-    page.set('prefs.safebrowsing.enabled.value', true);
-    page.set('prefs.safebrowsing.enhanced.value', false);
-    flush();
-    assertFalse(enhancedRadio.checked);
-    assertTrue(standardRadio.checked);
-    assertFalse(disabledRadio.checked);
-
-    // As above but for a safebrowsing disabled state.
-    page.set('prefs.safebrowsing.enabled.value', false);
-    page.set('prefs.safebrowsing.enhanced.value', false);
-    flush();
-    assertFalse(enhancedRadio.checked);
-    assertFalse(standardRadio.checked);
-    assertTrue(disabledRadio.checked);
-  });
-
-  test('SafeBrowsingRadio_ManagedState', async function() {
-    const enhancedRadio = page.$$('#safeBrowsingEnhanced');
-    const standardRadio = page.$$('#safeBrowsingStandard');
-    const disabledRadio = page.$$('#safeBrowsingDisabled');
-
-    const managedRadioState = {
-      enhanced:
-          {disabled: true, indicator: CrPolicyIndicatorType.DEVICE_POLICY},
-      standard:
-          {disabled: true, indicator: CrPolicyIndicatorType.DEVICE_POLICY},
-      disabled:
-          {disabled: true, indicator: CrPolicyIndicatorType.DEVICE_POLICY},
-    };
-
-    // Make sure the element has requested the managed state from its init.
-    await testSafeBrowsingBrowserProxy.whenCalled(
-        'getSafeBrowsingRadioManagedState');
-    testSafeBrowsingBrowserProxy.reset();
-
-    testSafeBrowsingBrowserProxy.setSafeBrowsingRadioManagedState(
-        managedRadioState);
-    // Change an arbitrary Safe Browsing pref to trigger managed state update.
-    page.set('prefs.safebrowsing.enabled.value', false);
-    await testSafeBrowsingBrowserProxy.whenCalled(
-        'getSafeBrowsingRadioManagedState');
-    testSafeBrowsingBrowserProxy.reset();
-    flush();
-
-    assertTrue(enhancedRadio.disabled);
-    assertEquals(
-        enhancedRadio.policyIndicatorType, CrPolicyIndicatorType.DEVICE_POLICY);
-    assertTrue(standardRadio.disabled);
-    assertEquals(
-        standardRadio.policyIndicatorType, CrPolicyIndicatorType.DEVICE_POLICY);
-    assertTrue(disabledRadio.disabled);
-    assertEquals(
-        disabledRadio.policyIndicatorType, CrPolicyIndicatorType.DEVICE_POLICY);
-
-    // Ensure reverting to an unmanaged state is correctly handled.
-    const unmanagedRadioState = {
-      enhanced: {disabled: false, indicator: CrPolicyIndicatorType.NONE},
-      standard: {disabled: false, indicator: CrPolicyIndicatorType.NONE},
-      disabled: {disabled: false, indicator: CrPolicyIndicatorType.NONE},
-    };
-    testSafeBrowsingBrowserProxy.setSafeBrowsingRadioManagedState(
-        unmanagedRadioState);
-    // Change an arbitrary Safe Browsing pref to trigger managed state update.
-    page.set('prefs.safebrowsing.enabled.value', true);
-    await testSafeBrowsingBrowserProxy.whenCalled(
-        'getSafeBrowsingRadioManagedState');
-    testSafeBrowsingBrowserProxy.reset();
-    flush();
-
-    assertFalse(enhancedRadio.disabled);
-    assertEquals(enhancedRadio.policyIndicatorType, CrPolicyIndicatorType.NONE);
-    assertFalse(standardRadio.disabled);
-    assertEquals(standardRadio.policyIndicatorType, CrPolicyIndicatorType.NONE);
-    assertFalse(disabledRadio.disabled);
-    assertEquals(disabledRadio.policyIndicatorType, CrPolicyIndicatorType.NONE);
-  });
 });
 
 
@@ -400,9 +308,6 @@
   /** @type {!SettingsSecurityPageElement} */
   let page;
 
-  /** @type {!TestSafeBrowsingBrowserProxy} */
-  let testSafeBrowsingBrowserProxy;
-
   suiteSetup(function() {
     loadTimeData.overrideValues({
       safeBrowsingEnhancedEnabled: false,
@@ -410,8 +315,6 @@
   });
 
   setup(function() {
-    testSafeBrowsingBrowserProxy = new TestSafeBrowsingBrowserProxy();
-    SafeBrowsingBrowserProxyImpl.instance_ = testSafeBrowsingBrowserProxy;
     document.body.innerHTML = '';
     page = /** @type {!SettingsSecurityPageElement} */ (
         document.createElement('settings-security-page'));
@@ -426,6 +329,12 @@
         scout_reporting_enabled: {value: true},
         enhanced: {value: false}
       },
+      generated: {
+        safe_browsing: {
+          type: chrome.settingsPrivate.PrefType.NUMBER,
+          value: SafeBrowsingSetting.STANDARD,
+        },
+      },
       dns_over_https:
           {mode: {value: SecureDnsMode.AUTOMATIC}, templates: {value: ''}},
     };
@@ -440,9 +349,4 @@
   test('enhancedHiddenWhenDisbled', function() {
     assertTrue(page.$$('#safeBrowsingEnhanced').hidden);
   });
-
-  test('validateSafeBrowsingEnhanced', function() {
-    return testSafeBrowsingBrowserProxy.whenCalled(
-        'validateSafeBrowsingEnhanced');
-  });
 });
diff --git a/chrome/test/data/webui/settings/test_safe_browsing_browser_proxy.js b/chrome/test/data/webui/settings/test_safe_browsing_browser_proxy.js
deleted file mode 100644
index 632bd881..0000000
--- a/chrome/test/data/webui/settings/test_safe_browsing_browser_proxy.js
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2020 The Chromium 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 {SafeBrowsingBrowserProxy, SafeBrowsingRadioManagedState} from 'chrome://settings/lazy_load.js';
-
-import {TestBrowserProxy} from '../test_browser_proxy.m.js';
-
-/** @implements {SafeBrowsingBrowserProxy} */
-export class TestSafeBrowsingBrowserProxy extends TestBrowserProxy {
-  constructor() {
-    super([
-      'getSafeBrowsingRadioManagedState',
-      'validateSafeBrowsingEnhanced',
-    ]);
-
-    /** @type {!SafeBrowsingRadioManagedState} */
-    this.managedRadioState_;
-  }
-
-  /** @param {!SafeBrowsingRadioManagedState} state */
-  setSafeBrowsingRadioManagedState(state) {
-    this.managedRadioState_ = state;
-  }
-
-  /** @override */
-  getSafeBrowsingRadioManagedState() {
-    this.methodCalled('getSafeBrowsingRadioManagedState');
-    return Promise.resolve(this.managedRadioState_);
-  }
-
-  /** @override */
-  validateSafeBrowsingEnhanced() {
-    this.methodCalled('validateSafeBrowsingEnhanced');
-  }
-}
diff --git a/chrome/tools/build/win/create_installer_archive.py b/chrome/tools/build/win/create_installer_archive.py
index ffbf9ec..818e836 100755
--- a/chrome/tools/build/win/create_installer_archive.py
+++ b/chrome/tools/build/win/create_installer_archive.py
@@ -94,7 +94,8 @@
 
 
 def CopyAllFilesToStagingDir(config, distribution, staging_dir, build_dir,
-                             enable_hidpi, include_snapshotblob, verbose):
+                             enable_hidpi, include_snapshotblob,
+                             component_build, component_ffmpeg_build, verbose):
   """Copies the files required for installer archive.
   Copies all common files required for various distributions of Chromium and
   also files for the specific Chromium build specified by distribution.
@@ -117,6 +118,10 @@
     CopySectionFilesToStagingDir(config, 'SNAPSHOTBLOB', staging_dir, build_dir,
                                  verbose)
 
+  if component_build != '1' and component_ffmpeg_build == '1':
+    CopySectionFilesToStagingDir(config, 'FFMPEG', staging_dir, build_dir,
+                                 verbose)
+
 # The 'SafeConfigParser' makes all strings lowercase - which works fine on
 # a cases-insensitive NTFS partition, but makes no sense when trying to build
 # mini_installer.exe on a linux box. This function can be used to make glob
@@ -538,6 +543,8 @@
                            staging_dir, options.build_dir,
                            options.enable_hidpi,
                            options.include_snapshotblob,
+                           options.component_build,
+                           options.component_ffmpeg_build,
                            options.verbose)
 
   if options.component_build == '1':
@@ -603,6 +610,8 @@
       help='Whether to include the V8 snapshot blob.')
   parser.add_option('--component_build', default='0',
       help='Whether this archive is packaging a component build.')
+  parser.add_option('--component_ffmpeg_build', default='0',
+      help='Whether this archive is packaging with ffmpeg component build.')
   parser.add_option('--skip_archive_compression',
       action='store_true', default=False,
       help='This will turn off compression of chrome.7z into chrome.packed.7z '
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index b905166..56471b7 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-13315.0.0
\ No newline at end of file
+13316.0.0
\ No newline at end of file
diff --git a/chromeos/components/camera_app_ui/resources/src/js/background.js b/chromeos/components/camera_app_ui/resources/src/js/background.js
index 7420cc8..b73f376 100644
--- a/chromeos/components/camera_app_ui/resources/src/js/background.js
+++ b/chromeos/components/camera_app_ui/resources/src/js/background.js
@@ -10,6 +10,7 @@
 // eslint-disable-next-line no-unused-vars
 import {TestingErrorCallback} from './error.js';
 import {Intent} from './intent.js';
+import {initMetrics, setMetricsEnabled} from './metrics.js';
 import {PerfEvent, PerfLogger} from './perf.js';
 
 /**
@@ -156,8 +157,14 @@
 
   /**
    * Creates app window and launches app.
+   * @return {!Promise}
    */
-  launch() {
+  async launch() {
+    // Disables the metrics sending if it is testing window.
+    if (this.testingCallbacks_ !== null) {
+      await setMetricsEnabled(false);
+    }
+
     this.state_ = WindowState.LAUNCHING;
 
     // The height will be later calculated to match video aspect ratio once the
@@ -319,6 +326,10 @@
      * @type {?Intent}
      */
     this.pendingIntent_ = null;
+
+    // By default, we enable the metrics sending on background page and will
+    // turn it off when launching testing windows.
+    initMetrics();
   }
 
   /**
diff --git a/chromeos/components/camera_app_ui/resources/src/js/main.js b/chromeos/components/camera_app_ui/resources/src/js/main.js
index 45e1639..b3ea4b0 100644
--- a/chromeos/components/camera_app_ui/resources/src/js/main.js
+++ b/chromeos/components/camera_app_ui/resources/src/js/main.js
@@ -269,7 +269,11 @@
   const /** !BackgroundOps */ bgOps = window['backgroundOps'];
 
   const testErrorCallback = bgOps.getTestingErrorCallback();
-  metrics.initMetrics(testErrorCallback !== null);
+  metrics.initMetrics();
+  if (testErrorCallback !== null) {
+    metrics.setMetricsEnabled(false);
+  }
+
   // TODO(crbug/1082585): Initializes it before any other javascript loaded.
   error.initialize(testErrorCallback);
 
diff --git a/chromeos/components/camera_app_ui/resources/src/js/metrics.js b/chromeos/components/camera_app_ui/resources/src/js/metrics.js
index fb17ed1..44a548b 100644
--- a/chromeos/components/camera_app_ui/resources/src/js/metrics.js
+++ b/chromeos/components/camera_app_ui/resources/src/js/metrics.js
@@ -17,6 +17,12 @@
 } from './type.js';
 
 /**
+ * The tracker ID of the GA metrics.
+ * @type {string}
+ */
+const GA_ID = 'UA-134822711-1';
+
+/**
  * @type {?Map<number, Object>}
  */
 let baseDimen = null;
@@ -46,17 +52,25 @@
 }
 
 /**
- * Initializes metrics with parameters.
- * @param {!boolean} isTesting Whether is collecting logs for running
- *     testing.
+ * Set if the metrics is enabled. Note that the metrics will only be sent if it
+ * is enabled AND the logging consent option is enabled in OS settings.
+ * @param {boolean} enabled True if the metrics is enabled.
  */
-export function initMetrics(isTesting) {
-  ready = (async () => {
-    const GA_ID = 'UA-134822711-1';
-    const canSendMetrics =
-        !isTesting && await browserProxy.isCrashReportingEnabled();
-    window[`ga-disable-${GA_ID}`] = !canSendMetrics;
+export function setMetricsEnabled(enabled) {
+  assert(ready !== null);
 
+  ready.then(async() => {
+    // This value reflects the logging constent option in OS settings.
+    const canSendMetrics = await browserProxy.isCrashReportingEnabled();
+    window[`ga-disable-${GA_ID}`] = !enabled || !canSendMetrics;
+  });
+}
+
+/**
+ * Initializes metrics with parameters.
+ */
+export function initMetrics() {
+  ready = (async () => {
     browserProxy.addDummyHistoryIfNotAvailable();
 
     // GA initialization function which is mostly copied from
@@ -104,6 +118,11 @@
     // check here since we are "chrome-extension://".
     window.ga('set', 'checkProtocolTask', null);
   })();
+
+  ready.then(async() => {
+    // The metrics is default enabled.
+    await setMetricsEnabled(true);
+  });
 }
 
 /**
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera_intent.js b/chromeos/components/camera_app_ui/resources/src/js/views/camera_intent.js
index ce6eddae..9348e52 100644
--- a/chromeos/components/camera_app_ui/resources/src/js/views/camera_intent.js
+++ b/chromeos/components/camera_app_ui/resources/src/js/views/camera_intent.js
@@ -157,12 +157,14 @@
         }
       })();
       const result = this.photoResult_ || this.videoResult_;
-      metrics.log(
-          metrics.Type.CAPTURE, this.facingMode_, result.duration || 0,
-          result.resolution,
-          confirmed ? metrics.IntentResultType.CONFIRMED :
-                      metrics.IntentResultType.CANCELED,
-          this.shutterType_);
+      metrics.log(metrics.Type.CAPTURE, {
+        facing: this.facingMode_,
+        duration: result.duration || undefined,
+        resolution: result.resolution,
+        intentResult: confirmed ? metrics.IntentResultType.CONFIRMED :
+                                  metrics.IntentResultType.CANCELED,
+        shutterType: this.shutterType_
+      });
       if (confirmed) {
         await this.intent_.finish();
         window.close();
diff --git a/chromeos/components/media_app_ui/BUILD.gn b/chromeos/components/media_app_ui/BUILD.gn
index e79d0f6..a9d49b5 100644
--- a/chromeos/components/media_app_ui/BUILD.gn
+++ b/chromeos/components/media_app_ui/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//chrome/test/base/js2gtest.gni")
+import("//chromeos/components/web_applications/system_apps.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 
@@ -86,20 +87,11 @@
   sources = [ "media_app_ui.mojom" ]
 }
 
-# Note we compile with reportUnknownTypes while it works, but if dependencies
-# get more complex, we should remove it and only enable in developer builds.
+media_test_closure_flags = system_app_closure_flags_strict + [ "hide_warnings_for=chromeos/components/media_app_ui/media_app_ui.mojom-lite-for-compile.js" ]
+
 js_type_check("closure_compile_tests") {
   testonly = true
-  closure_flags = default_closure_args + [
-                    "jscomp_error=strictCheckTypes",
-                    "jscomp_error=reportUnknownTypes",
-                    "language_in=ECMASCRIPT_2018",
-
-                    # TODO(crbug/1048973): Remove these when the mojo bindings
-                    # js is updated to pass a closure compile check.
-                    "hide_warnings_for=mojo/public/js/",
-                    "hide_warnings_for=chromeos/components/media_app_ui/media_app_ui.mojom-lite-for-compile.js",
-                  ]
+  closure_flags = media_test_closure_flags
   deps = [
     ":test_driver_api_js",
     ":test_driver_js",
diff --git a/chromeos/components/media_app_ui/resources/js/BUILD.gn b/chromeos/components/media_app_ui/resources/js/BUILD.gn
index 643bc13..da958e2 100644
--- a/chromeos/components/media_app_ui/resources/js/BUILD.gn
+++ b/chromeos/components/media_app_ui/resources/js/BUILD.gn
@@ -2,36 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//chromeos/components/web_applications/system_apps.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 
-# Lint checks are not well documented, but pick up some useful stuff. Currently
-# require it to be requested in developer builds only.
-enable_lint_checks = false
-
-# Note we compile with reportUnknownTypes while it works, but if dependencies
-# get more complex, we should remove it and only enable in developer builds.
-media_closure_flags = default_closure_args + [
-                        "conformance_configs " + rebase_path(
-                                "../../../web_applications/closure_conformance_checks.txt",
-                                root_build_dir),
-                        "jscomp_error=conformanceViolations",
-
-                        "jscomp_error=strictCheckTypes",
-                        "jscomp_error=reportUnknownTypes",
-                        "language_in=ECMASCRIPT_2018",
-
-                        # TODO(crbug/1048973): Remove these when the mojo bindings
-                        # js is updated to pass a closure compile check.
-                        "hide_warnings_for=mojo/public/js/",
-                        "hide_warnings_for=chromeos/components/media_app_ui/media_app_ui.mojom-lite-for-compile.js",
-                      ]
-
-if (enable_lint_checks) {
-  media_closure_flags += [
-    "jscomp_error=lintChecks",
-    "hide_warnings_for=mojo/public/interfaces/bindings",
-  ]
-}
+media_closure_flags = system_app_closure_flags_strict + [ "hide_warnings_for=chromeos/components/media_app_ui/media_app_ui.mojom-lite-for-compile.js" ]
 
 group("closure_compile") {
   deps = [
diff --git a/chromeos/components/media_app_ui/resources/js/launch.js b/chromeos/components/media_app_ui/resources/js/launch.js
index 6da99312..6b380a3 100644
--- a/chromeos/components/media_app_ui/resources/js/launch.js
+++ b/chromeos/components/media_app_ui/resources/js/launch.js
@@ -584,7 +584,7 @@
 /**
  * Sets state for the files opened in the current directory.
  * @param {!FileSystemDirectoryHandle} directory
- * @param {!{file: !File, handle: !FileSystemFileHandle}} focusFile
+ * @param {{file: !File, handle: !FileSystemFileHandle}} focusFile
  */
 function setCurrentDirectory(directory, focusFile) {
   // Load currentFiles into the guest.
diff --git a/chromeos/components/media_app_ui/resources/js/receiver.js b/chromeos/components/media_app_ui/resources/js/receiver.js
index f4c0ee0..e2b3608 100644
--- a/chromeos/components/media_app_ui/resources/js/receiver.js
+++ b/chromeos/components/media_app_ui/resources/js/receiver.js
@@ -192,7 +192,7 @@
    * @param {!mediaApp.AbstractFile} abstractFile
    * @return {!Promise<undefined>}
    */
-  async saveCopy(/** !mediaApp.AbstractFile */ abstractFile) {
+  async saveCopy(abstractFile) {
     /** @type {!SaveCopyMessage} */
     const msg = {blob: abstractFile.blob, suggestedName: abstractFile.name};
     await parentMessagePipe.sendMessage(Message.SAVE_COPY, msg);
diff --git a/chromeos/components/media_app_ui/test/dom_testing_helpers.js b/chromeos/components/media_app_ui/test/dom_testing_helpers.js
index 9a62a48..fc8a822 100644
--- a/chromeos/components/media_app_ui/test/dom_testing_helpers.js
+++ b/chromeos/components/media_app_ui/test/dom_testing_helpers.js
@@ -12,7 +12,7 @@
  *
  * @param {string} query
  * @param {!Array<string>=} opt_path
- * @return {Promise<!Element>}
+ * @return {!Promise<!Element>}
  */
 async function waitForNode(query, opt_path) {
   /** @type {!HTMLElement|!ShadowRoot} */
diff --git a/chromeos/components/media_app_ui/test/driver.js b/chromeos/components/media_app_ui/test/driver.js
index 577a616..09db356 100644
--- a/chromeos/components/media_app_ui/test/driver.js
+++ b/chromeos/components/media_app_ui/test/driver.js
@@ -21,15 +21,15 @@
    *
    * @param {string} query the querySelector to run in the guest.
    * @param {string=} opt_property a property to request on the found element.
-   * @param {Object=} opt_commands test commands to execute on the element.
+   * @param {!Object=} opt_commands test commands to execute on the element.
    * @return Promise<string> JSON.stringify()'d value of the property, or
    *   tagName if unspecified.
    */
   async waitForElementInGuest(query, opt_property, opt_commands = {}) {
-    /** @type {TestMessageQueryData} */
+    /** @type {!TestMessageQueryData} */
     const message = {testQuery: query, property: opt_property};
     await testMessageHandlersReady;
-    const result = /** @type {TestMessageResponseData} */ (
+    const result = /** @type {!TestMessageResponseData} */ (
         await guestMessagePipe.sendMessage(
             'test', {...message, ...opt_commands}));
     return result.testQueryResult;
@@ -41,7 +41,7 @@
  * @param {string} testCase
  */
 async function runTestInGuest(testCase) {
-  /** @type {TestMessageRunTestCase} */
+  /** @type {!TestMessageRunTestCase} */
   const message = {testCase};
   await testMessageHandlersReady;
   await guestMessagePipe.sendMessage('run-test-case', message);
@@ -54,7 +54,7 @@
  */
 async function getFileErrors() {
   const message = {getFileErrors: true};
-  const response = /** @type {TestMessageResponseData} */ (
+  const response = /** @type {!TestMessageResponseData} */ (
       await guestMessagePipe.sendMessage('test', message));
   return response.testQueryResult;
 }
@@ -64,7 +64,7 @@
   constructor(/** !Blob= */ data = new Blob()) {
     this.data = data;
 
-    /** @type {!Array<!{position: number, size: (number|undefined)}>} */
+    /** @type {!Array<{position: number, size: (number|undefined)}>} */
     this.writes = [];
 
     /** @type {function(!Blob)} */
@@ -77,6 +77,10 @@
   /** @override */
   async write(data) {
     const position = 0;  // Assume no seeks.
+    if (!data) {
+      this.writes.push({position, size: 0});
+      return;
+    }
     this.writes.push({position, size: data.size});
     this.data = new Blob([
       this.data.slice(0, position),
@@ -101,7 +105,7 @@
 /** @implements FileSystemHandle  */
 class FakeFileSystemHandle {
   /**
-   * @param {!string=} name
+   * @param {string=} name
    */
   constructor(name = 'fake_file.png') {
     this.isFile = true;
@@ -121,10 +125,10 @@
 /** @implements FileSystemFileHandle  */
 class FakeFileSystemFileHandle extends FakeFileSystemHandle {
   /**
-   * @param {!string=} name
-   * @param {!string=} type
+   * @param {string=} name
+   * @param {string=} type
    * @param {number=} lastModified
-   * @param {!Blob} blob
+   * @param {!Blob=} blob
    */
   constructor(
       name = 'fake_file.png', type = '', lastModified = 0, blob = new Blob()) {
@@ -133,10 +137,10 @@
 
     this.lastWritable.data = blob;
 
-    /** @type {!string} */
+    /** @type {string} */
     this.type = type;
 
-    /** @type {!number} */
+    /** @type {number} */
     this.lastModified = lastModified;
 
     /** @type {?DOMException} */
@@ -170,7 +174,7 @@
 /** @implements FileSystemDirectoryHandle  */
 class FakeFileSystemDirectoryHandle extends FakeFileSystemHandle {
   /**
-   * @param {!string=} name
+   * @param {string=} name
    */
   constructor(name = 'fake-dir') {
     super(name);
@@ -204,7 +208,7 @@
   /** @override */
   async getFile(name, options) {
     const fileHandle = this.files.find(f => f.name === name);
-    if (!fileHandle && options.create === true) {
+    if (!fileHandle && options && options.create === true) {
       // Simulate creating a new file, assume it is an image. This is needed for
       // renaming files to ensure it has the right mime type, the real
       // implementation copies the mime type from the binary.
@@ -244,7 +248,7 @@
  *   name: (string|undefined),
  *   type: (string|undefined),
  *   lastModified: (number|undefined),
- *   arrayBuffer: (function(): (Promise<ArrayBuffer>)|undefined)
+ *   arrayBuffer: (function(): (!Promise<!ArrayBuffer>)|undefined)
  * }}
  */
 let FileDesc;
@@ -252,11 +256,11 @@
 /**
  * Creates a mock directory with the provided files in it.
  * @param {!Array<!FileDesc>=} files
- * @return {Promise<FakeFileSystemDirectoryHandle>}
+ * @return {!Promise<!FakeFileSystemDirectoryHandle>}
  */
 async function createMockTestDirectory(files = [{}]) {
   const directory = new FakeFileSystemDirectoryHandle();
-  for (const /** FileDesc */ file of files) {
+  for (const /** !FileDesc */ file of files) {
     const fileBlob = file.arrayBuffer !== undefined ?
         new Blob([await file.arrayBuffer()]) :
         new Blob();
@@ -295,11 +299,11 @@
 
 /**
  * Creates a mock LaunchParams object from the provided `files`.
- * @param {!Array<FileSystemHandle>} files
- * @return {LaunchParams}
+ * @param {!Array<!FileSystemHandle>} files
+ * @return {!LaunchParams}
  */
 function handlesToLaunchParams(files) {
-  return /** @type{LaunchParams} */ ({files});
+  return /** @type{!LaunchParams} */ ({files});
 }
 
 /**
@@ -309,7 +313,7 @@
  * @param {!Array<!FakeFileSystemFileHandle>} directoryContents
  * @param {!Array<!FakeFileSystemFileHandle>=} multiSelectionFiles If provided,
  *     holds additional files selected in the files app at launch time.
- * @return {!Promise<FakeFileSystemDirectoryHandle>}
+ * @return {!Promise<!FakeFileSystemDirectoryHandle>}
  */
 async function launchWithHandles(directoryContents, multiSelectionFiles = []) {
   /** @type {?FakeFileSystemFileHandle} */
@@ -340,8 +344,8 @@
 /**
  * Helper to invoke launchWithHandles after wrapping `files` in fake handles.
  * @param {!Array<!File>} files
- * @param {!Array<!number>=} selectedIndexes
- * @return {!Promise<FakeFileSystemDirectoryHandle>}
+ * @param {!Array<number>=} selectedIndexes
+ * @return {!Promise<!FakeFileSystemDirectoryHandle>}
  */
 async function launchWithFiles(files, selectedIndexes = []) {
   const fileHandles = files.map(fileToFileHandle);
@@ -354,7 +358,7 @@
  * Creates an `Error` with the name field set.
  * @param {string} name
  * @param {string} msg
- * @return {Error}
+ * @return {!Error}
  */
 function createNamedError(name, msg) {
   const error = new Error(msg);
@@ -380,7 +384,7 @@
  * @param {?string} testCase
  */
 function assertFilesToBe(expectedFiles, testCase) {
-  return assertFilenamesToBe(expectedFiles.map(f => f.name).join(), testCase);
+  assertFilenamesToBe(expectedFiles.map(f => f.name).join(), testCase);
 }
 
 /**
@@ -402,30 +406,31 @@
  * Wraps `chai.assert.match` allowing tests to use `assertMatch`.
  * @param {string} string the string to match
  * @param {string} regex an escaped regex compatible string
- * @param {string|undefined} opt_message logged if the assertion fails
+ * @param {string=} opt_message logged if the assertion fails
  */
-function assertMatch(string, regex, opt_message) {
+function assertMatch(string, regex, opt_message = undefined) {
   chai.assert.match(string, new RegExp(regex), opt_message);
 }
 
 /**
  * Use to match error stack traces.
  * @param {string} stackTrace the stacktrace
- * @param {Array<string>} regexLines a list of escaped regex compatible strings,
- *     used to compare with the stacktrace.
- * @param {string|undefined} opt_message logged if the assertion fails
+ * @param {!Array<string>} regexLines a list of escaped regex compatible
+ *     strings, used to compare with the stacktrace.
+ * @param {string=} opt_message logged if the assertion fails
  */
-function assertMatchErrorStack(stackTrace, regexLines, opt_message) {
+function assertMatchErrorStack(
+    stackTrace, regexLines, opt_message = undefined) {
   const regex = `(.|\\n)*${regexLines.join('(.|\\n)*')}(.|\\n)*`;
   assertMatch(stackTrace, regex, opt_message);
 }
 
 /**
  * Returns the files loaded in the most recent call to `loadFiles()`.
- * @return {Promise<?Array<!ReceivedFile>>}
+ * @return {!Promise<?Array<!ReceivedFile>>}
  */
 async function getLoadedFiles() {
-  const response = /** @type {LastLoadedFilesResponse} */ (
+  const response = /** @type {!LastLoadedFilesResponse} */ (
       await guestMessagePipe.sendMessage('get-last-loaded-files'));
   if (response.fileList) {
     return response.fileList;
@@ -444,9 +449,11 @@
 
 /**
  * @param {!FakeFileSystemDirectoryHandle} directory
+ * @return {{handle: !FakeFileSystemFileHandle, file: !File}}
  */
 function launchWithFocusFile(directory) {
   const focusFile = {
+    /** @type {!FakeFileSystemFileHandle} */
     handle: directory.files[0],
     file: directory.files[0].getFileSync()
   };
@@ -464,7 +471,7 @@
 
   await sendFilesToGuest();
 
-  const loadedFiles = await getLoadedFiles();
+  const loadedFiles = assertCast(await getLoadedFiles());
   // The untrusted context only loads the first file.
   chai.assert.equal(1, loadedFiles.length);
   // All files are in the `FileSystemDirectoryHandle`.
diff --git a/chromeos/components/media_app_ui/test/driver_api.js b/chromeos/components/media_app_ui/test/driver_api.js
index 54651ab..a22c30a 100644
--- a/chromeos/components/media_app_ui/test/driver_api.js
+++ b/chromeos/components/media_app_ui/test/driver_api.js
@@ -12,7 +12,7 @@
  *     getFileErrors: (boolean|undefined),
  *     navigate: (string|undefined),
  *     overwriteLastFile: (string|undefined),
- *     pathToRoot: (Array<string>|undefined),
+ *     pathToRoot: (!Array<string>|undefined),
  *     property: (string|undefined),
  *     renameLastFile: (string|undefined),
  *     requestFullscreen: (boolean|undefined),
@@ -30,6 +30,6 @@
  * guest app using `loadFiles()`. We pass `ReceivedFileList.files` since passing
  * `ReceivedFileList` through different contexts prunes methods and fails due to
  * observers.
- * @typedef {{fileList: ?Array<ReceivedFile>}}
+ * @typedef {{fileList: ?Array<!ReceivedFile>}}
  */
 let LastLoadedFilesResponse;
diff --git a/chromeos/components/media_app_ui/test/guest_query_receiver.js b/chromeos/components/media_app_ui/test/guest_query_receiver.js
index 2376653..ec74e90 100644
--- a/chromeos/components/media_app_ui/test/guest_query_receiver.js
+++ b/chromeos/components/media_app_ui/test/guest_query_receiver.js
@@ -10,15 +10,21 @@
 
 /**
  * Test cases registered by GUEST_TEST.
- * @type {Map<string, function(): Promise<undefined>>}
+ * @type {!Map<string, function(): !Promise<undefined>>}
  */
 const guestTestCases = new Map();
 
 /**
+ * @return {!mediaApp.AbstractFile}
+ */
+function firstReceivedItem() {
+  return assertCast(assertCast(lastReceivedFileList).item(0));
+}
+
+/**
  * Acts on received TestMessageQueryData.
- *
- * @param {TestMessageQueryData} data
- * @return {!Promise<TestMessageResponseData>}
+ * @param {!TestMessageQueryData} data
+ * @return {!Promise<!TestMessageResponseData>}
  */
 async function runTestQuery(data) {
   let result = 'no result';
@@ -32,51 +38,53 @@
       try {
         await element.requestFullscreen();
         result = 'hooray';
-      } catch (/** @type {TypeError} */ typeError) {
+      } catch (/** @type {!TypeError} */ typeError) {
         result = typeError.message;
       }
     }
   } else if (data.navigate !== undefined) {
     if (data.navigate === 'next') {
-      await lastReceivedFileList.loadNext();
+      await assertCast(lastReceivedFileList).loadNext();
       result = 'loadNext called';
     } else if (data.navigate === 'prev') {
-      await lastReceivedFileList.loadPrev();
+      await assertCast(lastReceivedFileList).loadPrev();
       result = 'loadPrev called';
     } else {
       result = 'nothing called';
     }
   } else if (data.overwriteLastFile) {
     const testBlob = new Blob([data.overwriteLastFile]);
-    await lastReceivedFileList.item(0).overwriteOriginal(testBlob);
+    await assertCast(firstReceivedItem().overwriteOriginal)
+        .call(firstReceivedItem(), testBlob);
     result = 'overwriteOriginal resolved';
   } else if (data.deleteLastFile) {
     try {
       const deleteResult =
-          await lastReceivedFileList.item(0).deleteOriginalFile();
+          await assertCast(firstReceivedItem().deleteOriginalFile)
+              .call(firstReceivedItem());
       if (deleteResult === DeleteResult.FILE_MOVED) {
         result = 'deleteOriginalFile resolved file moved';
       } else {
         result = 'deleteOriginalFile resolved success';
       }
-    } catch (/** @type{Error} */ error) {
+    } catch (/** @type{!Error} */ error) {
       result = `deleteOriginalFile failed Error: ${error}`;
     }
   } else if (data.renameLastFile) {
     try {
       const renameResult =
-          await lastReceivedFileList.item(0).renameOriginalFile(
-              data.renameLastFile);
+          await assertCast(firstReceivedItem().renameOriginalFile)
+              .call(firstReceivedItem(), data.renameLastFile);
       if (renameResult === RenameResult.FILE_EXISTS) {
         result = 'renameOriginalFile resolved file exists';
       } else {
         result = 'renameOriginalFile resolved success';
       }
-    } catch (/** @type{Error} */ error) {
+    } catch (/** @type{!Error} */ error) {
       result = `renameOriginalFile failed Error: ${error}`;
     }
   } else if (data.saveCopy) {
-    const existingFile = lastReceivedFileList.item(0);
+    const existingFile = assertCast(lastReceivedFileList).item(0);
     if (!existingFile) {
       result = 'saveCopy failed, no file loaded';
     } else {
@@ -84,15 +92,16 @@
       result = 'boo yah!';
     }
   } else if (data.getFileErrors) {
-    result = lastReceivedFileList.files.map(file => file.error).join();
+    result =
+        assertCast(lastReceivedFileList).files.map(file => file.error).join();
   }
   return {testQueryResult: result};
 }
 
 /**
  * Acts on TestMessageRunTestCase.
- * @param {TestMessageRunTestCase} data
- * @return {!Promise<TestMessageResponseData>}
+ * @param {!TestMessageRunTestCase} data
+ * @return {!Promise<!TestMessageResponseData>}
  */
 async function runTestCase(data) {
   const testCase = guestTestCases.get(data.testCase);
@@ -107,7 +116,7 @@
  * Registers a test that runs in the guest context. To indicate failure, the
  * test throws an exception (e.g. via assertEquals).
  * @param {string} testName
- * @param {function(): Promise<undefined>} testCase
+ * @param {function(): !Promise<undefined>} testCase
  */
 function GUEST_TEST(testName, testCase) {
   guestTestCases.set(testName, testCase);
@@ -127,7 +136,7 @@
     try {
       await parentMessagePipe.sendMessage('test-handlers-ready', {});
       return;
-    } catch (/** @type {GenericErrorResponse} */ e) {
+    } catch (/** @type {!GenericErrorResponse} */ e) {
       if (e.message !== EXPECTED_ERROR) {
         console.error('Unexpected error in signalTestHandlersReady', e);
         return;
@@ -136,9 +145,10 @@
   }
 }
 
+/** Installs the MessagePipe handlers for receiving test queries. */
 function installTestHandlers() {
   parentMessagePipe.registerHandler('test', (data) => {
-    return runTestQuery(/** @type {TestMessageQueryData} */ (data));
+    return runTestQuery(/** @type {!TestMessageQueryData} */ (data));
   });
   // Turn off error rethrowing for tests so the test runner doesn't mark
   // our error handling tests as failed.
@@ -150,14 +160,14 @@
   });
 
   parentMessagePipe.registerHandler('run-test-case', (data) => {
-    return runTestCase(/** @type{TestMessageRunTestCase} */ (data));
+    return runTestCase(/** @type{!TestMessageRunTestCase} */ (data));
   });
 
   parentMessagePipe.registerHandler('get-last-loaded-files', () => {
     //  Note: the `ReceivedFileList` has methods stripped since it gets sent
     //  over a pipe so just send the underlying files.
-    return /** @type {LastLoadedFilesResponse} */ (
-        {fileList: lastReceivedFileList.files});
+    return /** @type {!LastLoadedFilesResponse} */ (
+        {fileList: assertCast(lastReceivedFileList).files});
   });
 
   // Log errors, rather than send them to console.error. This allows the error
@@ -168,10 +178,15 @@
 
   // Install spies.
   const realLoadFiles = loadFiles;
-  loadFiles = async (/** !ReceivedFileList */ fileList) => {
+  /**
+   * @param {!ReceivedFileList} fileList
+   * @return {!Promise<undefined>}
+   */
+  async function watchLoadFiles(fileList) {
     lastReceivedFileList = fileList;
     return realLoadFiles(fileList);
-  };
+  }
+  loadFiles = watchLoadFiles;
   signalTestHandlersReady();
 }
 
diff --git a/chromeos/components/telemetry_extension_ui/probe_service.h b/chromeos/components/telemetry_extension_ui/probe_service.h
index 5258056..d0e00ba 100644
--- a/chromeos/components/telemetry_extension_ui/probe_service.h
+++ b/chromeos/components/telemetry_extension_ui/probe_service.h
@@ -38,10 +38,14 @@
 
   void OnDisconnect();
 
-  mojo::Receiver<health::mojom::ProbeService> receiver_;
-
   // Pointer to real implementation.
   mojo::Remote<cros_healthd::mojom::CrosHealthdProbeService> service_;
+
+  // We must destroy |receiver_| before destroying |service_|, so we will close
+  // interface pipe before destroying pending response callbacks owned by
+  // |service_|. It is an error to drop response callbacks which still
+  // correspond to an open interface pipe.
+  mojo::Receiver<health::mojom::ProbeService> receiver_;
 };
 
 }  // namespace chromeos
diff --git a/chromeos/components/web_applications/system_apps.gni b/chromeos/components/web_applications/system_apps.gni
new file mode 100644
index 0000000..a7b96bb
--- /dev/null
+++ b/chromeos/components/web_applications/system_apps.gni
@@ -0,0 +1,31 @@
+import("//third_party/closure_compiler/compile_js.gni")
+
+declare_args() {
+  # Whether to enable additional linting of closure type annotations.
+  # Lint checks are not well documented, but pick up some useful stuff.
+  enable_system_app_lint_checks = false
+}
+
+system_app_closure_flags =
+    default_closure_args + [
+      "conformance_configs " +
+          rebase_path("closure_conformance_checks.txt", root_build_dir),
+      "jscomp_error=conformanceViolations",
+
+      "jscomp_error=strictCheckTypes",
+      "language_in=ECMASCRIPT_2018",
+
+      # TODO(crbug/1048973): Remove these when the mojo bindings
+      # js is updated to pass a closure compile check.
+      "hide_warnings_for=mojo/public/js/",
+    ]
+
+if (enable_system_app_lint_checks) {
+  system_app_closure_flags += [
+    "jscomp_error=lintChecks",
+    "hide_warnings_for=mojo/public/interfaces/bindings",
+  ]
+}
+
+system_app_closure_flags_strict =
+    system_app_closure_flags + [ "jscomp_error=reportUnknownTypes" ]
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index 5a7883aa..f5107d3 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -227,6 +227,10 @@
 const base::Feature kHelpAppReleaseNotes{"HelpAppReleaseNotes",
                                          base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enable the search service integration in the Help app.
+const base::Feature kHelpAppSearchServiceIntegration{
+    "HelpAppSearchServiceIntegration", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enable or disable Unified Input Logic for HMM decoder in the IME extension
 // on Chrome OS.
 const base::Feature kImeInputLogicHmm{"ImeInputLogicHmm",
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index 7069649..68c25d4 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -101,6 +101,8 @@
 extern const base::Feature kHelpAppFirstRun;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kHelpAppReleaseNotes;
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const base::Feature kHelpAppSearchServiceIntegration;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kHelpAppV2;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kImeInputLogicHmm;
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt
index 0562585..98521f7 100644
--- a/chromeos/profiles/orderfile.newest.txt
+++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@
-chromeos-chrome-orderfile-field-85-4170.0-1592820725-benchmark-85.0.4176.0-r1.orderfile.xz
+chromeos-chrome-orderfile-field-85-4170.0-1592820725-benchmark-85.0.4181.3-r1.orderfile.xz
diff --git a/components/assist_ranker/OWNERS b/components/assist_ranker/OWNERS
index 00608e8..6951cc1 100644
--- a/components/assist_ranker/OWNERS
+++ b/components/assist_ranker/OWNERS
@@ -1,4 +1,3 @@
-amoylan@chromium.org
 charleszhao@chromium.org
 hamelphi@chromium.org
 jiameng@chromium.org
diff --git a/components/assist_ranker/README.md b/components/assist_ranker/README.md
new file mode 100644
index 0000000..6207c77
--- /dev/null
+++ b/components/assist_ranker/README.md
@@ -0,0 +1,22 @@
+# Assist Ranker
+
+[TOC]
+
+## Introduction
+
+Assist Ranker is design to make Chrome smarter by providing client-side machine
+learning (ML) inference in Chrome. It is designed to be a generic infrastructure
+that supports ML needs for all Chrome feature teams on all platforms.
+
+Assist Ranker utilizes UKM logging to log per feature-label events. A ML model
+will be trained in the Cloud based on these logs; and then Assist Ranker will
+download and inference with the model.
+
+It currently only supports Logistic Regression and Multilayer Neural Networks.
+
+Assist Ranker was experiment on ContextualSearch; but it is not used in any
+production projects.
+
+## How to use it
+
+Please contact the owners before you use it.
\ No newline at end of file
diff --git a/components/browser_ui/banners/android/BUILD.gn b/components/browser_ui/banners/android/BUILD.gn
new file mode 100644
index 0000000..8092d104
--- /dev/null
+++ b/components/browser_ui/banners/android/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+  sources = [ "java/src/org/chromium/components/browser_ui/banners/SwipableOverlayView.java" ]
+
+  deps = [
+    "//base:base_java",
+    "//content/public/android:content_java",
+    "//third_party/android_deps:androidx_appcompat_appcompat_java",
+  ]
+}
diff --git a/components/browser_ui/banners/android/DEPS b/components/browser_ui/banners/android/DEPS
new file mode 100644
index 0000000..a8a0eaca
--- /dev/null
+++ b/components/browser_ui/banners/android/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "-content/public/android",
+  "+content/public/android/java/src/org/chromium/content_public",
+]
diff --git a/components/browser_ui/banners/android/OWNERS b/components/browser_ui/banners/android/OWNERS
new file mode 100644
index 0000000..2d62f33
--- /dev/null
+++ b/components/browser_ui/banners/android/OWNERS
@@ -0,0 +1 @@
+file://chrome/android/java/src/org/chromium/chrome/browser/banners/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java b/components/browser_ui/banners/android/java/src/org/chromium/components/browser_ui/banners/SwipableOverlayView.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java
rename to components/browser_ui/banners/android/java/src/org/chromium/components/browser_ui/banners/SwipableOverlayView.java
index 14b1903..5ad4328 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java
+++ b/components/browser_ui/banners/android/java/src/org/chromium/components/browser_ui/banners/SwipableOverlayView.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.banners;
+package org.chromium.components.browser_ui.banners;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -233,8 +233,8 @@
 
                 boolean isVisibleInitially = mInitialTranslationY < mTotalHeight;
                 float percentageVisible = 1.0f - (getTranslationY() / mTotalHeight);
-                float visibilityThreshold = isVisibleInitially
-                        ? VERTICAL_FLING_HIDE_THRESHOLD : VERTICAL_FLING_SHOW_THRESHOLD;
+                float visibilityThreshold = isVisibleInitially ? VERTICAL_FLING_HIDE_THRESHOLD
+                                                               : VERTICAL_FLING_SHOW_THRESHOLD;
                 boolean isVisibleEnough = percentageVisible > visibilityThreshold;
                 boolean isNearTopOfPage = scrollOffsetY < (mTotalHeight * FULL_THRESHOLD);
 
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
index ae7feef..c1a5bb6 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
@@ -512,6 +512,7 @@
                 return true;
             });
         } else {
+            setUpListPreference(preference, value, isEmbargoed);
             if (isPermissionControlledByDSE(ContentSettingsType.NOTIFICATIONS) && value != null) {
                 updatePreferenceForDSESetting(preference);
             }
diff --git a/components/infobars/android/BUILD.gn b/components/infobars/android/BUILD.gn
index 472f481..b7a6f32 100644
--- a/components/infobars/android/BUILD.gn
+++ b/components/infobars/android/BUILD.gn
@@ -16,6 +16,7 @@
     "res/drawable-xxhdpi/infobar_shadow_top.png",
     "res/drawable-xxxhdpi/infobar_shadow_left.9.png",
     "res/drawable-xxxhdpi/infobar_shadow_top.png",
+    "res/drawable/infobar_wrapper_bg.xml",
     "res/layout/infobar_control_icon_with_description.xml",
     "res/layout/infobar_control_message.xml",
     "res/layout/infobar_control_spinner.xml",
@@ -36,6 +37,8 @@
 
 static_library("android") {
   sources = [
+    "confirm_infobar.cc",
+    "confirm_infobar.h",
     "infobar_android.cc",
     "infobar_android.h",
   ]
@@ -44,11 +47,13 @@
     ":jni_headers",
     "//base",
     "//components/infobars/core",
+    "//ui/gfx",
   ]
 }
 
 android_library("java") {
   sources = [
+    "java/src/org/chromium/components/infobars/ConfirmInfoBar.java",
     "java/src/org/chromium/components/infobars/InfoBar.java",
     "java/src/org/chromium/components/infobars/InfoBarCompactLayout.java",
     "java/src/org/chromium/components/infobars/InfoBarControlLayout.java",
@@ -56,6 +61,7 @@
     "java/src/org/chromium/components/infobars/InfoBarLayout.java",
     "java/src/org/chromium/components/infobars/InfoBarMessageView.java",
     "java/src/org/chromium/components/infobars/InfoBarUiItem.java",
+    "java/src/org/chromium/components/infobars/InfoBarWrapper.java",
   ]
   deps = [
     ":infobar_android_enums_java",
@@ -82,7 +88,10 @@
 }
 
 generate_jni("jni_headers") {
-  sources = [ "java/src/org/chromium/components/infobars/InfoBar.java" ]
+  sources = [
+    "java/src/org/chromium/components/infobars/ConfirmInfoBar.java",
+    "java/src/org/chromium/components/infobars/InfoBar.java",
+  ]
 }
 
 android_library("javatests") {
diff --git a/components/infobars/android/confirm_infobar.cc b/components/infobars/android/confirm_infobar.cc
new file mode 100644
index 0000000..d25bd44
--- /dev/null
+++ b/components/infobars/android/confirm_infobar.cc
@@ -0,0 +1,79 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/infobars/android/confirm_infobar.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/android/jni_string.h"
+#include "components/infobars/android/jni_headers/ConfirmInfoBar_jni.h"
+#include "components/infobars/core/confirm_infobar_delegate.h"
+#include "ui/gfx/android/java_bitmap.h"
+#include "ui/gfx/image/image.h"
+
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+
+ConfirmInfoBar::ConfirmInfoBar(std::unique_ptr<ConfirmInfoBarDelegate> delegate,
+                               const ResourceIdMapper& resource_id_mapper)
+    : InfoBarAndroid(std::move(delegate), resource_id_mapper) {}
+
+ConfirmInfoBar::~ConfirmInfoBar() {}
+
+base::string16 ConfirmInfoBar::GetTextFor(
+    ConfirmInfoBarDelegate::InfoBarButton button) {
+  ConfirmInfoBarDelegate* delegate = GetDelegate();
+  return (delegate->GetButtons() & button) ? delegate->GetButtonLabel(button)
+                                           : base::string16();
+}
+
+ConfirmInfoBarDelegate* ConfirmInfoBar::GetDelegate() {
+  return delegate()->AsConfirmInfoBarDelegate();
+}
+
+ScopedJavaLocalRef<jobject> ConfirmInfoBar::CreateRenderInfoBar(JNIEnv* env) {
+  ScopedJavaLocalRef<jstring> ok_button_text =
+      base::android::ConvertUTF16ToJavaString(
+          env, GetTextFor(ConfirmInfoBarDelegate::BUTTON_OK));
+  ScopedJavaLocalRef<jstring> cancel_button_text =
+      base::android::ConvertUTF16ToJavaString(
+          env, GetTextFor(ConfirmInfoBarDelegate::BUTTON_CANCEL));
+  ConfirmInfoBarDelegate* delegate = GetDelegate();
+  ScopedJavaLocalRef<jstring> message_text =
+      base::android::ConvertUTF16ToJavaString(env, delegate->GetMessageText());
+  ScopedJavaLocalRef<jstring> link_text =
+      base::android::ConvertUTF16ToJavaString(env, delegate->GetLinkText());
+
+  ScopedJavaLocalRef<jobject> java_bitmap;
+  if (delegate->GetIconId() == infobars::InfoBarDelegate::kNoIconID &&
+      !delegate->GetIcon().IsEmpty()) {
+    java_bitmap = gfx::ConvertToJavaBitmap(delegate->GetIcon().ToSkBitmap());
+  }
+
+  return Java_ConfirmInfoBar_create(env, GetJavaIconId(), java_bitmap,
+                                    message_text, link_text, ok_button_text,
+                                    cancel_button_text);
+}
+
+void ConfirmInfoBar::OnLinkClicked(JNIEnv* env,
+                                   const JavaParamRef<jobject>& obj) {
+  if (!owner())
+    return;  // We're closing; don't call anything, it might access the owner.
+
+  if (GetDelegate()->LinkClicked(WindowOpenDisposition::NEW_FOREGROUND_TAB))
+    RemoveSelf();
+}
+
+void ConfirmInfoBar::ProcessButton(int action) {
+  if (!owner())
+    return;  // We're closing; don't call anything, it might access the owner.
+
+  DCHECK((action == InfoBarAndroid::ACTION_OK) ||
+         (action == InfoBarAndroid::ACTION_CANCEL));
+  ConfirmInfoBarDelegate* delegate = GetDelegate();
+  if ((action == InfoBarAndroid::ACTION_OK) ? delegate->Accept()
+                                            : delegate->Cancel())
+    RemoveSelf();
+}
diff --git a/chrome/browser/ui/android/infobars/confirm_infobar.h b/components/infobars/android/confirm_infobar.h
similarity index 75%
rename from chrome/browser/ui/android/infobars/confirm_infobar.h
rename to components/infobars/android/confirm_infobar.h
index f03d976..172cc44c 100644
--- a/chrome/browser/ui/android/infobars/confirm_infobar.h
+++ b/components/infobars/android/confirm_infobar.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_ANDROID_INFOBARS_CONFIRM_INFOBAR_H_
-#define CHROME_BROWSER_UI_ANDROID_INFOBARS_CONFIRM_INFOBAR_H_
+#ifndef COMPONENTS_INFOBARS_ANDROID_CONFIRM_INFOBAR_H_
+#define COMPONENTS_INFOBARS_ANDROID_CONFIRM_INFOBAR_H_
 
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
@@ -11,16 +11,14 @@
 #include "components/infobars/android/infobar_android.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 
-class TabAndroid;
-
 class ConfirmInfoBar : public InfoBarAndroid {
  public:
-  explicit ConfirmInfoBar(std::unique_ptr<ConfirmInfoBarDelegate> delegate);
+  ConfirmInfoBar(std::unique_ptr<ConfirmInfoBarDelegate> delegate,
+                 const ResourceIdMapper& resource_id_mapper);
   ~ConfirmInfoBar() override;
 
  protected:
   ConfirmInfoBarDelegate* GetDelegate();
-  TabAndroid* GetTab();
   base::string16 GetTextFor(ConfirmInfoBarDelegate::InfoBarButton button);
 
   // InfoBarAndroid overrides.
@@ -36,4 +34,4 @@
   DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBar);
 };
 
-#endif  // CHROME_BROWSER_UI_ANDROID_INFOBARS_CONFIRM_INFOBAR_H_
+#endif  // COMPONENTS_INFOBARS_ANDROID_CONFIRM_INFOBAR_H_
diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/infobar/ConfirmInfoBar.java b/components/infobars/android/java/src/org/chromium/components/infobars/ConfirmInfoBar.java
similarity index 94%
rename from chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/infobar/ConfirmInfoBar.java
rename to components/infobars/android/java/src/org/chromium/components/infobars/ConfirmInfoBar.java
index 89d1229..36c8470 100644
--- a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/infobar/ConfirmInfoBar.java
+++ b/components/infobars/android/java/src/org/chromium/components/infobars/ConfirmInfoBar.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.ui.messages.infobar;
+package org.chromium.components.infobars;
 
 import android.graphics.Bitmap;
 
@@ -10,8 +10,6 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.browser.infobar.ActionType;
-import org.chromium.components.infobars.InfoBar;
-import org.chromium.components.infobars.InfoBarLayout;
 
 /**
  * An infobar that presents the user with several buttons.
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/InfoBarWrapper.java b/components/infobars/android/java/src/org/chromium/components/infobars/InfoBarWrapper.java
similarity index 80%
rename from weblayer/browser/java/org/chromium/weblayer_private/InfoBarWrapper.java
rename to components/infobars/android/java/src/org/chromium/components/infobars/InfoBarWrapper.java
index ad8af86c..b85a9a4 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/InfoBarWrapper.java
+++ b/components/infobars/android/java/src/org/chromium/components/infobars/InfoBarWrapper.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.weblayer_private;
+package org.chromium.components.infobars;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -10,18 +10,16 @@
 import android.view.View;
 import android.widget.FrameLayout;
 
-import org.chromium.components.infobars.InfoBarUiItem;
-
 /**
  * Layout that holds an infobar's contents and provides a background color and a top shadow.
  */
-class InfoBarWrapper extends FrameLayout {
+public class InfoBarWrapper extends FrameLayout {
     private final InfoBarUiItem mItem;
 
     /**
      * Constructor for inflating from Java.
      */
-    InfoBarWrapper(Context context, InfoBarUiItem item) {
+    public InfoBarWrapper(Context context, InfoBarUiItem item) {
         super(context);
         mItem = item;
         Resources res = context.getResources();
@@ -30,11 +28,11 @@
         setMinimumHeight(peekingHeight + shadowHeight);
 
         // setBackgroundResource() changes the padding, so call setPadding() second.
-        setBackgroundResource(R.drawable.weblayer_infobar_wrapper_bg);
+        setBackgroundResource(R.drawable.infobar_wrapper_bg);
         setPadding(0, shadowHeight, 0, 0);
     }
 
-    InfoBarUiItem getItem() {
+    public InfoBarUiItem getItem() {
         return mItem;
     }
 
diff --git a/chrome/android/java/res/drawable/infobar_wrapper_bg.xml b/components/infobars/android/res/drawable/infobar_wrapper_bg.xml
similarity index 100%
rename from chrome/android/java/res/drawable/infobar_wrapper_bg.xml
rename to components/infobars/android/res/drawable/infobar_wrapper_bg.xml
diff --git a/components/neterror/README.md b/components/neterror/README.md
new file mode 100644
index 0000000..dd74717a
--- /dev/null
+++ b/components/neterror/README.md
@@ -0,0 +1,16 @@
+#Network error interstitial resources
+
+This directory contains the HTML template and resources displayed in the case of
+network errors received when fetching the root document or iframes. These error
+pages can be previewed by following the links listed to chrome://network-errors.
+
+The same template is used across all desktop and mobile platforms and for main
+frames and iframes.
+
+This also includes the scripts and images for the offline dino game.
+
+---
+See also:
+- [components/neterror/](components/neterror/) for the code that utilises this template
+- [components/security_interstitials/core/common/resources/](components/security_interstitials/core/common/resources/) for commons CSS and JS files with security interstitials
+
diff --git a/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc b/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc
index bb1c2acb0..9ca5844a 100644
--- a/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc
+++ b/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc
@@ -96,7 +96,7 @@
     const LeakCheckCredential& credential =
         waiting_encryption_.back()->credential;
     PrepareSingleLeakRequestData(
-        payload_task_runner_.get(), encryption_key_,
+        task_tracker_, *payload_task_runner_, encryption_key_,
         base::UTF16ToUTF8(credential.username()),
         base::UTF16ToUTF8(credential.password()),
         base::BindOnce(&BulkLeakCheckImpl::OnPayloadReady,
diff --git a/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h b/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h
index fba40bf..1315546 100644
--- a/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h
+++ b/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h
@@ -12,6 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/sequenced_task_runner.h"
+#include "base/task/cancelable_task_tracker.h"
 #include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h"
@@ -121,6 +122,9 @@
   // those tasks aren't parallelized.
   scoped_refptr<base::SequencedTaskRunner> payload_task_runner_;
 
+  // Cancels pending encryption tasks when destructing.
+  base::CancelableTaskTracker task_tracker_;
+
   // Weak pointers for different callbacks.
   base::WeakPtrFactory<BulkLeakCheckImpl> weak_ptr_factory_{this};
 };
diff --git a/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.cc b/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.cc
index 8ab41569..dbbd4cc 100644
--- a/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.cc
+++ b/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.cc
@@ -137,13 +137,14 @@
 }
 
 void PrepareSingleLeakRequestData(
-    base::TaskRunner* task_runner,
+    base::CancelableTaskTracker& task_tracker,
+    base::TaskRunner& task_runner,
     const std::string& encryption_key,
     const std::string& username,
     const std::string& password,
     base::OnceCallback<void(LookupSingleLeakPayload)> callback) {
-  base::PostTaskAndReplyWithResult(
-      task_runner, FROM_HERE,
+  task_tracker.PostTaskAndReplyWithResult(
+      &task_runner, FROM_HERE,
       base::BindOnce(&PrepareLookupSingleLeakDataWithKey, encryption_key,
                      username, password),
       std::move(callback));
diff --git a/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h b/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h
index 9878371..296a84f6 100644
--- a/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h
+++ b/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h
@@ -8,6 +8,7 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/strings/string_piece_forward.h"
+#include "base/task/cancelable_task_tracker.h"
 #include "base/task_runner.h"
 #include "components/signin/public/identity_manager/access_token_fetcher.h"
 
@@ -63,10 +64,11 @@
                                   SingleLeakRequestDataCallback callback);
 
 // Asynchronously creates a data payload for a credential check with the given
-// encryption key. The task is posted to |task_runner|.
+// encryption key. The task is posted to |task_runner| via |task_tracker|.
 // Callback is invoked on the calling thread with the protobuf.
 void PrepareSingleLeakRequestData(
-    base::TaskRunner* task_runner,
+    base::CancelableTaskTracker& task_tracker,
+    base::TaskRunner& task_runner,
     const std::string& encryption_key,
     const std::string& username,
     const std::string& password,
diff --git a/components/password_manager/core/browser/leak_detection/leak_detection_request_utils_unittest.cc b/components/password_manager/core/browser/leak_detection/leak_detection_request_utils_unittest.cc
index ed6b20c..5e08095 100644
--- a/components/password_manager/core/browser/leak_detection/leak_detection_request_utils_unittest.cc
+++ b/components/password_manager/core/browser/leak_detection/leak_detection_request_utils_unittest.cc
@@ -45,10 +45,11 @@
 TEST(LeakDetectionRequestUtils, PrepareSingleLeakRequestDataWithKey) {
   base::test::SingleThreadTaskEnvironment task_env;
   auto task_runner = task_env.GetMainThreadTaskRunner();
+  base::CancelableTaskTracker task_tracker;
   base::MockOnceCallback<void(LookupSingleLeakPayload)> callback;
 
-  PrepareSingleLeakRequestData(task_runner.get(), "random_key", "jonsnow",
-                               "1234", callback.Get());
+  PrepareSingleLeakRequestData(task_tracker, *task_runner, "random_key",
+                               "jonsnow", "1234", callback.Get());
   EXPECT_CALL(callback,
               Run(AllOf(Field(&LookupSingleLeakPayload::username_hash_prefix,
                               ElementsAre(61, 112, -45)),
@@ -57,6 +58,21 @@
   task_env.RunUntilIdle();
 }
 
+TEST(LeakDetectionRequestUtils, PrepareSingleLeakRequestDataCancelled) {
+  base::test::SingleThreadTaskEnvironment task_env;
+  auto task_runner = task_env.GetMainThreadTaskRunner();
+  base::MockOnceCallback<void(LookupSingleLeakPayload)> callback;
+  EXPECT_CALL(callback, Run).Times(0);
+
+  {
+    base::CancelableTaskTracker task_tracker;
+    PrepareSingleLeakRequestData(task_tracker, *task_runner, "random_key",
+                                 "jonsnow", "1234", callback.Get());
+  }
+
+  task_env.RunUntilIdle();
+}
+
 TEST(LeakDetectionRequestUtils, AnalyzeResponseResult_DecryptionError) {
   base::test::TaskEnvironment task_env;
 
diff --git a/components/payments/content/installable_payment_app_crawler.cc b/components/payments/content/installable_payment_app_crawler.cc
index 0d7422a..5c9f7a45 100644
--- a/components/payments/content/installable_payment_app_crawler.cc
+++ b/components/payments/content/installable_payment_app_crawler.cc
@@ -33,6 +33,9 @@
 
 namespace payments {
 
+RefetchedIcon::RefetchedIcon() = default;
+RefetchedIcon::~RefetchedIcon() = default;
+
 // TODO(crbug.com/782270): Use cache to accelerate crawling procedure.
 InstallablePaymentAppCrawler::InstallablePaymentAppCrawler(
     const url::Origin& merchant_origin,
@@ -514,8 +517,11 @@
                 "\" for payment handler manifest \"" +
                 method_manifest_url.spec() + "\".");
     } else {
-      refetched_icons_.insert(std::pair<GURL, std::unique_ptr<SkBitmap>>(
-          web_app_manifest_url, std::make_unique<SkBitmap>(icon)));
+      auto refetched_icon = std::make_unique<RefetchedIcon>();
+      refetched_icon->method_name = method_manifest_url.spec();
+      refetched_icon->icon = std::make_unique<SkBitmap>(icon);
+      refetched_icons_.insert(
+          std::make_pair(web_app_manifest_url, std::move(refetched_icon)));
     }
   }
 
diff --git a/components/payments/content/installable_payment_app_crawler.h b/components/payments/content/installable_payment_app_crawler.h
index dadcf77..71861a8e 100644
--- a/components/payments/content/installable_payment_app_crawler.h
+++ b/components/payments/content/installable_payment_app_crawler.h
@@ -33,6 +33,13 @@
 
 namespace payments {
 
+struct RefetchedIcon {
+  RefetchedIcon();
+  ~RefetchedIcon();
+  std::string method_name;
+  std::unique_ptr<SkBitmap> icon;
+};
+
 // Crawls installable web payment apps. First, fetches and parses the payment
 // method manifests to get 'default_applications' manifest urls. Then, fetches
 // and parses the web app manifests to get the installable payment apps' info.
@@ -40,7 +47,7 @@
  public:
   using FinishedCrawlingCallback = base::OnceCallback<void(
       std::map<GURL, std::unique_ptr<WebAppInstallationInfo>>,
-      std::map<GURL, std::unique_ptr<SkBitmap>>,
+      std::map<GURL, std::unique_ptr<RefetchedIcon>>,
       const std::string& error_message)>;
 
   enum class CrawlingMode {
@@ -138,7 +145,7 @@
   size_t number_of_web_app_icons_to_download_and_decode_;
   std::set<GURL> downloaded_web_app_manifests_;
   std::map<GURL, std::unique_ptr<WebAppInstallationInfo>> installable_apps_;
-  std::map<GURL, std::unique_ptr<SkBitmap>> refetched_icons_;
+  std::map<GURL, std::unique_ptr<RefetchedIcon>> refetched_icons_;
   std::set<GURL> method_manifest_urls_for_icon_refetch_;
 
   // The first error message (if any) to be forwarded to the merchant when
diff --git a/components/payments/content/service_worker_payment_app_finder.cc b/components/payments/content/service_worker_payment_app_finder.cc
index 14e2a3c..87b33d0 100644
--- a/components/payments/content/service_worker_payment_app_finder.cc
+++ b/components/payments/content/service_worker_payment_app_finder.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <vector>
 
+#include "base/base64.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/check.h"
@@ -25,11 +26,13 @@
 #include "components/payments/core/url_util.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/payment_app_provider.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/stored_payment_app.h"
 #include "content/public/browser/web_contents.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "ui/gfx/image/image.h"
 #include "url/url_canon.h"
 
 namespace payments {
@@ -270,13 +273,14 @@
 
   void OnPaymentAppsCrawled(
       std::map<GURL, std::unique_ptr<WebAppInstallationInfo>> apps_info,
-      std::map<GURL, std::unique_ptr<SkBitmap>> refetched_icons,
+      std::map<GURL, std::unique_ptr<RefetchedIcon>> refetched_icons,
       const std::string& error_message) {
     if (first_error_message_.empty())
       first_error_message_ = error_message;
 
     for (auto& refetched_icon : refetched_icons) {
       GURL web_app_manifest_url = refetched_icon.first;
+      RefetchedIcon* data = refetched_icon.second.get();
       for (auto& app : installed_apps_) {
         // It is possible (unlikely) to have multiple apps with same origins.
         // The proper validation is to store web_app_manifest_url in
@@ -284,9 +288,8 @@
         // web_app_manifest_url from which icon is fetched.
         if (crawler_->IsSameOriginWith(GURL(app.second->scope),
                                        web_app_manifest_url)) {
-          // TODO(crbug.com/1069010): Update the payment app database with the
-          // new icon.
-          app.second->icon = std::move(refetched_icon.second);
+          UpdatePaymentAppIcon(app.second, data->icon, data->method_name);
+          app.second->icon = std::move(data->icon);
           break;
         }
       }
@@ -295,6 +298,38 @@
                              first_error_message_);
   }
 
+  void UpdatePaymentAppIcon(
+      const std::unique_ptr<content::StoredPaymentApp>& app,
+      const std::unique_ptr<SkBitmap>& icon,
+      const std::string& method_name) {
+    number_of_app_icons_to_update_++;
+
+    DCHECK(!icon->empty());
+    std::string string_encoded_icon;
+    gfx::Image decoded_image = gfx::Image::CreateFrom1xBitmap(*(icon));
+    scoped_refptr<base::RefCountedMemory> raw_data =
+        decoded_image.As1xPNGBytes();
+    base::Base64Encode(
+        base::StringPiece(raw_data->front_as<char>(), raw_data->size()),
+        &string_encoded_icon);
+
+    auto* browser_context =
+        static_cast<content::WebContents*>(owner_)->GetBrowserContext();
+    content::PaymentAppProvider::GetInstance()->UpdatePaymentAppIcon(
+        browser_context, app->registration_id, app->scope.spec(), app->name,
+        string_encoded_icon, method_name, app->supported_delegations,
+        base::BindOnce(
+            &SelfDeletingServiceWorkerPaymentAppFinder::OnUpdatePaymentAppIcon,
+            weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  void OnUpdatePaymentAppIcon(payments::mojom::PaymentHandlerStatus status) {
+    DCHECK(number_of_app_icons_to_update_ > 0);
+    number_of_app_icons_to_update_--;
+    if (number_of_app_icons_to_update_ == 0)
+      FinishUsingResourcesIfReady();
+  }
+
   void OnPaymentAppsCrawlerFinishedUsingResources() {
     crawler_.reset();
 
@@ -312,7 +347,8 @@
   void FinishUsingResourcesIfReady() {
     if (is_payment_verifier_finished_using_resources_ &&
         is_payment_app_crawler_finished_using_resources_ &&
-        !finished_using_resources_callback_.is_null()) {
+        !finished_using_resources_callback_.is_null() &&
+        number_of_app_icons_to_update_ == 0) {
       downloader_.reset();
       parser_.reset();
       std::move(finished_using_resources_callback_).Run();
@@ -348,6 +384,8 @@
 
   content::PaymentAppProvider::PaymentApps installed_apps_;
 
+  size_t number_of_app_icons_to_update_ = 0;
+
   base::WeakPtrFactory<SelfDeletingServiceWorkerPaymentAppFinder>
       weak_ptr_factory_{this};
 };
diff --git a/components/prerender/common/BUILD.gn b/components/prerender/common/BUILD.gn
index 85f2acc..974b784 100644
--- a/components/prerender/common/BUILD.gn
+++ b/components/prerender/common/BUILD.gn
@@ -8,7 +8,6 @@
   sources = [
     "prerender_final_status.cc",
     "prerender_final_status.h",
-    "prerender_messages.h",
     "prerender_origin.cc",
     "prerender_origin.h",
   ]
diff --git a/components/prerender/common/prerender_canceler.mojom b/components/prerender/common/prerender_canceler.mojom
index 5f2863a..8d0be5e5 100644
--- a/components/prerender/common/prerender_canceler.mojom
+++ b/components/prerender/common/prerender_canceler.mojom
@@ -4,12 +4,14 @@
 
 module prerender.mojom;
 
-import "url/mojom/url.mojom";
-
 // This interface is provided to a renderer that is used for prerendering. It
 // enables the renderer to detect and respond to cases that should cause the
 // prerendering to be cancelled.
 interface PrerenderCanceler {
   // Cancels prerendering because of an unsupported scheme.
-  CancelPrerenderForUnsupportedScheme(url.mojom.Url url);
+  CancelPrerenderForUnsupportedScheme();
+
+  // Cancels prerendering because the resource prefetcher has discovered all
+  // possible subresources and issued requests for them.
+  CancelPrerenderForNoStatePrefetch();
 };
diff --git a/components/prerender/common/prerender_messages.h b/components/prerender/common/prerender_messages.h
deleted file mode 100644
index adc2e27c..0000000
--- a/components/prerender/common/prerender_messages.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PRERENDER_COMMON_PRERENDER_MESSAGES_H_
-#define COMPONENTS_PRERENDER_COMMON_PRERENDER_MESSAGES_H_
-
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_param_traits.h"
-
-#define IPC_MESSAGE_START PrerenderMsgStart
-
-// PrerenderLinkManager Messages
-
-// Sent by the renderer process to notify that the resource prefetcher has
-// discovered all possible subresources and issued requests for them.
-IPC_MESSAGE_CONTROL0(PrerenderHostMsg_PrefetchFinished)
-
-#endif  // COMPONENTS_PRERENDER_COMMON_PRERENDER_MESSAGES_H_
diff --git a/components/query_tiles/README.md b/components/query_tiles/README.md
new file mode 100644
index 0000000..3e1809b
--- /dev/null
+++ b/components/query_tiles/README.md
@@ -0,0 +1,70 @@
+# Query Tiles Service
+
+## Introduction
+Query tiles is a new feature to bring down the barriers for NIU users and boost
+their confidence when using Chrome in Android.  It encourages users to explore
+the internet by simply clicking on a few image tiles, and building a search
+query to find the information they want.
+
+With this feature enabled, users will see a list of image tiles with the
+corresponding query strings shown on NTP(new tab page) and Omnibox suggestions.
+By clicking on those tiles, users will be directed to the search result page
+provided.
+
+The client side will schedule fetch tasks from Google server periodically to
+update the latest data and images based on the user's locale.
+
+## Code structure
+
+[components/query_tiles](.)
+Public interfaces and data structure.
+
+[components/query_tiles/internal](./internal)
+internal implementations.
+
+[components/query_tiles/proto](./proto)
+Protobuf structure.
+
+[components/query_tiles/android](./android)
+UI related code.
+
+[chrome/browser/query_tiles](../../chrome/browser/query_tiles)
+include service factory and background task client code.
+
+[components/browser_ui/widget/image_tiles](../browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/image_tiles/)
+Generic widget representing image tiles carousel.
+
+`TileService` - Public interface for query tile service.
+
+`TileServiceScheduer` - Handles scheduling tasks to fetch tiles from the server.
+
+`TileManager` - Store and dispense query tiles.
+
+`ImageTileCoordinator` - UI widget representing the carousel.
+
+`TileProvider` - Handles backend interaction from the Java layer
+
+`QueryTileSection` - Query tiles widget on NTP.
+
+`QueryTileProvider` - Provider for omnibox query tile suggestions.
+
+
+## Test and debug
+
+### Feature flags
+In chrome://flags,
+
+* Disable `Start surface`
+
+* Enable `Query tiles`
+
+* Enable `Query tiles in omnibox`
+
+* Set `Country code for getting tiles` to `IN` or `US`
+
+* If you’d like to see the UI immediately, enable `Query tile instant fetch`,
+restart Chrome twice and wait for 10 seconds.
+
+### WebUI
+Use `chrome://internals/query-tiles` to manually tune the flow(start/reset) and
+show the internal status and data.
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeProfileDataSource.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeProfileDataSource.java
index 83f51ce..7b0c1f5 100644
--- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeProfileDataSource.java
+++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeProfileDataSource.java
@@ -19,7 +19,7 @@
  * returned by {@link #getProfileDataForAccount}.
  */
 public class FakeProfileDataSource implements ProfileDataSource {
-    private final ObserverList<Observer> mObservers = new ObserverList<>();
+    protected final ObserverList<Observer> mObservers = new ObserverList<>();
     private final Map<String, ProfileData> mProfileDataMap = new HashMap<>();
 
     public FakeProfileDataSource() {}
diff --git a/components/sync/base/model_type.h b/components/sync/base/model_type.h
index a4bfb3e3..a6827ca 100644
--- a/components/sync/base/model_type.h
+++ b/components/sync/base/model_type.h
@@ -284,12 +284,29 @@
   return ModelTypeSet(PASSWORDS, WIFI_CONFIGURATIONS);
 }
 
-// This is the subset of UserTypes() that have priority over other types.  These
-// types are synced before other user types.
+// This is the subset of UserTypes() that have priority over other types. These
+// types are synced before other user types (both for get_updates and commits).
+// This mostly matters during initial sync, since priority types can become
+// active before all the data for non-prio types has been downloaded (which may
+// be a lot of data).
 constexpr ModelTypeSet PriorityUserTypes() {
-  return ModelTypeSet(DEVICE_INFO, PRIORITY_PREFERENCES,
-                      SUPERVISED_USER_SETTINGS, SUPERVISED_USER_WHITELISTS,
-                      OS_PRIORITY_PREFERENCES, SHARING_MESSAGE, THEMES);
+  return ModelTypeSet(
+      // The "Send to Your Devices" feature needs fast updating of the list of
+      // your devices and also fast sending of the actual messages.
+      DEVICE_INFO, SHARING_MESSAGE,
+      // For supervised users, it is important to quickly deliver changes in
+      // settings and in allowed sites to the supervised user.
+      SUPERVISED_USER_SETTINGS, SUPERVISED_USER_WHITELISTS,
+      // These are by definition preferences for which it is important that the
+      // client picks them up quickly (also because these can get changed
+      // server-side). For example, such a pref could control whether a
+      // non-priority type gets enabled (Wallet has such a pref).
+      PRIORITY_PREFERENCES, OS_PRIORITY_PREFERENCES,
+      // Speed matters for the user experience when sync gets enabled directly
+      // in the creation flow for a new profile. If the user has no theme in
+      // their sync data, the browser offers a theme customization bubble which
+      // should appear soon after opening the browser.
+      THEMES);
 }
 
 // Proxy types are placeholder types for handling implicitly enabling real
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc
index a319d99..b4db086f 100644
--- a/components/sync/driver/profile_sync_service.cc
+++ b/components/sync/driver/profile_sync_service.cc
@@ -18,7 +18,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/rand_util.h"
-#include "base/run_loop.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/thread.h"
@@ -1963,14 +1962,6 @@
   sync_prefs_.SetPassphrasePrompted(prompted);
 }
 
-void ProfileSyncService::FlushBackendTaskRunnerForTest() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  base::RunLoop run_loop;
-
-  backend_task_runner_->PostTask(FROM_HERE, run_loop.QuitClosure());
-  run_loop.Run();
-}
-
 SyncEncryptionHandler::Observer*
 ProfileSyncService::GetEncryptionObserverForTest() {
   return &crypto_;
diff --git a/components/sync/driver/profile_sync_service.h b/components/sync/driver/profile_sync_service.h
index 112f102df..8d13868 100644
--- a/components/sync/driver/profile_sync_service.h
+++ b/components/sync/driver/profile_sync_service.h
@@ -239,9 +239,6 @@
 
   bool IsDataTypeControllerRunningForTest(ModelType type) const;
 
-  // Sometimes we need to wait for tasks on the |backend_task_runner_| in tests.
-  void FlushBackendTaskRunnerForTest() const;
-
   // Some tests rely on injecting calls to the encryption observer.
   SyncEncryptionHandler::Observer* GetEncryptionObserverForTest();
 
diff --git a/components/sync/engine_impl/cycle/status_controller_unittest.cc b/components/sync/engine_impl/cycle/status_controller_unittest.cc
index c90ca69..1fc15b0 100644
--- a/components/sync/engine_impl/cycle/status_controller_unittest.cc
+++ b/components/sync/engine_impl/cycle/status_controller_unittest.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "components/sync/engine_impl/cycle/sync_cycle.h"
-#include "components/sync/test/engine/test_id_factory.h"
 #include "net/http/http_status_code.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/sync/engine_impl/loopback_server/loopback_server_unittest.cc b/components/sync/engine_impl/loopback_server/loopback_server_unittest.cc
index 7753b1b2..bf931dfd 100644
--- a/components/sync/engine_impl/loopback_server/loopback_server_unittest.cc
+++ b/components/sync/engine_impl/loopback_server/loopback_server_unittest.cc
@@ -10,7 +10,6 @@
 #include "components/sync/engine_impl/syncer_proto_util.h"
 #include "components/sync/protocol/sync.pb.h"
 #include "components/sync/protocol/sync_enums.pb.h"
-#include "components/sync/test/engine/test_directory_setter_upper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using sync_pb::ClientToServerMessage;
diff --git a/components/sync/engine_impl/sync_manager_impl_unittest.cc b/components/sync/engine_impl/sync_manager_impl_unittest.cc
index 30fbc5c..6765ec7c 100644
--- a/components/sync/engine_impl/sync_manager_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_manager_impl_unittest.cc
@@ -47,7 +47,6 @@
 #include "components/sync/test/callback_counter.h"
 #include "components/sync/test/engine/fake_model_worker.h"
 #include "components/sync/test/engine/fake_sync_scheduler.h"
-#include "components/sync/test/engine/test_id_factory.h"
 #include "components/sync/test/fake_sync_encryption_handler.h"
 #include "services/network/test/test_network_connection_tracker.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/components/sync/engine_impl/syncer_unittest.cc b/components/sync/engine_impl/syncer_unittest.cc
index 2fd4a06..26c4421 100644
--- a/components/sync/engine_impl/syncer_unittest.cc
+++ b/components/sync/engine_impl/syncer_unittest.cc
@@ -392,13 +392,13 @@
   const sync_pb::EntitySpecifics pref = MakeSpecifics(PREFERENCES);
 
   // Normal sync, all the data types should get synced.
-  mock_server_->AddUpdateSpecifics(1, 0, "A", 10, 10, true, 0, bookmark,
+  mock_server_->AddUpdateSpecifics("1", "0", "A", 10, 10, true, 0, bookmark,
                                    foreign_cache_guid(), "-1");
-  mock_server_->AddUpdateSpecifics(2, 1, "B", 10, 10, false, 2, bookmark,
+  mock_server_->AddUpdateSpecifics("2", "1", "B", 10, 10, false, 2, bookmark,
                                    foreign_cache_guid(), "-2");
-  mock_server_->AddUpdateSpecifics(3, 1, "C", 10, 10, false, 1, bookmark,
+  mock_server_->AddUpdateSpecifics("3", "1", "C", 10, 10, false, 1, bookmark,
                                    foreign_cache_guid(), "-3");
-  mock_server_->AddUpdateSpecifics(4, 0, "D", 10, 10, false, 0, pref);
+  mock_server_->AddUpdateSpecifics("4", "0", "D", 10, 10, false, 0, pref);
 
   EXPECT_TRUE(SyncShareNudge());
   // Initial state. Everything is normal.
@@ -413,13 +413,13 @@
   mock_server_->set_throttling(true);
   mock_server_->SetPartialFailureTypes(throttled_types);
 
-  mock_server_->AddUpdateSpecifics(1, 0, "E", 20, 20, true, 0, bookmark,
+  mock_server_->AddUpdateSpecifics("1", "0", "E", 20, 20, true, 0, bookmark,
                                    foreign_cache_guid(), "-1");
-  mock_server_->AddUpdateSpecifics(2, 1, "F", 20, 20, false, 2, bookmark,
+  mock_server_->AddUpdateSpecifics("2", "1", "F", 20, 20, false, 2, bookmark,
                                    foreign_cache_guid(), "-2");
-  mock_server_->AddUpdateSpecifics(3, 1, "G", 20, 20, false, 1, bookmark,
+  mock_server_->AddUpdateSpecifics("3", "1", "G", 20, 20, false, 1, bookmark,
                                    foreign_cache_guid(), "-3");
-  mock_server_->AddUpdateSpecifics(4, 0, "H", 20, 20, false, 0, pref);
+  mock_server_->AddUpdateSpecifics("4", "0", "H", 20, 20, false, 0, pref);
   EXPECT_TRUE(SyncShareNudge());
 
   // PREFERENCES continues to work normally (not throttled).
@@ -430,13 +430,13 @@
   // Unthrottled BOOKMARKS, then BOOKMARKS should get synced now.
   mock_server_->set_throttling(false);
 
-  mock_server_->AddUpdateSpecifics(1, 0, "E", 30, 30, true, 0, bookmark,
+  mock_server_->AddUpdateSpecifics("1", "0", "E", 30, 30, true, 0, bookmark,
                                    foreign_cache_guid(), "-1");
-  mock_server_->AddUpdateSpecifics(2, 1, "F", 30, 30, false, 2, bookmark,
+  mock_server_->AddUpdateSpecifics("2", "1", "F", 30, 30, false, 2, bookmark,
                                    foreign_cache_guid(), "-2");
-  mock_server_->AddUpdateSpecifics(3, 1, "G", 30, 30, false, 1, bookmark,
+  mock_server_->AddUpdateSpecifics("3", "1", "G", 30, 30, false, 1, bookmark,
                                    foreign_cache_guid(), "-3");
-  mock_server_->AddUpdateSpecifics(4, 0, "H", 30, 30, false, 0, pref);
+  mock_server_->AddUpdateSpecifics("4", "0", "H", 30, 30, false, 0, pref);
   EXPECT_TRUE(SyncShareNudge());
   // BOOKMARKS unthrottled.
   EXPECT_EQ(2U, GetProcessor(BOOKMARKS)->GetNumUpdateResponses());
@@ -447,13 +447,13 @@
   const sync_pb::EntitySpecifics pref = MakeSpecifics(PREFERENCES);
 
   // Normal sync, all the data types should get synced.
-  mock_server_->AddUpdateSpecifics(1, 0, "A", 10, 10, true, 0, bookmark,
+  mock_server_->AddUpdateSpecifics("1", "0", "A", 10, 10, true, 0, bookmark,
                                    foreign_cache_guid(), "-1");
-  mock_server_->AddUpdateSpecifics(2, 1, "B", 10, 10, false, 2, bookmark,
+  mock_server_->AddUpdateSpecifics("2", "1", "B", 10, 10, false, 2, bookmark,
                                    foreign_cache_guid(), "-2");
-  mock_server_->AddUpdateSpecifics(3, 1, "C", 10, 10, false, 1, bookmark,
+  mock_server_->AddUpdateSpecifics("3", "1", "C", 10, 10, false, 1, bookmark,
                                    foreign_cache_guid(), "-3");
-  mock_server_->AddUpdateSpecifics(4, 0, "D", 10, 10, false, 0, pref);
+  mock_server_->AddUpdateSpecifics("4", "0", "D", 10, 10, false, 0, pref);
 
   EXPECT_TRUE(SyncShareNudge());
   // Initial state. Everything is normal.
@@ -468,13 +468,13 @@
   mock_server_->set_partial_failure(true);
   mock_server_->SetPartialFailureTypes(failed_types);
 
-  mock_server_->AddUpdateSpecifics(1, 0, "E", 20, 20, true, 0, bookmark,
+  mock_server_->AddUpdateSpecifics("1", "0", "E", 20, 20, true, 0, bookmark,
                                    foreign_cache_guid(), "-1");
-  mock_server_->AddUpdateSpecifics(2, 1, "F", 20, 20, false, 2, bookmark,
+  mock_server_->AddUpdateSpecifics("2", "1", "F", 20, 20, false, 2, bookmark,
                                    foreign_cache_guid(), "-2");
-  mock_server_->AddUpdateSpecifics(3, 1, "G", 20, 20, false, 1, bookmark,
+  mock_server_->AddUpdateSpecifics("3", "1", "G", 20, 20, false, 1, bookmark,
                                    foreign_cache_guid(), "-3");
-  mock_server_->AddUpdateSpecifics(4, 0, "H", 20, 20, false, 0, pref);
+  mock_server_->AddUpdateSpecifics("4", "0", "H", 20, 20, false, 0, pref);
   EXPECT_TRUE(SyncShareNudge());
 
   // PREFERENCES continues to work normally (not throttled).
@@ -485,13 +485,13 @@
   // Set BOOKMARKS not partial failed, then BOOKMARKS should get synced now.
   mock_server_->set_partial_failure(false);
 
-  mock_server_->AddUpdateSpecifics(1, 0, "E", 30, 30, true, 0, bookmark,
+  mock_server_->AddUpdateSpecifics("1", "0", "E", 30, 30, true, 0, bookmark,
                                    foreign_cache_guid(), "-1");
-  mock_server_->AddUpdateSpecifics(2, 1, "F", 30, 30, false, 2, bookmark,
+  mock_server_->AddUpdateSpecifics("2", "1", "F", 30, 30, false, 2, bookmark,
                                    foreign_cache_guid(), "-2");
-  mock_server_->AddUpdateSpecifics(3, 1, "G", 30, 30, false, 1, bookmark,
+  mock_server_->AddUpdateSpecifics("3", "1", "G", 30, 30, false, 1, bookmark,
                                    foreign_cache_guid(), "-3");
-  mock_server_->AddUpdateSpecifics(4, 0, "H", 30, 30, false, 0, pref);
+  mock_server_->AddUpdateSpecifics("4", "0", "H", 30, 30, false, 0, pref);
   EXPECT_TRUE(SyncShareNudge());
   // BOOKMARKS not failed.
   EXPECT_EQ(2U, GetProcessor(BOOKMARKS)->GetNumUpdateResponses());
@@ -509,10 +509,8 @@
                             MakeSpecifics(PREFERENCES), kSyncId2);
 
   EXPECT_TRUE(SyncShareNudge());
-  EXPECT_THAT(
-      mock_server_->committed_ids(),
-      UnorderedElementsAre(syncable::Id::CreateFromClientString(kSyncId1),
-                           syncable::Id::CreateFromClientString(kSyncId2)));
+  EXPECT_THAT(mock_server_->committed_ids(),
+              UnorderedElementsAre(kSyncId1, kSyncId2));
 }
 
 TEST_F(SyncerTest, TestSimpleGetUpdates) {
@@ -804,8 +802,8 @@
       GetSpecificsFieldNumberFromModelType(BOOKMARKS));
   bookmark_delay->set_delay_ms(950);
   command->set_client_invalidation_hint_buffer_size(11);
-  mock_server_->AddUpdateDirectory(1, 0, "in_root", 1, 1, foreign_cache_guid(),
-                                   "-1");
+  mock_server_->AddUpdateDirectory("1", "0", "in_root", 1, 1,
+                                   foreign_cache_guid(), "-1");
   mock_server_->SetGUClientCommand(std::move(command));
   EXPECT_TRUE(SyncShareNudge());
 
@@ -824,8 +822,8 @@
       GetSpecificsFieldNumberFromModelType(BOOKMARKS));
   bookmark_delay->set_delay_ms(1050);
   command->set_client_invalidation_hint_buffer_size(9);
-  mock_server_->AddUpdateDirectory(1, 0, "in_root", 1, 1, foreign_cache_guid(),
-                                   "-1");
+  mock_server_->AddUpdateDirectory("1", "0", "in_root", 1, 1,
+                                   foreign_cache_guid(), "-1");
   mock_server_->SetGUClientCommand(std::move(command));
   EXPECT_TRUE(SyncShareNudge());
 
@@ -882,7 +880,7 @@
 }
 
 TEST_F(SyncerTest, ClientTagServerCreatedUpdatesWork) {
-  mock_server_->AddUpdateDirectory(1, 0, "permitem1", 1, 10,
+  mock_server_->AddUpdateDirectory("1", "0", "permitem1", 1, 10,
                                    foreign_cache_guid(), "-1");
   mock_server_->SetLastUpdateClientTag("clienttag");
 
@@ -941,9 +939,7 @@
 
   // The sync cycle should have included a GetUpdate, then a commit.
   EXPECT_TRUE(mock_server_->last_request().has_commit());
-  EXPECT_THAT(
-      mock_server_->committed_ids(),
-      UnorderedElementsAre(syncable::Id::CreateFromClientString(to_commit)));
+  EXPECT_THAT(mock_server_->committed_ids(), UnorderedElementsAre(to_commit));
 
   // The update should have been received.
   ASSERT_EQ(1U, GetProcessor(BOOKMARKS)->GetNumUpdateResponses());
@@ -1125,13 +1121,11 @@
       "bookmarkid2");
 
   if (ShouldFailBookmarkCommit()) {
-    mock_server_->SetTransientErrorId(
-        syncable::Id::CreateFromClientString("bookmarkid2"));
+    mock_server_->SetTransientErrorId("bookmarkid2");
   }
 
   if (ShouldFailAutofillCommit()) {
-    mock_server_->SetTransientErrorId(
-        syncable::Id::CreateFromClientString("prefid1"));
+    mock_server_->SetTransientErrorId("prefid1");
   }
 
   // Put some extensions activity records into the monitor.
diff --git a/components/sync/test/engine/mock_connection_manager.cc b/components/sync/test/engine/mock_connection_manager.cc
index 7237b1f..691fe25 100644
--- a/components/sync/test/engine/mock_connection_manager.cc
+++ b/components/sync/test/engine/mock_connection_manager.cc
@@ -12,9 +12,6 @@
 #include "base/strings/stringprintf.h"
 #include "components/sync/engine_impl/syncer_proto_util.h"
 #include "components/sync/protocol/bookmark_specifics.pb.h"
-#include "components/sync/syncable/directory.h"
-#include "components/sync/syncable/syncable_write_transaction.h"
-#include "components/sync/test/engine/test_id_factory.h"
 #include "net/base/net_errors.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -210,19 +207,6 @@
   }
 }
 
-sync_pb::SyncEntity* MockConnectionManager::AddUpdateDirectory(
-    int id,
-    int parent_id,
-    const string& name,
-    int64_t version,
-    int64_t sync_ts,
-    const std::string& originator_cache_guid,
-    const std::string& originator_client_item_id) {
-  return AddUpdateDirectory(
-      TestIdFactory::FromNumber(id), TestIdFactory::FromNumber(parent_id), name,
-      version, sync_ts, originator_cache_guid, originator_client_item_id);
-}
-
 void MockConnectionManager::SetGUClientCommand(
     std::unique_ptr<sync_pb::ClientCommand> command) {
   gu_client_command_ = std::move(command);
@@ -233,26 +217,13 @@
   commit_client_command_ = std::move(command);
 }
 
-void MockConnectionManager::SetTransientErrorId(syncable::Id id) {
+void MockConnectionManager::SetTransientErrorId(const std::string& id) {
   transient_error_ids_.push_back(id);
 }
 
-sync_pb::SyncEntity* MockConnectionManager::AddUpdateBookmark(
-    int id,
-    int parent_id,
-    const string& name,
-    int64_t version,
-    int64_t sync_ts,
-    const string& originator_client_item_id,
-    const string& originator_cache_guid) {
-  return AddUpdateBookmark(
-      TestIdFactory::FromNumber(id), TestIdFactory::FromNumber(parent_id), name,
-      version, sync_ts, originator_client_item_id, originator_cache_guid);
-}
-
 sync_pb::SyncEntity* MockConnectionManager::AddUpdateSpecifics(
-    int id,
-    int parent_id,
+    const std::string& id,
+    const std::string& parent_id,
     const string& name,
     int64_t version,
     int64_t sync_ts,
@@ -260,9 +231,7 @@
     int64_t position,
     const sync_pb::EntitySpecifics& specifics) {
   sync_pb::SyncEntity* ent =
-      AddUpdateMeta(TestIdFactory::FromNumber(id).GetServerId(),
-                    TestIdFactory::FromNumber(parent_id).GetServerId(), name,
-                    version, sync_ts);
+      AddUpdateMeta(id, parent_id, name, version, sync_ts);
   ent->set_position_in_parent(position);
   ent->mutable_specifics()->CopyFrom(specifics);
   ent->set_folder(is_dir);
@@ -270,8 +239,8 @@
 }
 
 sync_pb::SyncEntity* MockConnectionManager::AddUpdateSpecifics(
-    int id,
-    int parent_id,
+    const std::string& id,
+    const std::string& parent_id,
     const string& name,
     int64_t version,
     int64_t sync_ts,
@@ -288,13 +257,13 @@
 }
 
 sync_pb::SyncEntity* MockConnectionManager::SetNigori(
-    int id,
+    const std::string& id,
     int64_t version,
     int64_t sync_ts,
     const sync_pb::EntitySpecifics& specifics) {
   sync_pb::SyncEntity* ent = GetUpdateResponse()->add_entries();
-  ent->set_id_string(TestIdFactory::FromNumber(id).GetServerId());
-  ent->set_parent_id_string(TestIdFactory::FromNumber(0).GetServerId());
+  ent->set_id_string(id);
+  ent->set_parent_id_string("0");
   ent->set_server_defined_unique_tag(ModelTypeToRootTag(NIGORI));
   ent->set_name("Nigori");
   ent->set_non_unique_name("Nigori");
@@ -407,9 +376,7 @@
 
   if (last_sent_commit().entries(0).deleted()) {
     ModelType type = GetModelType(last_sent_commit().entries(0));
-    AddUpdateTombstone(syncable::Id::CreateFromServerId(
-                           last_sent_commit().entries(0).id_string()),
-                       type);
+    AddUpdateTombstone(last_sent_commit().entries(0).id_string(), type);
   } else {
     sync_pb::SyncEntity* ent = GetUpdateResponse()->add_entries();
     ent->CopyFrom(last_sent_commit().entries(0));
@@ -434,11 +401,11 @@
   return GetMutableLastUpdate();
 }
 
-void MockConnectionManager::AddUpdateTombstone(const syncable::Id& id,
+void MockConnectionManager::AddUpdateTombstone(const std::string& id,
                                                ModelType type) {
   // Tombstones have only the ID set and dummy values for the required fields.
   sync_pb::SyncEntity* ent = GetUpdateResponse()->add_entries();
-  ent->set_id_string(id.GetServerId());
+  ent->set_id_string(id);
   ent->set_version(0);
   ent->set_name("");
   ent->set_deleted(true);
@@ -452,7 +419,7 @@
   string id_string = GetMutableLastUpdate()->id_string();
   ModelType type = GetModelType(*GetMutableLastUpdate());
   GetUpdateResponse()->mutable_entries()->RemoveLast();
-  AddUpdateTombstone(syncable::Id::CreateFromServerId(id_string), type);
+  AddUpdateTombstone(id_string, type);
 }
 
 void MockConnectionManager::SetLastUpdateOriginatorFields(
@@ -573,7 +540,7 @@
   return conflict;
 }
 
-bool MockConnectionManager::ShouldTransientErrorThisId(syncable::Id id) {
+bool MockConnectionManager::ShouldTransientErrorThisId(const std::string& id) {
   return base::Contains(transient_error_ids_, id);
 }
 
@@ -616,15 +583,8 @@
                     << entry.name().length();
       return false;
     }
-    syncable::Id id;
-    if (entry.version() == 0) {
-      // Relies on our new item string id format. (string representation of a
-      // negative number).
-      id = syncable::Id::CreateFromClientString(id_string);
-    } else {
-      id = syncable::Id::CreateFromServerId(id_string);
-    }
-    committed_ids_.push_back(id);
+
+    committed_ids_.push_back(id_string);
 
     if (response_map.end() == response_map.find(id_string))
       response_map[id_string] = commit_response->add_entryresponse();
@@ -633,7 +593,7 @@
       er->set_response_type(CommitResponse::CONFLICT);
       continue;
     }
-    if (ShouldTransientErrorThisId(id)) {
+    if (ShouldTransientErrorThisId(id_string)) {
       er->set_response_type(CommitResponse::TRANSIENT_ERROR);
       continue;
     }
@@ -682,32 +642,6 @@
   return true;
 }
 
-sync_pb::SyncEntity* MockConnectionManager::AddUpdateDirectory(
-    syncable::Id id,
-    syncable::Id parent_id,
-    const string& name,
-    int64_t version,
-    int64_t sync_ts,
-    const string& originator_cache_guid,
-    const string& originator_client_item_id) {
-  return AddUpdateDirectory(id.GetServerId(), parent_id.GetServerId(), name,
-                            version, sync_ts, originator_cache_guid,
-                            originator_client_item_id);
-}
-
-sync_pb::SyncEntity* MockConnectionManager::AddUpdateBookmark(
-    syncable::Id id,
-    syncable::Id parent_id,
-    const string& name,
-    int64_t version,
-    int64_t sync_ts,
-    const string& originator_cache_guid,
-    const string& originator_client_item_id) {
-  return AddUpdateBookmark(id.GetServerId(), parent_id.GetServerId(), name,
-                           version, sync_ts, originator_cache_guid,
-                           originator_client_item_id);
-}
-
 sync_pb::SyncEntity* MockConnectionManager::GetMutableLastUpdate() {
   sync_pb::GetUpdatesResponse* updates = GetUpdateResponse();
   EXPECT_GT(updates->entries_size(), 0);
diff --git a/components/sync/test/engine/mock_connection_manager.h b/components/sync/test/engine/mock_connection_manager.h
index 8076d3d..9753123c 100644
--- a/components/sync/test/engine/mock_connection_manager.h
+++ b/components/sync/test/engine/mock_connection_manager.h
@@ -21,7 +21,6 @@
 #include "components/sync/base/unique_position.h"
 #include "components/sync/engine_impl/net/server_connection_manager.h"
 #include "components/sync/protocol/sync.pb.h"
-#include "components/sync/syncable/syncable_id.h"
 
 namespace syncer {
 
@@ -61,40 +60,6 @@
   // (e.g. with SyncShare.) It allows to add further entity properties before
   // sync, using SetLastXXX() methods and/or GetMutableLastUpdate().
   sync_pb::SyncEntity* AddUpdateDirectory(
-      syncable::Id id,
-      syncable::Id parent_id,
-      const std::string& name,
-      int64_t version,
-      int64_t sync_ts,
-      const std::string& originator_cache_guid,
-      const std::string& originator_client_item_id);
-  sync_pb::SyncEntity* AddUpdateBookmark(
-      syncable::Id id,
-      syncable::Id parent_id,
-      const std::string& name,
-      int64_t version,
-      int64_t sync_ts,
-      const std::string& originator_cache_guid,
-      const std::string& originator_client_item_id);
-  // Versions of the AddUpdate functions that accept integer IDs.
-  sync_pb::SyncEntity* AddUpdateDirectory(
-      int id,
-      int parent_id,
-      const std::string& name,
-      int64_t version,
-      int64_t sync_ts,
-      const std::string& originator_cache_guid,
-      const std::string& originator_client_item_id);
-  sync_pb::SyncEntity* AddUpdateBookmark(
-      int id,
-      int parent_id,
-      const std::string& name,
-      int64_t version,
-      int64_t sync_ts,
-      const std::string& originator_cache_guid,
-      const std::string& originator_client_item_id);
-  // New protocol versions of the AddUpdate functions.
-  sync_pb::SyncEntity* AddUpdateDirectory(
       const std::string& id,
       const std::string& parent_id,
       const std::string& name,
@@ -112,8 +77,8 @@
       const std::string& originator_client_item_id);
   // Versions of the AddUpdate function that accept specifics.
   sync_pb::SyncEntity* AddUpdateSpecifics(
-      int id,
-      int parent_id,
+      const std::string& id,
+      const std::string& parent_id,
       const std::string& name,
       int64_t version,
       int64_t sync_ts,
@@ -121,8 +86,8 @@
       int64_t position,
       const sync_pb::EntitySpecifics& specifics);
   sync_pb::SyncEntity* AddUpdateSpecifics(
-      int id,
-      int parent_id,
+      const std::string& id,
+      const std::string& parent_id,
       const std::string& name,
       int64_t version,
       int64_t sync_ts,
@@ -131,7 +96,7 @@
       const sync_pb::EntitySpecifics& specifics,
       const std::string& originator_cache_guid,
       const std::string& originator_client_item_id);
-  sync_pb::SyncEntity* SetNigori(int id,
+  sync_pb::SyncEntity* SetNigori(const std::string& id,
                                  int64_t version,
                                  int64_t sync_ts,
                                  const sync_pb::EntitySpecifics& specifics);
@@ -150,7 +115,7 @@
   // Add a deleted item.  Deletion records typically contain no
   // additional information beyond the deletion, and no specifics.
   // The server may send the originator fields.
-  void AddUpdateTombstone(const syncable::Id& id, ModelType type);
+  void AddUpdateTombstone(const std::string& id, ModelType type);
 
   void SetLastUpdateDeleted();
   void SetLastUpdateServerTag(const std::string& tag);
@@ -178,9 +143,9 @@
   void SetGUClientCommand(std::unique_ptr<sync_pb::ClientCommand> command);
   void SetCommitClientCommand(std::unique_ptr<sync_pb::ClientCommand> command);
 
-  void SetTransientErrorId(syncable::Id);
+  void SetTransientErrorId(const std::string&);
 
-  const std::vector<syncable::Id>& committed_ids() const {
+  const std::vector<std::string>& committed_ids() const {
     return committed_ids_;
   }
   const std::vector<std::unique_ptr<sync_pb::CommitMessage>>& commit_messages()
@@ -269,12 +234,6 @@
   void ResetAccessToken() { ClearAccessToken(); }
 
  private:
-  sync_pb::SyncEntity* AddUpdateFull(syncable::Id id,
-                                     syncable::Id parentid,
-                                     const std::string& name,
-                                     int64_t version,
-                                     int64_t sync_ts,
-                                     bool is_dir);
   sync_pb::SyncEntity* AddUpdateFull(const std::string& id,
                                      const std::string& parentid,
                                      const std::string& name,
@@ -301,7 +260,7 @@
 
   // Determine if the given item's commit request should be refused with
   // a TRANSIENT_ERROR response.
-  bool ShouldTransientErrorThisId(syncable::Id id);
+  bool ShouldTransientErrorThisId(const std::string& id);
 
   // Generate a numeric position_in_parent value.  We use a global counter
   // that only decreases; this simulates new objects always being added to the
@@ -330,10 +289,10 @@
   bool server_reachable_;
 
   // All IDs that have been committed.
-  std::vector<syncable::Id> committed_ids_;
+  std::vector<std::string> committed_ids_;
 
   // List of IDs which should return a transient error.
-  std::vector<syncable::Id> transient_error_ids_;
+  std::vector<std::string> transient_error_ids_;
 
   // Control of when/if we return conflicts.
   bool conflict_all_commits_;
diff --git a/components/sync/test/engine/mock_model_type_worker.cc b/components/sync/test/engine/mock_model_type_worker.cc
index e32a928..2a8f9ee9 100644
--- a/components/sync/test/engine/mock_model_type_worker.cc
+++ b/components/sync/test/engine/mock_model_type_worker.cc
@@ -7,10 +7,10 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/check_op.h"
 #include "base/notreached.h"
 #include "components/sync/base/model_type.h"
-#include "components/sync/syncable/syncable_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace syncer {
diff --git a/components/sync/test/fake_sync_encryption_handler.cc b/components/sync/test/fake_sync_encryption_handler.cc
index 8b5d08b..9d6eb3fd 100644
--- a/components/sync/test/fake_sync_encryption_handler.cc
+++ b/components/sync/test/fake_sync_encryption_handler.cc
@@ -7,7 +7,6 @@
 #include "base/base64.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/protocol/nigori_specifics.pb.h"
-#include "components/sync/syncable/nigori_util.h"
 
 namespace syncer {
 
diff --git a/components/sync_bookmarks/bookmark_model_merger.cc b/components/sync_bookmarks/bookmark_model_merger.cc
index ece58f8..f729d2ea 100644
--- a/components/sync_bookmarks/bookmark_model_merger.cc
+++ b/components/sync_bookmarks/bookmark_model_merger.cc
@@ -792,8 +792,6 @@
   // Since we are merging top down, parent entity must be tracked.
   DCHECK(parent_entity);
 
-  // Similar to the directory implementation here:
-  // https://cs.chromium.org/chromium/src/components/sync/syncable/mutable_entry.cc?l=237&gsn=CreateEntryKernel
   // Assign a temp server id for the entity. Will be overridden by the actual
   // server id upon receiving commit response.
   const bookmarks::BookmarkNode* node = parent->children()[index].get();
diff --git a/components/sync_bookmarks/bookmark_model_observer_impl.cc b/components/sync_bookmarks/bookmark_model_observer_impl.cc
index 5fd0f712..9044378 100644
--- a/components/sync_bookmarks/bookmark_model_observer_impl.cc
+++ b/components/sync_bookmarks/bookmark_model_observer_impl.cc
@@ -90,8 +90,6 @@
   // Should be removed after figuring out the reason for the crash.
   CHECK(parent_entity);
 
-  // Similar to the directory implementation here:
-  // https://cs.chromium.org/chromium/src/components/sync/syncable/mutable_entry.cc?l=237&gsn=CreateEntryKernel
   // Assign a temp server id for the entity. Will be overriden by the actual
   // server id upon receiving commit response.
   DCHECK(base::IsValidGUIDOutputString(node->guid()));
diff --git a/components/webrtc/media_stream_devices_controller.cc b/components/webrtc/media_stream_devices_controller.cc
index 461fe000..8af62b39 100644
--- a/components/webrtc/media_stream_devices_controller.cc
+++ b/components/webrtc/media_stream_devices_controller.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/metrics/histogram_functions.h"
 #include "components/permissions/permission_manager.h"
 #include "components/permissions/permission_result.h"
 #include "components/permissions/permissions_client.h"
@@ -112,13 +113,15 @@
     will_prompt_for_video =
         permission_status.content_setting == CONTENT_SETTING_ASK;
 
+    bool has_pan_tilt_zoom_camera = controller->HasAvailableDevices(
+        ContentSettingsType::CAMERA_PAN_TILT_ZOOM,
+        request.requested_video_device_id);
+    base::UmaHistogramBoolean("WebRTC.MediaStreamDevices.HasPanTiltZoomCamera",
+                              has_pan_tilt_zoom_camera);
     // Request CAMERA_PAN_TILT_ZOOM only if the the website requested
     // the pan-tilt-zoom permission and there are suitable PTZ capable devices
     // available.
-    if (request.request_pan_tilt_zoom_permission &&
-        controller->HasAvailableDevices(
-            ContentSettingsType::CAMERA_PAN_TILT_ZOOM,
-            request.requested_video_device_id)) {
+    if (request.request_pan_tilt_zoom_permission && has_pan_tilt_zoom_camera) {
       permissions::PermissionResult permission_status =
           permission_manager->GetPermissionStatusForFrame(
               ContentSettingsType::CAMERA_PAN_TILT_ZOOM, rfh,
@@ -551,8 +554,7 @@
       continue;
     }
     if (content_type == ContentSettingsType::CAMERA_PAN_TILT_ZOOM &&
-        device.pan_tilt_zoom_supported.has_value() &&
-        !device.pan_tilt_zoom_supported.value()) {
+        !device.pan_tilt_zoom_supported) {
       continue;
     }
     return true;
diff --git a/content/browser/DEPS b/content/browser/DEPS
index b921101..f47e00f 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -142,13 +142,6 @@
   "browsing_data_(filter_builder|remover)_impl_unittest\.cc": [
     "+services/network/cookie_manager.h",
   ],
-  "cross_origin_read_blocking_checker\.(cc|h)": [
-    # TODO(crbug.com/1049894): Remove.
-    "+services/network/cross_origin_read_blocking.h",
-  ],
-  "cross_site_document_blocking_browsertest\.cc": [
-    "+services/network/cross_origin_read_blocking.h",
-  ],
   "navigation_url_loader_impl_unittest\.cc": [
     "+services/network/resource_scheduler/resource_scheduler_client.h",
     "+services/network/url_loader.h",
@@ -163,9 +156,6 @@
   "signed_exchange_handler_unittest\.cc": [
     "+services/network/network_context.h",
   ],
-  "signed_exchange_subresource_prefetch_browsertest\.cc": [
-    "+services/network/cross_origin_read_blocking.h",
-  ],
   # SiteInstance and BrowsingInstance should not depend on the types of things
   # that rely on them, like RenderFrameHostImpl or WebContentsImpl.
   "(site_instance_impl|browsing_instance)\.(cc|h)": [
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc
index 923f732..aaf0c392 100644
--- a/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -3678,57 +3678,62 @@
   Microsoft::WRL::ComPtr<IAccessibleText> input_text;
   SetUpInputField(&input_text);
 
-  // Trailing punctuation should be included as part of the previous word.
-  CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
-  CheckTextAtOffset(input_text, 2, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
+  // Trailing punctuation should not be included as part of the previous word.
+  CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_WORD, 0, 3, L"Moz");
+  CheckTextAtOffset(input_text, 2, IA2_TEXT_BOUNDARY_WORD, 0, 3, L"Moz");
 
   // If the offset is at the punctuation, it should return
-  // the previous word.
-  CheckTextAtOffset(input_text, 3, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
+  // the punctuation as a word.
+  CheckTextAtOffset(input_text, 3, IA2_TEXT_BOUNDARY_WORD, 3, 4, L"/");
 
   // Numbers with a decimal point ("." for U.S), should be treated as one word.
-  // Also, trailing punctuation that occurs after empty space should be part of
-  // the word. ("5.0 (" and not "5.0 ".)
-  CheckTextAtOffset(input_text, 4, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
-  CheckTextAtOffset(input_text, 5, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
-  CheckTextAtOffset(input_text, 6, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
-  CheckTextAtOffset(input_text, 7, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
+  // Also, trailing punctuation that occurs after empty space should not be part
+  // of the word. ("5.0 " and not "5.0 (".)
+  CheckTextAtOffset(input_text, 4, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+  CheckTextAtOffset(input_text, 5, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+  CheckTextAtOffset(input_text, 6, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+  CheckTextAtOffset(input_text, 7, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
 
   // Leading punctuation should not be included with the word after it.
-  CheckTextAtOffset(input_text, 8, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
+  CheckTextAtOffset(input_text, 8, IA2_TEXT_BOUNDARY_WORD, 8, 9, L"(");
   CheckTextAtOffset(input_text, 11, IA2_TEXT_BOUNDARY_WORD, 9, 12, L"ST ");
 
   // Numbers separated from letters with trailing punctuation should
-  // be split into two words. Same for abreviations like "i.e.".
-  CheckTextAtOffset(input_text, 12, IA2_TEXT_BOUNDARY_WORD, 12, 14, L"6.");
-  CheckTextAtOffset(input_text, 15, IA2_TEXT_BOUNDARY_WORD, 14, 17, L"x; ");
+  // be split into multiple words. Same for abbreviations like "i.e.".
+  CheckTextAtOffset(input_text, 12, IA2_TEXT_BOUNDARY_WORD, 12, 13, L"6");
+  CheckTextAtOffset(input_text, 13, IA2_TEXT_BOUNDARY_WORD, 13, 14, L".");
+  CheckTextAtOffset(input_text, 14, IA2_TEXT_BOUNDARY_WORD, 14, 15, L"x");
+  CheckTextAtOffset(input_text, 15, IA2_TEXT_BOUNDARY_WORD, 15, 17, L"; ");
 
   // Words with numbers should be treated like ordinary words.
-  CheckTextAtOffset(input_text, 17, IA2_TEXT_BOUNDARY_WORD, 17, 24, L"WWW33) ");
-  CheckTextAtOffset(input_text, 23, IA2_TEXT_BOUNDARY_WORD, 17, 24, L"WWW33) ");
+  CheckTextAtOffset(input_text, 17, IA2_TEXT_BOUNDARY_WORD, 17, 22, L"WWW33");
+  CheckTextAtOffset(input_text, 23, IA2_TEXT_BOUNDARY_WORD, 22, 24, L") ");
 
   // Multiple trailing empty spaces should be part of the word preceding it.
-  CheckTextAtOffset(input_text, 28, IA2_TEXT_BOUNDARY_WORD, 24, 33,
-                    L"WebKit  \"");
-  CheckTextAtOffset(input_text, 31, IA2_TEXT_BOUNDARY_WORD, 24, 33,
-                    L"WebKit  \"");
-  CheckTextAtOffset(input_text, 32, IA2_TEXT_BOUNDARY_WORD, 24, 33,
-                    L"WebKit  \"");
+  CheckTextAtOffset(input_text, 28, IA2_TEXT_BOUNDARY_WORD, 24, 32,
+                    L"WebKit  ");
+  CheckTextAtOffset(input_text, 31, IA2_TEXT_BOUNDARY_WORD, 24, 32,
+                    L"WebKit  ");
+  CheckTextAtOffset(input_text, 32, IA2_TEXT_BOUNDARY_WORD, 32, 33, L"\"");
 
-  // Leading punctuation such as quotation marks should not be part of the word.
-  CheckTextAtOffset(input_text, 33, IA2_TEXT_BOUNDARY_WORD, 33, 40, L"KHTML, ");
-  CheckTextAtOffset(input_text, 38, IA2_TEXT_BOUNDARY_WORD, 33, 40, L"KHTML, ");
+  // Leading and trailing punctuation such as quotation marks should not be part
+  // of the word.
+  CheckTextAtOffset(input_text, 33, IA2_TEXT_BOUNDARY_WORD, 33, 38, L"KHTML");
+  CheckTextAtOffset(input_text, 38, IA2_TEXT_BOUNDARY_WORD, 38, 40, L", ");
+  CheckTextAtOffset(input_text, 39, IA2_TEXT_BOUNDARY_WORD, 38, 40, L", ");
 
-  // Trailing final punctuation should be part of the last word.
+  // Trailing final punctuation should not be part of the last word.
   int contents_string_length = int{InputContentsString().size()};
-  CheckTextAtOffset(input_text, 41, IA2_TEXT_BOUNDARY_WORD, 40,
-                    contents_string_length, L"like\".");
-  CheckTextAtOffset(input_text, 45, IA2_TEXT_BOUNDARY_WORD, 40,
-                    contents_string_length, L"like\".");
+  CheckTextAtOffset(input_text, 40, IA2_TEXT_BOUNDARY_WORD, 40, 44, L"like");
+  CheckTextAtOffset(input_text, 41, IA2_TEXT_BOUNDARY_WORD, 40, 44, L"like");
+  CheckTextAtOffset(input_text, 44, IA2_TEXT_BOUNDARY_WORD, 44,
+                    contents_string_length, L"\".");
+  CheckTextAtOffset(input_text, 45, IA2_TEXT_BOUNDARY_WORD, 44,
+                    contents_string_length, L"\".");
 
   // Test special offsets.
   CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET, IA2_TEXT_BOUNDARY_WORD,
-                    40, contents_string_length, L"like\".");
+                    44, contents_string_length, L"\".");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
@@ -3736,62 +3741,64 @@
   Microsoft::WRL::ComPtr<IAccessibleText> textarea_text;
   SetUpTextareaField(&textarea_text);
 
-  // Trailing punctuation should be included as part of the previous word.
-  CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
-  CheckTextAtOffset(textarea_text, 2, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
+  // Trailing punctuation should not be included as part of the previous word.
+  CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_WORD, 0, 3, L"Moz");
+  CheckTextAtOffset(textarea_text, 2, IA2_TEXT_BOUNDARY_WORD, 0, 3, L"Moz");
 
   // If the offset is at the punctuation, it should return
-  // the previous word.
-  CheckTextAtOffset(textarea_text, 3, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
+  // the punctuation as a word.
+  CheckTextAtOffset(textarea_text, 3, IA2_TEXT_BOUNDARY_WORD, 3, 4, L"/");
 
   // Numbers with a decimal point ("." for U.S), should be treated as one word.
-  // Also, trailing punctuation that occurs after empty space should be part of
-  // the word. ("5.0 (" and not "5.0 ".)
-  CheckTextAtOffset(textarea_text, 4, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
-  CheckTextAtOffset(textarea_text, 5, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
-  CheckTextAtOffset(textarea_text, 6, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
-  CheckTextAtOffset(textarea_text, 7, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
+  // Also, trailing punctuation that occurs after empty space should not be part
+  // of the word. ("5.0 " and not "5.0 (".)
+  CheckTextAtOffset(textarea_text, 4, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+  CheckTextAtOffset(textarea_text, 5, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+  CheckTextAtOffset(textarea_text, 6, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+  CheckTextAtOffset(textarea_text, 7, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
 
   // Leading punctuation should not be included with the word after it.
-  CheckTextAtOffset(textarea_text, 8, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
+  CheckTextAtOffset(textarea_text, 8, IA2_TEXT_BOUNDARY_WORD, 8, 9, L"(");
   CheckTextAtOffset(textarea_text, 11, IA2_TEXT_BOUNDARY_WORD, 9, 12, L"ST ");
 
   // Numbers separated from letters with trailing punctuation should
-  // be split into two words. Same for abreviations like "i.e.".
-  CheckTextAtOffset(textarea_text, 12, IA2_TEXT_BOUNDARY_WORD, 12, 14, L"6.");
-  CheckTextAtOffset(textarea_text, 15, IA2_TEXT_BOUNDARY_WORD, 14, 17, L"x; ");
+  // be split into multiple words. Same for abbreviations like "i.e.".
+  CheckTextAtOffset(textarea_text, 12, IA2_TEXT_BOUNDARY_WORD, 12, 13, L"6");
+  CheckTextAtOffset(textarea_text, 13, IA2_TEXT_BOUNDARY_WORD, 13, 14, L".");
+  CheckTextAtOffset(textarea_text, 14, IA2_TEXT_BOUNDARY_WORD, 14, 15, L"x");
+  CheckTextAtOffset(textarea_text, 15, IA2_TEXT_BOUNDARY_WORD, 15, 17, L"; ");
 
   // Words with numbers should be treated like ordinary words.
-  CheckTextAtOffset(textarea_text, 17, IA2_TEXT_BOUNDARY_WORD, 17, 24,
-                    L"WWW33)\n");
-  CheckTextAtOffset(textarea_text, 23, IA2_TEXT_BOUNDARY_WORD, 17, 24,
-                    L"WWW33)\n");
+  CheckTextAtOffset(textarea_text, 17, IA2_TEXT_BOUNDARY_WORD, 17, 22,
+                    L"WWW33");
+  CheckTextAtOffset(textarea_text, 23, IA2_TEXT_BOUNDARY_WORD, 22, 24, L")\n");
 
   // Multiple trailing empty spaces should be part of the word preceding it.
-  CheckTextAtOffset(textarea_text, 28, IA2_TEXT_BOUNDARY_WORD, 24, 33,
-                    L"WebKit \n\"");
-  CheckTextAtOffset(textarea_text, 31, IA2_TEXT_BOUNDARY_WORD, 24, 33,
-                    L"WebKit \n\"");
-  CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_WORD, 24, 33,
-                    L"WebKit \n\"");
+  CheckTextAtOffset(textarea_text, 28, IA2_TEXT_BOUNDARY_WORD, 24, 32,
+                    L"WebKit \n");
+  CheckTextAtOffset(textarea_text, 31, IA2_TEXT_BOUNDARY_WORD, 24, 32,
+                    L"WebKit \n");
+  CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_WORD, 32, 33, L"\"");
 
-  // Leading punctuation such as quotation marks should not be part of the word.
-  CheckTextAtOffset(textarea_text, 33, IA2_TEXT_BOUNDARY_WORD, 33, 40,
-                    L"KHTML, ");
-  CheckTextAtOffset(textarea_text, 38, IA2_TEXT_BOUNDARY_WORD, 33, 40,
-                    L"KHTML, ");
+  // Leading and trailing punctuation such as quotation marks should not be part
+  // of the word.
+  CheckTextAtOffset(textarea_text, 33, IA2_TEXT_BOUNDARY_WORD, 33, 38,
+                    L"KHTML");
+  CheckTextAtOffset(textarea_text, 38, IA2_TEXT_BOUNDARY_WORD, 38, 40, L", ");
+  CheckTextAtOffset(textarea_text, 39, IA2_TEXT_BOUNDARY_WORD, 38, 40, L", ");
 
-  // Trailing final punctuation should be part of the last word.
+  // Trailing final punctuation should not be part of the last word.
   int contents_string_length = int{InputContentsString().size()};
-  CheckTextAtOffset(textarea_text, 41, IA2_TEXT_BOUNDARY_WORD, 40,
-                    contents_string_length, L"like\".");
-  CheckTextAtOffset(textarea_text, 45, IA2_TEXT_BOUNDARY_WORD, 40,
-                    contents_string_length, L"like\".");
+  CheckTextAtOffset(textarea_text, 40, IA2_TEXT_BOUNDARY_WORD, 40, 44, L"like");
+  CheckTextAtOffset(textarea_text, 41, IA2_TEXT_BOUNDARY_WORD, 40, 44, L"like");
+  CheckTextAtOffset(textarea_text, 44, IA2_TEXT_BOUNDARY_WORD, 44,
+                    contents_string_length, L"\".");
+  CheckTextAtOffset(textarea_text, 45, IA2_TEXT_BOUNDARY_WORD, 44,
+                    contents_string_length, L"\".");
 
   // Test special offsets.
   CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET,
-                    IA2_TEXT_BOUNDARY_WORD, 40, contents_string_length,
-                    L"like\".");
+                    IA2_TEXT_BOUNDARY_WORD, 44, contents_string_length, L"\".");
 }
 
 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
@@ -3800,23 +3807,12 @@
   SetUpSampleParagraph(&paragraph_text);
   base::string16 embedded_character(
       1, BrowserAccessibilityComWin::kEmbeddedCharacter);
-  std::vector<std::wstring> words;
-  words.push_back(L"Game ");
-  words.push_back(L"theory ");
-  words.push_back(L"is \"");
-  words.push_back(L"the ");
-  words.push_back(L"study ");
-  words.push_back(L"of ");
-  words.push_back(embedded_character);
-  words.push_back(L"of ");
-  words.push_back(L"conflict ");
-  words.push_back(L"and\n");
-  words.push_back(L"cooperation ");
-  words.push_back(L"between ");
-  words.push_back(L"intelligent ");
-  words.push_back(L"rational ");
-  words.push_back(L"decision-");
-  words.push_back(L"makers.\"");
+  std::vector<std::wstring> words = {
+      L"Game ",    L"theory ",      L"is ",       L"\"",
+      L"the ",     L"study ",       L"of ",       embedded_character,
+      L"of ",      L"conflict ",    L"and\n",     L"cooperation ",
+      L"between ", L"intelligent ", L"rational ", L"decision",
+      L"-",        L"makers",       L".\""};
 
   // Try to retrieve one word after another.
   LONG word_start_offset = 0;
diff --git a/content/browser/accessibility/android_granularity_movement_browsertest.cc b/content/browser/accessibility/android_granularity_movement_browsertest.cc
index 196d21f..5d8fd52 100644
--- a/content/browser/accessibility/android_granularity_movement_browsertest.cc
+++ b/content/browser/accessibility/android_granularity_movement_browsertest.cc
@@ -160,10 +160,10 @@
   BrowserAccessibility* button = button_container->PlatformGetChild(0);
   ASSERT_EQ(0U, button->PlatformChildCount());
 
-  ASSERT_EQ(base::ASCIIToUTF16("'O', 'n', 'e', ',', ' ', 't', 'w', 'o', "
+  EXPECT_EQ(base::ASCIIToUTF16("'O', 'n', 'e', ',', ' ', 't', 'w', 'o', "
                                "',', ' ', 't', 'h', 'r', 'e', 'e', '!'"),
             TraverseNodeAtGranularity(para, GRANULARITY_CHARACTER));
-  ASSERT_EQ(
+  EXPECT_EQ(
       base::ASCIIToUTF16("'S', 'e', 'v', 'e', 'n', ',', ' ', 'e', 'i', 'g', "
                          "'h', 't', ',', ' ', 'n', 'i', 'n', 'e', '!'"),
       TraverseNodeAtGranularity(button, GRANULARITY_CHARACTER));
@@ -187,9 +187,9 @@
   BrowserAccessibility* button = button_container->PlatformGetChild(0);
   ASSERT_EQ(0U, button->PlatformChildCount());
 
-  ASSERT_EQ(base::ASCIIToUTF16("'One', 'two', 'three'"),
+  EXPECT_EQ(base::ASCIIToUTF16("'One', ',', 'two', ',', 'three', '!'"),
             TraverseNodeAtGranularity(para, GRANULARITY_WORD));
-  ASSERT_EQ(base::ASCIIToUTF16("'Seven', 'eight', 'nine'"),
+  EXPECT_EQ(base::ASCIIToUTF16("'Seven', 'eight', 'nine'"),
             TraverseNodeAtGranularity(button, GRANULARITY_WORD));
 }
 
@@ -204,7 +204,7 @@
   BrowserAccessibility* pre = root->PlatformGetChild(0);
   ASSERT_EQ(0U, pre->PlatformChildCount());
 
-  ASSERT_EQ(base::ASCIIToUTF16("'One,', 'two,', 'three!'"),
+  EXPECT_EQ(base::ASCIIToUTF16("'One,', 'two,', 'three!'"),
             TraverseNodeAtGranularity(pre, GRANULARITY_LINE));
 }
 
diff --git a/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc b/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
index 164a92b..6777605 100644
--- a/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
+++ b/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
@@ -2237,30 +2237,30 @@
 
 IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
                        EntireMarkupSuccessiveMoveByWord) {
-  AssertMoveByUnitForMarkup(TextUnit_Word, "this is a test.",
-                            {L"this ", L"is ", L"a ", L"test."});
+  AssertMoveByUnitForMarkup(TextUnit_Word, "This is a test.",
+                            {L"This ", L"is ", L"a ", L"test", L"."});
 
   AssertMoveByUnitForMarkup(TextUnit_Word,
-                            "    this    is      a      test.    ",
-                            {L"this ", L"is ", L"a ", L"test."});
+                            "    This    is      a      test.    ",
+                            {L"This ", L"is ", L"a ", L"test", L"."});
 
   AssertMoveByUnitForMarkup(
       TextUnit_Word, "It said: to be continued...",
-      {L"It ", L"said: ", L"to ", L"be ", L"continued..."});
+      {L"It ", L"said", L": ", L"to ", L"be ", L"continued", L"..."});
 
   AssertMoveByUnitForMarkup(TextUnit_Word,
-                            "a <a>link with multiple words</a> and text after.",
-                            {L"a ", L"link ", L"with ", L"multiple ", L"words",
-                             L"and ", L"text ", L"after."});
+                            "A <a>link with multiple words</a> and text after.",
+                            {L"A ", L"link ", L"with ", L"multiple ", L"words",
+                             L"and ", L"text ", L"after", L"."});
 
   AssertMoveByUnitForMarkup(TextUnit_Word,
-                            "a <span aria-hidden='true'>span with ignored "
+                            "A <span aria-hidden='true'>span with ignored "
                             "text</span> and text after.",
-                            {L"a ", L"and ", L"text ", L"after."});
+                            {L"A ", L"and ", L"text ", L"after", L"."});
 
   AssertMoveByUnitForMarkup(
       TextUnit_Word, "<ol><li>item one</li><li>item two</li></ol>",
-      {L"1. ", L"item ", L"one", L"2. ", L"item ", L"two"});
+      {L"1", L". ", L"item ", L"one", L"2", L". ", L"item ", L"two"});
 
   // The following test should be enabled when crbug.com/1028830 is fixed.
   // AssertMoveByUnitForMarkup(TextUnit_Word,
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc
index 8861ca9d..120aefd 100644
--- a/content/browser/devtools/devtools_instrumentation.cc
+++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -205,8 +205,8 @@
             .SetDetails(issueDetails.Build())
             .Build();
 
-    DispatchToAgents(ftn, &protocol::AuditsHandler::OnIssueAdded,
-                     inspector_issue.get());
+    ReportBrowserInitiatedIssue(ftn->current_frame_host(),
+                                inspector_issue.get());
   }
 
   DispatchToAgents(ftn, &protocol::NetworkHandler::LoadingComplete, id,
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 6f13dd3..e148ada 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -726,7 +726,7 @@
     network::mojom::CrossOriginOpenerPolicyValue initiator_coop,
     network::mojom::CrossOriginEmbedderPolicyValue initiator_coep,
     const url::Origin& initiator_origin,
-    bool is_initiator_aboutblank,
+    bool is_initial_navigation,
     network::mojom::CrossOriginOpenerPolicyValue destination_coop,
     network::mojom::CrossOriginEmbedderPolicyValue destination_coep,
     const url::Origin& destination_origin) {
@@ -756,7 +756,7 @@
   // ```
   // [1]
   // https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e#changes-to-navigation
-  if (is_initiator_aboutblank &&
+  if (is_initial_navigation &&
       initiator_coop == CrossOriginOpenerPolicyValue::kSameOriginAllowPopups &&
       destination_coop == CrossOriginOpenerPolicyValue::kUnsafeNone) {
     return false;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index d2866960..1ff08ab 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -775,7 +775,7 @@
 
 }  // namespace
 
-bool CreateNewHostForCrashedFrame() {
+bool ShouldCreateNewHostForCrashedFrame() {
   return GetRenderDocumentLevel() >= RenderDocumentLevel::kCrashedFrame;
 }
 
@@ -1941,7 +1941,7 @@
   SetLastCommittedUrl(GURL());
   web_bundle_handle_.reset();
 
-  must_be_replaced_ = CreateNewHostForCrashedFrame();
+  must_be_replaced_ = ShouldCreateNewHostForCrashedFrame();
   has_committed_any_navigation_ = false;
 
 #if defined(OS_ANDROID)
@@ -2920,7 +2920,7 @@
   } else {
     // RenderDocument: After a local<->local swap, this function is called with
     // a null |proxy|.
-    CHECK(CreateNewHostForSameSiteSubframe());
+    CHECK(ShouldCreateNewHostForSameSiteSubframe());
 
     // The unload handlers already ran for this document during the
     // local<->local swap. Hence, there is no need to send
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index bd4fdba..abd9a7433 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -223,7 +223,7 @@
 
 // True if feature-flags indicate that we should replace crashed RFHs with new
 // instances rather than reusing them. See http://crbug.com/981339.
-CONTENT_EXPORT bool CreateNewHostForCrashedFrame();
+CONTENT_EXPORT bool ShouldCreateNewHostForCrashedFrame();
 
 // To be called when a RenderFrameHostImpl receives an event.
 // Provides the host, the event fired, and which node id the event was for.
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index bd9ebc0..0016807 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -692,8 +692,8 @@
 
   // Force using a different RenderFrameHost when RenderDocument is enabled.
   // TODO(arthursonzogni, fergal): Add support for the main frame.
-  if (CreateNewHostForSameSiteSubframe() && !frame_tree_node_->IsMainFrame() &&
-      !request->IsSameDocument() &&
+  if (ShouldCreateNewHostForSameSiteSubframe() &&
+      !frame_tree_node_->IsMainFrame() && !request->IsSameDocument() &&
       render_frame_host_->has_committed_any_navigation()) {
     use_current_rfh = false;
   }
@@ -2072,7 +2072,7 @@
   // [1] http://crbug.com/936696
   DCHECK(old_instance != new_instance ||
          render_frame_host_->must_be_replaced() ||
-         CreateNewHostForSameSiteSubframe());
+         ShouldCreateNewHostForSameSiteSubframe());
 
   // The process for the new SiteInstance may (if we're sharing a process with
   // another host that already initialized it) or may not (we have our own
@@ -2114,7 +2114,7 @@
   // [1] http://crbug.com/936696
   DCHECK(render_frame_host_->GetSiteInstance() != instance ||
          render_frame_host_->must_be_replaced() ||
-         CreateNewHostForSameSiteSubframe());
+         ShouldCreateNewHostForSameSiteSubframe());
 
   std::unique_ptr<RenderFrameHostImpl> new_render_frame_host =
       CreateRenderFrameHost(CreateFrameCase::kCreateSpeculative, instance,
@@ -2435,17 +2435,17 @@
     if (current_frame_host()->IsRenderFrameLive()) {
       // The new frame will replace an existing frame in the renderer. For now
       // this can only be when RenderDocument-subframe is enabled.
-      DCHECK(CreateNewHostForSameSiteSubframe());
+      DCHECK(ShouldCreateNewHostForSameSiteSubframe());
       DCHECK_NE(render_frame_host, current_frame_host());
       return current_frame_host()->GetRoutingID();
     } else {
       // The renderer crashed and there is no previous proxy or previous frame
       // in the renderer to be replaced.
       if (current_frame_host()->must_be_replaced()) {
-        DCHECK(CreateNewHostForCrashedFrame());
+        DCHECK(ShouldCreateNewHostForCrashedFrame());
         DCHECK_NE(render_frame_host, current_frame_host());
       } else {
-        DCHECK(!CreateNewHostForCrashedFrame());
+        DCHECK(!ShouldCreateNewHostForCrashedFrame());
         DCHECK_EQ(render_frame_host, current_frame_host());
       }
       return MSG_ROUTING_NONE;
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index 8be9a86..b7a71b5 100644
--- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -7403,7 +7403,7 @@
   if (!AreAllSitesIsolatedForTesting())
     return;
   // TODO(https://crbug.com/1064944): Fix this test and remove this.
-  if (CreateNewHostForSameSiteSubframe())
+  if (ShouldCreateNewHostForSameSiteSubframe())
     return;
 
   // 1. Navigate to A1(B2, B3(B4), C5).
@@ -7487,8 +7487,8 @@
   ASSERT_EQ(0u, b3->child_count());
 
   EXPECT_FALSE(a1->must_be_replaced());
-  EXPECT_EQ(b2->must_be_replaced(), CreateNewHostForCrashedFrame());
-  EXPECT_EQ(b3->must_be_replaced(), CreateNewHostForCrashedFrame());
+  EXPECT_EQ(b2->must_be_replaced(), ShouldCreateNewHostForCrashedFrame());
+  EXPECT_EQ(b3->must_be_replaced(), ShouldCreateNewHostForCrashedFrame());
   EXPECT_FALSE(c5->must_be_replaced());
 
   EXPECT_EQ(2u, proxy_count(a1));
@@ -7509,7 +7509,7 @@
   // 3. Reload B2, B6 is created.
   NavigateFrameToURL(b2->frame_tree_node(), b2_url);
 
-  if (CreateNewHostForCrashedFrame()) {
+  if (ShouldCreateNewHostForCrashedFrame()) {
     // B2 has been replaced
     EXPECT_NE(b2_routing_id,
               a1->child_at(0)->current_frame_host()->routing_id());
@@ -7521,7 +7521,7 @@
   // B3 hasn't been replaced.
   EXPECT_EQ(b3, a1->child_at(1)->current_frame_host());
   RenderFrameHostImpl* b6 = a1->child_at(0)->current_frame_host();
-  EXPECT_EQ(b3->must_be_replaced(), CreateNewHostForCrashedFrame());
+  EXPECT_EQ(b3->must_be_replaced(), ShouldCreateNewHostForCrashedFrame());
   EXPECT_FALSE(b6->must_be_replaced());
 
   EXPECT_EQ(a_site_instance, a1->GetSiteInstance());
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc
index d7388d69..4d1a5730 100644
--- a/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -291,26 +291,26 @@
 };
 
 TEST_F(RenderDocumentFeatureTest, FeatureDisabled) {
-  EXPECT_FALSE(CreateNewHostForCrashedFrame());
-  EXPECT_FALSE(CreateNewHostForSameSiteSubframe());
+  EXPECT_FALSE(ShouldCreateNewHostForCrashedFrame());
+  EXPECT_FALSE(ShouldCreateNewHostForSameSiteSubframe());
 }
 
 TEST_F(RenderDocumentFeatureTest, LevelDisabled) {
   SetLevel(RenderDocumentLevel::kDisabled);
-  EXPECT_FALSE(CreateNewHostForCrashedFrame());
-  EXPECT_FALSE(CreateNewHostForSameSiteSubframe());
+  EXPECT_FALSE(ShouldCreateNewHostForCrashedFrame());
+  EXPECT_FALSE(ShouldCreateNewHostForSameSiteSubframe());
 }
 
 TEST_F(RenderDocumentFeatureTest, LevelCrashed) {
   SetLevel(RenderDocumentLevel::kCrashedFrame);
-  EXPECT_TRUE(CreateNewHostForCrashedFrame());
-  EXPECT_FALSE(CreateNewHostForSameSiteSubframe());
+  EXPECT_TRUE(ShouldCreateNewHostForCrashedFrame());
+  EXPECT_FALSE(ShouldCreateNewHostForSameSiteSubframe());
 }
 
 TEST_F(RenderDocumentFeatureTest, LevelSub) {
   SetLevel(RenderDocumentLevel::kSubframe);
-  EXPECT_TRUE(CreateNewHostForCrashedFrame());
-  EXPECT_TRUE(CreateNewHostForSameSiteSubframe());
+  EXPECT_TRUE(ShouldCreateNewHostForCrashedFrame());
+  EXPECT_TRUE(ShouldCreateNewHostForSameSiteSubframe());
 }
 
 class RenderFrameHostManagerTest
@@ -1977,7 +1977,7 @@
   EXPECT_FALSE(contents2->GetMainFrame()->IsRenderFrameLive());
   EXPECT_EQ(contents1->GetSiteInstance(), contents2->GetSiteInstance());
   EXPECT_EQ((bool)contents1->GetMainFrame()->GetView(),
-            CreateNewHostForCrashedFrame());
+            ShouldCreateNewHostForCrashedFrame());
   EXPECT_FALSE(contents2->GetMainFrame()->GetView());
 
   // |contents1| creates an out of process iframe.
diff --git a/content/browser/loader/cross_origin_read_blocking_checker.cc b/content/browser/loader/cross_origin_read_blocking_checker.cc
index 003f890..cbdec744 100644
--- a/content/browser/loader/cross_origin_read_blocking_checker.cc
+++ b/content/browser/loader/cross_origin_read_blocking_checker.cc
@@ -9,7 +9,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "net/base/io_buffer.h"
 #include "net/base/mime_sniffer.h"
-#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 #include "storage/browser/blob/blob_data_handle.h"
diff --git a/content/browser/loader/cross_origin_read_blocking_checker.h b/content/browser/loader/cross_origin_read_blocking_checker.h
index b6ec7d85..4b82875 100644
--- a/content/browser/loader/cross_origin_read_blocking_checker.h
+++ b/content/browser/loader/cross_origin_read_blocking_checker.h
@@ -9,7 +9,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "net/base/net_errors.h"
-#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
 #include "services/network/public/mojom/url_response_head.mojom-forward.h"
 
 namespace net {
diff --git a/content/browser/loader/cross_site_document_blocking_browsertest.cc b/content/browser/loader/cross_site_document_blocking_browsertest.cc
index bc26b11..247b490 100644
--- a/content/browser/loader/cross_site_document_blocking_browsertest.cc
+++ b/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -47,7 +47,7 @@
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "net/test/embedded_test_server/controllable_http_response.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
-#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/initiator_lock_compatibility.h"
 #include "services/network/public/cpp/network_switches.h"
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc
index 16ebbfb9d..ec711b4 100644
--- a/content/browser/media/media_web_contents_observer.cc
+++ b/content/browser/media/media_web_contents_observer.cc
@@ -217,14 +217,7 @@
     int delegate_id,
     bool has_video,
     bool has_audio,
-    bool is_remote,
     media::MediaContentType media_content_type) {
-  // TODO(mlamouri): this used to be done to avoid video wake lock. However, it
-  // was doing much more. Removing will be done in a follow-up CL to avoid
-  // regressions to be pinpoint to the wake lock refactor.
-  if (is_remote)
-    return;
-
   const MediaPlayerId id(render_frame_host, delegate_id);
   if (has_audio)
     AddMediaPlayerEntry(id, &active_audio_players_);
@@ -233,7 +226,7 @@
     AddMediaPlayerEntry(id, &active_video_players_);
 
   if (!session_controllers_manager_.RequestPlay(
-          id, has_audio, is_remote, media_content_type, has_video)) {
+          id, has_audio, media_content_type, has_video)) {
     return;
   }
 
diff --git a/content/browser/media/media_web_contents_observer.h b/content/browser/media/media_web_contents_observer.h
index 36b7d7a7..f2a6d09 100644
--- a/content/browser/media/media_web_contents_observer.h
+++ b/content/browser/media/media_web_contents_observer.h
@@ -121,7 +121,6 @@
                       int delegate_id,
                       bool has_video,
                       bool has_audio,
-                      bool is_remote,
                       media::MediaContentType media_content_type);
   void OnMediaEffectivelyFullscreenChanged(
       RenderFrameHost* render_frame_host,
diff --git a/content/browser/media/session/media_session_controller.cc b/content/browser/media/session/media_session_controller.cc
index 323918c..80b791a 100644
--- a/content/browser/media/session/media_session_controller.cc
+++ b/content/browser/media/session/media_session_controller.cc
@@ -28,13 +28,11 @@
 
 bool MediaSessionController::Initialize(
     bool has_audio,
-    bool is_remote,
     media::MediaContentType media_content_type,
     media_session::MediaPosition* position,
     bool is_pip_available,
     bool has_video) {
   // Store these as we will need them later.
-  is_remote_ = is_remote;
   has_audio_ = has_audio;
   has_video_ = has_video;
   media_content_type_ = media_content_type;
@@ -170,9 +168,8 @@
   const bool has_audio =
       has_audio_ &&
       !media_web_contents_observer_->web_contents()->IsAudioMuted();
-  return !is_remote_ &&
-         (has_audio || media_web_contents_observer_->web_contents()
-                           ->HasPictureInPictureVideo());
+  return has_audio || media_web_contents_observer_->web_contents()
+                          ->HasPictureInPictureVideo();
 }
 
 void MediaSessionController::AddOrRemovePlayer() {
diff --git a/content/browser/media/session/media_session_controller.h b/content/browser/media/session/media_session_controller.h
index 92e200f..6b05a69 100644
--- a/content/browser/media/session/media_session_controller.h
+++ b/content/browser/media/session/media_session_controller.h
@@ -34,7 +34,6 @@
   // returns false.  May be called more than once; does nothing if none of the
   // input parameters have changed since the last call.
   bool Initialize(bool has_audio,
-                  bool is_remote,
                   media::MediaContentType media_content_type,
                   media_session::MediaPosition* position,
                   bool is_pip_available,
@@ -98,7 +97,6 @@
   bool has_session_ = false;
   bool has_audio_ = false;
   bool has_video_ = false;
-  bool is_remote_ = false;
   bool is_picture_in_picture_available_ = false;
   media::MediaContentType media_content_type_ =
       media::MediaContentType::Persistent;
diff --git a/content/browser/media/session/media_session_controller_unittest.cc b/content/browser/media/session/media_session_controller_unittest.cc
index e4476da..9dfb903 100644
--- a/content/browser/media/session/media_session_controller_unittest.cc
+++ b/content/browser/media/session/media_session_controller_unittest.cc
@@ -146,30 +146,22 @@
 };
 
 TEST_F(MediaSessionControllerTest, NoAudioNoSession) {
-  ASSERT_TRUE(controller_->Initialize(false, false,
-                                      media::MediaContentType::Persistent,
-                                      nullptr, false, false));
-  EXPECT_FALSE(media_session()->IsActive());
-  EXPECT_FALSE(media_session()->IsControllable());
-}
-
-TEST_F(MediaSessionControllerTest, IsRemoteNoSession) {
   ASSERT_TRUE(controller_->Initialize(
-      true, true, media::MediaContentType::Persistent, nullptr, false, false));
+      false, media::MediaContentType::Persistent, nullptr, false, false));
   EXPECT_FALSE(media_session()->IsActive());
   EXPECT_FALSE(media_session()->IsControllable());
 }
 
 TEST_F(MediaSessionControllerTest, TransientNoControllableSession) {
-  ASSERT_TRUE(controller_->Initialize(
-      true, false, media::MediaContentType::Transient, nullptr, false, false));
+  ASSERT_TRUE(controller_->Initialize(true, media::MediaContentType::Transient,
+                                      nullptr, false, false));
   EXPECT_TRUE(media_session()->IsActive());
   EXPECT_FALSE(media_session()->IsControllable());
 }
 
 TEST_F(MediaSessionControllerTest, BasicControls) {
-  ASSERT_TRUE(controller_->Initialize(
-      true, false, media::MediaContentType::Persistent, nullptr, false, false));
+  ASSERT_TRUE(controller_->Initialize(true, media::MediaContentType::Persistent,
+                                      nullptr, false, false));
   EXPECT_TRUE(media_session()->IsActive());
   EXPECT_TRUE(media_session()->IsControllable());
 
@@ -199,8 +191,8 @@
 }
 
 TEST_F(MediaSessionControllerTest, VolumeMultiplier) {
-  ASSERT_TRUE(controller_->Initialize(
-      true, false, media::MediaContentType::Persistent, nullptr, false, false));
+  ASSERT_TRUE(controller_->Initialize(true, media::MediaContentType::Persistent,
+                                      nullptr, false, false));
   EXPECT_TRUE(media_session()->IsActive());
   EXPECT_TRUE(media_session()->IsControllable());
 
@@ -216,8 +208,8 @@
 }
 
 TEST_F(MediaSessionControllerTest, ControllerSidePause) {
-  ASSERT_TRUE(controller_->Initialize(
-      true, false, media::MediaContentType::Persistent, nullptr, false, false));
+  ASSERT_TRUE(controller_->Initialize(true, media::MediaContentType::Persistent,
+                                      nullptr, false, false));
   EXPECT_TRUE(media_session()->IsActive());
   EXPECT_TRUE(media_session()->IsControllable());
 
@@ -227,29 +219,28 @@
   EXPECT_TRUE(media_session()->IsControllable());
 
   // Verify the next Initialize() call restores the session.
-  ASSERT_TRUE(controller_->Initialize(
-      true, false, media::MediaContentType::Persistent, nullptr, false, false));
+  ASSERT_TRUE(controller_->Initialize(true, media::MediaContentType::Persistent,
+                                      nullptr, false, false));
   EXPECT_TRUE(media_session()->IsActive());
   EXPECT_TRUE(media_session()->IsControllable());
 }
 
 TEST_F(MediaSessionControllerTest, Reinitialize) {
-  ASSERT_TRUE(controller_->Initialize(false, false,
-                                      media::MediaContentType::Persistent,
-                                      nullptr, false, false));
+  ASSERT_TRUE(controller_->Initialize(
+      false, media::MediaContentType::Persistent, nullptr, false, false));
   EXPECT_FALSE(media_session()->IsActive());
   EXPECT_FALSE(media_session()->IsControllable());
 
   // Create a transient type session.
-  ASSERT_TRUE(controller_->Initialize(
-      true, false, media::MediaContentType::Transient, nullptr, false, false));
+  ASSERT_TRUE(controller_->Initialize(true, media::MediaContentType::Transient,
+                                      nullptr, false, false));
   EXPECT_TRUE(media_session()->IsActive());
   EXPECT_FALSE(media_session()->IsControllable());
   const int current_player_id = controller_->get_player_id_for_testing();
 
   // Reinitialize the session as a content type.
-  ASSERT_TRUE(controller_->Initialize(
-      true, false, media::MediaContentType::Persistent, nullptr, false, false));
+  ASSERT_TRUE(controller_->Initialize(true, media::MediaContentType::Persistent,
+                                      nullptr, false, false));
   EXPECT_TRUE(media_session()->IsActive());
   EXPECT_TRUE(media_session()->IsControllable());
   // Player id should not change when there's an active session.
@@ -263,13 +254,6 @@
   // Likewise verify the resume behavior.
   Resume();
   EXPECT_TRUE(ReceivedMessagePlay<MediaPlayerDelegateMsg_Play>());
-
-  // Switch to a remote player, which should release the session.
-  ASSERT_TRUE(controller_->Initialize(
-      true, true, media::MediaContentType::Persistent, nullptr, false, false));
-  EXPECT_FALSE(media_session()->IsActive());
-  EXPECT_FALSE(media_session()->IsControllable());
-  EXPECT_EQ(current_player_id, controller_->get_player_id_for_testing());
 }
 
 TEST_F(MediaSessionControllerTest, PositionState) {
@@ -277,7 +261,7 @@
     media_session::MediaPosition expected_position(1.0, base::TimeDelta(),
                                                    base::TimeDelta());
 
-    ASSERT_TRUE(controller_->Initialize(true, true,
+    ASSERT_TRUE(controller_->Initialize(true,
                                         media::MediaContentType::Persistent,
                                         &expected_position, false, false));
 
@@ -297,8 +281,8 @@
 }
 
 TEST_F(MediaSessionControllerTest, RemovePlayerIfSessionReset) {
-  ASSERT_TRUE(controller_->Initialize(
-      true, false, media::MediaContentType::Persistent, nullptr, false, false));
+  ASSERT_TRUE(controller_->Initialize(true, media::MediaContentType::Persistent,
+                                      nullptr, false, false));
   EXPECT_TRUE(media_session()->IsActive());
 
   ResetHasSessionBit();
@@ -309,8 +293,8 @@
 }
 
 TEST_F(MediaSessionControllerTest, PictureInPictureAvailability) {
-  ASSERT_TRUE(controller_->Initialize(
-      true, false, media::MediaContentType::Persistent, nullptr, false, false));
+  ASSERT_TRUE(controller_->Initialize(true, media::MediaContentType::Persistent,
+                                      nullptr, false, false));
   EXPECT_FALSE(controller_->IsPictureInPictureAvailable(
       controller_->get_player_id_for_testing()));
 
@@ -323,8 +307,7 @@
   contents()->SetAudioMuted(true);
 
   ASSERT_TRUE(controller_->Initialize(
-      /* has_audio = */ true, /* is_remote = */ false,
-      media::MediaContentType::Persistent, nullptr,
+      /* has_audio = */ true, media::MediaContentType::Persistent, nullptr,
       /* is_pip_available = */ true, /* has_video = */ false));
   ASSERT_FALSE(media_session()->IsActive());
 
@@ -335,8 +318,7 @@
 
 TEST_F(MediaSessionControllerTest, RemovePlayerWhenMuted) {
   ASSERT_TRUE(controller_->Initialize(
-      /* has_audio = */ true, /* is_remote = */ false,
-      media::MediaContentType::Persistent, nullptr,
+      /* has_audio = */ true, media::MediaContentType::Persistent, nullptr,
       /* is_pip_available = */ true, /* has_video = */ false));
   ASSERT_TRUE(media_session()->IsActive());
 
@@ -349,8 +331,7 @@
   contents()->SetAudioMuted(true);
 
   ASSERT_TRUE(controller_->Initialize(
-      /* has_audio = */ true, /* is_remote = */ false,
-      media::MediaContentType::Persistent, nullptr,
+      /* has_audio = */ true, media::MediaContentType::Persistent, nullptr,
       /* is_pip_available = */ true, /* has_video = */ false));
   ASSERT_FALSE(media_session()->IsActive());
 
@@ -367,8 +348,7 @@
 
 TEST_F(MediaSessionControllerTest, MuteWithPictureInPicture) {
   ASSERT_TRUE(controller_->Initialize(
-      /* has_audio = */ true, /* is_remote = */ false,
-      media::MediaContentType::Persistent, nullptr,
+      /* has_audio = */ true, media::MediaContentType::Persistent, nullptr,
       /* is_pip_available = */ true, /* has_video = */ false));
   contents()->SetHasPictureInPictureVideo(true);
   controller_->PictureInPictureStateChanged(true);
@@ -383,8 +363,7 @@
   contents()->SetAudioMuted(true);
 
   ASSERT_TRUE(controller_->Initialize(
-      /* has_audio = */ true, /* is_remote = */ false,
-      media::MediaContentType::Persistent, nullptr,
+      /* has_audio = */ true, media::MediaContentType::Persistent, nullptr,
       /* is_pip_available = */ true, /* has_video = */ false));
   ASSERT_FALSE(media_session()->IsActive());
 
@@ -402,14 +381,12 @@
 
 TEST_F(MediaSessionControllerTest, AddPlayerWhenAddingAudio) {
   ASSERT_TRUE(controller_->Initialize(
-      /* has_audio = */ false, /* is_remote = */ false,
-      media::MediaContentType::Persistent, nullptr,
+      /* has_audio = */ false, media::MediaContentType::Persistent, nullptr,
       /* is_pip_available = */ true, /* has_video = */ false));
   ASSERT_FALSE(media_session()->IsActive());
 
   EXPECT_TRUE(controller_->Initialize(
-      /* has_audio = */ true, /* is_remote = */ false,
-      media::MediaContentType::Persistent, nullptr,
+      /* has_audio = */ true, media::MediaContentType::Persistent, nullptr,
       /* is_pip_available = */ true, /* has_video = */ false));
   EXPECT_TRUE(media_session()->IsActive());
 }
@@ -417,8 +394,7 @@
 TEST_F(MediaSessionControllerTest,
        AddPlayerWhenEnteringPictureInPictureWithNoAudio) {
   ASSERT_TRUE(controller_->Initialize(
-      /* has_audio = */ false, /* is_remote = */ false,
-      media::MediaContentType::Persistent, nullptr,
+      /* has_audio = */ false, media::MediaContentType::Persistent, nullptr,
       /* is_pip_available = */ true, /* has_video = */ false));
   ASSERT_FALSE(media_session()->IsActive());
 
@@ -432,8 +408,7 @@
   contents()->SetHasPictureInPictureVideo(true);
 
   ASSERT_TRUE(controller_->Initialize(
-      /* has_audio = */ false, /* is_remote = */ false,
-      media::MediaContentType::Persistent, nullptr,
+      /* has_audio = */ false, media::MediaContentType::Persistent, nullptr,
       /* is_pip_available = */ true, /* has_video = */ false));
   EXPECT_TRUE(media_session()->IsActive());
 
@@ -445,16 +420,14 @@
 
 TEST_F(MediaSessionControllerTest, HasVideo_True) {
   ASSERT_TRUE(controller_->Initialize(
-      /* has_audio = */ true, /* is_remote = */ false,
-      media::MediaContentType::Persistent, nullptr,
+      /* has_audio = */ true, media::MediaContentType::Persistent, nullptr,
       /* is_pip_available = */ true, /* has_video = */ true));
   EXPECT_TRUE(controller_->HasVideo(controller_->get_player_id_for_testing()));
 }
 
 TEST_F(MediaSessionControllerTest, HasVideo_False) {
   ASSERT_TRUE(controller_->Initialize(
-      /* has_audio = */ false, /* is_remote = */ false,
-      media::MediaContentType::Persistent, nullptr,
+      /* has_audio = */ false, media::MediaContentType::Persistent, nullptr,
       /* is_pip_available = */ true, /* has_video = */ false));
   EXPECT_FALSE(controller_->HasVideo(controller_->get_player_id_for_testing()));
 }
diff --git a/content/browser/media/session/media_session_controllers_manager.cc b/content/browser/media/session/media_session_controllers_manager.cc
index eb996cb..b93ff1e 100644
--- a/content/browser/media/session/media_session_controllers_manager.cc
+++ b/content/browser/media/session/media_session_controllers_manager.cc
@@ -43,7 +43,6 @@
 bool MediaSessionControllersManager::RequestPlay(
     const MediaPlayerId& id,
     bool has_audio,
-    bool is_remote,
     media::MediaContentType media_content_type,
     bool has_video) {
   if (!IsMediaSessionEnabled())
@@ -69,8 +68,8 @@
   // controller. A later playback attempt will create a new controller.
   auto it = controllers_map_.find(id);
   if (it != controllers_map_.end()) {
-    if (it->second->Initialize(has_audio, is_remote, media_content_type,
-                               position, is_pip_available, has_video)) {
+    if (it->second->Initialize(has_audio, media_content_type, position,
+                               is_pip_available, has_video)) {
       return true;
     }
 
@@ -80,8 +79,8 @@
   std::unique_ptr<MediaSessionController> controller(
       new MediaSessionController(id, media_web_contents_observer_));
 
-  if (!controller->Initialize(has_audio, is_remote, media_content_type,
-                              position, is_pip_available, has_video)) {
+  if (!controller->Initialize(has_audio, media_content_type, position,
+                              is_pip_available, has_video)) {
     return false;
   }
 
diff --git a/content/browser/media/session/media_session_controllers_manager.h b/content/browser/media/session/media_session_controllers_manager.h
index 6f1a420d..6c25dbf 100644
--- a/content/browser/media/session/media_session_controllers_manager.h
+++ b/content/browser/media/session/media_session_controllers_manager.h
@@ -50,7 +50,6 @@
   // Returns whether the player was added to the session and can start playing.
   bool RequestPlay(const MediaPlayerId& id,
                    bool has_audio,
-                   bool is_remote,
                    media::MediaContentType media_content_type,
                    bool has_video);
 
diff --git a/content/browser/media/session/media_session_controllers_manager_unittest.cc b/content/browser/media/session/media_session_controllers_manager_unittest.cc
index 8478b17..8918e5d 100644
--- a/content/browser/media/session/media_session_controllers_manager_unittest.cc
+++ b/content/browser/media/session/media_session_controllers_manager_unittest.cc
@@ -133,15 +133,15 @@
 TEST_P(MediaSessionControllersManagerTest, RequestPlayAddsSessionsToMap) {
   EXPECT_TRUE(GetControllersMap()->empty());
 
-  EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true, false,
+  EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true,
                                     media::MediaContentType::Transient, false));
   if (!IsMediaSessionEnabled()) {
     EXPECT_TRUE(GetControllersMap()->empty());
   } else {
     EXPECT_EQ(1U, GetControllersMap()->size());
-    EXPECT_TRUE(manager_->RequestPlay(
-        MediaPlayerId(contents()->GetMainFrame(), 2), true, false,
-        media::MediaContentType::Transient, false));
+    EXPECT_TRUE(
+        manager_->RequestPlay(MediaPlayerId(contents()->GetMainFrame(), 2),
+                              true, media::MediaContentType::Transient, false));
     EXPECT_EQ(2U, GetControllersMap()->size());
   }
 }
@@ -153,11 +153,11 @@
 
   EXPECT_TRUE(GetControllersMap()->empty());
 
-  EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true, false,
+  EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true,
                                     media::MediaContentType::Transient, false));
   EXPECT_EQ(1U, GetControllersMap()->size());
 
-  EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true, false,
+  EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true,
                                     media::MediaContentType::Transient, false));
   EXPECT_EQ(1U, GetControllersMap()->size());
 }
@@ -175,9 +175,8 @@
     manager_->RenderFrameDeleted(contents()->GetMainFrame());
     EXPECT_EQ(1U, GetControllersMap()->size());
   } else {
-    EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true, false,
-                                      media::MediaContentType::Transient,
-                                      false));
+    EXPECT_TRUE(manager_->RequestPlay(
+        media_player_id_, true, media::MediaContentType::Transient, false));
     EXPECT_EQ(1U, GetControllersMap()->size());
 
     manager_->RenderFrameDeleted(contents()->GetMainFrame());
@@ -221,9 +220,8 @@
     manager_->OnEnd(media_player_id_);
     EXPECT_EQ(1U, GetControllersMap()->size());
   } else {
-    EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true, false,
-                                      media::MediaContentType::Transient,
-                                      false));
+    EXPECT_TRUE(manager_->RequestPlay(
+        media_player_id_, true, media::MediaContentType::Transient, false));
     EXPECT_EQ(1U, GetControllersMap()->size());
 
     manager_->OnEnd(media_player_id_);
@@ -242,9 +240,8 @@
 
     manager_->OnMediaPositionStateChanged(media_player_id_, expected_position);
 
-    EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true, false,
-                                      media::MediaContentType::Transient,
-                                      false));
+    EXPECT_TRUE(manager_->RequestPlay(
+        media_player_id_, true, media::MediaContentType::Transient, false));
     EXPECT_EQ(1U, GetControllersMap()->size());
 
     // The controller should be created with the last received position for
@@ -266,9 +263,8 @@
     EXPECT_TRUE(GetControllersMap()->empty());
 
     // Recreate the current controller.
-    EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true, false,
-                                      media::MediaContentType::Transient,
-                                      false));
+    EXPECT_TRUE(manager_->RequestPlay(
+        media_player_id_, true, media::MediaContentType::Transient, false));
     EXPECT_EQ(1U, GetControllersMap()->size());
 
     // The controller should be created with the last received position for
@@ -293,9 +289,9 @@
   manager_->OnMediaPositionStateChanged(media_player_id_, expected_position1);
   manager_->OnMediaPositionStateChanged(media_player_id_2, expected_position2);
 
-  EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true, false,
+  EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true,
                                     media::MediaContentType::Transient, false));
-  EXPECT_TRUE(manager_->RequestPlay(media_player_id_2, true, false,
+  EXPECT_TRUE(manager_->RequestPlay(media_player_id_2, true,
                                     media::MediaContentType::Transient, false));
 
   EXPECT_EQ(2U, GetControllersMap()->size());
@@ -319,7 +315,7 @@
     return;
 
   manager_->OnPictureInPictureAvailabilityChanged(media_player_id_, true);
-  EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true, false,
+  EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true,
                                     media::MediaContentType::Transient, false));
   EXPECT_TRUE(IsPictureInPictureAvailable(media_player_id_));
 
@@ -337,12 +333,10 @@
 
   manager_->OnPictureInPictureAvailabilityChanged(media_player_id_, true);
   manager_->OnPictureInPictureAvailabilityChanged(media_player_id_2, true);
-  EXPECT_TRUE(manager_->RequestPlay(media_player_id_, true, false,
-                                    media::MediaContentType::Persistent,
-                                    false));
-  EXPECT_TRUE(manager_->RequestPlay(media_player_id_2, true, false,
-                                    media::MediaContentType::Persistent,
-                                    false));
+  EXPECT_TRUE(manager_->RequestPlay(
+      media_player_id_, true, media::MediaContentType::Persistent, false));
+  EXPECT_TRUE(manager_->RequestPlay(
+      media_player_id_2, true, media::MediaContentType::Persistent, false));
   EXPECT_TRUE(IsPictureInPictureAvailable(media_player_id_));
   EXPECT_TRUE(IsPictureInPictureAvailable(media_player_id_2));
 
diff --git a/content/browser/payments/payment_app_provider_impl.cc b/content/browser/payments/payment_app_provider_impl.cc
index 30fc06b..74bb39b 100644
--- a/content/browser/payments/payment_app_provider_impl.cc
+++ b/content/browser/payments/payment_app_provider_impl.cc
@@ -417,6 +417,31 @@
       base::BindOnce(&DidGetAllPaymentAppsOnCoreThread, std::move(callback)));
 }
 
+void DidUpdatePaymentAppIconOnCoreThread(
+    PaymentAppProvider::UpdatePaymentAppIconCallback callback,
+    payments::mojom::PaymentHandlerStatus status) {
+  GetUIThreadTaskRunner({})->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), status));
+}
+
+void UpdatePaymentAppIconOnCoreThread(
+    scoped_refptr<PaymentAppContextImpl> payment_app_context,
+    int64_t registration_id,
+    const std::string& instrument_key,
+    const std::string& name,
+    const std::string& string_encoded_icon,
+    const std::string& method_name,
+    const SupportedDelegations& supported_delegations,
+    PaymentAppProvider::UpdatePaymentAppIconCallback callback) {
+  DCHECK_CURRENTLY_ON(content::ServiceWorkerContext::GetCoreThreadId());
+  payment_app_context->payment_app_database()
+      ->SetPaymentAppInfoForRegisteredServiceWorker(
+          registration_id, instrument_key, name, string_encoded_icon,
+          method_name, supported_delegations,
+          base::BindOnce(&DidUpdatePaymentAppIconOnCoreThread,
+                         std::move(callback)));
+}
+
 void DispatchAbortPaymentEvent(
     BrowserContext* browser_context,
     PaymentAppProvider::AbortCallback callback,
@@ -891,6 +916,27 @@
                      std::move(callback)));
 }
 
+void PaymentAppProviderImpl::UpdatePaymentAppIcon(
+    BrowserContext* browser_context,
+    int64_t registration_id,
+    const std::string& instrument_key,
+    const std::string& name,
+    const std::string& string_encoded_icon,
+    const std::string& method_name,
+    const SupportedDelegations& supported_delegations,
+    PaymentAppProvider::UpdatePaymentAppIconCallback callback) {
+  StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+      BrowserContext::GetDefaultStoragePartition(browser_context));
+  scoped_refptr<PaymentAppContextImpl> payment_app_context =
+      partition->GetPaymentAppContext();
+
+  RunOrPostTaskOnThread(
+      FROM_HERE, content::ServiceWorkerContext::GetCoreThreadId(),
+      base::BindOnce(&UpdatePaymentAppIconOnCoreThread, payment_app_context,
+                     registration_id, instrument_key, name, string_encoded_icon,
+                     method_name, supported_delegations, std::move(callback)));
+}
+
 void PaymentAppProviderImpl::CanMakePayment(
     WebContents* web_contents,
     int64_t registration_id,
diff --git a/content/browser/payments/payment_app_provider_impl.h b/content/browser/payments/payment_app_provider_impl.h
index 821b529..11353c6 100644
--- a/content/browser/payments/payment_app_provider_impl.h
+++ b/content/browser/payments/payment_app_provider_impl.h
@@ -42,6 +42,14 @@
       const SupportedDelegations& supported_delegations,
       RegistrationIdCallback registration_id_callback,
       InvokePaymentAppCallback callback) override;
+  void UpdatePaymentAppIcon(BrowserContext* browser_context,
+                            int64_t registration_id,
+                            const std::string& instrument_key,
+                            const std::string& name,
+                            const std::string& string_encoded_icon,
+                            const std::string& method_name,
+                            const SupportedDelegations& supported_delegations,
+                            UpdatePaymentAppIconCallback callback) override;
   void CanMakePayment(WebContents* web_contents,
                       int64_t registration_id,
                       const url::Origin& sw_origin,
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
index eb26134..89dc4f0 100644
--- a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
+++ b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
@@ -266,8 +266,7 @@
         media_stream_manager_->media_devices_manager()->GetVideoInputFormats(
             device_info.device_id, true /* try_in_use_first */);
     capabilities->facing_mode = device_info.video_facing;
-    capabilities->pan_tilt_zoom_supported =
-        device_info.pan_tilt_zoom_supported.value_or(false);
+    capabilities->pan_tilt_zoom_supported = device_info.pan_tilt_zoom_supported;
     if (device_info.device_id == default_device_id) {
       video_input_capabilities.insert(video_input_capabilities.begin(),
                                       std::move(capabilities));
diff --git a/content/browser/service_worker/service_worker_cache_writer.cc b/content/browser/service_worker/service_worker_cache_writer.cc
index 3cfd4a07..450920f 100644
--- a/content/browser/service_worker/service_worker_cache_writer.cc
+++ b/content/browser/service_worker/service_worker_cache_writer.cc
@@ -503,10 +503,11 @@
   state_ = STATE_WRITE_HEADERS_FOR_COPY_DONE;
   if (IsCopying()) {
     DCHECK(response_head_to_read_);
-    return WriteResponseHead(*response_head_to_read_);
+    bytes_to_copy_ = response_head_to_read_->content_length;
+    return WriteResponseHead(std::move(response_head_to_read_));
   } else {
     DCHECK(response_head_to_write_);
-    return WriteResponseHead(*response_head_to_write_);
+    return WriteResponseHead(std::move(response_head_to_write_));
   }
 }
 
@@ -524,8 +525,7 @@
 
   // If the cache writer is only for copy, get the total size to read from
   // header data instead of |bytes_compared_| as no comparison is done.
-  size_t total_size_to_read =
-      IsCopying() ? response_head_to_read_->content_length : bytes_compared_;
+  size_t total_size_to_read = IsCopying() ? bytes_to_copy_ : bytes_compared_;
   size_t to_read =
       std::min(kCopyBufferSize, total_size_to_read - bytes_copied_);
 
@@ -575,7 +575,7 @@
   DCHECK(writer_);
   DCHECK(response_head_to_write_);
   state_ = STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE;
-  return WriteResponseHead(*response_head_to_write_);
+  return WriteResponseHead(std::move(response_head_to_write_));
 }
 
 int ServiceWorkerCacheWriter::DoWriteHeadersForPassthroughDone(int result) {
@@ -720,15 +720,15 @@
 }
 
 int ServiceWorkerCacheWriter::WriteResponseHeadToResponseWriter(
-    const network::mojom::URLResponseHead& response_head) {
+    network::mojom::URLResponseHeadPtr response_head) {
+  DCHECK(response_head);
   did_replace_ = true;
   net::CompletionOnceCallback run_callback = base::BindOnce(
       &ServiceWorkerCacheWriter::AsyncDoLoop, weak_factory_.GetWeakPtr());
   scoped_refptr<AsyncOnlyCompletionCallbackAdaptor> adaptor(
       new AsyncOnlyCompletionCallbackAdaptor(std::move(run_callback)));
-  // TODO(crbug.com/1055677): Avoid copying |response_head| if possible.
   writer_->WriteResponseHead(
-      response_head.Clone(),
+      std::move(response_head),
       base::BindOnce(&AsyncOnlyCompletionCallbackAdaptor::WrappedCallback,
                      adaptor));
   adaptor->set_async(true);
@@ -736,16 +736,17 @@
 }
 
 int ServiceWorkerCacheWriter::WriteResponseHead(
-    const network::mojom::URLResponseHead& response_head) {
+    network::mojom::URLResponseHeadPtr response_head) {
+  DCHECK(response_head);
   if (write_observer_) {
-    int result = write_observer_->WillWriteResponseHead(response_head);
+    int result = write_observer_->WillWriteResponseHead(*response_head);
     if (result != net::OK) {
       DCHECK_NE(result, net::ERR_IO_PENDING);
       state_ = STATE_DONE;
       return result;
     }
   }
-  return WriteResponseHeadToResponseWriter(response_head);
+  return WriteResponseHeadToResponseWriter(std::move(response_head));
 }
 
 int ServiceWorkerCacheWriter::WriteDataToResponseWriter(
diff --git a/content/browser/service_worker/service_worker_cache_writer.h b/content/browser/service_worker/service_worker_cache_writer.h
index af7dbc1..56a472e 100644
--- a/content/browser/service_worker/service_worker_cache_writer.h
+++ b/content/browser/service_worker/service_worker_cache_writer.h
@@ -265,10 +265,10 @@
   // If observer is set, the argument |response_info| or |data| is first sent
   // to observer then WriteResponseHeadToResponseWriter() or
   // WriteDataToResponseWriter() is called.
-  int WriteResponseHead(const network::mojom::URLResponseHead& response_head);
+  int WriteResponseHead(network::mojom::URLResponseHeadPtr response_head);
   int WriteData(scoped_refptr<net::IOBuffer> data, int length);
   int WriteResponseHeadToResponseWriter(
-      const network::mojom::URLResponseHead& response_head);
+      network::mojom::URLResponseHeadPtr response_head);
   int WriteDataToResponseWriter(scoped_refptr<net::IOBuffer> data, int length);
 
   // Called when |write_observer_| finishes its WillWriteData() operation.
@@ -311,6 +311,10 @@
   // fragments of the buffered network data.
   size_t bytes_compared_;
 
+  // The total size of the body for copying. Used only when IsCopying() returns
+  // true.
+  size_t bytes_to_copy_ = 0;
+
   // Count of bytes copied from |copy_reader_| to |writer_|.
   size_t bytes_copied_;
 
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index ae6a6b8..8007e75 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -8345,7 +8345,7 @@
 IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
                        NavigateCrashedSubframeToSameSite) {
   // TODO(https://crbug.com/1064944): Enable this when the fix is submitted.
-  if (CreateNewHostForSameSiteSubframe())
+  if (ShouldCreateNewHostForSameSiteSubframe())
     return;
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(b)"));
diff --git a/content/browser/site_per_process_unload_browsertest.cc b/content/browser/site_per_process_unload_browsertest.cc
index 2812511..4463765c 100644
--- a/content/browser/site_per_process_unload_browsertest.cc
+++ b/content/browser/site_per_process_unload_browsertest.cc
@@ -1350,7 +1350,7 @@
       WebContents::FromRenderFrameHost(web_contents()->GetMainFrame()));
 
   // All the documents must be properly deleted:
-  if (CreateNewHostForSameSiteSubframe())
+  if (ShouldCreateNewHostForSameSiteSubframe())
     delete_B2.WaitUntilDeleted();
   delete_B3.WaitUntilDeleted();
   delete_C4.WaitUntilDeleted();
diff --git a/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc b/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
index 5e0de4b..a041abf 100644
--- a/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
+++ b/content/browser/web_package/signed_exchange_subresource_prefetch_browsertest.cc
@@ -47,7 +47,7 @@
 #include "net/base/features.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/http/http_cache.h"
-#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
 #include "services/network/public/cpp/features.h"
 #include "storage/browser/blob/blob_storage_context.h"
 
diff --git a/content/browser/webui/web_ui_security_browsertest.cc b/content/browser/webui/web_ui_security_browsertest.cc
index 2fe4c59..e3da149 100644
--- a/content/browser/webui/web_ui_security_browsertest.cc
+++ b/content/browser/webui/web_ui_security_browsertest.cc
@@ -319,7 +319,7 @@
   }
   EXPECT_EQ(initial_site_instance,
             child->current_frame_host()->GetSiteInstance());
-  if (CreateNewHostForSameSiteSubframe()) {
+  if (ShouldCreateNewHostForSameSiteSubframe()) {
     EXPECT_NE(initial_web_ui, child->current_frame_host()->web_ui());
   } else {
     EXPECT_EQ(initial_web_ui, child->current_frame_host()->web_ui());
@@ -356,7 +356,7 @@
   }
   EXPECT_EQ(second_site_instance,
             child->current_frame_host()->GetSiteInstance());
-  if (CreateNewHostForSameSiteSubframe()) {
+  if (ShouldCreateNewHostForSameSiteSubframe()) {
     EXPECT_NE(second_web_ui, child->current_frame_host()->web_ui());
   } else {
     EXPECT_EQ(second_web_ui, child->current_frame_host()->web_ui());
diff --git a/content/common/content_navigation_policy.cc b/content/common/content_navigation_policy.cc
index 6b932f0..0095333 100644
--- a/content/common/content_navigation_policy.cc
+++ b/content/common/content_navigation_policy.cc
@@ -116,7 +116,7 @@
   return render_document_level.GetName(level);
 }
 
-bool CreateNewHostForSameSiteSubframe() {
+bool ShouldCreateNewHostForSameSiteSubframe() {
   return GetRenderDocumentLevel() >= RenderDocumentLevel::kSubframe;
 }
 
diff --git a/content/common/content_navigation_policy.h b/content/common/content_navigation_policy.h
index e7d1aae..2e71b90 100644
--- a/content/common/content_navigation_policy.h
+++ b/content/common/content_navigation_policy.h
@@ -64,7 +64,7 @@
   // Also do not reuse RenderFrameHosts when navigating subframes.
   kSubframe = 2,
 };
-CONTENT_EXPORT bool CreateNewHostForSameSiteSubframe();
+CONTENT_EXPORT bool ShouldCreateNewHostForSameSiteSubframe();
 CONTENT_EXPORT RenderDocumentLevel GetRenderDocumentLevel();
 CONTENT_EXPORT std::string GetRenderDocumentLevelName(
     RenderDocumentLevel level);
diff --git a/content/common/media/media_player_delegate_messages.h b/content/common/media/media_player_delegate_messages.h
index 80fcfb4..ece6cd4 100644
--- a/content/common/media/media_player_delegate_messages.h
+++ b/content/common/media/media_player_delegate_messages.h
@@ -89,11 +89,10 @@
                     int /* delegate_id, distinguishes instances */,
                     bool /* reached end of stream */)
 
-IPC_MESSAGE_ROUTED5(MediaPlayerDelegateHostMsg_OnMediaPlaying,
+IPC_MESSAGE_ROUTED4(MediaPlayerDelegateHostMsg_OnMediaPlaying,
                     int /* delegate_id, distinguishes instances */,
                     bool /* has_video */,
                     bool /* has_audio */,
-                    bool /* is_remote */,
                     media::MediaContentType /* media_content_type */)
 
 IPC_MESSAGE_ROUTED2(MediaPlayerDelegateHostMsg_OnMutedStatusChanged,
diff --git a/content/public/browser/payment_app_provider.h b/content/public/browser/payment_app_provider.h
index e4865ad..a317257 100644
--- a/content/public/browser/payment_app_provider.h
+++ b/content/public/browser/payment_app_provider.h
@@ -49,6 +49,8 @@
   using CanMakePaymentCallback =
       base::OnceCallback<void(payments::mojom::CanMakePaymentResponsePtr)>;
   using AbortCallback = base::OnceCallback<void(bool)>;
+  using UpdatePaymentAppIconCallback =
+      base::OnceCallback<void(payments::mojom::PaymentHandlerStatus status)>;
 
   // Should be accessed only on the UI thread.
   virtual void GetAllPaymentApps(BrowserContext* browser_context,
@@ -71,6 +73,15 @@
       const SupportedDelegations& supported_delegations,
       RegistrationIdCallback registration_id_callback,
       InvokePaymentAppCallback callback) = 0;
+  virtual void UpdatePaymentAppIcon(
+      BrowserContext* browser_context,
+      int64_t registration_id,
+      const std::string& instrument_key,
+      const std::string& name,
+      const std::string& string_encoded_icon,
+      const std::string& method_name,
+      const SupportedDelegations& supported_delegations,
+      UpdatePaymentAppIconCallback callback) = 0;
   virtual void CanMakePayment(
       WebContents* web_contents,
       int64_t registration_id,
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc
index 26b00e4..ce7e18c 100644
--- a/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -275,6 +275,7 @@
       if (settings) {
         if (mode.has_mode(ui::AXMode::kInlineTextBoxes)) {
           settings->SetInlineTextBoxAccessibilityEnabled(true);
+          tree_source_.GetRoot().UpdateLayoutAndCheckValidity();
           tree_source_.GetRoot().LoadInlineTextBoxes();
         } else {
           settings->SetInlineTextBoxAccessibilityEnabled(false);
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate.cc b/content/renderer/media/renderer_webmediaplayer_delegate.cc
index ae04d07..45f8a55c 100644
--- a/content/renderer/media/renderer_webmediaplayer_delegate.cc
+++ b/content/renderer/media/renderer_webmediaplayer_delegate.cc
@@ -99,8 +99,7 @@
   }
 
   Send(new MediaPlayerDelegateHostMsg_OnMediaPlaying(
-      routing_id(), player_id, has_video, has_audio, false,
-      media_content_type));
+      routing_id(), player_id, has_video, has_audio, media_content_type));
 
   ScheduleUpdateTask();
 }
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc b/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
index 2bc520d..3b29323 100644
--- a/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
+++ b/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
@@ -118,7 +118,7 @@
 
   // Verify the playing message.
   {
-    const bool kHasVideo = true, kHasAudio = false, kIsRemote = false;
+    const bool kHasVideo = true, kHasAudio = false;
     const media::MediaContentType kMediaContentType =
         media::MediaContentType::Transient;
     delegate_manager_->DidPlay(delegate_id, kHasVideo, kHasAudio,
@@ -128,13 +128,12 @@
         MediaPlayerDelegateHostMsg_OnMediaPlaying::ID);
     ASSERT_TRUE(msg);
 
-    std::tuple<int, bool, bool, bool, media::MediaContentType> result;
+    std::tuple<int, bool, bool, media::MediaContentType> result;
     ASSERT_TRUE(MediaPlayerDelegateHostMsg_OnMediaPlaying::Read(msg, &result));
     EXPECT_EQ(delegate_id, std::get<0>(result));
     EXPECT_EQ(kHasVideo, std::get<1>(result));
     EXPECT_EQ(kHasAudio, std::get<2>(result));
-    EXPECT_EQ(kIsRemote, std::get<3>(result));
-    EXPECT_EQ(kMediaContentType, std::get<4>(result));
+    EXPECT_EQ(kMediaContentType, std::get<3>(result));
   }
 
   // Verify the paused message.
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index c2379d8..867931d 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -3970,7 +3970,7 @@
       CHECK_EQ(routing_id_, proxy->provisional_frame_routing_id());
       proxy->set_provisional_frame_routing_id(MSG_ROUTING_NONE);
     } else
-      CHECK(CreateNewHostForSameSiteSubframe());
+      CHECK(ShouldCreateNewHostForSameSiteSubframe());
   }
 
   delete this;
diff --git a/content/shell/renderer/web_test/web_ax_object_proxy.cc b/content/shell/renderer/web_test/web_ax_object_proxy.cc
index d2ffa16..ee2b684 100644
--- a/content/shell/renderer/web_test/web_ax_object_proxy.cc
+++ b/content/shell/renderer/web_test/web_ax_object_proxy.cc
@@ -584,7 +584,7 @@
 
     // Look for a character within any word other than the last.
     for (size_t j = 0; j < word_count - 1; j++) {
-      if (local_index <= ends[j]) {
+      if (local_index < ends[j]) {
         word_start = start + starts[j];
         word_end = start + ends[j];
         return;
diff --git a/content/test/data/media/image_capture_test.html b/content/test/data/media/image_capture_test.html
index 6b4d20a..a59bd27 100644
--- a/content/test/data/media/image_capture_test.html
+++ b/content/test/data/media/image_capture_test.html
@@ -114,11 +114,6 @@
       .then(stream => {
         assertEquals('video', stream.getVideoTracks()[0].kind);
         imageCapturer = new ImageCapture(stream.getVideoTracks()[0]);
-        // TODO(mcasas): Before accesing synchronous track APIs we need a delay,
-        // use instead a round trip of capabilities: https://crbug.com/711524.
-        return imageCapturer.getPhotoCapabilities();
-      })
-      .then(capabilities => {
         imageCapturer.track.getCapabilities();
         // There's nothing to check here since |capabilities| vary per device.
         reportTestSuccess();
@@ -135,11 +130,6 @@
       .then(stream => {
         assertEquals('video', stream.getVideoTracks()[0].kind);
         imageCapturer = new ImageCapture(stream.getVideoTracks()[0]);
-        // TODO(mcasas): Before accesing synchronous track APIs we need a delay,
-        // use instead a round trip of capabilities: https://crbug.com/711524.
-        return imageCapturer.getPhotoCapabilities();
-      })
-      .then(capabilities => {
         imageCapturer.track.getSettings();
         // There's nothing to check here since |settings| vary per device.
         reportTestSuccess();
@@ -158,11 +148,6 @@
       .then(stream => {
         assertEquals('video', stream.getVideoTracks()[0].kind);
         imageCapturer = new ImageCapture(stream.getVideoTracks()[0]);
-        // TODO(mcasas): Before accesing synchronous track APIs we need a delay,
-        // use instead a round trip of capabilities: https://crbug.com/711524.
-        return imageCapturer.getPhotoCapabilities();
-      })
-      .then(capabilities => {
         const trackCapabilities = imageCapturer.track.getCapabilities();
         if (trackCapabilities.pan === undefined) {
           console.log('pan not supported, skipping test');
@@ -199,11 +184,6 @@
       .then(stream => {
         assertEquals('video', stream.getVideoTracks()[0].kind);
         imageCapturer = new ImageCapture(stream.getVideoTracks()[0]);
-        // TODO(mcasas): Before accesing synchronous track APIs we need a delay,
-        // use instead a round trip of capabilities: https://crbug.com/711524.
-        return imageCapturer.getPhotoCapabilities();
-      })
-      .then(capabilities => {
         const trackCapabilities = imageCapturer.track.getCapabilities();
         if (trackCapabilities.tilt === undefined) {
           console.log('tilt not supported, skipping test');
@@ -240,11 +220,6 @@
       .then(stream => {
         assertEquals('video', stream.getVideoTracks()[0].kind);
         imageCapturer = new ImageCapture(stream.getVideoTracks()[0]);
-        // TODO(mcasas): Before accesing synchronous track APIs we need a delay,
-        // use instead a round trip of capabilities: https://crbug.com/711524.
-        return imageCapturer.getPhotoCapabilities();
-      })
-      .then(capabilities => {
         const trackCapabilities = imageCapturer.track.getCapabilities();
         if (trackCapabilities.zoom === undefined) {
           console.log('zoom not supported, skipping test');
@@ -281,11 +256,6 @@
         .then(stream => {
             assertEquals('video', stream.getVideoTracks()[0].kind);
             imageCapturer = new ImageCapture(stream.getVideoTracks()[0]);
-            // TODO(mcasas): Before accesing synchronous track APIs we need a delay,
-            // use instead a round trip of capabilities: https://crbug.com/711524.
-            return imageCapturer.getPhotoCapabilities();
-        })
-        .then(capabilities => {
             const trackCapabilities = imageCapturer.track.getCapabilities();
             if (trackCapabilities.exposureTime === undefined) {
                 console.log('exposureTime not supported, skipping test');
@@ -340,11 +310,6 @@
         .then(stream => {
             assertEquals('video', stream.getVideoTracks()[0].kind);
             imageCapturer = new ImageCapture(stream.getVideoTracks()[0]);
-            // TODO(mcasas): Before accesing synchronous track APIs we need a delay,
-            // use instead a round trip of capabilities: https://crbug.com/711524.
-            return imageCapturer.getPhotoCapabilities();
-        })
-        .then(capabilities => {
             const trackCapabilities = imageCapturer.track.getCapabilities();
             if (trackCapabilities.focusDistance === undefined) {
                 console.log('focusDistance not supported, skipping test');
diff --git a/docs/how_cc_works.md b/docs/how_cc_works.md
index fa3b84e..981ca15 100644
--- a/docs/how_cc_works.md
+++ b/docs/how_cc_works.md
@@ -178,7 +178,7 @@
 ### HeadsUpDisplayLayer
 
 This layer supports [devtools rendering settings](https://developer.chrome.com/devtools/docs/rendering-settings).
-It draws an FPS meter, as well as overlays for paint invalidation or damage.
+It draws an Frame Rendering Stats, as well as overlays for paint invalidation or damage.
 This layer is special because it must be updated last because its inputs depend on all of the other layers’ damage calculations.
 
 ### UIResourceLayer / NinePatchLayer
diff --git a/docs/sync/model_api.md b/docs/sync/model_api.md
index 49ac84d..9875d380 100644
--- a/docs/sync/model_api.md
+++ b/docs/sync/model_api.md
@@ -267,8 +267,6 @@
     [`ProfileSyncServiceFactory`][ProfileSyncServiceFactory].
 *   Add to the [start order list][kStartOrder].
 *   Add an field for encrypted data to [`NigoriSpecifics`][NigoriSpecifics].
-*   Add to two encrypted types translation functions in
-    [`nigori_util.cc`][nigori_util].
 *   If your type should have its own toggle in sync settings, add an entry to
     the [`UserSelectableType`][UserSelectableType] enum, add a
     [preference][pref_names] for tracking whether your type is enabled, and
@@ -289,7 +287,6 @@
 [ProfileSyncServiceFactory]: https://cs.chromium.org/search/?q=:ProfileSyncServiceFactory%5C(%5C)
 [kStartOrder]: https://cs.chromium.org/search/?q="kStartOrder[]"
 [NigoriSpecifics]: https://cs.chromium.org/chromium/src/components/sync/protocol/nigori_specifics.proto
-[nigori_util]: https://cs.chromium.org/chromium/src/components/sync/syncable/nigori_util.cc
 [UserSelectableType]: https://cs.chromium.org/chromium/src/components/sync/base/user_selectable_type.h?type=cs&q="enum+class+UserSelectableType"
 [pref_names]: https://cs.chromium.org/chromium/src/components/sync/base/pref_names.h
 [GetPrefName]: https://cs.chromium.org/search/?q=GetPrefNameForType+file:sync_prefs.cc
diff --git a/ios/build/tools/setup-gn.py b/ios/build/tools/setup-gn.py
index 60f06725..8e63af7 100755
--- a/ios/build/tools/setup-gn.py
+++ b/ios/build/tools/setup-gn.py
@@ -307,6 +307,9 @@
   parser.add_argument(
       '--gn-path', default=None,
       help='path to gn binary (default: look up in $PATH)')
+  parser.add_argument(
+      '--build-dir', default='out',
+      help='path where the build should be created (default: %(default)s)')
   args = parser.parse_args(args)
 
   # Load configuration (first global and then any user overrides).
@@ -340,7 +343,7 @@
       sys.stderr.write('ERROR: cannot find gn in PATH\n')
       sys.exit(1)
 
-  out_dir = os.path.join(args.root, 'out')
+  out_dir = os.path.join(args.root, args.build_dir)
   if not os.path.isdir(out_dir):
     os.makedirs(out_dir)
 
diff --git a/ios/chrome/app/app_startup_parameters.h b/ios/chrome/app/app_startup_parameters.h
index c50efa4..edbf9505 100644
--- a/ios/chrome/app/app_startup_parameters.h
+++ b/ios/chrome/app/app_startup_parameters.h
@@ -9,6 +9,8 @@
 
 #include <map>
 
+enum class ApplicationModeForTabOpening { NORMAL, INCOGNITO, CURRENT };
+
 enum NTPTabOpeningPostOpeningAction {
   // No action should be done
   NO_ACTION = 0,
@@ -42,6 +44,8 @@
 
 // Boolean to track if the app should launch in incognito mode.
 @property(nonatomic, readwrite, assign) BOOL launchInIncognito;
+// The mode in which the tab must be opened.
+@property(nonatomic, readonly) ApplicationModeForTabOpening applicationMode;
 // Action to be taken after opening the initial NTP.
 @property(nonatomic, readwrite, assign)
     NTPTabOpeningPostOpeningAction postOpeningAction;
diff --git a/ios/chrome/app/app_startup_parameters.mm b/ios/chrome/app/app_startup_parameters.mm
index c7f81c5..26710b9 100644
--- a/ios/chrome/app/app_startup_parameters.mm
+++ b/ios/chrome/app/app_startup_parameters.mm
@@ -83,4 +83,9 @@
   return description;
 }
 
+- (ApplicationModeForTabOpening)applicationMode {
+  return self.launchInIncognito ? ApplicationModeForTabOpening::INCOGNITO
+                                : ApplicationModeForTabOpening::NORMAL;
+}
+
 @end
diff --git a/ios/chrome/app/application_delegate/tab_opening.h b/ios/chrome/app/application_delegate/tab_opening.h
index f3cf677..f7b847a4 100644
--- a/ios/chrome/app/application_delegate/tab_opening.h
+++ b/ios/chrome/app/application_delegate/tab_opening.h
@@ -17,8 +17,6 @@
 struct UrlLoadParams;
 @class URLOpenerParams;
 
-enum class ApplicationModeForTabOpening { NORMAL, INCOGNITO, CURRENT };
-
 // Protocol for object that can open new tabs during application launch.
 @protocol TabOpening<NSObject>
 
diff --git a/ios/chrome/app/application_delegate/url_opener.h b/ios/chrome/app/application_delegate/url_opener.h
index 38757a52..92de343 100644
--- a/ios/chrome/app/application_delegate/url_opener.h
+++ b/ios/chrome/app/application_delegate/url_opener.h
@@ -27,7 +27,6 @@
 
 // Handles open URL at application startup.
 + (void)handleLaunchOptions:(URLOpenerParams*)options
-          applicationActive:(BOOL)applicationActive
                   tabOpener:(id<TabOpening>)tabOpener
       connectionInformation:(id<ConnectionInformation>)connectionInformation
          startupInformation:(id<StartupInformation>)startupInformation
diff --git a/ios/chrome/app/application_delegate/url_opener.mm b/ios/chrome/app/application_delegate/url_opener.mm
index 1b3e5c0..83be66e 100644
--- a/ios/chrome/app/application_delegate/url_opener.mm
+++ b/ios/chrome/app/application_delegate/url_opener.mm
@@ -85,9 +85,7 @@
       }
       UrlLoadParams urlLoadParams = UrlLoadParams::InNewTab(URL, virtualURL);
 
-      ApplicationModeForTabOpening targetMode =
-          [params launchInIncognito] ? ApplicationModeForTabOpening::INCOGNITO
-                                     : ApplicationModeForTabOpening::NORMAL;
+      ApplicationModeForTabOpening targetMode = params.applicationMode;
       // If the call is coming from the app, it should be opened in the current
       // mode to avoid changing mode.
       if (callerApp == CALLER_APP_GOOGLE_CHROME)
@@ -117,14 +115,17 @@
 }
 
 + (void)handleLaunchOptions:(URLOpenerParams*)options
-          applicationActive:(BOOL)applicationActive
                   tabOpener:(id<TabOpening>)tabOpener
       connectionInformation:(id<ConnectionInformation>)connectionInformation
          startupInformation:(id<StartupInformation>)startupInformation
                    appState:(AppState*)appState {
   if (options.URL) {
+    // This method is always called when the SceneState transitions to
+    // SceneActivationLevelForegroundActive, and before the handling of
+    // startupInformation is done.
+    // Pass |NO| as active to avoid double processing.
     BOOL openURLResult = [URLOpener openURL:options
-                          applicationActive:applicationActive
+                          applicationActive:NO
                                   tabOpener:tabOpener
                       connectionInformation:connectionInformation
                          startupInformation:startupInformation];
diff --git a/ios/chrome/app/application_delegate/url_opener_unittest.mm b/ios/chrome/app/application_delegate/url_opener_unittest.mm
index 7832d38..07d169a 100644
--- a/ios/chrome/app/application_delegate/url_opener_unittest.mm
+++ b/ios/chrome/app/application_delegate/url_opener_unittest.mm
@@ -233,7 +233,6 @@
 
   // Action.
   [URLOpener handleLaunchOptions:urlOpenerParams
-               applicationActive:NO
                        tabOpener:tabOpenerMock
            connectionInformation:connectionInformationMock
               startupInformation:startupInformationMock
@@ -256,7 +255,6 @@
 
   // Action.
   [URLOpener handleLaunchOptions:nil
-               applicationActive:YES
                        tabOpener:nil
            connectionInformation:connectionInformationMock
               startupInformation:startupInformationMock
@@ -278,6 +276,7 @@
 
   id startupInformationMock =
       [OCMockObject mockForProtocol:@protocol(StartupInformation)];
+  [[startupInformationMock expect] resetFirstUserActionRecorder];
   [[[startupInformationMock expect] andReturnValue:@NO] isPresentingFirstRunUI];
   id connectionInformationMock =
       [OCMockObject mockForProtocol:@protocol(ConnectionInformation)];
@@ -296,11 +295,10 @@
 #endif
 
   id appStateMock = [OCMockObject mockForClass:[AppState class]];
-  [[appStateMock expect] launchFromURLHandled:YES];
+  [[appStateMock expect] launchFromURLHandled:NO];
 
   // Action.
   [URLOpener handleLaunchOptions:urlOpenerParams
-               applicationActive:YES
                        tabOpener:tabOpenerMock
            connectionInformation:connectionInformationMock
               startupInformation:startupInformationMock
@@ -329,7 +327,6 @@
 
   // Action.
   [URLOpener handleLaunchOptions:urlOpenerParams
-               applicationActive:YES
                        tabOpener:nil
            connectionInformation:connectionInformationMock
               startupInformation:startupInformationMock
@@ -365,7 +362,6 @@
 
   // Action.
   [URLOpener handleLaunchOptions:urlOpenerParams
-               applicationActive:NO
                        tabOpener:tabOpenerMock
            connectionInformation:connectionInformationMock
               startupInformation:startupInformationMock
@@ -398,7 +394,6 @@
 
   // Action.
   [URLOpener handleLaunchOptions:urlOpenerParams
-               applicationActive:NO
                        tabOpener:tabOpenerMock
            connectionInformation:connectionInformationMock
               startupInformation:startupInformationMock
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm
index 00f2f3f..74e93d1 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -196,9 +196,7 @@
     // The app is already active so the applicationDidBecomeActive: method will
     // never be called. Open the requested URL immediately.
     ApplicationModeForTabOpening targetMode =
-        [[connectionInformation startupParameters] launchInIncognito]
-            ? ApplicationModeForTabOpening::INCOGNITO
-            : ApplicationModeForTabOpening::NORMAL;
+        [[connectionInformation startupParameters] applicationMode];
     UrlLoadParams params = UrlLoadParams::InNewTab(webpageGURL);
     if (![[connectionInformation startupParameters] launchInIncognito] &&
         [tabOpener URLIsOpenedInRegularMode:webpageGURL]) {
@@ -291,9 +289,7 @@
     // been dismissed. |_startupParameters| must be retained until all deferred
     // modal UIs are dismissed and tab opened with requested URL.
     ApplicationModeForTabOpening targetMode =
-        [[connectionInformation startupParameters] launchInIncognito]
-            ? ApplicationModeForTabOpening::INCOGNITO
-            : ApplicationModeForTabOpening::NORMAL;
+        [[connectionInformation startupParameters] applicationMode];
     GURL URL;
     GURL virtualURL;
     GURL completeURL = connectionInformation.startupParameters.completeURL;
diff --git a/ios/chrome/app/tab_opener_unittest.mm b/ios/chrome/app/tab_opener_unittest.mm
index 7fd611b5..91b64c5 100644
--- a/ios/chrome/app/tab_opener_unittest.mm
+++ b/ios/chrome/app/tab_opener_unittest.mm
@@ -27,7 +27,6 @@
 // returns nothing.
 typedef void (^HandleLaunchOptions)(id self,
                                     NSDictionary* options,
-                                    BOOL applicationActive,
                                     id<TabOpening> tabOpener,
                                     id<StartupInformation> startupInformation,
                                     AppState* appState);
@@ -47,8 +46,7 @@
       AppState* expectedAppState) {
     swizzle_block_executed_ = NO;
     swizzle_block_ =
-        [^(id self, URLOpenerParams* params, BOOL applicationActive,
-           id<TabOpening> tabOpener,
+        [^(id self, URLOpenerParams* params, id<TabOpening> tabOpener,
            id<ConnectionInformation> connectionInformation,
            id<StartupInformation> startupInformation, AppState* appState) {
           swizzle_block_executed_ = YES;
@@ -61,8 +59,8 @@
     URL_opening_handle_launch_swizzler_.reset(new ScopedBlockSwizzler(
         [URLOpener class],
         @selector(handleLaunchOptions:
-                    applicationActive:tabOpener:connectionInformation
-                                     :startupInformation:appState:),
+                            tabOpener:connectionInformation:startupInformation
+                                     :appState:),
         swizzle_block_));
   }
 
diff --git a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
index 30eb5e4..7795eb40 100644
--- a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
+++ b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
@@ -36,6 +36,7 @@
 #include "ios/chrome/browser/language/url_language_histogram_factory.h"
 #import "ios/chrome/browser/metrics/ios_profile_session_durations_service_factory.h"
 #include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.h"
+#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h"
 #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
 #import "ios/chrome/browser/policy/policy_features.h"
 #include "ios/chrome/browser/policy_url_blocking/policy_url_blocking_service.h"
@@ -115,6 +116,7 @@
   IOSChromeGCMProfileServiceFactory::GetInstance();
   IOSChromeLargeIconCacheFactory::GetInstance();
   IOSChromeLargeIconServiceFactory::GetInstance();
+  IOSChromePasswordCheckManagerFactory::GetInstance();
   IOSChromePasswordStoreFactory::GetInstance();
   IOSChromeProfileInvalidationProviderFactory::GetInstance();
   IOSProfileSessionDurationsServiceFactory::GetInstance();
diff --git a/ios/chrome/browser/passwords/BUILD.gn b/ios/chrome/browser/passwords/BUILD.gn
index dbeb216c..2445106 100644
--- a/ios/chrome/browser/passwords/BUILD.gn
+++ b/ios/chrome/browser/passwords/BUILD.gn
@@ -13,6 +13,8 @@
     "ios_chrome_bulk_leak_check_service_factory.h",
     "ios_chrome_password_check_manager.h",
     "ios_chrome_password_check_manager.mm",
+    "ios_chrome_password_check_manager_factory.h",
+    "ios_chrome_password_check_manager_factory.mm",
     "ios_chrome_password_manager_client.h",
     "ios_chrome_password_manager_client.mm",
     "ios_chrome_password_manager_driver.h",
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_check_manager.h b/ios/chrome/browser/passwords/ios_chrome_password_check_manager.h
index 6f140ee..b9025cf 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_check_manager.h
+++ b/ios/chrome/browser/passwords/ios_chrome_password_check_manager.h
@@ -6,6 +6,7 @@
 #define IOS_CHROME_BROWSER_PASSWORDS_IOS_CHROME_PASSWORD_CHECK_MANAGER_H_
 
 #include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
 #include "components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.h"
@@ -14,6 +15,11 @@
 #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 
+class IOSChromePasswordCheckManager;
+namespace {
+class IOSChromePasswordCheckManagerProxy;
+}
+
 // Enum which represents possible states of Password Check on UI.
 // It's created based on BulkLeakCheckService::State.
 enum class PasswordCheckState {
@@ -28,7 +34,9 @@
 
 // This class handles the bulk password check feature.
 class IOSChromePasswordCheckManager
-    : public password_manager::SavedPasswordsPresenter::Observer,
+    : public base::SupportsWeakPtr<IOSChromePasswordCheckManager>,
+      public base::RefCounted<IOSChromePasswordCheckManager>,
+      public password_manager::SavedPasswordsPresenter::Observer,
       public password_manager::CompromisedCredentialsManager::Observer,
       public password_manager::BulkLeakCheckServiceInterface::Observer {
  public:
@@ -40,9 +48,6 @@
             credentials) {}
   };
 
-  explicit IOSChromePasswordCheckManager(ChromeBrowserState* browser_state);
-  ~IOSChromePasswordCheckManager() override;
-
   // Requests to start a check for compromised passwords.
   void StartPasswordCheck();
 
@@ -62,6 +67,12 @@
   }
 
  private:
+  friend class RefCounted<IOSChromePasswordCheckManager>;
+  friend class IOSChromePasswordCheckManagerProxy;
+
+  explicit IOSChromePasswordCheckManager(ChromeBrowserState* browser_state);
+  ~IOSChromePasswordCheckManager() override;
+
   // password_manager::SavedPasswordsPresenter::Observer:
   void OnSavedPasswordsChanged(
       password_manager::SavedPasswordsPresenter::SavedPasswordsView passwords)
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_check_manager.mm b/ios/chrome/browser/passwords/ios_chrome_password_check_manager.mm
index b4e3dd2..933ef18a 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_check_manager.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_check_manager.mm
@@ -22,6 +22,27 @@
     password_manager::SavedPasswordsPresenter::SavedPasswordsView;
 using State = password_manager::BulkLeakCheckServiceInterface::State;
 
+// Key used to attach UserData to a LeakCheckCredential.
+constexpr char kPasswordCheckDataKey[] = "password-check-manager-data-key";
+
+// Class which ensures that IOSChromePasswordCheckManager will stay alive
+// until password check is completed even if class what initially created
+// IOSChromePasswordCheckManager was destroyed.
+class IOSChromePasswordCheckManagerHolder : public LeakCheckCredential::Data {
+ public:
+  explicit IOSChromePasswordCheckManagerHolder(
+      scoped_refptr<IOSChromePasswordCheckManager> manager)
+      : manager_(std::move(manager)) {}
+  ~IOSChromePasswordCheckManagerHolder() override = default;
+
+  std::unique_ptr<Data> Clone() override {
+    return std::make_unique<IOSChromePasswordCheckManagerHolder>(manager_);
+  }
+
+ private:
+  scoped_refptr<IOSChromePasswordCheckManager> manager_;
+};
+
 PasswordCheckState ConvertBulkCheckState(State state) {
   switch (state) {
     case State::kIdle:
@@ -73,7 +94,10 @@
 IOSChromePasswordCheckManager::~IOSChromePasswordCheckManager() = default;
 
 void IOSChromePasswordCheckManager::StartPasswordCheck() {
-  bulk_leak_check_service_adapter_.StartBulkLeakCheck();
+  IOSChromePasswordCheckManagerHolder data(
+      scoped_refptr<IOSChromePasswordCheckManager>(this));
+  bulk_leak_check_service_adapter_.StartBulkLeakCheck(kPasswordCheckDataKey,
+                                                      &data);
   is_check_running_ = true;
 }
 
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h
new file mode 100644
index 0000000..074e96b
--- /dev/null
+++ b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium 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_PASSWORDS_IOS_CHROME_PASSWORD_CHECK_MANAGER_FACTORY_H_
+#define IOS_CHROME_BROWSER_PASSWORDS_IOS_CHROME_PASSWORD_CHECK_MANAGER_FACTORY_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/no_destructor.h"
+#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+
+class ChromeBrowserState;
+class IOSChromePasswordCheckManager;
+
+// Singleton that owns weak pointer to IOSChromePasswordCheckManager.
+class IOSChromePasswordCheckManagerFactory
+    : public BrowserStateKeyedServiceFactory {
+ public:
+  static IOSChromePasswordCheckManagerFactory* GetInstance();
+  static scoped_refptr<IOSChromePasswordCheckManager> GetForBrowserState(
+      ChromeBrowserState* browser_state);
+
+ private:
+  friend class base::NoDestructor<IOSChromePasswordCheckManagerFactory>;
+
+  IOSChromePasswordCheckManagerFactory();
+  ~IOSChromePasswordCheckManagerFactory() override;
+
+  std::unique_ptr<KeyedService> BuildServiceInstanceFor(
+      web::BrowserState* context) const override;
+};
+
+#endif  // IOS_CHROME_BROWSER_PASSWORDS_IOS_CHROME_PASSWORD_CHECK_MANAGER_FACTORY_H_
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.mm b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.mm
new file mode 100644
index 0000000..069c7b59
--- /dev/null
+++ b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.mm
@@ -0,0 +1,71 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "components/keyed_service/ios/browser_state_dependency_manager.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+class IOSChromePasswordCheckManagerProxy : public KeyedService {
+ public:
+  explicit IOSChromePasswordCheckManagerProxy(ChromeBrowserState* browser_state)
+      : browser_state_(browser_state) {}
+
+  void Shutdown() override { browser_state_ = nullptr; }
+
+  scoped_refptr<IOSChromePasswordCheckManager> GetOrCreateManager() {
+    if (instance_)
+      return scoped_refptr<IOSChromePasswordCheckManager>(instance_.get());
+
+    scoped_refptr<IOSChromePasswordCheckManager> manager =
+        new IOSChromePasswordCheckManager(browser_state_);
+    instance_ = manager->AsWeakPtr();
+    return manager;
+  }
+
+ private:
+  ChromeBrowserState* browser_state_ = nullptr;
+  base::WeakPtr<IOSChromePasswordCheckManager> instance_;
+};
+}
+
+// static
+IOSChromePasswordCheckManagerFactory*
+IOSChromePasswordCheckManagerFactory::GetInstance() {
+  static base::NoDestructor<IOSChromePasswordCheckManagerFactory> instance;
+  return instance.get();
+}
+
+// static
+scoped_refptr<IOSChromePasswordCheckManager>
+IOSChromePasswordCheckManagerFactory::GetForBrowserState(
+    ChromeBrowserState* browser_state) {
+  return static_cast<IOSChromePasswordCheckManagerProxy*>(
+             GetInstance()->GetServiceForBrowserState(browser_state, true))
+      ->GetOrCreateManager();
+}
+
+IOSChromePasswordCheckManagerFactory::IOSChromePasswordCheckManagerFactory()
+    : BrowserStateKeyedServiceFactory(
+          "PasswordCheckManager",
+          BrowserStateDependencyManager::GetInstance()) {}
+
+IOSChromePasswordCheckManagerFactory::~IOSChromePasswordCheckManagerFactory() =
+    default;
+
+std::unique_ptr<KeyedService>
+IOSChromePasswordCheckManagerFactory::BuildServiceInstanceFor(
+    web::BrowserState* context) const {
+  return std::make_unique<IOSChromePasswordCheckManagerProxy>(
+      ChromeBrowserState::FromBrowserState(context));
+}
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm
index 61c2e9e8..4006defe 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm
@@ -29,6 +29,7 @@
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/browser/passwords/ios_chrome_bulk_leak_check_service_factory.h"
+#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h"
 #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
 #include "ios/web/public/test/web_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -146,8 +147,9 @@
       : browser_state_(TestChromeBrowserState::Builder().Build()),
         bulk_leak_check_service_(
             CreateAndUseBulkLeakCheckService(browser_state_.get())),
-        store_(CreateAndUseTestPasswordStore(browser_state_.get())),
-        manager_(browser_state_.get()) {
+        store_(CreateAndUseTestPasswordStore(browser_state_.get())) {
+    manager_ = IOSChromePasswordCheckManagerFactory::GetForBrowserState(
+        browser_state_.get());
     scoped_feature_list_.InitAndEnableFeature(
         password_manager::features::kPasswordCheck);
   }
@@ -157,7 +159,7 @@
   ChromeBrowserState* browser_state() { return browser_state_.get(); }
   TestPasswordStore& store() { return *store_; }
   MockBulkLeakCheckService* service() { return bulk_leak_check_service_; }
-  IOSChromePasswordCheckManager& manager() { return manager_; }
+  IOSChromePasswordCheckManager& manager() { return *manager_; }
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -167,7 +169,7 @@
   std::unique_ptr<ChromeBrowserState> browser_state_;
   MockBulkLeakCheckService* bulk_leak_check_service_;
   scoped_refptr<TestPasswordStore> store_;
-  IOSChromePasswordCheckManager manager_;
+  scoped_refptr<IOSChromePasswordCheckManager> manager_;
 };
 }  // namespace
 
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm
index 5a63a4e..6c06f07 100644
--- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#import "base/test/ios/wait_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/browser/signin/feature_flags.h"
@@ -145,6 +146,8 @@
 
   NSDictionary* GetHeaderFieldsWithCookies(NSArray<NSHTTPCookie*>* cookies);
 
+  bool FetchURL(const GURL& url);
+
   friend TestGaiaAuthFetcherIOSNSURLSessionBridge;
 
   // kWKHTTPSystemCookieStore and kUseNSURLSessionForGaiaSigninRequests should
@@ -165,6 +168,7 @@
   NSHTTPCookieStorage* http_cookie_storage_mock_;
   NSURLSession* url_session_mock_;
   NSURLSessionDataTask* url_session_data_task_mock_;
+  bool url_session_data_task_resumed_ = false;
   NSURLSessionConfiguration* url_session_configuration_mock_;
   DataTaskWithRequestCompletionHandler completion_handler_;
 };
@@ -205,7 +209,9 @@
       .andReturn(url_session_configuration_mock_);
   url_session_data_task_mock_ =
       OCMStrictClassMock([NSURLSessionDataTask class]);
-  OCMExpect([url_session_data_task_mock_ resume]);
+  OCMExpect([url_session_data_task_mock_ resume]).andDo(^(NSInvocation*) {
+    url_session_data_task_resumed_ = true;
+  });
   completion_handler_ = nil;
 }
 
@@ -322,19 +328,29 @@
   return @{@"Set-Cookie" : cookie_string};
 }
 
+bool GaiaAuthFetcherIOSNSURLSessionBridgeTest::FetchURL(const GURL& url) {
+  DCHECK(!url_session_data_task_resumed_);
+  ns_url_session_bridge_->Fetch(url, "", "", false);
+  WaitForBackgroundTasks();
+  bool success = base::test::ios::WaitUntilConditionOrTimeout(
+      base::test::ios::kWaitForActionTimeout, ^bool {
+        return url_session_data_task_resumed_;
+      });
+  url_session_data_task_resumed_ = false;
+  return success;
+}
+
 #pragma mark - Tests
 
 // Tests to send a request with no cookies set in the cookie store and receive
 // multiples cookies from the request.
-// TODO(crbug.com/1065349): this test is flaky.
-TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest,
-       DISABLED_FetchWithEmptyCookieStore) {
-  ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false);
+TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FetchWithEmptyCookieStore) {
   OCMExpect([http_cookie_storage_mock_
       storeCookies:@[]
            forTask:url_session_data_task_mock_]);
-  WaitForBackgroundTasks();
-  EXPECT_NE(nullptr, completion_handler_);
+  ASSERT_TRUE(FetchURL(GetFetchGURL()));
+  ASSERT_TRUE(completion_handler_);
+
   NSHTTPURLResponse* http_url_reponse =
       CreateHTTPURLResponse(200, @[ GetCookie1(), GetCookie2() ]);
   completion_handler_([@"Test" dataUsingEncoding:NSUTF8StringEncoding],
@@ -349,17 +365,16 @@
 
 // Tests to send a request with one cookie set in the cookie store and receive
 // another cookies from the request.
-// TODO(crbug.com/1065349): this test is flaky.
-TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest,
-       DISABLED_FetchWithCookieStore) {
+TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FetchWithCookieStore) {
   NSArray* cookies_to_send = @[ GetCookie1() ];
   AddCookiesToCookieManager(cookies_to_send);
-  ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false);
+
   OCMExpect([http_cookie_storage_mock_
       storeCookies:cookies_to_send
            forTask:url_session_data_task_mock_]);
-  WaitForBackgroundTasks();
-  EXPECT_NE(nullptr, completion_handler_);
+  ASSERT_TRUE(FetchURL(GetFetchGURL()));
+  ASSERT_TRUE(completion_handler_);
+
   NSHTTPURLResponse* http_url_reponse =
       CreateHTTPURLResponse(200, @[ GetCookie2() ]);
   completion_handler_(nil, http_url_reponse, nil);
@@ -373,14 +388,13 @@
 
 // Tests to a request with a redirect. One cookie is received by the first
 // request, and a second one by the redirected request.
-// TODO(crbug.com/1065349): this test is flaky.
-TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, DISABLED_FetchWithRedirect) {
-  ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false);
+TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FetchWithRedirect) {
   OCMExpect([http_cookie_storage_mock_
       storeCookies:@[]
            forTask:url_session_data_task_mock_]);
-  WaitForBackgroundTasks();
-  EXPECT_NE(nullptr, completion_handler_);
+  ASSERT_TRUE(FetchURL(GetFetchGURL()));
+  ASSERT_TRUE(completion_handler_);
+
   NSURLRequest* redirected_url_request =
       OCMStrictClassMock([NSURLRequest class]);
   __block bool completion_handler_called = false;
@@ -410,12 +424,12 @@
 
 // Tests to cancel the request.
 TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FetchWithCancel) {
-  ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false);
   OCMExpect([http_cookie_storage_mock_
       storeCookies:@[]
            forTask:url_session_data_task_mock_]);
-  WaitForBackgroundTasks();
-  EXPECT_NE(nullptr, completion_handler_);
+  ASSERT_TRUE(FetchURL(GetFetchGURL()));
+  ASSERT_TRUE(completion_handler_);
+
   OCMExpect([url_session_data_task_mock_ cancel]);
   ns_url_session_bridge_->Cancel();
   WaitForBackgroundTasks();
@@ -428,12 +442,12 @@
 
 // Tests a request with error.
 TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FetchWithError) {
-  ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false);
   OCMExpect([http_cookie_storage_mock_
       storeCookies:@[]
            forTask:url_session_data_task_mock_]);
-  WaitForBackgroundTasks();
-  EXPECT_NE(nullptr, completion_handler_);
+  ASSERT_TRUE(FetchURL(GetFetchGURL()));
+  ASSERT_TRUE(completion_handler_);
+
   NSHTTPURLResponse* http_url_reponse =
       CreateHTTPURLResponse(501, @[ GetCookie1(), GetCookie2() ]);
   completion_handler_(nil, http_url_reponse,
diff --git a/ios/chrome/browser/ui/bookmarks/BUILD.gn b/ios/chrome/browser/ui/bookmarks/BUILD.gn
index ca88041..2e5504a9 100644
--- a/ios/chrome/browser/ui/bookmarks/BUILD.gn
+++ b/ios/chrome/browser/ui/bookmarks/BUILD.gn
@@ -203,6 +203,7 @@
     "//ios/chrome/browser/ui/authentication/signin:constants",
     "//ios/chrome/browser/ui/popup_menu:constants",
     "//ios/chrome/browser/ui/table_view:feature_flags",
+    "//ios/chrome/browser/ui/util:multiwindow_util",
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/testing/earl_grey:earl_grey_support",
@@ -284,6 +285,7 @@
     "//ios/chrome/browser/ui/authentication/signin:constants",
     "//ios/chrome/browser/ui/popup_menu:constants",
     "//ios/chrome/browser/ui/table_view:feature_flags",
+    "//ios/chrome/browser/ui/util:multiwindow_util",
     "//ios/chrome/test/earl_grey:eg_test_support+eg2",
     "//ios/testing/earl_grey:eg_test_support+eg2",
     "//ios/third_party/earl_grey2:test_lib",
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_entries_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_entries_egtest.mm
index 91eefdc..75d8f9e 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmarks_entries_egtest.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmarks_entries_egtest.mm
@@ -12,6 +12,7 @@
 #import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_ui.h"
 #import "ios/chrome/browser/ui/bookmarks/bookmark_ui_constants.h"
 #import "ios/chrome/browser/ui/table_view/feature_flags.h"
+#import "ios/chrome/browser/ui/util/multi_window_support.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
@@ -208,6 +209,41 @@
   [BookmarkEarlGreyUI verifyContextMenuForSingleURLWithEditEnabled:YES];
 }
 
+// Tests display and selection of 'Open in New Window' in a context menu on a
+// bookmarks entry.
+- (void)testContextMenuOpenInNewWindow {
+  // TODO(crbug.com/1035764): EG1 Test fails on iOS 12.
+  if (!base::ios::IsRunningOnIOS13OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"EG1 Fails on iOS 12.");
+  }
+
+  if (!IsMultiwindowSupported()) {
+    EARL_GREY_TEST_DISABLED(@"MultiWindow is not Supported.");
+  }
+
+  [BookmarkEarlGrey setupStandardBookmarks];
+  [BookmarkEarlGreyUI openBookmarks];
+  [BookmarkEarlGreyUI openMobileBookmarks];
+
+  [ChromeEarlGrey waitForBrowserCount:1];
+
+  // Open a bookmark in a new window (through a long press).
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"First URL")]
+      performAction:grey_longPress()];
+  [[EarlGrey
+      selectElementWithMatcher:ButtonWithAccessibilityLabelId(
+                                   IDS_IOS_CONTENT_CONTEXT_OPENINNEWWINDOW)]
+      performAction:grey_tap()];
+
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(
+                                          GetFirstUrl().GetContent())]
+      assertWithMatcher:grey_notNil()];
+  [ChromeEarlGrey waitForBrowserCount:2];
+
+  [ChromeEarlGrey closeCurrentTab];
+  [ChromeEarlGrey waitForBrowserCount:1];
+}
+
 // Verify Edit Text functionality on single URL selection.
 - (void)testEditTextOnSingleURL {
   // TODO(crbug.com/1049972): Re-enable on iOS 12.
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm
index de1e16d..3be3c4c 100644
--- a/ios/chrome/browser/ui/main/scene_controller.mm
+++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -338,17 +338,23 @@
                                  startupInformation:self.mainController];
         }
         self.sceneState.connectionOptions = nil;
-
-        // Handle URL opening from
-        // |UIWindowSceneDelegate scene:openURLContexts:|.
-        if (self.sceneState.URLContextsToOpen) {
-          // When multiwindow is supported we already pass the external URLs
-          // through the scene state, therefore we do not need to rely on
-          // startup parameters.
-          [self openURLContexts:self.sceneState.URLContextsToOpen];
-          self.sceneState.URLContextsToOpen = nil;
-        }
       }
+
+      if (self.startupParameters) {
+        ApplicationModeForTabOpening mode =
+            self.startupParameters.applicationMode;
+        UrlLoadParams params =
+            UrlLoadParams::InNewTab(self.startupParameters.externalURL);
+        BOOL dismissOmnibox =
+            [self.startupParameters postOpeningAction] != FOCUS_OMNIBOX;
+        [self dismissModalsAndOpenSelectedTabInMode:mode
+                                  withUrlLoadParams:params
+                                     dismissOmnibox:dismissOmnibox
+                                         completion:^{
+                                           self.startupParameters = nil;
+                                         }];
+      }
+
     } else {
       NSDictionary* launchOptions = self.mainController.launchOptions;
       URLOpenerParams* params =
@@ -451,16 +457,14 @@
 - (void)sceneState:(SceneState*)sceneState
     hasPendingURLs:(NSSet<UIOpenURLContext*>*)URLContexts
     API_AVAILABLE(ios(13)) {
-  if (URLContexts &&
-      sceneState.activationLevel == SceneActivationLevelForegroundActive) {
-    // It is necessary to reset the URLContextsToOpen after opening them.
-    // Handle the opening asynchronously to avoid interfering with potential
-    // other observers.
-    dispatch_async(dispatch_get_main_queue(), ^{
-      [self openURLContexts:sceneState.URLContextsToOpen];
-      self.sceneState.URLContextsToOpen = nil;
-    });
-  }
+  DCHECK(URLContexts);
+  // It is necessary to reset the URLContextsToOpen after opening them.
+  // Handle the opening asynchronously to avoid interfering with potential
+  // other observers.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    [self openURLContexts:sceneState.URLContextsToOpen];
+    self.sceneState.URLContextsToOpen = nil;
+  });
 }
 
 - (void)performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
@@ -1395,11 +1399,7 @@
                  startupInformation:(id<StartupInformation>)startupInformation
                            appState:(AppState*)appState {
   if (params) {
-    BOOL sceneIsActive =
-        self.sceneState.activationLevel >= SceneActivationLevelForegroundActive;
-
     [URLOpener handleLaunchOptions:params
-                 applicationActive:sceneIsActive
                          tabOpener:self
              connectionInformation:self
                 startupInformation:startupInformation
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
index 75836c8..9ddfd6e 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
@@ -33,6 +33,7 @@
 #include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/passwords/ios_chrome_password_check_manager.h"
+#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h"
 #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
 #import "ios/chrome/browser/passwords/save_passwords_consumer.h"
 #import "ios/chrome/browser/signin/authentication_service.h"
@@ -194,7 +195,7 @@
   // The item related to the button for exporting passwords.
   TableViewTextItem* _exportPasswordsItem;
   // The service responsible for password check feature.
-  std::unique_ptr<IOSChromePasswordCheckManager> _passwordCheck;
+  scoped_refptr<IOSChromePasswordCheckManager> _passwordCheck;
   // The interface for getting and manipulating a user's saved passwords.
   scoped_refptr<password_manager::PasswordStore> _passwordStore;
   // A helper object for passing data about saved passwords from a finished
@@ -268,7 +269,8 @@
     _passwordStore = IOSChromePasswordStoreFactory::GetForBrowserState(
         _browserState, ServiceAccessType::EXPLICIT_ACCESS);
     DCHECK(_passwordStore);
-    _passwordCheck.reset(new IOSChromePasswordCheckManager(_browserState));
+    _passwordCheck =
+        IOSChromePasswordCheckManagerFactory::GetForBrowserState(_browserState);
     _mediator =
         [[PasswordsMediator alloc] initWithConsumer:self
                                passwordCheckManager:_passwordCheck.get()];
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
index d8c28080..55de58f 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
@@ -204,10 +204,10 @@
   // |-traitCollectionDidChange:| is not properly called when the view rotates
   // while it is in a ViewController deeper in the ViewController hierarchy. Use
   // self.traitCollection since iOS 13 where the bug is fixed in UIKit.
-  return UIApplication.sharedApplication.keyWindow.traitCollection
-                 .verticalSizeClass == UIUserInterfaceSizeClassRegular &&
-         UIApplication.sharedApplication.keyWindow.traitCollection
-                 .horizontalSizeClass == UIUserInterfaceSizeClassCompact;
+  return self.window.traitCollection.verticalSizeClass ==
+             UIUserInterfaceSizeClassRegular &&
+         self.window.traitCollection.horizontalSizeClass ==
+             UIUserInterfaceSizeClassCompact;
 }
 
 @end
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index 4464f1e4..ecc7a9d1 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -28,7 +28,6 @@
   PrintMsgStart,
   ExtensionMsgStart,
   TextInputClientMsgStart,
-  PrerenderMsgStart,
   ChromotingMsgStart,
   AndroidWebViewMsgStart,
   NaClHostMsgStart,
diff --git a/ipc/trace_ipc_message.cc b/ipc/trace_ipc_message.cc
index 11fac576..503f26f 100644
--- a/ipc/trace_ipc_message.cc
+++ b/ipc/trace_ipc_message.cc
@@ -67,9 +67,6 @@
     case TextInputClientMsgStart:
       message_class = ChromeLegacyIpc::CLASS_TEXT_INPUT_CLIENT;
       break;
-    case PrerenderMsgStart:
-      message_class = ChromeLegacyIpc::CLASS_PRERENDER;
-      break;
     case ChromotingMsgStart:
       message_class = ChromeLegacyIpc::CLASS_CHROMOTING;
       break;
diff --git a/media/capture/mojom/video_capture_types.mojom b/media/capture/mojom/video_capture_types.mojom
index ce0943d..28b663e 100644
--- a/media/capture/mojom/video_capture_types.mojom
+++ b/media/capture/mojom/video_capture_types.mojom
@@ -303,9 +303,8 @@
   string model_id;
   VideoFacingMode facing_mode;
   VideoCaptureApi capture_api;
-  VideoCaptureTransportType transport_type;
-  bool has_pan_tilt_zoom_supported;
   bool pan_tilt_zoom_supported;
+  VideoCaptureTransportType transport_type;
 };
 
 // Bundles a VideoCaptureDeviceDescriptor with corresponding supported
diff --git a/media/capture/mojom/video_capture_types_mojom_traits.cc b/media/capture/mojom/video_capture_types_mojom_traits.cc
index d2f6048..97cc207 100644
--- a/media/capture/mojom/video_capture_types_mojom_traits.cc
+++ b/media/capture/mojom/video_capture_types_mojom_traits.cc
@@ -1685,10 +1685,9 @@
     return false;
   if (!data.ReadCaptureApi(&(output->capture_api)))
     return false;
+  output->set_pan_tilt_zoom_supported(data.pan_tilt_zoom_supported());
   if (!data.ReadTransportType(&(output->transport_type)))
     return false;
-  if (data.has_pan_tilt_zoom_supported())
-    output->set_pan_tilt_zoom_supported(data.pan_tilt_zoom_supported());
   return true;
 }
 
diff --git a/media/capture/mojom/video_capture_types_mojom_traits.h b/media/capture/mojom/video_capture_types_mojom_traits.h
index 548149d..db7de92a 100644
--- a/media/capture/mojom/video_capture_types_mojom_traits.h
+++ b/media/capture/mojom/video_capture_types_mojom_traits.h
@@ -184,21 +184,16 @@
     return input.capture_api;
   }
 
+  static bool pan_tilt_zoom_supported(
+      const media::VideoCaptureDeviceDescriptor& input) {
+    return input.pan_tilt_zoom_supported();
+  }
+
   static media::VideoCaptureTransportType transport_type(
       const media::VideoCaptureDeviceDescriptor& input) {
     return input.transport_type;
   }
 
-  static bool has_pan_tilt_zoom_supported(
-      const media::VideoCaptureDeviceDescriptor& input) {
-    return input.pan_tilt_zoom_supported().has_value();
-  }
-
-  static bool pan_tilt_zoom_supported(
-      const media::VideoCaptureDeviceDescriptor& input) {
-    return input.pan_tilt_zoom_supported().value_or(false);
-  }
-
   static bool Read(media::mojom::VideoCaptureDeviceDescriptorDataView data,
                    media::VideoCaptureDeviceDescriptor* output);
 };
diff --git a/media/capture/video/android/video_capture_device_factory_android.cc b/media/capture/video/android/video_capture_device_factory_android.cc
index 8e5cba8..2467931 100644
--- a/media/capture/video/android/video_capture_device_factory_android.cc
+++ b/media/capture/video/android/video_capture_device_factory_android.cc
@@ -82,9 +82,9 @@
     VideoCaptureDeviceDescriptor descriptor(
         display_name, device_id, "" /*model_id*/,
         static_cast<VideoCaptureApi>(capture_api_type),
+        /*pan_tilt_zoom_supported=*/false,
         VideoCaptureTransportType::OTHER_TRANSPORT,
-        static_cast<VideoFacingMode>(facing_mode),
-        /*pan_tilt_zoom_supported=*/false);
+        static_cast<VideoFacingMode>(facing_mode));
 
     // We put user-facing devices to the front of the list in order to make
     // them by-default preferred over environment-facing ones when no other
diff --git a/media/capture/video/fake_video_capture_device_factory.cc b/media/capture/video/fake_video_capture_device_factory.cc
index 32c6f2a..3c3f799 100644
--- a/media/capture/video/fake_video_capture_device_factory.cc
+++ b/media/capture/video/fake_video_capture_device_factory.cc
@@ -219,8 +219,8 @@
 #elif defined(OS_FUCHSIA)
         VideoCaptureApi::UNKNOWN,
 #endif
-        VideoCaptureTransportType::OTHER_TRANSPORT,
-        entry.photo_device_config.pan_tilt_zoom_supported);
+        entry.photo_device_config.pan_tilt_zoom_supported,
+        VideoCaptureTransportType::OTHER_TRANSPORT);
     entry_index++;
   }
 }
diff --git a/media/capture/video/linux/fake_v4l2_impl.cc b/media/capture/video/linux/fake_v4l2_impl.cc
index b46b8ae..0d2c365 100644
--- a/media/capture/video/linux/fake_v4l2_impl.cc
+++ b/media/capture/video/linux/fake_v4l2_impl.cc
@@ -137,10 +137,8 @@
       case V4L2_CID_PAN_ABSOLUTE:
       case V4L2_CID_TILT_ABSOLUTE:
       case V4L2_CID_ZOOM_ABSOLUTE:
-        if (!config_.descriptor.pan_tilt_zoom_supported().has_value() ||
-            !config_.descriptor.pan_tilt_zoom_supported().value()) {
+        if (!config_.descriptor.pan_tilt_zoom_supported())
           return EINVAL;
-        }
         control->flags = 0;
         control->minimum = 100;
         control->maximum = 400;
diff --git a/media/capture/video/linux/video_capture_device_factory_linux.cc b/media/capture/video/linux/video_capture_device_factory_linux.cc
index 60c8597..92b89a7 100644
--- a/media/capture/video/linux/video_capture_device_factory_linux.cc
+++ b/media/capture/video/linux/video_capture_device_factory_linux.cc
@@ -218,13 +218,14 @@
       device_descriptors->emplace_back(
           display_name, unique_id, model_id,
           VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE,
+          IsPanTiltZoomSupported(fd.get()),
           VideoCaptureTransportType::OTHER_TRANSPORT,
 #if defined(OS_CHROMEOS)
-          device_provider_->GetCameraFacing(unique_id, model_id),
+          device_provider_->GetCameraFacing(unique_id, model_id)
 #else
-          VideoFacingMode::MEDIA_VIDEO_FACING_NONE,
+          VideoFacingMode::MEDIA_VIDEO_FACING_NONE
 #endif
-          IsPanTiltZoomSupported(fd.get()));
+      );
     }
   }
   // Since JS doesn't have API to get camera facing, we sort the list to make
diff --git a/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc b/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc
index fd53b89..2ee1fdd 100644
--- a/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc
+++ b/media/capture/video/linux/video_capture_device_factory_linux_unittest.cc
@@ -104,7 +104,7 @@
   ASSERT_EQ(1u, descriptors.size());
   EXPECT_EQ(descriptor.device_id, descriptors[0].device_id);
   EXPECT_EQ(descriptor.display_name(), descriptors[0].display_name());
-  EXPECT_EQ(descriptor.pan_tilt_zoom_supported().value(),
+  EXPECT_EQ(descriptor.pan_tilt_zoom_supported(),
             descriptors[0].pan_tilt_zoom_supported());
 }
 
@@ -115,12 +115,10 @@
         VideoCaptureDeviceDescriptor("Fake Device 0",
                                      "/dev/video0",
                                      VideoCaptureApi::UNKNOWN,
-                                     VideoCaptureTransportType::OTHER_TRANSPORT,
                                      /*pan_tilt_zoom_supported=*/false),
         VideoCaptureDeviceDescriptor("Fake Device 0",
                                      "/dev/video0",
                                      VideoCaptureApi::UNKNOWN,
-                                     VideoCaptureTransportType::OTHER_TRANSPORT,
                                      /*pan_tilt_zoom_supported=*/true)));
 
 TEST_F(VideoCaptureDeviceFactoryLinuxTest,
diff --git a/media/capture/video/mac/video_capture_device_factory_mac.mm b/media/capture/video/mac/video_capture_device_factory_mac.mm
index 6482d1f..b7f6240 100644
--- a/media/capture/video/mac/video_capture_device_factory_mac.mm
+++ b/media/capture/video/mac/video_capture_device_factory_mac.mm
@@ -123,9 +123,8 @@
         device_id, capture_api, device_transport_type);
     VideoCaptureDeviceDescriptor descriptor(
         [[[capture_devices valueForKey:key] deviceName] UTF8String], device_id,
-        model_id, capture_api, device_transport_type,
-        VideoFacingMode::MEDIA_VIDEO_FACING_NONE,
-        /*pan_tilt_zoom_supported=*/false);
+        model_id, capture_api,
+        /*pan_tilt_zoom_supported=*/false, device_transport_type);
     if (IsDeviceBlacklisted(descriptor))
       continue;
     device_descriptors->push_back(descriptor);
diff --git a/media/capture/video/mac/video_capture_device_factory_mac_unittest.mm b/media/capture/video/mac/video_capture_device_factory_mac_unittest.mm
index 8133c4ac..f27dc2f2 100644
--- a/media/capture/video/mac/video_capture_device_factory_mac_unittest.mm
+++ b/media/capture/video/mac/video_capture_device_factory_mac_unittest.mm
@@ -57,7 +57,7 @@
       return;
     }
     for (const auto& descriptor : descriptors)
-      EXPECT_FALSE(descriptor.pan_tilt_zoom_supported().value());
+      EXPECT_FALSE(descriptor.pan_tilt_zoom_supported());
   }));
 }
 
diff --git a/media/capture/video/video_capture_device_descriptor.cc b/media/capture/video/video_capture_device_descriptor.cc
index 8ece28f..4733b1c 100644
--- a/media/capture/video/video_capture_device_descriptor.cc
+++ b/media/capture/video/video_capture_device_descriptor.cc
@@ -25,8 +25,8 @@
     const std::string& display_name,
     const std::string& device_id,
     VideoCaptureApi capture_api,
-    VideoCaptureTransportType transport_type,
-    const base::Optional<bool>& pan_tilt_zoom_supported)
+    bool pan_tilt_zoom_supported,
+    VideoCaptureTransportType transport_type)
     : device_id(device_id),
       facing(VideoFacingMode::MEDIA_VIDEO_FACING_NONE),
       capture_api(capture_api),
@@ -39,9 +39,9 @@
     const std::string& device_id,
     const std::string& model_id,
     VideoCaptureApi capture_api,
+    bool pan_tilt_zoom_supported,
     VideoCaptureTransportType transport_type,
-    VideoFacingMode facing,
-    const base::Optional<bool>& pan_tilt_zoom_supported)
+    VideoFacingMode facing)
     : device_id(device_id),
       model_id(model_id),
       facing(facing),
diff --git a/media/capture/video/video_capture_device_descriptor.h b/media/capture/video/video_capture_device_descriptor.h
index b2c3eb1..bd2dc8e 100644
--- a/media/capture/video/video_capture_device_descriptor.h
+++ b/media/capture/video/video_capture_device_descriptor.h
@@ -55,18 +55,18 @@
       const std::string& display_name,
       const std::string& device_id,
       VideoCaptureApi capture_api = VideoCaptureApi::UNKNOWN,
+      bool pan_tilt_zoom_supported = false,
       VideoCaptureTransportType transport_type =
-          VideoCaptureTransportType::OTHER_TRANSPORT,
-      const base::Optional<bool>& pan_tilt_zoom_supported = base::nullopt);
+          VideoCaptureTransportType::OTHER_TRANSPORT);
   VideoCaptureDeviceDescriptor(
       const std::string& display_name,
       const std::string& device_id,
       const std::string& model_id,
       VideoCaptureApi capture_api,
+      bool pan_tilt_zoom_supported,
       VideoCaptureTransportType transport_type =
           VideoCaptureTransportType::OTHER_TRANSPORT,
-      VideoFacingMode facing = VideoFacingMode::MEDIA_VIDEO_FACING_NONE,
-      const base::Optional<bool>& pan_tilt_zoom_supported = base::nullopt);
+      VideoFacingMode facing = VideoFacingMode::MEDIA_VIDEO_FACING_NONE);
   VideoCaptureDeviceDescriptor(const VideoCaptureDeviceDescriptor& other);
   ~VideoCaptureDeviceDescriptor();
 
@@ -86,9 +86,7 @@
   const std::string& display_name() const { return display_name_; }
   void set_display_name(const std::string& name);
 
-  const base::Optional<bool>& pan_tilt_zoom_supported() const {
-    return pan_tilt_zoom_supported_;
-  }
+  bool pan_tilt_zoom_supported() const { return pan_tilt_zoom_supported_; }
   void set_pan_tilt_zoom_supported(bool supported) {
     pan_tilt_zoom_supported_ = supported;
   }
@@ -106,7 +104,7 @@
 
  private:
   std::string display_name_;  // Name that is intended for display in the UI
-  base::Optional<bool> pan_tilt_zoom_supported_;
+  bool pan_tilt_zoom_supported_ = false;
 };
 
 using VideoCaptureDeviceDescriptors = std::vector<VideoCaptureDeviceDescriptor>;
diff --git a/media/capture/video/win/video_capture_device_factory_win.cc b/media/capture/video/win/video_capture_device_factory_win.cc
index cb88fb0e..6025e8a 100644
--- a/media/capture/video/win/video_capture_device_factory_win.cc
+++ b/media/capture/video/win/video_capture_device_factory_win.cc
@@ -707,9 +707,8 @@
                 VideoCaptureDeviceMFWin::IsPanTiltZoomSupported(
                     std::move(source));
             device_descriptors->emplace_back(display_name, device_id, model_id,
-                                             api_attributes.first);
-            device_descriptors->back().set_pan_tilt_zoom_supported(
-                pan_tilt_zoom_supported);
+                                             api_attributes.first,
+                                             pan_tilt_zoom_supported);
           }
         }
       }
@@ -808,9 +807,8 @@
             std::move(capture_filter));
 
     device_descriptors->emplace_back(device_name, id, model_id,
-                                     VideoCaptureApi::WIN_DIRECT_SHOW);
-    device_descriptors->back().set_pan_tilt_zoom_supported(
-        pan_tilt_zoom_supported);
+                                     VideoCaptureApi::WIN_DIRECT_SHOW,
+                                     pan_tilt_zoom_supported);
   }
 }
 
diff --git a/media/capture/video/win/video_capture_device_factory_win_unittest.cc b/media/capture/video/win/video_capture_device_factory_win_unittest.cc
index 2c1e67d..c4e306b 100644
--- a/media/capture/video/win/video_capture_device_factory_win_unittest.cc
+++ b/media/capture/video/win/video_capture_device_factory_win_unittest.cc
@@ -1219,44 +1219,39 @@
   ASSERT_NE(it, descriptors.end());
   EXPECT_EQ(it->capture_api, VideoCaptureApi::WIN_MEDIA_FOUNDATION);
   EXPECT_EQ(it->display_name(), base::SysWideToUTF8(kMFDeviceName0));
-  EXPECT_TRUE(it->pan_tilt_zoom_supported().has_value());
   // No IAMCameraControl and no IAMVideoProcAmp interfaces.
-  EXPECT_FALSE(it->pan_tilt_zoom_supported().value());
+  EXPECT_FALSE(it->pan_tilt_zoom_supported());
 
   it = FindDescriptorInRange(descriptors.begin(), descriptors.end(),
                              base::SysWideToUTF8(kMFDeviceId1));
   ASSERT_NE(it, descriptors.end());
   EXPECT_EQ(it->capture_api, VideoCaptureApi::WIN_MEDIA_FOUNDATION);
   EXPECT_EQ(it->display_name(), base::SysWideToUTF8(kMFDeviceName1));
-  EXPECT_TRUE(it->pan_tilt_zoom_supported().has_value());
   // No pan/tilt/zoom in IAMCameraControl interface.
-  EXPECT_FALSE(it->pan_tilt_zoom_supported().value());
+  EXPECT_FALSE(it->pan_tilt_zoom_supported());
 
   it = FindDescriptorInRange(descriptors.begin(), descriptors.end(),
                              base::SysWideToUTF8(kMFDeviceId2));
   ASSERT_NE(it, descriptors.end());
   EXPECT_EQ(it->capture_api, VideoCaptureApi::WIN_MEDIA_FOUNDATION_SENSOR);
   EXPECT_EQ(it->display_name(), base::SysWideToUTF8(kMFDeviceName2));
-  EXPECT_TRUE(it->pan_tilt_zoom_supported().has_value());
-  EXPECT_TRUE(it->pan_tilt_zoom_supported().value());
+  EXPECT_TRUE(it->pan_tilt_zoom_supported());
 
   it = FindDescriptorInRange(descriptors.begin(), descriptors.end(),
                              base::SysWideToUTF8(kDirectShowDeviceId3));
   ASSERT_NE(it, descriptors.end());
   EXPECT_EQ(it->capture_api, VideoCaptureApi::WIN_DIRECT_SHOW);
   EXPECT_EQ(it->display_name(), base::SysWideToUTF8(kDirectShowDeviceName3));
-  EXPECT_TRUE(it->pan_tilt_zoom_supported().has_value());
   // No ICameraControl interface.
-  EXPECT_FALSE(it->pan_tilt_zoom_supported().value());
+  EXPECT_FALSE(it->pan_tilt_zoom_supported());
 
   it = FindDescriptorInRange(descriptors.begin(), descriptors.end(),
                              base::SysWideToUTF8(kDirectShowDeviceId4));
   ASSERT_NE(it, descriptors.end());
   EXPECT_EQ(it->capture_api, VideoCaptureApi::WIN_DIRECT_SHOW);
   EXPECT_EQ(it->display_name(), base::SysWideToUTF8(kDirectShowDeviceName4));
-  EXPECT_TRUE(it->pan_tilt_zoom_supported().has_value());
   // No IVideoProcAmp interface.
-  EXPECT_FALSE(it->pan_tilt_zoom_supported().value());
+  EXPECT_FALSE(it->pan_tilt_zoom_supported());
 
   // Devices that are listed in MediaFoundation but only report supported
   // formats in DirectShow are expected to get enumerated with
@@ -1266,9 +1261,8 @@
   ASSERT_NE(it, descriptors.end());
   EXPECT_EQ(it->capture_api, VideoCaptureApi::WIN_DIRECT_SHOW);
   EXPECT_EQ(it->display_name(), base::SysWideToUTF8(kDirectShowDeviceName5));
-  EXPECT_TRUE(it->pan_tilt_zoom_supported().has_value());
   // No pan, tilt, or zoom ranges in ICameraControl interface.
-  EXPECT_FALSE(it->pan_tilt_zoom_supported().value());
+  EXPECT_FALSE(it->pan_tilt_zoom_supported());
 
   // Devices that are listed in both MediaFoundation and DirectShow but are
   // blacklisted for use with MediaFoundation are expected to get enumerated
@@ -1278,8 +1272,7 @@
   ASSERT_NE(it, descriptors.end());
   EXPECT_EQ(it->capture_api, VideoCaptureApi::WIN_DIRECT_SHOW);
   EXPECT_EQ(it->display_name(), base::SysWideToUTF8(kDirectShowDeviceName6));
-  EXPECT_TRUE(it->pan_tilt_zoom_supported().has_value());
-  EXPECT_TRUE(it->pan_tilt_zoom_supported().value());
+  EXPECT_TRUE(it->pan_tilt_zoom_supported());
 }
 
 }  // namespace media
diff --git a/pdf/document_loader_impl_unittest.cc b/pdf/document_loader_impl_unittest.cc
index bbad8f6..49ac373 100644
--- a/pdf/document_loader_impl_unittest.cc
+++ b/pdf/document_loader_impl_unittest.cc
@@ -17,9 +17,9 @@
 
 using ::testing::_;
 using ::testing::Mock;
-using ::testing::Sequence;
 using ::testing::NiceMock;
 using ::testing::Return;
+using ::testing::Sequence;
 
 namespace chrome_pdf {
 
diff --git a/pdf/pdf.h b/pdf/pdf.h
index 6a1c8c2..4e76f53 100644
--- a/pdf/pdf.h
+++ b/pdf/pdf.h
@@ -25,7 +25,7 @@
 namespace gfx {
 class Rect;
 class Size;
-}
+}  // namespace gfx
 
 namespace chrome_pdf {
 
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h
index 0b4babcd..c23f208 100644
--- a/pdf/pdf_engine.h
+++ b/pdf/pdf_engine.h
@@ -47,12 +47,12 @@
 namespace gfx {
 class Rect;
 class Size;
-}
+}  // namespace gfx
 
 namespace pp {
 class InputEvent;
 class VarDictionary;
-}
+}  // namespace pp
 
 namespace chrome_pdf {
 
diff --git a/pdf/pdf_transform.h b/pdf/pdf_transform.h
index 3ed6a95..91a27b5 100644
--- a/pdf/pdf_transform.h
+++ b/pdf/pdf_transform.h
@@ -9,7 +9,7 @@
 class PointF;
 class Rect;
 class SizeF;
-}
+}  // namespace gfx
 
 namespace chrome_pdf {
 
diff --git a/pdf/pdfium/findtext_unittest.cc b/pdf/pdfium/findtext_unittest.cc
index c77e7f2b..9934ce9b 100644
--- a/pdf/pdfium/findtext_unittest.cc
+++ b/pdf/pdfium/findtext_unittest.cc
@@ -9,8 +9,8 @@
 #include "pdf/test/test_client.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
-using testing::InSequence;
 using testing::_;
+using testing::InSequence;
 
 namespace chrome_pdf {
 
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 66f988b..a763671 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -64,8 +64,8 @@
 
 using printing::ConvertUnit;
 using printing::ConvertUnitDouble;
-using printing::kPointsPerInch;
 using printing::kPixelsPerInch;
+using printing::kPointsPerInch;
 
 namespace chrome_pdf {
 
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h
index 2261904a9..23bfc4f 100644
--- a/pdf/pdfium/pdfium_engine.h
+++ b/pdf/pdfium/pdfium_engine.h
@@ -48,7 +48,7 @@
 namespace draw_utils {
 class ShadowMatrix;
 struct PageInsetSizes;
-}
+}  // namespace draw_utils
 
 class PDFiumEngine : public PDFEngine,
                      public DocumentLoader::Client,
diff --git a/pdf/pdfium/pdfium_page.cc b/pdf/pdfium/pdfium_page.cc
index 6f95aff..c7b941c2 100644
--- a/pdf/pdfium/pdfium_page.cc
+++ b/pdf/pdfium/pdfium_page.cc
@@ -30,8 +30,8 @@
 #include "ui/gfx/range/range.h"
 
 using printing::ConvertUnitDouble;
-using printing::kPointsPerInch;
 using printing::kPixelsPerInch;
+using printing::kPointsPerInch;
 
 namespace chrome_pdf {
 
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn
index 2112d02..cf02b9ba 100644
--- a/services/network/BUILD.gn
+++ b/services/network/BUILD.gn
@@ -30,8 +30,8 @@
     "crash_keys.h",
     "crl_set_distributor.cc",
     "crl_set_distributor.h",
-    "cross_origin_read_blocking.cc",
-    "cross_origin_read_blocking.h",
+    "cross_origin_read_blocking_exception_for_plugin.cc",
+    "cross_origin_read_blocking_exception_for_plugin.h",
     "data_pipe_element_reader.cc",
     "data_pipe_element_reader.h",
     "dns_config_change_manager.cc",
@@ -287,7 +287,6 @@
     "cors/cors_url_loader_factory_unittest.cc",
     "cors/cors_url_loader_unittest.cc",
     "cors/preflight_controller_unittest.cc",
-    "cross_origin_read_blocking_unittest.cc",
     "data_pipe_element_reader_unittest.cc",
     "dns_config_change_manager_unittest.cc",
     "host_resolver_unittest.cc",
diff --git a/services/network/cors/cors_url_loader_factory.cc b/services/network/cors/cors_url_loader_factory.cc
index 9c73e446..c82b912 100644
--- a/services/network/cors/cors_url_loader_factory.cc
+++ b/services/network/cors/cors_url_loader_factory.cc
@@ -16,10 +16,11 @@
 #include "services/network/cors/cors_url_loader.h"
 #include "services/network/cors/preflight_controller.h"
 #include "services/network/crash_keys.h"
-#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/cross_origin_read_blocking_exception_for_plugin.h"
 #include "services/network/network_context.h"
 #include "services/network/network_service.h"
 #include "services/network/public/cpp/cors/cors.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/header_util.h"
 #include "services/network/public/cpp/initiator_lock_compatibility.h"
@@ -485,7 +486,8 @@
       request_initiator_site_lock, request_initiator);
 
   if (result == InitiatorLockCompatibility::kIncorrectLock &&
-      CrossOriginReadBlocking::ShouldAllowForPlugin(process_id)) {
+      CrossOriginReadBlockingExceptionForPlugin::ShouldAllowForPlugin(
+          process_id)) {
     result = InitiatorLockCompatibility::kExcludedCorbForPlugin;
   }
 
diff --git a/services/network/cross_origin_read_blocking_exception_for_plugin.cc b/services/network/cross_origin_read_blocking_exception_for_plugin.cc
new file mode 100644
index 0000000..53faac4
--- /dev/null
+++ b/services/network/cross_origin_read_blocking_exception_for_plugin.cc
@@ -0,0 +1,43 @@
+// Copyright 2020 The Chromium 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 <set>
+
+#include "base/no_destructor.h"
+#include "base/stl_util.h"
+#include "services/network/cross_origin_read_blocking_exception_for_plugin.h"
+
+namespace network {
+
+namespace {
+
+std::set<int>& GetPluginProxyingProcesses() {
+  static base::NoDestructor<std::set<int>> set;
+  return *set;
+}
+
+}  // namespace
+
+// static
+void CrossOriginReadBlockingExceptionForPlugin::AddExceptionForPlugin(
+    int process_id) {
+  std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
+  plugin_proxies.insert(process_id);
+}
+
+// static
+bool CrossOriginReadBlockingExceptionForPlugin::ShouldAllowForPlugin(
+    int process_id) {
+  std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
+  return base::Contains(plugin_proxies, process_id);
+}
+
+// static
+void CrossOriginReadBlockingExceptionForPlugin::RemoveExceptionForPlugin(
+    int process_id) {
+  std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
+  plugin_proxies.erase(process_id);
+}
+
+}  // namespace network
diff --git a/services/network/cross_origin_read_blocking_exception_for_plugin.h b/services/network/cross_origin_read_blocking_exception_for_plugin.h
new file mode 100644
index 0000000..8203475
--- /dev/null
+++ b/services/network/cross_origin_read_blocking_exception_for_plugin.h
@@ -0,0 +1,38 @@
+// Copyright 2020 The Chromium 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_NETWORK_CROSS_ORIGIN_READ_BLOCKING_EXCEPTION_FOR_PLUGIN_H_
+#define SERVICES_NETWORK_CROSS_ORIGIN_READ_BLOCKING_EXCEPTION_FOR_PLUGIN_H_
+
+#include "base/component_export.h"
+#include "base/macros.h"
+
+namespace network {
+
+class COMPONENT_EXPORT(NETWORK_SERVICE)
+    CrossOriginReadBlockingExceptionForPlugin {
+ public:
+  // Notifies CORB that |process_id| is proxying requests on behalf of a
+  // universal-access plugin and therefore CORB should stop blocking requests
+  // marked as ResourceType::kPluginResource.
+  //
+  // TODO(lukasza, laforge): https://crbug.com/702995: Remove the static
+  // ...ForPlugin methods once Flash support is removed from Chromium (probably
+  // around 2020 - see https://www.chromium.org/flash-roadmap).
+  static void AddExceptionForPlugin(int process_id);
+
+  // Returns true if CORB should ignore a request initiated by a universal
+  // access plugin - i.e. if |process_id| has been previously passed to
+  // AddExceptionForPlugin.
+  static bool ShouldAllowForPlugin(int process_id);
+
+  // Reverts AddExceptionForPlugin.
+  static void RemoveExceptionForPlugin(int process_id);
+
+  DISALLOW_COPY_AND_ASSIGN(CrossOriginReadBlockingExceptionForPlugin);
+};
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_CROSS_ORIGIN_READ_BLOCKING_EXCEPTION_FOR_PLUGIN_H_
diff --git a/services/network/network_service.cc b/services/network/network_service.cc
index 4e8effcd..a1d873e4 100644
--- a/services/network/network_service.cc
+++ b/services/network/network_service.cc
@@ -48,7 +48,7 @@
 #include "net/ssl/ssl_key_logger_impl.h"
 #include "net/url_request/url_request_context.h"
 #include "services/network/crl_set_distributor.h"
-#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/cross_origin_read_blocking_exception_for_plugin.h"
 #include "services/network/dns_config_change_manager.h"
 #include "services/network/http_auth_cache_copier.h"
 #include "services/network/legacy_tls_config_distributor.h"
@@ -56,6 +56,7 @@
 #include "services/network/net_log_proxy_sink.h"
 #include "services/network/network_context.h"
 #include "services/network/network_usage_accumulator.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/initiator_lock_compatibility.h"
 #include "services/network/public/cpp/load_info_util.h"
@@ -670,7 +671,7 @@
 
 void NetworkService::AddCorbExceptionForPlugin(int32_t process_id) {
   DCHECK_NE(mojom::kBrowserProcessId, process_id);
-  CrossOriginReadBlocking::AddExceptionForPlugin(process_id);
+  CrossOriginReadBlockingExceptionForPlugin::AddExceptionForPlugin(process_id);
 }
 
 void NetworkService::AddAllowedRequestInitiatorForPlugin(
@@ -684,7 +685,8 @@
 void NetworkService::RemoveSecurityExceptionsForPlugin(int32_t process_id) {
   DCHECK_NE(mojom::kBrowserProcessId, process_id);
 
-  CrossOriginReadBlocking::RemoveExceptionForPlugin(process_id);
+  CrossOriginReadBlockingExceptionForPlugin::RemoveExceptionForPlugin(
+      process_id);
 
   std::map<int, std::set<url::Origin>>& map = plugin_origins_;
   map.erase(process_id);
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn
index 0943274..579fede 100644
--- a/services/network/public/cpp/BUILD.gn
+++ b/services/network/public/cpp/BUILD.gn
@@ -43,6 +43,8 @@
     "cross_origin_embedder_policy_parser.h",
     "cross_origin_opener_policy_parser.cc",
     "cross_origin_opener_policy_parser.h",
+    "cross_origin_read_blocking.cc",
+    "cross_origin_read_blocking.h",
     "cross_origin_resource_policy.cc",
     "cross_origin_resource_policy.h",
     "cross_thread_pending_shared_url_loader_factory.cc",
@@ -277,6 +279,7 @@
     "cors/preflight_result_unittest.cc",
     "cross_origin_embedder_policy_parser_unittest.cc",
     "cross_origin_opener_policy_parser_unittest.cc",
+    "cross_origin_read_blocking_unittest.cc",
     "cross_origin_resource_policy_unittest.cc",
     "cross_thread_pending_shared_url_loader_factory_unittest.cc",
     "data_pipe_to_source_stream_unittest.cc",
diff --git a/services/network/cross_origin_read_blocking.cc b/services/network/public/cpp/cross_origin_read_blocking.cc
similarity index 98%
rename from services/network/cross_origin_read_blocking.cc
rename to services/network/public/cpp/cross_origin_read_blocking.cc
index c0eb842..f8749b4 100644
--- a/services/network/cross_origin_read_blocking.cc
+++ b/services/network/public/cpp/cross_origin_read_blocking.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 "services/network/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
 
 #include <stddef.h>
 
@@ -220,11 +220,6 @@
   headers->RemoveHeaders(names_of_headers_to_remove);
 }
 
-std::set<int>& GetPluginProxyingProcesses() {
-  static base::NoDestructor<std::set<int>> set;
-  return *set;
-}
-
 // The function below returns a set of MIME types below may be blocked by CORB
 // without any confirmation sniffing (in contrast to HTML/JSON/XML which require
 // confirmation sniffing because images, scripts, etc. are frequently
@@ -257,7 +252,7 @@
       // The types below (zip, protobuf, etc.) are based on most commonly used
       // content types according to HTTP Archive - see:
       // https://github.com/whatwg/fetch/issues/860#issuecomment-457330454
-      "application/gzip",
+            "application/gzip",
       "application/x-gzip",
       "application/x-protobuf",
       "application/zip",
@@ -325,6 +320,7 @@
 
 }  // namespace
 
+// static
 MimeType CrossOriginReadBlocking::GetCanonicalMimeType(
     base::StringPiece mime_type) {
   // Checking for image/svg+xml and application/dash+xml early ensures that they
@@ -365,6 +361,7 @@
   return MimeType::kOthers;
 }
 
+// static
 bool CrossOriginReadBlocking::IsBlockableScheme(const GURL& url) {
   // We exclude ftp:// from here. FTP doesn't provide a Content-Type
   // header which our policy depends on, so we cannot protect any
@@ -372,6 +369,7 @@
   return url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme);
 }
 
+// static
 bool CrossOriginReadBlocking::IsValidCorsHeaderSet(
     const url::Origin& frame_origin,
     const std::string& access_control_origin) {
@@ -395,6 +393,7 @@
       url::Origin::Create(GURL(access_control_origin)));
 }
 
+// static
 // This function is a slight modification of |net::SniffForHTML|.
 SniffingResult CrossOriginReadBlocking::SniffForHTML(StringPiece data) {
   // The content sniffers used by Chrome and Firefox are using "<!--" as one of
@@ -446,6 +445,7 @@
   return kMaybe;
 }
 
+// static
 SniffingResult CrossOriginReadBlocking::SniffForXML(base::StringPiece data) {
   // TODO(dsjang): Once CrossOriginReadBlocking is moved into the browser
   // process, we should do single-thread checking here for the static
@@ -456,6 +456,7 @@
                           base::CompareCase::SENSITIVE);
 }
 
+// static
 SniffingResult CrossOriginReadBlocking::SniffForJSON(base::StringPiece data) {
   // Currently this function looks for an opening brace ('{'), followed by a
   // double-quoted string literal, followed by a colon. Importantly, such a
@@ -518,6 +519,7 @@
   return kMaybe;
 }
 
+// static
 SniffingResult CrossOriginReadBlocking::SniffForFetchOnlyResource(
     base::StringPiece data) {
   // kScriptBreakingPrefixes contains prefixes that are conventionally used to
@@ -1333,22 +1335,4 @@
       supports_range_requests_);
 }
 
-// static
-void CrossOriginReadBlocking::AddExceptionForPlugin(int process_id) {
-  std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
-  plugin_proxies.insert(process_id);
-}
-
-// static
-bool CrossOriginReadBlocking::ShouldAllowForPlugin(int process_id) {
-  std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
-  return base::Contains(plugin_proxies, process_id);
-}
-
-// static
-void CrossOriginReadBlocking::RemoveExceptionForPlugin(int process_id) {
-  std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
-  plugin_proxies.erase(process_id);
-}
-
 }  // namespace network
diff --git a/services/network/cross_origin_read_blocking.h b/services/network/public/cpp/cross_origin_read_blocking.h
similarity index 93%
rename from services/network/cross_origin_read_blocking.h
rename to services/network/public/cpp/cross_origin_read_blocking.h
index 6538b0f..5a32a25 100644
--- a/services/network/cross_origin_read_blocking.h
+++ b/services/network/public/cpp/cross_origin_read_blocking.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 SERVICES_NETWORK_CROSS_ORIGIN_READ_BLOCKING_H_
-#define SERVICES_NETWORK_CROSS_ORIGIN_READ_BLOCKING_H_
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_CROSS_ORIGIN_READ_BLOCKING_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_CROSS_ORIGIN_READ_BLOCKING_H_
 
 #include <memory>
 #include <string>
@@ -37,7 +37,7 @@
 // steal private information from other sites.  For more details see
 // services/network/cross_origin_read_blocking_explainer.md
 
-class COMPONENT_EXPORT(NETWORK_SERVICE) CrossOriginReadBlocking {
+class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginReadBlocking {
  public:
   // This enum describes how CORB should decide whether to block a given
   // no-cors, cross-origin response.
@@ -73,7 +73,7 @@
 
   // An instance for tracking the state of analyzing a single response
   // and deciding whether CORB should block the response.
-  class COMPONENT_EXPORT(NETWORK_SERVICE) ResponseAnalyzer {
+  class COMPONENT_EXPORT(NETWORK_CPP) ResponseAnalyzer {
    public:
     // Categorizes the resource MIME type for CORB protection logging.
     enum MimeTypeBucket {
@@ -334,23 +334,6 @@
     kYes,
   };
 
-  // Notifies CORB that |process_id| is proxying requests on behalf of a
-  // universal-access plugin and therefore CORB should stop blocking requests
-  // marked as ResourceType::kPluginResource.
-  //
-  // TODO(lukasza, laforge): https://crbug.com/702995: Remove the static
-  // ...ForPlugin methods once Flash support is removed from Chromium (probably
-  // around 2020 - see https://www.chromium.org/flash-roadmap).
-  static void AddExceptionForPlugin(int process_id);
-
-  // Returns true if CORB should ignore a request initiated by a universal
-  // access plugin - i.e. if |process_id| has been previously passed to
-  // AddExceptionForPlugin.
-  static bool ShouldAllowForPlugin(int process_id);
-
-  // Reverts AddExceptionForPlugin.
-  static void RemoveExceptionForPlugin(int process_id);
-
  private:
   CrossOriginReadBlocking();  // Not instantiable.
 
@@ -406,4 +389,4 @@
 
 }  // namespace network
 
-#endif  // SERVICES_NETWORK_CROSS_ORIGIN_READ_BLOCKING_H_
+#endif  // SERVICES_NETWORK_PUBLIC_CPP_CROSS_ORIGIN_READ_BLOCKING_H_
diff --git a/services/network/cross_origin_read_blocking_unittest.cc b/services/network/public/cpp/cross_origin_read_blocking_unittest.cc
similarity index 99%
rename from services/network/cross_origin_read_blocking_unittest.cc
rename to services/network/public/cpp/cross_origin_read_blocking_unittest.cc
index 5fd359ae..b4f67a4 100644
--- a/services/network/cross_origin_read_blocking_unittest.cc
+++ b/services/network/public/cpp/cross_origin_read_blocking_unittest.cc
@@ -20,7 +20,7 @@
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_test_util.h"
-#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/services/network/public/cpp/initiator_lock_compatibility.h b/services/network/public/cpp/initiator_lock_compatibility.h
index e521251..42a36ada 100644
--- a/services/network/public/cpp/initiator_lock_compatibility.h
+++ b/services/network/public/cpp/initiator_lock_compatibility.h
@@ -44,7 +44,7 @@
   // - HTML Imports (see https://crbug.com/871827#c9).
   kIncorrectLock = 4,
 
-  // Covered by CrossOriginReadBlocking::ShouldAllowForPlugin.
+  // Covered by CrossOriginReadBlockingExceptionForPlugin::ShouldAllowForPlugin.
   kExcludedCorbForPlugin = 6,
 
   // Covered by AddAllowedRequestInitiatorForPlugin.
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index 628b38e..1614fd8d 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -44,6 +44,7 @@
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "services/network/chunked_data_pipe_upload_data_stream.h"
+#include "services/network/cross_origin_read_blocking_exception_for_plugin.h"
 #include "services/network/data_pipe_element_reader.h"
 #include "services/network/network_usage_accumulator.h"
 #include "services/network/origin_policy/origin_policy_constants.h"
@@ -594,7 +595,7 @@
 
   is_nocors_corb_excluded_request_ =
       request.corb_excluded && request.mode == mojom::RequestMode::kNoCors &&
-      CrossOriginReadBlocking::ShouldAllowForPlugin(
+      CrossOriginReadBlockingExceptionForPlugin::ShouldAllowForPlugin(
           factory_params_->process_id);
   request_mode_ = request.mode;
   if (request.trusted_params) {
diff --git a/services/network/url_loader.h b/services/network/url_loader.h
index 33e6b10..1c8a9ce 100644
--- a/services/network/url_loader.h
+++ b/services/network/url_loader.h
@@ -27,9 +27,9 @@
 #include "net/http/http_raw_request_headers.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_request.h"
-#include "services/network/cross_origin_read_blocking.h"
 #include "services/network/keepalive_statistics_recorder.h"
 #include "services/network/network_service.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
 #include "services/network/public/cpp/initiator_lock_compatibility.h"
 #include "services/network/public/mojom/cookie_access_observer.mojom.h"
 #include "services/network/public/mojom/cross_origin_embedder_policy.mojom-forward.h"
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc
index 981fd26d..62aa246 100644
--- a/services/network/url_loader_unittest.cc
+++ b/services/network/url_loader_unittest.cc
@@ -73,6 +73,7 @@
 #include "net/url_request/url_request_status.h"
 #include "net/url_request/url_request_test_job.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/network/cross_origin_read_blocking_exception_for_plugin.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/mojom/cookie_access_observer.mojom-forward.h"
@@ -3238,7 +3239,7 @@
   std::unique_ptr<URLLoader> url_loader;
   mojom::URLLoaderFactoryParams params;
   params.process_id = 123;
-  CrossOriginReadBlocking::AddExceptionForPlugin(123);
+  CrossOriginReadBlockingExceptionForPlugin::AddExceptionForPlugin(123);
   url_loader = std::make_unique<URLLoader>(
       context(), nullptr /* network_service_client */,
       nullptr /* network_context_client */,
@@ -3262,13 +3263,14 @@
   // The request body is allowed through because CORB isn't applied.
   ASSERT_NE(std::string(), body);
 
-  CrossOriginReadBlocking::RemoveExceptionForPlugin(123);
+  CrossOriginReadBlockingExceptionForPlugin::RemoveExceptionForPlugin(123);
 }
 
 // This simulates a renderer that pretends to be proxying requests for Flash
 // (when browser didn't actually confirm that Flash is hosted by the given
-// process via CrossOriginReadBlocking::AddExceptionForPlugin).  We should still
-// apply CORB in this case.
+// process via
+// CrossOriginReadBlockingExceptionForPlugin::AddExceptionForPlugin).  We should
+// still apply CORB in this case.
 TEST_F(URLLoaderTest, CorbEffectiveWithNoCorsWhenNoActualPlugin) {
   int kResourceType = 1;
   ResourceRequest request =
@@ -3283,8 +3285,9 @@
   std::unique_ptr<URLLoader> url_loader;
   mojom::URLLoaderFactoryParams params;
   params.process_id = 234;
-  // No call to CrossOriginReadBlocking::AddExceptionForPlugin(123) - this is
-  // what we primarily want to cover in this test.
+  // No call to
+  // CrossOriginReadBlockingExceptionForPlugin::AddExceptionForPlugin(123) -
+  // this is what we primarily want to cover in this test.
   url_loader = std::make_unique<URLLoader>(
       context(), nullptr /* network_service_client */,
       nullptr /* network_context_client */,
diff --git a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter
index 0f2e752..bc933196 100644
--- a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter
+++ b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter
@@ -57,6 +57,7 @@
 -KioskUpdateTest.*
 -KioskVirtualKeyboardTest.*
 -LoginCursorTest.*
+-LoginOfflineTest.*
 -LoginPolicyTestBase.*
 -MarketingOptInScreenTest.*
 -MarketingOptInScreenTestDisabled.*
diff --git a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter
index f13b3e9..dd1c1e97 100644
--- a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter
+++ b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter
@@ -57,6 +57,7 @@
 KioskUpdateTest.*
 KioskVirtualKeyboardTest.*
 LoginCursorTest.*
+LoginOfflineTest.*
 LoginPolicyTestBase.*
 MarketingOptInScreenTest.*
 MarketingOptInScreenTestDisabled.*
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 60fbaaa1..324f834 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2828,6 +2828,26 @@
             ]
         }
     ],
+    "FragmentItem": [
+        {
+            "platforms": [
+                "android",
+                "android_webview",
+                "chromeos",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled_20200615",
+                    "enable_features": [
+                        "FragmentItem"
+                    ]
+                }
+            ]
+        }
+    ],
     "FreezeBackgroundTabOnNetworkIdle": [
         {
             "platforms": [
diff --git a/third_party/abseil-cpp/absl/container/BUILD.gn b/third_party/abseil-cpp/absl/container/BUILD.gn
index 87574de..ed30228 100644
--- a/third_party/abseil-cpp/absl/container/BUILD.gn
+++ b/third_party/abseil-cpp/absl/container/BUILD.gn
@@ -351,7 +351,11 @@
 absl_source_set("inlined_vector_test") {
   testonly = true
   sources = [ "inlined_vector_test.cc" ]
-  cflags_cc = [ "-Wno-deprecated-declarations" ]
+  if (is_win && !is_clang) {
+    cflags_cc = [ "/wd4996" ]
+  } else {
+    cflags_cc = [ "-Wno-deprecated-declarations" ]
+  }
   deps = [
     ":counting_allocator",
     ":inlined_vector",
diff --git a/third_party/abseil-cpp/absl/meta/BUILD.gn b/third_party/abseil-cpp/absl/meta/BUILD.gn
index bfeb3f30..0cec53a 100644
--- a/third_party/abseil-cpp/absl/meta/BUILD.gn
+++ b/third_party/abseil-cpp/absl/meta/BUILD.gn
@@ -12,7 +12,9 @@
 absl_source_set("type_traits_test") {
   testonly = true
   sources = [ "type_traits_test.cc" ]
-  cflags_cc = [ "-Wno-unused-private-field" ]
+  if (is_clang) {
+    cflags_cc = [ "-Wno-unused-private-field" ]
+  }
   deps = [
     ":type_traits",
     "//third_party/googletest:gtest",
diff --git a/third_party/abseil-cpp/absl/types/BUILD.gn b/third_party/abseil-cpp/absl/types/BUILD.gn
index 751d8b8..40b9d9e6 100644
--- a/third_party/abseil-cpp/absl/types/BUILD.gn
+++ b/third_party/abseil-cpp/absl/types/BUILD.gn
@@ -117,7 +117,9 @@
 # absl_source_set("variant_test") {
 #   testonly = true
 #   sources = [ "variant_test.cc" ]
-#   cflags_cc = [ "-Wno-unused-function" ]
+#   if (is_clang) {
+#     cflags_cc = [ "-Wno-unused-function" ]
+#   }
 #   deps = [
 #     ":variant",
 #     "//third_party/abseil-cpp/absl/base:config",
diff --git a/third_party/blink/common/mediastream/media_devices.cc b/third_party/blink/common/mediastream/media_devices.cc
index 0a67e459..c6fc821 100644
--- a/third_party/blink/common/mediastream/media_devices.cc
+++ b/third_party/blink/common/mediastream/media_devices.cc
@@ -14,24 +14,23 @@
 
 WebMediaDeviceInfo::WebMediaDeviceInfo(WebMediaDeviceInfo&& other) = default;
 
-WebMediaDeviceInfo::WebMediaDeviceInfo(
-    const std::string& device_id,
-    const std::string& label,
-    const std::string& group_id,
-    media::VideoFacingMode video_facing,
-    const base::Optional<bool>& pan_tilt_zoom_supported)
+WebMediaDeviceInfo::WebMediaDeviceInfo(const std::string& device_id,
+                                       const std::string& label,
+                                       const std::string& group_id,
+                                       bool pan_tilt_zoom_supported,
+                                       media::VideoFacingMode video_facing)
     : device_id(device_id),
       label(label),
       group_id(group_id),
-      video_facing(video_facing),
-      pan_tilt_zoom_supported(pan_tilt_zoom_supported) {}
+      pan_tilt_zoom_supported(pan_tilt_zoom_supported),
+      video_facing(video_facing) {}
 
 WebMediaDeviceInfo::WebMediaDeviceInfo(
     const media::VideoCaptureDeviceDescriptor& descriptor)
     : device_id(descriptor.device_id),
       label(descriptor.GetNameAndModel()),
-      video_facing(descriptor.facing),
-      pan_tilt_zoom_supported(descriptor.pan_tilt_zoom_supported()) {}
+      pan_tilt_zoom_supported(descriptor.pan_tilt_zoom_supported()),
+      video_facing(descriptor.facing) {}
 
 WebMediaDeviceInfo::~WebMediaDeviceInfo() = default;
 
diff --git a/third_party/blink/common/mediastream/media_devices_unittest.cc b/third_party/blink/common/mediastream/media_devices_unittest.cc
index 143ca9d4..17aa9ad 100644
--- a/third_party/blink/common/mediastream/media_devices_unittest.cc
+++ b/third_party/blink/common/mediastream/media_devices_unittest.cc
@@ -11,12 +11,18 @@
 
 TEST(MediaDevicesTest, MediaDeviceInfoFromVideoDescriptor) {
   media::VideoCaptureDeviceDescriptor descriptor(
-      "display_name", "device_id", "model_id", media::VideoCaptureApi::UNKNOWN);
+      "display_name", "device_id", "model_id", media::VideoCaptureApi::UNKNOWN,
+      /*pan_tilt_zoom_supported=*/true,
+      media::VideoCaptureTransportType::OTHER_TRANSPORT,
+      media::VideoFacingMode::MEDIA_VIDEO_FACING_USER);
 
   // TODO(guidou): Add test for group ID when supported. See crbug.com/627793.
   WebMediaDeviceInfo device_info(descriptor);
   EXPECT_EQ(descriptor.device_id, device_info.device_id);
   EXPECT_EQ(descriptor.GetNameAndModel(), device_info.label);
+  EXPECT_EQ(descriptor.pan_tilt_zoom_supported(),
+            device_info.pan_tilt_zoom_supported);
+  EXPECT_EQ(descriptor.facing, device_info.video_facing);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/common/mediastream/media_stream_request.cc b/third_party/blink/common/mediastream/media_stream_request.cc
index a870fc4e..a0d3789 100644
--- a/third_party/blink/common/mediastream/media_stream_request.cc
+++ b/third_party/blink/common/mediastream/media_stream_request.cc
@@ -70,7 +70,7 @@
     const std::string& name,
     media::VideoFacingMode facing,
     const base::Optional<std::string>& group_id,
-    const base::Optional<bool>& pan_tilt_zoom_supported)
+    bool pan_tilt_zoom_supported)
     : type(type),
       id(id),
       video_facing(facing),
diff --git a/third_party/blink/public/common/mediastream/media_devices.h b/third_party/blink/public/common/mediastream/media_devices.h
index c0ba8bd..63324f0 100644
--- a/third_party/blink/public/common/mediastream/media_devices.h
+++ b/third_party/blink/public/common/mediastream/media_devices.h
@@ -33,8 +33,8 @@
       const std::string& device_id,
       const std::string& label,
       const std::string& group_id,
-      media::VideoFacingMode video_facing = media::MEDIA_VIDEO_FACING_NONE,
-      const base::Optional<bool>& pan_tilt_zoom_supported = base::nullopt);
+      bool pan_tilt_zoom_supported = false,
+      media::VideoFacingMode video_facing = media::MEDIA_VIDEO_FACING_NONE);
   explicit WebMediaDeviceInfo(
       const media::VideoCaptureDeviceDescriptor& descriptor);
   ~WebMediaDeviceInfo();
@@ -44,9 +44,9 @@
   std::string device_id;
   std::string label;
   std::string group_id;
+  bool pan_tilt_zoom_supported = false;
   media::VideoFacingMode video_facing =
       media::VideoFacingMode::MEDIA_VIDEO_FACING_NONE;
-  base::Optional<bool> pan_tilt_zoom_supported;
 };
 
 using WebMediaDeviceInfoArray = std::vector<WebMediaDeviceInfo>;
diff --git a/third_party/blink/public/common/mediastream/media_stream_request.h b/third_party/blink/public/common/mediastream/media_stream_request.h
index 6c530625..ab4cb9f2 100644
--- a/third_party/blink/public/common/mediastream/media_stream_request.h
+++ b/third_party/blink/public/common/mediastream/media_stream_request.h
@@ -52,13 +52,12 @@
   MediaStreamDevice(mojom::MediaStreamType type,
                     const std::string& id,
                     const std::string& name);
-  MediaStreamDevice(
-      mojom::MediaStreamType type,
-      const std::string& id,
-      const std::string& name,
-      media::VideoFacingMode facing,
-      const base::Optional<std::string>& group_id = base::nullopt,
-      const base::Optional<bool>& pan_tilt_zoom_supported = base::nullopt);
+  MediaStreamDevice(mojom::MediaStreamType type,
+                    const std::string& id,
+                    const std::string& name,
+                    media::VideoFacingMode facing,
+                    const base::Optional<std::string>& group_id = base::nullopt,
+                    bool pan_tilt_zoom_supported = false);
   MediaStreamDevice(mojom::MediaStreamType type,
                     const std::string& id,
                     const std::string& name,
@@ -99,9 +98,8 @@
   // The device's group ID.
   base::Optional<std::string> group_id;
 
-  // Whether the device supports pan-tilt-zoom.
-  // Only applicable to video devices.
-  base::Optional<bool> pan_tilt_zoom_supported;
+  // Whether the video capture device supports PTZ.
+  bool pan_tilt_zoom_supported;
 
   // The device id of a matched output device if any (otherwise empty).
   // Only applicable to audio devices.
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
index 52c3ee7..6d9e02a 100644
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
@@ -304,13 +304,11 @@
     {% set is_visited = property.style_builder_template == 'visited_color' %}
     {% set main_getter = is_visited and property.unvisited_property.getter or property.getter %}
     {% call(property) apply_initial(property) %}
-  auto color = {{initial_color}}();
-  {{set_value(property)}}(color);
+  {{set_value(property)}}({{initial_color}}());
     {% endcall %}
 
     {% call(property) apply_inherit(property) %}
-  auto color = state.ParentStyle()->{{main_getter}}();
-  {{set_value(property)}}(color);
+  {{set_value(property)}}(state.ParentStyle()->{{main_getter}}());
     {% endcall %}
 
     {% call(property) apply_value(property) %}
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 2f6efa7..a6128ea 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1256,6 +1256,7 @@
     "layout/ng/ng_fieldset_layout_algorithm_test.cc",
     "layout/ng/ng_fragment_child_iterator_test.cc",
     "layout/ng/ng_fragmentation_test.cc",
+    "layout/ng/ng_ink_overflow_test.cc",
     "layout/ng/ng_inline_layout_test.cc",
     "layout/ng/ng_layout_result_caching_test.cc",
     "layout/ng/ng_layout_test.h",
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index 91eaff51..7574288 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -710,7 +710,7 @@
       include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
       default_value: "StyleColor(Color::kBlack)",
       type_name: "StyleColor",
-      computed_style_custom_functions: ["getter", "setter"],
+      computed_style_custom_functions: ["getter"],
       style_builder_custom_functions: ["initial", "inherit", "value"],
       priority: "High",
       keywords: ["currentcolor"],
@@ -1300,7 +1300,7 @@
       include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
       default_value: "StyleColor::CurrentColor()",
       type_name: "StyleColor",
-      computed_style_custom_functions: ["getter", "setter"],
+      computed_style_custom_functions: ["getter"],
       keywords: ["currentcolor"],
       typedom_types: ["Keyword"],
       converter: "ConvertStyleColor",
@@ -1451,7 +1451,7 @@
       include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
       default_value: "StyleColor::CurrentColor()",
       type_name: "StyleColor",
-      computed_style_custom_functions: ["getter", "setter"],
+      computed_style_custom_functions: ["getter"],
       keywords: ["currentcolor"],
       typedom_types: ["Keyword"],
       converter: "ConvertStyleColor",
@@ -1503,7 +1503,7 @@
       include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
       default_value: "StyleColor::CurrentColor()",
       type_name: "StyleColor",
-      computed_style_custom_functions: ["getter", "setter"],
+      computed_style_custom_functions: ["getter"],
       keywords: ["currentcolor"],
       typedom_types: ["Keyword"],
       converter: "ConvertStyleColor",
@@ -1555,7 +1555,7 @@
       include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
       default_value: "StyleColor::CurrentColor()",
       type_name: "StyleColor",
-      computed_style_custom_functions: ["getter", "setter"],
+      computed_style_custom_functions: ["getter"],
       keywords: ["currentcolor"],
       typedom_types: ["Keyword"],
       converter: "ConvertStyleColor",
@@ -2763,7 +2763,7 @@
       include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
       default_value: "StyleColor::CurrentColor()",
       type_name: "StyleColor",
-      computed_style_custom_functions: ["getter", "setter"],
+      computed_style_custom_functions: ["getter"],
       keywords: ["currentcolor"],
       typedom_types: ["Keyword"],
       converter: "ConvertStyleColor",
@@ -3595,6 +3595,7 @@
       include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
       default_value: "StyleColor::CurrentColor()",
       type_name: "StyleColor",
+      computed_style_custom_functions: ["getter"],
       keywords: ["currentcolor"],
       typedom_types: ["Keyword"],
       converter: "ConvertStyleColor",
@@ -4121,7 +4122,7 @@
       include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
       default_value: "StyleColor::CurrentColor()",
       type_name: "StyleColor",
-      computed_style_custom_functions: ["getter","setter"],
+      computed_style_custom_functions: ["getter"],
       keywords: ["currentcolor"],
       typedom_types: ["Keyword"],
       converter: "ConvertStyleColor",
@@ -4422,7 +4423,7 @@
       include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
       default_value: "StyleColor::CurrentColor()",
       type_name: "StyleColor",
-      computed_style_custom_functions: ["getter", "setter"],
+      computed_style_custom_functions: ["getter"],
       converter: "ConvertStyleColor",
       style_builder_template: "color",
       affected_by_forced_colors: true,
@@ -4453,7 +4454,7 @@
       include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
       default_value: "StyleColor::CurrentColor()",
       type_name: "StyleColor",
-      computed_style_custom_functions: ["getter", "setter"],
+      computed_style_custom_functions: ["getter"],
       converter: "ConvertStyleColor",
       style_builder_template: "color",
     },
@@ -4476,7 +4477,7 @@
       include_paths: ["third_party/blink/renderer/core/css/style_color.h"],
       default_value: "StyleColor::CurrentColor()",
       type_name: "StyleColor",
-      computed_style_custom_functions: ["getter", "setter"],
+      computed_style_custom_functions: ["getter"],
       converter: "ConvertStyleColor",
       style_builder_template: "color",
     },
@@ -5910,9 +5911,6 @@
       computed_style_custom_functions: ["getter", "setter"],
       converter: "ConvertStyleColor",
       style_builder_template: "visited_color",
-      style_builder_template_args: {
-        initial_color: "StyleColor::CurrentColor",
-      },
       affected_by_forced_colors: true,
     },
     {
@@ -5928,9 +5926,6 @@
       computed_style_custom_functions: ["getter", "setter"],
       converter: "ConvertStyleColor",
       style_builder_template: "visited_color",
-      style_builder_template_args: {
-        initial_color: "StyleColor::CurrentColor",
-      },
     },
     {
       name: "-internal-visited-text-stroke-color",
@@ -5945,9 +5940,6 @@
       computed_style_custom_functions: ["getter", "setter"],
       converter: "ConvertStyleColor",
       style_builder_template: "visited_color",
-      style_builder_template_args: {
-        initial_color: "StyleColor::CurrentColor",
-      },
     },
 
     // Name: -internal-empty-line-height:
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 71dbd05..066db63 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -2538,7 +2538,7 @@
 const blink::Color FloodColor::ColorIncludingFallback(
     bool visited_link,
     const ComputedStyle& style) const {
-  StyleColor result = style.FloodColor();
+  const StyleColor& result = style.FloodColor();
   if (!result.IsCurrentColor())
     return result.GetColor();
   return visited_link ? style.GetInternalVisitedCurrentColor()
@@ -3745,7 +3745,7 @@
 const blink::Color LightingColor::ColorIncludingFallback(
     bool visited_link,
     const ComputedStyle& style) const {
-  StyleColor result = style.LightingColor();
+  const StyleColor& result = style.LightingColor();
   if (!result.IsCurrentColor())
     return result.GetColor();
   return visited_link ? style.GetInternalVisitedCurrentColor()
@@ -5846,7 +5846,7 @@
 const blink::Color StopColor::ColorIncludingFallback(
     bool visited_link,
     const ComputedStyle& style) const {
-  StyleColor result = style.StopColor();
+  const StyleColor& result = style.StopColor();
   if (!result.IsCurrentColor())
     return result.GetColor();
   return visited_link ? style.GetInternalVisitedCurrentColor()
@@ -7578,7 +7578,7 @@
 const blink::Color WebkitTapHighlightColor::ColorIncludingFallback(
     bool visited_link,
     const ComputedStyle& style) const {
-  StyleColor result = style.TapHighlightColor();
+  const StyleColor& result = style.TapHighlightColor();
   if (!result.IsCurrentColor())
     return result.GetColor();
   return visited_link ? style.GetInternalVisitedCurrentColor()
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.h b/third_party/blink/renderer/core/css/resolver/style_resolver.h
index 0d96981..174a2513 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.h
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.h
@@ -180,7 +180,6 @@
                                     unsigned rules_to_include);
   void MatchRuleSet(ElementRuleCollector&, RuleSet*);
   void MatchUARules(const Element&, ElementRuleCollector&);
-  void MatchUAPseudoElementRules(ElementRuleCollector&);
   void MatchUserRules(ElementRuleCollector&);
   // This matches `::part` selectors. It looks in ancestor scopes as far as
   // part mapping requires.
diff --git a/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc b/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc
index 371d926..0a089a7 100644
--- a/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc
+++ b/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc
@@ -32,10 +32,10 @@
 
 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
-#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h"
 #include "third_party/blink/renderer/platform/text/text_break_iterator.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
 
 namespace blink {
 
@@ -202,23 +202,71 @@
 
 void AbstractInlineTextBox::GetWordBoundaries(
     Vector<WordBoundaries>& words) const {
-  if (Len() == 0)
-    return;
-
   String text = GetText();
-  int len = text.length();
-  TextBreakIterator* iterator = WordBreakIterator(text, 0, len);
-
-  // FIXME: When http://crbug.com/411764 is fixed, replace this with an ASSERT.
-  if (!iterator)
+  if (!text.length())
     return;
 
-  int pos = iterator->first();
-  while (pos >= 0 && pos < len) {
-    int next = iterator->next();
-    if (IsWordTextBreak(iterator))
-      words.push_back(WordBoundaries(pos, next));
-    pos = next;
+  TextBreakIterator* it = WordBreakIterator(text, 0, text.length());
+  base::Optional<int> word_start;
+  for (int offset = 0; offset != kTextBreakDone && offset < int{text.length()};
+       offset = it->following(offset)) {
+    // Unlike in ICU's WordBreakIterator, a word boundary is valid only if it is
+    // before, or immediately preceded by, an alphanumeric character, a series
+    // of punctuation marks, an underscore or a line break. We therefore need to
+    // filter the boundaries returned by ICU's WordBreakIterator and return a
+    // subset of them. For example we should exclude a word boundary that is
+    // between two space characters, "Hello | there".
+
+    // Case 1: A new word should start if |offset| is before an alphanumeric
+    // character, an underscore or a hard line break
+    if (WTF::unicode::IsAlphanumeric(text[offset]) ||
+        text[offset] == kLowLineCharacter ||
+        text[offset] == kNewlineCharacter ||
+        text[offset] == kCarriageReturnCharacter) {
+      // We found a new word start or end. Append the previous word (if it
+      // exists) to the results, otherwise save this offset as a word start.
+      if (word_start)
+        words.emplace_back(*word_start, offset);
+      word_start = offset;
+
+      // Case 2: A new word should start before and end after a series of
+      // punctuation marks, i.e., Consecutive punctuation marks should be
+      // accumulated into a single word. For example, "|Hello|+++---|there|".
+    } else if (WTF::unicode::IsPunct(text[offset])) {
+      // At beginning of text, or the previous character was a punctuation
+      // symbol.
+      if (offset == 0 || !WTF::unicode::IsPunct(text[offset - 1])) {
+        if (word_start)
+          words.emplace_back(*word_start, offset);
+        word_start = offset;
+      }
+      continue;  // Skip to the end of the punctuation run.
+
+      // Case 3: A word should end if |offset| is proceeded by an alphanumeric
+      // character, a series of punctuation marks, an underscore or a hard line
+      // break.
+    } else if (offset > 0) {
+      UChar prev_character = text[offset - 1];
+      if (WTF::unicode::IsAlphanumeric(prev_character) ||
+          WTF::unicode::IsPunct(prev_character) ||
+          prev_character == kLowLineCharacter ||
+          prev_character == kNewlineCharacter ||
+          prev_character == kCarriageReturnCharacter) {
+        if (word_start) {
+          words.emplace_back(*word_start, offset);
+          word_start = base::nullopt;
+        }
+      }
+    }
+  }
+
+  // Case 4: If the character at last |offset| in |text| was an alphanumeric
+  // character, a punctuation mark, an underscore, or a line break, then it
+  // would have started a new word. We need to add its corresponding word end
+  // boundary which should be at |text|'s length.
+  if (word_start) {
+    words.emplace_back(*word_start, text.length());
+    word_start = base::nullopt;
   }
 }
 
@@ -228,7 +276,7 @@
 
   String result = inline_text_box_->GetText();
 
-  // Simplify all whitespace to just a space character, except for
+  // Change all whitespace to just a space character, except for
   // actual line breaks.
   if (!inline_text_box_->IsLineBreak())
     result = result.SimplifyWhiteSpace(WTF::kDoNotStripWhiteSpace);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
index 56af2e5c..57dcd3a 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
@@ -23,7 +23,8 @@
     NGTextOffset text_offset;
   } type_data;
   PhysicalRect rect;
-  void* pointers[2];
+  NGInkOverflow ink_overflow;
+  void* pointer;
   wtf_size_t sizes[2];
   unsigned flags;
 };
@@ -41,7 +42,7 @@
       style_variant_(static_cast<unsigned>(text.StyleVariant())),
       is_hidden_for_paint_(text.IsHiddenForPaint()),
       text_direction_(static_cast<unsigned>(text.ResolvedDirection())),
-      ink_overflow_computed_(false),
+      ink_overflow_type_(NGInkOverflow::kNotSet),
       is_dirty_(false),
       is_last_for_node_(true) {
 #if DCHECK_IS_ON()
@@ -74,7 +75,7 @@
       style_variant_(static_cast<unsigned>(inline_item.StyleVariant())),
       is_hidden_for_paint_(is_hidden_for_paint),
       text_direction_(static_cast<unsigned>(inline_item.Direction())),
-      ink_overflow_computed_(false),
+      ink_overflow_type_(NGInkOverflow::kNotSet),
       is_dirty_(false),
       is_last_for_node_(true) {
 #if DCHECK_IS_ON()
@@ -101,7 +102,7 @@
       style_variant_(static_cast<unsigned>(inline_item.StyleVariant())),
       is_hidden_for_paint_(is_hidden_for_paint),
       text_direction_(static_cast<unsigned>(inline_item.Direction())),
-      ink_overflow_computed_(false),
+      ink_overflow_type_(NGInkOverflow::kNotSet),
       is_dirty_(false),
       is_last_for_node_(true) {
 #if DCHECK_IS_ON()
@@ -123,7 +124,7 @@
       style_variant_(static_cast<unsigned>(line.StyleVariant())),
       is_hidden_for_paint_(false),
       text_direction_(static_cast<unsigned>(line.BaseDirection())),
-      ink_overflow_computed_(false),
+      ink_overflow_type_(NGInkOverflow::kNotSet),
       is_dirty_(false),
       is_last_for_node_(true) {
   DCHECK(!IsFormattingContextRoot());
@@ -138,7 +139,7 @@
       style_variant_(static_cast<unsigned>(box.StyleVariant())),
       is_hidden_for_paint_(box.IsHiddenForPaint()),
       text_direction_(static_cast<unsigned>(resolved_direction)),
-      ink_overflow_computed_(false),
+      ink_overflow_type_(NGInkOverflow::kNotSet),
       is_dirty_(false),
       is_last_for_node_(true) {
   DCHECK_EQ(IsFormattingContextRoot(), box.IsFormattingContextRoot());
@@ -194,7 +195,7 @@
       style_variant_(source.style_variant_),
       is_hidden_for_paint_(source.is_hidden_for_paint_),
       text_direction_(source.text_direction_),
-      ink_overflow_computed_(source.ink_overflow_computed_),
+      ink_overflow_type_(NGInkOverflow::kNotSet),
       is_dirty_(source.is_dirty_),
       is_last_for_node_(source.is_last_for_node_) {
   switch (Type()) {
@@ -215,8 +216,11 @@
   // Copy |ink_overflow_| only for text items, because ink overflow for other
   // items may be chnaged even in simplified layout or when reusing lines, and
   // that they need to be re-computed anyway.
-  if (source.ink_overflow_ && ink_overflow_computed_ && IsText())
-    ink_overflow_ = std::make_unique<NGInkOverflow>(*source.ink_overflow_);
+  if (IsText() && source.IsInkOverflowComputed()) {
+    ink_overflow_type_ = source.InkOverflowType();
+    new (&ink_overflow_)
+        NGInkOverflow(source.InkOverflowType(), source.ink_overflow_);
+  }
 }
 
 NGFragmentItem::~NGFragmentItem() {
@@ -234,6 +238,7 @@
       box_.~BoxItem();
       break;
   }
+  ink_overflow_.Reset(InkOverflowType());
 }
 
 bool NGFragmentItem::IsInlineBox() const {
@@ -321,26 +326,19 @@
 PhysicalRect NGFragmentItem::SelfInkOverflow() const {
   if (const LayoutBox* box = InkOverflowOwnerBox())
     return box->PhysicalSelfVisualOverflowRect();
-
-  if (!ink_overflow_)
+  if (!HasInkOverflow())
     return LocalRect();
-
-  return ink_overflow_->self_ink_overflow;
+  return ink_overflow_.Self(InkOverflowType(), Size());
 }
 
 PhysicalRect NGFragmentItem::InkOverflow() const {
   if (const LayoutBox* box = InkOverflowOwnerBox())
     return box->PhysicalVisualOverflowRect();
-
-  if (!ink_overflow_)
+  if (!HasInkOverflow())
     return LocalRect();
-
   if (!IsContainer() || HasOverflowClip())
-    return ink_overflow_->self_ink_overflow;
-
-  const NGContainerInkOverflow& container_ink_overflow =
-      static_cast<NGContainerInkOverflow&>(*ink_overflow_);
-  return container_ink_overflow.SelfAndContentsInkOverflow();
+    return ink_overflow_.Self(InkOverflowType(), Size());
+  return ink_overflow_.SelfAndContents(InkOverflowType(), Size());
 }
 
 const ShapeResultView* NGFragmentItem::TextShapeResult() const {
@@ -486,22 +484,20 @@
 
     // Re-computing text item is not necessary, because all changes that needs
     // to re-compute ink overflow invalidate layout.
-    if (ink_overflow_computed_) {
+    if (IsInkOverflowComputed()) {
       *self_and_contents_rect_out = SelfInkOverflow();
       return;
     }
-    ink_overflow_computed_ = true;
 
     NGTextFragmentPaintInfo paint_info = TextPaintInfo(cursor->Items());
     if (paint_info.shape_result) {
-      NGInkOverflow::ComputeTextInkOverflow(paint_info, Style(), Size(),
-                                            &ink_overflow_);
-      *self_and_contents_rect_out =
-          ink_overflow_ ? ink_overflow_->self_ink_overflow : LocalRect();
+      ink_overflow_type_ = ink_overflow_.SetTextInkOverflow(
+          InkOverflowType(), paint_info, Style(), Size(),
+          self_and_contents_rect_out);
       return;
     }
 
-    DCHECK(!ink_overflow_);
+    ink_overflow_type_ = ink_overflow_.Reset(InkOverflowType());
     *self_and_contents_rect_out = LocalRect();
     return;
   }
@@ -543,18 +539,13 @@
     NOTREACHED();
   }
 
-  SECURITY_CHECK(IsContainer());
+  DCHECK(IsContainer());
   if (LocalRect().Contains(*self_and_contents_rect_out)) {
-    ink_overflow_ = nullptr;
-  } else if (!ink_overflow_) {
-    ink_overflow_ =
-        std::make_unique<NGContainerInkOverflow>(self_rect, contents_rect);
-  } else {
-    NGContainerInkOverflow* ink_overflow =
-        static_cast<NGContainerInkOverflow*>(ink_overflow_.get());
-    ink_overflow->self_ink_overflow = self_rect;
-    ink_overflow->contents_ink_overflow = contents_rect;
+    ink_overflow_type_ = ink_overflow_.Reset(InkOverflowType());
+    return;
   }
+  ink_overflow_type_ =
+      ink_overflow_.Set(InkOverflowType(), self_rect, contents_rect, Size());
 }
 
 void NGFragmentItem::SetDeltaToNextForSameLayoutObject(wtf_size_t delta) const {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
index 7823ff0..38eb1d9 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
@@ -385,6 +385,15 @@
                  const PhysicalSize& size,
                  bool is_hidden_for_paint);
 
+  NGInkOverflow::Type InkOverflowType() const {
+    return static_cast<NGInkOverflow::Type>(ink_overflow_type_);
+  }
+  bool IsInkOverflowComputed() const {
+    return InkOverflowType() != NGInkOverflow::kNotSet;
+  }
+  bool HasInkOverflow() const {
+    return InkOverflowType() != NGInkOverflow::kNone;
+  }
   const LayoutBox* InkOverflowOwnerBox() const;
   LayoutBox* MutableInkOverflowOwnerBox();
 
@@ -407,7 +416,7 @@
 
   PhysicalRect rect_;
 
-  std::unique_ptr<NGInkOverflow> ink_overflow_;
+  NGInkOverflow ink_overflow_;
 
   mutable wtf_size_t fragment_id_ = 0;
 
@@ -423,8 +432,7 @@
   // |ShapeResult::Direction()|.
   unsigned text_direction_ : 1;  // TextDirection.
 
-  // Used only when |IsText()| to avoid re-computing ink overflow.
-  unsigned ink_overflow_computed_ : 1;
+  unsigned ink_overflow_type_ : 3;  // NGInkOverflow::Type
 
   mutable unsigned is_dirty_ : 1;
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc
index 592f46b652..7e73c11 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc
@@ -246,4 +246,14 @@
   return inline_size;
 }
 
+#if DCHECK_IS_ON()
+float NGLineInfo::ComputeWidthInFloat() const {
+  float inline_size = TextIndent();
+  for (const NGInlineItemResult& item_result : Results())
+    inline_size += item_result.inline_size.ToFloat();
+
+  return inline_size;
+}
+#endif
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
index eb31318..a1a7872 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
@@ -213,6 +213,12 @@
   // without clamping.
   LayoutUnit ComputeWidth() const;
 
+#if DCHECK_IS_ON()
+  // Returns width in float. This function is used for avoiding |LayoutUnit|
+  // saturated addition of items in line.
+  float ComputeWidthInFloat() const;
+#endif
+
   bool HasTrailingSpaces() const { return has_trailing_spaces_; }
   void SetHasTrailingSpaces() { has_trailing_spaces_ = true; }
   bool ShouldHangTrailingSpaces() const;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
index 45a4869..62f613d 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -465,9 +465,13 @@
   // always positive or 0.
   LayoutUnit available_width = AvailableWidth();
 
+#if DCHECK_IS_ON()
   // Text measurement is done using floats which may introduce small rounding
   // errors for near-saturated values.
-  DCHECK_EQ(position_.Round(), line_info->ComputeWidth().Round());
+  // See http://crbug.com/1098795
+  if (!LayoutUnit(line_info->ComputeWidthInFloat()).MightBeSaturated())
+    DCHECK_EQ(position_.Round(), line_info->ComputeWidth().Round());
+#endif
 
   line_info->SetWidth(available_width, position_);
   line_info->SetBfcOffset(
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
index 4d25662..08b8f0b0 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
@@ -202,8 +202,16 @@
     return;
   }
 
-  NGInkOverflow::ComputeTextInkOverflow(PaintInfo(), Style(), Size(),
-                                        &ink_overflow_);
+  base::Optional<PhysicalRect> ink_overflow =
+      NGInkOverflow::ComputeTextInkOverflow(PaintInfo(), Style(), Size());
+  if (!ink_overflow) {
+    ink_overflow_.reset();
+    return;
+  }
+  if (ink_overflow_)
+    ink_overflow_->self_ink_overflow = *ink_overflow;
+  else
+    ink_overflow_ = std::make_unique<NGSelfInkOverflow>(*ink_overflow);
 }
 
 scoped_refptr<const NGPhysicalTextFragment>
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h
index dee9056..442f8bf 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h
@@ -139,7 +139,7 @@
   // Fragments are immutable but allow certain expensive data, specifically ink
   // overflow, to be cached as long as it is guaranteed to always recompute to
   // the same value.
-  mutable std::unique_ptr<NGInkOverflow> ink_overflow_;
+  mutable std::unique_ptr<NGSelfInkOverflow> ink_overflow_;
 
   friend class NGTextFragmentBuilder;
 };
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc
index 22093be..c4a6d74 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_ruby_utils.cc
@@ -53,10 +53,6 @@
 // TODO(tkent): Rename this function. 'LogicalBottom' should not be used in NG.
 LayoutUnit LastLineTextLogicalBottom(const NGPhysicalBoxFragment& container,
                                      LayoutUnit default_value) {
-  const NGPhysicalFragment::TextHeightType height_type =
-      RuntimeEnabledFeatures::LayoutNGRubyEmHeightEnabled()
-          ? NGPhysicalFragment::kEmHeight
-          : NGPhysicalFragment::kNormalHeight;
   const ComputedStyle& container_style = container.Style();
   if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
     if (!container.Items())
@@ -70,7 +66,8 @@
     DCHECK(line_item->LineBoxFragment());
     PhysicalRect line_rect =
         line_item->LineBoxFragment()->ScrollableOverflowForLine(
-            container, container_style, *line_item, cursor, height_type);
+            container, container_style, *line_item, cursor,
+            NGPhysicalFragment::kEmHeight);
     return container.ConvertChildToLogical(line_rect).BlockEndOffset();
   }
 
@@ -85,8 +82,8 @@
   }
   if (!last_line)
     return default_value;
-  PhysicalRect line_rect =
-      last_line->ScrollableOverflow(container, container_style, height_type);
+  PhysicalRect line_rect = last_line->ScrollableOverflow(
+      container, container_style, NGPhysicalFragment::kEmHeight);
 
   line_rect.Move(last_line_offset);
   return container.ConvertChildToLogical(line_rect).BlockEndOffset();
@@ -95,10 +92,6 @@
 // TODO(tkent): Rename this function. 'LogicalTop' should not be used in NG.
 LayoutUnit FirstLineTextLogicalTop(const NGPhysicalBoxFragment& container,
                                    LayoutUnit default_value) {
-  const NGPhysicalFragment::TextHeightType height_type =
-      RuntimeEnabledFeatures::LayoutNGRubyEmHeightEnabled()
-          ? NGPhysicalFragment::kEmHeight
-          : NGPhysicalFragment::kNormalHeight;
   const ComputedStyle& container_style = container.Style();
   if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
     if (!container.Items())
@@ -112,14 +105,15 @@
     DCHECK(line_item->LineBoxFragment());
     PhysicalRect line_rect =
         line_item->LineBoxFragment()->ScrollableOverflowForLine(
-            container, container_style, *line_item, cursor, height_type);
+            container, container_style, *line_item, cursor,
+            NGPhysicalFragment::kEmHeight);
     return container.ConvertChildToLogical(line_rect).offset.block_offset;
   }
 
   for (const auto& child_link : container.PostLayoutChildren()) {
     if (const auto* line = DynamicTo<NGPhysicalLineBoxFragment>(*child_link)) {
-      PhysicalRect line_rect =
-          line->ScrollableOverflow(container, container_style, height_type);
+      PhysicalRect line_rect = line->ScrollableOverflow(
+          container, container_style, NGPhysicalFragment::kEmHeight);
       line_rect.Move(child_link.offset);
       return container.ConvertChildToLogical(line_rect).offset.block_offset;
     }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
index a3b4b61..211a20f 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
@@ -11,12 +11,243 @@
 
 namespace blink {
 
-// static
-void NGInkOverflow::ComputeTextInkOverflow(
+namespace {
+
+struct SameSizeAsNGInkOverflow {
+  void* pointer;
+#if DCHECK_IS_ON()
+  NGInkOverflow::Type type;
+#endif
+};
+
+static_assert(sizeof(NGInkOverflow) == sizeof(SameSizeAsNGInkOverflow),
+              "NGInkOverflow should stay small");
+
+inline bool HasOverflow(const PhysicalRect& rect, const PhysicalSize& size) {
+  return rect.X() < 0 || rect.Y() < 0 || rect.Right() > size.width ||
+         rect.Bottom() > size.height;
+}
+
+}  // namespace
+
+#if DCHECK_IS_ON()
+NGInkOverflow::~NGInkOverflow() {
+  // Because |Type| is kept outside of the instance, callers must call |Reset|
+  // before destructing.
+  DCHECK(type_ == kNotSet || type_ == kNone) << type_;
+}
+#endif
+
+NGInkOverflow::NGInkOverflow(Type source_type, const NGInkOverflow& source) {
+  source.CheckType(source_type);
+  new (this) NGInkOverflow();
+  switch (source_type) {
+    case kNotSet:
+    case kNone:
+      break;
+    case kSmallSelf:
+      static_assert(sizeof(outsets_) == sizeof(self_),
+                    "outsets should be the size of a pointer");
+      self_ = source.self_;
+#if DCHECK_IS_ON()
+      for (wtf_size_t i = 0; i < base::size(outsets_); ++i)
+        DCHECK_EQ(outsets_[i], source.outsets_[i]);
+#endif
+      break;
+    case kSelf:
+      self_ = new NGSelfInkOverflow(*source.self_);
+      break;
+    case kSelfAndContents:
+      container_ = new NGContainerInkOverflow(*source.container_);
+      break;
+  }
+  SetType(source_type);
+}
+
+NGInkOverflow::Type NGInkOverflow::Reset(Type type) {
+  CheckType(type);
+  switch (type) {
+    case kNotSet:
+    case kSmallSelf:
+      break;
+    case kNone:
+      return kNone;
+    case kSelf:
+      delete self_;
+      break;
+    case kSelfAndContents:
+      delete container_;
+      break;
+  }
+  return SetType(kNone);
+}
+
+PhysicalRect NGInkOverflow::FromOutsets(const PhysicalSize& size) const {
+  const LayoutUnit left_outset(LayoutUnit::FromRawValue(outsets_[0]));
+  const LayoutUnit top_outset(LayoutUnit::FromRawValue(outsets_[1]));
+  return {-left_outset, -top_outset,
+          left_outset + size.width + LayoutUnit::FromRawValue(outsets_[2]),
+          top_outset + size.height + LayoutUnit::FromRawValue(outsets_[3])};
+}
+
+PhysicalRect NGInkOverflow::Self(Type type, const PhysicalSize& size) const {
+  CheckType(type);
+#if DCHECK_IS_ON()
+  // TODO(crbug.com/829028): Should compute all ink overflow when
+  // NGBlockFragmentation is enabled.
+  if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled())
+    DCHECK_NE(type, kNotSet);
+#endif
+  switch (type) {
+    case kNotSet:
+    case kNone:
+      return {PhysicalOffset(), size};
+    case kSmallSelf:
+      return FromOutsets(size);
+    case kSelf:
+    case kSelfAndContents:
+      DCHECK(self_);
+      return self_->self_ink_overflow;
+  }
+  NOTREACHED();
+  return {PhysicalOffset(), size};
+}
+
+PhysicalRect NGInkOverflow::SelfAndContents(Type type,
+                                            const PhysicalSize& size) const {
+  CheckType(type);
+  switch (type) {
+    case kNotSet:
+      // It is fine to read |kNotSet|, because
+      // |PaintLayer::UpdateDescendantDependentFlags| needs to know the old
+      // value before it computes ink overflow.
+    case kNone:
+      return {PhysicalOffset(), size};
+    case kSmallSelf:
+      return FromOutsets(size);
+    case kSelf:
+      DCHECK(self_);
+      return self_->self_ink_overflow;
+    case kSelfAndContents:
+      DCHECK(container_);
+      return container_->SelfAndContentsInkOverflow();
+  }
+  NOTREACHED();
+  return {PhysicalOffset(), size};
+}
+
+// Store |ink_overflow| as |SmallRawValue| if possible and returns |true|.
+// Returns |false| if |ink_overflow| is too large for |SmallRawValue|.
+bool NGInkOverflow::TrySetOutsets(Type type,
+                                  const PhysicalRect& ink_overflow,
+                                  const PhysicalSize& size) {
+  CheckType(type);
+  const LayoutUnit max_small_value(
+      LayoutUnit::FromRawValue(std::numeric_limits<SmallRawValue>::max()));
+  const LayoutUnit left_outset = -ink_overflow.X();
+  if (left_outset > max_small_value)
+    return false;
+  const LayoutUnit top_outset = -ink_overflow.Y();
+  if (top_outset > max_small_value)
+    return false;
+  const LayoutUnit right_outset = ink_overflow.Right() - size.width;
+  if (right_outset > max_small_value)
+    return false;
+  const LayoutUnit bottom_outset = ink_overflow.Bottom() - size.height;
+  if (bottom_outset > max_small_value)
+    return false;
+  Reset(type);
+  outsets_[0] = left_outset.ClampNegativeToZero().RawValue();
+  outsets_[1] = top_outset.ClampNegativeToZero().RawValue();
+  outsets_[2] = right_outset.ClampNegativeToZero().RawValue();
+  outsets_[3] = bottom_outset.ClampNegativeToZero().RawValue();
+  return true;
+}
+
+NGInkOverflow::Type NGInkOverflow::SetSingle(Type type,
+                                             const PhysicalRect& ink_overflow,
+                                             const PhysicalSize& size,
+                                             Type new_type,
+                                             Type new_small_type) {
+  CheckType(type);
+  DCHECK(HasOverflow(ink_overflow, size));
+
+  if (TrySetOutsets(type, ink_overflow, size))
+    return SetType(new_small_type);
+
+  switch (type) {
+    case kSelfAndContents:
+      Reset(type);
+      FALLTHROUGH;
+    case kNotSet:
+    case kNone:
+    case kSmallSelf:
+      self_ = new NGSelfInkOverflow(ink_overflow);
+      return SetType(new_type);
+    case kSelf:
+      DCHECK(self_);
+      self_->self_ink_overflow = ink_overflow;
+      return SetType(new_type);
+  }
+  NOTREACHED();
+}
+
+NGInkOverflow::Type NGInkOverflow::SetSelf(Type type,
+                                           const PhysicalRect& ink_overflow,
+                                           const PhysicalSize& size) {
+  CheckType(type);
+  if (!HasOverflow(ink_overflow, size))
+    return Reset(type);
+  return SetSingle(type, ink_overflow, size, kSelf, kSmallSelf);
+}
+
+NGInkOverflow::Type NGInkOverflow::Set(Type type,
+                                       const PhysicalRect& self,
+                                       const PhysicalRect& contents,
+                                       const PhysicalSize& size) {
+  CheckType(type);
+
+  switch (type) {
+    case kSelf:
+      Reset(type);
+      FALLTHROUGH;
+    case kNotSet:
+    case kNone:
+    case kSmallSelf:
+      container_ = new NGContainerInkOverflow(self, contents);
+      return SetType(kSelfAndContents);
+    case kSelfAndContents:
+      DCHECK(container_);
+      container_->self_ink_overflow = self;
+      container_->contents_ink_overflow = contents;
+      return kSelfAndContents;
+  }
+  NOTREACHED();
+}
+
+NGInkOverflow::Type NGInkOverflow::SetTextInkOverflow(
+    Type type,
     const NGTextFragmentPaintInfo& text_info,
     const ComputedStyle& style,
     const PhysicalSize& size,
-    std::unique_ptr<NGInkOverflow>* ink_overflow_out) {
+    PhysicalRect* ink_overflow_out) {
+  CheckType(type);
+  DCHECK_EQ(type, kNotSet);
+  base::Optional<PhysicalRect> ink_overflow =
+      ComputeTextInkOverflow(text_info, style, size);
+  if (!ink_overflow) {
+    *ink_overflow_out = {PhysicalOffset(), size};
+    return Reset(type);
+  }
+  *ink_overflow_out = *ink_overflow;
+  return SetSelf(type, *ink_overflow, size);
+}
+
+// static
+base::Optional<PhysicalRect> NGInkOverflow::ComputeTextInkOverflow(
+    const NGTextFragmentPaintInfo& text_info,
+    const ComputedStyle& style,
+    const PhysicalSize& size) {
   // Glyph bounds is in logical coordinate, origin at the alphabetic baseline.
   const Font& font = style.GetFont();
   const FloatRect text_ink_bounds = font.TextInkBounds(text_info);
@@ -64,18 +295,12 @@
 
   // Uniting the frame rect ensures that non-ink spaces such side bearings, or
   // even space characters, are included in the visual rect for decorations.
-  PhysicalRect local_rect(PhysicalOffset(), size);
-  if (local_rect.Contains(local_ink_overflow)) {
-    *ink_overflow_out = nullptr;
-    return;
-  }
-  local_ink_overflow.Unite(local_rect);
+  if (!HasOverflow(local_ink_overflow, size))
+    return base::nullopt;
+
+  local_ink_overflow.Unite({{}, size});
   local_ink_overflow.ExpandEdgesToPixelBoundaries();
-  if (!*ink_overflow_out) {
-    *ink_overflow_out = std::make_unique<NGInkOverflow>(local_ink_overflow);
-    return;
-  }
-  (*ink_overflow_out)->self_ink_overflow = local_ink_overflow;
+  return local_ink_overflow;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
index f13cc87..753a2e57 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_INK_OVERFLOW_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_INK_OVERFLOW_H_
 
+#include "build/build_config.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
 
@@ -13,33 +14,26 @@
 class ComputedStyle;
 struct NGTextFragmentPaintInfo;
 
-// Represents an ink-overflow for objects without children, such as text runs.
-struct CORE_EXPORT NGInkOverflow {
-  USING_FAST_MALLOC(NGInkOverflow);
+// Represents an ink-overflow rectangle. Used for objects without children, such
+// as text runs.
+struct NGSelfInkOverflow {
+  USING_FAST_MALLOC(NGSelfInkOverflow);
 
  public:
-  NGInkOverflow(const PhysicalRect& self_ink_overflow)
-      : self_ink_overflow(self_ink_overflow) {}
-
-  static void ComputeTextInkOverflow(
-      const NGTextFragmentPaintInfo& text_info,
-      const ComputedStyle& style,
-      const PhysicalSize& size,
-      std::unique_ptr<NGInkOverflow>* ink_overflow_out);
+  explicit NGSelfInkOverflow(const PhysicalRect& ink_overflow)
+      : self_ink_overflow(ink_overflow) {}
 
   PhysicalRect self_ink_overflow;
 };
 
-// Represents an ink-overflow for objects with children, such as boxes. Keeps
-// ink-overflow for self and contents separately.
-struct CORE_EXPORT NGContainerInkOverflow : NGInkOverflow {
+// Represents two ink-overflow rectangles, to keep self and contents ink
+// overflow separately. Used for objects with children, such as boxes.
+struct NGContainerInkOverflow : NGSelfInkOverflow {
   USING_FAST_MALLOC(NGContainerInkOverflow);
 
  public:
-  NGContainerInkOverflow(const PhysicalRect& self_ink_overflow,
-                         const PhysicalRect& contents_ink_overflow)
-      : NGInkOverflow(self_ink_overflow),
-        contents_ink_overflow(contents_ink_overflow) {}
+  NGContainerInkOverflow(const PhysicalRect& self, const PhysicalRect& contents)
+      : NGSelfInkOverflow(self), contents_ink_overflow(contents) {}
 
   PhysicalRect SelfAndContentsInkOverflow() const {
     return UnionRect(self_ink_overflow, contents_ink_overflow);
@@ -48,6 +42,125 @@
   PhysicalRect contents_ink_overflow;
 };
 
+// Represents multiple types of ink overflow in a size of a pointer.
+//
+// When no overflow, or when overflow is small, this class does not allocate
+// memory.
+//
+// In order to keep the instance small, callers must keep |Type| separately.
+// |Set*| functions return |Type|, which callers must keep and pass to following
+// function calls. Functions have DCHECKs to ensure callers pass the correct
+// |Type|.
+class CORE_EXPORT NGInkOverflow {
+ public:
+  enum Type {
+    kNotSet,
+    kNone,
+    kSmallSelf,
+    kSelf,
+    kSelfAndContents
+    // When adding values, make sure |NGFragmentItem| has enough storage.
+  };
+
+  NGInkOverflow() = default;
+#if DCHECK_IS_ON()
+  ~NGInkOverflow();
+#endif
+
+  // Regular copy is prohibited because |Type| is outside of the instance. Use
+  // functions with |Type| below instead.
+  NGInkOverflow(const NGInkOverflow&) = delete;
+  NGInkOverflow& operator=(const NGInkOverflow&) = delete;
+
+  // To copy, |Type| is required.
+  NGInkOverflow(Type source_type, const NGInkOverflow& source);
+
+  // Get ink overflow of various types.
+  PhysicalRect Self(Type type, const PhysicalSize& size) const;
+  PhysicalRect SelfAndContents(Type type, const PhysicalSize& size) const;
+
+  // Reset to |kNone|.
+  Type Reset(Type type);
+
+  // Set self ink overflow rect.
+  Type SetSelf(Type type, const PhysicalRect& self, const PhysicalSize& size);
+
+  // Set self and contents ink overflow rects.
+  Type Set(Type type,
+           const PhysicalRect& self,
+           const PhysicalRect& contents,
+           const PhysicalSize& size);
+
+  // Compute and set ink overflow for text.
+  Type SetTextInkOverflow(Type type,
+                          const NGTextFragmentPaintInfo& text_info,
+                          const ComputedStyle& style,
+                          const PhysicalSize& size,
+                          PhysicalRect* ink_overflow_out);
+
+  static base::Optional<PhysicalRect> ComputeTextInkOverflow(
+      const NGTextFragmentPaintInfo& text_info,
+      const ComputedStyle& style,
+      const PhysicalSize& size);
+
+ private:
+  PhysicalRect FromOutsets(const PhysicalSize& size) const;
+
+  void CheckType(Type type) const;
+  Type SetType(Type type);
+
+  bool TrySetOutsets(Type type,
+                     const PhysicalRect& ink_overflow,
+                     const PhysicalSize& size);
+  Type SetSingle(Type type,
+                 const PhysicalRect& ink_overflow,
+                 const PhysicalSize& size,
+                 Type new_type,
+                 Type new_small_type);
+
+  // |SmallRawValue| can store small values without allocating memory.
+  // |LayoutUnit| uses 6 bits (|kLayoutUnitFractionalBits|) for fraction.
+#if defined(ARCH_CPU_32_BITS)
+  // |uint8_t| can represent 0 to (4 - 1/64) using 2 bits for integer.
+  using SmallRawValue = uint8_t;
+#elif defined(ARCH_CPU_64_BITS)
+  // |uint16_t| can represent 0 to (1024 - 1/64) using 10 bits for integer.
+  using SmallRawValue = uint16_t;
+#else
+#error Only support 32/64 bits.
+#endif
+
+  union {
+    // When only self or contents overflow.
+    NGSelfInkOverflow* self_;
+    // When both self and contents overflow.
+    NGContainerInkOverflow* container_;
+    // Outsets in small |LayoutUnit|s when overflow is small.
+    SmallRawValue outsets_[4];
+    static_assert(sizeof(outsets_) == sizeof(self_),
+                  "outsets should be the size of a pointer");
+  };
+
+#if DCHECK_IS_ON()
+  Type type_ = Type::kNotSet;
+#endif
+};
+
+#if DCHECK_IS_ON()
+inline void NGInkOverflow::CheckType(Type type) const {
+  DCHECK_EQ(type, type_);
+}
+inline NGInkOverflow::Type NGInkOverflow::SetType(Type type) {
+  type_ = type;
+  return type;
+}
+#else
+inline void NGInkOverflow::CheckType(Type type) const {}
+inline NGInkOverflow::Type NGInkOverflow::SetType(Type type) {
+  return type;
+}
+#endif
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_INK_OVERFLOW_H_
diff --git a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow_test.cc b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow_test.cc
new file mode 100644
index 0000000..3426101
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow_test.cc
@@ -0,0 +1,138 @@
+// Copyright 2020 The Chromium 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/layout/ng/ng_ink_overflow.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+
+namespace blink {
+
+namespace {
+
+PhysicalRect FromFloatRound(const FloatRect& rect) {
+  return {LayoutUnit::FromFloatRound(rect.X()),
+          LayoutUnit::FromFloatRound(rect.Y()),
+          LayoutUnit::FromFloatRound(rect.Width()),
+          LayoutUnit::FromFloatRound(rect.Height())};
+}
+
+using testing::ElementsAre;
+
+class NGInkOverflowTest : public testing::Test, private ScopedLayoutNGForTest {
+ public:
+  NGInkOverflowTest() : ScopedLayoutNGForTest(true) {}
+};
+
+#define MIN_LARGE32 4
+#define MIN_LARGE64 1024
+#if UINTPTR_MAX == 0xFFFFFFFF
+#define MIN_LARGE MIN_LARGE32
+#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu
+#define MIN_LARGE MIN_LARGE64
+#endif
+#define MAX_SMALL (LayoutUnit(MIN_LARGE) - LayoutUnit::Epsilon())
+
+struct RectData {
+  PhysicalSize size;
+  FloatRect rect;
+  FloatRect expect;
+  NGInkOverflow::Type type;
+} rect_data[] = {
+    {{20, 10}, {0, 0, 0, 0}, {0, 0, 20, 10}, NGInkOverflow::kNone},
+    {{20, 10}, {0, 0, 20, 10}, {0, 0, 20, 10}, NGInkOverflow::kNone},
+
+    // 2: One of values is max small, all others are 0.
+    {{20, 10},
+     {0, 0, MAX_SMALL + 20, 10},
+     {0, 0, MAX_SMALL + 20, 10},
+     NGInkOverflow::kSmallSelf},
+    {{20, 10},
+     {0, 0, 20, MAX_SMALL + 10},
+     {0, 0, 20, MAX_SMALL + 10},
+     NGInkOverflow::kSmallSelf},
+    {{20, 10},
+     {-MAX_SMALL, 0, MAX_SMALL + 20, 10},
+     {-MAX_SMALL, 0, MAX_SMALL + 20, 10},
+     NGInkOverflow::kSmallSelf},
+    {{20, 10},
+     {0, -MAX_SMALL, 20, MAX_SMALL + 10},
+     {0, -MAX_SMALL, 20, MAX_SMALL + 10},
+     NGInkOverflow::kSmallSelf},
+
+    // 6: One of values is large, all others are 0.
+    {{20, 10},
+     {0, 0, MIN_LARGE + 20, 10},
+     {0, 0, MIN_LARGE + 20, 10},
+     NGInkOverflow::kSelf},
+    {{20, 10},
+     {0, 0, 20, MIN_LARGE + 10},
+     {0, 0, 20, MIN_LARGE + 10},
+     NGInkOverflow::kSelf},
+    {{20, 10},
+     {-MIN_LARGE, 0, MIN_LARGE + 20, 10},
+     {-MIN_LARGE, 0, MIN_LARGE + 20, 10},
+     NGInkOverflow::kSelf},
+    {{20, 10},
+     {0, -MIN_LARGE, 20, MIN_LARGE + 10},
+     {0, -MIN_LARGE, 20, MIN_LARGE + 10},
+     NGInkOverflow::kSelf},
+
+    // 10: All values are the max small values.
+    {{20, 10},
+     {-MAX_SMALL, -MAX_SMALL, MAX_SMALL * 2 + 20, MAX_SMALL * 2 + 10},
+     {-MAX_SMALL, -MAX_SMALL, MAX_SMALL * 2 + 20, MAX_SMALL * 2 + 10},
+     NGInkOverflow::kSmallSelf},
+};
+
+class RectDataTest : public NGInkOverflowTest,
+                     public testing::WithParamInterface<RectData> {};
+
+INSTANTIATE_TEST_SUITE_P(NGInkOverflowTest,
+                         RectDataTest,
+                         testing::ValuesIn(rect_data));
+
+TEST_P(RectDataTest, Self) {
+  const RectData data = GetParam();
+  NGInkOverflow ink_overflow;
+  NGInkOverflow::Type type = ink_overflow.SetSelf(
+      NGInkOverflow::kNotSet, FromFloatRound(data.rect), data.size);
+  EXPECT_EQ(type, data.type);
+  PhysicalRect result = ink_overflow.Self(type, data.size);
+  EXPECT_EQ(result, FromFloatRound(data.expect));
+  ink_overflow.Reset(type);
+}
+
+TEST_P(RectDataTest, Contents) {
+  const RectData data = GetParam();
+  NGInkOverflow ink_overflow;
+  NGInkOverflow::Type type = ink_overflow.Set(
+      NGInkOverflow::kNotSet, {}, FromFloatRound(data.rect), data.size);
+  PhysicalRect result = ink_overflow.SelfAndContents(type, data.size);
+  // TODO(kojii): When empty is set, the visual overflow becomes empty rather
+  // than LocalRect. This is likely not needed and should be revisited, but keep
+  // the behavior for now to keep test results the same.
+  EXPECT_EQ(type, NGInkOverflow::kSelfAndContents);
+  if (data.rect.IsEmpty())
+    EXPECT_EQ(result, PhysicalRect());
+  else
+    EXPECT_EQ(result, FromFloatRound(data.expect));
+  ink_overflow.Reset(type);
+}
+
+TEST_P(RectDataTest, Copy) {
+  const RectData data = GetParam();
+  NGInkOverflow original;
+  NGInkOverflow::Type type = original.SetSelf(
+      NGInkOverflow::kNotSet, FromFloatRound(data.rect), data.size);
+  NGInkOverflow copy(type, original);
+  EXPECT_EQ(copy.Self(type, data.size), original.Self(type, data.size));
+  original.Reset(type);
+  copy.Reset(type);
+}
+
+}  // namespace
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/page/context_menu_controller_test.cc b/third_party/blink/renderer/core/page/context_menu_controller_test.cc
index b63f8e7..4e57341 100644
--- a/third_party/blink/renderer/core/page/context_menu_controller_test.cc
+++ b/third_party/blink/renderer/core/page/context_menu_controller_test.cc
@@ -7,8 +7,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/context_menu_data/edit_flags.h"
 #include "third_party/blink/public/common/input/web_menu_source_type.h"
-#include "third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h"
-#include "third_party/blink/public/platform/web_media_stream.h"
 #include "third_party/blink/public/platform/web_rect.h"
 #include "third_party/blink/public/web/web_context_menu_data.h"
 #include "third_party/blink/renderer/core/dom/xml_document.h"
@@ -22,6 +20,8 @@
 #include "third_party/blink/renderer/core/page/context_menu_controller.h"
 #include "third_party/blink/renderer/platform/geometry/int_rect.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h"
 #include "third_party/blink/renderer/platform/testing/empty_web_media_player.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -365,10 +365,10 @@
   // Setup video element.
   Persistent<HTMLVideoElement> video =
       MakeGarbageCollected<HTMLVideoElement>(*GetDocument());
-  blink::WebMediaStream web_media_stream;
-  blink::WebVector<blink::WebMediaStreamTrack> dummy_tracks;
-  web_media_stream.Initialize(dummy_tracks, dummy_tracks);
-  video->SetSrcObject(web_media_stream);
+  MediaStreamComponentVector dummy_components;
+  auto* media_stream_descriptor = MakeGarbageCollected<MediaStreamDescriptor>(
+      dummy_components, dummy_components);
+  video->SetSrcObject(media_stream_descriptor);
   GetDocument()->body()->AppendChild(video);
   test::RunPendingTasks();
   SetReadyState(video.Get(), HTMLMediaElement::kHaveMetadata);
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc
index 665fa29..ea46038 100644
--- a/third_party/blink/renderer/core/style/computed_style.cc
+++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -1335,13 +1335,6 @@
   SetListStyleImageInternal(v);
 }
 
-StyleColor ComputedStyle::GetColor() const {
-  return ColorInternal();
-}
-void ComputedStyle::SetColor(const StyleColor& v) {
-  SetColorInternal(v);
-}
-
 bool ComputedStyle::SetEffectiveZoom(float f) {
   // Clamp the effective zoom value to a smaller (but hopeful still large
   // enough) range, to avoid overflow in derived computations.
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index d0f4060..35985efd 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -571,35 +571,6 @@
     return BorderRightWidth() && (BorderRightStyle() != EBorderStyle::kNone);
   }
 
-  // Border color properties.
-  // border-left-color
-  void SetBorderLeftColor(const StyleColor& color) {
-    if (BorderLeftColor() != color) {
-      SetBorderLeftColorInternal(color);
-    }
-  }
-
-  // border-right-color
-  void SetBorderRightColor(const StyleColor& color) {
-    if (BorderRightColor() != color) {
-      SetBorderRightColorInternal(color);
-    }
-  }
-
-  // border-top-color
-  void SetBorderTopColor(const StyleColor& color) {
-    if (BorderTopColor() != color) {
-      SetBorderTopColorInternal(color);
-    }
-  }
-
-  // border-bottom-color
-  void SetBorderBottomColor(const StyleColor& color) {
-    if (BorderBottomColor() != color) {
-      SetBorderBottomColorInternal(color);
-    }
-  }
-
   // box-shadow (aka -webkit-box-shadow)
   bool BoxShadowDataEquivalent(const ComputedStyle& other) const {
     return DataEquivalent(BoxShadow(), other.BoxShadow());
@@ -626,13 +597,6 @@
     SetColumnCountInternal(ComputedStyleInitialValues::InitialColumnCount());
   }
 
-  // column-rule-color (aka -webkit-column-rule-color)
-  void SetColumnRuleColor(const StyleColor& c) {
-    if (ColumnRuleColor() != c) {
-      SetColumnRuleColorInternal(c);
-    }
-  }
-
   // column-rule-width (aka -webkit-column-rule-width)
   uint16_t ColumnRuleWidth() const {
     if (ColumnRuleStyle() == EBorderStyle::kNone ||
@@ -712,13 +676,6 @@
            OutlineStyleIsAuto() == other.OutlineStyleIsAuto();
   }
 
-  // outline-color
-  void SetOutlineColor(const StyleColor& v) {
-    if (OutlineColor() != v) {
-      SetOutlineColorInternal(v);
-    }
-  }
-
   // outline-width
   float OutlineWidth() const {
     if (OutlineStyle() == EBorderStyle::kNone)
@@ -975,9 +932,6 @@
 
   // Inherited properties.
 
-  // color
-  void SetColor(const StyleColor&);
-
   // line-height
   Length LineHeight() const;
 
@@ -1000,21 +954,6 @@
   const AtomicString& TextEmphasisMarkString() const;
   LineLogicalSide GetTextEmphasisLineLogicalSide() const;
 
-  // -webkit-text-emphasis-color (aka -epub-text-emphasis-color)
-  void SetTextEmphasisColor(const StyleColor& color) {
-    SetTextEmphasisColorInternal(color);
-  }
-
-  // -webkit-text-fill-color
-  void SetTextFillColor(const StyleColor& color) {
-    SetTextFillColorInternal(color);
-  }
-
-  // -webkit-text-stroke-color
-  void SetTextStrokeColor(const StyleColor& color) {
-    SetTextStrokeColorInternal(color);
-  }
-
   // caret-color
   void SetCaretColor(const StyleAutoColor& color) {
     SetCaretColorInternal(color.Resolve(Color()));
@@ -2757,12 +2696,20 @@
 
   // Color accessors are all private to make sure callers use
   // VisitedDependentColor instead to access them.
-  StyleColor BorderLeftColor() const { return BorderLeftColorInternal(); }
-  StyleColor BorderRightColor() const { return BorderRightColorInternal(); }
-  StyleColor BorderTopColor() const { return BorderTopColorInternal(); }
-  StyleColor BorderBottomColor() const { return BorderBottomColorInternal(); }
+  const StyleColor& BorderLeftColor() const {
+    return BorderLeftColorInternal();
+  }
+  const StyleColor& BorderRightColor() const {
+    return BorderRightColorInternal();
+  }
+  const StyleColor& BorderTopColor() const { return BorderTopColorInternal(); }
+  const StyleColor& BorderBottomColor() const {
+    return BorderBottomColorInternal();
+  }
 
-  StyleColor BackgroundColor() const { return BackgroundColorInternal(); }
+  const StyleColor& BackgroundColor() const {
+    return BackgroundColorInternal();
+  }
   StyleAutoColor CaretColor() const {
     if (CaretColorIsCurrentColorInternal())
       return StyleAutoColor::CurrentColor();
@@ -2770,13 +2717,22 @@
       return StyleAutoColor::AutoColor();
     return StyleAutoColor(CaretColorInternal());
   }
-  StyleColor GetColor() const;
-  StyleColor ColumnRuleColor() const { return ColumnRuleColorInternal(); }
-  StyleColor OutlineColor() const { return OutlineColorInternal(); }
-  StyleColor TextEmphasisColor() const { return TextEmphasisColorInternal(); }
-  StyleColor TextFillColor() const { return TextFillColorInternal(); }
-  StyleColor TextStrokeColor() const { return TextStrokeColorInternal(); }
-  StyleColor InternalVisitedColor() const {
+  const StyleColor& GetColor() const { return ColorInternal(); }
+  const StyleColor& ColumnRuleColor() const {
+    return ColumnRuleColorInternal();
+  }
+  const StyleColor& OutlineColor() const { return OutlineColorInternal(); }
+  const StyleColor& TextDecorationColor() const {
+    return TextDecorationColorInternal();
+  }
+  const StyleColor& TextEmphasisColor() const {
+    return TextEmphasisColorInternal();
+  }
+  const StyleColor& TextFillColor() const { return TextFillColorInternal(); }
+  const StyleColor& TextStrokeColor() const {
+    return TextStrokeColorInternal();
+  }
+  const StyleColor& InternalVisitedColor() const {
     return InternalVisitedColorInternal();
   }
   StyleAutoColor InternalVisitedCaretColor() const {
@@ -2786,10 +2742,10 @@
       return StyleAutoColor::AutoColor();
     return StyleAutoColor(InternalVisitedCaretColorInternal());
   }
-  StyleColor InternalVisitedBackgroundColor() const {
+  const StyleColor& InternalVisitedBackgroundColor() const {
     return InternalVisitedBackgroundColorInternal();
   }
-  StyleColor InternalVisitedBorderLeftColor() const {
+  const StyleColor& InternalVisitedBorderLeftColor() const {
     return InternalVisitedBorderLeftColorInternal();
   }
   bool InternalVisitedBorderLeftColorHasNotChanged(
@@ -2798,7 +2754,7 @@
                 other.InternalVisitedBorderLeftColor() ||
             !BorderLeftWidth());
   }
-  StyleColor InternalVisitedBorderRightColor() const {
+  const StyleColor& InternalVisitedBorderRightColor() const {
     return InternalVisitedBorderRightColorInternal();
   }
   bool InternalVisitedBorderRightColorHasNotChanged(
@@ -2807,7 +2763,7 @@
                 other.InternalVisitedBorderRightColor() ||
             !BorderRightWidth());
   }
-  StyleColor InternalVisitedBorderBottomColor() const {
+  const StyleColor& InternalVisitedBorderBottomColor() const {
     return InternalVisitedBorderBottomColorInternal();
   }
   bool InternalVisitedBorderBottomColorHasNotChanged(
@@ -2816,7 +2772,7 @@
                 other.InternalVisitedBorderBottomColor() ||
             !BorderBottomWidth());
   }
-  StyleColor InternalVisitedBorderTopColor() const {
+  const StyleColor& InternalVisitedBorderTopColor() const {
     return InternalVisitedBorderTopColorInternal();
   }
   bool InternalVisitedBorderTopColorHasNotChanged(
@@ -2825,7 +2781,7 @@
                 other.InternalVisitedBorderTopColor() ||
             !BorderTopWidth());
   }
-  StyleColor InternalVisitedOutlineColor() const {
+  const StyleColor& InternalVisitedOutlineColor() const {
     return InternalVisitedOutlineColorInternal();
   }
   bool InternalVisitedOutlineColorHasNotChanged(
@@ -2834,27 +2790,27 @@
                 other.InternalVisitedOutlineColor() ||
             !OutlineWidth());
   }
-  StyleColor InternalVisitedColumnRuleColor() const {
+  const StyleColor& InternalVisitedColumnRuleColor() const {
     return InternalVisitedColumnRuleColorInternal();
   }
-  StyleColor InternalVisitedTextDecorationColor() const {
+  const StyleColor& InternalVisitedTextDecorationColor() const {
     return InternalVisitedTextDecorationColorInternal();
   }
-  StyleColor InternalVisitedTextEmphasisColor() const {
+  const StyleColor& InternalVisitedTextEmphasisColor() const {
     return InternalVisitedTextEmphasisColorInternal();
   }
-  StyleColor InternalVisitedTextFillColor() const {
+  const StyleColor& InternalVisitedTextFillColor() const {
     return InternalVisitedTextFillColorInternal();
   }
-  StyleColor InternalVisitedTextStrokeColor() const {
+  const StyleColor& InternalVisitedTextStrokeColor() const {
     return InternalVisitedTextStrokeColorInternal();
   }
 
   StyleColor DecorationColorIncludingFallback(bool visited_link) const;
 
   const StyleColor& StopColor() const { return SvgStyle().StopColor(); }
-  StyleColor FloodColor() const { return SvgStyle().FloodColor(); }
-  StyleColor LightingColor() const { return SvgStyle().LightingColor(); }
+  const StyleColor& FloodColor() const { return SvgStyle().FloodColor(); }
+  const StyleColor& LightingColor() const { return SvgStyle().LightingColor(); }
 
   // Appearance accessors are private to make sure callers use
   // EffectiveAppearance in almost all cases.
diff --git a/third_party/blink/renderer/core/style/svg_computed_style.h b/third_party/blink/renderer/core/style/svg_computed_style.h
index b46d52f..975c60b 100644
--- a/third_party/blink/renderer/core/style/svg_computed_style.h
+++ b/third_party/blink/renderer/core/style/svg_computed_style.h
@@ -245,18 +245,14 @@
       misc.Access()->flood_opacity = obj;
   }
 
-  void SetFloodColor(const StyleColor& style_color) {
-    if (FloodColor() != style_color) {
-      StyleMiscData* mutable_misc = misc.Access();
-      mutable_misc->flood_color = style_color;
-    }
+  void SetFloodColor(const StyleColor& color) {
+    if (!(misc->flood_color == color))
+      misc.Access()->flood_color = color;
   }
 
-  void SetLightingColor(const StyleColor& style_color) {
-    if (LightingColor() != style_color) {
-      StyleMiscData* mutable_misc = misc.Access();
-      mutable_misc->lighting_color = style_color;
-    }
+  void SetLightingColor(const StyleColor& color) {
+    if (!(misc->lighting_color == color))
+      misc.Access()->lighting_color = color;
   }
 
   void SetBaselineShiftValue(const Length& baseline_shift_value) {
@@ -322,8 +318,8 @@
   float StopOpacity() const { return stops->opacity; }
   const StyleColor& StopColor() const { return stops->color; }
   float FloodOpacity() const { return misc->flood_opacity; }
-  StyleColor FloodColor() const { return misc->flood_color; }
-  StyleColor LightingColor() const { return misc->lighting_color; }
+  const StyleColor& FloodColor() const { return misc->flood_color; }
+  const StyleColor& LightingColor() const { return misc->lighting_color; }
   const Length& BaselineShiftValue() const {
     return misc->baseline_shift_value;
   }
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 0f08d603..65ac02e6 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -260,6 +260,7 @@
 
   sources = [
     "accessibility/accessibility_object_model_test.cc",
+    "accessibility/ax_inline_text_box_test.cc",
     "accessibility/ax_layout_object_test.cc",
     "accessibility/ax_object_cache_test.cc",
     "accessibility/ax_object_test.cc",
diff --git a/third_party/blink/renderer/modules/accessibility/ax_inline_text_box_test.cc b/third_party/blink/renderer/modules/accessibility/ax_inline_text_box_test.cc
new file mode 100644
index 0000000..0160daf
--- /dev/null
+++ b/third_party/blink/renderer/modules/accessibility/ax_inline_text_box_test.cc
@@ -0,0 +1,42 @@
+// Copyright 2020 The Chromium 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/modules/accessibility/ax_inline_text_box.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
+#include "third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+namespace test {
+
+TEST_P(ParameterizedAccessibilityTest, GetWordBoundaries) {
+  // &#9728; is the sun emoji symbol.
+  // &#2460; is circled digit one.
+  SetBodyInnerHTML(R"HTML(
+      <p id="paragraph">
+        &quot;This, &#9728; &#2460; is ... a---+++test.&quot;
+      </p>)HTML");
+
+  AXObject* ax_paragraph = GetAXObjectByElementId("paragraph");
+  ASSERT_NE(nullptr, ax_paragraph);
+  ASSERT_EQ(ax::mojom::Role::kParagraph, ax_paragraph->RoleValue());
+  ax_paragraph->LoadInlineTextBoxes();
+
+  const AXObject* ax_inline_text_box =
+      ax_paragraph->DeepestFirstChildIncludingIgnored();
+  ASSERT_NE(nullptr, ax_inline_text_box);
+  ASSERT_EQ(ax::mojom::Role::kInlineTextBox, ax_inline_text_box->RoleValue());
+
+  VectorOf<int> expected_word_starts{0, 1, 5, 9, 11, 14, 18, 19, 25, 29};
+  VectorOf<int> expected_word_ends{1, 5, 6, 10, 13, 17, 19, 22, 29, 31};
+  VectorOf<int> word_starts, word_ends;
+  ax_inline_text_box->GetWordBoundaries(word_starts, word_ends);
+  EXPECT_EQ(expected_word_starts, word_starts);
+  EXPECT_EQ(expected_word_ends, word_ends);
+}
+
+}  // namespace test
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index 5d1f7c7..43f038d 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -2273,7 +2273,7 @@
     case ax::mojom::blink::Role::kColorWell:
     case ax::mojom::blink::Role::kDate:
     case ax::mojom::blink::Role::kDateTime: {
-      for (const auto& child : children_) {
+      for (const auto& child : ChildrenIncludingIgnored()) {
         if (child->IsWebArea())
           return child;
       }
@@ -3022,7 +3022,7 @@
     return;
   }
 
-  for (const auto& child : children_) {
+  for (const auto& child : ChildrenIncludingIgnored()) {
     child->LoadInlineTextBoxes();
   }
 }
@@ -3034,8 +3034,9 @@
 
   Settings* settings = document->GetSettings();
   if (!force &&
-      (!settings || !settings->GetInlineTextBoxAccessibilityEnabled()))
+      (!settings || !settings->GetInlineTextBoxAccessibilityEnabled())) {
     return;
+  }
 
   if (!GetLayoutObject() || !GetLayoutObject()->IsText())
     return;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index 5bc9749..b379f696 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -2613,7 +2613,7 @@
 
 AXObject* AXObject::ElementAccessibilityHitTest(const IntPoint& point) const {
   // Check if there are any mock elements that need to be handled.
-  for (const auto& child : children_) {
+  for (const auto& child : ChildrenIncludingIgnored()) {
     if (child->IsMockObject() &&
         child->GetBoundsInFrameCoordinates().Contains(point))
       return child->ElementAccessibilityHitTest(point);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_test.cc b/third_party/blink/renderer/modules/accessibility/ax_object_test.cc
index 146c1968..03e1805e 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_test.cc
@@ -12,22 +12,6 @@
 namespace blink {
 namespace test {
 
-class AccessibilityLayoutTest : public testing::WithParamInterface<bool>,
-                                private ScopedLayoutNGForTest,
-                                public AccessibilityTest {
- public:
-  AccessibilityLayoutTest() : ScopedLayoutNGForTest(GetParam()) {}
-
- protected:
-  bool LayoutNGEnabled() const {
-    return RuntimeEnabledFeatures::LayoutNGEnabled();
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(AccessibilityTest,
-                         AccessibilityLayoutTest,
-                         testing::Bool());
-
 TEST_F(AccessibilityTest, IsDescendantOf) {
   SetBodyInnerHTML(R"HTML(<button id="button">button</button>)HTML");
 
@@ -390,7 +374,7 @@
   EXPECT_EQ(anchor->Url(), KURL("http://test.com/#target"));
 }
 
-TEST_P(AccessibilityLayoutTest, NextOnLine) {
+TEST_P(ParameterizedAccessibilityTest, NextOnLine) {
   SetBodyInnerHTML(R"HTML(
     <style>
     html {
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.cc b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
index 7115c21..e4e2ffb 100644
--- a/third_party/blink/renderer/modules/imagecapture/image_capture.cc
+++ b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
@@ -105,8 +105,8 @@
       (track->GetImageCapture() &&
        track->GetImageCapture()->HasPanTiltZoomPermissionGranted());
 
-  return MakeGarbageCollected<ImageCapture>(context, track,
-                                            pan_tilt_zoom_allowed);
+  return MakeGarbageCollected<ImageCapture>(
+      context, track, pan_tilt_zoom_allowed, base::DoNothing());
 }
 
 ImageCapture::~ImageCapture() {
@@ -697,8 +697,9 @@
 }
 
 void ImageCapture::SetPanTiltZoomSettingsFromTrack(
+    base::OnceClosure initialized_callback,
     media::mojom::blink::PhotoStatePtr photo_state) {
-  UpdateMediaTrackCapabilities(std::move(photo_state));
+  UpdateMediaTrackCapabilities(base::DoNothing(), std::move(photo_state));
 
   MediaStreamVideoTrack* video_track = MediaStreamVideoTrack::GetVideoTrack(
       WebMediaStreamTrack(stream_track_->Component()));
@@ -708,8 +709,16 @@
   base::Optional<double> tilt = video_track->tilt();
   base::Optional<double> zoom = video_track->zoom();
 
-  if (!pan.has_value() && !tilt.has_value() && !zoom.has_value())
+  const bool ptz_requested =
+      pan.has_value() || tilt.has_value() || zoom.has_value();
+  const bool ptz_supported = capabilities_->hasPan() ||
+                             capabilities_->hasTilt() ||
+                             capabilities_->hasZoom();
+  if (!ptz_supported || !ptz_requested || !HasPanTiltZoomPermissionGranted() ||
+      !service_.is_bound()) {
+    std::move(initialized_callback).Run();
     return;
+  }
 
   ExecutionContext* context = GetExecutionContext();
   if (pan.has_value())
@@ -719,17 +728,6 @@
   if (zoom.has_value())
     UseCounter::Count(context, WebFeature::kImageCaptureZoom);
 
-  if (!HasPanTiltZoomPermissionGranted())
-    return;
-
-  if (!capabilities_->hasPan() && !capabilities_->hasTilt() &&
-      !capabilities_->hasZoom()) {
-    return;
-  }
-
-  if (!service_.is_bound())
-    return;
-
   auto settings = media::mojom::blink::PhotoSettings::New();
 
   if (capabilities_->hasPan() && pan.has_value() &&
@@ -754,13 +752,16 @@
   service_->SetOptions(
       stream_track_->Component()->Source()->Id(), std::move(settings),
       WTF::Bind(&ImageCapture::OnSetPanTiltZoomSettingsFromTrack,
-                WrapPersistent(this)));
+                WrapPersistent(this), std::move(initialized_callback)));
 }
 
-void ImageCapture::OnSetPanTiltZoomSettingsFromTrack(bool result) {
-  service_->GetPhotoState(stream_track_->Component()->Source()->Id(),
-                          WTF::Bind(&ImageCapture::UpdateMediaTrackCapabilities,
-                                    WrapPersistent(this)));
+void ImageCapture::OnSetPanTiltZoomSettingsFromTrack(
+    base::OnceClosure done_callback,
+    bool result) {
+  service_->GetPhotoState(
+      stream_track_->Component()->Source()->Id(),
+      WTF::Bind(&ImageCapture::UpdateMediaTrackCapabilities,
+                WrapPersistent(this), std::move(done_callback)));
 }
 
 const MediaTrackConstraintSet* ImageCapture::GetMediaTrackConstraints() const {
@@ -828,7 +829,8 @@
 
 ImageCapture::ImageCapture(ExecutionContext* context,
                            MediaStreamTrack* track,
-                           bool pan_tilt_zoom_allowed)
+                           bool pan_tilt_zoom_allowed,
+                           base::OnceClosure initialized_callback)
     : ExecutionContextLifecycleObserver(context),
       stream_track_(track),
       service_(context),
@@ -861,7 +863,7 @@
   service_->GetPhotoState(
       stream_track_->Component()->Source()->Id(),
       WTF::Bind(&ImageCapture::SetPanTiltZoomSettingsFromTrack,
-                WrapPersistent(this)));
+                WrapPersistent(this), std::move(initialized_callback)));
 
   ConnectToPermissionService(
       context, permission_service_.BindNewPipeAndPassReceiver(
@@ -924,7 +926,7 @@
     photo_capabilities_->SetFillLightMode(photo_state->fill_light_mode);
 
   // Update the local track photo_state cache.
-  UpdateMediaTrackCapabilities(std::move(photo_state));
+  UpdateMediaTrackCapabilities(base::DoNothing(), std::move(photo_state));
 
   if (trigger_take_photo) {
     service_->TakePhoto(
@@ -983,9 +985,12 @@
 }
 
 void ImageCapture::UpdateMediaTrackCapabilities(
+    base::OnceClosure initialized_callback,
     media::mojom::blink::PhotoStatePtr photo_state) {
-  if (!photo_state)
+  if (!photo_state) {
+    std::move(initialized_callback).Run();
     return;
+  }
 
   WTF::Vector<WTF::String> supported_white_balance_modes;
   supported_white_balance_modes.ReserveInitialCapacity(
@@ -1104,6 +1109,8 @@
     capabilities_->setTorch(photo_state->supports_torch);
   if (photo_state->supports_torch)
     settings_->setTorch(photo_state->torch);
+
+  std::move(initialized_callback).Run();
 }
 
 void ImageCapture::OnServiceConnectionError() {
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.h b/third_party/blink/renderer/modules/imagecapture/image_capture.h
index b94af3d..0d492fa 100644
--- a/third_party/blink/renderer/modules/imagecapture/image_capture.h
+++ b/third_party/blink/renderer/modules/imagecapture/image_capture.h
@@ -45,9 +45,12 @@
                               MediaStreamTrack*,
                               ExceptionState&);
 
+  // |initialized_callback| is called when settings and capabilities are
+  // retrieved.
   ImageCapture(ExecutionContext*,
                MediaStreamTrack*,
-               bool pan_tilt_zoom_allowed);
+               bool pan_tilt_zoom_allowed,
+               base::OnceClosure initialized_callback);
   ~ImageCapture() override;
 
   // EventTarget implementation.
@@ -105,10 +108,20 @@
   // If getUserMedia contains either pan, tilt, or zoom constraints, the
   // corresponding settings will be set when image capture is created.
   void SetPanTiltZoomSettingsFromTrack(
+      base::OnceClosure callback,
       media::mojom::blink::PhotoStatePtr photo_state);
-  void OnSetPanTiltZoomSettingsFromTrack(bool result);
+  // Update local track settings and capabilities once pan, tilt, and zoom
+  // settings have been set. |done_callback| will be called when settings and
+  // capabilities are retrieved.
+  void OnSetPanTiltZoomSettingsFromTrack(base::OnceClosure done_callback,
+                                         bool result);
+  // Update local track settings and capabilities and call
+  // |initialized_callback| to indicate settings and capabilities have been
+  // retrieved.
+  void UpdateMediaTrackCapabilities(
+      base::OnceClosure initialized_callback,
+      media::mojom::blink::PhotoStatePtr photo_state);
 
-  void UpdateMediaTrackCapabilities(media::mojom::blink::PhotoStatePtr);
   void OnServiceConnectionError();
 
   void ResolveWithNothing(ScriptPromiseResolver*);
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream.cc b/third_party/blink/renderer/modules/mediastream/media_stream.cc
index ff20c2f..293efe7e 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream.cc
@@ -92,7 +92,15 @@
 
 MediaStream* MediaStream::Create(ExecutionContext* context,
                                  MediaStreamDescriptor* stream_descriptor) {
-  return MakeGarbageCollected<MediaStream>(context, stream_descriptor);
+  return MakeGarbageCollected<MediaStream>(context, stream_descriptor,
+                                           /*callback=*/base::DoNothing());
+}
+
+void MediaStream::Create(ExecutionContext* context,
+                         MediaStreamDescriptor* stream_descriptor,
+                         base::OnceCallback<void(MediaStream*)> callback) {
+  MakeGarbageCollected<MediaStream>(context, stream_descriptor,
+                                    std::move(callback));
 }
 
 MediaStream* MediaStream::Create(ExecutionContext* context,
@@ -104,9 +112,11 @@
 }
 
 MediaStream::MediaStream(ExecutionContext* context,
-                         MediaStreamDescriptor* stream_descriptor)
+                         MediaStreamDescriptor* stream_descriptor,
+                         base::OnceCallback<void(MediaStream*)> callback)
     : ExecutionContextClient(context),
       descriptor_(stream_descriptor),
+      media_stream_initialized_callback_(std::move(callback)),
       scheduled_event_timer_(
           context->GetTaskRunner(TaskType::kMediaElementEvent),
           this,
@@ -126,7 +136,9 @@
   video_tracks_.ReserveCapacity(number_of_video_tracks);
   for (uint32_t i = 0; i < number_of_video_tracks; i++) {
     auto* new_track = MakeGarbageCollected<MediaStreamTrack>(
-        context, descriptor_->VideoComponent(i));
+        context, descriptor_->VideoComponent(i),
+        WTF::Bind(&MediaStream::OnMediaStreamTrackInitialized,
+                  WrapPersistent(this)));
     new_track->RegisterMediaStream(this);
     video_tracks_.push_back(new_track);
   }
@@ -134,6 +146,17 @@
   if (EmptyOrOnlyEndedTracks()) {
     descriptor_->SetActive(false);
   }
+
+  if (number_of_video_tracks == 0) {
+    std::move(media_stream_initialized_callback_).Run(this);
+  }
+}
+
+void MediaStream::OnMediaStreamTrackInitialized() {
+  if (++number_of_video_tracks_initialized_ ==
+      descriptor_->NumberOfVideoComponents()) {
+    std::move(media_stream_initialized_callback_).Run(this);
+  }
 }
 
 MediaStream::MediaStream(ExecutionContext* context,
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream.h b/third_party/blink/renderer/modules/mediastream/media_stream.h
index ae4deff..92ba810 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream.h
@@ -67,6 +67,12 @@
   // Creates a MediaStream matching the MediaStreamDescriptor. MediaStreamTracks
   // are created for any MediaStreamComponents attached to the descriptor.
   static MediaStream* Create(ExecutionContext*, MediaStreamDescriptor*);
+  // Creates a MediaStream matching the MediaStreamDescriptor. MediaStreamTracks
+  // are created for any MediaStreamComponents attached to the descriptor. It
+  // returns the stream via callback.
+  static void Create(ExecutionContext*,
+                     MediaStreamDescriptor*,
+                     base::OnceCallback<void(MediaStream*)> callback);
   // Creates a MediaStream with the specified MediaStreamDescriptor and
   // MediaStreamTracks. The tracks must match the MediaStreamComponents attached
   // to the descriptor (or else a DCHECK fails). This allows you to create
@@ -81,7 +87,9 @@
                              const MediaStreamTrackVector& audio_tracks,
                              const MediaStreamTrackVector& video_tracks);
 
-  MediaStream(ExecutionContext*, MediaStreamDescriptor*);
+  MediaStream(ExecutionContext*,
+              MediaStreamDescriptor*,
+              base::OnceCallback<void(MediaStream*)> callback);
   MediaStream(ExecutionContext*,
               MediaStreamDescriptor*,
               const MediaStreamTrackVector& audio_tracks,
@@ -156,14 +164,22 @@
   void ScheduleDispatchEvent(Event*);
   void ScheduledEventTimerFired(TimerBase*);
 
+  void OnMediaStreamTrackInitialized();
+
   MediaStreamTrackVector audio_tracks_;
   MediaStreamTrackVector video_tracks_;
   Member<MediaStreamDescriptor> descriptor_;
   // Observers are informed when |addTrack| and |removeTrack| are called.
   HeapHashSet<WeakMember<MediaStreamObserver>> observers_;
 
+  // The callback to be called when the media stream is fully initialized,
+  // including image capture for video tracks.
+  base::OnceCallback<void(MediaStream*)> media_stream_initialized_callback_;
+
   TaskRunnerTimer<MediaStream> scheduled_event_timer_;
   HeapVector<Member<Event>> scheduled_events_;
+
+  uint32_t number_of_video_tracks_initialized_ = 0;
 };
 
 using MediaStreamVector = HeapVector<Member<MediaStream>>;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
index 3c9281f..04f91131 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
@@ -222,11 +222,21 @@
                                    MediaStreamComponent* component)
     : MediaStreamTrack(context,
                        component,
-                       component->Source()->GetReadyState()) {}
+                       component->Source()->GetReadyState(),
+                       /*callback=*/base::DoNothing()) {}
 
 MediaStreamTrack::MediaStreamTrack(ExecutionContext* context,
                                    MediaStreamComponent* component,
-                                   MediaStreamSource::ReadyState ready_state)
+                                   base::OnceClosure callback)
+    : MediaStreamTrack(context,
+                       component,
+                       component->Source()->GetReadyState(),
+                       std::move(callback)) {}
+
+MediaStreamTrack::MediaStreamTrack(ExecutionContext* context,
+                                   MediaStreamComponent* component,
+                                   MediaStreamSource::ReadyState ready_state,
+                                   base::OnceClosure callback)
     : ready_state_(ready_state),
       component_(component),
       execution_context_(context) {
@@ -244,8 +254,10 @@
     bool pan_tilt_zoom_allowed =
         image_capture_ ? image_capture_->HasPanTiltZoomPermissionGranted()
                        : video_track->pan_tilt_zoom_allowed();
-    image_capture_ = MakeGarbageCollected<ImageCapture>(context, this,
-                                                        pan_tilt_zoom_allowed);
+    image_capture_ = MakeGarbageCollected<ImageCapture>(
+        context, this, pan_tilt_zoom_allowed, std::move(callback));
+  } else {
+    std::move(callback).Run();
   }
 }
 
@@ -401,7 +413,8 @@
 MediaStreamTrack* MediaStreamTrack::clone(ScriptState* script_state) {
   MediaStreamComponent* cloned_component = Component()->Clone();
   MediaStreamTrack* cloned_track = MakeGarbageCollected<MediaStreamTrack>(
-      ExecutionContext::From(script_state), cloned_component, ready_state_);
+      ExecutionContext::From(script_state), cloned_component, ready_state_,
+      base::DoNothing());
   DidCloneMediaStreamTrack(Component(), cloned_component);
   return cloned_track;
 }
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track.h b/third_party/blink/renderer/modules/mediastream/media_stream_track.h
index 91a69a35..720d6c6 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_track.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_track.h
@@ -57,7 +57,11 @@
   MediaStreamTrack(ExecutionContext*, MediaStreamComponent*);
   MediaStreamTrack(ExecutionContext*,
                    MediaStreamComponent*,
-                   MediaStreamSource::ReadyState);
+                   base::OnceClosure callback);
+  MediaStreamTrack(ExecutionContext*,
+                   MediaStreamComponent*,
+                   MediaStreamSource::ReadyState,
+                   base::OnceClosure callback);
   ~MediaStreamTrack() override;
 
   String kind() const;
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_request.cc b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
index 694d47e5..877e0eb 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_request.cc
+++ b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
@@ -517,20 +517,21 @@
   if (!GetExecutionContext())
     return;
 
-  MediaStream* stream =
-      MediaStream::Create(GetExecutionContext(), stream_descriptor);
+  MediaStream::Create(GetExecutionContext(), stream_descriptor,
+                      WTF::Bind(&UserMediaRequest::OnMediaStreamInitialized,
+                                WrapPersistent(this)));
+}
+
+void UserMediaRequest::OnMediaStreamInitialized(MediaStream* stream) {
+  DCHECK(!is_resolved_);
 
   MediaStreamTrackVector audio_tracks = stream->getAudioTracks();
-  for (MediaStreamTrackVector::iterator iter = audio_tracks.begin();
-       iter != audio_tracks.end(); ++iter) {
-    (*iter)->SetConstraints(audio_);
-  }
+  for (const auto& audio_track : audio_tracks)
+    audio_track->SetConstraints(audio_);
 
   MediaStreamTrackVector video_tracks = stream->getVideoTracks();
-  for (MediaStreamTrackVector::iterator iter = video_tracks.begin();
-       iter != video_tracks.end(); ++iter) {
-    (*iter)->SetConstraints(video_);
-  }
+  for (const auto& video_track : video_tracks)
+    video_track->SetConstraints(video_);
 
   callbacks_->OnSuccess(nullptr, stream);
   is_resolved_ = true;
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_request.h b/third_party/blink/renderer/modules/mediastream/user_media_request.h
index d1e43fe5..561f1c5 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_request.h
+++ b/third_party/blink/renderer/modules/mediastream/user_media_request.h
@@ -119,6 +119,7 @@
   void Start();
 
   void Succeed(MediaStreamDescriptor*);
+  void OnMediaStreamInitialized(MediaStream* stream);
   void FailConstraint(const String& constraint_name, const String& message);
   void Fail(Error name, const String& message);
 
diff --git a/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc b/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc
index 5ce4046..fad9ec7 100644
--- a/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc
+++ b/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc
@@ -9,7 +9,7 @@
 
 namespace blink {
 
-MediaStreamComponent* CreateWebMediaStreamTrack(
+MediaStreamComponent* CreateMediaStreamComponent(
     const std::string& id,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   blink::WebMediaStreamSource web_source;
@@ -70,7 +70,7 @@
 }
 
 MediaStreamComponent* FakeRTCRtpSenderImpl::Track() const {
-  return track_id_ ? CreateWebMediaStreamTrack(*track_id_, task_runner_)
+  return track_id_ ? CreateMediaStreamComponent(*track_id_, task_runner_)
                    : nullptr;
 }
 
@@ -120,7 +120,7 @@
     const std::string& track_id,
     std::vector<std::string> stream_ids,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner)
-    : component_(CreateWebMediaStreamTrack(track_id, task_runner)),
+    : component_(CreateMediaStreamComponent(track_id, task_runner)),
       stream_ids_(std::move(stream_ids)) {}
 
 FakeRTCRtpReceiverImpl::FakeRTCRtpReceiverImpl(const FakeRTCRtpReceiverImpl&) =
diff --git a/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h b/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h
index 0e51a58..177c17d 100644
--- a/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h
+++ b/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h
@@ -23,7 +23,7 @@
 
 // TODO(https://crbug.com/868868): Similar methods to this exist in many blink
 // unittests. Move to a separate file and reuse it in all of them.
-MediaStreamComponent* CreateWebMediaStreamTrack(
+MediaStreamComponent* CreateMediaStreamComponent(
     const std::string& id,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner);
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
index a77372a7..e981963 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
@@ -215,9 +215,6 @@
                     const String& value));
   MOCK_METHOD1(TrackOnRenegotiationNeeded,
                void(RTCPeerConnectionHandler* pc_handler));
-  MOCK_METHOD2(TrackCreateDTMFSender,
-               void(RTCPeerConnectionHandler* pc_handler,
-                    const blink::WebMediaStreamTrack& track));
 };
 
 class DummyRTCVoidRequest final : public RTCVoidRequest {
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
index 52ef2a23..0515296 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
@@ -429,14 +429,14 @@
                                            "The peer connection is closed."));
     return promise;
   }
-  WebMediaStreamTrack web_track;
+  MediaStreamComponent* component = nullptr;
   if (with_track) {
     pc_->RegisterTrack(with_track);
-    web_track = with_track->Component();
+    component = with_track->Component();
   }
   ReplaceTrackRequest* request =
       MakeGarbageCollected<ReplaceTrackRequest>(this, with_track, resolver);
-  sender_->ReplaceTrack(web_track, request);
+  sender_->ReplaceTrack(component, request);
   return promise;
 }
 
diff --git a/third_party/blink/renderer/platform/geometry/layout_unit.h b/third_party/blink/renderer/platform/geometry/layout_unit.h
index 067c5529..2c35a66 100644
--- a/third_party/blink/renderer/platform/geometry/layout_unit.h
+++ b/third_party/blink/renderer/platform/geometry/layout_unit.h
@@ -133,6 +133,12 @@
     return v;
   }
 
+  static LayoutUnit FromRawValue(int raw_value) {
+    LayoutUnit v;
+    v.value_ = raw_value;
+    return v;
+  }
+
   constexpr int ToInt() const { return value_ / kFixedPointDenominator; }
   constexpr float ToFloat() const {
     return static_cast<float>(value_) / kFixedPointDenominator;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 252a2f0c9..8168172 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -969,10 +969,6 @@
       status: "experimental",
     },
     {
-      name: "LayoutNGRubyEmHeight",
-      depends_on: ["LayoutNGRuby"],
-    },
-    {
       name: "LayoutNGTable",
     },
     {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 7a504f12..fcd6e679 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2731,24 +2731,6 @@
 crbug.com/626703 [ Mac10.10 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/service-worker/about-blank-replacement.https.html [ Timeout ]
 crbug.com/626703 [ Mac10.10 ] virtual/cache-storage-sequence/external/wpt/service-workers/service-worker/fetch-response-taint.https.html [ Timeout ]
 crbug.com/626703 [ Mac10.10 ] virtual/cache-storage-eager-reading/external/wpt/service-workers/service-worker/service-worker-csp-script.https.html [ Timeout ]
-crbug.com/626703 [ Mac10.13 ] external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.html [ Failure Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.html [ Failure Timeout ]
-crbug.com/626703 [ Mac10.15 ] external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.html [ Failure Timeout ]
-crbug.com/626703 [ Retina ] external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.html [ Failure Timeout ]
-crbug.com/626703 [ Mac10.13 ] external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc.html [ Failure Timeout ]
-crbug.com/626703 [ Mac10.15 ] external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc.html [ Failure Timeout ]
-crbug.com/626703 [ Linux ] external/wpt/streams/idlharness.any.serviceworker.html [ Timeout ]
-crbug.com/626703 [ Mac ] external/wpt/streams/idlharness.any.serviceworker.html [ Timeout ]
-crbug.com/626703 [ Win ] external/wpt/streams/idlharness.any.serviceworker.html [ Timeout ]
-crbug.com/626703 [ Linux ] external/wpt/streams/idlharness.any.sharedworker.html [ Timeout ]
-crbug.com/626703 [ Mac ] external/wpt/streams/idlharness.any.sharedworker.html [ Timeout ]
-crbug.com/626703 [ Win ] external/wpt/streams/idlharness.any.sharedworker.html [ Timeout ]
-crbug.com/626703 [ Linux ] external/wpt/streams/idlharness.any.html [ Timeout ]
-crbug.com/626703 [ Mac ] external/wpt/streams/idlharness.any.html [ Timeout ]
-crbug.com/626703 [ Win ] external/wpt/streams/idlharness.any.html [ Timeout ]
-crbug.com/626703 [ Linux ] external/wpt/streams/idlharness.any.worker.html [ Timeout ]
-crbug.com/626703 [ Mac ] external/wpt/streams/idlharness.any.worker.html [ Timeout ]
-crbug.com/626703 [ Win ] external/wpt/streams/idlharness.any.worker.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/css/css-pseudo/textpath-selection-011.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/css/css-pseudo/textpath-selection-011.html [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/css/css-pseudo/textpath-selection-011.html [ Failure ]
@@ -5344,12 +5326,16 @@
 ###crbug.com/816914 [ Mac ] fast/canvas/canvas-drawImage-live-video.html [ Failure Pass ]
 crbug.com/817167 http/tests/devtools/oopif/oopif-cookies-refresh.js [ Failure Timeout Pass ]
 
-# Disable temporarily on Win7, will remove them when they are not flaky. 
-crbug.com/1047176 [ Win7 ] fast/forms/suggestion-picker/date-suggestion-picker-mouse-operations.html [ Pass Failure ]
-crbug.com/1047176 [ Win7 ] fast/forms/suggestion-picker/datetimelocal-suggestion-picker-mouse-operations.html [ Pass Failure ]
-crbug.com/1047176 [ Win7 ] fast/forms/suggestion-picker/month-suggestion-picker-mouse-operations.html [ Pass Failure ]
-crbug.com/1047176 [ Win7 ] fast/forms/suggestion-picker/time-suggestion-picker-mouse-operations.html [ Pass Failure ]
-crbug.com/1047176 [ Win7 ] fast/forms/suggestion-picker/week-suggestion-picker-mouse-operations.html [ Pass Failure ]
+# Disable temporarily on Win7, will remove them when they are not flaky.
+crbug.com/1047176 crbug.com/1100783 [ Win7 ] fast/forms/suggestion-picker/date-suggestion-picker-mouse-operations.html [ Pass Failure Timeout ]
+crbug.com/1047176 [ Win7 ] fast/forms/suggestion-picker/datetimelocal-suggestion-picker-mouse-operations.html [ Pass Failure Timeout ]
+crbug.com/1047176 [ Win7 ] fast/forms/suggestion-picker/month-suggestion-picker-mouse-operations.html [ Pass Failure Timeout ]
+crbug.com/1047176 [ Win7 ] fast/forms/suggestion-picker/time-suggestion-picker-mouse-operations.html [ Pass Failure Timeout ]
+crbug.com/1047176 crbug.com/1100783 [ Win7 ] fast/forms/suggestion-picker/week-suggestion-picker-mouse-operations.html [ Pass Failure Timeout ]
+crbug.com/1100785 [ Win7 ] virtual/form-controls-refresh-disabled/fast/forms/suggestion-picker/month-suggestion-picker-mouse-operations.html [ Pass Failure Timeout ]
+crbug.com/1100785 [ Win7 ] virtual/form-controls-refresh-disabled/fast/forms/suggestion-picker/date-suggestion-picker-mouse-operations.html [ Pass Failure Timeout ]
+crbug.com/1100785 [ Win7 ] virtual/form-controls-refresh-disabled/fast/forms/suggestion-picker/time-suggestion-picker-mouse-operations.html [ Pass Failure Timeout ]
+crbug.com/1100785 [ Win7 ] virtual/form-controls-refresh-disabled/fast/forms/suggestion-picker/week-suggestion-picker-mouse-operations.html [ Pass Failure Timeout ]
 
 # Sheriff 2018-03-02
 crbug.com/818076 http/tests/devtools/oopif/oopif-elements-navigate-in.js [ Failure Pass ]
@@ -6600,7 +6586,6 @@
 
 crbug.com/1058888 [ Linux ] animations/animationworklet/peek-updated-composited-property-on-main.html [ Pass Failure ]
 
-crbug.com/1013523 external/wpt/html/cross-origin-embedder-policy/require-corp.https.html [ Failure Pass ]
 crbug.com/1091665 [ Debug ] external/wpt/html/cross-origin-embedder-policy/reporting-navigation.https.html [ Pass Failure ]
 
 # [virtual/...]external/wpt/web-animation test flakes
@@ -6868,3 +6853,8 @@
 
 #Sheriff 2020-06-25
 crbug.com/1010170 media/video-played-reset.html [ Pass Failure ]
+
+#Sheriff 2020-06-30
+crbug.com/1100774 [ Mac10.13 ] virtual/threaded-no-composited-antialiasing/animations/svg-attribute-interpolation/svg-d-interpolation.html [ Pass Failure ]
+crbug.com/1100786 [ Mac10.10 ] fast/scroll-snap/snaps-after-touchpad-scrolling.html [ Failure ]
+crbug.com/1100786 [ Mac10.10 ] storage/indexeddb/transaction-active-flag.html [ Timeout ]
diff --git a/third_party/blink/web_tests/accessibility/inline-text-word-boundaries-expected.txt b/third_party/blink/web_tests/accessibility/inline-text-word-boundaries-expected.txt
deleted file mode 100644
index d204d02b..0000000
--- a/third_party/blink/web_tests/accessibility/inline-text-word-boundaries-expected.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-Ace ten twenty-one thirty-five. xxxxxxxxxxxxxxxxxxx
-
-Tests that we can compute word boundaries for any character index from the accessibility tree.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-Accessible text: "Ace ten twenty-one thirty-five. xxxxxxxxxxxxxxxxxxx"
-Character 0: 'A' word=(0, 3): 'Ace'
-Character 1: 'c' word=(0, 3): 'Ace'
-Character 2: 'e' word=(0, 3): 'Ace'
-Character 3: ' ' word=(0, 3): 'Ace'
-Character 4: 't' word=(4, 7): 'ten'
-Character 5: 'e' word=(4, 7): 'ten'
-Character 6: 'n' word=(4, 7): 'ten'
-Character 7: ' ' word=(4, 7): 'ten'
-Character 8: 't' word=(8, 14): 'twenty'
-Character 9: 'w' word=(8, 14): 'twenty'
-Character 10: 'e' word=(8, 14): 'twenty'
-Character 11: 'n' word=(8, 14): 'twenty'
-Character 12: 't' word=(8, 14): 'twenty'
-Character 13: 'y' word=(8, 14): 'twenty'
-Character 14: '-' word=(8, 14): 'twenty'
-Character 15: 'o' word=(15, 18): 'one'
-Character 16: 'n' word=(15, 18): 'one'
-Character 17: 'e' word=(15, 18): 'one'
-Character 18: ' ' word=(15, 18): 'one'
-Character 19: 't' word=(19, 25): 'thirty'
-Character 20: 'h' word=(19, 25): 'thirty'
-Character 21: 'i' word=(19, 25): 'thirty'
-Character 22: 'r' word=(19, 25): 'thirty'
-Character 23: 't' word=(19, 25): 'thirty'
-Character 24: 'y' word=(19, 25): 'thirty'
-Character 25: '-' word=(19, 25): 'thirty'
-Character 26: 'f' word=(26, 30): 'five'
-Character 27: 'i' word=(26, 30): 'five'
-Character 28: 'v' word=(26, 30): 'five'
-Character 29: 'e' word=(26, 30): 'five'
-Character 30: '.' word=(26, 30): 'five'
-Character 31: ' ' word=(26, 30): 'five'
-Character 32: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 33: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 34: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 35: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 36: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 37: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 38: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 39: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 40: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 41: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 42: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 43: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 44: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 45: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 46: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 47: 'x' word=(32, 48): 'xxxxxxxxxxxxxxxx'
-Character 48: 'x' word=(48, 51): 'xxx'
-Character 49: 'x' word=(48, 51): 'xxx'
-Character 50: 'x' word=(48, 51): 'xxx'
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/blink/web_tests/accessibility/inline-text-word-boundaries.html b/third_party/blink/web_tests/accessibility/inline-text-word-boundaries.html
deleted file mode 100644
index 8bc5cbe..0000000
--- a/third_party/blink/web_tests/accessibility/inline-text-word-boundaries.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<meta charset="utf-8">
-<script src="../resources/js-test.js"></script>
-</head>
-<body>
-
-<!-- Note: the xxxxxx... should wrap onto another line on all platforms. -->
-<p id="paragraph" style="width: 8em; word-wrap: break-word;">
-Ace ten twenty-one thirty-five. xxxxxxxxxxxxxxxxxxx
-</p>
-
-<p id="description"></p>
-
-<div id="console"></div>
-
-<script>
-
-    description("Tests that we can compute word boundaries for any character index from the accessibility tree.");
-
-    // Note: all that matters is that characters within actual words are mapped correctly.
-    // Whether a character between words is mapped to the previous or next word is arbitrary;
-    // all that matters is that we expose the start and end of real words.
-    if (window.accessibilityController) {
-        var axParagraph = accessibilityController.accessibleElementById('paragraph');
-        var axStaticText = axParagraph.childAtIndex(0);
-        var text = axStaticText.name;
-        debug("Accessible text: \"" + text + "\"");
-
-        for (var i = 0; i < text.length; i++) {
-            // Get the bounds from the accessibility tree.
-            var wordStart = axStaticText.wordStart(i);
-            var wordEnd = axStaticText.wordEnd(i);
-            debug("Character " + i + ": '" + text.substr(i, 1) +
-                  "' word=(" + wordStart + ", " + wordEnd + "): '" +
-                  text.substr(wordStart, wordEnd - wordStart) + "'");
-        }
-    }
-</script>
-
-</body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank-expected.txt
deleted file mode 100644
index ece776d..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-PASS Wait for the DOM to be built.
-PASS about:blank can always be embedded by a 'require-corp' document
-FAIL A(B(C)) A=require-corp, B=about:blank, C=no-require-corp => C can't load wait_for: Timed out waiting on condition
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.https.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.html
rename to third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.https.html
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.html.headers b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.https.html.headers
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.html.headers
rename to third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.https.html.headers
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc-expected.txt
deleted file mode 100644
index 03c7949..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-PASS Wait for the DOM to be built.
-PASS about:srcdoc can always be embedded by a 'require-corp' document
-FAIL A(B(C)) A=require-corp, B=about:srcdoc, C=no-require-corp => C can't load wait_for: Timed out waiting on condition
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc.html.headers b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc.html.headers
deleted file mode 100644
index 8df9847..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc.html.headers
+++ /dev/null
@@ -1 +0,0 @@
-cross-origin-embedder-policy: require-corp
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc.html
rename to third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.html.headers b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html.headers
similarity index 100%
copy from third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank.html.headers
copy to third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/require-corp-about-srcdoc.https.html.headers
diff --git a/third_party/blink/web_tests/fast/ruby/ruby-position-modern-japanese-fonts-expected.png b/third_party/blink/web_tests/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
deleted file mode 100644
index e076a4f1..0000000
--- a/third_party/blink/web_tests/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/base-shorter-than-text-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/base-shorter-than-text-expected.png
new file mode 100644
index 0000000..8e6b165
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/base-shorter-than-text-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-empty-rt-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-empty-rt-expected.png
new file mode 100644
index 0000000..5741ae18
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-empty-rt-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-simple-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-simple-expected.png
new file mode 100644
index 0000000..9109735
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-simple-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-simple-rp-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-simple-rp-expected.png
new file mode 100644
index 0000000..ffea2af
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-simple-rp-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-trailing-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-trailing-expected.png
new file mode 100644
index 0000000..2bd3d3c
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/ruby-trailing-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/css/bidi-override-in-anonymous-block-expected.png b/third_party/blink/web_tests/platform/linux/fast/css/bidi-override-in-anonymous-block-expected.png
index 27c9b03..ccc08b7 100644
--- a/third_party/blink/web_tests/platform/linux/fast/css/bidi-override-in-anonymous-block-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/css/bidi-override-in-anonymous-block-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/base-shorter-than-text-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/base-shorter-than-text-expected.png
index 8e6b165..fc96f8b 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/base-shorter-than-text-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/base-shorter-than-text-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/nested-ruby-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/nested-ruby-expected.png
index 2d43359..69e1ddf 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/nested-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/nested-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-empty-rt-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-empty-rt-expected.png
index 5741ae18..e2b80e5c0 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-empty-rt-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-empty-rt-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-length-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-length-expected.png
index 087843f..497bcc1 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-length-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-length-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-position-modern-japanese-fonts-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
index 1640aff..49f6e616 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-run-break-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-run-break-expected.png
index 45a1376..0c46e3d2 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-run-break-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-run-break-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-runs-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-runs-expected.png
index 46b2b4b..ddf3dba 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-runs-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-runs-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-runs-spans-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-runs-spans-expected.png
index 9156572..ce8bf52 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-runs-spans-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-runs-spans-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-simple-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-simple-expected.png
index 9109735..bebf5a3 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-simple-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-simple-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-simple-rp-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-simple-rp-expected.png
index ffea2af..03f01c5 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-simple-rp-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-simple-rp-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-text-before-after-content-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-text-before-after-content-expected.png
index 280773b4..d274042b 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-text-before-after-content-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-text-before-after-content-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-trailing-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-trailing-expected.png
index 2bd3d3c..397edc76 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-trailing-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/ruby-trailing-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/writing-mode/japanese-ruby-vertical-lr-expected.png b/third_party/blink/web_tests/platform/linux/fast/writing-mode/japanese-ruby-vertical-lr-expected.png
index 0c5e66b0..f447f94 100644
--- a/third_party/blink/web_tests/platform/linux/fast/writing-mode/japanese-ruby-vertical-lr-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/writing-mode/japanese-ruby-vertical-lr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/writing-mode/japanese-ruby-vertical-rl-expected.png b/third_party/blink/web_tests/platform/linux/fast/writing-mode/japanese-ruby-vertical-rl-expected.png
index 9356107..0709912 100644
--- a/third_party/blink/web_tests/platform/linux/fast/writing-mode/japanese-ruby-vertical-rl-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/writing-mode/japanese-ruby-vertical-rl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/ruby/nested-ruby-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/ruby/nested-ruby-expected.png
index 5fe5a88..7e21936 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/fast/ruby/nested-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/ruby/nested-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/ruby/ruby-position-modern-japanese-fonts-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
index 82f370a..29e4a91 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/fast/ruby/nested-ruby-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/fast/ruby/nested-ruby-expected.png
index 8b7a7cf..936af7e 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/fast/ruby/nested-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/fast/ruby/nested-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/css/bidi-override-in-anonymous-block-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/css/bidi-override-in-anonymous-block-expected.png
new file mode 100644
index 0000000..79494bb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/css/bidi-override-in-anonymous-block-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/ruby/nested-ruby-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/ruby/nested-ruby-expected.png
index df3fadb6..d75397a 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/ruby/nested-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/ruby/nested-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/ruby/ruby-text-before-after-content-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/ruby/ruby-text-before-after-content-expected.png
index 5bfdbfc6c..148efebc 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/ruby/ruby-text-before-after-content-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/ruby/ruby-text-before-after-content-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank-expected.txt
deleted file mode 100644
index ece776d..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-PASS Wait for the DOM to be built.
-PASS about:blank can always be embedded by a 'require-corp' document
-FAIL A(B(C)) A=require-corp, B=about:blank, C=no-require-corp => C can't load wait_for: Timed out waiting on condition
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/fast/ruby/nested-ruby-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/fast/ruby/nested-ruby-expected.png
index 4140130..d11dc3f 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/fast/ruby/nested-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/fast/ruby/nested-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank-expected.txt
deleted file mode 100644
index 1fbd9f6..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/html/cross-origin-embedder-policy/require-corp-about-blank-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-Content-Type: text/plain
-This is a testharness.js-based test.
-PASS Wait for the DOM to be built.
-PASS about:blank can always be embedded by a 'require-corp' document
-FAIL A(B(C)) A=require-corp, B=about:blank, C=no-require-corp => C can't load wait_for: Timed out waiting on condition
-Harness: the test ran to completion.
-
-#EOF
-#EOF
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/fast/ruby/nested-ruby-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/fast/ruby/nested-ruby-expected.png
index d28d0175..496e5a1 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/fast/ruby/nested-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/fast/ruby/nested-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/css/bidi-override-in-anonymous-block-expected.png b/third_party/blink/web_tests/platform/mac/fast/css/bidi-override-in-anonymous-block-expected.png
index 79494bb..19859b2 100644
--- a/third_party/blink/web_tests/platform/mac/fast/css/bidi-override-in-anonymous-block-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/css/bidi-override-in-anonymous-block-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/nested-ruby-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/nested-ruby-expected.png
index 3133ada1..8ce4780 100644
--- a/third_party/blink/web_tests/platform/mac/fast/ruby/nested-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/nested-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-empty-rt-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-empty-rt-expected.png
index 26cf2d50..388006e 100644
--- a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-empty-rt-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-empty-rt-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-length-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-length-expected.png
index a8415f3..b6149e32 100644
--- a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-length-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-length-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-position-modern-japanese-fonts-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
new file mode 100644
index 0000000..213acd4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-run-break-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-run-break-expected.png
index 6d6546c4..39aa5ae 100644
--- a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-run-break-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-run-break-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-runs-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-runs-expected.png
index 2d3cda24..64d4525 100644
--- a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-runs-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-runs-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-runs-spans-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-runs-spans-expected.png
index cd6ffe6..892c62e 100644
--- a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-runs-spans-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-runs-spans-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-simple-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-simple-expected.png
index 7b25fe3f..2b54d387 100644
--- a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-simple-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-simple-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-simple-rp-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-simple-rp-expected.png
index 10fca63..a37484e7 100644
--- a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-simple-rp-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-simple-rp-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-text-before-after-content-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-text-before-after-content-expected.png
index 90a744e..08392ca3 100644
--- a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-text-before-after-content-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-text-before-after-content-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-trailing-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-trailing-expected.png
index c682ec26..9fc5237 100644
--- a/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-trailing-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/ruby-trailing-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png
index a485f1b..c8719b7 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/nested-ruby-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/nested-ruby-expected.png
index d8e4f5e..226e4af 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/nested-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/nested-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-empty-rt-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-empty-rt-expected.png
index a8cde14..1be5049 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-empty-rt-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-empty-rt-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-length-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-length-expected.png
index ad36b6b..0d12450 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-length-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-length-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-position-modern-japanese-fonts-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
index ae78dad..a927dbf 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-position-modern-japanese-fonts-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-run-break-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-run-break-expected.png
index adfb17c..633139aa 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-run-break-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-run-break-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-runs-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-runs-expected.png
index 0b639ca..40b3b05 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-runs-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-runs-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-runs-spans-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-runs-spans-expected.png
index 88dbf37..ee3527f 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-runs-spans-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-runs-spans-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-simple-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-simple-expected.png
index a0beed7..ff2926c 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-simple-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-simple-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-simple-rp-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-simple-rp-expected.png
index 18ca8a5b..56fc363 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-simple-rp-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-simple-rp-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-text-before-after-content-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-text-before-after-content-expected.png
index 9e08006..e98de98 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-text-before-after-content-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-text-before-after-content-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-trailing-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-trailing-expected.png
index 03a4548..d13c0bc1 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/ruby-trailing-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/ruby-trailing-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-lr-expected.png b/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-lr-expected.png
index 58fc3471..e86f31c 100644
--- a/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-lr-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-lr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-rl-expected.png b/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-rl-expected.png
index 0190774..4bcac6aa 100644
--- a/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-rl-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-rl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/ruby/base-shorter-than-text-expected.png b/third_party/blink/web_tests/platform/win7/fast/ruby/base-shorter-than-text-expected.png
index f9461a7..68597b5 100644
--- a/third_party/blink/web_tests/platform/win7/fast/ruby/base-shorter-than-text-expected.png
+++ b/third_party/blink/web_tests/platform/win7/fast/ruby/base-shorter-than-text-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/ruby/nested-ruby-expected.png b/third_party/blink/web_tests/platform/win7/fast/ruby/nested-ruby-expected.png
index 39f1927..39a9e30 100644
--- a/third_party/blink/web_tests/platform/win7/fast/ruby/nested-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/win7/fast/ruby/nested-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-lr-expected.png b/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-lr-expected.png
index 765fae82..470c094 100644
--- a/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-lr-expected.png
+++ b/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-lr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-rl-expected.png b/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-rl-expected.png
index ba74600..ff12619 100644
--- a/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-rl-expected.png
+++ b/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-rl-expected.png
Binary files differ
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index a4cbd2d..9f8ce67a 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -13656,11 +13656,23 @@
 </enum>
 
 <enum name="CrostiniFailureClasses">
-  <int value="0" label="Concierge stopped"/>
-  <int value="1" label="Cicerone stopped"/>
-  <int value="2" label="Seneschal stopped"/>
-  <int value="3" label="Chunneld stopped"/>
-  <int value="4" label="VM hypervisor stopped"/>
+  <int value="0" label="Concierge"/>
+  <int value="1" label="Cicerone"/>
+  <int value="2" label="Seneschal"/>
+  <int value="3" label="Chunneld"/>
+  <int value="4" label="VM hypervisor"/>
+  <int value="5" label="In-VM syslog daemon"/>
+  <int value="6" label="VM ssh daemon"/>
+  <int value="7" label="LXCFS daemon"/>
+  <int value="8" label="Tremplin"/>
+  <int value="9" label="Ndproxyd"/>
+  <int value="10" label="Mcastd"/>
+  <int value="11" label="Lxd"/>
+  <int value="12" label="Garcon"/>
+  <int value="13" label="Sommelier wayland proxy"/>
+  <int value="14" label="Sommelier X11 proxy"/>
+  <int value="15" label="Cros-Sftp"/>
+  <int value="16" label="Cros-Notificationd"/>
 </enum>
 
 <enum name="CrostiniImportContainerResult">
@@ -39074,6 +39086,11 @@
   <int value="1" label="SinkNeverStarted"/>
 </enum>
 
+<enum name="LocalSearchServiceBackend">
+  <int value="0" label="LinearMap"/>
+  <int value="1" label="InvertedIndex"/>
+</enum>
+
 <enum name="LocalSearchServiceResponseStatus">
   <int value="0" label="UnknownError"/>
   <int value="1" label="Success"/>
@@ -39458,6 +39475,7 @@
   <int value="-1940377152" label="MacRTL:enabled"/>
   <int value="-1940291343" label="SpeculativeResourcePrefetching:enabled"/>
   <int value="-1939533266" label="LauncherSettingsSearch:enabled"/>
+  <int value="-1939525844" label="AssistantTimersV2:enabled"/>
   <int value="-1939016096"
       label="OmniboxUIExperimentHideSuggestionUrlTrivialSubdomains:enabled"/>
   <int value="-1939003674" label="NetworkServiceInProcess:disabled"/>
@@ -40108,6 +40126,7 @@
   <int value="-1255427595" label="HomePageButtonForceEnabled:enabled"/>
   <int value="-1254640444"
       label="OmniboxEnableClipboardProviderTextSuggestions:disabled"/>
+  <int value="-1254221389" label="AssistantBetterOnboarding:enabled"/>
   <int value="-1254070521" label="enable-slimming-paint-invalidation"/>
   <int value="-1253608371" label="IncognitoStrings:disabled"/>
   <int value="-1252976780" label="ShillSandboxing:disabled"/>
@@ -40335,6 +40354,7 @@
   <int value="-1027254093" label="LockScreenNotifications:disabled"/>
   <int value="-1027124889" label="NtlmV2Enabled:enabled"/>
   <int value="-1026192558" label="OopRasterizationDDL:enabled"/>
+  <int value="-1025125875" label="AssistantTimersV2:disabled"/>
   <int value="-1022971520" label="enable-search-button-in-omnibox-for-str"/>
   <int value="-1022165708" label="BreakingNewsPush:disabled"/>
   <int value="-1021097344" label="PolicyAtomicGroup:disabled"/>
@@ -41023,6 +41043,7 @@
   <int value="-262122630" label="ArcEnableDocumentsProviderInFilesApp:enabled"/>
   <int value="-258081634" label="AutofillAssistantDirectActions:disabled"/>
   <int value="-257478609" label="TextfieldFocusOnTapUp:enabled"/>
+  <int value="-256940675" label="HelpAppSearchServiceIntegration:disabled"/>
   <int value="-255264176" label="OmniboxSearchEngineLogo:disabled"/>
   <int value="-254887599" label="google-profile-info"/>
   <int value="-254158542" label="SubresourceRedirectPreviews:enabled"/>
@@ -42404,6 +42425,7 @@
   <int value="1284910808" label="disable-checker-imaging"/>
   <int value="1285905715" label="WebXRHitTest:enabled"/>
   <int value="1289433604" label="RecoverFromNeverSaveAndroid:enabled"/>
+  <int value="1289495171" label="AssistantBetterOnboarding:disabled"/>
   <int value="1291257442" label="TabsInCBD:disabled"/>
   <int value="1291761696" label="CCTModuleDexLoading:disabled"/>
   <int value="1291966558" label="ScrollAnchoring:disabled"/>
@@ -43154,6 +43176,7 @@
   <int value="2113804526" label="EnableAppShortcutSearch:enabled"/>
   <int value="2114843059" label="ContextualSuggestionsOptOut:enabled"/>
   <int value="2115848376" label="LacrosSupport:disabled"/>
+  <int value="2118287149" label="HelpAppSearchServiceIntegration:enabled"/>
   <int value="2119964154" label="enable-download-resumption"/>
   <int value="2120659210" label="BackForwardCache:enabled"/>
   <int value="2121056855" label="IncreaseInputAudioBufferSize:disabled"/>
@@ -51687,6 +51710,7 @@
   <int value="501" label="Ambient Mode On/Off"/>
   <int value="502" label="Ambient Mode Source"/>
   <int value="503" label="Change Device Account Image"/>
+  <int value="504" label="Ambient Mode Update Photos Containers"/>
   <int value="600" label="Preferred Search Engine"/>
   <int value="601" label="Assistant: On/Off"/>
   <int value="602" label="Assistant: Related Info"/>
@@ -51843,6 +51867,7 @@
   <int value="407" label="Power"/>
   <int value="500" label="Change Picture"/>
   <int value="501" label="Ambient Mode"/>
+  <int value="502" label="Ambient Mode Photos"/>
   <int value="600" label="Assistant"/>
   <int value="700" label="App Management"/>
   <int value="701" label="App Details"/>
@@ -73404,6 +73429,23 @@
   <int value="1" label="NotVisible"/>
 </enum>
 
+<enum name="WelcomeScreenA11yUserAction">
+  <int value="0" label="Enable spoken feedback"/>
+  <int value="1" label="Disable spoken feedback"/>
+  <int value="2" label="Enable large cursor"/>
+  <int value="3" label="Disable large cursor"/>
+  <int value="4" label="Enable high contrast"/>
+  <int value="5" label="Disable high contrast"/>
+  <int value="6" label="Enable screen magnifier"/>
+  <int value="7" label="Disable screen magnifier"/>
+  <int value="8" label="Enable select to speak option"/>
+  <int value="9" label="Disable select to speak option"/>
+  <int value="10" label="Enable docked magnifier"/>
+  <int value="11" label="Disable docked magnifier"/>
+  <int value="12" label="Enable virtual keyboard"/>
+  <int value="13" label="Disable virtual keyboard"/>
+</enum>
+
 <enum name="WelcomeSignInPromptOutcome">
   <int value="0" label="User navigated away from page"/>
   <int value="1" label="User clicked the 'Get Started' button"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index b93f01cb..f2589789 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -74022,6 +74022,20 @@
   </summary>
 </histogram>
 
+<histogram name="LocalSearchService.Backend" enum="LocalSearchServiceBackend"
+    expires_after="2020-11-30">
+<!-- Name completed by histogram_suffixes name="IndexId" -->
+
+  <owner>jiameng@chromium.org</owner>
+  <owner>tby@chromium.org</owner>
+  <owner>thanhdng@chromium.org</owner>
+  <owner>wrong@chromium.org</owner>
+  <summary>
+    Type of backend requested from the Local Search Service. It is reported once
+    at the initialization of an Index. Chrome OS only.
+  </summary>
+</histogram>
+
 <histogram name="LocalSearchService.DailySearch" units="count"
     expires_after="2020-11-30">
 <!-- Name completed by histogram_suffixes name="IndexId" -->
@@ -115801,6 +115815,17 @@
   </summary>
 </histogram>
 
+<histogram name="OOBE.WelcomeScreen.A11yUserActions"
+    enum="WelcomeScreenA11yUserAction" expires_after="2021-01-31">
+  <owner>dkuzmin@google.com</owner>
+  <owner>cros-oac@google.com</owner>
+  <summary>
+    Measures usage of the accessibility options on the welcome screen during
+    OOBE. Recorded when user enables or disables any of the accessibility
+    options from accessibility menu on the welcome screen.
+  </summary>
+</histogram>
+
 <histogram base="true" name="OptimizationGuide.ApplyDecision"
     enum="OptimizationGuideOptimizationTypeDecision" expires_after="2020-11-30">
   <owner>sophiechang@chromium.org</owner>
@@ -190726,6 +190751,17 @@
   </summary>
 </histogram>
 
+<histogram name="WebRTC.MediaStreamDevices.HasPanTiltZoomCamera"
+    enum="BooleanAvailable" expires_after="M88">
+  <owner>reillyg@chromium.org</owner>
+  <owner>device-dev@chromium.org</owner>
+  <summary>
+    Records whether a user would potentially see a permission prompt for moving
+    the camera. It is recorded when showing a camera permission prompt
+    regardless of whether or not the site requested camera movement.
+  </summary>
+</histogram>
+
 <histogram name="WebRTC.NAT.Metrics" enum="NatTypeCounters" expires_after="M85">
   <owner>guoweis@chromium.org</owner>
   <summary>
@@ -201759,6 +201795,7 @@
 
 <histogram_suffixes name="IndexId" separator="." ordering="prefix,1">
   <suffix name="CrosSettings" label="Cros Settings"/>
+  <affected-histogram name="LocalSearchService.Backend"/>
   <affected-histogram name="LocalSearchService.DailySearch"/>
   <affected-histogram name="LocalSearchService.NumberResults"/>
   <affected-histogram name="LocalSearchService.ResponseStatus"/>
diff --git a/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js b/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js
index d198bb2..c4d3990 100644
--- a/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js
+++ b/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js
@@ -796,57 +796,86 @@
     };
 
 /**
- * Sends a drag'n'drop set of events from |srcTarget| to |dstTarget|.
+ * Sends drag and drop events to simulate dragging a source over a target.
  *
  * @param {Window} contentWindow Window to be tested.
- * @param {string} srcTarget Query to specify the element as the source to be
- *   dragged.
- * @param {string} dstTarget Query to specify the element as the destination
- *   to drop.
- * @param {boolean=} skipDrop True if it should only hover over dstTarget.
- *   to drop.
- * @return {boolean} True if the event is sent to the target, false otherwise.
+ * @param {string} sourceQuery Query to specify the source element.
+ * @param {string} targetQuery Query to specify the target element.
+ * @param {boolean} skipDrop Set true to drag over (hover) the target
+ *    element only, and not send it drop and dragEnd events.
+ * @param {function(boolean)} callback Function called with result
+ *    true on success, or false on failure.
  */
-test.util.sync.fakeDragAndDrop =
-    (contentWindow, srcTarget, dstTarget, skipDrop) => {
-      const options = {
+test.util.async.fakeDragAndDrop =
+    (contentWindow, sourceQuery, targetQuery, skipDrop, callback) => {
+      const source = contentWindow.document.querySelector(sourceQuery);
+      const target = contentWindow.document.querySelector(targetQuery);
+
+      if (!source || !target) {
+        setTimeout(() => {
+          callback(false);
+        }, 0);
+        return;
+      }
+
+      const targetOptions = {
         bubbles: true,
         composed: true,
         dataTransfer: new DataTransfer(),
       };
-      const srcElement = contentWindow.document &&
-          contentWindow.document.querySelector(srcTarget);
-      const dstElement = contentWindow.document &&
-          contentWindow.document.querySelector(dstTarget);
 
-      if (!srcElement || !dstElement) {
-        return false;
+      // Get the middle of the source element since some of Files app
+      // logic requires clientX and clientY.
+      const sourceRect = source.getBoundingClientRect();
+      const sourceOptions = Object.assign({}, targetOptions);
+      sourceOptions.clientX = sourceRect.left + (sourceRect.width / 2);
+      sourceOptions.clientY = sourceRect.top + (sourceRect.height / 2);
+
+      let dragEventPhase = 0;
+      let event = null;
+
+      function sendPhasedDragDropEvents() {
+        let result = true;
+        switch (dragEventPhase) {
+          case 0:
+            event = new DragEvent('dragstart', sourceOptions);
+            result = source.dispatchEvent(event);
+            break;
+          case 1:
+            event = new DragEvent('dragenter', targetOptions);
+            result = target.dispatchEvent(event);
+            break;
+          case 2:
+            event = new DragEvent('dragover', targetOptions);
+            result = target.dispatchEvent(event);
+            break;
+          case 3:
+            if (!skipDrop) {
+              event = new DragEvent('drop', targetOptions);
+              result = target.dispatchEvent(event);
+            }
+            break;
+          case 4:
+            if (!skipDrop) {
+              event = new DragEvent('dragEnd', sourceOptions);
+              result = source.dispatchEvent(event);
+            }
+            break;
+          default:
+            result = false;
+            break;
+        }
+
+        if (!result) {
+          callback(false);
+        } else if (++dragEventPhase <= 4) {
+          contentWindow.requestIdleCallback(sendPhasedDragDropEvents);
+        } else {
+          callback(true);
+        }
       }
 
-      // Get the middle of the src element, because some of Files app logic
-      // requires clientX and clientY.
-      const srcRect = srcElement.getBoundingClientRect();
-      const srcOptions = Object.assign(
-          {
-            clientX: srcRect.left + (srcRect.width / 2),
-            clientY: srcRect.top + (srcRect.height / 2),
-          },
-          options);
-
-      const dragStart = new DragEvent('dragstart', srcOptions);
-      const dragEnter = new DragEvent('dragenter', options);
-      const dragOver = new DragEvent('dragover', options);
-      const drop = new DragEvent('drop', options);
-      const dragEnd = new DragEvent('dragEnd', options);
-
-      srcElement.dispatchEvent(dragStart);
-      dstElement.dispatchEvent(dragEnter);
-      dstElement.dispatchEvent(dragOver);
-      if (!skipDrop) {
-        dstElement.dispatchEvent(drop);
-      }
-      srcElement.dispatchEvent(dragEnd);
-      return true;
+      sendPhasedDragDropEvents();
     };
 
 /**
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html
index efe64839..06ebae28 100644
--- a/ui/file_manager/file_manager/main.html
+++ b/ui/file_manager/file_manager/main.html
@@ -184,7 +184,7 @@
         <cr-menu-item command="#open-with"
                   visibleif="full-page" class="hide-on-toolbar" sub-menu="#tasks-menu" hidden></cr-menu-item>
         <cr-menu-item command="#more-actions"
-                  visibleif="full-page" class="hide-on-toolbar" sub-menu="#share-sub-menu" hidden></cr-menu-item>
+                  visibleif="full-page" class="hide-on-toolbar" sub-menu="#share-menu" hidden></cr-menu-item>
         <cr-menu-item command="#go-to-file-location"
                   visibleif="full-page" class="hide-on-toolbar" hidden></cr-menu-item>
         <hr id="tasks-separator" visibleif="full-page" class="hide-on-toolbar" hidden>
diff --git a/ui/file_manager/integration_tests/file_manager/transfer.js b/ui/file_manager/integration_tests/file_manager/transfer.js
index 8bad6ae..1fe7afa 100644
--- a/ui/file_manager/integration_tests/file_manager/transfer.js
+++ b/ui/file_manager/integration_tests/file_manager/transfer.js
@@ -517,8 +517,10 @@
       'fakeMouseClick failed');
 
   // Drag and drop it.
+  const skipDrop = false;
   chrome.test.assertTrue(
-      await remoteCall.callRemoteTestUtil('fakeDragAndDrop', appId, [src, dst]),
+      await remoteCall.callRemoteTestUtil(
+          'fakeDragAndDrop', appId, [src, dst, skipDrop]),
       'fakeDragAndDrop failed');
 
   // Navigate to the dst folder.
diff --git a/ui/login/display_manager.js b/ui/login/display_manager.js
index c51ca09..a57441e 100644
--- a/ui/login/display_manager.js
+++ b/ui/login/display_manager.js
@@ -124,17 +124,6 @@
   ];
 
   /**
-   * Group of screens (screen IDs) that are not participating in
-   * left-current-right animation.
-   * @type Array<string>
-   * @const
-   */
-  var NOT_ANIMATED_SCREEN_GROUP = [
-    SCREEN_OOBE_ENABLE_DEBUGGING,
-    SCREEN_OOBE_RESET,
-  ];
-
-  /**
    * As Polymer behaviors do not provide true inheritance, when two behaviors
    * would declare same method one of them will be hidden. Also, if element
    * re-declares the method it needs explicitly iterate over behaviors and call
@@ -488,35 +477,6 @@
       }
     },
 
-    screenIsAnimated_: function(screenId) {
-      return NOT_ANIMATED_SCREEN_GROUP.indexOf(screenId) != -1;
-    },
-
-    /**
-     * Updates a step's css classes to reflect left, current, or right position.
-     * @param {number} stepIndex step index.
-     * @param {string} state one of 'left', 'current', 'right'.
-     */
-    updateStep_: function(stepIndex, state) {
-      var stepId = this.screens_[stepIndex];
-      var step = $(stepId);
-      var header = $('header-' + stepId);
-      var states = ['left', 'right', 'current'];
-      for (var i = 0; i < states.length; ++i) {
-        if (states[i] != state) {
-          step.classList.remove(states[i]);
-          if (header) {
-            header.classList.remove(states[i]);
-          }
-        }
-      }
-
-      step.classList.add(state);
-      if (header) {
-        header.classList.add(state);
-      }
-    },
-
     /**
      * Switches to the next OOBE step.
      * @param {number} nextStepIndex Index of the next step.
@@ -565,32 +525,9 @@
 
       newStep.classList.remove('hidden');
 
-      var currentIsAnimated = !currentStepAttributes.noAnimatedTransition &&
-                              this.screenIsAnimated_(currentStepId);
-      var newIsAnimated = !newStepAttributes.noAnimatedTransition &&
-                          this.screenIsAnimated_(nextStepId);
-
-      if (this.isOobeUI() && currentIsAnimated && newIsAnimated) {
-        // Start gliding animation for OOBE steps.
-        if (nextStepIndex > this.currentStep_) {
-          for (var i = this.currentStep_; i < nextStepIndex; ++i)
-            this.updateStep_(i, 'left');
-          this.updateStep_(nextStepIndex, 'current');
-        } else if (nextStepIndex < this.currentStep_) {
-          for (var i = this.currentStep_; i > nextStepIndex; --i)
-            this.updateStep_(i, 'right');
-          this.updateStep_(nextStepIndex, 'current');
-        }
-      } else {
-        // Start fading animation for login display or reset screen.
-        oldStep.classList.add('faded');
-        newStep.classList.remove('faded');
-        if (newStepAttributes.noAnimatedTransition ||
-            !this.screenIsAnimated_(nextStepId)) {
-          newStep.classList.remove('left');
-          newStep.classList.remove('right');
-        }
-      }
+      // Start fading animation for login display or reset screen.
+      oldStep.classList.add('faded');
+      newStep.classList.remove('faded');
 
       this.disableButtons_(newStep, false);
 
@@ -605,30 +542,10 @@
       var isOOBE = this.isOobeUI();
       if (this.currentStep_ != nextStepIndex &&
           !oldStep.classList.contains('hidden')) {
-        if (oldStep.classList.contains('animated')) {
-          innerContainer.classList.add('animation');
-          oldStep.addEventListener('transitionend', function f(e) {
-            oldStep.removeEventListener('transitionend', f);
-            if (oldStep.classList.contains('faded') ||
-                oldStep.classList.contains('left') ||
-                oldStep.classList.contains('right')) {
-              innerContainer.classList.remove('animation');
-              oldStep.classList.add('hidden');
-              if (!isOOBE)
-                oldStep.hidden = true;
-            }
-            // Refresh defaultControl. It could have changed.
-            var defaultControl = newStep.defaultControl;
-            if (defaultControl)
-              defaultControl.focus();
-          });
-          ensureTransitionEndEvent(oldStep, MAX_SCREEN_TRANSITION_DURATION);
-        } else {
-          oldStep.classList.add('hidden');
-          oldStep.hidden = true;
-          if (defaultControl)
-            defaultControl.focus();
-        }
+        oldStep.classList.add('hidden');
+        oldStep.hidden = true;
+        if (defaultControl)
+          defaultControl.focus();
       } else {
         // First screen on OOBE launch.
         if (this.isOobeUI() && innerContainer.classList.contains('down')) {
@@ -868,12 +785,6 @@
      * Prepares screens to use in login display.
      */
     prepareForLoginDisplay_: function() {
-      for (var i = 0, screenId; screenId = this.screens_[i]; ++i) {
-        var screen = $(screenId);
-        screen.classList.add('faded');
-        screen.classList.remove('right');
-        screen.classList.remove('left');
-      }
       if (this.showingViewsLogin) {
         $('top-header-bar').hidden = true;
       }
diff --git a/ui/login/display_manager_types.js b/ui/login/display_manager_types.js
index 54ace1e..d94b11a 100644
--- a/ui/login/display_manager_types.js
+++ b/ui/login/display_manager_types.js
@@ -11,7 +11,6 @@
  * @typedef {{
  *   enableDebuggingAllowed: (boolean|undefined),
  *   enterDemoModeAllowed: (boolean|undefined),
- *   noAnimatedTransition: (boolean|undefined),
  *   postponeEnrollmentAllowed: (boolean|undefined),
  *   resetAllowed: (boolean|undefined),
  *   startEnrollmentAllowed: (boolean|undefined),
@@ -34,12 +33,6 @@
 DisplayManagerScreenAttributes.enterDemoModeAllowed;
 
 /**
- * True if screen does not use left-current-right animation.
- * @type {boolean|undefined}
- */
-DisplayManagerScreenAttributes.noAnimatedTransition;
-
-/**
  * True if enrollment accelerator should schedule postponed enrollment.
  * @type {boolean|undefined}
  */
diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn
index 4621469..1679469 100644
--- a/weblayer/browser/java/BUILD.gn
+++ b/weblayer/browser/java/BUILD.gn
@@ -9,7 +9,6 @@
 
 android_resources("weblayer_resources") {
   sources = [
-    "res/drawable/weblayer_infobar_wrapper_bg.xml",
     "res/drawable/weblayer_tab_indicator.xml",
     "res/layout/site_settings_layout.xml",
     "res/layout/weblayer_infobar_translate_compact_content.xml",
@@ -97,7 +96,6 @@
     "org/chromium/weblayer_private/InfoBarContainer.java",
     "org/chromium/weblayer_private/InfoBarContainerLayout.java",
     "org/chromium/weblayer_private/InfoBarContainerView.java",
-    "org/chromium/weblayer_private/InfoBarWrapper.java",
     "org/chromium/weblayer_private/IntentUtils.java",
     "org/chromium/weblayer_private/InterceptNavigationDelegateClientImpl.java",
     "org/chromium/weblayer_private/LocaleChangedBroadcastReceiver.java",
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/InfoBarContainerLayout.java b/weblayer/browser/java/org/chromium/weblayer_private/InfoBarContainerLayout.java
index d33f258..59e31416 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/InfoBarContainerLayout.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/InfoBarContainerLayout.java
@@ -19,6 +19,7 @@
 import android.widget.FrameLayout;
 
 import org.chromium.components.infobars.InfoBarUiItem;
+import org.chromium.components.infobars.InfoBarWrapper;
 import org.chromium.ui.widget.OptimizedFrameLayout;
 import org.chromium.weblayer_private.InfoBarContainer.InfoBarAnimationListener;
 
diff --git a/weblayer/browser/java/res/drawable/weblayer_infobar_wrapper_bg.xml b/weblayer/browser/java/res/drawable/weblayer_infobar_wrapper_bg.xml
deleted file mode 100644
index e119c11..0000000
--- a/weblayer/browser/java/res/drawable/weblayer_infobar_wrapper_bg.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2015 The Chromium Authors. All rights reserved.
-     Use of this source code is governed by a BSD-style license that can be
-     found in the LICENSE file. -->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
-    <item>
-        <bitmap
-            android:src="@drawable/infobar_shadow_top"
-            android:gravity="top|fill_horizontal"
-            android:tileMode="disabled" />
-    </item>
-    <item
-        android:top="@dimen/infobar_shadow_height"
-        android:drawable="@color/infobar_background_color" />
-</layer-list>