diff --git a/DEPS b/DEPS
index 10864f6..a338b19 100644
--- a/DEPS
+++ b/DEPS
@@ -162,7 +162,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'c091a1b5c085ad3fccc1507caaf2be7ff124d62a',
+  'skia_revision': 'c13cb6e62441c499c2dca6b899c67f2c3e9208fe',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -174,7 +174,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '0b8eca7953499f9eb6459761aff1114f03bfa0e4',
+  'angle_revision': '9dbfeac8b553427eabe2c4b5bce322efecc0b440',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -182,7 +182,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '881c56bc068704d45398bd7dedd7dcab6461e999',
+  'pdfium_revision': '9fafe62237ad4cf5c502f9f81a5ce302fc69db3c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -225,7 +225,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '050abd8dd5c49167d4d33864f3c078d270d271af',
+  'catapult_revision': 'c5f9c068212598f72a2f07356be1d7452ce9861b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -281,7 +281,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '7f7236f1eba0afae2669ea777896f0435be4c96d',
+  'spv_tools_revision': 'c0e9807094ef6e345ef0a4d5f17af81af063cd27',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1414,7 +1414,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'abaae129d9a0c6e1e092067e0b105475df43352e',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '55f663f5ddff7be2943a528fc6896c220de45599',
+    Var('webrtc_git') + '/src.git' + '@' + '9a91161b9f65df0cbe64009827ca6b8d1c172675',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1455,7 +1455,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ea8664557d2e1199be7251933953f46f5a8cd39d',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@61336619eaf0d77cea9906b16f26377eb6441c4f',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 917e366..8c17807 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -220,7 +220,7 @@
 
 void PassMojoCookieManagerToAwCookieManager(
     CookieManager* cookie_manager,
-    const network::mojom::NetworkContextPtr& network_context) {
+    const mojo::Remote<network::mojom::NetworkContext>& network_context) {
   // Get the CookieManager from the NetworkContext.
   mojo::PendingRemote<network::mojom::CookieManager> cookie_manager_remote;
   network_context->GetCookieManager(
@@ -342,7 +342,8 @@
   content::GetNetworkService()->SetUpHttpAuth(std::move(auth_static_params));
 }
 
-network::mojom::NetworkContextPtr AwContentBrowserClient::CreateNetworkContext(
+mojo::Remote<network::mojom::NetworkContext>
+AwContentBrowserClient::CreateNetworkContext(
     content::BrowserContext* context,
     bool in_memory,
     const base::FilePath& relative_partition_path) {
@@ -352,14 +353,14 @@
       AwBrowserProcess::GetInstance()->CreateHttpAuthDynamicParams());
 
   auto* aw_context = static_cast<AwBrowserContext*>(context);
-  network::mojom::NetworkContextPtr network_context;
+  mojo::Remote<network::mojom::NetworkContext> network_context;
   network::mojom::NetworkContextParamsPtr context_params =
       aw_context->GetNetworkContextParams(in_memory, relative_partition_path);
 #if DCHECK_IS_ON()
   g_created_network_context_params = true;
 #endif
   content::GetNetworkService()->CreateNetworkContext(
-      MakeRequest(&network_context), std::move(context_params));
+      network_context.BindNewPipeAndPassReceiver(), std::move(context_params));
 
   // Pass a CookieManager to the code supporting AwCookieManager.java (i.e., the
   // Cookies APIs).
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index f67f2d1..32acca9 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "content/public/browser/content_browser_client.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 
 namespace content {
@@ -54,7 +55,7 @@
 
   void OnNetworkServiceCreated(
       network::mojom::NetworkService* network_service) override;
-  network::mojom::NetworkContextPtr CreateNetworkContext(
+  mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext(
       content::BrowserContext* context,
       bool in_memory,
       const base::FilePath& relative_partition_path) override;
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc
index 4e4981a..3572029 100644
--- a/ash/login/login_screen_controller.cc
+++ b/ash/login/login_screen_controller.cc
@@ -25,7 +25,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/debug/alias.h"
-#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/session_manager/session_manager_types.h"
@@ -124,9 +124,10 @@
 
   authentication_stage_ = AuthenticationStage::kDoAuthenticate;
 
-  int dummy_value;
-  bool is_pin =
-      authenticated_by_pin && base::StringToInt(password, &dummy_value);
+  // Checking if the password is only formed of numbers with base::StringToInt
+  // will easily fail due to numeric limits. ContainsOnlyChars is used instead.
+  const bool is_pin =
+      authenticated_by_pin && base::ContainsOnlyChars(password, "0123456789");
   client_->AuthenticateUserWithPasswordOrPin(
       account_id, password, is_pin,
       base::BindOnce(&LoginScreenController::OnAuthenticateComplete,
diff --git a/ash/login/login_screen_controller_unittest.cc b/ash/login/login_screen_controller_unittest.cc
index 3d1f2e5..e60beff 100644
--- a/ash/login/login_screen_controller_unittest.cc
+++ b/ash/login/login_screen_controller_unittest.cc
@@ -70,7 +70,8 @@
       Shell::Get()->session_controller()->GetLastActiveUserPrefService();
   EXPECT_TRUE(prefs->FindPreference(prefs::kQuickUnlockPinSalt));
 
-  std::string pin = "123456";
+  // Use a long PIN (N > 2^64) for the test to ensure that there is no overflow.
+  std::string pin = "12345678901234567890";
   EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin_(id, pin, true, _));
   base::RunLoop run_loop2;
   controller->AuthenticateUserWithPasswordOrPin(
diff --git a/base/strings/string_util.h b/base/strings/string_util.h
index 24f77bf..bddb038 100644
--- a/base/strings/string_util.h
+++ b/base/strings/string_util.h
@@ -269,6 +269,24 @@
 inline const char16* as_u16cstr(WStringPiece str) {
   return reinterpret_cast<const char16*>(str.data());
 }
+
+// Utility functions to convert between base::WStringPiece and
+// base::StringPiece16.
+inline WStringPiece AsWStringPiece(StringPiece16 str) {
+  return WStringPiece(as_wcstr(str.data()), str.size());
+}
+
+inline StringPiece16 AsStringPiece16(WStringPiece str) {
+  return StringPiece16(as_u16cstr(str.data()), str.size());
+}
+
+inline std::wstring AsWString(StringPiece16 str) {
+  return std::wstring(as_wcstr(str.data()), str.size());
+}
+
+inline string16 AsString16(WStringPiece str) {
+  return string16(as_u16cstr(str.data()), str.size());
+}
 #endif  // defined(WCHAR_T_IS_UTF16)
 
 // Trims any whitespace from either end of the input string.
diff --git a/base/strings/string_util_win.h b/base/strings/string_util_win.h
index 7f260bf..791f60e 100644
--- a/base/strings/string_util_win.h
+++ b/base/strings/string_util_win.h
@@ -39,6 +39,19 @@
   return length;
 }
 
+// Windows only overload of base::WriteInto for std::wstring. See the comment
+// above the cross-platform version in //base/strings/string_util.h for details.
+// TODO(crbug.com/911896): Rename this to WriteInto once base::string16 is
+// std::u16string on all platforms and using the name WriteInto here no longer
+// causes redefinition errors.
+inline wchar_t* WriteIntoW(std::wstring* str, size_t length_with_null) {
+  // Note: As of C++11 std::strings are guaranteed to be 0-terminated. Thus it
+  // is enough to reserve space for one char less.
+  DCHECK_GE(length_with_null, 1u);
+  str->resize(length_with_null - 1);
+  return &((*str)[0]);
+}
+
 }  // namespace base
 
 #endif  // BASE_STRINGS_STRING_UTIL_WIN_H_
diff --git a/base/syslog_logging.cc b/base/syslog_logging.cc
index 68483ef..6b7280d 100644
--- a/base/syslog_logging.cc
+++ b/base/syslog_logging.cc
@@ -34,7 +34,7 @@
 std::string* g_event_source_name = nullptr;
 uint16_t g_category = 0;
 uint32_t g_event_id = 0;
-base::string16* g_user_sid = nullptr;
+std::wstring* g_user_sid = nullptr;
 
 }  // namespace
 
@@ -46,7 +46,7 @@
   g_category = category;
   g_event_id = event_id;
   DCHECK_EQ(nullptr, g_user_sid);
-  g_user_sid = new base::string16();
+  g_user_sid = new std::wstring();
   base::win::GetUserSidString(g_user_sid);
 }
 
@@ -102,7 +102,7 @@
   }
   LPCSTR strings[1] = {message.data()};
   PSID user_sid = nullptr;
-  if (!::ConvertStringSidToSid(base::as_wcstr(*g_user_sid), &user_sid)) {
+  if (!::ConvertStringSidToSid(g_user_sid->c_str(), &user_sid)) {
     stream() << " !!ERROR GETTING USER SID!!";
   }
 
diff --git a/base/system/sys_info_win.cc b/base/system/sys_info_win.cc
index 87650d8..a600296 100644
--- a/base/system/sys_info_win.cc
+++ b/base/system/sys_info_win.cc
@@ -171,9 +171,9 @@
   win::WmiComputerSystemInfo wmi_info = win::WmiComputerSystemInfo::Get();
 
   HardwareInfo info;
-  info.manufacturer = UTF16ToUTF8(wmi_info.manufacturer());
-  info.model = UTF16ToUTF8(wmi_info.model());
-  info.serial_number = UTF16ToUTF8(wmi_info.serial_number());
+  info.manufacturer = WideToUTF8(wmi_info.manufacturer());
+  info.model = WideToUTF8(wmi_info.model());
+  info.serial_number = WideToUTF8(wmi_info.serial_number());
   DCHECK(IsStringUTF8(info.manufacturer));
   DCHECK(IsStringUTF8(info.model));
   DCHECK(IsStringUTF8(info.serial_number));
diff --git a/base/test/test_reg_util_win.cc b/base/test/test_reg_util_win.cc
index ad368ca..3635bc9 100644
--- a/base/test/test_reg_util_win.cc
+++ b/base/test/test_reg_util_win.cc
@@ -9,6 +9,7 @@
 #include "base/guid.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -21,12 +22,11 @@
 
 namespace {
 
-const base::char16 kTimestampDelimiter[] = STRING16_LITERAL("$");
-const base::char16 kTempTestKeyPath[] =
-    STRING16_LITERAL("Software\\Chromium\\TempTestKeys");
+constexpr base::char16 kTimestampDelimiter[] = STRING16_LITERAL("$");
+constexpr wchar_t kTempTestKeyPath[] = L"Software\\Chromium\\TempTestKeys";
 
 void DeleteStaleTestKeys(const base::Time& now,
-                         const base::string16& test_key_root) {
+                         const std::wstring& test_key_root) {
   base::win::RegKey test_root_key;
   if (test_root_key.Open(HKEY_CURRENT_USER,
                          test_key_root.c_str(),
@@ -38,10 +38,10 @@
   base::win::RegistryKeyIterator iterator_test_root_key(HKEY_CURRENT_USER,
                                                         test_key_root.c_str());
   for (; iterator_test_root_key.Valid(); ++iterator_test_root_key) {
-    base::string16 key_name = iterator_test_root_key.Name();
-    std::vector<base::string16> tokens = base::SplitString(
-        key_name, kTimestampDelimiter, base::KEEP_WHITESPACE,
-        base::SPLIT_WANT_NONEMPTY);
+    std::wstring key_name = iterator_test_root_key.Name();
+    std::vector<base::StringPiece16> tokens = base::SplitStringPiece(
+        base::AsStringPiece16(key_name), kTimestampDelimiter,
+        base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
     if (tokens.empty())
       continue;
     int64_t key_name_as_number = 0;
@@ -59,27 +59,25 @@
   }
 }
 
-base::string16 GenerateTempKeyPath(const base::string16& test_key_root,
-                                   const base::Time& timestamp) {
-  base::string16 key_path = test_key_root;
-  key_path += STRING16_LITERAL("\\") +
-              base::NumberToString16(timestamp.ToInternalValue());
-  key_path += kTimestampDelimiter + base::ASCIIToUTF16(base::GenerateGUID());
-
-  return key_path;
+std::wstring GenerateTempKeyPath(const std::wstring& test_key_root,
+                                 const base::Time& timestamp) {
+  return base::AsWString(base::StrCat(
+      {base::AsStringPiece16(test_key_root), STRING16_LITERAL("\\"),
+       base::NumberToString16(timestamp.ToInternalValue()), kTimestampDelimiter,
+       base::ASCIIToUTF16(base::GenerateGUID())}));
 }
 
 }  // namespace
 
 RegistryOverrideManager::ScopedRegistryKeyOverride::ScopedRegistryKeyOverride(
     HKEY override,
-    const base::string16& key_path)
+    const std::wstring& key_path)
     : override_(override), key_path_(key_path) {}
 
 RegistryOverrideManager::
     ScopedRegistryKeyOverride::~ScopedRegistryKeyOverride() {
   ::RegOverridePredefKey(override_, NULL);
-  base::win::RegKey(HKEY_CURRENT_USER, STRING16_LITERAL(""), KEY_QUERY_VALUE)
+  base::win::RegKey(HKEY_CURRENT_USER, L"", KEY_QUERY_VALUE)
       .DeleteKey(key_path_.c_str());
 }
 
@@ -90,7 +88,7 @@
 
 RegistryOverrideManager::RegistryOverrideManager(
     const base::Time& timestamp,
-    const base::string16& test_key_root)
+    const std::wstring& test_key_root)
     : timestamp_(timestamp), test_key_root_(test_key_root) {
   DeleteStaleTestKeys(timestamp_, test_key_root_);
 }
@@ -102,8 +100,8 @@
 }
 
 void RegistryOverrideManager::OverrideRegistry(HKEY override,
-                                               base::string16* override_path) {
-  base::string16 key_path = GenerateTempKeyPath(test_key_root_, timestamp_);
+                                               std::wstring* override_path) {
+  std::wstring key_path = GenerateTempKeyPath(test_key_root_, timestamp_);
 
   base::win::RegKey temp_key;
   ASSERT_EQ(ERROR_SUCCESS, temp_key.Create(HKEY_CURRENT_USER, key_path.c_str(),
@@ -116,9 +114,8 @@
     override_path->assign(key_path);
 }
 
-base::string16 GenerateTempKeyPath() {
-  return GenerateTempKeyPath(base::string16(kTempTestKeyPath),
-                             base::Time::Now());
+std::wstring GenerateTempKeyPath() {
+  return GenerateTempKeyPath(kTempTestKeyPath, base::Time::Now());
 }
 
 }  // namespace registry_util
diff --git a/base/test/test_reg_util_win.h b/base/test/test_reg_util_win.h
index d74028a..0592ff7 100644
--- a/base/test/test_reg_util_win.h
+++ b/base/test/test_reg_util_win.h
@@ -7,10 +7,10 @@
 
 // Registry utility functions used only by tests.
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "base/macros.h"
-#include "base/strings/string16.h"
 #include "base/time/time.h"
 #include "base/win/registry.h"
 
@@ -42,7 +42,7 @@
   // Calls to these functions must be wrapped in ASSERT_NO_FATAL_FAILURE to
   // ensure that tests do not proceeed in case of failure to override.
   void OverrideRegistry(HKEY override);
-  void OverrideRegistry(HKEY override, base::string16* override_path);
+  void OverrideRegistry(HKEY override, std::wstring* override_path);
 
  private:
   friend class RegistryOverrideManagerTest;
@@ -50,24 +50,24 @@
   // Keeps track of one override.
   class ScopedRegistryKeyOverride {
    public:
-    ScopedRegistryKeyOverride(HKEY override, const base::string16& key_path);
+    ScopedRegistryKeyOverride(HKEY override, const std::wstring& key_path);
     ~ScopedRegistryKeyOverride();
 
    private:
     HKEY override_;
-    base::string16 key_path_;
+    std::wstring key_path_;
 
     DISALLOW_COPY_AND_ASSIGN(ScopedRegistryKeyOverride);
   };
 
   // Used for testing only.
   RegistryOverrideManager(const base::Time& timestamp,
-                          const base::string16& test_key_root);
+                          const std::wstring& test_key_root);
 
   base::Time timestamp_;
-  base::string16 guid_;
+  std::wstring guid_;
 
-  base::string16 test_key_root_;
+  std::wstring test_key_root_;
   std::vector<std::unique_ptr<ScopedRegistryKeyOverride>> overrides_;
 
   DISALLOW_COPY_AND_ASSIGN(RegistryOverrideManager);
@@ -75,7 +75,7 @@
 
 // Generates a temporary key path that will be eventually deleted
 // automatically if the process crashes.
-base::string16 GenerateTempKeyPath();
+std::wstring GenerateTempKeyPath();
 
 }  // namespace registry_util
 
diff --git a/base/test/test_reg_util_win_unittest.cc b/base/test/test_reg_util_win_unittest.cc
index b1a7e17f..12c1d6b 100644
--- a/base/test/test_reg_util_win_unittest.cc
+++ b/base/test/test_reg_util_win_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -15,9 +16,8 @@
 namespace registry_util {
 
 namespace {
-const base::char16 kTestKeyPath[] =
-    STRING16_LITERAL("Software\\Chromium\\Foo\\Baz\\TestKey");
-const base::char16 kTestValueName[] = STRING16_LITERAL("TestValue");
+const wchar_t kTestKeyPath[] = L"Software\\Chromium\\Foo\\Baz\\TestKey";
+const wchar_t kTestValueName[] = L"TestValue";
 }  // namespace
 
 class RegistryOverrideManagerTest : public testing::Test {
@@ -40,29 +40,29 @@
     key.DeleteKey(fake_test_key_root_.c_str());
   }
 
-  void AssertKeyExists(const base::string16& key_path) {
+  void AssertKeyExists(const std::wstring& key_path) {
     base::win::RegKey key;
     ASSERT_EQ(ERROR_SUCCESS,
               key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ))
         << key_path << " does not exist.";
   }
 
-  void AssertKeyAbsent(const base::string16& key_path) {
+  void AssertKeyAbsent(const std::wstring& key_path) {
     base::win::RegKey key;
     ASSERT_NE(ERROR_SUCCESS,
               key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ))
         << key_path << " exists but it should not.";
   }
 
-  void CreateKey(const base::string16& key_path) {
+  void CreateKey(const std::wstring& key_path) {
     base::win::RegKey key;
     ASSERT_EQ(ERROR_SUCCESS,
               key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_ALL_ACCESS));
   }
 
-  base::string16 FakeOverrideManagerPath(const base::Time& time) {
-    return fake_test_key_root_ + STRING16_LITERAL("\\") +
-           base::NumberToString16(time.ToInternalValue());
+  std::wstring FakeOverrideManagerPath(const base::Time& time) {
+    return fake_test_key_root_ + L"\\" +
+           base::AsWString(base::NumberToString16(time.ToInternalValue()));
   }
 
   void CreateManager(const base::Time& timestamp) {
@@ -70,7 +70,7 @@
     manager_->OverrideRegistry(HKEY_CURRENT_USER);
   }
 
-  base::string16 fake_test_key_root_;
+  std::wstring fake_test_key_root_;
   std::unique_ptr<RegistryOverrideManager> manager_;
 };
 
@@ -105,15 +105,14 @@
   base::Time kTestTime;
   EXPECT_TRUE(base::Time::FromUTCExploded(kTestTimeExploded, &kTestTime));
 
-  base::string16 path_garbage =
-      fake_test_key_root_ + STRING16_LITERAL("\\Blah");
-  base::string16 path_very_stale =
+  std::wstring path_garbage = fake_test_key_root_ + L"\\Blah";
+  std::wstring path_very_stale =
       FakeOverrideManagerPath(kTestTime - base::TimeDelta::FromDays(100));
-  base::string16 path_stale =
+  std::wstring path_stale =
       FakeOverrideManagerPath(kTestTime - base::TimeDelta::FromDays(5));
-  base::string16 path_current =
+  std::wstring path_current =
       FakeOverrideManagerPath(kTestTime - base::TimeDelta::FromMinutes(1));
-  base::string16 path_future =
+  std::wstring path_future =
       FakeOverrideManagerPath(kTestTime + base::TimeDelta::FromMinutes(1));
 
   ASSERT_NO_FATAL_FAILURE(CreateKey(path_garbage));
diff --git a/base/test/test_shortcut_win.cc b/base/test/test_shortcut_win.cc
index 71766d5..9b5cb18 100644
--- a/base/test/test_shortcut_win.cc
+++ b/base/test/test_shortcut_win.cc
@@ -22,8 +22,8 @@
 
 void ValidatePathsAreEqual(const FilePath& expected_path,
                            const FilePath& actual_path) {
-  char16 long_expected_path_chars[MAX_PATH] = {0};
-  char16 long_actual_path_chars[MAX_PATH] = {0};
+  wchar_t long_expected_path_chars[MAX_PATH] = {0};
+  wchar_t long_actual_path_chars[MAX_PATH] = {0};
 
   // If |expected_path| is empty confirm immediately that |actual_path| is also
   // empty.
@@ -34,16 +34,14 @@
 
   // Proceed with LongPathName matching which will also confirm the paths exist.
   EXPECT_NE(0U, ::GetLongPathName(as_wcstr(expected_path.value()),
-                                  as_writable_wcstr(long_expected_path_chars),
-                                  MAX_PATH))
+                                  long_expected_path_chars, MAX_PATH))
       << "Failed to get LongPathName of " << expected_path.value();
   EXPECT_NE(0U, ::GetLongPathName(as_wcstr(actual_path.value()),
-                                  as_writable_wcstr(long_actual_path_chars),
-                                  MAX_PATH))
+                                  long_actual_path_chars, MAX_PATH))
       << "Failed to get LongPathName of " << actual_path.value();
 
-  FilePath long_expected_path(long_expected_path_chars);
-  FilePath long_actual_path(long_actual_path_chars);
+  FilePath long_expected_path(AsStringPiece16(long_expected_path_chars));
+  FilePath long_actual_path(AsStringPiece16(long_actual_path_chars));
   EXPECT_FALSE(long_expected_path.empty());
   EXPECT_FALSE(long_actual_path.empty());
 
@@ -55,11 +53,11 @@
   Microsoft::WRL::ComPtr<IShellLink> i_shell_link;
   Microsoft::WRL::ComPtr<IPersistFile> i_persist_file;
 
-  char16 read_target[MAX_PATH] = {0};
-  char16 read_working_dir[MAX_PATH] = {0};
-  char16 read_arguments[MAX_PATH] = {0};
-  char16 read_description[MAX_PATH] = {0};
-  char16 read_icon[MAX_PATH] = {0};
+  wchar_t read_target[MAX_PATH] = {0};
+  wchar_t read_working_dir[MAX_PATH] = {0};
+  wchar_t read_arguments[MAX_PATH] = {0};
+  wchar_t read_description[MAX_PATH] = {0};
+  wchar_t read_icon[MAX_PATH] = {0};
   int read_icon_index = 0;
 
   HRESULT hr;
@@ -84,33 +82,36 @@
     return;
 
   if (properties.options & ShortcutProperties::PROPERTIES_TARGET) {
-    EXPECT_TRUE(SUCCEEDED(i_shell_link->GetPath(
-        as_writable_wcstr(read_target), MAX_PATH, NULL, SLGP_SHORTPATH)));
-    ValidatePathsAreEqual(properties.target, FilePath(read_target));
+    EXPECT_TRUE(SUCCEEDED(
+        i_shell_link->GetPath(read_target, MAX_PATH, NULL, SLGP_SHORTPATH)));
+    ValidatePathsAreEqual(properties.target,
+                          FilePath(AsStringPiece16(read_target)));
   }
 
   if (properties.options & ShortcutProperties::PROPERTIES_WORKING_DIR) {
-    EXPECT_TRUE(SUCCEEDED(i_shell_link->GetWorkingDirectory(
-        as_writable_wcstr(read_working_dir), MAX_PATH)));
-    ValidatePathsAreEqual(properties.working_dir, FilePath(read_working_dir));
+    EXPECT_TRUE(SUCCEEDED(
+        i_shell_link->GetWorkingDirectory(read_working_dir, MAX_PATH)));
+    ValidatePathsAreEqual(properties.working_dir,
+                          FilePath(AsStringPiece16(read_working_dir)));
   }
 
   if (properties.options & ShortcutProperties::PROPERTIES_ARGUMENTS) {
-    EXPECT_TRUE(SUCCEEDED(i_shell_link->GetArguments(
-        as_writable_wcstr(read_arguments), MAX_PATH)));
+    EXPECT_TRUE(
+        SUCCEEDED(i_shell_link->GetArguments(read_arguments, MAX_PATH)));
     EXPECT_EQ(properties.arguments, read_arguments);
   }
 
   if (properties.options & ShortcutProperties::PROPERTIES_DESCRIPTION) {
-    EXPECT_TRUE(SUCCEEDED(i_shell_link->GetDescription(
-        as_writable_wcstr(read_description), MAX_PATH)));
+    EXPECT_TRUE(
+        SUCCEEDED(i_shell_link->GetDescription(read_description, MAX_PATH)));
     EXPECT_EQ(properties.description, read_description);
   }
 
   if (properties.options & ShortcutProperties::PROPERTIES_ICON) {
-    EXPECT_TRUE(SUCCEEDED(i_shell_link->GetIconLocation(
-        as_writable_wcstr(read_icon), MAX_PATH, &read_icon_index)));
-    ValidatePathsAreEqual(properties.icon, FilePath(read_icon));
+    EXPECT_TRUE(SUCCEEDED(
+        i_shell_link->GetIconLocation(read_icon, MAX_PATH, &read_icon_index)));
+    ValidatePathsAreEqual(properties.icon,
+                          FilePath(AsStringPiece16(read_icon)));
     EXPECT_EQ(properties.icon_index, read_icon_index);
   }
 
@@ -129,7 +130,7 @@
         EXPECT_TRUE(properties.app_id.empty());
         break;
       case VT_LPWSTR:
-        EXPECT_EQ(properties.app_id, WideToUTF16(pv_app_id.get().pwszVal));
+        EXPECT_EQ(properties.app_id, pv_app_id.get().pwszVal);
         break;
       default:
         ADD_FAILURE() << "Unexpected variant type: " << pv_app_id.get().vt;
diff --git a/base/time/time_win_unittest.cc b/base/time/time_win_unittest.cc
index 7460bd1..a21b982 100644
--- a/base/time/time_win_unittest.cc
+++ b/base/time/time_win_unittest.cc
@@ -259,13 +259,11 @@
     // Read the CPU frequency from the registry.
     base::win::RegKey processor_key(
         HKEY_LOCAL_MACHINE,
-        STRING16_LITERAL("Hardware\\Description\\System\\CentralProcessor\\0"),
-        KEY_QUERY_VALUE);
+        L"Hardware\\Description\\System\\CentralProcessor\\0", KEY_QUERY_VALUE);
     ASSERT_TRUE(processor_key.Valid());
     DWORD processor_mhz_from_registry;
     ASSERT_EQ(ERROR_SUCCESS,
-              processor_key.ReadValueDW(STRING16_LITERAL("~MHz"),
-                                        &processor_mhz_from_registry));
+              processor_key.ReadValueDW(L"~MHz", &processor_mhz_from_registry));
 
     // Expect the measured TSC frequency to be similar to the processor
     // frequency from the registry (0.5% error).
diff --git a/base/win/embedded_i18n/language_selector.cc b/base/win/embedded_i18n/language_selector.cc
index 1a3a8a7..762b371 100644
--- a/base/win/embedded_i18n/language_selector.cc
+++ b/base/win/embedded_i18n/language_selector.cc
@@ -44,13 +44,13 @@
 
 #if DCHECK_IS_ON()
 // Returns true if the items in the given range are sorted and lower cased.
-bool IsArraySortedAndLowerCased(
-    base::span<const LangToOffset> languages_to_offset) {
+bool IsArraySortedAndLowerCased(span<const LangToOffset> languages_to_offset) {
   return std::is_sorted(languages_to_offset.begin(),
                         languages_to_offset.end()) &&
          std::all_of(languages_to_offset.begin(), languages_to_offset.end(),
                      [](const auto& lang) {
-                       return base::ToLowerASCII(lang.first) == lang.first;
+                       auto language = AsStringPiece16(lang.first);
+                       return ToLowerASCII(language) == language;
                      });
 }
 #endif  // DCHECK_IS_ON()
@@ -58,29 +58,29 @@
 // Determines the availability of all languages that may be used as aliases in
 // GetAliasedLanguageOffset or GetCompatibleNeutralLanguageOffset
 AvailableLanguageAliases DetermineAvailableAliases(
-    base::span<const LangToOffset> languages_to_offset) {
+    span<const LangToOffset> languages_to_offset) {
   AvailableLanguageAliases available_aliases = {};
 
   for (const LangToOffset& lang_to_offset : languages_to_offset) {
-    if (lang_to_offset.first == STRING16_LITERAL("en-gb"))
+    if (lang_to_offset.first == L"en-gb")
       available_aliases.en_gb_language_offset = &lang_to_offset;
-    else if (lang_to_offset.first == STRING16_LITERAL("en-us"))
+    else if (lang_to_offset.first == L"en-us")
       available_aliases.en_us_language_offset = &lang_to_offset;
-    else if (lang_to_offset.first == STRING16_LITERAL("es"))
+    else if (lang_to_offset.first == L"es")
       available_aliases.es_language_offset = &lang_to_offset;
-    else if (lang_to_offset.first == STRING16_LITERAL("es-419"))
+    else if (lang_to_offset.first == L"es-419")
       available_aliases.es_419_language_offset = &lang_to_offset;
-    else if (lang_to_offset.first == STRING16_LITERAL("fil"))
+    else if (lang_to_offset.first == L"fil")
       available_aliases.fil_language_offset = &lang_to_offset;
-    else if (lang_to_offset.first == STRING16_LITERAL("iw"))
+    else if (lang_to_offset.first == L"iw")
       available_aliases.iw_language_offset = &lang_to_offset;
-    else if (lang_to_offset.first == STRING16_LITERAL("no"))
+    else if (lang_to_offset.first == L"no")
       available_aliases.no_language_offset = &lang_to_offset;
-    else if (lang_to_offset.first == STRING16_LITERAL("pt-br"))
+    else if (lang_to_offset.first == L"pt-br")
       available_aliases.pt_br_language_offset = &lang_to_offset;
-    else if (lang_to_offset.first == STRING16_LITERAL("zh-cn"))
+    else if (lang_to_offset.first == L"zh-cn")
       available_aliases.zh_cn_language_offset = &lang_to_offset;
-    else if (lang_to_offset.first == STRING16_LITERAL("zh-tw"))
+    else if (lang_to_offset.first == L"zh-tw")
       available_aliases.zh_tw_language_offset = &lang_to_offset;
   }
 
@@ -93,8 +93,8 @@
 // that matches the |language| exactly. |offset| will store the offset of the
 // language that matches if any. |languages_to_offset| must be sorted by
 // language and all languages must lower case.
-bool GetExactLanguageOffset(base::span<const LangToOffset> languages_to_offset,
-                            const base::string16& language,
+bool GetExactLanguageOffset(span<const LangToOffset> languages_to_offset,
+                            const std::wstring& language,
                             const LangToOffset** matched_language_to_offset) {
   DCHECK(matched_language_to_offset);
 
@@ -102,7 +102,7 @@
   // to a given language |name|.
   auto search_result = std::lower_bound(
       languages_to_offset.begin(), languages_to_offset.end(), language,
-      [](const LangToOffset& left, const base::string16& to_find) {
+      [](const LangToOffset& left, const std::wstring& to_find) {
         return left.first < to_find;
       });
   if (languages_to_offset.end() != search_result &&
@@ -115,65 +115,58 @@
 
 // Returns true if the current language can be aliased to another language.
 bool GetAliasedLanguageOffset(const AvailableLanguageAliases& available_aliases,
-                              const base::string16& language,
+                              const std::wstring& language,
                               const LangToOffset** matched_language_to_offset) {
   DCHECK(matched_language_to_offset);
 
   // Alias some English variants to British English (all others wildcard to
   // US).
   if (available_aliases.en_gb_language_offset &&
-      (language == STRING16_LITERAL("en-au") ||
-       language == STRING16_LITERAL("en-ca") ||
-       language == STRING16_LITERAL("en-nz") ||
-       language == STRING16_LITERAL("en-za"))) {
+      (language == L"en-au" || language == L"en-ca" || language == L"en-nz" ||
+       language == L"en-za")) {
     *matched_language_to_offset = available_aliases.en_gb_language_offset;
     return true;
   }
   // Alias es-es to es (all others wildcard to es-419).
-  if (available_aliases.es_language_offset &&
-      language == STRING16_LITERAL("es-es")) {
+  if (available_aliases.es_language_offset && language == L"es-es") {
     *matched_language_to_offset = available_aliases.es_language_offset;
     return true;
   }
   // Google web properties use iw for he. Handle both just to be safe.
-  if (available_aliases.iw_language_offset &&
-      language == STRING16_LITERAL("he")) {
+  if (available_aliases.iw_language_offset && language == L"he") {
     *matched_language_to_offset = available_aliases.iw_language_offset;
     return true;
   }
   // Google web properties use no for nb. Handle both just to be safe.
-  if (available_aliases.no_language_offset &&
-      language == STRING16_LITERAL("nb")) {
+  if (available_aliases.no_language_offset && language == L"nb") {
     *matched_language_to_offset = available_aliases.no_language_offset;
     return true;
   }
   // Some Google web properties use tl for fil. Handle both just to be safe.
   // They're not completely identical, but alias it here.
-  if (available_aliases.fil_language_offset &&
-      language == STRING16_LITERAL("tl")) {
+  if (available_aliases.fil_language_offset && language == L"tl") {
     *matched_language_to_offset = available_aliases.fil_language_offset;
     return true;
   }
   if (available_aliases.zh_cn_language_offset &&
       // Pre-Vista alias for Chinese w/ script subtag.
-      (language == STRING16_LITERAL("zh-chs") ||
+      (language == L"zh-chs" ||
        // Vista+ alias for Chinese w/ script subtag.
-       language == STRING16_LITERAL("zh-hans") ||
+       language == L"zh-hans" ||
        // Although the wildcard entry for zh would result in this, alias zh-sg
        // so that it will win if it precedes another valid tag in a list of
        // candidates.
-       language == STRING16_LITERAL("zh-sg"))) {
+       language == L"zh-sg")) {
     *matched_language_to_offset = available_aliases.zh_cn_language_offset;
     return true;
   }
   if (available_aliases.zh_tw_language_offset &&
       // Pre-Vista alias for Chinese w/ script subtag.
-      (language == STRING16_LITERAL("zh-cht") ||
+      (language == L"zh-cht" ||
        // Vista+ alias for Chinese w/ script subtag.
-       language == STRING16_LITERAL("zh-hant") ||
+       language == L"zh-hant" ||
        // Alias Hong Kong and Macau to Taiwan.
-       language == STRING16_LITERAL("zh-hk") ||
-       language == STRING16_LITERAL("zh-mo"))) {
+       language == L"zh-hk" || language == L"zh-mo")) {
     *matched_language_to_offset = available_aliases.zh_tw_language_offset;
     return true;
   }
@@ -185,30 +178,26 @@
 // language.
 bool GetCompatibleNeutralLanguageOffset(
     const AvailableLanguageAliases& available_aliases,
-    const base::string16& neutral_language,
+    const std::wstring& neutral_language,
     const LangToOffset** matched_language_to_offset) {
   DCHECK(matched_language_to_offset);
 
-  if (available_aliases.en_us_language_offset &&
-      neutral_language == STRING16_LITERAL("en")) {
+  if (available_aliases.en_us_language_offset && neutral_language == L"en") {
     // Use the U.S. region for anything English.
     *matched_language_to_offset = available_aliases.en_us_language_offset;
     return true;
   }
-  if (available_aliases.es_419_language_offset &&
-      neutral_language == STRING16_LITERAL("es")) {
+  if (available_aliases.es_419_language_offset && neutral_language == L"es") {
     // Use the Latin American region for anything Spanish.
     *matched_language_to_offset = available_aliases.es_419_language_offset;
     return true;
   }
-  if (available_aliases.pt_br_language_offset &&
-      neutral_language == STRING16_LITERAL("pt")) {
+  if (available_aliases.pt_br_language_offset && neutral_language == L"pt") {
     // Use the Brazil region for anything Portugese.
     *matched_language_to_offset = available_aliases.pt_br_language_offset;
     return true;
   }
-  if (available_aliases.zh_cn_language_offset &&
-      neutral_language == STRING16_LITERAL("zh")) {
+  if (available_aliases.zh_cn_language_offset && neutral_language == L"zh") {
     // Use the P.R.C. region for anything Chinese.
     *matched_language_to_offset = available_aliases.zh_cn_language_offset;
     return true;
@@ -223,11 +212,11 @@
 // candidate and |matched_offset| is assigned the language offset of the
 // selected translation.
 // static
-bool SelectIf(const std::vector<base::string16>& candidates,
-              base::span<const LangToOffset> languages_to_offset,
+bool SelectIf(const std::vector<std::wstring>& candidates,
+              span<const LangToOffset> languages_to_offset,
               const AvailableLanguageAliases& available_aliases,
               const LangToOffset** matched_language_to_offset,
-              base::string16* matched_name) {
+              std::wstring* matched_name) {
   DCHECK(matched_language_to_offset);
   DCHECK(matched_name);
 
@@ -236,8 +225,9 @@
 
   // An earlier candidate entry matching on an exact match or alias match takes
   // precedence over a later candidate entry matching on an exact match.
-  for (const base::string16& scan : candidates) {
-    base::string16 lower_case_candidate = base::ToLowerASCII(scan);
+  for (const std::wstring& scan : candidates) {
+    std::wstring lower_case_candidate =
+        AsWString(ToLowerASCII(AsStringPiece16(scan)));
     if (GetExactLanguageOffset(languages_to_offset, lower_case_candidate,
                                matched_language_to_offset) ||
         GetAliasedLanguageOffset(available_aliases, lower_case_candidate,
@@ -249,12 +239,13 @@
 
   // If no candidate matches exactly or by alias, try to match by locale neutral
   // language.
-  for (const base::string16& scan : candidates) {
-    base::string16 lower_case_candidate = base::ToLowerASCII(scan);
+  for (const std::wstring& scan : candidates) {
+    std::wstring lower_case_candidate =
+        AsWString(ToLowerASCII(AsStringPiece16(scan)));
 
     // Extract the locale neutral language from the language to search and try
     // to find an exact match for that language in the provided table.
-    base::string16 neutral_language =
+    std::wstring neutral_language =
         lower_case_candidate.substr(0, lower_case_candidate.find(L'-'));
 
     if (GetCompatibleNeutralLanguageOffset(available_aliases, neutral_language,
@@ -268,11 +259,11 @@
 }
 
 void SelectLanguageMatchingCandidate(
-    const std::vector<base::string16>& candidates,
-    base::span<const LangToOffset> languages_to_offset,
+    const std::vector<std::wstring>& candidates,
+    span<const LangToOffset> languages_to_offset,
     int* selected_offset,
-    base::string16* matched_candidate,
-    base::string16* selected_language) {
+    std::wstring* matched_candidate,
+    std::wstring* selected_language) {
   DCHECK(selected_offset);
   DCHECK(matched_candidate);
   DCHECK(selected_language);
@@ -303,18 +294,18 @@
                 &matched_language_to_offset, matched_candidate)) {
     matched_language_to_offset = available_aliases.en_us_language_offset;
     *matched_candidate =
-        base::string16(available_aliases.en_us_language_offset->first);
+        std::wstring(available_aliases.en_us_language_offset->first);
   }
 
   DCHECK(matched_language_to_offset);
   // Get the real language being used for the matched candidate.
-  *selected_language = base::string16(matched_language_to_offset->first);
+  *selected_language = std::wstring(matched_language_to_offset->first);
   *selected_offset = matched_language_to_offset->second;
 }
 
-std::vector<base::string16> GetCandidatesFromSystem(
-    base::StringPiece16 preferred_language) {
-  std::vector<base::string16> candidates;
+std::vector<std::wstring> GetCandidatesFromSystem(
+    WStringPiece preferred_language) {
+  std::vector<std::wstring> candidates;
 
   // Get the intitial candidate list for this particular implementation (if
   // applicable).
@@ -323,21 +314,19 @@
 
   // Now try the UI languages.  Use the thread preferred ones since that will
   // kindly return us a list of all kinds of fallbacks.
-  base::win::i18n::GetThreadPreferredUILanguageList(&candidates);
+  win::i18n::GetThreadPreferredUILanguageList(&candidates);
   return candidates;
 }
 
 }  // namespace
 
-LanguageSelector::LanguageSelector(
-    base::StringPiece16 preferred_language,
-    base::span<const LangToOffset> languages_to_offset)
+LanguageSelector::LanguageSelector(WStringPiece preferred_language,
+                                   span<const LangToOffset> languages_to_offset)
     : LanguageSelector(GetCandidatesFromSystem(preferred_language),
                        languages_to_offset) {}
 
-LanguageSelector::LanguageSelector(
-    const std::vector<base::string16>& candidates,
-    base::span<const LangToOffset> languages_to_offset)
+LanguageSelector::LanguageSelector(const std::vector<std::wstring>& candidates,
+                                   span<const LangToOffset> languages_to_offset)
     : selected_offset_(languages_to_offset.size()) {
   SelectLanguageMatchingCandidate(candidates, languages_to_offset,
                                   &selected_offset_, &matched_candidate_,
diff --git a/base/win/embedded_i18n/language_selector.h b/base/win/embedded_i18n/language_selector.h
index 2772aee..84d1e9cd 100644
--- a/base/win/embedded_i18n/language_selector.h
+++ b/base/win/embedded_i18n/language_selector.h
@@ -8,13 +8,13 @@
 #ifndef BASE_WIN_EMBEDDED_I18N_LANGUAGE_SELECTOR_H_
 #define BASE_WIN_EMBEDDED_I18N_LANGUAGE_SELECTOR_H_
 
+#include <string>
 #include <utility>
 #include <vector>
 
 #include "base/base_export.h"
 #include "base/containers/span.h"
 #include "base/macros.h"
-#include "base/strings/string16.h"
 #include "base/strings/string_piece.h"
 
 namespace base {
@@ -26,7 +26,7 @@
 // override selection should a corresponding translation be available.
 class BASE_EXPORT LanguageSelector {
  public:
-  using LangToOffset = std::pair<base::StringPiece16, int>;
+  using LangToOffset = std::pair<WStringPiece, int>;
 
   // Constructor to be used for users of this class that will provide the actual
   // language offsets that will be used.
@@ -36,8 +36,8 @@
   // |languages_to_offset_begin| and |languages_to_offset_end| point to a sorted
   // array of language identifiers (and their offsets) for which translations
   // are available.
-  LanguageSelector(base::StringPiece16 preferred_language,
-                   base::span<const LangToOffset> languages_to_offset);
+  LanguageSelector(WStringPiece preferred_language,
+                   span<const LangToOffset> languages_to_offset);
 
   // Constructor for testing purposes.
   // |candidates| is a list of all candiate languages that can be used to
@@ -45,8 +45,8 @@
   // |languages_to_offset_begin| and |languages_to_offset_end| point to a sorted
   // array of language identifiers (and their offsets) for which translations
   // are available.
-  LanguageSelector(const std::vector<base::string16>& candidates,
-                   base::span<const LangToOffset> languages_to_offset);
+  LanguageSelector(const std::vector<std::wstring>& candidates,
+                   span<const LangToOffset> languages_to_offset);
 
   ~LanguageSelector();
 
@@ -54,16 +54,16 @@
   int offset() const { return selected_offset_; }
 
   // The full name of the candidate language for which a match was found.
-  const base::string16& matched_candidate() const { return matched_candidate_; }
+  const std::wstring& matched_candidate() const { return matched_candidate_; }
 
   // The name of the selected translation.
-  const base::string16& selected_translation() const {
+  const std::wstring& selected_translation() const {
     return selected_language_;
   }
 
  private:
-  base::string16 matched_candidate_;
-  base::string16 selected_language_;
+  std::wstring matched_candidate_;
+  std::wstring selected_language_;
   int selected_offset_;
 
   DISALLOW_COPY_AND_ASSIGN(LanguageSelector);
diff --git a/base/win/embedded_i18n/language_selector_unittest.cc b/base/win/embedded_i18n/language_selector_unittest.cc
index 64efc1d..6903d0c 100644
--- a/base/win/embedded_i18n/language_selector_unittest.cc
+++ b/base/win/embedded_i18n/language_selector_unittest.cc
@@ -17,49 +17,26 @@
 namespace i18n {
 namespace {
 
-constexpr const base::char16* kExactMatchCandidates[] = {
-    STRING16_LITERAL("am"),     STRING16_LITERAL("ar"),
-    STRING16_LITERAL("bg"),     STRING16_LITERAL("bn"),
-    STRING16_LITERAL("ca"),     STRING16_LITERAL("cs"),
-    STRING16_LITERAL("da"),     STRING16_LITERAL("de"),
-    STRING16_LITERAL("el"),     STRING16_LITERAL("en-gb"),
-    STRING16_LITERAL("en-us"),  STRING16_LITERAL("es"),
-    STRING16_LITERAL("es-419"), STRING16_LITERAL("et"),
-    STRING16_LITERAL("fa"),     STRING16_LITERAL("fi"),
-    STRING16_LITERAL("fil"),    STRING16_LITERAL("fr"),
-    STRING16_LITERAL("gu"),     STRING16_LITERAL("hi"),
-    STRING16_LITERAL("hr"),     STRING16_LITERAL("hu"),
-    STRING16_LITERAL("id"),     STRING16_LITERAL("it"),
-    STRING16_LITERAL("iw"),     STRING16_LITERAL("ja"),
-    STRING16_LITERAL("kn"),     STRING16_LITERAL("ko"),
-    STRING16_LITERAL("lt"),     STRING16_LITERAL("lv"),
-    STRING16_LITERAL("ml"),     STRING16_LITERAL("mr"),
-    STRING16_LITERAL("nl"),     STRING16_LITERAL("no"),
-    STRING16_LITERAL("pl"),     STRING16_LITERAL("pt-br"),
-    STRING16_LITERAL("pt-pt"),  STRING16_LITERAL("ro"),
-    STRING16_LITERAL("ru"),     STRING16_LITERAL("sk"),
-    STRING16_LITERAL("sl"),     STRING16_LITERAL("sr"),
-    STRING16_LITERAL("sv"),     STRING16_LITERAL("sw"),
-    STRING16_LITERAL("ta"),     STRING16_LITERAL("te"),
-    STRING16_LITERAL("th"),     STRING16_LITERAL("tr"),
-    STRING16_LITERAL("uk"),     STRING16_LITERAL("vi"),
-    STRING16_LITERAL("zh-cn"),  STRING16_LITERAL("zh-tw")};
+constexpr const wchar_t* kExactMatchCandidates[] = {
+    L"am",  L"ar",    L"bg",    L"bn",    L"ca",     L"cs", L"da", L"de",
+    L"el",  L"en-gb", L"en-us", L"es",    L"es-419", L"et", L"fa", L"fi",
+    L"fil", L"fr",    L"gu",    L"hi",    L"hr",     L"hu", L"id", L"it",
+    L"iw",  L"ja",    L"kn",    L"ko",    L"lt",     L"lv", L"ml", L"mr",
+    L"nl",  L"no",    L"pl",    L"pt-br", L"pt-pt",  L"ro", L"ru", L"sk",
+    L"sl",  L"sr",    L"sv",    L"sw",    L"ta",     L"te", L"th", L"tr",
+    L"uk",  L"vi",    L"zh-cn", L"zh-tw"};
 
-constexpr const base::char16* kAliasMatchCandidates[] = {
-    STRING16_LITERAL("he"),      STRING16_LITERAL("nb"),
-    STRING16_LITERAL("tl"),      STRING16_LITERAL("zh-chs"),
-    STRING16_LITERAL("zh-cht"),  STRING16_LITERAL("zh-hans"),
-    STRING16_LITERAL("zh-hant"), STRING16_LITERAL("zh-hk"),
-    STRING16_LITERAL("zh-mo")};
+constexpr const wchar_t* kAliasMatchCandidates[] = {
+    L"he",      L"nb",      L"tl",    L"zh-chs", L"zh-cht",
+    L"zh-hans", L"zh-hant", L"zh-hk", L"zh-mo"};
 
-constexpr const base::char16* kWildcardMatchCandidates[] = {
-    STRING16_LITERAL("en-AU"), STRING16_LITERAL("es-CO"),
-    STRING16_LITERAL("pt-AB"), STRING16_LITERAL("zh-SG")};
+constexpr const wchar_t* kWildcardMatchCandidates[] = {L"en-AU", L"es-CO",
+                                                       L"pt-AB", L"zh-SG"};
 
 std::vector<LanguageSelector::LangToOffset> MakeLanguageOffsetPairs() {
   std::vector<LanguageSelector::LangToOffset> language_offset_pairs;
   int i = 0;
-  for (const base::char16* lang : kExactMatchCandidates) {
+  for (const wchar_t* lang : kExactMatchCandidates) {
     language_offset_pairs.push_back({lang, i++});
   }
 
@@ -68,13 +45,12 @@
 
 class TestLanguageSelector : public LanguageSelector {
  public:
-  TestLanguageSelector()
-      : TestLanguageSelector(std::vector<base::string16>()) {}
-  explicit TestLanguageSelector(const std::vector<base::string16>& candidates)
+  TestLanguageSelector() : TestLanguageSelector(std::vector<std::wstring>()) {}
+  explicit TestLanguageSelector(const std::vector<std::wstring>& candidates)
       : TestLanguageSelector(candidates, MakeLanguageOffsetPairs()) {}
   TestLanguageSelector(
-      const std::vector<base::string16>& candidates,
-      base::span<const LanguageSelector::LangToOffset> languages_to_offset)
+      const std::vector<std::wstring>& candidates,
+      span<const LanguageSelector::LangToOffset> languages_to_offset)
       : LanguageSelector(candidates, languages_to_offset) {}
 };
 
@@ -89,32 +65,28 @@
 // Test some hypothetical candidate sets.
 TEST(LanguageSelectorTest, AssortedSelections) {
   {
-    std::vector<base::string16> candidates = {STRING16_LITERAL("fr-BE"),
-                                              STRING16_LITERAL("fr"),
-                                              STRING16_LITERAL("en")};
+    std::vector<std::wstring> candidates = {L"fr-BE", L"fr", L"en"};
     TestLanguageSelector instance(candidates);
     // Expect the exact match to win.
-    EXPECT_EQ(STRING16_LITERAL("fr"), instance.matched_candidate());
+    EXPECT_EQ(L"fr", instance.matched_candidate());
   }
   {
-    std::vector<base::string16> candidates = {STRING16_LITERAL("xx-YY"),
-                                              STRING16_LITERAL("cc-Ssss-RR")};
+    std::vector<std::wstring> candidates = {L"xx-YY", L"cc-Ssss-RR"};
     TestLanguageSelector instance(candidates);
     // Expect the fallback to win.
-    EXPECT_EQ(STRING16_LITERAL("en-us"), instance.matched_candidate());
+    EXPECT_EQ(L"en-us", instance.matched_candidate());
   }
   {
-    std::vector<base::string16> candidates = {STRING16_LITERAL("zh-SG"),
-                                              STRING16_LITERAL("en-GB")};
+    std::vector<std::wstring> candidates = {L"zh-SG", L"en-GB"};
     TestLanguageSelector instance(candidates);
     // Expect the alias match to win.
-    EXPECT_EQ(STRING16_LITERAL("zh-SG"), instance.matched_candidate());
+    EXPECT_EQ(L"zh-SG", instance.matched_candidate());
   }
 }
 
 // A fixture for testing sets of single-candidate selections.
 class LanguageSelectorMatchCandidateTest
-    : public ::testing::TestWithParam<const base::char16*> {};
+    : public ::testing::TestWithParam<const wchar_t*> {};
 
 TEST_P(LanguageSelectorMatchCandidateTest, TestMatchCandidate) {
   TestLanguageSelector instance({GetParam()});
@@ -141,7 +113,7 @@
 // candidate that should be aliased to the expectation.
 class LanguageSelectorAliasTest
     : public ::testing::TestWithParam<
-          std::tuple<const base::char16*, const base::char16*>> {};
+          std::tuple<const wchar_t*, const wchar_t*>> {};
 
 // Test that the candidate language maps to the aliased translation.
 TEST_P(LanguageSelectorAliasTest, AliasesMatch) {
@@ -149,49 +121,42 @@
   EXPECT_EQ(std::get<0>(GetParam()), instance.selected_translation());
 }
 
-INSTANTIATE_TEST_SUITE_P(
-    EnGbAliases,
-    LanguageSelectorAliasTest,
-    ::testing::Combine(::testing::Values(STRING16_LITERAL("en-gb")),
-                       ::testing::Values(STRING16_LITERAL("en-au"),
-                                         STRING16_LITERAL("en-ca"),
-                                         STRING16_LITERAL("en-nz"),
-                                         STRING16_LITERAL("en-za"))));
+INSTANTIATE_TEST_SUITE_P(EnGbAliases,
+                         LanguageSelectorAliasTest,
+                         ::testing::Combine(::testing::Values(L"en-gb"),
+                                            ::testing::Values(L"en-au",
+                                                              L"en-ca",
+                                                              L"en-nz",
+                                                              L"en-za")));
 
-INSTANTIATE_TEST_SUITE_P(
-    IwAliases,
-    LanguageSelectorAliasTest,
-    ::testing::Combine(::testing::Values(STRING16_LITERAL("iw")),
-                       ::testing::Values(STRING16_LITERAL("he"))));
+INSTANTIATE_TEST_SUITE_P(IwAliases,
+                         LanguageSelectorAliasTest,
+                         ::testing::Combine(::testing::Values(L"iw"),
+                                            ::testing::Values(L"he")));
 
-INSTANTIATE_TEST_SUITE_P(
-    NoAliases,
-    LanguageSelectorAliasTest,
-    ::testing::Combine(::testing::Values(STRING16_LITERAL("no")),
-                       ::testing::Values(STRING16_LITERAL("nb"))));
+INSTANTIATE_TEST_SUITE_P(NoAliases,
+                         LanguageSelectorAliasTest,
+                         ::testing::Combine(::testing::Values(L"no"),
+                                            ::testing::Values(L"nb")));
 
-INSTANTIATE_TEST_SUITE_P(
-    FilAliases,
-    LanguageSelectorAliasTest,
-    ::testing::Combine(::testing::Values(STRING16_LITERAL("fil")),
-                       ::testing::Values(STRING16_LITERAL("tl"))));
+INSTANTIATE_TEST_SUITE_P(FilAliases,
+                         LanguageSelectorAliasTest,
+                         ::testing::Combine(::testing::Values(L"fil"),
+                                            ::testing::Values(L"tl")));
 
 INSTANTIATE_TEST_SUITE_P(
     ZhCnAliases,
     LanguageSelectorAliasTest,
-    ::testing::Combine(::testing::Values(STRING16_LITERAL("zh-cn")),
-                       ::testing::Values(STRING16_LITERAL("zh-chs"),
-                                         STRING16_LITERAL("zh-hans"),
-                                         STRING16_LITERAL("zh-sg"))));
+    ::testing::Combine(::testing::Values(L"zh-cn"),
+                       ::testing::Values(L"zh-chs", L"zh-hans", L"zh-sg")));
 
-INSTANTIATE_TEST_SUITE_P(
-    ZhTwAliases,
-    LanguageSelectorAliasTest,
-    ::testing::Combine(::testing::Values(STRING16_LITERAL("zh-tw")),
-                       ::testing::Values(STRING16_LITERAL("zh-cht"),
-                                         STRING16_LITERAL("zh-hant"),
-                                         STRING16_LITERAL("zh-hk"),
-                                         STRING16_LITERAL("zh-mo"))));
+INSTANTIATE_TEST_SUITE_P(ZhTwAliases,
+                         LanguageSelectorAliasTest,
+                         ::testing::Combine(::testing::Values(L"zh-tw"),
+                                            ::testing::Values(L"zh-cht",
+                                                              L"zh-hant",
+                                                              L"zh-hk",
+                                                              L"zh-mo")));
 
 // Test that we can get a match of the default language.
 TEST(LanguageSelectorTest, DefaultLanguageName) {
@@ -202,34 +167,32 @@
 // All languages given to the selector must be lower cased (since generally
 // the language names are generated by a python script).
 TEST(LanguageSelectorTest, InvalidLanguageCasing) {
-  constexpr LanguageSelector::LangToOffset kLangToOffset[] = {
-      {STRING16_LITERAL("en-US"), 0}};
+  constexpr LanguageSelector::LangToOffset kLangToOffset[] = {{L"en-US", 0}};
   EXPECT_DCHECK_DEATH(LanguageSelector instance(
-      std::vector<base::string16>({STRING16_LITERAL("en-us")}), kLangToOffset));
+      std::vector<std::wstring>({L"en-us"}), kLangToOffset));
 }
 
 // Language name and offset pairs must be ordered when generated by the
 // python script.
 TEST(LanguageSelectorTest, InvalidLanguageNameOrder) {
-  constexpr LanguageSelector::LangToOffset kLangToOffset[] = {
-      {STRING16_LITERAL("en-us"), 0}, {STRING16_LITERAL("en-gb"), 1}};
+  constexpr LanguageSelector::LangToOffset kLangToOffset[] = {{L"en-us", 0},
+                                                              {L"en-gb", 1}};
   EXPECT_DCHECK_DEATH(LanguageSelector instance(
-      std::vector<base::string16>({STRING16_LITERAL("en-us")}), kLangToOffset));
+      std::vector<std::wstring>({L"en-us"}), kLangToOffset));
 }
 
 // There needs to be a fallback language available in the generated
 // languages if ever the selector is given a language that does not exist.
 TEST(LanguageSelectorTest, NoFallbackLanguageAvailable) {
-  constexpr LanguageSelector::LangToOffset kLangToOffset[] = {
-      {STRING16_LITERAL("en-gb"), 0}};
+  constexpr LanguageSelector::LangToOffset kLangToOffset[] = {{L"en-gb", 0}};
   EXPECT_DCHECK_DEATH(LanguageSelector instance(
-      std::vector<base::string16>({STRING16_LITERAL("aa-bb")}), kLangToOffset));
+      std::vector<std::wstring>({L"aa-bb"}), kLangToOffset));
 }
 
 // No languages available.
 TEST(LanguageSelectorTest, NoLanguagesAvailable) {
-  EXPECT_DCHECK_DEATH(LanguageSelector instance(
-      std::vector<base::string16>({STRING16_LITERAL("en-us")}), {}));
+  EXPECT_DCHECK_DEATH(
+      LanguageSelector instance(std::vector<std::wstring>({L"en-us"}), {}));
 }
 
 }  // namespace i18n
diff --git a/base/win/i18n.cc b/base/win/i18n.cc
index adba36d..ca80f938 100644
--- a/base/win/i18n.cc
+++ b/base/win/i18n.cc
@@ -16,7 +16,7 @@
 
 bool GetPreferredUILanguageList(GetPreferredUILanguages_Fn function,
                                 ULONG flags,
-                                std::vector<base::string16>* languages) {
+                                std::vector<std::wstring>* languages) {
   DCHECK_EQ((flags & (MUI_LANGUAGE_ID | MUI_LANGUAGE_NAME)), 0U);
   const ULONG call_flags = flags | MUI_LANGUAGE_NAME;
   ULONG language_count = 0;
@@ -27,18 +27,21 @@
     return false;
   }
 
-  base::string16 buffer(buffer_length, '\0');
-  if (!function(call_flags, &language_count, base::as_writable_wcstr(buffer),
+  std::wstring buffer(buffer_length, '\0');
+  if (!function(call_flags, &language_count, base::data(buffer),
                 &buffer_length) ||
       !language_count) {
     DPCHECK(!language_count) << "Failed getting preferred UI languages.";
     return false;
   }
 
+  languages->clear();
   // Split string on NUL characters.
-  *languages =
-      base::SplitString(buffer, base::string16(1, '\0'), base::KEEP_WHITESPACE,
-                        base::SPLIT_WANT_NONEMPTY);
+  for (const auto& token : base::SplitStringPiece(
+           base::AsStringPiece16(buffer), base::string16(1, '\0'),
+           base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
+    languages->push_back(base::AsWString(token));
+  }
   DCHECK_EQ(languages->size(), language_count);
   return true;
 }
@@ -49,13 +52,13 @@
 namespace win {
 namespace i18n {
 
-bool GetUserPreferredUILanguageList(std::vector<base::string16>* languages) {
+bool GetUserPreferredUILanguageList(std::vector<std::wstring>* languages) {
   DCHECK(languages);
   return GetPreferredUILanguageList(::GetUserPreferredUILanguages, 0,
                                     languages);
 }
 
-bool GetThreadPreferredUILanguageList(std::vector<base::string16>* languages) {
+bool GetThreadPreferredUILanguageList(std::vector<std::wstring>* languages) {
   DCHECK(languages);
   return GetPreferredUILanguageList(
       ::GetThreadPreferredUILanguages,
diff --git a/base/win/i18n.h b/base/win/i18n.h
index d586646..9e74d3f 100644
--- a/base/win/i18n.h
+++ b/base/win/i18n.h
@@ -5,10 +5,10 @@
 #ifndef BASE_WIN_I18N_H_
 #define BASE_WIN_I18N_H_
 
+#include <string>
 #include <vector>
 
 #include "base/base_export.h"
-#include "base/strings/string16.h"
 
 namespace base {
 namespace win {
@@ -18,13 +18,13 @@
 // available, falling-back on the user default UI language otherwise.  Returns
 // true if at least one language is added.
 BASE_EXPORT bool GetUserPreferredUILanguageList(
-    std::vector<base::string16>* languages);
+    std::vector<std::wstring>* languages);
 
 // Adds to |languages| the list of thread, process, user, and system preferred
 // UI languages from MUI, if available, falling-back on the user default UI
 // language otherwise.  Returns true if at least one language is added.
 BASE_EXPORT bool GetThreadPreferredUILanguageList(
-    std::vector<base::string16>* languages);
+    std::vector<std::wstring>* languages);
 
 }  // namespace i18n
 }  // namespace win
diff --git a/base/win/i18n_unittest.cc b/base/win/i18n_unittest.cc
index 3b0b668a..f38db24 100644
--- a/base/win/i18n_unittest.cc
+++ b/base/win/i18n_unittest.cc
@@ -19,24 +19,24 @@
 
 // Tests that at least one user preferred UI language can be obtained.
 TEST(I18NTest, GetUserPreferredUILanguageList) {
-  std::vector<base::string16> languages;
+  std::vector<std::wstring> languages;
   EXPECT_TRUE(GetUserPreferredUILanguageList(&languages));
   EXPECT_FALSE(languages.empty());
   for (const auto& language : languages) {
     EXPECT_FALSE(language.empty());
     // Ensure there's no extra trailing 0 characters.
-    EXPECT_EQ(language.size(), wcslen(base::as_wcstr(language)));
+    EXPECT_EQ(language.size(), wcslen(language.c_str()));
   }
 }
 
 // Tests that at least one thread preferred UI language can be obtained.
 TEST(I18NTest, GetThreadPreferredUILanguageList) {
-  std::vector<base::string16> languages;
+  std::vector<std::wstring> languages;
   EXPECT_TRUE(GetThreadPreferredUILanguageList(&languages));
   EXPECT_FALSE(languages.empty());
   for (const auto& language : languages) {
     EXPECT_FALSE(language.empty());
-    EXPECT_EQ(language.size(), wcslen(base::as_wcstr(language)));
+    EXPECT_EQ(language.size(), wcslen(language.c_str()));
   }
 }
 
diff --git a/base/win/registry.cc b/base/win/registry.cc
index b95b474..cd6208ed 100644
--- a/base/win/registry.cc
+++ b/base/win/registry.cc
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
+#include "base/strings/string_util_win.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/win/shlwapi.h"
 #include "base/win/windows_version.h"
@@ -95,7 +96,7 @@
 RegKey::RegKey(HKEY key) : key_(key), wow64access_(0) {
 }
 
-RegKey::RegKey(HKEY rootkey, const char16* subkey, REGSAM access)
+RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access)
     : key_(NULL), wow64access_(0) {
   if (rootkey) {
     if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
@@ -112,20 +113,20 @@
   Close();
 }
 
-LONG RegKey::Create(HKEY rootkey, const char16* subkey, REGSAM access) {
+LONG RegKey::Create(HKEY rootkey, const wchar_t* subkey, REGSAM access) {
   DWORD disposition_value;
   return CreateWithDisposition(rootkey, subkey, &disposition_value, access);
 }
 
 LONG RegKey::CreateWithDisposition(HKEY rootkey,
-                                   const char16* subkey,
+                                   const wchar_t* subkey,
                                    DWORD* disposition,
                                    REGSAM access) {
   DCHECK(rootkey && subkey && access && disposition);
   HKEY subhkey = NULL;
-  LONG result = RegCreateKeyEx(rootkey, as_wcstr(subkey), 0, NULL,
-                               REG_OPTION_NON_VOLATILE, access, NULL, &subhkey,
-                               disposition);
+  LONG result =
+      RegCreateKeyEx(rootkey, subkey, 0, NULL, REG_OPTION_NON_VOLATILE, access,
+                     NULL, &subhkey, disposition);
   if (result == ERROR_SUCCESS) {
     Close();
     key_ = subhkey;
@@ -135,7 +136,7 @@
   return result;
 }
 
-LONG RegKey::CreateKey(const char16* name, REGSAM access) {
+LONG RegKey::CreateKey(const wchar_t* name, REGSAM access) {
   DCHECK(name && access);
   // After the application has accessed an alternate registry view using one of
   // the [KEY_WOW64_32KEY / KEY_WOW64_64KEY] flags, all subsequent operations
@@ -147,9 +148,8 @@
     return ERROR_INVALID_PARAMETER;
   }
   HKEY subkey = NULL;
-  LONG result =
-      RegCreateKeyEx(key_, as_wcstr(name), 0, NULL, REG_OPTION_NON_VOLATILE,
-                     access, NULL, &subkey, NULL);
+  LONG result = RegCreateKeyEx(key_, name, 0, NULL, REG_OPTION_NON_VOLATILE,
+                               access, NULL, &subkey, NULL);
   if (result == ERROR_SUCCESS) {
     Close();
     key_ = subkey;
@@ -159,11 +159,11 @@
   return result;
 }
 
-LONG RegKey::Open(HKEY rootkey, const char16* subkey, REGSAM access) {
+LONG RegKey::Open(HKEY rootkey, const wchar_t* subkey, REGSAM access) {
   DCHECK(rootkey && subkey && access);
   HKEY subhkey = NULL;
 
-  LONG result = RegOpenKeyEx(rootkey, as_wcstr(subkey), 0, access, &subhkey);
+  LONG result = RegOpenKeyEx(rootkey, subkey, 0, access, &subhkey);
   if (result == ERROR_SUCCESS) {
     Close();
     key_ = subhkey;
@@ -173,7 +173,7 @@
   return result;
 }
 
-LONG RegKey::OpenKey(const char16* relative_key_name, REGSAM access) {
+LONG RegKey::OpenKey(const wchar_t* relative_key_name, REGSAM access) {
   DCHECK(relative_key_name && access);
   // After the application has accessed an alternate registry view using one of
   // the [KEY_WOW64_32KEY / KEY_WOW64_64KEY] flags, all subsequent operations
@@ -185,8 +185,7 @@
     return ERROR_INVALID_PARAMETER;
   }
   HKEY subkey = NULL;
-  LONG result =
-      RegOpenKeyEx(key_, as_wcstr(relative_key_name), 0, access, &subkey);
+  LONG result = RegOpenKeyEx(key_, relative_key_name, 0, access, &subkey);
 
   // We have to close the current opened key before replacing it with the new
   // one.
@@ -221,9 +220,8 @@
   return key;
 }
 
-bool RegKey::HasValue(const char16* name) const {
-  return RegQueryValueEx(key_, as_wcstr(name), 0, NULL, NULL, NULL) ==
-         ERROR_SUCCESS;
+bool RegKey::HasValue(const wchar_t* name) const {
+  return RegQueryValueEx(key_, name, 0, NULL, NULL, NULL) == ERROR_SUCCESS;
 }
 
 DWORD RegKey::GetValueCount() const {
@@ -233,26 +231,25 @@
   return (result == ERROR_SUCCESS) ? count : 0;
 }
 
-LONG RegKey::GetValueNameAt(int index, string16* name) const {
-  char16 buf[256];
+LONG RegKey::GetValueNameAt(int index, std::wstring* name) const {
+  wchar_t buf[256];
   DWORD bufsize = size(buf);
-  LONG r = ::RegEnumValue(key_, index, as_writable_wcstr(buf), &bufsize, NULL,
-                          NULL, NULL, NULL);
+  LONG r = ::RegEnumValue(key_, index, buf, &bufsize, NULL, NULL, NULL, NULL);
   if (r == ERROR_SUCCESS)
     name->assign(buf, bufsize);
 
   return r;
 }
 
-LONG RegKey::DeleteKey(const char16* name) {
+LONG RegKey::DeleteKey(const wchar_t* name) {
   DCHECK(key_);
   DCHECK(name);
   HKEY subkey = NULL;
 
   // Verify the key exists before attempting delete to replicate previous
   // behavior.
-  LONG result = RegOpenKeyEx(key_, as_wcstr(name), 0,
-                             READ_CONTROL | wow64access_, &subkey);
+  LONG result =
+      RegOpenKeyEx(key_, name, 0, READ_CONTROL | wow64access_, &subkey);
   if (result != ERROR_SUCCESS)
     return result;
   RegCloseKey(subkey);
@@ -260,13 +257,13 @@
   return RegDelRecurse(key_, name, wow64access_);
 }
 
-LONG RegKey::DeleteEmptyKey(const char16* name) {
+LONG RegKey::DeleteEmptyKey(const wchar_t* name) {
   DCHECK(key_);
   DCHECK(name);
 
   HKEY target_key = NULL;
-  LONG result = RegOpenKeyEx(key_, as_wcstr(name), 0, KEY_READ | wow64access_,
-                             &target_key);
+  LONG result =
+      RegOpenKeyEx(key_, name, 0, KEY_READ | wow64access_, &target_key);
 
   if (result != ERROR_SUCCESS)
     return result;
@@ -281,18 +278,18 @@
     return result;
 
   if (count == 0)
-    return RegDeleteKeyEx(key_, as_wcstr(name), wow64access_, 0);
+    return RegDeleteKeyEx(key_, name, wow64access_, 0);
 
   return ERROR_DIR_NOT_EMPTY;
 }
 
-LONG RegKey::DeleteValue(const char16* value_name) {
+LONG RegKey::DeleteValue(const wchar_t* value_name) {
   DCHECK(key_);
-  LONG result = RegDeleteValue(key_, as_wcstr(value_name));
+  LONG result = RegDeleteValue(key_, value_name);
   return result;
 }
 
-LONG RegKey::ReadValueDW(const char16* name, DWORD* out_value) const {
+LONG RegKey::ReadValueDW(const wchar_t* name, DWORD* out_value) const {
   DCHECK(out_value);
   DWORD type = REG_DWORD;
   DWORD size = sizeof(DWORD);
@@ -308,7 +305,7 @@
   return result;
 }
 
-LONG RegKey::ReadInt64(const char16* name, int64_t* out_value) const {
+LONG RegKey::ReadInt64(const wchar_t* name, int64_t* out_value) const {
   DCHECK(out_value);
   DWORD type = REG_QWORD;
   int64_t local_value = 0;
@@ -325,20 +322,19 @@
   return result;
 }
 
-LONG RegKey::ReadValue(const char16* name, string16* out_value) const {
+LONG RegKey::ReadValue(const wchar_t* name, std::wstring* out_value) const {
   DCHECK(out_value);
   const size_t kMaxStringLength = 1024;  // This is after expansion.
   // Use the one of the other forms of ReadValue if 1024 is too small for you.
-  char16 raw_value[kMaxStringLength];
+  wchar_t raw_value[kMaxStringLength];
   DWORD type = REG_SZ, size = sizeof(raw_value);
-  LONG result = ReadValue(name, as_writable_wcstr(raw_value), &size, &type);
+  LONG result = ReadValue(name, raw_value, &size, &type);
   if (result == ERROR_SUCCESS) {
     if (type == REG_SZ) {
       *out_value = raw_value;
     } else if (type == REG_EXPAND_SZ) {
-      char16 expanded[kMaxStringLength];
-      size = ExpandEnvironmentStrings(
-          as_wcstr(raw_value), as_writable_wcstr(expanded), kMaxStringLength);
+      wchar_t expanded[kMaxStringLength];
+      size = ExpandEnvironmentStrings(raw_value, expanded, kMaxStringLength);
       // Success: returns the number of wchar_t's copied
       // Fail: buffer too small, returns the size required
       // Fail: other, returns 0
@@ -356,16 +352,17 @@
   return result;
 }
 
-LONG RegKey::ReadValue(const char16* name,
+LONG RegKey::ReadValue(const wchar_t* name,
                        void* data,
                        DWORD* dsize,
                        DWORD* dtype) const {
-  LONG result = RegQueryValueEx(key_, as_wcstr(name), 0, dtype,
+  LONG result = RegQueryValueEx(key_, name, 0, dtype,
                                 reinterpret_cast<LPBYTE>(data), dsize);
   return result;
 }
 
-LONG RegKey::ReadValues(const char16* name, std::vector<string16>* values) {
+LONG RegKey::ReadValues(const wchar_t* name,
+                        std::vector<std::wstring>* values) {
   values->clear();
 
   DWORD type = REG_MULTI_SZ;
@@ -377,8 +374,8 @@
   if (type != REG_MULTI_SZ)
     return ERROR_CANTREAD;
 
-  std::vector<char16> buffer(size / sizeof(char16));
-  result = ReadValue(name, as_writable_wcstr(buffer.data()), &size, NULL);
+  std::vector<wchar_t> buffer(size / sizeof(wchar_t));
+  result = ReadValue(name, buffer.data(), &size, NULL);
   if (result != ERROR_SUCCESS || size == 0)
     return result;
 
@@ -395,27 +392,27 @@
   return 0;
 }
 
-LONG RegKey::WriteValue(const char16* name, DWORD in_value) {
+LONG RegKey::WriteValue(const wchar_t* name, DWORD in_value) {
   return WriteValue(
       name, &in_value, static_cast<DWORD>(sizeof(in_value)), REG_DWORD);
 }
 
-LONG RegKey::WriteValue(const char16* name, const char16* in_value) {
+LONG RegKey::WriteValue(const wchar_t* name, const wchar_t* in_value) {
   return WriteValue(
       name, in_value,
       static_cast<DWORD>(sizeof(*in_value) *
-                         (std::char_traits<char16>::length(in_value) + 1)),
+                         (std::char_traits<wchar_t>::length(in_value) + 1)),
       REG_SZ);
 }
 
-LONG RegKey::WriteValue(const char16* name,
+LONG RegKey::WriteValue(const wchar_t* name,
                         const void* data,
                         DWORD dsize,
                         DWORD dtype) {
   DCHECK(data || !dsize);
 
   LONG result =
-      RegSetValueEx(key_, as_wcstr(name), 0, dtype,
+      RegSetValueEx(key_, name, 0, dtype,
                     reinterpret_cast<LPBYTE>(const_cast<void*>(data)), dsize);
   return result;
 }
@@ -431,22 +428,22 @@
 }
 
 // static
-LONG RegKey::RegDelRecurse(HKEY root_key, const char16* name, REGSAM access) {
+LONG RegKey::RegDelRecurse(HKEY root_key, const wchar_t* name, REGSAM access) {
   // First, see if the key can be deleted without having to recurse.
-  LONG result = RegDeleteKeyEx(root_key, as_wcstr(name), access, 0);
+  LONG result = RegDeleteKeyEx(root_key, name, access, 0);
   if (result == ERROR_SUCCESS)
     return result;
 
   HKEY target_key = NULL;
-  result = RegOpenKeyEx(root_key, as_wcstr(name), 0,
-                        KEY_ENUMERATE_SUB_KEYS | access, &target_key);
+  result = RegOpenKeyEx(root_key, name, 0, KEY_ENUMERATE_SUB_KEYS | access,
+                        &target_key);
 
   if (result == ERROR_FILE_NOT_FOUND)
     return ERROR_SUCCESS;
   if (result != ERROR_SUCCESS)
     return result;
 
-  string16 subkey_name(name);
+  std::wstring subkey_name(name);
 
   // Check for an ending slash and add one if it is missing.
   if (!subkey_name.empty() && subkey_name.back() != '\\')
@@ -456,12 +453,11 @@
   result = ERROR_SUCCESS;
   const DWORD kMaxKeyNameLength = MAX_PATH;
   const size_t base_key_length = subkey_name.length();
-  string16 key_name;
+  std::wstring key_name;
   while (result == ERROR_SUCCESS) {
     DWORD key_size = kMaxKeyNameLength;
     result =
-        RegEnumKeyEx(target_key, 0,
-                     as_writable_wcstr(WriteInto(&key_name, kMaxKeyNameLength)),
+        RegEnumKeyEx(target_key, 0, WriteIntoW(&key_name, kMaxKeyNameLength),
                      &key_size, NULL, NULL, NULL, NULL);
 
     if (result != ERROR_SUCCESS)
@@ -478,7 +474,7 @@
   RegCloseKey(target_key);
 
   // Try again to delete the key.
-  result = RegDeleteKeyEx(root_key, as_wcstr(name), access, 0);
+  result = RegDeleteKeyEx(root_key, name, access, 0);
 
   return result;
 }
@@ -486,24 +482,24 @@
 // RegistryValueIterator ------------------------------------------------------
 
 RegistryValueIterator::RegistryValueIterator(HKEY root_key,
-                                             const char16* folder_key,
+                                             const wchar_t* folder_key,
                                              REGSAM wow64access)
     : name_(MAX_PATH, '\0'), value_(MAX_PATH, '\0') {
   Initialize(root_key, folder_key, wow64access);
 }
 
 RegistryValueIterator::RegistryValueIterator(HKEY root_key,
-                                             const char16* folder_key)
+                                             const wchar_t* folder_key)
     : name_(MAX_PATH, '\0'), value_(MAX_PATH, '\0') {
   Initialize(root_key, folder_key, 0);
 }
 
 void RegistryValueIterator::Initialize(HKEY root_key,
-                                       const char16* folder_key,
+                                       const wchar_t* folder_key,
                                        REGSAM wow64access) {
   DCHECK_EQ(wow64access & ~kWow64AccessMask, static_cast<REGSAM>(0));
-  LONG result = RegOpenKeyEx(root_key, as_wcstr(folder_key), 0,
-                             KEY_READ | wow64access, &key_);
+  LONG result =
+      RegOpenKeyEx(root_key, folder_key, 0, KEY_READ | wow64access, &key_);
   if (result != ERROR_SUCCESS) {
     key_ = NULL;
   } else {
@@ -551,13 +547,10 @@
     DWORD capacity = static_cast<DWORD>(name_.capacity());
     DWORD name_size = capacity;
     // |value_size_| is in bytes. Reserve the last character for a NUL.
-    static_assert(sizeof(wchar_t) == sizeof(char16),
-                  "wchar_t is not the same size as base::char16");
     value_size_ = static_cast<DWORD>((value_.size() - 1) * sizeof(wchar_t));
     LONG result = ::RegEnumValue(
-        key_, index_, as_writable_wcstr(WriteInto(&name_, name_size)),
-        &name_size, NULL, &type_, reinterpret_cast<BYTE*>(value_.data()),
-        &value_size_);
+        key_, index_, WriteIntoW(&name_, name_size), &name_size, NULL, &type_,
+        reinterpret_cast<BYTE*>(value_.data()), &value_size_);
 
     if (result == ERROR_MORE_DATA) {
       // Registry key names are limited to 255 characters and fit within
@@ -572,9 +565,8 @@
       value_size_ = static_cast<DWORD>((value_.size() - 1) * sizeof(wchar_t));
       name_size = name_size == capacity ? MAX_REGISTRY_NAME_SIZE : capacity;
       result = ::RegEnumValue(
-          key_, index_, as_writable_wcstr(WriteInto(&name_, name_size)),
-          &name_size, NULL, &type_, reinterpret_cast<BYTE*>(value_.data()),
-          &value_size_);
+          key_, index_, WriteIntoW(&name_, name_size), &name_size, NULL, &type_,
+          reinterpret_cast<BYTE*>(value_.data()), &value_size_);
     }
 
     if (result == ERROR_SUCCESS) {
@@ -593,12 +585,12 @@
 // RegistryKeyIterator --------------------------------------------------------
 
 RegistryKeyIterator::RegistryKeyIterator(HKEY root_key,
-                                         const char16* folder_key) {
+                                         const wchar_t* folder_key) {
   Initialize(root_key, folder_key, 0);
 }
 
 RegistryKeyIterator::RegistryKeyIterator(HKEY root_key,
-                                         const char16* folder_key,
+                                         const wchar_t* folder_key,
                                          REGSAM wow64access) {
   Initialize(root_key, folder_key, wow64access);
 }
@@ -631,8 +623,8 @@
   if (Valid()) {
     DWORD ncount = static_cast<DWORD>(size(name_));
     FILETIME written;
-    LONG r = ::RegEnumKeyEx(key_, index_, as_writable_wcstr(name_), &ncount,
-                            NULL, NULL, NULL, &written);
+    LONG r = ::RegEnumKeyEx(key_, index_, name_, &ncount, NULL, NULL, NULL,
+                            &written);
     if (ERROR_SUCCESS == r)
       return true;
   }
@@ -642,11 +634,11 @@
 }
 
 void RegistryKeyIterator::Initialize(HKEY root_key,
-                                     const char16* folder_key,
+                                     const wchar_t* folder_key,
                                      REGSAM wow64access) {
   DCHECK_EQ(wow64access & ~kWow64AccessMask, static_cast<REGSAM>(0));
-  LONG result = RegOpenKeyEx(root_key, as_wcstr(folder_key), 0,
-                             KEY_READ | wow64access, &key_);
+  LONG result =
+      RegOpenKeyEx(root_key, folder_key, 0, KEY_READ | wow64access, &key_);
   if (result != ERROR_SUCCESS) {
     key_ = NULL;
   } else {
diff --git a/base/win/registry.h b/base/win/registry.h
index 1c57fc9..f772821 100644
--- a/base/win/registry.h
+++ b/base/win/registry.h
@@ -8,12 +8,12 @@
 #include <stdint.h>
 
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "base/base_export.h"
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/strings/string16.h"
 #include "base/win/object_watcher.h"
 #include "base/win/scoped_handle.h"
 #include "base/win/windows_types.h"
@@ -37,24 +37,24 @@
 
   RegKey();
   explicit RegKey(HKEY key);
-  RegKey(HKEY rootkey, const char16* subkey, REGSAM access);
+  RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access);
   ~RegKey();
 
-  LONG Create(HKEY rootkey, const char16* subkey, REGSAM access);
+  LONG Create(HKEY rootkey, const wchar_t* subkey, REGSAM access);
 
   LONG CreateWithDisposition(HKEY rootkey,
-                             const char16* subkey,
+                             const wchar_t* subkey,
                              DWORD* disposition,
                              REGSAM access);
 
   // Creates a subkey or open it if it already exists.
-  LONG CreateKey(const char16* name, REGSAM access);
+  LONG CreateKey(const wchar_t* name, REGSAM access);
 
   // Opens an existing reg key.
-  LONG Open(HKEY rootkey, const char16* subkey, REGSAM access);
+  LONG Open(HKEY rootkey, const wchar_t* subkey, REGSAM access);
 
   // Opens an existing reg key, given the relative key name.
-  LONG OpenKey(const char16* relative_key_name, REGSAM access);
+  LONG OpenKey(const wchar_t* relative_key_name, REGSAM access);
 
   // Closes this reg key.
   void Close();
@@ -67,51 +67,51 @@
 
   // Returns false if this key does not have the specified value, or if an error
   // occurrs while attempting to access it.
-  bool HasValue(const char16* value_name) const;
+  bool HasValue(const wchar_t* value_name) const;
 
   // Returns the number of values for this key, or 0 if the number cannot be
   // determined.
   DWORD GetValueCount() const;
 
   // Determines the nth value's name.
-  LONG GetValueNameAt(int index, string16* name) const;
+  LONG GetValueNameAt(int index, std::wstring* name) const;
 
   // True while the key is valid.
   bool Valid() const { return key_ != NULL; }
 
   // Kills a key and everything that lives below it; please be careful when
   // using it.
-  LONG DeleteKey(const char16* name);
+  LONG DeleteKey(const wchar_t* name);
 
   // Deletes an empty subkey.  If the subkey has subkeys or values then this
   // will fail.
-  LONG DeleteEmptyKey(const char16* name);
+  LONG DeleteEmptyKey(const wchar_t* name);
 
   // Deletes a single value within the key.
-  LONG DeleteValue(const char16* name);
+  LONG DeleteValue(const wchar_t* name);
 
   // Getters:
 
   // Reads a REG_DWORD (uint32_t) into |out_value|. If |name| is null or empty,
   // reads the key's default value, if any.
-  LONG ReadValueDW(const char16* name, DWORD* out_value) const;
+  LONG ReadValueDW(const wchar_t* name, DWORD* out_value) const;
 
   // Reads a REG_QWORD (int64_t) into |out_value|. If |name| is null or empty,
   // reads the key's default value, if any.
-  LONG ReadInt64(const char16* name, int64_t* out_value) const;
+  LONG ReadInt64(const wchar_t* name, int64_t* out_value) const;
 
   // Reads a string into |out_value|. If |name| is null or empty, reads
   // the key's default value, if any.
-  LONG ReadValue(const char16* name, string16* out_value) const;
+  LONG ReadValue(const wchar_t* name, std::wstring* out_value) const;
 
   // Reads a REG_MULTI_SZ registry field into a vector of strings. Clears
   // |values| initially and adds further strings to the list. Returns
   // ERROR_CANTREAD if type is not REG_MULTI_SZ.
-  LONG ReadValues(const char16* name, std::vector<string16>* values);
+  LONG ReadValues(const wchar_t* name, std::vector<std::wstring>* values);
 
   // Reads raw data into |data|. If |name| is null or empty, reads the key's
   // default value, if any.
-  LONG ReadValue(const char16* name,
+  LONG ReadValue(const wchar_t* name,
                  void* data,
                  DWORD* dsize,
                  DWORD* dtype) const;
@@ -119,13 +119,13 @@
   // Setters:
 
   // Sets an int32_t value.
-  LONG WriteValue(const char16* name, DWORD in_value);
+  LONG WriteValue(const wchar_t* name, DWORD in_value);
 
   // Sets a string value.
-  LONG WriteValue(const char16* name, const char16* in_value);
+  LONG WriteValue(const wchar_t* name, const wchar_t* in_value);
 
   // Sets raw data, including type.
-  LONG WriteValue(const char16* name,
+  LONG WriteValue(const wchar_t* name,
                   const void* data,
                   DWORD dsize,
                   DWORD dtype);
@@ -143,7 +143,7 @@
   class Watcher;
 
   // Recursively deletes a key and all of its subkeys.
-  static LONG RegDelRecurse(HKEY root_key, const char16* name, REGSAM access);
+  static LONG RegDelRecurse(HKEY root_key, const wchar_t* name, REGSAM access);
 
   HKEY key_;  // The registry key being iterated.
   REGSAM wow64access_;
@@ -156,7 +156,7 @@
 class BASE_EXPORT RegistryValueIterator {
  public:
   // Constructs a Registry Value Iterator with default WOW64 access.
-  RegistryValueIterator(HKEY root_key, const char16* folder_key);
+  RegistryValueIterator(HKEY root_key, const wchar_t* folder_key);
 
   // Constructs a Registry Key Iterator with specific WOW64 access, one of
   // KEY_WOW64_32KEY or KEY_WOW64_64KEY, or 0.
@@ -164,7 +164,7 @@
   // previously, or a predefined key (e.g. HKEY_LOCAL_MACHINE).
   // See http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129.aspx.
   RegistryValueIterator(HKEY root_key,
-                        const char16* folder_key,
+                        const wchar_t* folder_key,
                         REGSAM wow64access);
 
   ~RegistryValueIterator();
@@ -177,8 +177,8 @@
   // Advances to the next registry entry.
   void operator++();
 
-  const char16* Name() const { return name_.c_str(); }
-  const char16* Value() const { return value_.data(); }
+  const wchar_t* Name() const { return name_.c_str(); }
+  const wchar_t* Value() const { return value_.data(); }
   // ValueSize() is in bytes.
   DWORD ValueSize() const { return value_size_; }
   DWORD Type() const { return type_; }
@@ -189,7 +189,7 @@
   // Reads in the current values.
   bool Read();
 
-  void Initialize(HKEY root_key, const char16* folder_key, REGSAM wow64access);
+  void Initialize(HKEY root_key, const wchar_t* folder_key, REGSAM wow64access);
 
   // The registry key being iterated.
   HKEY key_;
@@ -198,8 +198,8 @@
   int index_;
 
   // Current values.
-  string16 name_;
-  std::vector<char16> value_;
+  std::wstring name_;
+  std::vector<wchar_t> value_;
   DWORD value_size_;
   DWORD type_;
 
@@ -209,7 +209,7 @@
 class BASE_EXPORT RegistryKeyIterator {
  public:
   // Constructs a Registry Key Iterator with default WOW64 access.
-  RegistryKeyIterator(HKEY root_key, const char16* folder_key);
+  RegistryKeyIterator(HKEY root_key, const wchar_t* folder_key);
 
   // Constructs a Registry Value Iterator with specific WOW64 access, one of
   // KEY_WOW64_32KEY or KEY_WOW64_64KEY, or 0.
@@ -217,7 +217,7 @@
   // previously, or a predefined key (e.g. HKEY_LOCAL_MACHINE).
   // See http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129.aspx.
   RegistryKeyIterator(HKEY root_key,
-                      const char16* folder_key,
+                      const wchar_t* folder_key,
                       REGSAM wow64access);
 
   ~RegistryKeyIterator();
@@ -230,7 +230,7 @@
   // Advances to the next entry in the folder.
   void operator++();
 
-  const char16* Name() const { return name_; }
+  const wchar_t* Name() const { return name_; }
 
   int Index() const { return index_; }
 
@@ -238,7 +238,7 @@
   // Reads in the current values.
   bool Read();
 
-  void Initialize(HKEY root_key, const char16* folder_key, REGSAM wow64access);
+  void Initialize(HKEY root_key, const wchar_t* folder_key, REGSAM wow64access);
 
   // The registry key being iterated.
   HKEY key_;
@@ -246,7 +246,7 @@
   // Current index of the iteration.
   int index_;
 
-  char16 name_[MAX_PATH];
+  wchar_t name_[MAX_PATH];
 
   DISALLOW_COPY_AND_ASSIGN(RegistryKeyIterator);
 };
diff --git a/base/win/registry_unittest.cc b/base/win/registry_unittest.cc
index 12ebc00..50be1d32 100644
--- a/base/win/registry_unittest.cc
+++ b/base/win/registry_unittest.cc
@@ -23,7 +23,7 @@
 
 namespace {
 
-const char16 kRootKey[] = STRING16_LITERAL("Base_Registry_Unittest");
+const wchar_t kRootKey[] = L"Base_Registry_Unittest";
 
 class RegistryTest : public testing::Test {
  protected:
@@ -38,18 +38,18 @@
   RegistryTest() {}
   void SetUp() override {
     // Create a temporary key.
-    RegKey key(HKEY_CURRENT_USER, STRING16_LITERAL(""), KEY_ALL_ACCESS);
+    RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS);
     key.DeleteKey(kRootKey);
     ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
     ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, kRootKey, KEY_READ));
-    foo_software_key_ = STRING16_LITERAL("Software\\");
+    foo_software_key_ = L"Software\\";
     foo_software_key_ += kRootKey;
-    foo_software_key_ += STRING16_LITERAL("\\Foo");
+    foo_software_key_ += L"\\Foo";
   }
 
   void TearDown() override {
     // Clean up the temporary key.
-    RegKey key(HKEY_CURRENT_USER, STRING16_LITERAL(""), KEY_SET_VALUE);
+    RegKey key(HKEY_CURRENT_USER, L"", KEY_SET_VALUE);
     ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
     ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
   }
@@ -62,7 +62,7 @@
 #endif
   }
 
-  string16 foo_software_key_;
+  std::wstring foo_software_key_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(RegistryTest);
@@ -75,8 +75,8 @@
 TEST_F(RegistryTest, ValueTest) {
   RegKey key;
 
-  string16 foo_key(kRootKey);
-  foo_key += STRING16_LITERAL("\\Foo");
+  std::wstring foo_key(kRootKey);
+  foo_key += L"\\Foo";
   ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
                                       KEY_READ));
 
@@ -85,10 +85,10 @@
                                       KEY_READ | KEY_SET_VALUE));
     ASSERT_TRUE(key.Valid());
 
-    const char16 kStringValueName[] = STRING16_LITERAL("StringValue");
-    const char16 kDWORDValueName[] = STRING16_LITERAL("DWORDValue");
-    const char16 kInt64ValueName[] = STRING16_LITERAL("Int64Value");
-    const char16 kStringData[] = STRING16_LITERAL("string data");
+    const wchar_t kStringValueName[] = L"StringValue";
+    const wchar_t kDWORDValueName[] = L"DWORDValue";
+    const wchar_t kInt64ValueName[] = L"Int64Value";
+    const wchar_t kStringData[] = L"string data";
     const DWORD kDWORDData = 0xdeadbabe;
     const int64_t kInt64Data = 0xdeadbabedeadbabeLL;
 
@@ -103,7 +103,7 @@
     EXPECT_TRUE(key.HasValue(kInt64ValueName));
 
     // Test Read
-    string16 string_value;
+    std::wstring string_value;
     DWORD dword_value = 0;
     int64_t int64_value = 0;
     ASSERT_EQ(ERROR_SUCCESS, key.ReadValue(kStringValueName, &string_value));
@@ -114,7 +114,7 @@
     EXPECT_EQ(kInt64Data, int64_value);
 
     // Make sure out args are not touched if ReadValue fails
-    const char16* kNonExistent = STRING16_LITERAL("NonExistent");
+    const wchar_t* kNonExistent = L"NonExistent";
     ASSERT_NE(ERROR_SUCCESS, key.ReadValue(kNonExistent, &string_value));
     ASSERT_NE(ERROR_SUCCESS, key.ReadValueDW(kNonExistent, &dword_value));
     ASSERT_NE(ERROR_SUCCESS, key.ReadInt64(kNonExistent, &int64_value));
@@ -135,8 +135,8 @@
 
 TEST_F(RegistryTest, BigValueIteratorTest) {
   RegKey key;
-  string16 foo_key(kRootKey);
-  foo_key += STRING16_LITERAL("\\Foo");
+  std::wstring foo_key(kRootKey);
+  foo_key += L"\\Foo";
   ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
                                       KEY_READ));
   ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
@@ -144,7 +144,7 @@
   ASSERT_TRUE(key.Valid());
 
   // Create a test value that is larger than MAX_PATH.
-  string16 data(MAX_PATH * 2, 'a');
+  std::wstring data(MAX_PATH * 2, 'a');
 
   ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(data.c_str(), data.c_str()));
 
@@ -153,23 +153,23 @@
   EXPECT_EQ(data, iterator.Name());
   EXPECT_EQ(data, iterator.Value());
   // ValueSize() is in bytes, including NUL.
-  EXPECT_EQ((MAX_PATH * 2 + 1) * sizeof(char16), iterator.ValueSize());
+  EXPECT_EQ((MAX_PATH * 2 + 1) * sizeof(wchar_t), iterator.ValueSize());
   ++iterator;
   EXPECT_FALSE(iterator.Valid());
 }
 
 TEST_F(RegistryTest, TruncatedCharTest) {
   RegKey key;
-  string16 foo_key(kRootKey);
-  foo_key += STRING16_LITERAL("\\Foo");
+  std::wstring foo_key(kRootKey);
+  foo_key += L"\\Foo";
   ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
                                       KEY_READ));
   ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
                                     KEY_READ | KEY_SET_VALUE));
   ASSERT_TRUE(key.Valid());
 
-  const char16 kName[] = STRING16_LITERAL("name");
-  // kData size is not a multiple of sizeof(char16).
+  const wchar_t kName[] = L"name";
+  // kData size is not a multiple of sizeof(wchar_t).
   const uint8_t kData[] = {1, 2, 3, 4, 5};
   EXPECT_EQ(5u, size(kData));
   ASSERT_EQ(ERROR_SUCCESS,
@@ -179,11 +179,11 @@
   ASSERT_TRUE(iterator.Valid());
   // Avoid having to use EXPECT_STREQ here by leveraging StringPiece's
   // operator== to perform a deep comparison.
-  EXPECT_EQ(StringPiece16(kName), StringPiece16(iterator.Name()));
+  EXPECT_EQ(WStringPiece(kName), WStringPiece(iterator.Name()));
   // ValueSize() is in bytes.
   ASSERT_EQ(size(kData), iterator.ValueSize());
   // Value() is NUL terminated.
-  int end = (iterator.ValueSize() + sizeof(char16) - 1) / sizeof(char16);
+  int end = (iterator.ValueSize() + sizeof(wchar_t) - 1) / sizeof(wchar_t);
   EXPECT_NE('\0', iterator.Value()[end - 1]);
   EXPECT_EQ('\0', iterator.Value()[end]);
   EXPECT_EQ(0, std::memcmp(kData, iterator.Value(), size(kData)));
@@ -201,50 +201,47 @@
   //                  \->Moo
   //                  \->Foo
   // and delete kRootKey->Foo
-  string16 foo_key(kRootKey);
-  foo_key += STRING16_LITERAL("\\Foo");
+  std::wstring foo_key(kRootKey);
+  foo_key += L"\\Foo";
   ASSERT_EQ(ERROR_SUCCESS,
             key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
-  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(STRING16_LITERAL("Bar"), KEY_WRITE));
-  ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(STRING16_LITERAL("TestValue"),
-                                          STRING16_LITERAL("TestData")));
+  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE));
+  ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
   ASSERT_EQ(ERROR_SUCCESS,
             key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
-  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(STRING16_LITERAL("Moo"), KEY_WRITE));
+  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Moo", KEY_WRITE));
   ASSERT_EQ(ERROR_SUCCESS,
             key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
-  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(STRING16_LITERAL("Foo"), KEY_WRITE));
-  foo_key += STRING16_LITERAL("\\Bar");
+  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
+  foo_key += L"\\Bar";
   ASSERT_EQ(ERROR_SUCCESS,
             key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
-  foo_key += STRING16_LITERAL("\\Foo");
-  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(STRING16_LITERAL("Foo"), KEY_WRITE));
-  ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(STRING16_LITERAL("TestValue"),
-                                          STRING16_LITERAL("TestData")));
+  foo_key += L"\\Foo";
+  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
+  ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
   ASSERT_EQ(ERROR_SUCCESS,
             key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
 
   ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
-  ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(STRING16_LITERAL("Bar")));
-  ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(STRING16_LITERAL("Foo")));
-  ASSERT_NE(ERROR_SUCCESS,
-            key.DeleteEmptyKey(STRING16_LITERAL("Foo\\Bar\\Foo")));
-  ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(STRING16_LITERAL("Foo\\Bar")));
-  ASSERT_EQ(ERROR_SUCCESS, key.DeleteEmptyKey(STRING16_LITERAL("Foo\\Foo")));
+  ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"Bar"));
+  ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo"));
+  ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Bar\\Foo"));
+  ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Bar"));
+  ASSERT_EQ(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Foo"));
 
   ASSERT_EQ(ERROR_SUCCESS,
             key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
-  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(STRING16_LITERAL("Bar"), KEY_WRITE));
-  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(STRING16_LITERAL("Foo"), KEY_WRITE));
+  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE));
+  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
   ASSERT_EQ(ERROR_SUCCESS,
             key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
-  ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(STRING16_LITERAL("")));
+  ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L""));
   ASSERT_NE(ERROR_SUCCESS,
             key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
 
   ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
-  ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(STRING16_LITERAL("Foo")));
-  ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(STRING16_LITERAL("Foo")));
+  ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"Foo"));
+  ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"Foo"));
   ASSERT_NE(ERROR_SUCCESS,
             key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
 }
@@ -273,18 +270,15 @@
 
   // Open the non-redirected view of the parent and try to delete the test key.
   ASSERT_EQ(ERROR_SUCCESS,
-            key.Open(HKEY_LOCAL_MACHINE, STRING16_LITERAL("Software"),
-                     KEY_SET_VALUE));
+            key.Open(HKEY_LOCAL_MACHINE, L"Software", KEY_SET_VALUE));
   ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
-  ASSERT_EQ(ERROR_SUCCESS,
-            key.Open(HKEY_LOCAL_MACHINE, STRING16_LITERAL("Software"),
-                     KEY_SET_VALUE | kNativeViewMask));
+  ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software",
+                                    KEY_SET_VALUE | kNativeViewMask));
   ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
 
   // Open the redirected view and delete the key created above.
-  ASSERT_EQ(ERROR_SUCCESS,
-            key.Open(HKEY_LOCAL_MACHINE, STRING16_LITERAL("Software"),
-                     KEY_SET_VALUE | kRedirectedViewMask));
+  ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software",
+                                    KEY_SET_VALUE | kRedirectedViewMask));
   ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
 }
 
@@ -294,13 +288,11 @@
 TEST_F(RegistryTest, SameWowFlags) {
   RegKey key;
 
+  ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software",
+                                    KEY_READ | KEY_WOW64_64KEY));
   ASSERT_EQ(ERROR_SUCCESS,
-            key.Open(HKEY_LOCAL_MACHINE, STRING16_LITERAL("Software"),
-                     KEY_READ | KEY_WOW64_64KEY));
-  ASSERT_EQ(ERROR_SUCCESS, key.OpenKey(STRING16_LITERAL("Microsoft"),
-                                       KEY_READ | KEY_WOW64_64KEY));
-  ASSERT_EQ(ERROR_SUCCESS, key.OpenKey(STRING16_LITERAL("Windows"),
-                                       KEY_READ | KEY_WOW64_64KEY));
+            key.OpenKey(L"Microsoft", KEY_READ | KEY_WOW64_64KEY));
+  ASSERT_EQ(ERROR_SUCCESS, key.OpenKey(L"Windows", KEY_READ | KEY_WOW64_64KEY));
 }
 
 // TODO(wfh): flaky test on Vista.  See http://crbug.com/377917
@@ -323,14 +315,12 @@
 
   // Open the redirected view of the parent and try to delete the test key
   // from the non-redirected view.
-  ASSERT_EQ(ERROR_SUCCESS,
-            key.Open(HKEY_LOCAL_MACHINE, STRING16_LITERAL("Software"),
-                     KEY_SET_VALUE | kRedirectedViewMask));
+  ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software",
+                                    KEY_SET_VALUE | kRedirectedViewMask));
   ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
 
-  ASSERT_EQ(ERROR_SUCCESS,
-            key.Open(HKEY_LOCAL_MACHINE, STRING16_LITERAL("Software"),
-                     KEY_SET_VALUE | kNativeViewMask));
+  ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software",
+                                    KEY_SET_VALUE | kNativeViewMask));
   ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
 }
 
@@ -341,18 +331,18 @@
                      kRootKey,
                      KEY_READ | KEY_CREATE_SUB_KEY));
 
-  ASSERT_NE(ERROR_SUCCESS, key.OpenKey(STRING16_LITERAL("foo"), KEY_READ));
-  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(STRING16_LITERAL("foo"), KEY_READ));
+  ASSERT_NE(ERROR_SUCCESS, key.OpenKey(L"foo", KEY_READ));
+  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"foo", KEY_READ));
   ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
-  ASSERT_EQ(ERROR_SUCCESS, key.OpenKey(STRING16_LITERAL("foo"), KEY_READ));
+  ASSERT_EQ(ERROR_SUCCESS, key.OpenKey(L"foo", KEY_READ));
 
-  string16 foo_key(kRootKey);
-  foo_key += STRING16_LITERAL("\\Foo");
+  std::wstring foo_key(kRootKey);
+  foo_key += L"\\Foo";
   ASSERT_EQ(ERROR_SUCCESS,
             key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
 
   ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
-  ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(STRING16_LITERAL("foo")));
+  ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"foo"));
 }
 
 class TestChangeDelegate {
@@ -380,8 +370,8 @@
   TestChangeDelegate delegate;
   test::TaskEnvironment task_environment;
 
-  string16 foo_key(kRootKey);
-  foo_key += STRING16_LITERAL("\\Foo");
+  std::wstring foo_key(kRootKey);
+  foo_key += L"\\Foo";
   ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
                                       KEY_READ));
 
@@ -394,8 +384,7 @@
   ASSERT_EQ(ERROR_SUCCESS, key2.Open(HKEY_CURRENT_USER, foo_key.c_str(),
                                       KEY_READ | KEY_SET_VALUE));
   ASSERT_TRUE(key2.Valid());
-  EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(STRING16_LITERAL("name"),
-                                           STRING16_LITERAL("data")));
+  EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(L"name", L"data"));
 
   // Allow delivery of the notification.
   EXPECT_FALSE(delegate.WasCalled());
@@ -408,8 +397,7 @@
       BindRepeating(&TestChangeDelegate::OnKeyChanged, Unretained(&delegate))));
 
   // Change something else.
-  EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(STRING16_LITERAL("name2"),
-                                           STRING16_LITERAL("data2")));
+  EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(L"name2", L"data2"));
   RunLoop().Run();
   ASSERT_TRUE(delegate.WasCalled());
 
diff --git a/base/win/scoped_bstr.cc b/base/win/scoped_bstr.cc
index dc68cba..94d7d08 100644
--- a/base/win/scoped_bstr.cc
+++ b/base/win/scoped_bstr.cc
@@ -16,8 +16,8 @@
 
 namespace {
 
-BSTR AllocBstrOrDie(StringPiece16 non_bstr) {
-  BSTR result = ::SysAllocStringLen(as_wcstr(non_bstr),
+BSTR AllocBstrOrDie(WStringPiece non_bstr) {
+  BSTR result = ::SysAllocStringLen(non_bstr.data(),
                                     checked_cast<UINT>(non_bstr.length()));
   if (!result) {
     base::TerminateBecauseOutOfMemory((non_bstr.length() + 1) *
@@ -35,7 +35,7 @@
 
 }  // namespace
 
-ScopedBstr::ScopedBstr(StringPiece16 non_bstr)
+ScopedBstr::ScopedBstr(WStringPiece non_bstr)
     : bstr_(AllocBstrOrDie(non_bstr)) {}
 
 ScopedBstr::~ScopedBstr() {
@@ -68,7 +68,7 @@
   return &bstr_;
 }
 
-BSTR ScopedBstr::Allocate(StringPiece16 str) {
+BSTR ScopedBstr::Allocate(WStringPiece str) {
   Reset(AllocBstrOrDie(str));
   return bstr_;
 }
diff --git a/base/win/scoped_bstr.h b/base/win/scoped_bstr.h
index 658e815..a3d3684 100644
--- a/base/win/scoped_bstr.h
+++ b/base/win/scoped_bstr.h
@@ -12,7 +12,6 @@
 #include "base/base_export.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/strings/string16.h"
 #include "base/strings/string_piece.h"
 
 namespace base {
@@ -28,7 +27,7 @@
   //
   // NOTE: Do not pass a BSTR to this constructor expecting ownership to
   // be transferred - even though it compiles! ;-)
-  explicit ScopedBstr(StringPiece16 non_bstr);
+  explicit ScopedBstr(WStringPiece non_bstr);
   ~ScopedBstr();
 
   // Give ScopedBstr ownership over an already allocated BSTR or null.
@@ -44,7 +43,7 @@
   // ScopedBstr instance, call |reset| instead.
   //
   // Returns a pointer to the new BSTR.
-  BSTR Allocate(StringPiece16 str);
+  BSTR Allocate(WStringPiece str);
 
   // Allocates a new BSTR with the specified number of bytes.
   // Returns a pointer to the new BSTR.
diff --git a/base/win/scoped_bstr_unittest.cc b/base/win/scoped_bstr_unittest.cc
index 1be543e..66cb0bd 100644
--- a/base/win/scoped_bstr_unittest.cc
+++ b/base/win/scoped_bstr_unittest.cc
@@ -7,8 +7,6 @@
 #include <stddef.h>
 
 #include "base/stl_util.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
@@ -16,8 +14,8 @@
 
 namespace {
 
-static const char16 kTestString1[] = STRING16_LITERAL("123");
-static const char16 kTestString2[] = STRING16_LITERAL("456789");
+static const wchar_t kTestString1[] = L"123";
+static const wchar_t kTestString2[] = L"456789";
 size_t test1_len = size(kTestString1) - 1;
 size_t test2_len = size(kTestString2) - 1;
 
@@ -35,7 +33,7 @@
 }
 
 void GiveMeABstr(BSTR* ret) {
-  *ret = SysAllocString(as_wcstr(kTestString1));
+  *ret = SysAllocString(kTestString1);
 }
 
 void BasicBstrTests() {
@@ -47,10 +45,10 @@
   b1.Swap(b2);
   EXPECT_EQ(test1_len, b2.Length());
   EXPECT_EQ(0u, b1.Length());
-  EXPECT_STREQ(b2, as_wcstr(kTestString1));
+  EXPECT_STREQ(b2, kTestString1);
   BSTR tmp = b2.Release();
   EXPECT_TRUE(tmp != NULL);
-  EXPECT_STREQ(tmp, as_wcstr(kTestString1));
+  EXPECT_STREQ(tmp, kTestString1);
   EXPECT_TRUE(b2 == NULL);
   SysFreeString(tmp);
 
@@ -60,7 +58,7 @@
   EXPECT_TRUE(b2.AllocateBytes(100) != NULL);
   EXPECT_EQ(100u, b2.ByteLength());
   EXPECT_EQ(100 / sizeof(kTestString1[0]), b2.Length());
-  lstrcpy(static_cast<BSTR>(b2), as_wcstr(kTestString1));
+  lstrcpy(static_cast<BSTR>(b2), kTestString1);
   EXPECT_EQ(test1_len, static_cast<size_t>(lstrlen(b2)));
   EXPECT_EQ(100 / sizeof(kTestString1[0]), b2.Length());
   b2.SetByteLen(lstrlen(b2) * sizeof(kTestString2[0]));
diff --git a/base/win/shortcut.cc b/base/win/shortcut.cc
index 289f5e6..5d9f1027 100644
--- a/base/win/shortcut.cc
+++ b/base/win/shortcut.cc
@@ -115,7 +115,7 @@
   }
 
   if (properties.options & ShortcutProperties::PROPERTIES_ARGUMENTS) {
-    if (FAILED(i_shell_link->SetArguments(as_wcstr(properties.arguments))))
+    if (FAILED(i_shell_link->SetArguments(properties.arguments.c_str())))
       return false;
   } else if (old_i_persist_file.Get()) {
     wchar_t current_arguments[MAX_PATH] = {0};
@@ -126,7 +126,7 @@
   }
 
   if ((properties.options & ShortcutProperties::PROPERTIES_DESCRIPTION) &&
-      FAILED(i_shell_link->SetDescription(as_wcstr(properties.description)))) {
+      FAILED(i_shell_link->SetDescription(properties.description.c_str()))) {
     return false;
   }
 
@@ -225,42 +225,39 @@
   // Reset |properties|.
   properties->options = 0;
 
-  char16 temp[MAX_PATH];
+  wchar_t temp[MAX_PATH];
   if (options & ShortcutProperties::PROPERTIES_TARGET) {
-    if (FAILED(i_shell_link->GetPath(as_writable_wcstr(temp), MAX_PATH, NULL,
-                                     SLGP_UNCPRIORITY))) {
+    if (FAILED(i_shell_link->GetPath(temp, MAX_PATH, NULL, SLGP_UNCPRIORITY))) {
       return false;
     }
-    properties->set_target(FilePath(temp));
+    properties->set_target(FilePath(AsStringPiece16(temp)));
   }
 
   if (options & ShortcutProperties::PROPERTIES_WORKING_DIR) {
-    if (FAILED(i_shell_link->GetWorkingDirectory(as_writable_wcstr(temp),
-                                                 MAX_PATH)))
+    if (FAILED(i_shell_link->GetWorkingDirectory(temp, MAX_PATH)))
       return false;
-    properties->set_working_dir(FilePath(temp));
+    properties->set_working_dir(FilePath(AsStringPiece16(temp)));
   }
 
   if (options & ShortcutProperties::PROPERTIES_ARGUMENTS) {
-    if (FAILED(i_shell_link->GetArguments(as_writable_wcstr(temp), MAX_PATH)))
+    if (FAILED(i_shell_link->GetArguments(temp, MAX_PATH)))
       return false;
     properties->set_arguments(temp);
   }
 
   if (options & ShortcutProperties::PROPERTIES_DESCRIPTION) {
     // Note: description length constrained by MAX_PATH.
-    if (FAILED(i_shell_link->GetDescription(as_writable_wcstr(temp), MAX_PATH)))
+    if (FAILED(i_shell_link->GetDescription(temp, MAX_PATH)))
       return false;
     properties->set_description(temp);
   }
 
   if (options & ShortcutProperties::PROPERTIES_ICON) {
     int temp_index;
-    if (FAILED(i_shell_link->GetIconLocation(as_writable_wcstr(temp), MAX_PATH,
-                                             &temp_index))) {
+    if (FAILED(i_shell_link->GetIconLocation(temp, MAX_PATH, &temp_index))) {
       return false;
     }
-    properties->set_icon(FilePath(temp), temp_index);
+    properties->set_icon(FilePath(AsStringPiece16(temp)), temp_index);
   }
 
   if (options & (ShortcutProperties::PROPERTIES_APP_ID |
@@ -278,10 +275,10 @@
       }
       switch (pv_app_id.get().vt) {
         case VT_EMPTY:
-          properties->set_app_id(string16());
+          properties->set_app_id(std::wstring());
           break;
         case VT_LPWSTR:
-          properties->set_app_id(WideToUTF16(pv_app_id.get().pwszVal));
+          properties->set_app_id(pv_app_id.get().pwszVal);
           break;
         default:
           NOTREACHED() << "Unexpected variant type: " << pv_app_id.get().vt;
@@ -336,7 +333,7 @@
 
 bool ResolveShortcut(const FilePath& shortcut_path,
                      FilePath* target_path,
-                     string16* args) {
+                     std::wstring* args) {
   uint32_t options = 0;
   if (target_path)
     options |= ShortcutProperties::PROPERTIES_TARGET;
diff --git a/base/win/shortcut.h b/base/win/shortcut.h
index 38c12b7..9f656ad 100644
--- a/base/win/shortcut.h
+++ b/base/win/shortcut.h
@@ -11,7 +11,6 @@
 #include "base/base_export.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
-#include "base/strings/string16.h"
 
 namespace base {
 namespace win {
@@ -62,14 +61,14 @@
     options |= PROPERTIES_WORKING_DIR;
   }
 
-  void set_arguments(const string16& arguments_in) {
+  void set_arguments(const std::wstring& arguments_in) {
     // Size restriction as per MSDN at http://goo.gl/TJ7q5.
     DCHECK(arguments_in.size() < MAX_PATH);
     arguments = arguments_in;
     options |= PROPERTIES_ARGUMENTS;
   }
 
-  void set_description(const string16& description_in) {
+  void set_description(const std::wstring& description_in) {
     // Size restriction as per MSDN at http://goo.gl/OdNQq.
     DCHECK(description_in.size() < MAX_PATH);
     description = description_in;
@@ -82,7 +81,7 @@
     options |= PROPERTIES_ICON;
   }
 
-  void set_app_id(const string16& app_id_in) {
+  void set_app_id(const std::wstring& app_id_in) {
     app_id = app_id_in;
     options |= PROPERTIES_APP_ID;
   }
@@ -104,16 +103,16 @@
   FilePath working_dir;
   // The arguments to be applied to |target| when launching from this shortcut.
   // The length of this string must be less than MAX_PATH.
-  string16 arguments;
+  std::wstring arguments;
   // The localized description of the shortcut.
   // The length of this string must be less than MAX_PATH.
-  string16 description;
+  std::wstring description;
   // The path to the icon (can be a dll or exe, in which case |icon_index| is
   // the resource id).
   FilePath icon;
   int icon_index;
   // The app model id for the shortcut.
-  string16 app_id;
+  std::wstring app_id;
   // Whether this is a dual mode shortcut (Win8+).
   bool dual_mode;
   // The CLSID of the COM object registered with the OS via the shortcut. This
@@ -159,7 +158,7 @@
 // |shortcut_path| and |target_path|.
 BASE_EXPORT bool ResolveShortcut(const FilePath& shortcut_path,
                                  FilePath* target_path,
-                                 string16* args);
+                                 std::wstring* args);
 
 // Pin to taskbar is only supported on Windows 7 and Windows 8. Returns true on
 // those platforms.
diff --git a/base/win/shortcut_unittest.cc b/base/win/shortcut_unittest.cc
index 992c1b1..76c80dcf 100644
--- a/base/win/shortcut_unittest.cc
+++ b/base/win/shortcut_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/stl_util.h"
-#include "base/strings/string16.h"
 #include "base/test/test_file_util.h"
 #include "base/test/test_shortcut_win.h"
 #include "base/win/scoped_com_initializer.h"
@@ -42,10 +41,10 @@
 
       link_properties_.set_target(target_file);
       link_properties_.set_working_dir(temp_dir_.GetPath());
-      link_properties_.set_arguments(STRING16_LITERAL("--magic --awesome"));
-      link_properties_.set_description(STRING16_LITERAL("Chrome is awesome."));
+      link_properties_.set_arguments(L"--magic --awesome");
+      link_properties_.set_description(L"Chrome is awesome.");
       link_properties_.set_icon(link_properties_.target, 4);
-      link_properties_.set_app_id(STRING16_LITERAL("Chrome"));
+      link_properties_.set_app_id(L"Chrome");
       link_properties_.set_dual_mode(false);
 
       // The CLSID below was randomly selected.
@@ -68,12 +67,10 @@
 
       link_properties_2_.set_target(target_file_2);
       link_properties_2_.set_working_dir(temp_dir_2_.GetPath());
-      link_properties_2_.set_arguments(STRING16_LITERAL("--super --crazy"));
-      link_properties_2_.set_description(
-          STRING16_LITERAL("The best in the west."));
+      link_properties_2_.set_arguments(L"--super --crazy");
+      link_properties_2_.set_description(L"The best in the west.");
       link_properties_2_.set_icon(icon_path_2, 0);
-      link_properties_2_.set_app_id(
-          STRING16_LITERAL("Chrome.UserLevelCrazySuffix"));
+      link_properties_2_.set_app_id(L"Chrome.UserLevelCrazySuffix");
       link_properties_2_.set_dual_mode(true);
       link_properties_2_.set_toast_activator_clsid(CLSID_NULL);
     }
@@ -133,11 +130,11 @@
   ValidatePathsAreEqual(only_target_properties.target,
                         properties_read_2.target);
   ValidatePathsAreEqual(FilePath(), properties_read_2.working_dir);
-  EXPECT_EQ(STRING16_LITERAL(""), properties_read_2.arguments);
-  EXPECT_EQ(STRING16_LITERAL(""), properties_read_2.description);
+  EXPECT_EQ(L"", properties_read_2.arguments);
+  EXPECT_EQ(L"", properties_read_2.description);
   ValidatePathsAreEqual(FilePath(), properties_read_2.icon);
   EXPECT_EQ(0, properties_read_2.icon_index);
-  EXPECT_EQ(STRING16_LITERAL(""), properties_read_2.app_id);
+  EXPECT_EQ(L"", properties_read_2.app_id);
   EXPECT_FALSE(properties_read_2.dual_mode);
   EXPECT_EQ(CLSID_NULL, properties_read_2.toast_activator_clsid);
 }
@@ -162,7 +159,7 @@
       link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS));
 
   FilePath resolved_name;
-  string16 args;
+  std::wstring args;
   EXPECT_TRUE(ResolveShortcut(link_file_, &resolved_name, &args));
 
   char read_contents[base::size(kFileContents)];
@@ -260,14 +257,14 @@
       link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS));
 
   ShortcutProperties clear_arguments_properties;
-  clear_arguments_properties.set_arguments(string16());
+  clear_arguments_properties.set_arguments(std::wstring());
 
   ASSERT_TRUE(CreateOrUpdateShortcutLink(
       link_file_, clear_arguments_properties,
       SHORTCUT_UPDATE_EXISTING));
 
   ShortcutProperties expected_properties = link_properties_;
-  expected_properties.set_arguments(string16());
+  expected_properties.set_arguments(std::wstring());
   ValidateShortcut(link_file_, expected_properties);
 }
 
@@ -303,7 +300,7 @@
   ShortcutProperties expected_properties(new_properties);
   expected_properties.set_working_dir(FilePath());
   expected_properties.set_icon(FilePath(), 0);
-  expected_properties.set_app_id(string16());
+  expected_properties.set_app_id(std::wstring());
   expected_properties.set_dual_mode(false);
   ValidateShortcut(link_file_, expected_properties);
 }
diff --git a/base/win/win_util.cc b/base/win/win_util.cc
index 7c87ace..97301a1 100644
--- a/base/win/win_util.cc
+++ b/base/win/win_util.cc
@@ -40,6 +40,7 @@
 #include "base/macros.h"
 #include "base/scoped_native_library.h"
 #include "base/strings/string_util.h"
+#include "base/strings/string_util_win.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/scoped_thread_priority.h"
@@ -334,20 +335,20 @@
       break;
 
     // Get the device ID.
-    char16 device_id[MAX_DEVICE_ID_LEN];
-    CONFIGRET status =
-        CM_Get_Device_ID(device_info_data.DevInst, as_writable_wcstr(device_id),
-                         MAX_DEVICE_ID_LEN, 0);
+    wchar_t device_id[MAX_DEVICE_ID_LEN];
+    CONFIGRET status = CM_Get_Device_ID(device_info_data.DevInst, device_id,
+                                        MAX_DEVICE_ID_LEN, 0);
     if (status == CR_SUCCESS) {
       // To reduce the scope of the hack we only look for ACPI and HID\\VID
       // prefixes in the keyboard device ids.
-      if (StartsWith(device_id, STRING16_LITERAL("ACPI"),
+      if (StartsWith(base::AsStringPiece16(device_id), STRING16_LITERAL("ACPI"),
                      CompareCase::INSENSITIVE_ASCII) ||
-          StartsWith(device_id, STRING16_LITERAL("HID\\VID"),
+          StartsWith(base::AsStringPiece16(device_id),
+                     STRING16_LITERAL("HID\\VID"),
                      CompareCase::INSENSITIVE_ASCII)) {
         if (reason) {
           *reason += "device: ";
-          *reason += UTF16ToUTF8(device_id);
+          *reason += WideToUTF8(device_id);
           *reason += '\n';
         }
         // The heuristic we are using is to check the count of keyboards and
@@ -374,7 +375,7 @@
   DCHECK(success);
 }
 
-bool GetUserSidString(string16* user_sid) {
+bool GetUserSidString(std::wstring* user_sid) {
   // Get the current token.
   HANDLE token = NULL;
   if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token))
@@ -396,7 +397,7 @@
   if (!::ConvertSidToStringSid(user->User.Sid, &sid_string))
     return false;
 
-  *user_sid = as_u16cstr(sid_string);
+  *user_sid = sid_string;
 
   ::LocalFree(sid_string);
 
@@ -409,14 +410,11 @@
   //   http://code.google.com/p/chromium/issues/detail?id=61644
   ThreadRestrictions::ScopedAllowIO allow_io;
 
-  RegKey key(
-      HKEY_LOCAL_MACHINE,
-      STRING16_LITERAL(
-          "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"),
-      KEY_READ);
+  RegKey key(HKEY_LOCAL_MACHINE,
+             L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
+             KEY_READ);
   DWORD uac_enabled;
-  if (key.ReadValueDW(STRING16_LITERAL("EnableLUA"), &uac_enabled) !=
-      ERROR_SUCCESS) {
+  if (key.ReadValueDW(L"EnableLUA", &uac_enabled) != ERROR_SUCCESS) {
     return true;
   }
   // Users can set the EnableLUA value to something arbitrary, like 2, which
@@ -440,9 +438,9 @@
 
 bool SetStringValueForPropertyStore(IPropertyStore* property_store,
                                     const PROPERTYKEY& property_key,
-                                    const char16* property_string_value) {
+                                    const wchar_t* property_string_value) {
   ScopedPropVariant property_value;
-  if (FAILED(InitPropVariantFromString(as_wcstr(property_string_value),
+  if (FAILED(InitPropVariantFromString(property_string_value,
                                        property_value.Receive()))) {
     return false;
   }
@@ -466,36 +464,37 @@
 }
 
 bool SetAppIdForPropertyStore(IPropertyStore* property_store,
-                              const char16* app_id) {
+                              const wchar_t* app_id) {
   // App id should be less than 64 chars and contain no space. And recommended
   // format is CompanyName.ProductName[.SubProduct.ProductNumber].
   // See http://msdn.microsoft.com/en-us/library/dd378459%28VS.85%29.aspx
-  DCHECK_LT(lstrlen(as_wcstr(app_id)), 64);
-  DCHECK_EQ(wcschr(as_wcstr(app_id), L' '), nullptr);
+  DCHECK_LT(lstrlen(app_id), 64);
+  DCHECK_EQ(wcschr(app_id, L' '), nullptr);
 
   return SetStringValueForPropertyStore(property_store,
                                         PKEY_AppUserModel_ID,
                                         app_id);
 }
 
-static const char16 kAutoRunKeyPath[] =
-    STRING16_LITERAL("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
+static const wchar_t kAutoRunKeyPath[] =
+    L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
 
-bool AddCommandToAutoRun(HKEY root_key, const string16& name,
-                         const string16& command) {
+bool AddCommandToAutoRun(HKEY root_key,
+                         const std::wstring& name,
+                         const std::wstring& command) {
   RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE);
   return (autorun_key.WriteValue(name.c_str(), command.c_str()) ==
       ERROR_SUCCESS);
 }
 
-bool RemoveCommandFromAutoRun(HKEY root_key, const string16& name) {
+bool RemoveCommandFromAutoRun(HKEY root_key, const std::wstring& name) {
   RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_SET_VALUE);
   return (autorun_key.DeleteValue(name.c_str()) == ERROR_SUCCESS);
 }
 
 bool ReadCommandFromAutoRun(HKEY root_key,
-                            const string16& name,
-                            string16* command) {
+                            const std::wstring& name,
+                            std::wstring* command) {
   RegKey autorun_key(root_key, kAutoRunKeyPath, KEY_QUERY_VALUE);
   return (autorun_key.ReadValue(name.c_str(), command) == ERROR_SUCCESS);
 }
@@ -766,9 +765,9 @@
   return nullptr;
 }
 
-string16 GetWindowObjectName(HANDLE handle) {
+std::wstring GetWindowObjectName(HANDLE handle) {
   // Get the size of the name.
-  string16 object_name;
+  std::wstring object_name;
 
   DWORD size = 0;
   ::GetUserObjectInformation(handle, UOI_NAME, nullptr, 0, &size);
@@ -781,7 +780,7 @@
 
   // Query the name of the object.
   if (!::GetUserObjectInformation(
-          handle, UOI_NAME, WriteInto(&object_name, size / sizeof(wchar_t)),
+          handle, UOI_NAME, WriteIntoW(&object_name, size / sizeof(wchar_t)),
           size, &size)) {
     DPCHECK(false);
   }
@@ -789,13 +788,14 @@
   return object_name;
 }
 
-bool IsRunningUnderDesktopName(StringPiece16 desktop_name) {
+bool IsRunningUnderDesktopName(WStringPiece desktop_name) {
   HDESK thread_desktop = ::GetThreadDesktop(::GetCurrentThreadId());
   if (!thread_desktop)
     return false;
 
-  string16 current_desktop_name = GetWindowObjectName(thread_desktop);
-  return EqualsCaseInsensitiveASCII(current_desktop_name, desktop_name);
+  std::wstring current_desktop_name = GetWindowObjectName(thread_desktop);
+  return EqualsCaseInsensitiveASCII(AsStringPiece16(current_desktop_name),
+                                    AsStringPiece16(desktop_name));
 }
 
 // This method is used to detect whether current session is a remote session.
@@ -810,14 +810,13 @@
   if (!::ProcessIdToSessionId(::GetCurrentProcessId(), &current_session_id))
     return false;
 
-  static constexpr char16 kRdpSettingsKeyName[] =
-      STRING16_LITERAL("SYSTEM\\CurrentControlSet\\Control\\Terminal Server");
+  static constexpr wchar_t kRdpSettingsKeyName[] =
+      L"SYSTEM\\CurrentControlSet\\Control\\Terminal Server";
   RegKey key(HKEY_LOCAL_MACHINE, kRdpSettingsKeyName, KEY_READ);
   if (!key.Valid())
     return false;
 
-  static constexpr char16 kGlassSessionIdValueName[] =
-      STRING16_LITERAL("GlassSessionId");
+  static constexpr wchar_t kGlassSessionIdValueName[] = L"GlassSessionId";
   DWORD glass_session_id = 0;
   if (key.ReadValueDW(kGlassSessionIdValueName, &glass_session_id) !=
       ERROR_SUCCESS)
diff --git a/base/win/win_util.h b/base/win/win_util.h
index 921b5c1..8c938957 100644
--- a/base/win/win_util.h
+++ b/base/win/win_util.h
@@ -58,7 +58,7 @@
 
 // Returns the string representing the current user sid. Does not modify
 // |user_sid| on failure.
-BASE_EXPORT bool GetUserSidString(string16* user_sid);
+BASE_EXPORT bool GetUserSidString(std::wstring* user_sid);
 
 // Returns false if user account control (UAC) has been disabled with the
 // EnableLUA registry flag. Returns true if user account control is enabled.
@@ -78,7 +78,7 @@
 BASE_EXPORT bool SetStringValueForPropertyStore(
     IPropertyStore* property_store,
     const PROPERTYKEY& property_key,
-    const char16* property_string_value);
+    const wchar_t* property_string_value);
 
 // Sets the CLSID value for a given key in a given IPropertyStore.
 BASE_EXPORT bool SetClsidForPropertyStore(IPropertyStore* property_store,
@@ -89,22 +89,23 @@
 // for tagging application/chromium shortcut, browser window and jump list for
 // Win7.
 BASE_EXPORT bool SetAppIdForPropertyStore(IPropertyStore* property_store,
-                                          const char16* app_id);
+                                          const wchar_t* app_id);
 
 // Adds the specified |command| using the specified |name| to the AutoRun key.
 // |root_key| could be HKCU or HKLM or the root of any user hive.
 BASE_EXPORT bool AddCommandToAutoRun(HKEY root_key,
-                                     const string16& name,
-                                     const string16& command);
+                                     const std::wstring& name,
+                                     const std::wstring& command);
 // Removes the command specified by |name| from the AutoRun key. |root_key|
 // could be HKCU or HKLM or the root of any user hive.
-BASE_EXPORT bool RemoveCommandFromAutoRun(HKEY root_key, const string16& name);
+BASE_EXPORT bool RemoveCommandFromAutoRun(HKEY root_key,
+                                          const std::wstring& name);
 
 // Reads the command specified by |name| from the AutoRun key. |root_key|
 // could be HKCU or HKLM or the root of any user hive. Used for unit-tests.
 BASE_EXPORT bool ReadCommandFromAutoRun(HKEY root_key,
-                                        const string16& name,
-                                        string16* command);
+                                        const std::wstring& name,
+                                        std::wstring* command);
 
 // Sets whether to crash the process during exit. This is inspected by DLLMain
 // and used to intercept unexpected terminations of the process (via calls to
@@ -216,12 +217,12 @@
     NativeLibraryLoadError* error = nullptr);
 
 // Returns the name of a desktop or a window station.
-BASE_EXPORT string16 GetWindowObjectName(HANDLE handle);
+BASE_EXPORT std::wstring GetWindowObjectName(HANDLE handle);
 
 // Checks if the calling thread is running under a desktop with the name
 // given by |desktop_name|. |desktop_name| is ASCII case insensitive (non-ASCII
 // characters will be compared with exact matches).
-BASE_EXPORT bool IsRunningUnderDesktopName(StringPiece16 desktop_name);
+BASE_EXPORT bool IsRunningUnderDesktopName(WStringPiece desktop_name);
 
 // Returns true if current session is a remote session.
 BASE_EXPORT bool IsCurrentSessionRemote();
diff --git a/base/win/win_util_unittest.cc b/base/win/win_util_unittest.cc
index 1b161aa..c0c7b239 100644
--- a/base/win/win_util_unittest.cc
+++ b/base/win/win_util_unittest.cc
@@ -43,7 +43,7 @@
 }
 
 TEST(BaseWinUtilTest, TestGetUserSidString) {
-  string16 user_sid;
+  std::wstring user_sid;
   EXPECT_TRUE(GetUserSidString(&user_sid));
   EXPECT_TRUE(!user_sid.empty());
 }
@@ -101,9 +101,9 @@
 }
 
 TEST(BaseWinUtilTest, GetWindowObjectName) {
-  base::string16 created_desktop_name(STRING16_LITERAL("test_desktop"));
+  std::wstring created_desktop_name(L"test_desktop");
   HDESK desktop_handle =
-      ::CreateDesktop(as_wcstr(created_desktop_name), nullptr, nullptr, 0,
+      ::CreateDesktop(created_desktop_name.c_str(), nullptr, nullptr, 0,
                       DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS |
                           READ_CONTROL | WRITE_DAC | WRITE_OWNER,
                       nullptr);
@@ -117,13 +117,15 @@
   HDESK thread_desktop = ::GetThreadDesktop(::GetCurrentThreadId());
 
   ASSERT_NE(thread_desktop, nullptr);
-  base::string16 desktop_name = GetWindowObjectName(thread_desktop);
+  std::wstring desktop_name = GetWindowObjectName(thread_desktop);
 
   EXPECT_TRUE(IsRunningUnderDesktopName(desktop_name));
-  EXPECT_TRUE(IsRunningUnderDesktopName(base::ToLowerASCII(desktop_name)));
-  EXPECT_TRUE(IsRunningUnderDesktopName(base::ToUpperASCII(desktop_name)));
-  EXPECT_FALSE(IsRunningUnderDesktopName(
-      desktop_name + STRING16_LITERAL("_non_existent_desktop_name")));
+  EXPECT_TRUE(IsRunningUnderDesktopName(
+      AsWString(ToLowerASCII(AsStringPiece16(desktop_name)))));
+  EXPECT_TRUE(IsRunningUnderDesktopName(
+      AsWString(ToUpperASCII(AsStringPiece16(desktop_name)))));
+  EXPECT_FALSE(
+      IsRunningUnderDesktopName(desktop_name + L"_non_existent_desktop_name"));
 }
 
 }  // namespace win
diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc
index 1d37219..88974fa 100644
--- a/base/win/windows_version.cc
+++ b/base/win/windows_version.cc
@@ -14,7 +14,6 @@
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/no_destructor.h"
-#include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/registry.h"
@@ -34,8 +33,8 @@
 
 // The values under the CurrentVersion registry hive are mirrored under
 // the corresponding Wow6432 hive.
-constexpr char16 kRegKeyWindowsNTCurrentVersion[] =
-    STRING16_LITERAL("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
+constexpr wchar_t kRegKeyWindowsNTCurrentVersion[] =
+    L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
 
 // Returns the "UBR" (Windows 10 patch number) and "ReleaseId" (Windows 10
 // release number) from the registry. "UBR" is an undocumented value and will be
@@ -43,16 +42,16 @@
 // value is not found.
 std::pair<int, std::string> GetVersionData() {
   DWORD ubr = 0;
-  string16 release_id;
+  std::wstring release_id;
   RegKey key;
 
   if (key.Open(HKEY_LOCAL_MACHINE, kRegKeyWindowsNTCurrentVersion,
                KEY_QUERY_VALUE) == ERROR_SUCCESS) {
-    key.ReadValueDW(STRING16_LITERAL("UBR"), &ubr);
-    key.ReadValue(STRING16_LITERAL("ReleaseId"), &release_id);
+    key.ReadValueDW(L"UBR", &ubr);
+    key.ReadValue(L"ReleaseId", &release_id);
   }
 
-  return std::make_pair(static_cast<int>(ubr), UTF16ToUTF8(release_id));
+  return std::make_pair(static_cast<int>(ubr), WideToUTF8(release_id));
 }
 
 const _SYSTEM_INFO& GetSystemInfoStorage() {
@@ -230,12 +229,12 @@
 
 std::string OSInfo::processor_model_name() {
   if (processor_model_name_.empty()) {
-    const char16 kProcessorNameString[] =
-        STRING16_LITERAL("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
+    const wchar_t kProcessorNameString[] =
+        L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
     RegKey key(HKEY_LOCAL_MACHINE, kProcessorNameString, KEY_READ);
-    string16 value;
-    key.ReadValue(STRING16_LITERAL("ProcessorNameString"), &value);
-    processor_model_name_ = UTF16ToUTF8(value);
+    std::wstring value;
+    key.ReadValue(L"ProcessorNameString", &value);
+    processor_model_name_ = WideToUTF8(value);
   }
   return processor_model_name_;
 }
diff --git a/base/win/wmi.cc b/base/win/wmi.cc
index 4d5e094c..c7da8a3 100644
--- a/base/win/wmi.cc
+++ b/base/win/wmi.cc
@@ -36,9 +36,9 @@
     return false;
 
   ComPtr<IWbemServices> wmi_services_r;
-  hr = wmi_locator->ConnectServer(ScopedBstr(STRING16_LITERAL("ROOT\\CIMV2")),
-                                  nullptr, nullptr, nullptr, 0, nullptr,
-                                  nullptr, &wmi_services_r);
+  hr =
+      wmi_locator->ConnectServer(ScopedBstr(L"ROOT\\CIMV2"), nullptr, nullptr,
+                                 nullptr, 0, nullptr, nullptr, &wmi_services_r);
   if (FAILED(hr))
     return false;
 
@@ -55,8 +55,8 @@
 }
 
 bool CreateWmiClassMethodObject(IWbemServices* wmi_services,
-                                StringPiece16 class_name,
-                                StringPiece16 method_name,
+                                WStringPiece class_name,
+                                WStringPiece method_name,
                                 ComPtr<IWbemClassObject>* class_instance) {
   // We attempt to instantiate a COM object that represents a WMI object plus
   // a method rolled into one entity.
@@ -90,20 +90,20 @@
 // NOTE: The documentation for the Create method suggests that the ProcessId
 // parameter and return value are of type uint32_t, but when we call the method
 // the values in the returned out_params, are VT_I4, which is int32_t.
-bool WmiLaunchProcess(const string16& command_line, int* process_id) {
+bool WmiLaunchProcess(const std::wstring& command_line, int* process_id) {
   ComPtr<IWbemServices> wmi_local;
   if (!CreateLocalWmiConnection(true, &wmi_local))
     return false;
 
-  static constexpr char16 class_name[] = STRING16_LITERAL("Win32_Process");
-  static constexpr char16 method_name[] = STRING16_LITERAL("Create");
+  static constexpr wchar_t class_name[] = L"Win32_Process";
+  static constexpr wchar_t method_name[] = L"Create";
   ComPtr<IWbemClassObject> process_create;
   if (!CreateWmiClassMethodObject(wmi_local.Get(), class_name, method_name,
                                   &process_create)) {
     return false;
   }
 
-  ScopedVariant b_command_line(as_wcstr(command_line));
+  ScopedVariant b_command_line(command_line.c_str());
 
   if (FAILED(process_create->Put(L"CommandLine", 0, b_command_line.AsInput(),
                                  0))) {
@@ -151,14 +151,14 @@
 
 void WmiComputerSystemInfo::PopulateModelAndManufacturer(
     const ComPtr<IWbemServices>& services) {
-  static constexpr StringPiece16 query_computer_system =
-      STRING16_LITERAL("SELECT Manufacturer,Model FROM Win32_ComputerSystem");
+  static constexpr WStringPiece query_computer_system =
+      L"SELECT Manufacturer,Model FROM Win32_ComputerSystem";
 
   ComPtr<IEnumWbemClassObject> enumerator_computer_system;
-  HRESULT hr = services->ExecQuery(
-      ScopedBstr(STRING16_LITERAL("WQL")), ScopedBstr(query_computer_system),
-      WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr,
-      &enumerator_computer_system);
+  HRESULT hr =
+      services->ExecQuery(ScopedBstr(L"WQL"), ScopedBstr(query_computer_system),
+                          WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
+                          nullptr, &enumerator_computer_system);
   if (FAILED(hr) || !enumerator_computer_system.Get())
     return;
 
@@ -172,27 +172,26 @@
   ScopedVariant manufacturer;
   hr = class_object->Get(L"Manufacturer", 0, manufacturer.Receive(), 0, 0);
   if (SUCCEEDED(hr) && manufacturer.type() == VT_BSTR) {
-    WideToUTF16(V_BSTR(manufacturer.ptr()),
-                ::SysStringLen(V_BSTR(manufacturer.ptr())), &manufacturer_);
+    manufacturer_.assign(V_BSTR(manufacturer.ptr()),
+                         ::SysStringLen(V_BSTR(manufacturer.ptr())));
   }
   ScopedVariant model;
   hr = class_object->Get(L"Model", 0, model.Receive(), 0, 0);
   if (SUCCEEDED(hr) && model.type() == VT_BSTR) {
-    WideToUTF16(V_BSTR(model.ptr()), ::SysStringLen(V_BSTR(model.ptr())),
-                &model_);
+    model_.assign(V_BSTR(model.ptr()), ::SysStringLen(V_BSTR(model.ptr())));
   }
 }
 
 void WmiComputerSystemInfo::PopulateSerialNumber(
     const ComPtr<IWbemServices>& services) {
-  static constexpr StringPiece16 query_bios =
-      STRING16_LITERAL("SELECT SerialNumber FROM Win32_Bios");
+  static constexpr WStringPiece query_bios =
+      L"SELECT SerialNumber FROM Win32_Bios";
 
   ComPtr<IEnumWbemClassObject> enumerator_bios;
-  HRESULT hr = services->ExecQuery(
-      ScopedBstr(STRING16_LITERAL("WQL")), ScopedBstr(query_bios),
-      WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr,
-      &enumerator_bios);
+  HRESULT hr =
+      services->ExecQuery(ScopedBstr(L"WQL"), ScopedBstr(query_bios),
+                          WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
+                          nullptr, &enumerator_bios);
   if (FAILED(hr) || !enumerator_bios.Get())
     return;
 
@@ -205,8 +204,8 @@
   ScopedVariant serial_number;
   hr = class_obj->Get(L"SerialNumber", 0, serial_number.Receive(), 0, 0);
   if (SUCCEEDED(hr) && serial_number.type() == VT_BSTR) {
-    WideToUTF16(V_BSTR(serial_number.ptr()),
-                ::SysStringLen(V_BSTR(serial_number.ptr())), &serial_number_);
+    serial_number_.assign(V_BSTR(serial_number.ptr()),
+                          ::SysStringLen(V_BSTR(serial_number.ptr())));
   }
 }
 
diff --git a/base/win/wmi.h b/base/win/wmi.h
index e1523152ce..7949888a 100644
--- a/base/win/wmi.h
+++ b/base/win/wmi.h
@@ -24,7 +24,6 @@
 #include <wrl/client.h>
 
 #include "base/base_export.h"
-#include "base/strings/string16.h"
 #include "base/strings/string_piece.h"
 
 namespace base {
@@ -47,8 +46,8 @@
 // WMI method that you can fill with parameter values using SetParameter.
 BASE_EXPORT bool CreateWmiClassMethodObject(
     IWbemServices* wmi_services,
-    StringPiece16 class_name,
-    StringPiece16 method_name,
+    WStringPiece class_name,
+    WStringPiece method_name,
     Microsoft::WRL::ComPtr<IWbemClassObject>* class_instance);
 
 // Creates a new process from |command_line|. The advantage over CreateProcess
@@ -61,7 +60,7 @@
 // Processes created this way are children of wmiprvse.exe and run with the
 // caller credentials.
 // More info: http://msdn2.microsoft.com/en-us/library/aa394372(VS.85).aspx
-BASE_EXPORT bool WmiLaunchProcess(const string16& command_line,
+BASE_EXPORT bool WmiLaunchProcess(const std::wstring& command_line,
                                   int* process_id);
 
 // An encapsulation of information retrieved from the 'Win32_ComputerSystem' and
@@ -72,9 +71,9 @@
  public:
   static WmiComputerSystemInfo Get();
 
-  const string16& manufacturer() const { return manufacturer_; }
-  const string16& model() const { return model_; }
-  const string16& serial_number() const { return serial_number_; }
+  const std::wstring& manufacturer() const { return manufacturer_; }
+  const std::wstring& model() const { return model_; }
+  const std::wstring& serial_number() const { return serial_number_; }
 
  private:
   void PopulateModelAndManufacturer(
@@ -82,9 +81,9 @@
   void PopulateSerialNumber(
       const Microsoft::WRL::ComPtr<IWbemServices>& services);
 
-  string16 manufacturer_;
-  string16 model_;
-  string16 serial_number_;
+  std::wstring manufacturer_;
+  std::wstring model_;
+  std::wstring serial_number_;
 };
 
 }  // namespace win
diff --git a/base/win/wmi_unittest.cc b/base/win/wmi_unittest.cc
index 6c46525..438fff7 100644
--- a/base/win/wmi_unittest.cc
+++ b/base/win/wmi_unittest.cc
@@ -42,8 +42,7 @@
   ASSERT_NE(wmi_services.Get(), nullptr);
   ComPtr<IWbemClassObject> class_method = nullptr;
   EXPECT_TRUE(CreateWmiClassMethodObject(
-      wmi_services.Get(), STRING16_LITERAL("Win32_ShortcutFile"),
-      STRING16_LITERAL("Rename"), &class_method));
+      wmi_services.Get(), L"Win32_ShortcutFile", L"Rename", &class_method));
   ASSERT_NE(class_method.Get(), nullptr);
   ULONG refs = class_method.Reset();
   EXPECT_EQ(0u, refs);
@@ -54,8 +53,7 @@
 // Creates an instance of cmd which executes 'echo' and exits immediately.
 TEST_F(WMITest, TestLaunchProcess) {
   int pid = 0;
-  bool result =
-      WmiLaunchProcess(STRING16_LITERAL("cmd.exe /c echo excelent!"), &pid);
+  bool result = WmiLaunchProcess(L"cmd.exe /c echo excelent!", &pid);
   EXPECT_TRUE(result);
   EXPECT_GT(pid, 0);
 }
diff --git a/build/android/gyp/dex.py b/build/android/gyp/dex.py
index a2e17b4..6d29ac5 100755
--- a/build/android/gyp/dex.py
+++ b/build/android/gyp/dex.py
@@ -35,7 +35,7 @@
       '--multi-dex',
       action='store_true',
       help='Allow multiple dex files within output.')
-  parser.add_argument('--d8-jar-path', required=True, help='Path to D8 jar.')
+  parser.add_argument('--r8-jar-path', required=True, help='Path to R8 jar.')
   parser.add_argument(
       '--release',
       action='store_true',
@@ -250,7 +250,7 @@
 
 
 def _PerformDexing(options):
-  dex_cmd = ['java', '-jar', options.d8_jar_path, '--no-desugaring']
+  dex_cmd = ['java', '-jar', options.r8_jar_path, 'd8', '--no-desugaring']
   if options.multi_dex and options.main_dex_list_path:
     dex_cmd += ['--main-dex-list', options.main_dex_list_path]
   if options.release:
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index c94c6e6..68f765b 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -1393,11 +1393,10 @@
           ]
         }
 
-        _d8_path = "//third_party/r8/lib/d8.jar"
-        inputs += [ _d8_path ]
+        inputs += [ _r8_path ]
         args += [
-          "--d8-jar-path",
-          rebase_path(_d8_path, root_build_dir),
+          "--r8-jar-path",
+          rebase_path(_r8_path, root_build_dir),
         ]
       }
     }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index e09be88..0bf082c 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8902647923806574208
\ No newline at end of file
+8902626326861029680
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 890df05..9a9205b 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8903108260652561184
\ No newline at end of file
+8902625321346829424
\ No newline at end of file
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index ff03023..bb1c5c5 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -386,6 +386,7 @@
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationEventObserver.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateController.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java",
+  "java/src/org/chromium/chrome/browser/customtabs/CustomTabSessionHandler.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabTopBarDelegate.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabsClientFileProcessor.java",
diff --git a/chrome/android/features/keyboard_accessory/internal/java/res/layout/address_accessory_sheet.xml b/chrome/android/features/keyboard_accessory/internal/java/res/layout/address_accessory_sheet.xml
index 2d0a899..4bc6b90 100644
--- a/chrome/android/features/keyboard_accessory/internal/java/res/layout/address_accessory_sheet.xml
+++ b/chrome/android/features/keyboard_accessory/internal/java/res/layout/address_accessory_sheet.xml
@@ -10,4 +10,5 @@
     android:layout_height="match_parent"
     android:layout_width="match_parent"
     android:clipToPadding="false"
-    android:paddingBottom="@dimen/keyboard_accessory_sheet_footer_trailing_margin"/>
+    android:paddingBottom="@dimen/keyboard_accessory_sheet_footer_trailing_margin"
+    android:background="@color/default_bg_color_elev_3"/>
diff --git a/chrome/android/features/keyboard_accessory/internal/java/res/layout/credit_card_accessory_sheet.xml b/chrome/android/features/keyboard_accessory/internal/java/res/layout/credit_card_accessory_sheet.xml
index 49683b0..97ee1dbd 100644
--- a/chrome/android/features/keyboard_accessory/internal/java/res/layout/credit_card_accessory_sheet.xml
+++ b/chrome/android/features/keyboard_accessory/internal/java/res/layout/credit_card_accessory_sheet.xml
@@ -10,4 +10,5 @@
     android:layout_height="match_parent"
     android:layout_width="match_parent"
     android:clipToPadding="false"
-    android:paddingBottom="@dimen/keyboard_accessory_sheet_footer_trailing_margin"/>
+    android:paddingBottom="@dimen/keyboard_accessory_sheet_footer_trailing_margin"
+    android:background="@color/default_bg_color_elev_3"/>
diff --git a/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_modern.xml b/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_modern.xml
index 22b2c3d..25ade2f 100644
--- a/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_modern.xml
+++ b/chrome/android/features/keyboard_accessory/internal/java/res/layout/keyboard_accessory_modern.xml
@@ -34,7 +34,7 @@
         android:layout_height="wrap_content"
         android:layout_gravity="start|bottom"
         android:orientation="horizontal"
-        android:background="@color/modern_primary_color">
+        android:background="@color/default_bg_color_elev_3">
 
         <ImageView
             android:id="@+id/show_keyboard"
diff --git a/chrome/android/features/keyboard_accessory/internal/java/res/layout/password_accessory_sheet.xml b/chrome/android/features/keyboard_accessory/internal/java/res/layout/password_accessory_sheet.xml
index 15f8885..3151229 100644
--- a/chrome/android/features/keyboard_accessory/internal/java/res/layout/password_accessory_sheet.xml
+++ b/chrome/android/features/keyboard_accessory/internal/java/res/layout/password_accessory_sheet.xml
@@ -10,4 +10,5 @@
     android:layout_height="match_parent"
     android:layout_width="match_parent"
     android:clipToPadding="false"
-    android:paddingBottom="@dimen/keyboard_accessory_sheet_footer_trailing_margin"/>
+    android:paddingBottom="@dimen/keyboard_accessory_sheet_footer_trailing_margin"
+    android:background="@color/default_bg_color_elev_3"/>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionDataHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionDataHolder.java
index 7bffd3b..736e6c2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionDataHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionDataHolder.java
@@ -33,7 +33,7 @@
     private final SparseArray<SessionData> mTaskIdToSessionData = new SparseArray<>();
 
     @Nullable
-    private SessionHandler mActiveContentHandler;
+    private SessionHandler mActiveSessionHandler;
 
     @Nullable
     private Callback<CustomTabsSessionToken> mSessionDisconnectCallback;
@@ -49,7 +49,7 @@
     private static class SessionData {
         public final CustomTabsSessionToken session;
 
-        // Content handlers can reside in Activities of different types, so we need to store the
+        // Session handlers can reside in Activities of different types, so we need to store the
         // Activity class to be able to route new intents into it.
         public final Class<? extends Activity> activityClass;
 
@@ -62,25 +62,25 @@
 
     /**
      * Sets the currently active {@link SessionHandler} in focus.
-     * @param contentHandler {@link SessionHandler} to set.
+     * @param sessionHandler {@link SessionHandler} to set.
      */
-    public void setActiveHandler(@NonNull SessionHandler contentHandler) {
-        mActiveContentHandler = contentHandler;
-        CustomTabsSessionToken session = contentHandler.getSession();
+    public void setActiveHandler(@NonNull SessionHandler sessionHandler) {
+        mActiveSessionHandler = sessionHandler;
+        CustomTabsSessionToken session = sessionHandler.getSession();
         if (session == null) return;
 
-        mTaskIdToSessionData.append(contentHandler.getTaskId(),
-                new SessionData(session, contentHandler.getActivityClass()));
+        mTaskIdToSessionData.append(sessionHandler.getTaskId(),
+                new SessionData(session, sessionHandler.getActivityClass()));
         ensureSessionCleanUpOnDisconnects();
     }
 
     /**
      * Notifies that given {@link SessionHandler} no longer has focus.
      */
-    public void removeActiveHandler(SessionHandler contentHandler) {
-        if (mActiveContentHandler == contentHandler) {
-            mActiveContentHandler = null;
-        } // else this contentHandler has already been replaced.
+    public void removeActiveHandler(SessionHandler sessionHandler) {
+        if (mActiveSessionHandler == sessionHandler) {
+            mActiveSessionHandler = null;
+        } // else this sessionHandler has already been replaced.
 
         // Intentionally not removing from mTaskIdToSessionData to handle cases when the task is
         // brought to foreground by a new intent - the CCT might not be able to call
@@ -129,10 +129,10 @@
      */
     @Nullable
     public SessionHandler getActiveHandler(@Nullable CustomTabsSessionToken session) {
-        if (mActiveContentHandler == null) return null;
-        CustomTabsSessionToken activeSession = mActiveContentHandler.getSession();
+        if (mActiveSessionHandler == null) return null;
+        CustomTabsSessionToken activeSession = mActiveSessionHandler.getSession();
         if (activeSession == null || !activeSession.equals(session)) return null;
-        return mActiveContentHandler;
+        return mActiveSessionHandler;
     }
 
     @Nullable
@@ -164,8 +164,8 @@
      */
     @Deprecated
     public String getCurrentUrlForActiveBrowserSession() {
-        if (mActiveContentHandler == null) return null;
-        return mActiveContentHandler.getCurrentUrl();
+        if (mActiveSessionHandler == null) return null;
+        return mActiveSessionHandler.getCurrentUrl();
     }
 
     /**
@@ -176,8 +176,8 @@
      */
     @Deprecated
     public String getPendingUrlForActiveBrowserSession() {
-        if (mActiveContentHandler == null) return null;
-        return mActiveContentHandler.getPendingUrl();
+        if (mActiveSessionHandler == null) return null;
+        return mActiveSessionHandler.getPendingUrl();
     }
 
     private void ensureSessionCleanUpOnDisconnects() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index 246a000..5ec213b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -4,16 +4,14 @@
 
 package org.chromium.chrome.browser.customtabs;
 
+import static org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishReason.USER_NAVIGATION;
+
 import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_DARK;
 import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_LIGHT;
 
-import static org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishReason.USER_NAVIGATION;
-
 import android.app.Activity;
-import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
-import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -24,20 +22,13 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.text.TextUtils;
 import android.util.Pair;
 import android.view.KeyEvent;
 import android.view.ViewGroup;
 import android.view.WindowManager;
-import android.widget.RemoteViews;
-
-import androidx.browser.customtabs.CustomTabsIntent;
-import androidx.browser.customtabs.CustomTabsService;
-import androidx.browser.customtabs.CustomTabsSessionToken;
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.CommandLine;
-import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
@@ -53,10 +44,6 @@
 import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate;
 import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantFacade;
 import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider.CustomTabsUiType;
-import org.chromium.chrome.browser.browserservices.Origin;
-import org.chromium.chrome.browser.browserservices.OriginVerifier;
-import org.chromium.chrome.browser.browserservices.SessionDataHolder;
-import org.chromium.chrome.browser.browserservices.SessionHandler;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabFactory;
@@ -89,18 +76,18 @@
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.NavigationEntry;
 import org.chromium.content_public.browser.WebContents;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * The activity for custom tabs. It will be launched on top of a client's task.
  */
 public class CustomTabActivity extends ChromeActivity<CustomTabActivityComponent> {
-    private static final String TAG = "CustomTabActivity";
-
     // For CustomTabs.ConnectionStatusOnReturn, see histograms.xml. Append only.
     @IntDef({ConnectionStatus.DISCONNECTED, ConnectionStatus.DISCONNECTED_KEEP_ALIVE,
             ConnectionStatus.CONNECTED, ConnectionStatus.CONNECTED_KEEP_ALIVE})
@@ -115,7 +102,6 @@
 
     private CustomTabIntentDataProvider mIntentDataProvider;
     private CustomTabsSessionToken mSession;
-    private SessionHandler mSessionHandler;
     private CustomTabBottomBarDelegate mBottomBarDelegate;
     private CustomTabActivityTabController mTabController;
     private CustomTabActivityTabProvider mTabProvider;
@@ -123,7 +109,6 @@
     private CustomTabActivityNavigationController mNavigationController;
     private CustomTabStatusBarColorProvider mCustomTabStatusBarColorProvider;
     private CustomTabToolbarCoordinator mToolbarCoordinator;
-    private SessionDataHolder mSessionDataHolder;
     private CustomTabIntentHandler mCustomTabIntentHandler;
 
     // This is to give the right package name while using the client's resources during an
@@ -314,79 +299,6 @@
             mDynamicModuleCoordinator = getComponent().resolveDynamicModuleCoordinator();
         }
 
-        mSessionHandler = new SessionHandler() {
-
-            @Override
-            public CustomTabsSessionToken getSession() {
-                return mSession;
-            }
-
-            @Override
-            public boolean updateCustomButton(int id, Bitmap bitmap, String description) {
-                CustomButtonParams params = mIntentDataProvider.getButtonParamsForId(id);
-                if (params == null) {
-                    Log.w(TAG, "Custom toolbar button with ID %d not found", id);
-                    return false;
-                }
-
-                params.update(bitmap, description);
-                if (params.showOnToolbar()) {
-                    return mToolbarCoordinator.updateCustomButton(params);
-                }
-                mBottomBarDelegate.updateBottomBarButtons(params);
-                return true;
-            }
-
-            @Override
-            public boolean updateRemoteViews(RemoteViews remoteViews, int[] clickableIDs,
-                    PendingIntent pendingIntent) {
-                return mBottomBarDelegate.updateRemoteViews(
-                        remoteViews, clickableIDs, pendingIntent);
-            }
-
-            @Override
-            @Nullable
-            public String getCurrentUrl() {
-                return getActivityTab() == null ? null : getActivityTab().getUrl();
-            }
-
-            @Override
-            @Nullable
-            public String getPendingUrl() {
-                if (getActivityTab() == null) return null;
-                if (getActivityTab().getWebContents() == null) return null;
-
-                NavigationEntry entry = getActivityTab().getWebContents().getNavigationController()
-                        .getPendingEntry();
-                return entry != null ? entry.getUrl() : null;
-            }
-
-            @Override
-            public int getTaskId() {
-                return CustomTabActivity.this.getTaskId();
-            }
-
-            @Override
-            public Class<? extends Activity> getActivityClass() {
-                return CustomTabActivity.this.getClass();
-            }
-
-            @Override
-            public boolean handleIntent(Intent intent) {
-                // This method exists only for legacy reasons, see LaunchIntentDispatcher#
-                // clearTopIntentsForCustomTabsEnabled.
-                return handleNewIntent(intent);
-            }
-
-            @Override
-            public boolean canUseReferrer(Uri referrer) {
-                String packageName = mConnection.getClientPackageNameForSession(mSession);
-                if (TextUtils.isEmpty(packageName)) return false;
-                return OriginVerifier.wasPreviouslyVerified(
-                    packageName, new Origin(referrer), CustomTabsService.RELATION_USE_AS_ORIGIN);
-            }
-        };
-
         mConnection.showSignInToastIfNecessary(mSession, getIntent());
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && useSeparateTask()) {
@@ -447,7 +359,6 @@
     @Override
     public void onStartWithNative() {
         super.onStartWithNative();
-        mSessionDataHolder.setActiveHandler(mSessionHandler);
         @TabCreationMode int mode = mTabProvider.getInitialTabCreationMode();
         boolean earlyCreatedTabIsReady =
                 (mode == TabCreationMode.HIDDEN || mode == TabCreationMode.EARLY)
@@ -456,12 +367,6 @@
     }
 
     @Override
-    public void onStopWithNative() {
-        super.onStopWithNative();
-        mSessionDataHolder.removeActiveHandler(mSessionHandler);
-    }
-
-    @Override
     protected void onDestroyInternal() {
         super.onDestroyInternal();
 
@@ -788,8 +693,8 @@
             handleFinishAndClose();
         });
         mCustomTabIntentHandler = component.resolveIntentHandler();
-        mSessionDataHolder = component.getParent().resolveSessionDataHolder();
         component.resolveCompositorContentInitializer();
+        component.resolveSessionHandler();
 
         if (mIntentDataProvider.isTrustedWebActivity()) {
             component.resolveTrustedWebActivityCoordinator();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabSessionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabSessionHandler.java
new file mode 100644
index 0000000..0cfc8c76
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabSessionHandler.java
@@ -0,0 +1,159 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.customtabs;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.widget.RemoteViews;
+
+import org.chromium.base.Log;
+import org.chromium.chrome.browser.browserservices.Origin;
+import org.chromium.chrome.browser.browserservices.OriginVerifier;
+import org.chromium.chrome.browser.browserservices.SessionDataHolder;
+import org.chromium.chrome.browser.browserservices.SessionHandler;
+import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
+import org.chromium.chrome.browser.customtabs.content.CustomTabIntentHandler;
+import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbarCoordinator;
+import org.chromium.chrome.browser.dependency_injection.ActivityScope;
+import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
+import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.content_public.browser.NavigationEntry;
+
+import javax.inject.Inject;
+
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+import dagger.Lazy;
+
+/**
+ * Implements {@link SessionHandler} for the given instance of Custom Tab activity; registers and
+ * unregisters itself in {@link SessionDataHolder}.
+ */
+@ActivityScope
+public class CustomTabSessionHandler implements SessionHandler, StartStopWithNativeObserver {
+
+    private static final String TAG = "CctSessionHandler";
+
+    private final CustomTabIntentDataProvider mIntentDataProvider;
+    private final CustomTabActivityTabProvider mTabProvider;
+    private final Lazy<CustomTabToolbarCoordinator> mToolbarCoordinator;
+    private final Lazy<CustomTabBottomBarDelegate> mBottomBarDelegate;
+    private final CustomTabIntentHandler mIntentHandler;
+    private final CustomTabsConnection mConnection;
+    private final SessionDataHolder mSessionDataHolder;
+    private final Activity mActivity;
+
+    @Inject
+    public CustomTabSessionHandler(CustomTabIntentDataProvider intentDataProvider,
+            CustomTabActivityTabProvider tabProvider,
+            Lazy<CustomTabToolbarCoordinator> toolbarCoordinator,
+            Lazy<CustomTabBottomBarDelegate> bottomBarDelegate,
+            CustomTabIntentHandler intentHandler,
+            CustomTabsConnection connection,
+            Activity activity,
+            ActivityLifecycleDispatcher lifecycleDispatcher,
+            SessionDataHolder sessionDataHolder) {
+        mIntentDataProvider = intentDataProvider;
+        mTabProvider = tabProvider;
+        mToolbarCoordinator = toolbarCoordinator;
+        mBottomBarDelegate = bottomBarDelegate;
+        mIntentHandler = intentHandler;
+        mConnection = connection;
+        mActivity = activity;
+        mSessionDataHolder = sessionDataHolder;
+        lifecycleDispatcher.register(this);
+    }
+
+    @Override
+    public void onStartWithNative() {
+        mSessionDataHolder.setActiveHandler(this);
+    }
+
+    @Override
+    public void onStopWithNative() {
+        mSessionDataHolder.removeActiveHandler(this);
+    }
+
+    @Override
+    public CustomTabsSessionToken getSession() {
+        return mIntentDataProvider.getSession();
+    }
+
+    @Override
+    public boolean updateCustomButton(int id, Bitmap bitmap, String description) {
+        CustomButtonParams params = mIntentDataProvider.getButtonParamsForId(id);
+        if (params == null) {
+            Log.w(TAG, "Custom toolbar button with ID %d not found", id);
+            return false;
+        }
+
+        params.update(bitmap, description);
+        if (params.showOnToolbar()) {
+            return mToolbarCoordinator.get().updateCustomButton(params);
+        }
+        mBottomBarDelegate.get().updateBottomBarButtons(params);
+        return true;
+    }
+
+    @Override
+    public boolean updateRemoteViews(RemoteViews remoteViews, int[] clickableIDs,
+            PendingIntent pendingIntent) {
+        return mBottomBarDelegate.get().updateRemoteViews(remoteViews, clickableIDs, pendingIntent);
+    }
+
+    @Override
+    @Nullable
+    public String getCurrentUrl() {
+        Tab tab = mTabProvider.getTab();
+        return tab == null ? null : tab.getUrl();
+    }
+
+    @Override
+    @Nullable
+    public String getPendingUrl() {
+        Tab tab = mTabProvider.getTab();
+        if (tab == null || tab.getWebContents() == null) return null;
+
+        NavigationEntry entry = tab.getWebContents().getNavigationController()
+                .getPendingEntry();
+        return entry != null ? entry.getUrl() : null;
+    }
+
+    @Override
+    public int getTaskId() {
+        return mActivity.getTaskId();
+    }
+
+    @Override
+    public Class<? extends Activity> getActivityClass() {
+        return mActivity.getClass();
+    }
+
+    @Override
+    public boolean handleIntent(Intent intent) {
+        // This method exists only for legacy reasons, see LaunchIntentDispatcher#
+        // clearTopIntentsForCustomTabsEnabled.
+        CustomTabIntentDataProvider dataProvider = new CustomTabIntentDataProvider(intent,
+                mActivity, CustomTabsIntent.COLOR_SCHEME_LIGHT);
+
+        return mIntentHandler.onNewIntent(dataProvider);
+    }
+
+    @Override
+    public boolean canUseReferrer(Uri referrer) {
+        CustomTabsSessionToken session = mIntentDataProvider.getSession();
+        String packageName = mConnection.getClientPackageNameForSession(session);
+        if (TextUtils.isEmpty(packageName)) return false;
+        return OriginVerifier.wasPreviouslyVerified(
+                packageName, new Origin(referrer), CustomTabsService.RELATION_USE_AS_ORIGIN);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
index 9edac88..1aba9d4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
@@ -8,13 +8,14 @@
 import org.chromium.chrome.browser.customtabs.CustomTabActivityLifecycleUmaTracker;
 import org.chromium.chrome.browser.customtabs.CustomTabBottomBarDelegate;
 import org.chromium.chrome.browser.customtabs.CustomTabCompositorContentInitializer;
+import org.chromium.chrome.browser.customtabs.CustomTabSessionHandler;
 import org.chromium.chrome.browser.customtabs.CustomTabStatusBarColorProvider;
 import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy;
-import org.chromium.chrome.browser.customtabs.content.CustomTabIntentHandler;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabFactory;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
+import org.chromium.chrome.browser.customtabs.content.CustomTabIntentHandler;
 import org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleCoordinator;
 import org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleToolbarController;
 import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbarCoordinator;
@@ -45,6 +46,7 @@
     CustomTabStatusBarColorProvider resolveCustomTabStatusBarColorProvider();
     CustomTabToolbarCoordinator resolveToolbarCoordinator();
     CustomTabCompositorContentInitializer resolveCompositorContentInitializer();
+    CustomTabSessionHandler resolveSessionHandler();
 
     CustomTabTabPersistencePolicy resolveTabPersistencePolicy(); // For testing
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java
index f451e7c..e7d495b5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java
@@ -10,6 +10,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.os.Build;
 import android.text.TextUtils;
 
 import org.chromium.base.BuildInfo;
@@ -127,9 +128,26 @@
      * Returns true if we should open the dialer straight away.
      */
     private static boolean shouldOpenDialer() {
-        // On Q and above, we never open the dialer directly. On pre-Q, we always open the dialer
-        // directly.
-        return !BuildInfo.isAtLeastQ() && FeatureUtilities.isClickToCallOpenDialerDirectlyEnabled();
+        if (!FeatureUtilities.isClickToCallOpenDialerDirectlyEnabled()) {
+            return false;
+        }
+
+        // On Android Q and above, we never open the dialer directly.
+        if (BuildInfo.isAtLeastQ()) {
+            return false;
+        }
+
+        // On Android N and below, we always open the dialer. If device is locked, we also show a
+        // notification. We can listen to ACTION_USER_PRESENT and remove this notification when
+        // device is unlocked.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+            return true;
+        }
+
+        // On Android O and P, we open dialer only when device is unlocked since we cannot listen to
+        // ACTION_USER_PRESENT.
+        return DeviceConditions.isCurrentlyScreenOnAndUnlocked(
+                ContextUtils.getApplicationContext());
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
index 91882b8..37077f7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -31,10 +31,13 @@
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.AccountTrackerService;
 import org.chromium.components.signin.ChromeSigninController;
+import org.chromium.components.signin.identitymanager.ClearAccountsAction;
 import org.chromium.components.signin.identitymanager.CoreAccountInfo;
 import org.chromium.components.signin.identitymanager.IdentityManager;
+import org.chromium.components.signin.identitymanager.PrimaryAccountMutator;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 import org.chromium.components.signin.metrics.SigninReason;
+import org.chromium.components.signin.metrics.SignoutDelete;
 import org.chromium.components.signin.metrics.SignoutReason;
 import org.chromium.components.sync.AndroidSyncSettings;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
@@ -191,6 +194,7 @@
     private final Context mContext;
     private final AccountTrackerService mAccountTrackerService;
     private final IdentityManager mIdentityManager;
+    private final PrimaryAccountMutator mPrimaryAccountMutator;
     private final AndroidSyncSettings mAndroidSyncSettings;
     private final ObserverList<SignInStateObserver> mSignInStateObservers = new ObserverList<>();
     private final ObserverList<SignInAllowedObserver> mSignInAllowedObservers =
@@ -245,6 +249,7 @@
         mNativeSigninManagerAndroid = nativeSigninManagerAndroid;
         mAccountTrackerService = accountTrackerService;
         mIdentityManager = identityManager;
+        mPrimaryAccountMutator = identityManager.getPrimaryAccountMutator();
         mAndroidSyncSettings = androidSyncSettings;
 
         mSigninAllowedByPolicy =
@@ -402,6 +407,7 @@
      * @param activity The activity used to launch UI prompts, or null for a forced signin.
      * @param callback Optional callback for when the sign-in process is finished.
      */
+    // TODO(crbug.com/1002056) SigninManager.Signin should use CoreAccountInfo as a parameter.
     public void signIn(
             Account account, @Nullable Activity activity, @Nullable SignInCallback callback) {
         if (account == null) {
@@ -431,6 +437,7 @@
     /**
      * Same as above but retrieves the Account object for the given accountName.
      */
+    // TODO(crbug.com/1002056) SigninManager.Signin should use CoreAccountInfo as a parameter.
     public void signIn(String accountName, @Nullable final Activity activity,
             @Nullable final SignInCallback callback) {
         AccountManagerFacade.get().getAccountFromName(
@@ -481,8 +488,13 @@
         // This method should be called at most once per sign-in flow.
         assert mSignInState != null;
 
-        if (!SigninManagerJni.get().setPrimaryAccount(
-                    mNativeSigninManagerAndroid, mSignInState.mAccount.name)) {
+        // TODO(crbug.com/1002056) When changing SignIn signature to use CoreAccountInfo, change the
+        // following line to use it instead of retrieving from IdentityManager.
+        if (!mPrimaryAccountMutator.setPrimaryAccount(
+                    mIdentityManager
+                            .findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
+                                    mSignInState.mAccount.name)
+                            .getId())) {
             Log.w(TAG, "Failed to set the PrimaryAccount in IdentityManager, aborting signin");
             abortSignIn();
             return;
@@ -524,7 +536,7 @@
      * Implements {@link IdentityManager.Observer}: take action when primary account is set.
      * Simply verify that the request is ongoing (mSignInState != null), as only SigninManager
      * should update IdentityManager. This is triggered by the call to
-     * SigninManagerJni.get().setPrimaryAccount.
+     * PrimaryAccountMutator.setPrimaryAccount
      */
     @VisibleForTesting
     @Override
@@ -616,7 +628,11 @@
 
         // User data will be wiped in disableSyncAndWipeData(), called from
         // onPrimaryAccountcleared().
-        SigninManagerJni.get().signOut(mNativeSigninManagerAndroid, signoutSource);
+        mPrimaryAccountMutator.clearPrimaryAccount(ClearAccountsAction.DEFAULT, signoutSource,
+                // Always use IGNORE_METRIC for the profile deletion argument. Chrome
+                // Android has just a single-profile which is never deleted upon
+                // sign-out.
+                SignoutDelete.IGNORE_METRIC);
     }
 
     /**
@@ -768,10 +784,6 @@
 
         boolean isForceSigninEnabled(long nativeSigninManagerAndroid);
 
-        boolean setPrimaryAccount(long nativeSigninManagerAndroid, String username);
-
-        void signOut(long nativeSigninManagerAndroid, @SignoutReason int reason);
-
         void clearLastSignedInUser(long nativeSigninManagerAndroid);
 
         void logInSignedInUser(long nativeSigninManagerAndroid);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
index d58e391..150d4ef 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
@@ -15,6 +15,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.MockitoAnnotations.initMocks;
@@ -36,6 +37,7 @@
 import org.chromium.components.signin.identitymanager.CoreAccountId;
 import org.chromium.components.signin.identitymanager.CoreAccountInfo;
 import org.chromium.components.signin.identitymanager.IdentityManager;
+import org.chromium.components.signin.identitymanager.PrimaryAccountMutator;
 import org.chromium.components.signin.metrics.SignoutReason;
 import org.chromium.components.sync.AndroidSyncSettings;
 
@@ -53,6 +55,7 @@
 
     private AccountTrackerService mAccountTrackerService;
     private IdentityManager mIdentityManager;
+    private PrimaryAccountMutator mPrimaryAccountMutator;
     private SigninManager mSigninManager;
     private CoreAccountInfo mAccount;
 
@@ -66,7 +69,10 @@
 
         mAccountTrackerService = mock(AccountTrackerService.class);
 
-        mIdentityManager = new IdentityManager(0 /* nativeIdentityManager */);
+        mPrimaryAccountMutator = mock(PrimaryAccountMutator.class);
+
+        mIdentityManager =
+                spy(new IdentityManager(0 /* nativeIdentityManager */, mPrimaryAccountMutator));
 
         AndroidSyncSettings androidSyncSettings = mock(AndroidSyncSettings.class);
 
@@ -75,7 +81,7 @@
                 androidSyncSettings);
 
         mAccount = new CoreAccountInfo(new CoreAccountId("gaia-id-user"),
-                AccountManagerFacade.createAccountFromName("user@domain.com"));
+                AccountManagerFacade.createAccountFromName("user@domain.com"), "gaia-id-user");
     }
 
     @Test
@@ -186,8 +192,8 @@
             mIdentityManager.onPrimaryAccountCleared(mAccount);
             return null;
         })
-                .when(mNativeMock)
-                .signOut(anyLong(), anyInt());
+                .when(mPrimaryAccountMutator)
+                .clearPrimaryAccount(anyInt(), anyInt(), anyInt());
 
         mSigninManager.signOut(SignoutReason.SIGNOUT_TEST);
         assertTrue(mSigninManager.isOperationInProgress());
@@ -202,19 +208,25 @@
 
     @Test
     public void callbackNotifiedOnSignin() {
+        CoreAccountInfo account = new CoreAccountInfo(new CoreAccountId("test_at_gmail.com"),
+                new Account("test@gmail.com", AccountManagerFacade.GOOGLE_ACCOUNT_TYPE),
+                "test_at_gmail.com");
+
         // No need to seed accounts to the native code.
         doReturn(true).when(mAccountTrackerService).checkAndSeedSystemAccounts();
         // Request that policy is loaded. It will pause sign-in until onPolicyCheckedBeforeSignIn is
         // invoked.
         doNothing().when(mNativeMock).fetchAndApplyCloudPolicy(anyLong(), any(), any());
 
-        doReturn(true).when(mNativeMock).setPrimaryAccount(anyLong(), any());
+        doReturn(account)
+                .when(mIdentityManager)
+                .findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(any());
+        doReturn(true).when(mPrimaryAccountMutator).setPrimaryAccount(any());
         doNothing().when(mNativeMock).logInSignedInUser(anyLong());
 
         mSigninManager.onFirstRunCheckDone(); // Allow sign-in.
 
-        Account account = new Account("test@gmail.com", AccountManagerFacade.GOOGLE_ACCOUNT_TYPE);
-        mSigninManager.signIn(account, null, null);
+        mSigninManager.signIn(account.getAccount(), null, null);
         assertTrue(mSigninManager.isOperationInProgress());
         AtomicInteger callCount = new AtomicInteger(0);
         mSigninManager.runAfterOperationInProgress(callCount::incrementAndGet);
diff --git a/chrome/browser/android/customtabs/detached_resource_request.cc b/chrome/browser/android/customtabs/detached_resource_request.cc
index 2b94bc8..0e90fa0 100644
--- a/chrome/browser/android/customtabs/detached_resource_request.cc
+++ b/chrome/browser/android/customtabs/detached_resource_request.cc
@@ -79,7 +79,8 @@
   resource_request->url = url_;
   // The referrer is stripped if it's not set properly initially.
   resource_request->referrer = net::URLRequestJob::ComputeReferrerForPolicy(
-      referrer_policy, site_for_cookies_, url_);
+      referrer_policy, site_for_cookies_,
+      url::Origin::Create(site_for_cookies_), url_);
   resource_request->referrer_policy = referrer_policy;
   resource_request->site_for_cookies = site_for_cookies_;
   resource_request->request_initiator = url::Origin::Create(site_for_cookies_);
diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/browser/android/signin/signin_manager_android.cc
index e128237..f9a6e7d 100644
--- a/chrome/browser/android/signin/signin_manager_android.cc
+++ b/chrome/browser/android/signin/signin_manager_android.cc
@@ -161,35 +161,6 @@
                              java_signin_manager_);
 }
 
-jboolean SigninManagerAndroid::SetPrimaryAccount(
-    JNIEnv* env,
-    const JavaParamRef<jstring>& username) {
-  DVLOG(1) << "SigninManagerAndroid::SetPrimaryAccount";
-
-  auto account =
-      identity_manager_
-          ->FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
-              base::android::ConvertJavaStringToUTF8(env, username));
-  DCHECK(account.has_value());
-  auto* account_mutator = identity_manager_->GetPrimaryAccountMutator();
-  return account_mutator->SetPrimaryAccount(account->account_id);
-}
-
-void SigninManagerAndroid::SignOut(JNIEnv* env,
-                                   jint signoutReason) {
-  auto* account_mutator = identity_manager_->GetPrimaryAccountMutator();
-
-  // GetPrimaryAccountMutator() returns nullptr on ChromeOS only.
-  DCHECK(account_mutator);
-  account_mutator->ClearPrimaryAccount(
-      signin::PrimaryAccountMutator::ClearAccountsAction::kDefault,
-      static_cast<signin_metrics::ProfileSignout>(signoutReason),
-      // Always use IGNORE_METRIC for the profile deletion argument. Chrome
-      // Android has just a single-profile which is never deleted upon
-      // sign-out.
-      signin_metrics::SignoutDelete::IGNORE_METRIC);
-}
-
 void SigninManagerAndroid::ClearLastSignedInUser(JNIEnv* env) {
   ClearLastSignedInUserForProfile(profile_);
 }
diff --git a/chrome/browser/android/signin/signin_manager_android.h b/chrome/browser/android/signin/signin_manager_android.h
index 1c8f5a3..fc1c3df 100644
--- a/chrome/browser/android/signin/signin_manager_android.h
+++ b/chrome/browser/android/signin/signin_manager_android.h
@@ -45,15 +45,6 @@
 
   base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
 
-  // Indicates that the user has made the choice to sign-in. |username|
-  // contains the email address of the account to use as primary.
-  jboolean SetPrimaryAccount(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jstring>& username);
-
-  void SignOut(JNIEnv* env,
-               jint signoutReason);
-
   void LogInSignedInUser(JNIEnv* env);
 
   void ClearLastSignedInUser(JNIEnv* env);
diff --git a/chrome/browser/apps/app_service/app_service_proxy.cc b/chrome/browser/apps/app_service/app_service_proxy.cc
index cf26ed2..e8c5fc7 100644
--- a/chrome/browser/apps/app_service/app_service_proxy.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy.cc
@@ -86,6 +86,22 @@
       icon_coalescer_(&inner_icon_loader_),
       outer_icon_loader_(&icon_coalescer_,
                          apps::IconCache::GarbageCollectionPolicy::kEager) {
+  Initialize(profile, connector);
+}
+
+AppServiceProxy::~AppServiceProxy() = default;
+
+void AppServiceProxy::ReInitializeForTesting(
+    Profile* profile,
+    service_manager::Connector* connector) {
+  // Some test code creates a profile and profile-linked services, like the App
+  // Service without linking to the correct connector. To work around that, we
+  // issue a second Initialize call to set the connector.
+  Initialize(profile, connector);
+}
+
+void AppServiceProxy::Initialize(Profile* profile,
+                                 service_manager::Connector* connector) {
   if (!profile) {
     return;
   }
@@ -125,8 +141,6 @@
   }
 }
 
-AppServiceProxy::~AppServiceProxy() = default;
-
 apps::mojom::AppServicePtr& AppServiceProxy::AppService() {
   return app_service_;
 }
diff --git a/chrome/browser/apps/app_service/app_service_proxy.h b/chrome/browser/apps/app_service/app_service_proxy.h
index fbdac3a..9ddf038 100644
--- a/chrome/browser/apps/app_service/app_service_proxy.h
+++ b/chrome/browser/apps/app_service/app_service_proxy.h
@@ -47,6 +47,9 @@
 
   ~AppServiceProxy() override;
 
+  void ReInitializeForTesting(Profile* profile,
+                              service_manager::Connector* connector);
+
   apps::mojom::AppServicePtr& AppService();
   apps::AppRegistryCache& AppRegistryCache();
 
@@ -141,6 +144,8 @@
 
   AppServiceProxy(Profile* profile, service_manager::Connector* connector);
 
+  void Initialize(Profile* profile, service_manager::Connector* connector);
+
   void AddAppIconSource(Profile* profile);
 
   // KeyedService overrides.
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc
index 7843758..a9ad356 100644
--- a/chrome/browser/apps/app_service/extension_apps.cc
+++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -420,7 +420,7 @@
       break;
     case extensions::UnloadedExtensionReason::UNINSTALL:
       readiness = apps::mojom::Readiness::kUninstalledByUser;
-      return;
+      break;
     default:
       return;
   }
diff --git a/chrome/browser/apps/user_type_filter_unittest.cc b/chrome/browser/apps/user_type_filter_unittest.cc
index 5717ef4..4bb54f5 100644
--- a/chrome/browser/apps/user_type_filter_unittest.cc
+++ b/chrome/browser/apps/user_type_filter_unittest.cc
@@ -26,7 +26,7 @@
   auto root = std::make_unique<base::DictionaryValue>();
   base::ListValue filter;
   for (const auto& user_type : user_types)
-    filter.GetList().push_back(base::Value(user_type));
+    filter.Append(base::Value(user_type));
   root->SetKey(kKeyUserType, std::move(filter));
   return root;
 }
@@ -123,8 +123,8 @@
 TEST_F(UserTypeFilterTest, DefaultFilter) {
   auto profile = CreateProfile();
   base::ListValue default_filter;
-  default_filter.GetList().push_back(base::Value(kUserTypeUnmanaged));
-  default_filter.GetList().push_back(base::Value(kUserTypeGuest));
+  default_filter.Append(base::Value(kUserTypeUnmanaged));
+  default_filter.Append(base::Value(kUserTypeGuest));
 
   // Unmanaged user.
   EXPECT_TRUE(MatchDefault(profile, default_filter));
diff --git a/chrome/browser/autofill/automated_tests/cache_replayer_unittest.cc b/chrome/browser/autofill/automated_tests/cache_replayer_unittest.cc
index 403f18f..6ea658d 100644
--- a/chrome/browser/autofill/automated_tests/cache_replayer_unittest.cc
+++ b/chrome/browser/autofill/automated_tests/cache_replayer_unittest.cc
@@ -179,8 +179,7 @@
     // Populate json dict node that contains Autofill Server requests per URL.
     if (urls_dict.find(url) == urls_dict.end())
       urls_dict[url] = std::make_unique<Value>(Value::ListStorage());
-    urls_dict[url]->GetList().push_back(
-        Value(std::move(request_response_node)));
+    urls_dict[url]->Append(Value(std::move(request_response_node)));
   }
 
   // Make json dict node that contains requests per domain.
@@ -285,7 +284,7 @@
   std::string invalid_request_url = GetParam();
   urls_dict[invalid_request_url] =
       std::make_unique<Value>(Value::ListStorage());
-  urls_dict[invalid_request_url]->GetList().push_back(
+  urls_dict[invalid_request_url]->Append(
       Value(std::move(request_response_node)));
 
   // Make json dict node that contains requests per domain.
diff --git a/chrome/browser/browser_switcher/alternative_browser_driver_unittest.cc b/chrome/browser/browser_switcher/alternative_browser_driver_unittest.cc
index 7041afc..33fc1c3 100644
--- a/chrome/browser/browser_switcher/alternative_browser_driver_unittest.cc
+++ b/chrome/browser/browser_switcher/alternative_browser_driver_unittest.cc
@@ -43,7 +43,7 @@
   base::ListValue out;
   out.GetList().reserve(src.size());
   for (base::StringPiece str : src)
-    out.GetList().push_back(base::Value(str));
+    out.Append(base::Value(str));
   return out;
 }
 
diff --git a/chrome/browser/browser_switcher/browser_switcher_browsertest.cc b/chrome/browser/browser_switcher/browser_switcher_browsertest.cc
index 99606ea..bef8fe8 100644
--- a/chrome/browser/browser_switcher/browser_switcher_browsertest.cc
+++ b/chrome/browser/browser_switcher/browser_switcher_browsertest.cc
@@ -86,12 +86,12 @@
 
   base::ListValue params;
   for (size_t i = 1; i < cmd_line.argv().size(); i++)
-    params.GetList().emplace_back(NativeToUTF8(cmd_line.argv()[i]));
+    params.Append(NativeToUTF8(cmd_line.argv()[i]));
   SetPolicy(&map, policy::key::kAlternativeBrowserParameters,
             std::make_unique<base::Value>(std::move(params)));
 
   base::ListValue sitelist;
-  sitelist.GetList().emplace_back("example.com");
+  sitelist.Append("example.com");
   SetPolicy(&map, policy::key::kBrowserSwitcherUrlList,
             std::make_unique<base::Value>(std::move(sitelist)));
 
diff --git a/chrome/browser/browser_switcher/browser_switcher_policy_migrator.cc b/chrome/browser/browser_switcher/browser_switcher_policy_migrator.cc
index 6bfdaf0..a1b3249 100644
--- a/chrome/browser/browser_switcher/browser_switcher_policy_migrator.cc
+++ b/chrome/browser/browser_switcher/browser_switcher_policy_migrator.cc
@@ -38,7 +38,7 @@
 void StringToList(base::Value* val) {
   std::string str = val->GetString();
   *val = base::Value(base::Value::Type::LIST);
-  val->GetList().push_back(base::Value(std::move(str)));
+  val->Append(base::Value(std::move(str)));
 }
 
 }  // namespace
diff --git a/chrome/browser/browser_switcher/browser_switcher_prefs.cc b/chrome/browser/browser_switcher/browser_switcher_prefs.cc
index 44d0ac2..e95e216 100644
--- a/chrome/browser/browser_switcher/browser_switcher_prefs.cc
+++ b/chrome/browser/browser_switcher/browser_switcher_prefs.cc
@@ -33,7 +33,7 @@
                     const std::vector<std::string>& rules) {
   base::ListValue rules_val;
   for (const auto& url : rules)
-    rules_val.GetList().push_back(base::Value(url));
+    rules_val.Append(base::Value(url));
   prefs->Set(pref_name, rules_val);
 }
 
diff --git a/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc b/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc
index 870bed8..360310c 100644
--- a/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc
+++ b/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc
@@ -419,7 +419,7 @@
   policy::PolicyMap policies;
   EnableBrowserSwitcher(&policies);
   auto url_list = std::make_unique<base::ListValue>();
-  url_list->GetList().emplace_back("*");
+  url_list->Append("*");
   SetPolicy(&policies, policy::key::kBrowserSwitcherUrlList,
             std::move(url_list));
   SetPolicy(&policies, policy::key::kBrowserSwitcherExternalGreylistUrl,
@@ -654,21 +654,21 @@
   SetPolicy(&policies, policy::key::kAlternativeBrowserPath,
             std::make_unique<base::Value>("IExplore.exe"));
   auto alt_params = std::make_unique<base::ListValue>();
-  alt_params->GetList().push_back(base::Value("--bogus-flag"));
+  alt_params->Append(base::Value("--bogus-flag"));
   SetPolicy(&policies, policy::key::kAlternativeBrowserParameters,
             std::move(alt_params));
   SetPolicy(&policies, policy::key::kBrowserSwitcherChromePath,
             std::make_unique<base::Value>("chrome.exe"));
   auto chrome_params = std::make_unique<base::ListValue>();
-  chrome_params->GetList().push_back(base::Value("--force-dark-mode"));
+  chrome_params->Append(base::Value("--force-dark-mode"));
   SetPolicy(&policies, policy::key::kBrowserSwitcherChromeParameters,
             std::move(chrome_params));
   auto url_list = std::make_unique<base::ListValue>();
-  url_list->GetList().push_back(base::Value("example.com"));
+  url_list->Append(base::Value("example.com"));
   SetPolicy(&policies, policy::key::kBrowserSwitcherUrlList,
             std::move(url_list));
   auto greylist = std::make_unique<base::ListValue>();
-  greylist->GetList().push_back(base::Value("foo.example.com"));
+  greylist->Append(base::Value("foo.example.com"));
   SetPolicy(&policies, policy::key::kBrowserSwitcherUrlGreylist,
             std::move(greylist));
   policy_provider().UpdateChromePolicy(policies);
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 5ca6076..1e9fd93 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1923,7 +1923,7 @@
   base::ListValue* list = update.Get();
   base::Value value(origin.Serialize());
   if (!base::Contains(list->GetList(), value))
-    list->GetList().push_back(std::move(value));
+    list->Append(std::move(value));
 }
 
 bool ChromeContentBrowserClient::IsFileAccessAllowed(
@@ -4653,22 +4653,14 @@
     RegisterNonNetworkServiceWorkerUpdateURLLoaderFactories(
         content::BrowserContext* browser_context,
         NonNetworkURLLoaderFactoryMap* factories) {
-#if BUILDFLAG(ENABLE_EXTENSIONS) || defined(OS_CHROMEOS)
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   DCHECK(browser_context);
   DCHECK(factories);
-#if BUILDFLAG(ENABLE_EXTENSIONS)
   factories->emplace(
       extensions::kExtensionScheme,
       extensions::CreateExtensionServiceWorkerScriptURLLoaderFactory(
           browser_context));
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
-#if defined(OS_CHROMEOS)
-  Profile* profile = Profile::FromBrowserContext(browser_context);
-  factories->emplace(content::kExternalFileScheme,
-                     std::make_unique<chromeos::ExternalFileURLLoaderFactory>(
-                         profile, content::ChildProcessHost::kInvalidUniqueID));
-#endif  // defined(OS_CHROMEOS)
-#endif  // BUILDFLAG(ENABLE_EXTENSIONS) || defined(OS_CHROMEOS)
 }
 
 namespace {
@@ -4968,7 +4960,7 @@
       network_service);
 }
 
-network::mojom::NetworkContextPtr
+mojo::Remote<network::mojom::NetworkContext>
 ChromeContentBrowserClient::CreateNetworkContext(
     content::BrowserContext* context,
     bool in_memory,
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 6bb5019..a219479 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -498,7 +498,7 @@
       override;
   void OnNetworkServiceCreated(
       network::mojom::NetworkService* network_service) override;
-  network::mojom::NetworkContextPtr CreateNetworkContext(
+  mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext(
       content::BrowserContext* context,
       bool in_memory,
       const base::FilePath& relative_partition_path) override;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 13604ed..f53e5a5 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1310,6 +1310,8 @@
     "login/saml/in_session_password_change_manager.h",
     "login/saml/password_expiry_notification.cc",
     "login/saml/password_expiry_notification.h",
+    "login/saml/public_saml_url_fetcher.cc",
+    "login/saml/public_saml_url_fetcher.h",
     "login/saml/saml_offline_signin_limiter.cc",
     "login/saml/saml_offline_signin_limiter.h",
     "login/saml/saml_offline_signin_limiter_factory.cc",
diff --git a/chrome/browser/chromeos/arc/policy/arc_policy_util.h b/chrome/browser/chromeos/arc/policy/arc_policy_util.h
index 238a18f..96f6f78 100644
--- a/chrome/browser/chromeos/arc/policy/arc_policy_util.h
+++ b/chrome/browser/chromeos/arc/policy/arc_policy_util.h
@@ -57,7 +57,7 @@
 
 // Returns set of packages requested to install from |arc_policy|. |arc_policy|
 // has JSON blob format, see
-// https://www.chromium.org/administrators/policy-list-3#ArcPolicy
+// https://cloud.google.com/docs/chrome-enterprise/policies/?policy=ArcPolicy
 std::set<std::string> GetRequestedPackagesFromArcPolicy(
     const std::string& arc_policy);
 
diff --git a/chrome/browser/chromeos/crostini/ansible/ansible_management_service.cc b/chrome/browser/chromeos/crostini/ansible/ansible_management_service.cc
index a88169f..393abb0 100644
--- a/chrome/browser/chromeos/crostini/ansible/ansible_management_service.cc
+++ b/chrome/browser/chromeos/crostini/ansible/ansible_management_service.cc
@@ -7,7 +7,9 @@
 #include "base/logging.h"
 #include "base/no_destructor.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager_factory.h"
+#include "chrome/browser/chromeos/crostini/crostini_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
@@ -48,6 +50,10 @@
   }
 };
 
+chromeos::CiceroneClient* GetCiceroneClient() {
+  return chromeos::DBusThreadManager::Get()->GetCiceroneClient();
+}
+
 }  // namespace
 
 AnsibleManagementService* AnsibleManagementService::GetForProfile(
@@ -123,8 +129,71 @@
 }
 
 void AnsibleManagementService::ApplyAnsiblePlaybookToDefaultContainer(
-    const std::string& playbook) {
-  NOTIMPLEMENTED();
+    const std::string& playbook,
+    base::OnceCallback<void(bool success)> callback) {
+  if (!GetCiceroneClient()->IsApplyAnsiblePlaybookProgressSignalConnected()) {
+    // Technically we could still start the application, but we wouldn't be able
+    // to detect when the application completes, successfully or otherwise.
+    LOG(ERROR)
+        << "Attempted to apply playbook when progress signal not connected.";
+    std::move(callback).Run(/*success=*/false);
+    return;
+  }
+
+  DCHECK(ansible_playbook_application_finished_callback_.is_null());
+  ansible_playbook_application_finished_callback_ = std::move(callback);
+
+  vm_tools::cicerone::ApplyAnsiblePlaybookRequest request;
+  request.set_owner_id(CryptohomeIdForProfile(profile_));
+  request.set_vm_name(std::move(kCrostiniDefaultContainerName));
+  request.set_container_name(std::move(kCrostiniDefaultContainerName));
+  request.set_playbook(std::move(playbook));
+
+  GetCiceroneClient()->ApplyAnsiblePlaybook(
+      std::move(request),
+      base::BindOnce(&AnsibleManagementService::OnApplyAnsiblePlaybook,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void AnsibleManagementService::OnApplyAnsiblePlaybook(
+    base::Optional<vm_tools::cicerone::ApplyAnsiblePlaybookResponse> response) {
+  if (!response) {
+    LOG(ERROR) << "Failed to apply Ansible playbook. Empty response.";
+    std::move(ansible_playbook_application_finished_callback_)
+        .Run(/*success=*/false);
+    return;
+  }
+
+  if (response->status() ==
+      vm_tools::cicerone::ApplyAnsiblePlaybookResponse::FAILED) {
+    LOG(ERROR) << "Failed to apply Ansible playbook: "
+               << response->failure_reason();
+    std::move(ansible_playbook_application_finished_callback_)
+        .Run(/*success=*/false);
+    return;
+  }
+
+  VLOG(1) << "Ansible playbook application has been started successfully";
+  // Waiting for Ansible playbook application progress being reported.
+}
+
+void AnsibleManagementService::OnApplyAnsiblePlaybookProgress(
+    vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::Status status) {
+  switch (status) {
+    case vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::SUCCEEDED:
+      std::move(ansible_playbook_application_finished_callback_)
+          .Run(/*success=*/true);
+      break;
+    case vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::FAILED:
+      std::move(ansible_playbook_application_finished_callback_)
+          .Run(/*success=*/false);
+      break;
+    case vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::IN_PROGRESS:
+      // TODO(okalitova): Report Ansible playbook application progress.
+      break;
+    default:
+      NOTREACHED();
+  }
 }
 
 }  // namespace crostini
diff --git a/chrome/browser/chromeos/crostini/ansible/ansible_management_service.h b/chrome/browser/chromeos/crostini/ansible/ansible_management_service.h
index ba5e5a6b..c9f7734 100644
--- a/chrome/browser/chromeos/crostini/ansible/ansible_management_service.h
+++ b/chrome/browser/chromeos/crostini/ansible/ansible_management_service.h
@@ -29,10 +29,14 @@
   explicit AnsibleManagementService(Profile* profile);
   ~AnsibleManagementService() override;
 
+  // |callback| is called once Ansible installation is finished.
   void InstallAnsibleInDefaultContainer(
       base::OnceCallback<void(bool success)> callback);
 
-  void ApplyAnsiblePlaybookToDefaultContainer(const std::string& playbook);
+  // |callback| is called once Ansible playbook application is finished.
+  void ApplyAnsiblePlaybookToDefaultContainer(
+      const std::string& playbook,
+      base::OnceCallback<void(bool success)> callback);
 
   // LinuxPackageOperationProgressObserver:
   void OnInstallLinuxPackageProgress(const std::string& vm_name,
@@ -44,12 +48,23 @@
                                   UninstallPackageProgressStatus status,
                                   int progress_percent) override;
 
+  void OnApplyAnsiblePlaybookProgress(
+      vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::Status status);
+
  private:
   void OnInstallAnsibleInDefaultContainer(CrostiniResult result);
 
+  // Callback for
+  // CrostiniAnsibleManagementService::ApplyAnsiblePlaybookToDefaultContainer
+  void OnApplyAnsiblePlaybook(
+      base::Optional<vm_tools::cicerone::ApplyAnsiblePlaybookResponse>
+          response);
+
   Profile* profile_;
   base::OnceCallback<void(bool success)>
       ansible_installation_finished_callback_;
+  base::OnceCallback<void(bool success)>
+      ansible_playbook_application_finished_callback_;
   base::WeakPtrFactory<AnsibleManagementService> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(AnsibleManagementService);
diff --git a/chrome/browser/chromeos/crostini/ansible/ansible_management_service_unittest.cc b/chrome/browser/chromeos/crostini/ansible/ansible_management_service_unittest.cc
index d6993a1..5ba744c 100644
--- a/chrome/browser/chromeos/crostini/ansible/ansible_management_service_unittest.cc
+++ b/chrome/browser/chromeos/crostini/ansible/ansible_management_service_unittest.cc
@@ -22,11 +22,13 @@
     fake_cicerone_client_ = static_cast<chromeos::FakeCiceroneClient*>(
         chromeos::DBusThreadManager::Get()->GetCiceroneClient());
     profile_ = std::make_unique<TestingProfile>();
+    crostini_manager_ = CrostiniManager::GetForProfile(profile_.get());
     ansible_management_service_ =
-        std::make_unique<AnsibleManagementService>(profile_.get());
+        AnsibleManagementService::GetForProfile(profile_.get());
   }
   ~AnsibleManagementServiceTest() override {
-    ansible_management_service_.reset();
+    ansible_management_service_->Shutdown();
+    crostini_manager_->Shutdown();
     profile_.reset();
     chromeos::DBusThreadManager::Shutdown();
   }
@@ -35,7 +37,7 @@
   Profile* profile() { return profile_.get(); }
 
   AnsibleManagementService* ansible_management_service() {
-    return ansible_management_service_.get();
+    return ansible_management_service_;
   }
 
   void SendSucceededInstallSignal() {
@@ -49,11 +51,25 @@
     fake_cicerone_client_->InstallLinuxPackageProgress(signal);
   }
 
+  void SendSucceededApplicationSignal() {
+    vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal signal;
+    signal.set_owner_id(CryptohomeIdForProfile(profile()));
+    signal.set_vm_name(kCrostiniDefaultVmName);
+    signal.set_container_name(kCrostiniDefaultContainerName);
+    signal.set_status(
+        vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::SUCCEEDED);
+
+    fake_cicerone_client_->NotifyApplyAnsiblePlaybookProgress(signal);
+  }
+
   content::BrowserTaskEnvironment task_environment_;
   std::unique_ptr<TestingProfile> profile_;
-  std::unique_ptr<AnsibleManagementService> ansible_management_service_;
+  CrostiniManager* crostini_manager_;
+  AnsibleManagementService* ansible_management_service_;
   base::MockCallback<base::OnceCallback<void(bool)>>
       ansible_installation_finished_mock_callback_;
+  base::MockCallback<base::OnceCallback<void(bool)>>
+      ansible_playbook_application_finished_mock_callback_;
   // Owned by chromeos::DBusThreadManager
   chromeos::FakeCiceroneClient* fake_cicerone_client_;
 
@@ -93,4 +109,41 @@
   base::RunLoop().RunUntilIdle();
 }
 
+TEST_F(AnsibleManagementServiceTest,
+       ApplyAnsiblePlaybookToDefaultContainerSuccess) {
+  vm_tools::cicerone::ApplyAnsiblePlaybookResponse response;
+  response.set_status(
+      vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED);
+  fake_cicerone_client_->set_apply_ansible_playbook_response(response);
+
+  EXPECT_CALL(ansible_playbook_application_finished_mock_callback_, Run(true))
+      .Times(1);
+
+  ansible_management_service()->ApplyAnsiblePlaybookToDefaultContainer(
+      /*playbook=*/"",
+      ansible_playbook_application_finished_mock_callback_.Get());
+
+  // Actually starts applying Ansible playbook.
+  base::RunLoop().RunUntilIdle();
+
+  SendSucceededApplicationSignal();
+}
+
+TEST_F(AnsibleManagementServiceTest,
+       ApplyAnsiblePlaybookToDefaultContainerFail) {
+  vm_tools::cicerone::ApplyAnsiblePlaybookResponse response;
+  response.set_status(vm_tools::cicerone::ApplyAnsiblePlaybookResponse::FAILED);
+  fake_cicerone_client_->set_apply_ansible_playbook_response(response);
+
+  EXPECT_CALL(ansible_playbook_application_finished_mock_callback_, Run(false))
+      .Times(1);
+
+  ansible_management_service()->ApplyAnsiblePlaybookToDefaultContainer(
+      /*playbook=*/"",
+      ansible_playbook_application_finished_mock_callback_.Get());
+
+  // Actually starts applying Ansible playbook.
+  base::RunLoop().RunUntilIdle();
+}
+
 }  // namespace crostini
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc
index 92063d8..bb2a546 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -2126,6 +2126,16 @@
   }
 }
 
+void CrostiniManager::OnApplyAnsiblePlaybookProgress(
+    const vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal& signal) {
+  if (signal.owner_id() != owner_id_)
+    return;
+
+  // TODO(okalitova): Add an observer.
+  AnsibleManagementService::GetForProfile(profile_)
+      ->OnApplyAnsiblePlaybookProgress(signal.status());
+}
+
 void CrostiniManager::OnUninstallPackageOwningFile(
     CrostiniResultCallback callback,
     base::Optional<vm_tools::cicerone::UninstallPackageOwningFileResponse>
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h
index 1cabdb9..ad5381a 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.h
+++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -467,6 +467,9 @@
       override;
   void OnPendingAppListUpdates(
       const vm_tools::cicerone::PendingAppListUpdatesSignal& signal) override;
+  void OnApplyAnsiblePlaybookProgress(
+      const vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal& signal)
+      override;
 
   // chromeos::PowerManagerClient::Observer overrides:
   void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
diff --git a/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc b/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
index c67a9dc..8f28536 100644
--- a/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
+++ b/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
@@ -46,6 +46,31 @@
 #define MAYBE_TestDeviceRequisition TestDeviceRequisition
 #endif
 
+// Disabled on debug build due to flakiness: https://crbug.com/997685.
+#if !defined(NDEBUG)
+#define MAYBE_TestAcceptEula DISABLED_TestAcceptEula
+#define MAYBE_TestDemoModeAcceptArcTos DISABLED_TestDemoModeAcceptArcTos
+#define MAYBE_TestDemoModeAcceptEula DISABLED_TestDemoModeAcceptEula
+#define MAYBE_TestDemoModeOfflineNetwork DISABLED_TestDemoModeOfflineNetwork
+#define MAYBE_TestDemoModePreferences DISABLED_TestDemoModePreferences
+#define MAYBE_TestEnableDemoMode DISABLED_TestEnableDemoMode
+#define MAYBE_TestLeaveWelcomeScreen DISABLED_TestLeaveWelcomeScreen
+#define MAYBE_TestSwitchLanguageIME DISABLED_TestSwitchLanguageIME
+#define MAYBE_TestLeaveWelcomeScreen DISABLED_TestLeaveWelcomeScreen
+#define MAYBE_TestSkipHIDDetection DISABLED_TestSkipHIDDetection
+#else
+#define MAYBE_TestAcceptEula TestAcceptEula
+#define MAYBE_TestDemoModeAcceptArcTos TestDemoModeAcceptArcTos
+#define MAYBE_TestDemoModeAcceptEula TestDemoModeAcceptEula
+#define MAYBE_TestDemoModeOfflineNetwork TestDemoModeOfflineNetwork
+#define MAYBE_TestDemoModePreferences TestDemoModePreferences
+#define MAYBE_TestEnableDemoMode TestEnableDemoMode
+#define MAYBE_TestLeaveWelcomeScreen TestLeaveWelcomeScreen
+#define MAYBE_TestSwitchLanguageIME TestSwitchLanguageIME
+#define MAYBE_TestLeaveWelcomeScreen TestLeaveWelcomeScreen
+#define MAYBE_TestSkipHIDDetection TestSkipHIDDetection
+#endif
+
 namespace chromeos {
 
 // This test case will use
@@ -186,13 +211,13 @@
 };
 
 // Check that configuration lets correctly pass Welcome screen.
-IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, TestLeaveWelcomeScreen) {
+IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, MAYBE_TestLeaveWelcomeScreen) {
   LoadConfiguration();
   OobeScreenWaiter(NetworkScreenView::kScreenId).Wait();
 }
 
 // Check that language and input methods are set correctly.
-IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, TestSwitchLanguageIME) {
+IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, MAYBE_TestSwitchLanguageIME) {
   LoadConfiguration();
   OobeScreenWaiter(NetworkScreenView::kScreenId).Wait();
 
@@ -214,20 +239,21 @@
 }
 
 // Check that configuration lets correctly start Demo mode setup.
-IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, TestEnableDemoMode) {
+IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, MAYBE_TestEnableDemoMode) {
   LoadConfiguration();
   OobeScreenWaiter(DemoPreferencesScreenView::kScreenId).Wait();
 }
 
 // Check that configuration lets correctly pass through demo preferences.
-IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, TestDemoModePreferences) {
+IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, MAYBE_TestDemoModePreferences) {
   LoadConfiguration();
   OobeScreenWaiter(NetworkScreenView::kScreenId).Wait();
 }
 
 // Check that configuration lets correctly use offline demo mode on network
 // screen.
-IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, TestDemoModeOfflineNetwork) {
+IN_PROC_BROWSER_TEST_F(OobeConfigurationTest,
+                       MAYBE_TestDemoModeOfflineNetwork) {
   LoadConfiguration();
   OobeScreenWaiter(DemoPreferencesScreenView::kScreenId).Wait();
   SimulateOfflineEnvironment();
@@ -236,7 +262,7 @@
 
 // Check that configuration lets correctly use offline demo mode on EULA
 // screen.
-IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, TestDemoModeAcceptEula) {
+IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, MAYBE_TestDemoModeAcceptEula) {
   LoadConfiguration();
   OobeScreenWaiter(DemoPreferencesScreenView::kScreenId).Wait();
   SimulateOfflineEnvironment();
@@ -245,7 +271,7 @@
 
 // Check that configuration lets correctly use offline demo mode on ARC++ ToS
 // screen.
-IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, TestDemoModeAcceptArcTos) {
+IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, MAYBE_TestDemoModeAcceptArcTos) {
   LoadConfiguration();
   OobeScreenWaiter(DemoPreferencesScreenView::kScreenId).Wait();
   SimulateOfflineEnvironment();
@@ -281,7 +307,7 @@
 }
 
 // Check that when configuration has ONC and EULA, we get to update screen.
-IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, TestAcceptEula) {
+IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, MAYBE_TestAcceptEula) {
   UpdateEngineClient::Status status;
   status.status = UpdateEngineClient::UPDATE_STATUS_DOWNLOADING;
   status.download_progress = 0.1;
@@ -331,7 +357,7 @@
 
 // Check that HID detection screen is really skipped and rest of configuration
 // is applied.
-IN_PROC_BROWSER_TEST_F(OobeConfigurationTestNoHID, TestSkipHIDDetection) {
+IN_PROC_BROWSER_TEST_F(OobeConfigurationTestNoHID, MAYBE_TestSkipHIDDetection) {
   LoadConfiguration();
   OobeScreenWaiter(NetworkScreenView::kScreenId).Wait();
 }
diff --git a/chrome/browser/chromeos/login/saml/public_saml_url_fetcher.cc b/chrome/browser/chromeos/login/saml/public_saml_url_fetcher.cc
new file mode 100644
index 0000000..623c33e
--- /dev/null
+++ b/chrome/browser/chromeos/login/saml/public_saml_url_fetcher.cc
@@ -0,0 +1,126 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/saml/public_saml_url_fetcher.h"
+
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/arc/arc_optin_uma.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/policy/device_local_account.h"
+#include "chrome/browser/chromeos/policy/dm_token_storage.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/chromeos/settings/device_settings_service.h"
+#include "chrome/browser/net/system_network_context_manager.h"
+#include "chromeos/tpm/install_attributes.h"
+#include "components/account_id/account_id.h"
+#include "components/policy/core/common/cloud/device_management_service.h"
+#include "components/policy/core/common/cloud/dm_auth.h"
+#include "components/policy/core/common/cloud/dmserver_job_configurations.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "url/gurl.h"
+
+namespace em = enterprise_management;
+namespace {
+std::string GetDeviceId() {
+  policy::BrowserPolicyConnectorChromeOS* connector =
+      g_browser_process->platform_part()->browser_policy_connector_chromeos();
+  return connector->GetInstallAttributes()->GetDeviceId();
+}
+
+std::string GetAccountId(std::string user_id) {
+  std::vector<policy::DeviceLocalAccount> device_local_accounts =
+      policy::GetDeviceLocalAccounts(chromeos::CrosSettings::Get());
+  for (auto account : device_local_accounts) {
+    if (account.user_id == user_id) {
+      return account.account_id;
+    }
+  }
+  return std::string();
+}
+}  // namespace
+
+namespace chromeos {
+PublicSamlUrlFetcher::PublicSamlUrlFetcher(AccountId account_id)
+    : account_id_(GetAccountId(account_id.GetUserEmail())) {}
+
+PublicSamlUrlFetcher::~PublicSamlUrlFetcher() = default;
+
+std::string PublicSamlUrlFetcher::GetRedirectUrl() {
+  return redirect_url_;
+}
+
+bool PublicSamlUrlFetcher::FetchSucceeded() {
+  return fetch_succeeded_;
+}
+
+void PublicSamlUrlFetcher::Fetch(base::OnceClosure callback) {
+  DCHECK(!callback_);
+  callback_ = std::move(callback);
+  policy::DeviceManagementService* service =
+      g_browser_process->platform_part()
+          ->browser_policy_connector_chromeos()
+          ->device_management_service();
+  std::unique_ptr<policy::DMServerJobConfiguration> config = std::make_unique<
+      policy::DMServerJobConfiguration>(
+      service,
+      policy::DeviceManagementService::JobConfiguration::TYPE_REQUEST_SAML_URL,
+      GetDeviceId(), /*critical=*/false,
+      policy::DMAuth::FromDMToken(chromeos::DeviceSettingsService::Get()
+                                      ->policy_data()
+                                      ->request_token()),
+      /*oauth_token=*/base::nullopt,
+      g_browser_process->system_network_context_manager()
+          ->GetSharedURLLoaderFactory(),
+      base::Bind(&PublicSamlUrlFetcher::OnPublicSamlUrlReceived,
+                 weak_ptr_factory_.GetWeakPtr()));
+
+  em::PublicSamlUserRequest* saml_url_request =
+      config->request()->mutable_public_saml_user_request();
+  saml_url_request->set_account_id(account_id_);
+  fetch_request_job_ = service->CreateJob(std::move(config));
+}
+
+void PublicSamlUrlFetcher::OnPublicSamlUrlReceived(
+    policy::DeviceManagementService::Job* job,
+    policy::DeviceManagementStatus dm_status,
+    int net_error,
+    const enterprise_management::DeviceManagementResponse& response) {
+  VLOG(1) << "Public SAML url response received. DM Status: " << dm_status;
+  fetch_request_job_.reset();
+  std::string user_id;
+
+  switch (dm_status) {
+    case policy::DM_STATUS_SUCCESS: {
+      if (!response.has_public_saml_user_response()) {
+        LOG(WARNING) << "Invalid public SAML url response.";
+        break;
+      }
+      const em::PublicSamlUserResponse& saml_url_response =
+          response.public_saml_user_response();
+
+      if (!saml_url_response.has_saml_parameters()) {
+        LOG(WARNING) << "Invalid public SAML url response.";
+        break;
+      }
+      // Fetch has succeeded.
+      fetch_succeeded_ = true;
+      const em::SamlParametersProto& saml_params =
+          saml_url_response.saml_parameters();
+      redirect_url_ = saml_params.auth_redirect_url();
+      break;
+    }
+    default: {  // All other error cases
+      LOG(ERROR) << "Fetching public SAML url failed. DM Status: " << dm_status;
+      break;
+    }
+  }
+  std::move(callback_).Run();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/saml/public_saml_url_fetcher.h b/chrome/browser/chromeos/login/saml/public_saml_url_fetcher.h
new file mode 100644
index 0000000..8b8a990
--- /dev/null
+++ b/chrome/browser/chromeos/login/saml/public_saml_url_fetcher.h
@@ -0,0 +1,67 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SAML_PUBLIC_SAML_URL_FETCHER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_SAML_PUBLIC_SAML_URL_FETCHER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/account_id/account_id.h"
+#include "components/policy/core/common/cloud/cloud_policy_constants.h"
+#include "components/policy/core/common/cloud/device_management_service.h"
+
+namespace enterprise_management {
+class DeviceManagementResponse;
+}  // namespace enterprise_management
+
+namespace chromeos {
+
+// This class handles sending request for public SAML session URL to DM
+// server, waits for the response and retrieves the redirect URL from it.
+class PublicSamlUrlFetcher {
+ public:
+  explicit PublicSamlUrlFetcher(AccountId account_id);
+  ~PublicSamlUrlFetcher();
+
+  // Sends request to the DM server, gets and checks the response and
+  // calls the callback.
+  void Fetch(base::OnceClosure callback);
+  std::string GetRedirectUrl();
+  bool FetchSucceeded();
+
+ private:
+  // Response from DM server. Calls the stored FetchCallback or initiates the
+  // SAML flow.
+  void OnPublicSamlUrlReceived(
+      policy::DeviceManagementService::Job* job,
+      policy::DeviceManagementStatus dm_status,
+      int net_error,
+      const enterprise_management::DeviceManagementResponse& response);
+
+  // Account ID, added to the DM server request.
+  std::string account_id_;
+
+  // Indicates whether fetching the redirect URL was successful.
+  bool fetch_succeeded_ = false;
+
+  // Job that sends request to the DM server.
+  std::unique_ptr<policy::DeviceManagementService::Job> fetch_request_job_;
+
+  // The redirect URL.
+  std::string redirect_url_;
+
+  // Called at the end of Fetch().
+  base::OnceClosure callback_;
+  base::WeakPtrFactory<PublicSamlUrlFetcher> weak_ptr_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(PublicSamlUrlFetcher);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SAML_PUBLIC_SAML_URL_FETCHER_H_
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index d31e2a4..eae4e07 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -417,6 +417,17 @@
                   POLICY_SOURCE_CLOUD, std::move(rules), nullptr);
   }
 
+  if (policy.has_device_login_screen_webusb_allow_devices_for_urls()) {
+    const em::DeviceLoginScreenWebUsbAllowDevicesForUrlsProto& container(
+        policy.device_login_screen_webusb_allow_devices_for_urls());
+    if (container.has_device_login_screen_webusb_allow_devices_for_urls()) {
+      SetJsonDevicePolicy(
+          key::kDeviceLoginScreenWebUsbAllowDevicesForUrls,
+          container.device_login_screen_webusb_allow_devices_for_urls(),
+          policies);
+    }
+  }
+
   if (policy.has_saml_login_authentication_type()) {
     const em::SamlLoginAuthenticationTypeProto& container(
         policy.saml_login_authentication_type());
diff --git a/chrome/browser/component_updater/metadata_table_chromeos.cc b/chrome/browser/component_updater/metadata_table_chromeos.cc
index 64a22e7..916a2c3 100644
--- a/chrome/browser/component_updater/metadata_table_chromeos.cc
+++ b/chrome/browser/component_updater/metadata_table_chromeos.cc
@@ -183,7 +183,7 @@
   base::Value item(base::Value::Type::DICTIONARY);
   item.SetKey(kMetadataContentItemHashedUserIdKey, base::Value(hashed_user_id));
   item.SetKey(kMetadataContentItemComponentKey, base::Value(component_name));
-  installed_items_.GetList().emplace_back(std::move(item));
+  installed_items_.Append(std::move(item));
 }
 
 bool MetadataTable::DeleteItem(const std::string& hashed_user_id,
diff --git a/chrome/browser/component_updater/supervised_user_whitelist_installer.cc b/chrome/browser/component_updater/supervised_user_whitelist_installer.cc
index c6ab4e3..2848ef3 100644
--- a/chrome/browser/component_updater/supervised_user_whitelist_installer.cc
+++ b/chrome/browser/component_updater/supervised_user_whitelist_installer.cc
@@ -571,7 +571,7 @@
 
     base::Value client(client_id);
     DCHECK(!base::Contains(clients->GetList(), client));
-    clients->GetList().push_back(std::move(client));
+    clients->Append(std::move(client));
   }
 
   if (!newly_added) {
diff --git a/chrome/browser/devtools/device/devtools_android_bridge.cc b/chrome/browser/devtools/device/devtools_android_bridge.cc
index ec89514..f799123 100644
--- a/chrome/browser/devtools/device/devtools_android_bridge.cc
+++ b/chrome/browser/devtools/device/devtools_android_bridge.cc
@@ -166,8 +166,8 @@
       base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders,
                  base::Unretained(this)));
   base::Value target_discovery(base::Value::Type::LIST);
-  target_discovery.GetList().emplace_back(kChromeDiscoveryURL);
-  target_discovery.GetList().emplace_back(kNodeDiscoveryURL);
+  target_discovery.Append(kChromeDiscoveryURL);
+  target_discovery.Append(kNodeDiscoveryURL);
   profile->GetPrefs()->SetDefaultPrefValue(prefs::kDevToolsTCPDiscoveryConfig,
                                            std::move(target_discovery));
   CreateDeviceProviders();
diff --git a/chrome/browser/devtools/serialize_host_descriptions.cc b/chrome/browser/devtools/serialize_host_descriptions.cc
index d1bdc91..054acd9 100644
--- a/chrome/browser/devtools/serialize_host_descriptions.cc
+++ b/chrome/browser/devtools/serialize_host_descriptions.cc
@@ -27,8 +27,7 @@
   auto child_it = children.find(root);
   if (child_it != children.end()) {
     for (base::DictionaryValue* child : child_it->second) {
-      children_list->base::Value::GetList().push_back(
-          Serialize(child_key, child, children));
+      children_list->base::Value::Append(Serialize(child_key, child, children));
     }
   }
 
@@ -98,8 +97,7 @@
 
   base::ListValue list_value;
   for (auto* root : roots) {
-    list_value.base::Value::GetList().push_back(
-        Serialize(child_key, root, children));
+    list_value.base::Value::Append(Serialize(child_key, root, children));
   }
   return list_value;
 }
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
index 2b44f3e..60e9da0 100644
--- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
+++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
@@ -255,7 +255,7 @@
   for (auto& component : components->GetList()) {
     base::Value row(base::Value::Type::DICTIONARY);
     row.SetKey("row", std::move(component));
-    rows.GetList().emplace_back(std::move(row));
+    rows.Append(std::move(row));
   }
 
   address_components.SetKey("components", std::move(rows));
diff --git a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
index 4ed224a..a96cf26 100644
--- a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
@@ -83,8 +83,8 @@
     function->set_has_callback(true);
 
     auto args = std::make_unique<base::Value>(base::Value::Type::LIST);
-    args->GetList().emplace_back(
-        base::Value::BlobStorage(app_id.begin(), app_id.end()));
+    args->Append(
+        base::Value(base::Value::BlobStorage(app_id.begin(), app_id.end())));
 
     if (!extension_function_test_utils::RunFunction(
             function.get(), base::ListValue::From(std::move(args)), browser(),
@@ -210,7 +210,7 @@
     dict.emplace("tabId", std::make_unique<base::Value>(tab_id_));
     dict.emplace("origin", std::make_unique<base::Value>(app_id));
     auto args = std::make_unique<base::Value>(base::Value::Type::LIST);
-    args->GetList().emplace_back(std::move(dict));
+    args->Append(base::Value(std::move(dict)));
     auto args_list = base::ListValue::From(std::move(args));
 
     extension_function_test_utils::RunFunction(
diff --git a/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc b/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
index 6d91223..997fed5 100644
--- a/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
+++ b/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
@@ -255,7 +255,7 @@
   // 2. Test writing behavior.
   {
     base::Value value(base::Value::Type::LIST);
-    value.GetList().push_back(base::Value(true));
+    value.Append(base::Value(true));
     cache_delegate->UpdateRules(extension1_->id(), std::move(value));
   }
   EXPECT_TRUE(cache_delegate->GetDeclarativeRulesStored(extension1_->id()));
@@ -302,7 +302,7 @@
   auto cache_delegate = std::make_unique<RulesCacheDelegate>(
       RulesCacheDelegate::Type::kEphemeral, false);
   base::Value value(base::Value::Type::LIST);
-  value.GetList().push_back(base::Value(true));
+  value.Append(base::Value(true));
   cache_delegate->UpdateRules(extension1_->id(), std::move(value));
   content::RunAllTasksUntilIdle();
   TestingValueStore* store = env_.GetExtensionSystem()->value_store();
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
index cf68ed7..62b206b 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
@@ -80,7 +80,7 @@
   list.GetList().reserve(controls.size());
   for (const auto& control : controls) {
     std::unique_ptr<base::Value> control_value = control.ToValue();
-    list.GetList().push_back(std::move(*control_value));
+    list.Append(std::move(*control_value));
   }
 
   std::string json;
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index 0e2a4d3..2694d31 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -932,7 +932,7 @@
   scoped_refptr<DownloadsOpenFunction> scoped_open(new DownloadsOpenFunction());
   scoped_open->set_user_gesture(true);
   base::Value args_list(base::Value::Type::LIST);
-  args_list.GetList().emplace_back(static_cast<int>(download_item->GetId()));
+  args_list.Append(static_cast<int>(download_item->GetId()));
   scoped_open->SetArgs(std::move(args_list));
   scoped_open->set_browser_context(current_browser()->profile());
   scoped_open->set_extension(extension());
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher.cc b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
index edfdcbf..e8480b4 100644
--- a/chrome/browser/extensions/api/messaging/native_process_launcher.cc
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
@@ -258,7 +258,7 @@
     base::Value args(base::Value::Type::LIST);
     args.GetList().reserve(reconnect_command_line.argv().size());
     for (const auto& arg : reconnect_command_line.argv()) {
-      args.GetList().emplace_back(arg);
+      args.Append(arg);
     }
     std::string encoded_reconnect_command;
     bool success =
diff --git a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc
index d06e55a..4fa4eac 100644
--- a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc
+++ b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc
@@ -379,7 +379,7 @@
   wrapper.SetKey(name, std::move(event));
 
   base::Value event_list(base::Value::Type::LIST);
-  event_list.GetList().push_back(std::move(wrapper));
+  event_list.Append(std::move(wrapper));
 
   client_->UploadRealtimeReport(
       policy::RealtimeReportingJobConfiguration::BuildReport(
diff --git a/chrome/browser/extensions/convert_web_app.cc b/chrome/browser/extensions/convert_web_app.cc
index 882dd14..e506394 100644
--- a/chrome/browser/extensions/convert_web_app.cc
+++ b/chrome/browser/extensions/convert_web_app.cc
@@ -73,9 +73,9 @@
         continue;
 
       if (acceptsUTF8[0] == '.') {
-        file_extensions.GetList().push_back(base::Value(acceptsUTF8.substr(1)));
+        file_extensions.Append(base::Value(acceptsUTF8.substr(1)));
       } else {
-        mime_types.GetList().push_back(base::Value(acceptsUTF8));
+        mime_types.Append(base::Value(acceptsUTF8));
       }
     }
 
diff --git a/chrome/browser/extensions/extension_web_ui_unittest.cc b/chrome/browser/extensions/extension_web_ui_unittest.cc
index 38a5b10..65c7e47 100644
--- a/chrome/browser/extensions/extension_web_ui_unittest.cc
+++ b/chrome/browser/extensions/extension_web_ui_unittest.cc
@@ -183,7 +183,7 @@
       base::Value newtab(base::Value::Type::DICTIONARY);
       newtab.SetKey("entry", base::Value(newtab_url.spec()));
       newtab.SetKey("active", base::Value(true));
-      newtab_list.GetList().push_back(std::move(newtab));
+      newtab_list.Append(std::move(newtab));
     }
     {
       base::Value newtab(base::Value::Type::DICTIONARY);
@@ -191,7 +191,7 @@
           "entry",
           base::Value(extension->GetResourceURL("oldtab.html").spec()));
       newtab.SetKey("active", base::Value(true));
-      newtab_list.GetList().push_back(std::move(newtab));
+      newtab_list.Append(std::move(newtab));
     }
 
     all_overrides->SetKey("newtab", std::move(newtab_list));
diff --git a/chrome/browser/extensions/external_pref_loader.cc b/chrome/browser/extensions/external_pref_loader.cc
index f4b5108..5c744bb 100644
--- a/chrome/browser/extensions/external_pref_loader.cc
+++ b/chrome/browser/extensions/external_pref_loader.cc
@@ -326,8 +326,7 @@
   std::unique_ptr<base::ListValue> default_user_types;
   if (options_ & USE_USER_TYPE_PROFILE_FILTER) {
     default_user_types = std::make_unique<base::ListValue>();
-    default_user_types->GetList().push_back(
-        base::Value(apps::kUserTypeUnmanaged));
+    default_user_types->Append(base::Value(apps::kUserTypeUnmanaged));
   }
 
   // For each file read the json description & build the proper
diff --git a/chrome/browser/media/router/mojo/media_sink_service_status.cc b/chrome/browser/media/router/mojo/media_sink_service_status.cc
index 2786d74..9edba9b 100644
--- a/chrome/browser/media/router/mojo/media_sink_service_status.cc
+++ b/chrome/browser/media/router/mojo/media_sink_service_status.cc
@@ -96,7 +96,7 @@
   for (const auto& sinks_it : sinks) {
     base::ListValue list;
     for (const auto& inner_sink : sinks_it.second)
-      list.GetList().push_back(ToValue(inner_sink));
+      list.Append(ToValue(inner_sink));
     dict.SetKey(sinks_it.first, std::move(list));
   }
   return dict;
@@ -112,7 +112,7 @@
     base::Value list(base::Value::Type::LIST);
     for (const auto& inner_sink : sinks_it.second) {
       std::string sink_id = inner_sink.sink().id();
-      list.GetList().push_back(base::Value(TruncateSinkId(sink_id)));
+      list.Append(base::Value(TruncateSinkId(sink_id)));
     }
     dict.SetKey(sinks_it.first, std::move(list));
   }
diff --git a/chrome/browser/media/router/providers/cast/cast_media_controller_unittest.cc b/chrome/browser/media/router/providers/cast/cast_media_controller_unittest.cc
index 04f39b43..72ff0e8 100644
--- a/chrome/browser/media/router/providers/cast/cast_media_controller_unittest.cc
+++ b/chrome/browser/media/router/providers/cast/cast_media_controller_unittest.cc
@@ -75,7 +75,7 @@
       image_value.SetIntKey("width", image->size->width());
       image_value.SetIntKey("height", image->size->height());
     }
-    image_list.GetList().push_back(std::move(image_value));
+    image_list.Append(std::move(image_value));
   }
   return image_list;
 }
@@ -170,7 +170,7 @@
 
     Value status_list(Value::Type::DICTIONARY);
     status_list.SetKey("status", Value(Value::Type::LIST));
-    status_list.FindKey("status")->GetList().push_back(std::move(status_value));
+    status_list.FindKey("status")->Append(std::move(status_value));
     controller_->SetMediaStatus(std::move(status_list));
   }
 
diff --git a/chrome/browser/media/webrtc/webrtc_log_uploader.cc b/chrome/browser/media/webrtc/webrtc_log_uploader.cc
index 118028e..1b386f4 100644
--- a/chrome/browser/media/webrtc/webrtc_log_uploader.cc
+++ b/chrome/browser/media/webrtc/webrtc_log_uploader.cc
@@ -544,7 +544,7 @@
     }
   }
 
-  // Write the capture time and log ID to the log list file. Leave the upload
+  // Write the log ID and capture time to the log list file. Leave the upload
   // time and report ID empty.
   contents += ",," + local_log_id + "," +
               base::NumberToString(base::Time::Now().ToDoubleT()) + '\n';
diff --git a/chrome/browser/media/webrtc/webrtc_log_uploader.h b/chrome/browser/media/webrtc/webrtc_log_uploader.h
index b1475a1..ea558ca 100644
--- a/chrome/browser/media/webrtc/webrtc_log_uploader.h
+++ b/chrome/browser/media/webrtc/webrtc_log_uploader.h
@@ -166,18 +166,19 @@
   // Append information (upload time, report ID and local ID) about a log to a
   // log list file, limited to |kLogListLimitLines| entries. This list is used
   // for viewing the logs under chrome://webrtc-logs, see WebRtcLogUploadList.
-  // The list has the format
-  // upload_time,report_id,local_id
-  // upload_time,report_id,local_id
-  // etc.
-  // where each line represents a log. "upload_time" is the time when the log
-  // was uploaded in Unix time. "report_id" is the ID reported back by the
-  // server. "local_id" is the ID for the locally stored log. It's the time
-  // stored in Unix time and it's also used as file name.
-  // AddLocallyStoredLogInfoToUploadListFile() will first be called,
-  // "upload_time" and "report_id" is the left empty in the entry written to the
-  // list file. If uploading is successful, AddUploadedLogInfoToUploadListFile()
-  // is called and those empty items are filled out.
+  // The list has the format:
+  //   [upload_time],[report_id],[local_id],[capture_time]
+  // Each line represents a log.
+  // * |upload_time| is the time when the log was uploaded in Unix time.
+  // * |report_id| is the ID reported back by the server.
+  // * |local_id| is the ID for the locally stored log. It's the time stored
+  //   in Unix time and it's also used as file name.
+  // * |capture_time| is the Unix time when the log was captured.
+  // AddLocallyStoredLogInfoToUploadListFile() will first be called.
+  // |upload_time| and |report_id| will be left empty in the entry written to
+  // the list file. If uploading is successful,
+  // AddUploadedLogInfoToUploadListFile() will be called and those empty fields
+  // will be filled out.
   // Must be called on the FILE thread.
   void AddLocallyStoredLogInfoToUploadListFile(
       const base::FilePath& upload_list_path,
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc
index 4001988..465949f 100644
--- a/chrome/browser/net/profile_network_context_service.cc
+++ b/chrome/browser/net/profile_network_context_service.cc
@@ -219,14 +219,14 @@
 
 ProfileNetworkContextService::~ProfileNetworkContextService() {}
 
-network::mojom::NetworkContextPtr
+mojo::Remote<network::mojom::NetworkContext>
 ProfileNetworkContextService::CreateNetworkContext(
     bool in_memory,
     const base::FilePath& relative_partition_path) {
-  network::mojom::NetworkContextPtr network_context;
+  mojo::Remote<network::mojom::NetworkContext> network_context;
 
   content::GetNetworkService()->CreateNetworkContext(
-      MakeRequest(&network_context),
+      network_context.BindNewPipeAndPassReceiver(),
       CreateNetworkContextParams(in_memory, relative_partition_path));
 
   if ((!in_memory && !profile_->IsOffTheRecord())) {
diff --git a/chrome/browser/net/profile_network_context_service.h b/chrome/browser/net/profile_network_context_service.h
index 0178384..ad43b67 100644
--- a/chrome/browser/net/profile_network_context_service.h
+++ b/chrome/browser/net/profile_network_context_service.h
@@ -21,6 +21,7 @@
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_member.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/net_buildflags.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 
@@ -45,7 +46,7 @@
   // Creates a NetworkContext for the BrowserContext, using the specified
   // parameters. An empty |relative_partition_path| corresponds to the main
   // network context.
-  network::mojom::NetworkContextPtr CreateNetworkContext(
+  mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext(
       bool in_memory,
       const base::FilePath& relative_partition_path);
 
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc
index 7f8536a..4092e1f 100644
--- a/chrome/browser/net/system_network_context_manager.cc
+++ b/chrome/browser/net/system_network_context_manager.cc
@@ -308,7 +308,7 @@
 
 network::mojom::NetworkContext* SystemNetworkContextManager::GetContext() {
   if (!network_service_network_context_ ||
-      network_service_network_context_.encountered_error()) {
+      !network_service_network_context_.is_connected()) {
     // This should call into OnNetworkServiceCreated(), which will re-create
     // the network service, if needed. There's a chance that it won't be
     // invoked, if the NetworkContext has encountered an error but the
@@ -597,8 +597,9 @@
 
   // The system NetworkContext must be created first, since it sets
   // |primary_network_context| to true.
+  network_service_network_context_.reset();
   network_service->CreateNetworkContext(
-      MakeRequest(&network_service_network_context_),
+      network_service_network_context_.BindNewPipeAndPassReceiver(),
       CreateNetworkContextParams());
 
   mojo::PendingRemote<network::mojom::NetworkContextClient> client_remote;
diff --git a/chrome/browser/net/system_network_context_manager.h b/chrome/browser/net/system_network_context_manager.h
index 1d1b129..28af103 100644
--- a/chrome/browser/net/system_network_context_manager.h
+++ b/chrome/browser/net/system_network_context_manager.h
@@ -15,6 +15,7 @@
 #include "chrome/browser/net/proxy_config_monitor.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_member.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/network/public/mojom/host_resolver.mojom-forward.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/network_service.mojom-forward.h"
@@ -170,7 +171,7 @@
 
   // NetworkContext using the network service, if the network service is
   // enabled. nullptr, otherwise.
-  network::mojom::NetworkContextPtr network_service_network_context_;
+  mojo::Remote<network::mojom::NetworkContext> network_service_network_context_;
 
   // URLLoaderFactory backed by the NetworkContext returned by GetContext(), so
   // consumers don't all need to create their own factory.
diff --git a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc
index 73b5cbc..3b6e11d 100644
--- a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc
@@ -121,6 +121,13 @@
     "PageLoad.Clients.NoServiceWorker2.DocumentTiming."
     "NavigationToLoadEventFired.search";
 
+const char kHistogramServiceWorkerFirstContentfulPaintDocs[] =
+    "PageLoad.Clients.ServiceWorker2.PaintTiming."
+    "NavigationToFirstContentfulPaint.docs";
+const char kHistogramNoServiceWorkerFirstContentfulPaintDocs[] =
+    "PageLoad.Clients.NoServiceWorker2.PaintTiming."
+    "NavigationToFirstContentfulPaint.docs";
+
 }  // namespace internal
 
 namespace {
@@ -129,6 +136,10 @@
   return url.host_piece() == "inbox.google.com";
 }
 
+bool IsDocsSite(const GURL& url) {
+  return url.host_piece() == "docs.google.com";
+}
+
 bool IsForwardBackLoad(ui::PageTransition transition) {
   return transition & ui::PAGE_TRANSITION_FORWARD_BACK;
 }
@@ -166,18 +177,24 @@
     const page_load_metrics::mojom::PageLoadTiming& timing) {
   if (!IsServiceWorkerControlled()) {
     if (!page_load_metrics::WasStartedInForegroundOptionalEventInForeground(
-            timing.paint_timing->first_contentful_paint, GetDelegate()) ||
-        !page_load_metrics::IsGoogleSearchResultUrl(GetDelegate().GetUrl())) {
+            timing.paint_timing->first_contentful_paint, GetDelegate())) {
       return;
     }
-    PAGE_LOAD_HISTOGRAM(
-        internal::kHistogramNoServiceWorkerFirstContentfulPaintSearch,
-        timing.paint_timing->first_contentful_paint.value());
-    PAGE_LOAD_HISTOGRAM(
-        internal::
-            kHistogramNoServiceWorkerParseStartToFirstContentfulPaintSearch,
-        timing.paint_timing->first_contentful_paint.value() -
-            timing.parse_timing->parse_start.value());
+
+    if (page_load_metrics::IsGoogleSearchResultUrl(GetDelegate().GetUrl())) {
+      PAGE_LOAD_HISTOGRAM(
+          internal::kHistogramNoServiceWorkerFirstContentfulPaintSearch,
+          timing.paint_timing->first_contentful_paint.value());
+      PAGE_LOAD_HISTOGRAM(
+          internal::
+              kHistogramNoServiceWorkerParseStartToFirstContentfulPaintSearch,
+          timing.paint_timing->first_contentful_paint.value() -
+              timing.parse_timing->parse_start.value());
+    } else if (IsDocsSite(GetDelegate().GetUrl())) {
+      PAGE_LOAD_HISTOGRAM(
+          internal::kHistogramNoServiceWorkerFirstContentfulPaintDocs,
+          timing.paint_timing->first_contentful_paint.value());
+    }
     return;
   }
   if (!page_load_metrics::WasStartedInForegroundOptionalEventInForeground(
@@ -223,6 +240,10 @@
         internal::kHistogramServiceWorkerParseStartToFirstContentfulPaintSearch,
         timing.paint_timing->first_contentful_paint.value() -
             timing.parse_timing->parse_start.value());
+  } else if (IsDocsSite(GetDelegate().GetUrl())) {
+    PAGE_LOAD_HISTOGRAM(
+        internal::kHistogramServiceWorkerFirstContentfulPaintDocs,
+        timing.paint_timing->first_contentful_paint.value());
   }
 }
 
diff --git a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h
index 8f38e39..a892dc8 100644
--- a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h
@@ -58,6 +58,9 @@
 extern const char kHistogramNoServiceWorkerDomContentLoadedSearch[];
 extern const char kHistogramNoServiceWorkerLoadSearch[];
 
+extern const char kHistogramServiceWorkerFirstContentfulPaintDocs[];
+extern const char kHistogramNoServiceWorkerFirstContentfulPaintDocs[];
+
 }  // namespace internal
 
 class ServiceWorkerPageLoadMetricsObserver
diff --git a/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc b/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc
index 6f4bdd720..f4775f33 100644
--- a/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc
+++ b/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc
@@ -154,7 +154,7 @@
   auto manager = std::make_unique<MockPasswordFormManager>(
       &client_, driver_.AsWeakPtr(), observed_form_, &fetcher_,
       metrics_recorder);
-  manager->ProvisionallySave(observed_form_, &driver_);
+  manager->ProvisionallySave(observed_form_, &driver_, nullptr);
   return manager;
 }
 
diff --git a/chrome/browser/password_manager/update_password_infobar_delegate_android_unittest.cc b/chrome/browser/password_manager/update_password_infobar_delegate_android_unittest.cc
index 546557b..49aa65c 100644
--- a/chrome/browser/password_manager/update_password_infobar_delegate_android_unittest.cc
+++ b/chrome/browser/password_manager/update_password_infobar_delegate_android_unittest.cc
@@ -108,7 +108,7 @@
       &client_, driver_.AsWeakPtr(), observed_form_, &fetcher_,
       std::make_unique<password_manager::StubFormSaver>(),
       nullptr /* metrics_recorder */);
-  manager->ProvisionallySave(observed_form_, &driver_);
+  manager->ProvisionallySave(observed_form_, &driver_, nullptr);
   return manager;
 }
 
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index c883849..37f5826 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -1225,7 +1225,8 @@
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
   handlers->AddHandler(
-      std::make_unique<WebUsbAllowDevicesForUrlsPolicyHandler>(chrome_schema));
+      WebUsbAllowDevicesForUrlsPolicyHandler::CreateForUserPolicy(
+          chrome_schema));
 
 // On most platforms, there is a legacy policy
 // kUnsafelyTreatInsecureOriginAsSecure which has been replaced by
@@ -1558,6 +1559,9 @@
       SCHEMA_ALLOW_UNKNOWN,
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
+  handlers->AddHandler(
+      WebUsbAllowDevicesForUrlsPolicyHandler::CreateForDevicePolicy(
+          chrome_schema));
 #endif  // defined(OS_CHROMEOS)
 
 #if BUILDFLAG(ENABLE_PLUGINS)
diff --git a/chrome/browser/policy/e2e_test/tests/allow_deleting_browser_history/allow_deleting_browser_history.py b/chrome/browser/policy/e2e_test/tests/allow_deleting_browser_history/allow_deleting_browser_history.py
index a698818..2a22c62 100644
--- a/chrome/browser/policy/e2e_test/tests/allow_deleting_browser_history/allow_deleting_browser_history.py
+++ b/chrome/browser/policy/e2e_test/tests/allow_deleting_browser_history/allow_deleting_browser_history.py
@@ -12,7 +12,7 @@
 class AllowDeletingBrowserHistory(ChromeEnterpriseTestCase):
   """Test the AllowDeletingBrowserHistory policy:
 
-    https://www.chromium.org/administrators/policy-list-3#AllowDeletingBrowserHistory.
+    https://cloud.google.com/docs/chrome-enterprise/policies/?policy=AllowDeletingBrowserHistory.
     """
 
   @before_all
diff --git a/chrome/browser/policy/e2e_test/tests/safe_browsing/safe_browsing.py b/chrome/browser/policy/e2e_test/tests/safe_browsing/safe_browsing.py
index 010340afe..ea4a36c 100644
--- a/chrome/browser/policy/e2e_test/tests/safe_browsing/safe_browsing.py
+++ b/chrome/browser/policy/e2e_test/tests/safe_browsing/safe_browsing.py
@@ -11,7 +11,7 @@
 class SafeBrowsingEnabledTest(ChromeEnterpriseTestCase):
   """Test the SafeBrowsingEnabled policy.
 
-  See https://www.chromium.org/administrators/policy-list-3#SafeBrowsingEnabled"""
+  See https://cloud.google.com/docs/chrome-enterprise/policies/?policy=SafeBrowsingEnabled"""
 
   @before_all
   def setup(self):
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 0a7a5a7..08e1422 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -4536,7 +4536,7 @@
         nullptr);
     auto urls = std::make_unique<base::Value>(base::Value::Type::LIST);
     for (const auto* url_string : kRestoredURLs)
-      urls->GetList().emplace_back(url_string);
+      urls->Append(url_string);
     policies.Set(key::kURLBlacklist, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
                  POLICY_SOURCE_CLOUD, std::move(urls), nullptr);
     provider_.UpdateChromePolicy(policies);
@@ -6548,7 +6548,7 @@
             GetAppLockScreenStatus(app->id()));
 
   auto policy = std::make_unique<base::ListValue>();
-  policy->GetList().emplace_back(base::Value(kTestAppId));
+  policy->Append(base::Value(kTestAppId));
   SetPolicyValue(std::move(policy));
 
   EXPECT_EQ(chromeos::NoteTakingLockScreenSupport::kSupported,
@@ -6850,17 +6850,17 @@
   device_value.SetKey("product_id", base::Value(0));
 
   base::Value devices_value(base::Value::Type::LIST);
-  devices_value.GetList().push_back(std::move(device_value));
+  devices_value.Append(std::move(device_value));
 
   base::Value urls_value(base::Value::Type::LIST);
-  urls_value.GetList().emplace_back(base::Value("https://foo.com"));
+  urls_value.Append(base::Value("https://foo.com"));
 
   base::Value entry(base::Value::Type::DICTIONARY);
   entry.SetKey("devices", std::move(devices_value));
   entry.SetKey("urls", std::move(urls_value));
 
   auto policy_value = std::make_unique<base::Value>(base::Value::Type::LIST);
-  policy_value->GetList().push_back(std::move(entry));
+  policy_value->Append(std::move(entry));
 
   SetPolicy(&policies, key::kWebUsbAllowDevicesForUrls,
             std::move(policy_value));
@@ -6975,7 +6975,7 @@
     item.SetKey("default_launch_container", std::move(launch_container));
 
     base::Value list(base::Value::Type::LIST);
-    list.GetList().push_back(std::move(item));
+    list.Append(std::move(item));
 
     PolicyMap policies;
     SetPolicy(&policies, key::kWebAppInstallForceList,
diff --git a/chrome/browser/policy/policy_conversions.cc b/chrome/browser/policy/policy_conversions.cc
index 0a34214..7489aa730 100644
--- a/chrome/browser/policy/policy_conversions.cc
+++ b/chrome/browser/policy/policy_conversions.cc
@@ -220,7 +220,7 @@
     extension_policies_data.SetKey("name", Value(extension->name()));
     extension_policies_data.SetKey("id", Value(extension->id()));
     extension_policies_data.SetKey("policies", std::move(extension_policies));
-    policies.GetList().push_back(std::move(extension_policies_data));
+    policies.Append(std::move(extension_policies_data));
   }
 #endif
   return policies;
@@ -297,7 +297,7 @@
     current_account_policies_data.SetKey("name", Value(user_id));
     current_account_policies_data.SetKey("policies",
                                          std::move(current_account_policies));
-    policies.GetList().push_back(std::move(current_account_policies_data));
+    policies.Append(std::move(current_account_policies_data));
   }
 
   // Reset |user_policies_enabled_| setup.
@@ -365,9 +365,9 @@
   Value result(Value::Type::LIST);
   for (const auto& element : value_copy.GetList()) {
     if (element.is_dict()) {
-      result.GetList().emplace_back(Value(ConvertValueToJSON(element)));
+      result.Append(Value(ConvertValueToJSON(element)));
     } else {
-      result.GetList().push_back(element.Clone());
+      result.Append(element.Clone());
     }
   }
   return result;
@@ -452,7 +452,7 @@
     for (const auto& conflict : policy.conflicts) {
       base::Value conflicted_policy_value =
           GetPolicyValue(policy_name, conflict, errors, known_policy_schemas);
-      conflict_values.GetList().push_back(std::move(conflicted_policy_value));
+      conflict_values.Append(std::move(conflicted_policy_value));
     }
 
     value.SetKey("conflicts", std::move(conflict_values));
@@ -569,7 +569,7 @@
   Value all_policies(Value::Type::LIST);
 
   if (profile()) {
-    all_policies.GetList().push_back(GetChromePolicies());
+    all_policies.Append(GetChromePolicies());
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
     Value extension_policies = GetExtensionsPolicies();
@@ -589,7 +589,7 @@
 
   Value identity_fields = GetIdentityFields();
   if (!identity_fields.is_none())
-    all_policies.GetList().push_back(std::move(identity_fields));
+    all_policies.Append(std::move(identity_fields));
 #endif  // defined(OS_CHROMEOS)
 
   return all_policies;
diff --git a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc
index 2bc531f..39fc46a 100644
--- a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc
+++ b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc
@@ -17,6 +17,7 @@
 #include "components/policy/core/browser/policy_error_map.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/policy_constants.h"
+#include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_value_map.h"
 #include "url/gurl.h"
 
@@ -38,12 +39,42 @@
 
 }  // namespace
 
+// static
+std::unique_ptr<WebUsbAllowDevicesForUrlsPolicyHandler>
+WebUsbAllowDevicesForUrlsPolicyHandler::CreateForUserPolicy(
+    const Schema& chrome_schema) {
+  return std::make_unique<WebUsbAllowDevicesForUrlsPolicyHandler>(
+      key::kWebUsbAllowDevicesForUrls, prefs::kManagedWebUsbAllowDevicesForUrls,
+      chrome_schema);
+}
+
+#if defined(OS_CHROMEOS)
+// static
+std::unique_ptr<WebUsbAllowDevicesForUrlsPolicyHandler>
+WebUsbAllowDevicesForUrlsPolicyHandler::CreateForDevicePolicy(
+    const Schema& chrome_schema) {
+  return std::make_unique<WebUsbAllowDevicesForUrlsPolicyHandler>(
+      key::kDeviceLoginScreenWebUsbAllowDevicesForUrls,
+      prefs::kDeviceLoginScreenWebUsbAllowDevicesForUrls, chrome_schema);
+}
+
+// static
+void WebUsbAllowDevicesForUrlsPolicyHandler::RegisterPrefs(
+    PrefRegistrySimple* registry) {
+  registry->RegisterListPref(
+      prefs::kDeviceLoginScreenWebUsbAllowDevicesForUrls);
+}
+#endif  // defined(OS_CHROMEOS)
+
 WebUsbAllowDevicesForUrlsPolicyHandler::WebUsbAllowDevicesForUrlsPolicyHandler(
-    Schema schema)
+    const char* policy_name,
+    const char* pref_name,
+    const Schema& chrome_schema)
     : SchemaValidatingPolicyHandler(
-          key::kWebUsbAllowDevicesForUrls,
-          schema.GetKnownProperty(key::kWebUsbAllowDevicesForUrls),
-          SchemaOnErrorStrategy::SCHEMA_ALLOW_UNKNOWN) {}
+          policy_name,
+          chrome_schema.GetKnownProperty(policy_name),
+          SchemaOnErrorStrategy::SCHEMA_ALLOW_UNKNOWN),
+      pref_name_(pref_name) {}
 
 WebUsbAllowDevicesForUrlsPolicyHandler::
     ~WebUsbAllowDevicesForUrlsPolicyHandler() {}
@@ -90,7 +121,7 @@
           device.FindKeyOfType(kProductIdKey, base::Value::Type::INTEGER);
       if (product_id_value) {
         // If a |product_id| is specified, then a |vendor_id| must also be
-        // specified. Otherwise, the device policy is invalid.
+        // specified. Otherwise, the policy is invalid.
         if (vendor_id_value) {
           const int product_id = product_id_value->GetInt();
           if (product_id > 0xFFFF || product_id < 0) {
@@ -181,7 +212,7 @@
   if (!value || !value->is_list())
     return;
 
-  prefs->SetValue(prefs::kManagedWebUsbAllowDevicesForUrls,
+  prefs->SetValue(pref_name_,
                   base::Value::FromUniquePtrValue(std::move(value)));
 }
 
diff --git a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h
index 9580c4c..a4a13d2 100644
--- a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h
+++ b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h
@@ -5,9 +5,12 @@
 #ifndef CHROME_BROWSER_POLICY_WEBUSB_ALLOW_DEVICES_FOR_URLS_POLICY_HANDLER_H_
 #define CHROME_BROWSER_POLICY_WEBUSB_ALLOW_DEVICES_FOR_URLS_POLICY_HANDLER_H_
 
+#include <memory>
+
 #include "base/macros.h"
 #include "components/policy/core/browser/configuration_policy_handler.h"
 
+class PrefRegistrySimple;
 class PrefValueMap;
 
 namespace policy {
@@ -18,7 +21,19 @@
 class WebUsbAllowDevicesForUrlsPolicyHandler
     : public SchemaValidatingPolicyHandler {
  public:
-  explicit WebUsbAllowDevicesForUrlsPolicyHandler(Schema schema);
+  static std::unique_ptr<WebUsbAllowDevicesForUrlsPolicyHandler>
+  CreateForUserPolicy(const Schema& chrome_schema);
+
+#if defined(OS_CHROMEOS)
+  static std::unique_ptr<WebUsbAllowDevicesForUrlsPolicyHandler>
+  CreateForDevicePolicy(const Schema& chrome_schema);
+
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+#endif  // defined(OS_CHROMEOS)
+
+  WebUsbAllowDevicesForUrlsPolicyHandler(const char* policy_name,
+                                         const char* pref_name,
+                                         const Schema& chrome_schema);
   ~WebUsbAllowDevicesForUrlsPolicyHandler() override;
 
   // ConfigurationPolicyHandler implementation:
@@ -28,6 +43,9 @@
                            PrefValueMap* prefs) override;
 
  private:
+  // The name of the pref to apply the policy to.
+  const char* pref_name_;
+
   DISALLOW_COPY_AND_ASSIGN(WebUsbAllowDevicesForUrlsPolicyHandler);
 };
 
diff --git a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc
index 1c0c1b2..138f1ca 100644
--- a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc
+++ b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/json/json_reader.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/common/pref_names.h"
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/policy/core/browser/configuration_policy_pref_store.h"
 #include "components/policy/core/browser/configuration_policy_pref_store_test.h"
@@ -18,11 +19,16 @@
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/core/common/schema.h"
 #include "components/policy/policy_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
 
 namespace {
 
+// For ChromeOS this test is parameterized to test user and device policy. For
+// other operating systems, this test just tests the user policy.
+enum class PolicyType { kUser, kDevice };
+
 constexpr char kDevicesKey[] = "devices";
 constexpr char kUrlsKey[] = "urls";
 constexpr char kVendorIdKey[] = "vendor_id";
@@ -203,6 +209,35 @@
       }
     ])";
 
+std::string GetPolicyName(PolicyType policy_type) {
+#if defined(OS_CHROMEOS)
+  if (policy_type == PolicyType::kDevice)
+    return key::kDeviceLoginScreenWebUsbAllowDevicesForUrls;
+#endif  // defined(OS_CHROMEOS)
+  return key::kWebUsbAllowDevicesForUrls;
+}
+
+std::string GetPrefName(PolicyType policy_type) {
+#if defined(OS_CHROMEOS)
+  if (policy_type == PolicyType::kDevice)
+    return prefs::kDeviceLoginScreenWebUsbAllowDevicesForUrls;
+#endif  // defined(OS_CHROMEOS)
+  return prefs::kManagedWebUsbAllowDevicesForUrls;
+}
+
+std::unique_ptr<WebUsbAllowDevicesForUrlsPolicyHandler> CreateHandler(
+    PolicyType policy_type,
+    const Schema& chrome_schema) {
+#if defined(OS_CHROMEOS)
+  if (policy_type == PolicyType::kDevice) {
+    return WebUsbAllowDevicesForUrlsPolicyHandler::CreateForDevicePolicy(
+        chrome_schema);
+  }
+#endif  // defined(OS_CHROMEOS)
+  return WebUsbAllowDevicesForUrlsPolicyHandler::CreateForUserPolicy(
+      chrome_schema);
+}
+
 std::unique_ptr<base::Value> ReadJson(base::StringPiece json) {
   base::Optional<base::Value> value = base::JSONReader::Read(json);
   EXPECT_TRUE(value);
@@ -212,44 +247,54 @@
 }  // namespace
 
 class WebUsbAllowDevicesForUrlsPolicyHandlerTest
-    : public ConfigurationPolicyPrefStoreTest {
+    : public ConfigurationPolicyPrefStoreTest,
+      public testing::WithParamInterface<PolicyType> {
  public:
+  WebUsbAllowDevicesForUrlsPolicyHandlerTest()
+      : policy_name_(GetPolicyName(GetParam())),
+        pref_name_(GetPrefName(GetParam())) {}
+
   WebUsbAllowDevicesForUrlsPolicyHandler* handler() { return handler_; }
 
+ protected:
+  const std::string policy_name_;
+  const std::string pref_name_;
+
  private:
   void SetUp() override {
     Schema chrome_schema = Schema::Wrap(GetChromeSchemaData());
-    auto handler =
-        std::make_unique<WebUsbAllowDevicesForUrlsPolicyHandler>(chrome_schema);
+    auto handler = CreateHandler(GetParam(), chrome_schema);
     handler_ = handler.get();
     handler_list_.AddHandler(std::move(handler));
   }
 
   WebUsbAllowDevicesForUrlsPolicyHandler* handler_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebUsbAllowDevicesForUrlsPolicyHandlerTest);
 };
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest, CheckPolicySettings) {
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest, CheckPolicySettings) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kValidPolicy), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD, ReadJson(kValidPolicy),
+             nullptr);
   ASSERT_TRUE(errors.empty());
   EXPECT_TRUE(handler()->CheckPolicySettings(policy, &errors));
   EXPECT_TRUE(errors.empty());
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithInvalidTopLevelEntry) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidTopLevelEntry), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidTopLevelEntry), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -258,18 +303,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[1]\": Missing or invalid required "
       "property: devices");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithMissingDevicesProperty) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMissingDevicesProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMissingDevicesProperty), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -278,18 +323,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0]\": Missing or invalid required "
       "property: devices");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithMissingUrlsProperty) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMissingUrlsProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMissingUrlsProperty), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -298,18 +343,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0]\": Missing or invalid required "
       "property: urls");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsUnknownProperty) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyUnknownProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyUnknownProperty), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_TRUE(handler()->CheckPolicySettings(policy, &errors));
@@ -318,38 +363,38 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].devices.items[0]\": Unknown "
       "property: serialNumber");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithMismatchedVendorIdType) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMismatchedVendorIdType), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMismatchedVendorIdType), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
   EXPECT_EQ(1ul, errors.size());
 
   const base::string16 kExpected = base::ASCIIToUTF16(
-      "Schema validation error at \"items[0].devices.items[0]\": The vendor_id "
-      "must be an unsigned short integer");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+      "Schema validation error at \"items[0].devices.items[0]\": The "
+      "vendor_id must be an unsigned short integer");
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithMismatchedProductIdType) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMismatchedProductIdType), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMismatchedProductIdType), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -358,18 +403,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].devices.items[0]\": The "
       "product_id must be an unsigned short integer");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithProductIdWithoutVendorId) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyProductIdWithoutVendorId), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyProductIdWithoutVendorId), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -378,18 +423,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].devices.items[0]\": A vendor_id "
       "must also be specified");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithInvalidRequestingUrlEntry) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidRequestingUrl), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidRequestingUrl), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -398,18 +443,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].urls.items[0]\": The urls item "
       "must contain valid URLs");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithInvalidEmbeddingUrlEntry) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidEmbeddingUrl), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidEmbeddingUrl), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -418,18 +463,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].urls.items[0]\": The urls item "
       "must contain valid URLs");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithInvalidUrlsEntry) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidUrlsEntry), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidUrlsEntry), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -438,18 +483,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].urls.items[0]\": Each urls "
       "string entry must contain between 1 to 2 URLs");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithNoUrls) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(InvalidPolicyNoUrls), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD, ReadJson(InvalidPolicyNoUrls),
+             nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -458,23 +503,21 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].urls.items[0]\": Each urls "
       "string entry must contain between 1 to 2 URLs");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest, ApplyPolicySettings) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest, ApplyPolicySettings) {
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kValidPolicy), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD, ReadJson(kValidPolicy),
+             nullptr);
   UpdateProviderPolicy(policy);
 
   const base::Value* pref_value = nullptr;
-  EXPECT_TRUE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_TRUE(store_->GetValue(pref_name_, &pref_value));
   ASSERT_TRUE(pref_value);
   ASSERT_TRUE(pref_value->is_list());
 
@@ -539,72 +582,64 @@
   EXPECT_EQ("https://chromium.org,", second_urls_list[0].GetString());
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithInvalidTopLevelEntry) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidTopLevelEntry), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidTopLevelEntry), nullptr);
   UpdateProviderPolicy(policy);
 
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithMissingDevicesProperty) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMissingDevicesProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMissingDevicesProperty), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithMissingUrlsProperty) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMissingUrlsProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMissingUrlsProperty), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithUnknownProperty) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyUnknownProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyUnknownProperty), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_TRUE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_TRUE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_TRUE(pref_value);
 
   std::unique_ptr<base::Value> expected_pref_value =
@@ -612,122 +647,119 @@
   EXPECT_EQ(*expected_pref_value, *pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithMismatchedVendorIdType) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMismatchedVendorIdType), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMismatchedVendorIdType), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithMismatchedProductIdType) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMismatchedProductIdType), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMismatchedProductIdType), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsProductIdWithoutVendorId) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyProductIdWithoutVendorId), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyProductIdWithoutVendorId), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsInvalidRequestingUrl) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidRequestingUrl), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidRequestingUrl), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsInvalidEmbeddingUrl) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidEmbeddingUrl), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidEmbeddingUrl), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsInvalidUrlsEntry) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidUrlsEntry), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidUrlsEntry), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest, ApplyPolicySettingsNoUrls) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest, ApplyPolicySettingsNoUrls) {
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(InvalidPolicyNoUrls), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD, ReadJson(InvalidPolicyNoUrls),
+             nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
+// For ChromeOS this test is parameterized to test user and device policy. For
+// other operating systems, this test just tests the user policy.
+INSTANTIATE_TEST_SUITE_P(,
+                         WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+#if defined(OS_CHROMEOS)
+                         testing::Values(PolicyType::kUser, PolicyType::kDevice)
+#else
+                         testing::Values(PolicyType::kUser)
+#endif
+);
+
 }  // namespace policy
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 45e09c1..ce7a864 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -45,6 +45,7 @@
 #include "chrome/browser/notifications/platform_notification_service_impl.h"
 #include "chrome/browser/pepper_flash_settings_manager.h"
 #include "chrome/browser/policy/developer_tools_policy_handler.h"
+#include "chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h"
 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/prefs/origin_trial_prefs.h"
@@ -700,6 +701,7 @@
   policy::DMTokenStorage::RegisterPrefs(registry);
   policy::PolicyCertServiceFactory::RegisterPrefs(registry);
   policy::TPMAutoUpdateModePolicyHandler::RegisterPrefs(registry);
+  policy::WebUsbAllowDevicesForUrlsPolicyHandler::RegisterPrefs(registry);
   quirks::QuirksManager::RegisterPrefs(registry);
   UpgradeDetectorChromeos::RegisterPrefs(registry);
   syncer::PerUserTopicRegistrationManager::RegisterPrefs(registry);
diff --git a/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc b/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc
index 35efb3dea..8defd79 100644
--- a/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc
+++ b/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc
@@ -171,6 +171,7 @@
 
   redirect_info_ = net::RedirectInfo::ComputeRedirectInfo(
       modified_resource_request_.method, modified_resource_request_.url,
+      modified_resource_request_.request_initiator,
       modified_resource_request_.site_for_cookies,
       net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT,
       modified_resource_request_.referrer_policy,
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc
index 56058d9..c193333 100644
--- a/chrome/browser/profiles/profile.cc
+++ b/chrome/browser/profiles/profile.cc
@@ -273,7 +273,7 @@
   return false;
 }
 
-network::mojom::NetworkContextPtr Profile::CreateNetworkContext(
+mojo::Remote<network::mojom::NetworkContext> Profile::CreateNetworkContext(
     bool in_memory,
     const base::FilePath& relative_partition_path) {
   return ProfileNetworkContextServiceFactory::GetForContext(this)
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index 6a7b2e1c..bb09087 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -19,6 +19,7 @@
 #include "components/domain_reliability/clear_mode.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/content_browser_client.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/network/public/mojom/network_service.mojom-forward.h"
 
 #if !defined(OS_ANDROID)
@@ -375,7 +376,7 @@
 
   // Creates NetworkContext for the specified isolated app (or for the profile
   // itself, if |relative_path| is empty).
-  virtual network::mojom::NetworkContextPtr CreateNetworkContext(
+  virtual mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext(
       bool in_memory,
       const base::FilePath& relative_partition_path);
 
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 5fb5b84..72136e5 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -252,7 +252,7 @@
   // on shutdown. In case of a crash remaining files are removed on next start.
   ListPrefUpdate deleted_profiles(g_browser_process->local_state(),
                                   prefs::kProfilesDeleted);
-  deleted_profiles->GetList().push_back(CreateFilePathValue(path));
+  deleted_profiles->Append(CreateFilePathValue(path));
 }
 
 // Cancel a scheduling deletion, so ScheduleProfileDirectoryForDeletion can be
diff --git a/chrome/browser/profiling_host/profiling_process_host.cc b/chrome/browser/profiling_host/profiling_process_host.cc
index efc1e4f..2b0df49 100644
--- a/chrome/browser/profiling_host/profiling_process_host.cc
+++ b/chrome/browser/profiling_host/profiling_process_host.cc
@@ -77,7 +77,7 @@
   base::Value rule(base::Value::Type::DICTIONARY);
   rule.SetKey("rule", base::Value("MEMLOG"));
   rule.SetKey("trigger_name", base::Value(std::move(trigger_name)));
-  rules_list.GetList().push_back(std::move(rule));
+  rules_list.Append(std::move(rule));
 
   std::string sampling_mode = base::StringPrintf("SAMPLING_%u", sampling_rate);
 
diff --git a/chrome/browser/resources/bookmarks/README.md b/chrome/browser/resources/bookmarks/README.md
index c6c83b16..272a91d 100644
--- a/chrome/browser/resources/bookmarks/README.md
+++ b/chrome/browser/resources/bookmarks/README.md
@@ -23,11 +23,11 @@
   and between two different BMM instances from different Chrome profiles.
 * **Policy support**: Several policies are respected:
 
-  - [EditBookmarksEnabled](https://www.chromium.org/administrators/policy-list-3#EditBookmarksEnabled):
+  - [EditBookmarksEnabled](https://cloud.google.com/docs/chrome-enterprise/policies/?policy=EditBookmarksEnabled):
     Prevents all editing operations
-  - [ManagedBookmarks](https://www.chromium.org/administrators/policy-list-3#ManagedBookmarks):
+  - [ManagedBookmarks](https://cloud.google.com/docs/chrome-enterprise/policies/?policy=ManagedBookmarks):
     Defines a folder of immutable bookmarks.
-  - [IncognitoModeAvailability](https://www.chromium.org/administrators/policy-list-3#IncognitoModeAvailability):
+  - [IncognitoModeAvailability](https://cloud.google.com/docs/chrome-enterprise/policies/?policy=IncognitoModeAvailability):
     Disables/force-enables opening bookmarks in Incognito
 
 ## Data-flow model
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html
index ee362e4..15c7ade 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html
@@ -33,7 +33,7 @@
             disabled="[[buttonsDisabled]]">
           <div i18n-content="assistantOptinSkipButton"></div>
         </oobe-text-button>
-        <oobe-text-button id="retry-button" inverse android
+        <oobe-text-button id="retry-button" inverse
             on-tap="onRetryTap_" disabled="[[buttonsDisabled]]">
           <div i18n-content="assistantOptinRetryButton"></div>
         </oobe-text-button>
diff --git a/chrome/browser/resources/chromeos/login/oobe_buttons.html b/chrome/browser/resources/chromeos/login/oobe_buttons.html
index 20ef6b3..373a888 100644
--- a/chrome/browser/resources/chromeos/login/oobe_buttons.html
+++ b/chrome/browser/resources/chromeos/login/oobe_buttons.html
@@ -59,7 +59,7 @@
     <link rel="stylesheet" href="oobe_text_buttons.css">
     <cr-button id="textButton" on-tap="onClick_" disabled="[[disabled]]"
         inverse$="[[inverse]]" aria-label$="[[labelForAria]]"
-        border$="[[border]]" android$="[[android]]">
+        border$="[[border]]">
       <div id="container"
           class="flex layout horizontal center center-justified self-stretch">
         <slot></slot>
diff --git a/chrome/browser/resources/chromeos/login/oobe_buttons.js b/chrome/browser/resources/chromeos/login/oobe_buttons.js
index 57d018a..f1da4755 100644
--- a/chrome/browser/resources/chromeos/login/oobe_buttons.js
+++ b/chrome/browser/resources/chromeos/login/oobe_buttons.js
@@ -15,8 +15,6 @@
 
     border: Boolean,
 
-    android: {type: Boolean, value: false},
-
     /* Note that we are not using "aria-label" property here, because
      * we want to pass the label value but not actually declare it as an
      * ARIA property anywhere but the actual target element.
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.css b/chrome/browser/resources/chromeos/login/oobe_dialog.css
index a0e4fc3..11ce8fed 100644
--- a/chrome/browser/resources/chromeos/login/oobe_dialog.css
+++ b/chrome/browser/resources/chromeos/login/oobe_dialog.css
@@ -77,18 +77,6 @@
   padding: unset;
 }
 
-#oobe-bottom[android] {
-  box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.14);
-}
-
-#oobe-bottom[android][hideShadow] {
-  box-shadow: unset;
-}
-
-#oobe-bottom[android] {
-  height: 60px;
-}
-
 #oobe-bottom ::slotted(*) {
   width: 100%;
 }
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.html b/chrome/browser/resources/chromeos/login/oobe_dialog.html
index 6363c8f..c7cdfbf 100644
--- a/chrome/browser/resources/chromeos/login/oobe_dialog.html
+++ b/chrome/browser/resources/chromeos/login/oobe_dialog.html
@@ -58,7 +58,7 @@
     <link rel="stylesheet" href="oobe_dialog.css">
     <link rel="stylesheet" href="oobe_flex_layout.css">
     <style include="cr-shared-style"></style>
-    <div id="header-container" hidden="[[noHeader]]" android$="[[android]]">
+    <div id="header-container" hidden="[[noHeader]]">
       <div id="oobe-icon-div">
         <slot name="oobe-icon"></slot>
       </div>
@@ -77,7 +77,7 @@
       <slot name="footer"></slot>
     </div>
     <template is="dom-if" if="[[hasButtons]]">
-      <div id="oobe-bottom" hideShadow$="[[hideShadow]]" android$="[[android]]"
+      <div id="oobe-bottom" hideShadow$="[[hideShadow]]"
         no-buttons-padding$="[[noButtonsPadding]]"
           class="layout horizontal center">
         <slot name="bottom-buttons"></slot>
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.js b/chrome/browser/resources/chromeos/login/oobe_dialog.js
index a139554..4702732d 100644
--- a/chrome/browser/resources/chromeos/login/oobe_dialog.js
+++ b/chrome/browser/resources/chromeos/login/oobe_dialog.js
@@ -55,11 +55,6 @@
       reflectToAttribute: true,
       observer: 'onfullScreenDialogChanged_',
     },
-
-    android: {
-      type: Boolean,
-      value: false,
-    },
   },
 
   focus: function() {
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog_host.css b/chrome/browser/resources/chromeos/login/oobe_dialog_host.css
index 5647c4b..4665668 100644
--- a/chrome/browser/resources/chromeos/login/oobe_dialog_host.css
+++ b/chrome/browser/resources/chromeos/login/oobe_dialog_host.css
@@ -22,8 +22,3 @@
   border-radius: 4px;
   box-shadow: 0 24px 24px rgba(0, 0, 0, .24), 0 0 24px rgba(0, 0, 0, .12);
 }
-
-:host([android]) {
-  min-height: 480px;
-  min-width: 576px;
-}
diff --git a/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html b/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html
index a974334..78ac464 100644
--- a/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html
+++ b/chrome/browser/resources/settings/about_page/channel_switcher_dialog.html
@@ -19,7 +19,7 @@
       <div slot="title">$i18n{aboutChangeChannel}</div>
       <div slot="body">
         <!-- TODO(dbeam): this can be policy-controlled. Show this in the UI.
-             https://www.chromium.org/administrators/policy-list-3#ChromeOsReleaseChannel
+             https://cloud.google.com/docs/chrome-enterprise/policies/?policy=ChromeOsReleaseChannel
         -->
         <cr-radio-group on-selected-changed="onChannelSelectionChanged_">
           <cr-radio-button name="[[browserChannelEnum_.STABLE]]">
diff --git a/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate_unittest.cc
index 8c08f13..1509f61 100644
--- a/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate_unittest.cc
@@ -147,8 +147,8 @@
       }
       case Value::Type::LIST: {
         Value value(base::Value::Type::LIST);
-        value.GetList().emplace_back(22);
-        value.GetList().emplace_back(47);
+        value.Append(22);
+        value.Append(47);
         return value;
       }
       default:
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index 3eeccbed..764baf1 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -352,7 +352,7 @@
     dict.SetKey("collectionName", base::Value(collection.collection_name));
     dict.SetKey("previewImageUrl",
                 base::Value(collection.preview_image_url.spec()));
-    collections.GetList().push_back(std::move(dict));
+    collections.Append(std::move(dict));
   }
   return collections;
 }
@@ -369,12 +369,12 @@
     dict.SetKey("collectionId", base::Value(image.collection_id));
     base::Value attributions(base::Value::Type::LIST);
     for (const auto& attribution : image.attribution) {
-      attributions.GetList().push_back(base::Value(attribution));
+      attributions.Append(base::Value(attribution));
     }
     dict.SetKey("attributions", std::move(attributions));
     dict.SetKey("attributionActionUrl",
                 base::Value(image.attribution_action_url.spec()));
-    images.GetList().push_back(std::move(dict));
+    images.Append(std::move(dict));
   }
   return images;
 }
diff --git a/chrome/browser/search/search_suggest/search_suggest_service.cc b/chrome/browser/search/search_suggest/search_suggest_service.cc
index cb93ea9..54d3a06 100644
--- a/chrome/browser/search/search_suggest/search_suggest_service.cc
+++ b/chrome/browser/search/search_suggest/search_suggest_service.cc
@@ -297,7 +297,7 @@
   base::Value* value = blocklist->FindKey(task_version_id);
   if (!value)
     value = blocklist->SetKey(task_version_id, base::ListValue());
-  value->GetList().emplace_back(base::Value(hash_string));
+  value->Append(base::Value(hash_string));
 
   search_suggest_data_ = base::nullopt;
   Refresh();
diff --git a/chrome/browser/site_isolation/site_isolation_policy_unittest.cc b/chrome/browser/site_isolation/site_isolation_policy_unittest.cc
index 3772365..7ecac8e 100644
--- a/chrome/browser/site_isolation/site_isolation_policy_unittest.cc
+++ b/chrome/browser/site_isolation/site_isolation_policy_unittest.cc
@@ -63,8 +63,8 @@
     ListPrefUpdate update(profile->GetPrefs(),
                           prefs::kUserTriggeredIsolatedOrigins);
     base::ListValue* list = update.Get();
-    list->GetList().emplace_back("http://foo.com");
-    list->GetList().emplace_back("https://bar.com");
+    list->Append("http://foo.com");
+    list->Append("https://bar.com");
   }
 
   // New SiteInstances for foo.com and bar.com shouldn't require a dedicated
@@ -141,7 +141,7 @@
     ListPrefUpdate update(profile->GetPrefs(),
                           prefs::kUserTriggeredIsolatedOrigins);
     base::ListValue* list = update.Get();
-    list->GetList().emplace_back("http://foo.com");
+    list->Append("http://foo.com");
   }
 
   // Applying saved isolated origins should have no effect, since site
diff --git a/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc b/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc
index 29ccbf2..9ac50ce 100644
--- a/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc
+++ b/chrome/browser/ssl/chrome_ssl_host_state_delegate.cc
@@ -122,7 +122,7 @@
     // (i.e. out of order). Save a new list composed of just this one error
     // instance.
     base::ListValue error_list;
-    error_list.GetList().push_back(base::Value(now));
+    error_list.Append(base::Value(now));
     pref_update->SetKey(net::ErrorToShortString(error), std::move(error_list));
   } else {
     // Only up to |threshold| values need to be stored. If the list already
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index 5e4d0be..9307472 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -1884,7 +1884,7 @@
     std::unique_ptr<base::ListValue> policy_value =
         std::make_unique<base::ListValue>();
     for (const auto& value : list_values) {
-      policy_value->GetList().emplace_back(value);
+      policy_value->Append(value);
     }
     policy::PolicyMap policy_map;
     policy_map.Set(policy_name, policy::POLICY_LEVEL_MANDATORY,
@@ -2279,7 +2279,7 @@
   base::Value* filters = setting->SetKey("filters", base::ListValue());
   base::DictionaryValue filter = base::DictionaryValue();
   filter.SetString("ISSUER.CN", "pywebsocket");
-  filters->GetList().push_back(std::move(filter));
+  filters->Append(std::move(filter));
   HostContentSettingsMapFactory::GetForProfile(profile)
       ->SetWebsiteSettingDefaultScope(
           url, GURL(), CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
@@ -2381,7 +2381,7 @@
   std::unique_ptr<base::DictionaryValue> setting =
       std::make_unique<base::DictionaryValue>();
   base::Value* filters = setting->SetKey("filters", base::ListValue());
-  filters->GetList().push_back(base::DictionaryValue());
+  filters->Append(base::DictionaryValue());
   HostContentSettingsMapFactory::GetForProfile(profile)
       ->SetWebsiteSettingDefaultScope(
           https_url, GURL(), CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
@@ -2417,7 +2417,7 @@
   std::unique_ptr<base::DictionaryValue> setting =
       std::make_unique<base::DictionaryValue>();
   base::Value* filters = setting->SetKey("filters", base::ListValue());
-  filters->GetList().push_back(base::DictionaryValue());
+  filters->Append(base::DictionaryValue());
   HostContentSettingsMapFactory::GetForProfile(profile)
       ->SetWebsiteSettingDefaultScope(
           https_url, GURL(), CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
@@ -2480,7 +2480,7 @@
   std::unique_ptr<base::DictionaryValue> setting =
       std::make_unique<base::DictionaryValue>();
   base::Value* filters = setting->SetKey("filters", base::ListValue());
-  filters->GetList().push_back(base::DictionaryValue());
+  filters->Append(base::DictionaryValue());
   HostContentSettingsMapFactory::GetForProfile(profile)
       ->SetWebsiteSettingDefaultScope(
           https_url, GURL(), CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
diff --git a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
index 4ea334d..9b9b453 100644
--- a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
+++ b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
@@ -247,15 +247,15 @@
 
   auto patterns = std::make_unique<base::ListValue>();
   // Patterns expected to be canonicalized.
-  patterns->GetList().emplace_back(base::Value("canon.example"));
-  patterns->GetList().emplace_back(base::Value(".NonCanon.example"));
-  patterns->GetList().emplace_back(base::Value("Non-Canon.example"));
-  patterns->GetList().emplace_back(base::Value("127.0.0.1"));
-  patterns->GetList().emplace_back(base::Value("2147614986"));
+  patterns->Append(base::Value("canon.example"));
+  patterns->Append(base::Value(".NonCanon.example"));
+  patterns->Append(base::Value("Non-Canon.example"));
+  patterns->Append(base::Value("127.0.0.1"));
+  patterns->Append(base::Value("2147614986"));
   // Patterns expected to be skipped.
-  patterns->GetList().emplace_back(base::Value("???"));
-  patterns->GetList().emplace_back(base::Value("example.com/"));
-  patterns->GetList().emplace_back(base::Value("xn--hellö.com"));
+  patterns->Append(base::Value("???"));
+  patterns->Append(base::Value("example.com/"));
+  patterns->Append(base::Value("xn--hellö.com"));
   local_state.SetUserPref(prefs::kH2ClientCertCoalescingHosts,
                           std::move(patterns));
 
diff --git a/chrome/browser/sync/test/integration/p2p_sync_refresher.cc b/chrome/browser/sync/test/integration/p2p_sync_refresher.cc
deleted file mode 100644
index ad89e83..0000000
--- a/chrome/browser/sync/test/integration/p2p_sync_refresher.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/sync/test/integration/p2p_sync_refresher.h"
-
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
-#include "chrome/browser/sync/test/integration/sync_test.h"
-#include "components/sync/driver/profile_sync_service.h"
-#include "components/sync/engine/cycle/sync_cycle_snapshot.h"
-#include "content/public/browser/notification_service.h"
-
-P2PSyncRefresher::P2PSyncRefresher(Profile* profile,
-                                   syncer::ProfileSyncService* sync_service)
-    : profile_(profile), sync_service_(sync_service) {
-  sync_service_->AddObserver(this);
-}
-
-P2PSyncRefresher::~P2PSyncRefresher() {
-  sync_service_->RemoveObserver(this);
-}
-
-void P2PSyncRefresher::OnSyncCycleCompleted(syncer::SyncService* sync) {
-  const syncer::SyncCycleSnapshot& snap =
-      sync_service_->GetLastCycleSnapshotForDebugging();
-  bool is_notifiable_commit =
-      (snap.model_neutral_state().num_successful_commits > 0);
-  if (is_notifiable_commit) {
-    syncer::ModelTypeSet model_types =
-        snap.model_neutral_state().commit_request_types;
-    SyncTest* test = sync_datatype_helper::test();
-    for (int i = 0; i < test->num_clients(); ++i) {
-      if (profile_ != test->GetProfile(i))
-        test->TriggerSyncForModelTypes(i, model_types);
-    }
-  }
-}
diff --git a/chrome/browser/sync/test/integration/p2p_sync_refresher.h b/chrome/browser/sync/test/integration/p2p_sync_refresher.h
deleted file mode 100644
index b925c6a..0000000
--- a/chrome/browser/sync/test/integration/p2p_sync_refresher.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_P2P_SYNC_REFRESHER_H_
-#define CHROME_BROWSER_SYNC_TEST_INTEGRATION_P2P_SYNC_REFRESHER_H_
-
-#include "base/macros.h"
-#include "components/sync/driver/sync_service_observer.h"
-
-class Profile;
-
-namespace syncer {
-class ProfileSyncService;
-}  // namespace syncer
-
-// This class observes ProfileSyncService events and emits refresh notifications
-// to other test profiles for any committed changes it observes.
-//
-// It register and unregisters in its constructor and destructor.  This is
-// intended to make it easy to manage with a scoped_ptr.
-class P2PSyncRefresher : public syncer::SyncServiceObserver {
- public:
-  P2PSyncRefresher(Profile* profile, syncer::ProfileSyncService* sync_service);
-  ~P2PSyncRefresher() override;
-
-  // Implementation of syncer::SyncServiceObserver
-  void OnSyncCycleCompleted(syncer::SyncService* sync) override;
-
- private:
-  Profile* const profile_;            // weak
-  syncer::ProfileSyncService* sync_service_;  // weak
-
-  DISALLOW_COPY_AND_ASSIGN(P2PSyncRefresher);
-};
-
-#endif  // CHROME_BROWSER_SYNC_TEST_INTEGRATION_P2P_SYNC_REFRESHER_H_
diff --git a/chrome/browser/sync/test/integration/single_client_themes_sync_test.cc b/chrome/browser/sync/test/integration/single_client_themes_sync_test.cc
index f2f1034..6c05e9d 100644
--- a/chrome/browser/sync/test/integration/single_client_themes_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_themes_sync_test.cc
@@ -54,12 +54,7 @@
   EXPECT_EQ(GetCustomTheme(0), GetThemeID(verifier()));
 }
 
-// TODO(sync): Fails on Chrome OS. See http://crbug.com/84575.
-#if defined(OS_CHROMEOS)
-IN_PROC_BROWSER_TEST_F(SingleClientThemesSyncTest, DISABLED_NativeTheme) {
-#else
 IN_PROC_BROWSER_TEST_F(SingleClientThemesSyncTest, NativeTheme) {
-#endif  // OS_CHROMEOS
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
 
   SetCustomTheme(GetProfile(0));
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index b77e899..46563311 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -29,7 +29,6 @@
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
-#include "chrome/browser/sync/test/integration/p2p_sync_refresher.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
@@ -568,7 +567,6 @@
   profiles_.resize(num_clients_);
   profile_delegates_.resize(num_clients_ + 1);  // + 1 for the verifier.
   clients_.resize(num_clients_);
-  sync_refreshers_.resize(num_clients_);
   fake_server_invalidation_observers_.resize(num_clients_);
 
   if (create_gaia_account_at_runtime_) {
@@ -864,20 +862,7 @@
     }
   }
 
-  // SyncRefresher is used instead of invalidations to notify other profiles to
-  // do a sync refresh on committed data sets. This is only needed when running
-  // tests against external live server, otherwise invalidation service is used.
-  // With external live servers, the profiles commit data on first sync cycle
-  // automatically after signing in. To avoid misleading sync commit
-  // notifications at start up, we start the SyncRefresher observers post
-  // client set up.
   if (UsingExternalServers()) {
-    for (int i = 0; i < num_clients_; ++i) {
-      DCHECK(!sync_refreshers_[i]);
-      sync_refreshers_[i] = std::make_unique<P2PSyncRefresher>(
-          GetProfile(i), clients_[i]->service());
-    }
-
     // OneClickSigninSyncStarter observer is created with a real user sign in.
     // It is deleted on certain conditions which are not satisfied by our tests,
     // and this causes the SigninTracker observer to stay hanging at shutdown.
@@ -923,7 +908,6 @@
   }
 
   // Delete things that unsubscribe in destructor before their targets are gone.
-  sync_refreshers_.clear();
   configuration_refresher_.reset();
 }
 
diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h
index 79b2ad6..d6f4e22 100644
--- a/chrome/browser/sync/test/integration/sync_test.h
+++ b/chrome/browser/sync/test/integration/sync_test.h
@@ -49,7 +49,6 @@
 #define E2E_ENABLED(test_name) MACRO_CONCAT(test_name, E2ETest)
 
 class ProfileSyncServiceHarness;
-class P2PSyncRefresher;
 
 namespace arc {
 class SyncArcPackageHelper;
@@ -465,10 +464,6 @@
   // Mapping from client indexes to decryption passphrases to use for them.
   std::map<int, std::string> client_decryption_passphrases_;
 
-  // A set of objects to listen for commit activity and broadcast refresh
-  // notifications of this activity to its peer sync clients.
-  std::vector<std::unique_ptr<P2PSyncRefresher>> sync_refreshers_;
-
   // Owns the FakeServerInvalidationSender for each profile.
   std::vector<std::unique_ptr<fake_server::FakeServerInvalidationSender>>
       fake_server_invalidation_observers_;
diff --git a/chrome/browser/sync_file_system/drive_backend/callback_helper_unittest.cc b/chrome/browser/sync_file_system/drive_backend/callback_helper_unittest.cc
index 26dd0e4..17865a6 100644
--- a/chrome/browser/sync_file_system/drive_backend/callback_helper_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/callback_helper_unittest.cc
@@ -43,7 +43,7 @@
 }  // namespace
 
 TEST(DriveBackendCallbackHelperTest, BasicTest) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
 
   bool called = false;
   RelayCallbackToCurrentThread(
@@ -63,7 +63,7 @@
 }
 
 TEST(DriveBackendCallbackHelperTest, RunOnOtherThreadTest) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
   base::Thread thread("WorkerThread");
   thread.Start();
 
@@ -91,7 +91,7 @@
 }
 
 TEST(DriveBackendCallbackHelperTest, PassNullFunctionTest) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
   base::Closure closure = RelayCallbackToCurrentThread(
       FROM_HERE,
       base::Closure());
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
index 0465696..e7de044 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
@@ -625,7 +625,7 @@
 
  private:
   base::ScopedTempDir database_dir_;
-  base::test::TaskEnvironment task_environment_;
+  base::test::SingleThreadTaskEnvironment task_environment_;
 
   std::unique_ptr<leveldb::Env> in_memory_env_;
   std::unique_ptr<MetadataDatabase> metadata_database_;
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc b/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc
index efcb26c..4b99a3c 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc
@@ -287,7 +287,7 @@
 }  // namespace
 
 TEST(SyncTaskManagerTest, ScheduleTask) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
   TaskManagerClient client(0 /* maximum_background_task */);
   int callback_count = 0;
   SyncStatusCode callback_status = SYNC_STATUS_OK;
@@ -307,7 +307,7 @@
 }
 
 TEST(SyncTaskManagerTest, ScheduleTwoTasks) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
   TaskManagerClient client(0 /* maximum_background_task */);
   int callback_count = 0;
   SyncStatusCode callback_status = SYNC_STATUS_OK;
@@ -330,7 +330,7 @@
 }
 
 TEST(SyncTaskManagerTest, ScheduleIdleTask) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
   TaskManagerClient client(0 /* maximum_background_task */);
 
   client.ScheduleTaskIfIdle(kStatus1);
@@ -344,7 +344,7 @@
 }
 
 TEST(SyncTaskManagerTest, ScheduleIdleTaskWhileNotIdle) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
   TaskManagerClient client(0 /* maximum_background_task */);
   int callback_count = 0;
   SyncStatusCode callback_status = SYNC_STATUS_OK;
@@ -366,7 +366,7 @@
 }
 
 TEST(SyncTaskManagerTest, ScheduleAndCancelSyncTask) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
 
   int callback_count = 0;
   SyncStatusCode status = SYNC_STATUS_UNKNOWN;
@@ -395,7 +395,7 @@
 }
 
 TEST(SyncTaskManagerTest, ScheduleTaskAtPriority) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
   SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
                                0 /* maximum_background_task */,
                                base::ThreadTaskRunnerHandle::Get());
@@ -456,7 +456,7 @@
 }
 
 TEST(SyncTaskManagerTest, BackgroundTask_Sequential) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
   SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
                                10 /* maximum_background_task */,
                                base::ThreadTaskRunnerHandle::Get());
@@ -488,7 +488,7 @@
 }
 
 TEST(SyncTaskManagerTest, BackgroundTask_Parallel) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
   SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
                                10 /* maximum_background_task */,
                                base::ThreadTaskRunnerHandle::Get());
@@ -520,7 +520,7 @@
 }
 
 TEST(SyncTaskManagerTest, BackgroundTask_Throttled) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
   SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
                                2 /* maximum_background_task */,
                                base::ThreadTaskRunnerHandle::Get());
@@ -552,7 +552,7 @@
 }
 
 TEST(SyncTaskManagerTest, UpdateTaskBlocker) {
-  base::test::TaskEnvironment task_environment;
+  base::test::SingleThreadTaskEnvironment task_environment;
   SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
                                10 /* maximum_background_task */,
                                base::ThreadTaskRunnerHandle::Get());
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc
index 96233c5b..890f833a 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc
@@ -244,7 +244,7 @@
                                   const std::string& model_identifier,
                                   OnConfigLoadedCallback callback) {
   DCHECK(connector_);
-  GetJsonParser().Parse(
+  GetJsonParser()->Parse(
       json_string,
       base::BindOnce(&JsonConfigConverter::OnJsonParsed, base::Unretained(this),
                      std::move(callback), model_identifier));
@@ -267,16 +267,16 @@
   }
 }
 
-data_decoder::mojom::JsonParser& JsonConfigConverter::GetJsonParser() {
+data_decoder::mojom::JsonParser* JsonConfigConverter::GetJsonParser() {
   if (!json_parser_) {
-    connector_->BindInterface(data_decoder::mojom::kServiceName,
-                              mojo::MakeRequest(&json_parser_));
-    json_parser_.set_connection_error_handler(base::BindOnce(
+    connector_->Connect(data_decoder::mojom::kServiceName,
+                        json_parser_.BindNewPipeAndPassReceiver());
+    json_parser_.set_disconnect_handler(base::BindOnce(
         [](JsonConfigConverter* const loader) { loader->json_parser_.reset(); },
         base::Unretained(this)));
   }
 
-  return *json_parser_;
+  return json_parser_.get();
 }
 
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.h b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.h
index c746ceb..b45aa24 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.h
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_config.pb.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/data_decoder/public/mojom/json_parser.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -58,7 +59,7 @@
  private:
   // Create or reuse a connection to the data decoder service for safe JSON
   // parsing.
-  data_decoder::mojom::JsonParser& GetJsonParser();
+  data_decoder::mojom::JsonParser* GetJsonParser();
 
   // Callback for parser.
   void OnJsonParsed(OnConfigLoadedCallback callback,
@@ -69,7 +70,7 @@
   std::string model_identifier_;
 
   service_manager::Connector* connector_;
-  data_decoder::mojom::JsonParserPtr json_parser_;
+  mojo::Remote<data_decoder::mojom::JsonParser> json_parser_;
 };
 
 }  // namespace app_list
diff --git a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
index 4293e78..6eab681 100644
--- a/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/arc_app_launcher_browsertest.cc
@@ -236,6 +236,9 @@
 
   void SendPackageRemoved(const std::string& package_name) {
     app_host()->OnPackageRemoved(package_name);
+
+    // Ensure async callbacks from the resulting observer calls are run.
+    base::RunLoop().RunUntilIdle();
   }
 
   void SendInstallationStarted(const std::string& package_name) {
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
index c650257..c014442 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -39,6 +39,7 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/arc_apps.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/crostini/crostini_test_helper.h"
@@ -278,7 +279,19 @@
 class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
  protected:
   ChromeLauncherControllerTest()
-      : BrowserWithTestWindowTest(Browser::TYPE_NORMAL) {}
+      : BrowserWithTestWindowTest(Browser::TYPE_NORMAL) {
+    if (!base::FeatureList::IsEnabled(features::kAppServiceAsh) &&
+        !base::FeatureList::IsEnabled(features::kAppServiceShelf)) {
+      return;
+    }
+
+    // We set some state to affect what ChromeLauncherControllerTest::SetUp
+    // does, making it set app_service_proxy_connector_ for app_service_proxy_.
+    app_service_ = std::make_unique<apps::AppService>(
+        test_connector_factory_.RegisterInstance(apps::mojom::kServiceName));
+    app_service_proxy_connector_ =
+        test_connector_factory_.GetDefaultConnector();
+  }
 
   ~ChromeLauncherControllerTest() override {}
 
@@ -300,6 +313,11 @@
     manifest.SetString(extensions::manifest_keys::kDescription,
                        "for testing pinned apps");
 
+    // AppService checks the app's type, so sets the type in manifest for
+    // extensions.
+    if (base::FeatureList::IsEnabled(features::kAppServiceShelf))
+      manifest.SetString(extensions::manifest_keys::kLaunchWebURL, kWebAppUrl);
+
     base::DictionaryValue manifest_platform_app;
     manifest_platform_app.SetString(extensions::manifest_keys::kName,
                                     "launcher controller test platform app");
@@ -325,25 +343,19 @@
     DCHECK(profile());
     extension_registry_ = extensions::ExtensionRegistry::Get(profile());
 
-    bool flush_app_service_mojo_calls = false;
     if (app_service_proxy_connector_) {
       DCHECK(profile());
-      app_service_proxy_.reset(apps::AppServiceProxy::CreateForTesting(
-          profile(), app_service_proxy_connector_));
-      old_app_service_proxy_for_testing_ =
-          AppServiceAppModelBuilder::SetAppServiceProxyForTesting(
-              app_service_proxy_.get());
-      // Flush the App Service Mojo calls, but only after calling
-      // arc_test_.SetUp, as it also pumps the run-loop in general.
-      flush_app_service_mojo_calls = true;
+      app_service_proxy_ =
+          apps::AppServiceProxyFactory::GetForProfile(profile());
+      app_service_proxy_->ReInitializeForTesting(profile(),
+                                                 app_service_proxy_connector_);
+      // Allow async callbacks to run.
+      WaitForAppService();
     }
 
     if (auto_start_arc_test_)
       arc_test_.SetUp(profile());
 
-    if (flush_app_service_mojo_calls)
-      app_service_proxy_->FlushMojoCallsForTesting();
-
     // Wait until |extension_system| is signaled as started.
     base::RunLoop run_loop;
     extension_system->ready().Post(FROM_HERE, run_loop.QuitClosure());
@@ -485,12 +497,11 @@
 
   void TearDown() override {
     arc_test_.TearDown();
-    if (app_service_proxy_) {
-      AppServiceAppModelBuilder::SetAppServiceProxyForTesting(
-          old_app_service_proxy_for_testing_);
-      app_service_proxy_.reset(nullptr);
-    }
     launcher_controller_ = nullptr;
+
+    if (app_service_proxy_connector_)
+      app_service_.reset(nullptr);
+
     BrowserWithTestWindowTest::TearDown();
   }
 
@@ -945,6 +956,22 @@
     prefs->OnTaskDestroyed(task_id);
   }
 
+  // Allow AppService async callbacks to run.
+  void WaitForAppService() { base::RunLoop().RunUntilIdle(); }
+
+  // Add extension and allow AppService async callbacks to run.
+  void AddExtension(const Extension* extension) {
+    extension_service_->AddExtension(extension);
+    WaitForAppService();
+  }
+
+  // Remove extension and allow AppService async callbacks to run.
+  void UnloadExtension(const std::string& extension_id,
+                       UnloadedExtensionReason reason) {
+    extension_service_->UnloadExtension(extension_id, reason);
+    WaitForAppService();
+  }
+
   // Needed for extension service & friends to work.
   scoped_refptr<Extension> extension_chrome_;
   scoped_refptr<Extension> extension1_;
@@ -975,8 +1002,10 @@
   app_list::AppListSyncableService* app_list_syncable_service_ = nullptr;
 
   service_manager::Connector* app_service_proxy_connector_ = nullptr;
-  std::unique_ptr<apps::AppServiceProxy> app_service_proxy_;
-  apps::AppServiceProxy* old_app_service_proxy_for_testing_ = nullptr;
+  apps::AppServiceProxy* app_service_proxy_ = nullptr;
+
+  service_manager::TestConnectorFactory test_connector_factory_;
+  std::unique_ptr<service_manager::Service> app_service_;
 
  private:
   TestBrowserWindow* CreateTestBrowserWindowAura() {
@@ -998,19 +1027,6 @@
  protected:
   ChromeLauncherControllerWithArcTest() {
     auto_start_arc_test_ = true;
-    if (!base::FeatureList::IsEnabled(features::kAppServiceAsh)) {
-      return;
-    }
-    // We set some state in the ChromeLauncherControllerTest superclass to
-    // affect what ChromeLauncherControllerTest::SetUp does, making it call
-    // AppServiceAppModelBuilder::SetAppServiceProxyForTesting (ASAMB::SASPFT).
-    // We can only call SASPFT after the TestingProfile is created (which
-    // happens in the superclass' SetUp) but before the ASAMB is constructed
-    // (which also happens in the superclass' SetUp).
-    app_service_ = std::make_unique<apps::AppService>(
-        test_connector_factory_.RegisterInstance(apps::mojom::kServiceName));
-    app_service_proxy_connector_ =
-        test_connector_factory_.GetDefaultConnector();
   }
 
   ~ChromeLauncherControllerWithArcTest() override {}
@@ -1020,24 +1036,9 @@
     ArcAppIcon::DisableSafeDecodingForTesting();
 
     ChromeLauncherControllerTest::SetUp();
-    if (app_service_proxy_connector_) {
-      arc_apps_.reset(
-          apps::ArcApps::CreateForTesting(profile(), app_service_proxy_.get()));
-    }
-  }
-
-  void TearDown() override {
-    if (app_service_proxy_connector_) {
-      arc_apps_.reset(nullptr);
-    }
-    ChromeLauncherControllerTest::TearDown();
   }
 
  private:
-  service_manager::TestConnectorFactory test_connector_factory_;
-  std::unique_ptr<service_manager::Service> app_service_;
-  std::unique_ptr<apps::ArcApps> arc_apps_;
-
   DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerWithArcTest);
 };
 
@@ -1343,15 +1344,15 @@
   // default apps appear on shelf between manually pinned App1.
 
   // Prefs are not yet synced. No default pin appears.
-  extension_service_->AddExtension(extensionYoutubeApp_.get());
+  AddExtension(extensionYoutubeApp_.get());
   EXPECT_EQ("Chrome, App1", GetPinnedAppStatus());
 
   StartPrefSyncService(syncer::SyncDataList());
   EXPECT_EQ("Chrome, Youtube, App1", GetPinnedAppStatus());
 
-  extension_service_->AddExtension(extensionDocApp_.get());
+  AddExtension(extensionDocApp_.get());
   EXPECT_EQ("Chrome, Doc, Youtube, App1", GetPinnedAppStatus());
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   EXPECT_EQ("Chrome, Gmail, Doc, Youtube, App1", GetPinnedAppStatus());
 }
 
@@ -1400,7 +1401,7 @@
       {std::pair<std::string, std::string>("app_count", "10")});
 
   // Trigger layout update, app_id does not matter.
-  extension_service_->AddExtension(extension1_.get());
+  AddExtension(extension1_.get());
 
   EXPECT_EQ(
       "Chrome, Gmail, Calendar, Doc, Sheets, Slides, Files, Camera, Photos, "
@@ -1423,7 +1424,7 @@
 
     // Trigger layout update, app_id does not matter. Experiment is still
     // forced.
-    extension_service_->AddExtension(extension1_.get());
+    AddExtension(extension1_.get());
 
     // Youtube is included into default but not to expermenetal. Refreshing
     // should not affect layout.
@@ -1431,7 +1432,7 @@
   }
 
   // Re-update but experiment is off now. No change to layout.
-  extension_service_->AddExtension(extension2_.get());
+  AddExtension(extension2_.get());
   EXPECT_EQ(expectations, GetPinnedAppStatus());
 }
 
@@ -1447,7 +1448,7 @@
       {std::pair<std::string, std::string>("app_count", "10")});
 
   // Trigger layout update, app_id does not matter.
-  extension_service_->AddExtension(extension1_.get());
+  AddExtension(extension1_.get());
 
   EXPECT_EQ("Chrome, Gmail, Doc, Play Store", GetPinnedAppStatus());
 }
@@ -1466,6 +1467,7 @@
   extension_service_->AddExtension(extension1_.get());
   extension_service_->AddExtension(extension2_.get());
   extension_service_->AddExtension(extensionGmailApp_.get());
+  WaitForAppService();
 
   // extension 1, 3 are pinned by user
   syncer::SyncChangeList sync_list;
@@ -1501,6 +1503,7 @@
 
   // Pins must be automatically updated.
   SendListOfArcApps();
+  WaitForAppService();
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
   EXPECT_TRUE(launcher_controller_->IsAppPinned(arc_app_id1));
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
@@ -1519,8 +1522,7 @@
   EXPECT_EQ("App2, Fake App 1, Chrome, App1, Fake App 0, Gmail",
             GetPinnedAppStatus());
 
-  if (app_service_proxy_)
-    app_service_proxy_->FlushMojoCallsForTesting();
+  WaitForAppService();
   copy_sync_list = app_list_syncable_service_->GetAllSyncData(syncer::APP_LIST);
 
   ResetLauncherController();
@@ -1550,6 +1552,7 @@
   EnablePlayStore(true);
 
   SendListOfArcApps();
+  WaitForAppService();
 
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
   EXPECT_TRUE(launcher_controller_->IsAppPinned(arc_app_id1));
@@ -1589,7 +1592,7 @@
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extensionGmailApp_->id()));
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extensionDocApp_->id()));
   // install extension 2 and check
-  extension_service_->AddExtension(extension2_.get());
+  AddExtension(extension2_.get());
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
 
   // Check user can manually pin or unpin these apps
@@ -1627,20 +1630,20 @@
   // Installing |extensionGmailApp_| should add it to the shelf - behind the
   // chrome icon.
   ash::ShelfItem item;
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
   EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
   EXPECT_EQ("Chrome, Gmail", GetPinnedAppStatus());
 
   // Installing |extension2_| should add it to the launcher - behind the
   // chrome icon, but in first location.
-  extension_service_->AddExtension(extension2_.get());
+  AddExtension(extension2_.get());
   EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
   EXPECT_EQ("Chrome, App2, Gmail", GetPinnedAppStatus());
 
   // Installing |extension1_| should add it to the launcher - behind the
   // chrome icon, but in first location.
-  extension_service_->AddExtension(extension1_.get());
+  AddExtension(extension1_.get());
   EXPECT_EQ("Chrome, App1, App2, Gmail", GetPinnedAppStatus());
 }
 
@@ -1664,20 +1667,20 @@
 
   // Installing |extension2_| should add it to the launcher - behind the
   // chrome icon.
-  extension_service_->AddExtension(extension2_.get());
+  AddExtension(extension2_.get());
   EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
   EXPECT_FALSE(launcher_controller_->IsAppPinned(extensionGmailApp_->id()));
   EXPECT_EQ("Chrome, App2", GetPinnedAppStatus());
 
   // Installing |extension1_| should add it to the launcher - behind the
   // chrome icon, but in first location.
-  extension_service_->AddExtension(extension1_.get());
+  AddExtension(extension1_.get());
   EXPECT_FALSE(launcher_controller_->IsAppPinned(extensionGmailApp_->id()));
   EXPECT_EQ("Chrome, App1, App2", GetPinnedAppStatus());
 
   // Installing |extensionGmailApp_| should add it to the launcher - behind the
   // chrome icon, but in first location.
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   EXPECT_EQ("Chrome, App1, App2, Gmail", GetPinnedAppStatus());
 }
 
@@ -1703,20 +1706,20 @@
   // Installing |extension2_| should add it to the shelf - behind the
   // chrome icon.
   ash::ShelfItem item;
-  extension_service_->AddExtension(extension2_.get());
+  AddExtension(extension2_.get());
   EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
   EXPECT_FALSE(launcher_controller_->IsAppPinned(extensionGmailApp_->id()));
   EXPECT_EQ("Chrome, App2", GetPinnedAppStatus());
 
   // Installing |extension1_| should add it to the launcher - behind the
   // chrome icon, but in first location.
-  extension_service_->AddExtension(extension1_.get());
+  AddExtension(extension1_.get());
   EXPECT_FALSE(launcher_controller_->IsAppPinned(extensionGmailApp_->id()));
   EXPECT_EQ("App1, Chrome, App2", GetPinnedAppStatus());
 
   // Installing |extensionGmailApp_| should add it to the launcher - behind the
   // chrome icon, but in first location.
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   EXPECT_EQ("App1, Chrome, App2, Gmail", GetPinnedAppStatus());
 }
 
@@ -1731,11 +1734,11 @@
   SendPinChanges(sync_list0, true);
 
   // The shelf layout has always one static item at the beginning (App List).
-  extension_service_->AddExtension(extension2_.get());
+  AddExtension(extension2_.get());
   EXPECT_EQ("Chrome, App2", GetPinnedAppStatus());
-  extension_service_->AddExtension(extension1_.get());
+  AddExtension(extension1_.get());
   EXPECT_EQ("Chrome, App1, App2", GetPinnedAppStatus());
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   EXPECT_EQ("Chrome, App1, App2, Gmail", GetPinnedAppStatus());
 
   // Change the order with increasing chrome position and decreasing position.
@@ -1764,17 +1767,14 @@
   EXPECT_EQ("Chrome, Gmail, App2, App1", GetPinnedAppStatus());
 
   // Check that unloading of extensions works as expected.
-  extension_service_->UnloadExtension(extension1_->id(),
-                                      UnloadedExtensionReason::UNINSTALL);
+  UnloadExtension(extension1_->id(), UnloadedExtensionReason::UNINSTALL);
   EXPECT_EQ("Chrome, Gmail, App2", GetPinnedAppStatus());
 
-  extension_service_->UnloadExtension(extension2_->id(),
-                                      UnloadedExtensionReason::UNINSTALL);
+  UnloadExtension(extension2_->id(), UnloadedExtensionReason::UNINSTALL);
   EXPECT_EQ("Chrome, Gmail", GetPinnedAppStatus());
 
   // Check that an update of an extension does not crash the system.
-  extension_service_->UnloadExtension(extensionGmailApp_->id(),
-                                      UnloadedExtensionReason::UPDATE);
+  UnloadExtension(extensionGmailApp_->id(), UnloadedExtensionReason::UPDATE);
   EXPECT_EQ("Chrome, Gmail", GetPinnedAppStatus());
 }
 
@@ -2843,16 +2843,16 @@
   SendPinChanges(sync_list, true);
 
   // The shelf layout has always one static item at the beginning (App List).
-  extension_service_->AddExtension(extension1_.get());
+  AddExtension(extension1_.get());
   EXPECT_EQ("Chrome, App1", GetPinnedAppStatus());
-  extension_service_->AddExtension(extension2_.get());
+  AddExtension(extension2_.get());
   // No new app icon will be generated.
   EXPECT_EQ("Chrome, App1", GetPinnedAppStatus());
 
   // Set the app status as running, which will add an unpinned item.
   launcher_controller_->SetV1AppStatus(extension2_->id(), ash::STATUS_RUNNING);
   EXPECT_EQ("Chrome, App1, app2", GetPinnedAppStatus());
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   EXPECT_EQ("Chrome, App1, Gmail, app2", GetPinnedAppStatus());
 
   // Now request to pin all items, which will pin the running unpinned items.
@@ -2889,15 +2889,15 @@
   InsertAddPinChange(&sync_list0, 1, extensionGmailApp_->id());
   SendPinChanges(sync_list0, true);
   // The shelf layout has always one static item at the beginning (app List).
-  extension_service_->AddExtension(extension1_.get());
+  AddExtension(extension1_.get());
   EXPECT_EQ("Chrome, App1", GetPinnedAppStatus());
-  extension_service_->AddExtension(extension_platform_app_.get());
+  AddExtension(extension_platform_app_.get());
   // No new app icon will be generated.
   EXPECT_EQ("Chrome, App1", GetPinnedAppStatus());
   // Add an unpinned but running V2 app.
   CreateRunningV2App(extension_platform_app_->id());
   EXPECT_EQ("Chrome, App1, *platform_app", GetPinnedAppStatus());
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   EXPECT_EQ("Chrome, App1, Gmail, *platform_app", GetPinnedAppStatus());
 
   // Now request to pin all items, which should pin the running unpinned item.
@@ -3033,7 +3033,7 @@
 
   // Installing |extension1_| should add it to the launcher. Note, App1 goes
   // before App2 that is aligned with the pin order in policy.
-  extension_service_->AddExtension(extension1_.get());
+  AddExtension(extension1_.get());
   EXPECT_EQ("Chrome, App1, App2", GetPinnedAppStatus());
 
   // Removing |extension1_| from the policy should not be reflected in the
@@ -3090,8 +3090,7 @@
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extensionGmailApp_->id()));
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extensionDocApp_->id()));
 
-  extension_service_->UnloadExtension(extensionGmailApp_->id(),
-                                      UnloadedExtensionReason::UNINSTALL);
+  UnloadExtension(extensionGmailApp_->id(), UnloadedExtensionReason::UNINSTALL);
 
   EXPECT_FALSE(launcher_controller_->IsAppPinned(extensionGmailApp_->id()));
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extensionDocApp_->id()));
@@ -3186,7 +3185,7 @@
   EXPECT_EQ(expected_pinned_apps, actual_pinned_apps);
 
   // Install |extension2| and verify it shows up between the other two.
-  extension_service_->AddExtension(extension2_.get());
+  AddExtension(extension2_.get());
   expected_pinned_apps.insert(expected_pinned_apps.begin() + 1,
                               extension2_->id());
   GetPinnedAppIds(launcher_controller_.get(), &actual_pinned_apps);
@@ -3305,7 +3304,7 @@
 
   // Installing |extensionGmailApp_| pins it to the launcher.
   const ash::ShelfID gmail_id(extensionGmailApp_->id());
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extensionGmailApp_->id()));
   launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(kGmailUrl));
 
@@ -3362,7 +3361,7 @@
 
   // Installing |extensionGmailApp_| pins it to the launcher.
   const ash::ShelfID gmail_id(extensionGmailApp_->id());
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extensionGmailApp_->id()));
   launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(kGmailUrl));
 
@@ -3780,13 +3779,14 @@
   // Add |extensionGmailApp_| to the launcher and add two items.
   GURL gmail = GURL("https://mail.google.com/mail/u");
   const ash::ShelfID gmail_id(extensionGmailApp_->id());
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(kGmailUrl));
   base::string16 title1 = ASCIIToUTF16("Test1");
   NavigateAndCommitActiveTabWithTitle(browser(), GURL(kGmailUrl), title1);
   chrome::NewTab(browser());
   base::string16 title2 = ASCIIToUTF16("Test2");
   NavigateAndCommitActiveTabWithTitle(browser(), GURL(kGmailUrl), title2);
+  WaitForAppService();
 
   // Check that the menu is properly set.
   ash::ShelfItem item_gmail;
@@ -3828,13 +3828,14 @@
 
   // Add |extensionGmailApp_| to the launcher and add two items.
   const ash::ShelfID gmail_id(extensionGmailApp_->id());
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(kGmailUrl));
   base::string16 title1 = ASCIIToUTF16("Test1");
   NavigateAndCommitActiveTabWithTitle(browser(), GURL(kGmailUrl), title1);
   chrome::NewTab(browser());
   base::string16 title2 = ASCIIToUTF16("Test2");
   NavigateAndCommitActiveTabWithTitle(browser(), GURL(kGmailUrl), title2);
+  WaitForAppService();
 
   // Check that the menu is properly set.
   ash::ShelfItem item_gmail;
@@ -3882,7 +3883,7 @@
 
   // Installing |extensionGmailApp_| pins it to the launcher.
   const ash::ShelfID gmail_id(extensionGmailApp_->id());
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extensionGmailApp_->id()));
 
   // Check that it is now handled.
@@ -3911,7 +3912,7 @@
 
   // Installing |extensionGmailApp_| pins it to the launcher.
   const ash::ShelfID gmail_id(extensionGmailApp_->id());
-  extension_service_->AddExtension(extensionGmailApp_.get());
+  AddExtension(extensionGmailApp_.get());
   EXPECT_TRUE(launcher_controller_->IsAppPinned(extensionGmailApp_->id()));
 
   // The content should not be able to be handled by the app.
@@ -4728,7 +4729,7 @@
   crostini::CrostiniTestHelper test_helper(profile());
   // TODO(crubug.com/918739): Fix pins are not refreshed on enabling Crostini.
   // As a workaround add any app that triggers pin update.
-  extension_service_->AddExtension(extension1_.get());
+  AddExtension(extension1_.get());
   EXPECT_EQ("Chrome, Terminal", GetPinnedAppStatus());
 
   // Unpin the Terminal
diff --git a/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc
index 34317f4..2c77fc9 100644
--- a/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc
@@ -317,7 +317,7 @@
   test_stored_forms().push_back(&saved_match());
   test_stored_forms().push_back(&psl_match());
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   passwords_data().OnPendingPassword(std::move(test_form_manager));
 
   EXPECT_THAT(passwords_data().GetCurrentForms(),
@@ -332,7 +332,7 @@
 TEST_F(ManagePasswordsStateTest, PasswordSaved) {
   test_stored_forms().push_back(&saved_match());
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   passwords_data().OnPendingPassword(std::move(test_form_manager));
   EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE,
             passwords_data().state());
@@ -349,7 +349,7 @@
 TEST_F(ManagePasswordsStateTest, PasswordSubmittedFederationsPresent) {
   std::unique_ptr<PasswordFormManager> test_form_manager(
       CreateFormManagerWithFederation());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   passwords_data().OnPendingPassword(std::move(test_form_manager));
 
   EXPECT_THAT(passwords_data().GetCurrentForms(),
@@ -422,7 +422,7 @@
   test_stored_forms().push_back(&saved_match());
   std::unique_ptr<PasswordFormManager> test_form_manager(
       CreateFormManagerWithFederation());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
 
   passwords_data().OnAutomaticPasswordSave(std::move(test_form_manager));
   EXPECT_THAT(passwords_data().GetCurrentForms(),
@@ -505,7 +505,7 @@
 
 TEST_F(ManagePasswordsStateTest, OnInactive) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
 
   passwords_data().OnPendingPassword(std::move(test_form_manager));
   EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE,
@@ -520,7 +520,7 @@
 
 TEST_F(ManagePasswordsStateTest, PendingPasswordAddBlacklisted) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   passwords_data().OnPendingPassword(std::move(test_form_manager));
   EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE,
             passwords_data().state());
@@ -553,7 +553,7 @@
 
 TEST_F(ManagePasswordsStateTest, AutomaticPasswordSaveAddBlacklisted) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   passwords_data().OnAutomaticPasswordSave(std::move(test_form_manager));
   EXPECT_EQ(password_manager::ui::CONFIRMATION_STATE, passwords_data().state());
 
@@ -573,7 +573,7 @@
 
 TEST_F(ManagePasswordsStateTest, PasswordUpdateAddBlacklisted) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   passwords_data().OnUpdatePassword(std::move(test_form_manager));
   EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_UPDATE_STATE,
             passwords_data().state());
@@ -585,7 +585,7 @@
   test_stored_forms().push_back(&saved_match());
   test_stored_forms().push_back(&psl_match());
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   passwords_data().OnUpdatePassword(std::move(test_form_manager));
 
   EXPECT_THAT(passwords_data().GetCurrentForms(),
@@ -605,7 +605,7 @@
   android_form.password_value = base::ASCIIToUTF16("old pass");
   test_stored_forms().push_back(&android_form);
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   passwords_data().OnUpdatePassword(std::move(test_form_manager));
 
   EXPECT_THAT(passwords_data().GetCurrentForms(),
@@ -622,7 +622,7 @@
   test_stored_forms().push_back(&saved_match());
   std::unique_ptr<PasswordFormManager> test_form_manager(
       CreateFormManagerWithFederation());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   passwords_data().OnUpdatePassword(std::move(test_form_manager));
 
   EXPECT_THAT(passwords_data().GetCurrentForms(),
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
index 13ff218..6945b91 100644
--- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
+++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
@@ -343,7 +343,7 @@
 
   // Set the bubble state to |state|.
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   if (state == password_manager::ui::PENDING_PASSWORD_STATE)
     controller()->OnPasswordSubmitted(std::move(test_form_manager));
@@ -389,7 +389,7 @@
 
 TEST_F(ManagePasswordsUIControllerTest, PasswordSubmitted) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnPasswordSubmitted(std::move(test_form_manager));
   EXPECT_TRUE(controller()->opened_automatic_bubble());
@@ -421,7 +421,7 @@
   stats[0].username_value = test_local_form().username_value;
   stats[0].dismissal_count = kGreatDissmisalCount;
   fetcher().set_stats(stats);
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnPasswordSubmitted(std::move(test_form_manager));
   EXPECT_FALSE(controller()->opened_automatic_bubble());
@@ -440,7 +440,7 @@
   stats[0].username_value = ASCIIToUTF16("not my username");
   stats[0].dismissal_count = kGreatDissmisalCount;
   fetcher().set_stats(stats);
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnPasswordSubmitted(std::move(test_form_manager));
   EXPECT_TRUE(controller()->opened_automatic_bubble());
@@ -461,7 +461,7 @@
   controller->set_client(&client());
 
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   // The bubble is ready to open but the tab is inactive. Therefore, we don't
   // call UpdateIconAndBubbleState here.
   controller->OnPasswordSubmitted(std::move(test_form_manager));
@@ -476,7 +476,7 @@
 
 TEST_F(ManagePasswordsUIControllerTest, PasswordSaved) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnPasswordSubmitted(std::move(test_form_manager));
 
@@ -515,7 +515,7 @@
     // Exercise controller.
     std::unique_ptr<PasswordFormManager> test_form_manager(
         CreateFormManagerWithMetricsRecorder(recorder));
-    test_form_manager->ProvisionallySave(submitted_form(), &driver());
+    test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
     EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
     controller()->OnPasswordSubmitted(std::move(test_form_manager));
 
@@ -573,7 +573,7 @@
 
 TEST_F(ManagePasswordsUIControllerTest, PasswordBlacklisted) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnPasswordSubmitted(std::move(test_form_manager));
 
@@ -587,7 +587,7 @@
   std::unique_ptr<PasswordFormManager> test_form_manager(
       CreateFormManagerWithBestMatches(observed_form(), {&test_local_form()},
                                        nullptr));
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnPasswordSubmitted(std::move(test_form_manager));
 
@@ -613,7 +613,7 @@
 
 TEST_F(ManagePasswordsUIControllerTest, NormalNavigationsClosedBubble) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnPasswordSubmitted(std::move(test_form_manager));
   controller()->SavePassword(test_local_form().username_value,
@@ -637,7 +637,7 @@
       ->NavigateAndCommit(GURL("chrome://sign-in"));
 
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnPasswordSubmitted(std::move(test_form_manager));
   EXPECT_EQ(GURL::EmptyGURL(), controller()->GetOrigin());
@@ -917,7 +917,7 @@
 
 TEST_F(ManagePasswordsUIControllerTest, PasswordUpdated) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnUpdatePasswordSubmitted(std::move(test_form_manager));
 
@@ -984,7 +984,7 @@
     std::unique_ptr<PasswordFormManager> test_form_manager(
         CreateFormManagerWithMetricsRecorder(recorder));
 
-    test_form_manager->ProvisionallySave(submitted_form(), &driver());
+    test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
     EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()).Times(3);
     controller()->OnShowManualFallbackForSaving(
         std::move(test_form_manager), false /* has_generated_password */,
@@ -1037,7 +1037,7 @@
                                          nullptr));
 
     // Simulate user typing a password.
-    test_form_manager->ProvisionallySave(submitted_form(), &driver());
+    test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
 
     EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
     controller()->OnShowManualFallbackForSaving(
@@ -1067,7 +1067,7 @@
       CreateFormManagerWithBestMatches(observed_form(), {}, nullptr));
 
   // Simulate user typing a password.
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
 
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnShowManualFallbackForSaving(
@@ -1092,7 +1092,7 @@
     ManagePasswordsUIController::set_save_fallback_timeout_in_seconds(0);
 
     std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-    test_form_manager->ProvisionallySave(submitted_form(), &driver());
+    test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
 
     EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
     controller()->OnShowManualFallbackForSaving(
@@ -1129,7 +1129,7 @@
 
     ManagePasswordsUIController::set_save_fallback_timeout_in_seconds(0);
     std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-    test_form_manager->ProvisionallySave(submitted_form(), &driver());
+    test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
 
     EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
     controller()->OnShowManualFallbackForSaving(
@@ -1169,7 +1169,7 @@
 TEST_F(ManagePasswordsUIControllerTest,
        ManualFallbackForSavingFollowedByAutomaticBubble) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
 
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnShowManualFallbackForSaving(
@@ -1186,7 +1186,7 @@
   FormData form = submitted_form();
   form.fields[0].value = ASCIIToUTF16("some_other_username");
   form.fields[1].value = ASCIIToUTF16("password123");
-  test_form_manager->ProvisionallySave(form, &driver());
+  test_form_manager->ProvisionallySave(form, &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()).Times(0);
   controller()->OnPasswordSubmitted(std::move(test_form_manager));
 
@@ -1206,7 +1206,7 @@
     std::unique_ptr<PasswordFormManager> test_form_manager(
         CreateFormManagerWithBestMatches(observed_form(), {&test_local_form()},
                                          nullptr));
-    test_form_manager->ProvisionallySave(submitted_form(), &driver());
+    test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
     EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
     controller()->OnShowManualFallbackForSaving(
         std::move(test_form_manager), true /* has_generated_password */, false);
@@ -1228,7 +1228,7 @@
 
 TEST_F(ManagePasswordsUIControllerTest, AutofillDuringSignInPromo) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnPasswordSubmitted(std::move(test_form_manager));
 
@@ -1251,7 +1251,7 @@
 
 TEST_F(ManagePasswordsUIControllerTest, AuthenticateUserToRevealPasswords) {
   std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager());
-  test_form_manager->ProvisionallySave(submitted_form(), &driver());
+  test_form_manager->ProvisionallySave(submitted_form(), &driver(), nullptr);
   EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility());
   controller()->OnPasswordSubmitted(std::move(test_form_manager));
   EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE,
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
index 7d64702..4f2b015 100644
--- a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
+++ b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
@@ -27,6 +27,8 @@
 #include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "components/payments/content/payment_request.h"
+#include "components/payments/core/features.h"
+#include "components/payments/core/payments_experimental_features.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
@@ -246,10 +248,8 @@
 
   HideProcessingSpinner();
 
-  if (request_->state()->are_requested_methods_supported() &&
-      observer_for_testing_) {
-    observer_for_testing_->OnDialogOpened();
-  }
+  if (request_->state()->are_requested_methods_supported())
+    OnDialogOpened();
 }
 
 void PaymentRequestDialogView::Pay() {
@@ -417,6 +417,23 @@
       request_->web_contents()->GetBrowserContext());
 }
 
+void PaymentRequestDialogView::OnDialogOpened() {
+  if (request_->spec()->request_shipping() &&
+      !request_->state()->selected_shipping_profile() &&
+      PaymentsExperimentalFeatures::IsEnabled(
+          features::kStrictHasEnrolledAutofillInstrument)) {
+    view_stack_->Push(
+        CreateViewAndInstallController(
+            ProfileListViewController::GetShippingProfileViewController(
+                request_->spec(), request_->state(), this),
+            &controller_map_),
+        /* animate = */ false);
+  }
+
+  if (observer_for_testing_)
+    observer_for_testing_->OnDialogOpened();
+}
+
 void PaymentRequestDialogView::ShowInitialPaymentSheet() {
   view_stack_->Push(CreateViewAndInstallController(
                         std::make_unique<PaymentSheetViewController>(
@@ -427,10 +444,8 @@
   if (number_of_initialization_tasks_ > 0)
     return;
 
-  if (request_->state()->are_requested_methods_supported() &&
-      observer_for_testing_) {
-    observer_for_testing_->OnDialogOpened();
-  }
+  if (request_->state()->are_requested_methods_supported())
+    OnDialogOpened();
 }
 
 void PaymentRequestDialogView::SetupSpinnerOverlay() {
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view.h b/chrome/browser/ui/views/payments/payment_request_dialog_view.h
index d6d57f7..b01db97 100644
--- a/chrome/browser/ui/views/payments/payment_request_dialog_view.h
+++ b/chrome/browser/ui/views/payments/payment_request_dialog_view.h
@@ -183,6 +183,7 @@
   views::View* throbber_overlay_for_testing() { return throbber_overlay_; }
 
  private:
+  void OnDialogOpened();
   void ShowInitialPaymentSheet();
   void SetupSpinnerOverlay();
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
index ce5eb34..ae1bc4b 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -67,6 +67,8 @@
       delegate_(delegate) {
   SetInkDropMode(InkDropMode::ON);
   set_has_ink_drop_action_on_click(true);
+  set_hide_ink_drop_when_showing_context_menu(false);
+  set_show_ink_drop_when_hot_tracked(true);
   SetID(VIEW_ID_BROWSER_ACTION);
   view_controller_->SetDelegate(this);
   SetHorizontalAlignment(gfx::ALIGN_CENTER);
@@ -272,23 +274,6 @@
   MenuButton::ViewHierarchyChanged(details);
 }
 
-void ToolbarActionView::StateChanged(views::Button::ButtonState old_state) {
-  MenuButton::StateChanged(old_state);
-  if (delegate_->ShownInsideMenu()) {
-    // The following code is necessary to ensure the item is properly
-    // highlighted when using keyboard navigation to select items in the menu.
-    // InkDrops will listen for hover events and highlight accordingly. However,
-    // menu items don't actually get focus so using SetShowHighlightOnFocus()
-    // won't work. The button state is set to STATE_HOVERED, so this code will
-    // ensure the InkDrop actually highlights.
-    views::InkDropState target_state = state() == views::Button::STATE_HOVERED
-                                           ? views::InkDropState::ACTIVATED
-                                           : views::InkDropState::HIDDEN;
-    if (GetInkDrop()->GetTargetInkDropState() != target_state)
-      AnimateInkDrop(target_state, nullptr);
-  }
-}
-
 views::View* ToolbarActionView::GetAsView() {
   return this;
 }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.h b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
index 92cf648..6a52d59 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
@@ -108,7 +108,6 @@
   void OnDragDone() override;
   void ViewHierarchyChanged(
       const views::ViewHierarchyChangedDetails& details) override;
-  void StateChanged(views::Button::ButtonState old_state) override;
 
   // ToolbarActionViewDelegateViews:
   views::View* GetAsView() override;
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index ee389c1..dd3bdfa 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/chromeos/language_preferences.h"
 #include "chrome/browser/chromeos/login/lock_screen_utils.h"
 #include "chrome/browser/chromeos/login/reauth_stats.h"
+#include "chrome/browser/chromeos/login/saml/public_saml_url_fetcher.h"
 #include "chrome/browser/chromeos/login/screens/network_error.h"
 #include "chrome/browser/chromeos/login/signin_partition_manager.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
@@ -365,10 +366,29 @@
   login::SigninPartitionManager* signin_partition_manager =
       login::SigninPartitionManager::Factory::GetForBrowserContext(
           Profile::FromWebUI(web_ui()));
-  signin_partition_manager->StartSigninSession(
-      web_ui()->GetWebContents(),
+
+  auto partition_call = base::BindOnce(
+      &login::SigninPartitionManager::StartSigninSession,
+      base::Unretained(signin_partition_manager), web_ui()->GetWebContents(),
       base::BindOnce(&GaiaScreenHandler::LoadGaiaWithPartition,
                      weak_factory_.GetWeakPtr(), context));
+
+  if (!context.email.empty()) {
+    const AccountId account_id = GetAccountId(
+        context.email, std::string() /* id */, AccountType::UNKNOWN);
+    const user_manager::User* const user =
+        user_manager::UserManager::Get()->FindUser(account_id);
+
+    if (user && user->using_saml() &&
+        user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) {
+      public_saml_url_fetcher_ =
+          std::make_unique<chromeos::PublicSamlUrlFetcher>(account_id);
+      public_saml_url_fetcher_->Fetch(std::move(partition_call));
+      return;
+    }
+  }
+  public_saml_url_fetcher_.reset();
+  std::move(partition_call).Run();
 }
 
 void GaiaScreenHandler::LoadGaiaWithPartition(
@@ -444,30 +464,6 @@
   screen_mode_ = GetGaiaScreenMode(context.email, context.use_offline);
   params.SetInteger("screenMode", screen_mode_);
 
-  if (!context.email.empty()) {
-    const AccountId account_id = GetAccountId(
-        context.email, std::string() /* id */, AccountType::UNKNOWN);
-    const user_manager::User* const user =
-        user_manager::UserManager::Get()->FindUser(account_id);
-    if (user && user->using_saml() &&
-        user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT &&
-        base::CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kPublicAccountsSamlUrl)) {
-      std::string saml_url =
-          base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-              switches::kPublicAccountsSamlUrl);
-      params.SetBoolean("startsOnSamlPage", true);
-      params.SetString("frameUrl", saml_url);
-      params.SetString("email", account_id.GetUserEmail());
-      CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kPublicAccountsSamlAclUrl));
-      std::string saml_acl_url =
-          base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-              switches::kPublicAccountsSamlAclUrl);
-      params.SetString("samlAclUrl", saml_acl_url);
-    }
-  }
-
   if (screen_mode_ == GAIA_SCREEN_MODE_AD && !authpolicy_login_helper_)
     authpolicy_login_helper_ = std::make_unique<AuthPolicyHelper>();
 
@@ -538,6 +534,26 @@
                     ExtractSamlPasswordAttributesEnabled());
   params.SetBoolean("enableGaiaActionButtons", GaiaActionButtonsEnabled());
 
+  if (public_saml_url_fetcher_) {
+    params.SetBoolean("startsOnSamlPage", true);
+    CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
+        switches::kPublicAccountsSamlAclUrl));
+    std::string saml_acl_url =
+        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+            switches::kPublicAccountsSamlAclUrl);
+    params.SetString("samlAclUrl", saml_acl_url);
+    if (public_saml_url_fetcher_->FetchSucceeded()) {
+      params.SetString("frameUrl", public_saml_url_fetcher_->GetRedirectUrl());
+    } else {
+      // TODO: make the string localized.
+      std::string msg = "Failed to fetch the SAML redirect URL from the server";
+      core_oobe_view_->ShowSignInError(
+          0, msg, std::string(), HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
+      return;
+    }
+  }
+  public_saml_url_fetcher_.reset();
+
   frame_state_ = FRAME_STATE_LOADING;
   CallJS("login.GaiaSigninScreen.loadAuthExtension", params);
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
index 9cba09d9..d460c6c 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -39,6 +39,7 @@
 class SamlPasswordAttributes;
 class SigninScreenHandler;
 class UserContext;
+class PublicSamlUrlFetcher;
 
 class GaiaView {
  public:
@@ -414,6 +415,8 @@
   std::unique_ptr<LoginClientCertUsageObserver>
       extension_provided_client_cert_usage_observer_;
 
+  std::unique_ptr<chromeos::PublicSamlUrlFetcher> public_saml_url_fetcher_;
+
   // State of the security token PIN dialogs:
 
   // Whether this instance is currently registered as a host for showing the
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
index 867c83d..acd4940 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
@@ -183,7 +183,7 @@
 IN_PROC_BROWSER_TEST_F(InterstitialUITest, OriginPolicyErrorInterstitial) {
   TestInterstitial(GURL("chrome://interstitials/origin_policy"),
                    "Origin Policy Error",
-                   base::ASCIIToUTF16("has requested that a security policy"));
+                   base::ASCIIToUTF16("has requested that an origin policy"));
 }
 
 // Tests that back button works after opening an interstitial from
diff --git a/chrome/browser/usb/usb_chooser_context.cc b/chrome/browser/usb/usb_chooser_context.cc
index d38392d..5f8ccef 100644
--- a/chrome/browser/usb/usb_chooser_context.cc
+++ b/chrome/browser/usb/usb_chooser_context.cc
@@ -15,10 +15,13 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/usb/usb_blocklist.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/content_settings/core/common/content_settings.h"
+#include "components/content_settings/core/common/pref_names.h"
 #include "content/public/browser/system_connector.h"
 #include "services/device/public/cpp/usb/usb_ids.h"
 #include "services/device/public/mojom/constants.mojom.h"
@@ -26,6 +29,10 @@
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#endif  // defined(OS_CHROMEOS)
+
 namespace {
 
 constexpr char kDeviceNameKey[] = "name";
@@ -130,8 +137,21 @@
                          CONTENT_SETTINGS_TYPE_USB_GUARD,
                          CONTENT_SETTINGS_TYPE_USB_CHOOSER_DATA),
       is_incognito_(profile->IsOffTheRecord()) {
+#if defined(OS_CHROMEOS)
+  bool is_signin_profile = chromeos::ProfileHelper::IsSigninProfile(profile);
+  PrefService* pref_service = is_signin_profile
+                                  ? g_browser_process->local_state()
+                                  : profile->GetPrefs();
+  const char* pref_name =
+      is_signin_profile ? prefs::kDeviceLoginScreenWebUsbAllowDevicesForUrls
+                        : prefs::kManagedWebUsbAllowDevicesForUrls;
+#else   // defined(OS_CHROMEOS)
+  PrefService* pref_service = profile->GetPrefs();
+  const char* pref_name = prefs::kManagedWebUsbAllowDevicesForUrls;
+#endif  // defined(OS_CHROMEOS)
+
   usb_policy_allowed_devices_.reset(
-      new UsbPolicyAllowedDevices(profile->GetPrefs()));
+      new UsbPolicyAllowedDevices(pref_service, pref_name));
 }
 
 // static
diff --git a/chrome/browser/usb/usb_chooser_context_unittest.cc b/chrome/browser/usb/usb_chooser_context_unittest.cc
index f9de110..9817e24 100644
--- a/chrome/browser/usb/usb_chooser_context_unittest.cc
+++ b/chrome/browser/usb/usb_chooser_context_unittest.cc
@@ -14,6 +14,10 @@
 #include "chrome/browser/usb/usb_chooser_context.h"
 #include "chrome/browser/usb/usb_chooser_context_factory.h"
 #include "chrome/browser/usb/usb_chooser_context_mock_device_observer.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
+#include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/pref_names.h"
@@ -593,6 +597,82 @@
                                          *unrelated_device_info));
 }
 
+#if defined(OS_CHROMEOS)
+
+class DeviceLoginScreenWebUsbChooserContextTest : public UsbChooserContextTest {
+ public:
+  DeviceLoginScreenWebUsbChooserContextTest()
+      : testing_local_state_(TestingBrowserProcess::GetGlobal()) {
+    TestingProfile::Builder builder;
+    builder.SetPath(base::FilePath(FILE_PATH_LITERAL(chrome::kInitialProfile)));
+    signin_profile_ = builder.Build();
+  }
+  ~DeviceLoginScreenWebUsbChooserContextTest() override {}
+
+ protected:
+  Profile* GetSigninProfile() { return signin_profile_.get(); }
+
+ private:
+  ScopedTestingLocalState testing_local_state_;
+  std::unique_ptr<Profile> signin_profile_;
+};
+
+TEST_F(DeviceLoginScreenWebUsbChooserContextTest,
+       UserUsbChooserContextOnlyUsesUserPolicy) {
+  const std::vector<GURL> kValidRequestingOrigins = {kProductVendorUrl,
+                                                     kVendorUrl, kAnyDeviceUrl};
+  const std::vector<GURL> kInvalidRequestingOrigins = {kGadgetUrl, kCoolUrl};
+
+  UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice(
+      6353, 5678, "Google", "Gizmo", "ABC123");
+
+  Profile* user_profile = profile();
+  Profile* signin_profile = GetSigninProfile();
+
+  auto* user_store = GetChooserContext(user_profile);
+  auto* signin_store = GetChooserContext(signin_profile);
+
+  ExpectNoPermissions(user_store, *specific_device_info);
+  ExpectNoPermissions(signin_store, *specific_device_info);
+
+  user_profile->GetPrefs()->Set(
+      prefs::kManagedWebUsbAllowDevicesForUrls,
+      *base::JSONReader::ReadDeprecated(kPolicySetting));
+
+  ExpectCorrectPermissions(user_store, kValidRequestingOrigins,
+                           kInvalidRequestingOrigins, *specific_device_info);
+  ExpectNoPermissions(signin_store, *specific_device_info);
+}
+
+TEST_F(DeviceLoginScreenWebUsbChooserContextTest,
+       SigninUsbChooserContextOnlyUsesDevicePolicy) {
+  const std::vector<GURL> kValidRequestingOrigins = {kProductVendorUrl,
+                                                     kVendorUrl, kAnyDeviceUrl};
+  const std::vector<GURL> kInvalidRequestingOrigins = {kGadgetUrl, kCoolUrl};
+
+  UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice(
+      6353, 5678, "Google", "Gizmo", "ABC123");
+
+  Profile* user_profile = profile();
+  Profile* signin_profile = GetSigninProfile();
+
+  auto* user_store = GetChooserContext(user_profile);
+  auto* signin_store = GetChooserContext(signin_profile);
+
+  ExpectNoPermissions(user_store, *specific_device_info);
+  ExpectNoPermissions(signin_store, *specific_device_info);
+
+  g_browser_process->local_state()->Set(
+      prefs::kDeviceLoginScreenWebUsbAllowDevicesForUrls,
+      *base::JSONReader::ReadDeprecated(kPolicySetting));
+
+  ExpectNoPermissions(user_store, *specific_device_info);
+  ExpectCorrectPermissions(signin_store, kValidRequestingOrigins,
+                           kInvalidRequestingOrigins, *specific_device_info);
+}
+
+#endif  // defined(OS_CHROMEOS)
+
 namespace {
 
 void ExpectDeviceObjectInfo(const base::Value& actual,
diff --git a/chrome/browser/usb/usb_policy_allowed_devices.cc b/chrome/browser/usb/usb_policy_allowed_devices.cc
index bcc26f0..b1298b4 100644
--- a/chrome/browser/usb/usb_policy_allowed_devices.cc
+++ b/chrome/browser/usb/usb_policy_allowed_devices.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/strings/string_split.h"
 #include "base/values.h"
-#include "components/content_settings/core/common/pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "services/device/public/mojom/usb_device.mojom.h"
 #include "services/device/public/mojom/usb_manager.mojom.h"
@@ -42,14 +41,15 @@
 
 }  // namespace
 
-UsbPolicyAllowedDevices::UsbPolicyAllowedDevices(PrefService* pref_service) {
+UsbPolicyAllowedDevices::UsbPolicyAllowedDevices(PrefService* pref_service,
+                                                 const char* pref_name)
+    : pref_name_(pref_name) {
   pref_change_registrar_.Init(pref_service);
-  // Add an observer for |kManagedWebUsbAllowDevicesForUrls| to call
-  // CreateOrUpdateMap when the value is changed. The lifetime of
-  // |pref_change_registrar_| is managed by this class, therefore it is safe to
-  // use base::Unretained here.
+  // Add an observer for |pref_name| to call CreateOrUpdateMap when the value is
+  // changed. The lifetime of |pref_change_registrar_| is managed by this class,
+  // therefore it is safe to use base::Unretained here.
   pref_change_registrar_.Add(
-      prefs::kManagedWebUsbAllowDevicesForUrls,
+      pref_name,
       base::BindRepeating(&UsbPolicyAllowedDevices::CreateOrUpdateMap,
                           base::Unretained(this)));
 
@@ -92,8 +92,8 @@
 }
 
 void UsbPolicyAllowedDevices::CreateOrUpdateMap() {
-  const base::Value* pref_value = pref_change_registrar_.prefs()->Get(
-      prefs::kManagedWebUsbAllowDevicesForUrls);
+  const base::Value* pref_value =
+      pref_change_registrar_.prefs()->Get(pref_name_);
   usb_device_ids_to_urls_.clear();
 
   // A policy has not been assigned.
diff --git a/chrome/browser/usb/usb_policy_allowed_devices.h b/chrome/browser/usb/usb_policy_allowed_devices.h
index ae80213..1497744 100644
--- a/chrome/browser/usb/usb_policy_allowed_devices.h
+++ b/chrome/browser/usb/usb_policy_allowed_devices.h
@@ -23,11 +23,12 @@
 class PrefService;
 
 // This class is used to initialize a UsbDeviceIdsToUrlsMap from the
-// preference value for the WebUsbAllowDevicesForUrls policy. The map
-// provides an efficient method of checking if a particular device is allowed to
-// be used by the given requesting and embedding origins. Additionally, this
-// class also uses |pref_change_registrar_| to observe for changes to the
-// preference value so that the map can be updated accordingly.
+// preference value for the WebUsbAllowDevicesForUrls or
+// DeviceLoginScreenWebUsbAllowDevicesForUrls policy. The map provides an
+// efficient method of checking if a particular device is allowed to be used by
+// the given requesting and embedding origins. Additionally, this class also
+// uses |pref_change_registrar_| to observe for changes to the preference value
+// so that the map can be updated accordingly.
 class UsbPolicyAllowedDevices {
  public:
   // A map of device IDs to a set of origins stored in a std::pair. The device
@@ -41,8 +42,8 @@
                std::set<std::pair<url::Origin, base::Optional<url::Origin>>>>;
 
   // Initializes |pref_change_registrar_| with |pref_service| and adds an
-  // an observer for the pref path |kManagedWebUsbAllowDevicesForUrls|.
-  explicit UsbPolicyAllowedDevices(PrefService* pref_service);
+  // an observer for the |pref_name|.
+  UsbPolicyAllowedDevices(PrefService* pref_service, const char* pref_name);
   ~UsbPolicyAllowedDevices();
 
   // Checks if |requesting_origin| (when embedded within |embedding_origin|) is
@@ -58,11 +59,12 @@
 
  private:
   // Creates or updates the |usb_device_ids_to_urls_| map using the
-  // pref at the path |kManagedWebUsbAllowDevicesForUrls|. The existing map is
-  // cleared to ensure that previous pref settings are removed.
+  // pref at |pref_name_|. The existing map is cleared to ensure that previous
+  // pref settings are removed.
   void CreateOrUpdateMap();
 
   // Allow for this class to observe changes to the pref value.
+  const char* pref_name_;
   PrefChangeRegistrar pref_change_registrar_;
   UsbDeviceIdsToUrlsMap usb_device_ids_to_urls_;
 };
diff --git a/chrome/browser/usb/usb_policy_allowed_devices_unittest.cc b/chrome/browser/usb/usb_policy_allowed_devices_unittest.cc
index 9ea6ad9..5527a87 100644
--- a/chrome/browser/usb/usb_policy_allowed_devices_unittest.cc
+++ b/chrome/browser/usb/usb_policy_allowed_devices_unittest.cc
@@ -32,6 +32,11 @@
  protected:
   Profile* profile() { return &profile_; }
 
+  std::unique_ptr<UsbPolicyAllowedDevices> CreateUsbPolicyAllowedDevices() {
+    return std::make_unique<UsbPolicyAllowedDevices>(
+        profile()->GetPrefs(), prefs::kManagedWebUsbAllowDevicesForUrls);
+  }
+
   device::FakeUsbDeviceManager device_manager_;
 
  private:
@@ -39,11 +44,16 @@
   TestingProfile profile_;
 };
 
+std::unique_ptr<base::Value> ReadJson(base::StringPiece json) {
+  base::Optional<base::Value> value = base::JSONReader::Read(json);
+  EXPECT_TRUE(value);
+  return value ? base::Value::ToUniquePtrValue(std::move(*value)) : nullptr;
+}
+
 }  // namespace
 
 TEST_F(UsbPolicyAllowedDevicesTest, InitializeWithMissingPrefValue) {
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   EXPECT_TRUE(usb_policy_allowed_devices->map().empty());
 }
@@ -53,8 +63,7 @@
 
   SetWebUsbAllowDevicesForUrlsPrefValue(pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   EXPECT_TRUE(usb_policy_allowed_devices->map().empty());
 }
@@ -94,13 +103,11 @@
 }  // namespace
 
 TEST_F(UsbPolicyAllowedDevicesTest, InitializeWithExistingPrefValue) {
-  std::unique_ptr<base::Value> pref_value =
-      base::JSONReader::ReadDeprecated(kPolicySetting);
+  std::unique_ptr<base::Value> pref_value = ReadJson(kPolicySetting);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const UsbPolicyAllowedDevices::UsbDeviceIdsToUrlsMap& map =
       usb_policy_allowed_devices->map();
@@ -132,13 +139,11 @@
 
 TEST_F(UsbPolicyAllowedDevicesTest,
        InitializeWithMissingPolicyThenUpdatePolicy) {
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
   EXPECT_TRUE(usb_policy_allowed_devices->map().empty());
 
   // Ensure that the allowed devices can be dynamically updated.
-  std::unique_ptr<base::Value> pref_value =
-      base::JSONReader::ReadDeprecated(kPolicySetting);
+  std::unique_ptr<base::Value> pref_value = ReadJson(kPolicySetting);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
@@ -172,13 +177,11 @@
 
 TEST_F(UsbPolicyAllowedDevicesTest,
        InitializeWithExistingPolicyThenRemovePolicy) {
-  std::unique_ptr<base::Value> pref_value =
-      base::JSONReader::ReadDeprecated(kPolicySetting);
+  std::unique_ptr<base::Value> pref_value = ReadJson(kPolicySetting);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const UsbPolicyAllowedDevices::UsbDeviceIdsToUrlsMap& map =
       usb_policy_allowed_devices->map();
@@ -234,13 +237,12 @@
 
 TEST_F(UsbPolicyAllowedDevicesTest,
        InitializeWithExistingPrefValueContainingDuplicateDevices) {
-  std::unique_ptr<base::Value> pref_value = base::JSONReader::ReadDeprecated(
-      kPolicySettingWithEntriesContainingDuplicateDevices);
+  std::unique_ptr<base::Value> pref_value =
+      ReadJson(kPolicySettingWithEntriesContainingDuplicateDevices);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const UsbPolicyAllowedDevices::UsbDeviceIdsToUrlsMap& map =
       usb_policy_allowed_devices->map();
@@ -275,13 +277,12 @@
 }  // namespace
 
 TEST_F(UsbPolicyAllowedDevicesTest, IsDeviceAllowed) {
-  std::unique_ptr<base::Value> pref_value = base::JSONReader::ReadDeprecated(
-      kPolicySettingWithEntriesMatchingMultipleDevices);
+  std::unique_ptr<base::Value> pref_value =
+      ReadJson(kPolicySettingWithEntriesMatchingMultipleDevices);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const auto kGoogleOrigin = url::Origin::Create(GURL("https://google.com"));
   const auto kYoutubeOrigin =
@@ -345,13 +346,12 @@
 }
 
 TEST_F(UsbPolicyAllowedDevicesTest, IsDeviceAllowedForUrlsNotInPref) {
-  std::unique_ptr<base::Value> pref_value = base::JSONReader::ReadDeprecated(
-      kPolicySettingWithEntriesMatchingMultipleDevices);
+  std::unique_ptr<base::Value> pref_value =
+      ReadJson(kPolicySettingWithEntriesMatchingMultipleDevices);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const url::Origin origins[] = {
       url::Origin::Create(GURL("https://evil.com")),
@@ -369,13 +369,12 @@
 }
 
 TEST_F(UsbPolicyAllowedDevicesTest, IsDeviceAllowedForDeviceNotInPref) {
-  std::unique_ptr<base::Value> pref_value = base::JSONReader::ReadDeprecated(
-      kPolicySettingWithEntriesMatchingMultipleDevices);
+  std::unique_ptr<base::Value> pref_value =
+      ReadJson(kPolicySettingWithEntriesMatchingMultipleDevices);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const url::Origin origins[] = {
       url::Origin::Create(GURL("https://google.com")),
@@ -407,13 +406,12 @@
 
 TEST_F(UsbPolicyAllowedDevicesTest,
        IsDeviceAllowedForUrlContainingEmbeddingOrigin) {
-  std::unique_ptr<base::Value> pref_value = base::JSONReader::ReadDeprecated(
-      kPolicySettingWithUrlContainingEmbeddingOrigin);
+  std::unique_ptr<base::Value> pref_value =
+      ReadJson(kPolicySettingWithUrlContainingEmbeddingOrigin);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const auto requesting_origin =
       url::Origin::Create(GURL("https://requesting.com"));
diff --git a/chrome/browser/web_applications/components/web_app_constants.h b/chrome/browser/web_applications/components/web_app_constants.h
index c34fdf2..2337cc3 100644
--- a/chrome/browser/web_applications/components/web_app_constants.h
+++ b/chrome/browser/web_applications/components/web_app_constants.h
@@ -72,7 +72,11 @@
   kIntentToPlayStore = 11,
   // A web app has been disabled by device policy or by other reasons.
   kWebAppDisabled = 12,
-  kMaxValue = kWebAppDisabled
+  // The network request for the install URL was redirected.
+  kInstallURLRedirected = 13,
+  // The network request for the install URL failed or timed out.
+  kInstallURLLoadFailed = 14,
+  kMaxValue = kInstallURLLoadFailed
 };
 
 // Checks if InstallResultCode is not a failure.
diff --git a/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc b/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc
index 49fabc0..1ecb5e3 100644
--- a/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc
@@ -855,4 +855,50 @@
   }
 }
 
+TEST_F(PendingAppInstallTaskTest, InstallURLLoadFailed) {
+  struct ResultPair {
+    WebAppUrlLoader::Result loader_result;
+    InstallResultCode install_result;
+  } result_pairs[] = {{WebAppUrlLoader::Result::kRedirectedUrlLoaded,
+                       InstallResultCode::kInstallURLRedirected},
+                      {WebAppUrlLoader::Result::kFailedUnknownReason,
+                       InstallResultCode::kInstallURLLoadFailed},
+                      {WebAppUrlLoader::Result::kFailedPageTookTooLong,
+                       InstallResultCode::kInstallURLLoadFailed}};
+
+  for (const auto& result_pair : result_pairs) {
+    base::RunLoop run_loop;
+
+    ExternalInstallOptions install_options(
+        GURL(), LaunchContainer::kWindow,
+        ExternalInstallSource::kInternalDefault);
+    PendingAppInstallTask install_task(profile(), registrar(), ui_manager(),
+                                       finalizer(), install_options);
+
+    install_task.Install(
+        web_contents(), result_pair.loader_result,
+        base::BindLambdaForTesting([&](PendingAppInstallTask::Result result) {
+          EXPECT_EQ(result.code, result_pair.install_result);
+          run_loop.Quit();
+        }));
+
+    run_loop.Run();
+  }
+}
+
+TEST_F(PendingAppInstallTaskTest, FailedWebContentsDestroyed) {
+  ExternalInstallOptions install_options(
+      GURL(), LaunchContainer::kWindow,
+      ExternalInstallSource::kInternalDefault);
+  PendingAppInstallTask install_task(profile(), registrar(), ui_manager(),
+                                     finalizer(), install_options);
+
+  install_task.Install(
+      web_contents(), WebAppUrlLoader::Result::kFailedWebContentsDestroyed,
+      base::BindLambdaForTesting(
+          [&](PendingAppInstallTask::Result) { NOTREACHED(); }));
+
+  base::RunLoop().RunUntilIdle();
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc
index 3a72998..ee20fc4 100644
--- a/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc
+++ b/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc
@@ -228,8 +228,8 @@
 TEST_F(WebAppPolicyManagerTest, TwoForceInstalledApps) {
   // Add two sites, one that opens in a window and one that opens in a tab.
   base::Value list(base::Value::Type::LIST);
-  list.GetList().push_back(GetWindowedItem());
-  list.GetList().push_back(GetTabbedItem());
+  list.Append(GetWindowedItem());
+  list.Append(GetTabbedItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
 
   policy_manager()->Start();
@@ -246,7 +246,7 @@
 
 TEST_F(WebAppPolicyManagerTest, ForceInstallAppWithNoDefaultLaunchContainer) {
   base::Value list(base::Value::Type::LIST);
-  list.GetList().push_back(GetNoContainerItem());
+  list.Append(GetNoContainerItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
 
   policy_manager()->Start();
@@ -263,7 +263,7 @@
 TEST_F(WebAppPolicyManagerTest,
        ForceInstallAppWithDefaultCreateDesktopShorcut) {
   base::Value list(base::Value::Type::LIST);
-  list.GetList().push_back(GetCreateDesktopShorcutDefaultItem());
+  list.Append(GetCreateDesktopShorcutDefaultItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
 
   policy_manager()->Start();
@@ -280,8 +280,8 @@
 
 TEST_F(WebAppPolicyManagerTest, ForceInstallAppWithCreateDesktopShortcut) {
   base::Value list(base::Value::Type::LIST);
-  list.GetList().push_back(GetCreateDesktopShorcutFalseItem());
-  list.GetList().push_back(GetCreateDesktopShorcutTrueItem());
+  list.Append(GetCreateDesktopShorcutFalseItem());
+  list.Append(GetCreateDesktopShorcutTrueItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
 
   policy_manager()->Start();
@@ -300,7 +300,7 @@
 
 TEST_F(WebAppPolicyManagerTest, DynamicRefresh) {
   base::Value first_list(base::Value::Type::LIST);
-  first_list.GetList().push_back(GetWindowedItem());
+  first_list.Append(GetWindowedItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList,
                              std::move(first_list));
 
@@ -315,7 +315,7 @@
   EXPECT_EQ(install_requests, expected_install_options_list);
 
   base::Value second_list(base::Value::Type::LIST);
-  second_list.GetList().push_back(GetTabbedItem());
+  second_list.Append(GetTabbedItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList,
                              std::move(second_list));
 
@@ -338,7 +338,7 @@
 
   // Push a policy with only one of the apps.
   base::Value first_list(base::Value::Type::LIST);
-  first_list.GetList().push_back(GetWindowedItem());
+  first_list.Append(GetWindowedItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList,
                              std::move(first_list));
 
@@ -364,8 +364,8 @@
 
   // Add two sites, one that opens in a window and one that opens in a tab.
   base::Value first_list(base::Value::Type::LIST);
-  first_list.GetList().push_back(GetWindowedItem());
-  first_list.GetList().push_back(GetTabbedItem());
+  first_list.Append(GetWindowedItem());
+  first_list.Append(GetTabbedItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList,
                              std::move(first_list));
   base::RunLoop().RunUntilIdle();
@@ -380,7 +380,7 @@
 
   // Push a new policy without the tabbed site.
   base::Value second_list(base::Value::Type::LIST);
-  second_list.GetList().push_back(GetWindowedItem());
+  second_list.Append(GetWindowedItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList,
                              std::move(second_list));
   base::RunLoop().RunUntilIdle();
@@ -398,7 +398,7 @@
 // Tests that we correctly reinstall a placeholder app.
 TEST_F(WebAppPolicyManagerTest, ReinstallPlaceholderApp) {
   base::Value list(base::Value::Type::LIST);
-  list.GetList().push_back(GetWindowedItem());
+  list.Append(GetWindowedItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
 
   policy_manager()->Start();
@@ -424,7 +424,7 @@
 
 TEST_F(WebAppPolicyManagerTest, TryToInexistentPlaceholderApp) {
   base::Value list(base::Value::Type::LIST);
-  list.GetList().push_back(GetWindowedItem());
+  list.Append(GetWindowedItem());
   profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
 
   policy_manager()->Start();
@@ -449,13 +449,13 @@
   // Add an app.
   {
     base::Value list(base::Value::Type::LIST);
-    list.GetList().push_back(GetWindowedItem());
+    list.Append(GetWindowedItem());
     profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
   }
   // Before it gets installed, set a policy that uninstalls it.
   {
     base::Value list(base::Value::Type::LIST);
-    list.GetList().push_back(GetTabbedItem());
+    list.Append(GetTabbedItem());
     profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
   }
   base::RunLoop().RunUntilIdle();
@@ -485,7 +485,7 @@
   policy_manager()->Start();
   {
     base::Value list(base::Value::Type::LIST);
-    list.GetList().push_back(GetWindowedItem());
+    list.Append(GetWindowedItem());
     profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
 
     histograms.ExpectTotalCount(
@@ -501,8 +501,8 @@
   }
   {
     base::Value list(base::Value::Type::LIST);
-    list.GetList().push_back(GetTabbedItem());
-    list.GetList().push_back(GetNoContainerItem());
+    list.Append(GetTabbedItem());
+    list.Append(GetNoContainerItem());
     pending_app_manager()->SetInstallResultCode(
         InstallResultCode::kProfileDestroyed);
 
diff --git a/chrome/browser/web_applications/pending_app_install_task.cc b/chrome/browser/web_applications/pending_app_install_task.cc
index 2027a1f..a6f3b92 100644
--- a/chrome/browser/web_applications/pending_app_install_task.cc
+++ b/chrome/browser/web_applications/pending_app_install_task.cc
@@ -86,10 +86,20 @@
     return;
   }
 
+  // Avoid counting an error if we are shutting down. This matches later
+  // stages of install where if the WebContents is destroyed we return early.
+  if (load_url_result == WebAppUrlLoader::Result::kFailedWebContentsDestroyed)
+    return;
+
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(result_callback),
-                                Result(InstallResultCode::kFailedUnknownReason,
-                                       base::nullopt)));
+      FROM_HERE,
+      base::BindOnce(
+          std::move(result_callback),
+          Result(
+              load_url_result == WebAppUrlLoader::Result::kRedirectedUrlLoaded
+                  ? InstallResultCode::kInstallURLRedirected
+                  : InstallResultCode::kInstallURLLoadFailed,
+              base::nullopt)));
 }
 
 void PendingAppInstallTask::UninstallPlaceholderApp(
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index ba64f7d..19d73db 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -68,7 +68,7 @@
 const base::Feature kAppServiceIntentHandling{
     "AppServiceIntentHandling", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kAppServiceShelf{"AppServiceShelf",
-                                     base::FEATURE_DISABLED_BY_DEFAULT};
+                                     base::FEATURE_ENABLED_BY_DEFAULT};
 #endif  // !defined(OS_ANDROID)
 
 // Enables the built-in DNS resolver.
diff --git a/chrome/common/extensions/docs/templates/intros/certificateProvider.html b/chrome/common/extensions/docs/templates/intros/certificateProvider.html
index ea0e39f..ff0589b 100644
--- a/chrome/common/extensions/docs/templates/intros/certificateProvider.html
+++ b/chrome/common/extensions/docs/templates/intros/certificateProvider.html
@@ -54,7 +54,7 @@
 The actual sequence of steps can be different. For example, the user will not be
 asked to select a certificate if the enterprise policy to automatically select a
 certificate is used (see
-<a href="https://www.chromium.org/administrators/policy-list-3#AutoSelectCertificateForUrls">AutoSelectCertificateForUrls</a>
+<a href="https://cloud.google.com/docs/chrome-enterprise/policies/?policy=AutoSelectCertificateForUrls">AutoSelectCertificateForUrls</a>
 and
 <a href="https://support.google.com/chrome/a/answer/2657289?hl=en#AutoSelectCertificateForUrls">Chrome policies for users</a>).
 </p>
diff --git a/chrome/common/extensions/docs/templates/intros/webRequest.html b/chrome/common/extensions/docs/templates/intros/webRequest.html
index 8e8b339..389b39d 100644
--- a/chrome/common/extensions/docs/templates/intros/webRequest.html
+++ b/chrome/common/extensions/docs/templates/intros/webRequest.html
@@ -119,12 +119,15 @@
 </p>
 
 <p>
-<span class="availability">Starting from Chrome 79</span>, header modifications
-affect Cross-Origin Resource Sharing (CORS) checks. If modified headers for
-cross-origin requests do not meet the criteria, it will result in sending a CORS
-preflight to ask the server if such headers can be accepted. If you really need
-to modify headers in a way to violate the CORS protocol, you need to specify
-<code>'extraHeaders'</code> in <code>opt_extraInfoSpec</code>.
+<span class="availability">Starting from Chrome 79</span>, request header
+modifications affect Cross-Origin Resource Sharing (CORS) checks. If modified
+headers for cross-origin requests do not meet the criteria, it will result in
+sending a CORS preflight to ask the server if such headers can be accepted.
+If you really need to modify headers in a way to violate the CORS protocol, you
+need to specify <code>'extraHeaders'</code> in <code>opt_extraInfoSpec</code>.
+On the other hand, response header modifications do not work to deceive CORS
+checks. If you need to deceive the CORS protocol, you also need to specify
+<code>'extraHeaders'</code> for the response modifications.
 </p>
 
 <p>
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc
index a036e1b..5009ec2 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc
+++ b/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc
@@ -91,7 +91,7 @@
   EXPECT_TRUE(BackgroundInfo::HasLazyBackgroundPage(extension.get()));
 
   base::Value permissions(base::Value::Type::LIST);
-  permissions.GetList().push_back(base::Value("webRequest"));
+  permissions.Append(base::Value("webRequest"));
   manifest.SetKey(keys::kPermissions, std::move(permissions));
   LoadAndExpectError(ManifestData(&manifest, ""),
                      errors::kWebRequestConflictsWithLazyBackground);
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_platformapp_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_platformapp_unittest.cc
index 6d6241b..4d1d897 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_platformapp_unittest.cc
+++ b/chrome/common/extensions/manifest_tests/extension_manifests_platformapp_unittest.cc
@@ -125,8 +125,8 @@
   // Create each manifest.
   for (const char* api_name : kPlatformAppExperimentalApis) {
     base::Value permissions(base::Value::Type::LIST);
-    permissions.GetList().push_back(base::Value("experimental"));
-    permissions.GetList().push_back(base::Value(api_name));
+    permissions.Append(base::Value("experimental"));
+    permissions.Append(base::Value(api_name));
     manifest.SetKey("permissions", std::move(permissions));
     manifests.push_back(
         std::make_unique<ManifestData>(manifest.CreateDeepCopy(), ""));
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_validapp_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_validapp_unittest.cc
index 193ac81..6b53be3 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_validapp_unittest.cc
+++ b/chrome/common/extensions/manifest_tests/extension_manifests_validapp_unittest.cc
@@ -31,6 +31,6 @@
   base::Value* permissions =
       manifest.FindKeyOfType("permissions", base::Value::Type::LIST);
   ASSERT_TRUE(permissions);
-  permissions->GetList().emplace_back("not-a-valid-permission");
+  permissions->Append("not-a-valid-permission");
   LoadAndExpectSuccess(ManifestData(std::move(manifest), ""));
 }
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 5343740..6f001b4 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -997,6 +997,11 @@
 // Boolean user profile pref that determines whether to show a banner in browser
 // settings "About Chrome" that links to OS settings "About Chrome OS".
 const char kSettingsShowAboutOSBanner[] = "settings.cros.show_about_os_banner";
+
+// A JSON pref for controlling which USB devices are whitelisted for certain
+// urls to be used via the WebUSB API on the login screen.
+const char kDeviceLoginScreenWebUsbAllowDevicesForUrls[] =
+    "device_login_screen_webusb_allow_devices_for_urls";
 #endif  // defined(OS_CHROMEOS)
 
 // A boolean pref set to true if a Home button to open the Home pages should be
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 4ea8ce8..f883b34 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -317,6 +317,7 @@
 extern const char kSettingsShowBrowserBanner[];
 extern const char kSettingsShowOSBanner[];
 extern const char kSettingsShowAboutOSBanner[];
+extern const char kDeviceLoginScreenWebUsbAllowDevicesForUrls[];
 #endif  // defined(OS_CHROMEOS)
 extern const char kShowHomeButton[];
 extern const char kSpeechRecognitionFilterProfanities[];
diff --git a/chrome/renderer/net/available_offline_content_helper.cc b/chrome/renderer/net/available_offline_content_helper.cc
index 71a035d..a7bd987 100644
--- a/chrome/renderer/net/available_offline_content_helper.cc
+++ b/chrome/renderer/net/available_offline_content_helper.cc
@@ -71,7 +71,7 @@
     const std::vector<AvailableOfflineContentPtr>& content_list) {
   base::Value value(base::Value::Type::LIST);
   for (const auto& content : content_list) {
-    value.GetList().push_back(AvailableContentToValue(content));
+    value.Append(AvailableContentToValue(content));
   }
   return value;
 }
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc
index 3147d97..a83b272 100644
--- a/chrome/renderer/searchbox/searchbox_extension.cc
+++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -1357,7 +1357,7 @@
       base::Value entry(base::Value::Type::DICTIONARY);
       entry.SetIntKey("offset", classification->offset);
       entry.SetIntKey("style", classification->style);
-      contents_class.GetList().push_back(std::move(entry));
+      contents_class.Append(std::move(entry));
     }
     dict.SetKey("contentsClass", std::move(contents_class));
     dict.SetStringKey("description", match->description);
@@ -1366,7 +1366,7 @@
       base::Value entry(base::Value::Type::DICTIONARY);
       entry.SetIntKey("offset", classification->offset);
       entry.SetIntKey("style", classification->style);
-      description_class.GetList().push_back(std::move(entry));
+      description_class.Append(std::move(entry));
     }
     dict.SetKey("descriptionClass", std::move(description_class));
     dict.SetStringKey("destinationUrl", match->destination_url);
@@ -1376,7 +1376,7 @@
     dict.SetBoolKey("swapContentsAndDescription",
                     match->swap_contents_and_description);
     dict.SetStringKey("type", match->type);
-    list.GetList().push_back(std::move(dict));
+    list.Append(std::move(dict));
   }
   std::string json;
   base::JSONWriter::Write(list, &json);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index edbf1e10..fb94160 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -5866,8 +5866,6 @@
       "../browser/sync/test/integration/migration_watcher.h",
       "../browser/sync/test/integration/multi_client_status_change_checker.cc",
       "../browser/sync/test/integration/multi_client_status_change_checker.h",
-      "../browser/sync/test/integration/p2p_sync_refresher.cc",
-      "../browser/sync/test/integration/p2p_sync_refresher.h",
       "../browser/sync/test/integration/passwords_helper.cc",
       "../browser/sync/test/integration/passwords_helper.h",
       "../browser/sync/test/integration/preferences_helper.cc",
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index df6d580..f4262863 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -1095,22 +1095,24 @@
   network_context_ = std::move(network_context);
 }
 
-network::mojom::NetworkContextPtr TestingProfile::CreateNetworkContext(
+mojo::Remote<network::mojom::NetworkContext>
+TestingProfile::CreateNetworkContext(
     bool in_memory,
     const base::FilePath& relative_partition_path) {
   if (network_context_) {
-    network::mojom::NetworkContextPtr network_context_ptr;
+    mojo::Remote<network::mojom::NetworkContext> network_context_remote;
     network_context_bindings_.AddBinding(
-        network_context_.get(), mojo::MakeRequest(&network_context_ptr));
-    return network_context_ptr;
+        network_context_.get(),
+        network_context_remote.BindNewPipeAndPassReceiver());
+    return network_context_remote;
   }
-  network::mojom::NetworkContextPtr network_context;
+  mojo::Remote<network::mojom::NetworkContext> network_context;
   network::mojom::NetworkContextParamsPtr context_params =
       network::mojom::NetworkContextParams::New();
   context_params->user_agent = GetUserAgent();
   context_params->accept_language = "en-us,en";
   content::GetNetworkService()->CreateNetworkContext(
-      MakeRequest(&network_context), std::move(context_params));
+      network_context.BindNewPipeAndPassReceiver(), std::move(context_params));
   return network_context;
 }
 
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index 962255d..7d163d2 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -354,7 +354,7 @@
   bool IsNewProfile() override;
   void SetExitType(ExitType exit_type) override {}
   ExitType GetLastSessionExitType() override;
-  network::mojom::NetworkContextPtr CreateNetworkContext(
+  mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext(
       bool in_memory,
       const base::FilePath& relative_partition_path) override;
 
diff --git a/chrome/test/chromedriver/chrome/cast_tracker_unittest.cc b/chrome/test/chromedriver/chrome/cast_tracker_unittest.cc
index b88437a..b9248ce 100644
--- a/chrome/test/chromedriver/chrome/cast_tracker_unittest.cc
+++ b/chrome/test/chromedriver/chrome/cast_tracker_unittest.cc
@@ -54,8 +54,8 @@
   EXPECT_EQ(0u, cast_tracker_->sinks().GetList().size());
 
   base::Value sinks(base::Value::Type::LIST);
-  sinks.GetList().emplace_back(CreateSink("sink1", "1"));
-  sinks.GetList().emplace_back(CreateSink("sink2", "2"));
+  sinks.Append(CreateSink("sink1", "1"));
+  sinks.Append(CreateSink("sink2", "2"));
   params.SetKey("sinks", std::move(sinks));
   cast_tracker_->OnEvent(&devtools_client_, "Cast.sinksUpdated", params);
   EXPECT_EQ(2u, cast_tracker_->sinks().GetList().size());
diff --git a/chrome/test/chromedriver/performance_logger_unittest.cc b/chrome/test/chromedriver/performance_logger_unittest.cc
index 40ec2847..adc959a 100644
--- a/chrome/test/chromedriver/performance_logger_unittest.cc
+++ b/chrome/test/chromedriver/performance_logger_unittest.cc
@@ -334,10 +334,10 @@
   auto trace_events = std::make_unique<base::ListValue>();
   auto event1 = std::make_unique<base::DictionaryValue>();
   event1->SetString("cat", "foo");
-  trace_events->GetList().push_back(event1->Clone());
+  trace_events->Append(event1->Clone());
   auto event2 = std::make_unique<base::DictionaryValue>();
   event2->SetString("cat", "bar");
-  trace_events->GetList().push_back(event2->Clone());
+  trace_events->Append(event2->Clone());
   params.Set("value", std::move(trace_events));
   ASSERT_EQ(kOk, client.TriggerEvent("Tracing.dataCollected", params).code());
 
diff --git a/chrome/test/data/extensions/api_test/webrequest/cors/fetch.html b/chrome/test/data/extensions/api_test/webrequest/cors/fetch.html
index 7c063db..ac81c202 100644
--- a/chrome/test/data/extensions/api_test/webrequest/cors/fetch.html
+++ b/chrome/test/data/extensions/api_test/webrequest/cors/fetch.html
@@ -6,8 +6,8 @@
 <script>
 const hostname = 'cors.example.com';
 const origin = location.protocol + '//' + hostname + ':' + location.port;
-const path = '/extensions/api_test/webrequest/cors/accept';
-const url = origin + path;
+const path = location.search.substr('?path='.length);
+const url = origin + '/extensions/api_test/webrequest/cors/' + path;
 
 fetch(url);
 </script>
diff --git a/chrome/test/data/extensions/api_test/webrequest/cors/reject b/chrome/test/data/extensions/api_test/webrequest/cors/reject
new file mode 100644
index 0000000..a862a62
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/webrequest/cors/reject
@@ -0,0 +1 @@
+ERR
diff --git a/chrome/test/data/extensions/api_test/webrequest/cors/reject.mock-http-headers b/chrome/test/data/extensions/api_test/webrequest/cors/reject.mock-http-headers
new file mode 100644
index 0000000..5c695b9
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/webrequest/cors/reject.mock-http-headers
@@ -0,0 +1,2 @@
+HTTP/1.1 200 OK
+Content-Type: text/plain
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_cors.js b/chrome/test/data/extensions/api_test/webrequest/test_cors.js
index 8de717f..64805b3 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_cors.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_cors.js
@@ -35,13 +35,13 @@
       onCompletedListener, {urls: [listeningUrlPattern]});
 }
 
-function registerHeaderInjectionListeners(extraInfoSpec) {
+function registerRequestHeaderInjectionListeners(extraInfoSpec) {
   const beforeSendHeadersListener = callbackPass(details => {
     details.requestHeaders.push({name: 'x-foo', value: 'trigger-preflight'});
-    return { requestHeaders: details.requestHeaders };
+    return {requestHeaders: details.requestHeaders};
   });
   chrome.webRequest.onBeforeSendHeaders.addListener(
-    beforeSendHeadersListener, {urls: [listeningUrlPattern]}, extraInfoSpec);
+      beforeSendHeadersListener, {urls: [listeningUrlPattern]}, extraInfoSpec);
 
   // If the 'x-foo' header is injected by |beforeSendHeadersListener| without
   // 'extraHeaders' and with OOR-CORS being enabled, it triggers CORS
@@ -66,6 +66,32 @@
   event.addListener(
       onCompletedOrErrorOccurredListener, {urls: [listeningUrlPattern]});
 }
+function registerResponseHeaderInjectionListeners(extraInfoSpec) {
+  const headersReceivedListener = details => {
+    details.responseHeaders.push(
+        {name: 'Access-Control-Allow-Origin', value: '*'});
+    return { responseHeaders: details.responseHeaders };
+  };
+  chrome.webRequest.onHeadersReceived.addListener(
+      headersReceivedListener, {urls: [listeningUrlPattern]}, extraInfoSpec);
+
+  // If the 'extraHeaders' is not specified and OOR-CORS is enabled, Chrome
+  // detects CORS failures before |headerReceivedListener| is called and injects
+  // fake headers to deceive the CORS checks.
+  const canInjectFakeCorsResponse =
+      extraInfoSpec.includes('extraHeaders') || getCorsMode() == 'blink';
+
+  const event = canInjectFakeCorsResponse ? chrome.webRequest.onCompleted :
+                                            chrome.webRequest.onErrorOccurred;
+
+  // Wait for the CORS request from the fetch.html to complete.
+  const onCompletedOrErrorOccurredListener = callbackPass(details => {
+    chrome.webRequest.onHeadersReceived.removeListener(headersReceivedListener);
+    event.removeListener(onCompletedOrErrorOccurredListener);
+  });
+  event.addListener(
+      onCompletedOrErrorOccurredListener, {urls: [listeningUrlPattern]});
+}
 
 runTests([
   function testOriginHeader() {
@@ -80,22 +106,38 @@
     registerOriginListeners(['origin'], [], ['requestHeaders', 'extraHeaders']);
 
     // Wait for the navigation to complete.
-    navigateAndWait(
-        getServerURL('extensions/api_test/webrequest/cors/fetch.html'));
+    navigateAndWait(getServerURL(
+        'extensions/api_test/webrequest/cors/fetch.html?path=accept'));
   },
   function testCorsSensitiveHeaderInjectionWithoutExtraHeaders() {
-    registerHeaderInjectionListeners(['blocking', 'requestHeaders']);
+    registerRequestHeaderInjectionListeners(['blocking', 'requestHeaders']);
 
     // Wait for the navigation to complete.
-    navigateAndWait(
-        getServerURL('extensions/api_test/webrequest/cors/fetch.html'));
+    navigateAndWait(getServerURL(
+        'extensions/api_test/webrequest/cors/fetch.html?path=accept'));
   },
   function testCorsSensitiveHeaderInjectionWithExtraHeaders() {
-    registerHeaderInjectionListeners(
+    registerRequestHeaderInjectionListeners(
         ['blocking', 'requestHeaders', 'extraHeaders']);
 
     // Wait for the navigation to complete.
-    navigateAndWait(
-        getServerURL('extensions/api_test/webrequest/cors/fetch.html'));
+    navigateAndWait(getServerURL(
+        'extensions/api_test/webrequest/cors/fetch.html?path=accept'));
+  },
+  function testCorsResponseHeaderInjectionWithoutExtraHeaders() {
+    registerResponseHeaderInjectionListeners(
+        ['blocking', 'responseHeaders']);
+
+    // Wait for the navigation to complete.
+    navigateAndWait(getServerURL(
+        'extensions/api_test/webrequest/cors/fetch.html?path=reject'));
+  },
+  function testCorsResponseHeaderInjectionWithExtraHeaders() {
+    registerResponseHeaderInjectionListeners(
+        ['blocking', 'responseHeaders', 'extraHeaders']);
+
+    // Wait for the navigation to complete.
+    navigateAndWait(getServerURL(
+        'extensions/api_test/webrequest/cors/fetch.html?path=reject'));
   },
 ]);
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index bcfaea3..dff752f 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -2040,6 +2040,19 @@
     ]
   },
 
+  "DeviceLoginScreenWebUsbAllowDevicesForUrls": {
+    "os": ["chromeos"],
+    "test_policy": { "DeviceLoginScreenWebUsbAllowDevicesForUrls": [{
+      "devices": [{"vendor_id": 1234, "product_id": 5678}],
+      "urls": ["https://google.com", "https://requesting.com,https://embedded.com"]
+    }]},
+    "pref_mappings": [
+      { "pref": "device_login_screen_webusb_allow_devices_for_urls",
+        "local_state": true
+      }
+    ]
+  },
+
   "WebUsbAskForUrls": {
     "os": ["win", "linux", "mac", "chromeos", "android"],
     "test_policy": { "WebUsbAskForUrls": ["[*.]google.com"] },
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index 517c43a..6012e74 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -44,6 +44,7 @@
 #include "extensions/test/extension_test_message_listener.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "net/base/net_errors.h"
@@ -841,9 +842,9 @@
 // pipe makes sure that everything happens asynchronously through a pipe.
 #define RUN_TCP_FAILURE_TEST(test_name, failure_type)                         \
   do {                                                                        \
-    network::mojom::NetworkContextPtr network_context_proxy;                  \
+    mojo::Remote<network::mojom::NetworkContext> network_context_proxy;       \
     MockNetworkContext network_context(                                       \
-        failure_type, mojo::MakeRequest(&network_context_proxy));             \
+        failure_type, network_context_proxy.BindNewPipeAndPassReceiver());    \
     ppapi::SetPepperTCPNetworkContextForTesting(network_context_proxy.get()); \
     RunTestViaHTTP(LIST_TEST(test_name));                                     \
     ppapi::SetPepperTCPNetworkContextForTesting(nullptr);                     \
diff --git a/chromecast/browser/application_media_capabilities.cc b/chromecast/browser/application_media_capabilities.cc
index 443baa0..f8ed2de 100644
--- a/chromecast/browser/application_media_capabilities.cc
+++ b/chromecast/browser/application_media_capabilities.cc
@@ -16,25 +16,26 @@
 
 ApplicationMediaCapabilities::~ApplicationMediaCapabilities() = default;
 
-void ApplicationMediaCapabilities::AddBinding(
-    mojom::ApplicationMediaCapabilitiesRequest request) {
-  bindings_.AddBinding(this, std::move(request));
+void ApplicationMediaCapabilities::AddReceiver(
+    mojo::PendingReceiver<mojom::ApplicationMediaCapabilities> receiver) {
+  receivers_.Add(this, std::move(receiver));
 }
 
 void ApplicationMediaCapabilities::SetSupportedBitstreamAudioCodecs(
     int codecs) {
   supported_bitstream_audio_codecs_ = codecs;
-  observers_.ForAllPtrs(
-      [codecs](mojom::ApplicationMediaCapabilitiesObserver* observer) {
-        observer->OnSupportedBitstreamAudioCodecsChanged(codecs);
-      });
+  for (auto& observer : observers_)
+    observer->OnSupportedBitstreamAudioCodecsChanged(codecs);
 }
 
 void ApplicationMediaCapabilities::AddObserver(
-    mojom::ApplicationMediaCapabilitiesObserverPtr observer) {
+    mojo::PendingRemote<mojom::ApplicationMediaCapabilitiesObserver>
+        observer_remote) {
+  mojo::Remote<mojom::ApplicationMediaCapabilitiesObserver> observer(
+      std::move(observer_remote));
   observer->OnSupportedBitstreamAudioCodecsChanged(
       supported_bitstream_audio_codecs_);
-  observers_.AddPtr(std::move(observer));
+  observers_.Add(std::move(observer));
 }
 
 }  // namespace shell
diff --git a/chromecast/browser/application_media_capabilities.h b/chromecast/browser/application_media_capabilities.h
index b19f838..bc5a6c2 100644
--- a/chromecast/browser/application_media_capabilities.h
+++ b/chromecast/browser/application_media_capabilities.h
@@ -7,8 +7,9 @@
 
 #include "base/macros.h"
 #include "chromecast/common/mojom/application_media_capabilities.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
 
 namespace content {
 class RenderFrameHost;
@@ -23,17 +24,19 @@
   ApplicationMediaCapabilities();
   ~ApplicationMediaCapabilities() override;
 
-  void AddBinding(mojom::ApplicationMediaCapabilitiesRequest request);
+  void AddReceiver(
+      mojo::PendingReceiver<mojom::ApplicationMediaCapabilities> receiver);
 
   void SetSupportedBitstreamAudioCodecs(int codecs);
 
  private:
   // mojom::ApplicationMediaCapabilities implementation:
   void AddObserver(
-      mojom::ApplicationMediaCapabilitiesObserverPtr observer) override;
+      mojo::PendingRemote<mojom::ApplicationMediaCapabilitiesObserver>
+          observer_remote) override;
 
-  mojo::BindingSet<mojom::ApplicationMediaCapabilities> bindings_;
-  mojo::InterfacePtrSet<mojom::ApplicationMediaCapabilitiesObserver> observers_;
+  mojo::ReceiverSet<mojom::ApplicationMediaCapabilities> receivers_;
+  mojo::RemoteSet<mojom::ApplicationMediaCapabilitiesObserver> observers_;
   int supported_bitstream_audio_codecs_;
 
   DISALLOW_COPY_AND_ASSIGN(ApplicationMediaCapabilities);
diff --git a/chromecast/browser/bluetooth/cast_bluetooth_chooser.cc b/chromecast/browser/bluetooth/cast_bluetooth_chooser.cc
index dd41c5e..dd6d401 100644
--- a/chromecast/browser/bluetooth/cast_bluetooth_chooser.cc
+++ b/chromecast/browser/bluetooth/cast_bluetooth_chooser.cc
@@ -4,20 +4,20 @@
 
 #include "chromecast/browser/bluetooth/cast_bluetooth_chooser.h"
 #include "base/bind.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace chromecast {
 
 CastBluetoothChooser::CastBluetoothChooser(
     content::BluetoothChooser::EventHandler event_handler,
-    mojom::BluetoothDeviceAccessProviderPtr provider)
-    : event_handler_(std::move(event_handler)), binding_(this) {
+    mojo::PendingRemote<mojom::BluetoothDeviceAccessProvider> pending_provider)
+    : event_handler_(std::move(event_handler)) {
   DCHECK(event_handler_);
-
-  mojom::BluetoothDeviceAccessProviderClientPtr client;
-  binding_.Bind(mojo::MakeRequest(&client));
-  binding_.set_connection_error_handler(base::BindOnce(
+  mojo::Remote<mojom::BluetoothDeviceAccessProvider> provider(
+      std::move(pending_provider));
+  provider->RequestDeviceAccess(receiver_.BindNewPipeAndPassRemote());
+  receiver_.set_disconnect_handler(base::BindOnce(
       &CastBluetoothChooser::OnClientConnectionError, base::Unretained(this)));
-  provider->RequestDeviceAccess(std::move(client));
 }
 
 CastBluetoothChooser::~CastBluetoothChooser() = default;
@@ -31,7 +31,7 @@
   }
 
   if (available_devices_.find(address) != available_devices_.end()) {
-    RunEventHandlerAndResetBinding(Event::SELECTED, address);
+    RunEventHandlerAndResetReceiver(Event::SELECTED, address);
     return;
   }
   approved_devices_.insert(address);
@@ -42,8 +42,8 @@
 
   all_devices_approved_ = true;
   if (!available_devices_.empty()) {
-    RunEventHandlerAndResetBinding(Event::SELECTED,
-                                   *available_devices_.begin());
+    RunEventHandlerAndResetReceiver(Event::SELECTED,
+                                    *available_devices_.begin());
   }
 }
 
@@ -58,18 +58,18 @@
   // Note: |device_id| is just a canonical Bluetooth address.
   if (all_devices_approved_ ||
       approved_devices_.find(device_id) != approved_devices_.end()) {
-    RunEventHandlerAndResetBinding(Event::SELECTED, device_id);
+    RunEventHandlerAndResetReceiver(Event::SELECTED, device_id);
     return;
   }
   available_devices_.insert(device_id);
 }
 
-void CastBluetoothChooser::RunEventHandlerAndResetBinding(
+void CastBluetoothChooser::RunEventHandlerAndResetReceiver(
     content::BluetoothChooser::Event event,
     std::string address) {
   DCHECK(event_handler_);
   std::move(event_handler_).Run(event, std::move(address));
-  binding_.Close();
+  receiver_.reset();
 }
 
 void CastBluetoothChooser::OnClientConnectionError() {
@@ -77,7 +77,7 @@
   // tear down the client immediately. In this case, do not run the event
   // handler, as we may have not had the opportunity to select a device.
   if (!all_devices_approved_ && event_handler_) {
-    RunEventHandlerAndResetBinding(Event::CANCELLED, "");
+    RunEventHandlerAndResetReceiver(Event::CANCELLED, "");
   }
 }
 
diff --git a/chromecast/browser/bluetooth/cast_bluetooth_chooser.h b/chromecast/browser/bluetooth/cast_bluetooth_chooser.h
index 60cbd02..97992b2 100644
--- a/chromecast/browser/bluetooth/cast_bluetooth_chooser.h
+++ b/chromecast/browser/bluetooth/cast_bluetooth_chooser.h
@@ -10,8 +10,8 @@
 
 #include "chromecast/browser/bluetooth/public/mojom/web_bluetooth.mojom.h"
 #include "content/public/browser/bluetooth_chooser.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace chromecast {
 
@@ -27,7 +27,8 @@
   // the |provider| destroys the connection to this client. |this| may destroy
   // |provider| immediately after requesting access.
   CastBluetoothChooser(content::BluetoothChooser::EventHandler event_handler,
-                       mojom::BluetoothDeviceAccessProviderPtr provider);
+                       mojo::PendingRemote<mojom::BluetoothDeviceAccessProvider>
+                           pending_provider);
   ~CastBluetoothChooser() override;
 
  private:
@@ -43,16 +44,16 @@
                          bool is_paired,
                          int signal_strength_level) override;
 
-  // Runs the event_handler and resets the client binding. After this is called,
-  // this class should not be used.
-  void RunEventHandlerAndResetBinding(content::BluetoothChooser::Event event,
-                                      std::string address);
+  // Runs the event_handler and resets the client receiver. After this is
+  // called, this class should not be used.
+  void RunEventHandlerAndResetReceiver(content::BluetoothChooser::Event event,
+                                       std::string address);
 
-  // Called when the remote connection held by |binding_| is torn down.
+  // Called when the remote connection held by |receiver_| is torn down.
   void OnClientConnectionError();
 
   content::BluetoothChooser::EventHandler event_handler_;
-  mojo::Binding<mojom::BluetoothDeviceAccessProviderClient> binding_;
+  mojo::Receiver<mojom::BluetoothDeviceAccessProviderClient> receiver_{this};
   std::unordered_set<std::string> available_devices_;
   std::unordered_set<std::string> approved_devices_;
   bool all_devices_approved_ = false;
diff --git a/chromecast/browser/bluetooth/cast_bluetooth_chooser_unittest.cc b/chromecast/browser/bluetooth/cast_bluetooth_chooser_unittest.cc
index ac25d3e..6eae56e 100644
--- a/chromecast/browser/bluetooth/cast_bluetooth_chooser_unittest.cc
+++ b/chromecast/browser/bluetooth/cast_bluetooth_chooser_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -19,22 +20,26 @@
 
   // mojom::BluetoothDeviceAccessProvider implementation:
   void RequestDeviceAccess(
-      mojom::BluetoothDeviceAccessProviderClientPtr client) override {
+      mojo::PendingRemote<mojom::BluetoothDeviceAccessProviderClient> client)
+      override {
     DCHECK(!client_);
-    client.set_connection_error_handler(connection_closed_.Get());
+    client_.Bind(std::move(client));
+    client_.set_disconnect_handler(connection_closed_.Get());
     for (const auto& address : approved_devices_)
-      client->GrantAccess(address);
-    client_ = std::move(client);
+      client_->GrantAccess(address);
   }
 
-  mojom::BluetoothDeviceAccessProviderClientPtr& client() { return client_; }
+  mojom::BluetoothDeviceAccessProviderClient* client() {
+    return client_ ? client_.get() : nullptr;
+  }
+  void reset_client() { return client_.reset(); }
   base::MockCallback<base::OnceClosure>& connection_closed() {
     return connection_closed_;
   }
   std::vector<std::string>& approved_devices() { return approved_devices_; }
 
  private:
-  mojom::BluetoothDeviceAccessProviderClientPtr client_;
+  mojo::Remote<mojom::BluetoothDeviceAccessProviderClient> client_;
   base::MockCallback<base::OnceClosure> connection_closed_;
   std::vector<std::string> approved_devices_;
 
@@ -47,11 +52,9 @@
 
 class CastBluetoothChooserTest : public testing::Test {
  public:
-  CastBluetoothChooserTest() : provider_binding_(&provider_) {
-    mojom::BluetoothDeviceAccessProviderPtr provider;
-    provider_binding_.Bind(mojo::MakeRequest(&provider));
+  CastBluetoothChooserTest() : provider_receiver_(&provider_) {
     cast_bluetooth_chooser_ = std::make_unique<CastBluetoothChooser>(
-        handler_.Get(), std::move(provider));
+        handler_.Get(), provider_receiver_.BindNewPipeAndPassRemote());
     task_environment_.RunUntilIdle();
   }
 
@@ -71,7 +74,7 @@
 
  private:
   SimpleDeviceAccessProvider provider_;
-  mojo::Binding<mojom::BluetoothDeviceAccessProvider> provider_binding_;
+  mojo::Receiver<mojom::BluetoothDeviceAccessProvider> provider_receiver_;
   std::unique_ptr<CastBluetoothChooser> cast_bluetooth_chooser_;
 
   DISALLOW_COPY_AND_ASSIGN(CastBluetoothChooserTest);
@@ -152,7 +155,7 @@
   // Tear down the client. Now that it has granted access to the client, it does
   // not need to keep a reference to it. However, the chooser should stay alive
   // and wait for devices to be made available.
-  provider().client().reset();
+  provider().reset_client();
   EXPECT_FALSE(provider().client());
   task_environment_.RunUntilIdle();
 
@@ -171,7 +174,7 @@
   // Tear the client down before any access is granted. |handler| should run,
   // but with Event::CANCELLED.
   EXPECT_CALL(handler_, Run(content::BluetoothChooser::Event::CANCELLED, ""));
-  provider().client().reset();
+  provider().reset_client();
   EXPECT_FALSE(provider().client());
   task_environment_.RunUntilIdle();
 }
diff --git a/chromecast/browser/bluetooth/public/mojom/web_bluetooth.mojom b/chromecast/browser/bluetooth/public/mojom/web_bluetooth.mojom
index 8270612..1d8d6ce 100644
--- a/chromecast/browser/bluetooth/public/mojom/web_bluetooth.mojom
+++ b/chromecast/browser/bluetooth/public/mojom/web_bluetooth.mojom
@@ -10,7 +10,8 @@
 // devices.
 interface BluetoothDeviceAccessProvider {
   // Request that the host begin granting |client| access to approved devices.
-  RequestDeviceAccess(BluetoothDeviceAccessProviderClient client);
+  RequestDeviceAccess(
+      pending_remote<BluetoothDeviceAccessProviderClient> client);
 };
 
 // The client for BluetoothDeviceAccessProvider, provided by the Activity,
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 6dc5d3f..577ba68 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -737,7 +737,7 @@
     blink::AssociatedInterfaceRegistry* associated_registry,
     content::RenderProcessHost* render_process_host) {
   registry->AddInterface(
-      base::Bind(&media::MediaCapsImpl::AddBinding,
+      base::Bind(&media::MediaCapsImpl::AddReceiver,
                  base::Unretained(cast_browser_main_parts_->media_caps())),
       base::ThreadTaskRunnerHandle::Get());
 
@@ -995,7 +995,7 @@
   cast_network_contexts_->OnNetworkServiceCreated(network_service);
 }
 
-network::mojom::NetworkContextPtr
+mojo::Remote<network::mojom::NetworkContext>
 CastContentBrowserClient::CreateNetworkContext(
     content::BrowserContext* context,
     bool in_memory,
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 562ee8d..e5acf04 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -213,7 +213,7 @@
       NonNetworkURLLoaderFactoryMap* factories) override;
   void OnNetworkServiceCreated(
       network::mojom::NetworkService* network_service) override;
-  network::mojom::NetworkContextPtr CreateNetworkContext(
+  mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext(
       content::BrowserContext* context,
       bool in_memory,
       const base::FilePath& relative_partition_path) override;
diff --git a/chromecast/browser/cast_network_contexts.cc b/chromecast/browser/cast_network_contexts.cc
index f9e9f7f..3f74108 100644
--- a/chromecast/browser/cast_network_contexts.cc
+++ b/chromecast/browser/cast_network_contexts.cc
@@ -137,13 +137,14 @@
   return system_shared_url_loader_factory_;
 }
 
-network::mojom::NetworkContextPtr CastNetworkContexts::CreateNetworkContext(
+mojo::Remote<network::mojom::NetworkContext>
+CastNetworkContexts::CreateNetworkContext(
     content::BrowserContext* context,
     bool in_memory,
     const base::FilePath& relative_partition_path) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  network::mojom::NetworkContextPtr network_context;
+  mojo::Remote<network::mojom::NetworkContext> network_context;
   network::mojom::NetworkContextParamsPtr context_params =
       CreateDefaultNetworkContextParams();
 
@@ -153,7 +154,7 @@
   context_params->accept_language = "en-us,en";
 
   content::GetNetworkService()->CreateNetworkContext(
-      MakeRequest(&network_context), std::move(context_params));
+      network_context.BindNewPipeAndPassReceiver(), std::move(context_params));
   return network_context;
 }
 
diff --git a/chromecast/browser/cast_network_contexts.h b/chromecast/browser/cast_network_contexts.h
index 2f356f1..2077fc0 100644
--- a/chromecast/browser/cast_network_contexts.h
+++ b/chromecast/browser/cast_network_contexts.h
@@ -13,6 +13,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/proxy_resolution/proxy_config_service.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/network/public/mojom/proxy_config.mojom.h"
@@ -70,7 +71,7 @@
   // system NetworkContext, if the network service is enabled.
   void OnNetworkServiceCreated(network::mojom::NetworkService* network_service);
 
-  network::mojom::NetworkContextPtr CreateNetworkContext(
+  mojo::Remote<network::mojom::NetworkContext> CreateNetworkContext(
       content::BrowserContext* context,
       bool in_memory,
       const base::FilePath& relative_partition_path);
@@ -131,4 +132,4 @@
 }  // namespace shell
 }  // namespace chromecast
 
-#endif  // CHROMECAST_BROWSER_URL_REQUEST_CONTEXT_FACTORY_H_
+#endif  // CHROMECAST_BROWSER_CAST_NETWORK_CONTEXTS_H_
diff --git a/chromecast/browser/media/media_caps_impl.cc b/chromecast/browser/media/media_caps_impl.cc
index d5df37c..a4add26 100644
--- a/chromecast/browser/media/media_caps_impl.cc
+++ b/chromecast/browser/media/media_caps_impl.cc
@@ -8,6 +8,7 @@
 #include "chromecast/browser/media/supported_codec_finder.h"
 #include "chromecast/media/base/media_caps.h"
 #include "chromecast/public/media/decoder_config.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 namespace chromecast {
 namespace media {
@@ -38,17 +39,15 @@
   supported_codec_finder.FindSupportedCodecProfileLevels(this);
 }
 
-void MediaCapsImpl::AddBinding(
-    mojom::MediaCapsRequest request) {
-  bindings_.AddBinding(this, std::move(request));
+void MediaCapsImpl::AddReceiver(
+    mojo::PendingReceiver<mojom::MediaCaps> receiver) {
+  receivers_.Add(this, std::move(receiver));
 }
 
 void MediaCapsImpl::ScreenResolutionChanged(unsigned width, unsigned height) {
   screen_resolution_ = gfx::Size(width, height);
-
-  observers_.ForAllPtrs([width, height](mojom::MediaCapsObserver* observer) {
+  for (auto& observer : observers_)
     observer->ScreenResolutionChanged(width, height);
-  });
 }
 
 void MediaCapsImpl::ScreenInfoChanged(int hdcp_version,
@@ -66,30 +65,28 @@
   current_mode_supports_hdr_ = current_mode_supports_hdr;
   current_mode_supports_dv_ = current_mode_supports_dv;
 
-  observers_.ForAllPtrs([hdcp_version, supported_eotfs, dolby_vision_flags,
-                         screen_width_mm, screen_height_mm,
-                         current_mode_supports_hdr, current_mode_supports_dv](
-      mojom::MediaCapsObserver* observer) {
+  for (auto& observer : observers_) {
     observer->ScreenInfoChanged(hdcp_version, supported_eotfs,
                                 dolby_vision_flags, screen_width_mm,
                                 screen_height_mm, current_mode_supports_hdr,
                                 current_mode_supports_dv);
-  });
+  }
 }
 
 void MediaCapsImpl::AddSupportedCodecProfileLevel(
     const CodecProfileLevel& codec_profile_level) {
   codec_profile_levels_.push_back(codec_profile_level);
-  observers_.ForAllPtrs(
-      [&codec_profile_level](mojom::MediaCapsObserver* observer) {
-        mojom::CodecProfileLevelPtr mojo_codec_profile_level(
-            ConvertCodecProfileLevelToMojo(codec_profile_level));
-        observer->AddSupportedCodecProfileLevel(
-            std::move(mojo_codec_profile_level));
-      });
+  for (auto& observer : observers_) {
+    mojom::CodecProfileLevelPtr mojo_codec_profile_level(
+        ConvertCodecProfileLevelToMojo(codec_profile_level));
+    observer->AddSupportedCodecProfileLevel(
+        std::move(mojo_codec_profile_level));
+  }
 }
 
-void MediaCapsImpl::AddObserver(mojom::MediaCapsObserverPtr observer) {
+void MediaCapsImpl::AddObserver(
+    mojo::PendingRemote<mojom::MediaCapsObserver> observer_remote) {
+  mojo::Remote<mojom::MediaCapsObserver> observer(std::move(observer_remote));
   observer->ScreenResolutionChanged(screen_resolution_.width(),
                                     screen_resolution_.height());
   observer->ScreenInfoChanged(hdcp_version_, supported_eotfs_,
@@ -102,7 +99,7 @@
     observer->AddSupportedCodecProfileLevel(
         ConvertCodecProfileLevelToMojo(codec_profile_level));
   }
-  observers_.AddPtr(std::move(observer));
+  observers_.Add(std::move(observer));
 }
 
 }  // namespace media
diff --git a/chromecast/browser/media/media_caps_impl.h b/chromecast/browser/media/media_caps_impl.h
index 5ba384c..9bb8213 100644
--- a/chromecast/browser/media/media_caps_impl.h
+++ b/chromecast/browser/media/media_caps_impl.h
@@ -9,8 +9,9 @@
 
 #include "base/macros.h"
 #include "chromecast/common/mojom/media_caps.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace chromecast {
@@ -24,7 +25,7 @@
   ~MediaCapsImpl() override;
 
   void Initialize();
-  void AddBinding(mojom::MediaCapsRequest request);
+  void AddReceiver(mojo::PendingReceiver<mojom::MediaCaps> receiver);
 
   void ScreenResolutionChanged(unsigned width, unsigned height);
   void ScreenInfoChanged(int hdcp_version,
@@ -39,7 +40,8 @@
 
  private:
   // chromecast::mojom::MediaCaps implementation.
-  void AddObserver(mojom::MediaCapsObserverPtr observer) override;
+  void AddObserver(
+      mojo::PendingRemote<mojom::MediaCapsObserver> observer) override;
 
   int hdcp_version_;
   int supported_eotfs_;
@@ -50,8 +52,8 @@
   bool current_mode_supports_dv_;
   gfx::Size screen_resolution_;
   std::vector<CodecProfileLevel> codec_profile_levels_;
-  mojo::InterfacePtrSet<mojom::MediaCapsObserver> observers_;
-  mojo::BindingSet<mojom::MediaCaps> bindings_;
+  mojo::RemoteSet<mojom::MediaCapsObserver> observers_;
+  mojo::ReceiverSet<mojom::MediaCaps> receivers_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaCapsImpl);
 };
diff --git a/chromecast/browser/memory_pressure_controller_impl.cc b/chromecast/browser/memory_pressure_controller_impl.cc
index 7650593..b093b53 100644
--- a/chromecast/browser/memory_pressure_controller_impl.cc
+++ b/chromecast/browser/memory_pressure_controller_impl.cc
@@ -24,14 +24,13 @@
 
 void MemoryPressureControllerImpl::OnMemoryPressure(
     base::MemoryPressureListener::MemoryPressureLevel level) {
-  observers_.ForAllPtrs([level](mojom::MemoryPressureObserver* observer) {
+  for (auto& observer : observers_)
     observer->MemoryPressureLevelChanged(level);
-  });
 }
 
 void MemoryPressureControllerImpl::AddObserver(
-    mojom::MemoryPressureObserverPtr observer) {
-  observers_.AddPtr(std::move(observer));
+    mojo::PendingRemote<mojom::MemoryPressureObserver> observer) {
+  observers_.Add(std::move(observer));
 }
 
 }  // namespace chromecast
diff --git a/chromecast/browser/memory_pressure_controller_impl.h b/chromecast/browser/memory_pressure_controller_impl.h
index bfeeb22..fd530fd 100644
--- a/chromecast/browser/memory_pressure_controller_impl.h
+++ b/chromecast/browser/memory_pressure_controller_impl.h
@@ -9,7 +9,8 @@
 #include "base/memory/memory_pressure_listener.h"
 #include "chromecast/common/mojom/memory_pressure.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
 
 namespace chromecast {
 
@@ -22,12 +23,13 @@
 
  private:
   // chromecast::mojom::MemoryPressure implementation.
-  void AddObserver(mojom::MemoryPressureObserverPtr observer) override;
+  void AddObserver(
+      mojo::PendingRemote<mojom::MemoryPressureObserver> observer) override;
 
   void OnMemoryPressure(
       base::MemoryPressureListener::MemoryPressureLevel level);
 
-  mojo::InterfacePtrSet<mojom::MemoryPressureObserver> observers_;
+  mojo::RemoteSet<mojom::MemoryPressureObserver> observers_;
   mojo::BindingSet<mojom::MemoryPressureController> bindings_;
 
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
diff --git a/chromecast/common/mojom/application_media_capabilities.mojom b/chromecast/common/mojom/application_media_capabilities.mojom
index 10f0cdcf..83634af 100644
--- a/chromecast/common/mojom/application_media_capabilities.mojom
+++ b/chromecast/common/mojom/application_media_capabilities.mojom
@@ -12,5 +12,5 @@
 
 // Media capabilities for an individual application.
 interface ApplicationMediaCapabilities {
-  AddObserver(ApplicationMediaCapabilitiesObserver observer);
+  AddObserver(pending_remote<ApplicationMediaCapabilitiesObserver> observer);
 };
diff --git a/chromecast/common/mojom/media_caps.mojom b/chromecast/common/mojom/media_caps.mojom
index 2c33389..5bb92873 100644
--- a/chromecast/common/mojom/media_caps.mojom
+++ b/chromecast/common/mojom/media_caps.mojom
@@ -12,7 +12,7 @@
 
 // Media capabilities that apply to all applications.
 interface MediaCaps {
-  AddObserver(MediaCapsObserver observer);
+  AddObserver(pending_remote<MediaCapsObserver> observer);
 };
 
 // Observes changes in media capabilities that apply to all applications.
diff --git a/chromecast/common/mojom/memory_pressure.mojom b/chromecast/common/mojom/memory_pressure.mojom
index 3e7face..3055448 100644
--- a/chromecast/common/mojom/memory_pressure.mojom
+++ b/chromecast/common/mojom/memory_pressure.mojom
@@ -5,7 +5,7 @@
 module chromecast.mojom;
 
 interface MemoryPressureController {
-  AddObserver(MemoryPressureObserver observer);
+  AddObserver(pending_remote<MemoryPressureObserver> observer);
 };
 
 interface MemoryPressureObserver {
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc
index 24d5cff..674d34a 100644
--- a/chromecast/renderer/cast_content_renderer_client.cc
+++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -29,6 +29,7 @@
 #include "media/base/audio_parameters.h"
 #include "media/base/media.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/platform/web_runtime_features.h"
 #include "third_party/blink/public/web/web_frame_widget.h"
@@ -76,7 +77,6 @@
 CastContentRendererClient::CastContentRendererClient()
     : supported_profiles_(
           std::make_unique<media::SupportedCodecProfileLevelsMemo>()),
-      app_media_capabilities_observer_binding_(this),
       supported_bitstream_audio_codecs_(kBitstreamAudioCodecNone) {
 #if defined(OS_ANDROID)
   DCHECK(::media::MediaCodecUtil::IsMediaCodecAvailable())
@@ -98,9 +98,9 @@
 void CastContentRendererClient::RenderThreadStarted() {
   // Register as observer for media capabilities
   content::RenderThread* thread = content::RenderThread::Get();
-  media::mojom::MediaCapsPtr media_caps;
-  thread->BindHostReceiver(mojo::MakeRequest(&media_caps));
-  media::mojom::MediaCapsObserverPtr proxy;
+  mojo::Remote<media::mojom::MediaCaps> media_caps;
+  thread->BindHostReceiver(media_caps.BindNewPipeAndPassReceiver());
+  mojo::PendingRemote<media::mojom::MediaCapsObserver> proxy;
   media_caps_observer_.reset(
       new media::MediaCapsObserverImpl(&proxy, supported_profiles_.get()));
   media_caps->AddObserver(std::move(proxy));
@@ -109,7 +109,8 @@
   // Register to observe memory pressure changes
   chromecast::mojom::MemoryPressureControllerPtr memory_pressure_controller;
   thread->BindHostReceiver(mojo::MakeRequest(&memory_pressure_controller));
-  chromecast::mojom::MemoryPressureObserverPtr memory_pressure_proxy;
+  mojo::PendingRemote<chromecast::mojom::MemoryPressureObserver>
+      memory_pressure_proxy;
   memory_pressure_observer_.reset(
       new MemoryPressureObserverImpl(&memory_pressure_proxy));
   memory_pressure_controller->AddObserver(std::move(memory_pressure_proxy));
@@ -174,13 +175,12 @@
   // APIs. The objects' lifetimes are bound to the RenderFrame's lifetime.
   new OnLoadScriptInjector(render_frame);
 
-  if (!app_media_capabilities_observer_binding_.is_bound()) {
-    mojom::ApplicationMediaCapabilitiesObserverPtr observer;
-    app_media_capabilities_observer_binding_.Bind(mojo::MakeRequest(&observer));
-    mojom::ApplicationMediaCapabilitiesPtr app_media_capabilities;
+  if (!app_media_capabilities_observer_receiver_.is_bound()) {
+    mojo::Remote<mojom::ApplicationMediaCapabilities> app_media_capabilities;
     render_frame->GetRemoteInterfaces()->GetInterface(
-        mojo::MakeRequest(&app_media_capabilities));
-    app_media_capabilities->AddObserver(std::move(observer));
+        app_media_capabilities.BindNewPipeAndPassReceiver());
+    app_media_capabilities->AddObserver(
+        app_media_capabilities_observer_receiver_.BindNewPipeAndPassRemote());
   }
 
 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
diff --git a/chromecast/renderer/cast_content_renderer_client.h b/chromecast/renderer/cast_content_renderer_client.h
index 27e5f38..af3dbf2 100644
--- a/chromecast/renderer/cast_content_renderer_client.h
+++ b/chromecast/renderer/cast_content_renderer_client.h
@@ -15,7 +15,7 @@
 #include "content/public/renderer/content_renderer_client.h"
 #include "media/base/audio_codecs.h"
 #include "media/base/audio_parameters.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace extensions {
 class ExtensionsClient;
@@ -96,8 +96,8 @@
       prescient_networking_dispatcher_;
   std::unique_ptr<media::MediaCapsObserverImpl> media_caps_observer_;
   std::unique_ptr<media::SupportedCodecProfileLevelsMemo> supported_profiles_;
-  mojo::Binding<mojom::ApplicationMediaCapabilitiesObserver>
-      app_media_capabilities_observer_binding_;
+  mojo::Receiver<mojom::ApplicationMediaCapabilitiesObserver>
+      app_media_capabilities_observer_receiver_{this};
 #if !defined(OS_ANDROID)
   std::unique_ptr<MemoryPressureObserverImpl> memory_pressure_observer_;
 #endif
diff --git a/chromecast/renderer/media/media_caps_observer_impl.cc b/chromecast/renderer/media/media_caps_observer_impl.cc
index a389d81..18978858 100644
--- a/chromecast/renderer/media/media_caps_observer_impl.cc
+++ b/chromecast/renderer/media/media_caps_observer_impl.cc
@@ -12,10 +12,10 @@
 namespace media {
 
 MediaCapsObserverImpl::MediaCapsObserverImpl(
-    mojom::MediaCapsObserverPtr* proxy,
+    mojo::PendingRemote<mojom::MediaCapsObserver>* proxy,
     SupportedCodecProfileLevelsMemo* supported_profiles)
     : supported_profiles_(supported_profiles),
-      binding_(this, mojo::MakeRequest(proxy)) {}
+      receiver_(this, proxy->InitWithNewPipeAndPassReceiver()) {}
 
 MediaCapsObserverImpl::~MediaCapsObserverImpl() = default;
 
diff --git a/chromecast/renderer/media/media_caps_observer_impl.h b/chromecast/renderer/media/media_caps_observer_impl.h
index 37904fa..04ee2bd 100644
--- a/chromecast/renderer/media/media_caps_observer_impl.h
+++ b/chromecast/renderer/media/media_caps_observer_impl.h
@@ -10,7 +10,8 @@
 #include "base/macros.h"
 #include "chromecast/common/mojom/media_caps.mojom.h"
 #include "chromecast/media/base/supported_codec_profile_levels_memo.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace chromecast {
@@ -18,7 +19,7 @@
 
 class MediaCapsObserverImpl : public mojom::MediaCapsObserver {
  public:
-  MediaCapsObserverImpl(mojom::MediaCapsObserverPtr* proxy,
+  MediaCapsObserverImpl(mojo::PendingRemote<mojom::MediaCapsObserver>* proxy,
                         SupportedCodecProfileLevelsMemo* supported_profiles);
   ~MediaCapsObserverImpl() override;
 
@@ -35,7 +36,7 @@
       mojom::CodecProfileLevelPtr codec_profile_level) override;
 
   SupportedCodecProfileLevelsMemo* supported_profiles_;
-  mojo::Binding<mojom::MediaCapsObserver> binding_;
+  mojo::Receiver<mojom::MediaCapsObserver> receiver_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaCapsObserverImpl);
 };
diff --git a/chromecast/renderer/memory_pressure_observer_impl.cc b/chromecast/renderer/memory_pressure_observer_impl.cc
index ccd6568..ccbcb0b3 100644
--- a/chromecast/renderer/memory_pressure_observer_impl.cc
+++ b/chromecast/renderer/memory_pressure_observer_impl.cc
@@ -9,8 +9,8 @@
 namespace chromecast {
 
 MemoryPressureObserverImpl::MemoryPressureObserverImpl(
-    mojom::MemoryPressureObserverPtr* proxy)
-    : binding_(this, mojo::MakeRequest(proxy)) {}
+    mojo::PendingRemote<mojom::MemoryPressureObserver>* observer)
+    : receiver_(this, observer->InitWithNewPipeAndPassReceiver()) {}
 
 MemoryPressureObserverImpl::~MemoryPressureObserverImpl() = default;
 
diff --git a/chromecast/renderer/memory_pressure_observer_impl.h b/chromecast/renderer/memory_pressure_observer_impl.h
index fb71957..ac6398f 100644
--- a/chromecast/renderer/memory_pressure_observer_impl.h
+++ b/chromecast/renderer/memory_pressure_observer_impl.h
@@ -7,19 +7,21 @@
 
 #include "base/macros.h"
 #include "chromecast/common/mojom/memory_pressure.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace chromecast {
 
 class MemoryPressureObserverImpl : public mojom::MemoryPressureObserver {
  public:
-  MemoryPressureObserverImpl(mojom::MemoryPressureObserverPtr* proxy);
+  MemoryPressureObserverImpl(
+      mojo::PendingRemote<mojom::MemoryPressureObserver>* observer);
   ~MemoryPressureObserverImpl() override;
 
  private:
   void MemoryPressureLevelChanged(int32_t pressure_level) override;
 
-  mojo::Binding<mojom::MemoryPressureObserver> binding_;
+  mojo::Receiver<mojom::MemoryPressureObserver> receiver_;
 
   DISALLOW_COPY_AND_ASSIGN(MemoryPressureObserverImpl);
 };
diff --git a/chromeos/components/proximity_auth/metrics.cc b/chromeos/components/proximity_auth/metrics.cc
index cb77635..1227423 100644
--- a/chromeos/components/proximity_auth/metrics.cc
+++ b/chromeos/components/proximity_auth/metrics.cc
@@ -12,6 +12,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/numerics/ranges.h"
 #include "base/stl_util.h"
 #include "base/sys_byteorder.h"
 
@@ -50,7 +51,7 @@
 
 void RecordAuthProximityRollingRssi(int rolling_rssi) {
   if (rolling_rssi != kUnknownProximityValue)
-    rolling_rssi = std::min(50, std::max(-100, rolling_rssi));
+    rolling_rssi = base::ClampToRange(rolling_rssi, -100, 50);
 
   base::UmaHistogramSparse("EasyUnlock.AuthProximity.RollingRssi",
                            rolling_rssi);
diff --git a/chromeos/components/tether/device_status_util.cc b/chromeos/components/tether/device_status_util.cc
index 5d134a9..cdb3e82 100644
--- a/chromeos/components/tether/device_status_util.cc
+++ b/chromeos/components/tether/device_status_util.cc
@@ -4,26 +4,12 @@
 
 #include "chromeos/components/tether/device_status_util.h"
 
+#include "base/numerics/ranges.h"
+
 namespace chromeos {
 
 namespace tether {
 
-namespace {
-
-const char kDefaultCellCarrierName[] = "unknown-carrier";
-
-// Android signal strength is measured between 0 and 4 (inclusive), but Chrome
-// OS signal strength is measured between 0 and 100 (inclusive). In order to
-// convert between Android signal strength to Chrome OS signal strength, the
-// value must be multiplied by the below value.
-const int32_t kAndroidTetherHostToChromeOSSignalStrengthMultiplier = 25;
-
-int32_t ForceBetweenZeroAndOneHundred(int32_t value) {
-  return std::min(std::max(value, 0), 100);
-}
-
-}  // namespace
-
 void NormalizeDeviceStatus(const DeviceStatus& status,
                            std::string* carrier_out,
                            int32_t* battery_percentage_out,
@@ -31,6 +17,7 @@
   // Use a sentinel value if carrier information is not available. This value is
   // special-cased and replaced with a localized string in the settings UI.
   if (carrier_out) {
+    constexpr char kDefaultCellCarrierName[] = "unknown-carrier";
     *carrier_out =
         (!status.has_cell_provider() || status.cell_provider().empty())
             ? kDefaultCellCarrierName
@@ -44,15 +31,19 @@
   if (battery_percentage_out) {
     *battery_percentage_out =
         status.has_battery_percentage()
-            ? ForceBetweenZeroAndOneHundred(status.battery_percentage())
+            ? base::ClampToRange(status.battery_percentage(), 0, 100)
             : 100;
   }
   if (signal_strength_out) {
+    // Android signal strength is measured between 0 and 4 (inclusive), but
+    // Chrome OS signal strength is measured between 0 and 100 (inclusive). In
+    // order to convert between Android signal strength to Chrome OS signal
+    // strength, the value must be multiplied by the below value.
+    constexpr int32_t kConversionFactor = 100 / 4;
     *signal_strength_out =
         status.has_connection_strength()
-            ? ForceBetweenZeroAndOneHundred(
-                  kAndroidTetherHostToChromeOSSignalStrengthMultiplier *
-                  status.connection_strength())
+            ? base::ClampToRange(
+                  kConversionFactor * status.connection_strength(), 0, 100)
             : 100;
   }
 }
diff --git a/chromeos/constants/chromeos_switches.cc b/chromeos/constants/chromeos_switches.cc
index 5f3cbab..571fd81 100644
--- a/chromeos/constants/chromeos_switches.cc
+++ b/chromeos/constants/chromeos_switches.cc
@@ -433,10 +433,6 @@
 // TODO(984021): Remove when URL is sent by DMServer.
 const char kPublicAccountsSamlAclUrl[] = "public-accounts-saml-acl-url";
 
-// Url address of SAML provider for a SAML public session.
-// TODO(984021): Remove when URL is sent by DMServer.
-const char kPublicAccountsSamlUrl[] = "public-accounts-saml-url";
-
 // If set to "true", the profile requires policy during restart (policy load
 // must succeed, otherwise session restart should fail).
 const char kProfileRequiresPolicy[] = "profile-requires-policy";
diff --git a/chromeos/constants/chromeos_switches.h b/chromeos/constants/chromeos_switches.h
index 6b8603c..8552484 100644
--- a/chromeos/constants/chromeos_switches.h
+++ b/chromeos/constants/chromeos_switches.h
@@ -172,7 +172,6 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kOobeTimerInterval[];
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const char kPublicAccountsSamlAclUrl[];
-COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kPublicAccountsSamlUrl[];
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const char kDisableArcCpuRestriction[];
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kProfileRequiresPolicy[];
diff --git a/chromeos/dbus/cicerone_client.cc b/chromeos/dbus/cicerone_client.cc
index 9c118f2..e6b9096e 100644
--- a/chromeos/dbus/cicerone_client.cc
+++ b/chromeos/dbus/cicerone_client.cc
@@ -90,6 +90,10 @@
     return is_pending_app_list_updates_signal_connected_;
   }
 
+  bool IsApplyAnsiblePlaybookProgressSignalConnected() override {
+    return is_apply_ansible_playbook_progress_signal_connected_;
+  }
+
   void LaunchContainerApplication(
       const vm_tools::cicerone::LaunchContainerApplicationRequest& request,
       DBusMethodCallback<vm_tools::cicerone::LaunchContainerApplicationResponse>
@@ -413,6 +417,29 @@
             weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
+  void ApplyAnsiblePlaybook(
+      const vm_tools::cicerone::ApplyAnsiblePlaybookRequest& request,
+      DBusMethodCallback<vm_tools::cicerone::ApplyAnsiblePlaybookResponse>
+          callback) override {
+    dbus::MethodCall method_call(
+        vm_tools::cicerone::kVmCiceroneInterface,
+        vm_tools::cicerone::kApplyAnsiblePlaybookMethod);
+    dbus::MessageWriter writer(&method_call);
+
+    if (!writer.AppendProtoAsArrayOfBytes(request)) {
+      LOG(ERROR) << "Failed to encode ApplyAnsiblePlaybookRequest protobuf";
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
+      return;
+    }
+
+    cicerone_proxy_->CallMethod(
+        &method_call, kDefaultTimeout.InMilliseconds(),
+        base::BindOnce(&CiceroneClientImpl::OnDBusProtoResponse<
+                           vm_tools::cicerone::ApplyAnsiblePlaybookResponse>,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
   void WaitForServiceToBeAvailable(
       dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback)
       override {
@@ -517,6 +544,14 @@
                             weak_ptr_factory_.GetWeakPtr()),
         base::BindOnce(&CiceroneClientImpl::OnSignalConnected,
                        weak_ptr_factory_.GetWeakPtr()));
+    cicerone_proxy_->ConnectToSignal(
+        vm_tools::cicerone::kVmCiceroneInterface,
+        vm_tools::cicerone::kApplyAnsiblePlaybookProgressSignal,
+        base::BindRepeating(
+            &CiceroneClientImpl::OnApplyAnsiblePlaybookProgressSignal,
+            weak_ptr_factory_.GetWeakPtr()),
+        base::BindOnce(&CiceroneClientImpl::OnSignalConnected,
+                       weak_ptr_factory_.GetWeakPtr()));
   }
 
  private:
@@ -681,6 +716,18 @@
     }
   }
 
+  void OnApplyAnsiblePlaybookProgressSignal(dbus::Signal* signal) {
+    vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal proto;
+    dbus::MessageReader reader(signal);
+    if (!reader.PopArrayOfBytesAsProto(&proto)) {
+      LOG(ERROR) << "Failed to parse proto from DBus Signal";
+      return;
+    }
+    for (auto& observer : observer_list_) {
+      observer.OnApplyAnsiblePlaybookProgress(proto);
+    }
+  }
+
   void OnSignalConnected(const std::string& interface_name,
                          const std::string& signal_name,
                          bool is_connected) {
@@ -719,6 +766,9 @@
     } else if (signal_name ==
                vm_tools::cicerone::kPendingAppListUpdatesSignal) {
       is_pending_app_list_updates_signal_connected_ = is_connected;
+    } else if (signal_name ==
+               vm_tools::cicerone::kApplyAnsiblePlaybookProgressSignal) {
+      is_apply_ansible_playbook_progress_signal_connected_ = is_connected;
     } else {
       NOTREACHED();
     }
@@ -740,6 +790,7 @@
   bool is_export_lxd_container_progress_signal_connected_ = false;
   bool is_import_lxd_container_progress_signal_connected_ = false;
   bool is_pending_app_list_updates_signal_connected_ = false;
+  bool is_apply_ansible_playbook_progress_signal_connected_ = false;
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
diff --git a/chromeos/dbus/cicerone_client.h b/chromeos/dbus/cicerone_client.h
index d780ea6..bacf22b 100644
--- a/chromeos/dbus/cicerone_client.h
+++ b/chromeos/dbus/cicerone_client.h
@@ -83,6 +83,12 @@
     virtual void OnPendingAppListUpdates(
         const vm_tools::cicerone::PendingAppListUpdatesSignal& signal) = 0;
 
+    // This is signaled from the container while a playbook is being applied
+    // via ApplyAnsiblePlaybook.
+    virtual void OnApplyAnsiblePlaybookProgress(
+        const vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal&
+            signal) = 0;
+
    protected:
     virtual ~Observer() = default;
   };
@@ -137,6 +143,9 @@
   // PendingAppListUpdatesSignal.
   virtual bool IsPendingAppListUpdatesSignalConnected() = 0;
 
+  // This should be true prior to calling ApplyAnsiblePlaybook.
+  virtual bool IsApplyAnsiblePlaybookProgressSignalConnected() = 0;
+
   // Launches an application inside a running Container.
   // |callback| is called after the method call finishes.
   virtual void LaunchContainerApplication(
@@ -238,6 +247,13 @@
       DBusMethodCallback<vm_tools::cicerone::CancelImportLxdContainerResponse>
           callback) = 0;
 
+  // Applies Ansible playbook.
+  // |callback| is called after the method call finishes.
+  virtual void ApplyAnsiblePlaybook(
+      const vm_tools::cicerone::ApplyAnsiblePlaybookRequest& request,
+      DBusMethodCallback<vm_tools::cicerone::ApplyAnsiblePlaybookResponse>
+          callback) = 0;
+
   // Registers |callback| to run when the Cicerone service becomes available.
   // If the service is already available, or if connecting to the name-owner-
   // changed signal fails, |callback| will be run once asynchronously.
diff --git a/chromeos/dbus/fake_cicerone_client.cc b/chromeos/dbus/fake_cicerone_client.cc
index 67a9547..0608e6f 100644
--- a/chromeos/dbus/fake_cicerone_client.cc
+++ b/chromeos/dbus/fake_cicerone_client.cc
@@ -94,6 +94,10 @@
   return is_import_lxd_container_progress_signal_connected_;
 }
 
+bool FakeCiceroneClient::IsApplyAnsiblePlaybookProgressSignalConnected() {
+  return is_apply_ansible_playbook_progress_signal_connected_;
+}
+
 // Currently no tests need to change the output of this method. If you want to
 // add one, make it return a variable like the above examples.
 bool FakeCiceroneClient::IsPendingAppListUpdatesSignalConnected() {
@@ -280,6 +284,15 @@
                                 cancel_import_lxd_container_response_));
 }
 
+void FakeCiceroneClient::ApplyAnsiblePlaybook(
+    const vm_tools::cicerone::ApplyAnsiblePlaybookRequest& request,
+    DBusMethodCallback<vm_tools::cicerone::ApplyAnsiblePlaybookResponse>
+        callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(std::move(callback), apply_ansible_playbook_response_));
+}
+
 void FakeCiceroneClient::NotifyLxdContainerCreated(
     const vm_tools::cicerone::LxdContainerCreatedSignal& proto) {
   for (auto& observer : observer_list_) {
@@ -343,4 +356,11 @@
   }
 }
 
+void FakeCiceroneClient::NotifyApplyAnsiblePlaybookProgress(
+    const vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal& signal) {
+  for (auto& observer : observer_list_) {
+    observer.OnApplyAnsiblePlaybookProgress(signal);
+  }
+}
+
 }  // namespace chromeos
diff --git a/chromeos/dbus/fake_cicerone_client.h b/chromeos/dbus/fake_cicerone_client.h
index f854294..47f6d0c 100644
--- a/chromeos/dbus/fake_cicerone_client.h
+++ b/chromeos/dbus/fake_cicerone_client.h
@@ -37,6 +37,7 @@
   bool IsExportLxdContainerProgressSignalConnected() override;
   bool IsImportLxdContainerProgressSignalConnected() override;
   bool IsPendingAppListUpdatesSignalConnected() override;
+  bool IsApplyAnsiblePlaybookProgressSignalConnected() override;
   void LaunchContainerApplication(
       const vm_tools::cicerone::LaunchContainerApplicationRequest& request,
       DBusMethodCallback<vm_tools::cicerone::LaunchContainerApplicationResponse>
@@ -100,6 +101,10 @@
       const vm_tools::cicerone::CancelImportLxdContainerRequest& request,
       DBusMethodCallback<vm_tools::cicerone::CancelImportLxdContainerResponse>
           callback) override;
+  void ApplyAnsiblePlaybook(
+      const vm_tools::cicerone::ApplyAnsiblePlaybookRequest& request,
+      DBusMethodCallback<vm_tools::cicerone::ApplyAnsiblePlaybookResponse>
+          callback) override;
   void WaitForServiceToBeAvailable(
       dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback) override;
 
@@ -232,10 +237,14 @@
   void set_lxd_container_os_release(vm_tools::cicerone::OsRelease os_release) {
     lxd_container_os_release_ = std::move(os_release);
   }
-
   void set_send_container_started_signal(bool send) {
     send_container_started_signal_ = send;
   }
+  void set_apply_ansible_playbook_response(
+      const vm_tools::cicerone::ApplyAnsiblePlaybookResponse&
+          apply_ansible_playbook_response) {
+    apply_ansible_playbook_response_ = apply_ansible_playbook_response;
+  }
 
   // Additional functions to allow tests to trigger Signals.
   void NotifyLxdContainerCreated(
@@ -258,6 +267,8 @@
       const vm_tools::cicerone::UninstallPackageProgressSignal& signal);
   void NotifyPendingAppListUpdates(
       const vm_tools::cicerone::PendingAppListUpdatesSignal& signal);
+  void NotifyApplyAnsiblePlaybookProgress(
+      const vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal& signal);
 
  protected:
   void Init(dbus::Bus* bus) override {}
@@ -274,6 +285,7 @@
   bool is_lxd_container_starting_signal_connected_ = true;
   bool is_export_lxd_container_progress_signal_connected_ = true;
   bool is_import_lxd_container_progress_signal_connected_ = true;
+  bool is_apply_ansible_playbook_progress_signal_connected_ = true;
 
   std::string last_container_username_;
   bool send_container_started_signal_ = true;
@@ -313,6 +325,8 @@
       cancel_export_lxd_container_response_;
   vm_tools::cicerone::CancelImportLxdContainerResponse
       cancel_import_lxd_container_response_;
+  vm_tools::cicerone::ApplyAnsiblePlaybookResponse
+      apply_ansible_playbook_response_;
 
   vm_tools::cicerone::OsRelease lxd_container_os_release_;
 
diff --git a/components/arc/net/arc_net_host_impl.cc b/components/arc/net/arc_net_host_impl.cc
index c970423..c04353b 100644
--- a/components/arc/net/arc_net_host_impl.cc
+++ b/components/arc/net/arc_net_host_impl.cc
@@ -858,7 +858,7 @@
   std::unique_ptr<base::Value> result =
       std::make_unique<base::Value>(base::Value::Type::LIST);
   for (const auto& item : string_list) {
-    result->GetList().emplace_back(item);
+    result->Append(item);
   }
   return result;
 }
diff --git a/components/autofill/core/browser/logging/log_buffer.cc b/components/autofill/core/browser/logging/log_buffer.cc
index 8bbd7a9..21ec495 100644
--- a/components/autofill/core/browser/logging/log_buffer.cc
+++ b/components/autofill/core/browser/logging/log_buffer.cc
@@ -40,7 +40,7 @@
   DCHECK(!IsTextNode(parent));
 
   if (auto* children = parent.FindListKey("children")) {
-    children->GetList().push_back(std::move(new_child));
+    children->Append(std::move(new_child));
     return;
   }
 
diff --git a/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc b/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
index 4364f145..bb3065a 100644
--- a/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
+++ b/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
@@ -439,7 +439,7 @@
   base::Value authenticator_transport_list =
       base::Value(base::Value::Type::LIST);
   for (FidoTransportProtocol protocol : attestation_response->transports) {
-    authenticator_transport_list.GetList().push_back(
+    authenticator_transport_list.Append(
         base::Value(base::ToUpperASCII(device::ToString(protocol))));
   }
 
diff --git a/components/autofill/core/browser/payments/payments_client.cc b/components/autofill/core/browser/payments/payments_client.cc
index b097a05..b24b371 100644
--- a/components/autofill/core/browser/payments/payments_client.cc
+++ b/components/autofill/core/browser/payments/payments_client.cc
@@ -142,7 +142,7 @@
                             base::Value& list) {
   const base::string16 value = profile.GetInfo(type, app_locale);
   if (!value.empty())
-    list.GetList().emplace_back(value);
+    list.Append(value);
 }
 
 // Returns a dictionary with the structure expected by Payments RPCs, containing
@@ -228,7 +228,7 @@
 
   base::Value active_chrome_experiments(base::Value::Type::LIST);
   for (const char* it : active_experiments)
-    active_chrome_experiments.GetList().emplace_back(it);
+    active_chrome_experiments.Append(it);
 
   request_dict.SetKey("active_chrome_experiments",
                       std::move(active_chrome_experiments));
@@ -568,8 +568,7 @@
       // min address is not possible). The final parameter directs
       // BuildAddressDictionary to omit names and phone numbers, which aren't
       // useful for these purposes.
-      addresses.GetList().push_back(
-          BuildAddressDictionary(profile, app_locale_, false));
+      addresses.Append(BuildAddressDictionary(profile, app_locale_, false));
     }
     request_dict.SetKey("address", std::move(addresses));
 
@@ -740,8 +739,7 @@
 
     base::Value addresses(base::Value::Type::LIST);
     for (const AutofillProfile& profile : request_details_.profiles) {
-      addresses.GetList().push_back(
-          BuildAddressDictionary(profile, app_locale, true));
+      addresses.Append(BuildAddressDictionary(profile, app_locale, true));
     }
     request_dict.SetKey("address", std::move(addresses));
 
@@ -859,7 +857,7 @@
     for (size_t index = 0; index < migratable_credit_cards_.size(); ++index) {
       std::string pan_field_name = GetPanFieldName(index);
       // Generate credit card dictionary.
-      migrate_cards.GetList().push_back(BuildCreditCardDictionary(
+      migrate_cards.Append(BuildCreditCardDictionary(
           migratable_credit_cards_[index].credit_card(), app_locale,
           pan_field_name));
       // Append pan data to the |all_pans_data|.
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc
index a1de20ba8..c454cc8 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -322,18 +322,8 @@
 
 #if defined(OS_CHROMEOS)
   if (!disabled_types.Has(syncer::PRINTERS)) {
-    // TODO(crbug.com/867801) This still uses a proxy delegate even though the
-    // model lives on the UI thread. Switching to forwarding delegate causes
-    // cryptic test failures on chromeos. Fix that and switch to the forwarding
-    // delegate.
-    controllers.push_back(std::make_unique<ModelTypeController>(
-        syncer::PRINTERS,
-        std::make_unique<syncer::ProxyModelTypeControllerDelegate>(
-            ui_thread_,
-            base::BindRepeating(&browser_sync::BrowserSyncClient::
-                                    GetControllerDelegateForModelType,
-                                base::Unretained(sync_client_),
-                                syncer::PRINTERS))));
+    controllers.push_back(
+        CreateModelTypeControllerForModelRunningOnUIThread(syncer::PRINTERS));
   }
   if (!disabled_types.Has(syncer::WIFI_CONFIGURATIONS) &&
       base::FeatureList::IsEnabled(switches::kSyncWifiConfigurations)) {
diff --git a/components/cast_channel/cast_message_util.cc b/components/cast_channel/cast_message_util.cc
index 42ddb52..d6b8fb8 100644
--- a/components/cast_channel/cast_message_util.cc
+++ b/components/cast_channel/cast_message_util.cc
@@ -341,7 +341,7 @@
               Value(EnumToString<CastMessageType,
                                  CastMessageType::kGetAppAvailability>()));
   Value app_id_value(Value::Type::LIST);
-  app_id_value.GetList().push_back(Value(app_id));
+  app_id_value.Append(Value(app_id));
   dict.SetKey("appId", std::move(app_id_value));
   dict.SetKey("requestId", Value(request_id));
 
diff --git a/components/cast_channel/cast_socket_unittest.cc b/components/cast_channel/cast_socket_unittest.cc
index 8942f08..18e879b 100644
--- a/components/cast_channel/cast_socket_unittest.cc
+++ b/components/cast_channel/cast_socket_unittest.cc
@@ -34,6 +34,7 @@
 #include "components/cast_channel/proto/cast_channel.pb.h"
 #include "content/public/test/browser_task_environment.h"
 #include "crypto/rsa_private_key.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/address_list.h"
 #include "net/base/net_errors.h"
 #include "net/cert/pem_tokenizer.h"
@@ -387,7 +388,7 @@
     url_request_context_.set_client_socket_factory(&client_socket_factory_);
     url_request_context_.Init();
     network_context_ = std::make_unique<network::NetworkContext>(
-        nullptr, mojo::MakeRequest(&network_context_ptr_),
+        nullptr, network_context_remote_.BindNewPipeAndPassReceiver(),
         &url_request_context_,
         /*cors_exempt_header_list=*/std::vector<std::string>());
   }
@@ -403,7 +404,7 @@
   content::BrowserTaskEnvironment task_environment_;
   net::TestURLRequestContext url_request_context_;
   std::unique_ptr<network::NetworkContext> network_context_;
-  network::mojom::NetworkContextPtr network_context_ptr_;
+  mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
   Logger* logger_;
   CompleteHandler handler_;
   std::unique_ptr<MockCastSocketObserver> observer_;
diff --git a/components/cloud_devices/common/description_items_inl.h b/components/cloud_devices/common/description_items_inl.h
index 096d366..8ed2fea 100644
--- a/components/cloud_devices/common/description_items_inl.h
+++ b/components/cloud_devices/common/description_items_inl.h
@@ -68,7 +68,7 @@
   for (const Option& option : options_) {
     base::Value option_value(base::Value::Type::DICTIONARY);
     Traits::Save(option, &option_value);
-    options_list->GetList().emplace_back(std::move(option_value));
+    options_list->Append(std::move(option_value));
   }
 }
 
@@ -157,7 +157,7 @@
     if (base::checked_cast<int>(i) == default_idx_)
       option_value.SetKey(json::kKeyIsDefault, base::Value(true));
     Traits::Save(options_[i], &option_value);
-    options_list.GetList().emplace_back(std::move(option_value));
+    options_list.Append(std::move(option_value));
   }
   dict->SetKey(json::kKeyOption, std::move(options_list));
 }
diff --git a/components/cloud_devices/common/printer_description.cc b/components/cloud_devices/common/printer_description.cc
index b2e9e9d..a3cf56c 100644
--- a/components/cloud_devices/common/printer_description.cc
+++ b/components/cloud_devices/common/printer_description.cc
@@ -1323,7 +1323,7 @@
         interval.SetKey(kPageRangeStart, base::Value(option[i].start));
         if (option[i].end < kMaxPageNumber)
           interval.SetKey(kPageRangeEnd, base::Value(option[i].end));
-        list.GetList().emplace_back(std::move(interval));
+        list.Append(std::move(interval));
       }
       dict->SetKey(kPageRangeInterval, std::move(list));
     }
diff --git a/components/content_settings/core/browser/content_settings_policy_provider.cc b/components/content_settings/core/browser/content_settings_policy_provider.cc
index 4e57830..f87f391 100644
--- a/components/content_settings/core/browser/content_settings_policy_provider.cc
+++ b/components/content_settings/core/browser/content_settings_policy_provider.cc
@@ -357,8 +357,7 @@
 
     // Don't pass removed values from |value|, because base::Values read with
     // JSONReader use a shared string buffer. Instead, Clone() here.
-    filters_map[pattern_str].FindKey("filters")->GetList().push_back(
-        filter->Clone());
+    filters_map[pattern_str].FindKey("filters")->Append(filter->Clone());
   }
 
   for (const auto& it : filters_map) {
diff --git a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
index de9c4ca..32f7ce59 100644
--- a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
+++ b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
@@ -169,9 +169,9 @@
 network::mojom::URLLoaderFactory*
 WarmupURLFetcher::GetNetworkServiceURLLoaderFactory(
     const DataReductionProxyServer& proxy_server) {
-  network::mojom::NetworkContextPtr context;
+  context_.reset();
   BindNetworkContext(create_custom_proxy_config_callback_.Run({proxy_server}),
-                     mojo::MakeRequest(&context_), user_agent_);
+                     context_.BindNewPipeAndPassReceiver(), user_agent_);
 
   auto factory_params = network::mojom::URLLoaderFactoryParams::New();
   factory_params->process_id = network::mojom::kBrowserProcessId;
diff --git a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
index 92edc0c..51a1c48d 100644
--- a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
+++ b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
@@ -13,6 +13,7 @@
 #include "base/optional.h"
 #include "base/sequence_checker.h"
 #include "base/timer/timer.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/proxy_server.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 
@@ -130,7 +131,7 @@
 
   CreateCustomProxyConfigCallback create_custom_proxy_config_callback_;
   network::mojom::URLLoaderFactoryPtr url_loader_factory_;
-  network::mojom::NetworkContextPtr context_;
+  mojo::Remote<network::mojom::NetworkContext> context_;
 
   // Callback that should be executed when the fetching of the warmup URL is
   // completed.
diff --git a/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.cc b/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.cc
index a08f307..b8e88b5 100644
--- a/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.cc
+++ b/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.cc
@@ -80,7 +80,7 @@
           celllangs_cached->GetList()[index] =
               GetCellLanguagePairValue(cell.parent(level), language);
         } else {
-          celllangs_cached->GetList().push_back(
+          celllangs_cached->Append(
               GetCellLanguagePairValue(cell.parent(level), language));
         }
       }
diff --git a/components/language/core/browser/fluent_language_model_unittest.cc b/components/language/core/browser/fluent_language_model_unittest.cc
index ff62558..00b2658 100644
--- a/components/language/core/browser/fluent_language_model_unittest.cc
+++ b/components/language/core/browser/fluent_language_model_unittest.cc
@@ -62,8 +62,8 @@
 TEST_F(FluentLanguageModelTest, AllFluent) {
   prefs_->SetString(prefs::kAcceptLanguages, "ja,fr");
   base::ListValue fluent_languages;
-  fluent_languages.GetList().emplace_back("fr");
-  fluent_languages.GetList().emplace_back("ja");
+  fluent_languages.Append("fr");
+  fluent_languages.Append("ja");
   prefs_->Set(prefs::kFluentLanguages, fluent_languages);
 
   FluentLanguageModel model(prefs_.get(), prefs::kAcceptLanguages);
@@ -74,8 +74,8 @@
 TEST_F(FluentLanguageModelTest, OneNonFluent) {
   prefs_->SetString(prefs::kAcceptLanguages, "ja,en,fr");
   base::ListValue fluent_languages;
-  fluent_languages.GetList().emplace_back("fr");
-  fluent_languages.GetList().emplace_back("ja");
+  fluent_languages.Append("fr");
+  fluent_languages.Append("ja");
   prefs_->Set(prefs::kFluentLanguages, fluent_languages);
 
   FluentLanguageModel model(prefs_.get(), prefs::kAcceptLanguages);
@@ -86,7 +86,7 @@
 TEST_F(FluentLanguageModelTest, OneFluent) {
   prefs_->SetString(prefs::kAcceptLanguages, "ja,en,fr");
   base::ListValue fluent_languages;
-  fluent_languages.GetList().emplace_back("ja");
+  fluent_languages.Append("ja");
   prefs_->Set(prefs::kFluentLanguages, fluent_languages);
 
   FluentLanguageModel model(prefs_.get(), prefs::kAcceptLanguages);
diff --git a/components/language/core/browser/language_prefs.cc b/components/language/core/browser/language_prefs.cc
index 769e262..d5e4c09 100644
--- a/components/language/core/browser/language_prefs.cc
+++ b/components/language/core/browser/language_prefs.cc
@@ -63,7 +63,7 @@
   std::string canonical_lang = language;
   language::ToTranslateLanguageSynonym(&canonical_lang);
   ListPrefUpdate update(prefs_, language::prefs::kFluentLanguages);
-  update->GetList().emplace_back(std::move(canonical_lang));
+  update->Append(std::move(canonical_lang));
 }
 
 void LanguagePrefs::ClearFluent(const std::string& language) {
@@ -115,7 +115,7 @@
 #endif
   base::Value language_values(base::Value::Type::LIST);
   for (const std::string& language : languages)
-    language_values.GetList().emplace_back(language);
+    language_values.Append(language);
 
   return language_values;
 }
diff --git a/components/mirroring/service/session.cc b/components/mirroring/service/session.cc
index 93c9d8b..5a80943 100644
--- a/components/mirroring/service/session.cc
+++ b/components/mirroring/service/session.cc
@@ -392,7 +392,8 @@
   DCHECK(resource_provider_);
   mirror_settings_.SetResolutionContraints(max_resolution.width(),
                                            max_resolution.height());
-  resource_provider_->GetNetworkContext(mojo::MakeRequest(&network_context_));
+  resource_provider_->GetNetworkContext(
+      network_context_.BindNewPipeAndPassReceiver());
 
   if (session_params->type != mojom::SessionType::AUDIO_ONLY &&
       io_task_runner) {
diff --git a/components/mirroring/service/session.h b/components/mirroring/service/session.h
index 34a3543..8444dab 100644
--- a/components/mirroring/service/session.h
+++ b/components/mirroring/service/session.h
@@ -25,6 +25,7 @@
 #include "media/mojo/mojom/video_encode_accelerator.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 
 namespace media {
@@ -162,7 +163,7 @@
 
   MessageDispatcher message_dispatcher_;
 
-  network::mojom::NetworkContextPtr network_context_;
+  mojo::Remote<network::mojom::NetworkContext> network_context_;
 
   base::Optional<SessionMonitor> session_monitor_;
 
diff --git a/components/mirroring/service/udp_socket_client_unittest.cc b/components/mirroring/service/udp_socket_client_unittest.cc
index 623936a..ae84a33 100644
--- a/components/mirroring/service/udp_socket_client_unittest.cc
+++ b/components/mirroring/service/udp_socket_client_unittest.cc
@@ -17,7 +17,7 @@
 #include "components/mirroring/service/fake_network_service.h"
 #include "media/cast/net/cast_transport_config.h"
 #include "media/cast/test/utility/net_utility.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/ip_endpoint.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -31,9 +31,9 @@
  public:
   UdpSocketClientTest() {
     network_context_ = std::make_unique<MockNetworkContext>(
-        mojo::MakeRequest(&network_context_ptr_));
+        network_context_remote_.BindNewPipeAndPassReceiver());
     udp_transport_client_ = std::make_unique<UdpSocketClient>(
-        media::cast::test::GetFreeLocalPort(), network_context_ptr_.get(),
+        media::cast::test::GetFreeLocalPort(), network_context_remote_.get(),
         base::OnceClosure());
   }
 
@@ -48,7 +48,7 @@
 
  protected:
   base::test::TaskEnvironment task_environment_;
-  network::mojom::NetworkContextPtr network_context_ptr_;
+  mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
   std::unique_ptr<MockNetworkContext> network_context_;
   std::unique_ptr<UdpSocketClient> udp_transport_client_;
   std::unique_ptr<Packet> received_packet_;
diff --git a/components/net_log/net_export_file_writer_unittest.cc b/components/net_log/net_export_file_writer_unittest.cc
index caaf54a..28f43d4 100644
--- a/components/net_log/net_export_file_writer_unittest.cc
+++ b/components/net_log/net_export_file_writer_unittest.cc
@@ -21,6 +21,7 @@
 #include "base/test/task_environment.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "net/base/network_change_notifier.h"
 #include "net/base/test_completion_callback.h"
@@ -268,7 +269,8 @@
     params->initial_proxy_config =
         net::ProxyConfigWithAnnotation::CreateDirect();
     network_context_ = std::make_unique<network::NetworkContext>(
-        network_service_.get(), mojo::MakeRequest(&network_context_ptr_),
+        network_service_.get(),
+        network_context_remote_.BindNewPipeAndPassReceiver(),
         std::move(params));
 
     // Override |file_writer_|'s default-log-base-directory-getter to
@@ -435,7 +437,7 @@
   TestStateObserver* test_state_observer() { return &test_state_observer_; }
 
   network::mojom::NetworkContext* network_context() {
-    return network_context_ptr_.get();
+    return network_context_remote_.get();
   }
 
  private:
@@ -444,10 +446,10 @@
   std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
   std::unique_ptr<network::NetworkService> network_service_;
 
-  network::mojom::NetworkContextPtr network_context_ptr_;
+  mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
   std::unique_ptr<network::NetworkContext> network_context_;
 
-  // |file_writer_| is initialized after |network_context_ptr_| since
+  // |file_writer_| is initialized after |network_context_remote_| since
   // |file_writer_| destructor can talk to mojo objects owned by
   // |network_context_|.
   NetExportFileWriter file_writer_;
diff --git a/components/ntp_snippets/remote/json_request.cc b/components/ntp_snippets/remote/json_request.cc
index 0dc2ecd..09059e1 100644
--- a/components/ntp_snippets/remote/json_request.cc
+++ b/components/ntp_snippets/remote/json_request.cc
@@ -351,8 +351,7 @@
     exclusive_category_parameters.SetInteger("numSuggestions",
                                              params_.count_to_fetch);
     base::ListValue category_parameters;
-    category_parameters.GetList().push_back(
-        std::move(exclusive_category_parameters));
+    category_parameters.Append(std::move(exclusive_category_parameters));
     request->SetKey("categoryParameters", std::move(category_parameters));
   }
 
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index b6752a5..e2619e98 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -163,6 +163,8 @@
     "password_sync_util.h",
     "password_ui_utils.cc",
     "password_ui_utils.h",
+    "possible_username_data.cc",
+    "possible_username_data.h",
     "psl_matching_helper.cc",
     "psl_matching_helper.h",
     "site_affiliation/asset_link_data.cc",
@@ -525,6 +527,7 @@
     "password_store_unittest.cc",
     "password_sync_util_unittest.cc",
     "password_ui_utils_unittest.cc",
+    "possible_username_data_unittest.cc",
     "psl_matching_helper_unittest.cc",
     "site_affiliation/asset_link_data_unittest.cc",
     "sql_table_builder_unittest.cc",
diff --git a/components/password_manager/core/browser/hash_password_manager.cc b/components/password_manager/core/browser/hash_password_manager.cc
index 9a8ee08..4e5fae3 100644
--- a/components/password_manager/core/browser/hash_password_manager.cc
+++ b/components/password_manager/core/browser/hash_password_manager.cc
@@ -355,14 +355,14 @@
     }
   }
   if (replace_old_entry) {
-    update->GetList().push_back(std::move(encrypted_password_hash_entry));
+    update->Append(std::move(encrypted_password_hash_entry));
     return true;
   }
 
   if (update->GetList().size() >= kMaxPasswordHashDataDictSize)
     RemoveOldestSignInPasswordHashData(&update->GetList());
 
-  update->GetList().push_back(std::move(encrypted_password_hash_entry));
+  update->Append(std::move(encrypted_password_hash_entry));
   return true;
 }
 
diff --git a/components/password_manager/core/browser/hsts_query_unittest.cc b/components/password_manager/core/browser/hsts_query_unittest.cc
index 2833a64..98a9b11 100644
--- a/components/password_manager/core/browser/hsts_query_unittest.cc
+++ b/components/password_manager/core/browser/hsts_query_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/url_request/url_request_test_util.h"
 #include "services/network/network_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -63,7 +64,7 @@
             base::ThreadTaskRunnerHandle::Get())),
         network_context_(std::make_unique<network::NetworkContext>(
             nullptr,
-            mojo::MakeRequest(&network_context_pipe_),
+            network_context_remote_.BindNewPipeAndPassReceiver(),
             request_context_->GetURLRequestContext(),
             /*cors_exempt_header_list=*/std::vector<std::string>())) {}
 
@@ -73,7 +74,7 @@
   // Used by request_context_.
   base::test::SingleThreadTaskEnvironment task_environment_;
   scoped_refptr<net::TestURLRequestContextGetter> request_context_;
-  network::mojom::NetworkContextPtr network_context_pipe_;
+  mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
   std::unique_ptr<network::NetworkContext> network_context_;
 
   DISALLOW_COPY_AND_ASSIGN(HSTSQueryTest);
diff --git a/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc b/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc
index 94a7cc9..83e88ab 100644
--- a/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc
+++ b/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc
@@ -17,6 +17,7 @@
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/url_request/url_request_test_util.h"
 #include "services/network/network_context.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -174,9 +175,9 @@
 
   auto request_context = base::MakeRefCounted<net::TestURLRequestContextGetter>(
       base::ThreadTaskRunnerHandle::Get());
-  network::mojom::NetworkContextPtr network_context_pipe;
+  mojo::Remote<network::mojom::NetworkContext> network_context_remote;
   auto network_context = std::make_unique<network::NetworkContext>(
-      nullptr, mojo::MakeRequest(&network_context_pipe),
+      nullptr, network_context_remote.BindNewPipeAndPassReceiver(),
       request_context->GetURLRequestContext(),
       /*cors_exempt_header_list=*/std::vector<std::string>());
 
@@ -201,13 +202,13 @@
   HttpCredentialCleaner cleaner(
       store_,
       base::BindLambdaForTesting([&]() -> network::mojom::NetworkContext* {
-        // This needs to be network_context_pipe.get() and
+        // This needs to be network_context_remote.get() and
         // not network_context.get() to make HSTS queries asynchronous, which
         // is what the progress tracking logic in HttpMetricsMigrationReporter
         // assumes.  This also matches reality, since
         // StoragePartition::GetNetworkContext will return a mojo pipe
         // even in the in-process case.
-        return network_context_pipe.get();
+        return network_context_remote.get();
       }),
       &prefs);
   EXPECT_CALL(observer, CleaningCompleted);
@@ -282,9 +283,9 @@
     auto request_context =
         base::MakeRefCounted<net::TestURLRequestContextGetter>(
             base::ThreadTaskRunnerHandle::Get());
-    network::mojom::NetworkContextPtr network_context_pipe;
+    mojo::Remote<network::mojom::NetworkContext> network_context_remote;
     auto network_context = std::make_unique<network::NetworkContext>(
-        nullptr, mojo::MakeRequest(&network_context_pipe),
+        nullptr, network_context_remote.BindNewPipeAndPassReceiver(),
         request_context->GetURLRequestContext(),
         /*cors_exempt_header_list=*/std::vector<std::string>());
 
@@ -292,13 +293,13 @@
     HttpCredentialCleaner cleaner(
         password_store,
         base::BindLambdaForTesting([&]() -> network::mojom::NetworkContext* {
-          // This needs to be network_context_pipe.get() and
+          // This needs to be network_context_remote.get() and
           // not network_context.get() to make HSTS queries asynchronous, which
           // is what the progress tracking logic in HttpMetricsMigrationReporter
           // assumes.  This also matches reality, since
           // StoragePartition::GetNetworkContext will return a mojo pipe
           // even in the in-process case.
-          return network_context_pipe.get();
+          return network_context_remote.get();
         }),
         &prefs);
     EXPECT_TRUE(cleaner.NeedsCleaning());
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 5cdc2e3..c313587 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -28,6 +28,7 @@
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_driver.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/password_manager/core/browser/possible_username_data.h"
 #include "components/password_manager/core/browser/statistics_table.h"
 
 using autofill::FormData;
@@ -625,7 +626,8 @@
 
 bool PasswordFormManager::ProvisionallySave(
     const FormData& submitted_form,
-    const PasswordManagerDriver* driver) {
+    const PasswordManagerDriver* driver,
+    const PossibleUsernameData* possible_username) {
   DCHECK(DoesManage(submitted_form, driver));
 
   std::unique_ptr<PasswordForm> parsed_submitted_form =
@@ -644,6 +646,13 @@
   is_submitted_ = true;
   CalculateFillingAssistanceMetric(submitted_form);
 
+  if (parsed_submitted_form_->username_value.empty() && possible_username &&
+      IsPossibleUsernameValid(*possible_username,
+                              parsed_submitted_form_->signon_realm,
+                              base::Time::Now())) {
+    parsed_submitted_form_->username_value = possible_username->value;
+  }
+
   CreatePendingCredentials();
   return true;
 }
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h
index 0451bcc..ee296dd 100644
--- a/components/password_manager/core/browser/password_form_manager.h
+++ b/components/password_manager/core/browser/password_form_manager.h
@@ -33,6 +33,7 @@
 class PasswordGenerationState;
 class PasswordManagerClient;
 class PasswordManagerDriver;
+struct PossibleUsernameData;
 
 // This class helps with filling the observed form and with saving/updating the
 // stored information about it. It is aimed to replace PasswordFormManager and
@@ -87,8 +88,12 @@
   // |submitted_form| and |driver|) then saves |submitted_form| to
   // |submitted_form_| field, sets |is_submitted| = true and returns true.
   // Otherwise returns false.
+  // If as a result of the parsing the username is not found, the
+  // |possible_username->value| is chosen as username if it looks like an
+  // username and came from the same domain as |submitted_form|.
   bool ProvisionallySave(const autofill::FormData& submitted_form,
-                         const PasswordManagerDriver* driver);
+                         const PasswordManagerDriver* driver,
+                         const PossibleUsernameData* possible_username);
 
   // If |submitted_form| is managed by *this then saves |submitted_form| to
   // |submitted_form_| field, sets |is_submitted| = true and returns true.
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index 3c017d7..539abc58 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -24,6 +24,7 @@
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
 #include "components/password_manager/core/browser/password_manager_util.h"
 #include "components/password_manager/core/browser/password_store.h"
+#include "components/password_manager/core/browser/possible_username_data.h"
 #include "components/password_manager/core/browser/stub_form_saver.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
 #include "components/password_manager/core/browser/stub_password_manager_driver.h"
@@ -560,7 +561,8 @@
 
 TEST_F(PasswordFormManagerTest, SetSubmitted) {
   EXPECT_FALSE(form_manager_->is_submitted());
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
   EXPECT_TRUE(form_manager_->is_submitted());
 
   FormData another_form = submitted_form_;
@@ -568,13 +570,15 @@
 #if !defined(OS_IOS)
   // |another_form| is managed because the same |unique_renderer_id| as
   // |observed_form_|.
-  EXPECT_TRUE(form_manager_->ProvisionallySave(another_form, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(another_form, &driver_, nullptr));
   EXPECT_TRUE(form_manager_->is_submitted());
 #endif
 }
 
 TEST_F(PasswordFormManagerTest, SetSubmittedMultipleTimes) {
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
   EXPECT_TRUE(form_manager_->is_submitted());
 
   // Make the submitted form to be invalid password form.
@@ -582,7 +586,8 @@
 
   // Expect that |form_manager_| is still in submitted state because the first
   // time the submited form was valid.
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
   EXPECT_TRUE(form_manager_->is_submitted());
   EXPECT_TRUE(form_manager_->GetSubmittedForm());
 }
@@ -659,7 +664,8 @@
 
   const base::Time kNow = base::Time::Now();
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
 
   const PasswordForm& pending_credentials =
       form_manager_->GetPendingCredentials();
@@ -675,7 +681,8 @@
   TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
   SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
   CheckPendingCredentials(parsed_submitted_form_,
                           form_manager_->GetPendingCredentials());
   EXPECT_EQ(UserAction::kOverrideUsernameAndPassword,
@@ -699,7 +706,8 @@
   for (bool is_incognito : {false, true}) {
     EXPECT_CALL(client_, IsIncognito).WillOnce(Return(is_incognito));
     form_manager_->Fill();
-    EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+    EXPECT_TRUE(
+        form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
     CheckPendingCredentials(/* expected */ saved_match_,
                             form_manager_->GetPendingCredentials());
     EXPECT_EQ(is_incognito ? UserAction::kChoose : UserAction::kNone,
@@ -724,7 +732,8 @@
   submitted_form_.fields[kPasswordFieldIndex].value =
       saved_match_.password_value;
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
   CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
   EXPECT_EQ(UserAction::kChoosePslMatch,
             form_manager_->GetMetricsRecorder()->GetUserAction());
@@ -742,7 +751,8 @@
   submitted_form_.fields[kUsernameFieldIndex].value =
       saved_match_.username_value;
   submitted_form_.fields[kPasswordFieldIndex].value = expected.password_value;
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
   CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
   EXPECT_EQ(UserAction::kOverridePassword,
             form_manager_->GetMetricsRecorder()->GetUserAction());
@@ -761,7 +771,8 @@
   PasswordForm expected = saved_match_;
   expected.password_value = ASCIIToUTF16("verystrongpassword");
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form, &driver_, nullptr));
   CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
   EXPECT_EQ(UserAction::kOverridePassword,
             form_manager_->GetMetricsRecorder()->GetUserAction());
@@ -782,7 +793,8 @@
   PasswordForm expected = saved_match_;
   expected.password_value = ASCIIToUTF16("verystrongpassword");
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form, &driver_, nullptr));
   CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
 }
 
@@ -801,7 +813,8 @@
 
   form_manager_->ProcessServerPredictions(predictions);
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(anonymous_signup, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(anonymous_signup, &driver_, nullptr));
   EXPECT_EQ(ASCIIToUTF16("a password"),
             form_manager_->GetPendingCredentials().password_value);
 }
@@ -821,7 +834,7 @@
   submitted_form.fields[kPasswordFieldIndex].value = ASCIIToUTF16("password");
 
   // Expect no crash.
-  form_manager_->ProvisionallySave(submitted_form, &driver_);
+  form_manager_->ProvisionallySave(submitted_form, &driver_, nullptr);
 }
 
 TEST_F(PasswordFormManagerTest, IsEqualToSubmittedForm) {
@@ -837,7 +850,8 @@
   // No submitted form yet.
   EXPECT_FALSE(form_manager_->IsEqualToSubmittedForm(submitted_form));
 
-  ASSERT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+  ASSERT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form, &driver_, nullptr));
 
   observed_form_.unique_renderer_id += 10;
   observed_form_.fields.clear();
@@ -861,7 +875,8 @@
   submitted_form.fields[kUsernameFieldIndex].value = new_username;
   submitted_form.fields[kPasswordFieldIndex].value = new_password;
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form, &driver_, nullptr));
   EXPECT_TRUE(form_manager_->IsNewLogin());
 
   MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
@@ -910,7 +925,8 @@
   submitted_form.fields[kPasswordFieldIndex].value =
       psl_saved_match_.password_value;
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form, &driver_, nullptr));
   EXPECT_TRUE(form_manager_->IsNewLogin());
   EXPECT_TRUE(form_manager_->IsPendingCredentialsPublicSuffixMatch());
 
@@ -946,7 +962,8 @@
   submitted_form.fields[kUsernameFieldIndex].value = username;
   submitted_form.fields[kPasswordFieldIndex].value = new_password;
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form, &driver_, nullptr));
   EXPECT_FALSE(form_manager_->IsNewLogin());
   EXPECT_TRUE(form_manager_->IsPasswordUpdate());
 
@@ -981,7 +998,8 @@
   base::string16 new_password = saved_match_.password_value + ASCIIToUTF16("1");
   submitted_form.fields[1].value = new_password;
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form, &driver_, nullptr));
   EXPECT_FALSE(form_manager_->IsNewLogin());
   EXPECT_TRUE(form_manager_->IsPasswordUpdate());
 
@@ -1017,7 +1035,8 @@
     auto new_password = saved_match_.password_value + ASCIIToUTF16("1");
     submitted_form.fields[1].value = new_password;
 
-    EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+    EXPECT_TRUE(
+        form_manager_->ProvisionallySave(submitted_form, &driver_, nullptr));
 
     std::map<base::string16, autofill::ServerFieldType> expected_types;
     expected_types[ASCIIToUTF16("password")] = autofill::PASSWORD;
@@ -1047,7 +1066,7 @@
   TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
   fetcher_->NotifyFetchCompleted();
 
-  form_manager_->ProvisionallySave(submitted_form_, &driver_);
+  form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr);
 
   base::string16 new_username =
       parsed_submitted_form_.username_value + ASCIIToUTF16("1");
@@ -1070,7 +1089,7 @@
       ASCIIToUTF16("automatically_chosen_username");
   submitted_form_.fields[0].value = user_chosen_username;
   submitted_form_.fields[1].value = automatically_chosen_username;
-  form_manager_->ProvisionallySave(submitted_form_, &driver_);
+  form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr);
 
   EXPECT_EQ(automatically_chosen_username,
             form_manager_->GetPendingCredentials().username_value);
@@ -1099,7 +1118,7 @@
   TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
   SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
 
-  form_manager_->ProvisionallySave(submitted_form_, &driver_);
+  form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr);
 
   base::string16 new_username = saved_match_.username_value;
   base::string16 expected_password = parsed_submitted_form_.password_value;
@@ -1117,7 +1136,7 @@
   TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
   fetcher_->NotifyFetchCompleted();
 
-  form_manager_->ProvisionallySave(submitted_form_, &driver_);
+  form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr);
 
   base::string16 new_password =
       parsed_submitted_form_.password_value + ASCIIToUTF16("1");
@@ -1145,7 +1164,7 @@
   // Emulate submitting form with known username and different password.
   submitted_form_.fields[kUsernameFieldIndex].value =
       saved_match_.username_value;
-  form_manager_->ProvisionallySave(submitted_form_, &driver_);
+  form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr);
 
   // The user changes password to already saved one.
   base::string16 password = saved_match_.password_value;
@@ -1166,7 +1185,7 @@
   base::string16 pin = ASCIIToUTF16("pin");
   form.fields[0].value = password;
   form.fields[1].value = pin;
-  form_manager_->ProvisionallySave(form, &driver_);
+  form_manager_->ProvisionallySave(form, &driver_, nullptr);
 
   // Check that a second password field is chosen for saving.
   EXPECT_EQ(pin, form_manager_->GetPendingCredentials().password_value);
@@ -1222,7 +1241,8 @@
   fetcher_->NotifyFetchCompleted();
 
   // Provisionally save in order to create pending credentials.
-  ASSERT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+  ASSERT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
 
   std::unique_ptr<PasswordFormManager> cloned_manager = form_manager_->Clone();
 
@@ -1313,7 +1333,8 @@
   ukm::TestAutoSetUkmRecorder test_ukm_recorder;
   SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
 
   // Destroy the form manager to destroy the UKM recorder it owns. The recorder
   // only records metrics in its destructor.
@@ -1337,7 +1358,8 @@
 
   FormData malformed_form = submitted_form_;
   malformed_form.fields.clear();
-  EXPECT_FALSE(form_manager_->ProvisionallySave(malformed_form, &driver_));
+  EXPECT_FALSE(
+      form_manager_->ProvisionallySave(malformed_form, &driver_, nullptr));
 
   // Destroy the form manager to destroy the UKM recorder it owns. The recorder
   // only records metrics in its destructor.
@@ -1482,7 +1504,8 @@
       .WillOnce(SaveArg<0>(&saved_form));
   EXPECT_CALL(client_, UpdateFormManagers());
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
   form_manager_->Save();
 
   EXPECT_EQ(submitted_form_.fields[kUsernameFieldIndex].value,
@@ -1715,7 +1738,8 @@
   submitted_form.fields[kUsernameFieldIndex].value = username;
   submitted_form.fields[kPasswordFieldIndex].value = new_password;
 
-  EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+  EXPECT_TRUE(
+      form_manager_->ProvisionallySave(submitted_form, &driver_, nullptr));
 
   MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
   PasswordForm updated_form;
@@ -1758,7 +1782,7 @@
 
   base::HistogramTester histogram_tester;
   //  Simulate successful submission.
-  form_manager_->ProvisionallySave(submitted_form_, &driver_);
+  form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr);
   form_manager_->GetMetricsRecorder()->LogSubmitPassed();
 
   form_manager_.reset();
@@ -1775,7 +1799,8 @@
     CreateFormManager(observed_form_);
     fetcher_->NotifyFetchCompleted();
 
-    EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+    EXPECT_TRUE(
+        form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
 
     if (password_revealed)
       form_manager_->OnPasswordsRevealed();
@@ -1802,7 +1827,8 @@
       form_manager_->SetGenerationPopupWasShown(
           true /*generation_popup_was_shown*/, false /*is_manual_generation*/);
     }
-    EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+    EXPECT_TRUE(
+        form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
 
     EXPECT_CALL(
         mock_autofill_download_manager_,
@@ -1827,7 +1853,8 @@
       form_manager_->SetGenerationPopupWasShown(
           true /*generation_popup_was_shown*/, false /*is_manual_generation*/);
     }
-    EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+    EXPECT_TRUE(
+        form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr));
 
     EXPECT_CALL(
         mock_autofill_download_manager_,
@@ -2016,6 +2043,48 @@
 
 #endif  // defined(OS_IOS)
 
+// Tests that username is taken during username first flow.
+TEST_F(PasswordFormManagerTest, UsernameFirstFlow) {
+  TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+  CreateFormManager(observed_form_only_password_fields_);
+  fetcher_->NotifyFetchCompleted();
+  const base::string16 possible_username = ASCIIToUTF16("possible_username");
+  PossibleUsernameData possible_username_data(
+      saved_match_.signon_realm, 1u /* renderer_id */, possible_username,
+      base::Time::Now());
+
+  FormData submitted_form = observed_form_only_password_fields_;
+  submitted_form.fields[0].value = ASCIIToUTF16("strongpassword");
+
+  ASSERT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_,
+                                               &possible_username_data));
+
+  // Check that a username is chosen from |possible_username_data|.
+  EXPECT_EQ(possible_username,
+            form_manager_->GetPendingCredentials().username_value);
+}
+
+// Tests that username is not taken when a possible username is not valid.
+TEST_F(PasswordFormManagerTest, UsernameFirstFlowDifferentDomains) {
+  TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+  CreateFormManager(observed_form_only_password_fields_);
+  fetcher_->NotifyFetchCompleted();
+  base::string16 possible_username = ASCIIToUTF16("possible_username");
+  PossibleUsernameData possible_username_data(
+      "https://another.domain.com", 1u /* renderer_id */, possible_username,
+      base::Time::Now());
+
+  FormData submitted_form = observed_form_only_password_fields_;
+  submitted_form.fields[0].value = ASCIIToUTF16("strongpassword");
+
+  ASSERT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_,
+                                               &possible_username_data));
+
+  // |possible_username_data| has different domain then |submitted_form|. Check
+  // that no username is chosen.
+  EXPECT_TRUE(form_manager_->GetPendingCredentials().username_value.empty());
+}
+
 }  // namespace
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index c2c9de7..f65a24c 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -419,11 +419,11 @@
 }
 
 void PasswordManager::OnUserModifiedNonPasswordField(
-    password_manager::PasswordManagerDriver* driver,
+    PasswordManagerDriver* driver,
     int32_t renderer_id,
     const base::string16& value) {
-  // TODO(https://crbug.com/959776): Implemented processing |value| as possible
-  // username for username first flow.
+  possible_username_.emplace(GetSignonRealm(driver->GetLastCommittedURL()),
+                             renderer_id, value, base::Time::Now());
 }
 
 void PasswordManager::ShowManualFallbackForSaving(
@@ -624,8 +624,12 @@
     return nullptr;
   }
 
-  if (!matched_manager->ProvisionallySave(submitted_form, driver))
+  const PossibleUsernameData* possible_username =
+      possible_username_ ? &possible_username_.value() : nullptr;
+  if (!matched_manager->ProvisionallySave(submitted_form, driver,
+                                          possible_username)) {
     return nullptr;
+  }
 
   // Set all other form managers to no submission state.
   for (const auto& manager : form_managers_) {
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h
index 28dbf3f..b08c907 100644
--- a/components/password_manager/core/browser/password_manager.h
+++ b/components/password_manager/core/browser/password_manager.h
@@ -24,6 +24,7 @@
 #include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h"
 #include "components/password_manager/core/browser/leak_detection_delegate.h"
 #include "components/password_manager/core/browser/password_manager_metrics_recorder.h"
+#include "components/password_manager/core/browser/possible_username_data.h"
 
 class PrefRegistrySimple;
 
@@ -45,6 +46,7 @@
 class PasswordFormManagerInterface;
 class PasswordManagerMetricsRecorder;
 class PasswordFormManager;
+struct PossibleUsernameData;
 
 // Per-tab password manager. Handles creation and management of UI elements,
 // receiving password form data from the renderer and managing the password
@@ -114,10 +116,9 @@
   // Called when a user changed a value in a non-password field. The field is in
   // a frame corresponding to |driver| and has a renderer id |renderer_id|.
   // |value| is the current value of the field.
-  void OnUserModifiedNonPasswordField(
-      password_manager::PasswordManagerDriver* driver,
-      int32_t renderer_id,
-      const base::string16& value);
+  void OnUserModifiedNonPasswordField(PasswordManagerDriver* driver,
+                                      int32_t renderer_id,
+                                      const base::string16& value);
 
   // Handles a request to show manual fallback for password saving, i.e. the
   // omnibox icon with the anchored hidden prompt.
@@ -340,7 +341,9 @@
 #if !defined(OS_IOS)
   // Helper for making the requests on leak detection.
   LeakDetectionDelegate leak_delegate_;
+
 #endif  // !defined(OS_IOS)
+  base::Optional<PossibleUsernameData> possible_username_;
 
   DISALLOW_COPY_AND_ASSIGN(PasswordManager);
 };
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index d17e9d0..77b2051 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -194,6 +194,7 @@
                void(const autofill::FormsPredictionsMap&));
   MOCK_METHOD0(GetPasswordManager, PasswordManager*());
   MOCK_METHOD0(GetPasswordAutofillManager, PasswordAutofillManager*());
+  MOCK_CONST_METHOD0(GetLastCommittedURL, const GURL&());
 };
 
 // Invokes the password store consumer with a single copy of |form|.
@@ -3281,4 +3282,46 @@
   EXPECT_EQ(password_field_id, form_generation_data.new_password_renderer_id);
 #endif
 }
+
+// Checks that username is saved on username first flow.
+TEST_F(PasswordManagerTest, UsernameFirstFlow) {
+  EXPECT_CALL(*store_, GetLogins(_, _))
+      .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
+
+  PasswordForm form(MakeSimpleFormWithOnlyPasswordField());
+  // Simulate the user typed a username in username form.
+  const base::string16 username = ASCIIToUTF16("username1");
+  EXPECT_CALL(driver_, GetLastCommittedURL()).WillOnce(ReturnRef(form.origin));
+  manager()->OnUserModifiedNonPasswordField(&driver_, 1001 /* renderer_id */,
+                                            username /* value */);
+
+  // Simulate that a form which contains only 1 field which is password is added
+  // to the page.
+  manager()->OnPasswordFormsParsed(&driver_, {form} /* observed */);
+
+  EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
+      .WillRepeatedly(Return(true));
+
+  // Simulate that the user typed password and submitted the password form.
+  const base::string16 password = ASCIIToUTF16("uniquepassword");
+  form.form_data.fields[0].value = password;
+  OnPasswordFormSubmitted(form);
+
+  std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
+  EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
+      .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
+
+  // Simlates successful submission.
+  manager()->OnPasswordFormsRendered(&driver_, {} /* observed */, true);
+
+  // Simulate saving the form, as if the info bar was accepted.
+  PasswordForm saved_form;
+  EXPECT_CALL(*store_, AddLogin(_)).WillOnce(SaveArg<0>(&saved_form));
+  ASSERT_TRUE(form_manager_to_save);
+  form_manager_to_save->Save();
+
+  EXPECT_EQ(username, saved_form.username_value);
+  EXPECT_EQ(password, saved_form.password_value);
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/possible_username_data.cc b/components/password_manager/core/browser/possible_username_data.cc
new file mode 100644
index 0000000..26d3bdb
--- /dev/null
+++ b/components/password_manager/core/browser/possible_username_data.cc
@@ -0,0 +1,49 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/possible_username_data.h"
+
+#include "base/strings/string_util.h"
+
+using base::char16;
+using base::TimeDelta;
+
+namespace password_manager {
+
+PossibleUsernameData::PossibleUsernameData(std::string signon_realm,
+                                           int32_t renderer_id,
+                                           base::string16 value,
+                                           base::Time last_change)
+    : signon_realm(std::move(signon_realm)),
+      renderer_id(renderer_id),
+      value(std::move(value)),
+      last_change(last_change) {}
+PossibleUsernameData::~PossibleUsernameData() = default;
+
+bool IsPossibleUsernameValid(const PossibleUsernameData& possible_username,
+                             const std::string& submitted_signon_realm,
+                             const base::Time now) {
+  if (submitted_signon_realm != possible_username.signon_realm)
+    return false;
+  // The goal is to avoid false positives in considering which strings might be
+  // username. In the initial version of the username first flow it is better to
+  // be conservative in that.
+  // TODO(https://crbug.com/959776): Reconsider allowing non-ascii symbols in
+  // username for the username first flow.
+  if (!base::IsStringASCII(possible_username.value))
+    return false;
+  for (char16 c : possible_username.value) {
+    if (base::IsUnicodeWhitespace(c))
+      return false;
+  }
+
+  if (now - possible_username.last_change >
+      kMaxDelayBetweenTypingUsernameAndSubmission) {
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace password_manager
diff --git a/components/password_manager/core/browser/possible_username_data.h b/components/password_manager/core/browser/possible_username_data.h
new file mode 100644
index 0000000..eb87b04
--- /dev/null
+++ b/components/password_manager/core/browser/possible_username_data.h
@@ -0,0 +1,47 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_POSSIBLE_USERNAME_DATA_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_POSSIBLE_USERNAME_DATA_H_
+
+#include <string>
+
+#include "base/strings/string16.h"
+#include "base/time/time.h"
+
+namespace password_manager {
+
+// The maximum time between the user typed in a text field and subsequent
+// submission of the password form, such that the typed value is considered to
+// be possible to be username.
+constexpr base::TimeDelta kMaxDelayBetweenTypingUsernameAndSubmission =
+    base::TimeDelta::FromSeconds(60);
+
+// Contains information that the user typed in a text field. It might be the
+// username during username first flow.
+struct PossibleUsernameData {
+  PossibleUsernameData(std::string signon_realm,
+                       int32_t renderer_id,
+                       base::string16 value,
+                       base::Time last_change);
+  ~PossibleUsernameData();
+
+  std::string signon_realm;
+  int32_t renderer_id;
+  base::string16 value;
+  base::Time last_change;
+};
+
+// Checks that |possible_username| might represent an username:
+// 1.|possible_username.signon_realm| == |submitted_signon_realm|
+// 2.|possible_username.value| does not have whitespaces and non-ASCII symbols.
+// 3.|possible_username.value.last_change| was not more than 60 seconds before
+// now.
+bool IsPossibleUsernameValid(const PossibleUsernameData& possible_username,
+                             const std::string& submitted_signon_realm,
+                             const base::Time now);
+
+}  // namespace password_manager
+
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_POSSIBLE_USERNAME_DATA_H_
diff --git a/components/password_manager/core/browser/possible_username_data_unittest.cc b/components/password_manager/core/browser/possible_username_data_unittest.cc
new file mode 100644
index 0000000..28039fe
--- /dev/null
+++ b/components/password_manager/core/browser/possible_username_data_unittest.cc
@@ -0,0 +1,85 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/possible_username_data.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::ASCIIToUTF16;
+using base::Time;
+using base::TimeDelta;
+
+namespace password_manager {
+
+namespace {
+
+class IsPossibleUsernameValidTest : public testing::Test {
+ public:
+  IsPossibleUsernameValidTest()
+      : possible_username_data_(
+            "https://example.com/" /* submitted_signon_realm */,
+            1u /* renderer_id */,
+            ASCIIToUTF16("username") /* value */,
+            base::Time::Now() /* last_change */) {}
+
+ protected:
+  PossibleUsernameData possible_username_data_;
+};
+
+TEST_F(IsPossibleUsernameValidTest, Valid) {
+  EXPECT_TRUE(IsPossibleUsernameValid(possible_username_data_,
+                                      possible_username_data_.signon_realm,
+                                      possible_username_data_.last_change));
+}
+
+// Check that if time delta between last change and submission is more than 60
+// seconds, than data is invalid.
+TEST_F(IsPossibleUsernameValidTest, TimeDeltaBeforeLastChangeAndSubmission) {
+  Time valid_submission_time = possible_username_data_.last_change +
+                               kMaxDelayBetweenTypingUsernameAndSubmission;
+  Time invalid_submission_time =
+      valid_submission_time + TimeDelta::FromSeconds(1);
+  EXPECT_TRUE(IsPossibleUsernameValid(possible_username_data_,
+                                      possible_username_data_.signon_realm,
+                                      valid_submission_time));
+  EXPECT_FALSE(IsPossibleUsernameValid(possible_username_data_,
+                                       possible_username_data_.signon_realm,
+                                       invalid_submission_time));
+}
+
+TEST_F(IsPossibleUsernameValidTest, SignonRealm) {
+  EXPECT_FALSE(IsPossibleUsernameValid(possible_username_data_,
+                                       "https://m.example.com/",
+                                       possible_username_data_.last_change));
+
+  EXPECT_FALSE(IsPossibleUsernameValid(possible_username_data_,
+                                       "https://google.com/",
+                                       possible_username_data_.last_change));
+}
+
+TEST_F(IsPossibleUsernameValidTest, PossibleUsernameValue) {
+  PossibleUsernameData possible_username_data = possible_username_data_;
+
+  // White spaces are not allowed in username.
+  possible_username_data.value = ASCIIToUTF16("user name");
+  EXPECT_FALSE(IsPossibleUsernameValid(possible_username_data,
+                                       possible_username_data.signon_realm,
+                                       possible_username_data.last_change));
+
+  // New lines are not allowed in username.
+  possible_username_data.value = ASCIIToUTF16("user\nname");
+  EXPECT_FALSE(IsPossibleUsernameValid(possible_username_data,
+                                       possible_username_data.signon_realm,
+                                       possible_username_data.last_change));
+
+  // Digits and special characters are ok.
+  possible_username_data.value = ASCIIToUTF16("User_name1234!+&%#\'\"@");
+  EXPECT_TRUE(IsPossibleUsernameValid(possible_username_data,
+                                      possible_username_data.signon_realm,
+                                      possible_username_data.last_change));
+}
+
+}  // namespace
+}  // namespace password_manager
diff --git a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
index 6f3b5c0..9024e60 100644
--- a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
+++ b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
@@ -135,7 +135,7 @@
     fetcher_.SetNonFederated(matches);
     fetcher_.NotifyFetchCompleted();
 
-    form_manager_.ProvisionallySave(pending_.form_data, &driver_);
+    form_manager_.ProvisionallySave(pending_.form_data, &driver_, nullptr);
   }
 
  protected:
diff --git a/components/policy/content/policy_blacklist_navigation_throttle_unittest.cc b/components/policy/content/policy_blacklist_navigation_throttle_unittest.cc
index 43540a4..24c9e3e 100644
--- a/components/policy/content/policy_blacklist_navigation_throttle_unittest.cc
+++ b/components/policy/content/policy_blacklist_navigation_throttle_unittest.cc
@@ -96,7 +96,7 @@
 
   void SetBlacklistUrlPattern(const std::string& pattern) {
     auto value = std::make_unique<base::Value>(base::Value::Type::LIST);
-    value->GetList().push_back(base::Value(pattern));
+    value->Append(base::Value(pattern));
     pref_service_.SetManagedPref(policy::policy_prefs::kUrlBlacklist,
                                  std::move(value));
     base::RunLoop().RunUntilIdle();
@@ -104,7 +104,7 @@
 
   void SetWhitelistUrlPattern(const std::string& pattern) {
     auto value = std::make_unique<base::Value>(base::Value::Type::LIST);
-    value->GetList().push_back(base::Value(pattern));
+    value->Append(base::Value(pattern));
     pref_service_.SetManagedPref(policy::policy_prefs::kUrlWhitelist,
                                  std::move(value));
     base::RunLoop().RunUntilIdle();
diff --git a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
index 5ed845e..c673919 100644
--- a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
@@ -1477,7 +1477,7 @@
   event.SetStringPath("foo.prop3", "value3");
 
   base::Value event_list(base::Value::Type::LIST);
-  event_list.GetList().push_back(std::move(event));
+  event_list.Append(std::move(event));
 
   client_->UploadRealtimeReport(
       std::move(policy::RealtimeReportingJobConfiguration::BuildReport(
diff --git a/components/policy/core/common/cloud/cloud_policy_constants.cc b/components/policy/core/common/cloud/cloud_policy_constants.cc
index bdc9cff3..ff3397a9 100644
--- a/components/policy/core/common/cloud/cloud_policy_constants.cc
+++ b/components/policy/core/common/cloud/cloud_policy_constants.cc
@@ -64,6 +64,7 @@
     "device_initial_enrollment_state";
 const char kValueRequestUploadPolicyValidationReport[] =
     "policy_validation_report";
+const char kValueRequestPublicSamlUser[] = "public_saml_user_request";
 
 const char kChromeDevicePolicyType[] = "google/chromeos/device";
 #if defined(OS_CHROMEOS)
diff --git a/components/policy/core/common/cloud/cloud_policy_constants.h b/components/policy/core/common/cloud/cloud_policy_constants.h
index 39cae34..518ece5 100644
--- a/components/policy/core/common/cloud/cloud_policy_constants.h
+++ b/components/policy/core/common/cloud/cloud_policy_constants.h
@@ -57,6 +57,7 @@
 POLICY_EXPORT extern const char kValueRequestChromeDesktopReport[];
 POLICY_EXPORT extern const char kValueRequestInitialEnrollmentStateRetrieval[];
 POLICY_EXPORT extern const char kValueRequestUploadPolicyValidationReport[];
+POLICY_EXPORT extern const char kValueRequestPublicSamlUser[];
 
 // Policy type strings for the policy_type field in PolicyFetchRequest.
 POLICY_EXPORT extern const char kChromeDevicePolicyType[];
diff --git a/components/policy/core/common/cloud/device_management_service.cc b/components/policy/core/common/cloud/device_management_service.cc
index 0dabcba..0294351e 100644
--- a/components/policy/core/common/cloud/device_management_service.cc
+++ b/components/policy/core/common/cloud/device_management_service.cc
@@ -185,6 +185,8 @@
     case DeviceManagementService::JobConfiguration::
         TYPE_UPLOAD_REAL_TIME_REPORT:
       return "UploadrealtimeReport";
+    case DeviceManagementService::JobConfiguration::TYPE_REQUEST_SAML_URL:
+      return "PublicSamlUserRequest";
   }
   NOTREACHED() << "Invalid job type " << type;
   return "";
diff --git a/components/policy/core/common/cloud/device_management_service.h b/components/policy/core/common/cloud/device_management_service.h
index b2cda39..8a41868 100644
--- a/components/policy/core/common/cloud/device_management_service.h
+++ b/components/policy/core/common/cloud/device_management_service.h
@@ -49,7 +49,7 @@
   // 1..kMaxRetries: number of retries. kMaxRetries is the maximum number of
   // retries allowed, defined in the .cc file.
 
-  // The request failed (too many retries or non-retriable error).
+  // The request failed (too many retries or non-retryable error).
   kRequestFailed = 10,
   // The server responded with an error.
   kRequestError = 11,
@@ -119,7 +119,7 @@
   //
   // JobConfiguration is the interface used by callers to specify parameters
   // of network requests.  This object is not immutable and may be changed after
-  // a call to OnBeforeRetry().  DeviceManagemmentService calls the GetXXX
+  // a call to OnBeforeRetry().  DeviceManagementService calls the GetXXX
   // methods again to create a new network request for each retry.
   //
   // JobControl is the interface used internally by DeviceManagementService to
@@ -163,6 +163,7 @@
       TYPE_INITIAL_ENROLLMENT_STATE_RETRIEVAL = 20,
       TYPE_UPLOAD_POLICY_VALIDATION_REPORT = 21,
       TYPE_UPLOAD_REAL_TIME_REPORT = 22,
+      TYPE_REQUEST_SAML_URL = 23,
     };
 
     // The set of HTTP query parmaters of the request.
@@ -350,7 +351,7 @@
 
  protected:
   // Adds the query parameter to the network request's URL.  If the parameter
-  // already eixsts its value is replaced.
+  // already exists its value is replaced.
   void AddParameter(const std::string& name, const std::string& value);
 
   const DMAuth& GetAuth() { return *auth_data_.get(); }
@@ -379,7 +380,7 @@
   // and |oauth_token_| can be specified for one request.
   base::Optional<std::string> oauth_token_;
 
-  // Query pamaters for the network request.
+  // Query parameters for the network request.
   ParameterMap query_params_;
 
   DISALLOW_COPY_AND_ASSIGN(JobConfigurationBase);
diff --git a/components/policy/core/common/cloud/dmserver_job_configurations.cc b/components/policy/core/common/cloud/dmserver_job_configurations.cc
index dcf95fde..bb6e6d4 100644
--- a/components/policy/core/common/cloud/dmserver_job_configurations.cc
+++ b/components/policy/core/common/cloud/dmserver_job_configurations.cc
@@ -76,6 +76,8 @@
     case DeviceManagementService::JobConfiguration::
         TYPE_UPLOAD_POLICY_VALIDATION_REPORT:
       return dm_protocol::kValueRequestUploadPolicyValidationReport;
+    case DeviceManagementService::JobConfiguration::TYPE_REQUEST_SAML_URL:
+      return dm_protocol::kValueRequestPublicSamlUser;
     case DeviceManagementService::JobConfiguration::
         TYPE_UPLOAD_REAL_TIME_REPORT:
       NOTREACHED() << "Not a DMServer request type" << type;
diff --git a/components/policy/core/common/policy_merger.cc b/components/policy/core/common/policy_merger.cc
index c931bc5..bf5b236 100644
--- a/components/policy/core/common/policy_merger.cc
+++ b/components/policy/core/common/policy_merger.cc
@@ -117,7 +117,7 @@
   if (value_changed) {
     base::ListValue* new_value = new base::ListValue();
     for (const base::Value* it : merged_values)
-      new_value->GetList().emplace_back(it->Clone());
+      new_value->Append(it->Clone());
 
     policy->value.reset(new_value);
   }
diff --git a/components/policy/core/common/policy_service_impl_unittest.cc b/components/policy/core/common/policy_service_impl_unittest.cc
index 4cd96e0..2ccd9f0 100644
--- a/components/policy/core/common/policy_service_impl_unittest.cc
+++ b/components/policy/core/common/policy_service_impl_unittest.cc
@@ -783,8 +783,7 @@
 
   std::unique_ptr<base::Value> policy =
       std::make_unique<base::Value>(base::Value::Type::LIST);
-  policy->GetList().push_back(
-      base::Value(policy::key::kContentPackManualBehaviorURLs));
+  policy->Append(base::Value(policy::key::kContentPackManualBehaviorURLs));
 
   auto policy_bundle1 = std::make_unique<PolicyBundle>();
   PolicyMap& policy_map1 = policy_bundle1->Get(chrome_namespace);
@@ -828,19 +827,18 @@
   const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string());
 
   std::unique_ptr<base::ListValue> list1 = std::make_unique<base::ListValue>();
-  list1->GetList().push_back(base::Value("google.com"));
-  list1->GetList().push_back(base::Value("gmail.com"));
+  list1->Append(base::Value("google.com"));
+  list1->Append(base::Value("gmail.com"));
   std::unique_ptr<base::ListValue> list2 = std::make_unique<base::ListValue>();
-  list2->GetList().push_back(base::Value("example.com"));
-  list2->GetList().push_back(base::Value("gmail.com"));
+  list2->Append(base::Value("example.com"));
+  list2->Append(base::Value("gmail.com"));
   std::unique_ptr<base::ListValue> result = std::make_unique<base::ListValue>();
-  result->GetList().push_back(base::Value("google.com"));
-  result->GetList().push_back(base::Value("gmail.com"));
-  result->GetList().push_back(base::Value("example.com"));
+  result->Append(base::Value("google.com"));
+  result->Append(base::Value("gmail.com"));
+  result->Append(base::Value("example.com"));
 
   std::unique_ptr<base::ListValue> policy = std::make_unique<base::ListValue>();
-  policy->GetList().push_back(
-      base::Value(policy::key::kExtensionInstallForcelist));
+  policy->Append(base::Value(policy::key::kExtensionInstallForcelist));
 
   auto policy_bundle1 = std::make_unique<PolicyBundle>();
   PolicyMap& policy_map1 = policy_bundle1->Get(chrome_namespace);
@@ -883,20 +881,18 @@
   const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string());
 
   std::unique_ptr<base::ListValue> list1 = std::make_unique<base::ListValue>();
-  list1->GetList().push_back(base::Value("google.com"));
+  list1->Append(base::Value("google.com"));
   std::unique_ptr<base::ListValue> list2 = std::make_unique<base::ListValue>();
-  list2->GetList().push_back(base::Value("example.com"));
+  list2->Append(base::Value("example.com"));
   std::unique_ptr<base::ListValue> list3 = std::make_unique<base::ListValue>();
-  list3->GetList().push_back(base::Value("example_xyz.com"));
+  list3->Append(base::Value("example_xyz.com"));
   std::unique_ptr<base::ListValue> result = std::make_unique<base::ListValue>();
-  result->GetList().push_back(base::Value("google.com"));
-  result->GetList().push_back(base::Value("example.com"));
+  result->Append(base::Value("google.com"));
+  result->Append(base::Value("example.com"));
 
   std::unique_ptr<base::ListValue> policy = std::make_unique<base::ListValue>();
-  policy->GetList().push_back(
-      base::Value(policy::key::kExtensionInstallForcelist));
-  policy->GetList().push_back(
-      base::Value(policy::key::kExtensionInstallBlacklist));
+  policy->Append(base::Value(policy::key::kExtensionInstallForcelist));
+  policy->Append(base::Value(policy::key::kExtensionInstallBlacklist));
 
   auto policy_bundle1 = std::make_unique<PolicyBundle>();
   PolicyMap& policy_map1 = policy_bundle1->Get(chrome_namespace);
@@ -953,20 +949,18 @@
   const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string());
 
   std::unique_ptr<base::ListValue> list1 = std::make_unique<base::ListValue>();
-  list1->GetList().push_back(base::Value("google.com"));
+  list1->Append(base::Value("google.com"));
   std::unique_ptr<base::ListValue> list2 = std::make_unique<base::ListValue>();
-  list2->GetList().push_back(base::Value("example.com"));
+  list2->Append(base::Value("example.com"));
   std::unique_ptr<base::ListValue> list3 = std::make_unique<base::ListValue>();
-  list3->GetList().push_back(base::Value("example_xyz.com"));
+  list3->Append(base::Value("example_xyz.com"));
   std::unique_ptr<base::ListValue> result = std::make_unique<base::ListValue>();
-  result->GetList().push_back(base::Value("google.com"));
-  result->GetList().push_back(base::Value("example.com"));
+  result->Append(base::Value("google.com"));
+  result->Append(base::Value("example.com"));
 
   std::unique_ptr<base::ListValue> policy = std::make_unique<base::ListValue>();
-  policy->GetList().push_back(
-      base::Value(policy::key::kExtensionInstallForcelist));
-  policy->GetList().push_back(
-      base::Value(policy::key::kExtensionInstallBlacklist));
+  policy->Append(base::Value(policy::key::kExtensionInstallForcelist));
+  policy->Append(base::Value(policy::key::kExtensionInstallBlacklist));
 
   auto policy_bundle1 = std::make_unique<PolicyBundle>();
   PolicyMap& policy_map1 = policy_bundle1->Get(chrome_namespace);
diff --git a/components/policy/core/common/schema_unittest.cc b/components/policy/core/common/schema_unittest.cc
index bb79daa..d65815b 100644
--- a/components/policy/core/common/schema_unittest.cc
+++ b/components/policy/core/common/schema_unittest.cc
@@ -711,8 +711,8 @@
     dict.SetString("one", "string");
     dict.SetInteger("two", 2);