diff --git a/DEPS b/DEPS
index 601db6c..247bffe 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '07efdd707852ef8b9aca212417e824a13652f8cb',
+  'v8_revision': '64c745349ec8e447722ec903aad31e7380cbcfc9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -363,7 +363,7 @@
       Var('chromium_git') + '/external/github.com/swisspol/GCDWebServer.git' + '@' + '43555c66627f6ed44817855a0f6d465f559d30e0',
 
     'src/ios/third_party/material_components_ios/src':
-      Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'd08f9c0c1926fce2964cffbc163385896c86798a',
+      Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'cb191e7c014cc871b5351a3911a1d0bc71b71699',
 
     'src/ios/third_party/material_font_disk_loader_ios/src':
       Var('chromium_git') + '/external/github.com/material-foundation/material-font-disk-loader-ios.git' + '@' + '8e30188777b016182658fbaa0a4a020a48183224',
diff --git a/build/linux/sysroot_scripts/install-sysroot.py b/build/linux/sysroot_scripts/install-sysroot.py
index 90b7068..181ac936 100755
--- a/build/linux/sysroot_scripts/install-sysroot.py
+++ b/build/linux/sysroot_scripts/install-sysroot.py
@@ -64,17 +64,17 @@
   detected_host_arch = detect_host_arch.HostArch()
   if detected_host_arch == 'x64':
     return 'amd64'
-  elif detected_host_arch == 'ia32':
+  if detected_host_arch == 'ia32':
     return 'i386'
-  elif detected_host_arch == 'arm':
+  if detected_host_arch == 'arm':
     return 'arm'
-  elif detected_host_arch == 'arm64':
+  if detected_host_arch == 'arm64':
     return 'arm64'
-  elif detected_host_arch == 'mips':
+  if detected_host_arch == 'mips':
     return 'mips'
-  elif detected_host_arch == 'ppc':
+  if detected_host_arch == 'ppc':
     return 'ppc'
-  elif detected_host_arch == 's390':
+  if detected_host_arch == 's390':
     return 's390'
 
   raise Error('Unrecognized host arch: %s' % detected_host_arch)
@@ -93,13 +93,13 @@
   target_arch = gyp_defines.get('target_arch')
   if target_arch == 'x64':
     return 'amd64'
-  elif target_arch == 'ia32':
+  if target_arch == 'ia32':
     return 'i386'
-  elif target_arch == 'arm':
+  if target_arch == 'arm':
     return 'arm'
-  elif target_arch == 'arm64':
+  if target_arch == 'arm64':
     return 'arm64'
-  elif target_arch == 'mipsel':
+  if target_arch == 'mipsel':
     return 'mips'
 
   return None
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 7f8bf12a..b9d9861 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -8784,8 +8784,8 @@
       <message name="IDS_SYNC_CONFIRMATION_PERSONALIZE_SERVICES_BODY_CHILD_ACCOUNT" desc="Body of the personalize services section of the sync confirmation dialog in the tab modal signin flow for child accounts" formatter_data="android_java">
         Google may use your browsing history to personalize Search and other Google services
       </message>
-      <message name="IDS_SYNC_CONFIRMATION_SYNC_SETTINGS_LABEL" desc="Label of the checkbox that allows users to configure their sync settings on the settings page before signing in to Chrome.">
-        Manage Chrome Sync and personalization in Settings
+      <message name="IDS_SYNC_CONFIRMATION_SYNC_SETTINGS_LINK_BODY" desc="Label of the section containing the link to go to the sync setting page.">
+        Manage Chrome Sync and personalization in <ph name="BEGIN_LINK">&lt;a id="settingsLink" href="chrome://settings"&gt;</ph>Settings<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
       </message>
       <message name="IDS_SYNC_CONFIRMATION_CONFIRM_BUTTON_LABEL" desc="Label of the confirmation button in the sync confirmation dialog of the tab modal signin flow">
         Ok, got it
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 323cf399..b7ba2ec2 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1533,6 +1533,11 @@
      flag_descriptions::kPasswordGenerationDescription, kOsAll,
      ENABLE_DISABLE_VALUE_TYPE(autofill::switches::kEnablePasswordGeneration,
                                autofill::switches::kDisablePasswordGeneration)},
+    {"enable-username-correction",
+     flag_descriptions::kEnableUsernameCorrectionName,
+     flag_descriptions::kEnableUsernameCorrectionDescription,
+     kOsWin | kOsLinux | kOsCrOS,
+     FEATURE_VALUE_TYPE(password_manager::features::kEnableUsernameCorrection)},
     {"enable-password-force-saving",
      flag_descriptions::kPasswordForceSavingName,
      flag_descriptions::kPasswordForceSavingDescription, kOsAll,
@@ -3191,6 +3196,12 @@
      kOsDesktop,
      FEATURE_VALUE_TYPE(features::kCaptureThumbnailOnNavigatingAway)},
 
+#if defined(OS_CHROMEOS)
+    {"use-cros-midi-service", flag_descriptions::kUseCrosMidiServiceName,
+     flag_descriptions::kUseCrosMidiServiceNameDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(midi::features::kMidiManagerCros)},
+#endif  // defined(OS_CHROMEOS)
+
     // NOTE: Adding new command-line switches requires adding corresponding
     // entries to enum "LoginCustomFlags" in histograms/enums.xml. See note in
     // enums.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/browsing_data/bookmark_counter_unittest.cc b/chrome/browser/browsing_data/bookmark_counter_unittest.cc
index 8aa8b17..a3d7d849 100644
--- a/chrome/browser/browsing_data/bookmark_counter_unittest.cc
+++ b/chrome/browser/browsing_data/bookmark_counter_unittest.cc
@@ -42,7 +42,6 @@
 
   void Callback(
       std::unique_ptr<browsing_data::BrowsingDataCounter::Result> result) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     DCHECK(result->Finished());
     finished_ = result->Finished();
     result_ = static_cast<browsing_data::BrowsingDataCounter::FinishedResult*>(
@@ -52,7 +51,6 @@
   }
 
   void WaitForResult() {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     run_loop_->Run();
     run_loop_.reset(new base::RunLoop());
   }
diff --git a/chrome/browser/browsing_data/browsing_data_channel_id_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_channel_id_helper_unittest.cc
index 87dcd90..69a3b1d 100644
--- a/chrome/browser/browsing_data/browsing_data_channel_id_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_channel_id_helper_unittest.cc
@@ -53,7 +53,6 @@
 
   void FetchCallback(
       const net::ChannelIDStore::ChannelIDList& channel_ids) {
-    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     channel_id_list_ = channel_ids;
   }
 
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 4f9e43d..c2aa350 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -910,8 +910,6 @@
     if (create_service)
       service_ = base::MakeUnique<MockReportingService>();
 
-    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
     net::URLRequestContext* request_context =
         profile_->GetRequestContext()->GetURLRequestContext();
     old_service_ = request_context->reporting_service();
@@ -919,8 +917,6 @@
   }
 
   ~ClearReportingCacheTester() {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
     net::URLRequestContext* request_context =
         profile_->GetRequestContext()->GetURLRequestContext();
     DCHECK_EQ(service_.get(), request_context->reporting_service());
@@ -930,7 +926,6 @@
   void GetMockInfo(int* remove_calls_out,
                    int* last_data_type_mask_out,
                    base::Callback<bool(const GURL&)>* last_origin_filter_out) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
     DCHECK_NE(nullptr, service_.get());
 
     *remove_calls_out = service_->remove_calls();
diff --git a/chrome/browser/browsing_data/site_data_counting_helper_unittest.cc b/chrome/browser/browsing_data/site_data_counting_helper_unittest.cc
index 2c322369..cb86e12 100644
--- a/chrome/browser/browsing_data/site_data_counting_helper_unittest.cc
+++ b/chrome/browser/browsing_data/site_data_counting_helper_unittest.cc
@@ -31,6 +31,7 @@
 
   void SetUp() override {
     profile_.reset(new TestingProfile());
+    run_loop_.reset(new base::RunLoop());
     tasks_ = 0;
     cookie_callback_ = base::Bind(&SiteDataCountingHelperTest::CookieCallback,
                                   base::Unretained(this));
@@ -44,7 +45,6 @@
   void CookieCallback(int count) {
     // Negative values represent an unexpected error.
     DCHECK(count >= 0);
-    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     last_count_ = count;
 
     if (run_loop_)
@@ -61,16 +61,11 @@
                        base::Unretained(this)));
   }
 
