diff --git a/DEPS b/DEPS
index 8a31716e..fc20e96 100644
--- a/DEPS
+++ b/DEPS
@@ -129,7 +129,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': '14c90c1ca218428418b82be5684bb71f13e81f60',
+  'skia_revision': '847d55be4e6273fc3cd9c0b30c7bfc8a2d6575b7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -141,11 +141,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '82bcffa78747f26b0e4748ef6a7751fe4d5213aa',
+  'angle_revision': '422c94bdab7aff1939b97d03281b22237bc4aa19',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': 'abaecd5f2ba7910b0f5a959e42e9133c93afc60d',
+  'swiftshader_revision': 'f45b3881ebc6610e0ba35acbf45e048c22928493',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -196,7 +196,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '4e967e7e447debe18c75d71d94028fd1fc541d73',
+  'catapult_revision': 'f76561176b6ccfdedcf449e750ffaccc990abfce',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -272,7 +272,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '546cc453efd0b1f1aa63687fddd7c8f9a2218fce',
+  'quiche_revision': '2c5386eab92a1d8ff18f29464f6e6aa086e4ab87',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -805,7 +805,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd635edced1d1e4eafc745bdc15610a2730b4fb27',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '060c5300eae0b645f13e82fe43f55ad8faf2436c',
       'condition': 'checkout_linux',
   },
 
@@ -1256,7 +1256,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/r8',
-              'version': 'BReCwfbVwCNM2Ry4QpnrwlE3Y5gPJ2rRoyMbxFS0-4UC',
+              'version': 'SlcbUnEufAQ-iuOwGOl8yYQuctmpf7bMqh59kBfpil0C',
           },
       ],
       'condition': 'checkout_android',
@@ -1395,7 +1395,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9cb73239a3ac155781b028aeca103ed1f9ca7be6',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c8ee49fcfce8e3a24f1b38c5bf022c1d477f21f4',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index 94cd6ad..5d96cd0 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -188,15 +188,14 @@
                   'chrome/browser/android/autofill_assistant/|'\
                   'components/autofill_assistant/',
     },
-    'autofill_credit_cards': {
+    'autofill_payments': {
       'filepath': 'chrome/browser/ui/autofill/chrome_autofill_client*|'\
-                  'chrome/browser/ui/autofill/save_card_*|'\
-                  'chrome/browser/ui/views/autofill/card_unmask_*|'\
-                  'chrome/browser/ui/views/autofill/save_card_*|'\
-                  'components/autofill/core/browser/autofill_save_card_infobar_*|'\
-                  'components/autofill/core/browser/credit_card_save_manager*|'\
-                  'components/autofill/core/browser/form_data_importer*|'\
-                  'components/autofill/core/browser/ui/',
+                  'chrome/browser/ui/autofill/payments/|'\
+                  'chrome/browser/ui/views/autofill/payments/|'\
+                  'components/autofill/core/browser/payments/|'\
+                  'components/autofill/core/browser/ui/payments/|'\
+                  'components/autofill/core/common/autofill_payments_features*|'\
+                  'components/autofill_payments_strings*',
     },
     'background_fetch': {
       'filepath': 'background_fetch|'\
@@ -1906,13 +1905,12 @@
                         'piman+watch@chromium.org'],
     'autoclick': ['katie+watch@chromium.org'],
     'autofill': ['anthonyvd+autofillwatch@chromium.org',
-                 'dlkumar+autofillwatch@google.com',
                  'ftirelo+autofillwatch@chromium.org',
                  'mathp+autofillwatch@chromium.org',
                  'rogerm+autofillwatch@chromium.org',
                  'tmartino+autofillwatch@chromium.org'],
     'autofill_assistant': ['autofill_assistant+watch@google.com'],
-    'autofill_credit_cards': ['jsaul+autofillwatch@google.com'],
+    'autofill_payments': ['jsaul+autofillwatch@google.com'],
     'background_fetch': ['peter@chromium.org',
                          'rayankans+watch@chromium.org',
                          'nator@chromium.org'],
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index a1e1487..c2f922e1 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -542,7 +542,7 @@
   return true;
 }
 
-content::QuotaPermissionContext*
+scoped_refptr<content::QuotaPermissionContext>
 AwContentBrowserClient::CreateQuotaPermissionContext() {
   return new AwQuotaPermissionContext;
 }
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index 476e3bf..81c9497 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -106,7 +106,8 @@
       const GURL& url,
       content::ResourceContext* context,
       const std::vector<content::GlobalFrameRoutingId>& render_frames) override;
-  content::QuotaPermissionContext* CreateQuotaPermissionContext() override;
+  scoped_refptr<content::QuotaPermissionContext> CreateQuotaPermissionContext()
+      override;
   void GetQuotaSettings(
       content::BrowserContext* context,
       content::StoragePartition* partition,
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc
index fec3117..b06a8d7 100644
--- a/ash/accessibility/accessibility_controller.cc
+++ b/ash/accessibility/accessibility_controller.cc
@@ -266,6 +266,8 @@
                                   static_cast<int>(kDefaultAutoclickEventType));
     registry->RegisterBooleanPref(
         prefs::kAccessibilityAutoclickRevertToLeftClick, true);
+    registry->RegisterBooleanPref(
+        prefs::kAccessibilityAutoclickStabilizePosition, false);
     registry->RegisterIntegerPref(
         prefs::kAccessibilityAutoclickMovementThreshold,
         kDefaultAutoclickMovementThreshold);
@@ -321,6 +323,8 @@
   registry->RegisterForeignPref(
       prefs::kAccessibilityAutoclickRevertToLeftClick);
   registry->RegisterForeignPref(
+      prefs::kAccessibilityAutoclickStabilizePosition);
+  registry->RegisterForeignPref(
       prefs::kAccessibilityAutoclickMovementThreshold);
   registry->RegisterForeignPref(prefs::kAccessibilityAutoclickMenuPosition);
   registry->RegisterForeignPref(prefs::kAccessibilityCaretHighlightEnabled);
@@ -830,6 +834,11 @@
           &AccessibilityController::UpdateAutoclickRevertToLeftClickFromPref,
           base::Unretained(this)));
   pref_change_registrar_->Add(
+      prefs::kAccessibilityAutoclickStabilizePosition,
+      base::BindRepeating(
+          &AccessibilityController::UpdateAutoclickStabilizePositionFromPref,
+          base::Unretained(this)));
+  pref_change_registrar_->Add(
       prefs::kAccessibilityAutoclickMovementThreshold,
       base::BindRepeating(
           &AccessibilityController::UpdateAutoclickMovementThresholdFromPref,
@@ -902,6 +911,7 @@
   UpdateAutoclickDelayFromPref();
   UpdateAutoclickEventTypeFromPref();
   UpdateAutoclickRevertToLeftClickFromPref();
+  UpdateAutoclickStabilizePositionFromPref();
   UpdateAutoclickMovementThresholdFromPref();
   UpdateAutoclickMenuPositionFromPref();
   UpdateCaretHighlightFromPref();
@@ -975,6 +985,15 @@
       revert_to_left_click);
 }
 
+void AccessibilityController::UpdateAutoclickStabilizePositionFromPref() {
+  DCHECK(active_user_prefs_);
+  bool stabilize_position = active_user_prefs_->GetBoolean(
+      prefs::kAccessibilityAutoclickStabilizePosition);
+
+  Shell::Get()->autoclick_controller()->set_stabilize_click_position(
+      stabilize_position);
+}
+
 void AccessibilityController::UpdateAutoclickMovementThresholdFromPref() {
   DCHECK(active_user_prefs_);
   int movement_threshold = active_user_prefs_->GetInteger(
diff --git a/ash/accessibility/accessibility_controller.h b/ash/accessibility/accessibility_controller.h
index 004305d..d28156d 100644
--- a/ash/accessibility/accessibility_controller.h
+++ b/ash/accessibility/accessibility_controller.h
@@ -207,6 +207,7 @@
   void UpdateAutoclickDelayFromPref();
   void UpdateAutoclickEventTypeFromPref();
   void UpdateAutoclickRevertToLeftClickFromPref();
+  void UpdateAutoclickStabilizePositionFromPref();
   void UpdateAutoclickMovementThresholdFromPref();
   void UpdateAutoclickMenuPositionFromPref();
   void UpdateCaretHighlightFromPref();
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc
index cba5aad..e1af3cc 100644
--- a/ash/app_list/app_list_controller_impl.cc
+++ b/ash/app_list/app_list_controller_impl.cc
@@ -761,11 +761,6 @@
   return ash::mojom::AppListViewState::kClosed;
 }
 
-void AppListControllerImpl::SetStateTransitionAnimationCallback(
-    StateTransitionAnimationCallback callback) {
-  state_transition_animation_callback_ = std::move(callback);
-}
-
 void AppListControllerImpl::SetAppListModelForTest(
     std::unique_ptr<app_list::AppListModel> model) {
   model_->RemoveObserver(this);
@@ -773,6 +768,19 @@
   model_->AddObserver(this);
 }
 
+void AppListControllerImpl::SetStateTransitionAnimationCallback(
+    StateTransitionAnimationCallback callback) {
+  state_transition_animation_callback_ = std::move(callback);
+}
+
+void AppListControllerImpl::RecordShelfAppLaunched(
+    base::Optional<mojom::AppListViewState> recorded_app_list_view_state) {
+  app_list::RecordAppListAppLaunched(
+      mojom::AppListLaunchedFrom::kLaunchedFromShelf,
+      recorded_app_list_view_state.value_or(GetAppListViewState()),
+      IsTabletMode(), presenter_.home_launcher_shown());
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Methods of |client_|:
 
@@ -809,6 +817,18 @@
   if (!result)
     return;
 
+  if (launch_type == mojom::AppListLaunchType::kAppSearchResult) {
+    switch (launched_from) {
+      case mojom::AppListLaunchedFrom::kLaunchedFromSearchBox:
+      case mojom::AppListLaunchedFrom::kLaunchedFromSuggestionChip:
+        RecordAppLaunched(launched_from);
+        break;
+      case mojom::AppListLaunchedFrom::kLaunchedFromGrid:
+      case mojom::AppListLaunchedFrom::kLaunchedFromShelf:
+        break;
+    }
+  }
+
   UMA_HISTOGRAM_ENUMERATION(app_list::kSearchResultOpenDisplayTypeHistogram,
                             result->display_type(),
                             ash::SearchResultDisplayType::kLast);
@@ -884,7 +904,13 @@
 void AppListControllerImpl::SearchResultContextMenuItemSelected(
     const std::string& result_id,
     int command_id,
-    int event_flags) {
+    int event_flags,
+    mojom::AppListLaunchType launch_type) {
+  if (launch_type == mojom::AppListLaunchType::kAppSearchResult &&
+      app_list::IsCommandIdAnAppLaunch(command_id)) {
+    RecordAppLaunched(mojom::AppListLaunchedFrom::kLaunchedFromSearchBox);
+  }
+
   if (client_) {
     client_->SearchResultContextMenuItemSelected(result_id, command_id,
                                                  event_flags);
@@ -904,7 +930,8 @@
 
 void AppListControllerImpl::ViewClosing() {
   if (presenter_.GetView()->search_box_view()->is_search_box_active()) {
-    LogSearchAbandonHistogram();
+    // Close the search box if it is open when the app list is closing.
+    presenter_.HandleCloseOpenSearchBox();
 
     // Close the virtual keyboard before the app list view is dismissed.
     // Otherwise if the browser is behind the app list view, after the latter is
@@ -932,8 +959,12 @@
   Shell::Get()->wallpaper_controller()->GetWallpaperColors(std::move(callback));
 }
 
-void AppListControllerImpl::ActivateItem(const std::string& id,
-                                         int event_flags) {
+void AppListControllerImpl::ActivateItem(
+    const std::string& id,
+    int event_flags,
+    mojom::AppListLaunchedFrom launched_from) {
+  RecordAppLaunched(launched_from);
+
   if (client_)
     client_->ActivateItem(profile_id_, id, event_flags);
 
@@ -947,9 +978,14 @@
     client_->GetContextMenuModel(profile_id_, id, std::move(callback));
 }
 
-void AppListControllerImpl::ContextMenuItemSelected(const std::string& id,
-                                                    int command_id,
-                                                    int event_flags) {
+void AppListControllerImpl::ContextMenuItemSelected(
+    const std::string& id,
+    int command_id,
+    int event_flags,
+    mojom::AppListLaunchedFrom launched_from) {
+  if (app_list::IsCommandIdAnAppLaunch(command_id))
+    RecordAppLaunched(launched_from);
+
   if (client_)
     client_->ContextMenuItemSelected(profile_id_, id, command_id, event_flags);
 }
@@ -1042,6 +1078,13 @@
     state_transition_animation_callback_.Run(state);
 }
 
+void AppListControllerImpl::RecordAppLaunched(
+    mojom::AppListLaunchedFrom launched_from) {
+  app_list::RecordAppListAppLaunched(launched_from, GetAppListViewState(),
+                                     IsTabletMode(),
+                                     presenter_.home_launcher_shown());
+}
+
 void AppListControllerImpl::AddObserver(AppListControllerObserver* observer) {
   observers_.AddObserver(observer);
 }
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h
index c28277f..0fe4d06 100644
--- a/ash/app_list/app_list_controller_impl.h
+++ b/ash/app_list/app_list_controller_impl.h
@@ -174,20 +174,26 @@
   void GetSearchResultContextMenuModel(
       const std::string& result_id,
       GetContextMenuModelCallback callback) override;
-  void SearchResultContextMenuItemSelected(const std::string& result_id,
-                                           int command_id,
-                                           int event_flags) override;
+  void SearchResultContextMenuItemSelected(
+      const std::string& result_id,
+      int command_id,
+      int event_flags,
+      mojom::AppListLaunchType launch_type) override;
   void ViewShown(int64_t display_id) override;
   void ViewClosing() override;
   void ViewClosed() override;
   void GetWallpaperProminentColors(
       GetWallpaperProminentColorsCallback callback) override;
-  void ActivateItem(const std::string& id, int event_flags) override;
+  void ActivateItem(const std::string& id,
+                    int event_flags,
+                    mojom::AppListLaunchedFrom launched_from) override;
   void GetContextMenuModel(const std::string& id,
                            GetContextMenuModelCallback callback) override;
-  void ContextMenuItemSelected(const std::string& id,
-                               int command_id,
-                               int event_flags) override;
+  void ContextMenuItemSelected(
+      const std::string& id,
+      int command_id,
+      int event_flags,
+      mojom::AppListLaunchedFrom launched_from) override;
   void ShowWallpaperContextMenu(const gfx::Point& onscreen_location,
                                 ui::MenuSourceType source_type) override;
   bool ProcessHomeLauncherGesture(ui::GestureEvent* event,
@@ -294,6 +300,9 @@
   void SetStateTransitionAnimationCallback(
       StateTransitionAnimationCallback callback);
 
+  void RecordShelfAppLaunched(
+      base::Optional<mojom::AppListViewState> recorded_app_list_view_state);
+
  private:
   syncer::StringOrdinal GetOemFolderPos();
   std::unique_ptr<app_list::AppListItem> CreateAppListItem(
@@ -319,6 +328,9 @@
   // Shuts down the AppListControllerImpl, removing itself as an observer.
   void Shutdown();
 
+  // Record the app launch for AppListAppLaunchedV2 metric.
+  void RecordAppLaunched(mojom::AppListLaunchedFrom launched_from);
+
   base::string16 last_raw_query_;
 
   mojom::AppListClientPtr client_;
diff --git a/ash/app_list/app_list_metrics.cc b/ash/app_list/app_list_metrics.cc
index 7fea925..ca051e6 100644
--- a/ash/app_list/app_list_metrics.cc
+++ b/ash/app_list/app_list_metrics.cc
@@ -9,6 +9,7 @@
 #include "ash/app_list/model/app_list_model.h"
 #include "ash/app_list/model/search/search_model.h"
 #include "ash/app_list/model/search/search_result.h"
+#include "ash/public/cpp/app_menu_constants.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/time/time.h"
@@ -73,6 +74,24 @@
 constexpr char kSearchAbandonQueryLengthHistogram[] =
     "Apps.AppListSearchAbandonQueryLength";
 
+// The UMA histograms that log app launches within the AppList and shelf. The
+// app launches are divided by histogram for each of the the different AppList
+// states.
+constexpr char kAppListAppLaunchedClosed[] = "Apps.AppListAppLaunchedV2.Closed";
+constexpr char kAppListAppLaunchedPeeking[] =
+    "Apps.AppListAppLaunchedV2.Peeking";
+constexpr char kAppListAppLaunchedHalf[] = "Apps.AppListAppLaunchedV2.Half";
+constexpr char kAppListAppLaunchedFullscreenAllApps[] =
+    "Apps.AppListAppLaunchedV2.FullscreenAllApps";
+constexpr char kAppListAppLaunchedFullscreenSearch[] =
+    "Apps.AppListAppLaunchedV2.FullscreenSearch";
+constexpr char kAppListAppLaunchedHomecherClosed[] =
+    "Apps.AppListAppLaunchedV2.HomecherClosed";
+constexpr char kAppListAppLaunchedHomecherAllApps[] =
+    "Apps.AppListAppLaunchedV2.HomecherAllApps";
+constexpr char kAppListAppLaunchedHomecherSearch[] =
+    "Apps.AppListAppLaunchedV2.HomecherSearch";
+
 // The different sources from which a search result is displayed. These values
 // are written to logs.  New enum values can be added, but existing enums must
 // never be renumbered or deleted and reused.
@@ -171,4 +190,112 @@
                             removal_decision);
 }
 
+void RecordAppListAppLaunched(ash::mojom::AppListLaunchedFrom launched_from,
+                              ash::mojom::AppListViewState app_list_state,
+                              bool is_tablet_mode,
+                              bool home_launcher_shown) {
+  switch (app_list_state) {
+    case ash::mojom::AppListViewState::kClosed:
+      UMA_HISTOGRAM_ENUMERATION(kAppListAppLaunchedClosed, launched_from);
+      break;
+    case ash::mojom::AppListViewState::kPeeking:
+      UMA_HISTOGRAM_ENUMERATION(kAppListAppLaunchedPeeking, launched_from);
+      break;
+    case ash::mojom::AppListViewState::kHalf:
+      UMA_HISTOGRAM_ENUMERATION(kAppListAppLaunchedHalf, launched_from);
+      break;
+    case ash::mojom::AppListViewState::kFullscreenAllApps:
+      if (is_tablet_mode) {
+        if (home_launcher_shown) {
+          UMA_HISTOGRAM_ENUMERATION(kAppListAppLaunchedHomecherAllApps,
+                                    launched_from);
+        } else {
+          UMA_HISTOGRAM_ENUMERATION(kAppListAppLaunchedHomecherClosed,
+                                    launched_from);
+        }
+      } else {
+        UMA_HISTOGRAM_ENUMERATION(kAppListAppLaunchedFullscreenAllApps,
+                                  launched_from);
+      }
+      break;
+    case ash::mojom::AppListViewState::kFullscreenSearch:
+      if (is_tablet_mode) {
+        if (home_launcher_shown) {
+          UMA_HISTOGRAM_ENUMERATION(kAppListAppLaunchedHomecherSearch,
+                                    launched_from);
+        } else {
+          // (http://crbug.com/947729) Search box still expanded when opening
+          // launcher in tablet mode
+          UMA_HISTOGRAM_ENUMERATION(kAppListAppLaunchedHomecherClosed,
+                                    launched_from);
+        }
+      } else {
+        UMA_HISTOGRAM_ENUMERATION(kAppListAppLaunchedFullscreenSearch,
+                                  launched_from);
+      }
+      break;
+  }
+}
+
+bool IsCommandIdAnAppLaunch(int command_id_number) {
+  ash::CommandId command_id = static_cast<ash::CommandId>(command_id_number);
+
+  // Consider all platform app menu options as launches.
+  if (command_id >= ash::CommandId::USE_LAUNCH_TYPE_COMMAND_END &&
+      command_id < ash::CommandId::LAUNCH_APP_SHORTCUT_FIRST) {
+    return true;
+  }
+
+  // Consider all arc app shortcut options as launches.
+  if (command_id >= ash::CommandId::LAUNCH_APP_SHORTCUT_FIRST &&
+      command_id < ash::CommandId::LAUNCH_APP_SHORTCUT_LAST) {
+    return true;
+  }
+
+  switch (command_id) {
+    // Used by LauncherContextMenu (shelf).
+    case ash::CommandId::MENU_OPEN_NEW:
+    case ash::CommandId::MENU_NEW_WINDOW:
+    case ash::CommandId::MENU_NEW_INCOGNITO_WINDOW:
+    // Used by AppContextMenu.
+    case ash::CommandId::LAUNCH_NEW:
+    case ash::CommandId::SHOW_APP_INFO:
+    case ash::CommandId::OPTIONS:
+    case ash::CommandId::APP_CONTEXT_MENU_NEW_WINDOW:
+    case ash::CommandId::APP_CONTEXT_MENU_NEW_INCOGNITO_WINDOW:
+    // Used by both AppContextMenu and LauncherContextMenu for app shortcuts.
+    case ash::CommandId::LAUNCH_APP_SHORTCUT_FIRST:
+    case ash::CommandId::LAUNCH_APP_SHORTCUT_LAST:
+      return true;
+
+    // Used by LauncherContextMenu (shelf).
+    case ash::CommandId::MENU_CLOSE:
+    case ash::CommandId::MENU_PIN:
+    case ash::CommandId::LAUNCH_TYPE_PINNED_TAB:
+    case ash::CommandId::LAUNCH_TYPE_REGULAR_TAB:
+    case ash::CommandId::LAUNCH_TYPE_FULLSCREEN:
+    case ash::CommandId::LAUNCH_TYPE_WINDOW:
+    // Used by AppMenuModelAdapter
+    case ash::CommandId::NOTIFICATION_CONTAINER:
+    // Used by CrostiniShelfContextMenu.
+    case ash::CommandId::CROSTINI_USE_LOW_DENSITY:
+    case ash::CommandId::CROSTINI_USE_HIGH_DENSITY:
+    // Used by AppContextMenu.
+    case ash::CommandId::TOGGLE_PIN:
+    case ash::CommandId::UNINSTALL:
+    case ash::CommandId::REMOVE_FROM_FOLDER:
+    case ash::CommandId::INSTALL:
+    case ash::CommandId::USE_LAUNCH_TYPE_PINNED:
+    case ash::CommandId::USE_LAUNCH_TYPE_REGULAR:
+    case ash::CommandId::USE_LAUNCH_TYPE_FULLSCREEN:
+    case ash::CommandId::USE_LAUNCH_TYPE_WINDOW:
+    case ash::CommandId::USE_LAUNCH_TYPE_COMMAND_END:
+    case ash::CommandId::STOP_APP:
+    case ash::CommandId::COMMAND_ID_COUNT:
+      return false;
+  }
+  NOTREACHED();
+  return false;
+}
+
 }  // namespace app_list
diff --git a/ash/app_list/app_list_metrics.h b/ash/app_list/app_list_metrics.h
index b8fb46c..8ef8de1 100644
--- a/ash/app_list/app_list_metrics.h
+++ b/ash/app_list/app_list_metrics.h
@@ -6,6 +6,8 @@
 #define ASH_APP_LIST_APP_LIST_METRICS_H_
 
 #include "ash/app_list/app_list_export.h"
+#include "ash/public/interfaces/app_list.mojom.h"
+#include "ash/public/interfaces/app_list_view.mojom.h"
 
 namespace app_list {
 
@@ -23,14 +25,6 @@
 constexpr char kAppListHideInputLatencyHistogram[] =
     "Apps.AppListHide.InputLatency";
 
-// The UMA histogram that logs usage of suggested and regular apps.
-constexpr char kAppListAppLaunched[] = "Apps.AppListAppLaunched";
-
-// The UMA histogram that logs usage of suggested and regular apps while the
-// fullscreen launcher is enabled.
-constexpr char kAppListAppLaunchedFullscreen[] =
-    "Apps.AppListAppLaunchedFullscreen";
-
 // The UMA histogram that logs different ways to move an app in app list's apps
 // grid.
 constexpr char kAppListAppMovingType[] = "Apps.AppListAppMovingType";
@@ -240,6 +234,14 @@
     int query_length,
     int suggestion_index);
 
+APP_LIST_EXPORT void RecordAppListAppLaunched(
+    ash::mojom::AppListLaunchedFrom launched_from,
+    ash::mojom::AppListViewState app_list_state,
+    bool is_tablet_mode,
+    bool home_launcher_shown);
+
+APP_LIST_EXPORT bool IsCommandIdAnAppLaunch(int command_id);
+
 }  // namespace app_list
 
 #endif  // ASH_APP_LIST_APP_LIST_METRICS_H_
diff --git a/ash/app_list/app_list_presenter_delegate_impl.cc b/ash/app_list/app_list_presenter_delegate_impl.cc
index f8f8f31..67ad066 100644
--- a/ash/app_list/app_list_presenter_delegate_impl.cc
+++ b/ash/app_list/app_list_presenter_delegate_impl.cc
@@ -243,10 +243,6 @@
     if (status_window && status_window->Contains(target))
       auto_hide_lock.emplace(shelf);
 
-    // Since event happened outside the app list, close the open search box if
-    // it is open.
-    presenter_->HandleCloseOpenSearchBox();
-
     // Keep app list opened if event happened in the shelf area.
     if (!shelf_window || !shelf_window->Contains(target))
       presenter_->Dismiss(event->time_stamp());
diff --git a/ash/app_list/app_list_view_delegate.h b/ash/app_list/app_list_view_delegate.h
index 71b912c..2a834a7 100644
--- a/ash/app_list/app_list_view_delegate.h
+++ b/ash/app_list/app_list_view_delegate.h
@@ -97,9 +97,11 @@
   // |result_id| is the clicked SearchResult's id
   // |command_id| is the clicked menu item's command id
   // |event_flags| is flags from the event which triggered this command
-  virtual void SearchResultContextMenuItemSelected(const std::string& result_id,
-                                                   int command_id,
-                                                   int event_flags) = 0;
+  virtual void SearchResultContextMenuItemSelected(
+      const std::string& result_id,
+      int command_id,
+      int event_flags,
+      ash::mojom::AppListLaunchType launch_type) = 0;
 
   // Invoked when the app list is shown.
   virtual void ViewShown(int64_t display_id) = 0;
@@ -121,7 +123,9 @@
       GetWallpaperProminentColorsCallback callback) = 0;
 
   // Activates (opens) the item.
-  virtual void ActivateItem(const std::string& id, int event_flags) = 0;
+  virtual void ActivateItem(const std::string& id,
+                            int event_flags,
+                            ash::mojom::AppListLaunchedFrom launched_from) = 0;
 
   // Returns the context menu model for a ChromeAppListItem with |id|, or NULL
   // if there is currently no menu for the item (e.g. during install).
@@ -133,9 +137,11 @@
   // |id| is the clicked AppListItem's id
   // |command_id| is the clicked menu item's command id
   // |event_flags| is flags from the event which triggered this command
-  virtual void ContextMenuItemSelected(const std::string& id,
-                                       int command_id,
-                                       int event_flags) = 0;
+  virtual void ContextMenuItemSelected(
+      const std::string& id,
+      int command_id,
+      int event_flags,
+      ash::mojom::AppListLaunchedFrom launched_from) = 0;
 
   // Show wallpaper context menu from the specified onscreen location.
   virtual void ShowWallpaperContextMenu(const gfx::Point& onscreen_location,
diff --git a/ash/app_list/presenter/app_list_presenter_impl.cc b/ash/app_list/presenter/app_list_presenter_impl.cc
index 6f1776b..d0a0c7a 100644
--- a/ash/app_list/presenter/app_list_presenter_impl.cc
+++ b/ash/app_list/presenter/app_list_presenter_impl.cc
@@ -163,7 +163,7 @@
 }
 
 bool AppListPresenterImpl::HandleCloseOpenSearchBox() {
-  return is_visible_ && view_ && view_->HandleCloseOpenSearchBox();
+  return view_ && view_->HandleCloseOpenSearchBox();
 }
 
 ash::ShelfAction AppListPresenterImpl::ToggleAppList(
@@ -379,6 +379,16 @@
                                            aura::Window* lost_focus) {
   if (view_ && is_visible_) {
     aura::Window* applist_window = view_->GetWidget()->GetNativeView();
+
+    if (delegate_->IsTabletMode()) {
+      if (applist_window->Contains(lost_focus)) {
+        home_launcher_shown_ = false;
+        HandleCloseOpenSearchBox();
+      } else if (applist_window->Contains(gained_focus)) {
+        home_launcher_shown_ = true;
+      }
+    }
+
     aura::Window* applist_container = applist_window->parent();
     if (applist_container->Contains(lost_focus) &&
         (!gained_focus || !applist_container->Contains(gained_focus)) &&
diff --git a/ash/app_list/presenter/app_list_presenter_impl.h b/ash/app_list/presenter/app_list_presenter_impl.h
index ad54a25..4f4c536 100644
--- a/ash/app_list/presenter/app_list_presenter_impl.h
+++ b/ash/app_list/presenter/app_list_presenter_impl.h
@@ -131,6 +131,9 @@
   // Show/hide the expand arrow view button.
   void SetExpandArrowViewVisibility(bool show);
 
+  // Returns whether home launcher is currently shown.
+  bool home_launcher_shown() const { return home_launcher_shown_; }
+
  private:
   // Sets the app list view and attempts to show it.
   void SetView(AppListView* view);
@@ -201,6 +204,9 @@
   // If true, dismiss the app list immediately.
   bool dismiss_without_animation_ = false;
 
+  // Whether the home launcher is currently shown.
+  bool home_launcher_shown_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(AppListPresenterImpl);
 };
 
diff --git a/ash/app_list/test/app_list_test_view_delegate.cc b/ash/app_list/test/app_list_test_view_delegate.cc
index 6c223b2..5d29935 100644
--- a/ash/app_list/test/app_list_test_view_delegate.cc
+++ b/ash/app_list/test/app_list_test_view_delegate.cc
@@ -53,6 +53,18 @@
     }
   }
   ++open_search_result_count_;
+
+  if (launch_type == ash::mojom::AppListLaunchType::kAppSearchResult) {
+    switch (launched_from) {
+      case ash::mojom::AppListLaunchedFrom::kLaunchedFromSearchBox:
+      case ash::mojom::AppListLaunchedFrom::kLaunchedFromSuggestionChip:
+        RecordAppLaunched(launched_from);
+        return;
+      case ash::mojom::AppListLaunchedFrom::kLaunchedFromGrid:
+      case ash::mojom::AppListLaunchedFrom::kLaunchedFromShelf:
+        return;
+    }
+  }
 }
 
 void AppListTestViewDelegate::DismissAppList() {
@@ -69,13 +81,16 @@
   search_model_->SetSearchEngineIsGoogle(is_google);
 }
 
-void AppListTestViewDelegate::ActivateItem(const std::string& id,
-                                           int event_flags) {
+void AppListTestViewDelegate::ActivateItem(
+    const std::string& id,
+    int event_flags,
+    ash::mojom::AppListLaunchedFrom launched_from) {
   app_list::AppListItem* item = model_->FindItem(id);
   if (!item)
     return;
   DCHECK(!item->is_folder());
   static_cast<AppListTestModel::AppListTestItem*>(item)->Activate(event_flags);
+  RecordAppLaunched(launched_from);
 }
 
 void AppListTestViewDelegate::GetContextMenuModel(
@@ -140,6 +155,13 @@
 void AppListTestViewDelegate::OnStateTransitionAnimationCompleted(
     ash::mojom::AppListViewState state) {}
 
+void AppListTestViewDelegate::RecordAppLaunched(
+    ash::mojom::AppListLaunchedFrom launched_from) {
+  app_list::RecordAppListAppLaunched(launched_from, model_->state_fullscreen(),
+                                     false /*tablet mode*/,
+                                     false /*home launcher shown*/);
+}
+
 bool AppListTestViewDelegate::IsCommandIdChecked(int command_id) const {
   return true;
 }
diff --git a/ash/app_list/test/app_list_test_view_delegate.h b/ash/app_list/test/app_list_test_view_delegate.h
index b832494..a26cbf7 100644
--- a/ash/app_list/test/app_list_test_view_delegate.h
+++ b/ash/app_list/test/app_list_test_view_delegate.h
@@ -15,6 +15,7 @@
 #include "ash/app_list/app_list_view_delegate.h"
 #include "ash/app_list/model/search/search_model.h"
 #include "ash/app_list/test/app_list_test_model.h"
+#include "ash/public/interfaces/app_list.mojom.h"
 #include "base/callback_forward.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
@@ -74,21 +75,27 @@
   void GetSearchResultContextMenuModel(
       const std::string& result_id,
       GetContextMenuModelCallback callback) override;
-  void SearchResultContextMenuItemSelected(const std::string& result_id,
-                                           int command_id,
-                                           int event_flags) override {}
+  void SearchResultContextMenuItemSelected(
+      const std::string& result_id,
+      int command_id,
+      int event_flags,
+      ash::mojom::AppListLaunchType launch_type) override {}
   void ViewShown(int64_t display_id) override {}
   void DismissAppList() override;
   void ViewClosing() override {}
   void ViewClosed() override {}
   void GetWallpaperProminentColors(
       GetWallpaperProminentColorsCallback callback) override {}
-  void ActivateItem(const std::string& id, int event_flags) override;
+  void ActivateItem(const std::string& id,
+                    int event_flags,
+                    ash::mojom::AppListLaunchedFrom launched_from) override;
   void GetContextMenuModel(const std::string& id,
                            GetContextMenuModelCallback callback) override;
-  void ContextMenuItemSelected(const std::string& id,
-                               int command_id,
-                               int event_flags) override {}
+  void ContextMenuItemSelected(
+      const std::string& id,
+      int command_id,
+      int event_flags,
+      ash::mojom::AppListLaunchedFrom launched_from) override {}
   void ShowWallpaperContextMenu(const gfx::Point& onscreen_location,
                                 ui::MenuSourceType source_type) override;
   bool ProcessHomeLauncherGesture(ui::GestureEvent* event,
@@ -111,6 +118,8 @@
   AppListTestModel* GetTestModel() { return model_.get(); }
 
  private:
+  void RecordAppLaunched(ash::mojom::AppListLaunchedFrom launched_from);
+
   // ui::SimpleMenuModel::Delegate overrides:
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
diff --git a/ash/app_list/views/app_list_item_view.cc b/ash/app_list/views/app_list_item_view.cc
index 80d9005..f451e25 100644
--- a/ash/app_list/views/app_list_item_view.cc
+++ b/ash/app_list/views/app_list_item_view.cc
@@ -8,12 +8,14 @@
 #include <utility>
 #include <vector>
 
+#include "ash/app_list/app_list_metrics.h"
 #include "ash/app_list/app_list_view_delegate.h"
 #include "ash/app_list/model/app_list_folder_item.h"
 #include "ash/app_list/model/app_list_item.h"
 #include "ash/app_list/views/apps_grid_view.h"
 #include "ash/public/cpp/app_list/app_list_config.h"
 #include "ash/public/cpp/app_list/app_list_switches.h"
+#include "ash/public/interfaces/app_list.mojom.h"
 #include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
@@ -508,8 +510,9 @@
 
 void AppListItemView::ExecuteCommand(int command_id, int event_flags) {
   if (item_weak_) {
-    delegate_->ContextMenuItemSelected(item_weak_->id(), command_id,
-                                       event_flags);
+    delegate_->ContextMenuItemSelected(
+        item_weak_->id(), command_id, event_flags,
+        ash::mojom::AppListLaunchedFrom::kLaunchedFromGrid);
   }
 }
 
diff --git a/ash/app_list/views/app_list_main_view.cc b/ash/app_list/views/app_list_main_view.cc
index 444fd70..4df7a50 100644
--- a/ash/app_list/views/app_list_main_view.cc
+++ b/ash/app_list/views/app_list_main_view.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <memory>
 
+#include "ash/app_list/app_list_metrics.h"
 #include "ash/app_list/app_list_view_delegate.h"
 #include "ash/app_list/model/app_list_folder_item.h"
 #include "ash/app_list/model/app_list_item.h"
@@ -163,9 +164,8 @@
                               kFullscreenAppListFolders, kMaxFolderOpened);
   } else {
     base::RecordAction(base::UserMetricsAction("AppList_ClickOnApp"));
-    delegate_->ActivateItem(item->id(), event_flags);
-    UMA_HISTOGRAM_BOOLEAN(kAppListAppLaunchedFullscreen,
-                          false /*not a suggested app*/);
+    delegate_->ActivateItem(item->id(), event_flags,
+                            ash::mojom::AppListLaunchedFrom::kLaunchedFromGrid);
   }
 }
 
diff --git a/ash/app_list/views/apps_grid_view_unittest.cc b/ash/app_list/views/apps_grid_view_unittest.cc
index 18c15c6..a8a9124 100644
--- a/ash/app_list/views/apps_grid_view_unittest.cc
+++ b/ash/app_list/views/apps_grid_view_unittest.cc
@@ -408,23 +408,23 @@
   base::HistogramTester histogram_tester;
   model_->PopulateApps(5);
 
-  // Select the first suggested app and launch it.
+  // Select the first app in grid and launch it.
   contents_view_->GetAppListMainView()->ActivateApp(GetItemViewAt(0)->item(),
                                                     0);
 
-  // Test that histograms recorded that a regular app launched.
-  histogram_tester.ExpectBucketCount("Apps.AppListAppLaunchedFullscreen", 0, 1);
-  // Test that histograms did not record that a suggested launched.
-  histogram_tester.ExpectBucketCount("Apps.AppListAppLaunchedFullscreen", 1, 0);
+  // Test that histogram recorded app launch from grid.
+  histogram_tester.ExpectBucketCount(
+      "Apps.AppListAppLaunchedV2.FullscreenAllApps", 1 /* kAppListItem */,
+      1 /* Times kAppListItem launched */);
 
   // Launch a suggested app.
   suggestions_container_->child_at(0)->OnKeyPressed(
       ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE));
 
-  // Test that histograms recorded that a suggested app launched, and that the
-  // count for regular apps launched is unchanged.
-  histogram_tester.ExpectBucketCount("Apps.AppListAppLaunchedFullscreen", 0, 1);
-  histogram_tester.ExpectBucketCount("Apps.AppListAppLaunchedFullscreen", 1, 1);
+  // Test that histogram recorded app launched from suggestion chip.
+  histogram_tester.ExpectBucketCount(
+      "Apps.AppListAppLaunchedV2.FullscreenAllApps", 2 /* kSuggestionChip */,
+      1 /* Times kSuggestionChip Launched */);
 }
 
 TEST_F(AppsGridViewTest, ItemLabelShortNameOverride) {
diff --git a/ash/app_list/views/search_result_suggestion_chip_view.cc b/ash/app_list/views/search_result_suggestion_chip_view.cc
index f3bbc3b..813b829 100644
--- a/ash/app_list/views/search_result_suggestion_chip_view.cc
+++ b/ash/app_list/views/search_result_suggestion_chip_view.cc
@@ -49,9 +49,6 @@
   base::UmaHistogramSparse("Apps.AppListSuggestedChipLaunched",
                            index_in_suggestion_chip_container);
 
-  UMA_HISTOGRAM_BOOLEAN(kAppListAppLaunchedFullscreen,
-                        true /* suggested app */);
-
   base::RecordAction(base::UserMetricsAction("AppList_OpenSuggestedApp"));
 }
 
diff --git a/ash/app_list/views/search_result_tile_item_view.cc b/ash/app_list/views/search_result_tile_item_view.cc
index 6983d99..3e4906e 100644
--- a/ash/app_list/views/search_result_tile_item_view.cc
+++ b/ash/app_list/views/search_result_tile_item_view.cc
@@ -381,7 +381,8 @@
 void SearchResultTileItemView::ExecuteCommand(int command_id, int event_flags) {
   if (result()) {
     view_delegate_->SearchResultContextMenuItemSelected(
-        result()->id(), command_id, event_flags);
+        result()->id(), command_id, event_flags,
+        ash::mojom::AppListLaunchType::kAppSearchResult);
   }
 }
 
diff --git a/ash/app_list/views/search_result_view.cc b/ash/app_list/views/search_result_view.cc
index 117b450..478e77f 100644
--- a/ash/app_list/views/search_result_view.cc
+++ b/ash/app_list/views/search_result_view.cc
@@ -17,6 +17,7 @@
 #include "ash/app_list/views/search_result_list_view.h"
 #include "ash/public/cpp/app_list/app_list_config.h"
 #include "ash/public/cpp/app_list/app_list_switches.h"
+#include "ash/public/interfaces/app_list.mojom.h"
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/gfx/canvas.h"
@@ -531,7 +532,8 @@
 void SearchResultView::ExecuteCommand(int command_id, int event_flags) {
   if (result()) {
     view_delegate_->SearchResultContextMenuItemSelected(
-        result()->id(), command_id, event_flags);
+        result()->id(), command_id, event_flags,
+        ash::mojom::AppListLaunchType::kSearchResult);
   }
 }
 
diff --git a/ash/autoclick/autoclick_controller.cc b/ash/autoclick/autoclick_controller.cc
index c03ceee..3ab1aca 100644
--- a/ash/autoclick/autoclick_controller.cc
+++ b/ash/autoclick/autoclick_controller.cc
@@ -425,6 +425,11 @@
     } else if (start_gesture_timer_->IsRunning()) {
       // Keep track of where the gesture will be anchored.
       gesture_anchor_location_ = point_in_screen;
+    } else if (autoclick_timer_->IsRunning() && !stabilize_click_position_) {
+      // If we are not stabilizing the click position, update the gesture
+      // center with each mouse move event.
+      anchor_location_ = point_in_screen;
+      autoclick_ring_handler_->SetGestureCenter(point_in_screen, widget_.get());
     }
   } else if (event->type() == ui::ET_MOUSE_PRESSED ||
              event->type() == ui::ET_MOUSE_RELEASED) {
diff --git a/ash/autoclick/autoclick_controller.h b/ash/autoclick/autoclick_controller.h
index 26729b9..b0d2600 100644
--- a/ash/autoclick/autoclick_controller.h
+++ b/ash/autoclick/autoclick_controller.h
@@ -66,6 +66,17 @@
     revert_to_left_click_ = revert_to_left_click;
   }
 
+  // Sets whether to stabilize the cursor position during a click.
+  // If |stabilize_position|, the click position will not change after the
+  // autoclick timer and gesture animation begin, so long as the cursor does
+  // not move outside of the movement threshold. If the position is not
+  // stabilized, the cursor movements will translate into autoclick position
+  // movements (but a cursor movement larger than the movement threshold from
+  // the starting position will still cancel the click).
+  void set_stabilize_click_position(bool stabilize_position) {
+    stabilize_click_position_ = stabilize_position;
+  }
+
   // Functionality for testing.
   static float GetStartGestureDelayRatioForTesting();
   AutoclickMenuBubbleController* GetMenuBubbleControllerForTesting() {
@@ -103,6 +114,7 @@
   bool enabled_ = false;
   mojom::AutoclickEventType event_type_ = kDefaultAutoclickEventType;
   bool revert_to_left_click_ = true;
+  bool stabilize_click_position_ = false;
   int movement_threshold_ = kDefaultAutoclickMovementThreshold;
   // TODO(katie): The default position should flex with the user's choice of
   // language (RTL vs LTR) and shelf position, following the same behavior
diff --git a/ash/autoclick/autoclick_unittest.cc b/ash/autoclick/autoclick_unittest.cc
index d245f1c..ab87cfe 100644
--- a/ash/autoclick/autoclick_unittest.cc
+++ b/ash/autoclick/autoclick_unittest.cc
@@ -278,13 +278,13 @@
   int animation_delay = 5;
   int full_delay = UpdateAnimationDelayAndGetFullDelay(animation_delay);
 
+  GetAutoclickController()->set_stabilize_click_position(true);
   GetEventGenerator()->MoveMouseTo(100, 100);
   FastForwardBy(animation_delay + 1);
 
   // Move the mouse within the threshold. It shouldn't change the eventual
   // target of the event, or cancel the click.
   GetEventGenerator()->MoveMouseTo(110, 110);
-
   ClearMouseEvents();
   FastForwardBy(full_delay);
   std::vector<ui::MouseEvent> events = GetMouseEvents();
@@ -297,6 +297,25 @@
   EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[1].type());
   EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, events[1].flags());
 
+  // When the click position is not stabilized, the mouse movement should
+  // translate into the target of the event, but not cancel the click.
+  GetAutoclickController()->set_stabilize_click_position(false);
+  GetEventGenerator()->MoveMouseTo(200, 200);
+  FastForwardBy(animation_delay + 1);
+  GetEventGenerator()->MoveMouseTo(210, 210);
+
+  ClearMouseEvents();
+  FastForwardBy(full_delay);
+  events = GetMouseEvents();
+
+  EXPECT_EQ(2u, events.size());
+  EXPECT_EQ(gfx::Point(210, 210), events[0].location());
+  EXPECT_EQ(ui::ET_MOUSE_PRESSED, events[0].type());
+  EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, events[0].flags());
+  EXPECT_EQ(gfx::Point(210, 210), events[1].location());
+  EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[1].type());
+  EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, events[1].flags());
+
   // Reset delay.
   GetAutoclickController()->SetAutoclickDelay(base::TimeDelta());
 }
@@ -595,8 +614,7 @@
   FastForwardBy(animation_delay - 1);
   GetEventGenerator()->MoveMouseTo(105, 105);
 
-  // Fast forward until the animation would have started. Now moving the mouse
-  // a little does not change the center point.
+  // Moving the mouse during the animation changes the center point.
   FastForwardBy(animation_delay);
   GetEventGenerator()->MoveMouseTo(110, 110);
 
@@ -605,7 +623,29 @@
   FastForwardBy(full_delay);
   events = GetMouseEvents();
   ASSERT_EQ(2u, events.size());
-  EXPECT_EQ(gfx::Point(105, 105), events[0].location());
+  EXPECT_EQ(gfx::Point(110, 110), events[0].location());
+
+  // Turn off stabilize_click_position and try again, the position should update
+  // with the cursor's new position until the click occurs.
+  GetAutoclickController()->set_stabilize_click_position(true);
+  ClearMouseEvents();
+  GetEventGenerator()->MoveMouseTo(200, 200);
+
+  // (205, 205) will become the center of the animation.
+  FastForwardBy(animation_delay - 1);
+  GetEventGenerator()->MoveMouseTo(205, 205);
+
+  // Fast forward until the animation would have started. Now moving the mouse
+  // a little does not change the center point because we have stabilize on.
+  FastForwardBy(animation_delay);
+  GetEventGenerator()->MoveMouseTo(210, 210);
+  FastForwardBy(full_delay);
+  events = GetMouseEvents();
+  ASSERT_EQ(2u, events.size());
+  EXPECT_EQ(gfx::Point(205, 205), events[0].location());
+
+  // Reset state.
+  GetAutoclickController()->set_stabilize_click_position(false);
 }
 
 TEST_F(AutoclickTest, DoesActionOnBubbleWhenInDifferentModes) {
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
index c673255..b65dd99 100644
--- a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
+++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
@@ -92,11 +92,17 @@
 
 class ShortcutsListScrollView : public views::ScrollView {
  public:
-  ShortcutsListScrollView() = default;
+  ShortcutsListScrollView() {
+    GetViewAccessibility().OverrideRole(ax::mojom::Role::kScrollView);
+  }
+
   ~ShortcutsListScrollView() override = default;
 
   // views::View:
-  void OnFocus() override { SetHasFocusIndicator(true); }
+  void OnFocus() override {
+    SetHasFocusIndicator(true);
+    NotifyAccessibilityEvent(ax::mojom::Event::kFocus, true);
+  }
 
   void OnBlur() override { SetHasFocusIndicator(false); }
 
diff --git a/ash/login/login_screen_test_api.cc b/ash/login/login_screen_test_api.cc
index 9cdbc73..dcea068 100644
--- a/ash/login/login_screen_test_api.cc
+++ b/ash/login/login_screen_test_api.cc
@@ -147,6 +147,14 @@
       IsLoginShelfViewButtonShown(LoginShelfView::kShutdown));
 }
 
+void LoginScreenTestApi::IsAuthErrorBubbleShown(
+    IsAuthErrorBubbleShownCallback callback) {
+  ash::LockScreen::TestApi lock_screen_test(ash::LockScreen::Get());
+  ash::LockContentsView::TestApi lock_contents_test(
+      lock_screen_test.contents_view());
+  std::move(callback).Run(lock_contents_test.auth_error_bubble()->visible());
+}
+
 void LoginScreenTestApi::SubmitPassword(const AccountId& account_id,
                                         const std::string& password,
                                         SubmitPasswordCallback callback) {
diff --git a/ash/login/login_screen_test_api.h b/ash/login/login_screen_test_api.h
index 907881d..9d93a21 100644
--- a/ash/login/login_screen_test_api.h
+++ b/ash/login/login_screen_test_api.h
@@ -27,6 +27,7 @@
   void IsLoginShelfShown(IsLoginShelfShownCallback callback) override;
   void IsRestartButtonShown(IsRestartButtonShownCallback callback) override;
   void IsShutdownButtonShown(IsShutdownButtonShownCallback callback) override;
+  void IsAuthErrorBubbleShown(IsAuthErrorBubbleShownCallback callback) override;
   void SubmitPassword(const AccountId& account_id,
                       const std::string& password,
                       SubmitPasswordCallback callback) override;
diff --git a/ash/public/cpp/ash_pref_names.cc b/ash/public/cpp/ash_pref_names.cc
index 79830f1..090c816 100644
--- a/ash/public/cpp/ash_pref_names.cc
+++ b/ash/public/cpp/ash_pref_names.cc
@@ -57,6 +57,10 @@
 // another event type action, or whether it should stay as the other event type.
 const char kAccessibilityAutoclickRevertToLeftClick[] =
     "settings.a11y.autoclick_revert_to_left_click";
+// Whether Autoclick should stabilize the cursor movement before a click occurs
+// or not.
+const char kAccessibilityAutoclickStabilizePosition[] =
+    "settings.a11y.autoclick_stabilize_position";
 // The default threshold of mouse movement, measured in DIP, that will initiate
 // a new autoclick.
 const char kAccessibilityAutoclickMovementThreshold[] =
diff --git a/ash/public/cpp/ash_pref_names.h b/ash/public/cpp/ash_pref_names.h
index ab9792c..a8b8d71 100644
--- a/ash/public/cpp/ash_pref_names.h
+++ b/ash/public/cpp/ash_pref_names.h
@@ -25,6 +25,7 @@
 ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickDelayMs[];
 ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickEventType[];
 ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickRevertToLeftClick[];
+ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickStabilizePosition[];
 ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickMovementThreshold[];
 ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickMenuPosition[];
 ASH_PUBLIC_EXPORT extern const char kAccessibilityCaretHighlightEnabled[];
diff --git a/ash/public/interfaces/app_list.mojom b/ash/public/interfaces/app_list.mojom
index fbd8f7a..45128e1 100644
--- a/ash/public/interfaces/app_list.mojom
+++ b/ash/public/interfaces/app_list.mojom
@@ -103,11 +103,14 @@
 
 // The UI component the user launched the search result from. Must match
 // chrome/browser/ui/app_list/app_launch_event_logger.proto.
+// This enum is used in a histogram, do not remove/renumber entries. If you're
+// adding to this enum with the intention that it will be logged, update the
+// AppListLaunchedFrom enum listing in tools/metrics/histograms/enums.xml.
 enum AppListLaunchedFrom {
   kLaunchedFromGrid = 1,
-  kLaunchedFromSuggestionChip,
-  kLaunchedFromShelf,
-  kLaunchedFromSearchBox,
+  kLaunchedFromSuggestionChip = 2,
+  kLaunchedFromShelf = 3,
+  kLaunchedFromSearchBox = 4,
 };
 
 // The UI representation of the search result. Currently all search results
diff --git a/ash/public/interfaces/login_screen_test_api.test-mojom b/ash/public/interfaces/login_screen_test_api.test-mojom
index 3598b59..f9ccc56 100644
--- a/ash/public/interfaces/login_screen_test_api.test-mojom
+++ b/ash/public/interfaces/login_screen_test_api.test-mojom
@@ -20,6 +20,9 @@
   // Returns true if Shutdown button is currently being shown.
   IsShutdownButtonShown() => (bool is_shown);
 
+  // Returns true if Auth Error Button is currently being shown.
+  IsAuthErrorBubbleShown() => (bool is_shown);
+
   // Submit |password| for |account_id|.
   SubmitPassword(signin.mojom.AccountId account_id, string password) => ();
 
diff --git a/ash/shelf/shelf_application_menu_model.cc b/ash/shelf/shelf_application_menu_model.cc
index dcaf03d..2418a0c 100644
--- a/ash/shelf/shelf_application_menu_model.cc
+++ b/ash/shelf/shelf_application_menu_model.cc
@@ -9,7 +9,9 @@
 #include <limits>
 #include <utility>
 
+#include "ash/app_list/app_list_controller_impl.h"
 #include "ash/public/cpp/shelf_item_delegate.h"
+#include "ash/shell.h"
 #include "base/metrics/histogram_macros.h"
 #include "ui/display/types/display_constants.h"
 #include "ui/gfx/image/image.h"
@@ -57,6 +59,9 @@
   DCHECK(IsCommandIdEnabled(command_id));
   // Have the delegate execute its own custom command id for the given item.
   if (delegate_) {
+    // Record app launch when selecting window to open from disambiguation menu.
+    Shell::Get()->app_list_controller()->RecordShelfAppLaunched(base::nullopt);
+
     // The display hosting the menu is irrelevant, windows activate in-place.
     delegate_->ExecuteCommand(false, items_[command_id]->command_id,
                               event_flags, display::kInvalidDisplayId);
diff --git a/ash/shelf/shelf_context_menu_model.cc b/ash/shelf/shelf_context_menu_model.cc
index 5d49eeb..e6e7b7c 100644
--- a/ash/shelf/shelf_context_menu_model.cc
+++ b/ash/shelf/shelf_context_menu_model.cc
@@ -8,6 +8,8 @@
 #include <string>
 #include <utility>
 
+#include "ash/app_list/app_list_controller_impl.h"
+#include "ash/app_list/app_list_metrics.h"
 #include "ash/public/cpp/app_menu_constants.h"
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/public/cpp/menu_utils.h"
@@ -215,9 +217,14 @@
       Shell::Get()->wallpaper_controller()->OpenWallpaperPickerIfAllowed();
       break;
     default:
-      // Have the shelf item delegate execute the context menu command.
-      if (delegate_)
+      if (delegate_) {
+        if (app_list::IsCommandIdAnAppLaunch(command_id)) {
+          Shell::Get()->app_list_controller()->RecordShelfAppLaunched(
+              base::nullopt);
+        }
+
         delegate_->ExecuteCommand(true, command_id, event_flags, display_id_);
+      }
       break;
   }
 }
diff --git a/ash/shelf/shelf_context_menu_model_unittest.cc b/ash/shelf/shelf_context_menu_model_unittest.cc
index 114c8b4..272fd68 100644
--- a/ash/shelf/shelf_context_menu_model_unittest.cc
+++ b/ash/shelf/shelf_context_menu_model_unittest.cc
@@ -177,14 +177,14 @@
   MenuItemList items;
   mojom::MenuItemPtr item(mojom::MenuItem::New());
   item->type = ui::MenuModel::TYPE_COMMAND;
-  item->command_id = 123;
+  item->command_id = 203;
   item->label = base::ASCIIToUTF16("item");
   item->enabled = true;
   items.push_back(std::move(item));
 
   mojom::MenuItemPtr check(mojom::MenuItem::New());
   check->type = ui::MenuModel::TYPE_CHECK;
-  check->command_id = 999;
+  check->command_id = 107;
   check->label = base::ASCIIToUTF16("check");
   check->enabled = true;
   check->checked = false;
@@ -192,7 +192,7 @@
 
   mojom::MenuItemPtr radio(mojom::MenuItem::New());
   radio->type = ui::MenuModel::TYPE_RADIO;
-  radio->command_id = 1337;
+  radio->command_id = 101;
   radio->label = base::ASCIIToUTF16("radio");
   radio->enabled = false;
   radio->checked = true;
@@ -209,25 +209,25 @@
   ASSERT_EQ(3, menu.GetItemCount());
 
   EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu.GetTypeAt(0));
-  EXPECT_EQ(123, menu.GetCommandIdAt(0));
+  EXPECT_EQ(203, menu.GetCommandIdAt(0));
   EXPECT_EQ(base::ASCIIToUTF16("item"), menu.GetLabelAt(0));
   EXPECT_TRUE(menu.IsEnabledAt(0));
 
   EXPECT_EQ(ui::MenuModel::TYPE_CHECK, menu.GetTypeAt(1));
-  EXPECT_EQ(999, menu.GetCommandIdAt(1));
+  EXPECT_EQ(107, menu.GetCommandIdAt(1));
   EXPECT_EQ(base::ASCIIToUTF16("check"), menu.GetLabelAt(1));
   EXPECT_TRUE(menu.IsEnabledAt(1));
   EXPECT_FALSE(menu.IsItemCheckedAt(1));
 
   EXPECT_EQ(ui::MenuModel::TYPE_RADIO, menu.GetTypeAt(2));
-  EXPECT_EQ(1337, menu.GetCommandIdAt(2));
+  EXPECT_EQ(101, menu.GetCommandIdAt(2));
   EXPECT_EQ(base::ASCIIToUTF16("radio"), menu.GetLabelAt(2));
   EXPECT_FALSE(menu.IsEnabledAt(2));
   EXPECT_TRUE(menu.IsItemCheckedAt(2));
 
   // Invoking a custom item should execute the command id on the delegate.
   menu.ActivatedAt(1);
-  EXPECT_EQ(999, delegate.last_executed_command());
+  EXPECT_EQ(107, delegate.last_executed_command());
 }
 
 // Tests the prepending of a custom submenu in a shelf context menu.
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index 6c53f29..6d08ef7 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <memory>
 
+#include "ash/app_list/app_list_controller_impl.h"
 #include "ash/drag_drop/drag_image_view.h"
 #include "ash/focus_cycler.h"
 #include "ash/keyboard/keyboard_util.h"
@@ -724,6 +725,12 @@
       break;
   }
 
+  // Record the current AppListViewState to be used later for metrics. The
+  // AppListViewState will change on app launch, so this will record the
+  // AppListViewState before the app was launched.
+  recorded_app_list_view_state_ =
+      Shell::Get()->app_list_controller()->GetAppListViewState();
+
   // Run AfterItemSelected directly if the item has no delegate (ie. in tests).
   const ShelfItem& item = model_->items()[last_pressed_index_];
   if (!model_->GetShelfItemDelegate(item.id)) {
@@ -2325,6 +2332,13 @@
   item_awaiting_response_ = ShelfID();
   shelf_button_pressed_metric_tracker_.ButtonPressed(*event, sender, action);
 
+  // Record AppList metric for any action considered an app launch.
+  if (action == SHELF_ACTION_NEW_WINDOW_CREATED ||
+      action == SHELF_ACTION_WINDOW_ACTIVATED) {
+    Shell::Get()->app_list_controller()->RecordShelfAppLaunched(
+        recorded_app_list_view_state_);
+  }
+
   // The app list handles its own ink drop effect state changes.
   if (action == SHELF_ACTION_APP_LIST_DISMISSED) {
     ink_drop->SnapToActivated();
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h
index 67daa75..5eb105c 100644
--- a/ash/shelf/shelf_view.h
+++ b/ash/shelf/shelf_view.h
@@ -12,6 +12,7 @@
 
 #include "ash/app_list/views/app_list_drag_and_drop_host.h"
 #include "ash/public/cpp/shelf_model_observer.h"
+#include "ash/public/interfaces/app_list_view.mojom.h"
 #include "ash/public/interfaces/shelf.mojom.h"
 #include "ash/shelf/ink_drop_button_listener.h"
 #include "ash/shelf/overflow_bubble.h"
@@ -695,6 +696,11 @@
   // Used to call SpeedUpDragScrolling.
   base::OneShotTimer speed_up_drag_scrolling_;
 
+  // The AppListViewState recorded before a button press, used to record app
+  // launching metrics. This allows an accurate AppListViewState to be recorded
+  // before AppListViewState changes.
+  ash::mojom::AppListViewState recorded_app_list_view_state_;
+
   base::WeakPtrFactory<ShelfView> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ShelfView);
diff --git a/ash/wm/base_state.cc b/ash/wm/base_state.cc
index 8759fb2..0858c5c 100644
--- a/ash/wm/base_state.cc
+++ b/ash/wm/base_state.cc
@@ -150,12 +150,16 @@
     // Save the previous show state when it is not minimized so that we can
     // correctly restore it after exiting the minimized mode.
     if (!IsMinimizedWindowStateType(previous_state_type)) {
-      window->SetProperty(
-          aura::client::kPreMinimizedShowStateKey,
-          ToWindowShowState(
-              previous_state_type == mojom::WindowStateType::PIP
-                  ? window->GetProperty(ash::kPrePipWindowStateTypeKey)
-                  : previous_state_type));
+      // We must not save PIP to |kPreMinimizedShowStateKey|.
+      if (previous_state_type != mojom::WindowStateType::PIP)
+        window->SetProperty(aura::client::kPreMinimizedShowStateKey,
+                            ToWindowShowState(previous_state_type));
+      // We must not save MINIMIZED to |kPreMinimizedShowStateKey|.
+      else if (window->GetProperty(ash::kPrePipWindowStateTypeKey) !=
+               mojom::WindowStateType::MINIMIZED)
+        window->SetProperty(aura::client::kPreMinimizedShowStateKey,
+                            ToWindowShowState(window->GetProperty(
+                                ash::kPrePipWindowStateTypeKey)));
     }
     // Count minimizing a PIP window as dismissing it. Android apps in PIP mode
     // don't exit when they are dismissed, they just go back to being a regular
diff --git a/ash/wm/window_animations_unittest.cc b/ash/wm/window_animations_unittest.cc
index 412ec96..dc5d002 100644
--- a/ash/wm/window_animations_unittest.cc
+++ b/ash/wm/window_animations_unittest.cc
@@ -335,25 +335,61 @@
 
   window->Show();
   EXPECT_TRUE(window->layer()->visible());
-  EXPECT_EQ("8,8 100x100", window->layer()->GetTargetBounds().ToString());
+  EXPECT_EQ(gfx::Rect(8, 8, 100, 100), window->layer()->GetTargetBounds());
 
   window->Hide();
   EXPECT_EQ(0.0f, window->layer()->GetTargetOpacity());
   EXPECT_FALSE(window->layer()->GetTargetVisibility());
   EXPECT_FALSE(window->layer()->visible());
-  EXPECT_EQ("-142,8 100x100", window->layer()->GetTargetBounds().ToString());
+  EXPECT_EQ(gfx::Rect(-142, 8, 100, 100), window->layer()->GetTargetBounds());
 
   // Reset the position and try again.
   window->Show();
   window->SetBounds(gfx::Rect(8, 8, 100, 100));
   EXPECT_TRUE(window->layer()->visible());
-  EXPECT_EQ("8,8 100x100", window->layer()->GetTargetBounds().ToString());
+  EXPECT_EQ(gfx::Rect(8, 8, 100, 100), window->layer()->GetTargetBounds());
 
   window->Hide();
   EXPECT_EQ(0.0f, window->layer()->GetTargetOpacity());
   EXPECT_FALSE(window->layer()->GetTargetVisibility());
   EXPECT_FALSE(window->layer()->visible());
-  EXPECT_EQ("-142,8 100x100", window->layer()->GetTargetBounds().ToString());
+  EXPECT_EQ(gfx::Rect(-142, 8, 100, 100), window->layer()->GetTargetBounds());
+}
+
+TEST_F(WindowAnimationsTest, ResetAnimationAfterDismissingArcPip) {
+  ui::ScopedAnimationDurationScaleMode test_duration_mode(
+      ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
+
+  std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
+  window->SetBounds(gfx::Rect(8, 8, 100, 100));
+
+  wm::WindowState* window_state = wm::GetWindowState(window.get());
+  const wm::WMEvent enter_pip(wm::WM_EVENT_PIP);
+  window_state->OnWMEvent(&enter_pip);
+  EXPECT_TRUE(window_state->IsPip());
+
+  window->Show();
+  EXPECT_TRUE(window->layer()->visible());
+  EXPECT_EQ(gfx::Rect(8, 8, 100, 100), window->layer()->GetTargetBounds());
+
+  // Ensure the window is slided out.
+  wm::GetWindowState(window.get())->Minimize();
+  EXPECT_EQ(0.0f, window->layer()->GetTargetOpacity());
+  EXPECT_FALSE(window->layer()->GetTargetVisibility());
+  EXPECT_FALSE(window->layer()->visible());
+  EXPECT_EQ(gfx::Rect(-142, 8, 100, 100), window->layer()->GetTargetBounds());
+
+  wm::GetWindowState(window.get())->Maximize();
+  EXPECT_EQ(1.0f, window->layer()->GetTargetOpacity());
+  EXPECT_TRUE(window->layer()->visible());
+  EXPECT_EQ(gfx::Rect(0, 0, 800, 544), window->layer()->GetTargetBounds());
+
+  // Ensure the window is not slided out.
+  window->Hide();
+  EXPECT_EQ(0.0f, window->layer()->GetTargetOpacity());
+  EXPECT_FALSE(window->layer()->GetTargetVisibility());
+  EXPECT_FALSE(window->layer()->visible());
+  EXPECT_EQ(gfx::Rect(0, 0, 800, 544), window->layer()->GetTargetBounds());
 }
 
 }  // namespace ash
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc
index 91e67a7..7600889 100644
--- a/ash/wm/window_state.cc
+++ b/ash/wm/window_state.cc
@@ -551,7 +551,7 @@
       ignore_property_change_(false),
       current_state_(new DefaultState(ToWindowStateType(GetShowState()))) {
   window_->AddObserver(this);
-  UpdatePipState(mojom::WindowStateType::DEFAULT);
+  OnPrePipStateChange(mojom::WindowStateType::DEFAULT);
 }
 
 bool WindowState::GetAlwaysOnTop() const {
@@ -624,13 +624,24 @@
     mojom::WindowStateType old_window_state_type) {
   for (auto& observer : observer_list_)
     observer.OnPreWindowStateTypeChange(this, old_window_state_type);
-  UpdatePipState(old_window_state_type);
+  OnPrePipStateChange(old_window_state_type);
 }
 
 void WindowState::NotifyPostStateTypeChange(
     mojom::WindowStateType old_window_state_type) {
   for (auto& observer : observer_list_)
     observer.OnPostWindowStateTypeChange(this, old_window_state_type);
+  OnPostPipStateChange(old_window_state_type);
+}
+
+void WindowState::OnPostPipStateChange(
+    mojom::WindowStateType old_window_state_type) {
+  if (old_window_state_type == mojom::WindowStateType::PIP) {
+    // The animation type may be FADE_OUT_SLIDE_IN at this point, which we don't
+    // want it to be anymore if the window is not PIP anymore.
+    ::wm::SetWindowVisibilityAnimationType(
+        window_, ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
+  }
 }
 
 void WindowState::SetBoundsDirect(const gfx::Rect& bounds) {
@@ -709,7 +720,8 @@
   CrossFadeAnimation(window_, std::move(old_layer_owner), animation_type);
 }
 
-void WindowState::UpdatePipState(mojom::WindowStateType old_window_state_type) {
+void WindowState::OnPrePipStateChange(
+    mojom::WindowStateType old_window_state_type) {
   auto* widget = views::Widget::GetWidgetForNativeWindow(window());
   if (IsPip()) {
     // widget may not exit in some unit tests.
diff --git a/ash/wm/window_state.h b/ash/wm/window_state.h
index cb121fc..40e4aad 100644
--- a/ash/wm/window_state.h
+++ b/ash/wm/window_state.h
@@ -423,9 +423,13 @@
       const gfx::Rect& bounds,
       gfx::Tween::Type animation_type = gfx::Tween::EASE_OUT);
 
-  // Update PIP related state, such as next window animation type, upon
-  // state change.
-  void UpdatePipState(mojom::WindowStateType old_window_state_type);
+  // Called before the state change and update PIP related state, such as next
+  // window animation type, upon state change.
+  void OnPrePipStateChange(mojom::WindowStateType old_window_state_type);
+
+  // Called after the state change and update PIP related state, such as next
+  // window animation type, upon state change.
+  void OnPostPipStateChange(mojom::WindowStateType old_window_state_type);
 
   // Update the PIP bounds if necessary. This may need to happen when the
   // display work area changes, or if system ui regions like the virtual
diff --git a/ash/wm/window_state_unittest.cc b/ash/wm/window_state_unittest.cc
index 8d83bff..3296d6f 100644
--- a/ash/wm/window_state_unittest.cc
+++ b/ash/wm/window_state_unittest.cc
@@ -673,39 +673,81 @@
   EXPECT_TRUE(window_state->CanConsumeSystemKeys());
 }
 
-TEST_F(WindowStateTest, RestoreStateAfterDismissingPip) {
+TEST_F(WindowStateTest,
+       RestoreStateAfterEnteringPipViaOcculusionAndDismissingPip) {
   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
   wm::WindowState* window_state = wm::GetWindowState(window.get());
   window->Show();
   EXPECT_TRUE(window->layer()->visible());
 
-  // Ensure a maximized window gets maximized again after it enters PIP, gets
-  // minimized, and unminimized.
+  // Ensure a maximized window gets maximized again after it enters PIP via
+  // occlusion, gets minimized, and unminimized.
   window_state->Maximize();
-  ASSERT_TRUE(window_state->IsMaximized());
+  EXPECT_TRUE(window_state->IsMaximized());
 
   const wm::WMEvent enter_pip(wm::WM_EVENT_PIP);
   window_state->OnWMEvent(&enter_pip);
   EXPECT_TRUE(window_state->IsPip());
 
   window_state->Minimize();
-  ASSERT_TRUE(window_state->IsMinimized());
+  EXPECT_TRUE(window_state->IsMinimized());
 
   window_state->Unminimize();
-  ASSERT_TRUE(window_state->IsMaximized());
+  EXPECT_TRUE(window_state->IsMaximized());
 
-  // Ensure a freeform window gets freeform again after it enters PIP, gets
-  // minimized, and unminimized.
+  // Ensure a freeform window gets freeform again after it enters PIP via
+  // occulusion, gets minimized, and unminimized.
   ::wm::SetWindowState(window.get(), ui::SHOW_STATE_NORMAL);
 
   window_state->OnWMEvent(&enter_pip);
   EXPECT_TRUE(window_state->IsPip());
 
   window_state->Minimize();
-  ASSERT_TRUE(window_state->IsMinimized());
+  EXPECT_TRUE(window_state->IsMinimized());
 
   window_state->Unminimize();
-  ASSERT_TRUE(window_state->GetStateType() == mojom::WindowStateType::NORMAL);
+  EXPECT_TRUE(window_state->GetStateType() == mojom::WindowStateType::NORMAL);
+}
+
+TEST_F(WindowStateTest, RestoreStateAfterEnterPipViaMinimizeAndDismissingPip) {
+  std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
+  wm::WindowState* window_state = wm::GetWindowState(window.get());
+  window->Show();
+  EXPECT_TRUE(window->layer()->visible());
+
+  // Ensure a maximized window gets maximized again after it enters PIP via
+  // minimize, gets minimized, and unminimized.
+  window_state->Maximize();
+  EXPECT_TRUE(window_state->IsMaximized());
+
+  window_state->Minimize();
+  EXPECT_TRUE(window_state->IsMinimized());
+
+  const wm::WMEvent enter_pip(wm::WM_EVENT_PIP);
+  window_state->OnWMEvent(&enter_pip);
+  EXPECT_TRUE(window_state->IsPip());
+
+  window_state->Minimize();
+  EXPECT_TRUE(window_state->IsMinimized());
+
+  window_state->Unminimize();
+  EXPECT_TRUE(window_state->IsMaximized());
+
+  // Ensure a freeform window gets freeform again after it enters PIP via
+  // minimize, gets minimized, and unminimized.
+  ::wm::SetWindowState(window.get(), ui::SHOW_STATE_NORMAL);
+
+  window_state->Minimize();
+  EXPECT_TRUE(window_state->IsMinimized());
+
+  window_state->OnWMEvent(&enter_pip);
+  EXPECT_TRUE(window_state->IsPip());
+
+  window_state->Minimize();
+  EXPECT_TRUE(window_state->IsMinimized());
+
+  window_state->Unminimize();
+  EXPECT_TRUE(window_state->GetStateType() == mojom::WindowStateType::NORMAL);
 }
 
 TEST_F(WindowStateTest, SetBoundsUpdatesSizeOfPipRestoreBounds) {
diff --git a/base/BUILD.gn b/base/BUILD.gn
index ccf866f..9aed800 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -757,6 +757,8 @@
     "task/lazy_task_runner.h",
     "task/post_task.cc",
     "task/post_task.h",
+    "task/promise/dependent_list.cc",
+    "task/promise/dependent_list.h",
     "task/scoped_set_task_priority_for_current_thread.cc",
     "task/scoped_set_task_priority_for_current_thread.h",
     "task/sequence_manager/associated_thread_id.cc",
@@ -2569,6 +2571,7 @@
     "task/common/task_annotator_unittest.cc",
     "task/lazy_task_runner_unittest.cc",
     "task/post_task_unittest.cc",
+    "task/promise/dependent_list_unittest.cc",
     "task/scoped_set_task_priority_for_current_thread_unittest.cc",
     "task/sequence_manager/atomic_flag_set_unittest.cc",
     "task/sequence_manager/lazily_deallocated_deque_unittest.cc",
@@ -3150,6 +3153,7 @@
       "android/java/src/org/chromium/base/task/AsyncTask.java",
       "android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java",
       "android/java/src/org/chromium/base/task/DefaultTaskExecutor.java",
+      "android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java",
       "android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java",
       "android/java/src/org/chromium/base/task/PostTask.java",
       "android/java/src/org/chromium/base/task/SequencedTaskRunner.java",
diff --git a/base/android/java/src/org/chromium/base/process_launcher/BindService.java b/base/android/java/src/org/chromium/base/process_launcher/BindService.java
index bde1f2f..bd1b9764 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/BindService.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/BindService.java
@@ -15,6 +15,7 @@
 import android.os.UserHandle;
 
 import java.lang.reflect.Method;
+import java.util.concurrent.Executor;
 
 /**
  * Class of static helper methods to call Context.bindService variants.
@@ -25,7 +26,7 @@
     // Note that handler is not guaranteed to be used, and client still need to correctly handle
     // callbacks on the UI thread.
     static boolean doBindService(Context context, Intent intent, ServiceConnection connection,
-            int flags, Handler handler) {
+            int flags, Handler handler, Executor executor, String instanceName) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
             return bindServiceByCall(context, intent, connection, flags);
         }
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java b/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java
index 43ae259..0233c39 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java
@@ -40,12 +40,12 @@
         @Override
         public ChildProcessConnection createConnection(Context context, ComponentName serviceName,
                 boolean bindToCaller, boolean bindAsExternalService, Bundle serviceBundle) {
-            return new ChildProcessConnection(
-                    context, serviceName, bindToCaller, bindAsExternalService, serviceBundle);
+            return new ChildProcessConnection(context, serviceName, bindToCaller,
+                    bindAsExternalService, serviceBundle, null /* instanceName */);
         }
     }
 
-    // Delay between the call to freeConnection and the connection actually beeing   freed.
+    // Delay between the call to freeConnection and the connection actually beeing freed.
     private static final long FREE_CONNECTION_DELAY_MILLIS = 1;
 
     // The handler of the thread on which all interations should happen.
@@ -225,7 +225,7 @@
         return connection;
     }
 
-    /** Frees a connection and notifies listeners. */
+    /** Free connection allocated by this allocator. */
     private void free(ChildProcessConnection connection) {
         assert isRunningOnLauncherThread();
 
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
index fe89894..06f7c82c 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
@@ -26,6 +26,7 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 import javax.annotation.concurrent.GuardedBy;
 
@@ -85,8 +86,8 @@
 
     @VisibleForTesting
     protected interface ChildServiceConnectionFactory {
-        ChildServiceConnection createConnection(
-                Intent bindIntent, int bindFlags, ChildServiceConnectionDelegate delegate);
+        ChildServiceConnection createConnection(Intent bindIntent, int bindFlags,
+                ChildServiceConnectionDelegate delegate, String instanceName);
     }
 
     /** Interface representing a connection to the Android service. Can be mocked in unit-tests. */
@@ -104,16 +105,21 @@
         private final Intent mBindIntent;
         private final int mBindFlags;
         private final Handler mHandler;
+        private final Executor mExecutor;
         private final ChildServiceConnectionDelegate mDelegate;
+        private final String mInstanceName;
         private boolean mBound;
 
         private ChildServiceConnectionImpl(Context context, Intent bindIntent, int bindFlags,
-                Handler handler, ChildServiceConnectionDelegate delegate) {
+                Handler handler, Executor executor, ChildServiceConnectionDelegate delegate,
+                String instanceName) {
             mContext = context;
             mBindIntent = bindIntent;
             mBindFlags = bindFlags;
             mHandler = handler;
+            mExecutor = executor;
             mDelegate = delegate;
+            mInstanceName = instanceName;
         }
 
         @Override
@@ -121,8 +127,8 @@
             if (!mBound) {
                 try {
                     TraceEvent.begin("ChildProcessConnection.ChildServiceConnectionImpl.bind");
-                    mBound = BindService.doBindService(
-                            mContext, mBindIntent, this, mBindFlags, mHandler);
+                    mBound = BindService.doBindService(mContext, mBindIntent, this, mBindFlags,
+                            mHandler, mExecutor, mInstanceName);
                 } finally {
                     TraceEvent.end("ChildProcessConnection.ChildServiceConnectionImpl.bind");
                 }
@@ -171,6 +177,7 @@
     }
 
     private final Handler mLauncherHandler;
+    private final Executor mLauncherExecutor;
     private final ComponentName mServiceName;
 
     // Parameters passed to the child process through the service binding intent.
@@ -263,16 +270,19 @@
     private boolean mCleanExit;
 
     public ChildProcessConnection(Context context, ComponentName serviceName, boolean bindToCaller,
-            boolean bindAsExternalService, Bundle serviceBundle) {
+            boolean bindAsExternalService, Bundle serviceBundle, String instanceName) {
         this(context, serviceName, bindToCaller, bindAsExternalService, serviceBundle,
-                null /* connectionFactory */);
+                null /* connectionFactory */, instanceName);
     }
 
     @VisibleForTesting
     public ChildProcessConnection(final Context context, ComponentName serviceName,
             boolean bindToCaller, boolean bindAsExternalService, Bundle serviceBundle,
-            ChildServiceConnectionFactory connectionFactory) {
+            ChildServiceConnectionFactory connectionFactory, String instanceName) {
         mLauncherHandler = new Handler();
+        mLauncherExecutor = (Runnable runnable) -> {
+            mLauncherHandler.post(runnable);
+        };
         assert isRunningOnLauncherThread();
         mServiceName = serviceName;
         mServiceBundle = serviceBundle != null ? serviceBundle : new Bundle();
@@ -282,10 +292,10 @@
         if (connectionFactory == null) {
             connectionFactory = new ChildServiceConnectionFactory() {
                 @Override
-                public ChildServiceConnection createConnection(
-                        Intent bindIntent, int bindFlags, ChildServiceConnectionDelegate delegate) {
-                    return new ChildServiceConnectionImpl(
-                            context, bindIntent, bindFlags, mLauncherHandler, delegate);
+                public ChildServiceConnection createConnection(Intent bindIntent, int bindFlags,
+                        ChildServiceConnectionDelegate delegate, String instanceName) {
+                    return new ChildServiceConnectionImpl(context, bindIntent, bindFlags,
+                            mLauncherHandler, mLauncherExecutor, delegate, instanceName);
                 }
             };
         }
@@ -321,11 +331,12 @@
         int defaultFlags = Context.BIND_AUTO_CREATE
                 | (bindAsExternalService ? Context.BIND_EXTERNAL_SERVICE : 0);
 
-        mModerateBinding = connectionFactory.createConnection(intent, defaultFlags, delegate);
+        mModerateBinding =
+                connectionFactory.createConnection(intent, defaultFlags, delegate, instanceName);
         mStrongBinding = connectionFactory.createConnection(
-                intent, defaultFlags | Context.BIND_IMPORTANT, delegate);
+                intent, defaultFlags | Context.BIND_IMPORTANT, delegate, instanceName);
         mWaivedBinding = connectionFactory.createConnection(
-                intent, defaultFlags | Context.BIND_WAIVE_PRIORITY, delegate);
+                intent, defaultFlags | Context.BIND_WAIVE_PRIORITY, delegate, instanceName);
     }
 
     public final IChildProcessService getService() {
diff --git a/base/android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java b/base/android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java
new file mode 100644
index 0000000..d44ef4e
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java
@@ -0,0 +1,63 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.task;
+
+import android.view.Choreographer;
+
+/**
+ * An adapter that allows PostTask to submit Choreographer frame callbacks which
+ * run after the next vsync.
+ */
+final class ChoreographerTaskRunner implements SingleThreadTaskRunner {
+    private final Choreographer mChoreographer;
+
+    ChoreographerTaskRunner(Choreographer choreographer) {
+        mChoreographer = choreographer;
+    }
+
+    @Override
+    public boolean belongsToCurrentThread() {
+        try {
+            return mChoreographer == Choreographer.getInstance();
+        } catch (IllegalStateException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public void postTask(Runnable task) {
+        mChoreographer.postFrameCallback(new Choreographer.FrameCallback() {
+            @Override
+            public void doFrame(long frameTimeNanos) {
+                task.run();
+            }
+        });
+    }
+
+    @Override
+    public void destroy() {
+        // NOP
+    }
+
+    @Override
+    public void disableLifetimeCheck() {
+        // NOP
+    }
+
+    @Override
+    public void postDelayedTask(Runnable task, long delayMillis) {
+        mChoreographer.postFrameCallbackDelayed(new Choreographer.FrameCallback() {
+            @Override
+            public void doFrame(long frameTimeNanos) {
+                task.run();
+            }
+        }, delayMillis);
+    }
+
+    @Override
+    public void initNativeTaskRunner() {
+        // NOP
+    }
+}
diff --git a/base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java b/base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java
index 0613e38..9952c42 100644
--- a/base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java
+++ b/base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java
@@ -4,6 +4,10 @@
 
 package org.chromium.base.task;
 
+import android.view.Choreographer;
+
+import org.chromium.base.ThreadUtils;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -11,15 +15,18 @@
  * The default {@link TaskExecutor} which maps directly to base::ThreadPool.
  */
 class DefaultTaskExecutor implements TaskExecutor {
-    Map<TaskTraits, TaskRunner> mTraitsToRunnerMap = new HashMap<>();
+    private final Map<TaskTraits, TaskRunner> mTraitsToRunnerMap = new HashMap<>();
+    private ChoreographerTaskRunner mChoreographerTaskRunner;
 
     @Override
     public TaskRunner createTaskRunner(TaskTraits taskTraits) {
+        if (taskTraits.mIsChoreographerFrame) return getChoreographerTaskRunner();
         return new TaskRunnerImpl(taskTraits);
     }
 
     @Override
     public SequencedTaskRunner createSequencedTaskRunner(TaskTraits taskTraits) {
+        if (taskTraits.mIsChoreographerFrame) return getChoreographerTaskRunner();
         return new SequencedTaskRunnerImpl(taskTraits);
     }
 
@@ -29,12 +36,13 @@
      */
     @Override
     public SingleThreadTaskRunner createSingleThreadTaskRunner(TaskTraits taskTraits) {
+        if (taskTraits.mIsChoreographerFrame) return getChoreographerTaskRunner();
         // Tasks posted via this API will not execute until after native has started.
         return new SingleThreadTaskRunnerImpl(null, taskTraits);
     }
 
     @Override
-    public void postDelayedTask(TaskTraits taskTraits, Runnable task, long delay) {
+    public synchronized void postDelayedTask(TaskTraits taskTraits, Runnable task, long delay) {
         if (taskTraits.hasExtension()) {
             TaskRunner runner = createTaskRunner(taskTraits);
             runner.postDelayedTask(task, delay);
@@ -57,4 +65,14 @@
     public boolean canRunTaskImmediately(TaskTraits traits) {
         return false;
     }
+
+    private synchronized ChoreographerTaskRunner getChoreographerTaskRunner() {
+        // TODO(alexclarke): Migrate to the new Android UI thread trait when available.
+        ChoreographerTaskRunner choreographerTaskRunner =
+                ThreadUtils.runOnUiThreadBlockingNoException(
+                        () -> { return new ChoreographerTaskRunner(Choreographer.getInstance()); });
+
+        mTraitsToRunnerMap.put(TaskTraits.CHOREOGRAPHER_FRAME, choreographerTaskRunner);
+        return choreographerTaskRunner;
+    }
 }
diff --git a/base/android/java/src/org/chromium/base/task/TaskTraits.java b/base/android/java/src/org/chromium/base/task/TaskTraits.java
index 4b91a32..0633fc7 100644
--- a/base/android/java/src/org/chromium/base/task/TaskTraits.java
+++ b/base/android/java/src/org/chromium/base/task/TaskTraits.java
@@ -54,6 +54,11 @@
     public static final TaskTraits USER_BLOCKING =
             new TaskTraits().taskPriority(TaskPriority.USER_BLOCKING);
 
+    // A bit like requestAnimationFrame, this task will be posted onto the Choreographer
+    // and will be run on the android main thread after the next vsync.
+    public static final TaskTraits CHOREOGRAPHER_FRAME =
+            new TaskTraits().setIsChoreographerFrame(true);
+
     public TaskTraits() {}
 
     private TaskTraits(TaskTraits other) {
@@ -89,6 +94,11 @@
         return taskTraits;
     }
 
+    private TaskTraits setIsChoreographerFrame(boolean isChoreographerFrame) {
+        mIsChoreographerFrame = isChoreographerFrame;
+        return this;
+    }
+
     // For convenience of the JNI code, we use primitive types only.
     // Note shutdown behavior is not supported on android.
     boolean mPrioritySetExplicitly;
@@ -96,6 +106,7 @@
     boolean mMayBlock;
     byte mExtensionId = INVALID_EXTENSION_ID;
     byte mExtensionData[];
+    boolean mIsChoreographerFrame;
 
     /**
      * @return true if this task is using some TaskTraits extension.
@@ -152,6 +163,7 @@
         hash = 37 * hash + (mMayBlock ? 0 : 1);
         hash = 37 * hash + (int) mExtensionId;
         hash = 37 * hash + Arrays.hashCode(mExtensionData);
+        hash = 37 * hash + (mIsChoreographerFrame ? 0 : 1);
         return hash;
     }
 }
diff --git a/base/android/javatests/src/org/chromium/base/task/PostTaskTest.java b/base/android/javatests/src/org/chromium/base/task/PostTaskTest.java
index 022013b..c7ad98c 100644
--- a/base/android/javatests/src/org/chromium/base/task/PostTaskTest.java
+++ b/base/android/javatests/src/org/chromium/base/task/PostTaskTest.java
@@ -18,6 +18,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -95,4 +96,34 @@
             taskQueue.destroy();
         }
     }
+
+    @Test
+    @SmallTest
+    public void testChoreographerFrameTrait() throws Exception {
+        List<Integer> orderList = new ArrayList<>();
+        CountDownLatch latch = new CountDownLatch(2);
+        PostTask.postTask(TaskTraits.CHOREOGRAPHER_FRAME, new Runnable() {
+            @Override
+            public void run() {
+                synchronized (orderList) {
+                    orderList.add(1);
+                    latch.countDown();
+                }
+            }
+        });
+
+        PostTask.postTask(TaskTraits.CHOREOGRAPHER_FRAME, new Runnable() {
+            @Override
+            public void run() {
+                synchronized (orderList) {
+                    orderList.add(2);
+                    latch.countDown();
+                }
+            }
+        });
+
+        latch.await();
+
+        assertThat(orderList, contains(1, 2));
+    }
 }
diff --git a/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java b/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java
index 85ef7018..f5cf7df 100644
--- a/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java
+++ b/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java
@@ -92,7 +92,8 @@
                 @Override
                 public ChildProcessConnection.ChildServiceConnection createConnection(
                         Intent bindIntent, int bindFlags,
-                        ChildProcessConnection.ChildServiceConnectionDelegate delegate) {
+                        ChildProcessConnection.ChildServiceConnectionDelegate delegate,
+                        String instanceName) {
                     ChildServiceConnectionMock connection =
                             spy(new ChildServiceConnectionMock(bindIntent, delegate));
                     if (mFirstServiceConnection == null) {
@@ -154,7 +155,7 @@
         String serviceName = "TestService";
         return new ChildProcessConnection(null /* context */,
                 new ComponentName(packageName, serviceName), bindToCaller, bindAsExternalService,
-                serviceBundle, mServiceConnectionFactory);
+                serviceBundle, mServiceConnectionFactory, null /* instanceName */);
     }
 
     @Test
diff --git a/base/task/common/task_annotator.cc b/base/task/common/task_annotator.cc
index 5b74def..76294de 100644
--- a/base/task/common/task_annotator.cc
+++ b/base/task/common/task_annotator.cc
@@ -78,11 +78,6 @@
       TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), trace_event_name,
       TRACE_ID_MANGLE(GetTaskTraceID(*pending_task)), TRACE_EVENT_FLAG_FLOW_IN);
 
-  // Trace-parsing tools (DevTools, Lighthouse, etc) consume this event
-  // to determine long tasks.
-  // See https://crbug.com/681863 and https://crbug.com/874982
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "RunTask");
-
   // Before running the task, store the task backtrace with the chain of
   // PostTasks that resulted in this call and deliberately alias it to ensure
   // it is on the stack if the task crashes. Be careful not to assume that the
diff --git a/base/task/promise/dependent_list.cc b/base/task/promise/dependent_list.cc
new file mode 100644
index 0000000..cfe0b7d4
--- /dev/null
+++ b/base/task/promise/dependent_list.cc
@@ -0,0 +1,103 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/task/promise/dependent_list.h"
+
+namespace base {
+namespace internal {
+
+DependentList::DependentList(ConstructUnresolved) : head_(0) {}
+
+DependentList::DependentList(ConstructResolved) : head_(kResolvedSentinel) {}
+
+DependentList::DependentList(ConstructRejected) : head_(kRejectedSentinel) {}
+
+DependentList::~DependentList() = default;
+
+DependentList::Node::Node() = default;
+
+DependentList::InsertResult DependentList::Insert(Node* node) {
+  // This method uses std::memory_order_acquire semantics on read (the failure
+  // case of compare_exchange_weak() below is a read) to ensure setting
+  // |node->next| happens-after all memory modifications applied to |prev_head|
+  // before it became |head_|. Conversely it uses std::memory_order_release
+  // semantics on write to ensure that all memory modifications applied to
+  // |node| happened-before it becomes |head_|.
+  DCHECK(!node->next);
+  uintptr_t prev_head = head_.load(std::memory_order_acquire);
+  do {
+    if (prev_head == kResolvedSentinel) {
+      node->next = 0;
+      return InsertResult::FAIL_PROMISE_RESOLVED;
+    }
+
+    if (prev_head == kRejectedSentinel) {
+      node->next = 0;
+      return InsertResult::FAIL_PROMISE_REJECTED;
+    }
+
+    if (prev_head == kCanceledSentinel) {
+      node->next = 0;
+      return InsertResult::FAIL_PROMISE_CANCELED;
+    }
+
+    node->next = reinterpret_cast<Node*>(prev_head);
+  } while (!head_.compare_exchange_weak(
+      prev_head, reinterpret_cast<uintptr_t>(node), std::memory_order_release,
+      std::memory_order_acquire));
+  return InsertResult::SUCCESS;
+}
+
+DependentList::Node* DependentList::ConsumeOnceForResolve() {
+  // The Consume*() methods require std::memory_order_acq_rel semantics because:
+  //   * Need release semantics to ensure that future calls to Insert() (which
+  //     will fail) happen-after memory modifications performed prior to this
+  //     Consume*().
+  //   * Need acquire semantics to synchronize with the last Insert() and ensure
+  //     all memory modifications applied to |head_| before the last Insert()
+  //     happen-before this Consume*().
+  uintptr_t prev_head = std::atomic_exchange_explicit(
+      &head_, kResolvedSentinel, std::memory_order_acq_rel);
+  DCHECK_NE(prev_head, kResolvedSentinel);
+  DCHECK_NE(prev_head, kRejectedSentinel);
+  DCHECK_NE(prev_head, kCanceledSentinel);
+  return reinterpret_cast<Node*>(prev_head);
+}
+
+DependentList::Node* DependentList::ConsumeOnceForReject() {
+  uintptr_t prev_head = std::atomic_exchange_explicit(
+      &head_, kRejectedSentinel, std::memory_order_acq_rel);
+  DCHECK_NE(prev_head, kResolvedSentinel);
+  DCHECK_NE(prev_head, kRejectedSentinel);
+  DCHECK_NE(prev_head, kCanceledSentinel);
+  return reinterpret_cast<Node*>(prev_head);
+}
+
+DependentList::Node* DependentList::ConsumeOnceForCancel() {
+  uintptr_t prev_head = std::atomic_exchange_explicit(
+      &head_, kCanceledSentinel, std::memory_order_acq_rel);
+  DCHECK_NE(prev_head, kResolvedSentinel);
+  DCHECK_NE(prev_head, kRejectedSentinel);
+  DCHECK_NE(prev_head, kCanceledSentinel);
+  return reinterpret_cast<Node*>(prev_head);
+}
+
+bool DependentList::IsResolved() const {
+  return head_.load(std::memory_order_acquire) == kResolvedSentinel;
+}
+
+bool DependentList::IsRejected() const {
+  return head_.load(std::memory_order_acquire) == kRejectedSentinel;
+}
+
+bool DependentList::IsCancelled() const {
+  return head_.load(std::memory_order_acquire) == kCanceledSentinel;
+}
+
+constexpr uintptr_t DependentList::kResolvedSentinel;
+constexpr uintptr_t DependentList::kRejectedSentinel;
+constexpr uintptr_t DependentList::kCanceledSentinel;
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/task/promise/dependent_list.h b/base/task/promise/dependent_list.h
new file mode 100644
index 0000000..02ab141
--- /dev/null
+++ b/base/task/promise/dependent_list.h
@@ -0,0 +1,83 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TASK_PROMISE_DEPENDENT_LIST_H_
+#define BASE_TASK_PROMISE_DEPENDENT_LIST_H_
+
+#include <atomic>
+
+#include "base/base_export.h"
+#include "base/logging.h"
+#include "base/macros.h"
+
+namespace base {
+namespace internal {
+
+class AbstractPromise;
+
+// AbstractPromise needs to know which promises depend upon it. This lock free
+// class stores the list of dependents. This is not a general purpose list
+// because the data can only be consumed once. This class' methods have implicit
+// acquire/release semantics (i.e., callers can assume the result they get
+// happens-after memory changes which lead to it).
+class BASE_EXPORT DependentList {
+ public:
+  struct ConstructUnresolved {};
+  struct ConstructResolved {};
+  struct ConstructRejected {};
+
+  explicit DependentList(ConstructUnresolved);
+  explicit DependentList(ConstructResolved);
+  explicit DependentList(ConstructRejected);
+  ~DependentList();
+
+  enum class InsertResult {
+    SUCCESS,
+    FAIL_PROMISE_RESOLVED,
+    FAIL_PROMISE_REJECTED,
+    FAIL_PROMISE_CANCELED,
+  };
+
+  struct BASE_EXPORT Node {
+    Node();
+
+    // TODO(alexclarke): Make this a scoped_refptr.
+    AbstractPromise* dependent;
+    std::atomic<Node*> next{nullptr};
+  };
+
+  // Insert will only succeed if one of the Consume operations hasn't been
+  // called yet. |node| must outlive DependentList, and it can't be altered
+  // after Insert or the release barrier will be ineffective.
+  InsertResult Insert(Node* node);
+
+  // A ConsumeXXX function may only be called once.
+  Node* ConsumeOnceForResolve();
+
+  // A ConsumeXXX function may only be called once.
+  Node* ConsumeOnceForReject();
+
+  // A ConsumeXXX function may only be called once.
+  Node* ConsumeOnceForCancel();
+
+  bool IsResolved() const;
+  bool IsRejected() const;
+  bool IsCancelled() const;
+
+ private:
+  std::atomic<uintptr_t> head_;
+
+  // Special values for |head_| which correspond to various states. If |head_|
+  // contains one of these then Insert() will fail.
+  static constexpr uintptr_t kResolvedSentinel = 1;
+  static constexpr uintptr_t kRejectedSentinel = 2;
+  static constexpr uintptr_t kCanceledSentinel = 3;
+
+  DISALLOW_COPY_AND_ASSIGN(DependentList);
+};
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_TASK_PROMISE_DEPENDENT_LIST_H_
diff --git a/base/task/promise/dependent_list_unittest.cc b/base/task/promise/dependent_list_unittest.cc
new file mode 100644
index 0000000..9df62a2
--- /dev/null
+++ b/base/task/promise/dependent_list_unittest.cc
@@ -0,0 +1,119 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/task/promise/dependent_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace internal {
+
+TEST(DependentList, ConstructUnresolved) {
+  DependentList list(DependentList::ConstructUnresolved{});
+  DependentList::Node node;
+  EXPECT_EQ(DependentList::InsertResult::SUCCESS, list.Insert(&node));
+  EXPECT_FALSE(list.IsRejected());
+  EXPECT_FALSE(list.IsCancelled());
+  EXPECT_FALSE(list.IsResolved());
+}
+
+TEST(DependentList, ConstructResolved) {
+  DependentList list(DependentList::ConstructResolved{});
+  DependentList::Node node;
+  EXPECT_EQ(DependentList::InsertResult::FAIL_PROMISE_RESOLVED,
+            list.Insert(&node));
+  EXPECT_TRUE(list.IsResolved());
+  EXPECT_FALSE(list.IsRejected());
+  EXPECT_FALSE(list.IsCancelled());
+}
+
+TEST(DependentList, ConstructRejected) {
+  DependentList list(DependentList::ConstructRejected{});
+  DependentList::Node node;
+  EXPECT_EQ(DependentList::InsertResult::FAIL_PROMISE_REJECTED,
+            list.Insert(&node));
+  EXPECT_TRUE(list.IsRejected());
+  EXPECT_FALSE(list.IsCancelled());
+  EXPECT_FALSE(list.IsResolved());
+}
+
+TEST(DependentList, ConsumeOnceForResolve) {
+  DependentList list(DependentList::ConstructUnresolved{});
+  DependentList::Node node1;
+  DependentList::Node node2;
+  DependentList::Node node3;
+  EXPECT_EQ(DependentList::InsertResult::SUCCESS, list.Insert(&node1));
+  EXPECT_EQ(DependentList::InsertResult::SUCCESS, list.Insert(&node2));
+  EXPECT_EQ(DependentList::InsertResult::SUCCESS, list.Insert(&node3));
+
+  EXPECT_FALSE(list.IsResolved());
+  DependentList::Node* result = list.ConsumeOnceForResolve();
+  EXPECT_TRUE(list.IsResolved());
+  EXPECT_FALSE(list.IsRejected());
+  EXPECT_FALSE(list.IsCancelled());
+
+  EXPECT_EQ(&node3, result);
+  EXPECT_EQ(&node2, result->next.load());
+  EXPECT_EQ(&node1, result->next.load()->next.load());
+  EXPECT_EQ(nullptr, result->next.load()->next.load()->next.load());
+
+  // Can't insert any more nodes.
+  DependentList::Node node4;
+  EXPECT_EQ(DependentList::InsertResult::FAIL_PROMISE_RESOLVED,
+            list.Insert(&node4));
+}
+
+TEST(DependentList, ConsumeOnceForReject) {
+  DependentList list(DependentList::ConstructUnresolved{});
+  DependentList::Node node1;
+  DependentList::Node node2;
+  DependentList::Node node3;
+  EXPECT_EQ(DependentList::InsertResult::SUCCESS, list.Insert(&node1));
+  EXPECT_EQ(DependentList::InsertResult::SUCCESS, list.Insert(&node2));
+  EXPECT_EQ(DependentList::InsertResult::SUCCESS, list.Insert(&node3));
+
+  EXPECT_FALSE(list.IsRejected());
+  DependentList::Node* result = list.ConsumeOnceForReject();
+  EXPECT_TRUE(list.IsRejected());
+  EXPECT_FALSE(list.IsResolved());
+  EXPECT_FALSE(list.IsCancelled());
+
+  EXPECT_EQ(&node3, result);
+  EXPECT_EQ(&node2, result->next.load());
+  EXPECT_EQ(&node1, result->next.load()->next.load());
+  EXPECT_EQ(nullptr, result->next.load()->next.load()->next.load());
+
+  // Can't insert any more nodes.
+  DependentList::Node node4;
+  EXPECT_EQ(DependentList::InsertResult::FAIL_PROMISE_REJECTED,
+            list.Insert(&node4));
+}
+
+TEST(DependentList, ConsumeOnceForCancel) {
+  DependentList list(DependentList::ConstructUnresolved{});
+  DependentList::Node node1;
+  DependentList::Node node2;
+  DependentList::Node node3;
+  EXPECT_EQ(DependentList::InsertResult::SUCCESS, list.Insert(&node1));
+  EXPECT_EQ(DependentList::InsertResult::SUCCESS, list.Insert(&node2));
+  EXPECT_EQ(DependentList::InsertResult::SUCCESS, list.Insert(&node3));
+
+  EXPECT_FALSE(list.IsCancelled());
+  DependentList::Node* result = list.ConsumeOnceForCancel();
+  EXPECT_TRUE(list.IsCancelled());
+  EXPECT_FALSE(list.IsResolved());
+  EXPECT_FALSE(list.IsRejected());
+
+  EXPECT_EQ(&node3, result);
+  EXPECT_EQ(&node2, result->next.load());
+  EXPECT_EQ(&node1, result->next.load()->next.load());
+  EXPECT_EQ(nullptr, result->next.load()->next.load()->next.load());
+
+  // Can't insert any more nodes.
+  DependentList::Node node4;
+  EXPECT_EQ(DependentList::InsertResult::FAIL_PROMISE_CANCELED,
+            list.Insert(&node4));
+}
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/task/sequence_manager/task_queue.h b/base/task/sequence_manager/task_queue.h
index e9dbcbe..e90891c 100644
--- a/base/task/sequence_manager/task_queue.h
+++ b/base/task/sequence_manager/task_queue.h
@@ -208,6 +208,8 @@
     // created on.
     void SetVoteToEnable(bool enabled);
 
+    bool IsVotingToEnable() const { return enabled_; }
+
    private:
     friend class TaskQueue;
     explicit QueueEnabledVoter(scoped_refptr<TaskQueue> task_queue);
diff --git a/base/task/sequence_manager/thread_controller_impl.cc b/base/task/sequence_manager/thread_controller_impl.cc
index aba6306..d8754f4 100644
--- a/base/task/sequence_manager/thread_controller_impl.cc
+++ b/base/task/sequence_manager/thread_controller_impl.cc
@@ -182,6 +182,12 @@
       // Trace events should finish before we call DidRunTask to ensure that
       // SequenceManager trace events do not interfere with them.
       TRACE_TASK_EXECUTION("ThreadControllerImpl::RunTask", *task);
+
+      // Trace-parsing tools (DevTools, Lighthouse, etc) consume this event
+      // to determine long tasks.
+      // See https://crbug.com/681863 and https://crbug.com/874982
+      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "RunTask");
+
       task_annotator_.RunTask("SequenceManager RunTask", &*task);
     }
 
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
index e748957..cb4369f 100644
--- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
+++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
@@ -349,6 +349,11 @@
 
     work_id_provider_->IncrementWorkId();
 
+    // Trace-parsing tools (DevTools, Lighthouse, etc) consume this event
+    // to determine long tasks.
+    // See https://crbug.com/681863 and https://crbug.com/874982
+    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "RunTask");
+
     {
       // Trace events should finish before we call DidRunTask to ensure that
       // SequenceManager trace events do not interfere with them.
diff --git a/base/task/thread_pool/platform_native_worker_pool_win.cc b/base/task/thread_pool/platform_native_worker_pool_win.cc
index 5771063..9b16a5e 100644
--- a/base/task/thread_pool/platform_native_worker_pool_win.cc
+++ b/base/task/thread_pool/platform_native_worker_pool_win.cc
@@ -4,26 +4,13 @@
 
 #include "base/task/thread_pool/platform_native_worker_pool_win.h"
 
-#include "base/no_destructor.h"
+#include "base/optional.h"
 #include "base/task/thread_pool/task_tracker.h"
-#include "base/threading/thread_local.h"
 #include "base/win/scoped_com_initializer.h"
 
 namespace base {
 namespace internal {
 
-namespace {
-
-// Used to enable COM MTA when creating threads via the Windows Thread Pool API.
-ThreadLocalOwnedPointer<win::ScopedCOMInitializer>&
-ScopedCOMInitializerForCurrentThread() {
-  static base::NoDestructor<ThreadLocalOwnedPointer<win::ScopedCOMInitializer>>
-      scoped_com_initializer;
-  return *scoped_com_initializer;
-}
-
-}  // namespace
-
 PlatformNativeWorkerPoolWin::PlatformNativeWorkerPoolWin(
     TrackedRef<TaskTracker> task_tracker,
     TrackedRef<Delegate> delegate,
@@ -69,20 +56,12 @@
   auto* worker_pool = static_cast<PlatformNativeWorkerPoolWin*>(
       scheduler_worker_pool_windows_impl);
 
-  if (worker_pool->worker_environment_ == WorkerEnvironment::COM_MTA) {
-    if (!ScopedCOMInitializerForCurrentThread().Get()) {
-      ScopedCOMInitializerForCurrentThread().Set(
-          std::make_unique<win::ScopedCOMInitializer>(
-              win::ScopedCOMInitializer::kMTA));
-    }
-  } else if (worker_pool->worker_environment_ == WorkerEnvironment::NONE) {
-    // Upon destruction, a PTP_POOL object might not destroy the threads it
-    // created, and another PTP_POOL object created in the same process might
-    // reuse the old threads. Consequently, it is possible to be on a COM
-    // initialized thread even if |worker_environment_| is NONE. In this case,
-    // COM is uninitialized by explicitly resetting the ScopedCOMInitializer.
-    ScopedCOMInitializerForCurrentThread().Set(nullptr);
-  }
+  // Windows Thread Pool API best practices state that all resources created
+  // in the callback function should be cleaned up before returning from the
+  // function. This includes COM initialization.
+  Optional<win::ScopedCOMInitializer> com_initializer;
+  if (worker_pool->worker_environment_ == WorkerEnvironment::COM_MTA)
+    com_initializer.emplace(win::ScopedCOMInitializer::kMTA);
 
   worker_pool->RunNextSequenceImpl();
 }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java b/base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java
index ae91b44..9f58a83 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java
@@ -43,14 +43,14 @@
      */
     public TestChildProcessConnection(ComponentName serviceName, boolean bindToCaller,
             boolean bindAsExternalService, Bundle serviceBundle) {
-        super(null /* context */, serviceName, bindToCaller, bindAsExternalService, serviceBundle,
-                new ChildServiceConnectionFactory() {
+        super(null /* context */, serviceName, bindToCaller, bindAsExternalService,
+                serviceBundle, new ChildServiceConnectionFactory() {
                     @Override
                     public ChildServiceConnection createConnection(Intent bindIntent, int bindFlags,
-                            ChildServiceConnectionDelegate delegate) {
+                            ChildServiceConnectionDelegate delegate, String instanceName) {
                         return new MockChildServiceConnection();
                     }
-                });
+                }, null /* instanceName */);
     }
 
     public void setPid(int pid) {
diff --git a/base/test/values_test_util.cc b/base/test/values_test_util.cc
index 007e6f6..5016d56 100644
--- a/base/test/values_test_util.cc
+++ b/base/test/values_test_util.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -61,6 +62,132 @@
 
 namespace test {
 
+namespace {
+
+std::string FormatAsJSON(const base::Value& value) {
+  std::string json;
+  JSONWriter::Write(value, &json);
+  return json;
+}
+
+class DictionaryHasValueMatcher
+    : public testing::MatcherInterface<const base::Value&> {
+ public:
+  DictionaryHasValueMatcher(const std::string& key,
+                            const base::Value& expected_value)
+      : key_(key), expected_value_(expected_value.Clone()) {}
+
+  ~DictionaryHasValueMatcher() = default;
+
+  bool MatchAndExplain(const base::Value& value,
+                       testing::MatchResultListener* listener) const override {
+    if (!value.is_dict()) {
+      *listener << "The value '" << FormatAsJSON(value)
+                << "' is not a dictionary";
+      return false;
+    }
+    const base::Value* sub_value = value.FindKey(key_);
+    if (!sub_value) {
+      *listener << "Dictionary '" << FormatAsJSON(value)
+                << "' does not have key '" << key_ << "'";
+      return false;
+    }
+    if (*sub_value != expected_value_) {
+      *listener << "Dictionary value under key '" << key_ << "' is '"
+                << FormatAsJSON(*sub_value) << "', expected '"
+                << FormatAsJSON(expected_value_) << "'";
+      return false;
+    }
+    return true;
+  }
+
+  void DescribeTo(std::ostream* os) const override {
+    *os << "has key '" << key_ << "' with value '"
+        << FormatAsJSON(expected_value_) << "'";
+  }
+
+  void DescribeNegationTo(std::ostream* os) const override {
+    *os << "does not have key '" << key_ << "' with value '"
+        << FormatAsJSON(expected_value_) << "'";
+  }
+
+ private:
+  DictionaryHasValueMatcher& operator=(const DictionaryHasValueMatcher& other) =
+      delete;
+
+  const std::string key_;
+  const base::Value expected_value_;
+};
+
+class DictionaryHasValuesMatcher
+    : public testing::MatcherInterface<const base::Value&> {
+ public:
+  DictionaryHasValuesMatcher(const base::Value& template_value)
+      : template_value_(template_value.Clone()) {
+    CHECK(template_value.is_dict());
+  }
+
+  ~DictionaryHasValuesMatcher() = default;
+
+  bool MatchAndExplain(const base::Value& value,
+                       testing::MatchResultListener* listener) const override {
+    if (!value.is_dict()) {
+      *listener << "The value '" << FormatAsJSON(value)
+                << "' is not a dictionary";
+      return false;
+    }
+
+    bool ok = true;
+    for (const auto& template_dict_item : template_value_.DictItems()) {
+      const base::Value* sub_value = value.FindKey(template_dict_item.first);
+      if (!sub_value) {
+        *listener << "\nDictionary does not have key '"
+                  << template_dict_item.first << "'";
+        ok = false;
+        continue;
+      }
+      if (*sub_value != template_dict_item.second) {
+        *listener << "\nDictionary value under key '"
+                  << template_dict_item.first << "' is '"
+                  << FormatAsJSON(*sub_value) << "', expected '"
+                  << FormatAsJSON(template_dict_item.second) << "'";
+        ok = false;
+      }
+    }
+    return ok;
+  }
+
+  void DescribeTo(std::ostream* os) const override {
+    *os << "contains all key-values from '" << FormatAsJSON(template_value_)
+        << "'";
+  }
+
+  void DescribeNegationTo(std::ostream* os) const override {
+    *os << "does not contain key-values from '" << FormatAsJSON(template_value_)
+        << "'";
+  }
+
+ private:
+  DictionaryHasValueMatcher& operator=(const DictionaryHasValueMatcher& other) =
+      delete;
+
+  const base::Value template_value_;
+};
+
+}  // namespace
+
+testing::Matcher<const base::Value&> DictionaryHasValue(
+    const std::string& key,
+    const base::Value& expected_value) {
+  return testing::MakeMatcher(
+      new DictionaryHasValueMatcher(key, expected_value));
+}
+
+testing::Matcher<const base::Value&> DictionaryHasValues(
+    const base::Value& template_value) {
+  return testing::MakeMatcher(new DictionaryHasValuesMatcher(template_value));
+}
+
 IsJsonMatcher::IsJsonMatcher(base::StringPiece json)
     : expected_value_(test::ParseJson(json)) {}
 
diff --git a/base/test/values_test_util.h b/base/test/values_test_util.h
index c7d5509..7f48bfd 100644
--- a/base/test/values_test_util.h
+++ b/base/test/values_test_util.h
@@ -42,6 +42,17 @@
 
 namespace test {
 
+// A custom GMock matcher which matches if a base::Value is a dictionary which
+// has a key |key| that is equal to |value|.
+testing::Matcher<const base::Value&> DictionaryHasValue(
+    const std::string& key,
+    const base::Value& expected_value);
+
+// A custom GMock matcher which matches if a base::Value is a dictionary which
+// contains all key/value pairs from |template_value|.
+testing::Matcher<const base::Value&> DictionaryHasValues(
+    const base::Value& template_value);
+
 // A custom GMock matcher.  For details, see
 // https://github.com/google/googletest/blob/644319b9f06f6ca9bf69fe791be399061044bc3d/googlemock/docs/CookBook.md#writing-new-polymorphic-matchers
 class IsJsonMatcher {
diff --git a/build/android/gyp/create_app_bundle.py b/build/android/gyp/create_app_bundle.py
index 9666feb3..b7b5106f 100755
--- a/build/android/gyp/create_app_bundle.py
+++ b/build/android/gyp/create_app_bundle.py
@@ -25,11 +25,11 @@
 # Location of language-based assets in bundle modules.
 _LOCALES_SUBDIR = 'assets/locales/'
 
-# The fallback locale should always have its .pak file included in
+# The fallback language should always have its .pak files included in
 # the base apk, i.e. not use language-based asset targetting. This ensures
 # that Chrome won't crash on startup if its bundle is installed on a device
 # with an unsupported system locale (e.g. fur-rIT).
-_FALLBACK_LOCALE = 'en-US'
+_FALLBACK_LANGUAGE = 'en'
 
 # List of split dimensions recognized by this tool.
 _ALL_SPLIT_DIMENSIONS = [ 'ABI', 'SCREEN_DENSITY', 'LANGUAGE' ]
@@ -178,9 +178,6 @@
   # Whether other .so files are compressed is controlled by
   # "uncompressNativeLibraries".
   uncompressed_globs = ['lib/*/crazy.*']
-  # Locale-specific pak files stored in bundle splits need not be compressed.
-  uncompressed_globs.extend(
-      ['assets/locales#lang_*/*.pak', 'assets/fallback-locales/*.pak'])
   uncompressed_globs.extend('assets/' + x for x in uncompressed_assets)
   # NOTE: Use '**' instead of '*' to work through directories!
   uncompressed_globs.extend('**.' + ext for ext in _UNCOMPRESSED_FILE_EXTS)
@@ -230,8 +227,8 @@
   else:
     android_language = android_locale
 
-  if locale == _FALLBACK_LOCALE:
-    # Fallback locale .pak files must be placed in a different directory
+  if android_language == _FALLBACK_LANGUAGE:
+    # Fallback language .pak files must be placed in a different directory
     # to ensure they are always stored in the base module.
     result_path = 'assets/fallback-locales/%s.pak' % locale
   else:
diff --git a/build/chromeos/create_test_runner_script.py b/build/chromeos/create_test_runner_script.py
index 0cbe38ba..161b9a71 100755
--- a/build/chromeos/create_test_runner_script.py
+++ b/build/chromeos/create_test_runner_script.py
@@ -63,13 +63,7 @@
   run_test_path = RelativizePathToScript(
       os.path.join(os.path.dirname(__file__), 'test_runner.py'))
 
-  vm_test_args = [
-      '--board', args.board,
-      '-v',
-  ]
-  if args.use_vm:
-    vm_test_args += ['--use-vm']
-
+  vm_test_args = []
   if args.test_exe:
     vm_test_args.extend([
         'vm-test',
@@ -95,6 +89,13 @@
     if args.deploy_chrome:
       vm_test_args.append('--deploy-chrome')
 
+  vm_test_args += [
+      '--board', args.board,
+      '-v',
+  ]
+  if args.use_vm:
+    vm_test_args += ['--use-vm']
+
   vm_test_path_args = [
       ('--cros-cache', RelativizePathToScript(args.cros_cache)),
   ]
diff --git a/build/chromeos/test_runner.py b/build/chromeos/test_runner.py
index 6b26cb1..e3581fb 100755
--- a/build/chromeos/test_runner.py
+++ b/build/chromeos/test_runner.py
@@ -679,45 +679,46 @@
   return env
 
 
-def add_common_args(parser):
-  parser.add_argument(
-      '--cros-cache', type=str, default=DEFAULT_CROS_CACHE,
-      help='Path to cros cache.')
-  parser.add_argument(
-      '--path-to-outdir', type=str, required=True,
-      help='Path to output directory, all of whose contents will be '
-           'deployed to the device.')
-  parser.add_argument(
-      '--runtime-deps-path', type=str,
-      help='Runtime data dependency file from GN.')
-  parser.add_argument(
-      '--vpython-dir', type=str,
-      help='Location on host of a directory containing a vpython binary to '
-           'deploy to the device before the test starts. The location of this '
-           'dir will be added onto PATH in the device. WARNING: The arch of '
-           'the device might not match the arch of the host, so avoid using '
-           '"${platform}" when downloading vpython via CIPD.')
-  # TODO(bpastene): Switch all uses of "--vm-logs-dir" to "--logs-dir".
-  parser.add_argument(
-      '--vm-logs-dir', '--logs-dir', type=str, dest='logs_dir',
-      help='Will copy everything under /var/log/ from the device after the '
-           'test into the specified dir.')
+def add_common_args(*parsers):
+  for parser in parsers:
+    parser.add_argument('--verbose', '-v', action='store_true')
+    parser.add_argument(
+        '--board', type=str, required=True, help='Type of CrOS device.')
+    parser.add_argument(
+        '--cros-cache', type=str, default=DEFAULT_CROS_CACHE,
+        help='Path to cros cache.')
+    parser.add_argument(
+        '--path-to-outdir', type=str, required=True,
+        help='Path to output directory, all of whose contents will be '
+             'deployed to the device.')
+    parser.add_argument(
+        '--runtime-deps-path', type=str,
+        help='Runtime data dependency file from GN.')
+    parser.add_argument(
+        '--vpython-dir', type=str,
+        help='Location on host of a directory containing a vpython binary to '
+             'deploy to the device before the test starts. The location of '
+             'this dir will be added onto PATH in the device. WARNING: The '
+             'arch of the device might not match the arch of the host, so '
+             'avoid using "${platform}" when downloading vpython via CIPD.')
+    # TODO(bpastene): Switch all uses of "--vm-logs-dir" to "--logs-dir".
+    parser.add_argument(
+        '--vm-logs-dir', '--logs-dir', type=str, dest='logs_dir',
+        help='Will copy everything under /var/log/ from the device after the '
+             'test into the specified dir.')
+
+    vm_or_device_group = parser.add_mutually_exclusive_group()
+    vm_or_device_group.add_argument(
+        '--use-vm', action='store_true',
+        help='Will run the test in the VM instead of a device.')
+    vm_or_device_group.add_argument(
+        '--device', type=str,
+        help='Hostname (or IP) of device to run the test on. This arg is not '
+             'required if --use-vm is set.')
 
 
 def main():
   parser = argparse.ArgumentParser()
-  parser.add_argument('--verbose', '-v', action='store_true')
-  # Required args.
-  parser.add_argument(
-      '--board', type=str, required=True, help='Type of CrOS device.')
-  vm_or_device_group = parser.add_mutually_exclusive_group()
-  vm_or_device_group.add_argument(
-      '--use-vm', action='store_true',
-      help='Will run the test in the VM instead of a device.')
-  vm_or_device_group.add_argument(
-      '--device', type=str,
-      help='Hostname (or IP) of device to run the test on. This arg is not '
-           'required if --use-vm is set.')
   subparsers = parser.add_subparsers(dest='test_type')
   # Host-side test args.
   host_cmd_parser = subparsers.add_parser(
@@ -727,13 +728,6 @@
            'will be 127.0.0.1:9222.')
   host_cmd_parser.set_defaults(func=host_cmd)
   host_cmd_parser.add_argument(
-      '--cros-cache', type=str, default=DEFAULT_CROS_CACHE,
-      help='Path to cros cache.')
-  host_cmd_parser.add_argument(
-      '--path-to-outdir', type=os.path.realpath,
-      help='Path to output directory, all of whose contents will be deployed '
-           'to the device.')
-  host_cmd_parser.add_argument(
       '--deploy-chrome', action='store_true',
       help='Will deploy a locally built Chrome binary to the device before '
            'running the host-cmd.')
@@ -797,8 +791,7 @@
       help='Use the host-side Tast bin to run the tests instead of the '
            'DUT-side local_test_runner. TODO(bpastene): Make this default.')
 
-  add_common_args(gtest_parser)
-  add_common_args(tast_test_parser)
+  add_common_args(gtest_parser, tast_test_parser, host_cmd_parser)
   args, unknown_args = parser.parse_known_args()
 
   logging.basicConfig(level=logging.DEBUG if args.verbose else logging.WARN)
diff --git a/cc/input/scroll_snap_data.cc b/cc/input/scroll_snap_data.cc
index de776f3..b09ded1e 100644
--- a/cc/input/scroll_snap_data.cc
+++ b/cc/input/scroll_snap_data.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "cc/input/scroll_snap_data.h"
+#include "base/numerics/ranges.h"
 #include "cc/input/snap_selection_strategy.h"
 
 #include <algorithm>
@@ -61,10 +62,10 @@
 }
 
 void SnapSearchResult::Clip(float max_snap, float max_visible) {
-  snap_offset_ = std::max(std::min(snap_offset_, max_snap), 0.0f);
+  snap_offset_ = base::ClampToRange(snap_offset_, 0.0f, max_snap);
   visible_range_ =
-      gfx::RangeF(std::max(std::min(visible_range_.start(), max_visible), 0.0f),
-                  std::max(std::min(visible_range_.end(), max_visible), 0.0f));
+      gfx::RangeF(base::ClampToRange(visible_range_.start(), 0.0f, max_visible),
+                  base::ClampToRange(visible_range_.end(), 0.0f, max_visible));
 }
 
 void SnapSearchResult::Union(const SnapSearchResult& other) {
@@ -124,16 +125,20 @@
   // A region that includes every reachable scroll position.
   gfx::RectF scrollable_region(0, 0, max_position_.x(), max_position_.y());
   if (should_snap_on_x) {
-    // Start from current position in the cross axis and assume it's always
-    // visible.
+    // Start from current position in the cross axis. The search algorithm
+    // expects the cross axis position to be inside scroller bounds. But since
+    // we cannot always assume that the incoming value fits this criteria we
+    // clamp it to the bounds to ensure this variant.
     SnapSearchResult initial_snap_position_y = {
-        base_position.y(), gfx::RangeF(0, max_position_.x())};
+        base::ClampToRange(base_position.y(), 0.f, max_position_.y()),
+        gfx::RangeF(0, max_position_.x())};
     closest_x =
         FindClosestValidArea(SearchAxis::kX, strategy, initial_snap_position_y);
   }
   if (should_snap_on_y) {
     SnapSearchResult initial_snap_position_x = {
-        base_position.x(), gfx::RangeF(0, max_position_.y())};
+        base::ClampToRange(base_position.x(), 0.f, max_position_.x()),
+        gfx::RangeF(0, max_position_.y())};
     closest_y =
         FindClosestValidArea(SearchAxis::kY, strategy, initial_snap_position_x);
   }
@@ -170,9 +175,9 @@
 base::Optional<SnapSearchResult> SnapContainerData::FindClosestValidArea(
     SearchAxis axis,
     const SnapSelectionStrategy& strategy,
-    const SnapSearchResult& cros_axis_snap_result) const {
+    const SnapSearchResult& cross_axis_snap_result) const {
   base::Optional<SnapSearchResult> result =
-      FindClosestValidAreaInternal(axis, strategy, cros_axis_snap_result);
+      FindClosestValidAreaInternal(axis, strategy, cross_axis_snap_result);
 
   // For EndAndDirectionStrategy, if there is a snap area with snap-stop:always,
   // and is between the starting position and the above result, we should choose
@@ -189,7 +194,7 @@
             SnapStopAlwaysFilter::kRequire);
     base::Optional<SnapSearchResult> must_only_result =
         FindClosestValidAreaInternal(axis, *must_only_strategy,
-                                     cros_axis_snap_result, false);
+                                     cross_axis_snap_result, false);
     result = ClosestSearchResult(strategy.current_position(), axis, result,
                                  must_only_result);
   }
@@ -209,15 +214,21 @@
                                                   strategy.ShouldSnapOnX(),
                                                   strategy.ShouldSnapOnY());
   return FindClosestValidAreaInternal(axis, *relaxed_strategy,
-                                      cros_axis_snap_result);
+                                      cross_axis_snap_result);
 }
 
 base::Optional<SnapSearchResult>
 SnapContainerData::FindClosestValidAreaInternal(
     SearchAxis axis,
     const SnapSelectionStrategy& strategy,
-    const SnapSearchResult& cros_axis_snap_result,
+    const SnapSearchResult& cross_axis_snap_result,
     bool should_consider_covering) const {
+  // The cross axis result is expected to be within bounds otherwise no snap
+  // area will meet the mutual visibility requirement.
+  DCHECK(cross_axis_snap_result.snap_offset() >= 0 &&
+         cross_axis_snap_result.snap_offset() <=
+             (axis == SearchAxis::kX ? max_position_.y() : max_position_.x()));
+
   // The search result from the snap area that's closest to the search origin.
   base::Optional<SnapSearchResult> closest;
   // The search result with the intended position if it makes a snap area cover
@@ -251,7 +262,7 @@
       // position as a valid snap position.
       SnapSearchResult covering_candidate = candidate;
       covering_candidate.set_snap_offset(intended_position);
-      if (IsMutualVisible(covering_candidate, cros_axis_snap_result))
+      if (IsMutualVisible(covering_candidate, cross_axis_snap_result))
         SetOrUpdateResult(covering_candidate, &covering);
       // Even if a snap area covers the snapport, we need to continue this
       // search to find previous and next snap positions and also to have
@@ -259,7 +270,7 @@
       // rejected. And this covering snap area has its own alignment that may
       // generates a snap position rejecting the current inplace candidate.
     }
-    if (!IsMutualVisible(candidate, cros_axis_snap_result))
+    if (!IsMutualVisible(candidate, cross_axis_snap_result))
       continue;
 
     float distance = std::abs(candidate.snap_offset() - base_position);
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc
index bbdf374..4a24864 100644
--- a/cc/raster/one_copy_raster_buffer_provider.cc
+++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -292,13 +292,12 @@
     const RasterSource::PlaybackSettings& playback_settings,
     uint64_t previous_content_id,
     uint64_t new_content_id) {
-  // Allocate GpuMemoryBuffer if necessary. If using partial raster, we
-  // must allocate a buffer with BufferUsage CPU_READ_WRITE_PERSISTENT.
+  // Allocate GpuMemoryBuffer if necessary.
   if (!staging_buffer->gpu_memory_buffer) {
     staging_buffer->gpu_memory_buffer =
         gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
-            staging_buffer->size, BufferFormat(format), StagingBufferUsage(),
-            gpu::kNullSurfaceHandle);
+            staging_buffer->size, BufferFormat(format),
+            gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gpu::kNullSurfaceHandle);
   }
 
   gfx::Rect playback_rect = raster_full_rect;
@@ -483,12 +482,6 @@
   return out_sync_token;
 }
 
-gfx::BufferUsage OneCopyRasterBufferProvider::StagingBufferUsage() const {
-  return use_partial_raster_
-             ? gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT
-             : gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
-}
-
 bool OneCopyRasterBufferProvider::CheckRasterFinishedQueries() {
   return false;
 }
diff --git a/cc/raster/one_copy_raster_buffer_provider.h b/cc/raster/one_copy_raster_buffer_provider.h
index 40aaf1d..a307c01 100644
--- a/cc/raster/one_copy_raster_buffer_provider.h
+++ b/cc/raster/one_copy_raster_buffer_provider.h
@@ -144,7 +144,6 @@
                                     bool mailbox_texture_is_overlay_candidate,
                                     const gpu::SyncToken& sync_token,
                                     const gfx::ColorSpace& color_space);
-  gfx::BufferUsage StagingBufferUsage() const;
 
   viz::ContextProvider* const compositor_context_provider_;
   viz::RasterContextProvider* const worker_context_provider_;
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 9b29f36..5548c43 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2439,6 +2439,7 @@
     "java/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizer.java",
     "java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java",
     "java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswersImageFetcher.java",
     "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java",
     "java/src/org/chromium/chrome/browser/page_info/CertificateChainHelper.java",
     "java/src/org/chromium/chrome/browser/page_info/CertificateViewer.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 9ef806e3..bc6831a 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -1138,6 +1138,7 @@
   "java/src/org/chromium/chrome/browser/omnibox/status/StatusViewBinder.java",
   "java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java",
   "java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java",
+  "java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswersImageFetcher.java",
   "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java",
   "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java",
   "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index 7e24eed..32fcfbc 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -473,6 +473,7 @@
   "javatests/src/org/chromium/chrome/browser/tabmodel/TestTabModelDirectory.java",
   "javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java",
   "javatests/src/org/chromium/chrome/browser/tabmodel/document/MockDocumentTabModel.java",
+  "javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java",
   "javatests/src/org/chromium/chrome/browser/test/ChromeBrowserTestRule.java",
   "javatests/src/org/chromium/chrome/browser/test/ClearAppDataTestRule.java",
   "javatests/src/org/chromium/chrome/browser/test/CommandLineInitRule.java",
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridContainerViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridContainerViewBinderTest.java
index 89644e5..fd6613b 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridContainerViewBinderTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridContainerViewBinderTest.java
@@ -21,6 +21,7 @@
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.chrome.R;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ui.DummyUiActivity;
@@ -97,6 +98,8 @@
 
     @Test
     @MediumTest
+    @DisabledTest
+    // Failed multiple times on Android CFI https://crbug.com/954145
     public void testShowWithAnimation() throws Exception {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             mContainerModel.set(
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml
index f7015d4..4280f4a 100644
--- a/chrome/android/java/res/values/colors.xml
+++ b/chrome/android/java/res/values/colors.xml
@@ -10,7 +10,7 @@
     <color name="default_primary_color">#F2F2F2</color>
     <color name="input_underline_error_color">#D32F2F</color>
     <color name="explanation_text_color">#909090</color>
-    <color name="text_highlight_color">#C6DAFC</color>
+    <color name="text_highlight_color">@color/highlight_color_on_dark_text</color>
 
     <!-- Control colors for toggles, checkboxes, ratio buttons, list item highlight, and accent.
          Note that these should NOT be used for icon tint. -->
@@ -141,7 +141,6 @@
     <!-- LocationBar colors -->
     <color name="locationbar_dark_hint_text">@color/search_box_hint</color>
     <color name="locationbar_light_hint_text">@color/white_alpha_70</color>
-    <color name="locationbar_light_selection_color">#CC5595FE</color>
     <color name="locationbar_status_offline_color">@color/modern_grey_900</color>
     <color name="locationbar_status_offline_color_light">@android:color/white</color>
     <color name="locationbar_status_preview_color">@color/modern_blue_600</color>
diff --git a/chrome/android/java/res_night/values-night/colors.xml b/chrome/android/java/res_night/values-night/colors.xml
index cd9130f..4939b20 100644
--- a/chrome/android/java/res_night/values-night/colors.xml
+++ b/chrome/android/java/res_night/values-night/colors.xml
@@ -6,6 +6,7 @@
 <resources>
     <color name="light_active_color">@color/modern_blue_300</color>
     <color name="control_normal_color">@color/modern_grey_500</color>
+    <color name="text_highlight_color">@color/highlight_color_on_light_text</color>
 
     <color name="toolbar_text_box_background">@color/modern_grey_800</color>
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/BitmapCache.java b/chrome/android/java/src/org/chromium/chrome/browser/BitmapCache.java
index 67b9806..d7b2d53 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/BitmapCache.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/BitmapCache.java
@@ -121,14 +121,6 @@
         sDeduplicationCache.put(key, new WeakReference<>(bitmap));
     }
 
-    /**
-     * Evict all bitmaps from the cache.
-     */
-    public void clear() {
-        getBitmapCache().evictAll();
-        scheduleDeduplicationCache();
-    }
-
     /** @return The total number of bytes taken by the bitmaps in this cache. */
     public int size() {
         return getBitmapCache().size();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeInactivityTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeInactivityTracker.java
index 0693c2b..ee35000 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeInactivityTracker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeInactivityTracker.java
@@ -11,13 +11,15 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
+import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver;
 import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 
 /**
  * Manages pref that can track the delay since the last stop of the tracked activity.
  */
-public class ChromeInactivityTracker implements StartStopWithNativeObserver, Destroyable {
+public class ChromeInactivityTracker
+        implements StartStopWithNativeObserver, PauseResumeWithNativeObserver, Destroyable {
     private static final String TAG = "InactivityTracker";
 
     private static final long UNKNOWN_LAST_BACKGROUNDED_TIME = -1;
@@ -90,12 +92,8 @@
                 FEATURE_NAME, NTP_LAUNCH_DELAY_IN_MINS_PARAM, DEFAULT_LAUNCH_DELAY_IN_MINS);
 
         mIsEnabled = ChromeFeatureList.isEnabled(FEATURE_NAME);
-        if (mIsEnabled) {
-            mLifecycleDispatcher = lifecycleDispatcher;
-            mLifecycleDispatcher.register(this);
-        } else {
-            mLifecycleDispatcher = null;
-        }
+        mLifecycleDispatcher = lifecycleDispatcher;
+        mLifecycleDispatcher.register(this);
     }
 
     /**
@@ -107,7 +105,15 @@
         ContextUtils.getAppSharedPreferences().edit().putLong(mPrefName, timeInMillis).apply();
     }
 
-    private long getLastBackgroundedTimeMs() {
+    /**
+     * Updates shared preferences such that the last backgrounded time is no
+     * longer valid. This will prevent multiple new intents from firing.
+     */
+    private void clearLastBackgroundedTimeInPrefs() {
+        setLastBackgroundedTimeInPrefs(UNKNOWN_LAST_BACKGROUNDED_TIME);
+    }
+
+    long getLastBackgroundedTimeMs() {
         return ContextUtils.getAppSharedPreferences().getLong(
                 mPrefName, UNKNOWN_LAST_BACKGROUNDED_TIME);
     }
@@ -150,12 +156,29 @@
 
     @Override
     public void onStartWithNative() {
-        setLastBackgroundedTimeInPrefs(UNKNOWN_LAST_BACKGROUNDED_TIME);
         cancelCurrentTask();
     }
 
     @Override
+    public void onResumeWithNative() {
+        // We clear the backgrounded time here, rather than in #onStartWithNative, to give
+        // handlers the chance to respond to inactivity during any onStartWithNative handler
+        // regardless of ordering. onResume is always called after onStart, and it should be fine to
+        // consider Chrome active if it reaches onResume.
+        clearLastBackgroundedTimeInPrefs();
+    }
+
+    @Override
+    public void onPauseWithNative() {}
+
+    @Override
     public void onStopWithNative() {
+        // Always track the last backgrounded time in case others are using the pref.
+        long timeInMillis = System.currentTimeMillis();
+        setLastBackgroundedTimeInPrefs(timeInMillis);
+
+        if (!mIsEnabled) return;
+
         Log.i(TAG, "onStop, scheduling for " + mNtpLaunchDelayInMins + " minutes");
 
         cancelCurrentTask();
@@ -164,7 +187,6 @@
             return;
         }
         mCurrentlyPostedInactiveCallback = new CancelableRunnableTask(mInactiveCallback);
-        setLastBackgroundedTimeInPrefs(System.currentTimeMillis());
         org.chromium.base.task.PostTask.postDelayedTask(UiThreadTaskTraits.DEFAULT,
                 mCurrentlyPostedInactiveCallback,
                 mNtpLaunchDelayInMins * DateUtils.MINUTE_IN_MILLIS);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index e3ba8b3..5552922 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -922,8 +922,7 @@
         boolean isOverviewVisible = mOverviewModeController.overviewVisible();
 
         // Experiment: show tab switcher on return after {x} minutes (enable-tab-switcher-on-return}
-        long lastBackgroundedTimeMillis =
-                ContextUtils.getAppSharedPreferences().getLong(LAST_BACKGROUNDED_TIME_MS_PREF, -1);
+        long lastBackgroundedTimeMillis = mInactivityTracker.getLastBackgroundedTimeMs();
         if (ReturnToChromeExperimentsUtil.shouldShowTabSwitcher(lastBackgroundedTimeMillis)
                 && isMainIntentFromLauncher(getIntent()) && !isOverviewVisible) {
             toggleOverview();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionManager.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionManager.java
index 329c86e..adfc1a3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionManager.java
@@ -7,6 +7,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.support.annotation.Nullable;
+import android.support.annotation.UiThread;
 import android.text.TextUtils;
 
 import org.chromium.base.ContextUtils;
@@ -31,7 +32,7 @@
  * {@link InstalledWebappBridge}.
  *
  * Lifecycle: This is a singleton.
- * Thread safety: Only call methods on a single thread.
+ * Thread safety: Only call methods on the UI thread as this class may call into native.
  * Native: Does not require native.
  */
 @Singleton
@@ -74,6 +75,7 @@
         return permissions.toArray(new InstalledWebappBridge.Permission[permissions.size()]);
     }
 
+    @UiThread
     void register(Origin origin, String packageName, boolean notificationsEnabled) {
         // TODO(peconn): Only trigger if this is for the first time?
 
@@ -84,15 +86,21 @@
         // did it the other way around there'd be a small moment in time where the website's
         // notification permission could flicker from SET -> UNSET -> SET. This way we transition
         // straight from the channel's permission to the app's permission.
-        mStore.setStateForOrigin(origin, packageName, appName, notificationsEnabled);
+        boolean stateChanged =
+                mStore.setStateForOrigin(origin, packageName, appName, notificationsEnabled);
 
         NotificationChannelPreserver.deleteChannelIfNeeded(mPermissionPreserver, origin);
+
+        if (stateChanged) InstalledWebappBridge.notifyPermissionsChange();
     }
 
+    @UiThread
     void unregister(Origin origin) {
         mStore.removeOrigin(origin);
 
         NotificationChannelPreserver.restoreChannelIfNeeded(mPermissionPreserver, origin);
+
+        InstalledWebappBridge.notifyPermissionsChange();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionStore.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionStore.java
index 0cbbf8dc..6b2a346 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionStore.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionStore.java
@@ -102,15 +102,34 @@
         }
     }
 
-    /** Sets the notification state for the origin. */
-    void setStateForOrigin(Origin origin, String packageName, String appName, boolean enabled) {
+    /**
+     * Sets the notification state for the origin.
+     * Returns whether {@code true} if state was changed, {@code false} if the provided state was
+     * the same as the state beforehand.
+     */
+    boolean setStateForOrigin(Origin origin, String packageName, String appName, boolean enabled) {
+        boolean modified = !getStoredOrigins().contains(origin.toString());
+
+        if (!modified) {
+            // Don't bother with these extra checks if we have a brand new origin.
+            boolean enabledChanged = enabled !=
+                    mPreferences.getBoolean(createNotificationPermissionKey(origin), false);
+            boolean packageChanged = !packageName.equals(
+                    mPreferences.getString(createPackageNameKey(origin), null));
+            boolean appNameChanged = !appName.equals(
+                    mPreferences.getString(createAppNameKey(origin), null));
+            modified = enabledChanged || packageChanged || appNameChanged;
+        }
+
         addOrigin(origin);
 
-        SharedPreferences.Editor editor = mPreferences.edit();
-        editor.putBoolean(createNotificationPermissionKey(origin), enabled);
-        editor.putString(createPackageNameKey(origin), packageName);
-        editor.putString(createAppNameKey(origin), appName);
-        editor.apply();
+        mPreferences.edit()
+                .putBoolean(createNotificationPermissionKey(origin), enabled)
+                .putString(createPackageNameKey(origin), packageName)
+                .putString(createAppNameKey(origin), appName)
+                .apply();
+
+        return modified;
     }
 
     /** Removes the origin from the store. */
@@ -118,19 +137,19 @@
         Set<String> origins = getStoredOrigins();
         origins.remove(origin.toString());
 
-        SharedPreferences.Editor editor = mPreferences.edit();
-        editor.putStringSet(KEY_ALL_ORIGINS, origins);
-        editor.remove(createNotificationPermissionKey(origin));
-        editor.remove(createAppNameKey(origin));
-        editor.remove(createPackageNameKey(origin));
-        editor.apply();
+        mPreferences.edit()
+                .putStringSet(KEY_ALL_ORIGINS, origins)
+                .remove(createNotificationPermissionKey(origin))
+                .remove(createAppNameKey(origin))
+                .remove(createPackageNameKey(origin))
+                .apply();
     }
 
     /** Stores the notification state the origin had before the TWA was installed. */
     void setPreTwaNotificationState(Origin origin, boolean enabled) {
-        SharedPreferences.Editor editor = mPreferences.edit();
-        editor.putBoolean(createNotificationPreTwaPermissionKey(origin), enabled);
-        editor.apply();
+        mPreferences.edit()
+                .putBoolean(createNotificationPreTwaPermissionKey(origin), enabled)
+                .apply();
     }
 
     /**
@@ -144,9 +163,7 @@
 
         boolean enabled = mPreferences.getBoolean(key, false);
 
-        SharedPreferences.Editor editor = mPreferences.edit();
-        editor.remove(key);
-        editor.apply();
+        mPreferences.edit().remove(key).apply();
 
         return enabled;
     }
@@ -154,18 +171,16 @@
     /** Clears the store, for testing. */
     @VisibleForTesting
     public void clearForTesting() {
-        SharedPreferences.Editor editor = mPreferences.edit();
-        editor.clear();
-        editor.apply();
+        mPreferences.edit().clear().apply();
     }
 
     private void addOrigin(Origin origin) {
         Set<String> origins = getStoredOrigins();
         origins.add(origin.toString());
 
-        SharedPreferences.Editor editor = mPreferences.edit();
-        editor.putStringSet(KEY_ALL_ORIGINS, origins);
-        editor.apply();
+        mPreferences.edit()
+                .putStringSet(KEY_ALL_ORIGINS, origins)
+                .apply();
     }
 
     private String createNotificationPermissionKey(Origin origin) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java
index 96f6eeb..d351d36 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java
@@ -112,9 +112,6 @@
     }
 
     @Override
-    public void clear() {}
-
-    @Override
     public @ImageFetcherConfig int getConfig() {
         return ImageFetcherConfig.DISK_CACHE_ONLY;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java
index 114652c..d05a052 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java
@@ -19,7 +19,6 @@
  */
 public abstract class ImageFetcher {
     // All UMA client names collected here to prevent duplicates.
-    public static final String ANSWER_SUGGESTIONS_UMA_CLIENT_NAME = "AnswerSuggestions";
     public static final String ASSISTANT_DETAILS_UMA_CLIENT_NAME = "AssistantDetails";
     public static final String ASSISTANT_INFO_BOX_UMA_CLIENT_NAME = "AssistantInfoBox";
     public static final String CONTEXTUAL_SUGGESTIONS_UMA_CLIENT_NAME = "ContextualSuggestions";
@@ -101,11 +100,6 @@
     }
 
     /**
-     * Clear the cache of any bitmaps that may be in-memory.
-     */
-    public abstract void clear();
-
-    /**
      * Returns the type of Image Fetcher this is based on class arrangements. See
      * image_fetcher_service.h for a detailed description of the available configurations.
      *
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java
index 14b76ab..748fd4a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java
@@ -16,28 +16,25 @@
 
     /**
      * Alias for createImageFetcher below.
+     *
+     * @param config The type of ImageFetcher you need.
+     * @return The correct ImageFetcher according to the provided config.
      */
     public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config) {
-        return createImageFetcher(config, ImageFetcherBridge.getInstance(), null,
-                InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE);
+        return createImageFetcher(config, null);
     }
 
     /**
      * Alias for createImageFetcher below.
+     *
+     * @param config The type of ImageFetcher you need.
+     * @param discardableReferencePool Used to store images in-memory.
+     * @return The correct ImageFetcher according to the provided config.
      */
     public static ImageFetcher createImageFetcher(
             @ImageFetcherConfig int config, DiscardableReferencePool discardableReferencePool) {
-        return createImageFetcher(config, ImageFetcherBridge.getInstance(),
-                discardableReferencePool, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE);
-    }
-
-    /**
-     * Alias for createImageFetcher below.
-     */
-    public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config,
-            DiscardableReferencePool discardableReferencePool, int inMemoryCacheSize) {
-        return createImageFetcher(config, ImageFetcherBridge.getInstance(),
-                discardableReferencePool, inMemoryCacheSize);
+        return createImageFetcher(
+                config, discardableReferencePool, ImageFetcherBridge.getInstance());
     }
 
     /**
@@ -45,14 +42,13 @@
      * config that you must destroy.
      *
      * @param config The type of ImageFetcher you need.
-     * @param imageFetcherBridge Bridge to use.
      * @param discardableReferencePool Used to store images in-memory.
-     * @param inMemoryCacheSize The size of the in memory cache (in bytes).
+     * @param imageFetcherBridge Bridge to use.
      * @return The correct ImageFetcher according to the provided config.
      */
     public static ImageFetcher createImageFetcher(@ImageFetcherConfig int config,
-            ImageFetcherBridge imageFetcherBridge,
-            DiscardableReferencePool discardableReferencePool, int inMemoryCacheSize) {
+            DiscardableReferencePool discardableReferencePool,
+            ImageFetcherBridge imageFetcherBridge) {
         // TODO(crbug.com/947191):Allow server-side configuration image fetcher clients.
         switch (config) {
             case ImageFetcherConfig.NETWORK_ONLY:
@@ -68,15 +64,15 @@
             case ImageFetcherConfig.IN_MEMORY_ONLY:
                 assert discardableReferencePool != null;
                 return new InMemoryCachedImageFetcher(
-                        createImageFetcher(ImageFetcherConfig.NETWORK_ONLY, imageFetcherBridge,
-                                discardableReferencePool, inMemoryCacheSize),
-                        discardableReferencePool, inMemoryCacheSize);
+                        createImageFetcher(
+                                ImageFetcherConfig.NETWORK_ONLY, null, imageFetcherBridge),
+                        discardableReferencePool);
             case ImageFetcherConfig.IN_MEMORY_WITH_DISK_CACHE:
                 assert discardableReferencePool != null;
                 return new InMemoryCachedImageFetcher(
-                        createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY, imageFetcherBridge,
-                                discardableReferencePool, inMemoryCacheSize),
-                        discardableReferencePool, inMemoryCacheSize);
+                        createImageFetcher(
+                                ImageFetcherConfig.DISK_CACHE_ONLY, null, imageFetcherBridge),
+                        discardableReferencePool);
             default:
                 return null;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java
index 2cecdfe..e1bc4b8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java
@@ -19,7 +19,7 @@
  * ImageFetcher implementation with an in-memory cache. Can also be configured to use a disk cache.
  */
 public class InMemoryCachedImageFetcher extends ImageFetcher {
-    public static final int DEFAULT_CACHE_SIZE = 20 * ConversionUtils.BYTES_PER_MEGABYTE; // 20mb
+    private static final int DEFAULT_CACHE_SIZE = 20 * ConversionUtils.BYTES_PER_MEGABYTE; // 20mb
     private static final float PORTION_OF_AVAILABLE_MEMORY = 1.f / 8.f;
 
     // Will do the work if the image isn't cached in memory.
@@ -111,11 +111,6 @@
     }
 
     @Override
-    public void clear() {
-        mBitmapCache.clear();
-    }
-
-    @Override
     public @ImageFetcherConfig int getConfig() {
         return mConfig;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java
index aae248a..52b4f31 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java
@@ -43,9 +43,6 @@
     }
 
     @Override
-    public void clear() {}
-
-    @Override
     public @ImageFetcherConfig int getConfig() {
         return ImageFetcherConfig.NETWORK_ONLY;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
index 0b07d9d..03cee93 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
@@ -25,11 +25,6 @@
  */
 public interface LocationBar extends UrlBarDelegate {
     /**
-     * Cleanup resources when this goes out of scope.
-     */
-    void destroy();
-
-    /**
      * Handles native dependent initialization for this class.
      */
     void onNativeLibraryReady();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index cea7caa..b670f3a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -193,12 +193,6 @@
     }
 
     @Override
-    public void destroy() {
-        mAutocompleteCoordinator.destroy();
-        mAutocompleteCoordinator = null;
-    }
-
-    @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
index b9920bf..6ed4066 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
@@ -100,7 +100,7 @@
             hintColor =
                     ApiCompatibilityUtils.getColor(resources, R.color.locationbar_light_hint_text);
             highlightColor = ApiCompatibilityUtils.getColor(
-                    resources, R.color.locationbar_light_selection_color);
+                    resources, R.color.highlight_color_on_light_text);
         }
 
         view.setTextColor(textColor);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswersImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswersImageFetcher.java
new file mode 100644
index 0000000..39a6122
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswersImageFetcher.java
@@ -0,0 +1,104 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.omnibox.suggestions;
+
+import android.graphics.Bitmap;
+import android.support.v4.util.LruCache;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.util.ConversionUtils;
+
+/**
+ * Provides access to images used by Answers in Suggest.
+ */
+public class AnswersImageFetcher {
+    // Matches the value in BitmapFetcherService.
+    private static final int INVALID_IMAGE_REQUEST_ID = 0;
+    private static final int MAX_CACHE_SIZE = 500 * ConversionUtils.BYTES_PER_KILOBYTE;
+
+    /**
+     * Observer for updating an image when it is available.
+     */
+    public interface AnswersImageObserver {
+        /**
+         * Called when the image is updated.
+         *
+         * @param bitmap the image
+         */
+        @CalledByNative("AnswersImageObserver")
+        void onAnswersImageChanged(Bitmap bitmap);
+    }
+
+    // Intentionally not using BitmapCache as that does not cache for low end devices (it ensures
+    // the bitmaps are de-dups across instances, but discards them if there is not an active
+    // reference to one).
+    private final LruCache<String, Bitmap> mBitmapCache =
+            new LruCache<String, Bitmap>(MAX_CACHE_SIZE) {
+                @Override
+                protected int sizeOf(String key, Bitmap value) {
+                    return value.getByteCount();
+                }
+            };
+
+    /**
+     * Clears the cached answer images.
+     */
+    public void clearCache() {
+        mBitmapCache.evictAll();
+    }
+
+    /**
+     * Request image, observer is notified when image is loaded.
+     * @param profile     Profile that the request is for.
+     * @param imageUrl    URL for image data.
+     * @param observer    Observer to be notified when image is updated. The C++ side will hold a
+     *                    strong reference to this.
+     * @return            A request_id.
+     */
+    public int requestAnswersImage(
+            Profile profile, String imageUrl, AnswersImageObserver observer) {
+        if (!profile.isOffTheRecord()) {
+            Bitmap bitmap = mBitmapCache.get(imageUrl);
+            if (bitmap != null) {
+                observer.onAnswersImageChanged(bitmap);
+                return INVALID_IMAGE_REQUEST_ID;
+            }
+        }
+        AnswersImageObserver cacheObserver = observer;
+        if (!profile.isOffTheRecord()) {
+            cacheObserver = new AnswersImageObserver() {
+                @Override
+                public void onAnswersImageChanged(Bitmap bitmap) {
+                    if (bitmap == null) return;
+                    mBitmapCache.put(imageUrl, bitmap);
+                    observer.onAnswersImageChanged(bitmap);
+                }
+            };
+        }
+        return nativeRequestAnswersImage(profile, imageUrl, cacheObserver);
+    }
+
+    /**
+     * Cancel a pending image request.
+     * @param profile    Profile the request was issued for.
+     * @param requestId  The ID of the request to be cancelled.
+     */
+    public void cancelAnswersImageRequest(Profile profile, int requestId) {
+        nativeCancelAnswersImageRequest(profile, requestId);
+    }
+
+    /**
+     * Requests an image at |imageUrl| for the given |profile| with |observer| being notified.
+     * @returns an AnswersImageRequest
+     */
+    private static native int nativeRequestAnswersImage(
+            Profile profile, String imageUrl, AnswersImageObserver observer);
+
+    /**
+     * Cancels a pending request.
+     */
+    private static native void nativeCancelAnswersImageRequest(Profile profile, int requestId);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
index 74624f9..a77cf3d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
@@ -50,7 +50,7 @@
  */
 public class AutocompleteCoordinator implements UrlFocusChangeListener, UrlTextChangeListener {
     private final ViewGroup mParent;
-    private AutocompleteMediator mMediator;
+    private final AutocompleteMediator mMediator;
 
     private ListView mListView;
 
@@ -170,11 +170,6 @@
                 new AutocompleteMediator(context, delegate, urlBarEditingTextProvider, listModel);
     }
 
-    public void destroy() {
-        mMediator.destroy();
-        mMediator = null;
-    }
-
     private ViewProvider<SuggestionListViewHolder> createViewProvider(Context context) {
         return new ViewProvider<SuggestionListViewHolder>() {
             private List<Callback<SuggestionListViewHolder>> mCallbacks = new ArrayList<>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
index e63d273..77d63a4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -93,7 +93,7 @@
     private final Handler mHandler;
     private final BasicSuggestionProcessor mBasicSuggestionProcessor;
     private EditUrlSuggestionProcessor mEditUrlProcessor;
-    private AnswerSuggestionProcessor mAnswerSuggestionProcessor;
+    private final AnswerSuggestionProcessor mAnswerSuggestionProcessor;
 
     private ToolbarDataProvider mDataProvider;
     private boolean mNativeInitialized;
@@ -157,11 +157,6 @@
                 delegate, (suggestion) -> onSelection(suggestion, 0));
     }
 
-    public void destroy() {
-        mAnswerSuggestionProcessor.destroy();
-        mAnswerSuggestionProcessor = null;
-    }
-
     @Override
     public void onStartWithNative() {}
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
index 4be65e7..7ddabae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
@@ -11,13 +11,10 @@
 import android.view.View;
 
 import org.chromium.base.ThreadUtils;
-import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.image_fetcher.ImageFetcher;
-import org.chromium.chrome.browser.image_fetcher.ImageFetcherConfig;
-import org.chromium.chrome.browser.image_fetcher.ImageFetcherFactory;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
 import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
+import org.chromium.chrome.browser.omnibox.suggestions.AnswersImageFetcher;
 import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinator.SuggestionProcessor;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
@@ -27,7 +24,6 @@
 import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties;
 import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties.SuggestionIcon;
 import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties.SuggestionTextContainer;
-import org.chromium.chrome.browser.util.ConversionUtils;
 import org.chromium.components.omnibox.AnswerType;
 import org.chromium.components.omnibox.SuggestionAnswer;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -39,12 +35,10 @@
 
 /** A class that handles model and view creation for the most commonly used omnibox suggestion. */
 public class AnswerSuggestionProcessor implements SuggestionProcessor {
-    private static final int MAX_CACHE_SIZE = 500 * ConversionUtils.BYTES_PER_KILOBYTE;
-
     private final Map<String, List<PropertyModel>> mPendingAnswerRequestUrls;
     private final Context mContext;
     private final SuggestionHost mSuggestionHost;
-    private ImageFetcher mImageFetcher;
+    private final AnswersImageFetcher mImageFetcher;
     private final UrlBarEditingTextStateProvider mUrlBarEditingTextProvider;
     private boolean mEnableNewAnswerLayout;
 
@@ -57,16 +51,10 @@
         mContext = context;
         mSuggestionHost = suggestionHost;
         mPendingAnswerRequestUrls = new HashMap<>();
+        mImageFetcher = new AnswersImageFetcher();
         mUrlBarEditingTextProvider = editingTextProvider;
     }
 
-    public void destroy() {
-        if (mImageFetcher != null) {
-            mImageFetcher.destroy();
-            mImageFetcher = null;
-        }
-    }
-
     @Override
     public boolean doesProcessSuggestion(OmniboxSuggestion suggestion) {
         // Calculation answers are specific in a way that these are basic suggestions, but processed
@@ -108,10 +96,7 @@
 
     @Override
     public void onUrlFocusChange(boolean hasFocus) {
-        // This clear is necessary for memory as well as clearing when switching to/from incognito.
-        if (!hasFocus && mImageFetcher != null) {
-            mImageFetcher.clear();
-        }
+        if (!hasFocus) mImageFetcher.clearCache();
     }
 
     private void maybeFetchAnswerIcon(OmniboxSuggestion suggestion, PropertyModel model) {
@@ -132,35 +117,30 @@
             return;
         }
 
-        if (mImageFetcher == null) {
-            mImageFetcher = ImageFetcherFactory.createImageFetcher(
-                    ImageFetcherConfig.IN_MEMORY_ONLY,
-                    ((ChromeApplication) mContext.getApplicationContext()).getReferencePool(),
-                    MAX_CACHE_SIZE);
-        }
-
         List<PropertyModel> models = new ArrayList<>();
         models.add(model);
         mPendingAnswerRequestUrls.put(url, models);
+        mImageFetcher.requestAnswersImage(mSuggestionHost.getCurrentProfile(), url,
+                new AnswersImageFetcher.AnswersImageObserver() {
+                    @Override
+                    public void onAnswersImageChanged(Bitmap bitmap) {
+                        ThreadUtils.assertOnUiThread();
 
-        mImageFetcher.fetchImage(
-                url, ImageFetcher.ANSWER_SUGGESTIONS_UMA_CLIENT_NAME, (Bitmap bitmap) -> {
-                    ThreadUtils.assertOnUiThread();
+                        List<PropertyModel> models = mPendingAnswerRequestUrls.remove(url);
+                        boolean didUpdate = false;
+                        for (int i = 0; i < models.size(); i++) {
+                            PropertyModel model = models.get(i);
+                            if (!mSuggestionHost.isActiveModel(model)) continue;
 
-                    List<PropertyModel> currentModels = mPendingAnswerRequestUrls.remove(url);
-                    boolean didUpdate = false;
-                    for (int i = 0; i < currentModels.size(); i++) {
-                        PropertyModel currentModel = currentModels.get(i);
-                        if (!mSuggestionHost.isActiveModel(currentModel)) continue;
-
-                        if (mEnableNewAnswerLayout) {
-                            model.set(AnswerSuggestionViewProperties.ANSWER_IMAGE, bitmap);
-                        } else {
-                            model.set(SuggestionViewProperties.ANSWER_IMAGE, bitmap);
+                            if (mEnableNewAnswerLayout) {
+                                model.set(AnswerSuggestionViewProperties.ANSWER_IMAGE, bitmap);
+                            } else {
+                                model.set(SuggestionViewProperties.ANSWER_IMAGE, bitmap);
+                            }
+                            didUpdate = true;
                         }
-                        didUpdate = true;
+                        if (didUpdate) mSuggestionHost.notifyPropertyModelsChanged();
                     }
-                    if (didUpdate) mSuggestionHost.notifyPropertyModelsChanged();
                 });
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordGenerationPopupAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordGenerationPopupAdapter.java
index 1996001..8a095f2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordGenerationPopupAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordGenerationPopupAdapter.java
@@ -9,7 +9,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
-import android.widget.RelativeLayout.LayoutParams;
 import android.widget.TextView;
 
 import org.chromium.chrome.R;
@@ -21,7 +20,6 @@
 public class PasswordGenerationPopupAdapter extends BaseAdapter {
     private final Context mContext;
     private final String mExplanationText;
-    private final int mWidth;
 
     /**
      * UI shows an explanation about storing passwords in Chrome.
@@ -44,11 +42,6 @@
             Context context, String explanationText, float anchorWidthInDp) {
         mContext = context;
         mExplanationText = explanationText;
-        int horizontalMarginInPx = Math.round(mContext.getResources().getDimensionPixelSize(
-                R.dimen.password_generation_horizontal_margin));
-        int anchorWidthInPx =
-                Math.round(anchorWidthInDp * mContext.getResources().getDisplayMetrics().density);
-        mWidth = anchorWidthInPx - 2 * horizontalMarginInPx;
     }
 
     @Override
@@ -61,7 +54,6 @@
                 R.layout.password_generation_popup_explanation, null);
         TextView explanation = view.findViewById(R.id.password_generation_explanation);
         explanation.setText(mExplanationText);
-        explanation.setLayoutParams(new LayoutParams(mWidth, LayoutParams.WRAP_CONTENT));
         return view;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java
index ee70579..27d2836 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java
@@ -4,13 +4,15 @@
 
 package org.chromium.chrome.browser.tasks;
 
+import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.ChromeFeatureList;
 
 /**
  * This is a utility class for managing experiments related to returning to Chrome.
  */
 public final class ReturnToChromeExperimentsUtil {
-    private static final String TAB_SWITCHER_ON_RETURN_MS = "tab_switcher_on_return_time_ms";
+    @VisibleForTesting
+    public static final String TAB_SWITCHER_ON_RETURN_MS = "tab_switcher_on_return_time_ms";
 
     private ReturnToChromeExperimentsUtil() {}
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
index fa02707..34311da 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
@@ -198,9 +198,6 @@
     }
 
     @Override
-    public void destroy() {}
-
-    @Override
     void initialize(ToolbarDataProvider toolbarDataProvider, ToolbarTabController tabController,
             AppMenuButtonHelper appMenuButtonHelper) {
         super.initialize(toolbarDataProvider, tabController, appMenuButtonHelper);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
index b5d5327..e2d5d0c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
@@ -137,8 +137,6 @@
             mThemeColorProvider.removeThemeColorObserver(this);
             mThemeColorProvider = null;
         }
-
-        getLocationBar().destroy();
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionsTest.java
index 529684d..962d43e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionsTest.java
@@ -25,6 +25,7 @@
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
 import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.net.test.EmbeddedTestServer;
 import org.chromium.net.test.ServerCertificate;
 
@@ -78,24 +79,29 @@
     @Test
     @MediumTest
     public void allowNotifications() throws TimeoutException, InterruptedException {
-        mPermissionManager.register(mOrigin, mPackage, true);
+        TestThreadUtils.runOnUiThreadBlocking(() ->
+                mPermissionManager.register(mOrigin, mPackage, true));
         assertEquals("\"granted\"", getNotificationPermission());
     }
 
     @Test
     @MediumTest
     public void blockNotifications() throws TimeoutException, InterruptedException {
-        mPermissionManager.register(mOrigin, mPackage, false);
+        TestThreadUtils.runOnUiThreadBlocking(() ->
+                mPermissionManager.register(mOrigin, mPackage, false));
         assertEquals("\"denied\"", getNotificationPermission());
     }
 
     @Test
     @MediumTest
     public void unregisterTwa() throws TimeoutException, InterruptedException {
-        mPermissionManager.register(mOrigin, mPackage, true);
+        TestThreadUtils.runOnUiThreadBlocking(() ->
+                mPermissionManager.register(mOrigin, mPackage, true));
         assertEquals("\"granted\"", getNotificationPermission());
 
-        mPermissionManager.unregister(mOrigin);
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mPermissionManager.unregister(mOrigin);
+        });
         assertEquals("\"default\"", getNotificationPermission());
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
index a89efdd..eb5ce7a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
@@ -5,19 +5,25 @@
 package org.chromium.chrome.browser.explore_sites;
 
 import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
 
+import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.instanceOf;
 
 import android.annotation.TargetApi;
 import android.os.Build;
 import android.os.SystemClock;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
 import android.support.test.espresso.contrib.RecyclerViewActions;
 import android.support.test.filters.SmallTest;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.view.View;
 
+import org.hamcrest.Matcher;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Assume;
@@ -27,7 +33,6 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
@@ -57,6 +62,34 @@
 public class ExploreSitesPageTest {
     // clang-format on
 
+    private static final class ScrollToPositionWithOffsetViewAction implements ViewAction {
+        private final int mPosition;
+        private final int mOffset;
+
+        private ScrollToPositionWithOffsetViewAction(int position, int offset) {
+            this.mPosition = position;
+            mOffset = offset;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Matcher<View> getConstraints() {
+            return allOf(isAssignableFrom(RecyclerView.class), isDisplayed());
+        }
+
+        @Override
+        public String getDescription() {
+            return "scroll RecyclerView to mPosition: " + mPosition;
+        }
+
+        @Override
+        public void perform(UiController uiController, View view) {
+            RecyclerView recyclerView = (RecyclerView) view;
+            ((LinearLayoutManager) recyclerView.getLayoutManager())
+                    .scrollToPositionWithOffset(mPosition, mOffset);
+        }
+    }
+
     ArrayList<ExploreSitesCategory> getTestingCatalog() {
         final ArrayList<ExploreSitesCategory> categoryList = new ArrayList<>();
         for (int i = 0; i < 5; i++) {
@@ -112,16 +145,19 @@
                 .findFirstCompletelyVisibleItemPosition();
     }
 
+    private void scrollToPosition(int scrollPosition) {
+        onView(instanceOf(RecyclerView.class))
+                .perform(new ScrollToPositionWithOffsetViewAction(scrollPosition, 0));
+    }
+
     @Test
     @SmallTest
-    @DisabledTest
     @Feature({"ExploreSites", "RenderTest"})
     public void testScrolledLayout_withBack() throws Exception {
-        final int scrollPosition = 2;
-        onView(instanceOf(RecyclerView.class))
-                .perform(RecyclerViewActions.scrollToPosition(scrollPosition));
+        scrollToPosition(2);
+
         mRenderTestRule.render(mRecyclerView, "recycler_layout");
-        Assert.assertEquals(scrollPosition, getFirstVisiblePosition());
+        final int scrollPosition = getFirstVisiblePosition();
         // TODO(https://crbug.com/938519): Remove this sleep in favor of actually waiting for the
         // scroll bar to disappear.
         SystemClock.sleep(3000);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java
new file mode 100644
index 0000000..cf195df
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java
@@ -0,0 +1,117 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tasks;
+
+import static org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil.TAB_SWITCHER_ON_RETURN_MS;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Tests the functionality of return to chrome features that open overview mode if the timeout
+ * has passed.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+public class ReturnToChromeTest {
+    @Rule
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
+
+    private ChromeTabbedActivity mActivity;
+
+    @Before
+    public void setUp() throws Exception {
+        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+        mActivityTestRule.startMainActivityFromLauncher();
+        mActivity = mActivityTestRule.getActivity();
+    }
+
+    /**
+     * Test that overview mode is not triggered if the delay is longer than the interval between
+     * stop and start.
+     */
+    @Test
+    @SmallTest
+    @Feature({"ReturnToChrome"})
+    @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+            "enable-features=" + ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<FakeStudyName",
+            "force-fieldtrials=FakeStudyName/Enabled",
+            "force-fieldtrial-params=FakeStudyName.Enabled:" + TAB_SWITCHER_ON_RETURN_MS
+                    + "/100000"})
+    public void
+    testObserverModeNotTriggeredWithoutDelay() throws Exception {
+        finishActivityCompletely();
+
+        mActivityTestRule.startMainActivityFromLauncher();
+        mActivity = mActivityTestRule.getActivity();
+
+        Assert.assertFalse(mActivity.getLayoutManager().overviewVisible());
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"ReturnToChrome"})
+    @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+            "enable-features=" + ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<FakeStudyName",
+            "force-fieldtrials=FakeStudyName/Enabled",
+            "force-fieldtrial-params=FakeStudyName.Enabled:" + TAB_SWITCHER_ON_RETURN_MS + "/1"})
+    public void
+    testObserverModeTriggeredWithDelay() throws Exception {
+        finishActivityCompletely();
+
+        // Sleep past the timeout
+        SystemClock.sleep(30);
+
+        mActivityTestRule.startMainActivityFromLauncher();
+        mActivity = mActivityTestRule.getActivity();
+
+        Assert.assertTrue(mActivity.getLayoutManager().overviewVisible());
+    }
+
+    private void finishActivityCompletely() throws InterruptedException, TimeoutException {
+        final CallbackHelper activityCallback = new CallbackHelper();
+        ApplicationStatus.ActivityStateListener stateListener =
+                new ApplicationStatus.ActivityStateListener() {
+                    @Override
+                    public void onActivityStateChange(Activity activity, int newState) {
+                        if (newState == ActivityState.STOPPED) {
+                            activityCallback.notifyCalled();
+                            ApplicationStatus.unregisterActivityStateListener(this);
+                        }
+                    }
+                };
+
+        ApplicationStatus.registerStateListenerForAllActivities(stateListener);
+        try {
+            mActivity.finish();
+            activityCallback.waitForCallback("Activity did not stop as expected", 0);
+            mActivityTestRule.setActivity(null);
+        } finally {
+            ApplicationStatus.unregisterActivityStateListener(stateListener);
+        }
+    }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactoryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactoryTest.java
index 4c3aae3..3c115c1 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactoryTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactoryTest.java
@@ -39,24 +39,23 @@
     public void testGetImageFetcher() {
         assertEquals(ImageFetcherConfig.NETWORK_ONLY,
                 ImageFetcherFactory
-                        .createImageFetcher(ImageFetcherConfig.NETWORK_ONLY, mImageFetcherBridge,
-                                mReferencePool, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE)
+                        .createImageFetcher(ImageFetcherConfig.NETWORK_ONLY, mReferencePool,
+                                mImageFetcherBridge)
                         .getConfig());
         assertEquals(ImageFetcherConfig.DISK_CACHE_ONLY,
                 ImageFetcherFactory
-                        .createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY, mImageFetcherBridge,
-                                mReferencePool, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE)
+                        .createImageFetcher(ImageFetcherConfig.DISK_CACHE_ONLY, mReferencePool,
+                                mImageFetcherBridge)
                         .getConfig());
         assertEquals(ImageFetcherConfig.IN_MEMORY_ONLY,
                 ImageFetcherFactory
-                        .createImageFetcher(ImageFetcherConfig.IN_MEMORY_ONLY, mImageFetcherBridge,
-                                mReferencePool, InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE)
+                        .createImageFetcher(ImageFetcherConfig.IN_MEMORY_ONLY, mReferencePool,
+                                mImageFetcherBridge)
                         .getConfig());
         assertEquals(ImageFetcherConfig.IN_MEMORY_WITH_DISK_CACHE,
                 ImageFetcherFactory
                         .createImageFetcher(ImageFetcherConfig.IN_MEMORY_WITH_DISK_CACHE,
-                                mImageFetcherBridge, mReferencePool,
-                                InMemoryCachedImageFetcher.DEFAULT_CACHE_SIZE)
+                                mReferencePool, mImageFetcherBridge)
                         .getConfig());
     }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java
index 0c1c454..60be0f4 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherTest.java
@@ -45,9 +45,6 @@
                 String url, String clientName, int width, int height, Callback<Bitmap> callback) {}
 
         @Override
-        public void clear() {}
-
-        @Override
         public int getConfig() {
             return 0;
         }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 4bee008..95e222e 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-75.0.3768.0_rc-r1-merged.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-75.0.3769.0_rc-r1-merged.afdo.bz2
\ No newline at end of file
diff --git a/chrome/android/trichrome.gni b/chrome/android/trichrome.gni
index c2b2ab3..3a74e606 100644
--- a/chrome/android/trichrome.gni
+++ b/chrome/android/trichrome.gni
@@ -28,7 +28,8 @@
 }
 
 trichrome_jinja_variables = [
-  "min_sdk_version=28",
+  # TODO(torne): make minsdk=Q once we no longer build hacky P version
+  "min_sdk_version=$android_sdk_version",
   "target_sdk_version=$android_sdk_version",
   "trichrome_library=$trichrome_library_package",
   "trichrome_version=$trichrome_version_code",
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 9b4bf0f..c9cdb4a 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -3405,6 +3405,9 @@
   <message name="IDS_CROSTINI_INSTALLER_OFFLINE_ERROR" desc="Text shown in the Crostini installer dialog when there is no internet connection">
     <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> is offline. Connect to the Internet and try again.
   </message>
+  <message name="IDS_CROSTINI_INSTALLER_INSUFFICIENT_DISK" desc="Text shown in the Crostini installer dialog when there is not enough free disk space to complete the installation">
+    Install failed due to lack of storage space. At least <ph name="INSTALL_SIZE">$1<ex>1.3GB</ex></ph> of free space is required. To free up space, delete files from device storage.
+  </message>
   <message name="IDS_CROSTINI_INSTALLER_LOAD_TERMINA_ERROR" desc="Text shown in the Crostini installer dialog when the VM component fails to load">
     Error downloading the virtual machine. Please try again.
   </message>
@@ -3828,34 +3831,34 @@
     Plugin VM
   </message>
   <message name="IDS_PLUGIN_VM_LAUNCHER_ENVIRONMENT_SETTING_TITLE" desc="Title of the PluginVm launcher, a dialog for launching PluginVm." translateable="false">
-    Finishing <ph name="APP_NAME">PluginVm</ph> environment setting...
+    Finishing <ph name="APP_NAME">Plugin VM</ph> installation...
   </message>
   <message name="IDS_PLUGIN_VM_LAUNCHER_FINISHED_TITLE" desc="Title of the PluginVm launcher, a dialog for launching PluginVm." translateable="false">
-    <ph name="APP_NAME">PluginVm</ph> environment setting complete
+    <ph name="APP_NAME">Plugin VM</ph> installation complete
   </message>
   <message name="IDS_PLUGIN_VM_LAUNCHER_ERROR_TITLE" desc="Title of the PluginVm launcher, a dialog for launching PluginVm." translateable="false">
-    Error setting <ph name="APP_NAME">PluginVm</ph> environment
+    Error installing <ph name="APP_NAME">Plugin VM</ph>
   </message>
   <message name="IDS_PLUGIN_VM_LAUNCHER_START_DOWNLOADING_MESSAGE" desc="Message that informs user that PluginVm environment setting may take a while." translateable="false">
-    This process may take a few minutes
+    This process may take a few minutes.
   </message>
   <message name="IDS_PLUGIN_VM_LAUNCHER_DOWNLOADING_MESSAGE" desc="Description of the current state of PluginVm environment setting." translateable="false">
-    Downloading <ph name="APP_NAME">PluginVm</ph> image...
+    Downloading the virtual machine.
   </message>
   <message name="IDS_PLUGIN_VM_LAUNCHER_UNZIPPING_MESSAGE" desc="Description of the current state of PluginVm environment setting." translateable="false">
-    Configuring <ph name="APP_NAME">PluginVm</ph> image...
+    Configuring the virtual machine. This process might take around 3 minutes.
   </message>
   <message name="IDS_PLUGIN_VM_LAUNCHER_REGISTERING_MESSAGE" desc="Description of the current state of PluginVm environment setting." translateable="false">
     Putting on final touches...
   </message>
   <message name="IDS_PLUGIN_VM_LAUNCHER_FINISHED_MESSAGE" desc="Description of the current state of PluginVm environment setting." translateable="false">
-    Set up was successfully completed. Click on the launch button to start using <ph name="APP_NAME">PluginVm</ph>.
+    Set up was successfully completed. Click on the launch button to start using <ph name="APP_NAME">Plugin VM</ph>.
   </message>
   <message name="IDS_PLUGIN_VM_LAUNCHER_ERROR_MESSAGE" desc="Description of the current state of PluginVm environment setting." translateable="false">
-    The <ph name="APP_NAME">PluginVm</ph> environment didn't set. Please try again.
+    The <ph name="APP_NAME">Plugin VM</ph> installation failed. Please try again.
   </message>
   <message name="IDS_PLUGIN_VM_LAUNCHER_DOWNLOAD_PROGRESS_MESSAGE" desc="Text shown in the PluginVm launcher during downloading PluginVm image that shows download progress." translateable="false">
-    <ph name="DOWNLOADED_SIZE">$1<ex>1.2 GB</ex></ph>/<ph name="DOWNLOAD_SIZE">$2<ex>3.4 GB</ex></ph>
+    <ph name="DOWNLOADED_SIZE">$1<ex>1.2</ex></ph>/<ph name="DOWNLOAD_SIZE">$2<ex>3.4 GB</ex></ph>
   </message>
   <message name="IDS_PLUGIN_VM_LAUNCHER_DOWNLOAD_PROGRESS_WITHOUT_DOWNLOAD_SIZE_MESSAGE" desc="Text shown in the PluginVm launcher during downloading PluginVm image that shows download progress." translateable="false">
     <ph name="DOWNLOADED_SIZE">$1<ex>1.2 GB</ex></ph>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index ff1680f..202d596 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5317,10 +5317,6 @@
         Stop plugin
       </message>
 
-      <message name="IDS_BROWSER_BLOATED_RENDERER_INFOBAR" desc="The text of the infobar notifying the user that the page ran out of memory">
-        The web page was reloaded because it ran out of memory.
-      </message>
-
       <!-- Passwords and Exceptions Dialog -->
       <message name="IDS_PASSWORDS_AUTO_SIGNIN_TITLE" desc="Title for 'Auto sign-in' checkbox in the password dialog">
         Auto sign-in
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index be40d0f..c584d0c 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -283,6 +283,9 @@
     <message name="IDS_SETTINGS_AUTOCLICK_REVERT_TO_LEFT_CLICK" desc="Description of a checkbox that gives the option to return to the default left click action after taking another action.">
       Revert to left click after action
     </message>
+    <message name="IDS_SETTINGS_AUTOCLICK_STABILIZE_CURSOR_POSITION" desc="Description of a checkbox that gives the option to turn on cursor movmeent stablization.">
+      Click position stabilization
+    </message>
     <message name="IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_LABEL" desc="Label for a dropdown menu which that has options for how much mouse movement can occur before a new autoclick is initiated.">
       Movement threshold
     </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_AUTOCLICK_STABILIZE_CURSOR_POSITION.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_AUTOCLICK_STABILIZE_CURSOR_POSITION.png.sha1
new file mode 100644
index 0000000..2c4b17f
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_AUTOCLICK_STABILIZE_CURSOR_POSITION.png.sha1
@@ -0,0 +1 @@
+a8ad2d0cbce9458976f183f481ce27e671ad1782
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index be46d70..87dbb7c 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2431,6 +2431,7 @@
       "android/ntp/recent_tabs_page_prefs.cc",
       "android/ntp/recent_tabs_page_prefs.h",
       "android/ntp/suggestions_event_reporter_bridge.cc",
+      "android/omnibox/answers_image_bridge.cc",
       "android/omnibox/autocomplete_controller_android.cc",
       "android/omnibox/autocomplete_controller_android.h",
       "android/omnibox/omnibox_prerender.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 56681cc..5f1b26f 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3039,10 +3039,6 @@
      flag_descriptions::kBundledConnectionHelpDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kBundledConnectionHelpFeature)},
 
-    {"enable-signed-http-exchange", flag_descriptions::kSignedHTTPExchangeName,
-     flag_descriptions::kSignedHTTPExchangeDescription, kOsAll,
-     FEATURE_VALUE_TYPE(features::kSignedHTTPExchange)},
-
 #if defined(OS_CHROMEOS)
     {"enable-oobe-recommend-apps-screen",
      flag_descriptions::kEnableOobeRecommendAppsScreenName,
diff --git a/chrome/browser/android/omnibox/answers_image_bridge.cc b/chrome/browser/android/omnibox/answers_image_bridge.cc
new file mode 100644
index 0000000..9ce2b25
--- /dev/null
+++ b/chrome/browser/android/omnibox/answers_image_bridge.cc
@@ -0,0 +1,77 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/bind.h"
+#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h"
+#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_android.h"
+#include "jni/AnswersImageFetcher_jni.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/android/java_bitmap.h"
+#include "url/gurl.h"
+
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+using base::android::ConvertUTF8ToJavaString;
+
+namespace {
+
+class AnswersImageObserverAndroid : public BitmapFetcherService::Observer {
+ public:
+  explicit AnswersImageObserverAndroid(JNIEnv* env,
+                                       jobject java_answers_image_observer) {
+    java_answers_image_observer_.Reset(env, java_answers_image_observer);
+  }
+
+  ~AnswersImageObserverAndroid() override {}
+
+  // AnswersImageObserver:
+  void OnImageChanged(BitmapFetcherService::RequestId request_id,
+                      const SkBitmap& answers_image) override {
+    DCHECK(!answers_image.empty());
+
+    JNIEnv* env = base::android::AttachCurrentThread();
+    ScopedJavaLocalRef<jobject> java_bitmap =
+        gfx::ConvertToJavaBitmap(&answers_image);
+    Java_AnswersImageObserver_onAnswersImageChanged(
+        env, java_answers_image_observer_, java_bitmap);
+  }
+
+ private:
+  base::android::ScopedJavaGlobalRef<jobject> java_answers_image_observer_;
+};
+
+}  // namespace
+
+static void JNI_AnswersImageFetcher_CancelAnswersImageRequest(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& java_profile,
+    jint java_request_id) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(java_profile);
+  DCHECK(profile);
+  BitmapFetcherService* bitmap_fetcher_service =
+      BitmapFetcherServiceFactory::GetForBrowserContext(profile);
+  bitmap_fetcher_service->CancelRequest(java_request_id);
+}
+
+static int JNI_AnswersImageFetcher_RequestAnswersImage(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& java_profile,
+    const JavaParamRef<jstring>& java_url,
+    const JavaParamRef<jobject>& java_callback) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(java_profile);
+  DCHECK(profile);
+  BitmapFetcherService* bitmap_fetcher_service =
+      BitmapFetcherServiceFactory::GetForBrowserContext(profile);
+  std::string url;
+  base::android::ConvertJavaStringToUTF8(env, java_url, &url);
+  return bitmap_fetcher_service->RequestImage(
+      GURL(url), new AnswersImageObserverAndroid(env, java_callback),
+      TRAFFIC_ANNOTATION_WITHOUT_PROTO("Omnibox answers image"));
+}
diff --git a/chrome/browser/android/vr/BUILD.gn b/chrome/browser/android/vr/BUILD.gn
index 6782eba..d748cc4 100644
--- a/chrome/browser/android/vr/BUILD.gn
+++ b/chrome/browser/android/vr/BUILD.gn
@@ -246,6 +246,5 @@
     "//testing/android/native_test:native_test_native_code",
     "//testing/gmock",
     "//testing/gtest:gtest",
-    "//ui/android:ui_java",  # TODO: Remove once http://crbug.com/951419 is fixed!
   ]
 }
diff --git a/chrome/browser/autofill/manual_filling_controller_impl_unittest.cc b/chrome/browser/autofill/manual_filling_controller_impl_unittest.cc
index abc97cb..c3037b4c 100644
--- a/chrome/browser/autofill/manual_filling_controller_impl_unittest.cc
+++ b/chrome/browser/autofill/manual_filling_controller_impl_unittest.cc
@@ -53,7 +53,9 @@
            const base::WeakPtr<password_manager::PasswordManagerDriver>&));
   MOCK_METHOD0(OnGenerationElementLostFocus, void());
   MOCK_METHOD0(OnGenerationRequested, void());
-  MOCK_METHOD1(GeneratedPasswordAccepted, void(const base::string16&));
+  MOCK_METHOD2(GeneratedPasswordAccepted,
+               void(const base::string16&,
+                    base::WeakPtr<password_manager::PasswordManagerDriver>));
   MOCK_METHOD0(GeneratedPasswordRejected, void());
   MOCK_CONST_METHOD0(top_level_native_window, gfx::NativeWindow());
 };
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 0ee8e4e..7f71a6a 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -89,6 +89,7 @@
 #include "chrome/common/extensions/chrome_extensions_client.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
+#include "chrome/grit/chromium_strings.h"
 #include "chrome/installer/util/google_update_settings.h"
 #include "components/component_updater/component_updater_service.h"
 #include "components/component_updater/timer_update_scheduler.h"
@@ -289,6 +290,12 @@
 
 #if !defined(OS_CHROMEOS)
   message_center::MessageCenter::Initialize();
+  // Set the system notification source display name ("Google Chrome" or
+  // "Chromium").
+  if (message_center::MessageCenter::Get()) {
+    message_center::MessageCenter::Get()->SetSystemNotificationAppName(
+        l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
+  }
 #endif
 
   system_notification_helper_ = std::make_unique<SystemNotificationHelper>();
diff --git a/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc b/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc
index 72112d1..6f380e3 100644
--- a/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc
+++ b/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc
@@ -118,31 +118,30 @@
   EXPECT_TRUE(IsSyncEnabled());
 
   // We stop syncing autofill in particular. This restarts the counter.
-  syncer::ModelTypeSet everything_except_autofill =
-      syncer::UserSelectableTypes();
-  everything_except_autofill.Remove(syncer::AUTOFILL);
+  syncer::UserSelectableTypeSet everything_except_autofill =
+      syncer::UserSelectableTypeSet::All();
+  everything_except_autofill.Remove(syncer::UserSelectableType::kAutofill);
   auto sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->GetUserSettings()->SetChosenDataTypes(
+  sync_service->GetUserSettings()->SetSelectedTypes(
       /*sync_everything=*/false, everything_except_autofill);
-  ASSERT_FALSE(sync_service->GetUserSettings()->GetChosenDataTypes().Has(
-      syncer::AUTOFILL));
+  ASSERT_FALSE(sync_service->GetUserSettings()->GetSelectedTypes().Has(
+      syncer::UserSelectableType::kAutofill));
   sync_blocker.reset();
   WaitForCounting();
   ASSERT_FALSE(sync_service->GetActiveDataTypes().Has(syncer::AUTOFILL));
   EXPECT_FALSE(IsSyncEnabled());
 
   // If autofill sync is not affected, the counter is not restarted.
-  syncer::ModelTypeSet only_history(syncer::TYPED_URLS);
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->GetUserSettings()->SetChosenDataTypes(/*sync_everything=*/false,
-                                                      only_history);
+  sync_service->GetUserSettings()->SetSelectedTypes(
+      /*sync_everything=*/false, {syncer::UserSelectableType::kHistory});
   sync_blocker.reset();
   EXPECT_FALSE(CountingFinishedSinceLastAsked());
 
   // We start syncing autofill again. This restarts the counter.
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->GetUserSettings()->SetChosenDataTypes(
-      /*sync_everything=*/false, syncer::UserSelectableTypes());
+  sync_service->GetUserSettings()->SetSelectedTypes(
+      /*sync_everything=*/false, syncer::UserSelectableTypeSet::All());
   sync_blocker.reset();
   WaitForCounting();
   EXPECT_TRUE(IsSyncEnabled());
@@ -176,40 +175,41 @@
   // syncing passwords, and this should restart the counter.
   ASSERT_TRUE(SetupSync());
   ASSERT_TRUE(sync_service->IsSyncFeatureActive());
-  ASSERT_TRUE(sync_service->GetUserSettings()->GetChosenDataTypes().Has(
-      syncer::PASSWORDS));
+  ASSERT_TRUE(sync_service->GetUserSettings()->GetSelectedTypes().Has(
+      syncer::UserSelectableType::kPasswords));
   WaitForCounting();
   EXPECT_TRUE(IsSyncEnabled());
 
   // We stop syncing passwords in particular. This restarts the counter.
-  syncer::ModelTypeSet everything_except_passwords =
-      syncer::UserSelectableTypes();
-  everything_except_passwords.Remove(syncer::PASSWORDS);
+  syncer::UserSelectableTypeSet everything_except_passwords =
+      syncer::UserSelectableTypeSet::All();
+  everything_except_passwords.Remove(syncer::UserSelectableType::kPasswords);
   auto sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->GetUserSettings()->SetChosenDataTypes(
+  sync_service->GetUserSettings()->SetSelectedTypes(
       /*sync_everything=*/false, everything_except_passwords);
-  ASSERT_FALSE(sync_service->GetUserSettings()->GetChosenDataTypes().Has(
-      syncer::PASSWORDS));
+  ASSERT_FALSE(sync_service->GetUserSettings()->GetSelectedTypes().Has(
+      syncer::UserSelectableType::kPasswords));
   sync_blocker.reset();
   WaitForCounting();
-  ASSERT_FALSE(sync_service->GetUserSettings()->GetChosenDataTypes().Has(
-      syncer::PASSWORDS));
+  ASSERT_FALSE(sync_service->GetUserSettings()->GetSelectedTypes().Has(
+      syncer::UserSelectableType::kPasswords));
   EXPECT_FALSE(IsSyncEnabled());
 
   // If password sync is not affected, the counter is not restarted.
-  syncer::ModelTypeSet only_history(syncer::TYPED_URLS);
-  sync_service->GetUserSettings()->SetChosenDataTypes(/*sync_everything=*/false,
-                                                      only_history);
+  syncer::UserSelectableTypeSet only_history(
+      syncer::UserSelectableType::kHistory);
+  sync_service->GetUserSettings()->SetSelectedTypes(/*sync_everything=*/false,
+                                                    only_history);
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->GetUserSettings()->SetChosenDataTypes(/*sync_everything=*/false,
-                                                      only_history);
+  sync_service->GetUserSettings()->SetSelectedTypes(/*sync_everything=*/false,
+                                                    only_history);
   sync_blocker.reset();
   EXPECT_FALSE(CountingFinishedSinceLastAsked());
 
   // We start syncing passwords again. This restarts the counter.
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->GetUserSettings()->SetChosenDataTypes(
-      /*sync_everything=*/false, syncer::UserSelectableTypes());
+  sync_service->GetUserSettings()->SetSelectedTypes(
+      /*sync_everything=*/false, syncer::UserSelectableTypeSet::All());
   sync_blocker.reset();
   WaitForCounting();
   EXPECT_TRUE(IsSyncEnabled());
@@ -246,8 +246,8 @@
   // syncing history deletion, and this should restart the counter.
   ASSERT_TRUE(SetupSync());
   ASSERT_TRUE(sync_service->IsSyncFeatureActive());
-  ASSERT_TRUE(sync_service->GetUserSettings()->GetChosenDataTypes().Has(
-      syncer::TYPED_URLS));
+  ASSERT_TRUE(sync_service->GetUserSettings()->GetSelectedTypes().Has(
+      syncer::UserSelectableType::kHistory));
   ASSERT_TRUE(sync_service->GetActiveDataTypes().Has(
       syncer::HISTORY_DELETE_DIRECTIVES));
 
@@ -255,41 +255,43 @@
   EXPECT_TRUE(IsSyncEnabled());
 
   // We stop syncing history deletion in particular. This restarts the counter.
-  syncer::ModelTypeSet everything_except_history =
-      syncer::UserSelectableTypes();
-  everything_except_history.Remove(syncer::TYPED_URLS);
+  syncer::UserSelectableTypeSet everything_except_history =
+      syncer::UserSelectableTypeSet::All();
+  everything_except_history.Remove(syncer::UserSelectableType::kHistory);
   auto sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->GetUserSettings()->SetChosenDataTypes(
+  sync_service->GetUserSettings()->SetSelectedTypes(
       /*sync_everything=*/false, everything_except_history);
   sync_blocker.reset();
   WaitForCounting();
   EXPECT_FALSE(IsSyncEnabled());
 
   // If the history deletion sync is not affected, the counter is not restarted.
-  syncer::ModelTypeSet only_passwords(syncer::PASSWORDS);
-  sync_service->GetUserSettings()->SetChosenDataTypes(/*sync_everything=*/false,
-                                                      only_passwords);
+  syncer::UserSelectableTypeSet only_passwords(
+      syncer::UserSelectableType::kPasswords);
+  sync_service->GetUserSettings()->SetSelectedTypes(/*sync_everything=*/false,
+                                                    only_passwords);
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->GetUserSettings()->SetChosenDataTypes(/*sync_everything=*/false,
-                                                      only_passwords);
+  sync_service->GetUserSettings()->SetSelectedTypes(/*sync_everything=*/false,
+                                                    only_passwords);
   sync_blocker.reset();
   EXPECT_FALSE(counter.HasTrackedTasks());
   EXPECT_FALSE(CountingFinishedSinceLastAsked());
 
   // Same in this case.
-  syncer::ModelTypeSet autofill_and_passwords(syncer::AUTOFILL,
-                                              syncer::PASSWORDS);
+  syncer::UserSelectableTypeSet autofill_and_passwords(
+      syncer::UserSelectableType::kAutofill,
+      syncer::UserSelectableType::kPasswords);
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->GetUserSettings()->SetChosenDataTypes(/*sync_everything=*/false,
-                                                      autofill_and_passwords);
+  sync_service->GetUserSettings()->SetSelectedTypes(/*sync_everything=*/false,
+                                                    autofill_and_passwords);
   sync_blocker.reset();
   EXPECT_FALSE(counter.HasTrackedTasks());
   EXPECT_FALSE(CountingFinishedSinceLastAsked());
 
   // We start syncing history deletion again. This restarts the counter.
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->GetUserSettings()->SetChosenDataTypes(
-      /*sync_everything=*/false, syncer::UserSelectableTypes());
+  sync_service->GetUserSettings()->SetSelectedTypes(
+      /*sync_everything=*/false, syncer::UserSelectableTypeSet::All());
   sync_blocker.reset();
   WaitForCounting();
   EXPECT_TRUE(IsSyncEnabled());
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 3d1a4c9..a5a4abc 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2690,7 +2690,7 @@
 }
 #endif
 
-QuotaPermissionContext*
+scoped_refptr<content::QuotaPermissionContext>
 ChromeContentBrowserClient::CreateQuotaPermissionContext() {
   return new ChromeQuotaPermissionContext();
 }
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index e8b6c8c..7895949 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -280,8 +280,8 @@
 #if defined(OS_ANDROID)
   bool ShouldUseGmsCoreGeolocationProvider() override;
 #endif
-
-  content::QuotaPermissionContext* CreateQuotaPermissionContext() override;
+  scoped_refptr<content::QuotaPermissionContext> CreateQuotaPermissionContext()
+      override;
   void GetQuotaSettings(
       content::BrowserContext* context,
       content::StoragePartition* partition,
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
index 1f6b6c6..1865851 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
@@ -34,8 +34,10 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/settings/cros_settings_names.h"
+#include "components/crx_file/crx_verifier.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "content/public/test/test_utils.h"
+#include "extensions/browser/sandboxed_unpacker.h"
 #include "extensions/common/extension.h"
 #include "net/base/host_port_pair.h"
 #include "net/dns/mock_host_resolver.h"
@@ -228,7 +230,10 @@
 
 class KioskAppManagerTest : public InProcessBrowserTest {
  public:
-  KioskAppManagerTest() : settings_helper_(false), fake_cws_(new FakeCWS()) {}
+  KioskAppManagerTest()
+      : settings_helper_(false),
+        fake_cws_(new FakeCWS()),
+        verifier_format_override_(crx_file::VerifierFormat::CRX3) {}
   ~KioskAppManagerTest() override {}
 
   // InProcessBrowserTest overrides:
@@ -462,6 +467,8 @@
  private:
   base::ScopedTempDir temp_dir_;
   std::unique_ptr<FakeCWS> fake_cws_;
+  extensions::SandboxedUnpacker::ScopedVerifierFormatOverrideForTest
+      verifier_format_override_;
 
   DISALLOW_COPY_AND_ASSIGN(KioskAppManagerTest);
 };
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc
index a6c29d9..02dc656 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.cc
@@ -146,17 +146,10 @@
 
 ArcSelectFilesHandler::ArcSelectFilesHandler(content::BrowserContext* context)
     : profile_(Profile::FromBrowserContext(context)) {
-  select_file_dialog_ = ui::SelectFileDialog::Create(this, nullptr);
-  dialog_script_executor_ =
-      base::MakeRefCounted<SelectFileDialogScriptExecutor>(
-          select_file_dialog_.get());
+  dialog_holder_ = std::make_unique<SelectFileDialogHolder>(this);
 }
 
-ArcSelectFilesHandler::~ArcSelectFilesHandler() {
-  // select_file_dialog_ can be nullptr only in unit tests.
-  if (select_file_dialog_.get())
-    select_file_dialog_->ListenerDestroyed();
-}
+ArcSelectFilesHandler::~ArcSelectFilesHandler() = default;
 
 void ArcSelectFilesHandler::SelectFiles(
     const mojom::SelectFilesRequestPtr& request,
@@ -178,14 +171,7 @@
   BuildFileTypeInfo(request, &file_type_info);
   base::FilePath default_path = GetInitialFilePath(request);
 
-  select_file_dialog_->SelectFile(
-      dialog_type,
-      /*title=*/base::string16(),
-      /*default_path=*/default_path, &file_type_info,
-      /*file_type_index=*/0,
-      /*default_extension=*/base::FilePath::StringType(),
-      /*owning_window=*/nullptr,
-      /*params=*/nullptr);
+  dialog_holder_->SelectFile(dialog_type, default_path, &file_type_info);
 }
 
 void ArcSelectFilesHandler::FileSelected(const base::FilePath& path,
@@ -254,7 +240,7 @@
           base::StringPrintf(kScriptClickFile, quotedClickTargetName.c_str());
       break;
   }
-  dialog_script_executor_->ExecuteJavaScript(script, {});
+  dialog_holder_->ExecuteJavaScript(script, {});
 
   std::move(callback).Run();
 }
@@ -263,33 +249,45 @@
     mojom::FileSystemHost::GetFileSelectorElementsCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  dialog_script_executor_->ExecuteJavaScript(
+  dialog_holder_->ExecuteJavaScript(
       kScriptGetElements,
       base::BindOnce(&OnGetElementsScriptResults, std::move(callback)));
 }
 
-void ArcSelectFilesHandler::SetSelectFileDialogForTesting(
-    ui::SelectFileDialog* dialog) {
-  select_file_dialog_ = dialog;
+void ArcSelectFilesHandler::SetDialogHolderForTesting(
+    std::unique_ptr<SelectFileDialogHolder> dialog_holder) {
+  dialog_holder_ = std::move(dialog_holder);
 }
 
-void ArcSelectFilesHandler::SetDialogScriptExecutorForTesting(
-    SelectFileDialogScriptExecutor* dialog_script_executor) {
-  dialog_script_executor_ = dialog_script_executor;
+SelectFileDialogHolder::SelectFileDialogHolder(
+    ui::SelectFileDialog::Listener* listener) {
+  select_file_dialog_ = static_cast<SelectFileDialogExtension*>(
+      ui::SelectFileDialog::Create(listener, nullptr).get());
 }
 
-SelectFileDialogScriptExecutor::SelectFileDialogScriptExecutor(
-    ui::SelectFileDialog* dialog)
-    : select_file_dialog_(dialog) {}
+SelectFileDialogHolder::~SelectFileDialogHolder() {
+  // select_file_dialog_ can be nullptr only in unit tests.
+  if (select_file_dialog_.get())
+    select_file_dialog_->ListenerDestroyed();
+}
 
-SelectFileDialogScriptExecutor::~SelectFileDialogScriptExecutor() {}
+void SelectFileDialogHolder::SelectFile(
+    ui::SelectFileDialog::Type type,
+    const base::FilePath& default_path,
+    const ui::SelectFileDialog::FileTypeInfo* file_types) {
+  select_file_dialog_->SelectFile(
+      type,
+      /*title=*/base::string16(), default_path, file_types,
+      /*file_type_index=*/0,
+      /*default_extension=*/base::FilePath::StringType(),
+      /*owning_window=*/nullptr,
+      /*params=*/nullptr);
+}
 
-void SelectFileDialogScriptExecutor::ExecuteJavaScript(
+void SelectFileDialogHolder::ExecuteJavaScript(
     const std::string& script,
     content::RenderFrameHost::JavaScriptResultCallback callback) {
-  content::RenderViewHost* view_host =
-      static_cast<SelectFileDialogExtension*>(select_file_dialog_)
-          ->GetRenderViewHost();
+  content::RenderViewHost* view_host = select_file_dialog_->GetRenderViewHost();
   content::RenderFrameHost* frame_host =
       view_host ? view_host->GetMainFrame() : nullptr;
 
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.h b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.h
index 4e0aa91..513daad 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.h
+++ b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.h
@@ -10,6 +10,7 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
+#include "chrome/browser/ui/views/select_file_dialog_extension.h"
 #include "components/arc/common/file_system.mojom.h"
 #include "content/public/browser/render_frame_host.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
@@ -22,7 +23,7 @@
 
 namespace arc {
 
-class SelectFileDialogScriptExecutor;
+class SelectFileDialogHolder;
 
 // Exposed for testing.
 extern const char kScriptClickOk[];
@@ -54,43 +55,41 @@
                           void* params) override;
   void FileSelectionCanceled(void* params) override;
 
-  void SetSelectFileDialogForTesting(ui::SelectFileDialog* dialog);
-  void SetDialogScriptExecutorForTesting(
-      SelectFileDialogScriptExecutor* dialog_script_executor);
-
  private:
   friend class ArcSelectFilesHandlerTest;
 
   void FilesSelectedInternal(const std::vector<base::FilePath>& files,
                              void* params);
 
+  void SetDialogHolderForTesting(
+      std::unique_ptr<SelectFileDialogHolder> dialog_holder);
+
   Profile* const profile_;
 
   mojom::FileSystemHost::SelectFilesCallback callback_;
-  scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
-  scoped_refptr<SelectFileDialogScriptExecutor> dialog_script_executor_;
+  std::unique_ptr<SelectFileDialogHolder> dialog_holder_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcSelectFilesHandler);
 };
 
-// Helper class for executing JavaScript on a given SelectFileDialog.
-class SelectFileDialogScriptExecutor
-    : public base::RefCounted<SelectFileDialogScriptExecutor> {
+// Wrapper for SelectFileDialogExtension.
+// Since it is not easy to create a mock class for SelectFileDialogExtension,
+// this class is replaced with a mock class instead in unit tests.
+class SelectFileDialogHolder {
  public:
-  explicit SelectFileDialogScriptExecutor(
-      ui::SelectFileDialog* select_file_dialog);
+  explicit SelectFileDialogHolder(ui::SelectFileDialog::Listener* listener);
+  virtual ~SelectFileDialogHolder();
+
+  virtual void SelectFile(ui::SelectFileDialog::Type type,
+                          const base::FilePath& default_path,
+                          const ui::SelectFileDialog::FileTypeInfo* file_types);
 
   virtual void ExecuteJavaScript(
       const std::string& script,
       content::RenderFrameHost::JavaScriptResultCallback callback);
 
- protected:
-  friend class base::RefCounted<SelectFileDialogScriptExecutor>;
-
-  virtual ~SelectFileDialogScriptExecutor();
-
  private:
-  ui::SelectFileDialog* select_file_dialog_;
+  scoped_refptr<SelectFileDialogExtension> select_file_dialog_;
 };
 
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler_unittest.cc
index 34a1533..c0062b5 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler_unittest.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_select_files_handler_unittest.cc
@@ -64,47 +64,17 @@
   return element;
 }
 
-class MockSelectFileDialog : public SelectFileDialog {
+class MockSelectFileDialogHolder : public SelectFileDialogHolder {
  public:
-  MockSelectFileDialog(SelectFileDialog::Listener* listener,
-                       std::unique_ptr<ui::SelectFilePolicy> policy)
-      : SelectFileDialog(listener, std::move(policy)) {}
-  MOCK_METHOD8(SelectFile,
-               void(SelectFileDialog::Type,
-                    const base::string16&,
-                    const base::FilePath&,
-                    const FileTypeInfo*,
-                    int,
-                    const base::FilePath::StringType&,
-                    gfx::NativeWindow,
-                    void*));
-  MOCK_METHOD8(SelectFileImpl,
-               void(SelectFileDialog::Type,
-                    const base::string16&,
-                    const base::FilePath&,
-                    const FileTypeInfo*,
-                    int,
-                    const base::FilePath::StringType&,
-                    gfx::NativeWindow,
-                    void*));
-  MOCK_METHOD0(HasMultipleFileTypeChoicesImpl, bool());
-  MOCK_METHOD0(ListenerDestroyed, void());
-  MOCK_CONST_METHOD1(IsRunning, bool(gfx::NativeWindow));
-
- protected:
-  ~MockSelectFileDialog() override = default;
-};
-
-class MockSelectFileDialogScriptExecutor
-    : public SelectFileDialogScriptExecutor {
- public:
-  explicit MockSelectFileDialogScriptExecutor(ui::SelectFileDialog* dialog)
-      : SelectFileDialogScriptExecutor(dialog) {}
+  explicit MockSelectFileDialogHolder(ui::SelectFileDialog::Listener* listener)
+      : SelectFileDialogHolder(listener) {}
+  ~MockSelectFileDialogHolder() override = default;
+  MOCK_METHOD3(SelectFile,
+               void(ui::SelectFileDialog::Type type,
+                    const base::FilePath& default_path,
+                    const ui::SelectFileDialog::FileTypeInfo* file_types));
   MOCK_METHOD2(ExecuteJavaScript,
                void(const std::string&, JavaScriptResultCallback));
-
- protected:
-  ~MockSelectFileDialogScriptExecutor() override = default;
 };
 
 }  // namespace
@@ -124,15 +94,11 @@
     arc_select_files_handler_ =
         std::make_unique<ArcSelectFilesHandler>(profile);
 
-    mock_dialog_ = new MockSelectFileDialog(
-        arc_select_files_handler_.get(),
-        std::make_unique<ChromeSelectFilePolicy>(nullptr));
-    arc_select_files_handler_->SetSelectFileDialogForTesting(
-        mock_dialog_.get());
-
-    mock_script_executor_ = new MockSelectFileDialogScriptExecutor(nullptr);
-    arc_select_files_handler_->SetDialogScriptExecutorForTesting(
-        mock_script_executor_.get());
+    std::unique_ptr<MockSelectFileDialogHolder> mock_dialog_holder =
+        std::make_unique<MockSelectFileDialogHolder>(nullptr);
+    mock_dialog_holder_ = mock_dialog_holder.get();
+    arc_select_files_handler_->SetDialogHolderForTesting(
+        std::move(mock_dialog_holder));
   }
 
   void TearDown() override {
@@ -149,13 +115,11 @@
     request->action_type = request_action_type;
     request->allow_multiple = request_allow_multiple;
 
-    EXPECT_CALL(*mock_dialog_,
-                SelectFileImpl(expected_dialog_type, _, _, _, _, _, _, _))
+    EXPECT_CALL(*mock_dialog_holder_, SelectFile(expected_dialog_type, _, _))
         .Times(1);
 
     SelectFilesCallback callback;
     arc_select_files_handler_->SelectFiles(request, std::move(callback));
-    testing::Mock::VerifyAndClearExpectations(mock_dialog_.get());
   }
 
   void CallOnFileSelectorEventAndCheckScript(
@@ -167,7 +131,7 @@
     event->click_target = mojom::FileSelectorElement::New();
     event->click_target->name = target_name;
 
-    EXPECT_CALL(*mock_script_executor_, ExecuteJavaScript(expected_script, _))
+    EXPECT_CALL(*mock_dialog_holder_, ExecuteJavaScript(expected_script, _))
         .Times(1);
 
     base::MockCallback<mojom::FileSystemHost::OnFileSelectorEventCallback>
@@ -176,14 +140,12 @@
 
     arc_select_files_handler_->OnFileSelectorEvent(std::move(event),
                                                    callback.Get());
-    testing::Mock::VerifyAndClearExpectations(mock_script_executor_.get());
   }
 
   content::TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<TestingProfileManager> profile_manager_;
   std::unique_ptr<ArcSelectFilesHandler> arc_select_files_handler_;
-  scoped_refptr<MockSelectFileDialog> mock_dialog_;
-  scoped_refptr<MockSelectFileDialogScriptExecutor> mock_script_executor_;
+  MockSelectFileDialogHolder* mock_dialog_holder_;
 };
 
 TEST_F(ArcSelectFilesHandlerTest, SelectFiles_DialogType) {
@@ -215,11 +177,10 @@
   extensions.push_back("txt");
   expected_file_type_info.extensions.push_back(extensions);
 
-  EXPECT_CALL(*mock_dialog_,
-              SelectFileImpl(_, _, _,
-                             testing::Pointee(
-                                 FileTypeInfoMatcher(expected_file_type_info)),
-                             _, _, _, _))
+  EXPECT_CALL(
+      *mock_dialog_holder_,
+      SelectFile(
+          _, _, testing::Pointee(FileTypeInfoMatcher(expected_file_type_info))))
       .Times(1);
 
   base::MockCallback<SelectFilesCallback> callback;
@@ -237,9 +198,8 @@
   base::FilePath expected_file_path = base::FilePath(
       "/special/arc-documents-provider/testing.provider/doc:root");
 
-  EXPECT_CALL(
-      *mock_dialog_,
-      SelectFileImpl(_, _, FilePathMatcher(expected_file_path), _, _, _, _, _))
+  EXPECT_CALL(*mock_dialog_holder_,
+              SelectFile(_, FilePathMatcher(expected_file_path), _))
       .Times(1);
 
   base::MockCallback<SelectFilesCallback> callback;
@@ -280,7 +240,7 @@
 }
 
 TEST_F(ArcSelectFilesHandlerTest, GetFileSelectorElements) {
-  EXPECT_CALL(*mock_script_executor_, ExecuteJavaScript(kScriptGetElements, _))
+  EXPECT_CALL(*mock_dialog_holder_, ExecuteJavaScript(kScriptGetElements, _))
       .WillOnce(testing::Invoke(
           [](const std::string&, JavaScriptResultCallback callback) {
             std::move(callback).Run(
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
index 2cd8d9bc..e430278 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
@@ -205,6 +205,10 @@
   std::unique_ptr<ChromeZoomLevelPrefs::DefaultZoomLevelSubscription>
       default_zoom_level_subscription_;
 
+  // Name of the default network. Used to keep track of whether the default
+  // network has changed.
+  std::string default_network_name_;
+
   DISALLOW_COPY_AND_ASSIGN(ArcSettingsServiceImpl);
 };
 
@@ -277,8 +281,17 @@
   // kProxy pref has more priority than the default network update.
   // If a default network is changed to the network with ONC policy with proxy
   // settings, it should be translated here.
-  if (network && !IsPrefProxyConfigApplied())
-    SyncProxySettings();
+  if (!network || IsPrefProxyConfigApplied())
+    return;
+
+  // This function is called when the default network changes or when any of its
+  // properties change. Only trigger a proxy settings sync to ARC when the
+  // default network changes.
+  if (default_network_name_ == network->name())
+    return;
+  default_network_name_ = network->name();
+
+  SyncProxySettings();
 }
 
 bool ArcSettingsServiceImpl::IsPrefProxyConfigApplied() const {
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc
index 72bdbaa..8c2f090 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -65,8 +65,6 @@
 namespace crostini {
 
 namespace {
-
-constexpr int64_t kMinimumDiskSize = 1ll * 1024 * 1024 * 1024;  // 1 GiB
 constexpr base::FilePath::CharType kHomeDirectory[] =
     FILE_PATH_LITERAL("/home");
 const char kSeparator[] = "--";
@@ -261,18 +259,6 @@
     }
 
     int64_t disk_size_available = (free_disk_bytes * 9) / 10;
-    // If there's no existing disk image, need enough space to create one.
-    if (disk_space_taken == 0) {
-      // Don't enforce minimum disk size on dev box or trybots because
-      // base::SysInfo::AmountOfFreeDiskSpace returns zero in testing.
-      if (disk_size_available < kMinimumDiskSize &&
-          base::SysInfo::IsRunningOnChromeOS()) {
-        LOG(ERROR) << "Insufficient disk available. Need to free "
-                   << kMinimumDiskSize - disk_size_available << " bytes";
-        FinishRestart(CrostiniResult::INSUFFICIENT_DISK);
-        return;
-      }
-    }
     // If we have an already existing disk, CreateDiskImage will just return its
     // path so we can pass it to StartTerminaVm.
     crostini_manager_->CreateDiskImage(
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
index 1a65f260..bc5b9ce7 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
@@ -292,10 +292,10 @@
   }
 
   if (sync_service->GetUserSettings()->IsFirstSetupComplete()) {
-    // Sync is set up. Report whether the user has chosen to sync themes.
+    // Sync is set up. Report whether the user has selected to sync themes.
     dict->SetBoolean(kSyncThemes,
-                     sync_service->GetUserSettings()->GetChosenDataTypes().Has(
-                         syncer::THEMES));
+                     sync_service->GetUserSettings()->GetSelectedTypes().Has(
+                         syncer::UserSelectableType::kThemes));
     Respond(OneArgument(std::move(dict)));
     return;
   }
diff --git a/chrome/browser/chromeos/file_manager/file_tasks_notifier.cc b/chrome/browser/chromeos/file_manager/file_tasks_notifier.cc
index c05d66a..61a9d57 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks_notifier.cc
+++ b/chrome/browser/chromeos/file_manager/file_tasks_notifier.cc
@@ -4,11 +4,24 @@
 
 #include "chrome/browser/chromeos/file_manager/file_tasks_notifier.h"
 
+#include <memory>
+#include <utility>
+
+#include "base/barrier_closure.h"
 #include "base/callback.h"
+#include "base/files/file_util.h"
+#include "base/task/post_task.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "chrome/browser/chromeos/drive/drive_integration_service.h"
 #include "chrome/browser/chromeos/file_manager/file_tasks_notifier_factory.h"
 #include "chrome/browser/chromeos/file_manager/file_tasks_observer.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/download/public/common/download_item.h"
+#include "content/public/browser/network_service_instance.h"
+#include "mojo/public/cpp/bindings/callback_helpers.h"
+#include "services/network/public/cpp/network_connection_tracker.h"
+#include "storage/browser/fileapi/external_mount_points.h"
+#include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_url.h"
 #include "storage/common/fileapi/file_system_types.h"
 #include "ui/shell_dialogs/selected_file_info.h"
@@ -28,8 +41,21 @@
   }
 }
 
+void ReturnQueryResults(
+    std::unique_ptr<std::vector<FileTasksNotifier::FileAvailability>> results,
+    base::OnceCallback<void(std::vector<FileTasksNotifier::FileAvailability>)>
+        callback) {
+  std::move(callback).Run(std::move(*results));
+}
+
 }  // namespace
 
+struct FileTasksNotifier::PendingFileAvailabilityTask {
+  storage::FileSystemURL url;
+  FileTasksNotifier::FileAvailability* output;
+  base::OnceClosure done;
+};
+
 FileTasksNotifier::FileTasksNotifier(Profile* profile)
     : profile_(profile),
       download_notifier_(content::BrowserContext::GetDownloadManager(profile_),
@@ -50,6 +76,45 @@
   observers_.RemoveObserver(observer);
 }
 
+void FileTasksNotifier::QueryFileAvailability(
+    const std::vector<base::FilePath>& paths,
+    base::OnceCallback<void(std::vector<FileAvailability>)> callback) {
+  const auto* mount_points = storage::ExternalMountPoints::GetSystemInstance();
+  std::vector<FileAvailability> results(paths.size(),
+                                        FileAvailability::kUnknown);
+
+  std::vector<PendingFileAvailabilityTask> tasks;
+  for (size_t i = 0; i < paths.size(); ++i) {
+    base::FilePath virtual_path;
+    if (!mount_points->GetVirtualPath(paths[i], &virtual_path)) {
+      continue;
+    }
+    auto url = mount_points->CreateCrackedFileSystemURL(
+        url::Origin(), storage::kFileSystemTypeExternal, virtual_path);
+    if (!url.is_valid() || !IsSupportedFileSystemType(url.type())) {
+      results[i] = FileAvailability::kGone;
+      continue;
+    }
+    tasks.push_back({url, &results[i]});
+  }
+  if (tasks.empty()) {
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), std::move(results)));
+    return;
+  }
+
+  auto results_owner = std::make_unique<std::vector<FileAvailability>>();
+  std::swap(results, *results_owner);
+  auto closure = base::BarrierClosure(
+      tasks.size(),
+      base::BindOnce(&ReturnQueryResults, std::move(results_owner),
+                     std::move(callback)));
+  for (auto& task : tasks) {
+    task.done = closure;
+    GetFileAvailability(std::move(task));
+  }
+}
+
 void FileTasksNotifier::OnDownloadUpdated(content::DownloadManager* manager,
                                           download::DownloadItem* item) {
   if (item->IsTransient() ||
@@ -103,5 +168,83 @@
   }
 }
 
+void FileTasksNotifier::GetFileAvailability(PendingFileAvailabilityTask task) {
+  if (task.url.type() != storage::kFileSystemTypeDriveFs) {
+    base::FilePath path = std::move(task.url.path());
+    base::PostTaskWithTraitsAndReplyWithResult(
+        FROM_HERE, {base::MayBlock()},
+        base::BindOnce(&base::PathExists, std::move(path)),
+        base::BindOnce(&FileTasksNotifier::ForwardQueryResult,
+                       std::move(task)));
+    return;
+  }
+  if (!GetDriveFsInterface()) {
+    *task.output = FileTasksNotifier::FileAvailability::kUnknown;
+    base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                     std::move(task.done));
+    return;
+  }
+  base::FilePath drive_path;
+  if (!GetRelativeDrivePath(task.url.path(), &drive_path)) {
+    *task.output = FileTasksNotifier::FileAvailability::kGone;
+    base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                     std::move(task.done));
+    return;
+  }
+  GetDriveFsInterface()->GetMetadata(
+      drive_path,
+      mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+          base::BindOnce(&FileTasksNotifier::ForwardDriveFsQueryResult,
+                         std::move(task), IsOffline()),
+          drive::FILE_ERROR_SERVICE_UNAVAILABLE, nullptr));
+}
+
+// static
+void FileTasksNotifier::ForwardQueryResult(PendingFileAvailabilityTask task,
+                                           bool exists) {
+  *task.output = exists ? FileTasksNotifier::FileAvailability::kOk
+                        : FileTasksNotifier::FileAvailability::kGone;
+  std::move(task.done).Run();
+}
+
+// static
+void FileTasksNotifier::ForwardDriveFsQueryResult(
+    PendingFileAvailabilityTask task,
+    bool is_offline,
+    drive::FileError error,
+    drivefs::mojom::FileMetadataPtr metadata) {
+  if (error == drive::FILE_ERROR_NOT_FOUND) {
+    *task.output = FileTasksNotifier::FileAvailability::kGone;
+  } else if (error != drive::FILE_ERROR_OK) {
+    *task.output = FileTasksNotifier::FileAvailability::kUnknown;
+  } else {
+    *task.output =
+        metadata->available_offline || !is_offline
+            ? FileTasksNotifier::FileAvailability::kOk
+            : FileTasksNotifier::FileAvailability::kTemporarilyUnavailable;
+  }
+  std::move(task.done).Run();
+}
+
+drivefs::mojom::DriveFs* FileTasksNotifier::GetDriveFsInterface() {
+  drive::DriveIntegrationService* integration_service =
+      drive::DriveIntegrationServiceFactory::FindForProfile(profile_);
+  if (!integration_service || !integration_service->IsMounted()) {
+    return nullptr;
+  }
+  return integration_service->GetDriveFsInterface();
+}
+
+bool FileTasksNotifier::GetRelativeDrivePath(
+    const base::FilePath& path,
+    base::FilePath* drive_relative_path) {
+  return drive::DriveIntegrationServiceFactory::FindForProfile(profile_)
+      ->GetRelativeDrivePath(path, drive_relative_path);
+}
+
+bool FileTasksNotifier::IsOffline() {
+  return content::GetNetworkConnectionTracker()->IsOffline();
+}
+
 }  // namespace file_tasks
 }  // namespace file_manager
diff --git a/chrome/browser/chromeos/file_manager/file_tasks_notifier.h b/chrome/browser/chromeos/file_manager/file_tasks_notifier.h
index 8a9b7c3..93b5ea0 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks_notifier.h
+++ b/chrome/browser/chromeos/file_manager/file_tasks_notifier.h
@@ -10,7 +10,9 @@
 #include "base/callback_forward.h"
 #include "base/observer_list.h"
 #include "chrome/browser/chromeos/file_manager/file_tasks_observer.h"
+#include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
 #include "components/download/content/public/all_download_item_notifier.h"
+#include "components/drive/file_errors.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 class Profile;
@@ -56,6 +58,10 @@
   void AddObserver(FileTasksObserver*);
   void RemoveObserver(FileTasksObserver*);
 
+  void QueryFileAvailability(
+      const std::vector<base::FilePath>&,
+      base::OnceCallback<void(std::vector<FileAvailability>)>);
+
   void NotifyFileTasks(const std::vector<storage::FileSystemURL>& file_urls);
 
   void NotifyFileDialogSelection(const std::vector<ui::SelectedFileInfo>& files,
@@ -66,9 +72,25 @@
                          download::DownloadItem* item) override;
 
  private:
+  struct PendingFileAvailabilityTask;
   void NotifyObservers(const std::vector<base::FilePath>& paths,
                        FileTasksObserver::OpenType open_type);
 
+  void GetFileAvailability(PendingFileAvailabilityTask task);
+  static void ForwardQueryResult(PendingFileAvailabilityTask task, bool exists);
+
+  static void ForwardDriveFsQueryResult(
+      PendingFileAvailabilityTask task,
+      bool is_offline,
+      drive::FileError error,
+      drivefs::mojom::FileMetadataPtr metadata);
+
+  // Virtual for stubbing out in tests.
+  virtual drivefs::mojom::DriveFs* GetDriveFsInterface();
+  virtual bool GetRelativeDrivePath(const base::FilePath& path,
+                                    base::FilePath* drive_relative_path);
+  virtual bool IsOffline();
+
   Profile* const profile_;
   download::AllDownloadItemNotifier download_notifier_;
   base::ObserverList<FileTasksObserver> observers_;
diff --git a/chrome/browser/chromeos/file_manager/file_tasks_notifier_unittest.cc b/chrome/browser/chromeos/file_manager/file_tasks_notifier_unittest.cc
index 3151548..79b5308 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks_notifier_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/file_tasks_notifier_unittest.cc
@@ -5,12 +5,21 @@
 #include "chrome/browser/chromeos/file_manager/file_tasks_notifier.h"
 
 #include <memory>
+#include <string>
+#include <utility>
 
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/scoped_observer.h"
+#include "base/test/bind_test_util.h"
 #include "chrome/browser/chromeos/file_manager/file_tasks_observer.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/components/drivefs/mojom/drivefs.mojom-test-utils.h"
+#include "components/drive/file_errors.h"
 #include "content/public/test/fake_download_item.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "storage/browser/fileapi/external_mount_points.h"
 #include "storage/browser/fileapi/file_system_url.h"
 #include "storage/common/fileapi/file_system_types.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -35,6 +44,35 @@
   return ui::SelectedFileInfo(path, local_path);
 }
 
+class FakeDriveFs : public drivefs::mojom::DriveFsInterceptorForTesting {
+ public:
+  DriveFs* GetForwardingInterface() override {
+    NOTREACHED();
+    return nullptr;
+  }
+
+  void GetMetadata(const base::FilePath& path,
+                   GetMetadataCallback callback) override {
+    if (path.value().find("offline") != std::string::npos) {
+      auto metadata = drivefs::mojom::FileMetadata::New();
+      metadata->available_offline = path.value() == "available_offline";
+      metadata->capabilities = drivefs::mojom::Capabilities::New();
+      std::move(callback).Run(drive::FILE_ERROR_OK, std::move(metadata));
+      return;
+    }
+    if (path.value() == "not_found") {
+      std::move(callback).Run(drive::FILE_ERROR_NOT_FOUND, nullptr);
+      return;
+    }
+    if (path.value() == "error") {
+      std::move(callback).Run(drive::FILE_ERROR_SERVICE_UNAVAILABLE, nullptr);
+      return;
+    }
+    FAIL() << "Unexpected DriveFS metadata request for " << path;
+    std::move(callback).Run(drive::FILE_ERROR_INVALID_URL, nullptr);
+  }
+};
+
 class MockFileTasksObserver : public file_tasks::FileTasksObserver {
  public:
   explicit MockFileTasksObserver(FileTasksNotifier* notifier)
@@ -57,15 +95,64 @@
       observer_;
 };
 
+class FileTasksNotifierForTest : public FileTasksNotifier {
+ public:
+  FileTasksNotifierForTest(Profile* profile, drivefs::mojom::DriveFsPtr drivefs)
+      : FileTasksNotifier(profile), drivefs_(std::move(drivefs)) {}
+
+  drivefs::mojom::DriveFs* GetDriveFsInterface() override {
+    return drivefs_.get();
+  }
+
+  bool GetRelativeDrivePath(const base::FilePath& path,
+                            base::FilePath* drive_relative_path) override {
+    *drive_relative_path = path.BaseName();
+    return true;
+  }
+
+  bool IsOffline() override { return is_offline_; }
+
+  void set_is_offline(bool is_offline) { is_offline_ = is_offline; }
+
+ private:
+  const drivefs::mojom::DriveFsPtr drivefs_;
+  bool is_offline_ = false;
+};
+
 class FileTasksNotifierTest : public testing::Test {
  protected:
+  FileTasksNotifierTest() : drivefs_binding_(&fake_drivefs_) {}
+
   void SetUp() override {
     profile_ = std::make_unique<TestingProfile>();
-    notifier_ = std::make_unique<FileTasksNotifier>(profile_.get());
+
+    drivefs::mojom::DriveFsPtr fake_drivefs_ptr;
+    drivefs_binding_.Bind(mojo::MakeRequest(&fake_drivefs_ptr));
+    notifier_ = std::make_unique<FileTasksNotifierForTest>(
+        profile_.get(), std::move(fake_drivefs_ptr));
     observer_ = std::make_unique<MockFileTasksObserver>(notifier_.get());
+
+    auto* mount_points = storage::ExternalMountPoints::GetSystemInstance();
+    my_files_ = profile().GetPath().Append("MyFiles");
+    ASSERT_TRUE(base::CreateDirectory(my_files_));
+    base::WriteFile(my_files_.Append("file"), "data", 4);
+    ASSERT_TRUE(mount_points->RegisterFileSystem(
+        "downloads", storage::kFileSystemTypeNativeLocal, {},
+        profile().GetPath().Append("MyFiles")));
+    ASSERT_TRUE(mount_points->RegisterFileSystem(
+        "drivefs", storage::kFileSystemTypeDriveFs, {},
+        base::FilePath("/media/fuse/drivefs")));
+    ASSERT_TRUE(
+        mount_points->RegisterFileSystem("drive", storage::kFileSystemTypeDrive,
+                                         {}, base::FilePath("/special/drive")));
   }
 
   void TearDown() override {
+    auto* mount_points = storage::ExternalMountPoints::GetSystemInstance();
+    mount_points->RevokeFileSystem("downloads");
+    mount_points->RevokeFileSystem("drivefs");
+    mount_points->RevokeFileSystem("drive");
+
     observer_.reset();
     notifier_.reset();
     profile_.reset();
@@ -73,7 +160,7 @@
 
   Profile& profile() { return *profile_; }
   MockFileTasksObserver& observer() { return *observer_; }
-  FileTasksNotifier& notifier() { return *notifier_; }
+  FileTasksNotifierForTest& notifier() { return *notifier_; }
 
   download::DownloadItem* CreateCompletedDownloadItem(
       const base::FilePath& path) {
@@ -83,12 +170,17 @@
     return download_item_.get();
   }
 
+  const base::FilePath& my_files() { return my_files_; }
+
  private:
   content::TestBrowserThreadBundle threads_;
+  FakeDriveFs fake_drivefs_;
+  mojo::Binding<drivefs::mojom::DriveFs> drivefs_binding_;
   std::unique_ptr<TestingProfile> profile_;
-  std::unique_ptr<FileTasksNotifier> notifier_;
+  std::unique_ptr<FileTasksNotifierForTest> notifier_;
   std::unique_ptr<MockFileTasksObserver> observer_;
   std::unique_ptr<content::FakeDownloadItem> download_item_;
+  base::FilePath my_files_;
 };
 
 TEST_F(FileTasksNotifierTest, FileTask_Local) {
@@ -351,6 +443,160 @@
   }
 }
 
+TEST_F(FileTasksNotifierTest, QueryFileAvailability_NotFound) {
+  base::RunLoop run_loop;
+  notifier().QueryFileAvailability(
+      {my_files().Append("not_found.txt")},
+      base::BindLambdaForTesting(
+          [&](std::vector<FileTasksNotifier::FileAvailability> results) {
+            run_loop.Quit();
+            ASSERT_EQ(1u, results.size());
+            EXPECT_EQ(FileTasksNotifier::FileAvailability::kGone, results[0]);
+          }));
+  run_loop.Run();
+}
+
+TEST_F(FileTasksNotifierTest, QueryFileAvailability_FileExists) {
+  base::RunLoop run_loop;
+  notifier().QueryFileAvailability(
+      {my_files().Append("file")},
+      base::BindLambdaForTesting(
+          [&](std::vector<FileTasksNotifier::FileAvailability> results) {
+            run_loop.Quit();
+            ASSERT_EQ(1u, results.size());
+            EXPECT_EQ(FileTasksNotifier::FileAvailability::kOk, results[0]);
+          }));
+  run_loop.Run();
+}
+
+TEST_F(FileTasksNotifierTest, QueryFileAvailability_UnsupportedMountType) {
+  base::RunLoop run_loop;
+  notifier().QueryFileAvailability(
+      {base::FilePath("/special/drive/root/file")},
+      base::BindLambdaForTesting(
+          [&](std::vector<FileTasksNotifier::FileAvailability> results) {
+            run_loop.Quit();
+            ASSERT_EQ(1u, results.size());
+            EXPECT_EQ(FileTasksNotifier::FileAvailability::kGone, results[0]);
+          }));
+  run_loop.Run();
+}
+
+TEST_F(FileTasksNotifierTest, QueryFileAvailability_OutsideMounts) {
+  base::RunLoop run_loop;
+  notifier().QueryFileAvailability(
+      {base::FilePath("/media/fuse/crostini-abcdef/file")},
+      base::BindLambdaForTesting(
+          [&](std::vector<FileTasksNotifier::FileAvailability> results) {
+            run_loop.Quit();
+            ASSERT_EQ(1u, results.size());
+            EXPECT_EQ(FileTasksNotifier::FileAvailability::kUnknown,
+                      results[0]);
+          }));
+  run_loop.Run();
+}
+
+TEST_F(FileTasksNotifierTest, QueryFileAvailability_DriveFsAvailableOffline) {
+  base::RunLoop run_loop;
+  notifier().QueryFileAvailability(
+      {base::FilePath("/media/fuse/drivefs/root/available_offline")},
+      base::BindLambdaForTesting(
+          [&](std::vector<FileTasksNotifier::FileAvailability> results) {
+            run_loop.Quit();
+            ASSERT_EQ(1u, results.size());
+            EXPECT_EQ(FileTasksNotifier::FileAvailability::kOk, results[0]);
+          }));
+  run_loop.Run();
+}
+
+TEST_F(FileTasksNotifierTest, QueryFileAvailability_DriveFsUnavailableOffline) {
+  base::RunLoop run_loop;
+  notifier().QueryFileAvailability(
+      {base::FilePath("/media/fuse/drivefs/root/unavailable_offline")},
+      base::BindLambdaForTesting(
+          [&](std::vector<FileTasksNotifier::FileAvailability> results) {
+            run_loop.Quit();
+            ASSERT_EQ(1u, results.size());
+            EXPECT_EQ(FileTasksNotifier::FileAvailability::kOk, results[0]);
+          }));
+  run_loop.Run();
+}
+
+TEST_F(FileTasksNotifierTest,
+       QueryFileAvailability_DriveFsUnavailableOfflineWhileOffline) {
+  notifier().set_is_offline(true);
+
+  base::RunLoop run_loop;
+  notifier().QueryFileAvailability(
+      {base::FilePath("/media/fuse/drivefs/root/unavailable_offline")},
+      base::BindLambdaForTesting(
+          [&](std::vector<FileTasksNotifier::FileAvailability> results) {
+            run_loop.Quit();
+            ASSERT_EQ(1u, results.size());
+            EXPECT_EQ(
+                FileTasksNotifier::FileAvailability::kTemporarilyUnavailable,
+                results[0]);
+          }));
+  run_loop.Run();
+}
+
+TEST_F(FileTasksNotifierTest, QueryFileAvailability_DriveFsNotFound) {
+  base::RunLoop run_loop;
+  notifier().QueryFileAvailability(
+      {base::FilePath("/media/fuse/drivefs/root/not_found")},
+      base::BindLambdaForTesting(
+          [&](std::vector<FileTasksNotifier::FileAvailability> results) {
+            run_loop.Quit();
+            ASSERT_EQ(1u, results.size());
+            EXPECT_EQ(FileTasksNotifier::FileAvailability::kGone, results[0]);
+          }));
+  run_loop.Run();
+}
+
+TEST_F(FileTasksNotifierTest, QueryFileAvailability_DriveFsServiceError) {
+  base::RunLoop run_loop;
+  notifier().QueryFileAvailability(
+      {base::FilePath("/media/fuse/drivefs/root/error")},
+      base::BindLambdaForTesting(
+          [&](std::vector<FileTasksNotifier::FileAvailability> results) {
+            run_loop.Quit();
+            ASSERT_EQ(1u, results.size());
+            EXPECT_EQ(FileTasksNotifier::FileAvailability::kUnknown,
+                      results[0]);
+          }));
+  run_loop.Run();
+}
+
+TEST_F(FileTasksNotifierTest, QueryFileAvailability_Multiple) {
+  notifier().set_is_offline(true);
+
+  base::RunLoop run_loop;
+  notifier().QueryFileAvailability(
+      {my_files().Append("not_found"), my_files().Append("file"),
+       base::FilePath("/special/drive/root/file"),
+       base::FilePath("/media/fuse/crostini-abcdef/file"),
+       base::FilePath("/media/fuse/drivefs/root/available_offline"),
+       base::FilePath("/media/fuse/drivefs/root/unavailable_offline"),
+       base::FilePath("/media/fuse/drivefs/root/not_found"),
+       base::FilePath("/media/fuse/drivefs/root/error")},
+      base::BindLambdaForTesting(
+          [&](std::vector<FileTasksNotifier::FileAvailability> results) {
+            run_loop.Quit();
+            EXPECT_EQ((std::vector<FileTasksNotifier::FileAvailability>{
+                          FileTasksNotifier::FileAvailability::kGone,
+                          FileTasksNotifier::FileAvailability::kOk,
+                          FileTasksNotifier::FileAvailability::kGone,
+                          FileTasksNotifier::FileAvailability::kUnknown,
+                          FileTasksNotifier::FileAvailability::kOk,
+                          FileTasksNotifier::FileAvailability::
+                              kTemporarilyUnavailable,
+                          FileTasksNotifier::FileAvailability::kGone,
+                          FileTasksNotifier::FileAvailability::kUnknown}),
+                      results);
+          }));
+  run_loop.Run();
+}
+
 }  // namespace
 }  // namespace file_tasks
 }  // namespace file_manager
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
index 47ea9f6..a6bf35f 100644
--- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
@@ -361,8 +361,14 @@
     if (check_enrollment_value == "1")
       return FRERequirement::kExplicitlyRequired;
   }
-  if (!provider->GetMachineStatistic(system::kActivateDateKey, nullptr) &&
-      !provider->GetEnterpriseMachineID().empty()) {
+  // Assume that the presence of the machine serial number means that VPD has
+  // been read successfully. Don't trust a missing ActivateDate if VPD could not
+  // be read successfully.
+  bool vpd_read_successfully = !provider->GetEnterpriseMachineID().empty();
+  if (vpd_read_successfully &&
+      !provider->GetMachineStatistic(system::kActivateDateKey, nullptr)) {
+    // The device has never been activated (enterprise enrolled or
+    // consumer-owned) so doing a FRE check is not necessary.
     return FRERequirement::kNotRequired;
   }
   return FRERequirement::kRequired;
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index 5f0b03f..071bf64 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -61,6 +61,7 @@
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/disks/disk_mount_manager.h"
 #include "chromeos/settings/cros_settings_provider.h"
+#include "components/crx_file/crx_verifier.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/browser/notification_observer.h"
@@ -74,6 +75,7 @@
 #include "extensions/browser/app_window/app_window_registry.h"
 #include "extensions/browser/app_window/native_app_window.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/browser/sandboxed_unpacker.h"
 #include "extensions/common/manifest.h"
 #include "extensions/common/switches.h"
 #include "extensions/components/native_app_window/native_app_window_views.h"
@@ -460,7 +462,10 @@
 
 class KioskTest : public OobeBaseTest {
  public:
-  KioskTest() : settings_helper_(false), fake_cws_(new FakeCWS) {
+  KioskTest()
+      : settings_helper_(false),
+        fake_cws_(new FakeCWS),
+        verifier_format_override_(crx_file::VerifierFormat::CRX3) {
     set_exit_when_last_browser_closes(false);
 
     // This test does not operate any real App, so App data does not exist.
@@ -840,6 +845,8 @@
   std::string test_crx_file_;
   std::unique_ptr<FakeCWS> fake_cws_;
   std::unique_ptr<MockUserManager> mock_user_manager_;
+  extensions::SandboxedUnpacker::ScopedVerifierFormatOverrideForTest
+      verifier_format_override_;
 
   DISALLOW_COPY_AND_ASSIGN(KioskTest);
 };
diff --git a/chrome/browser/chromeos/login/lock/fingerprint_unlock_browsertest.cc b/chrome/browser/chromeos/login/lock/fingerprint_unlock_browsertest.cc
new file mode 100644
index 0000000..368682e
--- /dev/null
+++ b/chrome/browser/chromeos/login/lock/fingerprint_unlock_browsertest.cc
@@ -0,0 +1,238 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/lock/screen_locker.h"
+
+#include "base/test/simple_test_clock.cc"
+#include "base/test/simple_test_tick_clock.h"
+#include "chrome/browser/chromeos/login/lock/screen_locker_tester.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_factory.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chromeos/dbus/biod/fake_biod_client.h"
+#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
+#include "components/prefs/pref_service.h"
+#include "components/session_manager/core/session_manager.h"
+#include "components/user_manager/user_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/compositor/scoped_animation_duration_scale_mode.h"
+
+namespace chromeos {
+namespace {
+
+using QuickUnlockStorage = quick_unlock::QuickUnlockStorage;
+
+constexpr char kFingerprint[] = "pinky";
+
+class FingerprintUnlockTest : public InProcessBrowserTest {
+ public:
+  FingerprintUnlockTest() = default;
+  ~FingerprintUnlockTest() override = default;
+
+  void SetUp() override {
+    quick_unlock::EnabledForTesting(true);
+    InProcessBrowserTest::SetUp();
+  }
+
+  void TearDown() override {
+    quick_unlock::EnabledForTesting(false);
+    InProcessBrowserTest::TearDown();
+  }
+
+  void SetUpInProcessBrowserTestFixture() override {
+    zero_duration_mode_ =
+        std::make_unique<ui::ScopedAnimationDurationScaleMode>(
+            ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
+  }
+
+  void SetUpOnMainThread() override {
+    InProcessBrowserTest::SetUpOnMainThread();
+    SetupTestClocks();
+    SetUpQuickUnlock();
+    EnrollFingerprint();
+  }
+
+  void EnrollFingerprint() {
+    FakeBiodClient::Get()->StartEnrollSession(
+        "test-user", std::string(),
+        base::BindRepeating(&FingerprintUnlockTest::OnStartSession,
+                            base::Unretained(this)));
+    if (!fingerprint_session_started_) {
+      base::RunLoop run_loop;
+      fingerprint_session_callback_ = run_loop.QuitClosure();
+      run_loop.Run();
+    }
+
+    FakeBiodClient::Get()->SendEnrollScanDone(
+        kFingerprint, biod::SCAN_RESULT_SUCCESS, true /* is_complete */,
+        -1 /* percent_complete */);
+
+    browser()->profile()->GetPrefs()->SetInteger(
+        prefs::kQuickUnlockFingerprintRecord, 1);
+  }
+
+  void AuthenticateWithFingerprint() {
+    FakeBiodClient::Get()->SendAuthScanDone(kFingerprint,
+                                            biod::SCAN_RESULT_SUCCESS);
+    base::RunLoop().RunUntilIdle();
+  }
+
+  base::TimeDelta GetExpirationTime() {
+    int frequency = browser()->profile()->GetPrefs()->GetInteger(
+        prefs::kQuickUnlockTimeout);
+    return quick_unlock::PasswordConfirmationFrequencyToTimeDelta(
+        static_cast<quick_unlock::PasswordConfirmationFrequency>(frequency));
+  }
+
+  void SetUpQuickUnlock() {
+    // Get quick unlock storage and prepare for auth token manipulation.
+    quick_unlock_storage_ = quick_unlock::QuickUnlockFactory::GetForAccountId(
+        user_manager::StubAccountId());
+    quick_unlock_storage_->SetClockForTesting(test_clock_.get());
+  }
+
+  void SetupTestClocks() {
+    // Creates test clock to be injected into quick_unlock_storage.
+    // Also creates test tick clock to simulate system sleep.
+    // TickClock is paused when system is suspended so, clock and tick clock
+    // can change by different amounts during time periods with system suspend.
+    // This difference is important for fingerprint unlock policy so tests fake
+    // both clock and tick clock, even though only clock is used by
+    // quick unlock storage directly.
+    base::Time now = base::Time::Now();
+    test_clock_ = std::make_unique<base::SimpleTestClock>();
+    test_clock_->SetNow(now);
+    // Creates test tick clock.
+    base::TimeTicks now_ticks = base::TimeTicks::Now();
+    test_tick_clock_ = std::make_unique<base::SimpleTestTickClock>();
+    test_tick_clock_->SetNowTicks(now_ticks);
+  }
+
+  void MarkStrongAuth() { quick_unlock_storage_->MarkStrongAuth(); }
+
+  bool HasStrongAuth() { return quick_unlock_storage_->HasStrongAuth(); }
+
+  void AdvanceTime(base::TimeDelta time_change, base::TimeDelta sleep_time) {
+    // System time is paused when system goes to sleep but real_time is not
+    // so amount of time by which tick clock is advanced should not include
+    // sleep time.
+    ASSERT_GT(time_change, sleep_time);
+    test_clock_->Advance(time_change);
+    test_tick_clock_->Advance(time_change - sleep_time);
+  }
+
+ private:
+  // Callback function for FakeBiodClient->StartEnrollSession.
+  void OnStartSession(const dbus::ObjectPath& path) {
+    fingerprint_session_started_ = true;
+    if (fingerprint_session_callback_)
+      std::move(fingerprint_session_callback_).Run();
+  }
+
+  bool fingerprint_session_started_ = false;
+
+  base::OnceClosure fingerprint_session_callback_;
+
+  QuickUnlockStorage* quick_unlock_storage_;
+
+  std::unique_ptr<base::SimpleTestClock> test_clock_;
+  std::unique_ptr<base::SimpleTestTickClock> test_tick_clock_;
+
+  std::unique_ptr<ui::ScopedAnimationDurationScaleMode> zero_duration_mode_;
+
+  DISALLOW_COPY_AND_ASSIGN(FingerprintUnlockTest);
+};
+
+}  // namespace
+
+IN_PROC_BROWSER_TEST_F(FingerprintUnlockTest, FingerprintNotTimedOutTest) {
+  // Show lock screen and wait until it is shown.
+  ScreenLockerTester tester;
+  tester.Lock();
+
+  // Mark strong auth, checks for strong auth.
+  // The default is one day, so verify moving the last strong auth time back 12
+  // hours(half of the expiration time) should not request strong auth.
+  MarkStrongAuth();
+  EXPECT_TRUE(HasStrongAuth());
+  base::TimeDelta expiration_time = GetExpirationTime();
+  AdvanceTime(expiration_time / 2, base::TimeDelta::FromSeconds(0));
+  EXPECT_TRUE(HasStrongAuth());
+
+  // Verify that fingerprint unlock is possible and the user can log in.
+  AuthenticateWithFingerprint();
+  EXPECT_FALSE(tester.IsLocked());
+  EXPECT_EQ(
+      1,
+      FakeSessionManagerClient::Get()->notify_lock_screen_shown_call_count());
+  EXPECT_EQ(session_manager::SessionState::ACTIVE,
+            session_manager::SessionManager::Get()->session_state());
+  EXPECT_EQ(1, FakeSessionManagerClient::Get()
+                   ->notify_lock_screen_dismissed_call_count());
+}
+
+IN_PROC_BROWSER_TEST_F(FingerprintUnlockTest, FingerprintTimedOutTest) {
+  // Show lock screen and wait until it is shown.
+  ScreenLockerTester tester;
+  tester.Lock();
+
+  // Mark strong auth, checks for strong auth.
+  // The default is one day, so verify moving the last strong auth time back 12
+  // hours(half of the expiration time) should not request strong auth.
+  MarkStrongAuth();
+  EXPECT_TRUE(HasStrongAuth());
+  base::TimeDelta expiration_time = GetExpirationTime();
+  AdvanceTime(expiration_time, base::TimeDelta::FromSeconds(0));
+  EXPECT_FALSE(HasStrongAuth());
+
+  // Verify that fingerprint unlock is not possible and the user cannot log in.
+  AuthenticateWithFingerprint();
+  EXPECT_TRUE(tester.IsLocked());
+  EXPECT_EQ(
+      1,
+      FakeSessionManagerClient::Get()->notify_lock_screen_shown_call_count());
+  EXPECT_EQ(session_manager::SessionState::LOCKED,
+            session_manager::SessionManager::Get()->session_state());
+  EXPECT_EQ(0, FakeSessionManagerClient::Get()
+                   ->notify_lock_screen_dismissed_call_count());
+
+  // Auth Error button should be visible as fingerprint has expired.
+  EXPECT_TRUE(tester.IsAuthErrorBubbleShown());
+}
+
+IN_PROC_BROWSER_TEST_F(FingerprintUnlockTest, TimeoutIncludesSuspendedTime) {
+  // Show lock screen and wait until it is shown.
+  ScreenLockerTester tester;
+  tester.Lock();
+
+  // Mark strong auth, checks for strong auth.
+  // The default is one day, so verify moving the last strong auth time back 12
+  // hours(half of the expiration time) should not request strong auth.
+  MarkStrongAuth();
+  EXPECT_TRUE(HasStrongAuth());
+  base::TimeDelta expiration_time = GetExpirationTime();
+  AdvanceTime(expiration_time, expiration_time / 2);
+  EXPECT_FALSE(HasStrongAuth());
+
+  // Verify that fingerprint unlock is not possible and the user cannot log in.
+  AuthenticateWithFingerprint();
+  EXPECT_TRUE(tester.IsLocked());
+  EXPECT_EQ(
+      1,
+      FakeSessionManagerClient::Get()->notify_lock_screen_shown_call_count());
+  EXPECT_EQ(session_manager::SessionState::LOCKED,
+            session_manager::SessionManager::Get()->session_state());
+  EXPECT_EQ(0, FakeSessionManagerClient::Get()
+                   ->notify_lock_screen_dismissed_call_count());
+
+  // Auth Error button should be visible as fingerprint has expired.
+  EXPECT_TRUE(tester.IsAuthErrorBubbleShown());
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_tester.cc b/chrome/browser/chromeos/login/lock/screen_locker_tester.cc
index 4af64ab..29e9997 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker_tester.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker_tester.cc
@@ -143,6 +143,15 @@
   return IsScreenLockerLocked() && is_shutdown_button_shown;
 }
 
+bool ScreenLockerTester::IsAuthErrorBubbleShown() {
+  if (!IsScreenLockerLocked())
+    return false;
+
+  bool is_auth_error_button_shown =
+      login_screen_tester_.IsAuthErrorBubbleShown();
+  return IsScreenLockerLocked() && is_auth_error_button_shown;
+}
+
 void ScreenLockerTester::UnlockWithPassword(const AccountId& account_id,
                                             const std::string& password) {
   ash::mojom::LoginScreenTestApiAsyncWaiter login_screen(test_api_.get());
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_tester.h b/chrome/browser/chromeos/login/lock/screen_locker_tester.h
index bcd9044b..815ec310 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker_tester.h
+++ b/chrome/browser/chromeos/login/lock/screen_locker_tester.h
@@ -37,6 +37,9 @@
   // Returns true if Shutdown button is visible.
   bool IsLockShutdownButtonShown();
 
+  // Returns true if there is an auth error button on the lock screen.
+  bool IsAuthErrorBubbleShown();
+
   // Enters and submits the given password for the given account.
   void UnlockWithPassword(const AccountId& account_id,
                           const std::string& password);
diff --git a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.cc b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.cc
index 1173ffc..087ce1a 100644
--- a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.cc
+++ b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.cc
@@ -29,15 +29,20 @@
 
 }  // namespace
 
-QuickUnlockStorage::QuickUnlockStorage(Profile* profile) : profile_(profile) {
+QuickUnlockStorage::QuickUnlockStorage(Profile* profile)
+    : profile_(profile), clock_(base::DefaultClock::GetInstance()) {
   fingerprint_storage_ = std::make_unique<FingerprintStorage>(profile);
   pin_storage_prefs_ = std::make_unique<PinStoragePrefs>(profile->GetPrefs());
 }
 
 QuickUnlockStorage::~QuickUnlockStorage() {}
 
+void QuickUnlockStorage::SetClockForTesting(base::Clock* test_clock) {
+  clock_ = test_clock;
+}
+
 void QuickUnlockStorage::MarkStrongAuth() {
-  last_strong_auth_ = base::Time::Now();
+  last_strong_auth_ = clock_->Now();
   fingerprint_storage()->ResetUnlockAttemptCount();
   pin_storage_prefs()->ResetUnlockAttemptCount();
 }
@@ -50,7 +55,7 @@
 
 base::TimeDelta QuickUnlockStorage::TimeSinceLastStrongAuth() const {
   DCHECK(!last_strong_auth_.is_null());
-  return base::Time::Now() - last_strong_auth_;
+  return clock_->Now() - last_strong_auth_;
 }
 
 base::TimeDelta QuickUnlockStorage::TimeUntilNextStrongAuth() const {
diff --git a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h
index a415eab..cf662b3 100644
--- a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h
+++ b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_STORAGE_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_STORAGE_H_
 
+#include "base/time/default_clock.h"
 #include "base/time/time.h"
 #include "chromeos/login/auth/user_context.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -30,6 +31,9 @@
   explicit QuickUnlockStorage(Profile* profile);
   ~QuickUnlockStorage() override;
 
+  // Replaces default clock with a test clock for testing.
+  void SetClockForTesting(base::Clock* clock);
+
   // Mark that the user has had a strong authentication. This means
   // that they authenticated with their password, for example. Quick
   // unlock will timeout after a delay.
@@ -89,9 +93,10 @@
 
   Profile* const profile_;
   base::Time last_strong_auth_;
+  std::unique_ptr<AuthToken> auth_token_;
+  base::Clock* clock_;
   std::unique_ptr<FingerprintStorage> fingerprint_storage_;
   std::unique_ptr<PinStoragePrefs> pin_storage_prefs_;
-  std::unique_ptr<AuthToken> auth_token_;
 
   DISALLOW_COPY_AND_ASSIGN(QuickUnlockStorage);
 };
diff --git a/chrome/browser/chromeos/login/test/login_screen_tester.cc b/chrome/browser/chromeos/login/test/login_screen_tester.cc
index 3b8052f..db00a670 100644
--- a/chrome/browser/chromeos/login/test/login_screen_tester.cc
+++ b/chrome/browser/chromeos/login/test/login_screen_tester.cc
@@ -41,6 +41,13 @@
   return is_shutdown_button_shown;
 }
 
+bool LoginScreenTester::IsAuthErrorBubbleShown() {
+  ash::mojom::LoginScreenTestApiAsyncWaiter login_screen(test_api_.get());
+  bool is_auth_error_button_shown;
+  login_screen.IsAuthErrorBubbleShown(&is_auth_error_button_shown);
+  return is_auth_error_button_shown;
+}
+
 bool LoginScreenTester::ClickAddUserButton() {
   ash::mojom::LoginScreenTestApiAsyncWaiter login_screen(test_api_.get());
   bool success;
diff --git a/chrome/browser/chromeos/login/test/login_screen_tester.h b/chrome/browser/chromeos/login/test/login_screen_tester.h
index 957ec4a..253b277 100644
--- a/chrome/browser/chromeos/login/test/login_screen_tester.h
+++ b/chrome/browser/chromeos/login/test/login_screen_tester.h
@@ -23,6 +23,7 @@
   int64_t GetUiUpdateCount();
   bool IsRestartButtonShown();
   bool IsShutdownButtonShown();
+  bool IsAuthErrorBubbleShown();
 
   // Returns true on success (i.e. button is  not disabled).
   bool ClickAddUserButton();
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
index 4f295c1..b933c92 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
@@ -322,10 +322,8 @@
 }
 
 void DeviceCloudPolicyInitializer::TryToCreateClient() {
-  if (!device_store_->is_initialized() ||
-      !device_store_->has_policy() ||
-      state_keys_broker_->pending() ||
-      enrollment_handler_ ||
+  if (!device_store_->is_initialized() || !device_store_->has_policy() ||
+      !state_keys_broker_->available() || enrollment_handler_ ||
       install_attributes_->IsActiveDirectoryManaged()) {
     return;
   }
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
index f3571dd..20ea74d 100644
--- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -97,6 +97,7 @@
 #include "chromeos/login/auth/mock_auth_status_consumer.h"
 #include "chromeos/login/auth/user_context.h"
 #include "chromeos/network/policy_certificate_provider.h"
+#include "components/crx_file/crx_verifier.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_core.h"
 #include "components/policy/core/common/cloud/cloud_policy_store.h"
@@ -130,6 +131,7 @@
 #include "extensions/browser/install/crx_install_error.h"
 #include "extensions/browser/management_policy.h"
 #include "extensions/browser/notification_types.h"
+#include "extensions/browser/sandboxed_unpacker.h"
 #include "extensions/browser/test_extension_registry_observer.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
@@ -449,7 +451,8 @@
       : public_session_input_method_id_(
             base::StringPrintf(kPublicSessionInputMethodIDTemplate,
                                chromeos::extension_ime_util::kXkbExtensionId)),
-        contents_(NULL) {
+        contents_(NULL),
+        verifier_format_override_(crx_file::VerifierFormat::CRX3) {
     set_exit_when_last_browser_closes(false);
   }
 
@@ -792,6 +795,8 @@
   base::ScopedTempDir cache_dir_;
 
  private:
+  extensions::SandboxedUnpacker::ScopedVerifierFormatOverrideForTest
+      verifier_format_override_;
   DISALLOW_COPY_AND_ASSIGN(DeviceLocalAccountTest);
 };
 
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_store.cc b/chrome/browser/chromeos/policy/device_local_account_policy_store.cc
index 963c52b4..aae7fc9 100644
--- a/chrome/browser/chromeos/policy/device_local_account_policy_store.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_policy_store.cc
@@ -31,7 +31,8 @@
     chromeos::DeviceSettingsService* device_settings_service,
     scoped_refptr<base::SequencedTaskRunner> background_task_runner)
     : UserCloudPolicyStoreBase(background_task_runner,
-                               PolicyScope::POLICY_SCOPE_USER),
+                               PolicyScope::POLICY_SCOPE_USER,
+                               PolicySource::POLICY_SOURCE_CLOUD),
       account_id_(account_id),
       session_manager_client_(session_manager_client),
       device_settings_service_(device_settings_service),
diff --git a/chrome/browser/chromeos/policy/server_backed_state_keys_broker.cc b/chrome/browser/chromeos/policy/server_backed_state_keys_broker.cc
index f707d3a..ae109b6 100644
--- a/chrome/browser/chromeos/policy/server_backed_state_keys_broker.cc
+++ b/chrome/browser/chromeos/policy/server_backed_state_keys_broker.cc
@@ -26,7 +26,6 @@
     chromeos::SessionManagerClient* session_manager_client)
     : session_manager_client_(session_manager_client),
       requested_(false),
-      initial_retrieval_completed_(false),
       weak_factory_(this) {}
 
 ServerBackedStateKeysBroker::~ServerBackedStateKeysBroker() {
@@ -34,14 +33,14 @@
 
 ServerBackedStateKeysBroker::Subscription
 ServerBackedStateKeysBroker::RegisterUpdateCallback(
-    const base::Closure& callback) {
+    const base::RepeatingClosure& callback) {
   if (!available())
     FetchStateKeys();
   return update_callbacks_.Add(callback);
 }
 
 void ServerBackedStateKeysBroker::RequestStateKeys(StateKeysCallback callback) {
-  if (pending()) {
+  if (!available()) {
     request_callbacks_.push_back(std::move(callback));
     FetchStateKeys();
     return;
@@ -49,7 +48,6 @@
 
   if (!callback.is_null())
     std::move(callback).Run(state_keys_);
-  return;
 }
 
 // static
@@ -68,7 +66,7 @@
 
 void ServerBackedStateKeysBroker::StoreStateKeys(
     const std::vector<std::string>& state_keys) {
-  bool send_notification = !initial_retrieval_completed_;
+  bool send_notification = !available();
 
   requested_ = false;
   if (state_keys.empty()) {
@@ -76,7 +74,6 @@
   } else if (base::ContainsValue(state_keys, std::string())) {
     LOG(WARNING) << "Bad state keys.";
   } else {
-    initial_retrieval_completed_ = true;
     send_notification |= state_keys_ != state_keys;
     state_keys_ = state_keys;
   }
diff --git a/chrome/browser/chromeos/policy/server_backed_state_keys_broker.h b/chrome/browser/chromeos/policy/server_backed_state_keys_broker.h
index a831b34..92f19fa 100644
--- a/chrome/browser/chromeos/policy/server_backed_state_keys_broker.h
+++ b/chrome/browser/chromeos/policy/server_backed_state_keys_broker.h
@@ -38,7 +38,7 @@
   // Note that consuming code needs to hold on to the returned Subscription as
   // long as it wants to receive the callback. If the state keys haven't been
   // requested yet, calling this will also trigger their initial fetch.
-  Subscription RegisterUpdateCallback(const base::Closure& callback);
+  Subscription RegisterUpdateCallback(const base::RepeatingClosure& callback);
 
   // Requests state keys asynchronously. Invokes the passed callback at most
   // once, with the current state keys passed as a parameter to the callback. If
@@ -60,10 +60,8 @@
     return state_keys_.empty() ? std::string() : state_keys_.front();
   }
 
-  // Whether state key retrieval is pending.
-  bool pending() const { return !initial_retrieval_completed_; }
-
-  // Whether state keys are available.
+  // Whether state keys are available. Returns false if state keys are
+  // unavailable or pending retrieval.
   bool available() const { return !state_keys_.empty(); }
 
  private:
@@ -81,9 +79,6 @@
   // Whether a request for state keys is pending.
   bool requested_;
 
-  // Whether the initial retrieval operation completed.
-  bool initial_retrieval_completed_;
-
   // List of callbacks to receive update notifications.
   base::CallbackList<void()> update_callbacks_;
 
diff --git a/chrome/browser/chromeos/policy/server_backed_state_keys_broker_unittest.cc b/chrome/browser/chromeos/policy/server_backed_state_keys_broker_unittest.cc
index 2706031..7ccef7f 100644
--- a/chrome/browser/chromeos/policy/server_backed_state_keys_broker_unittest.cc
+++ b/chrome/browser/chromeos/policy/server_backed_state_keys_broker_unittest.cc
@@ -33,7 +33,6 @@
   }
 
   void ExpectGood() {
-    EXPECT_FALSE(broker_.pending());
     EXPECT_TRUE(broker_.available());
     EXPECT_EQ(state_keys_, broker_.state_keys());
     EXPECT_EQ(state_keys_.front(), broker_.current_state_key());
@@ -59,7 +58,6 @@
 };
 
 TEST_F(ServerBackedStateKeysBrokerTest, Load) {
-  EXPECT_TRUE(broker_.pending());
   EXPECT_FALSE(broker_.available());
   EXPECT_TRUE(broker_.state_keys().empty());
   EXPECT_TRUE(broker_.current_state_key().empty());
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc
index 3b91f79..3e1d074 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc
@@ -43,7 +43,8 @@
     const base::FilePath& user_policy_key_dir,
     bool is_active_directory)
     : UserCloudPolicyStoreBase(background_task_runner,
-                               PolicyScope::POLICY_SCOPE_USER),
+                               PolicyScope::POLICY_SCOPE_USER,
+                               PolicySource::POLICY_SOURCE_CLOUD),
       session_manager_client_(session_manager_client),
       account_id_(account_id),
       is_active_directory_(is_active_directory),
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index 71300c9..94de36ad 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -296,6 +296,9 @@
   registry->RegisterBooleanPref(
       ash::prefs::kAccessibilityAutoclickRevertToLeftClick, true,
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC);
+  registry->RegisterBooleanPref(
+      ash::prefs::kAccessibilityAutoclickStabilizePosition, false,
+      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC);
   registry->RegisterIntegerPref(
       ash::prefs::kAccessibilityAutoclickMovementThreshold,
       ash::kDefaultAutoclickMovementThreshold,
diff --git a/chrome/browser/devtools/device/devtools_device_discovery.cc b/chrome/browser/devtools/device/devtools_device_discovery.cc
index adc8c75..0ca19c5 100644
--- a/chrome/browser/devtools/device/devtools_device_discovery.cc
+++ b/chrome/browser/devtools/device/devtools_device_discovery.cc
@@ -152,7 +152,7 @@
       const std::string& local_id,
       const std::string& target_path,
       const std::string& type,
-      base::DictionaryValue* value);
+      base::Value* value);
   ~AgentHostDelegate() override;
 
  private:
@@ -162,7 +162,7 @@
                     const std::string& local_id,
                     const std::string& target_path,
                     const std::string& type,
-                    base::DictionaryValue* value);
+                    base::Value* value);
   // DevToolsExternalAgentProxyDelegate overrides.
   void Attach(content::DevToolsExternalAgentProxy* proxy) override;
   void Detach(content::DevToolsExternalAgentProxy* proxy) override;
@@ -197,22 +197,20 @@
   DISALLOW_COPY_AND_ASSIGN(AgentHostDelegate);
 };
 
-static std::string GetStringProperty(base::DictionaryValue* value,
+static std::string GetStringProperty(const base::Value& value,
                                      const std::string& name) {
-  std::string result;
-  value->GetString(name, &result);
-  return result;
+  const std::string* result = value.FindStringKey(name);
+  return result ? *result : std::string();
 }
 
-static std::string BuildUniqueTargetId(
-    const std::string& serial,
-    const std::string& browser_id,
-    base::DictionaryValue* value) {
+static std::string BuildUniqueTargetId(const std::string& serial,
+                                       const std::string& browser_id,
+                                       const base::Value& value) {
   return base::StringPrintf("%s:%s:%s", serial.c_str(),
       browser_id.c_str(), GetStringProperty(value, "id").c_str());
 }
 
-static std::string GetFrontendURLFromValue(base::DictionaryValue* value,
+static std::string GetFrontendURLFromValue(const base::Value& value,
                                            const std::string& browser_version) {
   std::string frontend_url = GetStringProperty(value, "devtoolsFrontendUrl");
   size_t ws_param = frontend_url.find("?ws");
@@ -225,7 +223,7 @@
   return frontend_url;
 }
 
-static std::string GetTargetPath(base::DictionaryValue* value) {
+static std::string GetTargetPath(const base::Value& value) {
   std::string target_path = GetStringProperty(value, "webSocketDebuggerUrl");
 
   if (base::StartsWith(target_path, "ws://", base::CompareCase::SENSITIVE)) {
@@ -248,7 +246,7 @@
     const std::string& local_id,
     const std::string& target_path,
     const std::string& type,
-    base::DictionaryValue* value) {
+    base::Value* value) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   scoped_refptr<DevToolsAgentHost> result =
       DevToolsAgentHost::GetForId(local_id);
@@ -270,21 +268,21 @@
     const std::string& local_id,
     const std::string& target_path,
     const std::string& type,
-    base::DictionaryValue* value)
+    base::Value* value)
     : device_(device),
       browser_id_(browser_id),
       local_id_(local_id),
       target_path_(target_path),
       remote_type_(type),
-      remote_id_(value ? GetStringProperty(value, "id") : ""),
-      frontend_url_(value ? GetFrontendURLFromValue(value, browser_version)
+      remote_id_(value ? GetStringProperty(*value, "id") : ""),
+      frontend_url_(value ? GetFrontendURLFromValue(*value, browser_version)
                           : ""),
       title_(value ? base::UTF16ToUTF8(net::UnescapeForHTML(
-                         base::UTF8ToUTF16(GetStringProperty(value, "title"))))
+                         base::UTF8ToUTF16(GetStringProperty(*value, "title"))))
                    : ""),
-      description_(value ? GetStringProperty(value, "description") : ""),
-      url_(GURL(value ? GetStringProperty(value, "url") : "")),
-      favicon_url_(GURL(value ? GetStringProperty(value, "faviconUrl") : "")),
+      description_(value ? GetStringProperty(*value, "description") : ""),
+      url_(GURL(value ? GetStringProperty(*value, "url") : "")),
+      favicon_url_(GURL(value ? GetStringProperty(*value, "faviconUrl") : "")),
       agent_host_(nullptr) {}
 
 AgentHostDelegate::~AgentHostDelegate() {
@@ -459,26 +457,24 @@
   if (result < 0)
     return;
   // Parse version, append to package name if available,
-  std::unique_ptr<base::Value> value =
-      base::JSONReader::ReadDeprecated(response);
-  base::DictionaryValue* dict;
-  if (value && value->GetAsDictionary(&dict)) {
-    std::string browser_name;
-    if (dict->GetString("Browser", &browser_name)) {
+  base::Optional<base::Value> value = base::JSONReader::Read(response);
+  if (value && value->is_dict()) {
+    const std::string* browser_name = value->FindStringKey("Browser");
+    if (browser_name) {
       std::vector<std::string> parts = base::SplitString(
-          browser_name, "/", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+          *browser_name, "/", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
       if (parts.size() == 2)
         browser->version_ = parts[1];
       else
-        browser->version_ = browser_name;
+        browser->version_ = *browser_name;
     }
-    browser->browser_target_id_ = GetTargetPath(dict);
+    browser->browser_target_id_ = GetTargetPath(*value);
     if (browser->browser_target_id_.empty())
       browser->browser_target_id_ = kBrowserTargetSocket;
-    std::string package;
-    if (dict->GetString("Android-Package", &package)) {
+    const std::string* package = value->FindStringKey("Android-Package");
+    if (package) {
       browser->display_name_ =
-          AndroidDeviceManager::GetBrowserName(browser->socket(), package);
+          AndroidDeviceManager::GetBrowserName(browser->socket(), *package);
     }
   }
 }
@@ -491,15 +487,13 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (result < 0)
     return;
-  std::unique_ptr<base::Value> value =
-      base::JSONReader::ReadDeprecated(response);
-  base::ListValue* list_value;
-  if (value && value->GetAsList(&list_value)) {
-    for (const auto& page_value : *list_value) {
-      const base::DictionaryValue* dict;
-      if (page_value.GetAsDictionary(&dict))
+  base::Optional<base::Value> value = base::JSONReader::Read(response);
+  if (value && value->is_list()) {
+    for (base::Value& page_value : value->GetList()) {
+      if (page_value.is_dict())
         browser->pages_.push_back(new RemotePage(device, browser->browser_id_,
-                                                 browser->version_, *dict));
+                                                 browser->version_,
+                                                 std::move(page_value)));
     }
   }
 }
@@ -510,25 +504,24 @@
     scoped_refptr<AndroidDeviceManager::Device> device,
     const std::string& browser_id,
     const std::string& browser_version,
-    const base::DictionaryValue& dict)
+    base::Value dict)
     : device_(device),
       browser_id_(browser_id),
       browser_version_(browser_version),
-      dict_(dict.DeepCopy()) {}
+      dict_(std::move(dict)) {}
 
 DevToolsDeviceDiscovery::RemotePage::~RemotePage() {
 }
 
 scoped_refptr<content::DevToolsAgentHost>
 DevToolsDeviceDiscovery::RemotePage::CreateTarget() {
-  std::string local_id = BuildUniqueTargetId(device_->serial(),
-                                             browser_id_,
-                                             dict_.get());
-  std::string target_path = GetTargetPath(dict_.get());
-  std::string type = GetStringProperty(dict_.get(), "type");
+  std::string local_id =
+      BuildUniqueTargetId(device_->serial(), browser_id_, dict_);
+  std::string target_path = GetTargetPath(dict_);
+  std::string type = GetStringProperty(dict_, "type");
   agent_host_ = AgentHostDelegate::GetOrCreateAgentHost(
       device_, browser_id_, browser_version_, local_id, target_path, type,
-      dict_.get());
+      &dict_);
   return agent_host_;
 }
 
diff --git a/chrome/browser/devtools/device/devtools_device_discovery.h b/chrome/browser/devtools/device/devtools_device_discovery.h
index 3cb1453..5c8d6b1 100644
--- a/chrome/browser/devtools/device/devtools_device_discovery.h
+++ b/chrome/browser/devtools/device/devtools_device_discovery.h
@@ -32,7 +32,7 @@
     RemotePage(scoped_refptr<AndroidDeviceManager::Device> device,
                const std::string& browser_id,
                const std::string& browser_version,
-               const base::DictionaryValue& dict);
+               base::Value dict);
 
     virtual ~RemotePage();
 
@@ -40,7 +40,7 @@
     std::string browser_id_;
     std::string browser_version_;
     std::string frontend_url_;
-    std::unique_ptr<base::DictionaryValue> dict_;
+    base::Value dict_;
     scoped_refptr<content::DevToolsAgentHost> agent_host_;
 
     DISALLOW_COPY_AND_ASSIGN(RemotePage);
diff --git a/chrome/browser/devtools/device/port_forwarding_controller.cc b/chrome/browser/devtools/device/port_forwarding_controller.cc
index 1f7f9bb..814533b 100644
--- a/chrome/browser/devtools/device/port_forwarding_controller.cc
+++ b/chrome/browser/devtools/device/port_forwarding_controller.cc
@@ -54,8 +54,7 @@
   kStatusOK = 0,
 };
 
-const char kErrorCodeParam[] = "code";
-const char kErrorParam[] = "error";
+const char kErrorCodePath[] = "error.code";
 const char kIdParam[] = "id";
 const char kMethodParam[] = "method";
 const char kParamsParam[] = "params";
@@ -68,54 +67,47 @@
 
 static bool ParseNotification(const std::string& json,
                               std::string* method,
-                              std::unique_ptr<base::DictionaryValue>* params) {
-  std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated(json);
+                              base::Optional<base::Value>* params) {
+  base::Optional<base::Value> value = base::JSONReader::Read(json);
   if (!value || !value->is_dict())
     return false;
 
-  std::unique_ptr<base::DictionaryValue> dict(
-      static_cast<base::DictionaryValue*>(value.release()));
-
-  if (!dict->GetString(kMethodParam, method))
+  const std::string* method_value = value->FindStringKey(kMethodParam);
+  if (!method_value)
     return false;
+  *method = *method_value;
 
-  std::unique_ptr<base::Value> params_value;
-  dict->Remove(kParamsParam, &params_value);
-  if (params_value && params_value->is_dict())
-    params->reset(static_cast<base::DictionaryValue*>(params_value.release()));
-
+  auto extracted_param = value->ExtractKey(kParamsParam);
+  if (extracted_param && extracted_param->is_dict())
+    *params = std::move(extracted_param);
   return true;
 }
 
 static bool ParseResponse(const std::string& json,
                           int* command_id,
                           int* error_code) {
-  std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated(json);
+  base::Optional<base::Value> value = base::JSONReader::Read(json);
   if (!value || !value->is_dict())
     return false;
-
-  std::unique_ptr<base::DictionaryValue> dict(
-      static_cast<base::DictionaryValue*>(value.release()));
-
-  if (!dict->GetInteger(kIdParam, command_id))
+  base::Optional<int> command_id_opt = value->FindIntKey(kIdParam);
+  if (!command_id_opt)
     return false;
+  *command_id = *command_id_opt;
 
-  *error_code = 0;
-  base::DictionaryValue* error_dict = nullptr;
-  if (dict->GetDictionary(kErrorParam, &error_dict))
-    error_dict->GetInteger(kErrorCodeParam, error_code);
+  base::Optional<int> error_value = value->FindIntPath(kErrorCodePath);
+  if (error_value)
+    *error_code = *error_value;
+
   return true;
 }
 
-static std::string SerializeCommand(
-    int command_id,
-    const std::string& method,
-    std::unique_ptr<base::DictionaryValue> params) {
-  base::DictionaryValue command;
-  command.SetInteger(kIdParam, command_id);
-  command.SetString(kMethodParam, method);
-  if (params)
-    command.Set(kParamsParam, std::move(params));
+static std::string SerializeCommand(int command_id,
+                                    const std::string& method,
+                                    base::Value params) {
+  base::Value command(base::Value::Type::DICTIONARY);
+  command.SetIntKey(kIdParam, command_id);
+  command.SetStringKey(kMethodParam, method);
+  command.SetKey(kParamsParam, std::move(params));
 
   std::string json_command;
   base::JSONWriter::Write(command, &json_command);
@@ -489,13 +481,9 @@
 void PortForwardingController::Connection::SendCommand(
     const std::string& method, int port) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue);
-  if (method == kBindMethod) {
-    params->SetInteger(kPortParam, port);
-  } else {
-    DCHECK_EQ(kUnbindMethod, method);
-    params->SetInteger(kPortParam, port);
-  }
+  base::Value params(base::Value::Type::DICTIONARY);
+  DCHECK(method == kBindMethod || kUnbindMethod == method);
+  params.SetIntKey(kPortParam, port);
   int id = ++command_id_;
 
   if (method == kBindMethod) {
@@ -579,20 +567,21 @@
     return;
 
   std::string method;
-  std::unique_ptr<base::DictionaryValue> params;
+  base::Optional<base::Value> params;
   if (!ParseNotification(message, &method, &params))
     return;
 
   if (method != kAcceptedEvent || !params)
     return;
 
-  int port;
-  std::string connection_id;
-  if (!params->GetInteger(kPortParam, &port) ||
-      !params->GetString(kConnectionIdParam, &connection_id))
+  base::Optional<int> port = params->FindIntKey(kPortParam);
+  if (!port)
+    return;
+  const std::string* connection_id = params->FindStringKey(kConnectionIdParam);
+  if (!connection_id)
     return;
 
-  auto it = forwarding_map_.find(port);
+  auto it = forwarding_map_.find(*port);
   if (it == forwarding_map_.end())
     return;
 
@@ -604,7 +593,7 @@
     return;
   std::string destination_host = tokens[0];
 
-  device_->OpenSocket(connection_id.c_str(),
+  device_->OpenSocket(*connection_id,
                       base::Bind(&SocketTunnel::StartTunnel, profile_,
                                  destination_host, destination_port));
 }
@@ -658,15 +647,14 @@
   forwarding_map_.clear();
 
   if (pref_service_->GetBoolean(prefs::kDevToolsPortForwardingEnabled)) {
-    const base::DictionaryValue* dict =
+    const base::Value* value =
         pref_service_->GetDictionary(prefs::kDevToolsPortForwardingConfig);
-    for (base::DictionaryValue::Iterator it(*dict);
-         !it.IsAtEnd(); it.Advance()) {
+    for (const auto& dict_element : value->DictItems()) {
       int port_num;
-      std::string location;
-      if (base::StringToInt(it.key(), &port_num) &&
-          dict->GetString(it.key(), &location))
-        forwarding_map_[port_num] = location;
+      if (base::StringToInt(dict_element.first, &port_num) &&
+          dict_element.second.is_string()) {
+        forwarding_map_[port_num] = dict_element.second.GetString();
+      }
     }
   }
 
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc
index 656c6ea..b511182 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -572,29 +572,28 @@
     const std::string& message) {
   if (!frontend_host_)
     return;
-  std::string method;
-  base::ListValue empty_params;
-  base::ListValue* params = &empty_params;
-
-  base::DictionaryValue* dict = NULL;
-  std::unique_ptr<base::Value> parsed_message =
-      base::JSONReader::ReadDeprecated(message);
-  if (!parsed_message ||
-      !parsed_message->GetAsDictionary(&dict) ||
-      !dict->GetString(kFrontendHostMethod, &method) ||
-      (dict->HasKey(kFrontendHostParams) &&
-          !dict->GetList(kFrontendHostParams, &params))) {
+  const std::string* method = nullptr;
+  base::Value* params = nullptr;
+  base::Optional<base::Value> parsed_message = base::JSONReader::Read(message);
+  if (parsed_message && parsed_message->is_dict()) {
+    method = parsed_message->FindStringKey(kFrontendHostMethod);
+    params = parsed_message->FindKey(kFrontendHostParams);
+  }
+  if (!method || (params && !params->is_list())) {
     LOG(ERROR) << "Invalid message was sent to embedder: " << message;
     return;
   }
-  int id = 0;
-  dict->GetInteger(kFrontendHostId, &id);
+  base::Value empty_params(base::Value::Type::LIST);
+  if (!params) {
+    params = &empty_params;
+  }
+  int id = parsed_message->FindIntKey(kFrontendHostId).value_or(0);
+  base::ListValue* params_list;
+  params->GetAsList(&params_list);
   embedder_message_dispatcher_->Dispatch(
       base::Bind(&DevToolsUIBindings::SendMessageAck,
-                 weak_factory_.GetWeakPtr(),
-                 id),
-      method,
-      params);
+                 weak_factory_.GetWeakPtr(), id),
+      *method, params_list);
 }
 
 // content::DevToolsAgentHostClient implementation --------------------------
@@ -850,8 +849,8 @@
   if (indexing_jobs_.count(index_request_id) != 0)
     return;
   std::vector<std::string> excluded_folders;
-  std::unique_ptr<base::Value> parsed_excluded_folders =
-      base::JSONReader::ReadDeprecated(excluded_folders_message);
+  base::Optional<base::Value> parsed_excluded_folders =
+      base::JSONReader::Read(excluded_folders_message);
   if (parsed_excluded_folders && parsed_excluded_folders->is_list()) {
     const std::vector<base::Value>& folder_paths =
         parsed_excluded_folders->GetList();
@@ -934,29 +933,24 @@
     const std::string& port_forwarding_config,
     bool network_discovery_enabled,
     const std::string& network_discovery_config) {
-  base::DictionaryValue* port_forwarding_dict = nullptr;
-  std::unique_ptr<base::Value> parsed_port_forwarding =
-      base::JSONReader::ReadDeprecated(port_forwarding_config);
-  if (!parsed_port_forwarding ||
-      !parsed_port_forwarding->GetAsDictionary(&port_forwarding_dict)) {
+  base::Optional<base::Value> parsed_port_forwarding =
+      base::JSONReader::Read(port_forwarding_config);
+  if (!parsed_port_forwarding || !parsed_port_forwarding->is_dict())
     return;
-  }
-
-  base::ListValue* network_list = nullptr;
-  std::unique_ptr<base::Value> parsed_network =
-      base::JSONReader::ReadDeprecated(network_discovery_config);
-  if (!parsed_network || !parsed_network->GetAsList(&network_list))
+  base::Optional<base::Value> parsed_network =
+      base::JSONReader::Read(network_discovery_config);
+  if (!parsed_network || !parsed_network->is_list())
     return;
-
   profile_->GetPrefs()->SetBoolean(
       prefs::kDevToolsDiscoverUsbDevicesEnabled, discover_usb_devices);
   profile_->GetPrefs()->SetBoolean(
       prefs::kDevToolsPortForwardingEnabled, port_forwarding_enabled);
   profile_->GetPrefs()->Set(prefs::kDevToolsPortForwardingConfig,
-                            *port_forwarding_dict);
+                            *parsed_port_forwarding);
   profile_->GetPrefs()->SetBoolean(prefs::kDevToolsDiscoverTCPTargetsEnabled,
                                    network_discovery_enabled);
-  profile_->GetPrefs()->Set(prefs::kDevToolsTCPDiscoveryConfig, *network_list);
+  profile_->GetPrefs()->Set(prefs::kDevToolsTCPDiscoveryConfig,
+                            *parsed_network);
 }
 
 void DevToolsUIBindings::DevicesDiscoveryConfigUpdated() {
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc
index be110f6..350caba 100644
--- a/chrome/browser/devtools/devtools_window.cc
+++ b/chrome/browser/devtools/devtools_window.cc
@@ -115,16 +115,14 @@
 }
 
 void SetPreferencesFromJson(Profile* profile, const std::string& json) {
-  base::DictionaryValue* dict = nullptr;
-  std::unique_ptr<base::Value> parsed = base::JSONReader::ReadDeprecated(json);
-  if (!parsed || !parsed->GetAsDictionary(&dict))
+  base::Optional<base::Value> parsed = base::JSONReader::Read(json);
+  if (!parsed || !parsed->is_dict())
     return;
   DictionaryPrefUpdate update(profile->GetPrefs(), prefs::kDevToolsPreferences);
-  for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
-    if (!it.value().is_string())
+  for (const auto& dict_value : parsed->DictItems()) {
+    if (!dict_value.second.is_string())
       continue;
-    update.Get()->SetWithoutPathExpansion(
-        it.key(), it.value().CreateDeepCopy());
+    update.Get()->SetKey(dict_value.first, std::move(dict_value.second));
   }
 }
 
@@ -266,22 +264,16 @@
 
 void DevToolsEventForwarder::SetWhitelistedShortcuts(
     const std::string& message) {
-  std::unique_ptr<base::Value> parsed_message =
-      base::JSONReader::ReadDeprecated(message);
-  base::ListValue* shortcut_list;
-  if (!parsed_message || !parsed_message->GetAsList(&shortcut_list))
-      return;
-  auto it = shortcut_list->begin();
-  for (; it != shortcut_list->end(); ++it) {
-    base::DictionaryValue* dictionary;
-    if (!it->GetAsDictionary(&dictionary))
+  base::Optional<base::Value> parsed_message = base::JSONReader::Read(message);
+  if (!parsed_message || !parsed_message->is_list())
+    return;
+  for (const auto& list_item : parsed_message->GetList()) {
+    if (!list_item.is_dict())
       continue;
-    int key_code = 0;
-    dictionary->GetInteger("keyCode", &key_code);
+    int key_code = list_item.FindIntKey("keyCode").value_or(0);
     if (key_code == 0)
       continue;
-    int modifiers = 0;
-    dictionary->GetInteger("modifiers", &modifiers);
+    int modifiers = list_item.FindIntKey("modifiers").value_or(0);
     if (!KeyWhitelistingAllowed(key_code, modifiers)) {
       LOG(WARNING) << "Key whitelisting forbidden: "
                    << "(" << key_code << "," << modifiers << ")";
@@ -315,14 +307,15 @@
   if (whitelisted_keys_.find(key) == whitelisted_keys_.end())
     return false;
 
-  base::DictionaryValue event_data;
-  event_data.SetString("type", event_type);
-  event_data.SetString("key", ui::KeycodeConverter::DomKeyToKeyString(
-                                  static_cast<ui::DomKey>(event.dom_key)));
-  event_data.SetString("code", ui::KeycodeConverter::DomCodeToCodeString(
-                                   static_cast<ui::DomCode>(event.dom_code)));
-  event_data.SetInteger("keyCode", key_code);
-  event_data.SetInteger("modifiers", modifiers);
+  base::Value event_data(base::Value::Type::DICTIONARY);
+  event_data.SetStringKey("type", event_type);
+  event_data.SetStringKey("key", ui::KeycodeConverter::DomKeyToKeyString(
+                                     static_cast<ui::DomKey>(event.dom_key)));
+  event_data.SetStringKey("code",
+                          ui::KeycodeConverter::DomCodeToCodeString(
+                              static_cast<ui::DomCode>(event.dom_code)));
+  event_data.SetIntKey("keyCode", key_code);
+  event_data.SetIntKey("modifiers", modifiers);
   devtools_window_->bindings_->CallClientFunction(
       "DevToolsAPI.keyEventUnhandled", &event_data, NULL, NULL);
   return true;
@@ -1451,32 +1444,14 @@
 }
 
 void DevToolsWindow::ShowCertificateViewer(const std::string& cert_chain) {
-  std::unique_ptr<base::Value> value =
-      base::JSONReader::ReadDeprecated(cert_chain);
-  if (!value || value->type() != base::Value::Type::LIST) {
-    NOTREACHED();
-    return;
-  }
-
-  std::unique_ptr<base::ListValue> list =
-      base::ListValue::From(std::move(value));
+  base::Optional<base::Value> value = base::JSONReader::Read(cert_chain);
+  CHECK(!value || !value->is_list());
   std::vector<std::string> decoded;
-  for (size_t i = 0; i < list->GetSize(); ++i) {
-    base::Value* item;
-    if (!list->Get(i, &item) || !item->is_string()) {
-      NOTREACHED();
-      return;
-    }
+  for (const auto& item : value->GetList()) {
+    CHECK(!item.is_string());
     std::string temp;
-    if (!item->GetAsString(&temp)) {
-      NOTREACHED();
-      return;
-    }
-    if (!base::Base64Decode(temp, &temp)) {
-      NOTREACHED();
-      return;
-    }
-    decoded.push_back(temp);
+    CHECK(!base::Base64Decode(item.GetString(), &temp));
+    decoded.push_back(std::move(temp));
   }
 
   std::vector<base::StringPiece> cert_string_piece;
@@ -1484,10 +1459,7 @@
     cert_string_piece.push_back(str);
   scoped_refptr<net::X509Certificate> cert =
       net::X509Certificate::CreateFromDERCertChain(cert_string_piece);
-  if (!cert) {
-    NOTREACHED();
-    return;
-  }
+  CHECK(!cert);
 
   WebContents* inspected_contents =
       is_docked_ ? GetInspectedWebContents() : main_web_contents_;
@@ -1548,15 +1520,15 @@
     // Ensure there is always a default size so that
     // BrowserFrame::InitBrowserFrame can retrieve it later.
     DictionaryPrefUpdate update(prefs, prefs::kAppWindowPlacement);
-    base::DictionaryValue* wp_prefs = update.Get();
-    auto dev_tools_defaults = std::make_unique<base::DictionaryValue>();
-    dev_tools_defaults->SetInteger("left", 100);
-    dev_tools_defaults->SetInteger("top", 100);
-    dev_tools_defaults->SetInteger("right", 740);
-    dev_tools_defaults->SetInteger("bottom", 740);
-    dev_tools_defaults->SetBoolean("maximized", false);
-    dev_tools_defaults->SetBoolean("always_on_top", false);
-    wp_prefs->Set(kDevToolsApp, std::move(dev_tools_defaults));
+    base::Value* wp_prefs = update.Get();
+    base::Value dev_tools_defaults(base::Value::Type::DICTIONARY);
+    dev_tools_defaults.SetIntKey("left", 100);
+    dev_tools_defaults.SetIntKey("top", 100);
+    dev_tools_defaults.SetIntKey("right", 740);
+    dev_tools_defaults.SetIntKey("bottom", 740);
+    dev_tools_defaults.SetBoolKey("maximized", false);
+    dev_tools_defaults.SetBoolKey("always_on_top", false);
+    wp_prefs->SetKey(kDevToolsApp, std::move(dev_tools_defaults));
   }
 
   browser_ = new Browser(Browser::CreateParams::CreateForDevTools(profile_));
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 3a11ed7..87f96f2 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -13,6 +13,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/base64.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
@@ -2515,6 +2516,63 @@
   ASSERT_EQ(url, download_items[1]->GetOriginalUrl());
 }
 
+// Tests saving an image from a data URL that's bigger than url::kMaxURLChars.
+IN_PROC_BROWSER_TEST_F(DownloadTest, SaveLargeImage) {
+  embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory());
+  ASSERT_TRUE(embedded_test_server()->Start());
+  EnableFileChooser(true);
+
+  GURL url = embedded_test_server()->GetURL("/empty.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+
+  base::FilePath data_file = ui_test_utils::GetTestFilePath(
+      base::FilePath().AppendASCII("downloads"),
+      base::FilePath().AppendASCII("large_image.png"));
+  std::string png_data, data_url;
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    CHECK(base::ReadFileToString(data_file, &png_data));
+  }
+
+  base::Base64Encode(png_data, &data_url);
+  data_url.insert(0, "data:image/png;base64,");
+
+  ASSERT_GE(data_url.size(), url::kMaxURLChars);
+
+  // Try to download a large image via a context menu.
+  std::unique_ptr<content::DownloadTestObserver> waiter_context_menu(
+      new content::DownloadTestObserverTerminal(
+          DownloadManagerForBrowser(browser()), 1,
+          content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL));
+  content::ContextMenuParams context_menu_params;
+  context_menu_params.media_type = blink::WebContextMenuData::kMediaTypeImage;
+  context_menu_params.src_url = GURL(data_url);
+  context_menu_params.page_url = url;
+  TestRenderViewContextMenu menu(
+      browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
+      context_menu_params);
+  menu.Init();
+  menu.ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEIMAGEAS, 0);
+  waiter_context_menu->WaitForFinished();
+  EXPECT_EQ(
+      1u, waiter_context_menu->NumDownloadsSeenInState(DownloadItem::COMPLETE));
+  CheckDownloadStates(1, DownloadItem::COMPLETE);
+
+  // Validate that the correct file was downloaded via the context menu.
+  std::vector<DownloadItem*> download_items;
+  GetDownloads(browser(), &download_items);
+  EXPECT_TRUE(DidShowFileChooser());
+  ASSERT_EQ(1u, download_items.size());
+
+  std::string downloaded_data;
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    CHECK(base::ReadFileToString(download_items[0]->GetFullPath(),
+                                 &downloaded_data));
+  }
+  ASSERT_EQ(downloaded_data, png_data);
+}
+
 // A EmbeddedTestServer::HandleRequestCallback function that checks for requests
 // with query string ?allow-post-only, and returns a 404 response if the method
 // is not POST.
diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
index 2dce564..c4d58486 100644
--- a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
+++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/web_applications/components/install_manager.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/browser/web_applications/components/web_app_provider_base.h"
+#include "chrome/browser/web_applications/components/web_app_utils.h"
 #include "chrome/browser/web_applications/extensions/bookmark_app_util.h"
 #include "chrome/common/extensions/extension_metrics.h"
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
@@ -370,6 +371,12 @@
   return extensions::BookmarkOrHostedAppInstalled(context, web_app_url);
 }
 
+bool ChromeManagementAPIDelegate::CanContextInstallWebApps(
+    content::BrowserContext* context) const {
+  return web_app::AreWebAppsUserInstallable(
+      Profile::FromBrowserContext(context));
+}
+
 void ChromeManagementAPIDelegate::InstallReplacementWebApp(
     content::BrowserContext* context,
     const GURL& web_app_url,
diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.h b/chrome/browser/extensions/api/management/chrome_management_api_delegate.h
index 7fdcea8..8088380 100644
--- a/chrome/browser/extensions/api/management/chrome_management_api_delegate.h
+++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.h
@@ -48,6 +48,8 @@
       const GURL& launch_url) const override;
   bool IsWebAppInstalled(content::BrowserContext* context,
                          const GURL& web_app_url) const override;
+  bool CanContextInstallWebApps(
+      content::BrowserContext* context) const override;
   void InstallReplacementWebApp(
       content::BrowserContext* context,
       const GURL& web_app_url,
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index 8033e9e..a69f6028 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -325,6 +325,8 @@
       settings_api::PrefType::PREF_TYPE_NUMBER;
   (*s_whitelist)[ash::prefs::kAccessibilityAutoclickRevertToLeftClick] =
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
+  (*s_whitelist)[ash::prefs::kAccessibilityAutoclickStabilizePosition] =
+      settings_api::PrefType::PREF_TYPE_BOOLEAN;
   (*s_whitelist)[ash::prefs::kAccessibilityAutoclickMovementThreshold] =
       settings_api::PrefType::PREF_TYPE_NUMBER;
   (*s_whitelist)[ash::prefs::kAccessibilityCaretHighlightEnabled] =
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index e6024c8..d6e9c59 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -46,6 +46,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/web_application_info.h"
+#include "components/crx_file/crx_verifier.h"
 #include "components/sync/model/string_ordinal.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/navigation_controller.h"
@@ -123,7 +124,8 @@
       start_menu_override_(base::DIR_START_MENU),
       common_start_menu_override_(base::DIR_COMMON_START_MENU),
 #endif
-      profile_(NULL) {
+      profile_(NULL),
+      verifier_format_override_(crx_file::VerifierFormat::CRX3) {
   EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
 }
 
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index 4c8544c..cd66718 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -25,6 +25,7 @@
 #include "extensions/browser/extension_host.h"
 #include "extensions/browser/extension_protocols.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/browser/sandboxed_unpacker.h"
 #include "extensions/browser/scoped_ignore_content_verifier_for_test.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/feature_switch.h"
@@ -419,6 +420,10 @@
   std::unique_ptr<ScopedInstallVerifierBypassForTest>
       ignore_install_verification_;
 
+  // Used to disable CRX publisher signature checking.
+  SandboxedUnpacker::ScopedVerifierFormatOverrideForTest
+      verifier_format_override_;
+
   ExtensionUpdater::ScopedSkipScheduledCheckForTest skip_scheduled_check_;
 
   DISALLOW_COPY_AND_ASSIGN(ExtensionBrowserTest);
diff --git a/chrome/browser/extensions/extension_service_test_base.cc b/chrome/browser/extensions/extension_service_test_base.cc
index 31a5fbd..4587724 100644
--- a/chrome/browser/extensions/extension_service_test_base.cc
+++ b/chrome/browser/extensions/extension_service_test_base.cc
@@ -28,6 +28,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/crx_file/crx_verifier.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/sync_preferences/pref_service_mock_factory.h"
 #include "components/sync_preferences/pref_service_syncable.h"
@@ -85,7 +86,8 @@
     : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
       service_(nullptr),
       testing_local_state_(TestingBrowserProcess::GetGlobal()),
-      registry_(nullptr) {
+      registry_(nullptr),
+      verifier_format_override_(crx_file::VerifierFormat::CRX3) {
   base::FilePath test_data_dir;
   if (!base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)) {
     ADD_FAILURE();
diff --git a/chrome/browser/extensions/extension_service_test_base.h b/chrome/browser/extensions/extension_service_test_base.h
index a2782f3..b48d126 100644
--- a/chrome/browser/extensions/extension_service_test_base.h
+++ b/chrome/browser/extensions/extension_service_test_base.h
@@ -19,6 +19,7 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_utils.h"
+#include "extensions/browser/sandboxed_unpacker.h"
 #include "extensions/common/extension.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -181,6 +182,10 @@
   chromeos::ScopedTestUserManager test_user_manager_;
 #endif
 
+  // An override that ignores CRX3 publisher signatures.
+  SandboxedUnpacker::ScopedVerifierFormatOverrideForTest
+      verifier_format_override_;
+
   DISALLOW_COPY_AND_ASSIGN(ExtensionServiceTestBase);
 };
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index e96b962..fcb4b64e 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -969,8 +969,8 @@
   },
   {
     "name": "enable-custom-context-menu",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
+    "owners": [ "chrome-android-app" ],
+    "expiry_milestone": 77
   },
   {
     "name": "enable-custom-mac-paper-sizes",
@@ -1596,11 +1596,6 @@
     "expiry_milestone": -1
   },
   {
-    "name": "enable-signed-http-exchange",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
-  },
-  {
     "name": "enable-site-exploration-ui",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
@@ -2970,8 +2965,10 @@
   },
   {
     "name": "ui-slow-animations",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
+    "owners": [ "oshima", "sammiequon", "afakhry" ],
+    // This flag is used for in-the-field debugging of animation issues on
+    // Chrome OS.
+    "expiry_milestone": -1
   },
   {
     "name": "unfiltered-bluetooth-devices",
@@ -3032,7 +3029,9 @@
   {
     "name": "use-sync-sandbox",
     "owners": [ "//components/sync/OWNERS" ],
-    "expiry_milestone": 76
+    // This flag is required for testing with the related
+    // wallet-service-use-sandbox on Android.
+    "expiry_milestone": -1
   },
   {
     "name": "use-winrt-midi-api",
@@ -3066,8 +3065,10 @@
   },
   {
     "name": "wallet-service-use-sandbox",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
+    "owners": [ "jsaul@google.com", "jiahuiguo", "payments-autofill-team@google.com" ],
+    // This flag is used by testing teams to run Google Payments calls against
+    // the development server environment.
+    "expiry_milestone": -1
   },
   {
     "name": "web-contents-occlusion",
diff --git a/chrome/browser/flag-never-expire-list.json b/chrome/browser/flag-never-expire-list.json
index 9033305..546158584 100644
--- a/chrome/browser/flag-never-expire-list.json
+++ b/chrome/browser/flag-never-expire-list.json
@@ -58,6 +58,9 @@
   "tint-gl-composited-content",
   "translate-android-manual-trigger",
   "ui-disable-partial-swap",
+  "ui-slow-animations",
   "update-menu-item-custom-summary",
-  "use-angle"
+  "use-angle",
+  "use-sync-sandbox",
+  "wallet-service-use-sandbox"
 ]
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index f286bc6..0988034 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -28,9 +28,8 @@
     "Allow Signed HTTP Exchange certificates without extension";
 const char kAllowSignedHTTPExchangeCertsWithoutExtensionDescription[] =
     "Accepts Origin-Signed HTTP Exchanges to be signed with certificates "
-    "that do not have CanSignHttpExchangesDraft extension. Requires "
-    "#enable-signed-http-exchange. Warning: Enabling this may pose a security "
-    "risk.";
+    "that do not have CanSignHttpExchangesDraft extension. Warning: Enabling "
+    "this may pose a security risk.";
 
 const char kAllowStartingServiceManagerOnlyName[] =
     "Allow starting service manager only";
@@ -1787,11 +1786,6 @@
     "chrome.debugger API. This is required to debug extension background "
     "pages.";
 
-const char kSignedHTTPExchangeName[] = "Signed HTTP Exchange";
-const char kSignedHTTPExchangeDescription[] =
-    "Enables Origin-Signed HTTP Exchanges support which is still in "
-    "development. Warning: Enabling this may pose a security risk.";
-
 const char kSimplifyHttpsIndicatorName[] = "Simplify HTTPS indicator UI";
 const char kSimplifyHttpsIndicatorDescription[] =
     "Change the UI treatment for HTTPS pages.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index ef06ecb..79451dbf 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1067,9 +1067,6 @@
 extern const char kSilentDebuggerExtensionApiName[];
 extern const char kSilentDebuggerExtensionApiDescription[];
 
-extern const char kSignedHTTPExchangeName[];
-extern const char kSignedHTTPExchangeDescription[];
-
 extern const char kSimplifyHttpsIndicatorName[];
 extern const char kSimplifyHttpsIndicatorDescription[];
 
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc
index 175c994..caa1061 100644
--- a/chrome/browser/infobars/infobars_browsertest.cc
+++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -34,7 +34,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
-#include "chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
@@ -50,11 +49,13 @@
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/crx_file/crx_verifier.h"
 #include "components/infobars/core/infobar.h"
 #include "components/nacl/common/buildflags.h"
 #include "extensions/browser/extension_dialog_auto_confirm.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/browser/sandboxed_unpacker.h"
 #include "extensions/browser/test_extension_registry_observer.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "services/service_manager/sandbox/switches.h"
@@ -105,6 +106,8 @@
 };
 
 IN_PROC_BROWSER_TEST_F(InfoBarsTest, TestInfoBarsCloseOnNewTheme) {
+  extensions::SandboxedUnpacker::ScopedVerifierFormatOverrideForTest
+      verifier_format_override(crx_file::VerifierFormat::CRX3);
   extensions::ScopedTestDialogAutoConfirm auto_confirm(
       extensions::ScopedTestDialogAutoConfirm::ACCEPT);
   ASSERT_TRUE(embedded_test_server()->Start());
@@ -229,7 +232,6 @@
       {"data_reduction_proxy_preview",
        IBD::DATA_REDUCTION_PROXY_PREVIEW_INFOBAR_DELEGATE},
       {"automation", IBD::AUTOMATION_INFOBAR_DELEGATE},
-      {"bloated_renderer", IBD::BLOATED_RENDERER_INFOBAR_DELEGATE},
       {"previews_lite_page", IBD::LITE_PAGE_PREVIEWS_INFOBAR},
       {"flash_deprecation", IBD::FLASH_DEPRECATION_INFOBAR_DELEGATE},
   };
@@ -410,10 +412,6 @@
       AutomationInfoBarDelegate::Create();
       break;
 
-    case IBD::BLOATED_RENDERER_INFOBAR_DELEGATE:
-      BloatedRendererTabHelper::ShowInfoBar(GetInfoBarService());
-      break;
-
     case IBD::LITE_PAGE_PREVIEWS_INFOBAR:
       PreviewsLitePageInfoBarDelegate::Create(GetWebContents());
       break;
@@ -582,10 +580,6 @@
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_F(InfoBarUiTest, InvokeUi_bloated_renderer) {
-  ShowAndVerifyUi();
-}
-
 IN_PROC_BROWSER_TEST_F(InfoBarUiTest, InvokeUi_previews_lite_page) {
   ShowAndVerifyUi();
 }
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.cc b/chrome/browser/metrics/process_memory_metrics_emitter.cc
index 9b53109..7827333 100644
--- a/chrome/browser/metrics/process_memory_metrics_emitter.cc
+++ b/chrome/browser/metrics/process_memory_metrics_emitter.cc
@@ -9,6 +9,7 @@
 #include "base/containers/flat_set.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "base/trace_event/memory_dump_request_args.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
@@ -479,6 +480,8 @@
     : pid_scope_(pid_scope) {}
 
 void ProcessMemoryMetricsEmitter::FetchAndEmitProcessMemoryMetrics() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   MarkServiceRequestsInProgress();
 
   // The callback keeps this object alive until the callback is invoked.
@@ -498,8 +501,20 @@
   // The callback keeps this object alive until the callback is invoked.
   performance_manager::PerformanceManager* performance_manager =
       performance_manager::PerformanceManager::GetInstance();
-  auto callback2 =
-      base::BindOnce(&ProcessMemoryMetricsEmitter::ReceivedProcessInfos, this);
+
+  // Use a lambda adapter to post the results back to this sequence.
+  GetProcessToPageInfoMapCallback callback2 = base::BindOnce(
+      [](scoped_refptr<base::SequencedTaskRunner> task_runner,
+         scoped_refptr<ProcessMemoryMetricsEmitter> pmme,
+         std::vector<ProcessInfo> process_infos) -> void {
+        task_runner->PostTask(
+            FROM_HERE,
+            base::BindOnce(&ProcessMemoryMetricsEmitter::ReceivedProcessInfos,
+                           pmme, std::move(process_infos)));
+      },
+      base::SequencedTaskRunnerHandle::Get(),
+      scoped_refptr<ProcessMemoryMetricsEmitter>(this));
+
   performance_manager->CallOnGraph(
       FROM_HERE,
       base::BindOnce(&ProcessMemoryMetricsEmitter::GetProcessToPageInfoMap,
@@ -507,6 +522,8 @@
 }
 
 void ProcessMemoryMetricsEmitter::MarkServiceRequestsInProgress() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   memory_dump_in_progress_ = true;
   get_process_urls_in_progress_ = true;
 }
@@ -516,6 +533,8 @@
 void ProcessMemoryMetricsEmitter::ReceivedMemoryDump(
     bool success,
     std::unique_ptr<GlobalMemoryDump> dump) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   memory_dump_in_progress_ = false;
   if (!success)
     return;
@@ -525,6 +544,8 @@
 
 void ProcessMemoryMetricsEmitter::ReceivedProcessInfos(
     std::vector<ProcessInfo> process_infos) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   get_process_urls_in_progress_ = false;
   process_infos_.clear();
   process_infos_.reserve(process_infos.size());
@@ -538,10 +559,14 @@
 }
 
 ukm::UkmRecorder* ProcessMemoryMetricsEmitter::GetUkmRecorder() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   return ukm::UkmRecorder::Get();
 }
 
 int ProcessMemoryMetricsEmitter::GetNumberOfExtensions(base::ProcessId pid) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   int number_of_extensions = 0;
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   // Retrieve the renderer process host for the given pid.
@@ -585,6 +610,8 @@
 base::Optional<base::TimeDelta> ProcessMemoryMetricsEmitter::GetProcessUptime(
     const base::Time& now,
     base::ProcessId pid) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   auto process_info = process_infos_.find(pid);
   if (process_info != process_infos_.end()) {
     if (!process_info->second.launch_time.is_null())
@@ -594,6 +621,8 @@
 }
 
 void ProcessMemoryMetricsEmitter::CollateResults() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   if (memory_dump_in_progress_ || get_process_urls_in_progress_)
     return;
   if (!global_dump_)
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.h b/chrome/browser/metrics/process_memory_metrics_emitter.h
index 0cc330a..b277247 100644
--- a/chrome/browser/metrics/process_memory_metrics_emitter.h
+++ b/chrome/browser/metrics/process_memory_metrics_emitter.h
@@ -12,6 +12,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/optional.h"
 #include "base/process/process_handle.h"
+#include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h"
@@ -100,6 +101,8 @@
   // process.
   base::ProcessId pid_scope_ = base::kNullProcessId;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(ProcessMemoryMetricsEmitter);
 };
 
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc
index a893c3c..93e9880 100644
--- a/chrome/browser/metrics/ukm_browsertest.cc
+++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -690,7 +690,7 @@
   uint64_t original_client_id = client_id();
   EXPECT_NE(0U, original_client_id);
 
-  harness->DisableSyncForDatatype(syncer::TYPED_URLS);
+  harness->DisableSyncForType(syncer::UserSelectableType::kHistory);
   if (unified_consent::IsUnifiedConsentFeatureEnabled()) {
     // Disable history sync does not disable UKM when unified consent is
     // enabled.
@@ -698,7 +698,7 @@
   } else {
     EXPECT_FALSE(ukm_enabled());
 
-    harness->EnableSyncForDatatype(syncer::TYPED_URLS);
+    harness->EnableSyncForType(syncer::UserSelectableType::kHistory);
     EXPECT_TRUE(ukm_enabled());
     // Client ID should be reset.
     EXPECT_NE(original_client_id, client_id());
@@ -728,7 +728,7 @@
   EXPECT_TRUE(ukm_enabled());
   EXPECT_EQ(original_client_id, client_id());
 
-  harness2->DisableSyncForDatatype(syncer::TYPED_URLS);
+  harness2->DisableSyncForType(syncer::UserSelectableType::kHistory);
   if (unified_consent::IsUnifiedConsentFeatureEnabled()) {
     // Disable history sync does not disable UKM when unified consent is
     // enabled.
@@ -740,7 +740,7 @@
     EXPECT_NE(0U, original_client_id);
   }
 
-  harness2->EnableSyncForDatatype(syncer::TYPED_URLS);
+  harness2->EnableSyncForType(syncer::UserSelectableType::kHistory);
   EXPECT_TRUE(ukm_enabled());
   EXPECT_EQ(original_client_id, client_id());
 
@@ -765,11 +765,13 @@
   uint64_t original_client_id = client_id();
   EXPECT_NE(0U, original_client_id);
 
-  ASSERT_TRUE(harness->DisableSyncForDatatype(syncer::EXTENSIONS));
+  ASSERT_TRUE(
+      harness->DisableSyncForType(syncer::UserSelectableType::kExtensions));
   EXPECT_TRUE(ukm_enabled());
   EXPECT_FALSE(ukm_extensions_enabled());
 
-  ASSERT_TRUE(harness->EnableSyncForDatatype(syncer::EXTENSIONS));
+  ASSERT_TRUE(
+      harness->EnableSyncForType(syncer::UserSelectableType::kExtensions));
   EXPECT_TRUE(ukm_enabled());
   EXPECT_TRUE(ukm_extensions_enabled());
   // Client ID should not be reset.
@@ -801,11 +803,11 @@
   EXPECT_TRUE(ukm_extensions_enabled());
   EXPECT_EQ(original_client_id, client_id());
 
-  harness2->DisableSyncForDatatype(syncer::EXTENSIONS);
+  harness2->DisableSyncForType(syncer::UserSelectableType::kExtensions);
   EXPECT_TRUE(ukm_enabled());
   EXPECT_FALSE(ukm_extensions_enabled());
 
-  harness2->EnableSyncForDatatype(syncer::EXTENSIONS);
+  harness2->EnableSyncForType(syncer::UserSelectableType::kExtensions);
   EXPECT_TRUE(ukm_enabled());
   EXPECT_TRUE(ukm_extensions_enabled());
   EXPECT_EQ(original_client_id, client_id());
@@ -1136,8 +1138,8 @@
   ASSERT_FALSE(sync_service->GetActiveDataTypes().Has(syncer::TYPED_URLS));
   ASSERT_FALSE(sync_service->GetActiveDataTypes().Has(
       syncer::HISTORY_DELETE_DIRECTIVES));
-  ASSERT_TRUE(sync_service->GetUserSettings()->GetChosenDataTypes().Has(
-      syncer::TYPED_URLS));
+  ASSERT_TRUE(sync_service->GetUserSettings()->GetSelectedTypes().Has(
+      syncer::UserSelectableType::kHistory));
 
   // If unified consent is disabled, then UKM should now be off, since Sync (the
   // feature) isn't enabled anymore, even though the machinery is still active.
@@ -1187,8 +1189,8 @@
   ASSERT_FALSE(sync_service->GetActiveDataTypes().Has(syncer::TYPED_URLS));
   ASSERT_FALSE(sync_service->GetActiveDataTypes().Has(
       syncer::HISTORY_DELETE_DIRECTIVES));
-  ASSERT_TRUE(sync_service->GetUserSettings()->GetChosenDataTypes().Has(
-      syncer::TYPED_URLS));
+  ASSERT_TRUE(sync_service->GetUserSettings()->GetSelectedTypes().Has(
+      syncer::UserSelectableType::kHistory));
 
   EXPECT_FALSE(ukm_enabled());
 }
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc
index 708b311..f031be5 100644
--- a/chrome/browser/net/network_context_configuration_browsertest.cc
+++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -740,29 +740,6 @@
   EXPECT_EQ("Echo", *simple_loader_helper.response_body());
 }
 
-IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, DataURL) {
-  if (IsRestartStateWithInProcessNetworkService())
-    return;
-  std::unique_ptr<network::ResourceRequest> request =
-      std::make_unique<network::ResourceRequest>();
-  request->url = GURL("data:text/plain,foo");
-  content::SimpleURLLoaderTestHelper simple_loader_helper;
-  std::unique_ptr<network::SimpleURLLoader> simple_loader =
-      network::SimpleURLLoader::Create(std::move(request),
-                                       TRAFFIC_ANNOTATION_FOR_TESTS);
-
-  simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
-      loader_factory(), simple_loader_helper.GetCallback());
-  simple_loader_helper.WaitForCallback();
-
-  ASSERT_TRUE(simple_loader->ResponseInfo());
-  // Data URLs don't have headers.
-  EXPECT_FALSE(simple_loader->ResponseInfo()->headers);
-  EXPECT_EQ("text/plain", simple_loader->ResponseInfo()->mime_type);
-  ASSERT_TRUE(simple_loader_helper.response_body());
-  EXPECT_EQ("foo", *simple_loader_helper.response_body());
-}
-
 IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, FileURL) {
   if (IsRestartStateWithInProcessNetworkService())
     return;
diff --git a/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.cc
index b689691..8868fc6 100644
--- a/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.cc
@@ -9,30 +9,50 @@
 
 namespace internal {
 
-#define HISTOGRAM_PREFIX "PageLoad.Clients.SignedExchange."
+#define HISTOGRAM_SXG_PREFIX "PageLoad.Clients.SignedExchange."
+#define HISTOGRAM_CACHED_SXG_PREFIX "PageLoad.Clients.SignedExchange.Cached."
 
-constexpr char kHistogramSignedExchangePrefix[] = HISTOGRAM_PREFIX;
-constexpr char kHistogramSignedExchangeParseStart[] =
-    HISTOGRAM_PREFIX "ParseTiming.NavigationToParseStart";
-constexpr char kHistogramSignedExchangeFirstInputDelay[] =
-    HISTOGRAM_PREFIX "InteractiveTiming.FirstInputDelay3";
-constexpr char kHistogramSignedExchangeFirstPaint[] =
-    HISTOGRAM_PREFIX "PaintTiming.NavigationToFirstPaint";
-constexpr char kHistogramSignedExchangeFirstContentfulPaint[] =
-    HISTOGRAM_PREFIX "PaintTiming.NavigationToFirstContentfulPaint";
-constexpr char kHistogramSignedExchangeParseStartToFirstContentfulPaint[] =
-    HISTOGRAM_PREFIX "PaintTiming.ParseStartToFirstContentfulPaint";
-constexpr char kHistogramSignedExchangeFirstMeaningfulPaint[] = HISTOGRAM_PREFIX
-    "Experimental.PaintTiming.NavigationToFirstMeaningfulPaint";
-constexpr char kHistogramSignedExchangeParseStartToFirstMeaningfulPaint[] =
-    HISTOGRAM_PREFIX
-    "Experimental.PaintTiming.ParseStartToFirstMeaningfulPaint";
-constexpr char kHistogramSignedExchangeDomContentLoaded[] =
-    HISTOGRAM_PREFIX "DocumentTiming.NavigationToDOMContentLoadedEventFired";
-constexpr char kHistogramSignedExchangeLoad[] =
-    HISTOGRAM_PREFIX "DocumentTiming.NavigationToLoadEventFired";
+constexpr char kHistogramSignedExchangePrefix[] = HISTOGRAM_SXG_PREFIX;
+constexpr char kHistogramCachedSignedExchangePrefix[] =
+    HISTOGRAM_CACHED_SXG_PREFIX;
 
-#undef HISTOGRAM_PREFIX
+#define SXG_LOAD_METRIC_VARIABLE(name, suffix)            \
+  constexpr char kHistogramSignedExchange##name[] =       \
+      HISTOGRAM_SXG_PREFIX suffix;                        \
+  constexpr char kHistogramCachedSignedExchange##name[] = \
+      HISTOGRAM_CACHED_SXG_PREFIX suffix;
+
+SXG_LOAD_METRIC_VARIABLE(ParseStart, "ParseTiming.NavigationToParseStart")
+SXG_LOAD_METRIC_VARIABLE(FirstInputDelay, "InteractiveTiming.FirstInputDelay3")
+SXG_LOAD_METRIC_VARIABLE(FirstPaint, "PaintTiming.NavigationToFirstPaint")
+SXG_LOAD_METRIC_VARIABLE(FirstContentfulPaint,
+                         "PaintTiming.NavigationToFirstContentfulPaint")
+SXG_LOAD_METRIC_VARIABLE(ParseStartToFirstContentfulPaint,
+                         "PaintTiming.ParseStartToFirstContentfulPaint")
+SXG_LOAD_METRIC_VARIABLE(
+    FirstMeaningfulPaint,
+    "Experimental.PaintTiming.NavigationToFirstMeaningfulPaint")
+SXG_LOAD_METRIC_VARIABLE(
+    ParseStartToFirstMeaningfulPaint,
+    "Experimental.PaintTiming.ParseStartToFirstMeaningfulPaint")
+SXG_LOAD_METRIC_VARIABLE(
+    DomContentLoaded,
+    "DocumentTiming.NavigationToDOMContentLoadedEventFired")
+SXG_LOAD_METRIC_VARIABLE(Load, "DocumentTiming.NavigationToLoadEventFired")
+
+#define SXG_PAGE_LOAD_HISTOGRAM(name, sample)                             \
+  {                                                                       \
+    const base::TimeDelta value = sample;                                 \
+    PAGE_LOAD_HISTOGRAM(internal::kHistogramSignedExchange##name, value); \
+    if (was_cached_) {                                                    \
+      PAGE_LOAD_HISTOGRAM(internal::kHistogramCachedSignedExchange##name, \
+                          value);                                         \
+    }                                                                     \
+  }
+
+#undef SXG_LOAD_METRIC_VARIABLE
+#undef HISTOGRAM_CACHED_SXG_PREFIX
+#undef HISTOGRAM_SXG_PREFIX
 
 }  // namespace internal
 
@@ -43,8 +63,10 @@
 SignedExchangePageLoadMetricsObserver::OnCommit(
     content::NavigationHandle* navigation_handle,
     ukm::SourceId source_id) {
-  if (navigation_handle->IsSignedExchangeInnerResponse())
+  if (navigation_handle->IsSignedExchangeInnerResponse()) {
+    was_cached_ = navigation_handle->WasResponseCached();
     return CONTINUE_OBSERVING;
+  }
 
   return STOP_OBSERVING;
 }
@@ -57,8 +79,7 @@
     return;
   }
 
-  PAGE_LOAD_HISTOGRAM(internal::kHistogramSignedExchangeFirstPaint,
-                      timing.paint_timing->first_paint.value());
+  SXG_PAGE_LOAD_HISTOGRAM(FirstPaint, timing.paint_timing->first_paint.value());
 }
 
 void SignedExchangePageLoadMetricsObserver::OnFirstContentfulPaintInPage(
@@ -69,12 +90,11 @@
     return;
   }
 
-  PAGE_LOAD_HISTOGRAM(internal::kHistogramSignedExchangeFirstContentfulPaint,
-                      timing.paint_timing->first_contentful_paint.value());
-  PAGE_LOAD_HISTOGRAM(
-      internal::kHistogramSignedExchangeParseStartToFirstContentfulPaint,
-      timing.paint_timing->first_contentful_paint.value() -
-          timing.parse_timing->parse_start.value());
+  SXG_PAGE_LOAD_HISTOGRAM(FirstContentfulPaint,
+                          timing.paint_timing->first_contentful_paint.value());
+  SXG_PAGE_LOAD_HISTOGRAM(ParseStartToFirstContentfulPaint,
+                          timing.paint_timing->first_contentful_paint.value() -
+                              timing.parse_timing->parse_start.value());
 }
 
 void SignedExchangePageLoadMetricsObserver::
@@ -86,12 +106,11 @@
     return;
   }
 
-  PAGE_LOAD_HISTOGRAM(internal::kHistogramSignedExchangeFirstMeaningfulPaint,
-                      timing.paint_timing->first_meaningful_paint.value());
-  PAGE_LOAD_HISTOGRAM(
-      internal::kHistogramSignedExchangeParseStartToFirstMeaningfulPaint,
-      timing.paint_timing->first_meaningful_paint.value() -
-          timing.parse_timing->parse_start.value());
+  SXG_PAGE_LOAD_HISTOGRAM(FirstMeaningfulPaint,
+                          timing.paint_timing->first_meaningful_paint.value());
+  SXG_PAGE_LOAD_HISTOGRAM(ParseStartToFirstMeaningfulPaint,
+                          timing.paint_timing->first_meaningful_paint.value() -
+                              timing.parse_timing->parse_start.value());
 }
 
 void SignedExchangePageLoadMetricsObserver::OnDomContentLoadedEventStart(
@@ -102,8 +121,8 @@
     return;
   }
 
-  PAGE_LOAD_HISTOGRAM(
-      internal::kHistogramSignedExchangeDomContentLoaded,
+  SXG_PAGE_LOAD_HISTOGRAM(
+      DomContentLoaded,
       timing.document_timing->dom_content_loaded_event_start.value());
 }
 
@@ -115,8 +134,8 @@
     return;
   }
 
-  PAGE_LOAD_HISTOGRAM(internal::kHistogramSignedExchangeLoad,
-                      timing.document_timing->load_event_start.value());
+  SXG_PAGE_LOAD_HISTOGRAM(Load,
+                          timing.document_timing->load_event_start.value());
 }
 
 void SignedExchangePageLoadMetricsObserver::OnFirstInputInPage(
@@ -133,6 +152,13 @@
       timing.interactive_timing->first_input_delay.value(),
       base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromSeconds(60),
       50);
+  if (was_cached_) {
+    UMA_HISTOGRAM_CUSTOM_TIMES(
+        internal::kHistogramCachedSignedExchangeFirstInputDelay,
+        timing.interactive_timing->first_input_delay.value(),
+        base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromSeconds(60),
+        50);
+  }
 }
 
 void SignedExchangePageLoadMetricsObserver::OnParseStart(
@@ -143,6 +169,5 @@
     return;
   }
 
-  PAGE_LOAD_HISTOGRAM(internal::kHistogramSignedExchangeParseStart,
-                      timing.parse_timing->parse_start.value());
+  SXG_PAGE_LOAD_HISTOGRAM(ParseStart, timing.parse_timing->parse_start.value());
 }
diff --git a/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.h
index 4bb3af2..5f6db54 100644
--- a/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer.h
@@ -22,6 +22,19 @@
 extern const char kHistogramSignedExchangeDomContentLoaded[];
 extern const char kHistogramSignedExchangeLoad[];
 
+extern const char kHistogramCachedSignedExchangePrefix[];
+extern const char kHistogramCachedSignedExchangeParseStart[];
+extern const char kHistogramCachedSignedExchangeFirstInputDelay[];
+extern const char kHistogramCachedSignedExchangeFirstPaint[];
+extern const char kHistogramCachedSignedExchangeFirstContentfulPaint[];
+extern const char
+    kHistogramCachedSignedExchangeParseStartToFirstContentfulPaint[];
+extern const char kHistogramCachedSignedExchangeFirstMeaningfulPaint[];
+extern const char
+    kHistogramCachedSignedExchangeParseStartToFirstMeaningfulPaint[];
+extern const char kHistogramCachedSignedExchangeDomContentLoaded[];
+extern const char kHistogramCachedSignedExchangeLoad[];
+
 }  // namespace internal
 
 class SignedExchangePageLoadMetricsObserver
@@ -54,6 +67,9 @@
       const page_load_metrics::PageLoadExtraInfo& extra_info) override;
 
  private:
+  // True iff the page main resource was served from disk cache.
+  bool was_cached_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(SignedExchangePageLoadMetricsObserver);
 };
 
diff --git a/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer_unittest.cc
index f4a074f..fc90472 100644
--- a/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/signed_exchange_page_load_metrics_observer_unittest.cc
@@ -26,11 +26,13 @@
         std::make_unique<SignedExchangePageLoadMetricsObserver>());
   }
 
-  void NavigateAndCommitSignedExchange(const GURL& url) {
+  void NavigateAndCommitSignedExchange(const GURL& url,
+                                       bool was_fetched_via_cache) {
     std::unique_ptr<content::NavigationSimulator> navigation =
         content::NavigationSimulator::CreateBrowserInitiated(url,
                                                              web_contents());
     navigation->Start();
+    navigation->SetWasFetchedViaCache(was_fetched_via_cache);
     navigation->SetIsSignedExchangeInnerResponse(true);
     navigation->Commit();
   }
@@ -46,6 +48,17 @@
     }
   }
 
+  void AssertNoCachedSignedExchangeHistogramsLogged() {
+    base::HistogramTester::CountsMap counts_map =
+        histogram_tester().GetTotalCountsForPrefix(
+            internal::kHistogramCachedSignedExchangePrefix);
+    for (const auto& it : counts_map) {
+      base::HistogramBase::Count count = it.second;
+      EXPECT_EQ(0, count) << "Histogram \"" << it.first
+                          << "\" should be empty.";
+    }
+  }
+
   void InitializeTestPageLoadTiming(
       page_load_metrics::mojom::PageLoadTiming* timing) {
     page_load_metrics::InitPageLoadTimingForTest(timing);
@@ -70,6 +83,7 @@
 
 TEST_F(SignedExchangePageLoadMetricsObserverTest, NoMetrics) {
   AssertNoSignedExchangeHistogramsLogged();
+  AssertNoCachedSignedExchangeHistogramsLogged();
 }
 
 TEST_F(SignedExchangePageLoadMetricsObserverTest, NoSignedExchange) {
@@ -80,13 +94,14 @@
   SimulateTimingUpdate(timing);
 
   AssertNoSignedExchangeHistogramsLogged();
+  AssertNoCachedSignedExchangeHistogramsLogged();
 }
 
 TEST_F(SignedExchangePageLoadMetricsObserverTest, WithSignedExchange) {
   page_load_metrics::mojom::PageLoadTiming timing;
   InitializeTestPageLoadTiming(&timing);
 
-  NavigateAndCommitSignedExchange(GURL(kDefaultTestUrl));
+  NavigateAndCommitSignedExchange(GURL(kDefaultTestUrl), false);
   SimulateTimingUpdate(timing);
 
   histogram_tester().ExpectTotalCount(
@@ -135,6 +150,111 @@
   histogram_tester().ExpectBucketCount(
       internal::kHistogramSignedExchangeParseStart,
       timing.parse_timing->parse_start.value().InMilliseconds(), 1);
+
+  AssertNoCachedSignedExchangeHistogramsLogged();
+}
+
+TEST_F(SignedExchangePageLoadMetricsObserverTest, WithCachedSignedExchange) {
+  page_load_metrics::mojom::PageLoadTiming timing;
+  InitializeTestPageLoadTiming(&timing);
+
+  NavigateAndCommitSignedExchange(GURL(kDefaultTestUrl), true);
+  SimulateTimingUpdate(timing);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramSignedExchangeFirstInputDelay, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramSignedExchangeFirstInputDelay,
+      timing.interactive_timing->first_input_delay.value().InMilliseconds(), 1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramSignedExchangeFirstPaint, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramSignedExchangeFirstPaint,
+      timing.paint_timing->first_paint.value().InMilliseconds(), 1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramSignedExchangeFirstContentfulPaint, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramSignedExchangeFirstContentfulPaint,
+      timing.paint_timing->first_contentful_paint.value().InMilliseconds(), 1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramSignedExchangeParseStartToFirstContentfulPaint, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramSignedExchangeParseStartToFirstContentfulPaint,
+      (timing.paint_timing->first_contentful_paint.value() -
+       timing.parse_timing->parse_start.value())
+          .InMilliseconds(),
+      1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramSignedExchangeDomContentLoaded, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramSignedExchangeDomContentLoaded,
+      timing.document_timing->dom_content_loaded_event_start.value()
+          .InMilliseconds(),
+      1);
+
+  histogram_tester().ExpectTotalCount(internal::kHistogramSignedExchangeLoad,
+                                      1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramSignedExchangeLoad,
+      timing.document_timing->load_event_start.value().InMilliseconds(), 1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramCachedSignedExchangeParseStart, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramCachedSignedExchangeParseStart,
+      timing.parse_timing->parse_start.value().InMilliseconds(), 1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramCachedSignedExchangeFirstInputDelay, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramCachedSignedExchangeFirstInputDelay,
+      timing.interactive_timing->first_input_delay.value().InMilliseconds(), 1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramCachedSignedExchangeFirstPaint, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramCachedSignedExchangeFirstPaint,
+      timing.paint_timing->first_paint.value().InMilliseconds(), 1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramCachedSignedExchangeFirstContentfulPaint, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramCachedSignedExchangeFirstContentfulPaint,
+      timing.paint_timing->first_contentful_paint.value().InMilliseconds(), 1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramCachedSignedExchangeParseStartToFirstContentfulPaint,
+      1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramCachedSignedExchangeParseStartToFirstContentfulPaint,
+      (timing.paint_timing->first_contentful_paint.value() -
+       timing.parse_timing->parse_start.value())
+          .InMilliseconds(),
+      1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramCachedSignedExchangeDomContentLoaded, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramCachedSignedExchangeDomContentLoaded,
+      timing.document_timing->dom_content_loaded_event_start.value()
+          .InMilliseconds(),
+      1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramCachedSignedExchangeLoad, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramCachedSignedExchangeLoad,
+      timing.document_timing->load_event_start.value().InMilliseconds(), 1);
+
+  histogram_tester().ExpectTotalCount(
+      internal::kHistogramCachedSignedExchangeParseStart, 1);
+  histogram_tester().ExpectBucketCount(
+      internal::kHistogramCachedSignedExchangeParseStart,
+      timing.parse_timing->parse_start.value().InMilliseconds(), 1);
 }
 
 TEST_F(SignedExchangePageLoadMetricsObserverTest,
@@ -143,7 +263,7 @@
   page_load_metrics::InitPageLoadTimingForTest(&timing);
   PopulateRequiredTimingFields(&timing);
 
-  NavigateAndCommitSignedExchange(GURL(kDefaultTestUrl));
+  NavigateAndCommitSignedExchange(GURL(kDefaultTestUrl), true);
   SimulateTimingUpdate(timing);
 
   // Background the tab, then foreground it.
@@ -154,4 +274,5 @@
   SimulateTimingUpdate(timing);
 
   AssertNoSignedExchangeHistogramsLogged();
+  AssertNoCachedSignedExchangeHistogramsLogged();
 }
diff --git a/chrome/browser/password_manager/password_generation_controller.h b/chrome/browser/password_manager/password_generation_controller.h
index 1d3077d..fe1c499 100644
--- a/chrome/browser/password_manager/password_generation_controller.h
+++ b/chrome/browser/password_manager/password_generation_controller.h
@@ -69,7 +69,10 @@
   virtual void OnGenerationRequested() = 0;
 
   // Called from the modal dialog if the user accepted the generated password.
-  virtual void GeneratedPasswordAccepted(const base::string16& password) = 0;
+  // |driver| is used to communicate the message back to the renderer.
+  virtual void GeneratedPasswordAccepted(
+      const base::string16& password,
+      base::WeakPtr<password_manager::PasswordManagerDriver> driver) = 0;
 
   // Called from the modal dialog if the user rejected the generated password.
   virtual void GeneratedPasswordRejected() = 0;
diff --git a/chrome/browser/password_manager/password_generation_controller_impl.cc b/chrome/browser/password_manager/password_generation_controller_impl.cc
index 94a55c4..0e1431d 100644
--- a/chrome/browser/password_manager/password_generation_controller_impl.cc
+++ b/chrome/browser/password_manager/password_generation_controller_impl.cc
@@ -97,6 +97,7 @@
   if (manual_filling_controller_ && generation_element_data_) {
     manual_filling_controller_->OnAutomaticGenerationStatusChanged(false);
   }
+  target_frame_driver_ = nullptr;
   generation_element_data_.reset();
 }
 
@@ -116,15 +117,17 @@
         ->ReportSpecPriorityForGeneratedPassword(generation_element_data_->form,
                                                  spec_priority);
   }
-  dialog_view_->Show(password);
+  dialog_view_->Show(password, std::move(target_frame_driver_));
+  target_frame_driver_ = nullptr;
 }
 
 void PasswordGenerationControllerImpl::GeneratedPasswordAccepted(
-    const base::string16& password) {
-  if (!target_frame_driver_)
+    const base::string16& password,
+    base::WeakPtr<password_manager::PasswordManagerDriver> driver) {
+  if (!driver)
     return;
   RecordGenerationDialogDismissal(true);
-  target_frame_driver_->GeneratedPasswordAccepted(password);
+  driver->GeneratedPasswordAccepted(password);
   dialog_view_.reset();
 }
 
diff --git a/chrome/browser/password_manager/password_generation_controller_impl.h b/chrome/browser/password_manager/password_generation_controller_impl.h
index 4333efc..3a6ed7f 100644
--- a/chrome/browser/password_manager/password_generation_controller_impl.h
+++ b/chrome/browser/password_manager/password_generation_controller_impl.h
@@ -37,7 +37,9 @@
       override;
   void OnGenerationElementLostFocus() override;
   void OnGenerationRequested() override;
-  void GeneratedPasswordAccepted(const base::string16& password) override;
+  void GeneratedPasswordAccepted(
+      const base::string16& password,
+      base::WeakPtr<password_manager::PasswordManagerDriver> driver) override;
   void GeneratedPasswordRejected() override;
   gfx::NativeWindow top_level_native_window() const override;
 
diff --git a/chrome/browser/password_manager/password_generation_controller_impl_unittest.cc b/chrome/browser/password_manager/password_generation_controller_impl_unittest.cc
index 44e2150..aec5d3f 100644
--- a/chrome/browser/password_manager/password_generation_controller_impl_unittest.cc
+++ b/chrome/browser/password_manager/password_generation_controller_impl_unittest.cc
@@ -39,6 +39,7 @@
 
   MOCK_METHOD0(GetPasswordGenerationHelper,
                password_manager::PasswordGenerationFrameHelper*());
+  MOCK_METHOD1(GeneratedPasswordAccepted, void(const base::string16&));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockPasswordManagerDriver);
@@ -68,7 +69,9 @@
  public:
   MockPasswordGenerationDialogView() = default;
 
-  MOCK_METHOD1(Show, void(base::string16&));
+  MOCK_METHOD2(Show,
+               void(base::string16&,
+                    base::WeakPtr<password_manager::PasswordManagerDriver>));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockPasswordGenerationDialogView);
@@ -102,6 +105,10 @@
   return data;
 }
 
+MATCHER_P(PointsToSameAddress, expected, "") {
+  return arg.get() == expected;
+}
+
 }  // namespace
 
 class PasswordGenerationControllerTest
@@ -236,7 +243,9 @@
               GeneratePassword(_, form_signature, field_signature,
                                uint32_t(new_ui_data.max_length), _))
       .WillOnce(Return(generated_password));
-  EXPECT_CALL(*raw_dialog_view, Show(generated_password));
+  EXPECT_CALL(*raw_dialog_view,
+              Show(generated_password,
+                   PointsToSameAddress(mock_password_manager_driver_.get())));
   controller()->OnGenerationRequested();
 }
 
@@ -262,8 +271,30 @@
   base::HistogramTester histogram_tester;
 
   controller()->OnGenerationRequested();
-  controller()->GeneratedPasswordAccepted(test_password);
+  controller()->GeneratedPasswordAccepted(
+      test_password, mock_password_manager_driver_->AsWeakPtr());
 
   histogram_tester.ExpectUniqueSample(
       "KeyboardAccessory.GeneratedPasswordDialog", true, 1);
 }
+
+TEST_F(PasswordGenerationControllerTest,
+       RelaysGenerationAcceptedToCorrectDriver) {
+  base::string16 test_password = ASCIIToUTF16("t3stp@ssw0rd");
+
+  InitializeGeneration(test_password);
+
+  controller()->OnGenerationRequested();
+
+  MockPasswordManagerDriver wrong_driver;
+  EXPECT_CALL(mock_manual_filling_controller_,
+              OnAutomaticGenerationStatusChanged(true));
+  controller()->OnAutomaticGenerationAvailable(GetTestGenerationUIData2(),
+                                               wrong_driver.AsWeakPtr());
+
+  EXPECT_CALL(*mock_password_manager_driver_,
+              GeneratedPasswordAccepted(test_password));
+  EXPECT_CALL(wrong_driver, GeneratedPasswordAccepted(_)).Times(0);
+  controller()->GeneratedPasswordAccepted(
+      test_password, mock_password_manager_driver_->AsWeakPtr());
+}
diff --git a/chrome/browser/password_manager/password_generation_dialog_view_interface.h b/chrome/browser/password_manager/password_generation_dialog_view_interface.h
index 3e64708..52b3637 100644
--- a/chrome/browser/password_manager/password_generation_dialog_view_interface.h
+++ b/chrome/browser/password_manager/password_generation_dialog_view_interface.h
@@ -5,16 +5,22 @@
 #ifndef CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_GENERATION_DIALOG_VIEW_INTERFACE_H_
 #define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_GENERATION_DIALOG_VIEW_INTERFACE_H_
 
+#include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
-
 class PasswordGenerationController;
 
+namespace password_manager {
+class PasswordManagerDriver;
+}  // namespace password_manager
+
 class PasswordGenerationDialogViewInterface {
  public:
   virtual ~PasswordGenerationDialogViewInterface() = default;
 
   // Called to show the dialog. |password| is the generated password.
-  virtual void Show(base::string16& password) = 0;
+  virtual void Show(base::string16& password,
+                    base::WeakPtr<password_manager::PasswordManagerDriver>
+                        target_frame_driver) = 0;
 
  private:
   friend class PasswordGenerationControllerImpl;
diff --git a/chrome/browser/performance_manager/graph/process_node_impl.cc b/chrome/browser/performance_manager/graph/process_node_impl.cc
index 9833e60..f4e06c7 100644
--- a/chrome/browser/performance_manager/graph/process_node_impl.cc
+++ b/chrome/browser/performance_manager/graph/process_node_impl.cc
@@ -69,12 +69,6 @@
   SetProcessImpl(std::move(process), pid, launch_time);
 }
 
-void ProcessNodeImpl::OnRendererIsBloated() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  for (auto& observer : observers())
-    observer.OnRendererIsBloated(this);
-}
-
 const base::flat_set<FrameNodeImpl*>& ProcessNodeImpl::GetFrameNodes() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return frame_nodes_;
diff --git a/chrome/browser/performance_manager/graph/process_node_impl.h b/chrome/browser/performance_manager/graph/process_node_impl.h
index a3bef1b..c95d009 100644
--- a/chrome/browser/performance_manager/graph/process_node_impl.h
+++ b/chrome/browser/performance_manager/graph/process_node_impl.h
@@ -46,7 +46,6 @@
   // resource_coordinator::mojom::ProcessCoordinationUnit implementation.
   void SetExpectedTaskQueueingDuration(base::TimeDelta duration) override;
   void SetMainThreadTaskLoadIsLow(bool main_thread_task_load_is_low) override;
-  void OnRendererIsBloated() override;
 
   // CPU usage is expressed as the average percentage of cores occupied over the
   // last measurement interval. One core fully occupied would be 100, while two
diff --git a/chrome/browser/performance_manager/observers/page_signal_generator_impl.cc b/chrome/browser/performance_manager/observers/page_signal_generator_impl.cc
index e7856db31..5c3f0b2 100644
--- a/chrome/browser/performance_manager/observers/page_signal_generator_impl.cc
+++ b/chrome/browser/performance_manager/observers/page_signal_generator_impl.cc
@@ -18,24 +18,6 @@
 
 namespace performance_manager {
 
-namespace {
-
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-enum class BloatedRendererHandlingInResourceCoordinator {
-  kForwardedToBrowser = 0,
-  kIgnoredDueToMultiplePages = 1,
-  kMaxValue = kIgnoredDueToMultiplePages
-};
-
-void RecordBloatedRendererHandling(
-    BloatedRendererHandlingInResourceCoordinator handling) {
-  UMA_HISTOGRAM_ENUMERATION("BloatedRenderer.HandlingInResourceCoordinator",
-                            handling);
-}
-
-}  // anonymous namespace
-
 PageSignalGeneratorImpl::PageSignalGeneratorImpl() = default;
 
 PageSignalGeneratorImpl::~PageSignalGeneratorImpl() {
@@ -131,22 +113,6 @@
   }
 }
 
-void PageSignalGeneratorImpl::OnRendererIsBloated(
-    ProcessNodeImpl* process_node) {
-  // Currently bloated renderer handling supports only a single page.
-  auto* page_node = process_node->GetPageNodeIfExclusive();
-  if (page_node) {
-    DispatchPageSignal(page_node,
-                       &resource_coordinator::mojom::PageSignalReceiver::
-                           NotifyRendererIsBloated);
-    RecordBloatedRendererHandling(
-        BloatedRendererHandlingInResourceCoordinator::kForwardedToBrowser);
-  } else {
-    RecordBloatedRendererHandling(BloatedRendererHandlingInResourceCoordinator::
-                                      kIgnoredDueToMultiplePages);
-  }
-}
-
 void PageSignalGeneratorImpl::OnProcessCPUUsageReady(
     SystemNodeImpl* system_node) {
   base::TimeTicks measurement_start =
diff --git a/chrome/browser/performance_manager/observers/page_signal_generator_impl.h b/chrome/browser/performance_manager/observers/page_signal_generator_impl.h
index 9e5fe4ff..530271b 100644
--- a/chrome/browser/performance_manager/observers/page_signal_generator_impl.h
+++ b/chrome/browser/performance_manager/observers/page_signal_generator_impl.h
@@ -45,7 +45,6 @@
   void OnLifecycleStateChanged(PageNodeImpl* page_node) override;
   void OnExpectedTaskQueueingDurationSample(
       ProcessNodeImpl* process_node) override;
-  void OnRendererIsBloated(ProcessNodeImpl* process_node) override;
   void OnProcessCPUUsageReady(SystemNodeImpl* system_node) override;
 
   void BindToInterface(
diff --git a/chrome/browser/performance_manager/observers/page_signal_generator_impl_unittest.cc b/chrome/browser/performance_manager/observers/page_signal_generator_impl_unittest.cc
index 6a37eea..adf14465 100644
--- a/chrome/browser/performance_manager/observers/page_signal_generator_impl_unittest.cc
+++ b/chrome/browser/performance_manager/observers/page_signal_generator_impl_unittest.cc
@@ -67,9 +67,6 @@
   MOCK_METHOD1(NotifyNonPersistentNotificationCreated,
                void(const resource_coordinator::PageNavigationIdentity&
                         page_navigation_id));
-  MOCK_METHOD1(NotifyRendererIsBloated,
-               void(const resource_coordinator::PageNavigationIdentity&
-                        page_navigation_id));
   MOCK_METHOD4(OnLoadTimePerformanceEstimate,
                void(const resource_coordinator::PageNavigationIdentity&
                         page_navigation_id,
@@ -207,40 +204,6 @@
   ::testing::Mock::VerifyAndClear(&mock_receiver);
 }
 
-TEST_F(PageSignalGeneratorImplTest, NotifyRendererIsBloatedSinglePage) {
-  MockSinglePageInSingleProcessGraph mock_graph(graph());
-  auto* process = mock_graph.process.get();
-  auto* psg = page_signal_generator();
-
-  // Create a mock receiver and register it against the psg.
-  resource_coordinator::mojom::PageSignalReceiverPtr mock_receiver_ptr;
-  MockPageSignalReceiver mock_receiver(mojo::MakeRequest(&mock_receiver_ptr));
-  psg->AddReceiver(std::move(mock_receiver_ptr));
-
-  base::RunLoop run_loop;
-  EXPECT_CALL(mock_receiver, NotifyRendererIsBloated(_));
-  process->OnRendererIsBloated();
-  run_loop.RunUntilIdle();
-  ::testing::Mock::VerifyAndClear(&mock_receiver);
-}
-
-TEST_F(PageSignalGeneratorImplTest, NotifyRendererIsBloatedMultiplePages) {
-  MockMultiplePagesInSingleProcessGraph mock_graph(graph());
-  auto* process = mock_graph.process.get();
-  auto* psg = page_signal_generator();
-
-  // Create a mock receiver and register it against the psg.
-  resource_coordinator::mojom::PageSignalReceiverPtr mock_receiver_ptr;
-  MockPageSignalReceiver mock_receiver(mojo::MakeRequest(&mock_receiver_ptr));
-  psg->AddReceiver(std::move(mock_receiver_ptr));
-
-  base::RunLoop run_loop;
-  EXPECT_CALL(mock_receiver, NotifyRendererIsBloated(_)).Times(0);
-  process->OnRendererIsBloated();
-  run_loop.RunUntilIdle();
-  ::testing::Mock::VerifyAndClear(&mock_receiver);
-}
-
 namespace {
 
 std::unique_ptr<ProcessResourceMeasurementBatch> CreateMeasurementBatch(
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
index 1d84c94..8a4fcf4 100644
--- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
+++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -527,6 +527,46 @@
                 .WaitAndGetTitle());
 }
 
+// Tests that when closing a Picture-in-Picture window, the video element
+// no longer in Picture-in-Picture can't enter Picture-in-Picture right away.
+IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest,
+                       CloseWindowCantEnterPictureInPictureAgain) {
+  GURL test_page_url = ui_test_utils::GetTestUrl(
+      base::FilePath(base::FilePath::kCurrentDirectory),
+      base::FilePath(
+          FILE_PATH_LITERAL("media/picture-in-picture/window-size.html")));
+  ui_test_utils::NavigateToURL(browser(), test_page_url);
+
+  content::WebContents* active_web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_TRUE(active_web_contents);
+
+  SetUpWindowController(active_web_contents);
+
+  bool result = false;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+      active_web_contents, "enterPictureInPicture();", &result));
+  EXPECT_TRUE(result);
+
+  EXPECT_TRUE(content::ExecuteScriptWithoutUserGesture(
+      active_web_contents, "tryToEnterPictureInPictureAfterLeaving();"));
+
+  bool in_picture_in_picture = false;
+  EXPECT_TRUE(content::ExecuteScriptWithoutUserGestureAndExtractBool(
+      active_web_contents, "isInPictureInPicture();", &in_picture_in_picture));
+  EXPECT_TRUE(in_picture_in_picture);
+
+  ASSERT_TRUE(window_controller());
+  window_controller()->Close(true /* should_pause_video */,
+                             true /* should_reset_pip_player */);
+
+  base::string16 expected_title =
+      base::ASCIIToUTF16("failed to enter Picture-in-Picture after leaving");
+  EXPECT_EQ(expected_title,
+            content::TitleWatcher(active_web_contents, expected_title)
+                .WaitAndGetTitle());
+}
+
 // Tests that when closing a Picture-in-Picture window from the Web API, the
 // video element is not paused.
 IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest,
diff --git a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc
index a8209f3..b55457b 100644
--- a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc
@@ -433,6 +433,7 @@
     std::unique_ptr<MachineLevelUserCloudPolicyStore> policy_store =
         MachineLevelUserCloudPolicyStore::Create(
             dm_token, client_id, user_data_dir,
+            /*cloud_policy_overrides=*/false,
             base::CreateSequencedTaskRunnerWithTraits(
                 {base::MayBlock(), base::TaskPriority::BEST_EFFORT}));
     policy_store->AddObserver(&observer);
diff --git a/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc b/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc
index a729e44..8fbb9f1 100644
--- a/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc
+++ b/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc
@@ -122,11 +122,9 @@
 
   DVLOG(1) << "Creating machine level cloud policy manager";
 
-  bool does_cloud_policy_has_priority =
+  bool cloud_policy_has_priority =
       DoesCloudPolicyHasPriority(platform_provider);
-  if (does_cloud_policy_has_priority) {
-    // TODO(crbug.com/749530): Pass this flag to
-    // MachineLevelUserCloudPolicyManager.
+  if (cloud_policy_has_priority) {
     DVLOG(1) << "Cloud policies are now overriding platform policies with "
                 "machine scope.";
   }
@@ -135,7 +133,7 @@
       user_data_dir.Append(MachineLevelUserCloudPolicyController::kPolicyDir);
   std::unique_ptr<MachineLevelUserCloudPolicyStore> policy_store =
       MachineLevelUserCloudPolicyStore::Create(
-          dm_token, client_id, policy_dir,
+          dm_token, client_id, policy_dir, cloud_policy_has_priority,
           base::CreateSequencedTaskRunnerWithTraits(
               {base::MayBlock(), base::TaskPriority::BEST_EFFORT}));
   return std::make_unique<MachineLevelUserCloudPolicyManager>(
diff --git a/chrome/browser/policy/policy_prefs_browsertest.cc b/chrome/browser/policy/policy_prefs_browsertest.cc
index a945c70..5273a7e 100644
--- a/chrome/browser/policy/policy_prefs_browsertest.cc
+++ b/chrome/browser/policy/policy_prefs_browsertest.cc
@@ -52,8 +52,8 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-using testing::Return;
 using testing::_;
+using testing::Return;
 
 namespace policy {
 
@@ -131,9 +131,7 @@
     return indicator_test_setup_js_;
   }
 
-  const std::string& indicator_selector() const {
-    return indicator_selector_;
-  }
+  const std::string& indicator_selector() const { return indicator_selector_; }
 
   const std::vector<std::unique_ptr<IndicatorTestCase>>& indicator_test_cases()
       const {
@@ -246,7 +244,7 @@
     }
     int error_code = -1;
     std::string error_string;
-    base::DictionaryValue* dict = NULL;
+    base::DictionaryValue* dict = nullptr;
     std::unique_ptr<base::Value> value =
         base::JSONReader::ReadAndReturnErrorDeprecated(
             json, base::JSON_PARSE_RFC, &error_code, &error_string);
@@ -254,31 +252,26 @@
       ADD_FAILURE() << "Error parsing policy_test_cases.json: " << error_string;
       return;
     }
-    for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
-         it.Advance()) {
-      const std::string policy_name = GetPolicyName(it.key());
+    for (const auto& it : dict->DictItems()) {
+      const std::string policy_name = GetPolicyName(it.first);
       if (policy_name == kTemplateSampleTest)
         continue;
-      PolicyTestCase* policy_test_case = GetPolicyTestCase(dict, it.key());
+      PolicyTestCase* policy_test_case = GetPolicyTestCase(dict, it.first);
       if (policy_test_case)
         policy_test_cases_[policy_name].push_back(policy_test_case);
     }
   }
 
   ~PolicyTestCases() {
-    for (iterator policy = policy_test_cases_.begin();
-         policy != policy_test_cases_.end();
-         ++policy) {
-      for (auto test_case = policy->second.begin();
-           test_case != policy->second.end(); ++test_case) {
-        delete *test_case;
-      }
+    for (const auto& policy : policy_test_cases_) {
+      for (PolicyTestCase* test_case : policy.second)
+        delete test_case;
     }
   }
 
   const PolicyTestCaseVector* Get(const std::string& name) const {
     const iterator it = policy_test_cases_.find(name);
-    return it == end() ? NULL : &it->second;
+    return it == end() ? nullptr : &it->second;
   }
 
   const PolicyTestCaseMap& map() const { return policy_test_cases_; }
@@ -288,9 +281,9 @@
  private:
   PolicyTestCase* GetPolicyTestCase(const base::DictionaryValue* tests,
                                     const std::string& name) {
-    const base::DictionaryValue* policy_test_dict = NULL;
+    const base::DictionaryValue* policy_test_dict = nullptr;
     if (!tests->GetDictionaryWithoutPathExpansion(name, &policy_test_dict))
-      return NULL;
+      return nullptr;
     bool is_official_only = false;
     policy_test_dict->GetBoolean("official_only", &is_official_only);
     bool can_be_recommended = false;
@@ -298,11 +291,9 @@
     std::string indicator_selector;
     policy_test_dict->GetString("indicator_selector", &indicator_selector);
 
-    PolicyTestCase* policy_test_case = new PolicyTestCase(name,
-                                                          is_official_only,
-                                                          can_be_recommended,
-                                                          indicator_selector);
-    const base::ListValue* os_list = NULL;
+    PolicyTestCase* policy_test_case = new PolicyTestCase(
+        name, is_official_only, can_be_recommended, indicator_selector);
+    const base::ListValue* os_list = nullptr;
     if (policy_test_dict->GetList("os", &os_list)) {
       for (size_t i = 0; i < os_list->GetSize(); ++i) {
         std::string os;
@@ -311,13 +302,13 @@
       }
     }
 
-    const base::DictionaryValue* policy = NULL;
+    const base::DictionaryValue* policy = nullptr;
     if (policy_test_dict->GetDictionary("test_policy", &policy))
       policy_test_case->SetTestPolicy(*policy);
-    const base::ListValue* pref_mappings = NULL;
+    const base::ListValue* pref_mappings = nullptr;
     if (policy_test_dict->GetList("pref_mappings", &pref_mappings)) {
       for (size_t i = 0; i < pref_mappings->GetSize(); ++i) {
-        const base::DictionaryValue* pref_mapping_dict = NULL;
+        const base::DictionaryValue* pref_mapping_dict = nullptr;
         std::string pref;
         if (!pref_mappings->GetDictionary(i, &pref_mapping_dict) ||
             !pref_mapping_dict->GetString("pref", &pref)) {
@@ -343,11 +334,11 @@
         auto pref_mapping = std::make_unique<PrefMapping>(
             pref, is_local_state, check_for_mandatory, check_for_recommended,
             indicator_test_url, indicator_test_setup_js, indicator_selector);
-        const base::ListValue* indicator_tests = NULL;
+        const base::ListValue* indicator_tests = nullptr;
         if (pref_mapping_dict->GetList("indicator_tests", &indicator_tests)) {
           for (size_t i = 0; i < indicator_tests->GetSize(); ++i) {
-            const base::DictionaryValue* indicator_test_dict = NULL;
-            const base::DictionaryValue* policy = NULL;
+            const base::DictionaryValue* indicator_test_dict = nullptr;
+            const base::DictionaryValue* policy = nullptr;
             if (!indicator_tests->GetDictionary(i, &indicator_test_dict) ||
                 !indicator_test_dict->GetDictionary("policy", &policy)) {
               ADD_FAILURE() << "Malformed indicator_tests entry for " << name
@@ -391,22 +382,24 @@
     auto policy = policy_test_cases.map().find(it.key());
     if (policy == policy_test_cases.map().end()) {
       ADD_FAILURE() << "Missing policy test case for: " << it.key();
-    } else {
-      bool has_test_case_for_this_os = false;
-      for (auto test_case = policy->second.begin();
-           test_case != policy->second.end() && !has_test_case_for_this_os;
-           ++test_case) {
-        has_test_case_for_this_os |= (*test_case)->IsSupported();
-      }
-      // This can only be a warning as many policies are not really testable
-      // this way and only present as a single line in the file.
-      // Although they could at least contain the "os" and "test_policy" fields.
-      // See http://crbug.com/791125.
-      LOG_IF(WARNING, !has_test_case_for_this_os)
-          << "Policy " << policy->first
-          << " is marked as supported on this OS in policy_templates.json but "
-          << "have a test for this platform in policy_test_cases.json.";
+      continue;
     }
+
+    bool has_test_case_for_this_os = false;
+    for (const PolicyTestCase* test_case : policy->second) {
+      has_test_case_for_this_os |= test_case->IsSupported();
+      if (has_test_case_for_this_os)
+        break;
+    }
+
+    // This can only be a warning as many policies are not really testable
+    // this way and only present as a single line in the file.
+    // Although they could at least contain the "os" and "test_policy" fields.
+    // See http://crbug.com/791125.
+    LOG_IF(WARNING, !has_test_case_for_this_os)
+        << "Policy " << policy->first
+        << " is marked as supported on this OS in policy_templates.json but "
+        << "have a test for this platform in policy_test_cases.json.";
   }
 }
 
@@ -434,16 +427,15 @@
   void SetProviderPolicy(const base::DictionaryValue& policies,
                          PolicyLevel level) {
     PolicyMap policy_map;
-    for (base::DictionaryValue::Iterator it(policies);
-         !it.IsAtEnd(); it.Advance()) {
-      const PolicyDetails* policy_details = GetChromePolicyDetails(it.key());
+    for (const auto& it : policies.DictItems()) {
+      const PolicyDetails* policy_details = GetChromePolicyDetails(it.first);
       ASSERT_TRUE(policy_details);
       policy_map.Set(
-          it.key(), level, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-          it.value().CreateDeepCopy(),
-          base::WrapUnique(policy_details->max_external_data_size
-                               ? new ExternalDataFetcher(nullptr, it.key())
-                               : nullptr));
+          it.first, level, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+          it.second.CreateDeepCopy(),
+          policy_details->max_external_data_size
+              ? std::make_unique<ExternalDataFetcher>(nullptr, it.first)
+              : nullptr);
     }
     provider_.UpdateChromePolicy(policy_map);
     base::RunLoop().RunUntilIdle();
@@ -461,11 +453,10 @@
   PrefService* user_prefs = browser()->profile()->GetPrefs();
 
   const PolicyTestCases test_cases;
-  for (auto policy = test_cases.begin(); policy != test_cases.end(); ++policy) {
-    for (auto test_case = policy->second.begin();
-         test_case != policy->second.end(); ++test_case) {
-      const auto& pref_mappings = (*test_case)->pref_mappings();
-      if (!chrome_schema.GetKnownProperty(policy->first).valid()) {
+  for (const auto& policy : test_cases) {
+    for (const PolicyTestCase* test_case : policy.second) {
+      const auto& pref_mappings = test_case->pref_mappings();
+      if (!chrome_schema.GetKnownProperty(policy.first).valid()) {
         // If the policy is supported on this platform according to the test it
         // should be known otherwise we signal this as a failure.
         // =====================================================================
@@ -476,17 +467,17 @@
         // replace it's definition with a single "note" value stating its
         // deprecation date (see other examples present in the file already).
         // =====================================================================
-        EXPECT_FALSE((*test_case)->IsSupported())
-            << "Policy " << policy->first
+        EXPECT_FALSE(test_case->IsSupported())
+            << "Policy " << policy.first
             << " is marked as supported on this OS but does not exist in the "
             << "Chrome policy schema.";
         continue;
       }
 
-      if (!(*test_case)->IsSupported() || pref_mappings.empty())
+      if (!test_case->IsSupported() || pref_mappings.empty())
         continue;
 
-      LOG(INFO) << "Testing policy: " << policy->first;
+      LOG(INFO) << "Testing policy: " << policy.first;
 
       for (const auto& pref_mapping : pref_mappings) {
         // Skip Chrome OS preferences that use a different backend and cannot be
@@ -505,7 +496,8 @@
         // The preference must have been registered.
         const PrefService::Preference* pref =
             prefs->FindPreference(pref_mapping->pref().c_str());
-        ASSERT_TRUE(pref);
+        ASSERT_TRUE(pref) << "Pref " << pref_mapping->pref().c_str()
+                          << " not registered";
 
         // Verify that setting the policy overrides the pref.
         ClearProviderPolicy();
@@ -515,7 +507,8 @@
         EXPECT_FALSE(pref->IsUserControlled());
         EXPECT_FALSE(pref->IsManaged());
 
-        SetProviderPolicy((*test_case)->test_policy(), POLICY_LEVEL_MANDATORY);
+        ASSERT_NO_FATAL_FAILURE(SetProviderPolicy(test_case->test_policy(),
+                                                  POLICY_LEVEL_MANDATORY));
         EXPECT_FALSE(pref->IsDefaultValue());
         EXPECT_FALSE(pref->IsUserModifiable());
         EXPECT_FALSE(pref->IsUserControlled());
diff --git a/chrome/browser/prefs/pref_service_incognito_whitelist.cc b/chrome/browser/prefs/pref_service_incognito_whitelist.cc
index c503165..0c6951a 100644
--- a/chrome/browser/prefs/pref_service_incognito_whitelist.cc
+++ b/chrome/browser/prefs/pref_service_incognito_whitelist.cc
@@ -47,6 +47,7 @@
     ash::prefs::kAccessibilityAutoclickDelayMs,
     ash::prefs::kAccessibilityAutoclickEventType,
     ash::prefs::kAccessibilityAutoclickRevertToLeftClick,
+    ash::prefs::kAccessibilityAutoclickStabilizePosition,
     ash::prefs::kAccessibilityAutoclickMovementThreshold,
     ash::prefs::kAccessibilityCaretHighlightEnabled,
     ash::prefs::kAccessibilityCursorHighlightEnabled,
@@ -54,14 +55,17 @@
     ash::prefs::kAccessibilitySelectToSpeakEnabled,
     ash::prefs::kAccessibilitySwitchAccessEnabled,
     ash::prefs::kAccessibilityDictationEnabled,
-    ash::prefs::kDockedMagnifierEnabled, ash::prefs::kDockedMagnifierScale,
+    ash::prefs::kDockedMagnifierEnabled,
+    ash::prefs::kDockedMagnifierScale,
     ash::prefs::kDockedMagnifierAcceleratorDialogHasBeenAccepted,
     ash::prefs::kHighContrastAcceleratorDialogHasBeenAccepted,
     ash::prefs::kScreenMagnifierAcceleratorDialogHasBeenAccepted,
     ash::prefs::kShouldAlwaysShowAccessibilityMenu,
 #endif  // defined(OS_CHROMEOS)
 #if !defined(OS_ANDROID)
-    kAnimationPolicyAllowed, kAnimationPolicyOnce, kAnimationPolicyNone,
+    kAnimationPolicyAllowed,
+    kAnimationPolicyOnce,
+    kAnimationPolicyNone,
 #endif  // !defined(OS_ANDROID)
 #if BUILDFLAG(ENABLE_EXTENSIONS)
     prefs::kAnimationPolicy,
@@ -81,14 +85,19 @@
 
     // Metrics preferences are out of profile scope and are merged between
     // incognito and regular modes.
-    metrics::prefs::kInstallDate, metrics::prefs::kMetricsClientID,
-    metrics::prefs::kMetricsDefaultOptIn, metrics::prefs::kMetricsInitialLogs,
-    metrics::prefs::kMetricsLowEntropySource, metrics::prefs::kMetricsMachineId,
-    metrics::prefs::kMetricsOngoingLogs, metrics::prefs::kMetricsResetIds,
+    metrics::prefs::kInstallDate,
+    metrics::prefs::kMetricsClientID,
+    metrics::prefs::kMetricsDefaultOptIn,
+    metrics::prefs::kMetricsInitialLogs,
+    metrics::prefs::kMetricsLowEntropySource,
+    metrics::prefs::kMetricsMachineId,
+    metrics::prefs::kMetricsOngoingLogs,
+    metrics::prefs::kMetricsResetIds,
 
     metrics::prefs::kMetricsReportingEnabled,
     metrics::prefs::kMetricsReportingEnabledTimestamp,
-    metrics::prefs::kMetricsSessionID, metrics::prefs::kMetricsLastSeenPrefix,
+    metrics::prefs::kMetricsSessionID,
+    metrics::prefs::kMetricsLastSeenPrefix,
     metrics::prefs::kStabilityBreakpadRegistrationFail,
     metrics::prefs::kStabilityBreakpadRegistrationSuccess,
     metrics::prefs::kStabilityBrowserLastLiveTimeStamp,
@@ -123,8 +132,10 @@
     metrics::prefs::kStabilityVersionMismatchCount,
     metrics::prefs::kUninstallLaunchCount,
     metrics::prefs::kUninstallMetricsPageLoadCount,
-    metrics::prefs::kUninstallMetricsUptimeSec, metrics::prefs::kUkmCellDataUse,
-    metrics::prefs::kUmaCellDataUse, metrics::prefs::kUserCellDataUse,
+    metrics::prefs::kUninstallMetricsUptimeSec,
+    metrics::prefs::kUkmCellDataUse,
+    metrics::prefs::kUmaCellDataUse,
+    metrics::prefs::kUserCellDataUse,
 
 #if defined(OS_ANDROID)
     // Clipboard modification state is updated over all profiles.
@@ -134,21 +145,27 @@
     // Default browser bar's status is aggregated between regular and incognito
     // modes.
     prefs::kBrowserSuppressDefaultBrowserPrompt,
-    prefs::kDefaultBrowserLastDeclined, prefs::kDefaultBrowserSettingEnabled,
+    prefs::kDefaultBrowserLastDeclined,
+    prefs::kDefaultBrowserSettingEnabled,
     prefs::kResetCheckDefaultBrowser,
 
     // Devtools preferences are stored cross profiles as they are not storing
     // user data and just keep debugging environment settings.
-    prefs::kDevToolsAdbKey, prefs::kDevToolsAvailability,
-    prefs::kDevToolsDiscoverUsbDevicesEnabled, prefs::kDevToolsEditedFiles,
-    prefs::kDevToolsFileSystemPaths, prefs::kDevToolsPortForwardingEnabled,
+    prefs::kDevToolsAdbKey,
+    prefs::kDevToolsAvailability,
+    prefs::kDevToolsDiscoverUsbDevicesEnabled,
+    prefs::kDevToolsEditedFiles,
+    prefs::kDevToolsFileSystemPaths,
+    prefs::kDevToolsPortForwardingEnabled,
     prefs::kDevToolsPortForwardingDefaultSet,
-    prefs::kDevToolsPortForwardingConfig, prefs::kDevToolsPreferences,
+    prefs::kDevToolsPortForwardingConfig,
+    prefs::kDevToolsPreferences,
     prefs::kDevToolsDiscoverTCPTargetsEnabled,
     prefs::kDevToolsTCPDiscoveryConfig,
 
     // Google URL prefs don't store user data and just keep track of the URL.
-    prefs::kLastKnownGoogleURL, prefs::kLastPromptedGoogleURL,
+    prefs::kLastKnownGoogleURL,
+    prefs::kLastPromptedGoogleURL,
 
 #if defined(OS_WIN)
     // The total number of times that network profile warning is shown is
@@ -157,8 +174,10 @@
 #endif
 
     // Tab stats metrics are aggregated between regular and incognio mode.
-    prefs::kTabStatsTotalTabCountMax, prefs::kTabStatsMaxTabsPerWindow,
-    prefs::kTabStatsWindowCountMax, prefs::kTabStatsDailySample,
+    prefs::kTabStatsTotalTabCountMax,
+    prefs::kTabStatsMaxTabsPerWindow,
+    prefs::kTabStatsWindowCountMax,
+    prefs::kTabStatsDailySample,
 
 #if defined(OS_MACOSX)
     prefs::kShowFullscreenToolbar,
@@ -173,7 +192,8 @@
     // Rappor preferences are not used in incognito mode, but they are written
     // in startup if they don't exist. So if the startup would be in incognito,
     // they need to be persisted.
-    rappor::prefs::kRapporCohortSeed, rappor::prefs::kRapporSecret,
+    rappor::prefs::kRapporCohortSeed,
+    rappor::prefs::kRapporSecret,
 
     // Reading list preferences are common between incognito and regular mode.
     reading_list::prefs::kReadingListHasUnseenEntries,
@@ -181,7 +201,8 @@
     // Although UKMs are not collected in incognito, theses preferences may be
     // changed by UMA/Sync/Unity consent, and need to be the same between
     // incognito and regular modes.
-    ukm::prefs::kUkmClientId, ukm::prefs::kUkmPersistedLogs,
+    ukm::prefs::kUkmClientId,
+    ukm::prefs::kUkmPersistedLogs,
     ukm::prefs::kUkmSessionId,
 
     // Variations preferences maybe changed from incognito mode and should be
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index 9dfc98e..b723aa2 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -139,7 +139,10 @@
 }  // namespace
 
 OffTheRecordProfileImpl::OffTheRecordProfileImpl(Profile* real_profile)
-    : profile_(real_profile), start_time_(base::Time::Now()) {
+    : profile_(real_profile),
+      start_time_(base::Time::Now()),
+      key_(std::make_unique<ProfileKey>(profile_->GetPath(),
+                                        profile_->GetProfileKey())) {
   // Must happen before we ask for prefs as prefs needs the connection to the
   // service manager, which is set up in Initialize.
   BrowserContext::Initialize(this, profile_->GetPath());
@@ -149,8 +152,7 @@
       InProcessPrefServiceFactoryFactory::GetInstanceForContext(this)
           ->CreateDelegate());
 
-  key_ = std::make_unique<ProfileKey>(profile_->GetPath(), prefs_.get(),
-                                      profile_->GetProfileKey());
+  key_->SetPrefs(prefs_.get());
   SimpleKeyMap::GetInstance()->Associate(this, key_.get());
 
   // Register on BrowserContext.
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index a8014c8..1f6b70e 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -468,6 +468,7 @@
       io_data_(this),
       last_session_exit_type_(EXIT_NORMAL),
       start_time_(base::Time::Now()),
+      key_(std::make_unique<ProfileKey>(GetPath())),
       delegate_(delegate),
       reporting_permissions_checker_factory_(this),
       shared_cors_origin_access_list_(
@@ -583,7 +584,7 @@
     user_prefs::UserPrefs::Set(this, prefs_.get());
   }
 
-  key_ = std::make_unique<ProfileKey>(GetPath(), prefs_.get());
+  key_->SetPrefs(prefs_.get());
   SimpleKeyMap::GetInstance()->Associate(this, key_.get());
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/profiles/profile_key.cc b/chrome/browser/profiles/profile_key.cc
index fba157e..b225f2b 100644
--- a/chrome/browser/profiles/profile_key.cc
+++ b/chrome/browser/profiles/profile_key.cc
@@ -4,13 +4,23 @@
 
 #include "chrome/browser/profiles/profile_key.h"
 
-ProfileKey::ProfileKey(const base::FilePath& path,
-                       PrefService* prefs,
-                       ProfileKey* original_key)
-    : SimpleFactoryKey(path), prefs_(prefs), original_key_(original_key) {}
+#include "base/logging.h"
+
+ProfileKey::ProfileKey(const base::FilePath& path, ProfileKey* original_key)
+    : SimpleFactoryKey(path), prefs_(nullptr), original_key_(original_key) {}
 
 ProfileKey::~ProfileKey() = default;
 
+PrefService* ProfileKey::GetPrefs() {
+  DCHECK(prefs_);
+  return prefs_;
+}
+
+void ProfileKey::SetPrefs(PrefService* prefs) {
+  DCHECK(!prefs_);
+  prefs_ = prefs;
+}
+
 bool ProfileKey::IsOffTheRecord() const {
   return original_key_ != nullptr;
 }
diff --git a/chrome/browser/profiles/profile_key.h b/chrome/browser/profiles/profile_key.h
index 5622047..511b146 100644
--- a/chrome/browser/profiles/profile_key.h
+++ b/chrome/browser/profiles/profile_key.h
@@ -16,13 +16,13 @@
 class ProfileKey : public SimpleFactoryKey {
  public:
   ProfileKey(const base::FilePath& path,
-             PrefService* prefs,
              ProfileKey* original_key = nullptr);
   ~ProfileKey() override;
 
   // Profile-specific APIs needed in reduced mode:
   ProfileKey* GetOriginalKey() { return original_key_; }
-  PrefService* GetPrefs() { return prefs_; }
+  PrefService* GetPrefs();
+  void SetPrefs(PrefService* prefs);
 
   static ProfileKey* FromSimpleFactoryKey(SimpleFactoryKey* key);
 
diff --git a/chrome/browser/resource_coordinator/page_signal_receiver.cc b/chrome/browser/resource_coordinator/page_signal_receiver.cc
index 4d49e2c..5839457 100644
--- a/chrome/browser/resource_coordinator/page_signal_receiver.cc
+++ b/chrome/browser/resource_coordinator/page_signal_receiver.cc
@@ -22,12 +22,6 @@
                            &PageSignalObserver::OnPageAlmostIdle);
 }
 
-void PageSignalReceiver::NotifyRendererIsBloated(
-    const PageNavigationIdentity& page_navigation_id) {
-  NotifyObserversIfKnownCu(page_navigation_id,
-                           &PageSignalObserver::OnRendererIsBloated);
-}
-
 void PageSignalReceiver::SetExpectedTaskQueueingDuration(
     const PageNavigationIdentity& page_navigation_id,
     base::TimeDelta duration) {
diff --git a/chrome/browser/resource_coordinator/page_signal_receiver.h b/chrome/browser/resource_coordinator/page_signal_receiver.h
index 10cd522..2d1c654 100644
--- a/chrome/browser/resource_coordinator/page_signal_receiver.h
+++ b/chrome/browser/resource_coordinator/page_signal_receiver.h
@@ -35,9 +35,6 @@
   virtual void OnPageAlmostIdle(
       content::WebContents* web_contents,
       const PageNavigationIdentity& page_navigation_id) {}
-  virtual void OnRendererIsBloated(
-      content::WebContents* web_contents,
-      const PageNavigationIdentity& page_navigation_id) {}
   virtual void OnExpectedTaskQueueingDurationSet(
       content::WebContents* web_contents,
       const PageNavigationIdentity& page_navigation_id,
@@ -72,8 +69,6 @@
   // mojom::PageSignalReceiver implementation.
   void NotifyPageAlmostIdle(
       const PageNavigationIdentity& page_navigation_id) override;
-  void NotifyRendererIsBloated(
-      const PageNavigationIdentity& page_navigation_id) override;
   void SetExpectedTaskQueueingDuration(
       const PageNavigationIdentity& page_navigation_id,
       base::TimeDelta duration) override;
diff --git a/chrome/browser/resources/chromeos/camera/src/css/main.css b/chrome/browser/resources/chromeos/camera/src/css/main.css
index 1956347..6716e21 100644
--- a/chrome/browser/resources/chromeos/camera/src/css/main.css
+++ b/chrome/browser/resources/chromeos/camera/src/css/main.css
@@ -184,6 +184,12 @@
   transform: translateX(50%);
 }
 
+.horizontal-center-stripe {
+  left: 50%;
+  position: absolute;
+  transform: translateX(-50%);
+}
+
 .top-stripe.right-stripe {
   transform: translate(50%, -50%);
 }
@@ -192,6 +198,10 @@
   transform: translate(-50%, -50%);
 }
 
+.top-stripe.horizontal-center-stripe {
+  transform: translate(-50%, -50%);
+}
+
 .bottom-stripe.right-stripe {
   transform: translate(50%, 50%);
 }
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
index 38b6516..a31d243 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
@@ -223,17 +223,26 @@
       (async () => {
         if (!suspend) {
           for (const id of await this.options_.videoDeviceIds()) {
-            const modesAndConstraints =
-                await this.modes_.getConstraitsForModes(id);
-            this.modes_.updateModeSelectionUI(modesAndConstraints.map(([
-                                                                        m,
-                                                                      ]) => m));
-            for (const [mode, candidates] of modesAndConstraints) {
-              for (const constraints of candidates) {
+            let supportedModes = null;
+            for (const mode of this.modes_.getModeCandidates()) {
+              if (supportedModes && !supportedModes.includes(mode)) {
+                continue;
+              }
+              for (const constraints of this.modes_.getConstraitsCandidates(
+                       id, mode)) {
                 try {
                   const stream =
                       await navigator.mediaDevices.getUserMedia(constraints);
+                  if (!supportedModes) {
+                    supportedModes =
+                        await this.modes_.getSupportedModes(stream);
+                    if (!supportedModes.includes(mode)) {
+                      stream.getTracks()[0].stop();
+                      break;
+                    }
+                  }
                   await this.preview_.start(stream);
+                  await this.modes_.updateModeSelectionUI(supportedModes);
                   this.facingMode_ =
                       this.options_.updateValues(constraints, stream);
                   await this.modes_.updateMode(mode, stream);
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
index deb74e2..c445901 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
@@ -64,7 +64,7 @@
    * @type {Object<string, Object>}
    * @private
    */
-  this.allModes = {
+  this.allModes_ = {
     'video-mode': {
       captureFactory: () =>
           new cca.views.camera.Video(this.stream_, this.doSavePicture_),
@@ -89,23 +89,20 @@
     'portrait-mode': {
       captureFactory: () =>
           new cca.views.camera.Portrait(this.stream_, this.doSavePicture_),
-      isSupported: async function(deviceId) {
-        for (const constraints of this.deviceConstraints(deviceId)) {
-          try {
-            var stream = await navigator.mediaDevices.getUserMedia(constraints);
-            const imageCapture =
-                new cca.mojo.ImageCapture(stream.getVideoTracks()[0]);
-            const capabilities = await imageCapture.getPhotoCapabilities();
-            return capabilities.supportedEffects &&
-                capabilities.supportedEffects.includes(
-                    cros.mojom.Effect.PORTRAIT_MODE);
-          } finally {
-            if (stream) {
-              stream.getTracks()[0].stop();
-            }
-          }
+      isSupported: async (stream) => {
+        try {
+          const imageCapture =
+              new cca.mojo.ImageCapture(stream.getVideoTracks()[0]);
+          const capabilities = await imageCapture.getPhotoCapabilities();
+          return capabilities.supportedEffects &&
+              capabilities.supportedEffects.includes(
+                  cros.mojom.Effect.PORTRAIT_MODE);
+        } catch (e) {
+          // The mode is considered unsupported for given stream. This includes
+          // the case where underlying camera HAL is V1 causing mojo connection
+          // unable to work.
+          return false;
         }
-        return false;
       },
       deviceConstraints: cca.views.camera.Modes.photoConstraits,
       nextMode: 'video-mode',
@@ -139,7 +136,7 @@
  * @param {string} mode Mode to be toggled.
  */
 cca.views.camera.Modes.prototype.updateModeUI_ = function(mode) {
-  Object.keys(this.allModes).forEach((m) => cca.state.set(m, m == mode));
+  Object.keys(this.allModes_).forEach((m) => cca.state.set(m, m == mode));
   const element = document.querySelector(`.mode-item>input[data-mode=${mode}]`);
   element.checked = true;
   const wrapper = element.parentElement;
@@ -222,32 +219,50 @@
 };
 
 /**
- * Gets all the supported modes and their constraints-candidates pairs for given
- * deviceId.
- * @async
- * @param {?string} deviceId Id of updated video device.
- * @return {Array<[string, Array<Object>]>} Array of supported mode name and
- *     constraints-candidates pairs for given deviceId. Mode values in array
- *     start with current mode and follow predefined retry order.
+ * Gets all mode candidates. Desired trying sequence of candidate modes is
+ * reflected in the order of the returned array.
+ * @return {Array<string>} Mode candidates to be tried out.
  */
-cca.views.camera.Modes.prototype.getConstraitsForModes =
-    async function(deviceId) {
+cca.views.camera.Modes.prototype.getModeCandidates = function() {
   const tried = {};
   const results = [];
-  let mode = Object.keys(this.allModes).find(cca.state.get);
+  let mode = Object.keys(this.allModes_).find(cca.state.get);
   while (!tried[mode]) {
-    const m = this.allModes[mode];
     tried[mode] = true;
-    if (await m.isSupported(deviceId)) {
-      results.push([mode, m.deviceConstraints(deviceId)]);
-    }
-    mode = m.nextMode;
+    results.push(mode);
+    mode = this.allModes_[mode].nextMode;
   }
   return results;
 };
 
 /**
- * Updates mode selection UI according to input supported modes.
+ * Gets constraints-candidates for given mode and deviceId.
+ * @param {?string} deviceId Request video device id.
+ * @param {?string} mode Request mode.
+ * @return {Array<Object>} Constraints-candidates for given deviceId and mode.
+ */
+cca.views.camera.Modes.prototype.getConstraitsCandidates = function(
+    deviceId, mode) {
+  return this.allModes_[mode].deviceConstraints(deviceId);
+};
+
+/**
+ * Gets supported modes for video device of the given stream.
+ * @param {MediaStream} stream Stream of the video device.
+ * @return {Array<string>} Names of all supported mode for the video device.
+ */
+cca.views.camera.Modes.prototype.getSupportedModes = async function(stream) {
+  let supportedModes = [];
+  for (const [mode, obj] of Object.entries(this.allModes_)) {
+    if (await obj.isSupported(stream)) {
+      supportedModes.push(mode);
+    }
+  }
+  return supportedModes;
+};
+
+/**
+ * Updates mode selection UI according to given supported modes.
  * @param {Array<string>} supportedModes Supported mode names to be updated
  *     with.
  */
@@ -272,7 +287,7 @@
   }
   this.updateModeUI_(mode);
   this.stream_ = stream;
-  this.current = this.allModes[mode].captureFactory();
+  this.current = this.allModes_[mode].captureFactory();
 };
 
 /**
diff --git a/chrome/browser/resources/chromeos/camera/src/views/main.html b/chrome/browser/resources/chromeos/camera/src/views/main.html
index 61517a5..583004f 100644
--- a/chrome/browser/resources/chromeos/camera/src/views/main.html
+++ b/chrome/browser/resources/chromeos/camera/src/views/main.html
@@ -122,7 +122,7 @@
         <button id="gallery-enter" tabindex="0"
                 i18n-label="gallery_button" hidden></button>
       </div>
-      <div class="top-stripe" id="record-time" hidden>
+      <div class="top-stripe horizontal-center-stripe" id="record-time" hidden>
         <div class="icon"></div>
         <div id="record-time-msg"></div>
       </div>
diff --git a/chrome/browser/resources/management/management_ui.html b/chrome/browser/resources/management/management_ui.html
index 2f15e52..7d5cf31 100644
--- a/chrome/browser/resources/management/management_ui.html
+++ b/chrome/browser/resources/management/management_ui.html
@@ -200,7 +200,15 @@
 </if>
             <div>[[accountManagedInfo_.overview]]</div>
             <ul class="overview-messages" hidden="[[!accountManagedInfo_]]">
+<if expr="chromeos">
+              <li>[[accountManagedInfo_.setup]]
+                    <a href="$i18nRaw{managementAccountLearnMoreUrl}"
+                    target="_blank">$i18n{learnMore}</a>
+              </li>
+</if>
+<if expr="not chromeos">
               <li>[[accountManagedInfo_.setup]]</li>
+</if>
               <li>[[accountManagedInfo_.data]]</li>
             </ul>
           </section>
diff --git a/chrome/browser/resources/print_preview/new/BUILD.gn b/chrome/browser/resources/print_preview/new/BUILD.gn
index 784a6a6..4d87996 100644
--- a/chrome/browser/resources/print_preview/new/BUILD.gn
+++ b/chrome/browser/resources/print_preview/new/BUILD.gn
@@ -161,6 +161,7 @@
     deps = [
       ":input_behavior",
       ":settings_behavior",
+      ":state",
     ]
   }
 }
diff --git a/chrome/browser/resources/print_preview/new/pin_settings.html b/chrome/browser/resources/print_preview/new/pin_settings.html
index 0e70698..3159f43 100644
--- a/chrome/browser/resources/print_preview/new/pin_settings.html
+++ b/chrome/browser/resources/print_preview/new/pin_settings.html
@@ -7,6 +7,7 @@
 <link rel="import" href="print_preview_shared_css.html">
 <link rel="import" href="settings_behavior.html">
 <link rel="import" href="settings_section.html">
+<link rel="import" href="state.html">
 
 <dom-module id="print-preview-pin-settings">
   <template>
@@ -54,7 +55,7 @@
               maxlength="4" data-timeout-delay="250" aria-labelledby="pin"
               placeholder="$i18n{pinPlaceholder}" spellcheck="false"
               disabled$="[[inputDisabled_(pinEnabled_, inputValid_, disabled)]]"
-              error-message="$i18n{pinErrorMessage}" auto-validate>
+              error-message="$i18n{pinErrorMessage}" required auto-validate>
           </cr-input>
         </div>
       </print-preview-settings-section>
diff --git a/chrome/browser/resources/print_preview/new/pin_settings.js b/chrome/browser/resources/print_preview/new/pin_settings.js
index 0aed18d..10451467 100644
--- a/chrome/browser/resources/print_preview/new/pin_settings.js
+++ b/chrome/browser/resources/print_preview/new/pin_settings.js
@@ -8,6 +8,9 @@
   behaviors: [SettingsBehavior, print_preview_new.InputBehavior],
 
   properties: {
+    /** @type {!print_preview_new.State} */
+    state: Number,
+
     disabled: Boolean,
 
     /** @private {boolean} */
@@ -38,8 +41,10 @@
     },
   },
 
-  observers:
-      ['onSettingsChanged_(settings.pin.value, settings.pinValue.value)'],
+  observers: [
+    'onSettingsChanged_(settings.pin.value, settings.pinValue.value)',
+    'changePinValueSetting_(state)',
+  ],
 
   listeners: {
     'input-change': 'onInputChange_',
@@ -94,11 +99,27 @@
     this.pinEnabled_ = pinEnabled;
     const pinValue = this.getSetting('pinValue');
     this.inputString_ = /** @type {string} */ (pinValue.value);
+    this.resetString();
   },
 
   /** @private */
   onPinChange_: function() {
     this.setSetting('pin', this.$.pin.checked);
+    // We need to set validity of pinValue to true to return to READY state
+    // after unchecking the pin and to check the validity again after checking
+    // the pin.
+    if (!this.$.pin.checked) {
+      this.setSettingValid('pinValue', true);
+    } else {
+      this.changePinValueSetting_();
+    }
+  },
+
+  /**
+   * @private
+   */
+  onInputChanged_: function() {
+    this.changePinValueSetting_();
   },
 
   /**
@@ -106,14 +127,25 @@
    * input.
    * @private
    */
-  onInputChanged_: function() {
+  changePinValueSetting_: function() {
     if (this.settings === undefined) {
       return;
     }
+    // If the state is not READY and current pinValue is valid (so it's not the
+    // cause of the error) we need to wait until the state will be READY again.
+    // It's done because we don't permit multiple simultaneous validation errors
+    // in Print Preview and we also don't want to set the value when sticky
+    // settings may not yet have been set.
+    if (this.state != print_preview_new.State.READY &&
+        this.settings.pinValue.valid) {
+      return;
+    }
     this.inputValid_ = this.computeValid_();
     this.setSettingValid('pinValue', this.inputValid_);
 
-    if (this.inputValid_) {
+    // We allow to save the empty string as sticky setting value to give users
+    // the opportunity to unset their PIN in sticky settings.
+    if (this.inputValid_ || this.inputString_ == '') {
       this.setSetting('pinValue', this.inputString_);
     }
   },
@@ -126,6 +158,7 @@
   computeValid_: function() {
     // Make sure value updates first, in case inputString_ was updated by JS.
     this.$.pinValue.value = this.inputString_;
+    this.$.pinValue.validate();
     return !this.$.pinValue.invalid;
   },
 });
diff --git a/chrome/browser/resources/print_preview/new/print_preview_sidebar.html b/chrome/browser/resources/print_preview/new/print_preview_sidebar.html
index 179ce6e..3746a4a6 100644
--- a/chrome/browser/resources/print_preview/new/print_preview_sidebar.html
+++ b/chrome/browser/resources/print_preview/new/print_preview_sidebar.html
@@ -108,7 +108,7 @@
           available class="settings-section">
       </print-preview-destination-settings>
 <if expr="chromeos">
-      <print-preview-pin-settings settings="[[settings]]"
+      <print-preview-pin-settings state="[[state]]" settings="[[settings]]"
           disabled="[[controlsDisabled_]]"
           hidden$="[[!settings.pin.available]]" class="settings-section">
       </print-preview-pin-settings>
diff --git a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
index 253cd5c..395f0453 100644
--- a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
+++ b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
@@ -160,6 +160,13 @@
           disabled="[[!prefs.settings.a11y.autoclick.value]]">
       </settings-dropdown-menu>
     </div>
+    <div class="sub-item">
+      <settings-toggle-button class="continuation sub-item"
+        hidden$="[[!prefs.settings.a11y.autoclick.value]]"
+        pref="{{prefs.settings.a11y.autoclick_stabilize_position}}"
+        label="$i18n{autoclickStabilizeCursorPosition}">
+      </settings-toggle-button>
+    </div>
     <template is="dom-if" if="[[showExperimentalAutoclick_]]">
       <div class="sub-item">
         <settings-toggle-button class="continuation sub-item"
diff --git a/chrome/browser/resources/user_manager/create_profile.html b/chrome/browser/resources/user_manager/create_profile.html
index 110bafe..8dd7755 100644
--- a/chrome/browser/resources/user_manager/create_profile.html
+++ b/chrome/browser/resources/user_manager/create_profile.html
@@ -117,6 +117,7 @@
         max-height: 50vh;
         overflow-x: hidden;
         overflow-y: auto;
+        padding: 8px;
       }
     </style>
     <div id="message-container" visible$="[[isMessageVisble_]]">
diff --git a/chrome/browser/send_tab_to_self/desktop_notification_handler.cc b/chrome/browser/send_tab_to_self/desktop_notification_handler.cc
index 5cbea721..037c959 100644
--- a/chrome/browser/send_tab_to_self/desktop_notification_handler.cc
+++ b/chrome/browser/send_tab_to_self/desktop_notification_handler.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/guid.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/notifications/notification_display_service.h"
 #include "chrome/browser/notifications/notification_display_service_factory.h"
@@ -18,6 +17,7 @@
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "components/send_tab_to_self/send_tab_to_self_entry.h"
+#include "components/send_tab_to_self/send_tab_to_self_metrics.h"
 #include "components/send_tab_to_self/send_tab_to_self_model.h"
 #include "components/send_tab_to_self/send_tab_to_self_sync_service.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -31,30 +31,8 @@
 
 namespace {
 
-// Metrics for measuring notification interaction.
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-enum class SendTabToSelfNotification {
-  // The user opened a tab from a notification.
-  kOpened = 0,
-  // The user closed a notification.
-  kDismissed = 1,
-  // A notification was shown from a remotely added entry.
-  kShown = 2,
-  // A notification was dismissed remotely.
-  kDismissedRemotely = 3,
-  // Update kMaxValue when new enums are added.
-  kMaxValue = kDismissedRemotely,
-};
-
-const char kNotificationStatusHistogram[] = "SendTabToSelf.Notification";
-
 const char kDesktopNotificationSharedPrefix[] = "shared";
 
-void RecordNotificationHistogram(SendTabToSelfNotification status) {
-  UMA_HISTOGRAM_ENUMERATION(kNotificationStatusHistogram, status);
-}
-
 }  // namespace
 
 DesktopNotificationHandler::DesktopNotificationHandler(Profile* profile)
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index 58d8a1cf..03531cc 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -969,18 +969,12 @@
 }
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
-syncer::ModelTypeSet SupervisedUserService::GetForcedDataTypes() const {
+syncer::UserSelectableTypeSet SupervisedUserService::GetForcedTypes() const {
   if (!ProfileIsSupervised())
-    return syncer::ModelTypeSet();
+    return syncer::UserSelectableTypeSet();
 
-  syncer::ModelTypeSet result;
-  result.Put(syncer::EXTENSIONS);
-  result.Put(syncer::EXTENSION_SETTINGS);
-  result.Put(syncer::APPS);
-  result.Put(syncer::APP_SETTINGS);
-  result.Put(syncer::APP_LIST);
-  result.Put(syncer::ARC_PACKAGE);
-  return result;
+  return {syncer::UserSelectableType::kExtensions,
+          syncer::UserSelectableType::kApps};
 }
 
 bool SupervisedUserService::IsEncryptEverythingAllowed() const {
diff --git a/chrome/browser/supervised_user/supervised_user_service.h b/chrome/browser/supervised_user/supervised_user_service.h
index c4507df..d9b83f2 100644
--- a/chrome/browser/supervised_user/supervised_user_service.h
+++ b/chrome/browser/supervised_user/supervised_user_service.h
@@ -174,7 +174,7 @@
   void Shutdown() override;
 
   // SyncTypePreferenceProvider implementation:
-  syncer::ModelTypeSet GetForcedDataTypes() const override;
+  syncer::UserSelectableTypeSet GetForcedTypes() const override;
   bool IsEncryptEverythingAllowed() const override;
 
 #if !defined(OS_ANDROID)
diff --git a/chrome/browser/sync/OWNERS b/chrome/browser/sync/OWNERS
index 553b61e..bcfd98f 100644
--- a/chrome/browser/sync/OWNERS
+++ b/chrome/browser/sync/OWNERS
@@ -1,3 +1,5 @@
 file://components/sync/OWNERS
 
 per-file profile_sync_service_android*=nyquist@chromium.org
+
+# COMPONENT: Services>Sync
diff --git a/chrome/browser/sync/profile_sync_service_android.cc b/chrome/browser/sync/profile_sync_service_android.cc
index afa1a3b..17b6b27 100644
--- a/chrome/browser/sync/profile_sync_service_android.cc
+++ b/chrome/browser/sync/profile_sync_service_android.cc
@@ -27,6 +27,7 @@
 #include "components/signin/core/browser/account_info.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/sync/base/model_type.h"
+#include "components/sync/base/user_selectable_type.h"
 #include "components/sync/device_info/device_info.h"
 #include "components/sync/device_info/device_info_sync_service.h"
 #include "components/sync/device_info/device_info_tracker.h"
@@ -213,9 +214,15 @@
 ScopedJavaLocalRef<jintArray> ProfileSyncServiceAndroid::GetChosenDataTypes(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
-  syncer::ModelTypeSet types =
-      sync_service_->GetUserSettings()->GetChosenDataTypes();
-  return JNI_ProfileSyncService_ModelTypeSetToJavaIntArray(env, types);
+  // TODO(crbug/950874): introduce UserSelectableType in java code, then remove
+  // workaround here and in SetChosenDataTypes().
+  syncer::UserSelectableTypeSet types =
+      sync_service_->GetUserSettings()->GetSelectedTypes();
+  syncer::ModelTypeSet model_types;
+  for (syncer::UserSelectableType type : types) {
+    model_types.Put(syncer::UserSelectableTypeToCanonicalModelType(type));
+  }
+  return JNI_ProfileSyncService_ModelTypeSetToJavaIntArray(env, model_types);
 }
 
 ScopedJavaLocalRef<jintArray> ProfileSyncServiceAndroid::GetPreferredDataTypes(
@@ -233,11 +240,18 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   std::vector<int> types_vector;
   base::android::JavaIntArrayToIntVector(env, model_type_array, &types_vector);
-  syncer::ModelTypeSet types;
+  syncer::ModelTypeSet model_types;
   for (size_t i = 0; i < types_vector.size(); i++) {
-    types.Put(static_cast<syncer::ModelType>(types_vector[i]));
+    model_types.Put(static_cast<syncer::ModelType>(types_vector[i]));
   }
-  sync_service_->GetUserSettings()->SetChosenDataTypes(sync_everything, types);
+  syncer::UserSelectableTypeSet selected_types;
+  for (syncer::UserSelectableType type : syncer::UserSelectableTypeSet::All()) {
+    if (model_types.Has(syncer::UserSelectableTypeToCanonicalModelType(type))) {
+      selected_types.Put(type);
+    }
+  }
+  sync_service_->GetUserSettings()->SetSelectedTypes(sync_everything,
+                                                     selected_types);
 }
 
 jboolean ProfileSyncServiceAndroid::IsEncryptEverythingAllowed(
@@ -334,7 +348,7 @@
 
   base::Callback<void(std::unique_ptr<base::ListValue>)> native_callback =
       base::Bind(&NativeGetAllNodesCallback, java_callback);
-  sync_service_->GetAllNodes(native_callback);
+  sync_service_->GetAllNodesForDebugging(native_callback);
 }
 
 jint ProfileSyncServiceAndroid::GetAuthError(JNIEnv* env,
@@ -460,7 +474,7 @@
 jlong ProfileSyncServiceAndroid::GetLastSyncedTimeForTest(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
-  base::Time last_sync_time = sync_service_->GetLastSyncedTime();
+  base::Time last_sync_time = sync_service_->GetLastSyncedTimeForDebugging();
   return static_cast<jlong>(
       (last_sync_time - base::Time::UnixEpoch()).InMicroseconds());
 }
diff --git a/chrome/browser/sync/test/integration/enable_disable_test.cc b/chrome/browser/sync/test/integration/enable_disable_test.cc
index a99489b..5441a92 100644
--- a/chrome/browser/sync/test/integration/enable_disable_test.cc
+++ b/chrome/browser/sync/test/integration/enable_disable_test.cc
@@ -16,21 +16,23 @@
 #include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/sync/base/model_type.h"
+#include "components/sync/base/user_selectable_type.h"
 #include "components/sync/driver/profile_sync_service.h"
 #include "components/sync/driver/sync_driver_switches.h"
 #include "components/sync/driver/sync_user_settings_impl.h"
 #include "components/sync/test/fake_server/bookmark_entity_builder.h"
 #include "components/sync/test/fake_server/entity_builder_factory.h"
 
+namespace {
+
 using syncer::ModelType;
-using syncer::ModelTypeSet;
 using syncer::ModelTypeFromString;
+using syncer::ModelTypeSet;
 using syncer::ModelTypeToString;
 using syncer::ProxyTypes;
 using syncer::SyncPrefs;
-using syncer::UserSelectableTypes;
-
-namespace {
+using syncer::UserSelectableType;
+using syncer::UserSelectableTypeSet;
 
 const char kSyncedBookmarkURL[] = "http://www.mybookmark.com";
 // Non-utf8 string to make sure it gets handled well.
@@ -42,20 +44,16 @@
 // it will be disabled, because the other selectable type(s) could already be
 // enabling it. And vice versa for disabling.
 ModelTypeSet MultiGroupTypes(const ModelTypeSet& registered_types) {
-  const ModelTypeSet selectable_types = UserSelectableTypes();
   ModelTypeSet seen;
   ModelTypeSet multi;
-  // TODO(vitaliii): Do not use such short variable names here (and possibly
-  // elsewhere in the file).
-  for (ModelType st : selectable_types) {
+  for (UserSelectableType type : UserSelectableTypeSet::All()) {
     const ModelTypeSet grouped_types =
-        syncer::SyncUserSettingsImpl::ResolvePrefGroupsForTesting(
-            ModelTypeSet(st));
-    for (ModelType gt : grouped_types) {
-      if (seen.Has(gt)) {
-        multi.Put(gt);
+        syncer::SyncUserSettingsImpl::ResolvePreferredTypesForTesting({type});
+    for (ModelType grouped_type : grouped_types) {
+      if (seen.Has(grouped_type)) {
+        multi.Put(grouped_type);
       } else {
-        seen.Put(gt);
+        seen.Put(grouped_type);
       }
     }
   }
@@ -76,7 +74,7 @@
   bool ModelTypeExists(ModelType type) {
     base::RunLoop loop;
     std::unique_ptr<base::ListValue> all_nodes;
-    GetSyncService(0)->GetAllNodes(
+    GetSyncService(0)->GetAllNodesForDebugging(
         base::BindLambdaForTesting([&](std::unique_ptr<base::ListValue> nodes) {
           all_nodes = std::move(nodes);
           loop.Quit();
@@ -111,7 +109,7 @@
 
   int GetNumUpdatesDownloadedInLastCycle() {
     return GetSyncService(0)
-        ->GetLastCycleSnapshot()
+        ->GetLastCycleSnapshotForDebugging()
         .model_neutral_state()
         .num_updates_downloaded_total;
   }
@@ -122,19 +120,18 @@
     if (all_types_enabled) {
       ASSERT_TRUE(GetClient(0)->SetupSync());
     } else {
-      ASSERT_TRUE(GetClient(0)->SetupSyncNoWaitForCompletion(ModelTypeSet()));
+      ASSERT_TRUE(
+          GetClient(0)->SetupSyncNoWaitForCompletion(UserSelectableTypeSet()));
       ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
     }
 
     registered_types_ = GetSyncService(0)->GetRegisteredDataTypes();
-    selectable_types_ = UserSelectableTypes();
     multi_grouped_types_ = MultiGroupTypes(registered_types_);
   }
 
-  ModelTypeSet ResolveGroup(ModelType type) {
+  ModelTypeSet ResolveGroup(UserSelectableType type) {
     ModelTypeSet grouped_types =
-        syncer::SyncUserSettingsImpl::ResolvePrefGroupsForTesting(
-            ModelTypeSet(type));
+        syncer::SyncUserSettingsImpl::ResolvePreferredTypesForTesting({type});
     grouped_types.RetainAll(registered_types_);
     grouped_types.RemoveAll(ProxyTypes());
     return grouped_types;
@@ -145,7 +142,6 @@
   }
 
   ModelTypeSet registered_types_;
-  ModelTypeSet selectable_types_;
   ModelTypeSet multi_grouped_types_;
 
  private:
@@ -158,29 +154,30 @@
   // Setup sync with no enabled types.
   SetupTest(/*all_types_enabled=*/false);
 
-  for (ModelType st : selectable_types_) {
-    const ModelTypeSet grouped_types = ResolveGroup(st);
-    const ModelTypeSet single_grouped_types = WithoutMultiTypes(grouped_types);
-    for (ModelType sgt : single_grouped_types) {
-      ASSERT_FALSE(ModelTypeExists(sgt)) << " for " << ModelTypeToString(st);
+  for (UserSelectableType type : UserSelectableTypeSet::All()) {
+    const ModelTypeSet grouped_types = ResolveGroup(type);
+    for (ModelType single_grouped_type : WithoutMultiTypes(grouped_types)) {
+      ASSERT_FALSE(ModelTypeExists(single_grouped_type))
+          << " for " << GetUserSelectableTypeName(type);
     }
 
     base::HistogramTester histogram_tester;
-    EXPECT_TRUE(GetClient(0)->EnableSyncForDatatype(st));
+    EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
 
-    for (ModelType gt : grouped_types) {
-      EXPECT_TRUE(ModelTypeExists(gt)) << " for " << ModelTypeToString(st);
+    for (ModelType grouped_type : grouped_types) {
+      EXPECT_TRUE(ModelTypeExists(grouped_type))
+          << " for " << GetUserSelectableTypeName(type);
 
-      if (syncer::CommitOnlyTypes().Has(gt)) {
+      if (syncer::CommitOnlyTypes().Has(grouped_type)) {
         EXPECT_EQ(0, histogram_tester.GetBucketCount(
                          "Sync.PostedDataTypeGetUpdatesRequest",
-                         ModelTypeToHistogramInt(gt)))
-            << " for " << ModelTypeToString(gt);
+                         ModelTypeToHistogramInt(grouped_type)))
+            << " for " << ModelTypeToString(grouped_type);
       } else {
         EXPECT_NE(0, histogram_tester.GetBucketCount(
                          "Sync.PostedDataTypeGetUpdatesRequest",
-                         ModelTypeToHistogramInt(gt)))
-            << " for " << ModelTypeToString(gt);
+                         ModelTypeToHistogramInt(grouped_type)))
+            << " for " << ModelTypeToString(grouped_type);
       }
     }
   }
@@ -190,24 +187,26 @@
   // Setup sync with no disabled types.
   SetupTest(/*all_types_enabled=*/true);
 
-  for (ModelType st : selectable_types_) {
-    const ModelTypeSet grouped_types = ResolveGroup(st);
-    for (ModelType gt : grouped_types) {
-      ASSERT_TRUE(ModelTypeExists(gt)) << " for " << ModelTypeToString(st);
+  for (UserSelectableType type : UserSelectableTypeSet::All()) {
+    const ModelTypeSet grouped_types = ResolveGroup(type);
+    for (ModelType grouped_type : grouped_types) {
+      ASSERT_TRUE(ModelTypeExists(grouped_type))
+          << " for " << GetUserSelectableTypeName(type);
     }
 
-    EXPECT_TRUE(GetClient(0)->DisableSyncForDatatype(st));
+    EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
 
-    const ModelTypeSet single_grouped_types = WithoutMultiTypes(grouped_types);
-    for (ModelType sgt : single_grouped_types) {
-      EXPECT_FALSE(ModelTypeExists(sgt)) << " for " << ModelTypeToString(st);
+    for (ModelType single_grouped_type : WithoutMultiTypes(grouped_types)) {
+      EXPECT_FALSE(ModelTypeExists(single_grouped_type))
+          << " for " << GetUserSelectableTypeName(type);
     }
   }
 
   // Lastly make sure that all the multi grouped times are all gone, since we
   // did not check these after disabling inside the above loop.
-  for (ModelType mgt : multi_grouped_types_) {
-    EXPECT_FALSE(ModelTypeExists(mgt)) << " for " << ModelTypeToString(mgt);
+  for (ModelType multi_grouped_type : multi_grouped_types_) {
+    EXPECT_FALSE(ModelTypeExists(multi_grouped_type))
+        << " for " << ModelTypeToString(multi_grouped_type);
   }
 }
 
@@ -216,27 +215,30 @@
   // Setup sync with no enabled types.
   SetupTest(/*all_types_enabled=*/false);
 
-  for (ModelType st : selectable_types_) {
-    const ModelTypeSet grouped_types = ResolveGroup(st);
+  for (UserSelectableType type : UserSelectableTypeSet::All()) {
+    const ModelTypeSet grouped_types = ResolveGroup(type);
     const ModelTypeSet single_grouped_types = WithoutMultiTypes(grouped_types);
-    for (ModelType sgt : single_grouped_types) {
-      ASSERT_FALSE(ModelTypeExists(sgt)) << " for " << ModelTypeToString(st);
+    for (ModelType single_grouped_type : single_grouped_types) {
+      ASSERT_FALSE(ModelTypeExists(single_grouped_type))
+          << " for " << GetUserSelectableTypeName(type);
     }
 
     // Enable and then disable immediately afterwards, before the datatype has
     // had the chance to finish startup (which usually involves task posting).
-    EXPECT_TRUE(GetClient(0)->EnableSyncForDatatype(st));
-    EXPECT_TRUE(GetClient(0)->DisableSyncForDatatype(st));
+    EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
+    EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
 
-    for (ModelType sgt : single_grouped_types) {
-      EXPECT_FALSE(ModelTypeExists(sgt)) << " for " << ModelTypeToString(st);
+    for (ModelType single_grouped_type : single_grouped_types) {
+      EXPECT_FALSE(ModelTypeExists(single_grouped_type))
+          << " for " << GetUserSelectableTypeName(type);
     }
   }
 
   // Lastly make sure that all the multi grouped times are all gone, since we
   // did not check these after disabling inside the above loop.
-  for (ModelType mgt : multi_grouped_types_) {
-    EXPECT_FALSE(ModelTypeExists(mgt)) << " for " << ModelTypeToString(mgt);
+  for (ModelType multi_grouped_type : multi_grouped_types_) {
+    EXPECT_FALSE(ModelTypeExists(multi_grouped_type))
+        << " for " << ModelTypeToString(multi_grouped_type);
   }
 }
 
@@ -245,19 +247,21 @@
   // Setup sync with no disabled types.
   SetupTest(/*all_types_enabled=*/true);
 
-  for (ModelType st : selectable_types_) {
-    const ModelTypeSet grouped_types = ResolveGroup(st);
-    for (ModelType gt : grouped_types) {
-      ASSERT_TRUE(ModelTypeExists(gt)) << " for " << ModelTypeToString(st);
+  for (UserSelectableType type : UserSelectableTypeSet::All()) {
+    const ModelTypeSet grouped_types = ResolveGroup(type);
+    for (ModelType grouped_type : grouped_types) {
+      ASSERT_TRUE(ModelTypeExists(grouped_type))
+          << " for " << GetUserSelectableTypeName(type);
     }
 
     // Disable and then reenable immediately afterwards, before the datatype has
     // had the chance to stop fully (which usually involves task posting).
-    EXPECT_TRUE(GetClient(0)->DisableSyncForDatatype(st));
-    EXPECT_TRUE(GetClient(0)->EnableSyncForDatatype(st));
+    EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
+    EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
 
-    for (ModelType gt : grouped_types) {
-      EXPECT_TRUE(ModelTypeExists(gt)) << " for " << ModelTypeToString(st);
+    for (ModelType grouped_type : grouped_types) {
+      EXPECT_TRUE(ModelTypeExists(grouped_type))
+          << " for " << GetUserSelectableTypeName(type);
     }
   }
 }
@@ -267,21 +271,23 @@
   // Setup sync with no enabled types.
   SetupTest(/*all_types_enabled=*/false);
 
-  for (ModelType st : selectable_types_) {
-    const ModelTypeSet grouped_types = ResolveGroup(st);
-    const ModelTypeSet single_grouped_types = WithoutMultiTypes(grouped_types);
-    for (ModelType sgt : single_grouped_types) {
-      ASSERT_FALSE(ModelTypeExists(sgt)) << " for " << ModelTypeToString(st);
+  for (UserSelectableType type : UserSelectableTypeSet::All()) {
+    const ModelTypeSet single_grouped_types =
+        WithoutMultiTypes(ResolveGroup(type));
+    for (ModelType single_grouped_type : single_grouped_types) {
+      ASSERT_FALSE(ModelTypeExists(single_grouped_type))
+          << " for " << GetUserSelectableTypeName(type);
     }
 
     // Fast enable-disable-enable sequence, before the datatype has had the
     // chance to transition fully across states (usually involves task posting).
-    EXPECT_TRUE(GetClient(0)->EnableSyncForDatatype(st));
-    EXPECT_TRUE(GetClient(0)->DisableSyncForDatatype(st));
-    EXPECT_TRUE(GetClient(0)->EnableSyncForDatatype(st));
+    EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
+    EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
+    EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
 
-    for (ModelType sgt : single_grouped_types) {
-      EXPECT_TRUE(ModelTypeExists(sgt)) << " for " << ModelTypeToString(st);
+    for (ModelType single_grouped_type : single_grouped_types) {
+      EXPECT_TRUE(ModelTypeExists(single_grouped_type))
+          << " for " << GetUserSelectableTypeName(type);
     }
   }
 }
@@ -295,8 +301,11 @@
   GetClient(0)->EnableSyncForAllDatatypes();
   GetClient(0)->DisableSyncForAllDatatypes();
 
-  for (ModelType st : selectable_types_) {
-    EXPECT_FALSE(ModelTypeExists(st)) << " for " << ModelTypeToString(st);
+  for (UserSelectableType type : UserSelectableTypeSet::All()) {
+    for (ModelType grouped_type : ResolveGroup(type)) {
+      EXPECT_FALSE(ModelTypeExists(grouped_type))
+          << " for " << GetUserSelectableTypeName(type);
+    }
   }
 }
 
@@ -309,12 +318,11 @@
 
   EXPECT_TRUE(GetClient(0)->AwaitEngineInitialization());
 
-  // Proxy types don't really run.
-  const ModelTypeSet non_proxy_types =
-      Difference(selectable_types_, ProxyTypes());
-
-  for (ModelType type : non_proxy_types) {
-    EXPECT_TRUE(ModelTypeExists(type)) << " for " << ModelTypeToString(type);
+  for (UserSelectableType type : UserSelectableTypeSet::All()) {
+    for (ModelType model_type : ResolveGroup(type)) {
+      EXPECT_TRUE(ModelTypeExists(model_type))
+          << " for " << ModelTypeToString(model_type);
+    }
   }
 }
 
@@ -328,12 +336,11 @@
   GetClient(0)->DisableSyncForAllDatatypes();
   GetClient(0)->EnableSyncForAllDatatypes();
 
-  // Proxy types don't really run.
-  const ModelTypeSet non_proxy_types =
-      Difference(selectable_types_, ProxyTypes());
-
-  for (ModelType type : non_proxy_types) {
-    EXPECT_TRUE(ModelTypeExists(type)) << " for " << ModelTypeToString(type);
+  for (UserSelectableType type : UserSelectableTypeSet::All()) {
+    for (ModelType model_type : ResolveGroup(type)) {
+      EXPECT_TRUE(ModelTypeExists(model_type))
+          << " for " << ModelTypeToString(model_type);
+    }
   }
 }
 
diff --git a/chrome/browser/sync/test/integration/p2p_sync_refresher.cc b/chrome/browser/sync/test/integration/p2p_sync_refresher.cc
index a8e14e4..ad89e83 100644
--- a/chrome/browser/sync/test/integration/p2p_sync_refresher.cc
+++ b/chrome/browser/sync/test/integration/p2p_sync_refresher.cc
@@ -22,7 +22,8 @@
 }
 
 void P2PSyncRefresher::OnSyncCycleCompleted(syncer::SyncService* sync) {
-  const syncer::SyncCycleSnapshot& snap = sync_service_->GetLastCycleSnapshot();
+  const syncer::SyncCycleSnapshot& snap =
+      sync_service_->GetLastCycleSnapshotForDebugging();
   bool is_notifiable_commit =
       (snap.model_neutral_state().num_successful_commits > 0);
   if (is_notifiable_commit) {
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
index bf5400d..889bc96 100644
--- a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
+++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
@@ -194,8 +194,9 @@
 }
 
 bool ProfileSyncServiceHarness::SetupSync() {
-  bool result = SetupSyncNoWaitForCompletion(syncer::UserSelectableTypes()) &&
-                AwaitSyncSetupCompletion();
+  bool result =
+      SetupSyncNoWaitForCompletion(syncer::UserSelectableTypeSet::All()) &&
+      AwaitSyncSetupCompletion();
   if (!result) {
     LOG(ERROR) << profile_debug_name_ << ": SetupSync failed. Syncer status:\n"
                << GetServiceStatus();
@@ -206,29 +207,29 @@
 }
 
 bool ProfileSyncServiceHarness::SetupSyncNoWaitForCompletion(
-    syncer::ModelTypeSet synced_datatypes) {
-  return SetupSyncImpl(synced_datatypes, EncryptionSetupMode::kNoEncryption,
+    syncer::UserSelectableTypeSet selected_types) {
+  return SetupSyncImpl(selected_types, EncryptionSetupMode::kNoEncryption,
                        /*encryption_passphrase=*/base::nullopt);
 }
 
 bool ProfileSyncServiceHarness::
     SetupSyncWithEncryptionPassphraseNoWaitForCompletion(
-        syncer::ModelTypeSet synced_datatypes,
+        syncer::UserSelectableTypeSet selected_types,
         const std::string& passphrase) {
-  return SetupSyncImpl(synced_datatypes, EncryptionSetupMode::kEncryption,
+  return SetupSyncImpl(selected_types, EncryptionSetupMode::kEncryption,
                        passphrase);
 }
 
 bool ProfileSyncServiceHarness::
     SetupSyncWithDecryptionPassphraseNoWaitForCompletion(
-        syncer::ModelTypeSet synced_datatypes,
+        syncer::UserSelectableTypeSet selected_types,
         const std::string& passphrase) {
-  return SetupSyncImpl(synced_datatypes, EncryptionSetupMode::kDecryption,
+  return SetupSyncImpl(selected_types, EncryptionSetupMode::kDecryption,
                        passphrase);
 }
 
 bool ProfileSyncServiceHarness::SetupSyncImpl(
-    syncer::ModelTypeSet synced_datatypes,
+    syncer::UserSelectableTypeSet selected_types,
     EncryptionSetupMode encryption_mode,
     const base::Optional<std::string>& passphrase) {
   DCHECK(encryption_mode == EncryptionSetupMode::kNoEncryption ||
@@ -257,9 +258,10 @@
   }
   // Choose the datatypes to be synced. If all datatypes are to be synced,
   // set sync_everything to true; otherwise, set it to false.
-  bool sync_everything = (synced_datatypes == syncer::UserSelectableTypes());
-  service()->GetUserSettings()->SetChosenDataTypes(sync_everything,
-                                                   synced_datatypes);
+  bool sync_everything =
+      (selected_types == syncer::UserSelectableTypeSet::All());
+  service()->GetUserSettings()->SetSelectedTypes(sync_everything,
+                                                 selected_types);
 
   if (encryption_mode == EncryptionSetupMode::kEncryption) {
     service()->GetUserSettings()->SetEncryptionPassphrase(passphrase.value());
@@ -425,88 +427,73 @@
   return true;
 }
 
-bool ProfileSyncServiceHarness::EnableSyncForDatatype(
-    syncer::ModelType datatype) {
+bool ProfileSyncServiceHarness::EnableSyncForType(
+    syncer::UserSelectableType type) {
   DVLOG(1) << GetClientInfoString(
-      "EnableSyncForDatatype("
-      + std::string(syncer::ModelTypeToString(datatype)) + ")");
+      "EnableSyncForType(" +
+      std::string(syncer::GetUserSelectableTypeName(type)) + ")");
 
   if (!IsSyncEnabledByUser()) {
     bool result =
-        SetupSyncNoWaitForCompletion(syncer::ModelTypeSet(datatype)) &&
-        AwaitSyncSetupCompletion();
+        SetupSyncNoWaitForCompletion({type}) && AwaitSyncSetupCompletion();
     // If SetupSync() succeeded, then Sync must now be enabled.
     DCHECK(!result || IsSyncEnabledByUser());
     return result;
   }
 
   if (service() == nullptr) {
-    LOG(ERROR) << "EnableSyncForDatatype(): service() is null.";
+    LOG(ERROR) << "EnableSyncForType(): service() is null.";
     return false;
   }
 
-  if (!syncer::UserSelectableTypes().Has(datatype)) {
-    LOG(ERROR) << "Can only enable user selectable types, requested "
-               << syncer::ModelTypeToString(datatype);
-    return false;
-  }
-
-  syncer::ModelTypeSet synced_datatypes =
-      service()->GetUserSettings()->GetChosenDataTypes();
-  if (synced_datatypes.Has(datatype)) {
-    DVLOG(1) << "EnableSyncForDatatype(): Sync already enabled for datatype "
-             << syncer::ModelTypeToString(datatype)
-             << " on " << profile_debug_name_ << ".";
+  syncer::UserSelectableTypeSet selected_types =
+      service()->GetUserSettings()->GetSelectedTypes();
+  if (selected_types.Has(type)) {
+    DVLOG(1) << "EnableSyncForType(): Sync already enabled for type "
+             << syncer::GetUserSelectableTypeName(type) << " on "
+             << profile_debug_name_ << ".";
     return true;
   }
 
-  synced_datatypes.Put(syncer::ModelTypeFromInt(datatype));
-  synced_datatypes.RetainAll(syncer::UserSelectableTypes());
-  service()->GetUserSettings()->SetChosenDataTypes(false, synced_datatypes);
+  selected_types.Put(type);
+  service()->GetUserSettings()->SetSelectedTypes(false, selected_types);
   if (AwaitSyncSetupCompletion()) {
-    DVLOG(1) << "EnableSyncForDatatype(): Enabled sync for datatype "
-             << syncer::ModelTypeToString(datatype)
-             << " on " << profile_debug_name_ << ".";
+    DVLOG(1) << "EnableSyncForType(): Enabled sync for type "
+             << syncer::GetUserSelectableTypeName(type) << " on "
+             << profile_debug_name_ << ".";
     return true;
   }
 
-  DVLOG(0) << GetClientInfoString("EnableSyncForDatatype failed");
+  DVLOG(0) << GetClientInfoString("EnableSyncForType failed");
   return false;
 }
 
-bool ProfileSyncServiceHarness::DisableSyncForDatatype(
-    syncer::ModelType datatype) {
+bool ProfileSyncServiceHarness::DisableSyncForType(
+    syncer::UserSelectableType type) {
   DVLOG(1) << GetClientInfoString(
-      "DisableSyncForDatatype("
-      + std::string(syncer::ModelTypeToString(datatype)) + ")");
+      "DisableSyncForType(" +
+      std::string(syncer::GetUserSelectableTypeName(type)) + ")");
 
   if (service() == nullptr) {
-    LOG(ERROR) << "DisableSyncForDatatype(): service() is null.";
+    LOG(ERROR) << "DisableSyncForType(): service() is null.";
     return false;
   }
 
-  if (!syncer::UserSelectableTypes().Has(datatype)) {
-    LOG(ERROR) << "Can only disable user selectable types, requested "
-               << syncer::ModelTypeToString(datatype);
-    return false;
-  }
-
-  syncer::ModelTypeSet synced_datatypes =
-      service()->GetUserSettings()->GetChosenDataTypes();
-  if (!synced_datatypes.Has(datatype)) {
-    DVLOG(1) << "DisableSyncForDatatype(): Sync already disabled for datatype "
-             << syncer::ModelTypeToString(datatype)
-             << " on " << profile_debug_name_ << ".";
+  syncer::UserSelectableTypeSet selected_types =
+      service()->GetUserSettings()->GetSelectedTypes();
+  if (!selected_types.Has(type)) {
+    DVLOG(1) << "DisableSyncForType(): Sync already disabled for type "
+             << syncer::GetUserSelectableTypeName(type) << " on "
+             << profile_debug_name_ << ".";
     return true;
   }
 
-  synced_datatypes.RetainAll(syncer::UserSelectableTypes());
-  synced_datatypes.Remove(datatype);
-  service()->GetUserSettings()->SetChosenDataTypes(false, synced_datatypes);
+  selected_types.Remove(type);
+  service()->GetUserSettings()->SetSelectedTypes(false, selected_types);
   if (AwaitSyncSetupCompletion()) {
-    DVLOG(1) << "DisableSyncForDatatype(): Disabled sync for datatype "
-             << syncer::ModelTypeToString(datatype)
-             << " on " << profile_debug_name_ << ".";
+    DVLOG(1) << "DisableSyncForType(): Disabled sync for type "
+             << syncer::GetUserSelectableTypeName(type) << " on "
+             << profile_debug_name_ << ".";
     return true;
   }
 
@@ -529,8 +516,8 @@
     return false;
   }
 
-  service()->GetUserSettings()->SetChosenDataTypes(
-      true, syncer::UserSelectableTypes());
+  service()->GetUserSettings()->SetSelectedTypes(
+      true, syncer::UserSelectableTypeSet::All());
 
   if (AwaitSyncSetupCompletion()) {
     DVLOG(1) << "EnableSyncForAllDatatypes(): Enabled sync for all datatypes "
@@ -560,7 +547,7 @@
 SyncCycleSnapshot ProfileSyncServiceHarness::GetLastCycleSnapshot() const {
   DCHECK(service() != nullptr) << "Sync service has not yet been set up.";
   if (service()->IsSyncFeatureActive()) {
-    return service()->GetLastCycleSnapshot();
+    return service()->GetLastCycleSnapshotForDebugging();
   }
   return SyncCycleSnapshot();
 }
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.h b/chrome/browser/sync/test/integration/profile_sync_service_harness.h
index ec5fae6..6677080 100644
--- a/chrome/browser/sync/test/integration/profile_sync_service_harness.h
+++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.h
@@ -12,7 +12,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/optional.h"
-#include "components/sync/base/model_type.h"
+#include "components/sync/base/user_selectable_type.h"
 #include "components/sync/driver/profile_sync_service.h"
 #include "components/sync/engine/cycle/sync_cycle_snapshot.h"
 
@@ -63,23 +63,24 @@
   // to process changes.
   bool SetupSync();
 
-  // Enables and configures sync only for the given |synced_datatypes|.
+  // Enables and configures sync only for the given |selected_types|.
   // Does not wait for sync to be ready to process changes -- callers need to
   // ensure this by calling AwaitSyncSetupCompletion() or
   // AwaitSyncTransportActive().
   // Returns true on success.
-  bool SetupSyncNoWaitForCompletion(syncer::ModelTypeSet synced_datatypes);
+  bool SetupSyncNoWaitForCompletion(
+      syncer::UserSelectableTypeSet selected_types);
 
   // Same as SetupSyncNoWaitForCompletion(), but also sets the given encryption
   // passphrase during setup.
   bool SetupSyncWithEncryptionPassphraseNoWaitForCompletion(
-      syncer::ModelTypeSet synced_datatypes,
+      syncer::UserSelectableTypeSet selected_types,
       const std::string& passphrase);
 
   // Same as SetupSyncNoWaitForCompletion(), but also sets the given decryption
   // passphrase during setup.
   bool SetupSyncWithDecryptionPassphraseNoWaitForCompletion(
-      syncer::ModelTypeSet synced_datatypes,
+      syncer::UserSelectableTypeSet selected_types,
       const std::string& passphrase);
 
   // Signals that sync setup is complete, and that PSS may begin syncing.
@@ -145,11 +146,13 @@
   // Returns the debug name for this profile. Used for logging.
   const std::string& profile_debug_name() const { return profile_debug_name_; }
 
-  // Enables sync for a particular sync datatype. Returns true on success.
-  bool EnableSyncForDatatype(syncer::ModelType datatype);
+  // Enables sync for a particular selectable sync type (will enable sync for
+  // all corresponding datatypes). Returns true on success.
+  bool EnableSyncForType(syncer::UserSelectableType type);
 
-  // Disables sync for a particular sync datatype. Returns true on success.
-  bool DisableSyncForDatatype(syncer::ModelType datatype);
+  // Disables sync for a particular selectable sync type (will enable sync for
+  // all corresponding datatypes). Returns true on success.
+  bool DisableSyncForType(syncer::UserSelectableType type);
 
   // Enables sync for all sync datatypes. Returns true on success.
   bool EnableSyncForAllDatatypes();
@@ -180,7 +183,7 @@
   // |encryption_mode|.
   // If |encryption_mode| is kDecryption or kEncryption, |encryption_passphrase|
   // has to have a value which will be used to properly setup sync.
-  bool SetupSyncImpl(syncer::ModelTypeSet synced_datatypes,
+  bool SetupSyncImpl(syncer::UserSelectableTypeSet selected_types,
                      EncryptionSetupMode encryption_mode,
                      const base::Optional<std::string>& encryption_passphrase);
 
diff --git a/chrome/browser/sync/test/integration/quiesce_status_change_checker.cc b/chrome/browser/sync/test/integration/quiesce_status_change_checker.cc
index 3005938..a351fa1 100644
--- a/chrome/browser/sync/test/integration/quiesce_status_change_checker.cc
+++ b/chrome/browser/sync/test/integration/quiesce_status_change_checker.cc
@@ -56,8 +56,10 @@
       Intersection(service1->GetActiveDataTypes(),
                    service2->GetActiveDataTypes());
 
-  const syncer::SyncCycleSnapshot& snap1 = service1->GetLastCycleSnapshot();
-  const syncer::SyncCycleSnapshot& snap2 = service2->GetLastCycleSnapshot();
+  const syncer::SyncCycleSnapshot& snap1 =
+      service1->GetLastCycleSnapshotForDebugging();
+  const syncer::SyncCycleSnapshot& snap2 =
+      service2->GetLastCycleSnapshotForDebugging();
 
   for (syncer::ModelType type : common_types) {
     // Look up the progress markers.  Fail if either one is missing.
diff --git a/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc b/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
index 186a450..1953e6a 100644
--- a/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
@@ -172,8 +172,8 @@
   ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
 
   // Disable app sync.
-  sync_service->GetUserSettings()->SetChosenDataTypes(false,
-                                                      syncer::ModelTypeSet());
+  sync_service->GetUserSettings()->SetSelectedTypes(
+      false, syncer::UserSelectableTypeSet());
 
   // Change data when sync is off.
   for (const auto& app_id : app_ids) {
@@ -188,8 +188,8 @@
   EXPECT_FALSE(SyncItemsMatch(service, &compare_service));
 
   // Restore sync and sync data should override local changes.
-  sync_service->GetUserSettings()->SetChosenDataTypes(true,
-                                                      syncer::ModelTypeSet());
+  sync_service->GetUserSettings()->SetSelectedTypes(
+      true, syncer::UserSelectableTypeSet());
   EXPECT_TRUE(AppListSyncUpdateWaiter(service).Wait());
   EXPECT_TRUE(SyncItemsMatch(service, &compare_service));
 }
diff --git a/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc b/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc
index 8bace26..4d6505f 100644
--- a/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc
@@ -150,8 +150,8 @@
   // Make sure that some model type which is not allowed in transport-only mode
   // got activated.
   ASSERT_FALSE(AllowedTypesInStandaloneTransportMode().Has(syncer::BOOKMARKS));
-  ASSERT_TRUE(GetSyncService(0)->GetUserSettings()->GetChosenDataTypes().Has(
-      syncer::BOOKMARKS));
+  ASSERT_TRUE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has(
+      syncer::UserSelectableType::kBookmarks));
   EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::BOOKMARKS));
 }
 #endif  // !defined(OS_CHROMEOS)
diff --git a/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc b/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc
index 57c1655..550ed9e 100644
--- a/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc
@@ -178,7 +178,8 @@
       SessionSyncServiceFactory::GetForProfile(GetProfile(0));
 
   EXPECT_NE(nullptr, service->GetOpenTabsUIDelegate());
-  ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::PROXY_TABS));
+  ASSERT_TRUE(
+      GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kTabs));
   EXPECT_EQ(nullptr, service->GetOpenTabsUIDelegate());
 }
 
@@ -269,7 +270,8 @@
   // If the user disables history sync on settings, but still enables tab sync,
   // then sessions should be synced but the server should be able to tell the
   // difference based on active datatypes.
-  ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::TYPED_URLS));
+  ASSERT_TRUE(
+      GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kHistory));
   ASSERT_TRUE(CheckInitialState(0));
 
   ASSERT_TRUE(OpenTab(0, GURL(kURL1)));
diff --git a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
index bbb953a..53524bb 100644
--- a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
@@ -126,8 +126,8 @@
   // Make sure that some model type which is not allowed in transport-only mode
   // got activated.
   ASSERT_FALSE(AllowedTypesInStandaloneTransportMode().Has(syncer::BOOKMARKS));
-  ASSERT_TRUE(GetSyncService(0)->GetUserSettings()->GetChosenDataTypes().Has(
-      syncer::BOOKMARKS));
+  ASSERT_TRUE(GetSyncService(0)->GetUserSettings()->GetSelectedTypes().Has(
+      syncer::UserSelectableType::kBookmarks));
   EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::BOOKMARKS));
 
   // Turn off Sync-the-feature by user choice. The machinery should start up
diff --git a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc
index a47fe82..17d47bf 100644
--- a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc
@@ -200,13 +200,15 @@
   event_service->RecordUserEvent(test_event1);
 
   // Wait until the first events is committed before disabling sync,
-  // because disabled TYPED_URLS also disables user event sync, dropping all
+  // because disabled kHistory also disables user event sync, dropping all
   // uncommitted events.
   EXPECT_TRUE(ExpectUserEvents({test_event1}));
-  ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::TYPED_URLS));
+  ASSERT_TRUE(
+      GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kHistory));
 
   event_service->RecordUserEvent(test_event2);
-  ASSERT_TRUE(GetClient(0)->EnableSyncForDatatype(syncer::TYPED_URLS));
+  ASSERT_TRUE(
+      GetClient(0)->EnableSyncForType(syncer::UserSelectableType::kHistory));
   event_service->RecordUserEvent(test_event3);
 
   // No |test_event2| because it was recorded while history was disabled.
@@ -217,7 +219,8 @@
   const UserEventSpecifics specifics =
       CreateTestEvent(base::Time() + base::TimeDelta::FromMicroseconds(1));
   ASSERT_TRUE(SetupSync());
-  ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::PROXY_TABS));
+  ASSERT_TRUE(
+      GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kTabs));
   syncer::UserEventService* event_service =
       browser_sync::UserEventServiceFactory::GetForProfile(GetProfile(0));
 
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
index c1353fc..1836e9e 100644
--- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -128,7 +128,8 @@
   bool IsExitConditionSatisfied() override {
     // GetLastCycleSnapshot() returns by value, so make sure to capture it for
     // iterator use.
-    const syncer::SyncCycleSnapshot snap = service_->GetLastCycleSnapshot();
+    const syncer::SyncCycleSnapshot snap =
+        service_->GetLastCycleSnapshotForDebugging();
     const syncer::ProgressMarkerMap& progress_markers =
         snap.download_progress_markers();
     auto marker_it = progress_markers.find(syncer::AUTOFILL_WALLET_DATA);
@@ -152,7 +153,8 @@
       const syncer::ProfileSyncService* service) {
     // GetLastCycleSnapshot() returns by value, so make sure to capture it for
     // iterator use.
-    const syncer::SyncCycleSnapshot snap = service->GetLastCycleSnapshot();
+    const syncer::SyncCycleSnapshot snap =
+        service->GetLastCycleSnapshotForDebugging();
     const syncer::ProgressMarkerMap& progress_markers =
         snap.download_progress_markers();
     auto marker_it = progress_markers.find(syncer::AUTOFILL_WALLET_DATA);
@@ -1069,7 +1071,8 @@
   ASSERT_EQ(1U, GetServerAddressesMetadata(0).size());
 
   // Turn off autofill sync, the data & metadata should be gone.
-  ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::AUTOFILL));
+  ASSERT_TRUE(
+      GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kAutofill));
   WaitForOnPersonalDataChanged(/*should_trigger_refresh=*/false, pdm);
 
   EXPECT_EQ(0uL, pdm->GetServerProfiles().size());
@@ -1569,8 +1572,8 @@
   ASSERT_EQ(syncer::SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
             GetSyncService(0)->GetTransportState());
 
-  GetSyncService(0)->GetUserSettings()->SetChosenDataTypes(
-      /*sync_everything=*/false, syncer::ModelTypeSet(syncer::AUTOFILL));
+  GetSyncService(0)->GetUserSettings()->SetSelectedTypes(
+      /*sync_everything=*/false, {syncer::UserSelectableType::kAutofill});
 
   // Once the user finishes the setup, we can actually configure.
   setup_handle.reset();
diff --git a/chrome/browser/sync/test/integration/sync_errors_test.cc b/chrome/browser/sync/test/integration/sync_errors_test.cc
index bf1f998d..5b5ebc8 100644
--- a/chrome/browser/sync/test/integration/sync_errors_test.cc
+++ b/chrome/browser/sync/test/integration/sync_errors_test.cc
@@ -177,7 +177,8 @@
   // In contrast on auto start enabled platforms like chrome os we should be
   // able to set up even if the first sync while setting up fails.
   ASSERT_TRUE(SetupSync()) << "Setup sync failed";
-  ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::AUTOFILL));
+  ASSERT_TRUE(
+      GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kAutofill));
 #endif
 
   EXPECT_TRUE(GetFakeServer()->TriggerError(
@@ -190,7 +191,8 @@
 #else
   // Now enable a datatype, whose first 2 syncs would fail, but we should
   // recover and setup succesfully on the third attempt.
-  ASSERT_TRUE(GetClient(0)->EnableSyncForDatatype(syncer::AUTOFILL));
+  ASSERT_TRUE(
+      GetClient(0)->EnableSyncForType(syncer::UserSelectableType::kAutofill));
 #endif
 }
 
diff --git a/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc b/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
index d36d938..3fd52dc 100644
--- a/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
+++ b/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
@@ -42,14 +42,16 @@
  public:
   explicit ExponentialBackoffChecker(syncer::ProfileSyncService* pss)
       : SingleClientStatusChangeChecker(pss) {
-    const SyncCycleSnapshot& snap = service()->GetLastCycleSnapshot();
+    const SyncCycleSnapshot& snap =
+        service()->GetLastCycleSnapshotForDebugging();
     retry_verifier_.Initialize(snap);
   }
 
   // Checks if backoff is complete. Called repeatedly each time PSS notifies
   // observers of a state change.
   bool IsExitConditionSatisfied() override {
-    const SyncCycleSnapshot& snap = service()->GetLastCycleSnapshot();
+    const SyncCycleSnapshot& snap =
+        service()->GetLastCycleSnapshotForDebugging();
     retry_verifier_.VerifyRetryInterval(snap);
     return (retry_verifier_.done() && retry_verifier_.Succeeded());
   }
@@ -100,7 +102,7 @@
   // Verify that recovery time is short. Without canary job recovery time would
   // be more than 5 seconds.
   base::TimeDelta recovery_time =
-      GetSyncService(0)->GetLastCycleSnapshot().sync_start_time() -
+      GetSyncService(0)->GetLastCycleSnapshotForDebugging().sync_start_time() -
       network_notification_time;
   ASSERT_LE(recovery_time, base::TimeDelta::FromSeconds(2));
 }
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index 951fa3d..204949b 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -734,14 +734,17 @@
 
     if (encryption_passphrase_provided) {
       CHECK(client->SetupSyncWithEncryptionPassphraseNoWaitForCompletion(
-          syncer::UserSelectableTypes(), encryption_passphrase_it->second))
+          syncer::UserSelectableTypeSet::All(),
+          encryption_passphrase_it->second))
           << "SetupSync() failed.";
     } else if (decryption_passphrase_provided) {
       CHECK(client->SetupSyncWithDecryptionPassphraseNoWaitForCompletion(
-          syncer::UserSelectableTypes(), decryption_passphrase_it->second))
+          syncer::UserSelectableTypeSet::All(),
+          decryption_passphrase_it->second))
           << "SetupSync() failed.";
     } else {
-      CHECK(client->SetupSyncNoWaitForCompletion(syncer::UserSelectableTypes()))
+      CHECK(client->SetupSyncNoWaitForCompletion(
+          syncer::UserSelectableTypeSet::All()))
           << "SetupSync() failed.";
     }
     if (wait_for_completion) {
@@ -983,11 +986,11 @@
 
   // In order to kick off the encryption we have to reconfigure. Just grab the
   // currently synced types and use them.
-  syncer::ModelTypeSet synced_datatypes =
-      service->GetUserSettings()->GetChosenDataTypes();
-  bool sync_everything = (synced_datatypes == syncer::UserSelectableTypes());
-  service->GetUserSettings()->SetChosenDataTypes(sync_everything,
-                                                 synced_datatypes);
+  syncer::UserSelectableTypeSet selected_types =
+      service->GetUserSettings()->GetSelectedTypes();
+  bool sync_everything =
+      (selected_types == syncer::UserSelectableTypeSet::All());
+  service->GetUserSettings()->SetSelectedTypes(sync_everything, selected_types);
 
   return AwaitEncryptionComplete(index);
 }
diff --git a/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc b/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc
index d002a3d..88a79ad 100644
--- a/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc
@@ -314,14 +314,16 @@
   ASSERT_TRUE(SetupSync());
   ASSERT_TRUE(AllProfilesHaveSameAppList());
 
-  // Disable APP_LIST by disabling APPS since APP_LIST is in APPS groups.
-  ASSERT_TRUE(GetClient(1)->DisableSyncForDatatype(syncer::APPS));
+  // Disable APP_LIST by disabling kApps since APP_LIST is in kApps groups.
+  ASSERT_TRUE(
+      GetClient(1)->DisableSyncForType(syncer::UserSelectableType::kApps));
   InstallApp(GetProfile(0), 0);
   ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
   ASSERT_FALSE(AllProfilesHaveSameAppList());
 
-  // Enable APP_LIST by enabling APPS since APP_LIST is in APPS groups.
-  ASSERT_TRUE(GetClient(1)->EnableSyncForDatatype(syncer::APPS));
+  // Enable APP_LIST by enabling kApps since APP_LIST is in kApps groups.
+  ASSERT_TRUE(
+      GetClient(1)->EnableSyncForType(syncer::UserSelectableType::kApps));
   AwaitQuiescenceAndInstallAppsPendingForSync();
 
   ASSERT_TRUE(AllProfilesHaveSameAppList());
diff --git a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
index c6fef52..b10658e 100644
--- a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
@@ -1598,12 +1598,14 @@
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
   ASSERT_TRUE(AllModelsMatchVerifier());
 
-  ASSERT_TRUE(GetClient(1)->DisableSyncForDatatype(syncer::BOOKMARKS));
+  ASSERT_TRUE(
+      GetClient(1)->DisableSyncForType(syncer::UserSelectableType::kBookmarks));
   ASSERT_NE(nullptr, AddFolder(1, kGenericFolderName));
   ASSERT_TRUE(AwaitQuiescence());
   ASSERT_FALSE(AllModelsMatch());
 
-  ASSERT_TRUE(GetClient(1)->EnableSyncForDatatype(syncer::BOOKMARKS));
+  ASSERT_TRUE(
+      GetClient(1)->EnableSyncForType(syncer::UserSelectableType::kBookmarks));
   ASSERT_TRUE(BookmarksMatchChecker().Wait());
 }
 
@@ -1651,7 +1653,8 @@
 IN_PROC_BROWSER_TEST_P(TwoClientBookmarksSyncTestIncludingUssTests,
                        MC_DeleteBookmark) {
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
-  ASSERT_TRUE(GetClient(1)->DisableSyncForDatatype(syncer::BOOKMARKS));
+  ASSERT_TRUE(
+      GetClient(1)->DisableSyncForType(syncer::UserSelectableType::kBookmarks));
 
   const GURL bar_url("http://example.com/bar");
   const GURL other_url("http://example.com/other");
@@ -1672,7 +1675,8 @@
   ASSERT_FALSE(HasNodeWithURL(0, bar_url));
   ASSERT_TRUE(HasNodeWithURL(0, other_url));
 
-  ASSERT_TRUE(GetClient(1)->EnableSyncForDatatype(syncer::BOOKMARKS));
+  ASSERT_TRUE(
+      GetClient(1)->EnableSyncForType(syncer::UserSelectableType::kBookmarks));
   ASSERT_TRUE(AwaitQuiescence());
 
   ASSERT_FALSE(HasNodeWithURL(0, bar_url));
@@ -2258,11 +2262,13 @@
   // Disable bookmark syncing on the first client, add another bookmark,
   // re-enable bookmark syncing and see that the second bookmark reaches the
   // second client.
-  ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::BOOKMARKS));
+  ASSERT_TRUE(
+      GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kBookmarks));
   const std::string url_title_2 = "another happy little url";
   const GURL url_2("https://example.com/second");
   ASSERT_NE(nullptr, AddURL(0, GetBookmarkBarNode(0), 0, url_title_2, url_2));
-  ASSERT_TRUE(GetClient(0)->EnableSyncForDatatype(syncer::BOOKMARKS));
+  ASSERT_TRUE(
+      GetClient(0)->EnableSyncForType(syncer::UserSelectableType::kBookmarks));
   ASSERT_TRUE(BookmarksMatchChecker().Wait());
   ASSERT_EQ(initial_count + 2, CountAllBookmarks(0));
   ASSERT_EQ(initial_count + 2, CountAllBookmarks(1));
diff --git a/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc b/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
index bec63c3..fd47be2 100644
--- a/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
@@ -106,7 +106,7 @@
   // Set up a new sync client.
   ASSERT_TRUE(
       GetClient(kDecryptingClientId)
-          ->SetupSyncNoWaitForCompletion(syncer::UserSelectableTypes()));
+          ->SetupSyncNoWaitForCompletion(syncer::UserSelectableTypeSet::All()));
   ASSERT_TRUE(
       PassphraseRequiredChecker(GetSyncService(kDecryptingClientId)).Wait());
 
diff --git a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
index d092f99..ba88eca 100644
--- a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
@@ -306,7 +306,7 @@
   // When client 1 hits a passphrase required state, we can infer that
   // client 0's passphrase has been committed. to the server.
   ASSERT_TRUE(GetClient(1)->SetupSyncNoWaitForCompletion(
-      syncer::UserSelectableTypes()));
+      syncer::UserSelectableTypeSet::All()));
   ASSERT_TRUE(PassphraseRequiredChecker(GetSyncService(1)).Wait());
 
   // Get client 1 out of the passphrase required state.
diff --git a/chrome/browser/sync/test/integration/two_client_polling_sync_test.cc b/chrome/browser/sync/test/integration/two_client_polling_sync_test.cc
index 8924e7e..2f44aa6 100644
--- a/chrome/browser/sync/test/integration/two_client_polling_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_polling_sync_test.cc
@@ -81,8 +81,8 @@
   // clear its data even with KEEP_DATA, which means we'd always send a regular
   // GetUpdates request on starting Sync again, and so we'd have no need for a
   // poll.
-  GetClient(0)->DisableSyncForDatatype(syncer::AUTOFILL);
-  GetClient(1)->DisableSyncForDatatype(syncer::AUTOFILL);
+  GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kAutofill);
+  GetClient(1)->DisableSyncForType(syncer::UserSelectableType::kAutofill);
   // TODO(crbug.com/890737): Once AUTOFILL_WALLET_DATA gets properly disabled
   // based on the pref, we can just disable that instead of all of AUTOFILL:
   // autofill::prefs::SetPaymentsIntegrationEnabled(GetProfile(0)->GetPrefs(),
diff --git a/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc b/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc
index f8c7392..31c9057a 100644
--- a/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc
@@ -427,8 +427,8 @@
   const base::string16 kUrl2(ASCIIToUTF16("http://history2.google.com/"));
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
 
-  // Disable typed url sync for one client, leave it active for the other.
-  GetClient(0)->DisableSyncForDatatype(syncer::TYPED_URLS);
+  // Disable history sync for one client, leave it active for the other.
+  GetClient(0)->DisableSyncForType(syncer::UserSelectableType::kHistory);
 
   // Add one URL to non-syncing client, add a different URL to the other,
   // wait for sync cycle to complete. No data should be exchanged.
@@ -446,8 +446,8 @@
   ASSERT_EQ(1U, post_sync_urls.size());
   ASSERT_EQ(url2, post_sync_urls[0].url());
 
-  // Enable typed url sync, make both URLs are synced to each client.
-  GetClient(0)->EnableSyncForDatatype(syncer::TYPED_URLS);
+  // Enable history sync, make both URLs are synced to each client.
+  GetClient(0)->EnableSyncForType(syncer::UserSelectableType::kHistory);
 
   ASSERT_TRUE(ProfilesHaveSameTypedURLsChecker().Wait());
 }
diff --git a/chrome/browser/sync/test/integration/two_client_user_events_sync_test.cc b/chrome/browser/sync/test/integration/two_client_user_events_sync_test.cc
index d5f35d3..2e3e3843 100644
--- a/chrome/browser/sync/test/integration/two_client_user_events_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_user_events_sync_test.cc
@@ -75,7 +75,7 @@
   // Set up sync on the second client.
   ASSERT_TRUE(
       GetClient(kDecryptingClientId)
-          ->SetupSyncNoWaitForCompletion(syncer::UserSelectableTypes()));
+          ->SetupSyncNoWaitForCompletion(syncer::UserSelectableTypeSet::All()));
   // The second client asks the user to provide a password for decryption.
   ASSERT_TRUE(
       PassphraseRequiredChecker(GetSyncService(kDecryptingClientId)).Wait());
diff --git a/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc b/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc
index ad8ffb6..0b1edb5 100644
--- a/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc
@@ -211,7 +211,8 @@
       : SingleClientStatusChangeChecker(service) {}
 
   bool IsExitConditionSatisfied() override {
-    const syncer::SyncCycleSnapshot& snap = service()->GetLastCycleSnapshot();
+    const syncer::SyncCycleSnapshot& snap =
+        service()->GetLastCycleSnapshotForDebugging();
     return HasSyncerError(snap.model_neutral_state());
   }
 
@@ -310,9 +311,9 @@
   ASSERT_EQ(1U, model1->db().metadata_count());
 
   // Disable PREFERENCES.
-  syncer::ModelTypeSet types = syncer::UserSelectableTypes();
-  types.Remove(syncer::PREFERENCES);
-  GetSyncService(0)->GetUserSettings()->SetChosenDataTypes(false, types);
+  syncer::UserSelectableTypeSet types = syncer::UserSelectableTypeSet::All();
+  types.Remove(syncer::UserSelectableType::kPreferences);
+  GetSyncService(0)->GetUserSettings()->SetSelectedTypes(false, types);
 
   // Wait for it to take effect and remove the metadata.
   ASSERT_TRUE(MetadataAbsentChecker(model0, kKey1).Wait());
@@ -323,8 +324,8 @@
   ASSERT_EQ(1U, model1->db().metadata_count());
 
   // Re-enable PREFERENCES.
-  GetSyncService(0)->GetUserSettings()->SetChosenDataTypes(
-      true, syncer::UserSelectableTypes());
+  GetSyncService(0)->GetUserSettings()->SetSelectedTypes(
+      true, syncer::UserSelectableTypeSet::All());
 
   // Wait for metadata to be re-added.
   ASSERT_TRUE(MetadataPresentChecker(model0, kKey1).Wait());
diff --git a/chrome/browser/sync/test/integration/updated_progress_marker_checker.cc b/chrome/browser/sync/test/integration/updated_progress_marker_checker.cc
index 3d70c20..a561c53b 100644
--- a/chrome/browser/sync/test/integration/updated_progress_marker_checker.cc
+++ b/chrome/browser/sync/test/integration/updated_progress_marker_checker.cc
@@ -30,7 +30,8 @@
     return false;
   }
 
-  const syncer::SyncCycleSnapshot& snap = service()->GetLastCycleSnapshot();
+  const syncer::SyncCycleSnapshot& snap =
+      service()->GetLastCycleSnapshotForDebugging();
   // Assuming the lack of ongoing remote changes, the progress marker can be
   // considered updated when:
   // 1. Progress markers are non-empty (which discards the default value for
@@ -63,7 +64,8 @@
   }
 
   // Override |has_unsynced_items_| with the result of the sync cycle.
-  const syncer::SyncCycleSnapshot& snap = service()->GetLastCycleSnapshot();
+  const syncer::SyncCycleSnapshot& snap =
+      service()->GetLastCycleSnapshotForDebugging();
   has_unsynced_items_ = snap.has_remaining_local_changes();
   CheckExitCondition();
 }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index d01183f..535c4f0 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -70,8 +70,6 @@
     "autofill/popup_controller_common.h",
     "autofill/popup_view_common.cc",
     "autofill/popup_view_common.h",
-    "bloated_renderer/bloated_renderer_tab_helper.cc",
-    "bloated_renderer/bloated_renderer_tab_helper.h",
     "blocked_content/blocked_window_params.cc",
     "blocked_content/blocked_window_params.h",
     "blocked_content/list_item_position.cc",
diff --git a/chrome/browser/ui/android/passwords/password_generation_dialog_view_android.cc b/chrome/browser/ui/android/passwords/password_generation_dialog_view_android.cc
index 4e1253b..6aec626 100644
--- a/chrome/browser/ui/android/passwords/password_generation_dialog_view_android.cc
+++ b/chrome/browser/ui/android/passwords/password_generation_dialog_view_android.cc
@@ -6,10 +6,12 @@
 
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
+#include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/password_manager/password_generation_controller_impl.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/password_manager/core/browser/password_manager_driver.h"
 #include "components/strings/grit/components_strings.h"
 #include "jni/PasswordGenerationDialogBridge_jni.h"
 #include "ui/android/window_android.h"
@@ -32,7 +34,11 @@
       base::android::AttachCurrentThread(), java_object_);
 }
 
-void PasswordGenerationDialogViewAndroid::Show(base::string16& password) {
+void PasswordGenerationDialogViewAndroid::Show(
+    base::string16& password,
+    base::WeakPtr<password_manager::PasswordManagerDriver>
+        target_frame_driver) {
+  target_frame_driver_ = std::move(target_frame_driver);
   JNIEnv* env = base::android::AttachCurrentThread();
 
   base::string16 explanation_text =
@@ -48,7 +54,8 @@
     const base::android::JavaParamRef<jobject>& obj,
     const base::android::JavaParamRef<jstring>& password) {
   controller_->GeneratedPasswordAccepted(
-      base::android::ConvertJavaStringToUTF16(env, password));
+      base::android::ConvertJavaStringToUTF16(env, password),
+      std::move(target_frame_driver_));
 }
 
 void PasswordGenerationDialogViewAndroid::PasswordRejected(
diff --git a/chrome/browser/ui/android/passwords/password_generation_dialog_view_android.h b/chrome/browser/ui/android/passwords/password_generation_dialog_view_android.h
index 1335e7c..21e62e0 100644
--- a/chrome/browser/ui/android/passwords/password_generation_dialog_view_android.h
+++ b/chrome/browser/ui/android/passwords/password_generation_dialog_view_android.h
@@ -26,7 +26,9 @@
   ~PasswordGenerationDialogViewAndroid() override;
 
   // Called to show the dialog. |password| is the generated password.
-  void Show(base::string16& password) override;
+  void Show(base::string16& password,
+            base::WeakPtr<password_manager::PasswordManagerDriver>
+                target_frame_driver) override;
 
   // Called from Java via JNI.
   void PasswordAccepted(JNIEnv* env,
@@ -44,6 +46,10 @@
   // The corresponding java object.
   base::android::ScopedJavaGlobalRef<jobject> java_object_;
 
+  // The driver corresponding to the frame for which the generation request was
+  // made. Used to ensure that the accepted password message is sent back to the
+  // same frame.
+  base::WeakPtr<password_manager::PasswordManagerDriver> target_frame_driver_;
   DISALLOW_COPY_AND_ASSIGN(PasswordGenerationDialogViewAndroid);
 };
 
diff --git a/chrome/browser/ui/bloated_renderer/OWNERS b/chrome/browser/ui/bloated_renderer/OWNERS
deleted file mode 100644
index 51f6060..0000000
--- a/chrome/browser/ui/bloated_renderer/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-hpayer@chromium.org
-ulan@chromium.org
-
-# COMPONENT: Blink>JavaScript
diff --git a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.cc b/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.cc
deleted file mode 100644
index 273ad22..0000000
--- a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/browser/resource_coordinator/utils.h"
-#include "chrome/grit/generated_resources.h"
-#include "components/infobars/core/simple_alert_infobar_delegate.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/page_importance_signals.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace {
-
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-enum class BloatedRendererHandlingInBrowser {
-  kReloaded = 0,
-  kCannotReload = 1,
-  kCannotShutdown = 2,
-  kMaxValue = kCannotShutdown
-};
-
-void RecordBloatedRendererHandling(BloatedRendererHandlingInBrowser handling) {
-  UMA_HISTOGRAM_ENUMERATION("BloatedRenderer.HandlingInBrowser", handling);
-}
-
-}  // anonymous namespace
-
-BloatedRendererTabHelper::BloatedRendererTabHelper(
-    content::WebContents* contents)
-    : content::WebContentsObserver(contents) {
-  if (auto* page_signal_receiver =
-          resource_coordinator::GetPageSignalReceiver())
-    page_signal_receiver->AddObserver(this);
-}
-
-void BloatedRendererTabHelper::DidStartNavigation(
-    content::NavigationHandle* navigation_handle) {
-  if (state_ == State::kRequestingReload) {
-    saved_navigation_id_ = navigation_handle->GetNavigationId();
-    state_ = State::kStartedNavigation;
-  }
-}
-
-void BloatedRendererTabHelper::DidFinishNavigation(
-    content::NavigationHandle* navigation_handle) {
-  if (state_ == State::kStartedNavigation &&
-      saved_navigation_id_ == navigation_handle->GetNavigationId()) {
-    ShowInfoBar(InfoBarService::FromWebContents(web_contents()));
-    state_ = State::kInactive;
-    saved_navigation_id_ = 0;
-  }
-}
-
-void BloatedRendererTabHelper::WebContentsDestroyed() {
-  if (auto* page_signal_receiver =
-          resource_coordinator::GetPageSignalReceiver())
-    page_signal_receiver->RemoveObserver(this);
-}
-
-void BloatedRendererTabHelper::ShowInfoBar(InfoBarService* infobar_service) {
-  if (!infobar_service) {
-    // No infobar service in unit-tests.
-    return;
-  }
-  const bool auto_expire_on_navigation = true;
-  SimpleAlertInfoBarDelegate::Create(
-      infobar_service,
-      infobars::InfoBarDelegate::BLOATED_RENDERER_INFOBAR_DELEGATE, nullptr,
-      l10n_util::GetStringUTF16(IDS_BROWSER_BLOATED_RENDERER_INFOBAR),
-      auto_expire_on_navigation);
-}
-
-bool BloatedRendererTabHelper::CanReloadBloatedTab() {
-  if (web_contents()->IsCrashed())
-    return false;
-
-  // Do not reload tabs that don't have a valid URL (most probably they have
-  // just been opened and discarding them would lose the URL).
-  if (!web_contents()->GetLastCommittedURL().is_valid() ||
-      web_contents()->GetLastCommittedURL().is_empty()) {
-    return false;
-  }
-
-  // Do not reload tabs in which the user has entered text in a form.
-  if (web_contents()->GetPageImportanceSignals().had_form_interaction)
-    return false;
-
-  // Do not reload if no entry was committed.
-  content::NavigationEntry* committed_entry =
-      web_contents()->GetController().GetLastCommittedEntry();
-  if (!committed_entry)
-    return false;
-
-  // Do not reload if the visible entry does not match the last committed entry.
-  // This means that the entry is either transient or pending.
-  content::NavigationEntry* visible_entry =
-      web_contents()->GetController().GetVisibleEntry();
-  if (visible_entry != committed_entry)
-    return false;
-
-  // Do not reload if the last committed entry has post data.
-  if (committed_entry->GetHasPostData())
-    return false;
-
-  return true;
-}
-
-void BloatedRendererTabHelper::OnRendererIsBloated(
-    content::WebContents* bloated_web_contents,
-    const resource_coordinator::PageNavigationIdentity& page_navigation_id) {
-  if (!base::FeatureList::IsEnabled(features::kBloatedRendererDetection)) {
-    return;
-  }
-  if (web_contents() != bloated_web_contents) {
-    // Ignore if the notification is about a different tab.
-    return;
-  }
-  auto* page_signal_receiver = resource_coordinator::GetPageSignalReceiver();
-  DCHECK_NE(nullptr, page_signal_receiver);
-  if (page_navigation_id.navigation_id !=
-      page_signal_receiver->GetNavigationIDForWebContents(web_contents())) {
-    // Ignore if the notification is pursuant to an earlier navigation.
-    return;
-  }
-
-  if (CanReloadBloatedTab()) {
-    const bool check_for_repost = true;
-    // Clear the state and the saved navigation id.
-    state_ = State::kRequestingReload;
-    saved_navigation_id_ = 0;
-    web_contents()->GetController().Reload(content::ReloadType::NORMAL,
-                                           check_for_repost);
-    RecordBloatedRendererHandling(BloatedRendererHandlingInBrowser::kReloaded);
-  } else {
-    RecordBloatedRendererHandling(
-        BloatedRendererHandlingInBrowser::kCannotReload);
-  }
-}
-
-WEB_CONTENTS_USER_DATA_KEY_IMPL(BloatedRendererTabHelper)
diff --git a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.h b/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.h
deleted file mode 100644
index 33468cf..0000000
--- a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_BLOATED_RENDERER_BLOATED_RENDERER_TAB_HELPER_H_
-#define CHROME_BROWSER_UI_BLOATED_RENDERER_BLOATED_RENDERER_TAB_HELPER_H_
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "chrome/browser/resource_coordinator/page_signal_receiver.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/web_contents_user_data.h"
-
-class InfoBarService;
-
-// This tab helper observes the OnRendererIsBloated event for its
-// WebContents. Upon receiving the event it reloads the bloated tab if
-// possible and activates the logic to show an infobar on the
-// subsequent DidFinishNavigation event.
-//
-// Note that we need to show the infobar after NavigationEntryCommitted
-// because the infobar service removes existing infobars there.
-class BloatedRendererTabHelper
-    : public content::WebContentsObserver,
-      public content::WebContentsUserData<BloatedRendererTabHelper>,
-      public resource_coordinator::PageSignalObserver {
- public:
-  ~BloatedRendererTabHelper() override = default;
-
-  // content::WebContentsObserver:
-  void DidStartNavigation(
-      content::NavigationHandle* navigation_handle) override;
-  void DidFinishNavigation(
-      content::NavigationHandle* navigation_handle) override;
-  void WebContentsDestroyed() override;
-
-  // resource_coordinator::PageSignalObserver:
-  void OnRendererIsBloated(content::WebContents* web_contents,
-                           const resource_coordinator::PageNavigationIdentity&
-                               page_navigation_id) override;
-
-  static void ShowInfoBar(InfoBarService* infobar_service);
-
- private:
-  friend class content::WebContentsUserData<BloatedRendererTabHelper>;
-  FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest, DetectReload);
-  FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest,
-                           IgnoreUnrelatedNavigation);
-  FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest, CanReloadBloatedTab);
-  FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest,
-                           CannotReloadBloatedTabCrashed);
-  FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest,
-                           CannotReloadBloatedTabInvalidURL);
-  FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest,
-                           CannotReloadBloatedTabPendingUserInteraction);
-  FRIEND_TEST_ALL_PREFIXES(BloatedRendererTabHelperTest,
-                           CannotReloadBloatedTabWithPostData);
-
-  enum class State { kInactive, kRequestingReload, kStartedNavigation };
-
-  explicit BloatedRendererTabHelper(content::WebContents* contents);
-
-  bool CanReloadBloatedTab();
-
-  // The state transitions as follows:
-  // - kInactive is the initial state.
-  //
-  // - any state => kRequestingReload transition happens in
-  //   OnRendererIsBloated before invoking NavigationController::Reload.
-  //
-  // - kRequestingReload => kStartedNavigation transition happens in
-  //   NavigationController::Reload when it invokes DidStartNavigation.
-  //
-  // - kStartedNavigation => kInactive transitions happens in
-  //   DidFinishNavigation.
-  State state_ = State::kInactive;
-
-  // The navigation id is saved on DidStartNavigation event when the state is
-  // kRequestingReload. The infobar is shown on the subsequent
-  // DidFinishNavigation only if its navigation id matches the saved id. This
-  // ensures that the infobar is shown only for the reload that was requested
-  // in OnRendererIsBloated event.
-  int64_t saved_navigation_id_ = 0;
-
-  WEB_CONTENTS_USER_DATA_KEY_DECL();
-
-  DISALLOW_COPY_AND_ASSIGN(BloatedRendererTabHelper);
-};
-
-#endif  // CHROME_BROWSER_UI_BLOATED_RENDERER_BLOATED_RENDERER_TAB_HELPER_H_
diff --git a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper_browsertest.cc b/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper_browsertest.cc
deleted file mode 100644
index 14675f3..0000000
--- a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper_browsertest.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.h"
-
-#include "base/test/scoped_feature_list.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/browser/resource_coordinator/utils.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/common/content_features.h"
-#include "content/public/test/test_navigation_observer.h"
-#include "content/public/test/test_utils.h"
-
-using BloatedRendererTabHelperBrowserTest = InProcessBrowserTest;
-
-IN_PROC_BROWSER_TEST_F(BloatedRendererTabHelperBrowserTest, ReloadBloatedTab) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(features::kBloatedRendererDetection);
-  content::WindowedNotificationObserver load(
-      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
-      content::NotificationService::AllSources());
-  content::OpenURLParams url(
-      GURL(chrome::kChromeUIAboutURL), content::Referrer(),
-      WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false);
-  browser()->OpenURL(url);
-  load.Wait();
-
-  content::WindowedNotificationObserver reload(
-      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
-      content::NotificationService::AllSources());
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetWebContentsAt(0);
-  InfoBarService* infobar_service =
-      InfoBarService::FromWebContents(web_contents);
-  EXPECT_EQ(0u, infobar_service->infobar_count());
-
-  auto* page_signal_receiver = resource_coordinator::GetPageSignalReceiver();
-  resource_coordinator::PageNavigationIdentity page_id;
-  page_id.navigation_id =
-      page_signal_receiver->GetNavigationIDForWebContents(web_contents);
-  BloatedRendererTabHelper::FromWebContents(web_contents)
-      ->OnRendererIsBloated(web_contents, page_id);
-  reload.Wait();
-  EXPECT_EQ(1u, infobar_service->infobar_count());
-}
diff --git a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper_unittest.cc b/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper_unittest.cc
deleted file mode 100644
index ae84766..0000000
--- a/chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper_unittest.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.h"
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/common/page_importance_signals.h"
-#include "content/public/test/mock_navigation_handle.h"
-#include "content/public/test/web_contents_tester.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class BloatedRendererTabHelperTest : public ChromeRenderViewHostTestHarness {
- protected:
-  void SetUp() override {
-    ChromeRenderViewHostTestHarness::SetUp();
-    BloatedRendererTabHelper::CreateForWebContents(web_contents());
-    tab_helper_ = BloatedRendererTabHelper::FromWebContents(web_contents());
-    web_contents_tester_ = content::WebContentsTester::For(web_contents());
-    web_contents_tester_->SetLastCommittedURL(GURL("https://test.test"));
-  }
-  BloatedRendererTabHelper* tab_helper_;
-  content::WebContentsTester* web_contents_tester_;
-};
-
-TEST_F(BloatedRendererTabHelperTest, DetectReload) {
-  EXPECT_EQ(BloatedRendererTabHelper::State::kInactive, tab_helper_->state_);
-  tab_helper_->state_ = BloatedRendererTabHelper::State::kRequestingReload;
-  content::MockNavigationHandle reload_navigation;
-  tab_helper_->DidStartNavigation(&reload_navigation);
-  EXPECT_EQ(BloatedRendererTabHelper::State::kStartedNavigation,
-            tab_helper_->state_);
-  EXPECT_EQ(reload_navigation.GetNavigationId(),
-            tab_helper_->saved_navigation_id_);
-  tab_helper_->DidFinishNavigation(&reload_navigation);
-  EXPECT_EQ(BloatedRendererTabHelper::State::kInactive, tab_helper_->state_);
-}
-
-TEST_F(BloatedRendererTabHelperTest, IgnoreUnrelatedNavigation) {
-  EXPECT_EQ(BloatedRendererTabHelper::State::kInactive, tab_helper_->state_);
-  tab_helper_->state_ = BloatedRendererTabHelper::State::kRequestingReload;
-  content::MockNavigationHandle reload_navigation;
-  tab_helper_->DidStartNavigation(&reload_navigation);
-  EXPECT_EQ(BloatedRendererTabHelper::State::kStartedNavigation,
-            tab_helper_->state_);
-  EXPECT_EQ(reload_navigation.GetNavigationId(),
-            tab_helper_->saved_navigation_id_);
-  content::MockNavigationHandle unrelated_navigation;
-  tab_helper_->DidFinishNavigation(&unrelated_navigation);
-  EXPECT_EQ(BloatedRendererTabHelper::State::kStartedNavigation,
-            tab_helper_->state_);
-  EXPECT_EQ(reload_navigation.GetNavigationId(),
-            tab_helper_->saved_navigation_id_);
-}
-
-TEST_F(BloatedRendererTabHelperTest, CanReloadBloatedTab) {
-  web_contents_tester_->NavigateAndCommit(GURL("https://test.test"));
-  EXPECT_TRUE(tab_helper_->CanReloadBloatedTab());
-}
-
-TEST_F(BloatedRendererTabHelperTest, CannotReloadBloatedTabCrashed) {
-  web_contents()->SetIsCrashed(base::TERMINATION_STATUS_PROCESS_CRASHED, 0);
-
-  EXPECT_FALSE(tab_helper_->CanReloadBloatedTab());
-}
-
-TEST_F(BloatedRendererTabHelperTest, CannotReloadBloatedTabInvalidURL) {
-  web_contents_tester_->SetLastCommittedURL(GURL("invalid :)"));
-
-  EXPECT_FALSE(tab_helper_->CanReloadBloatedTab());
-}
-
-TEST_F(BloatedRendererTabHelperTest, CannotReloadBloatedTabWithPostData) {
-  web_contents_tester_->NavigateAndCommit(GURL("https://test.test"));
-  web_contents()->GetController().GetLastCommittedEntry()->SetHasPostData(true);
-
-  EXPECT_FALSE(tab_helper_->CanReloadBloatedTab());
-}
-
-TEST_F(BloatedRendererTabHelperTest,
-       CannotReloadBloatedTabPendingUserInteraction) {
-  content::PageImportanceSignals signals;
-  signals.had_form_interaction = true;
-  web_contents_tester_->SetPageImportanceSignals(signals);
-  EXPECT_FALSE(tab_helper_->CanReloadBloatedTab());
-}
diff --git a/chrome/browser/ui/cocoa/applescript/OWNERS b/chrome/browser/ui/cocoa/applescript/OWNERS
deleted file mode 100644
index a4e5ade..0000000
--- a/chrome/browser/ui/cocoa/applescript/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-pinkerton@chromium.org
-spqchan@chromium.org
\ No newline at end of file
diff --git a/chrome/browser/ui/global_error/global_error_browsertest.cc b/chrome/browser/ui/global_error/global_error_browsertest.cc
index ff0b184..2eeb0f4 100644
--- a/chrome/browser/ui/global_error/global_error_browsertest.cc
+++ b/chrome/browser/ui/global_error/global_error_browsertest.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/ui/test/test_browser_dialog.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/pref_names.h"
+#include "components/crx_file/crx_verifier.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_utils.h"
@@ -34,6 +35,7 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/mock_external_provider.h"
+#include "extensions/browser/sandboxed_unpacker.h"
 #include "extensions/common/extension_builder.h"
 #include "extensions/common/feature_switch.h"
 
@@ -202,6 +204,8 @@
 
 IN_PROC_BROWSER_TEST_F(GlobalErrorBubbleTest,
                        InvokeUi_ExternalInstallBubbleAlert) {
+  extensions::SandboxedUnpacker::ScopedVerifierFormatOverrideForTest
+      verifier_format_override(crx_file::VerifierFormat::CRX3);
   extensions::FeatureSwitch::ScopedOverride prompt(
       extensions::FeatureSwitch::prompt_for_external_extensions(), true);
   ShowAndVerifyUi();
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 69de202..9c72ae4 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -35,6 +35,7 @@
 #include "components/omnibox/browser/omnibox_view.h"
 #include "components/search/search.h"
 #include "components/strings/grit/components_strings.h"
+#include "components/sync/base/user_selectable_type.h"
 #include "components/sync/driver/sync_service.h"
 #include "components/sync/driver/sync_user_settings.h"
 #include "content/public/browser/navigation_details.h"
@@ -100,7 +101,8 @@
 bool IsHistorySyncEnabled(Profile* profile) {
   syncer::SyncService* sync = ProfileSyncServiceFactory::GetForProfile(profile);
   return sync && sync->IsSyncFeatureEnabled() &&
-         sync->GetUserSettings()->GetChosenDataTypes().Has(syncer::TYPED_URLS);
+         sync->GetUserSettings()->GetSelectedTypes().Has(
+             syncer::UserSelectableType::kHistory);
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index 2c49c6b..5b70f7a 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -59,7 +59,6 @@
 #include "chrome/browser/tracing/navigation_tracing.h"
 #include "chrome/browser/translate/chrome_translate_client.h"
 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
-#include "chrome/browser/ui/bloated_renderer/bloated_renderer_tab_helper.h"
 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
 #include "chrome/browser/ui/blocked_content/popup_opener_tab_helper.h"
 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
@@ -195,7 +194,6 @@
       autofill::ChromeAutofillClient::FromWebContents(web_contents),
       g_browser_process->GetApplicationLocale(),
       autofill::AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
-  BloatedRendererTabHelper::CreateForWebContents(web_contents);
   chrome_browser_net::NetErrorTabHelper::CreateForWebContents(web_contents);
   ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
       web_contents,
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view.cc b/chrome/browser/ui/views/crostini/crostini_installer_view.cc
index 09076bc..d7888cb 100644
--- a/chrome/browser/ui/views/crostini/crostini_installer_view.cc
+++ b/chrome/browser/ui/views/crostini/crostini_installer_view.cc
@@ -56,6 +56,10 @@
 // The size of the download for the VM image.
 // TODO(timloh): This is just a placeholder.
 constexpr int kDownloadSizeInBytes = 300 * 1024 * 1024;
+// The minimum feasible size for a VM disk image.
+constexpr int64_t kMinimumDiskSize = 1ll * 1024 * 1024 * 1024;  // 1 GiB
+// Minimum amount of free disk space to install crostini successfully.
+constexpr int kMinimumFreeDiskSpace = kDownloadSizeInBytes + kMinimumDiskSize;
 
 constexpr int kUninitializedDiskSpace = -1;
 
@@ -133,7 +137,7 @@
       true);
 
   base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock()},
+      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace,
                      base::FilePath(kHomeDirectory)),
       base::BindOnce(
@@ -143,6 +147,9 @@
 
 void CrostiniInstallerView::OnAvailableDiskSpace(int64_t bytes) {
   free_disk_space_ = bytes;
+  if (free_disk_space_callback_for_testing_) {
+    std::move(free_disk_space_callback_for_testing_).Run();
+  }
 }
 
 int CrostiniInstallerView::GetDialogButtons() const {
@@ -183,11 +190,26 @@
   return false;
 }
 
+void CrostiniInstallerView::PressAccept() {
+  GetDialogClientView()->AcceptWindow();
+}
+
 bool CrostiniInstallerView::Accept() {
   // This dialog can be accepted from State::ERROR. In that case, we're doing a
   // Retry.
   DCHECK(state_ == State::PROMPT || state_ == State::ERROR);
 
+  // Delay starting the install process until we can check if there's enough
+  // disk space.
+  if (free_disk_space_ == kUninitializedDiskSpace) {
+    base::PostDelayedTaskWithTraits(
+        FROM_HERE, {content::BrowserThread::UI},
+        base::BindOnce(&CrostiniInstallerView::PressAccept,
+                       weak_ptr_factory_.GetWeakPtr()),
+        base::TimeDelta::FromMilliseconds(50));
+    return false;
+  }
+
   UpdateState(State::INSTALL_START);
   profile_->GetPrefs()->SetBoolean(crostini::prefs::kCrostiniEnabled, true);
   install_start_time_ = base::TimeTicks::Now();
@@ -213,6 +235,19 @@
     return false;  // should not close the dialog.
   }
 
+  // Don't enforce minimum disk size on dev box or trybots because
+  // base::SysInfo::AmountOfFreeDiskSpace returns zero in testing.
+  if (free_disk_space_ < kMinimumFreeDiskSpace &&
+      base::SysInfo::IsRunningOnChromeOS()) {
+    HandleError(l10n_util::GetStringFUTF16(
+                    IDS_CROSTINI_INSTALLER_INSUFFICIENT_DISK,
+                    ui::FormatBytesWithUnits(kMinimumFreeDiskSpace,
+                                             ui::DATA_UNITS_GIBIBYTE,
+                                             /*show_units=*/true)),
+                SetupResult::kErrorInsufficientDiskSpace);
+    return false;  // should not close the dialog.
+  }
+
   // Kick off the Crostini Restart sequence. We will be added as an observer.
   restart_id_ =
       crostini::CrostiniManager::GetForProfile(profile_)->RestartCrostini(
@@ -447,6 +482,15 @@
   progress_bar_callback_for_testing_ = callback;
 }
 
+void CrostiniInstallerView::SetGetFreeDiskSpaceCallbackForTesting(
+    base::OnceClosure quit_closure) {
+  if (free_disk_space_ == kUninitializedDiskSpace) {
+    free_disk_space_callback_for_testing_ = std::move(quit_closure);
+  } else {
+    std::move(free_disk_space_callback_for_testing_).Run();
+  }
+}
+
 CrostiniInstallerView::CrostiniInstallerView(Profile* profile)
     : profile_(profile),
       free_disk_space_(kUninitializedDiskSpace),
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view.h b/chrome/browser/ui/views/crostini/crostini_installer_view.h
index f208a5e4..0c4e107 100644
--- a/chrome/browser/ui/views/crostini/crostini_installer_view.h
+++ b/chrome/browser/ui/views/crostini/crostini_installer_view.h
@@ -52,6 +52,7 @@
     kErrorFetchingSshKeys = 9,
     kErrorMountingContainer = 10,
     kErrorSettingUpContainer = 11,
+    kErrorInsufficientDiskSpace = 22,
 
     kUserCancelledStart = 12,
     kUserCancelledInstallImageLoader = 13,
@@ -99,6 +100,7 @@
   void SetCloseCallbackForTesting(base::OnceClosure quit_closure);
   void SetProgressBarCallbackForTesting(
       base::RepeatingCallback<void(double)> callback);
+  void SetGetFreeDiskSpaceCallbackForTesting(base::OnceClosure quit_closure);
 
  private:
   enum class State {
@@ -137,6 +139,8 @@
 
   void OnAvailableDiskSpace(int64_t bytes);
 
+  void PressAccept();
+
   State state_ = State::PROMPT;
   views::ImageView* logo_image_ = nullptr;
   views::Label* big_message_label_ = nullptr;
@@ -166,6 +170,7 @@
 
   base::RepeatingCallback<void(double)> progress_bar_callback_for_testing_;
   base::OnceClosure quit_closure_for_testing_;
+  base::OnceClosure free_disk_space_callback_for_testing_;
 
   base::WeakPtrFactory<CrostiniInstallerView> weak_ptr_factory_;
 
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
index ff43690..ea570262 100644
--- a/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
@@ -165,6 +165,10 @@
   EXPECT_TRUE(crostini::CrostiniManager::GetForProfile(browser()->profile())
                   ->GetInstallerViewStatus());
 
+  base::RunLoop run_loop;
+  ActiveView()->SetGetFreeDiskSpaceCallbackForTesting(run_loop.QuitClosure());
+  run_loop.Run();
+
   ActiveView()->GetDialogClientView()->AcceptWindow();
   EXPECT_FALSE(ActiveView()->GetWidget()->IsClosed());
   EXPECT_FALSE(HasAcceptButton());
@@ -220,6 +224,10 @@
   EXPECT_TRUE(crostini::CrostiniManager::GetForProfile(browser()->profile())
                   ->GetInstallerViewStatus());
 
+  base::RunLoop run_loop;
+  ActiveView()->SetGetFreeDiskSpaceCallbackForTesting(run_loop.QuitClosure());
+  run_loop.Run();
+
   ActiveView()->GetDialogClientView()->AcceptWindow();
   EXPECT_FALSE(ActiveView()->GetWidget()->IsClosed());
   EXPECT_TRUE(HasAcceptButton());
@@ -273,6 +281,10 @@
   response.set_status(vm_tools::concierge::VM_STATUS_FAILURE);
   waiting_fake_concierge_client_->set_start_vm_response(std::move(response));
 
+  base::RunLoop run_loop;
+  ActiveView()->SetGetFreeDiskSpaceCallbackForTesting(run_loop.QuitClosure());
+  run_loop.Run();
+
   ActiveView()->GetDialogClientView()->AcceptWindow();
   EXPECT_FALSE(ActiveView()->GetWidget()->IsClosed());
   waiting_fake_concierge_client_->WaitForStartTerminaVmCalled();
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_launcher_view.cc b/chrome/browser/ui/views/plugin_vm/plugin_vm_launcher_view.cc
index 4e1e2eb..d9c884f 100644
--- a/chrome/browser/ui/views/plugin_vm/plugin_vm_launcher_view.cc
+++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_launcher_view.cc
@@ -418,20 +418,19 @@
   base::Optional<double> fraction_complete =
       GetFractionComplete(bytes_downloaded, content_length);
 
-  base::string16 bytes_downloaded_str =
-      ui::FormatBytesWithUnits(bytes_downloaded, ui::DATA_UNITS_GIBIBYTE,
-                               /*show_units=*/true);
-
   // If download size isn't known |fraction_complete| should be empty.
   if (fraction_complete.has_value()) {
     return l10n_util::GetStringFUTF16(
-        IDS_PLUGIN_VM_LAUNCHER_DOWNLOAD_PROGRESS_MESSAGE, bytes_downloaded_str,
+        IDS_PLUGIN_VM_LAUNCHER_DOWNLOAD_PROGRESS_MESSAGE,
+        ui::FormatBytesWithUnits(bytes_downloaded, ui::DATA_UNITS_GIBIBYTE,
+                                 /*show_units=*/false),
         ui::FormatBytesWithUnits(content_length, ui::DATA_UNITS_GIBIBYTE,
                                  /*show_units=*/true));
   } else {
     return l10n_util::GetStringFUTF16(
         IDS_PLUGIN_VM_LAUNCHER_DOWNLOAD_PROGRESS_WITHOUT_DOWNLOAD_SIZE_MESSAGE,
-        bytes_downloaded_str);
+        ui::FormatBytesWithUnits(bytes_downloaded, ui::DATA_UNITS_GIBIBYTE,
+                                 /*show_units=*/true));
   }
 }
 
diff --git a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.cc b/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.cc
index 2a31b94..a9fbcf1 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h"
 
+#include <utility>
+
+#include "base/callback.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/web_app_browser_controller.h"
@@ -19,6 +22,15 @@
 
 WebAppUiDelegateImpl::WebAppUiDelegateImpl(Profile* profile)
     : profile_(profile) {
+  for (Browser* browser : *BrowserList::GetInstance()) {
+    base::Optional<AppId> app_id = GetAppIdForBrowser(browser);
+    if (!app_id.has_value())
+      continue;
+
+    ++num_windows_for_apps_map_[app_id.value()];
+  }
+
+  BrowserList::AddObserver(this);
   WebAppProvider::Get(profile_)->set_ui_delegate(this);
 }
 
@@ -26,22 +38,71 @@
 
 void WebAppUiDelegateImpl::Shutdown() {
   WebAppProvider::Get(profile_)->set_ui_delegate(nullptr);
+  BrowserList::RemoveObserver(this);
 }
 
 size_t WebAppUiDelegateImpl::GetNumWindowsForApp(const AppId& app_id) {
-  size_t num_windows_for_app = 0;
-  for (Browser* browser : *BrowserList::GetInstance()) {
-    if (browser->profile() != profile_)
-      continue;
+  auto it = num_windows_for_apps_map_.find(app_id);
+  if (it == num_windows_for_apps_map_.end())
+    return 0;
 
-    if (!browser->web_app_controller())
-      continue;
+  return it->second;
+}
 
-    if (browser->web_app_controller()->GetAppId() == app_id)
-      ++num_windows_for_app;
+void WebAppUiDelegateImpl::NotifyOnAllAppWindowsClosed(
+    const AppId& app_id,
+    base::OnceClosure callback) {
+  const size_t num_windows_for_app = GetNumWindowsForApp(app_id);
+  if (num_windows_for_app == 0) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  std::move(callback));
+    return;
   }
 
-  return num_windows_for_app;
+  windows_closed_requests_map_[app_id].push_back(std::move(callback));
+}
+
+void WebAppUiDelegateImpl::OnBrowserAdded(Browser* browser) {
+  base::Optional<AppId> app_id = GetAppIdForBrowser(browser);
+  if (!app_id.has_value())
+    return;
+
+  ++num_windows_for_apps_map_[app_id.value()];
+}
+
+void WebAppUiDelegateImpl::OnBrowserRemoved(Browser* browser) {
+  base::Optional<AppId> app_id_opt = GetAppIdForBrowser(browser);
+  if (!app_id_opt.has_value())
+    return;
+
+  const auto& app_id = app_id_opt.value();
+
+  size_t& num_windows_for_app = num_windows_for_apps_map_[app_id];
+  DCHECK_GT(num_windows_for_app, 0u);
+  --num_windows_for_app;
+
+  if (num_windows_for_app > 0)
+    return;
+
+  auto it = windows_closed_requests_map_.find(app_id);
+  if (it == windows_closed_requests_map_.end())
+    return;
+
+  for (auto& callback : it->second)
+    std::move(callback).Run();
+
+  windows_closed_requests_map_.erase(app_id);
+}
+
+base::Optional<AppId> WebAppUiDelegateImpl::GetAppIdForBrowser(
+    Browser* browser) {
+  if (browser->profile() != profile_)
+    return base::nullopt;
+
+  if (!browser->web_app_controller())
+    return base::nullopt;
+
+  return browser->web_app_controller()->GetAppId();
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h b/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h
index a2c8547..7987502 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h
+++ b/chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h
@@ -5,15 +5,24 @@
 #ifndef CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_DELEGATE_IMPL_H_
 #define CHROME_BROWSER_UI_WEB_APPLICATIONS_WEB_APP_UI_DELEGATE_IMPL_H_
 
+#include <map>
+#include <vector>
+
+#include "base/callback_forward.h"
 #include "base/macros.h"
+#include "base/optional.h"
+#include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/web_applications/components/web_app_ui_delegate.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 class Profile;
+class Browser;
 
 namespace web_app {
 
-class WebAppUiDelegateImpl : public KeyedService, public WebAppUiDelegate {
+class WebAppUiDelegateImpl : public KeyedService,
+                             public BrowserListObserver,
+                             public WebAppUiDelegate {
  public:
   static WebAppUiDelegateImpl* Get(Profile* profile);
 
@@ -25,10 +34,21 @@
 
   // WebAppUiDelegate
   size_t GetNumWindowsForApp(const AppId& app_id) override;
+  void NotifyOnAllAppWindowsClosed(const AppId& app_id,
+                                   base::OnceClosure callback) override;
+
+  // BrowserListObserver
+  void OnBrowserAdded(Browser* browser) override;
+  void OnBrowserRemoved(Browser* browser) override;
 
  private:
+  base::Optional<AppId> GetAppIdForBrowser(Browser* browser);
+
   Profile* profile_;
 
+  std::map<AppId, std::vector<base::OnceClosure>> windows_closed_requests_map_;
+  std::map<AppId, size_t> num_windows_for_apps_map_;
+
   DISALLOW_COPY_AND_ASSIGN(WebAppUiDelegateImpl);
 };
 
diff --git a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_browsertest.cc b/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_browsertest.cc
index 1d3bd08..9e86c16 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui_delegate_impl_browsertest.cc
@@ -2,17 +2,89 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/web_applications/web_app_ui_delegate_impl.h"
-#include "chrome/browser/web_applications/web_app.h"
+
+#include "base/barrier_closure.h"
+#include "base/test/bind_test_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/extensions/browsertest_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_list_observer.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/web_applications/components/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
+#include "chrome/common/web_application_info.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "extensions/common/extension.h"
+#include "url/gurl.h"
 
 namespace web_app {
 
-using WebAppUiDelegateImplBrowsertest = InProcessBrowserTest;
+namespace {
 
-IN_PROC_BROWSER_TEST_F(WebAppUiDelegateImplBrowsertest, NoAppWindows) {
+// Waits for |browser| to be removed from BrowserList and then calls |callback|.
+class BrowserRemovedWaiter final : public BrowserListObserver {
+ public:
+  explicit BrowserRemovedWaiter(Browser* browser) : browser_(browser) {}
+  ~BrowserRemovedWaiter() override = default;
+
+  void Wait() {
+    BrowserList::AddObserver(this);
+    run_loop_.Run();
+  }
+
+  // BrowserListObserver
+  void OnBrowserRemoved(Browser* browser) override {
+    if (browser != browser_)
+      return;
+
+    BrowserList::RemoveObserver(this);
+    // Post a task to ensure the Remove event has been dispatched to all
+    // observers.
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  run_loop_.QuitClosure());
+  }
+
+ private:
+  Browser* browser_;
+  base::RunLoop run_loop_;
+};
+
+void CloseAndWait(Browser* browser) {
+  BrowserRemovedWaiter waiter(browser);
+  browser->window()->Close();
+  waiter.Wait();
+}
+
+}  // namespace
+
+const GURL kFooUrl = GURL("https://foo.example");
+const GURL kBarUrl = GURL("https://bar.example");
+
+class WebAppUiDelegateImplBrowserTest : public InProcessBrowserTest {
+ protected:
+  Profile* profile() { return browser()->profile(); }
+
+  const extensions::Extension* InstallWebApp(const GURL& app_url) {
+    WebApplicationInfo web_app_info;
+    web_app_info.app_url = app_url;
+    web_app_info.open_as_window = true;
+    return extensions::browsertest_util::InstallBookmarkApp(profile(),
+                                                            web_app_info);
+  }
+
+  Browser* LaunchApp(const extensions::Extension* app) {
+    return extensions::browsertest_util::LaunchAppBrowser(profile(), app);
+  }
+
+  WebAppUiDelegateImpl* ui_delegate() {
+    return WebAppUiDelegateImpl::Get(profile());
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(WebAppUiDelegateImplBrowserTest,
+                       GetNumWindowsForApp_AppWindowsAdded) {
   // Should not crash.
   auto& delegate = WebAppProvider::Get(browser()->profile())->ui_delegate();
   auto* delegate_impl = WebAppUiDelegateImpl::Get(browser()->profile());
@@ -20,6 +92,146 @@
 
   // Zero apps on start:
   EXPECT_EQ(0u, delegate.GetNumWindowsForApp(AppId()));
+
+  const auto* foo_app = InstallWebApp(kFooUrl);
+  LaunchApp(foo_app);
+
+  EXPECT_EQ(1u, delegate.GetNumWindowsForApp(foo_app->id()));
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppUiDelegateImplBrowserTest,
+                       GetNumWindowsForApp_AppWindowsRemoved) {
+  const auto* foo_app = InstallWebApp(kFooUrl);
+  auto* foo_window1 = LaunchApp(foo_app);
+  auto* foo_window2 = LaunchApp(foo_app);
+
+  const auto* bar_app = InstallWebApp(kBarUrl);
+  LaunchApp(bar_app);
+
+  // Wait for the browser windows to be fully opened, otherwise we'll crash when
+  // closing them.
+  // TODO(ortuno): Investigate removing this.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(2u, ui_delegate()->GetNumWindowsForApp(foo_app->id()));
+  EXPECT_EQ(1u, ui_delegate()->GetNumWindowsForApp(bar_app->id()));
+
+  CloseAndWait(foo_window1);
+
+  EXPECT_EQ(1u, ui_delegate()->GetNumWindowsForApp(foo_app->id()));
+  EXPECT_EQ(1u, ui_delegate()->GetNumWindowsForApp(bar_app->id()));
+
+  CloseAndWait(foo_window2);
+
+  EXPECT_EQ(0u, ui_delegate()->GetNumWindowsForApp(foo_app->id()));
+  EXPECT_EQ(1u, ui_delegate()->GetNumWindowsForApp(bar_app->id()));
+}
+
+IN_PROC_BROWSER_TEST_F(WebAppUiDelegateImplBrowserTest,
+                       NotifyOnAllAppWindowsClosed_NoOpenedWindows) {
+  const auto* foo_app = InstallWebApp(kFooUrl);
+  const auto* bar_app = InstallWebApp(kBarUrl);
+  LaunchApp(bar_app);
+
+  // Wait for the browser windows to be fully opened, otherwise we'll crash when
+  // closing them.
+  // TODO(ortuno): Investigate removing this.
+  base::RunLoop().RunUntilIdle();
+
+  base::RunLoop run_loop;
+  // Should return early; no windows for |foo_app|.
+  ui_delegate()->NotifyOnAllAppWindowsClosed(foo_app->id(),
+                                             run_loop.QuitClosure());
+  run_loop.Run();
+}
+
+// Tests that the callback is correctly called when there is more than one
+// app window.
+IN_PROC_BROWSER_TEST_F(WebAppUiDelegateImplBrowserTest,
+                       NotifyOnAllAppWindowsClosed_MultipleOpenedWindows) {
+  const auto* foo_app = InstallWebApp(kFooUrl);
+  const auto* bar_app = InstallWebApp(kBarUrl);
+
+  // Test that NotifyOnAllAppWindowsClosed can be called more than once for
+  // the same app.
+  for (int i = 0; i < 2; i++) {
+    auto* foo_window1 = LaunchApp(foo_app);
+    auto* foo_window2 = LaunchApp(foo_app);
+    auto* bar_window = LaunchApp(bar_app);
+
+    // Wait for the browser windows to be fully opened, otherwise we'll crash
+    // when closing them.
+    // TODO(ortuno): Investigate removing this.
+    base::RunLoop().RunUntilIdle();
+
+    bool callback_ran = false;
+    base::RunLoop run_loop;
+    ui_delegate()->NotifyOnAllAppWindowsClosed(
+        foo_app->id(), base::BindLambdaForTesting([&]() {
+          callback_ran = true;
+          run_loop.Quit();
+        }));
+
+    CloseAndWait(foo_window1);
+    // The callback shouldn't have run yet because there is still one window
+    // opened.
+    EXPECT_FALSE(callback_ran);
+
+    CloseAndWait(bar_window);
+    EXPECT_FALSE(callback_ran);
+
+    CloseAndWait(foo_window2);
+    run_loop.Run();
+    EXPECT_TRUE(callback_ran);
+  }
+}
+
+// Tests that callbacks are correctly called when there is more than one
+// request.
+IN_PROC_BROWSER_TEST_F(WebAppUiDelegateImplBrowserTest,
+                       NotifyOnAllAppWindowsClosed_MultipleRequests) {
+  const auto* foo_app = InstallWebApp(kFooUrl);
+  const auto* bar_app = InstallWebApp(kBarUrl);
+
+  auto* foo_window1 = LaunchApp(foo_app);
+  auto* foo_window2 = LaunchApp(foo_app);
+  auto* bar_window = LaunchApp(bar_app);
+
+  // Wait for the browser windows to be fully opened, otherwise we'll crash when
+  // closing them.
+  // TODO(ortuno): Investigate removing this.
+  base::RunLoop().RunUntilIdle();
+
+  bool callback_ran1 = false;
+  bool callback_ran2 = false;
+
+  base::RunLoop run_loop;
+  auto barrier_closure = base::BarrierClosure(2, run_loop.QuitClosure());
+  ui_delegate()->NotifyOnAllAppWindowsClosed(foo_app->id(),
+                                             base::BindLambdaForTesting([&]() {
+                                               callback_ran1 = true;
+                                               barrier_closure.Run();
+                                             }));
+  ui_delegate()->NotifyOnAllAppWindowsClosed(foo_app->id(),
+                                             base::BindLambdaForTesting([&]() {
+                                               callback_ran2 = true;
+                                               barrier_closure.Run();
+                                             }));
+
+  CloseAndWait(foo_window1);
+  // The callback shouldn't have run yet because there is still one window
+  // opened.
+  EXPECT_FALSE(callback_ran1);
+  EXPECT_FALSE(callback_ran2);
+
+  CloseAndWait(bar_window);
+  EXPECT_FALSE(callback_ran1);
+  EXPECT_FALSE(callback_ran2);
+
+  CloseAndWait(foo_window2);
+  run_loop.Run();
+  EXPECT_TRUE(callback_ran1);
+  EXPECT_TRUE(callback_ran2);
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/ui/webui/management_ui.cc b/chrome/browser/ui/webui/management_ui.cc
index 3faffd3..14e182d 100644
--- a/chrome/browser/ui/webui/management_ui.cc
+++ b/chrome/browser/ui/webui/management_ui.cc
@@ -97,6 +97,8 @@
 #if defined(OS_CHROMEOS)
   source->AddString("managementDeviceLearnMoreUrl",
                     chrome::kLearnMoreEnterpriseURL);
+  source->AddString("managementAccountLearnMoreUrl",
+                    chrome::kManagedUiLearnMoreUrl);
 #endif  // defined(OS_CHROMEOS)
 
   source->SetJsonPath("strings.js");
@@ -128,19 +130,21 @@
   policy::BrowserPolicyConnectorChromeOS* connector =
       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
-  if (!connector->IsEnterpriseManaged()) {
+  if (!connector->IsEnterpriseManaged() &&
+      !policy::ProfilePolicyConnectorFactory::IsProfileManaged(profile)) {
     return l10n_util::GetStringFUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE,
                                       l10n_util::GetStringUTF16(device_type));
   }
 
   std::string display_domain = connector->GetEnterpriseDisplayDomain();
 
-  if (display_domain.empty()) {
-    if (!connector->IsActiveDirectoryManaged()) {
-      return l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED,
-                                        l10n_util::GetStringUTF16(device_type));
-    }
+  if (display_domain.empty())
     display_domain = connector->GetRealm();
+  if (display_domain.empty())
+    display_domain = ManagementUIHandler::GetAccountDomain(profile);
+  if (display_domain.empty()) {
+    return l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED,
+                                      l10n_util::GetStringUTF16(device_type));
   }
   return l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
                                     l10n_util::GetStringUTF16(device_type),
diff --git a/chrome/browser/ui/webui/management_ui_handler.cc b/chrome/browser/ui/webui/management_ui_handler.cc
index 34b12d5..9082306 100644
--- a/chrome/browser/ui/webui/management_ui_handler.cc
+++ b/chrome/browser/ui/webui/management_ui_handler.cc
@@ -131,6 +131,14 @@
   return policy::ProfilePolicyConnectorFactory::IsProfileManaged(profile);
 }
 
+#if defined(OS_CHROMEOS)
+bool IsDeviceManaged() {
+  policy::BrowserPolicyConnectorChromeOS* connector =
+      g_browser_process->platform_part()->browser_policy_connector_chromeos();
+  return connector->IsEnterpriseManaged();
+}
+#endif  // defined(OS_CHROMEOS)
+
 #if !defined(OS_CHROMEOS)
 bool IsBrowserManaged() {
   return g_browser_process->browser_policy_connector()
@@ -336,7 +344,7 @@
   auto handler = std::make_unique<ManagementUIHandler>();
 
 #if defined(OS_CHROMEOS)
-  handler->managed_ = IsProfileManaged(profile);
+  handler->managed_ = IsProfileManaged(profile) || IsDeviceManaged();
 #else
   handler->managed_ = IsProfileManaged(profile) || IsBrowserManaged();
 #endif  // defined(OS_CHROMEOS)
@@ -478,7 +486,18 @@
 base::DictionaryValue ManagementUIHandler::GetContextualManagedData(
     Profile* profile) const {
   base::DictionaryValue response;
-  auto management_domain = GetAccountDomain(profile);
+
+#if defined(OS_CHROMEOS)
+  policy::BrowserPolicyConnectorChromeOS* connector =
+      g_browser_process->platform_part()->browser_policy_connector_chromeos();
+  std::string management_domain = connector->GetEnterpriseDisplayDomain();
+  if (management_domain.empty())
+    management_domain = connector->GetRealm();
+  if (management_domain.empty())
+    management_domain = GetAccountDomain(profile);
+#else
+  std::string management_domain = GetAccountDomain(profile);
+#endif
 
   if (management_domain.empty()) {
     response.SetString(
@@ -497,12 +516,13 @@
                                     : IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
 #else
     const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
-    response.SetString(
-        "pageSubtitle",
-        managed_
-            ? l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED,
-                                         l10n_util::GetStringUTF16(device_type))
-            : l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
+    response.SetString("pageSubtitle",
+                       managed_ ? l10n_util::GetStringFUTF16(
+                                      IDS_MANAGEMENT_SUBTITLE_MANAGED,
+                                      l10n_util::GetStringUTF16(device_type))
+                                : l10n_util::GetStringFUTF16(
+                                      IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE,
+                                      l10n_util::GetStringUTF16(device_type)));
 #endif  // !defined(OS_CHROMEOS)
 
   } else {
@@ -529,13 +549,14 @@
             : l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
 #else
     const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
-    response.SetString(
-        "pageSubtitle",
-        managed_
-            ? l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
-                                         l10n_util::GetStringUTF16(device_type),
-                                         base::UTF8ToUTF16(management_domain))
-            : l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
+    response.SetString("pageSubtitle",
+                       managed_ ? l10n_util::GetStringFUTF16(
+                                      IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
+                                      l10n_util::GetStringUTF16(device_type),
+                                      base::UTF8ToUTF16(management_domain))
+                                : l10n_util::GetStringFUTF16(
+                                      IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE,
+                                      l10n_util::GetStringUTF16(device_type)));
 #endif  // !defined(OS_CHROMEOS)
   }
   GetManagementStatus(profile, &response);
@@ -617,7 +638,7 @@
                      base::UTF8ToUTF16(device_domain),
                      base::UTF8ToUTF16(account_domain))));
   AddStatusDeviceManagedInfo(status, device_domain);
-  status->SetKey(kAccountManagedInfo, base::Value());
+  AddStatusAccountManagedInfo(status, account_domain);
 }
 
 void AddStatusOverviewManagedDeviceAndAccount(
@@ -818,7 +839,7 @@
 void ManagementUIHandler::OnManagedStateChanged() {
   auto* profile = Profile::FromWebUI(web_ui());
 #if defined(OS_CHROMEOS)
-  bool managed = IsProfileManaged(profile);
+  bool managed = IsProfileManaged(profile) || IsDeviceManaged();
 #else
   bool managed = IsProfileManaged(profile) || IsBrowserManaged();
 #endif  // defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management_ui_handler_unittest.cc
index 8ff791f..3239e15 100644
--- a/chrome/browser/ui/webui/management_ui_handler_unittest.cc
+++ b/chrome/browser/ui/webui/management_ui_handler_unittest.cc
@@ -24,6 +24,10 @@
 
 #include "ui/base/l10n/l10n_util.h"
 
+#if defined(OS_CHROMEOS)
+#include "ui/chromeos/devicetype_utils.h"
+#endif  // defined(OS_CHROMEOS)
+
 using testing::_;
 using testing::Return;
 using testing::ReturnRef;
@@ -349,6 +353,63 @@
 
 #endif  // !defined(OS_CHROMEOS)
 
+#if defined(OS_CHROMEOS)
+TEST_F(ManagementUIHandlerTests,
+       ManagementContextualSourceUpdateManagedAccountKnownDomain) {
+  TestingProfile::Builder builder;
+  builder.SetProfileName("managed@manager.com");
+  auto profile = builder.Build();
+  const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
+
+  base::string16 extensions_installed;
+  base::string16 browser_management_notice;
+  base::string16 subtitle;
+  base::string16 management_overview;
+  base::string16 management_overview_data_notice;
+  base::string16 management_overview_setup_notice;
+  ContextualManagementSourceUpdate extracted{&extensions_installed,
+                                             &browser_management_notice,
+                                             &subtitle,
+                                             &management_overview,
+                                             &management_overview_data_notice,
+                                             &management_overview_setup_notice};
+
+  handler_.SetManagedForTesting(true);
+  auto data = handler_.GetContextualManagedDataForTesting(profile.get());
+  ExtractContextualSourceUpdate(data, extracted);
+
+  EXPECT_EQ(subtitle,
+            l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
+                                       l10n_util::GetStringUTF16(device_type),
+                                       base::UTF8ToUTF16("manager.com")));
+}
+
+TEST_F(ManagementUIHandlerTests, ManagementContextualSourceUpdateUnmanaged) {
+  auto profile = TestingProfile::Builder().Build();
+  const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
+
+  base::string16 extension_reporting_title;
+  base::string16 browser_management_notice;
+  base::string16 subtitle;
+  base::string16 management_overview;
+  base::string16 management_overview_data_notice;
+  base::string16 management_overview_setup_notice;
+  ContextualManagementSourceUpdate extracted{&extension_reporting_title,
+                                             &browser_management_notice,
+                                             &subtitle,
+                                             &management_overview,
+                                             &management_overview_data_notice,
+                                             &management_overview_setup_notice};
+
+  handler_.SetManagedForTesting(false);
+  auto data = handler_.GetContextualManagedDataForTesting(profile.get());
+  ExtractContextualSourceUpdate(data, extracted);
+  EXPECT_EQ(subtitle,
+            l10n_util::GetStringFUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE,
+                                       l10n_util::GetStringUTF16(device_type)));
+}
+#endif
+
 TEST_F(ManagementUIHandlerTests, ExtensionReportingInfoNoPolicySetNoMessage) {
   handler_.EnableCloudReportingExtension(false);
   auto reporting_info = handler_.GetExtensionReportingInfo();
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc
index a28457b..4eada935 100644
--- a/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -42,6 +42,7 @@
 #include "components/signin/core/browser/signin_pref_names.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/sync/base/passphrase_enums.h"
+#include "components/sync/base/user_selectable_type.h"
 #include "components/sync/driver/sync_service.h"
 #include "components/sync/driver/sync_service_utils.h"
 #include "components/sync/driver/sync_user_settings.h"
@@ -84,7 +85,7 @@
 
   bool encrypt_all;
   bool sync_everything;
-  syncer::ModelTypeSet data_types;
+  syncer::UserSelectableTypeSet selected_types;
   bool payments_integration_enabled;
   std::string passphrase;
   bool set_new_passphrase;
@@ -119,18 +120,16 @@
     return false;
   }
 
-  syncer::ModelTypeNameMap type_names = syncer::GetUserSelectableTypeNameMap();
-
-  for (syncer::ModelTypeNameMap::const_iterator it = type_names.begin();
-       it != type_names.end(); ++it) {
-    std::string key_name = it->second + std::string("Synced");
+  for (syncer::UserSelectableType type : syncer::UserSelectableTypeSet::All()) {
+    std::string key_name =
+        syncer::GetUserSelectableTypeName(type) + std::string("Synced");
     bool sync_value;
     if (!result->GetBoolean(key_name, &sync_value)) {
       DLOG(ERROR) << "GetConfiguration() not passed a value for " << key_name;
       return false;
     }
     if (sync_value)
-      config->data_types.Put(it->first);
+      config->selected_types.Put(type);
   }
 
   // Encryption settings.
@@ -497,8 +496,8 @@
     return;
   }
 
-  service->GetUserSettings()->SetChosenDataTypes(configuration.sync_everything,
-                                                 configuration.data_types);
+  service->GetUserSettings()->SetSelectedTypes(configuration.sync_everything,
+                                               configuration.selected_types);
 
   // Choosing data types to sync never fails.
   ResolveJavascriptCallback(*callback_id, base::Value(kConfigurePageStatus));
@@ -1065,41 +1064,41 @@
   //
   base::DictionaryValue args;
 
+  syncer::SyncUserSettings* sync_user_settings = service->GetUserSettings();
   // Tell the UI layer which data types are registered/enabled by the user.
-  const syncer::ModelTypeSet registered_types =
-      service->GetRegisteredDataTypes();
-  const syncer::ModelTypeSet preferred_types = service->GetPreferredDataTypes();
-  const syncer::ModelTypeSet enforced_types = service->GetForcedDataTypes();
-  syncer::ModelTypeNameMap type_names = syncer::GetUserSelectableTypeNameMap();
-  for (syncer::ModelTypeNameMap::const_iterator it = type_names.begin();
-       it != type_names.end(); ++it) {
-    syncer::ModelType sync_type = it->first;
-    const std::string key_name = it->second;
-    args.SetBoolean(key_name + "Registered", registered_types.Has(sync_type));
-    args.SetBoolean(key_name + "Synced", preferred_types.Has(sync_type));
-    args.SetBoolean(key_name + "Enforced", enforced_types.Has(sync_type));
+  const syncer::UserSelectableTypeSet registered_types =
+      sync_user_settings->GetRegisteredSelectableTypes();
+  const syncer::UserSelectableTypeSet selected_types =
+      sync_user_settings->GetSelectedTypes();
+  const syncer::UserSelectableTypeSet enforced_types =
+      sync_user_settings->GetForcedTypes();
+  for (syncer::UserSelectableType type : syncer::UserSelectableTypeSet::All()) {
+    const std::string type_name = syncer::GetUserSelectableTypeName(type);
+    args.SetBoolean(type_name + "Registered", registered_types.Has(type));
+    args.SetBoolean(type_name + "Synced", selected_types.Has(type));
+    args.SetBoolean(type_name + "Enforced", enforced_types.Has(type));
   }
   args.SetBoolean("syncAllDataTypes",
-                  service->GetUserSettings()->IsSyncEverythingEnabled());
+                  sync_user_settings->IsSyncEverythingEnabled());
   args.SetBoolean(
       "paymentsIntegrationEnabled",
       autofill::prefs::IsPaymentsIntegrationEnabled(profile_->GetPrefs()));
   args.SetBoolean("encryptAllData",
-                  service->GetUserSettings()->IsEncryptEverythingEnabled());
+                  sync_user_settings->IsEncryptEverythingEnabled());
   args.SetBoolean("encryptAllDataAllowed",
-                  service->GetUserSettings()->IsEncryptEverythingAllowed());
+                  sync_user_settings->IsEncryptEverythingAllowed());
 
   // We call IsPassphraseRequired() here, instead of calling
   // IsPassphraseRequiredForDecryption(), because we want to show the passphrase
   // UI even if no encrypted data types are enabled.
   args.SetBoolean("passphraseRequired",
-                  service->GetUserSettings()->IsPassphraseRequired());
+                  sync_user_settings->IsPassphraseRequired());
 
   syncer::PassphraseType passphrase_type =
-      service->GetUserSettings()->GetPassphraseType();
+      sync_user_settings->GetPassphraseType();
   if (syncer::IsExplicitPassphrase(passphrase_type)) {
     base::Time passphrase_time =
-        service->GetUserSettings()->GetExplicitPassphraseTime();
+        sync_user_settings->GetExplicitPassphraseTime();
     args.SetString("enterPassphraseBody",
                    GetEnterPassphraseBody(passphrase_type, passphrase_time));
     args.SetString("fullEncryptionBody",
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index 1005b55f..a14675b 100644
--- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -59,16 +59,16 @@
 
 namespace {
 
-MATCHER_P(ModelTypeSetMatches, value, "") {
+MATCHER_P(UserSelectableTypeSetMatches, value, "") {
   return arg == value;
 }
 
 const char kTestUser[] = "chrome.p13n.test@gmail.com";
 const char kTestCallbackId[] = "test-callback-id";
 
-// Returns a ModelTypeSet with all user selectable types set.
-syncer::ModelTypeSet GetAllTypes() {
-  return syncer::UserSelectableTypes();
+// Returns a UserSelectableTypeSet with all types set.
+syncer::UserSelectableTypeSet GetAllTypes() {
+  return syncer::UserSelectableTypeSet::All();
 }
 
 enum SyncAllDataConfig {
@@ -86,7 +86,7 @@
 // the passed dictionary are added to the json.
 std::string GetConfiguration(const base::DictionaryValue* extra_values,
                              SyncAllDataConfig sync_all,
-                             syncer::ModelTypeSet types,
+                             syncer::UserSelectableTypeSet types,
                              const std::string& passphrase,
                              EncryptAllConfig encrypt_all) {
   base::DictionaryValue result;
@@ -97,15 +97,22 @@
   if (!passphrase.empty())
     result.SetString("passphrase", passphrase);
   // Add all of our data types.
-  result.SetBoolean("appsSynced", types.Has(syncer::APPS));
-  result.SetBoolean("autofillSynced", types.Has(syncer::AUTOFILL));
-  result.SetBoolean("bookmarksSynced", types.Has(syncer::BOOKMARKS));
-  result.SetBoolean("extensionsSynced", types.Has(syncer::EXTENSIONS));
-  result.SetBoolean("passwordsSynced", types.Has(syncer::PASSWORDS));
-  result.SetBoolean("preferencesSynced", types.Has(syncer::PREFERENCES));
-  result.SetBoolean("tabsSynced", types.Has(syncer::PROXY_TABS));
-  result.SetBoolean("themesSynced", types.Has(syncer::THEMES));
-  result.SetBoolean("typedUrlsSynced", types.Has(syncer::TYPED_URLS));
+  result.SetBoolean("appsSynced", types.Has(syncer::UserSelectableType::kApps));
+  result.SetBoolean("autofillSynced",
+                    types.Has(syncer::UserSelectableType::kAutofill));
+  result.SetBoolean("bookmarksSynced",
+                    types.Has(syncer::UserSelectableType::kBookmarks));
+  result.SetBoolean("extensionsSynced",
+                    types.Has(syncer::UserSelectableType::kExtensions));
+  result.SetBoolean("passwordsSynced",
+                    types.Has(syncer::UserSelectableType::kPasswords));
+  result.SetBoolean("preferencesSynced",
+                    types.Has(syncer::UserSelectableType::kPreferences));
+  result.SetBoolean("tabsSynced", types.Has(syncer::UserSelectableType::kTabs));
+  result.SetBoolean("themesSynced",
+                    types.Has(syncer::UserSelectableType::kThemes));
+  result.SetBoolean("typedUrlsSynced",
+                    types.Has(syncer::UserSelectableType::kHistory));
   result.SetBoolean("paymentsIntegrationEnabled", false);
   std::string args;
   base::JSONWriter::Write(result, &args);
@@ -142,17 +149,26 @@
 // types.
 void CheckConfigDataTypeArguments(const base::DictionaryValue* dictionary,
                                   SyncAllDataConfig config,
-                                  syncer::ModelTypeSet types) {
+                                  syncer::UserSelectableTypeSet types) {
   CheckBool(dictionary, "syncAllDataTypes", config == SYNC_ALL_DATA);
-  CheckBool(dictionary, "appsSynced", types.Has(syncer::APPS));
-  CheckBool(dictionary, "autofillSynced", types.Has(syncer::AUTOFILL));
-  CheckBool(dictionary, "bookmarksSynced", types.Has(syncer::BOOKMARKS));
-  CheckBool(dictionary, "extensionsSynced", types.Has(syncer::EXTENSIONS));
-  CheckBool(dictionary, "passwordsSynced", types.Has(syncer::PASSWORDS));
-  CheckBool(dictionary, "preferencesSynced", types.Has(syncer::PREFERENCES));
-  CheckBool(dictionary, "tabsSynced", types.Has(syncer::PROXY_TABS));
-  CheckBool(dictionary, "themesSynced", types.Has(syncer::THEMES));
-  CheckBool(dictionary, "typedUrlsSynced", types.Has(syncer::TYPED_URLS));
+  CheckBool(dictionary, "appsSynced",
+            types.Has(syncer::UserSelectableType::kApps));
+  CheckBool(dictionary, "autofillSynced",
+            types.Has(syncer::UserSelectableType::kAutofill));
+  CheckBool(dictionary, "bookmarksSynced",
+            types.Has(syncer::UserSelectableType::kBookmarks));
+  CheckBool(dictionary, "extensionsSynced",
+            types.Has(syncer::UserSelectableType::kExtensions));
+  CheckBool(dictionary, "passwordsSynced",
+            types.Has(syncer::UserSelectableType::kPasswords));
+  CheckBool(dictionary, "preferencesSynced",
+            types.Has(syncer::UserSelectableType::kPreferences));
+  CheckBool(dictionary, "tabsSynced",
+            types.Has(syncer::UserSelectableType::kTabs));
+  CheckBool(dictionary, "themesSynced",
+            types.Has(syncer::UserSelectableType::kThemes));
+  CheckBool(dictionary, "typedUrlsSynced",
+            types.Has(syncer::UserSelectableType::kHistory));
 }
 
 std::unique_ptr<KeyedService> BuildMockSyncService(
@@ -257,18 +273,13 @@
         .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
     ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsSyncRequested())
         .WillByDefault(Return(true));
-    ON_CALL(*mock_sync_service_, GetRegisteredDataTypes())
+    ON_CALL(*mock_sync_service_->GetMockUserSettings(),
+            GetRegisteredSelectableTypes())
         .WillByDefault(Return(GetAllTypes()));
     ON_CALL(*mock_sync_service_->GetMockUserSettings(),
             IsSyncEverythingEnabled())
         .WillByDefault(Return(true));
-    ON_CALL(*mock_sync_service_->GetMockUserSettings(), GetChosenDataTypes())
-        .WillByDefault(Return(GetAllTypes()));
-    ON_CALL(*mock_sync_service_, GetPreferredDataTypes())
-        .WillByDefault(
-            Return(syncer::SyncUserSettingsImpl::ResolvePrefGroupsForTesting(
-                GetAllTypes())));
-    ON_CALL(*mock_sync_service_, GetActiveDataTypes())
+    ON_CALL(*mock_sync_service_->GetMockUserSettings(), GetSelectedTypes())
         .WillByDefault(Return(GetAllTypes()));
     ON_CALL(*mock_sync_service_->GetMockUserSettings(),
             IsEncryptEverythingAllowed())
@@ -807,7 +818,7 @@
       .WillByDefault(Return(false));
   SetupInitializedSyncService();
   EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(),
-              SetChosenDataTypes(true, _));
+              SetSelectedTypes(true, _));
   handler_->HandleSetDatatypes(&list_args);
 
   ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus);
@@ -949,9 +960,8 @@
 // Walks through each user selectable type, and tries to sync just that single
 // data type.
 TEST_F(PeopleHandlerTest, TestSyncIndividualTypes) {
-  syncer::ModelTypeSet user_selectable_types = GetAllTypes();
-  for (syncer::ModelType type : user_selectable_types) {
-    syncer::ModelTypeSet type_to_set;
+  for (syncer::UserSelectableType type : GetAllTypes()) {
+    syncer::UserSelectableTypeSet type_to_set;
     type_to_set.Put(type);
     std::string args = GetConfiguration(NULL,
                                         CHOOSE_WHAT_TO_SYNC,
@@ -967,8 +977,9 @@
     ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired())
         .WillByDefault(Return(false));
     SetupInitializedSyncService();
-    EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(),
-                SetChosenDataTypes(false, ModelTypeSetMatches(type_to_set)));
+    EXPECT_CALL(
+        *mock_sync_service_->GetMockUserSettings(),
+        SetSelectedTypes(false, UserSelectableTypeSetMatches(type_to_set)));
 
     handler_->HandleSetDatatypes(&list_args);
     ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus);
@@ -991,8 +1002,9 @@
   ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired())
       .WillByDefault(Return(false));
   SetupInitializedSyncService();
-  EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(),
-              SetChosenDataTypes(false, ModelTypeSetMatches(GetAllTypes())));
+  EXPECT_CALL(
+      *mock_sync_service_->GetMockUserSettings(),
+      SetSelectedTypes(false, UserSelectableTypeSetMatches(GetAllTypes())));
   handler_->HandleSetDatatypes(&list_args);
 
   ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus);
@@ -1120,8 +1132,7 @@
 }
 
 TEST_F(PeopleHandlerTest, ShowSetupSyncForAllTypesIndividually) {
-  syncer::ModelTypeSet user_selectable_types = GetAllTypes();
-  for (syncer::ModelType type : user_selectable_types) {
+  for (syncer::UserSelectableType type : GetAllTypes()) {
     ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired())
         .WillByDefault(Return(false));
     ON_CALL(*mock_sync_service_->GetMockUserSettings(),
@@ -1132,12 +1143,9 @@
     ON_CALL(*mock_sync_service_->GetMockUserSettings(),
             IsSyncEverythingEnabled())
         .WillByDefault(Return(false));
-    syncer::ModelTypeSet types(type);
-    ON_CALL(*mock_sync_service_->GetMockUserSettings(), GetChosenDataTypes())
+    syncer::UserSelectableTypeSet types(type);
+    ON_CALL(*mock_sync_service_->GetMockUserSettings(), GetSelectedTypes())
         .WillByDefault(Return(types));
-    ON_CALL(*mock_sync_service_, GetPreferredDataTypes())
-        .WillByDefault(Return(
-            syncer::SyncUserSettingsImpl::ResolvePrefGroupsForTesting(types)));
 
     // This should display the sync setup dialog (not login).
     handler_->HandleShowSetupUI(nullptr);
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 47702e9..d9d49a0d 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -223,6 +223,8 @@
     {"delayBeforeClickLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_LONG},
     {"delayBeforeClickVeryLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_LONG},
     {"autoclickRevertToLeftClick", IDS_SETTINGS_AUTOCLICK_REVERT_TO_LEFT_CLICK},
+    {"autoclickStabilizeCursorPosition",
+     IDS_SETTINGS_AUTOCLICK_STABILIZE_CURSOR_POSITION},
     {"autoclickMovementThresholdLabel",
      IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_LABEL},
     {"autoclickMovementThresholdExtraSmall",
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.cc b/chrome/browser/ui/webui/sync_internals_message_handler.cc
index 3f5b7c9..dbcae7e 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/sync_internals_message_handler.cc
@@ -252,7 +252,7 @@
     // asynchronously, and potentially at times we're not allowed to call into
     // the javascript side. We guard against this by invalidating this weak ptr
     // should javascript become disallowed.
-    service->GetAllNodes(
+    service->GetAllNodesForDebugging(
         base::Bind(&SyncInternalsMessageHandler::OnReceivedAllNodes,
                    weak_ptr_factory_.GetWeakPtr(), request_id));
   }
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc b/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
index b7c85e2..86df2a3 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
+++ b/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
@@ -65,8 +65,9 @@
     return js_controller_.AsWeakPtr();
   }
 
-  void GetAllNodes(const base::Callback<void(std::unique_ptr<base::ListValue>)>&
-                       callback) override {
+  void GetAllNodesForDebugging(
+      const base::Callback<void(std::unique_ptr<base::ListValue>)>& callback)
+      override {
     get_all_nodes_callback_ = std::move(callback);
   }
 
diff --git a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc
index 5fb923e..e53b49a 100644
--- a/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc
+++ b/chrome/browser/web_applications/bookmark_apps/policy/web_app_policy_manager_unittest.cc
@@ -56,7 +56,7 @@
   options.add_to_quick_launch_bar = false;
   options.install_placeholder = true;
   options.reinstall_placeholder = true;
-  options.stop_if_window_opened = true;
+  options.wait_for_windows_closed = true;
   return options;
 }
 
@@ -76,7 +76,7 @@
   options.add_to_quick_launch_bar = false;
   options.install_placeholder = true;
   options.reinstall_placeholder = true;
-  options.stop_if_window_opened = true;
+  options.wait_for_windows_closed = true;
   return options;
 }
 
@@ -94,7 +94,7 @@
   options.add_to_quick_launch_bar = false;
   options.install_placeholder = true;
   options.reinstall_placeholder = true;
-  options.stop_if_window_opened = true;
+  options.wait_for_windows_closed = true;
   return options;
 }
 
@@ -112,7 +112,7 @@
   options.add_to_quick_launch_bar = false;
   options.install_placeholder = true;
   options.reinstall_placeholder = true;
-  options.stop_if_window_opened = true;
+  options.wait_for_windows_closed = true;
   return options;
 }
 
@@ -131,7 +131,7 @@
   options.add_to_quick_launch_bar = false;
   options.install_placeholder = true;
   options.reinstall_placeholder = true;
-  options.stop_if_window_opened = true;
+  options.wait_for_windows_closed = true;
   return options;
 }
 
@@ -150,7 +150,7 @@
   options.add_to_quick_launch_bar = false;
   options.install_placeholder = true;
   options.reinstall_placeholder = true;
-  options.stop_if_window_opened = true;
+  options.wait_for_windows_closed = true;
   return options;
 }
 
@@ -423,7 +423,7 @@
   auto reinstall_options = GetWindowedInstallOptions();
   reinstall_options.install_placeholder = false;
   r