-  void DoneCallback() {
-    DCHECK_CURRENTLY_ON(BrowserThread::UI);
-    if (run_loop_)
-      run_loop_->Quit();
-  }
+  void DoneCallback() { run_loop_->Quit(); }
 
   void WaitForTasksOnIOThread() {
-    DCHECK_CURRENTLY_ON(BrowserThread::UI);
-    run_loop_.reset(new base::RunLoop());
     run_loop_->Run();
+    run_loop_.reset(new base::RunLoop());
   }
 
   void CreateCookies(base::Time creation_time,
@@ -107,8 +102,6 @@
       const scoped_refptr<net::URLRequestContextGetter>& rq_context,
       base::Time creation_time,
       std::vector<std::string> urls) {
-    DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
     net::CookieStore* cookie_store =
         rq_context->GetURLRequestContext()->cookie_store();
 
@@ -128,7 +121,6 @@
   }
 
   void CountEntries(base::Time begin_time) {
-    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     last_count_ = -1;
     auto* helper =
         new SiteDataCountingHelper(profile(), begin_time, cookie_callback_);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 1ec4119..b757f5f 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -362,6 +362,8 @@
     "arc/intent_helper/arc_navigation_throttle.h",
     "arc/intent_helper/arc_settings_service.cc",
     "arc/intent_helper/arc_settings_service.h",
+    "arc/kiosk/arc_kiosk_bridge.cc",
+    "arc/kiosk/arc_kiosk_bridge.h",
     "arc/notification/arc_boot_error_notification.cc",
     "arc/notification/arc_boot_error_notification.h",
     "arc/notification/arc_provision_notification_service.cc",
@@ -1677,6 +1679,7 @@
     "arc/fileapi/arc_file_system_operation_runner_unittest.cc",
     "arc/intent_helper/arc_external_protocol_dialog_unittest.cc",
     "arc/intent_helper/arc_navigation_throttle_unittest.cc",
+    "arc/kiosk/arc_kiosk_bridge_unittest.cc",
     "arc/notification/arc_provision_notification_service_unittest.cc",
     "arc/optin/arc_active_directory_auth_negotiator_unittest.cc",
     "arc/optin/arc_terms_of_service_default_negotiator_unittest.cc",
@@ -1812,6 +1815,7 @@
     "ownership/fake_owner_settings_service.cc",
     "ownership/fake_owner_settings_service.h",
     "ownership/owner_settings_service_chromeos_unittest.cc",
+    "policy/active_directory_policy_manager_unittest.cc",
     "policy/affiliated_cloud_policy_invalidator_unittest.cc",
     "policy/affiliated_invalidation_service_provider_impl_unittest.cc",
     "policy/android_management_client_unittest.cc",
diff --git a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h
index a737022..a210341 100644
--- a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h
+++ b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h
@@ -9,9 +9,9 @@
 #include "base/timer/timer.h"
 #include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_launcher.h"
 #include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_manager.h"
+#include "chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_icon.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
-#include "components/arc/kiosk/arc_kiosk_bridge.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_change_registrar.h"
 
diff --git a/chrome/browser/chromeos/arc/arc_service_launcher.cc b/chrome/browser/chromeos/arc/arc_service_launcher.cc
index 940d8a4..f2444f7a 100644
--- a/chrome/browser/chromeos/arc/arc_service_launcher.cc
+++ b/chrome/browser/chromeos/arc/arc_service_launcher.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h"
 #include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h"
 #include "chrome/browser/chromeos/arc/arc_play_store_enabled_preference_handler.h"
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
@@ -21,6 +20,7 @@
 #include "chrome/browser/chromeos/arc/fileapi/arc_file_system_mounter.h"
 #include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h"
 #include "chrome/browser/chromeos/arc/intent_helper/arc_settings_service.h"
+#include "chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.h"
 #include "chrome/browser/chromeos/arc/notification/arc_boot_error_notification.h"
 #include "chrome/browser/chromeos/arc/notification/arc_provision_notification_service.h"
 #include "chrome/browser/chromeos/arc/policy/arc_policy_bridge.h"
@@ -45,7 +45,6 @@
 #include "components/arc/crash_collector/arc_crash_collector_bridge.h"
 #include "components/arc/ime/arc_ime_service.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "components/arc/kiosk/arc_kiosk_bridge.h"
 #include "components/arc/metrics/arc_metrics_service.h"
 #include "components/arc/net/arc_net_host_impl.h"
 #include "components/arc/obb_mounter/arc_obb_mounter_bridge.h"
@@ -53,7 +52,6 @@
 #include "components/arc/storage_manager/arc_storage_manager.h"
 #include "components/arc/volume_mounter/arc_volume_mounter_bridge.h"
 #include "components/prefs/pref_member.h"
-#include "components/user_manager/user_manager.h"
 #include "ui/arc/notification/arc_notification_manager.h"
 
 namespace arc {
@@ -147,6 +145,7 @@
   ArcFileSystemOperationRunner::GetForBrowserContext(profile);
   ArcImeService::GetForBrowserContext(profile);
   ArcIntentHelperBridge::GetForBrowserContext(profile);
+  ArcKioskBridge::GetForBrowserContext(profile);
   ArcMetricsService::GetForBrowserContext(profile);
   ArcNetHostImpl::GetForBrowserContext(profile);
   ArcNotificationManager::GetForBrowserContext(profile);
@@ -166,15 +165,6 @@
   ArcWallpaperService::GetForBrowserContext(profile);
   GpuArcVideoServiceHost::GetForBrowserContext(profile);
 
-  // Kiosk apps should be run only for kiosk sessions.
-  if (user_manager::UserManager::Get()->IsLoggedInAsArcKioskApp()) {
-    // ArcKioskAppService is BrowserContextKeyedService so that it's destroyed
-    // on destroying the Profile, that is after ArcServiceLauncher::Shutdown().
-    arc_service_manager_->AddService(base::MakeUnique<ArcKioskBridge>(
-        arc_service_manager_->arc_bridge_service(),
-        chromeos::ArcKioskAppService::Get(profile)));
-  }
-
   arc_session_manager_->Initialize();
   arc_play_store_enabled_preference_handler_ =
       base::MakeUnique<ArcPlayStoreEnabledPreferenceHandler>(
diff --git a/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.cc b/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.cc
new file mode 100644
index 0000000..64fa0bc
--- /dev/null
+++ b/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.cc
@@ -0,0 +1,112 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.h"
+
+#include <utility>
+
+#include "base/memory/singleton.h"
+#include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h"
+#include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service_factory.h"
+#include "components/arc/arc_bridge_service.h"
+#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "components/user_manager/user_manager.h"
+
+namespace arc {
+namespace {
+
+// Singleton factory for ArcKioskBridge.
+class ArcKioskBridgeFactory
+    : public internal::ArcBrowserContextKeyedServiceFactoryBase<
+          ArcKioskBridge,
+          ArcKioskBridgeFactory> {
+ public:
+  // Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
+  static constexpr const char* kName = "ArcKioskBridgeFactory";
+
+  static ArcKioskBridgeFactory* GetInstance() {
+    return base::Singleton<ArcKioskBridgeFactory>::get();
+  }
+
+ private:
+  friend base::DefaultSingletonTraits<ArcKioskBridgeFactory>;
+
+  ArcKioskBridgeFactory() {
+    DependsOn(chromeos::ArcKioskAppServiceFactory::GetInstance());
+  }
+  ~ArcKioskBridgeFactory() override = default;
+
+  // BrowserContextKeyedServiceFactory override:
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const override {
+    // Kiosk apps should be run only for kiosk sessions.
+    if (!user_manager::UserManager::Get()->IsLoggedInAsArcKioskApp())
+      return nullptr;
+    return ArcBrowserContextKeyedServiceFactoryBase::BuildServiceInstanceFor(
+        context);
+  }
+};
+
+}  // namespace
+
+// static
+ArcKioskBridge* ArcKioskBridge::GetForBrowserContext(
+    content::BrowserContext* context) {
+  return ArcKioskBridgeFactory::GetForBrowserContext(context);
+}
+
+// static
+std::unique_ptr<ArcKioskBridge> ArcKioskBridge::CreateForTesting(
+    ArcBridgeService* arc_bridge_service,
+    Delegate* delegate) {
+  // MakeUnique cannot be used because the ctor is private.
+  return base::WrapUnique(new ArcKioskBridge(arc_bridge_service, delegate));
+}
+
+ArcKioskBridge::ArcKioskBridge(content::BrowserContext* context,
+                               ArcBridgeService* bridge_service)
+    : ArcKioskBridge(bridge_service,
+                     chromeos::ArcKioskAppService::Get(context)) {}
+
+ArcKioskBridge::ArcKioskBridge(ArcBridgeService* bridge_service,
+                               Delegate* delegate)
+    : arc_bridge_service_(bridge_service), binding_(this), delegate_(delegate) {
+  DCHECK(delegate_);
+  arc_bridge_service_->kiosk()->AddObserver(this);
+}
+
+ArcKioskBridge::~ArcKioskBridge() {
+  // TODO(hidehiko): Currently, the lifetime of ArcBridgeService and
+  // BrowserContextKeyedService is not nested.
+  // If ArcServiceManager::Get() returns nullptr, it is already destructed,
+  // so do not touch it.
+  if (ArcServiceManager::Get())
+    arc_bridge_service_->kiosk()->RemoveObserver(this);
+}
+
+void ArcKioskBridge::OnInstanceReady() {
+  mojom::KioskInstance* kiosk_instance =
+      ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->kiosk(), Init);
+  DCHECK(kiosk_instance);
+  mojom::KioskHostPtr host_proxy;
+  binding_.Bind(mojo::MakeRequest(&host_proxy));
+  kiosk_instance->Init(std::move(host_proxy));
+}
+
+void ArcKioskBridge::OnMaintenanceSessionCreated(int32_t session_id) {
+  session_id_ = session_id;
+  delegate_->OnMaintenanceSessionCreated();
+  // TODO(poromov@) Show appropriate splash screen.
+}
+
+void ArcKioskBridge::OnMaintenanceSessionFinished(int32_t session_id,
+                                                  bool success) {
+  // Filter only callbacks for the started kiosk session.
+  if (session_id != session_id_)
+    return;
+  session_id_ = -1;
+  delegate_->OnMaintenanceSessionFinished();
+}
+
+}  // namespace arc
diff --git a/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.h b/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.h
new file mode 100644
index 0000000..8650edbc
--- /dev/null
+++ b/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.h
@@ -0,0 +1,74 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_ARC_KIOSK_ARC_KIOSK_BRIDGE_H_
+#define CHROME_BROWSER_CHROMEOS_ARC_KIOSK_ARC_KIOSK_BRIDGE_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "components/arc/common/kiosk.mojom.h"
+#include "components/arc/instance_holder.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace content {
+class BrowserContext;
+}  // namespace content
+
+namespace arc {
+
+class ArcBridgeService;
+
+// TODO(hidehiko): Consider to migrate this class into ArcKioskAppService.
+class ArcKioskBridge : public KeyedService,
+                       public InstanceHolder<mojom::KioskInstance>::Observer,
+                       public mojom::KioskHost {
+ public:
+  // Received IPCs are passed to this delegate.
+  class Delegate {
+   public:
+    virtual ~Delegate() = default;
+    virtual void OnMaintenanceSessionCreated() = 0;
+    virtual void OnMaintenanceSessionFinished() = 0;
+  };
+
+  // Returns singleton instance for the given BrowserContext,
+  // or nullptr if the browser |context| is not allowed to use ARC.
+  static ArcKioskBridge* GetForBrowserContext(content::BrowserContext* context);
+
+  // Returns a created instance for testing.
+  static std::unique_ptr<ArcKioskBridge> CreateForTesting(
+      ArcBridgeService* bridge_service,
+      Delegate* delegate);
+
+  ArcKioskBridge(content::BrowserContext* context,
+                 ArcBridgeService* bridge_service);
+  ~ArcKioskBridge() override;
+
+  // InstanceHolder<mojom::KioskInstance>::Observer overrides.
+  void OnInstanceReady() override;
+
+  // mojom::KioskHost overrides.
+  void OnMaintenanceSessionCreated(int32_t session_id) override;
+  void OnMaintenanceSessionFinished(int32_t session_id, bool success) override;
+
+ private:
+  // |delegate| should be alive while the ArcKioskBridge instance is alive.
+  ArcKioskBridge(ArcBridgeService* bridge_service, Delegate* delegate);
+
+  ArcBridgeService* const arc_bridge_service_;  // Owned by ArcServiceManager.
+
+  mojo::Binding<mojom::KioskHost> binding_;
+  Delegate* const delegate_;
+
+  // Tracks current maintenance session id.
+  int32_t session_id_ = -1;
+
+  DISALLOW_COPY_AND_ASSIGN(ArcKioskBridge);
+};
+
+}  // namespace arc
+
+#endif  // CHROME_BROWSER_CHROMEOS_ARC_KIOSK_ARC_KIOSK_BRIDGE_H_
diff --git a/components/arc/kiosk/arc_kiosk_bridge_unittest.cc b/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge_unittest.cc
similarity index 93%
rename from components/arc/kiosk/arc_kiosk_bridge_unittest.cc
rename to chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge_unittest.cc
index b2243f7c..9b3b1f4 100644
--- a/components/arc/kiosk/arc_kiosk_bridge_unittest.cc
+++ b/chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge_unittest.cc
@@ -6,8 +6,8 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "chrome/browser/chromeos/arc/kiosk/arc_kiosk_bridge.h"
 #include "components/arc/arc_bridge_service.h"
-#include "components/arc/kiosk/arc_kiosk_bridge.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -30,7 +30,7 @@
   ArcKioskBridgeTest()
       : bridge_service_(base::MakeUnique<ArcBridgeService>()),
         delegate_(base::MakeUnique<MockArcKioskBridgeDelegate>()),
-        kiosk_bridge_(base::MakeUnique<ArcKioskBridge>(bridge_service_.get(),
+        kiosk_bridge_(ArcKioskBridge::CreateForTesting(bridge_service_.get(),
                                                        delegate_.get())) {}
 
  protected:
diff --git a/chrome/browser/chromeos/policy/active_directory_policy_manager.cc b/chrome/browser/chromeos/policy/active_directory_policy_manager.cc
index 195140d..fc1fcbf 100644
--- a/chrome/browser/chromeos/policy/active_directory_policy_manager.cc
+++ b/chrome/browser/chromeos/policy/active_directory_policy_manager.cc
@@ -31,17 +31,23 @@
 std::unique_ptr<ActiveDirectoryPolicyManager>
 ActiveDirectoryPolicyManager::CreateForDevicePolicy(
     std::unique_ptr<CloudPolicyStore> store) {
+  // Can't use MakeUnique<> because the constructor is private.
   return base::WrapUnique(
-      new ActiveDirectoryPolicyManager(EmptyAccountId(), std::move(store)));
+      new ActiveDirectoryPolicyManager(EmptyAccountId(), base::TimeDelta(),
+                                       base::OnceClosure(), std::move(store)));
 }
 
 // static
 std::unique_ptr<ActiveDirectoryPolicyManager>
 ActiveDirectoryPolicyManager::CreateForUserPolicy(
     const AccountId& account_id,
+    base::TimeDelta initial_policy_fetch_timeout,
+    base::OnceClosure exit_session,
     std::unique_ptr<CloudPolicyStore> store) {
-  return base::WrapUnique(
-      new ActiveDirectoryPolicyManager(account_id, std::move(store)));
+  // Can't use MakeUnique<> because the constructor is private.
+  return base::WrapUnique(new ActiveDirectoryPolicyManager(
+      account_id, initial_policy_fetch_timeout, std::move(exit_session),
+      std::move(store)));
 }
 
 void ActiveDirectoryPolicyManager::Init(SchemaRegistry* registry) {
@@ -56,7 +62,7 @@
   PublishPolicy();
 
   scheduler_ = base::MakeUnique<PolicyScheduler>(
-      base::BindRepeating(&ActiveDirectoryPolicyManager::DoFetch,
+      base::BindRepeating(&ActiveDirectoryPolicyManager::DoPolicyFetch,
                           weak_ptr_factory_.GetWeakPtr()),
       base::BindRepeating(&ActiveDirectoryPolicyManager::OnPolicyFetched,
                           weak_ptr_factory_.GetWeakPtr()),
@@ -70,6 +76,9 @@
 
 bool ActiveDirectoryPolicyManager::IsInitializationComplete(
     PolicyDomain domain) const {
+  if (waiting_for_initial_policy_fetch_) {
+    return false;
+  }
   if (domain == POLICY_DOMAIN_CHROME) {
     return store_->is_initialized();
   }
@@ -84,6 +93,12 @@
     CloudPolicyStore* cloud_policy_store) {
   DCHECK_EQ(store_.get(), cloud_policy_store);
   PublishPolicy();
+  if (fetch_ever_completed_) {
+    // Policy is guaranteed to be up to date with the previous fetch result
+    // because OnPolicyFetched() cancels any potentially running Load()
+    // operations.
+    CancelWaitForInitialPolicy(fetch_ever_succeeded_ /* success */);
+  }
 }
 
 void ActiveDirectoryPolicyManager::OnStoreError(
@@ -93,12 +108,39 @@
   // complete on the ConfigurationPolicyProvider interface. Technically, this is
   // only required on the first load, but doesn't hurt in any case.
   PublishPolicy();
+  if (fetch_ever_completed_) {
+    CancelWaitForInitialPolicy(false /* success */);
+  }
+}
+
+void ActiveDirectoryPolicyManager::ForceTimeoutForTest() {
+  DCHECK(initial_policy_timeout_.IsRunning());
+  // Stop the timer to mimic what happens when a real timer fires, then invoke
+  // the timer callback directly.
+  initial_policy_timeout_.Stop();
+  OnBlockingFetchTimeout();
 }
 
 ActiveDirectoryPolicyManager::ActiveDirectoryPolicyManager(
     const AccountId& account_id,
+    base::TimeDelta initial_policy_fetch_timeout,
+    base::OnceClosure exit_session,
     std::unique_ptr<CloudPolicyStore> store)
-    : account_id_(account_id), store_(std::move(store)) {}
+    : account_id_(account_id),
+      waiting_for_initial_policy_fetch_(
+          !initial_policy_fetch_timeout.is_zero()),
+      initial_policy_fetch_may_fail_(!initial_policy_fetch_timeout.is_max()),
+      exit_session_(std::move(exit_session)),
+      store_(std::move(store)) {
+  // Delaying initialization complete is intended for user policy only.
+  DCHECK(account_id != EmptyAccountId() || !waiting_for_initial_policy_fetch_);
+  if (waiting_for_initial_policy_fetch_ && initial_policy_fetch_may_fail_) {
+    initial_policy_timeout_.Start(
+        FROM_HERE, initial_policy_fetch_timeout,
+        base::Bind(&ActiveDirectoryPolicyManager::OnBlockingFetchTimeout,
+                   weak_ptr_factory_.GetWeakPtr()));
+  }
+}
 
 void ActiveDirectoryPolicyManager::PublishPolicy() {
   if (!store_->is_initialized()) {
@@ -117,7 +159,7 @@
   UpdatePolicy(std::move(bundle));
 }
 
-void ActiveDirectoryPolicyManager::DoFetch(
+void ActiveDirectoryPolicyManager::DoPolicyFetch(
     base::OnceCallback<void(bool success)> callback) {
   chromeos::DBusThreadManager* thread_manager =
       chromeos::DBusThreadManager::Get();
@@ -133,12 +175,65 @@
 }
 
 void ActiveDirectoryPolicyManager::OnPolicyFetched(bool success) {
-  if (!success) {
+  fetch_ever_completed_ = true;
+  if (success) {
+    fetch_ever_succeeded_ = true;
+  } else {
     LOG(ERROR) << "Active Directory policy fetch failed.";
+    if (store_->is_initialized()) {
+      CancelWaitForInitialPolicy(false /* success */);
+    }
   }
-  // Load independently of success or failure to keep up to date with whatever
-  // has happened on the authpolicyd / session manager side.
+  // Load independently of success or failure to keep in sync with the state in
+  // session manager. This cancels any potentially running Load() operations
+  // thus it is guaranteed that at the next OnStoreLoaded() invocation the
+  // policy is up-to-date with what was fetched.
   store_->Load();
 }
 
+void ActiveDirectoryPolicyManager::OnBlockingFetchTimeout() {
+  DCHECK(waiting_for_initial_policy_fetch_);
+  LOG(WARNING) << "Timed out while waiting for the policy fetch. "
+               << "The session will start with the cached policy.";
+  CancelWaitForInitialPolicy(false);
+}
+
+void ActiveDirectoryPolicyManager::CancelWaitForInitialPolicy(bool success) {
+  if (!waiting_for_initial_policy_fetch_)
+    return;
+
+  initial_policy_timeout_.Stop();
+
+  // If the conditions to continue profile initialization are not met, the user
+  // session is exited and initialization is not set as completed.
+  // TODO(tnagel): Maybe add code to retry policy fetch?
+  if (!store_->has_policy()) {
+    // If there's no policy at all (not even cached) the user session must not
+    // continue.
+    LOG(ERROR) << "Policy could not be obtained. "
+               << "Aborting profile initialization";
+    // Prevent duplicate exit session calls.
+    if (exit_session_) {
+      std::move(exit_session_).Run();
+    }
+    return;
+  }
+  if (!success && !initial_policy_fetch_may_fail_) {
+    LOG(ERROR) << "Policy fetch failed for the user. "
+               << "Aborting profile initialization";
+    // Prevent duplicate exit session calls.
+    if (exit_session_) {
+      std::move(exit_session_).Run();
+    }
+    return;
+  }
+
+  // Set initialization complete.
+  waiting_for_initial_policy_fetch_ = false;
+
+  // Publish policy (even though it hasn't changed) in order to signal load
+  // complete on the ConfigurationPolicyProvider interface.
+  PublishPolicy();
+}
+
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/active_directory_policy_manager.h b/chrome/browser/chromeos/policy/active_directory_policy_manager.h
index 46cf742..5502fb82b 100644
--- a/chrome/browser/chromeos/policy/active_directory_policy_manager.h
+++ b/chrome/browser/chromeos/policy/active_directory_policy_manager.h
@@ -7,8 +7,11 @@
 
 #include <memory>
 
+#include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "components/policy/core/common/cloud/cloud_policy_store.h"
 #include "components/policy/core/common/configuration_policy_provider.h"
 #include "components/policy/core/common/policy_scheduler.h"
@@ -18,9 +21,11 @@
 
 // ConfigurationPolicyProvider for device or user policy from Active Directory.
 // The choice of constructor determines whether device or user policy is
-// provided.  The policy is fetched from the Domain Controller by authpolicyd
-// which stores it in session manager and from where it is loaded by
-// ActiveDirectoryPolicyManager.
+// provided.
+// Data flow: Triggered by DoPolicyFetch(), policy is fetched by authpolicyd and
+// stored in session manager with completion indicated by OnPolicyFetched().
+// From there policy load from session manager is triggered, completion of which
+// is notified via OnStoreLoaded()/OnStoreError().
 class ActiveDirectoryPolicyManager : public ConfigurationPolicyProvider,
                                      public CloudPolicyStore::Observer {
  public:
@@ -33,6 +38,8 @@
   // Create manager for |accound_id| user policy.
   static std::unique_ptr<ActiveDirectoryPolicyManager> CreateForUserPolicy(
       const AccountId& account_id,
+      base::TimeDelta initial_policy_fetch_timeout,
+      base::OnceClosure exit_session,
       std::unique_ptr<CloudPolicyStore> store);
 
   // ConfigurationPolicyProvider:
@@ -47,10 +54,25 @@
 
   CloudPolicyStore* store() const { return store_.get(); }
 
+  // Helper function to force a policy fetch timeout.
+  void ForceTimeoutForTest();
+
  private:
-  // |account_id| specifies the user to manage policy for.  If |account_id| is
+  // |account_id| specifies the user to manage policy for. If |account_id| is
   // empty, device policy is managed.
+  //
+  // The following applies to user policy only: If
+  // |initial_policy_fetch_timeout| is non-zero, IsInitializationComplete() is
+  // forced to false until either there has been a successful policy fetch from
+  // the server and a subsequent successful load from session manager or
+  // |initial_policy_fetch_timeout| has expired and there has been a successful
+  // load from session manager. The timeout may be set to TimeDelta::Max() to
+  // enforce successful policy fetch. In case the conditions for signaling
+  // initialization complete are not met, the user session is aborted by calling
+  // |exit_session|.
   ActiveDirectoryPolicyManager(const AccountId& account_id,
+                               base::TimeDelta initial_policy_fetch_timeout,
+                               base::OnceClosure exit_session,
                                std::unique_ptr<CloudPolicyStore> store);
 
   // Publish the policy that's currently cached in the store.
@@ -58,14 +80,49 @@
 
   // Calls into authpolicyd to fetch policy. Reports success or failure via
   // |callback|.
-  void DoFetch(PolicyScheduler::TaskCallback callback);
+  void DoPolicyFetch(PolicyScheduler::TaskCallback callback);
 
-  // Called by scheduler with result of policy fetch.
+  // Called by scheduler with result of policy fetch. This covers policy
+  // download, parsing and storing into session manager. (To access and publish
+  // the policy, the store needs to be reloaded from session manager.)
   void OnPolicyFetched(bool success);
 
-  const AccountId account_id_;
-  std::unique_ptr<CloudPolicyStore> store_;
+  // Called when |initial_policy_timeout_| times out, to cancel the blocking
+  // wait for the initial policy fetch.
+  void OnBlockingFetchTimeout();
 
+  // Cancels waiting for the initial policy fetch/load and flags the
+  // ConfigurationPolicyProvider ready (assuming all other initialization tasks
+  // have completed) or exits the session in case the requirements to continue
+  // have not been met. |success| denotes whether the policy fetch was
+  // successful.
+  void CancelWaitForInitialPolicy(bool success);
+
+  const AccountId account_id_;
+
+  // Whether we're waiting for a policy fetch to complete before reporting
+  // IsInitializationComplete().
+  bool waiting_for_initial_policy_fetch_;
+
+  // Whether the user session is continued in case of failure of initial policy
+  // fetch.
+  bool initial_policy_fetch_may_fail_;
+
+  // Whether policy fetch has ever been reported as completed by authpolicyd.
+  bool fetch_ever_completed_ = false;
+
+  // Whether policy fetch has ever been reported as successful by authpolicyd.
+  bool fetch_ever_succeeded_ = false;
+
+  // A timer that puts a hard limit on the maximum time to wait for the initial
+  // policy fetch/load.
+  base::Timer initial_policy_timeout_{false /* retain_user_task */,
+                                      false /* is_repeating */};
+
+  // Callback to exit the session.
+  base::OnceClosure exit_session_;
+
+  std::unique_ptr<CloudPolicyStore> store_;
   std::unique_ptr<PolicyScheduler> scheduler_;
 
   // Must be last member.
diff --git a/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc b/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc
new file mode 100644
index 0000000..d473ca4b
--- /dev/null
+++ b/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc
@@ -0,0 +1,432 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/policy/active_directory_policy_manager.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "chromeos/dbus/auth_policy_client.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
+#include "components/policy/core/common/schema_registry.h"
+#include "components/signin/core/account_id/account_id.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class TestAuthPolicyClient : public chromeos::AuthPolicyClient {
+ public:
+  void Init(dbus::Bus* bus) override { NOTIMPLEMENTED(); }
+
+  void JoinAdDomain(const std::string& machine_name,
+                    const std::string& user_principal_name,
+                    int password_fd,
+                    JoinCallback callback) override {
+    NOTIMPLEMENTED();
+  }
+
+  void AuthenticateUser(const std::string& user_principal_name,
+                        const std::string& object_guid,
+                        int password_fd,
+                        AuthCallback callback) override {
+    NOTIMPLEMENTED();
+  }
+
+  void GetUserStatus(const std::string& object_guid,
+                     GetUserStatusCallback callback) override {
+    NOTIMPLEMENTED();
+  }
+
+  void RefreshDevicePolicy(RefreshPolicyCallback callback) override {
+    NOTIMPLEMENTED();
+  }
+
+  void RefreshUserPolicy(const AccountId& account_id,
+                         RefreshPolicyCallback callback) override {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback),
+                                  refresh_user_policy_callback_success_));
+  }
+
+  void SetRefreshUserPolicyCallbackSuccess(bool success) {
+    refresh_user_policy_callback_success_ = success;
+  }
+
+ private:
+  bool refresh_user_policy_callback_success_ = true;
+};
+
+}  // namespace
+
+namespace policy {
+
+// Note that session exit is asynchronous and thus ActiveDirectoryPolicyManager
+// still needs to react reasonably to events happening after session exit has
+// been fired.
+class ActiveDirectoryPolicyManagerTest : public testing::Test {
+ public:
+  ActiveDirectoryPolicyManagerTest() {
+    auto mock_client_unique_ptr = base::MakeUnique<TestAuthPolicyClient>();
+    mock_client_ = mock_client_unique_ptr.get();
+    chromeos::DBusThreadManager::GetSetterForTesting()->SetAuthPolicyClient(
+        std::move(mock_client_unique_ptr));
+  }
+
+  ~ActiveDirectoryPolicyManagerTest() override {
+    EXPECT_EQ(session_exit_expected_, session_exited_);
+    policy_manager_->Shutdown();
+  }
+
+ protected:
+  // Expect that session exit will be called below. (Must only be called once.)
+  void ExpectSessionExit() {
+    ASSERT_FALSE(session_exit_expected_);
+    EXPECT_FALSE(session_exited_);
+    session_exit_expected_ = true;
+  }
+
+  // Expect that session exit has been called above. (Must only be called after
+  // ExpectSessionExit().)
+  void ExpectSessionExited() {
+    ASSERT_TRUE(session_exit_expected_);
+    EXPECT_TRUE(session_exited_);
+  }
+
+  // Closure to exit the session.
+  void ExitSession() {
+    EXPECT_TRUE(session_exit_expected_);
+    session_exited_ = true;
+  }
+
+  bool session_exited_ = false;
+  bool session_exit_expected_ = false;
+
+  // To be handed over to ActiveDirectoryPolicyManager.
+  base::OnceClosure exit_session_{
+      base::BindOnce(&ActiveDirectoryPolicyManagerTest::ExitSession,
+                     base::Unretained(this))};
+
+  // To be handed over to ActiveDirectoryPolicyManager ...
+  std::unique_ptr<MockCloudPolicyStore> mock_store_unique_ptr_{
+      base::MakeUnique<MockCloudPolicyStore>()};
+
+  // ... but keeping a non-owned pointer.
+  MockCloudPolicyStore* mock_store_{mock_store_unique_ptr_.get()};
+
+  // Owned by DBusThreadManager.
+  TestAuthPolicyClient* mock_client_;
+
+  SchemaRegistry schema_registry_;
+
+  // Initialized by the individual tests but owned by the test class so that it
+  // can be shut down automatically after the test has run.
+  std::unique_ptr<ActiveDirectoryPolicyManager> policy_manager_;
+
+ private:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+};
+
+TEST_F(ActiveDirectoryPolicyManagerTest, DontWait) {
+  policy_manager_ = ActiveDirectoryPolicyManager::CreateForUserPolicy(
+      AccountId::AdFromUserEmailObjGuid("bla", "ble"), base::TimeDelta(),
+      std::move(exit_session_), std::move(mock_store_unique_ptr_));
+  EXPECT_TRUE(policy_manager_);
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Configure mock policy fetch to fail.
+  mock_client_->SetRefreshUserPolicyCallbackSuccess(false);
+
+  // Trigger mock policy fetch from authpolicyd.
+  policy_manager_->Init(&schema_registry_);
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Simulate failed store load. Initialization is reported complete at this
+  // point.
+  mock_store_->NotifyStoreError();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Process reply for mock policy fetch.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Simulate failed store load.
+  mock_store_->NotifyStoreError();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+}
+
+// If the initial fetch timeout is infinite, initialization is only complete
+// after policy has been fetched and after that has been loaded.
+TEST_F(ActiveDirectoryPolicyManagerTest,
+       WaitInfinite_LoadSuccess_FetchSuccess) {
+  policy_manager_ = ActiveDirectoryPolicyManager::CreateForUserPolicy(
+      AccountId::AdFromUserEmailObjGuid("bla", "ble"), base::TimeDelta::Max(),
+      std::move(exit_session_), std::move(mock_store_unique_ptr_));
+  ASSERT_TRUE(policy_manager_);
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Configure mock policy fetch to succeed.
+  mock_client_->SetRefreshUserPolicyCallbackSuccess(true);
+
+  // Trigger mock policy fetch from authpolicyd.
+  policy_manager_->Init(&schema_registry_);
+
+  // Simulate successful store load.
+  mock_store_->policy_ = base::MakeUnique<enterprise_management::PolicyData>();
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Process reply for mock policy fetch.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Simulate successful store load. At this point initialization is complete.
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+}
+
+// If the initial fetch timeout is infinite, initialization does not complete if
+// load after fetch fails.
+TEST_F(ActiveDirectoryPolicyManagerTest,
+       WaitInfinite_LoadSuccess_FetchSuccess_LoadFail) {
+  policy_manager_ = ActiveDirectoryPolicyManager::CreateForUserPolicy(
+      AccountId::AdFromUserEmailObjGuid("bla", "ble"), base::TimeDelta::Max(),
+      std::move(exit_session_), std::move(mock_store_unique_ptr_));
+  ASSERT_TRUE(policy_manager_);
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Configure mock policy fetch to succeed.
+  mock_client_->SetRefreshUserPolicyCallbackSuccess(true);
+
+  // Trigger mock policy fetch from authpolicyd.
+  policy_manager_->Init(&schema_registry_);
+
+  // Simulate successful store load.
+  mock_store_->policy_ = base::MakeUnique<enterprise_management::PolicyData>();
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Process reply for mock policy fetch.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  ExpectSessionExit();
+
+  // Simulate failed store load.
+  mock_store_->NotifyStoreError();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  ExpectSessionExited();
+
+  // Simulate successful store load.
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+}
+
+// If the initial fetch timeout is infinite, failure in policy fetch prevents
+// initialization from finishing, ever.
+TEST_F(ActiveDirectoryPolicyManagerTest, WaitInfinite_LoadSuccess_FetchFail) {
+  policy_manager_ = ActiveDirectoryPolicyManager::CreateForUserPolicy(
+      AccountId::AdFromUserEmailObjGuid("bla", "ble"), base::TimeDelta::Max(),
+      std::move(exit_session_), std::move(mock_store_unique_ptr_));
+  ASSERT_TRUE(policy_manager_);
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Configure mock policy fetch to fail.
+  mock_client_->SetRefreshUserPolicyCallbackSuccess(false);
+
+  // Trigger mock policy fetch from authpolicyd.
+  policy_manager_->Init(&schema_registry_);
+
+  // Simulate successful store load.
+  mock_store_->policy_ = base::MakeUnique<enterprise_management::PolicyData>();
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  ExpectSessionExit();
+
+  // Process reply for mock policy fetch.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  ExpectSessionExited();
+
+  // Simulate successful store load.
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+}
+
+// If the initial fetch timeout is not infinite, we're in best-effort mode but
+// still require the policy load to succeed so that there's *some* policy
+// present (though possibly outdated).
+TEST_F(ActiveDirectoryPolicyManagerTest, WaitFinite_LoadSuccess_FetchFail) {
+  policy_manager_ = ActiveDirectoryPolicyManager::CreateForUserPolicy(
+      AccountId::AdFromUserEmailObjGuid("bla", "ble"),
+      base::TimeDelta::FromDays(365), std::move(exit_session_),
+      std::move(mock_store_unique_ptr_));
+  ASSERT_TRUE(policy_manager_);
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Configure mock policy fetch to fail.
+  mock_client_->SetRefreshUserPolicyCallbackSuccess(false);
+
+  // Trigger mock policy fetch from authpolicyd.
+  policy_manager_->Init(&schema_registry_);
+
+  // Simulate successful store load.
+  mock_store_->policy_ = base::MakeUnique<enterprise_management::PolicyData>();
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Process reply for mock policy fetch. At this point initialization is
+  // complete (we have waited for the fetch but now that we know it has failed
+  // we continue).
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Simulate successful store load.
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+}
+
+// If the initial fetch timeout is not infinite, we're in best-effort mode but
+// still require the policy load to succeed so that there's *some* policy
+// present (though possibly outdated). Here the sequence is inverted: Fetch
+// returns before load.
+TEST_F(ActiveDirectoryPolicyManagerTest, WaitFinite_FetchFail_LoadSuccess) {
+  policy_manager_ = ActiveDirectoryPolicyManager::CreateForUserPolicy(
+      AccountId::AdFromUserEmailObjGuid("bla", "ble"),
+      base::TimeDelta::FromDays(365), std::move(exit_session_),
+      std::move(mock_store_unique_ptr_));
+  ASSERT_TRUE(policy_manager_);
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Configure mock policy fetch to fail.
+  mock_client_->SetRefreshUserPolicyCallbackSuccess(false);
+
+  // Trigger mock policy fetch from authpolicyd.
+  policy_manager_->Init(&schema_registry_);
+
+  // Process reply for mock policy fetch.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Simulate successful store load.
+  mock_store_->policy_ = base::MakeUnique<enterprise_management::PolicyData>();
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+}
+
+// If the initial fetch timeout is not infinite, we're in best-effort mode but
+// if we can't load existing policy from disk we have to give up.
+TEST_F(ActiveDirectoryPolicyManagerTest, WaitFinite_LoadFail_FetchFail) {
+  policy_manager_ = ActiveDirectoryPolicyManager::CreateForUserPolicy(
+      AccountId::AdFromUserEmailObjGuid("bla", "ble"),
+      base::TimeDelta::FromDays(365), std::move(exit_session_),
+      std::move(mock_store_unique_ptr_));
+  ASSERT_TRUE(policy_manager_);
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Configure mock policy fetch to fail.
+  mock_client_->SetRefreshUserPolicyCallbackSuccess(false);
+
+  // Trigger mock policy fetch from authpolicyd.
+  policy_manager_->Init(&schema_registry_);
+
+  // Simulate failed store load.
+  mock_store_->NotifyStoreError();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  ExpectSessionExit();
+
+  // Process reply for mock policy fetch.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  ExpectSessionExited();
+
+  // Simulate successful store load.
+  mock_store_->policy_ = base::MakeUnique<enterprise_management::PolicyData>();
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+}
+
+// If the initial fetch timeout is not infinite, we're in best-effort mode and
+// upon timeout initialization is complete if any policy could be loaded from
+// disk.
+TEST_F(ActiveDirectoryPolicyManagerTest, WaitFinite_LoadSuccess_FetchTimeout) {
+  policy_manager_ = ActiveDirectoryPolicyManager::CreateForUserPolicy(
+      AccountId::AdFromUserEmailObjGuid("bla", "ble"),
+      base::TimeDelta::FromDays(365), std::move(exit_session_),
+      std::move(mock_store_unique_ptr_));
+  ASSERT_TRUE(policy_manager_);
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Configure mock policy fetch to fail.
+  mock_client_->SetRefreshUserPolicyCallbackSuccess(false);
+
+  // Trigger mock policy fetch from authpolicyd.
+  policy_manager_->Init(&schema_registry_);
+
+  // Simulate successful store load.
+  mock_store_->policy_ = base::MakeUnique<enterprise_management::PolicyData>();
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Simulate policy fetch timeout.
+  policy_manager_->ForceTimeoutForTest();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Process reply for mock policy fetch.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Simulate failed store load.
+  mock_store_->NotifyStoreError();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+}
+
+// If the initial fetch timeout is not infinite, we're in best-effort mode but
+// without a successful policy load we still can't continue.
+TEST_F(ActiveDirectoryPolicyManagerTest, WaitFinite_LoadTimeout_FetchTimeout) {
+  policy_manager_ = ActiveDirectoryPolicyManager::CreateForUserPolicy(
+      AccountId::AdFromUserEmailObjGuid("bla", "ble"),
+      base::TimeDelta::FromDays(365), std::move(exit_session_),
+      std::move(mock_store_unique_ptr_));
+  ASSERT_TRUE(policy_manager_);
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Configure mock policy fetch to fail.
+  mock_client_->SetRefreshUserPolicyCallbackSuccess(false);
+
+  // Trigger mock policy fetch from authpolicyd.
+  policy_manager_->Init(&schema_registry_);
+
+  ExpectSessionExit();
+
+  // Simulate policy fetch timeout.
+  policy_manager_->ForceTimeoutForTest();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  ExpectSessionExited();
+
+  // Process reply for mock policy fetch.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+
+  // Simulate successful store load.
+  mock_store_->policy_ = base::MakeUnique<enterprise_management::PolicyData>();
+  mock_store_->NotifyStoreLoaded();
+  EXPECT_TRUE(policy_manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
+}
+
+}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
index 2edac9ed..fe72e87 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
@@ -87,7 +87,6 @@
     std::unique_ptr<CloudPolicyStore> store,
     std::unique_ptr<CloudExternalDataManager> external_data_manager,
     const base::FilePath& component_policy_cache_path,
-    bool wait_for_policy_fetch,
     base::TimeDelta initial_policy_fetch_timeout,
     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
     const scoped_refptr<base::SequencedTaskRunner>& file_task_runner,
@@ -101,18 +100,16 @@
       store_(std::move(store)),
       external_data_manager_(std::move(external_data_manager)),
       component_policy_cache_path_(component_policy_cache_path),
-      wait_for_policy_fetch_(wait_for_policy_fetch) {
+      waiting_for_initial_policy_fetch_(
+          !initial_policy_fetch_timeout.is_zero()) {
   time_init_started_ = base::Time::Now();
 
-  // Caller must pass a non-zero policy_fetch_timeout iff
-  // |wait_for_policy_fetch| is true.
-  DCHECK_NE(wait_for_policy_fetch_, initial_policy_fetch_timeout.is_zero());
-  allow_failed_policy_fetches_ =
+  initial_policy_fetch_may_fail_ =
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           chromeos::switches::kAllowFailedPolicyFetchForTest) ||
       !initial_policy_fetch_timeout.is_max();
   // No need to set the timer when the timeout is infinite.
-  if (wait_for_policy_fetch_ && !initial_policy_fetch_timeout.is_max()) {
+  if (waiting_for_initial_policy_fetch_ && initial_policy_fetch_may_fail_) {
     policy_fetch_timeout_.Start(
         FROM_HERE,
         initial_policy_fetch_timeout,
@@ -174,10 +171,10 @@
     // store has already been loaded and contains a valid policy - the
     // registration setup in this case is performed by the CloudPolicyService
     // that is instantiated inside the CloudPolicyCore::Connect() method call.
-    // If that's the case and |wait_for_policy_fetch_| is true, then the policy
-    // fetch needs to be issued (it happens otherwise after the client
-    // registration is finished, in OnRegistrationStateChanged()).
-    if (client()->is_registered() && wait_for_policy_fetch_) {
+    // If that's the case and |waiting_for_initial_policy_fetch_| is true, then
+    // the policy fetch needs to be issued (it happens otherwise after the
+    // client registration is finished, in OnRegistrationStateChanged()).
+    if (client()->is_registered() && waiting_for_initial_policy_fetch_) {
       service()->RefreshPolicy(
           base::Bind(&UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch,
                      base::Unretained(this)));
@@ -230,7 +227,7 @@
   if (!CloudPolicyManager::IsInitializationComplete(domain))
     return false;
   if (domain == POLICY_DOMAIN_CHROME)
-    return !wait_for_policy_fetch_;
+    return !waiting_for_initial_policy_fetch_;
   return true;
 }
 
@@ -246,25 +243,27 @@
   // If the CloudPolicyClient isn't registered at this stage then it needs an
   // OAuth token for the initial registration.
   //
-  // If |wait_for_policy_fetch_| is true then Profile initialization is blocking
-  // on the initial policy fetch, so the token must be fetched immediately.
-  // In that case, the signin Profile is used to authenticate a Gaia request to
-  // fetch a refresh token, and then the policy token is fetched.
+  // If |waiting_for_initial_policy_fetch_| is true then Profile initialization
+  // is blocking on the initial policy fetch, so the token must be fetched
+  // immediately. In that case, the signin Profile is used to authenticate a
+  // Gaia request to fetch a refresh token, and then the policy token is
+  // fetched.
   //
-  // If |wait_for_policy_fetch_| is false then the UserCloudPolicyTokenForwarder
-  // service will eventually call OnAccessTokenAvailable() once an access token
-  // is available. That call may have already happened while waiting for
-  // initialization of the CloudPolicyService, so in that case check if an
-  // access token is already available.
+  // If |waiting_for_initial_policy_fetch_| is false then the
+  // UserCloudPolicyTokenForwarder service will eventually call
+  // OnAccessTokenAvailable() once an access token is available. That call may
+  // have already happened while waiting for initialization of the
+  // CloudPolicyService, so in that case check if an access token is already
+  // available.
   if (!client()->is_registered()) {
-    if (wait_for_policy_fetch_) {
+    if (waiting_for_initial_policy_fetch_) {
       FetchPolicyOAuthToken();
     } else if (!access_token_.empty()) {
       OnAccessTokenAvailable(access_token_);
     }
   }
 
-  if (!wait_for_policy_fetch_) {
+  if (!waiting_for_initial_policy_fetch_) {
     // If this isn't blocking on a policy fetch then
     // CloudPolicyManager::OnStoreLoaded() already published the cached policy.
     // Start the refresh scheduler now, which will eventually refresh the
@@ -285,7 +284,7 @@
     CloudPolicyClient* cloud_policy_client) {
   DCHECK_EQ(client(), cloud_policy_client);
 
-  if (wait_for_policy_fetch_) {
+  if (waiting_for_initial_policy_fetch_) {
     time_client_registered_ = base::Time::Now();
     if (!time_token_available_.is_null()) {
       UMA_HISTOGRAM_MEDIUM_TIMES(
@@ -310,7 +309,7 @@
 void UserCloudPolicyManagerChromeOS::OnClientError(
     CloudPolicyClient* cloud_policy_client) {
   DCHECK_EQ(client(), cloud_policy_client);
-  if (wait_for_policy_fetch_) {
+  if (waiting_for_initial_policy_fetch_) {
     UMA_HISTOGRAM_SPARSE_SLOWLY(kUMAInitialFetchClientError,
                                 cloud_policy_client->status());
   }
@@ -404,7 +403,7 @@
     const GoogleServiceAuthError& error) {
   DCHECK(!client()->is_registered());
   time_token_available_ = base::Time::Now();
-  if (wait_for_policy_fetch_) {
+  if (waiting_for_initial_policy_fetch_) {
     UMA_HISTOGRAM_MEDIUM_TIMES(kUMAInitialFetchDelayOAuth2Token,
                                time_token_available_ - time_init_completed_);
   }
@@ -445,14 +444,14 @@
 }
 
 void UserCloudPolicyManagerChromeOS::OnBlockingFetchTimeout() {
-  DCHECK(wait_for_policy_fetch_);
+  DCHECK(waiting_for_initial_policy_fetch_);
   LOG(WARNING) << "Timed out while waiting for the policy fetch. "
                << "The session will start with the cached policy.";
   CancelWaitForPolicyFetch(false);
 }
 
 void UserCloudPolicyManagerChromeOS::CancelWaitForPolicyFetch(bool success) {
-  if (!wait_for_policy_fetch_)
+  if (!waiting_for_initial_policy_fetch_)
     return;
 
   policy_fetch_timeout_.Stop();
@@ -461,7 +460,7 @@
   // to go forward after a failed policy fetch, then just return (profile
   // initialization will not complete).
   // TODO(atwilson): Add code to retry policy fetching.
-  if (!success && !allow_failed_policy_fetches_) {
+  if (!success && !initial_policy_fetch_may_fail_) {
     LOG(ERROR) << "Policy fetch failed for the user. "
                   "Aborting profile initialization";
     // Need to exit the current user, because we've already started this user's
@@ -470,10 +469,11 @@
     return;
   }
 
-  wait_for_policy_fetch_ = false;
+  waiting_for_initial_policy_fetch_ = false;
+
   CheckAndPublishPolicy();
-  // Now that |wait_for_policy_fetch_| is guaranteed to be false, the scheduler
-  // can be started.
+  // Now that |waiting_for_initial_policy_fetch_| is guaranteed to be false, the
+  // scheduler can be started.
   StartRefreshSchedulerIfReady();
 }
 
@@ -481,7 +481,7 @@
   if (core()->refresh_scheduler())
     return;  // Already started.
 
-  if (wait_for_policy_fetch_)
+  if (waiting_for_initial_policy_fetch_)
     return;  // Still waiting for the initial, blocking fetch.
 
   if (!service() || !local_state_)
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h
index 1aff359..59444c87 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h
@@ -45,10 +45,10 @@
                                        public CloudPolicyService::Observer,
                                        public KeyedService {
  public:
-  // If |wait_for_policy_fetch| is true, IsInitializationComplete() is forced to
-  // false until either there has been a successful policy fetch from the server
-  // or |initial_policy_fetch_timeout| has expired. (The timeout may be set to
-  // TimeDelta::Max() to block permanently.)
+  // If |initial_policy_fetch_timeout| is non-zero, IsInitializationComplete()
+  // is forced to false until either there has been a successful policy fetch
+  // from the server or |initial_policy_fetch_timeout| has expired. (The timeout
+  // may be set to TimeDelta::Max() to block permanently.)
   // |task_runner| is the runner for policy refresh tasks.
   // |file_task_runner| is used for file operations. Currently this must be the
   // FILE BrowserThread.
@@ -58,7 +58,6 @@
       std::unique_ptr<CloudPolicyStore> store,
       std::unique_ptr<CloudExternalDataManager> external_data_manager,
       const base::FilePath& component_policy_cache_path,
-      bool wait_for_policy_fetch,
       base::TimeDelta initial_policy_fetch_timeout,
       const scoped_refptr<base::SequencedTaskRunner>& task_runner,
       const scoped_refptr<base::SequencedTaskRunner>& file_task_runner,
@@ -127,19 +126,19 @@
                                   const GoogleServiceAuthError& error);
 
   // Completion handler for the explicit policy fetch triggered on startup in
-  // case |wait_for_policy_fetch_| is true. |success| is true if the fetch was
-  // successful.
+  // case |waiting_for_initial_policy_fetch_| is true. |success| is true if the
+  // fetch was successful.
   void OnInitialPolicyFetchComplete(bool success);
 
-  // Called when |policy_fetch_timeout_| times out, to cancel the blocking
-  // wait for the initial policy fetch.
+  // Called when |policy_fetch_timeout_| times out, to cancel the blocking wait
+  // for the initial policy fetch.
   void OnBlockingFetchTimeout();
 
-  // Cancels waiting for the policy fetch and flags the
+  // Cancels waiting for the initial policy fetch and flags the
   // ConfigurationPolicyProvider ready (assuming all other initialization tasks
-  // have completed). Pass |true| if policy fetch was successful (either
-  // because policy was successfully fetched, or if DMServer has notified us
-  // that the user is not managed).
+  // have completed). Pass |true| if policy fetch was successful (either because
+  // policy was successfully fetched, or if DMServer has notified us that the
+  // user is not managed).
   void CancelWaitForPolicyFetch(bool success);
 
   void StartRefreshSchedulerIfReady();
@@ -156,18 +155,18 @@
   // Path where policy for components will be cached.
   base::FilePath component_policy_cache_path_;
 
-  // Whether to wait for a policy fetch to complete before reporting
+  // Whether we're waiting for a policy fetch to complete before reporting
   // IsInitializationComplete().
-  bool wait_for_policy_fetch_;
+  bool waiting_for_initial_policy_fetch_;
 
-  // Whether we should allow policy fetches to fail, or wait forever until they
-  // succeed (typically we won't allow them to fail until we have loaded policy
-  // at least once).
-  bool allow_failed_policy_fetches_;
+  // Whether the user session is continued in case of failure of initial policy
+  // fetch.
+  bool initial_policy_fetch_may_fail_;
 
   // A timer that puts a hard limit on the maximum time to wait for the initial
   // policy fetch.
-  base::Timer policy_fetch_timeout_{false, false};
+  base::Timer policy_fetch_timeout_{false /* retain_user_task */,
+                                    false /* is_repeating */};
 
   // The pref service to pass to the refresh scheduler on initialization.
   PrefService* local_state_;
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
index d8f7558..ccb1d1d 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
@@ -88,17 +88,16 @@
  public:
   // Note: This method has to be public, so that a pointer to it may be obtained
   // in the test.
-  void MakeManagerWithPreloadedStore(bool wait_for_fetch,
-                                     int fetch_timeout_seconds) {
+  void MakeManagerWithPreloadedStore(int fetch_timeout_seconds) {
     std::unique_ptr<MockCloudPolicyStore> store =
         base::MakeUnique<MockCloudPolicyStore>();
     store->policy_.reset(new em::PolicyData(policy_data_));
     store->policy_map_.CopyFrom(policy_map_);
     store->NotifyStoreLoaded();
-    CreateManager(std::move(store), wait_for_fetch, fetch_timeout_seconds);
+    CreateManager(std::move(store), fetch_timeout_seconds);
     // The manager gets already initialized by this point if the store is
     // initialized and there is no blocking for policy fetch.
-    EXPECT_NE(wait_for_fetch,
+    EXPECT_NE(fetch_timeout_seconds != 0,
               manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
     InitAndConnectManager();
     EXPECT_TRUE(manager_->core()->service()->IsInitializationComplete());
@@ -179,11 +178,11 @@
     profile_manager_->DeleteTestingProfile(chrome::kInitialProfile);
   }
 
-  void MakeManagerWithEmptyStore(bool wait_for_fetch, int fetch_timeout) {
+  void MakeManagerWithEmptyStore(int fetch_timeout) {
     std::unique_ptr<MockCloudPolicyStore> store =
         base::MakeUnique<MockCloudPolicyStore>();
     EXPECT_CALL(*store, Load());
-    CreateManager(std::move(store), wait_for_fetch, fetch_timeout);
+    CreateManager(std::move(store), fetch_timeout);
     EXPECT_FALSE(manager_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
     InitAndConnectManager();
     Mock::VerifyAndClearExpectations(store_);
@@ -339,7 +338,6 @@
 
  private:
   void CreateManager(std::unique_ptr<MockCloudPolicyStore> store,
-                     bool wait_for_fetch,
                      int fetch_timeout_seconds) {
     store_ = store.get();
     external_data_manager_ = new MockCloudExternalDataManager;
@@ -347,11 +345,10 @@
     manager_.reset(new UserCloudPolicyManagerChromeOS(
         std::move(store),
         base::WrapUnique<MockCloudExternalDataManager>(external_data_manager_),
-        base::FilePath(), wait_for_fetch,
-        base::TimeDelta::FromSeconds(fetch_timeout_seconds), task_runner_,
-        task_runner_, task_runner_));
+        base::FilePath(), base::TimeDelta::FromSeconds(fetch_timeout_seconds),
+        task_runner_, task_runner_, task_runner_));
     manager_->AddObserver(&observer_);
-    should_create_token_forwarder_ = !wait_for_fetch;
+    should_create_token_forwarder_ = (fetch_timeout_seconds == 0);
   }
 
   void InitAndConnectManager() {
@@ -381,7 +378,7 @@
 TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFirstFetch) {
   // Tests the initialization of a manager whose Profile is waiting for the
   // initial fetch, when the policy cache is empty.
-  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(true, 1000));
+  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(1000));
 
   // Initialize the CloudPolicyService without any stored data.
   EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
@@ -404,7 +401,7 @@
 TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingRefreshFetch) {
   // Tests the initialization of a manager whose Profile is waiting for the
   // initial fetch, when a previously cached policy and DMToken already exist.
-  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(true, 1000));
+  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(1000));
 
   // Set the initially cached data and initialize the CloudPolicyService.
   // The initial policy fetch is issued using the cached DMToken.
@@ -425,13 +422,13 @@
   // performed by the manager).
   FetchPolicy(base::Bind(
       &UserCloudPolicyManagerChromeOSTest::MakeManagerWithPreloadedStore,
-      base::Unretained(this), true, 1000));
+      base::Unretained(this), 1000));
 }
 
 TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFetchStoreError) {
   // Tests the initialization of a manager whose Profile is waiting for the
   // initial fetch, when the initial store load fails.
-  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(true, 1000));
+  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(1000));
 
   // Initialize the CloudPolicyService without any stored data.
   EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
@@ -454,7 +451,7 @@
 TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFetchOAuthError) {
   // Tests the initialization of a manager whose Profile is waiting for the
   // initial fetch, when the OAuth2 token fetch fails.
-  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(true, 1000));
+  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(1000));
 
   // Initialize the CloudPolicyService without any stored data.
   EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
@@ -483,7 +480,7 @@
 TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFetchRegisterError) {
   // Tests the initialization of a manager whose Profile is waiting for the
   // initial fetch, when the device management registration fails.
-  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(true, 1000));
+  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(1000));
 
   // Initialize the CloudPolicyService without any stored data.
   EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
@@ -509,7 +506,7 @@
 TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFetchPolicyFetchError) {
   // Tests the initialization of a manager whose Profile is waiting for the
   // initial fetch, when the policy fetch request fails.
-  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(true, 1000));
+  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(1000));
 
   // Initialize the CloudPolicyService without any stored data.
   EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
@@ -548,7 +545,7 @@
 }
 
 TEST_F(UserCloudPolicyManagerChromeOSTest, BlockingFetchTimeout) {
-  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(true, 1000));
+  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(1000));
 
   // Initialize the CloudPolicyService without any stored data.
   EXPECT_FALSE(manager_->core()->service()->IsInitializationComplete());
@@ -567,7 +564,7 @@
 
 TEST_F(UserCloudPolicyManagerChromeOSTest, NonBlockingFirstFetch) {
   // Tests the first policy fetch request by a Profile that isn't managed.
-  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(false, 0));
+  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(0));
 
   // Initialize the CloudPolicyService without any stored data. Since the
   // manager is not waiting for the initial fetch, it will become initialized
@@ -613,7 +610,7 @@
 TEST_F(UserCloudPolicyManagerChromeOSTest, NonBlockingRefreshFetch) {
   // Tests a non-blocking initial policy fetch for a Profile that already has
   // a cached DMToken.
-  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(false, 0));
+  ASSERT_NO_FATAL_FAILURE(MakeManagerWithEmptyStore(0));
 
   // Set the initially cached data and initialize the CloudPolicyService.
   // The initial policy fetch is issued using the cached DMToken.
@@ -639,7 +636,7 @@
   // fetch, when a previously cached policy and DMToken are already loaded
   // before the manager is constructed. The manager gets initialized straight
   // away after the construction.
-  MakeManagerWithPreloadedStore(false, 0);
+  MakeManagerWithPreloadedStore(0);
   EXPECT_TRUE(manager_->policies().Equals(expected_bundle_));
 }
 
diff --git a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
index 4a3d4807..f3dd27ff 100644
--- a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
+++ b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/settings/install_attributes.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/policy/schema_registry_service.h"
 #include "chrome/browser/policy/schema_registry_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -261,8 +262,9 @@
 
   if (is_active_directory) {
     std::unique_ptr<ActiveDirectoryPolicyManager> manager =
-        ActiveDirectoryPolicyManager::CreateForUserPolicy(account_id,
-                                                          std::move(store));
+        ActiveDirectoryPolicyManager::CreateForUserPolicy(
+            account_id, initial_policy_fetch_timeout,
+            base::BindOnce(&chrome::AttemptUserExit), std::move(store));
     manager->Init(
         SchemaRegistryServiceFactory::GetForContext(profile)->registry());
 
@@ -272,9 +274,9 @@
     std::unique_ptr<UserCloudPolicyManagerChromeOS> manager =
         base::MakeUnique<UserCloudPolicyManagerChromeOS>(
             std::move(store), std::move(external_data_manager),
-            component_policy_cache_dir, wait_for_policy_fetch,
-            initial_policy_fetch_timeout, base::ThreadTaskRunnerHandle::Get(),
-            file_task_runner, io_task_runner);
+            component_policy_cache_dir, initial_policy_fetch_timeout,
+            base::ThreadTaskRunnerHandle::Get(), file_task_runner,
+            io_task_runner);
 
     // TODO(tnagel): Enable whitelist for Active Directory.
     bool wildcard_match = false;
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 1379b7be..256ac73 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -381,6 +381,11 @@
 const char kEnableTokenBindingName[] = "Token Binding.";
 const char kEnableTokenBindingDescription[] = "Enable Token Binding support.";
 
+const char kEnableUsernameCorrectionName[] = "Enable username correction";
+const char kEnableUsernameCorrectionDescription[] =
+    "While on the pending password state, add an edit button to the bubble so "
+    "that user can edit the username.";
+
 const char kEnableUseZoomForDsfName[] =
     "Use Blink's zoom for device scale factor.";
 const char kEnableUseZoomForDsfDescription[] =
@@ -2696,6 +2701,11 @@
     "Enables inspection of native UI elements. For local inspection use "
     "chrome://inspect#other";
 
+const char kUseCrosMidiServiceName[] = "Use Chrome OS MIDI Service";
+const char kUseCrosMidiServiceNameDescription[] =
+    "Use Chrome OS MIDI Service for Web MIDI and allow ARC to support Android "
+    "MIDI.";
+
 const char kMultideviceName[] = "Enable multidevice features";
 const char kMultideviceDescription[] =
     "Enables UI for controlling multidevice features.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index a0ec35a..cfee3e4 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -257,6 +257,9 @@
 extern const char kEnableTokenBindingName[];
 extern const char kEnableTokenBindingDescription[];
 
+extern const char kEnableUsernameCorrectionName[];
+extern const char kEnableUsernameCorrectionDescription[];
+
 extern const char kEnableUseZoomForDsfName[];
 extern const char kEnableUseZoomForDsfDescription[];
 extern const char kEnableUseZoomForDsfChoiceDefault[];
@@ -1396,6 +1399,9 @@
 extern const char kUiDevToolsName[];
 extern const char kUiDevToolsDescription[];
 
+extern const char kUseCrosMidiServiceName[];
+extern const char kUseCrosMidiServiceNameDescription[];
+
 extern const char kUseMusName[];
 extern const char kUseMusDescription[];
 extern const char kEnableMashDescription[];
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html
index ca47f6a..6f7d2eff 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.html
@@ -3,9 +3,7 @@
   <head>
     <meta charset="utf-8">
     <link rel="import" href="chrome://resources/html/polymer.html">
-    <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
     <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-    <link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
     <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
     <link rel="import" href="signin_shared_css.html">
     <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
@@ -17,20 +15,6 @@
         -webkit-margin-start: 0;
       }
 </if>
-      /* TODO(dbeam): de-duplicate this style with MD Settings. */
-      paper-checkbox {
-        --paper-checkbox-checked-color: var(--google-blue-500);
-        --paper-checkbox-label-color: inherit;
-        --paper-checkbox-label-spacing: 22px;
-        --paper-checkbox-size: 16px;
-        --paper-checkbox-unchecked-color: var(--paper-grey-600);
-        -webkit-margin-start: 2px;
-      }
-<if expr="is_macosx">
-      html:not(.focus-allowed) paper-checkbox {
-        --paper-checkbox-ink-size: 0;
-      }
-</if>
     </style>
   </head>
   <body>
@@ -72,9 +56,7 @@
           <div id="chrome-logo" class="logo"></div>
           <div>
             <div class="title">$i18n{syncConfirmationChromeSyncTitle}</div>
-            <div class="body text">
-              $i18nRaw{syncConfirmationChromeSyncBody}
-            </div>
+            <div class="body text">$i18n{syncConfirmationChromeSyncBody}</div>
           </div>
         </div>
         <div class="message-container">
@@ -93,11 +75,7 @@
           </div>
         </div>
         <div class="message-container">
-          <div class="body">
-            <paper-checkbox id="configure-before-signing-in">
-              $i18n{syncConfirmationSyncSettingsLabel}
-            </paper-checkbox>
-          </div>
+          <div class="body">$i18nRaw{syncConfirmationSyncSettingsLinkBody}</div>
         </div>
       </div>
       <div class="details" id="syncDisabledDetails">
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js
index 53d6853..5ae5baf 100644
--- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js
+++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js
@@ -6,18 +6,23 @@
   'use strict';
 
   function onConfirm(e) {
-    chrome.send('confirm', [$('configure-before-signing-in').checked]);
+    chrome.send('confirm');
   }
 
   function onUndo(e) {
     chrome.send('undo');
   }
 
+  function onGoToSettings(e) {
+    chrome.send('goToSettings');
+  }
+
   function initialize() {
     document.addEventListener('keydown', onKeyDown);
     $('confirmButton').addEventListener('click', onConfirm);
     $('undoButton').addEventListener('click', onUndo);
     if (loadTimeData.getBoolean('isSyncAllowed')) {
+      $('settingsLink').addEventListener('click', onGoToSettings);
       $('profile-picture').addEventListener('load', onPictureLoaded);
       $('syncDisabledDetails').hidden = true;
     } else {
@@ -32,7 +37,6 @@
 
   function clearFocus() {
     document.activeElement.blur();
-    document.documentElement.classList.add('focus-allowed');
   }
 
   function setUserImageURL(url) {
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
index 34ef988f..4ada3cac 100644
--- a/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
@@ -19,6 +19,7 @@
 #include "net/cert/signed_certificate_timestamp_and_status.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
 #include "net/test/test_data_directory.h"
 #include "net/test/url_request/url_request_failed_job.h"
@@ -337,26 +338,34 @@
 
   std::unique_ptr<net::test_server::HttpResponse> HandleReportPreflight(
       const net::test_server::HttpRequest& request) {
-    num_requests_++;
-    if (!requests_callback_.is_null()) {
-      requests_callback_.Run();
-    }
+    handled_preflight_ = true;
     std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
         new net::test_server::BasicHttpResponse());
     http_response->set_code(net::HTTP_OK);
     for (const auto& cors_header : cors_headers_) {
       http_response->AddCustomHeader(cors_header.first, cors_header.second);
     }
+
+    // If WaitForReportPreflight() has been called, signal that a preflight has
+    // been handled. Do this after copying |cors_headers_| to the response,
+    // because tests can mutate |cors_headers_| immediately after
+    // |preflight_run_loop_| quits.
+    if (preflight_run_loop_) {
+      preflight_run_loop_->Quit();
+    }
+
     return http_response;
   }
 
+  // Can only be called once per test to wait for a single preflight.
   void WaitForReportPreflight() {
-    if (num_requests_ >= 1) {
+    DCHECK(!preflight_run_loop_)
+        << "WaitForReportPreflight should only be called once per test";
+    if (handled_preflight_) {
       return;
     }
-    base::RunLoop run_loop;
-    requests_callback_ = run_loop.QuitClosure();
-    run_loop.Run();
+    preflight_run_loop_ = base::MakeUnique<base::RunLoop>();
+    preflight_run_loop_->Run();
   }
 
  protected:
@@ -399,8 +408,11 @@
  private:
   content::TestBrowserThreadBundle thread_bundle_;
   net::EmbeddedTestServer report_server_;
-  uint32_t num_requests_ = 0;
-  base::Closure requests_callback_;
+  // Set to true when HandleReportPreflight() has been called. Used by
+  // WaitForReportPreflight() to determine when to just return immediately
+  // because a preflight has already been handled.
+  bool handled_preflight_ = false;
+  std::unique_ptr<base::RunLoop> preflight_run_loop_;
   std::map<std::string, std::string> cors_headers_{
       {"Access-Control-Allow-Origin", "*"},
       {"Access-Control-Allow-Methods", "GET,POST"},
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
index 9427fe30..3f0d19e 100644
--- a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
+++ b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h"
 
+#include <utility>
+
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/ui/views/ime_driver/remote_text_input_client.h"
 
@@ -28,16 +30,15 @@
   input_method_chromeos_->OnCaretBoundsChanged(client_.get());
 }
 
-void InputMethodBridge::ProcessKeyEvent(
-    std::unique_ptr<ui::Event> event,
-    const ProcessKeyEventCallback& callback) {
+void InputMethodBridge::ProcessKeyEvent(std::unique_ptr<ui::Event> event,
+                                        ProcessKeyEventCallback callback) {
   DCHECK(event->IsKeyEvent());
   ui::KeyEvent* key_event = event->AsKeyEvent();
   if (!key_event->is_char()) {
     input_method_chromeos_->DispatchKeyEvent(key_event, std::move(callback));
   } else {
     const bool handled = false;
-    callback.Run(handled);
+    std::move(callback).Run(handled);
   }
 }
 
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h
index 8ca254d..b54608c 100644
--- a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h
+++ b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h
@@ -20,7 +20,7 @@
   void OnTextInputTypeChanged(ui::TextInputType text_input_type) override;
   void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override;
   void ProcessKeyEvent(std::unique_ptr<ui::Event> key_event,
-                       const ProcessKeyEventCallback& callback) override;
+                       ProcessKeyEventCallback callback) override;
   void CancelComposition() override;
 
  private:
diff --git a/chrome/browser/ui/views/ime_driver/simple_input_method.cc b/chrome/browser/ui/views/ime_driver/simple_input_method.cc
index 7ca08882..0dd51a3 100644
--- a/chrome/browser/ui/views/ime_driver/simple_input_method.cc
+++ b/chrome/browser/ui/views/ime_driver/simple_input_method.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/views/ime_driver/simple_input_method.h"
 
+#include <utility>
+
 SimpleInputMethod::SimpleInputMethod() {}
 
 SimpleInputMethod::~SimpleInputMethod() {}
@@ -13,10 +15,9 @@
 
 void SimpleInputMethod::OnCaretBoundsChanged(const gfx::Rect& caret_bounds) {}
 
-void SimpleInputMethod::ProcessKeyEvent(
-    std::unique_ptr<ui::Event> key_event,
-    const ProcessKeyEventCallback& callback) {
-  callback.Run(false);
+void SimpleInputMethod::ProcessKeyEvent(std::unique_ptr<ui::Event> key_event,
+                                        ProcessKeyEventCallback callback) {
+  std::move(callback).Run(false);
 }
 
 void SimpleInputMethod::CancelComposition() {}
diff --git a/chrome/browser/ui/views/ime_driver/simple_input_method.h b/chrome/browser/ui/views/ime_driver/simple_input_method.h
index 9f666283..f262c21d 100644
--- a/chrome/browser/ui/views/ime_driver/simple_input_method.h
+++ b/chrome/browser/ui/views/ime_driver/simple_input_method.h
@@ -20,7 +20,7 @@
   void OnTextInputTypeChanged(ui::TextInputType text_input_type) override;
   void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override;
   void ProcessKeyEvent(std::unique_ptr<ui::Event> key_event,
-                       const ProcessKeyEventCallback& callback) override;
+                       ProcessKeyEventCallback callback) override;
   void CancelComposition() override;
 
  private:
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
index 0a99dbb7..ea30744 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
@@ -56,6 +56,9 @@
                  base::Unretained(this)));
   web_ui()->RegisterMessageCallback("undo",
       base::Bind(&SyncConfirmationHandler::HandleUndo, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "goToSettings", base::Bind(&SyncConfirmationHandler::HandleGoToSettings,
+                                 base::Unretained(this)));
   web_ui()->RegisterMessageCallback("initializedWithSize",
       base::Bind(&SyncConfirmationHandler::HandleInitializedWithSize,
                  base::Unretained(this)));
@@ -63,11 +66,12 @@
 
 void SyncConfirmationHandler::HandleConfirm(const base::ListValue* args) {
   did_user_explicitly_interact = true;
-  bool configure_sync_first = false;
-  CHECK(args->GetBoolean(0, &configure_sync_first));
-  CloseModalSigninWindow(configure_sync_first
-                             ? LoginUIService::CONFIGURE_SYNC_FIRST
-                             : LoginUIService::SYNC_WITH_DEFAULT_SETTINGS);
+  CloseModalSigninWindow(LoginUIService::SYNC_WITH_DEFAULT_SETTINGS);
+}
+
+void SyncConfirmationHandler::HandleGoToSettings(const base::ListValue* args) {
+  did_user_explicitly_interact = true;
+  CloseModalSigninWindow(LoginUIService::CONFIGURE_SYNC_FIRST);
 }
 
 void SyncConfirmationHandler::HandleUndo(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.h b/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
index 7de6334..8953681e 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
@@ -36,8 +36,7 @@
  protected:
   // Handles "confirm" message from the page. No arguments.
   // This message is sent when the user confirms that they want complete sign in
-  // with default sync settings. Passed a single boolean argument: whether to
-  // configure settings before signing in.
+  // with default sync settings.
   virtual void HandleConfirm(const base::ListValue* args);
 
   // Handles "undo" message from the page. No arguments.
@@ -45,6 +44,12 @@
   // dialog, which aborts signin and prevents sync from starting.
   virtual void HandleUndo(const base::ListValue* args);
 
+  // Handles "goToSettings" message from the page. No arguments.
+  // This message is sent when the user clicks on the "Settings" link in the
+  // sync confirmation dialog, which completes sign in but takes the user to the
+  // sync settings page for configuration before starting sync.
+  virtual void HandleGoToSettings(const base::ListValue* args);
+
   // Handles the web ui message sent when the html content is done being laid
   // out and it's time to resize the native view hosting it to fit. |args| is
   // a single integer value for the height the native view should resize to.
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
index 2627333..c6e6599 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
@@ -43,6 +43,7 @@
   using SyncConfirmationHandler::HandleConfirm;
   using SyncConfirmationHandler::HandleUndo;
   using SyncConfirmationHandler::HandleInitializedWithSize;
+  using SyncConfirmationHandler::HandleGoToSettings;
   using SyncConfirmationHandler::SetUserImageURL;
 
  private:
@@ -91,7 +92,6 @@
  public:
   SyncConfirmationHandlerTest()
       : did_user_explicitly_interact(false), web_ui_(new content::TestWebUI) {}
-
   void SetUp() override {
     BrowserWithTestWindowTest::SetUp();
     chrome::NewTab(browser());
@@ -119,10 +119,11 @@
     web_ui_.reset();
     BrowserWithTestWindowTest::TearDown();
 
-    if (did_user_explicitly_interact)
+    if (did_user_explicitly_interact) {
       EXPECT_EQ(0, user_action_tester()->GetActionCount("Signin_Abort_Signin"));
-    else
+    } else {
       EXPECT_EQ(1, user_action_tester()->GetActionCount("Signin_Abort_Signin"));
+    }
   }
 
   TestingSyncConfirmationHandler* handler() {
@@ -316,9 +317,7 @@
   EXPECT_FALSE(sync()->IsFirstSetupComplete());
   EXPECT_TRUE(sync()->IsFirstSetupInProgress());
 
-  base::ListValue args;
-  args.AppendBoolean(false /* show advanced */);
-  handler()->HandleConfirm(&args);
+  handler()->HandleConfirm(nullptr);
   did_user_explicitly_interact = true;
 
   EXPECT_FALSE(sync()->IsFirstSetupInProgress());
@@ -336,9 +335,7 @@
   EXPECT_FALSE(sync()->IsFirstSetupComplete());
   EXPECT_TRUE(sync()->IsFirstSetupInProgress());
 
-  base::ListValue args;
-  args.AppendBoolean(true /* show advanced */);
-  handler()->HandleConfirm(&args);
+  handler()->HandleGoToSettings(nullptr);
   did_user_explicitly_interact = true;
 
   EXPECT_FALSE(sync()->IsFirstSetupInProgress());
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
index 701a65f..e6e68e00 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
@@ -38,8 +38,8 @@
       IDS_SYNC_CONFIRMATION_PERSONALIZE_SERVICES_TITLE);
   source->AddLocalizedString("syncConfirmationPersonalizeServicesBody",
       IDS_SYNC_CONFIRMATION_PERSONALIZE_SERVICES_BODY);
-  source->AddLocalizedString("syncConfirmationSyncSettingsLabel",
-                             IDS_SYNC_CONFIRMATION_SYNC_SETTINGS_LABEL);
+  source->AddLocalizedString("syncConfirmationSyncSettingsLinkBody",
+                             IDS_SYNC_CONFIRMATION_SYNC_SETTINGS_LINK_BODY);
   source->AddLocalizedString("syncDisabledConfirmationDetails",
                              IDS_SYNC_DISABLED_CONFIRMATION_DETAILS);
 
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc
index e25de68..88571830 100644
--- a/chromeos/dbus/dbus_thread_manager.cc
+++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -309,6 +309,12 @@
 
 DBusThreadManagerSetter::~DBusThreadManagerSetter() {}
 
+void DBusThreadManagerSetter::SetAuthPolicyClient(
+    std::unique_ptr<AuthPolicyClient> client) {
+  DBusThreadManager::Get()->clients_browser_->auth_policy_client_ =
+      std::move(client);
+}
+
 void DBusThreadManagerSetter::SetBiodClient(
     std::unique_ptr<BiodClient> client) {
   DBusThreadManager::Get()->clients_common_->biod_client_ = std::move(client);
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h
index c7f793d..b16c9eeb 100644
--- a/chromeos/dbus/dbus_thread_manager.h
+++ b/chromeos/dbus/dbus_thread_manager.h
@@ -180,6 +180,7 @@
  public:
   ~DBusThreadManagerSetter();
 
+  void SetAuthPolicyClient(std::unique_ptr<AuthPolicyClient> client);
   void SetBiodClient(std::unique_ptr<BiodClient> client);
   void SetCrasAudioClient(std::unique_ptr<CrasAudioClient> client);
   void SetCrosDisksClient(std::unique_ptr<CrosDisksClient> client);
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index 2414bb9..542f5a50 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -43,8 +43,6 @@
     "intent_helper/link_handler_model_impl.h",
     "intent_helper/page_transition_util.cc",
     "intent_helper/page_transition_util.h",
-    "kiosk/arc_kiosk_bridge.cc",
-    "kiosk/arc_kiosk_bridge.h",
     "metrics/arc_metrics_service.cc",
     "metrics/arc_metrics_service.h",
     "net/arc_net_host_impl.cc",
@@ -227,7 +225,6 @@
     "intent_helper/intent_filter_unittest.cc",
     "intent_helper/link_handler_model_impl_unittest.cc",
     "intent_helper/page_transition_util_unittest.cc",
-    "kiosk/arc_kiosk_bridge_unittest.cc",
   ]
 
   deps = [
diff --git a/components/arc/kiosk/arc_kiosk_bridge.cc b/components/arc/kiosk/arc_kiosk_bridge.cc
deleted file mode 100644
index 32ffe52..0000000
--- a/components/arc/kiosk/arc_kiosk_bridge.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/arc/kiosk/arc_kiosk_bridge.h"
-
-#include "components/arc/arc_bridge_service.h"
-
-namespace arc {
-
-ArcKioskBridge::ArcKioskBridge(ArcBridgeService* bridge_service,
-                               Delegate* delegate)
-    : ArcService(bridge_service), binding_(this), delegate_(delegate) {
-  DCHECK(delegate_);
-  arc_bridge_service()->kiosk()->AddObserver(this);
-}
-
-ArcKioskBridge::~ArcKioskBridge() {
-  arc_bridge_service()->kiosk()->RemoveObserver(this);
-}
-
-void ArcKioskBridge::OnInstanceReady() {
-  mojom::KioskInstance* kiosk_instance =
-      ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service()->kiosk(), Init);
-  DCHECK(kiosk_instance);
-  mojom::KioskHostPtr host_proxy;
-  binding_.Bind(mojo::MakeRequest(&host_proxy));
-  kiosk_instance->Init(std::move(host_proxy));
-}
-
-void ArcKioskBridge::OnMaintenanceSessionCreated(int32_t session_id) {
-  session_id_ = session_id;
-  delegate_->OnMaintenanceSessionCreated();
-  // TODO(poromov@) Show appropriate splash screen.
-}
-
-void ArcKioskBridge::OnMaintenanceSessionFinished(int32_t session_id,
-                                                  bool success) {
-  // Filter only callbacks for the started kiosk session.
-  if (session_id != session_id_)
-    return;
-  session_id_ = -1;
-  delegate_->OnMaintenanceSessionFinished();
-}
-
-}  // namespace arc
diff --git a/components/arc/kiosk/arc_kiosk_bridge.h b/components/arc/kiosk/arc_kiosk_bridge.h
deleted file mode 100644
index 2c46e05..0000000
--- a/components/arc/kiosk/arc_kiosk_bridge.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_ARC_KIOSK_ARC_KIOSK_BRIDGE_H_
-#define COMPONENTS_ARC_KIOSK_ARC_KIOSK_BRIDGE_H_
-
-#include <map>
-
-#include "base/macros.h"
-#include "components/arc/arc_service.h"
-#include "components/arc/common/kiosk.mojom.h"
-#include "components/arc/instance_holder.h"
-#include "mojo/public/cpp/bindings/binding.h"
-
-namespace arc {
-
-class ArcBridgeService;
-
-class ArcKioskBridge : public ArcService,
-                       public InstanceHolder<mojom::KioskInstance>::Observer,
-                       public mojom::KioskHost {
- public:
-  // Received IPCs are passed to this delegate.
-  class Delegate {
-   public:
-    virtual ~Delegate() = default;
-    virtual void OnMaintenanceSessionCreated() = 0;
-    virtual void OnMaintenanceSessionFinished() = 0;
-  };
-
-  // |delegate| should be alive while the ArcKioskBridge instance is alive.
-  ArcKioskBridge(ArcBridgeService* bridge_service, Delegate* delegate);
-  ~ArcKioskBridge() override;
-
-  // InstanceHolder<mojom::KioskInstance>::Observer overrides.
-  void OnInstanceReady() override;
-
-  // mojom::KioskHost overrides.
-  void OnMaintenanceSessionCreated(int32_t session_id) override;
-  void OnMaintenanceSessionFinished(int32_t session_id, bool success) override;
-
- private:
-  mojo::Binding<mojom::KioskHost> binding_;
-  Delegate* const delegate_;
-
-  // Tracks current maintenance session id.
-  int32_t session_id_ = -1;
-
-  DISALLOW_COPY_AND_ASSIGN(ArcKioskBridge);
-};
-
-}  // namespace arc
-
-#endif  // COMPONENTS_ARC_KIOSK_ARC_KIOSK_BRIDGE_H_
diff --git a/components/browsing_data/core/BUILD.gn b/components/browsing_data/core/BUILD.gn
index c3fb039a..4f0e479 100644
--- a/components/browsing_data/core/BUILD.gn
+++ b/components/browsing_data/core/BUILD.gn
@@ -23,6 +23,8 @@
     "counters/passwords_counter.h",
     "counters/site_settings_counter.cc",
     "counters/site_settings_counter.h",
+    "counters/sync_tracker.cc",
+    "counters/sync_tracker.h",
     "history_notice_utils.cc",
     "history_notice_utils.h",
     "pref_names.cc",
diff --git a/components/browsing_data/core/counters/autofill_counter.cc b/components/browsing_data/core/counters/autofill_counter.cc
index 0b9a7d8..30127cb 100644
--- a/components/browsing_data/core/counters/autofill_counter.cc
+++ b/components/browsing_data/core/counters/autofill_counter.cc
@@ -31,26 +31,21 @@
     scoped_refptr<autofill::AutofillWebDataService> web_data_service,
     syncer::SyncService* sync_service)
     : web_data_service_(web_data_service),
-      sync_service_(sync_service),
+      sync_tracker_(this, sync_service),
       suggestions_query_(0),
       credit_cards_query_(0),
       addresses_query_(0),
       num_suggestions_(0),
       num_credit_cards_(0),
-      num_addresses_(0),
-      autofill_sync_enabled_() {}
+      num_addresses_(0) {}
 
 AutofillCounter::~AutofillCounter() {
   CancelAllRequests();
-  if (sync_service_)
-    sync_service_->RemoveObserver(this);
 }
 
 void AutofillCounter::OnInitialized() {
   DCHECK(web_data_service_);
-  if (sync_service_)
-    sync_service_->AddObserver(this);
-  autofill_sync_enabled_ = IsAutofillSyncEnabled(sync_service_);
+  sync_tracker_.OnInitialized(base::Bind(&IsAutofillSyncEnabled));
 }
 
 const char* AutofillCounter::GetPrefName() const {
@@ -172,7 +167,7 @@
 
   auto reported_result = base::MakeUnique<AutofillResult>(
       this, num_suggestions_, num_credit_cards_, num_addresses_,
-      autofill_sync_enabled_);
+      sync_tracker_.IsSyncActive());
   ReportResult(std::move(reported_result));
 }
 
@@ -185,14 +180,6 @@
     web_data_service_->CancelRequest(addresses_query_);
 }
 
-void AutofillCounter::OnStateChanged(syncer::SyncService* sync) {
-  bool sync_enabled_new = IsAutofillSyncEnabled(sync);
-  if (autofill_sync_enabled_ != sync_enabled_new) {
-    autofill_sync_enabled_ = sync_enabled_new;
-    Restart();
-  }
-}
-
 // AutofillCounter::AutofillResult ---------------------------------------------
 
 AutofillCounter::AutofillResult::AutofillResult(const AutofillCounter* source,
diff --git a/components/browsing_data/core/counters/autofill_counter.h b/components/browsing_data/core/counters/autofill_counter.h
index 7352a0c..8c657dc 100644
--- a/components/browsing_data/core/counters/autofill_counter.h
+++ b/components/browsing_data/core/counters/autofill_counter.h
@@ -10,7 +10,7 @@
 #include "base/time/time.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/browsing_data/core/counters/browsing_data_counter.h"
-#include "components/sync/driver/sync_service_observer.h"
+#include "components/browsing_data/core/counters/sync_tracker.h"
 #include "components/webdata/common/web_data_service_consumer.h"
 
 namespace autofill {
@@ -20,8 +20,7 @@
 namespace browsing_data {
 
 class AutofillCounter : public browsing_data::BrowsingDataCounter,
-                        public WebDataServiceConsumer,
-                        public syncer::SyncServiceObserver {
+                        public WebDataServiceConsumer {
  public:
   class AutofillResult : public SyncResult {
    public:
@@ -68,16 +67,13 @@
       WebDataServiceBase::Handle handle,
       std::unique_ptr<WDTypedResult> result) override;
 
-  // SyncServiceObserver implementation.
-  void OnStateChanged(syncer::SyncService* sync) override;
-
   // Cancel all pending requests to AutofillWebdataService.
   void CancelAllRequests();
 
   base::ThreadChecker thread_checker_;
 
   scoped_refptr<autofill::AutofillWebDataService> web_data_service_;
-  syncer::SyncService* sync_service_;
+  SyncTracker sync_tracker_;
 
   WebDataServiceBase::Handle suggestions_query_;
   WebDataServiceBase::Handle credit_cards_query_;
@@ -86,7 +82,6 @@
   ResultInt num_suggestions_;
   ResultInt num_credit_cards_;
   ResultInt num_addresses_;
-  bool autofill_sync_enabled_;
 
   base::Time period_start_for_testing_;
 
diff --git a/components/browsing_data/core/counters/history_counter.cc b/components/browsing_data/core/counters/history_counter.cc
index c75416a..376e5e8 100644
--- a/components/browsing_data/core/counters/history_counter.cc
+++ b/components/browsing_data/core/counters/history_counter.cc
@@ -23,24 +23,19 @@
     syncer::SyncService* sync_service)
     : history_service_(history_service),
       web_history_service_callback_(callback),
-      sync_service_(sync_service),
+      sync_tracker_(this, sync_service),
       has_synced_visits_(false),
       local_counting_finished_(false),
       web_counting_finished_(false),
-      history_sync_enabled_(false),
       weak_ptr_factory_(this) {
   DCHECK(history_service_);
 }
 
-HistoryCounter::~HistoryCounter() {
-  if (sync_service_)
-    sync_service_->RemoveObserver(this);
-}
+HistoryCounter::~HistoryCounter() {}
 
 void HistoryCounter::OnInitialized() {
-  if (sync_service_)
-    sync_service_->AddObserver(this);
-  history_sync_enabled_ = !!GetWebHistoryService();
+  sync_tracker_.OnInitialized(base::Bind(&HistoryCounter::IsHistorySyncEnabled,
+                                         base::Unretained(this)));
 }
 
 bool HistoryCounter::HasTrackedTasks() {
@@ -182,18 +177,12 @@
     return;
 
   ReportResult(base::MakeUnique<HistoryResult>(
-      this, local_result_, history_sync_enabled_, has_synced_visits_));
+      this, local_result_, sync_tracker_.IsSyncActive(), has_synced_visits_));
 }
 
-void HistoryCounter::OnStateChanged(syncer::SyncService* sync) {
-  bool history_sync_enabled_new_state = !!GetWebHistoryService();
-
-  // If the history sync was just enabled or disabled, restart the counter
-  // so that we update the result accordingly.
-  if (history_sync_enabled_ != history_sync_enabled_new_state) {
-    history_sync_enabled_ = history_sync_enabled_new_state;
-    Restart();
-  }
+bool HistoryCounter::IsHistorySyncEnabled(
+    const syncer::SyncService* sync_service) {
+  return !!GetWebHistoryService();
 }
 
 HistoryCounter::HistoryResult::HistoryResult(const HistoryCounter* source,
diff --git a/components/browsing_data/core/counters/history_counter.h b/components/browsing_data/core/counters/history_counter.h
index 15cf9060..985365c 100644
--- a/components/browsing_data/core/counters/history_counter.h
+++ b/components/browsing_data/core/counters/history_counter.h
@@ -10,15 +10,14 @@
 #include "base/task/cancelable_task_tracker.h"
 #include "base/timer/timer.h"
 #include "components/browsing_data/core/counters/browsing_data_counter.h"
+#include "components/browsing_data/core/counters/sync_tracker.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/history/core/browser/web_history_service.h"
 #include "components/sync/driver/sync_service.h"
-#include "components/sync/driver/sync_service_observer.h"
 
 namespace browsing_data {
 
-class HistoryCounter : public browsing_data::BrowsingDataCounter,
-                       public syncer::SyncServiceObserver {
+class HistoryCounter : public browsing_data::BrowsingDataCounter {
  public:
   typedef base::Callback<history::WebHistoryService*()>
       GetUpdatedWebHistoryServiceCallback;
@@ -60,14 +59,13 @@
 
   history::WebHistoryService* GetWebHistoryService();
 
-  // SyncServiceObserver implementation.
-  void OnStateChanged(syncer::SyncService* sync) override;
+  bool IsHistorySyncEnabled(const syncer::SyncService* sync_service);
 
   history::HistoryService* history_service_;
 
   GetUpdatedWebHistoryServiceCallback web_history_service_callback_;
 
-  syncer::SyncService* sync_service_;
+  SyncTracker sync_tracker_;
 
   bool has_synced_visits_;
 
@@ -82,8 +80,6 @@
 
   BrowsingDataCounter::ResultInt local_result_;
 
-  bool history_sync_enabled_;
-
   base::WeakPtrFactory<HistoryCounter> weak_ptr_factory_;
 };
 
diff --git a/components/browsing_data/core/counters/passwords_counter.cc b/components/browsing_data/core/counters/passwords_counter.cc
index b78cd06..9ee62cf 100644
--- a/components/browsing_data/core/counters/passwords_counter.cc
+++ b/components/browsing_data/core/counters/passwords_counter.cc
@@ -25,21 +25,17 @@
 PasswordsCounter::PasswordsCounter(
     scoped_refptr<password_manager::PasswordStore> store,
     syncer::SyncService* sync_service)
-    : store_(store), sync_service_(sync_service), password_sync_enabled_() {
+    : store_(store), sync_tracker_(this, sync_service) {
   DCHECK(store_);
 }
 
 PasswordsCounter::~PasswordsCounter() {
   store_->RemoveObserver(this);
-  if (sync_service_)
-    sync_service_->RemoveObserver(this);
 }
 
 void PasswordsCounter::OnInitialized() {
+  sync_tracker_.OnInitialized(base::Bind(&IsPasswordSyncEnabled));
   store_->AddObserver(this);
-  if (sync_service_)
-    sync_service_->AddObserver(this);
-  password_sync_enabled_ = IsPasswordSyncEnabled(sync_service_);
 }
 
 const char* PasswordsCounter::GetPrefName() const {
@@ -64,7 +60,7 @@
         return form->date_created >= start;
       });
   ReportResult(base::MakeUnique<SyncResult>(this, num_passwords,
-                                            password_sync_enabled_));
+                                            sync_tracker_.IsSyncActive()));
 }
 
 void PasswordsCounter::OnLoginsChanged(
@@ -72,13 +68,4 @@
   Restart();
 }
 
-void PasswordsCounter::OnStateChanged(syncer::SyncService* sync) {
-  bool sync_enabled_new = IsPasswordSyncEnabled(sync_service_);
-
-  if (password_sync_enabled_ != sync_enabled_new) {
-    password_sync_enabled_ = sync_enabled_new;
-    Restart();
-  }
-}
-
 }  // namespace browsing_data
diff --git a/components/browsing_data/core/counters/passwords_counter.h b/components/browsing_data/core/counters/passwords_counter.h
index bb71ff3..bfdb086 100644
--- a/components/browsing_data/core/counters/passwords_counter.h
+++ b/components/browsing_data/core/counters/passwords_counter.h
@@ -9,16 +9,15 @@
 #include <vector>
 
 #include "components/browsing_data/core/counters/browsing_data_counter.h"
+#include "components/browsing_data/core/counters/sync_tracker.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/sync/driver/sync_service_observer.h"
 
 namespace browsing_data {
 
 class PasswordsCounter : public browsing_data::BrowsingDataCounter,
                          public password_manager::PasswordStoreConsumer,
-                         public password_manager::PasswordStore::Observer,
-                         public syncer::SyncServiceObserver {
+                         public password_manager::PasswordStore::Observer {
  public:
   explicit PasswordsCounter(
       scoped_refptr<password_manager::PasswordStore> store,
@@ -40,15 +39,11 @@
   void OnLoginsChanged(
       const password_manager::PasswordStoreChangeList& changes) override;
 
-  // SyncServiceObserver implementation.
-  void OnStateChanged(syncer::SyncService* sync) override;
-
   void Count() override;
 
   base::CancelableTaskTracker cancelable_task_tracker_;
   scoped_refptr<password_manager::PasswordStore> store_;
-  syncer::SyncService* sync_service_;
-  bool password_sync_enabled_;
+  SyncTracker sync_tracker_;
 };
 
 }  // namespace browsing_data
diff --git a/components/browsing_data/core/counters/sync_tracker.cc b/components/browsing_data/core/counters/sync_tracker.cc
new file mode 100644
index 0000000..5c25a3c
--- /dev/null
+++ b/components/browsing_data/core/counters/sync_tracker.cc
@@ -0,0 +1,44 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/browsing_data/core/counters/sync_tracker.h"
+
+#include "components/browsing_data/core/counters/browsing_data_counter.h"
+#include "components/sync/driver/sync_service.h"
+
+namespace browsing_data {
+
+SyncTracker::SyncTracker(BrowsingDataCounter* counter,
+                         syncer::SyncService* sync_service)
+    : counter_(counter), sync_service_(sync_service), sync_enabled_() {
+  DCHECK(counter_);
+}
+
+SyncTracker::~SyncTracker() {
+  if (sync_service_)
+    sync_service_->RemoveObserver(this);
+}
+
+void SyncTracker::OnInitialized(SyncPredicate predicate) {
+  DCHECK(!predicate.is_null());
+  predicate_ = predicate;
+  if (sync_service_)
+    sync_service_->AddObserver(this);
+  sync_enabled_ = predicate_.Run(sync_service_);
+}
+
+bool SyncTracker::IsSyncActive() {
+  return sync_enabled_;
+}
+
+void SyncTracker::OnStateChanged(syncer::SyncService* sync) {
+  bool sync_enabled_new = predicate_.Run(sync_service_);
+
+  if (sync_enabled_ != sync_enabled_new) {
+    sync_enabled_ = sync_enabled_new;
+    counter_->Restart();
+  }
+}
+
+}  // namespace browsing_data
diff --git a/components/browsing_data/core/counters/sync_tracker.h b/components/browsing_data/core/counters/sync_tracker.h
new file mode 100644
index 0000000..df8ca4f
--- /dev/null
+++ b/components/browsing_data/core/counters/sync_tracker.h
@@ -0,0 +1,40 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_BROWSING_DATA_CORE_COUNTERS_SYNC_TRACKER_H_
+#define COMPONENTS_BROWSING_DATA_CORE_COUNTERS_SYNC_TRACKER_H_
+
+#include "base/callback.h"
+#include "components/sync/driver/sync_service_observer.h"
+
+namespace browsing_data {
+
+// A helper class that subscribes to sync changes and notifies
+// |counter| when the sync state changes.
+class BrowsingDataCounter;
+
+class SyncTracker : public syncer::SyncServiceObserver {
+ public:
+  using SyncPredicate = base::Callback<bool(const syncer::SyncService*)>;
+
+  SyncTracker(BrowsingDataCounter* counter, syncer::SyncService* sync_service);
+  ~SyncTracker() override;
+
+  void OnInitialized(SyncPredicate predicate);
+
+  bool IsSyncActive();
+
+ private:
+  // SyncServiceObserver implementation.
+  void OnStateChanged(syncer::SyncService* sync) override;
+
+  BrowsingDataCounter* counter_;
+  syncer::SyncService* sync_service_;
+  SyncPredicate predicate_;
+  bool sync_enabled_;
+};
+
+}  // namespace browsing_data
+
+#endif  // COMPONENTS_BROWSING_DATA_CORE_COUNTERS_SYNC_TRACKER_H_
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index 57d8790..02fbac1 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -10,6 +10,15 @@
   sources = [
     "buffer.cc",
     "buffer.h",
+    "data_device.cc",
+    "data_device.h",
+    "data_device_delegate.h",
+    "data_offer.cc",
+    "data_offer.h",
+    "data_offer_delegate.h",
+    "data_source.cc",
+    "data_source.h",
+    "data_source_delegate.h",
     "display.cc",
     "display.h",
     "gaming_seat.h",
diff --git a/components/exo/data_device.cc b/components/exo/data_device.cc
new file mode 100644
index 0000000..2d6864f
--- /dev/null
+++ b/components/exo/data_device.cc
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/exo/data_device.h"
+
+#include "base/logging.h"
+#include "components/exo/data_device_delegate.h"
+
+namespace exo {
+
+DataDevice::DataDevice(DataDeviceDelegate* delegate) : delegate_(delegate) {}
+
+DataDevice::~DataDevice() {
+  delegate_->OnDataDeviceDestroying(this);
+}
+
+void DataDevice::StartDrag(const DataSource* source_resource,
+                           Surface* origin_resource,
+                           Surface* icon_resource,
+                           uint32_t serial) {
+  // TODO(hirono): Check if serial is valid. crbug.com/746111
+  NOTIMPLEMENTED();
+}
+
+void DataDevice::SetSelection(const DataSource* source, uint32_t serial) {
+  // TODO(hirono): Check if serial is valid. crbug.com/746111
+  NOTIMPLEMENTED();
+}
+
+}  // namespace exo
diff --git a/components/exo/data_device.h b/components/exo/data_device.h
new file mode 100644
index 0000000..f2f9696
--- /dev/null
+++ b/components/exo/data_device.h
@@ -0,0 +1,50 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_DATA_DEVICE_H_
+#define COMPONENTS_EXO_DATA_DEVICE_H_
+
+#include <cstdint>
+
+#include "base/macros.h"
+
+namespace exo {
+
+class DataDeviceDelegate;
+class DataSource;
+class Surface;
+
+enum class DndAction { kNone, kCopy, kMove, kAsk };
+
+// Data transfer device providing access to inter-client data transfer
+// mechanisms such as copy-and-paste and drag-and-drop.
+class DataDevice {
+ public:
+  explicit DataDevice(DataDeviceDelegate* delegate);
+  ~DataDevice();
+
+  // Starts drag-and-drop operation.
+  // |source| is data source for the eventual transfer or null if data passing
+  // is handled by a client internally. |origin| is a surface where the drag
+  // originates. |icon| is drag-and-drop icon surface, which can be nullptr.
+  // |serial| is a unique number of implicit grab.
+  void StartDrag(const DataSource* source,
+                 Surface* origin,
+                 Surface* icon,
+                 uint32_t serial);
+
+  // Copies data to the selection.
+  // |source| is data source for the selection, or nullptr to unset the
+  // selection. |serial| is a unique number of event which tigers SetSelection.
+  void SetSelection(const DataSource* source, uint32_t serial);
+
+ private:
+  DataDeviceDelegate* const delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(DataDevice);
+};
+
+}  // namespace exo
+
+#endif  // COMPONENTS_EXO_DATA_DEVICE_H_
diff --git a/components/exo/data_device_delegate.h b/components/exo/data_device_delegate.h
new file mode 100644
index 0000000..c9f2e3d
--- /dev/null
+++ b/components/exo/data_device_delegate.h
@@ -0,0 +1,66 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_DATA_DEVICE_DELEGATE_H_
+#define COMPONENTS_EXO_DATA_DEVICE_DELEGATE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/containers/flat_set.h"
+
+namespace base {
+class TimeTicks;
+}
+
+namespace gfx {
+class PointF;
+}
+
+namespace exo {
+
+class DataDevice;
+class DataOffer;
+enum class DndAction;
+
+// Handles events on data devices in context-specific ways.
+class DataDeviceDelegate {
+ public:
+  // Called at the top of the data device's destructor, to give observers a
+  // chance to remove themselves.
+  virtual void OnDataDeviceDestroying(DataDevice* data_device) = 0;
+
+  // Called when DataOffer object is delivered from a client. DataDeviceDelegate
+  // has responsibility to release the returned DataOffer object.
+  virtual DataOffer* OnDataOffer(
+      const std::vector<std::string>& mime_types,
+      const base::flat_set<DndAction>& source_actions,
+      DndAction dnd_action) = 0;
+
+  // Called during a drag operation when pointer enters |surface|.
+  virtual void OnEnter(Surface* surface,
+                       const gfx::PointF& location,
+                       const DataOffer& data_offer) = 0;
+
+  // Called during a drag operation when pointer leaves |surface|.
+  virtual void OnLeave() = 0;
+
+  // Called during a drag operation when pointer moves on the |surface|.
+  virtual void OnMotion(base::TimeTicks time_stamp,
+                        const gfx::PointF& location) = 0;
+
+  // Called during a drag operation when user drops dragging data on the
+  // |surface|.
+  virtual void OnDrop() = 0;
+
+  // Called when the data is pasted on the DataDevice.
+  virtual void OnSelection(const DataOffer& data_offer) = 0;
+
+ protected:
+  virtual ~DataDeviceDelegate() {}
+};
+
+}  // namespace exo
+
+#endif  // COMPONENTS_EXO_DATA_DEVICE_DELEGATE_H_
diff --git a/components/exo/data_offer.cc b/components/exo/data_offer.cc
new file mode 100644
index 0000000..057a3062
--- /dev/null
+++ b/components/exo/data_offer.cc
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/exo/data_offer.h"
+
+#include "components/exo/data_offer_delegate.h"
+
+namespace exo {
+
+DataOffer::DataOffer(DataOfferDelegate* delegate) : delegate_(delegate) {}
+
+DataOffer::~DataOffer() {
+  delegate_->OnDataOfferDestroying(this);
+}
+
+void DataOffer::Accept(const std::string& mime_type) {
+  NOTIMPLEMENTED();
+}
+void DataOffer::Receive(const std::string& mime_type, base::ScopedFD fd) {
+  NOTIMPLEMENTED();
+}
+void DataOffer::Finish() {
+  NOTIMPLEMENTED();
+}
+void DataOffer::SetActions(const base::flat_set<DndAction>& dnd_actions,
+                           DndAction preferred_action) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace exo
diff --git a/components/exo/data_offer.h b/components/exo/data_offer.h
new file mode 100644
index 0000000..7b1fa034
--- /dev/null
+++ b/components/exo/data_offer.h
@@ -0,0 +1,49 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_DATA_OFFER_H_
+#define COMPONENTS_EXO_DATA_OFFER_H_
+
+#include <cstdint>
+#include <string>
+
+#include "base/containers/flat_set.h"
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
+#include "ui/base/class_property.h"
+
+namespace exo {
+
+class DataOfferDelegate;
+enum class DndAction;
+
+// Object representing transferred data offered to a client.
+class DataOffer : public ui::PropertyHandler {
+ public:
+  explicit DataOffer(DataOfferDelegate* delegate);
+  ~DataOffer();
+
+  // Accepts one of the offered mime types.
+  void Accept(const std::string& mime_type);
+
+  // Requests that the data is transferred. |fd| is a file descriptor for data
+  // transfer.
+  void Receive(const std::string& mime_type, base::ScopedFD fd);
+
+  // Called when the client is no longer using the data offer object.
+  void Finish();
+
+  // Sets the available/preferred drag-and-drop actions.
+  void SetActions(const base::flat_set<DndAction>& dnd_actions,
+                  DndAction preferred_action);
+
+ private:
+  DataOfferDelegate* const delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(DataOffer);
+};
+
+}  // namespace exo
+
+#endif  // COMPONENTS_EXO_DATA_OFFER_H_
diff --git a/components/exo/data_offer_delegate.h b/components/exo/data_offer_delegate.h
new file mode 100644
index 0000000..41337c3
--- /dev/null
+++ b/components/exo/data_offer_delegate.h
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_DATA_OFFER_DELEGATE_H_
+#define COMPONENTS_EXO_DATA_OFFER_DELEGATE_H_
+
+#include <string>
+
+namespace exo {
+
+class DataOffer;
+enum class DndAction;
+
+// Handles events on data devices in context-specific ways.
+class DataOfferDelegate {
+ public:
+  // Called at the top of the data device's destructor, to give observers a
+  // chance to remove themselves.
+  virtual void OnDataOfferDestroying(DataOffer* offer) = 0;
+
+  // Called when |mime_type| is offered by the client.
+  virtual void OnOffer(const std::string& mime_type) = 0;
+
+  // Called when possible |source_actions| is offered by the client.
+  virtual void OnSourceActions(
+      const base::flat_set<DndAction>& source_actions) = 0;
+
+  // Called when current |action| is offered by the client.
+  virtual void OnAction(DndAction action) = 0;
+
+ protected:
+  virtual ~DataOfferDelegate() {}
+};
+
+}  // namespace exo
+
+#endif  // COMPONENTS_EXO_DATA_OFFER_DELEGATE_H_
diff --git a/components/exo/data_source.cc b/components/exo/data_source.cc
new file mode 100644
index 0000000..e70ddfa
--- /dev/null
+++ b/components/exo/data_source.cc
@@ -0,0 +1,25 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/exo/data_source.h"
+
+#include "components/exo/data_source_delegate.h"
+
+namespace exo {
+
+DataSource::DataSource(DataSourceDelegate* delegate) : delegate_(delegate) {}
+
+DataSource::~DataSource() {
+  delegate_->OnDataSourceDestroying(this);
+}
+
+void DataSource::Offer(const std::string& mime_type) {
+  NOTIMPLEMENTED();
+}
+
+void DataSource::SetActions(const base::flat_set<DndAction>& dnd_actions) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace exo
diff --git a/components/exo/data_source.h b/components/exo/data_source.h
new file mode 100644
index 0000000..c8a1b7a
--- /dev/null
+++ b/components/exo/data_source.h
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_DATA_SOURCE_H_
+#define COMPONENTS_EXO_DATA_SOURCE_H_
+
+#include <string>
+
+#include "base/containers/flat_set.h"
+#include "base/macros.h"
+
+namespace exo {
+
+class DataSourceDelegate;
+enum class DndAction;
+
+// Object representing transferred data offered by a client.
+class DataSource {
+ public:
+  explicit DataSource(DataSourceDelegate* delegate);
+  ~DataSource();
+
+  // Adds an offered mime type.
+  void Offer(const std::string& mime_type);
+
+  // Sets the available drag-and-drop actions.
+  void SetActions(const base::flat_set<DndAction>& dnd_actions);
+
+ private:
+  DataSourceDelegate* const delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(DataSource);
+};
+
+}  // namespace exo
+
+#endif  // COMPONENTS_EXO_DATA_SOURCE_H_
diff --git a/components/exo/data_source_delegate.h b/components/exo/data_source_delegate.h
new file mode 100644
index 0000000..6c2c2bf
--- /dev/null
+++ b/components/exo/data_source_delegate.h
@@ -0,0 +1,47 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_DATA_SOURCE_DELEGATE_H_
+#define COMPONENTS_EXO_DATA_SOURCE_DELEGATE_H_
+
+#include <string>
+
+#include "base/files/scoped_file.h"
+
+namespace exo {
+
+class DataSource;
+
+// Handles events on data devices in context-specific ways.
+class DataSourceDelegate {
+ public:
+  // Called at the top of the data device's destructor, to give observers a
+  // chance to remove themselves.
+  virtual void OnDataSourceDestroying(DataSource* source) = 0;
+
+  // Called when a target accepts an offered mime type.
+  virtual void OnTarget(const std::string& mime_type) = 0;
+
+  // Called when the data is requested.
+  virtual void OnSend(const std::string& mime_type, base::ScopedFD fd) = 0;
+
+  // Called when selection was cancelled.
+  virtual void OnCancelled() = 0;
+
+  // Called when the drag-and-drop operation physically finished.
+  virtual void OnDndDropPerformed() = 0;
+
+  // Called when the drag-and-drop operation concluded.
+  virtual void OnDndFinished() = 0;
+
+  // Called when the action is selected by the compositor.
+  virtual void OnAction(DndAction dnd_action) = 0;
+
+ protected:
+  virtual ~DataSourceDelegate() {}
+};
+
+}  // namespace exo
+
+#endif  // COMPONENTS_EXO_DATA_SOURCE_DELEGATE_H_
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index 20880dc..3801c92 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -48,6 +48,12 @@
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/exo/buffer.h"
+#include "components/exo/data_device.h"
+#include "components/exo/data_device_delegate.h"
+#include "components/exo/data_offer.h"
+#include "components/exo/data_offer_delegate.h"
+#include "components/exo/data_source.h"
+#include "components/exo/data_source_delegate.h"
 #include "components/exo/display.h"
 #include "components/exo/gamepad_delegate.h"
 #include "components/exo/gaming_seat.h"
@@ -151,6 +157,55 @@
   return TimeTicksToMilliseconds(base::TimeTicks::Now());
 }
 
+uint32_t WaylandDataDeviceManagerDndAction(DndAction action) {
+  switch (action) {
+    case DndAction::kNone:
+      return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
+    case DndAction::kCopy:
+      return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
+    case DndAction::kMove:
+      return WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
+    case DndAction::kAsk:
+      return WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
+  }
+  NOTREACHED();
+}
+
+uint32_t WaylandDataDeviceManagerDndActions(
+    const base::flat_set<DndAction>& dnd_actions) {
+  uint32_t actions = 0;
+  for (DndAction action : dnd_actions)
+    actions |= WaylandDataDeviceManagerDndAction(action);
+  return actions;
+}
+
+DndAction DataDeviceManagerDndAction(uint32_t value) {
+  switch (value) {
+    case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
+      return DndAction::kNone;
+    case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY:
+      return DndAction::kCopy;
+    case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE:
+      return DndAction::kMove;
+    case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
+      return DndAction::kAsk;
+    default:
+      NOTREACHED();
+      return DndAction::kNone;
+  }
+}
+
+base::flat_set<DndAction> DataDeviceManagerDndActions(uint32_t value) {
+  base::flat_set<DndAction> actions;
+  if (value & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
+    actions.insert(DndAction::kCopy);
+  if (value & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
+    actions.insert(DndAction::kMove);
+  if (value & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
+    actions.insert(DndAction::kAsk);
+  return actions;
+}
+
 // A property key containing the surface resource that is associated with
 // window. If unset, no surface resource is associated with window.
 DEFINE_UI_CLASS_PROPERTY_KEY(wl_resource*, kSurfaceResourceKey, nullptr);
@@ -176,10 +231,18 @@
 // object is associated with a window.
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSurfaceHasStylusToolKey, false);
 
+// A property key containing the data offer resource that is associated with
+// data offer object.
+DEFINE_UI_CLASS_PROPERTY_KEY(wl_resource*, kDataOfferResourceKey, nullptr);
+
 wl_resource* GetSurfaceResource(Surface* surface) {
   return surface->GetProperty(kSurfaceResourceKey);
 }
 
+wl_resource* GetDataOfferResource(const DataOffer* data_offer) {
+  return data_offer->GetProperty(kDataOfferResourceKey);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // wl_buffer_interface:
 
@@ -2639,26 +2702,206 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// wl_data_source_interface:
+
+class WaylandDataSourceDelegate : public DataSourceDelegate {
+ public:
+  explicit WaylandDataSourceDelegate(wl_resource* source)
+      : data_source_resource_(source) {}
+
+  // Overridden from DataSourceDelegate:
+  void OnDataSourceDestroying(DataSource* device) override { delete this; }
+  void OnTarget(const std::string& mime_type) override {
+    wl_data_source_send_target(data_source_resource_, mime_type.c_str());
+  }
+  void OnSend(const std::string& mime_type, base::ScopedFD fd) override {
+    wl_data_source_send_send(data_source_resource_, mime_type.c_str(),
+                             fd.get());
+  }
+  void OnCancelled() override {
+    wl_data_source_send_cancelled(data_source_resource_);
+  }
+  void OnDndDropPerformed() override {
+    wl_data_source_send_dnd_drop_performed(data_source_resource_);
+  }
+  void OnDndFinished() override {
+    wl_data_source_send_dnd_finished(data_source_resource_);
+  }
+  void OnAction(DndAction dnd_action) override {
+    wl_data_source_send_action(data_source_resource_,
+                               WaylandDataDeviceManagerDndAction(dnd_action));
+  }
+
+ private:
+  wl_resource* const data_source_resource_;
+
+  DISALLOW_COPY_AND_ASSIGN(WaylandDataSourceDelegate);
+};
+
+void data_source_offer(wl_client* client,
+                       wl_resource* resource,
+                       const char* mime_type) {
+  GetUserDataAs<DataSource>(resource)->Offer(mime_type);
+}
+
+void data_source_destroy(wl_client* client, wl_resource* resource) {
+  wl_resource_destroy(resource);
+}
+
+void data_source_set_actions(wl_client* client,
+                             wl_resource* resource,
+                             uint32_t dnd_actions) {
+  GetUserDataAs<DataSource>(resource)->SetActions(
+      DataDeviceManagerDndActions(dnd_actions));
+}
+
+const struct wl_data_source_interface data_source_implementation = {
+    data_source_offer, data_source_destroy, data_source_set_actions};
+
+////////////////////////////////////////////////////////////////////////////////
+// wl_data_offer_interface:
+
+class WaylandDataOfferDelegate : public DataOfferDelegate {
+ public:
+  explicit WaylandDataOfferDelegate(wl_resource* offer)
+      : data_offer_resource_(offer) {}
+
+  // Overridden from DataOfferDelegate:
+  void OnDataOfferDestroying(DataOffer* device) override { delete this; }
+  void OnOffer(const std::string& mime_type) override {
+    wl_data_offer_send_offer(data_offer_resource_, mime_type.c_str());
+  }
+  void OnSourceActions(
+      const base::flat_set<DndAction>& source_actions) override {
+    wl_data_offer_send_source_actions(
+        data_offer_resource_,
+        WaylandDataDeviceManagerDndActions(source_actions));
+  }
+  void OnAction(DndAction action) override {
+    wl_data_offer_send_action(data_offer_resource_,
+                              WaylandDataDeviceManagerDndAction(action));
+  }
+
+ private:
+  wl_resource* const data_offer_resource_;
+
+  DISALLOW_COPY_AND_ASSIGN(WaylandDataOfferDelegate);
+};
+
+void data_offer_accept(wl_client* client,
+                       wl_resource* resource,
+                       uint32_t serial,
+                       const char* mime_type) {
+  GetUserDataAs<DataOffer>(resource)->Accept(mime_type);
+}
+
+void data_offer_receive(wl_client* client,
+                        wl_resource* resource,
+                        const char* mime_type,
+                        int fd) {
+  GetUserDataAs<DataOffer>(resource)->Receive(mime_type, base::ScopedFD(fd));
+}
+
+void data_offer_destroy(wl_client* client, wl_resource* resource) {
+  wl_resource_destroy(resource);
+}
+
+void data_offer_finish(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<DataOffer>(resource)->Finish();
+}
+
+void data_offer_set_actions(wl_client* client,
+                            wl_resource* resource,
+                            uint32_t dnd_actions,
+                            uint32_t preferred_action) {
+  GetUserDataAs<DataOffer>(resource)->SetActions(
+      DataDeviceManagerDndActions(dnd_actions),
+      DataDeviceManagerDndAction(preferred_action));
+}
+
+const struct wl_data_offer_interface data_offer_implementation = {
+    data_offer_accept, data_offer_receive, data_offer_finish,
+    data_offer_destroy, data_offer_set_actions};
+
+////////////////////////////////////////////////////////////////////////////////
 // wl_data_device_interface:
 
+class WaylandDataDeviceDelegate : public DataDeviceDelegate {
+ public:
+  WaylandDataDeviceDelegate(wl_client* client, wl_resource* device_resource)
+      : client_(client), data_device_resource_(device_resource) {}
+
+  // Overridden from DataDeviceDelegate:
+  void OnDataDeviceDestroying(DataDevice* device) override { delete this; }
+  class DataOffer* OnDataOffer(const std::vector<std::string>& mime_types,
+                               const base::flat_set<DndAction>& source_actions,
+                               DndAction dnd_action) override {
+    wl_resource* data_offer_resource =
+        wl_resource_create(client_, &wl_data_offer_interface, 1, 0);
+    std::unique_ptr<DataOffer> data_offer = base::MakeUnique<DataOffer>(
+        new WaylandDataOfferDelegate(data_offer_resource));
+    data_offer->SetProperty(kDataOfferResourceKey, data_offer_resource);
+    SetImplementation(data_offer_resource, &data_offer_implementation,
+                      std::move(data_offer));
+
+    wl_data_device_send_data_offer(data_device_resource_, data_offer_resource);
+
+    return GetUserDataAs<DataOffer>(data_offer_resource);
+  }
+  void OnEnter(Surface* surface,
+               const gfx::PointF& point,
+               const DataOffer& data_offer) override {
+    wl_data_device_send_enter(
+        data_device_resource_,
+        wl_display_next_serial(wl_client_get_display(client_)),
+        GetSurfaceResource(surface), wl_fixed_from_double(point.x()),
+        wl_fixed_from_double(point.y()), GetDataOfferResource(&data_offer));
+  }
+  void OnLeave() override { wl_data_device_send_leave(data_device_resource_); }
+  void OnMotion(base::TimeTicks time_stamp, const gfx::PointF& point) override {
+    wl_data_device_send_motion(
+        data_device_resource_, TimeTicksToMilliseconds(time_stamp),
+        wl_fixed_from_double(point.x()), wl_fixed_from_double(point.y()));
+  }
+  void OnDrop() override { wl_data_device_send_drop(data_device_resource_); }
+  void OnSelection(const class DataOffer& data_offer) override {
+    wl_data_device_send_selection(data_device_resource_,
+                                  GetDataOfferResource(&data_offer));
+  }
+
+ private:
+  wl_client* const client_;
+  wl_resource* const data_device_resource_;
+
+  DISALLOW_COPY_AND_ASSIGN(WaylandDataDeviceDelegate);
+};
+
 void data_device_start_drag(wl_client* client,
                             wl_resource* resource,
                             wl_resource* source_resource,
                             wl_resource* origin_resource,
                             wl_resource* icon_resource,
                             uint32_t serial) {
-  NOTIMPLEMENTED();
+  GetUserDataAs<DataDevice>(resource)->StartDrag(
+      source_resource ? GetUserDataAs<DataSource>(source_resource) : nullptr,
+      GetUserDataAs<Surface>(origin_resource),
+      icon_resource ? GetUserDataAs<Surface>(icon_resource) : nullptr, serial);
 }
 
 void data_device_set_selection(wl_client* client,
                                wl_resource* resource,
                                wl_resource* data_source,
                                uint32_t serial) {
-  NOTIMPLEMENTED();
+  GetUserDataAs<DataDevice>(resource)->SetSelection(
+      GetUserDataAs<DataSource>(data_source), serial);
+}
+
+void data_device_release(wl_client* client, wl_resource* resource) {
+  wl_resource_destroy(resource);
 }
 
 const struct wl_data_device_interface data_device_implementation = {
-    data_device_start_drag, data_device_set_selection};
+    data_device_start_drag, data_device_set_selection, data_device_release};
 
 ////////////////////////////////////////////////////////////////////////////////
 // wl_data_device_manager_interface:
@@ -2666,7 +2909,11 @@
 void data_device_manager_create_data_source(wl_client* client,
                                             wl_resource* resource,
                                             uint32_t id) {
-  NOTIMPLEMENTED();
+  wl_resource* data_source_resource =
+      wl_resource_create(client, &wl_data_device_interface, 1, id);
+  SetImplementation(data_source_resource, &data_source_implementation,
+                    base::MakeUnique<DataSource>(
+                        new WaylandDataSourceDelegate(data_source_resource)));
 }
 
 void data_device_manager_get_data_device(wl_client* client,
@@ -2675,9 +2922,9 @@
                                          wl_resource* seat_resource) {
   wl_resource* data_device_resource =
       wl_resource_create(client, &wl_data_device_interface, 1, id);
-
-  wl_resource_set_implementation(data_device_resource,
-                                 &data_device_implementation, nullptr, nullptr);
+  SetImplementation(data_device_resource, &data_device_implementation,
+                    base::MakeUnique<DataDevice>(new WaylandDataDeviceDelegate(
+                        client, data_device_resource)));
 }
 
 const struct wl_data_device_manager_interface
@@ -2691,9 +2938,8 @@
                               uint32_t id) {
   wl_resource* resource =
       wl_resource_create(client, &wl_data_device_manager_interface, 1, id);
-
   wl_resource_set_implementation(resource, &data_device_manager_implementation,
-                                 data, nullptr);
+                                 nullptr, nullptr);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn
index 319d951..2775981 100644
--- a/components/metrics/BUILD.gn
+++ b/components/metrics/BUILD.gn
@@ -31,8 +31,6 @@
     "environment_recorder.h",
     "execution_phase.cc",
     "execution_phase.h",
-    "field_trials_provider.cc",
-    "field_trials_provider.h",
     "file_metrics_provider.cc",
     "file_metrics_provider.h",
     "histogram_encoder.cc",
@@ -348,7 +346,6 @@
     "data_use_tracker_unittest.cc",
     "drive_metrics_provider_unittest.cc",
     "environment_recorder_unittest.cc",
-    "field_trials_provider_unittest.cc",
     "file_metrics_provider_unittest.cc",
     "histogram_encoder_unittest.cc",
     "machine_id_provider_win_unittest.cc",
diff --git a/components/metrics/field_trials_provider.cc b/components/metrics/field_trials_provider.cc
deleted file mode 100644
index f67fc3c..0000000
--- a/components/metrics/field_trials_provider.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/metrics/field_trials_provider.h"
-
-#include "components/metrics/proto/system_profile.pb.h"
-#include "components/variations/active_field_trials.h"
-#include "components/variations/synthetic_trial_registry.h"
-
-namespace variations {
-
-namespace {
-
-void WriteFieldTrials(const std::vector<ActiveGroupId>& field_trial_ids,
-                      metrics::SystemProfileProto* system_profile) {
-  for (const ActiveGroupId& id : field_trial_ids) {
-    metrics::SystemProfileProto::FieldTrial* field_trial =
-        system_profile->add_field_trial();
-    field_trial->set_name_id(id.name);
-    field_trial->set_group_id(id.group);
-  }
-}
-
-}  // namespace
-
-FieldTrialsProvider::FieldTrialsProvider(SyntheticTrialRegistry* registry)
-    : registry_(registry) {}
-FieldTrialsProvider::~FieldTrialsProvider() = default;
-
-void FieldTrialsProvider::GetFieldTrialIds(
-    std::vector<ActiveGroupId>* field_trial_ids) const {
-  variations::GetFieldTrialActiveGroupIds(field_trial_ids);
-}
-
-void FieldTrialsProvider::OnDidCreateMetricsLog() {
-  creation_times_.push_back(base::TimeTicks::Now());
-}
-
-void FieldTrialsProvider::ProvideSystemProfileMetrics(
-    metrics::SystemProfileProto* system_profile_proto) {
-  base::TimeTicks creation_time;
-  // Should always be true, but don't crash even if there is a bug.
-  if (!creation_times_.empty()) {
-    creation_time = creation_times_.back();
-    creation_times_.pop_back();
-  }
-  std::vector<ActiveGroupId> synthetic_trials;
-  registry_->GetSyntheticFieldTrialsOlderThan(creation_time, &synthetic_trials);
-
-  std::vector<ActiveGroupId> field_trial_ids;
-  GetFieldTrialIds(&field_trial_ids);
-  WriteFieldTrials(field_trial_ids, system_profile_proto);
-  WriteFieldTrials(synthetic_trials, system_profile_proto);
-}
-
-}  // namespace variations
diff --git a/components/metrics/field_trials_provider.h b/components/metrics/field_trials_provider.h
deleted file mode 100644
index 6242a20d..0000000
--- a/components/metrics/field_trials_provider.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_METRICS_FIELD_TRIALS_PROVIDER_H_
-#define COMPONENTS_METRICS_FIELD_TRIALS_PROVIDER_H_
-
-#include <vector>
-
-#include "base/time/time.h"
-#include "components/metrics/metrics_provider.h"
-
-// TODO(crbug/507665): Once MetricsProvider/SystemProfileProto are moved into
-// //services/metrics, then //components/variations can depend on them, and
-// this should be moved there.
-namespace variations {
-
-class SyntheticTrialRegistry;
-struct ActiveGroupId;
-
-class FieldTrialsProvider : public metrics::MetricsProvider {
- public:
-  // |registry| must outlive this metrics provider.
-  FieldTrialsProvider(SyntheticTrialRegistry* registry);
-  ~FieldTrialsProvider() override;
-
-  // metrics::MetricsProvider:
-  void OnDidCreateMetricsLog() override;
-  void ProvideSystemProfileMetrics(
-      metrics::SystemProfileProto* system_profile_proto) override;
-
- private:
-  // Overrideable for testing.
-  virtual void GetFieldTrialIds(
-      std::vector<ActiveGroupId>* field_trial_ids) const;
-
-  SyntheticTrialRegistry* registry_;
-
-  // A stack of log creation times.
-  // While the initial metrics log exists, there will be two logs open.
-  // Use a stack so that we use the right creation time for the first ongoing
-  // log.
-  // TODO(crbug/746098): Simplify InitialMetricsLog logic so this is not
-  // necessary.
-  std::vector<base::TimeTicks> creation_times_;
-};
-
-}  // namespace variations
-
-#endif  // COMPONENTS_METRICS_FIELD_TRIALS_PROVIDER_H_
diff --git a/components/metrics/field_trials_provider_unittest.cc b/components/metrics/field_trials_provider_unittest.cc
deleted file mode 100644
index f50f63e..0000000
--- a/components/metrics/field_trials_provider_unittest.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/metrics/field_trials_provider.h"
-
-#include "components/metrics/proto/system_profile.pb.h"
-#include "components/variations/active_field_trials.h"
-#include "components/variations/synthetic_trial_registry.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace variations {
-
-namespace {
-
-const ActiveGroupId kFieldTrialIds[] = {{37, 43}, {13, 47}, {23, 17}};
-const ActiveGroupId kSyntheticTrials[] = {{55, 15}, {66, 16}};
-
-class TestProvider : public FieldTrialsProvider {
- public:
-  TestProvider(SyntheticTrialRegistry* registry)
-      : FieldTrialsProvider(registry) {}
-  ~TestProvider() override {}
-
-  void GetFieldTrialIds(
-      std::vector<ActiveGroupId>* field_trial_ids) const override {
-    ASSERT_TRUE(field_trial_ids->empty());
-    for (const ActiveGroupId& id : kFieldTrialIds) {
-      field_trial_ids->push_back(id);
-    }
-  }
-};
-
-// Check that the values in |system_values| correspond to the test data
-// defined at the top of this file.
-void CheckSystemProfile(const metrics::SystemProfileProto& system_profile) {
-  ASSERT_EQ(arraysize(kFieldTrialIds) + arraysize(kSyntheticTrials),
-            static_cast<size_t>(system_profile.field_trial_size()));
-  for (size_t i = 0; i < arraysize(kFieldTrialIds); ++i) {
-    const metrics::SystemProfileProto::FieldTrial& field_trial =
-        system_profile.field_trial(i);
-    EXPECT_EQ(kFieldTrialIds[i].name, field_trial.name_id());
-    EXPECT_EQ(kFieldTrialIds[i].group, field_trial.group_id());
-  }
-  // Verify the right data is present for the synthetic trials.
-  for (size_t i = 0; i < arraysize(kSyntheticTrials); ++i) {
-    const metrics::SystemProfileProto::FieldTrial& field_trial =
-        system_profile.field_trial(i + arraysize(kFieldTrialIds));
-    EXPECT_EQ(kSyntheticTrials[i].name, field_trial.name_id());
-    EXPECT_EQ(kSyntheticTrials[i].group, field_trial.group_id());
-  }
-}
-
-}  // namespace
-
-class FieldTrialsProviderTest : public ::testing::Test {
- public:
-  FieldTrialsProviderTest() {}
-  ~FieldTrialsProviderTest() override {}
-
- protected:
-  // Register trials which should get recorded.
-  void RegisterExpectedSyntheticTrials() {
-    for (const ActiveGroupId& id : kSyntheticTrials) {
-      registry_.RegisterSyntheticFieldTrial(
-          SyntheticTrialGroup(id.name, id.group));
-    }
-  }
-  // Register trial which shouldn't get recorded.
-  void RegisterExtraSyntheticTrial() {
-    registry_.RegisterSyntheticFieldTrial(SyntheticTrialGroup(100, 1000));
-  }
-
-  SyntheticTrialRegistry registry_;
-};
-
-TEST_F(FieldTrialsProviderTest, ProvideSyntheticTrials) {
-  TestProvider provider(&registry_);
-
-  RegisterExpectedSyntheticTrials();
-  provider.OnDidCreateMetricsLog();
-  RegisterExtraSyntheticTrial();
-
-  metrics::SystemProfileProto proto;
-  provider.ProvideSystemProfileMetrics(&proto);
-  CheckSystemProfile(proto);
-}
-
-}  // namespace variations
diff --git a/components/metrics/metrics_log.cc b/components/metrics/metrics_log.cc
index 29a5e12d..ba570a7 100644
--- a/components/metrics/metrics_log.cc
+++ b/components/metrics/metrics_log.cc
@@ -31,6 +31,7 @@
 #include "components/metrics/proto/user_action_event.pb.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
+#include "components/variations/active_field_trials.h"
 
 #if defined(OS_ANDROID)
 #include "base/android/build_info.h"
@@ -41,6 +42,7 @@
 #endif
 
 using base::SampleCountIterator;
+typedef variations::ActiveGroupId ActiveGroupId;
 
 namespace metrics {
 
@@ -79,6 +81,17 @@
   return id.size() < 16;
 }
 
+void WriteFieldTrials(const std::vector<ActiveGroupId>& field_trial_ids,
+                      SystemProfileProto* system_profile) {
+  for (std::vector<ActiveGroupId>::const_iterator it =
+       field_trial_ids.begin(); it != field_trial_ids.end(); ++it) {
+    SystemProfileProto::FieldTrial* field_trial =
+        system_profile->add_field_trial();
+    field_trial->set_name_id(it->name);
+    field_trial->set_group_id(it->group);
+  }
+}
+
 // Round a timestamp measured in seconds since epoch to one with a granularity
 // of an hour. This can be used before uploaded potentially sensitive
 // timestamps.
@@ -233,6 +246,11 @@
     metrics_providers[i]->ProvideGeneralMetrics(uma_proto());
 }
 
+void MetricsLog::GetFieldTrialIds(
+    std::vector<ActiveGroupId>* field_trial_ids) const {
+  variations::GetFieldTrialActiveGroupIds(field_trial_ids);
+}
+
 bool MetricsLog::HasEnvironment() const {
   return uma_proto()->system_profile().has_uma_enabled_date();
 }
@@ -285,6 +303,7 @@
 
 std::string MetricsLog::RecordEnvironment(
     const std::vector<std::unique_ptr<MetricsProvider>>& metrics_providers,
+    const std::vector<variations::ActiveGroupId>& synthetic_trials,
     int64_t install_date,
     int64_t metrics_reporting_enabled_date) {
   DCHECK(!HasEnvironment());
@@ -312,6 +331,11 @@
   cpu->set_signature(cpu_info.signature());
   cpu->set_num_cores(base::SysInfo::NumberOfProcessors());
 
+  std::vector<ActiveGroupId> field_trial_ids;
+  GetFieldTrialIds(&field_trial_ids);
+  WriteFieldTrials(field_trial_ids, system_profile);
+  WriteFieldTrials(synthetic_trials, system_profile);
+
   for (size_t i = 0; i < metrics_providers.size(); ++i)
     metrics_providers[i]->ProvideSystemProfileMetrics(system_profile);
 
diff --git a/components/metrics/metrics_log.h b/components/metrics/metrics_log.h
index 27e9033..688a624 100644
--- a/components/metrics/metrics_log.h
+++ b/components/metrics/metrics_log.h
@@ -25,6 +25,10 @@
 class HistogramSamples;
 }
 
+namespace variations {
+struct ActiveGroupId;
+}
+
 namespace metrics {
 
 namespace internal {
@@ -98,6 +102,7 @@
   // current environment is returned serialized as a string.
   std::string RecordEnvironment(
       const std::vector<std::unique_ptr<MetricsProvider>>& metrics_providers,
+      const std::vector<variations::ActiveGroupId>& synthetic_trials,
       int64_t install_date,
       int64_t metrics_reporting_enabled_date);
 
@@ -151,6 +156,11 @@
  protected:
   // Exposed for the sake of mocking/accessing in test code.
 
+  // Fills |field_trial_ids| with the list of initialized field trials name and
+  // group ids.
+  virtual void GetFieldTrialIds(
+      std::vector<variations::ActiveGroupId>* field_trial_ids) const;
+
   ChromeUserMetricsExtension* uma_proto() { return &uma_proto_; }
 
   // Exposed to allow subclass to access to export the uma_proto. Can be used
diff --git a/components/metrics/metrics_log_unittest.cc b/components/metrics/metrics_log_unittest.cc
index cb48cc09..8a1c6bc 100644
--- a/components/metrics/metrics_log_unittest.cc
+++ b/components/metrics/metrics_log_unittest.cc
@@ -46,6 +46,15 @@
 const int64_t kEnabledDate = 1373001211;
 const int64_t kEnabledDateExpected = 1373000400;  // Computed from kEnabledDate.
 const int kSessionId = 127;
+const variations::ActiveGroupId kFieldTrialIds[] = {
+  {37, 43},
+  {13, 47},
+  {23, 17}
+};
+const variations::ActiveGroupId kSyntheticTrials[] = {
+  {55, 15},
+  {66, 16}
+};
 
 class TestMetricsLog : public MetricsLog {
  public:
@@ -79,6 +88,15 @@
                       base::Int64ToString(kEnabledDate));
   }
 
+  void GetFieldTrialIds(
+      std::vector<variations::ActiveGroupId>* field_trial_ids) const override {
+    ASSERT_TRUE(field_trial_ids->empty());
+
+    for (size_t i = 0; i < arraysize(kFieldTrialIds); ++i) {
+      field_trial_ids->push_back(kFieldTrialIds[i]);
+    }
+  }
+
   // Weak pointer to the PrefsService used by this log.
   TestingPrefServiceSimple* prefs_;
 
@@ -103,6 +121,22 @@
     EXPECT_EQ(kInstallDateExpected, system_profile.install_date());
     EXPECT_EQ(kEnabledDateExpected, system_profile.uma_enabled_date());
 
+    ASSERT_EQ(arraysize(kFieldTrialIds) + arraysize(kSyntheticTrials),
+              static_cast<size_t>(system_profile.field_trial_size()));
+    for (size_t i = 0; i < arraysize(kFieldTrialIds); ++i) {
+      const SystemProfileProto::FieldTrial& field_trial =
+          system_profile.field_trial(i);
+      EXPECT_EQ(kFieldTrialIds[i].name, field_trial.name_id());
+      EXPECT_EQ(kFieldTrialIds[i].group, field_trial.group_id());
+    }
+    // Verify the right data is present for the synthetic trials.
+    for (size_t i = 0; i < arraysize(kSyntheticTrials); ++i) {
+      const SystemProfileProto::FieldTrial& field_trial =
+          system_profile.field_trial(i + arraysize(kFieldTrialIds));
+      EXPECT_EQ(kSyntheticTrials[i].name, field_trial.name_id());
+      EXPECT_EQ(kSyntheticTrials[i].group, field_trial.group_id());
+    }
+
     EXPECT_EQ(TestMetricsServiceClient::kBrandForTesting,
               system_profile.brand_code());
 
@@ -255,8 +289,13 @@
   TestMetricsLog log(
       kClientId, kSessionId, MetricsLog::ONGOING_LOG, &client, &prefs_);
 
+  std::vector<variations::ActiveGroupId> synthetic_trials;
+  // Add two synthetic trials.
+  synthetic_trials.push_back(kSyntheticTrials[0]);
+  synthetic_trials.push_back(kSyntheticTrials[1]);
+
   log.RecordEnvironment(std::vector<std::unique_ptr<MetricsProvider>>(),
-                        kInstallDate, kEnabledDate);
+                        synthetic_trials, kInstallDate, kEnabledDate);
   // Check that the system profile on the log has the correct values set.
   CheckSystemProfile(log.system_profile());
 
@@ -272,15 +311,17 @@
   TestMetricsLog log_unknown(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
                              &client, &prefs_);
 
+  std::vector<variations::ActiveGroupId> synthetic_trials;
+
   log_unknown.RecordEnvironment(std::vector<std::unique_ptr<MetricsProvider>>(),
-                                kInstallDate, kEnabledDate);
+                                synthetic_trials, kInstallDate, kEnabledDate);
   EXPECT_FALSE(log_unknown.system_profile().has_uma_default_state());
 
   client.set_enable_default(EnableMetricsDefault::OPT_IN);
   TestMetricsLog log_opt_in(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
                             &client, &prefs_);
   log_opt_in.RecordEnvironment(std::vector<std::unique_ptr<MetricsProvider>>(),
-                               kInstallDate, kEnabledDate);
+                               synthetic_trials, kInstallDate, kEnabledDate);
   EXPECT_TRUE(log_opt_in.system_profile().has_uma_default_state());
   EXPECT_EQ(SystemProfileProto_UmaDefaultState_OPT_IN,
             log_opt_in.system_profile().uma_default_state());
@@ -289,7 +330,7 @@
   TestMetricsLog log_opt_out(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
                              &client, &prefs_);
   log_opt_out.RecordEnvironment(std::vector<std::unique_ptr<MetricsProvider>>(),
-                                kInstallDate, kEnabledDate);
+                                synthetic_trials, kInstallDate, kEnabledDate);
   EXPECT_TRUE(log_opt_out.system_profile().has_uma_default_state());
   EXPECT_EQ(SystemProfileProto_UmaDefaultState_OPT_OUT,
             log_opt_out.system_profile().uma_default_state());
@@ -298,7 +339,7 @@
   TestMetricsLog log_managed(kClientId, kSessionId, MetricsLog::ONGOING_LOG,
                              &client, &prefs_);
   log_managed.RecordEnvironment(std::vector<std::unique_ptr<MetricsProvider>>(),
-                                kInstallDate, kEnabledDate);
+                                synthetic_trials, kInstallDate, kEnabledDate);
   EXPECT_TRUE(log_managed.system_profile().has_uma_default_state());
   EXPECT_EQ(SystemProfileProto_UmaDefaultState_POLICY_FORCED_ENABLED,
             log_managed.system_profile().uma_default_state());
@@ -314,7 +355,9 @@
   TestMetricsProvider* test_provider = new TestMetricsProvider();
   std::vector<std::unique_ptr<MetricsProvider>> metrics_providers;
   metrics_providers.push_back(base::WrapUnique<MetricsProvider>(test_provider));
-  log.RecordEnvironment(metrics_providers, kInstallDate, kEnabledDate);
+  log.RecordEnvironment(metrics_providers,
+                        std::vector<variations::ActiveGroupId>(), kInstallDate,
+                        kEnabledDate);
   log.RecordStabilityMetrics(metrics_providers, base::TimeDelta(),
                              base::TimeDelta());
 
@@ -331,7 +374,9 @@
   TestMetricsProvider* test_provider = new TestMetricsProvider();
   std::vector<std::unique_ptr<MetricsProvider>> metrics_providers;
   metrics_providers.push_back(base::WrapUnique<MetricsProvider>(test_provider));
-  log.RecordEnvironment(metrics_providers, kInstallDate, kEnabledDate);
+  log.RecordEnvironment(metrics_providers,
+                        std::vector<variations::ActiveGroupId>(), kInstallDate,
+                        kEnabledDate);
   log.RecordStabilityMetrics(metrics_providers, base::TimeDelta(),
                              base::TimeDelta());
 
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc
index ef1d389..4e9fa9e 100644
--- a/components/metrics/metrics_service.cc
+++ b/components/metrics/metrics_service.cc
@@ -145,7 +145,6 @@
 #include "base/tracked_objects.h"
 #include "build/build_config.h"
 #include "components/metrics/environment_recorder.h"
-#include "components/metrics/field_trials_provider.h"
 #include "components/metrics/metrics_log.h"
 #include "components/metrics/metrics_log_manager.h"
 #include "components/metrics/metrics_log_uploader.h"
@@ -232,11 +231,8 @@
   if (install_date == 0)
     local_state_->SetInt64(prefs::kInstallDate, base::Time::Now().ToTimeT());
 
-  RegisterMetricsProvider(
-      base::MakeUnique<StabilityMetricsProvider>(local_state_));
-
-  RegisterMetricsProvider(base::MakeUnique<variations::FieldTrialsProvider>(
-      &synthetic_trial_registry_));
+  RegisterMetricsProvider(std::unique_ptr<metrics::MetricsProvider>(
+      new StabilityMetricsProvider(local_state_)));
 }
 
 MetricsService::~MetricsService() {
@@ -867,8 +863,12 @@
 
 void MetricsService::RecordCurrentEnvironment(MetricsLog* log) {
   DCHECK(client_);
+  std::vector<variations::ActiveGroupId> synthetic_trials;
+  synthetic_trial_registry_.GetSyntheticFieldTrialsOlderThan(
+      log->creation_time(), &synthetic_trials);
   std::string serialized_environment = log->RecordEnvironment(
-      metrics_providers_, GetInstallDate(), GetMetricsReportingEnabledDate());
+      metrics_providers_, synthetic_trials, GetInstallDate(),
+      GetMetricsReportingEnabledDate());
   client_->OnEnvironmentUpdate(&serialized_environment);
 }
 
diff --git a/components/metrics/metrics_service_unittest.cc b/components/metrics/metrics_service_unittest.cc
index 6c1497326..790c81b7 100644
--- a/components/metrics/metrics_service_unittest.cc
+++ b/components/metrics/metrics_service_unittest.cc
@@ -191,7 +191,8 @@
   // saved from a previous session.
   TestMetricsServiceClient client;
   TestMetricsLog log("client", 1, &client, GetLocalState());
-  log.RecordEnvironment(std::vector<std::unique_ptr<MetricsProvider>>(), 0, 0);
+  log.RecordEnvironment(std::vector<std::unique_ptr<MetricsProvider>>(),
+                        std::vector<variations::ActiveGroupId>(), 0, 0);
 
   // Record stability build time and version from previous session, so that
   // stability metrics (including exited cleanly flag) won't be cleared.
@@ -261,7 +262,8 @@
   // saved from a previous session.
   TestMetricsServiceClient client;
   TestMetricsLog log("client", 1, &client, GetLocalState());
-  log.RecordEnvironment(std::vector<std::unique_ptr<MetricsProvider>>(), 0, 0);
+  log.RecordEnvironment(std::vector<std::unique_ptr<MetricsProvider>>(),
+                        std::vector<variations::ActiveGroupId>(), 0, 0);
 
   // Record stability build time and version from previous session, so that
   // stability metrics (including exited cleanly flag) won't be cleared.
diff --git a/components/variations/synthetic_trial_registry.h b/components/variations/synthetic_trial_registry.h
index db37ade0..b15fff8 100644
--- a/components/variations/synthetic_trial_registry.h
+++ b/components/variations/synthetic_trial_registry.h
@@ -12,13 +12,12 @@
 
 namespace metrics {
 class MetricsServiceAccessor;
+class MetricsService;
 }  // namespace metrics
 
 namespace variations {
 
 struct ActiveGroupId;
-class FieldTrialsProvider;
-class FieldTrialsProviderTest;
 
 class SyntheticTrialRegistry {
  public:
@@ -33,8 +32,7 @@
 
  private:
   friend metrics::MetricsServiceAccessor;
-  friend FieldTrialsProvider;
-  friend FieldTrialsProviderTest;
+  friend metrics::MetricsService;
   FRIEND_TEST_ALL_PREFIXES(SyntheticTrialRegistryTest, RegisterSyntheticTrial);
   FRIEND_TEST_ALL_PREFIXES(SyntheticTrialRegistryTest,
                            RegisterSyntheticMultiGroupFieldTrial);
diff --git a/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc b/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
index 717527d3..3aae2ad7 100644
--- a/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
+++ b/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
@@ -12,6 +12,7 @@
 #include "base/scoped_observer.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "components/network_session_configurator/common/network_switches.h"
 #include "content/browser/browsing_data/browsing_data_filter_builder_impl.h"
 #include "content/browser/service_worker/service_worker_context_core_observer.h"
@@ -408,7 +409,15 @@
 // Tests that the header is recognized on the beginning, in the middle, and on
 // the end of a navigation redirect chain. Each of the three parts of the chain
 // may or may not send the header, so there are 8 configurations to test.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, RedirectNavigation) {
+
+// Crashes on Win only. https://crbug.com/741189
+#if defined(OS_WIN)
+#define MAYBE_RedirectNavigation DISABLED_RedirectNavigation
+#else
+#define MAYBE_RedirectNavigation RedirectNavigation
+#endif
+IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
+                       MAYBE_RedirectNavigation) {
   GURL page_urls[3] = {
       https_server()->GetURL("origin1.com", "/"),
       https_server()->GetURL("origin2.com", "/foo/bar"),
@@ -447,7 +456,15 @@
 // Tests that the header is recognized on the beginning, in the middle, and on
 // the end of a resource load redirect chain. Each of the three parts of the
 // chain may or may not send the header, so there are 8 configurations to test.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, RedirectResourceLoad) {
+
+// Crashes on Win only. https://crbug.com/741189
+#if defined(OS_WIN)
+#define MAYBE_RedirectResourceLoad DISABLED_RedirectResourceLoad
+#else
+#define MAYBE_RedirectResourceLoad RedirectResourceLoad
+#endif
+IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
+                       MAYBE_RedirectResourceLoad) {
   GURL resource_urls[3] = {
       https_server()->GetURL("origin1.com", "/redirect-start"),
       https_server()->GetURL("origin2.com", "/redirect-middle"),
@@ -619,7 +636,14 @@
 
 // Tests that Clear-Site-Data is only executed on a resource fetch
 // if credentials are allowed in that fetch.
-IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Credentials) {
+
+// Crashes on Win only. https://crbug.com/741189
+#if defined(OS_WIN)
+#define MAYBE_Credentials DISABLED_Credentials
+#else
+#define MAYBE_Credentials Credentials
+#endif
+IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, MAYBE_Credentials) {
   GURL page_template = https_server()->GetURL("origin1.com", "/");
   GURL same_origin_resource =
       https_server()->GetURL("origin1.com", "/resource");
diff --git a/content/browser/resources/media/media_internals.html b/content/browser/resources/media/media_internals.html
index fc16569..24801d8 100644
--- a/content/browser/resources/media/media_internals.html
+++ b/content/browser/resources/media/media_internals.html
@@ -7,6 +7,7 @@
 <html dir="$i18n{textdirection}" lang="$i18n{language}">
 <head>
   <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
   <title>Media Internals</title>
   <link rel="stylesheet" href="media_internals.css">
   <script src="chrome://resources/js/cr.js"></script>
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 178d504..b7fadcf8 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -774,7 +774,14 @@
 
 // Ensure that navigating subframes in --site-per-process mode works and the
 // correct documents are committed.
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
+
+// Crashes on Win only. https://crbug.com/746055
+#if defined(OS_WIN)
+#define MAYBE_CrossSiteIframe DISABLED_CrossSiteIframe
+#else
+#define MAYBE_CrossSiteIframe CrossSiteIframe
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrossSiteIframe) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1885,7 +1892,15 @@
 }
 
 // Ensure that OOPIFs are deleted after navigating to a new main frame.
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CleanupCrossSiteIframe) {
+
+// Crashes on Win only. https://crbug.com/746055
+#if defined(OS_WIN)
+#define MAYBE_CleanupCrossSiteIframe DISABLED_CleanupCrossSiteIframe
+#else
+#define MAYBE_CleanupCrossSiteIframe CleanupCrossSiteIframe
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+                       MAYBE_CleanupCrossSiteIframe) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1942,7 +1957,14 @@
 }
 
 // Ensure that root frames cannot be detached.
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, RestrictFrameDetach) {
+
+// Crashes on Win only. https://crbug.com/746055
+#if defined(OS_WIN)
+#define MAYBE_RestrictFrameDetach DISABLED_RestrictFrameDetach
+#else
+#define MAYBE_RestrictFrameDetach RestrictFrameDetach
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_RestrictFrameDetach) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -2004,7 +2026,13 @@
       DepictFrameTree(root));
 }
 
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateRemoteFrame) {
+// Crashes on Win only. https://crbug.com/746055
+#if defined(OS_WIN)
+#define MAYBE_NavigateRemoteFrame DISABLED_NavigateRemoteFrame
+#else
+#define MAYBE_NavigateRemoteFrame NavigateRemoteFrame
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_NavigateRemoteFrame) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -3210,8 +3238,15 @@
 
 // Ensure that when navigating a frame cross-process RenderFrameProxyHosts are
 // created in the FrameTree skipping the subtree of the navigating frame.
+
+// Crashes on Win only. https://crbug.com/746055
+#if defined(OS_WIN)
+#define MAYBE_ProxyCreationSkipsSubtree DISABLED_ProxyCreationSkipsSubtree
+#else
+#define MAYBE_ProxyCreationSkipsSubtree ProxyCreationSkipsSubtree
+#endif
 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
-                       ProxyCreationSkipsSubtree) {
+                       MAYBE_ProxyCreationSkipsSubtree) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -8380,7 +8415,14 @@
 // 2. Attribute injected dynamically via JavaScript
 // 3. Multiple levels of nesting (A-embed-B-embed-C)
 // 4. Cross-site subframe navigation
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, AllowFullscreen) {
+
+// Crashes on Win only. https://crbug.com/746055
+#if defined(OS_WIN)
+#define MAYBE_AllowFullscreen DISABLED_AllowFullscreen
+#else
+#define MAYBE_AllowFullscreen AllowFullscreen
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_AllowFullscreen) {
   // Load a page with a cross-site <iframe allowFullscreen>.
   GURL url_1(embedded_test_server()->GetURL(
       "a.com", "/page_with_allowfullscreen_frame.html"));
@@ -10464,8 +10506,17 @@
 // Check that subframes for the same site rendering in unrelated tabs start
 // sharing processes that are already dedicated to that site when over process
 // limit. See https://crbug.com/513036.
+
+// Crashes on Win only. https://crbug.com/746055
+#if defined(OS_WIN)
+#define MAYBE_SubframeProcessReuseWhenOverLimit \
+  DISABLED_SubframeProcessReuseWhenOverLimit
+#else
+#define MAYBE_SubframeProcessReuseWhenOverLimit \
+  SubframeProcessReuseWhenOverLimit
+#endif
 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
-                       SubframeProcessReuseWhenOverLimit) {
+                       MAYBE_SubframeProcessReuseWhenOverLimit) {
   // Set the process limit to 1.
   RenderProcessHost::SetMaxRendererProcessCount(1);
 
diff --git a/content/browser/top_document_isolation_browsertest.cc b/content/browser/top_document_isolation_browsertest.cc
index be1fa6e..cb57f06 100644
--- a/content/browser/top_document_isolation_browsertest.cc
+++ b/content/browser/top_document_isolation_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/common/content_features.h"
@@ -133,7 +134,14 @@
       DepictFrameTree(root()));
 }
 
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, NavigateSubframeToTopSite) {
+// Crashes on Win only. https://crbug.com/746063
+#if defined(OS_WIN)
+#define MAYBE_NavigateSubframeToTopSite DISABLED_NavigateSubframeToTopSite
+#else
+#define MAYBE_NavigateSubframeToTopSite NavigateSubframeToTopSite
+#endif
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
+                       MAYBE_NavigateSubframeToTopSite) {
   if (content::AreAllSitesIsolatedForTesting())
     return;  // Top Document Isolation is disabled in this mode.
 
@@ -195,8 +203,15 @@
       DepictFrameTree(root()));
 }
 
+// Crashes on Win only. https://crbug.com/746063
+#if defined(OS_WIN)
+#define MAYBE_NavigateToSubframeSiteWithPopup \
+  DISABLED_NavigateToSubframeSiteWithPopup
+#else
+#define MAYBE_NavigateToSubframeSiteWithPopup NavigateToSubframeSiteWithPopup
+#endif
 IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
-                       NavigateToSubframeSiteWithPopup) {
+                       MAYBE_NavigateToSubframeSiteWithPopup) {
   if (content::AreAllSitesIsolatedForTesting())
     return;  // Top Document Isolation is disabled in this mode.
 
@@ -283,8 +298,15 @@
       DepictFrameTree(root()));
 }
 
+// Crashes on Win only. https://crbug.com/746063
+#if defined(OS_WIN)
+#define MAYBE_NavigateToSubframeSiteWithPopup2 \
+  DISABLED_NavigateToSubframeSiteWithPopup2
+#else
+#define MAYBE_NavigateToSubframeSiteWithPopup2 NavigateToSubframeSiteWithPopup2
+#endif
 IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
-                       NavigateToSubframeSiteWithPopup2) {
+                       MAYBE_NavigateToSubframeSiteWithPopup2) {
   if (content::AreAllSitesIsolatedForTesting())
     return;  // Top Document Isolation is disabled in this mode.
 
@@ -399,7 +421,13 @@
       DepictFrameTree(root()));
 }
 
-IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, FramesForSitesInHistory) {
+// Crashes on Win only. https://crbug.com/746063
+#if defined(OS_WIN)
+#define MAYBE_FrameForSitesInHistory DISABLED_FrameForSitesInHistory
+#else
+#define MAYBE_FrameForSitesInHistory FrameForSitesInHistory
+#endif
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, MAYBE_FrameForSitesInHistory) {
   if (content::AreAllSitesIsolatedForTesting())
     return;  // Top Document Isolation is disabled in this mode.
 
diff --git a/content/common/media/media_devices.cc b/content/common/media/media_devices.cc
index 5eb8a18..90488d0 100644
--- a/content/common/media/media_devices.cc
+++ b/content/common/media/media_devices.cc
@@ -44,7 +44,9 @@
 MediaDeviceInfo& MediaDeviceInfo::operator=(MediaDeviceInfo&& other) = default;
 
 bool operator==(const MediaDeviceInfo& first, const MediaDeviceInfo& second) {
-  return first.device_id == second.device_id && first.label == second.label;
+  return first.device_id == second.device_id && first.label == second.label &&
+         first.group_id == second.group_id &&
+         first.video_facing == second.video_facing;
 }
 
 }  // namespace content
diff --git a/content/shell/renderer/layout_test/blink_test_runner.cc b/content/shell/renderer/layout_test/blink_test_runner.cc
index 39c1e32d..661d5f7a 100644
--- a/content/shell/renderer/layout_test/blink_test_runner.cc
+++ b/content/shell/renderer/layout_test/blink_test_runner.cc
@@ -405,37 +405,6 @@
       new ShellViewHostMsg_SetPopupBlockingEnabled(routing_id(), block_popups));
 }
 
-std::string BlinkTestRunner::makeURLErrorDescription(const WebURLError& error) {
-  std::string domain = error.domain.Utf8();
-  int code = error.reason;
-
-  if (domain == net::kErrorDomain) {
-    domain = "NSURLErrorDomain";
-    switch (error.reason) {
-    case net::ERR_ABORTED:
-      code = -999;  // NSURLErrorCancelled
-      break;
-    case net::ERR_UNSAFE_PORT:
-      // Our unsafe port checking happens at the network stack level, but we
-      // make this translation here to match the behavior of stock WebKit.
-      domain = "WebKitErrorDomain";
-      code = 103;
-      break;
-    case net::ERR_ADDRESS_INVALID:
-    case net::ERR_ADDRESS_UNREACHABLE:
-    case net::ERR_NETWORK_ACCESS_DENIED:
-      code = -1004;  // NSURLErrorCannotConnectToHost
-      break;
-    }
-  } else {
-    DLOG(WARNING) << "Unknown error domain";
-  }
-
-  return base::StringPrintf("<NSError domain %s, code %d, failing URL \"%s\">",
-                            domain.c_str(), code,
-                            error.unreachable_url.GetString().Utf8().data());
-}
-
 void BlinkTestRunner::UseUnfortunateSynchronousResizeMode(bool enable) {
   UseSynchronousResizeModeVisitor visitor(enable);
   RenderView::ForEach(&visitor);
diff --git a/content/shell/renderer/layout_test/blink_test_runner.h b/content/shell/renderer/layout_test/blink_test_runner.h
index 22c3f718..7662edb 100644
--- a/content/shell/renderer/layout_test/blink_test_runner.h
+++ b/content/shell/renderer/layout_test/blink_test_runner.h
@@ -84,7 +84,6 @@
   test_runner::TestPreferences* Preferences() override;
   void ApplyPreferences() override;
   void SetPopupBlockingEnabled(bool block_popups) override;
-  virtual std::string makeURLErrorDescription(const blink::WebURLError& error);
   void UseUnfortunateSynchronousResizeMode(bool enable) override;
   void EnableAutoResizeMode(const blink::WebSize& min_size,
                             const blink::WebSize& max_size) override;
diff --git a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm
index cc329b5..6355a937 100644
--- a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm
+++ b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm
@@ -46,6 +46,58 @@
   }
 }
 
+void RecordSigninImpressionWithAccountUserActionForAccessPoint(
+    signin_metrics::AccessPoint access_point) {
+  switch (access_point) {
+    case signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
+      base::RecordAction(base::UserMetricsAction(
+          "Signin_ImpressionWithAccount_FromBookmarkManager"));
+      break;
+    case signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS:
+      base::RecordAction(base::UserMetricsAction(
+          "Signin_ImpressionWithAccount_FromRecentTabs"));
+      break;
+    case signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS:
+      base::RecordAction(
+          base::UserMetricsAction("Signin_ImpressionWithAccount_FromSettings"));
+      break;
+    case signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER:
+      base::RecordAction(base::UserMetricsAction(
+          "Signin_ImpressionWithAccount_FromTabSwitcher"));
+      break;
+    default:
+      NOTREACHED() << "Unexpected value for access point "
+                   << static_cast<int>(access_point);
+      break;
+  }
+}
+
+void RecordSigninImpressionWithNoAccountUserActionForAccessPoint(
+    signin_metrics::AccessPoint access_point) {
+  switch (access_point) {
+    case signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
+      base::RecordAction(base::UserMetricsAction(
+          "Signin_ImpressionWithNoAccount_FromBookmarkManager"));
+      break;
+    case signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS:
+      base::RecordAction(base::UserMetricsAction(
+          "Signin_ImpressionWithNoAccount_FromRecentTabs"));
+      break;
+    case signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS:
+      base::RecordAction(base::UserMetricsAction(
+          "Signin_ImpressionWithNoAccount_FromSettings"));
+      break;
+    case signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER:
+      base::RecordAction(base::UserMetricsAction(
+          "Signin_ImpressionWithNoAccount_FromTabSwitcher"));
+      break;
+    default:
+      NOTREACHED() << "Unexpected value for access point "
+                   << static_cast<int>(access_point);
+      break;
+  }
+}
+
 void RecordSigninUserActionForAccessPoint(
     signin_metrics::AccessPoint access_point) {
   switch (access_point) {
@@ -215,6 +267,11 @@
     if (identities.count != 0) {
       [self selectIdentity:identities[0]];
     }
+    if (_defaultIdentity) {
+      RecordSigninImpressionWithAccountUserActionForAccessPoint(accessPoint);
+    } else {
+      RecordSigninImpressionWithNoAccountUserActionForAccessPoint(accessPoint);
+    }
     _identityServiceObserver =
         base::MakeUnique<ChromeIdentityServiceObserverBridge>(self);
     _browserProviderObserver =
diff --git a/ios/chrome/today_extension/today_metrics_logger.mm b/ios/chrome/today_extension/today_metrics_logger.mm
index 7eb52e32..55c2ddc 100644
--- a/ios/chrome/today_extension/today_metrics_logger.mm
+++ b/ios/chrome/today_extension/today_metrics_logger.mm
@@ -250,7 +250,8 @@
 
   log_->RecordEnvironment(
       std::vector<std::unique_ptr<metrics::MetricsProvider>>(),
-      [install_date longLongValue], [enabled_date longLongValue]);
+      std::vector<variations::ActiveGroupId>(), [install_date longLongValue],
+      [enabled_date longLongValue]);
 
   return true;
 }
diff --git a/ios/third_party/material_components_ios/README.chromium b/ios/third_party/material_components_ios/README.chromium
index 90acb03..cbb387d 100644
--- a/ios/third_party/material_components_ios/README.chromium
+++ b/ios/third_party/material_components_ios/README.chromium
@@ -1,7 +1,7 @@
 Name: Material Components for iOS
 URL: https://github.com/material-components/material-components-ios
 Version: 0
-Revision: d08f9c0c1926fce2964cffbc163385896c86798a
+Revision: cb191e7c014cc871b5351a3911a1d0bc71b71699
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index ce14ab8..d84a0ce 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -254,16 +254,6 @@
     "web_state/ui/wk_web_view_configuration_provider.mm",
     "web_state/web_controller_observer_bridge.h",
     "web_state/web_controller_observer_bridge.mm",
-    "web_state/web_state.mm",
-    "web_state/web_state_delegate.mm",
-    "web_state/web_state_delegate_bridge.mm",
-    "web_state/web_state_impl.h",
-    "web_state/web_state_impl.mm",
-    "web_state/web_state_observer.mm",
-    "web_state/web_state_observer_bridge.mm",
-    "web_state/web_state_policy_decider.mm",
-    "web_state/web_state_weak_ptr_factory.h",
-    "web_state/web_state_weak_ptr_factory.mm",
     "web_state/web_view_internal_creation_util.h",
     "web_state/web_view_internal_creation_util.mm",
     "web_state/wk_web_view_security_util.h",
@@ -338,6 +328,16 @@
     "web_state/ui/crw_web_controller.mm",
     "web_state/ui/crw_web_controller_container_view.h",
     "web_state/ui/crw_web_controller_container_view.mm",
+    "web_state/web_state.mm",
+    "web_state/web_state_delegate.mm",
+    "web_state/web_state_delegate_bridge.mm",
+    "web_state/web_state_impl.h",
+    "web_state/web_state_impl.mm",
+    "web_state/web_state_observer.mm",
+    "web_state/web_state_observer_bridge.mm",
+    "web_state/web_state_policy_decider.mm",
+    "web_state/web_state_weak_ptr_factory.h",
+    "web_state/web_state_weak_ptr_factory.mm",
   ]
 
   libs = [
diff --git a/ios/web/web_state/web_state.mm b/ios/web/web_state/web_state.mm
index 55ece67..ad5791d 100644
--- a/ios/web/web_state/web_state.mm
+++ b/ios/web/web_state/web_state.mm
@@ -4,10 +4,6 @@
 
 #import "ios/web/public/web_state/web_state.h"
 
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
 namespace web {
 
 WebState::CreateParams::CreateParams(web::BrowserState* browser_state)
diff --git a/ios/web/web_state/web_state_delegate.mm b/ios/web/web_state/web_state_delegate.mm
index 2c58355..c6a2def0 100644
--- a/ios/web/web_state/web_state_delegate.mm
+++ b/ios/web/web_state/web_state_delegate.mm
@@ -6,10 +6,6 @@
 
 #import "ios/web/public/web_state/web_state.h"
 
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
 namespace web {
 
 WebStateDelegate::WebStateDelegate() {}
diff --git a/ios/web/web_state/web_state_delegate_bridge.mm b/ios/web/web_state/web_state_delegate_bridge.mm
index b4c1255..797e9f46 100644
--- a/ios/web/web_state/web_state_delegate_bridge.mm
+++ b/ios/web/web_state/web_state_delegate_bridge.mm
@@ -7,10 +7,6 @@
 #include "base/logging.h"
 #import "ios/web/public/web_state/context_menu_params.h"
 
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
 namespace web {
 
 WebStateDelegateBridge::WebStateDelegateBridge(id<CRWWebStateDelegate> delegate)
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index c6a673e..676b8af 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -44,10 +44,6 @@
 #include "net/http/http_response_headers.h"
 #include "ui/gfx/image/image.h"
 
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
 namespace web {
 
 /* static */
@@ -177,7 +173,7 @@
 
 void WebStateImpl::SetWebController(CRWWebController* web_controller) {
   [web_controller_ close];
-  web_controller_.reset(web_controller);
+  web_controller_.reset([web_controller retain]);
 }
 
 void WebStateImpl::OnTitleChanged() {
diff --git a/ios/web/web_state/web_state_observer.mm b/ios/web/web_state/web_state_observer.mm
index 4c24630..1408a6e8 100644
--- a/ios/web/web_state/web_state_observer.mm
+++ b/ios/web/web_state/web_state_observer.mm
@@ -7,10 +7,6 @@
 #include "ios/web/public/load_committed_details.h"
 #import "ios/web/public/web_state/web_state.h"
 
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
 namespace web {
 
 WebStateObserver::WebStateObserver(WebState* web_state) : web_state_(nullptr) {
diff --git a/ios/web/web_state/web_state_observer_bridge.mm b/ios/web/web_state/web_state_observer_bridge.mm
index 12de262..73982ff 100644
--- a/ios/web/web_state/web_state_observer_bridge.mm
+++ b/ios/web/web_state/web_state_observer_bridge.mm
@@ -4,10 +4,6 @@
 
 #import "ios/web/public/web_state/web_state_observer_bridge.h"
 
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
 namespace web {
 
 WebStateObserverBridge::WebStateObserverBridge(web::WebState* webState,
diff --git a/ios/web/web_state/web_state_policy_decider.mm b/ios/web/web_state/web_state_policy_decider.mm
index 5f3e69d..f061dfa12 100644
--- a/ios/web/web_state/web_state_policy_decider.mm
+++ b/ios/web/web_state/web_state_policy_decider.mm
@@ -7,10 +7,6 @@
 #import "ios/web/public/web_state/web_state.h"
 #import "ios/web/web_state/web_state_impl.h"
 
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
 namespace web {
 
 WebStatePolicyDecider::WebStatePolicyDecider(WebState* web_state)
diff --git a/ios/web/web_state/web_state_weak_ptr_factory.mm b/ios/web/web_state/web_state_weak_ptr_factory.mm
index 2b94ef4..3b93e4b 100644
--- a/ios/web/web_state/web_state_weak_ptr_factory.mm
+++ b/ios/web/web_state/web_state_weak_ptr_factory.mm
@@ -6,10 +6,6 @@
 
 #import "ios/web/public/web_state/web_state.h"
 
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
 namespace web {
 
 // static
diff --git a/ios/web/webui/web_ui_mojo_inttest.mm b/ios/web/webui/web_ui_mojo_inttest.mm
index 4e64d41e..0d240d8c 100644
--- a/ios/web/webui/web_ui_mojo_inttest.mm
+++ b/ios/web/webui/web_ui_mojo_inttest.mm
@@ -147,23 +147,6 @@
         new TestWebUIControllerFactory(ui_handler_.get()));
   }
 
-  void TearDown() override {
-    @autoreleasepool {
-      // WebState owns CRWWebUIManager. When WebState is destroyed,
-      // CRWWebUIManager is autoreleased and will be destroyed upon autorelease
-      // pool purge. However in this test, WebTest destructor is called before
-      // PlatformTest, thus CRWWebUIManager outlives the WebThreadBundle.
-      // However, CRWWebUIManager owns a URLFetcherImpl, which DCHECKs that its
-      // destructor is called on UI web thread. Hence, URLFetcherImpl has to
-      // outlive the WebThreadBundle, since [NSThread mainThread] will not be
-      // WebThread::UI once WebThreadBundle is destroyed.
-      web_state_.reset();
-      ui_handler_.reset();
-    }
-
-    WebIntTest::TearDown();
-  }
-
   // Returns WebState which loads test WebUI page.
   WebStateImpl* web_state() { return web_state_.get(); }
   // Returns UI handler which communicates with WebUI page.
@@ -184,33 +167,31 @@
 #endif
 // TODO(crbug.com/720098): Enable this test on device.
 TEST_F(WebUIMojoTest, MAYBE_MessageExchange) {
-  @autoreleasepool {
-    web_state()->SetWebUsageEnabled(true);
-    web_state()->GetView();  // WebState won't load URL without view.
-    GURL url(url::SchemeHostPort(kTestWebUIScheme, kTestWebUIURLHost, 0)
-                 .Serialize());
-    NavigationManager::WebLoadParams load_params(url);
-    web_state()->GetNavigationManager()->LoadURLWithParams(load_params);
+  web_state()->SetWebUsageEnabled(true);
+  web_state()->GetView();  // WebState won't load URL without view.
+  GURL url(
+      url::SchemeHostPort(kTestWebUIScheme, kTestWebUIURLHost, 0).Serialize());
+  NavigationManager::WebLoadParams load_params(url);
+  web_state()->GetNavigationManager()->LoadURLWithParams(load_params);
 
-    // Wait until |TestUIHandler| receives "fin" message from WebUI page.
-    bool fin_received = testing::WaitUntilConditionOrTimeout(kMessageTimeout, ^{
-      // Flush any pending tasks. Don't RunUntilIdle() because
-      // RunUntilIdle() is incompatible with mojo::SimpleWatcher's
-      // automatic arming behavior, which Mojo JS still depends upon.
-      //
-      // TODO(crbug.com/701875): Introduce the full watcher API to JS and get
-      // rid of this hack.
-      base::RunLoop loop;
-      base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                    loop.QuitClosure());
-      loop.Run();
-      return test_ui_handler()->IsFinReceived();
-    });
+  // Wait until |TestUIHandler| receives "fin" message from WebUI page.
+  bool fin_received = testing::WaitUntilConditionOrTimeout(kMessageTimeout, ^{
+    // Flush any pending tasks. Don't RunUntilIdle() because
+    // RunUntilIdle() is incompatible with mojo::SimpleWatcher's
+    // automatic arming behavior, which Mojo JS still depends upon.
+    //
+    // TODO(crbug.com/701875): Introduce the full watcher API to JS and get rid
+    // of this hack.
+    base::RunLoop loop;
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  loop.QuitClosure());
+    loop.Run();
+    return test_ui_handler()->IsFinReceived();
+  });
 
-    ASSERT_TRUE(fin_received);
-    EXPECT_FALSE(web_state()->IsLoading());
-    EXPECT_EQ(url, web_state()->GetLastCommittedURL());
-  }
+  ASSERT_TRUE(fin_received);
+  EXPECT_FALSE(web_state()->IsLoading());
+  EXPECT_EQ(url, web_state()->GetLastCommittedURL());
 }
 
 }  // namespace web
diff --git a/media/midi/BUILD.gn b/media/midi/BUILD.gn
index 5bbf810..5e40368 100644
--- a/media/midi/BUILD.gn
+++ b/media/midi/BUILD.gn
@@ -156,6 +156,17 @@
     }
   }
 
+  if (is_chromeos) {
+    # CrOS version can be used with target_os="chromeos" on Linux.
+    # MIDI Service client library should be added here. We would have a separate
+    # build flag, use_midis, to use the real MIDI Service on Chrome OS device
+    # builds, and add a mocked service for unit tests to run on Linux.
+    sources += [
+      "chromeos/midi_manager_cros.cc",
+      "chromeos/midi_manager_cros.h",
+    ]
+  }
+
   if (use_alsa && use_udev) {
     deps += [
       "//crypto",
diff --git a/media/midi/chromeos/midi_manager_cros.cc b/media/midi/chromeos/midi_manager_cros.cc
new file mode 100644
index 0000000..b554e0ab
--- /dev/null
+++ b/media/midi/chromeos/midi_manager_cros.cc
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/midi/chromeos/midi_manager_cros.h"
+
+#include "media/midi/midi_manager_alsa.h"
+#include "media/midi/midi_switches.h"
+
+namespace midi {
+
+MidiManagerCros::MidiManagerCros(MidiService* service) : MidiManager(service) {}
+
+MidiManagerCros::~MidiManagerCros() = default;
+
+MidiManager* MidiManager::Create(MidiService* service) {
+  // Note: Because of crbug.com/719489, chrome://flags does not affect
+  // base::FeatureList::IsEnabled when you build target_os="chromeos" on Linux.
+  if (base::FeatureList::IsEnabled(features::kMidiManagerCros))
+    return new MidiManagerCros(service);
+  return new MidiManagerAlsa(service);
+}
+
+}  // namespace midi
diff --git a/media/midi/chromeos/midi_manager_cros.h b/media/midi/chromeos/midi_manager_cros.h
new file mode 100644
index 0000000..4a8f94a
--- /dev/null
+++ b/media/midi/chromeos/midi_manager_cros.h
@@ -0,0 +1,23 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_MIDI_CHROMEOS_MIDI_MANAGER_CROS_H_
+#define MEDIA_MIDI_CHROMEOS_MIDI_MANAGER_CROS_H_
+
+#include "media/midi/midi_export.h"
+#include "media/midi/midi_manager.h"
+
+namespace midi {
+
+class MIDI_EXPORT MidiManagerCros final : public MidiManager {
+ public:
+  explicit MidiManagerCros(MidiService* service);
+  ~MidiManagerCros() override;
+
+  DISALLOW_COPY_AND_ASSIGN(MidiManagerCros);
+};
+
+}  // namespace midi
+
+#endif  // MEDIA_MIDI_CHROMEOS_MIDI_MANAGER_CROS_H_
diff --git a/media/midi/midi_manager_alsa.cc b/media/midi/midi_manager_alsa.cc
index 1ef6e569..dc33c29 100644
--- a/media/midi/midi_manager_alsa.cc
+++ b/media/midi/midi_manager_alsa.cc
@@ -25,6 +25,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "crypto/sha2.h"
 #include "media/midi/midi_port_info.h"
 #include "media/midi/midi_service.h"
@@ -164,6 +165,8 @@
 MidiManagerAlsa::MidiManagerAlsa(MidiService* service) : MidiManager(service) {}
 
 MidiManagerAlsa::~MidiManagerAlsa() {
+  base::AutoLock lock(lazy_init_member_lock_);
+
   // Extra CHECK to verify all members are already reset.
   CHECK(!in_client_);
   CHECK(!out_client_);
@@ -178,6 +181,8 @@
     return CompleteInitialization(Result::INITIALIZATION_ERROR);
   }
 
+  base::AutoLock lock(lazy_init_member_lock_);
+
   // Create client handles.
   snd_seq_t* tmp_seq = nullptr;
   int err =
@@ -296,15 +301,19 @@
 }
 
 void MidiManagerAlsa::Finalize() {
-  // Close the out client. This will trigger the event thread to stop,
-  // because of SND_SEQ_EVENT_CLIENT_EXIT.
-  out_client_.reset();
+  {
+    base::AutoLock lock(out_client_lock_);
+    // Close the out client. This will trigger the event thread to stop,
+    // because of SND_SEQ_EVENT_CLIENT_EXIT.
+    out_client_.reset();
+  }
 
   // Ensure that no task is running any more.
   bool result = service()->task_service()->UnbindInstance();
   CHECK(result);
 
   // Destruct the other stuff we initialized in StartInitialization().
+  base::AutoLock lock(lazy_init_member_lock_);
   udev_monitor_.reset();
   udev_.reset();
   decoder_.reset();
@@ -857,6 +866,9 @@
       base::AutoLock lock(out_ports_lock_);
       auto it = out_ports_.find(port_index);
       if (it != out_ports_.end()) {
+        base::AutoLock lock(out_client_lock_);
+        if (!out_client_)
+          return;
         snd_seq_ev_set_source(&event, it->second);
         snd_seq_ev_set_subs(&event);
         snd_seq_ev_set_direct(&event);
@@ -1377,8 +1389,10 @@
   return true;
 }
 
+#if !defined(OS_CHROMEOS)
 MidiManager* MidiManager::Create(MidiService* service) {
   return new MidiManagerAlsa(service);
 }
+#endif
 
 }  // namespace midi
diff --git a/media/midi/midi_manager_alsa.h b/media/midi/midi_manager_alsa.h
index de48824..c563584 100644
--- a/media/midi/midi_manager_alsa.h
+++ b/media/midi/midi_manager_alsa.h
@@ -417,10 +417,15 @@
   // wait for our information from ALSA and udev to get back in sync.
   int alsa_card_midi_count_ = 0;
 
+  // Guards members below. They are initialized before posting any tasks running
+  // on TaskRunner, and finalized after all posted tasks run.
+  base::Lock lazy_init_member_lock_;
+
   // ALSA seq handles and ids.
   ScopedSndSeqPtr in_client_;
   int in_client_id_;
-  ScopedSndSeqPtr out_client_;
+  base::Lock out_client_lock_;  // guards out_client_
+  ScopedSndSeqPtr out_client_;  // guarded by out_client_lock_
   int out_client_id_;
   int in_port_id_;
 
diff --git a/media/midi/midi_switches.cc b/media/midi/midi_switches.cc
index 96e7974b..c64c544 100644
--- a/media/midi/midi_switches.cc
+++ b/media/midi/midi_switches.cc
@@ -18,6 +18,11 @@
                                       base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
 
+#if defined(OS_CHROMEOS)
+const base::Feature kMidiManagerCros{"MidiManagerCros",
+                                     base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
 const base::Feature kMidiManagerDynamicInstantiation{
     "MidiManagerDynamicInstantiation", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/media/midi/midi_switches.h b/media/midi/midi_switches.h
index b5e45b0..e6b3526 100644
--- a/media/midi/midi_switches.h
+++ b/media/midi/midi_switches.h
@@ -22,6 +22,10 @@
 MIDI_EXPORT extern const base::Feature kMidiManagerWinrt;
 #endif
 
+#if defined(OS_CHROMEOS)
+MIDI_EXPORT extern const base::Feature kMidiManagerCros;
+#endif
+
 MIDI_EXPORT extern const base::Feature kMidiManagerDynamicInstantiation;
 
 }  // namespace features
diff --git a/services/ui/ime/test_ime_driver/test_ime_driver.cc b/services/ui/ime/test_ime_driver/test_ime_driver.cc
index 8d1aa63..8e17f1f 100644
--- a/services/ui/ime/test_ime_driver/test_ime_driver.cc
+++ b/services/ui/ime/test_ime_driver/test_ime_driver.cc
@@ -4,6 +4,8 @@
 
 #include "services/ui/ime/test_ime_driver/test_ime_driver.h"
 
+#include <utility>
+
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/ui/public/interfaces/ime/ime.mojom.h"
 
@@ -21,14 +23,14 @@
   void OnTextInputTypeChanged(TextInputType text_input_type) override {}
   void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override {}
   void ProcessKeyEvent(std::unique_ptr<Event> key_event,
-                       const ProcessKeyEventCallback& callback) override {
+                       ProcessKeyEventCallback callback) override {
     DCHECK(key_event->IsKeyEvent());
 
     if (key_event->AsKeyEvent()->is_char()) {
       client_->InsertChar(std::move(key_event));
-      callback.Run(true);
+      std::move(callback).Run(true);
     } else {
-      callback.Run(false);
+      std::move(callback).Run(false);
     }
   }
   void CancelComposition() override {}
diff --git a/services/ui/public/interfaces/ime/BUILD.gn b/services/ui/public/interfaces/ime/BUILD.gn
index c84682d..85909fb 100644
--- a/services/ui/public/interfaces/ime/BUILD.gn
+++ b/services/ui/public/interfaces/ime/BUILD.gn
@@ -15,9 +15,6 @@
     "//ui/gfx/geometry/mojo",
     "//ui/gfx/range/mojo",
   ]
-
-  # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
-  use_once_callback = false
 }
 
 mojom("test_interfaces") {
@@ -28,7 +25,4 @@
   public_deps = [
     ":ime",
   ]
-
-  # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
-  use_once_callback = false
 }
diff --git a/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc b/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc
index 4497652..cfaec6f8 100644
--- a/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc
+++ b/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "services/ui/public/interfaces/ime/ime_struct_traits.h"
 
+#include <utility>
+
 #include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
@@ -32,12 +34,12 @@
  private:
   // mojom::IMEStructTraitsTest:
   void EchoTextInputMode(TextInputMode in,
-                         const EchoTextInputModeCallback& callback) override {
-    callback.Run(in);
+                         EchoTextInputModeCallback callback) override {
+    std::move(callback).Run(in);
   }
   void EchoTextInputType(TextInputType in,
-                         const EchoTextInputTypeCallback& callback) override {
-    callback.Run(in);
+                         EchoTextInputTypeCallback callback) override {
+    std::move(callback).Run(in);
   }
 
   base::MessageLoop loop_;  // A MessageLoop is needed for Mojo IPC to work.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/skip-waiting-installed.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/skip-waiting-installed.https.html
index 93dc06d..21e26be5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/skip-waiting-installed.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/skip-waiting-installed.https.html
@@ -20,15 +20,14 @@
           assert_equals(
             message, 'PASS',
             'skipWaiting promise should be resolved with undefined');
-
-          assert_equals(registration.active.scriptURL, normalizeURL(url2),
-                        'skipWaiting should make worker become active');
         });
     var saw_controllerchanged = new Promise(function(resolve) {
         oncontrollerchanged = function() {
             assert_equals(
                 frame_sw.controller.scriptURL, normalizeURL(url2),
                 'Controller scriptURL should change to the second one');
+            assert_equals(registration.active.scriptURL, normalizeURL(url2),
+                          'Worker which calls skipWaiting should be active by controllerchange');
             resolve();
         };
       });
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-clear-function-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-clear-function-expected.txt
index 816acea..a30d1dc 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-clear-function-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-clear-function-expected.txt
@@ -1,13 +1,31 @@
 CONSOLE MESSAGE: line 10: one
 CONSOLE MESSAGE: line 11: two
 CONSOLE MESSAGE: line 12: three
+CONSOLE MESSAGE: line 10: one
+CONSOLE MESSAGE: line 11: two
+CONSOLE MESSAGE: line 12: three
 Tests that console is cleared via console.clear() method
 
 Bug 101021
+
+Running: clearFromConsoleAPI
 === Before clear ===
 console-clear-function.html:10 one
 console-clear-function.html:11 two
 console-clear-function.html:12 three
 === After clear ===
-console-clear-function.html:19 Console was cleared
+console-clear-function.html:17 Console was cleared
+
+Running: shouldNotClearWithPreserveLog
+=== Before clear ===
+console-clear-function.html:17 Console was cleared
+console-clear-function.html:10 one
+console-clear-function.html:11 two
+console-clear-function.html:12 three
+=== After clear ===
+console-clear-function.html:17 Console was cleared
+console-clear-function.html:10 one
+console-clear-function.html:11 two
+console-clear-function.html:12 three
+console-clear-function.html:17 console.clear() was prevented due to 'Preserve log'
 
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-clear-function.html b/third_party/WebKit/LayoutTests/inspector/console/console-clear-function.html
index 691ce56..d282e05 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-clear-function.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-clear-function.html
@@ -12,23 +12,40 @@
     console.log("three");
 }
 
-log();
-
-function foo()
+function clearConsoleFromPage()
 {
     console.clear();
 }
 
 async function test()
 {
-    InspectorTest.addResult("=== Before clear ===");
-    InspectorTest.dumpConsoleMessages();
+    InspectorTest.runTestSuite([
+        async function clearFromConsoleAPI(next) {
+            await InspectorTest.RuntimeAgent.evaluate("log();");
+            InspectorTest.addResult("=== Before clear ===");
+            InspectorTest.dumpConsoleMessages();
 
-    await InspectorTest.RuntimeAgent.evaluate("foo();");
+            await InspectorTest.RuntimeAgent.evaluate("clearConsoleFromPage();");
 
-    InspectorTest.addResult("=== After clear ===");
-    InspectorTest.dumpConsoleMessages();
-    InspectorTest.completeTest();
+            InspectorTest.addResult("=== After clear ===");
+            InspectorTest.dumpConsoleMessages();
+            next();
+        },
+
+        async function shouldNotClearWithPreserveLog(next) {
+            await InspectorTest.RuntimeAgent.evaluate("log();");
+            InspectorTest.addResult("=== Before clear ===");
+            InspectorTest.dumpConsoleMessages();
+            Common.moduleSetting("preserveConsoleLog").set(true);
+
+            await InspectorTest.RuntimeAgent.evaluate("clearConsoleFromPage();");
+
+            InspectorTest.addResult("=== After clear ===");
+            InspectorTest.dumpConsoleMessages();
+            Common.moduleSetting("preserveConsoleLog").set(false);
+            next();
+        }
+    ]);
 }
 
 </script>
@@ -38,7 +55,7 @@
 <p>
 Tests that console is cleared via console.clear() method
 </p>
-<a href="https://bugs.webkit.org/show_bug.cgi?id=101021">Bug 101021 </a>
+<a href="https://bugs.webkit.org/show_bug.cgi?id=101021">Bug 101021</a>
 
 </body>
 </html>
diff --git a/third_party/WebKit/PerformanceTests/CSS/ChangeStyleDeepTree.html b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleDeepTree.html
index 5947a8e..f56ac7c 100644
--- a/third_party/WebKit/PerformanceTests/CSS/ChangeStyleDeepTree.html
+++ b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleDeepTree.html
@@ -28,9 +28,9 @@
             run: function() {
                 for (var i=0; i < length; i++) {
                     allElements[i].id = "item";
-                    PerfTestRunner.forceLayout(allElements[i]);
+                    forceStyleRecalc(allElements[i]);
                     allElements[i].id = "";
-                    PerfTestRunner.forceLayout(allElements[i]);
+                    forceStyleRecalc(allElements[i]);
                 }
             },
             tracingCategories: 'blink',
diff --git a/third_party/WebKit/PerformanceTests/CSS/ChangeStyleNestedPseudoSelector.html b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleNestedPseudoSelector.html
new file mode 100644
index 0000000..863c2af
--- /dev/null
+++ b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleNestedPseudoSelector.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../resources/runner.js"></script>
+    <script src="resources/utils.js"></script>
+</head>
+<body>
+</body>
+    <script>
+        createRegularDOMTree();
+        PerfTestRunner.measureTime({
+            description: "Measures the performance of a solo pseudo selector applied on a grandchild of a div.",
+            run: function() {
+                var rule = applyCSSRule("div div div:after { content: 'after'; }");
+                forceStyleRecalc(document.body);
+                rule.remove();
+                forceStyleRecalc(document.body);
+            },
+            tracingCategories: 'blink',
+            traceEventsToMeasure: [
+                'Document::updateStyle',
+                'Document::recalcStyle',
+                'Document::rebuildLayoutTree'
+            ]
+        });
+    </script>
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/PerformanceTests/CSS/ChangeStylePairOfNthChildSelector.html b/third_party/WebKit/PerformanceTests/CSS/ChangeStylePairOfNthChildSelector.html
new file mode 100644
index 0000000..8f5bcdf2
--- /dev/null
+++ b/third_party/WebKit/PerformanceTests/CSS/ChangeStylePairOfNthChildSelector.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../resources/runner.js"></script>
+    <script src="resources/utils.js"></script>
+</head>
+<body>
+</body>
+    <script>
+        createRegularDOMTree();
+        PerfTestRunner.measureTime({
+            description: "Measures the performance of a pair of nth-child selectors.",
+            run: function() {
+                var rule = applyCSSRule("div:nth-child(1) div:nth-child(1) div { color: red; }");
+                forceStyleRecalc(document.body);
+                rule.remove();
+                forceStyleRecalc(document.body);
+            },
+            tracingCategories: 'blink',
+            traceEventsToMeasure: [
+                'Document::updateStyle',
+                'Document::recalcStyle',
+                'Document::rebuildLayoutTree'
+            ]
+        });
+    </script>
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/PerformanceTests/CSS/ChangeStyleShallowTree.html b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleShallowTree.html
index 554dfca..7a9a8ef 100644
--- a/third_party/WebKit/PerformanceTests/CSS/ChangeStyleShallowTree.html
+++ b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleShallowTree.html
@@ -28,9 +28,9 @@
             run: function() {
                 for (var i=0; i < length; i++) {
                     allElements[i].id = "item";
-                    PerfTestRunner.forceLayout(allElements[i]);
+                    forceStyleRecalc(allElements[i]);
                     allElements[i].id = "";
-                    PerfTestRunner.forceLayout(allElements[i]);
+                    forceStyleRecalc(allElements[i]);
                 }
             },
             tracingCategories: 'blink',
diff --git a/third_party/WebKit/PerformanceTests/CSS/ChangeStyleSingleNthChildSelector.html b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleSingleNthChildSelector.html
new file mode 100644
index 0000000..d2ba23d
--- /dev/null
+++ b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleSingleNthChildSelector.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../resources/runner.js"></script>
+    <script src="resources/utils.js"></script>
+</head>
+<body>
+</body>
+    <script>
+        createRegularDOMTree();
+        PerfTestRunner.measureTime({
+            description: "Measures the performance of a nth-child selector.",
+            run: function() {
+                var rule = applyCSSRule("div:nth-child(1) div { color: red; }");
+                forceStyleRecalc(document.body);
+                rule.remove();
+                forceStyleRecalc(document.body);
+            },
+            tracingCategories: 'blink',
+            traceEventsToMeasure: [
+                'Document::updateStyle',
+                'Document::recalcStyle',
+                'Document::rebuildLayoutTree'
+            ]
+        });
+    </script>
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/PerformanceTests/CSS/ChangeStyleSinglePseudoSelector.html b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleSinglePseudoSelector.html
new file mode 100644
index 0000000..335a15e8f2
--- /dev/null
+++ b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleSinglePseudoSelector.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../resources/runner.js"></script>
+    <script src="resources/utils.js"></script>
+</head>
+<body>
+</body>
+    <script>
+        createRegularDOMTree();
+        PerfTestRunner.measureTime({
+            description: "Measures the performance of a solo pseudo selector.",
+            run: function() {
+                var rule = applyCSSRule("div:after { content: 'after'; }");
+                forceStyleRecalc(document.body);
+                rule.remove();
+                forceStyleRecalc(document.body);
+            },
+            tracingCategories: 'blink',
+            traceEventsToMeasure: [
+                'Document::updateStyle',
+                'Document::recalcStyle',
+                'Document::rebuildLayoutTree'
+            ]
+        });
+    </script>
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/PerformanceTests/CSS/resources/utils.js b/third_party/WebKit/PerformanceTests/CSS/resources/utils.js
index cc06c0a..e6e39cba 100644
--- a/third_party/WebKit/PerformanceTests/CSS/resources/utils.js
+++ b/third_party/WebKit/PerformanceTests/CSS/resources/utils.js
@@ -9,9 +9,25 @@
 }
 
 function createDeepDOMTree() {
-        createDOMTree(document.body, 2, 10);
+    createDOMTree(document.body, 2, 10);
+}
+
+function forceStyleRecalc(node) {
+    node.offsetTop; // forces style recalc
 }
 
 function createShallowDOMTree() {
-        createDOMTree(document.body, 10, 2);
-}
\ No newline at end of file
+    createDOMTree(document.body, 10, 2);
+}
+
+function createRegularDOMTree() {
+    createDOMTree(document.body, 6, 6);
+}
+
+function applyCSSRule(rule) {
+    var css = document.createElement("style");
+    css.type = "text/css";
+    css.innerHTML = rule;
+    document.body.appendChild(css);
+    return css;
+}
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
index 185716d..857e7dca 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -296,20 +296,6 @@
       Event::Create(EventTypeNames::selectionchange));
 }
 
-void FrameSelection::SetSelection(const SelectionInFlatTree& new_selection,
-                                  SetSelectionOptions options,
-                                  CursorAlignOnScroll align,
-                                  TextGranularity granularity) {
-  new_selection.AssertValidFor(GetDocument());
-  SelectionInDOMTree::Builder builder;
-  builder.SetAffinity(new_selection.Affinity())
-      .SetBaseAndExtent(ToPositionInDOMTree(new_selection.Base()),
-                        ToPositionInDOMTree(new_selection.Extent()))
-      .SetIsDirectional(new_selection.IsDirectional())
-      .SetIsHandleVisible(new_selection.IsHandleVisible());
-  return SetSelection(builder.Build(), options, align, granularity);
-}
-
 void FrameSelection::NodeChildrenWillBeRemoved(ContainerNode& container) {
   if (!container.InActiveDocument())
     return;
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.h b/third_party/WebKit/Source/core/editing/FrameSelection.h
index 4f0b8c95..e897f56 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.h
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.h
@@ -114,11 +114,6 @@
                     SetSelectionOptions = kCloseTyping | kClearTypingStyle,
                     CursorAlignOnScroll = CursorAlignOnScroll::kIfNeeded,
                     TextGranularity = TextGranularity::kCharacter);
-
-  void SetSelection(const SelectionInFlatTree&,
-                    SetSelectionOptions = kCloseTyping | kClearTypingStyle,
-                    CursorAlignOnScroll = CursorAlignOnScroll::kIfNeeded,
-                    TextGranularity = TextGranularity::kCharacter);
   void SelectAll(EUserTriggered = kNotUserTriggered);
   void Clear();
   bool IsHidden() const;
diff --git a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
index eafe272..b6dd9d6 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
@@ -166,9 +166,10 @@
   // Select "two" for selection in DOM tree
   // Select "twoone" for selection in Flat tree
   Selection().SetSelection(
-      SelectionInFlatTree::Builder()
-          .Collapse(PositionInFlatTree(host, 0))
-          .Extend(PositionInFlatTree(GetDocument().body(), 2))
+      SelectionInDOMTree::Builder()
+          .Collapse(ToPositionInDOMTree(PositionInFlatTree(host, 0)))
+          .Extend(
+              ToPositionInDOMTree(PositionInFlatTree(GetDocument().body(), 2)))
           .Build());
   Selection().Modify(FrameSelection::kAlterationExtend, kDirectionForward,
                      TextGranularity::kWord);
@@ -450,9 +451,8 @@
 
   Node* text_node = shadow_root->firstChild();
   Selection().SetSelection(
-      SelectionInFlatTree::Builder()
-          .SetBaseAndExtent(PositionInFlatTree(text_node, 0),
-                            PositionInFlatTree(text_node, 3))
+      SelectionInDOMTree::Builder()
+          .SetBaseAndExtent(Position(text_node, 0), Position(text_node, 3))
           .Build());
   EXPECT_EQ_SELECTED_TEXT("hey");
   EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsRange());
diff --git a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
index 72ecb59..dfd7b6f 100644
--- a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
@@ -42,6 +42,9 @@
       end_offset_(end_offset) {
   DCHECK(start_layout_object_);
   DCHECK(end_layout_object_);
+  traverse_stop_ = end_layout_object_->ChildAt(end_offset);
+  if (!traverse_stop_)
+    traverse_stop_ = end_layout_object_->NextInPreOrderAfterChildren();
   if (start_layout_object_ != end_layout_object_)
     return;
   DCHECK_LT(start_offset_, end_offset_);
@@ -79,12 +82,8 @@
     current_ = nullptr;
     return;
   }
+  range_ = range;
   current_ = range->StartLayoutObject();
-  included_end_ = range->EndLayoutObject();
-  stop_ = range->EndLayoutObject()->ChildAt(range->EndOffset());
-  if (stop_)
-    return;
-  stop_ = range->EndLayoutObject()->NextInPreOrderAfterChildren();
 }
 
 LayoutObject* SelectionPaintRange::Iterator::operator*() const {
@@ -94,9 +93,10 @@
 
 SelectionPaintRange::Iterator& SelectionPaintRange::Iterator::operator++() {
   DCHECK(current_);
-  for (current_ = current_->NextInPreOrder(); current_ && current_ != stop_;
+  for (current_ = current_->NextInPreOrder();
+       current_ && current_ != range_->traverse_stop_;
        current_ = current_->NextInPreOrder()) {
-    if (current_ == included_end_ || current_->CanBeSelectionLeaf())
+    if (current_->CanBeSelectionLeaf())
       return *this;
   }
 
diff --git a/third_party/WebKit/Source/core/editing/LayoutSelection.h b/third_party/WebKit/Source/core/editing/LayoutSelection.h
index f56967b..c67ca15 100644
--- a/third_party/WebKit/Source/core/editing/LayoutSelection.h
+++ b/third_party/WebKit/Source/core/editing/LayoutSelection.h
@@ -57,9 +57,8 @@
     LayoutObject* operator*() const;
 
    private:
+    const SelectionPaintRange* range_;
     LayoutObject* current_;
-    const LayoutObject* included_end_;
-    const LayoutObject* stop_;
   };
   Iterator begin() const { return Iterator(this); };
   Iterator end() const { return Iterator(nullptr); };
@@ -84,6 +83,7 @@
   int start_offset_ = -1;
   LayoutObject* end_layout_object_ = nullptr;
   int end_offset_ = -1;
+  LayoutObject* traverse_stop_ = nullptr;
 };
 
 class LayoutSelection final : public GarbageCollected<LayoutSelection> {
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp
index a64208a..eccb5f8 100644
--- a/third_party/WebKit/Source/core/editing/SelectionController.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -71,6 +71,17 @@
 
 namespace {
 
+SelectionInDOMTree ConvertToSelectionInDOMTree(
+    const SelectionInFlatTree& selection_in_flat_tree) {
+  return SelectionInDOMTree::Builder()
+      .SetAffinity(selection_in_flat_tree.Affinity())
+      .SetBaseAndExtent(ToPositionInDOMTree(selection_in_flat_tree.Base()),
+                        ToPositionInDOMTree(selection_in_flat_tree.Extent()))
+      .SetIsDirectional(selection_in_flat_tree.IsDirectional())
+      .SetIsHandleVisible(selection_in_flat_tree.IsHandleVisible())
+      .Build();
+}
+
 DispatchEventResult DispatchSelectStart(Node* node) {
   if (!node || !node->GetLayoutObject())
     return DispatchEventResult::kNotCanceled;
@@ -786,7 +797,7 @@
       Selection().IsHandleVisible() == selection_in_flat_tree.IsHandleVisible())
     return;
   Selection().SetSelection(
-      selection_in_flat_tree,
+      ConvertToSelectionInDOMTree(selection_in_flat_tree),
       FrameSelection::kCloseTyping | FrameSelection::kClearTypingStyle,
       CursorAlignOnScroll::kIfNeeded, granularity);
 }
@@ -1006,7 +1017,7 @@
 
     if (Selection().ComputeVisibleSelectionInFlatTree() !=
         CreateVisibleSelection(builder.Build())) {
-      Selection().SetSelection(builder.Build());
+      Selection().SetSelection(ConvertToSelectionInDOMTree(builder.Build()));
     }
 
     handled = true;
@@ -1164,12 +1175,13 @@
   const VisiblePositionInFlatTree& visible_pos =
       VisiblePositionOfHitTestResult(mev.GetHitTestResult());
   if (visible_pos.IsNull()) {
-    Selection().SetSelection(SelectionInFlatTree());
+    Selection().SetSelection(SelectionInDOMTree());
     return;
   }
-  Selection().SetSelection(SelectionInFlatTree::Builder()
-                               .Collapse(visible_pos.ToPositionWithAffinity())
-                               .Build());
+  Selection().SetSelection(ConvertToSelectionInDOMTree(
+      SelectionInFlatTree::Builder()
+          .Collapse(visible_pos.ToPositionWithAffinity())
+          .Build()));
 }
 
 void SelectionController::InitializeSelectionState() {
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
index a55d7d2..3d291db 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
@@ -574,6 +574,40 @@
   return nullptr;
 }
 
+// The selection ends in editable content or non-editable content inside a
+// different editable ancestor, move backward until non-editable content inside
+// the same lowest editable ancestor is reached.
+template <typename Strategy>
+PositionTemplate<Strategy> AdjustSelectionEndToAvoidCrossingEditingBoundaries(
+    const PositionTemplate<Strategy>& end,
+    ContainerNode* end_root,
+    Element* base_editable_ancestor) {
+  Element* const end_editable_ancestor =
+      LowestEditableAncestor(end.ComputeContainerNode());
+  if (end_root || end_editable_ancestor != base_editable_ancestor) {
+    PositionTemplate<Strategy> position =
+        PreviousVisuallyDistinctCandidate(end);
+    Element* shadow_ancestor = end_root ? end_root->OwnerShadowHost() : nullptr;
+    if (position.IsNull() && shadow_ancestor)
+      position = PositionTemplate<Strategy>::AfterNode(*shadow_ancestor);
+    while (position.IsNotNull() &&
+           !(LowestEditableAncestor(position.ComputeContainerNode()) ==
+                 base_editable_ancestor &&
+             !IsEditablePosition(position))) {
+      Element* root = RootEditableElementOf(position);
+      shadow_ancestor = root ? root->OwnerShadowHost() : nullptr;
+      position = IsAtomicNode(position.ComputeContainerNode())
+                     ? PositionTemplate<Strategy>::InParentBeforeNode(
+                           *position.ComputeContainerNode())
+                     : PreviousVisuallyDistinctCandidate(position);
+      if (position.IsNull() && shadow_ancestor)
+        position = PositionTemplate<Strategy>::AfterNode(*shadow_ancestor);
+    }
+    return CreateVisiblePosition(position).DeepEquivalent();
+  }
+  return end;
+}
+
 template <typename Strategy>
 void VisibleSelectionTemplate<
     Strategy>::AdjustSelectionToAvoidCrossingEditingBoundaries() {
@@ -623,42 +657,14 @@
   } else {
     // FIXME: Non-editable pieces inside editable content should be atomic, in
     // the same way that editable pieces in non-editable content are atomic.
-
-    // The selection ends in editable content or non-editable content inside a
-    // different editable ancestor, move backward until non-editable content
-    // inside the same lowest editable ancestor is reached.
-    Element* end_editable_ancestor =
-        LowestEditableAncestor(end_.ComputeContainerNode());
-    if (end_root || end_editable_ancestor != base_editable_ancestor) {
-      PositionTemplate<Strategy> p = PreviousVisuallyDistinctCandidate(end_);
-      Element* shadow_ancestor =
-          end_root ? end_root->OwnerShadowHost() : nullptr;
-      if (p.IsNull() && shadow_ancestor)
-        p = PositionTemplate<Strategy>::AfterNode(*shadow_ancestor);
-      while (p.IsNotNull() &&
-             !(LowestEditableAncestor(p.ComputeContainerNode()) ==
-                   base_editable_ancestor &&
-               !IsEditablePosition(p))) {
-        Element* root = RootEditableElementOf(p);
-        shadow_ancestor = root ? root->OwnerShadowHost() : nullptr;
-        p = IsAtomicNode(p.ComputeContainerNode())
-                ? PositionTemplate<Strategy>::InParentBeforeNode(
-                      *p.ComputeContainerNode())
-                : PreviousVisuallyDistinctCandidate(p);
-        if (p.IsNull() && shadow_ancestor)
-          p = PositionTemplate<Strategy>::AfterNode(*shadow_ancestor);
-      }
-      const VisiblePositionTemplate<Strategy> previous =
-          CreateVisiblePosition(p);
-
-      if (previous.IsNull()) {
-        // The selection crosses an Editing boundary.  This is a
-        // programmer error in the editing code.  Happy debugging!
-        NOTREACHED();
-        *this = VisibleSelectionTemplate<Strategy>();
-        return;
-      }
-      end_ = previous.DeepEquivalent();
+    end_ = AdjustSelectionEndToAvoidCrossingEditingBoundaries(
+        end_, end_root, base_editable_ancestor);
+    if (end_.IsNull()) {
+      // The selection crosses an Editing boundary.  This is a
+      // programmer error in the editing code.  Happy debugging!
+      NOTREACHED();
+      *this = VisibleSelectionTemplate<Strategy>();
+      return;
     }
 
     // The selection starts in editable content or non-editable content inside a
@@ -697,11 +703,6 @@
       start_ = next.DeepEquivalent();
     }
   }
-
-  // Correct the extent if necessary.
-  if (base_editable_ancestor !=
-      LowestEditableAncestor(extent_.ComputeContainerNode()))
-    extent_ = base_is_first_ ? end_ : start_;
 }
 
 template <typename Strategy>
diff --git a/third_party/WebKit/Source/core/exported/WebFactory.h b/third_party/WebKit/Source/core/exported/WebFactory.h
index 07e6208a..4f0cedf 100644
--- a/third_party/WebKit/Source/core/exported/WebFactory.h
+++ b/third_party/WebKit/Source/core/exported/WebFactory.h
@@ -12,6 +12,7 @@
 namespace blink {
 
 class ChromeClient;
+class LocalFrameClient;
 class WebView;
 class WebViewBase;
 class WebLocalFrameBase;
@@ -40,6 +41,8 @@
       WebFrameClient*,
       InterfaceRegistry*,
       WebFrame* opener) const = 0;
+  virtual LocalFrameClient* CreateLocalFrameClient(
+      WebLocalFrameBase*) const = 0;
 
  protected:
   // Takes ownership of |factory|.
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameClient.h b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
index 402eac4..972ac8c1 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameClient.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
@@ -85,6 +85,7 @@
 class WebApplicationCacheHost;
 class WebApplicationCacheHostClient;
 class WebCookieJar;
+class WebFrame;
 class WebMediaPlayer;
 class WebMediaPlayerClient;
 class WebMediaPlayerSource;
@@ -99,6 +100,8 @@
  public:
   ~LocalFrameClient() override {}
 
+  virtual WebFrame* GetWebFrame() const { return nullptr; }
+
   virtual bool HasWebView() const = 0;  // mainly for assertions
 
   virtual void DispatchWillSendRequest(ResourceRequest&) = 0;
diff --git a/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js b/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js
index f45965c..0869c213 100644
--- a/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js
+++ b/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js
@@ -115,7 +115,7 @@
     UI.installDragHandle(
         this._colorElement, dragStart.bind(this, positionColor.bind(this)), positionColor.bind(this), null, 'default');
 
-    this.element.classList.add('palettes-enabled');
+    this.element.classList.add('palettes-enabled', 'flex-none');
     /** @type {!Map.<string, !ColorPicker.Spectrum.Palette>} */
     this._palettes = new Map();
     this._palettePanel = this.contentElement.createChild('div', 'palette-panel');
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
index a0d3ec7..67db0c4 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
@@ -204,7 +204,12 @@
           break;
         case ConsoleModel.ConsoleMessage.MessageType.Clear:
           messageElement = createElementWithClass('span', 'console-info');
-          messageElement.textContent = Common.UIString('Console was cleared');
+          if (Common.moduleSetting('preserveConsoleLog').get())
+            messageElement.textContent = Common.UIString('console.clear() was prevented due to \'Preserve log\'');
+          else
+            messageElement.textContent = Common.UIString('Console was cleared');
+          messageElement.title =
+              Common.UIString('Clear all messages with ' + UI.shortcutRegistry.shortcutTitleForAction('console.clear'));
           break;
         case ConsoleModel.ConsoleMessage.MessageType.Assert:
           var args = [Common.UIString('Assertion failed:')];
diff --git a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
index ad35836..d79b3503 100644
--- a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
@@ -162,7 +162,7 @@
 
     if (msg.source === ConsoleModel.ConsoleMessage.MessageSource.ConsoleAPI &&
         msg.type === ConsoleModel.ConsoleMessage.MessageType.Clear)
-      this._clear();
+      this._clearIfNecessary();
 
     this._messages.push(msg);
     var runtimeModel = msg.runtimeModel();
@@ -250,10 +250,7 @@
     this.addMessage(consoleMessage);
   }
 
-  /**
-   * @param {!Common.Event} event
-   */
-  _clearIfNecessary(event) {
+  _clearIfNecessary() {
     if (!Common.moduleSetting('preserveConsoleLog').get())
       this._clear();
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js b/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js
index 9375cb0..dd6f964f 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/GlassPane.js
@@ -159,7 +159,7 @@
 
     var showArrow = this._marginBehavior === UI.GlassPane.MarginBehavior.Arrow;
     var gutterSize = showArrow ? 8 : (this._marginBehavior === UI.GlassPane.MarginBehavior.NoMargin ? 0 : 3);
-    var scrollbarSize = 14;
+    var scrollbarSize = 15;
     var arrowSize = 10;
 
     var container = UI.GlassPane._containers.get(/** @type {!Document} */ (this.element.ownerDocument));
diff --git a/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp
index cac5d29..a182100 100644
--- a/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp
+++ b/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp
@@ -164,6 +164,10 @@
   LocalFrameClient::Trace(visitor);
 }
 
+WebLocalFrameBase* LocalFrameClientImpl::GetWebFrame() const {
+  return web_frame_.Get();
+}
+
 void LocalFrameClientImpl::DidCreateNewDocument() {
   if (web_frame_->Client())
     web_frame_->Client()->DidCreateNewDocument(web_frame_);
diff --git a/third_party/WebKit/Source/web/LocalFrameClientImpl.h b/third_party/WebKit/Source/web/LocalFrameClientImpl.h
index c02c52d3..f904502 100644
--- a/third_party/WebKit/Source/web/LocalFrameClientImpl.h
+++ b/third_party/WebKit/Source/web/LocalFrameClientImpl.h
@@ -33,6 +33,7 @@
 #define LocalFrameClientImpl_h
 
 #include "core/frame/LocalFrameClient.h"
+#include "core/frame/WebLocalFrameBase.h"
 #include "platform/heap/Handle.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/wtf/RefPtr.h"
@@ -54,7 +55,7 @@
 
   DECLARE_VIRTUAL_TRACE();
 
-  WebLocalFrameBase* GetWebFrame() const { return web_frame_.Get(); }
+  WebLocalFrameBase* GetWebFrame() const override;
 
   // LocalFrameClient ----------------------------------------------
 
diff --git a/third_party/WebKit/Source/web/WebFactoryImpl.cpp b/third_party/WebKit/Source/web/WebFactoryImpl.cpp
index 45d9449..3633d2dc 100644
--- a/third_party/WebKit/Source/web/WebFactoryImpl.cpp
+++ b/third_party/WebKit/Source/web/WebFactoryImpl.cpp
@@ -4,6 +4,7 @@
 
 #include "web/WebFactoryImpl.h"
 #include "web/ChromeClientImpl.h"
+#include "web/LocalFrameClientImpl.h"
 #include "web/WebLocalFrameImpl.h"
 #include "web/WebViewImpl.h"
 
@@ -40,4 +41,9 @@
   return WebLocalFrameImpl::Create(type, client, registry, opener);
 }
 
+LocalFrameClient* WebFactoryImpl::CreateLocalFrameClient(
+    WebLocalFrameBase* local_frame_base) const {
+  return LocalFrameClientImpl::Create(local_frame_base);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/web/WebFactoryImpl.h b/third_party/WebKit/Source/web/WebFactoryImpl.h
index 9219769..259214b 100644
--- a/third_party/WebKit/Source/web/WebFactoryImpl.h
+++ b/third_party/WebKit/Source/web/WebFactoryImpl.h
@@ -29,6 +29,8 @@
                                              WebFrameClient*,
                                              InterfaceRegistry*,
                                              WebFrame* opener) const override;
+
+  LocalFrameClient* CreateLocalFrameClient(WebLocalFrameBase*) const override;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
index 355d863..9703a28 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -127,6 +127,7 @@
 #include "core/exported/WebAssociatedURLLoaderImpl.h"
 #include "core/exported/WebDataSourceImpl.h"
 #include "core/exported/WebDevToolsAgentImpl.h"
+#include "core/exported/WebFactory.h"
 #include "core/exported/WebPluginContainerImpl.h"
 #include "core/exported/WebRemoteFrameImpl.h"
 #include "core/exported/WebViewBase.h"
@@ -1597,7 +1598,8 @@
     WebFrameClient* client,
     blink::InterfaceRegistry* interface_registry)
     : WebLocalFrameBase(scope),
-      local_frame_client_impl_(LocalFrameClientImpl::Create(this)),
+      local_frame_client_(
+          WebFactory::GetInstance().CreateLocalFrameClient(this)),
       client_(client),
       autofill_client_(0),
       input_events_scale_factor_for_emulation_(1),
@@ -1629,7 +1631,7 @@
 }
 
 DEFINE_TRACE(WebLocalFrameImpl) {
-  visitor->Trace(local_frame_client_impl_);
+  visitor->Trace(local_frame_client_);
   visitor->Trace(frame_);
   visitor->Trace(dev_tools_agent_);
   visitor->Trace(frame_widget_);
@@ -1650,7 +1652,7 @@
 void WebLocalFrameImpl::InitializeCoreFrame(Page& page,
                                             FrameOwner* owner,
                                             const AtomicString& name) {
-  SetCoreFrame(LocalFrame::Create(local_frame_client_impl_.Get(), page, owner,
+  SetCoreFrame(LocalFrame::Create(local_frame_client_.Get(), page, owner,
                                   interface_registry_));
   frame_->Tree().SetName(name);
   // We must call init() after frame_ is assigned because it is referenced
@@ -1756,7 +1758,7 @@
   LocalFrameClient* client = frame.Client();
   if (!client || !client->IsLocalFrameClientImpl())
     return nullptr;
-  return ToWebLocalFrameImpl(ToLocalFrameClientImpl(client)->GetWebFrame());
+  return ToWebLocalFrameImpl(client->GetWebFrame());
 }
 
 WebLocalFrameImpl* WebLocalFrameImpl::FromFrameOwnerElement(Element* element) {
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.h b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
index 4695423..ccc34a8 100644
--- a/third_party/WebKit/Source/web/WebLocalFrameImpl.h
+++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.h
@@ -37,14 +37,12 @@
 #include "core/frame/LocalFrame.h"
 #include "core/frame/WebFrameWidgetBase.h"
 #include "core/frame/WebLocalFrameBase.h"
-#include "modules/mediastream/UserMediaClientImpl.h"
 #include "platform/geometry/FloatRect.h"
 #include "platform/heap/SelfKeepAlive.h"
 #include "platform/wtf/Compiler.h"
 #include "platform/wtf/text/WTFString.h"
 #include "public/platform/WebFileSystemType.h"
 #include "public/web/WebLocalFrame.h"
-#include "web/LocalFrameClientImpl.h"
 #include "web/WebExport.h"
 
 #include <memory>
@@ -54,6 +52,7 @@
 class ChromePrintContext;
 class IntSize;
 class KURL;
+class LocalFrameClient;
 class ScrollableArea;
 class SharedWorkerRepositoryClientImpl;
 class TextCheckerClient;
@@ -450,7 +449,6 @@
   DECLARE_VIRTUAL_TRACE();
 
  private:
-  friend class LocalFrameClientImpl;
 
   WebLocalFrameImpl(WebTreeScopeType,
                     WebFrameClient*,
@@ -479,7 +477,7 @@
   // Returns true if the frame is focused.
   bool IsFocused() const;
 
-  Member<LocalFrameClientImpl> local_frame_client_impl_;
+  Member<LocalFrameClient> local_frame_client_;
 
   // The embedder retains a reference to the WebCore LocalFrame while it is
   // active in the DOM. This reference is released when the frame is removed
diff --git a/tools/gn/bootstrap/bootstrap.py b/tools/gn/bootstrap/bootstrap.py
index 8beca90..231ff03 100755
--- a/tools/gn/bootstrap/bootstrap.py
+++ b/tools/gn/bootstrap/bootstrap.py
@@ -467,7 +467,6 @@
       'base/process/process_metrics.cc',
       'base/profiler/scoped_profile.cc',
       'base/profiler/scoped_tracker.cc',
-      'base/profiler/tracked_time.cc',
       'base/rand_util.cc',
       'base/run_loop.cc',
       'base/sequence_token.cc',
@@ -567,6 +566,7 @@
       'base/tracked_objects.cc',
       'base/tracking_info.cc',
       'base/unguessable_token.cc',
+      'base/value_iterators.cc',
       'base/values.cc',
       'base/vlog.cc',
   ])
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 20cfee2..4eed89e2 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -15536,6 +15536,74 @@
   </description>
 </action>
 
+<action name="Signin_ImpressionWithAccount_FromBookmarkManager">
+  <owner>jlebel@chromium.org</owner>
+  <description>
+    Recorded when starting sign-in using the promo view, with a default account,
+    from bookmarks manager
+    (signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER).
+  </description>
+</action>
+
+<action name="Signin_ImpressionWithAccount_FromRecentTabs">
+  <owner>jlebel@chromium.org</owner>
+  <description>
+    Recorded when starting sign-in using the promo view, with a default account,
+    from recent tabs (signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS).
+  </description>
+</action>
+
+<action name="Signin_ImpressionWithAccount_FromSettings">
+  <owner>jlebel@chromium.org</owner>
+  <description>
+    Recorded when starting sign-in using the promo view, with a default account,
+    from settings (signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS).
+  </description>
+</action>
+
+<action name="Signin_ImpressionWithAccount_FromTabSwitcher">
+  <owner>jlebel@chromium.org</owner>
+  <description>
+    Recorded when starting sign-in using the promo view, with a default account,
+    from tab switcher (signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER).
+  </description>
+</action>
+
+<action name="Signin_ImpressionWithNoAccount_FromBookmarkManager">
+  <owner>jlebel@chromium.org</owner>
+  <description>
+    Recorded when starting sign-in using the promo view, with no default
+    account, from bookmarks manager
+    (signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER).
+  </description>
+</action>
+
+<action name="Signin_ImpressionWithNoAccount_FromRecentTabs">
+  <owner>jlebel@chromium.org</owner>
+  <description>
+    Recorded when starting sign-in using the promo view, with no default
+    account, from recent tabs
+    (signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS).
+  </description>
+</action>
+
+<action name="Signin_ImpressionWithNoAccount_FromSettings">
+  <owner>jlebel@chromium.org</owner>
+  <description>
+    Recorded when starting sign-in using the promo view, with no default
+    account, from settings (signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS).
+  </description>
+</action>
+
+<action name="Signin_ImpressionWithNoAccount_FromTabSwitcher">
+  <owner>jlebel@chromium.org</owner>
+  <description>
+    Recorded when starting sign-in using the promo view, with no default
+    account, from tab switcher
+    (signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER).
+  </description>
+</action>
+
 <action name="Signin_Impression_FromAppsPageLink">
   <owner>gogerald@chromium.org</owner>
   <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 7e86cf5..d80500cc 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -9256,6 +9256,21 @@
   <int value="9" label="SCRIPT_READ_FINISHED"/>
 </enum>
 
+<enum name="EmmcLifeUsed">
+  <int value="0" label="Not defined"/>
+  <int value="1" label="0% - 10% device life time used"/>
+  <int value="2" label="10% -20% device life time used"/>
+  <int value="3" label="20% -30% device life time used"/>
+  <int value="4" label="30% - 40% device life time used"/>
+  <int value="5" label="40% - 50% device life time used"/>
+  <int value="6" label="50% - 60% device life time used"/>
+  <int value="7" label="60% - 70% device life time used"/>
+  <int value="8" label="70% - 80% device life time used"/>
+  <int value="9" label="80% - 90% device life time used"/>
+  <int value="10" label="90% - 100% device life time used"/>
+  <int value="11" label="Exceeded its maximum estimated device life time"/>
+</enum>
+
 <enum name="EncodingMethod">
   <int value="0" label="UNKNOWN"/>
   <int value="1" label="Big5"/>
@@ -22645,6 +22660,7 @@
   <int value="-1812579951" label="ContentSuggestionsCategoryRanker:enabled"/>
   <int value="-1811394154" label="disable-webrtc-hw-vp8-encoding"/>
   <int value="-1810294310" label="AndroidPaymentApps:enabled"/>
+  <int value="-1808477331" label="MidiManagerCros:disabled"/>
   <int value="-1804485171" label="disable-fullscreen-tab-detaching"/>
   <int value="-1802502753" label="enable-manual-password-generation:enabled"/>
   <int value="-1798337879" label="enable-md-downloads"/>
@@ -23107,6 +23123,7 @@
   <int value="-216219963" label="ash-shelf-color-scheme"/>
   <int value="-213518852" label="protect-sync-credential:enabled"/>
   <int value="-213214894" label="enable-chromevox-arc-support"/>
+  <int value="-208435024" label="EnableUsernameCorrection:enabled"/>
   <int value="-206393363" label="enable-scroll-prediction"/>
   <int value="-204355195" label="secondary-ui-md"/>
   <int value="-202007318" label="AndroidAIAFetching:enabled"/>
@@ -23345,6 +23362,7 @@
   <int value="644674603" label="DataReductionProxySiteBreakdown:disabled"/>
   <int value="646252875" label="ReadItLaterInMenu:enabled"/>
   <int value="646738320" label="disable-gesture-editing"/>
+  <int value="649111851" label="MidiManagerCros:enabled"/>
   <int value="651421878" label="VideoRotateToFullscreen:enabled"/>
   <int value="652561231" label="CustomContextMenu:enabled"/>
   <int value="683410401"
@@ -23762,6 +23780,7 @@
   <int value="2014331873" label="NTPDownloadSuggestions:disabled"/>
   <int value="2020107447" label="AndroidPayIntegrationV1:enabled"/>
   <int value="2037756154" label="enable-impl-side-painting"/>
+  <int value="2056572020" label="EnableUsernameCorrection:disabled"/>
   <int value="2059322877" label="new-avatar-menu"/>
   <int value="2063091429" label="OfflinePagesSharing:enabled"/>
   <int value="2067634730" label="LsdPermissionPrompt:disabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 0e249e8..3a75eab 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -54666,6 +54666,16 @@
   </summary>
 </histogram>
 
+<histogram name="Platform.Emmc.LifeUsed" enum="EmmcLifeUsed">
+  <owner>gwendal@google.com</owner>
+  <summary>
+    eMMC [5.0] Device life time estimation for flash. This field provides an
+    estimated indication about the device life time that is reflected by the
+    averaged wear out of memory of a given type relative to its maximum
+    estimated lifetime.
+  </summary>
+</histogram>
+
 <histogram name="Platform.IntelMaxMicroArchitecture"
     enum="IntelMaxMicroArchitecture">
   <owner>fbarchard@chromium.org</owner>
@@ -96295,6 +96305,12 @@
   <affected-histogram name="Platform.BootMode.FirmwareWriteProtect"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="PlatformEmmcLifeUsed" separator=".">
+  <suffix name="TypeA" label="Memory Type A"/>
+  <suffix name="TypeB" label="Memory Type B"/>
+  <affected-histogram name="Platform.Emmc.LifeUsed"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="PlatformMeminfoPercentage" separator="">
   <suffix name="infoActive" label="Active memory."/>
   <suffix name="infoActiveAnon"
diff --git a/ui/aura/mus/input_method_mus_unittest.cc b/ui/aura/mus/input_method_mus_unittest.cc
index 51ed8279..e430f57 100644
--- a/ui/aura/mus/input_method_mus_unittest.cc
+++ b/ui/aura/mus/input_method_mus_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "ui/aura/mus/input_method_mus.h"
 
+#include <utility>
+
 #include "services/ui/public/interfaces/ime/ime.mojom.h"
 #include "ui/aura/test/aura_test_base.h"
 #include "ui/aura/test/mus/input_method_mus_test_api.h"
@@ -29,7 +31,7 @@
   DISALLOW_COPY_AND_ASSIGN(TestInputMethodDelegate);
 };
 
-using ProcessKeyEventCallback = base::Callback<void(bool)>;
+using ProcessKeyEventCallback = base::OnceCallback<void(bool)>;
 using ProcessKeyEventCallbacks = std::vector<ProcessKeyEventCallback>;
 using EventResultCallback = base::Callback<void(ui::mojom::EventResult)>;
 
@@ -48,8 +50,8 @@
   void OnTextInputTypeChanged(ui::TextInputType text_input_type) override {}
   void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override {}
   void ProcessKeyEvent(std::unique_ptr<ui::Event> key_event,
-                       const ProcessKeyEventCallback& callback) override {
-    process_key_event_callbacks_.push_back(callback);
+                       ProcessKeyEventCallback callback) override {
+    process_key_event_callbacks_.push_back(std::move(callback));
   }
   void CancelComposition() override {}
 
@@ -197,7 +199,7 @@
   ASSERT_EQ(1u, test_input_method.process_key_event_callbacks()->size());
   // Callback should not have been run yet.
   EXPECT_FALSE(was_event_result_callback_run);
-  (*test_input_method.process_key_event_callbacks())[0].Run(false);
+  std::move((*test_input_method.process_key_event_callbacks())[0]).Run(false);
 
   // Callback should have been run.
   EXPECT_TRUE(was_event_result_callback_run);
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/input_method_chromeos.cc
index de201a3..1312ba4 100644
--- a/ui/base/ime/input_method_chromeos.cc
+++ b/ui/base/ime/input_method_chromeos.cc
@@ -9,6 +9,7 @@
 #include <algorithm>
 #include <cstring>
 #include <set>
+#include <utility>
 #include <vector>
 
 #include "base/bind.h"
diff --git a/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js b/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js
index b035356..28e65d0 100644
--- a/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js
@@ -41,6 +41,8 @@
    */
   this.commandHandler_ = commandHandler;
 
+  gearMenu.volumeSpaceInfo.addEventListener(
+      'mouseover', this.onMouseOverVolumeSpaceInfo_.bind(this));
   gearButton.addEventListener('menushow', this.onShowGearMenu_.bind(this));
   gearButton.addEventListener('menuhide', this.onHideGearMenu_.bind(this));
   directoryModel.addEventListener(
@@ -51,6 +53,15 @@
 }
 
 /**
+ * Handles mouseover event and prevents any further action to execute.
+ * @param {Event} event The mouseover event.
+ * @private
+ */
+GearMenuController.prototype.onMouseOverVolumeSpaceInfo_ = function(event) {
+  event.stopPropagation();
+};
+
+/**
  * @private
  */
 GearMenuController.prototype.onShowGearMenu_ = function() {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js b/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
index 8807c5c..28bfe1bb 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
@@ -25,9 +25,8 @@
   /**
    * @type {!HTMLElement}
    * @const
-   * @private
    */
-  this.volumeSpaceInfo_ = queryRequiredElement('#volume-space-info', element);
+  this.volumeSpaceInfo = queryRequiredElement('#volume-space-info', element);
 
   /**
    * @type {!HTMLElement}
@@ -84,12 +83,12 @@
   this.spaceInfoPromise_ = spaceInfoPromise;
 
   if (!spaceInfoPromise) {
-    this.volumeSpaceInfo_.hidden = true;
+    this.volumeSpaceInfo.hidden = true;
     this.volumeSpaceInfoSeparator_.hidden = true;
     return;
   }
 
-  this.volumeSpaceInfo_.hidden = false;
+  this.volumeSpaceInfo.hidden = false;
   this.volumeSpaceInfoSeparator_.hidden = false;
   this.volumeSpaceInnerBar_.setAttribute('pending', '');
   if (showLoadingCaption) {