diff --git a/AUTHORS b/AUTHORS
index 32f5c83..0835163 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,4 @@
-# Names should be added to this file with this pattern:
+# Names should be added to this file with this pattern:
 #
 # For individuals:
 #   Name <email address>
@@ -492,6 +492,7 @@
 Milton Chiang <milton.chiang@mediatek.com>
 Minggang Wang <minggang.wang@intel.com>
 Mingmin Xie <melvinxie@gmail.com>
+Minseok Koo <kei98301@gmail.com>
 Minsoo Max Koo <msu.koo@samsung.com>
 Miran Karic <miran.karic@imgtec.com>
 Mirela Budaes <mbudaes@gmail.com>
@@ -734,6 +735,7 @@
 Vivek Galatage <vivek.vg@samsung.com>
 Volker Sorge <volker.sorge@gmail.com>
 Waihung Fu <fufranci@amazon.com>
+Wanchang Ryu <wanchang.ryu@lge.com>
 Wesley Lancel <wesleylancel@gmail.com>
 Wesley Wigham <t-weswig@microsoft.com>
 Wesley Wigham <wwigham@gmail.com>
diff --git a/android_webview/common/crash_reporter/aw_microdump_crash_reporter.cc b/android_webview/common/crash_reporter/aw_microdump_crash_reporter.cc
index 518e1fbb..4241a53 100644
--- a/android_webview/common/crash_reporter/aw_microdump_crash_reporter.cc
+++ b/android_webview/common/crash_reporter/aw_microdump_crash_reporter.cc
@@ -4,6 +4,8 @@
 
 #include "android_webview/common/crash_reporter/aw_microdump_crash_reporter.h"
 
+#include <random>
+
 #include "android_webview/common/aw_descriptors.h"
 #include "android_webview/common/aw_paths.h"
 #include "android_webview/common/aw_version_info_values.h"
@@ -17,6 +19,7 @@
 #include "base/path_service.h"
 #include "base/scoped_native_library.h"
 #include "base/synchronization/lock.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/crash/content/app/breakpad_linux.h"
 #include "components/crash/content/app/crash_reporter_client.h"
@@ -27,10 +30,27 @@
 
 namespace {
 
+// TODO(gsennton) lower the following value before pushing to stable:
+const double minidump_generation_user_fraction = 1.0;
+
+// Returns whether the current process should be reporting crashes through
+// minidumps. This function should only be called once per process - the return
+// value might differ between different calls to this function.
+bool is_process_in_crash_reporting_sample() {
+  // TODO(gsennton): update this method to depend on finch when that is
+  // implemented for WebView.
+  base::Time cur_time = base::Time::Now();
+  std::minstd_rand generator(cur_time.ToInternalValue() /* seed */);
+  std::uniform_real_distribution<double> distribution(0.0, 1.0);
+  return minidump_generation_user_fraction > distribution(generator);
+}
+
 class AwCrashReporterClient : public ::crash_reporter::CrashReporterClient {
  public:
   AwCrashReporterClient()
-      : dump_fd_(kAndroidMinidumpDescriptor), crash_signal_fd_(-1) {}
+      : dump_fd_(kAndroidMinidumpDescriptor),
+        crash_signal_fd_(-1),
+        in_crash_reporting_sample_(is_process_in_crash_reporting_sample()) {}
 
   // Does not use lock, can only be called immediately after creation.
   void set_crash_signal_fd(int fd) { crash_signal_fd_ = fd; }
@@ -41,20 +61,7 @@
   const char* const* GetCrashKeyWhiteList() override;
 
   bool IsRunningUnattended() override { return false; }
-  bool GetCollectStatsConsent() override {
-#if defined(GOOGLE_CHROME_BUILD)
-    // TODO(gsennton): Enabling minidump-generation unconditionally means we
-    // will generate minidumps even if the user doesn't consent to minidump
-    // uploads. However, we will check user-consent before uploading any
-    // minidumps, if we do not have user consent we will delete the minidumps.
-    // We should investigate whether we can avoid generating minidumps
-    // altogether if we don't have user consent, see crbug.com/692485
-    return true;
-#else
-    return false;
-#endif  // defined(GOOGLE_CHROME_BUILD)
-  }
-
+  bool GetCollectStatsConsent() override;
   void GetProductNameAndVersion(const char** product_name,
                                 const char** version) override {
     *product_name = "AndroidWebView";
@@ -82,6 +89,7 @@
  private:
   int dump_fd_;
   int crash_signal_fd_;
+  bool in_crash_reporting_sample_;
   DISALLOW_COPY_AND_ASSIGN(AwCrashReporterClient);
 };
 
@@ -93,6 +101,20 @@
   return crash_keys::kWebViewCrashKeyWhiteList;
 }
 
+bool AwCrashReporterClient::GetCollectStatsConsent() {
+#if defined(GOOGLE_CHROME_BUILD)
+  // TODO(gsennton): Enabling minidump-generation unconditionally means we
+  // will generate minidumps even if the user doesn't consent to minidump
+  // uploads. However, we will check user-consent before uploading any
+  // minidumps, if we do not have user consent we will delete the minidumps.
+  // We should investigate whether we can avoid generating minidumps
+  // altogether if we don't have user consent, see crbug.com/692485
+  return in_crash_reporting_sample_;
+#else
+  return false;
+#endif  // !defined(GOOGLE_CHROME_BUILD)
+}
+
 base::LazyInstance<AwCrashReporterClient>::Leaky g_crash_reporter_client =
     LAZY_INSTANCE_INITIALIZER;
 
@@ -206,6 +228,7 @@
 }
 
 bool DumpWithoutCrashingToFd(int fd) {
+  ::crash_reporter::SetCrashReporterClient(g_crash_reporter_client.Pointer());
   return g_crash_reporter_client.Pointer()->DumpWithoutCrashingToFd(fd);
 }
 
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index 9a9de0d..4271b94 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -1321,8 +1321,9 @@
   RunTest("testSharedWorker", kSharedWorkerTestPage, kSharedWorkerTestWorker);
 }
 
-// Flakey on Win.  http://crbug.com/663351
-#if defined(OS_WIN)
+// Flaky on Windows and on Mac.
+// http://crbug.com/663351 and http://crbug.com/432444.
+#if defined(OS_WIN) || defined(OS_MACOSX)
 #define MAYBE_PauseInSharedWorkerInitialization \
   DISABLED_PauseInSharedWorkerInitialization
 #else
diff --git a/chrome/browser/extensions/extension_management.cc b/chrome/browser/extensions/extension_management.cc
index f169ae0..202f84c 100644
--- a/chrome/browser/extensions/extension_management.cc
+++ b/chrome/browser/extensions/extension_management.cc
@@ -36,10 +36,15 @@
 #include "extensions/common/url_pattern.h"
 #include "url/gurl.h"
 
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#endif
+
 namespace extensions {
 
-ExtensionManagement::ExtensionManagement(PrefService* pref_service)
-    : pref_service_(pref_service) {
+ExtensionManagement::ExtensionManagement(PrefService* pref_service,
+                                         bool is_signin_profile)
+    : pref_service_(pref_service), is_signin_profile_(is_signin_profile) {
   TRACE_EVENT0("browser,startup",
                "ExtensionManagement::ExtensionManagement::ctor");
   pref_change_registrar_.Init(pref_service_);
@@ -51,6 +56,8 @@
                              pref_change_callback);
   pref_change_registrar_.Add(pref_names::kInstallForceList,
                              pref_change_callback);
+  pref_change_registrar_.Add(pref_names::kInstallLoginScreenAppList,
+                             pref_change_callback);
   pref_change_registrar_.Add(pref_names::kAllowedInstallSites,
                              pref_change_callback);
   pref_change_registrar_.Add(pref_names::kAllowedTypes, pref_change_callback);
@@ -111,28 +118,12 @@
 
 std::unique_ptr<base::DictionaryValue>
 ExtensionManagement::GetForceInstallList() const {
-  std::unique_ptr<base::DictionaryValue> install_list(
-      new base::DictionaryValue());
-  for (const auto& entry : settings_by_id_) {
-    if (entry.second->installation_mode == INSTALLATION_FORCED) {
-      ExternalPolicyLoader::AddExtension(install_list.get(), entry.first,
-                                         entry.second->update_url);
-    }
-  }
-  return install_list;
+  return GetInstallListByMode(INSTALLATION_FORCED);
 }
 
 std::unique_ptr<base::DictionaryValue>
 ExtensionManagement::GetRecommendedInstallList() const {
-  std::unique_ptr<base::DictionaryValue> install_list(
-      new base::DictionaryValue());
-  for (const auto& entry : settings_by_id_) {
-    if (entry.second->installation_mode == INSTALLATION_RECOMMENDED) {
-      ExternalPolicyLoader::AddExtension(install_list.get(), entry.first,
-                                         entry.second->update_url);
-    }
-  }
-  return install_list;
+  return GetInstallListByMode(INSTALLATION_RECOMMENDED);
 }
 
 bool ExtensionManagement::IsInstallationExplicitlyAllowed(
@@ -255,6 +246,12 @@
   const base::DictionaryValue* forced_list_pref =
       static_cast<const base::DictionaryValue*>(LoadPreference(
           pref_names::kInstallForceList, true, base::Value::Type::DICTIONARY));
+  const base::DictionaryValue* login_screen_app_list_pref = nullptr;
+  if (is_signin_profile_) {
+    login_screen_app_list_pref = static_cast<const base::DictionaryValue*>(
+        LoadPreference(pref_names::kInstallLoginScreenAppList, true,
+                       base::Value::Type::DICTIONARY));
+  }
   const base::ListValue* install_sources_pref =
       static_cast<const base::ListValue*>(LoadPreference(
           pref_names::kAllowedInstallSites, true, base::Value::Type::LIST));
@@ -315,22 +312,8 @@
     }
   }
 
-  if (forced_list_pref) {
-    std::string update_url;
-    for (base::DictionaryValue::Iterator it(*forced_list_pref); !it.IsAtEnd();
-         it.Advance()) {
-      if (!crx_file::id_util::IdIsValid(it.key()))
-        continue;
-      const base::DictionaryValue* dict_value = NULL;
-      if (it.value().GetAsDictionary(&dict_value) &&
-          dict_value->GetStringWithoutPathExpansion(
-              ExternalProviderImpl::kExternalUpdateUrl, &update_url)) {
-        internal::IndividualSettings* by_id = AccessById(it.key());
-        by_id->installation_mode = INSTALLATION_FORCED;
-        by_id->update_url = update_url;
-      }
-    }
-  }
+  UpdateForcedExtensions(forced_list_pref);
+  UpdateForcedExtensions(login_screen_app_list_pref);
 
   if (install_sources_pref) {
     global_settings_->has_restricted_install_sources = true;
@@ -438,6 +421,40 @@
     observer.OnExtensionManagementSettingsChanged();
 }
 
+std::unique_ptr<base::DictionaryValue>
+ExtensionManagement::GetInstallListByMode(
+    InstallationMode installation_mode) const {
+  auto extension_dict = base::MakeUnique<base::DictionaryValue>();
+  for (const auto& entry : settings_by_id_) {
+    if (entry.second->installation_mode == installation_mode) {
+      ExternalPolicyLoader::AddExtension(extension_dict.get(), entry.first,
+                                         entry.second->update_url);
+    }
+  }
+  return extension_dict;
+}
+
+void ExtensionManagement::UpdateForcedExtensions(
+    const base::DictionaryValue* extension_dict) {
+  if (!extension_dict)
+    return;
+
+  std::string update_url;
+  for (base::DictionaryValue::Iterator it(*extension_dict); !it.IsAtEnd();
+       it.Advance()) {
+    if (!crx_file::id_util::IdIsValid(it.key()))
+      continue;
+    const base::DictionaryValue* dict_value = nullptr;
+    if (it.value().GetAsDictionary(&dict_value) &&
+        dict_value->GetStringWithoutPathExpansion(
+            ExternalProviderImpl::kExternalUpdateUrl, &update_url)) {
+      internal::IndividualSettings* by_id = AccessById(it.key());
+      by_id->installation_mode = INSTALLATION_FORCED;
+      by_id->update_url = update_url;
+    }
+  }
+}
+
 internal::IndividualSettings* ExtensionManagement::AccessById(
     const ExtensionId& id) {
   DCHECK(crx_file::id_util::IdIsValid(id)) << "Invalid ID: " << id;
@@ -484,8 +501,12 @@
     content::BrowserContext* context) const {
   TRACE_EVENT0("browser,startup",
                "ExtensionManagementFactory::BuildServiceInstanceFor");
-  return new ExtensionManagement(
-      Profile::FromBrowserContext(context)->GetPrefs());
+  Profile* profile = Profile::FromBrowserContext(context);
+  bool is_signin_profile = false;
+#if defined(OS_CHROMEOS)
+  is_signin_profile = chromeos::ProfileHelper::IsSigninProfile(profile);
+#endif
+  return new ExtensionManagement(profile->GetPrefs(), is_signin_profile);
 }
 
 content::BrowserContext* ExtensionManagementFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/extensions/extension_management.h b/chrome/browser/extensions/extension_management.h
index 58c621f90..a686f34 100644
--- a/chrome/browser/extensions/extension_management.h
+++ b/chrome/browser/extensions/extension_management.h
@@ -70,7 +70,7 @@
     INSTALLATION_RECOMMENDED,
   };
 
-  explicit ExtensionManagement(PrefService* pref_service);
+  ExtensionManagement(PrefService* pref_service, bool is_signin_profile);
   ~ExtensionManagement() override;
 
   // KeyedService implementations:
@@ -153,6 +153,14 @@
   void OnExtensionPrefChanged();
   void NotifyExtensionManagementPrefChanged();
 
+  // Helper to return an extension install list, in format specified by
+  // ExternalPolicyLoader::AddExtension().
+  std::unique_ptr<base::DictionaryValue> GetInstallListByMode(
+      InstallationMode installation_mode) const;
+
+  // Helper to update |extension_dict| for forced installs.
+  void UpdateForcedExtensions(const base::DictionaryValue* extension_dict);
+
   // Helper function to access |settings_by_id_| with |id| as key.
   // Adds a new IndividualSettings entry to |settings_by_id_| if none exists for
   // |id| yet.
@@ -183,7 +191,8 @@
   // Extension settings applicable to all extensions.
   std::unique_ptr<internal::GlobalSettings> global_settings_;
 
-  PrefService* pref_service_;
+  PrefService* pref_service_ = nullptr;
+  bool is_signin_profile_ = false;
 
   base::ObserverList<Observer, true> observer_list_;
   PrefChangeRegistrar pref_change_registrar_;
diff --git a/chrome/browser/extensions/extension_management_unittest.cc b/chrome/browser/extensions/extension_management_unittest.cc
index 56618b81..30aa6a1 100644
--- a/chrome/browser/extensions/extension_management_unittest.cc
+++ b/chrome/browser/extensions/extension_management_unittest.cc
@@ -97,7 +97,8 @@
         pref_names::kInstallForceList);
     pref_service_->registry()->RegisterDictionaryPref(
         pref_names::kExtensionManagement);
-    extension_management_.reset(new ExtensionManagement(pref_service_.get()));
+    extension_management_.reset(
+        new ExtensionManagement(pref_service_.get(), false));
   }
 
   void SetPref(bool managed, const char* path, base::Value* value) {
diff --git a/chrome/browser/extensions/permissions_based_management_policy_provider_unittest.cc b/chrome/browser/extensions/permissions_based_management_policy_provider_unittest.cc
index 5651c8db..41e308c 100644
--- a/chrome/browser/extensions/permissions_based_management_policy_provider_unittest.cc
+++ b/chrome/browser/extensions/permissions_based_management_policy_provider_unittest.cc
@@ -31,7 +31,7 @@
 
   PermissionsBasedManagementPolicyProviderTest()
       : pref_service_(new TestingPrefServiceSimple()),
-        settings_(new ExtensionManagement(pref_service_.get())),
+        settings_(new ExtensionManagement(pref_service_.get(), false)),
         provider_(settings_.get()) {}
 
   void SetUp() override {
diff --git a/chrome/browser/extensions/policy_handlers.cc b/chrome/browser/extensions/policy_handlers.cc
index fa80158..8ee0bee3 100644
--- a/chrome/browser/extensions/policy_handlers.cc
+++ b/chrome/browser/extensions/policy_handlers.cc
@@ -99,43 +99,41 @@
   return true;
 }
 
-// ExtensionInstallForcelistPolicyHandler implementation -----------------------
+// ExtensionInstallListPolicyHandler implementation ----------------------------
 
-ExtensionInstallForcelistPolicyHandler::ExtensionInstallForcelistPolicyHandler()
-    : policy::TypeCheckingPolicyHandler(policy::key::kExtensionInstallForcelist,
-                                        base::Value::Type::LIST) {}
+ExtensionInstallListPolicyHandler::ExtensionInstallListPolicyHandler(
+    const char* policy_name,
+    const char* pref_name)
+    : policy::TypeCheckingPolicyHandler(policy_name, base::Value::Type::LIST),
+      pref_name_(pref_name) {}
 
-ExtensionInstallForcelistPolicyHandler::
-    ~ExtensionInstallForcelistPolicyHandler() {}
-
-bool ExtensionInstallForcelistPolicyHandler::CheckPolicySettings(
+bool ExtensionInstallListPolicyHandler::CheckPolicySettings(
     const policy::PolicyMap& policies,
     policy::PolicyErrorMap* errors) {
   const base::Value* value;
   return CheckAndGetValue(policies, errors, &value) &&
-      ParseList(value, NULL, errors);
+         ParseList(value, nullptr, errors);
 }
 
-void ExtensionInstallForcelistPolicyHandler::ApplyPolicySettings(
+void ExtensionInstallListPolicyHandler::ApplyPolicySettings(
     const policy::PolicyMap& policies,
     PrefValueMap* prefs) {
-  const base::Value* value = NULL;
+  const base::Value* value = nullptr;
   std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
-  if (CheckAndGetValue(policies, NULL, &value) &&
-      value &&
-      ParseList(value, dict.get(), NULL)) {
-    prefs->SetValue(pref_names::kInstallForceList, std::move(dict));
+  if (CheckAndGetValue(policies, nullptr, &value) && value &&
+      ParseList(value, dict.get(), nullptr)) {
+    prefs->SetValue(pref_name_, std::move(dict));
   }
 }
 
-bool ExtensionInstallForcelistPolicyHandler::ParseList(
+bool ExtensionInstallListPolicyHandler::ParseList(
     const base::Value* policy_value,
     base::DictionaryValue* extension_dict,
     policy::PolicyErrorMap* errors) {
   if (!policy_value)
     return true;
 
-  const base::ListValue* policy_list_value = NULL;
+  const base::ListValue* policy_list_value = nullptr;
   if (!policy_value->GetAsList(&policy_list_value)) {
     // This should have been caught in CheckPolicySettings.
     NOTREACHED();
@@ -167,8 +165,8 @@
       continue;
     }
 
-    std::string extension_id = entry_string.substr(0, pos);
-    std::string update_url = entry_string.substr(pos+1);
+    const std::string extension_id = entry_string.substr(0, pos);
+    const std::string update_url = entry_string.substr(pos + 1);
     if (!crx_file::id_util::IdIsValid(extension_id) ||
         !GURL(update_url).is_valid()) {
       if (errors) {
@@ -180,14 +178,28 @@
     }
 
     if (extension_dict) {
-      extensions::ExternalPolicyLoader::AddExtension(
-          extension_dict, extension_id, update_url);
+      ExternalPolicyLoader::AddExtension(extension_dict, extension_id,
+                                         update_url);
     }
   }
 
   return true;
 }
 
+// ExtensionInstallForcelistPolicyHandler implementation -----------------------
+
+ExtensionInstallForcelistPolicyHandler::ExtensionInstallForcelistPolicyHandler()
+    : ExtensionInstallListPolicyHandler(policy::key::kExtensionInstallForcelist,
+                                        pref_names::kInstallForceList) {}
+
+// ExtensionInstallLoginScreenAppListPolicyHandler implementation --------------
+
+ExtensionInstallLoginScreenAppListPolicyHandler::
+    ExtensionInstallLoginScreenAppListPolicyHandler()
+    : ExtensionInstallListPolicyHandler(
+          policy::key::kDeviceLoginScreenAppInstallList,
+          pref_names::kInstallLoginScreenAppList) {}
+
 // ExtensionURLPatternListPolicyHandler implementation -------------------------
 
 ExtensionURLPatternListPolicyHandler::ExtensionURLPatternListPolicyHandler(
diff --git a/chrome/browser/extensions/policy_handlers.h b/chrome/browser/extensions/policy_handlers.h
index cd7e5d99..df99405 100644
--- a/chrome/browser/extensions/policy_handlers.h
+++ b/chrome/browser/extensions/policy_handlers.h
@@ -49,27 +49,55 @@
   DISALLOW_COPY_AND_ASSIGN(ExtensionListPolicyHandler);
 };
 
-class ExtensionInstallForcelistPolicyHandler
+// Base class for parsing the list of extensions to force install.
+class ExtensionInstallListPolicyHandler
     : public policy::TypeCheckingPolicyHandler {
  public:
-  ExtensionInstallForcelistPolicyHandler();
-  ~ExtensionInstallForcelistPolicyHandler() override;
-
   // ConfigurationPolicyHandler methods:
   bool CheckPolicySettings(const policy::PolicyMap& policies,
                            policy::PolicyErrorMap* errors) override;
   void ApplyPolicySettings(const policy::PolicyMap& policies,
                            PrefValueMap* prefs) override;
 
+ protected:
+  ExtensionInstallListPolicyHandler(const char* policy_name,
+                                    const char* pref_name);
+
+  ~ExtensionInstallListPolicyHandler() override = default;
+
  private:
   // Parses the data in |policy_value| and writes them to |extension_dict|.
   bool ParseList(const base::Value* policy_value,
                  base::DictionaryValue* extension_dict,
                  policy::PolicyErrorMap* errors);
 
+  const char* const pref_name_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionInstallListPolicyHandler);
+};
+
+// Parses the extension force install list for user sessions.
+class ExtensionInstallForcelistPolicyHandler
+    : public ExtensionInstallListPolicyHandler {
+ public:
+  ExtensionInstallForcelistPolicyHandler();
+  ~ExtensionInstallForcelistPolicyHandler() override = default;
+
+ private:
   DISALLOW_COPY_AND_ASSIGN(ExtensionInstallForcelistPolicyHandler);
 };
 
+// Parses the extension force install list for the login profile.
+class ExtensionInstallLoginScreenAppListPolicyHandler
+    : public ExtensionInstallListPolicyHandler {
+ public:
+  ExtensionInstallLoginScreenAppListPolicyHandler();
+  ~ExtensionInstallLoginScreenAppListPolicyHandler() override = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ExtensionInstallLoginScreenAppListPolicyHandler);
+};
+
 // Implements additional checks for policies that are lists of extension
 // URLPatterns.
 class ExtensionURLPatternListPolicyHandler
diff --git a/chrome/browser/extensions/standard_management_policy_provider_unittest.cc b/chrome/browser/extensions/standard_management_policy_provider_unittest.cc
index e1b2f540..a9826d2 100644
--- a/chrome/browser/extensions/standard_management_policy_provider_unittest.cc
+++ b/chrome/browser/extensions/standard_management_policy_provider_unittest.cc
@@ -25,7 +25,7 @@
       : ui_thread_(content::BrowserThread::UI, &message_loop_),
         file_thread_(content::BrowserThread::FILE, &message_loop_),
         prefs_(message_loop_.task_runner().get()),
-        settings_(new ExtensionManagement(prefs()->pref_service())),
+        settings_(new ExtensionManagement(prefs()->pref_service(), false)),
         provider_(settings_.get()) {}
 
  protected:
diff --git a/chrome/browser/notifications/OWNERS b/chrome/browser/notifications/OWNERS
index b43d842..da23ac6 100644
--- a/chrome/browser/notifications/OWNERS
+++ b/chrome/browser/notifications/OWNERS
@@ -1,12 +1,12 @@
 dewittj@chromium.org
 dimich@chromium.org
+miguelg@chromium.org
 mukai@chromium.org
 peter@chromium.org
 stevenjb@chromium.org
 yoshiki@chromium.org
 
 # Mac files
-per-file *_mac*=miguelg@chromium.org
 per-file *_mac*=rsesek@chromium.org
 
 # TEAM: platform-capabilities@chromium.org
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index a454161..8d2886d5 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -885,6 +885,9 @@
   handlers->AddHandler(
       base::MakeUnique<extensions::ExtensionInstallForcelistPolicyHandler>());
   handlers->AddHandler(
+      base::MakeUnique<
+          extensions::ExtensionInstallLoginScreenAppListPolicyHandler>());
+  handlers->AddHandler(
       base::MakeUnique<extensions::ExtensionURLPatternListPolicyHandler>(
           key::kExtensionInstallSources,
           extensions::pref_names::kAllowedInstallSites));
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 5e588a8..21607605 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -555,7 +555,8 @@
   }
   // Because IMEs may eat the tab key, we don't show "press tab to search" while
   // IME composition is in progress.
-  if (!keyword.empty() && omnibox_view_->model()->is_keyword_hint() &&
+  if (HasFocus() && !keyword.empty() &&
+      omnibox_view_->model()->is_keyword_hint() &&
       !omnibox_view_->IsImeComposing()) {
     trailing_decorations.AddDecoration(vertical_padding, location_height, true,
                                        0, item_padding, item_padding,
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index 689b651..4597e0c 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -758,6 +758,10 @@
     SelectRange(saved_selection_for_focus_change_);
     saved_selection_for_focus_change_ = gfx::Range::InvalidRange();
   }
+
+  // Focus changes can affect the visibility of any keyword hint.
+  if (model()->is_keyword_hint())
+    location_bar_view_->Layout();
 }
 
 void OmniboxViewViews::OnBlur() {
@@ -783,6 +787,10 @@
   // Make sure the beginning of the text is visible.
   SelectRange(gfx::Range(0));
 
+  // Focus changes can affect the visibility of any keyword hint.
+  if (model()->is_keyword_hint())
+    location_bar_view_->Layout();
+
   // The location bar needs to repaint without a focus ring.
   location_bar_view_->SchedulePaint();
 }
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
index f6718c78..d1b4eed 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -26,59 +26,49 @@
 #include "chrome/browser/chromeos/input_method/mock_input_method_manager_impl.h"
 #endif
 
+using gfx::Range;
+
 namespace {
 
-class TestingOmniboxViewViews : public OmniboxViewViews {
+// TestingOmniboxView ---------------------------------------------------------
+
+class TestingOmniboxView : public OmniboxViewViews {
  public:
-  TestingOmniboxViewViews(OmniboxEditController* controller,
-                          Profile* profile,
-                          CommandUpdater* command_updater)
-      : OmniboxViewViews(controller,
-                         profile,
-                         command_updater,
-                         false,
-                         nullptr,
-                         gfx::FontList()),
-        update_popup_call_count_(0),
-        profile_(profile),
-        base_text_is_emphasized_(false) {}
+  enum BaseTextEmphasis {
+    DEEMPHASIZED,
+    EMPHASIZED,
+    UNSET,
+  };
 
-  void CheckUpdatePopupCallInfo(size_t call_count, const base::string16& text,
-                                const gfx::Range& selection_range) {
-    EXPECT_EQ(call_count, update_popup_call_count_);
-    EXPECT_EQ(text, update_popup_text_);
-    EXPECT_EQ(selection_range, update_popup_selection_range_);
+  TestingOmniboxView(OmniboxEditController* controller,
+                     Profile* profile,
+                     CommandUpdater* command_updater);
+
+  static BaseTextEmphasis to_base_text_emphasis(bool emphasize) {
+    return emphasize ? EMPHASIZED : DEEMPHASIZED;
   }
 
-  void EmphasizeURLComponents() override {
-    UpdateTextStyle(text(), ChromeAutocompleteSchemeClassifier(profile_));
-  }
+  void ResetEmphasisTestState();
 
-  gfx::Range scheme_range() const { return scheme_range_; }
-  gfx::Range emphasis_range() const { return emphasis_range_; }
-  bool base_text_is_emphasized() const { return base_text_is_emphasized_; }
+  void CheckUpdatePopupCallInfo(size_t call_count,
+                                const base::string16& text,
+                                const Range& selection_range);
+
+  Range scheme_range() const { return scheme_range_; }
+  Range emphasis_range() const { return emphasis_range_; }
+  BaseTextEmphasis base_text_emphasis() const { return base_text_emphasis_; }
+
+  // OmniboxViewViews:
+  void EmphasizeURLComponents() override;
 
  private:
-  // OmniboxView:
-  void UpdatePopup() override {
-    ++update_popup_call_count_;
-    update_popup_text_ = text();
-    update_popup_selection_range_ = GetSelectedRange();
-  }
-
-  void SetEmphasis(bool emphasize, const gfx::Range& range) override {
-    if (range == gfx::Range::InvalidRange()) {
-      base_text_is_emphasized_ = emphasize;
-      return;
-    }
-
-    EXPECT_TRUE(emphasize);
-    emphasis_range_ = range;
-  }
-
-  void UpdateSchemeStyle(const gfx::Range& range) override {
-    scheme_range_ = range;
-  }
+  // OmniboxViewViews:
+  // There is no popup and it doesn't actually matter whether we change the
+  // visual style of the text, so these methods are all overridden merely to
+  // capture relevant state at the time of the call, to be checked by test code.
+  void UpdatePopup() override;
+  void SetEmphasis(bool emphasize, const Range& range) override;
+  void UpdateSchemeStyle(const Range& range) override;
 
   // Simplistic test override returns whether a given string looks like a URL
   // without having to mock AutocompleteClassifier objects and their
@@ -89,29 +79,81 @@
     return looks_like_url;
   }
 
-  size_t update_popup_call_count_;
+  size_t update_popup_call_count_ = 0;
   base::string16 update_popup_text_;
-  gfx::Range update_popup_selection_range_;
+  Range update_popup_selection_range_;
   Profile* profile_;
 
   // Range of the last scheme logged by UpdateSchemeStyle().
-  gfx::Range scheme_range_;
+  Range scheme_range_;
 
   // Range of the last text emphasized by SetEmphasis().
-  gfx::Range emphasis_range_;
+  Range emphasis_range_;
 
   // SetEmphasis() logs whether the base color of the text is emphasized.
-  bool base_text_is_emphasized_;
+  BaseTextEmphasis base_text_emphasis_ = UNSET;
 
-  DISALLOW_COPY_AND_ASSIGN(TestingOmniboxViewViews);
+  DISALLOW_COPY_AND_ASSIGN(TestingOmniboxView);
 };
 
+TestingOmniboxView::TestingOmniboxView(OmniboxEditController* controller,
+                                       Profile* profile,
+                                       CommandUpdater* command_updater)
+    : OmniboxViewViews(controller,
+                       profile,
+                       command_updater,
+                       false,
+                       nullptr,
+                       gfx::FontList()),
+      profile_(profile) {}
+
+void TestingOmniboxView::ResetEmphasisTestState() {
+  base_text_emphasis_ = UNSET;
+  emphasis_range_ = Range::InvalidRange();
+  scheme_range_ = Range::InvalidRange();
+}
+
+void TestingOmniboxView::CheckUpdatePopupCallInfo(
+    size_t call_count,
+    const base::string16& text,
+    const Range& selection_range) {
+  EXPECT_EQ(call_count, update_popup_call_count_);
+  EXPECT_EQ(text, update_popup_text_);
+  EXPECT_EQ(selection_range, update_popup_selection_range_);
+}
+
+void TestingOmniboxView::EmphasizeURLComponents() {
+  UpdateTextStyle(text(), ChromeAutocompleteSchemeClassifier(profile_));
+}
+
+void TestingOmniboxView::UpdatePopup() {
+  ++update_popup_call_count_;
+  update_popup_text_ = text();
+  update_popup_selection_range_ = GetSelectedRange();
+}
+
+void TestingOmniboxView::SetEmphasis(bool emphasize, const Range& range) {
+  if (range == Range::InvalidRange()) {
+    base_text_emphasis_ = to_base_text_emphasis(emphasize);
+    return;
+  }
+
+  EXPECT_TRUE(emphasize);
+  emphasis_range_ = range;
+}
+
+void TestingOmniboxView::UpdateSchemeStyle(const Range& range) {
+  scheme_range_ = range;
+}
+
+// TestingOmniboxEditController -----------------------------------------------
+
 class TestingOmniboxEditController : public ChromeOmniboxEditController {
  public:
   explicit TestingOmniboxEditController(CommandUpdater* command_updater)
       : ChromeOmniboxEditController(command_updater) {}
 
- protected:
+ private:
   // ChromeOmniboxEditController:
   void UpdateWithoutTabRestore() override {}
   void OnChanged() override {}
@@ -119,66 +161,70 @@
   const ToolbarModel* GetToolbarModel() const override { return nullptr; }
   content::WebContents* GetWebContents() override { return nullptr; }
 
- private:
   DISALLOW_COPY_AND_ASSIGN(TestingOmniboxEditController);
 };
 
 }  // namespace
 
+// OmniboxViewViewsTest -------------------------------------------------------
+
 class OmniboxViewViewsTest : public testing::Test {
  public:
-  OmniboxViewViewsTest()
-      : command_updater_(NULL),
-        omnibox_edit_controller_(&command_updater_) {
-  }
+  OmniboxViewViewsTest();
 
-  TestingOmniboxViewViews* omnibox_view() {
-    return omnibox_view_.get();
-  }
-
-  views::Textfield* omnibox_textfield() {
-    return omnibox_view();
-  }
-
+  TestingOmniboxView* omnibox_view() { return omnibox_view_.get(); }
+  views::Textfield* omnibox_textfield() { return omnibox_view(); }
   ui::TextEditCommand scheduled_text_edit_command() const {
     return test_api_->scheduled_text_edit_command();
   }
 
-  void SetAndEmphasizeText(const std::string& new_text) {
-    omnibox_textfield()->SetText(base::ASCIIToUTF16(new_text));
-    omnibox_view()->EmphasizeURLComponents();
-  }
+  // Sets |new_text| as the omnibox text, and emphasizes it appropriately.
+  void SetAndEmphasizeText(const std::string& new_text);
 
  private:
   // testing::Test:
-  void SetUp() override {
-#if defined(OS_CHROMEOS)
-    chromeos::input_method::InitializeForTesting(
-        new chromeos::input_method::MockInputMethodManagerImpl);
-#endif
-    omnibox_view_.reset(new TestingOmniboxViewViews(
-        &omnibox_edit_controller_, &profile_, &command_updater_));
-    test_api_.reset(new views::TextfieldTestApi(omnibox_view_.get()));
-    omnibox_view_->Init();
-  }
-
-  void TearDown() override {
-    omnibox_view_.reset();
-#if defined(OS_CHROMEOS)
-    chromeos::input_method::Shutdown();
-#endif
-  }
+  void SetUp() override;
+  void TearDown() override;
 
   content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
   CommandUpdater command_updater_;
   TestingOmniboxEditController omnibox_edit_controller_;
-  std::unique_ptr<TestingOmniboxViewViews> omnibox_view_;
+  std::unique_ptr<TestingOmniboxView> omnibox_view_;
   std::unique_ptr<views::TextfieldTestApi> test_api_;
 
   DISALLOW_COPY_AND_ASSIGN(OmniboxViewViewsTest);
 };
 
+OmniboxViewViewsTest::OmniboxViewViewsTest()
+    : command_updater_(nullptr), omnibox_edit_controller_(&command_updater_) {}
+
+void OmniboxViewViewsTest::SetAndEmphasizeText(const std::string& new_text) {
+  omnibox_view()->ResetEmphasisTestState();
+  omnibox_view()->SetText(base::ASCIIToUTF16(new_text));
+  omnibox_view()->EmphasizeURLComponents();
+}
+
+void OmniboxViewViewsTest::SetUp() {
+#if defined(OS_CHROMEOS)
+  chromeos::input_method::InitializeForTesting(
+      new chromeos::input_method::MockInputMethodManagerImpl);
+#endif
+  omnibox_view_ = base::MakeUnique<TestingOmniboxView>(
+      &omnibox_edit_controller_, &profile_, &command_updater_);
+  test_api_ = base::MakeUnique<views::TextfieldTestApi>(omnibox_view_.get());
+  omnibox_view_->Init();
+}
+
+void OmniboxViewViewsTest::TearDown() {
+  omnibox_view_.reset();
+#if defined(OS_CHROMEOS)
+  chromeos::input_method::Shutdown();
+#endif
+}
+
+// Actual tests ---------------------------------------------------------------
+
 // Checks that a single change of the text in the omnibox invokes
 // only one call to OmniboxViewViews::UpdatePopup().
 TEST_F(OmniboxViewViewsTest, UpdatePopupCall) {
@@ -186,20 +232,20 @@
                           ui::DomKey::FromCharacter('a'),
                           ui::EventTimeForNow());
   omnibox_textfield()->InsertChar(char_event);
-  omnibox_view()->CheckUpdatePopupCallInfo(
-      1, base::ASCIIToUTF16("a"), gfx::Range(1));
+  omnibox_view()->CheckUpdatePopupCallInfo(1, base::ASCIIToUTF16("a"),
+                                           Range(1));
 
   char_event =
       ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_B, ui::DomCode::US_B, 0,
                    ui::DomKey::FromCharacter('b'), ui::EventTimeForNow());
   omnibox_textfield()->InsertChar(char_event);
-  omnibox_view()->CheckUpdatePopupCallInfo(
-      2, base::ASCIIToUTF16("ab"), gfx::Range(2));
+  omnibox_view()->CheckUpdatePopupCallInfo(2, base::ASCIIToUTF16("ab"),
+                                           Range(2));
 
   ui::KeyEvent pressed(ui::ET_KEY_PRESSED, ui::VKEY_BACK, 0);
   omnibox_textfield()->OnKeyEvent(&pressed);
-  omnibox_view()->CheckUpdatePopupCallInfo(
-      3, base::ASCIIToUTF16("a"), gfx::Range(1));
+  omnibox_view()->CheckUpdatePopupCallInfo(3, base::ASCIIToUTF16("a"),
+                                           Range(1));
 }
 
 // Test that the scheduled text edit command is cleared when Textfield receives
@@ -216,67 +262,37 @@
             scheduled_text_edit_command());
 }
 
-// Ensure that the scheme is emphasized for data: URLs.
-TEST_F(OmniboxViewViewsTest, TestEmphasisForDATA) {
-  SetAndEmphasizeText("data:text/html,Hello%20World");
-  EXPECT_EQ(gfx::Range(0, 4), omnibox_view()->scheme_range());
-  EXPECT_FALSE(omnibox_view()->base_text_is_emphasized());
-  EXPECT_EQ(gfx::Range(0, 4), omnibox_view()->emphasis_range());
-}
+TEST_F(OmniboxViewViewsTest, Emphasis) {
+  constexpr struct {
+    const char* input;
+    bool expected_base_text_emphasized;
+    Range expected_emphasis_range;
+    Range expected_scheme_range;
+  } test_cases[] = {
+      {"data:text/html,Hello%20World", false, Range(0, 4), Range(0, 4)},
+      {"http://www.example.com/path/file.htm", false, Range(7, 22),
+       Range(0, 4)},
+      {"https://www.example.com/path/file.htm", false, Range(8, 23),
+       Range(0, 5)},
+      {"chrome-extension://ldfbacdbackkjhclmhnjabngnppnkagl", false,
+       Range::InvalidRange(), Range(0, 16)},
+      {"nosuchscheme://opaque/string", true, Range::InvalidRange(),
+       Range(0, 12)},
+      {"nosuchscheme:opaquestring", true, Range::InvalidRange(), Range(0, 12)},
+      {"host.com/path/file", false, Range(0, 8), Range::InvalidRange()},
+      {"This is plain text", true, Range::InvalidRange(),
+       Range::InvalidRange()},
+  };
 
-// Ensure that the origin is emphasized for http: URLs.
-TEST_F(OmniboxViewViewsTest, TestEmphasisForHTTP) {
-  SetAndEmphasizeText("http://www.example.com/path/file.htm");
-  EXPECT_EQ(gfx::Range(0, 4), omnibox_view()->scheme_range());
-  EXPECT_FALSE(omnibox_view()->base_text_is_emphasized());
-  EXPECT_EQ(gfx::Range(7, 22), omnibox_view()->emphasis_range());
-}
+  for (const auto& test_case : test_cases) {
+    SCOPED_TRACE(test_case.input);
 
-// Ensure that the origin is emphasized for https: URLs.
-TEST_F(OmniboxViewViewsTest, TestEmphasisForHTTPS) {
-  SetAndEmphasizeText("https://www.example.com/path/file.htm");
-  EXPECT_EQ(gfx::Range(0, 5), omnibox_view()->scheme_range());
-  EXPECT_FALSE(omnibox_view()->base_text_is_emphasized());
-  EXPECT_EQ(gfx::Range(8, 23), omnibox_view()->emphasis_range());
-}
-
-// Ensure that nothing is emphasized for chrome-extension: URLs.
-TEST_F(OmniboxViewViewsTest, TestEmphasisForChromeExtensionScheme) {
-  SetAndEmphasizeText("chrome-extension://ldfbacdbackkjhclmhnjabngnppnkagl");
-  EXPECT_EQ(gfx::Range(0, 16), omnibox_view()->scheme_range());
-  EXPECT_FALSE(omnibox_view()->base_text_is_emphasized());
-  EXPECT_EQ(gfx::Range(), omnibox_view()->emphasis_range());
-}
-
-// Ensure that everything is emphasized for unknown scheme hierarchical URLs.
-TEST_F(OmniboxViewViewsTest, TestEmphasisForUnknownHierarchicalScheme) {
-  SetAndEmphasizeText("nosuchscheme://opaque/string");
-  EXPECT_EQ(gfx::Range(0, 12), omnibox_view()->scheme_range());
-  EXPECT_TRUE(omnibox_view()->base_text_is_emphasized());
-  EXPECT_EQ(gfx::Range(), omnibox_view()->emphasis_range());
-}
-
-// Ensure that everything is emphasized for unknown scheme URLs.
-TEST_F(OmniboxViewViewsTest, TestEmphasisForUnknownScheme) {
-  SetAndEmphasizeText("nosuchscheme:opaquestring");
-  EXPECT_EQ(gfx::Range(0, 12), omnibox_view()->scheme_range());
-  EXPECT_TRUE(omnibox_view()->base_text_is_emphasized());
-  EXPECT_EQ(gfx::Range(), omnibox_view()->emphasis_range());
-}
-
-// Ensure that the origin is emphasized for URL-like text.
-TEST_F(OmniboxViewViewsTest, TestEmphasisForPartialURLs) {
-  SetAndEmphasizeText("example/path/file");
-  EXPECT_EQ(gfx::Range(), omnibox_view()->scheme_range());
-  EXPECT_FALSE(omnibox_view()->base_text_is_emphasized());
-  EXPECT_EQ(gfx::Range(0, 7), omnibox_view()->emphasis_range());
-}
-
-// Ensure that everything is emphasized for plain text.
-TEST_F(OmniboxViewViewsTest, TestEmphasisForNonURLs) {
-  SetAndEmphasizeText("This is plain text");
-
-  EXPECT_EQ(gfx::Range(), omnibox_view()->scheme_range());
-  EXPECT_TRUE(omnibox_view()->base_text_is_emphasized());
-  EXPECT_EQ(gfx::Range(), omnibox_view()->emphasis_range());
+    SetAndEmphasizeText(test_case.input);
+    EXPECT_EQ(TestingOmniboxView::to_base_text_emphasis(
+                  test_case.expected_base_text_emphasized),
+              omnibox_view()->base_text_emphasis());
+    EXPECT_EQ(test_case.expected_emphasis_range,
+              omnibox_view()->emphasis_range());
+    EXPECT_EQ(test_case.expected_scheme_range, omnibox_view()->scheme_range());
+  }
 }
diff --git a/components/rappor/log_uploader.cc b/components/rappor/log_uploader.cc
index 7f2f0f79..4f36aee 100644
--- a/components/rappor/log_uploader.cc
+++ b/components/rappor/log_uploader.cc
@@ -13,6 +13,7 @@
 #include "components/data_use_measurement/core/data_use_user_data.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_fetcher.h"
 
 namespace {
@@ -113,8 +114,34 @@
     return;
   DVLOG(2) << "Upload to " << server_url_.spec() << " starting.";
   has_callback_pending_ = true;
-  current_fetch_ =
-      net::URLFetcher::Create(server_url_, net::URLFetcher::POST, this);
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("rappor_report", R"(
+        semantics {
+          sender: "RAPPOR"
+          description:
+            "This service sends RAPPOR anonymous usage statistics to Google."
+          trigger:
+            "Reports are automatically generated on startup and at intervals "
+            "while Chromium is running."
+          data: "A protocol buffer with RAPPOR anonymous usage statistics."
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: false
+          setting:
+            "Users can enable or disable this feature by stopping "
+            "'Automatically send usage statistics and crash reports to Google'"
+            "in Chromium's settings under Advanced Settings, Privacy. The "
+            "feature is enabled by default."
+          policy {
+            MetricsReportingEnabled {
+              policy_options {mode: MANDATORY}
+              MetricsReportingEnabled: false
+            }
+          }
+        })");
+  current_fetch_ = net::URLFetcher::Create(server_url_, net::URLFetcher::POST,
+                                           this, traffic_annotation);
   data_use_measurement::DataUseUserData::AttachToFetcher(
       current_fetch_.get(), data_use_measurement::DataUseUserData::RAPPOR);
   current_fetch_->SetRequestContext(request_context_.get());
diff --git a/content/browser/notifications/OWNERS b/content/browser/notifications/OWNERS
index f525291..2f61331 100644
--- a/content/browser/notifications/OWNERS
+++ b/content/browser/notifications/OWNERS
@@ -3,8 +3,8 @@
 # //content/child/notifications/
 # //content/test/mock_platform_notification_service.*
 
-johnme@chromium.org
 mkwst@chromium.org
+miguelg@chromium.org
 mvanouwerkerk@chromium.org
 peter@chromium.org
 
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index eaf48f3..8d08043 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -1766,6 +1766,7 @@
   registry->RegisterListPref(pref_names::kInstallAllowList);
   registry->RegisterListPref(pref_names::kInstallDenyList);
   registry->RegisterDictionaryPref(pref_names::kInstallForceList);
+  registry->RegisterDictionaryPref(pref_names::kInstallLoginScreenAppList);
   registry->RegisterListPref(pref_names::kAllowedTypes);
   registry->RegisterBooleanPref(pref_names::kStorageGarbageCollect, false);
   registry->RegisterInt64Pref(pref_names::kLastUpdateCheck, 0);
diff --git a/extensions/browser/pref_names.cc b/extensions/browser/pref_names.cc
index 29c3945..08eb86c 100644
--- a/extensions/browser/pref_names.cc
+++ b/extensions/browser/pref_names.cc
@@ -38,6 +38,8 @@
 const char kInstallAllowList[] = "extensions.install.allowlist";
 const char kInstallDenyList[] = "extensions.install.denylist";
 const char kInstallForceList[] = "extensions.install.forcelist";
+const char kInstallLoginScreenAppList[] =
+    "extensions.install.login_screen_app_list";
 const char kLastChromeVersion[] = "extensions.last_chrome_version";
 const char kLastUpdateCheck[] = "extensions.autoupdate.last_check";
 const char kNativeMessagingBlacklist[] = "native_messaging.blacklist";
diff --git a/extensions/browser/pref_names.h b/extensions/browser/pref_names.h
index e221c35c..6ca1446 100644
--- a/extensions/browser/pref_names.h
+++ b/extensions/browser/pref_names.h
@@ -68,6 +68,13 @@
 // accessed through extensions::ExternalPolicyProvider.
 extern const char kInstallForceList[];
 
+// A list containing apps that Chrome will silently install on the login screen
+// on Chrome OS at startup time. It is a list of strings, each string contains
+// an app ID and an update URL, delimited by a semicolon.
+// This preference is set by an admin policy, and meant to be only
+// accessed through extensions::ExternalPolicyProvider.
+extern const char kInstallLoginScreenAppList[];
+
 // String pref for what version chrome was last time the extension prefs were
 // loaded.
 extern const char kLastChromeVersion[];
diff --git a/ios/chrome/browser/ui/collection_view/collection_view_controller.h b/ios/chrome/browser/ui/collection_view/collection_view_controller.h
index cd8d08c6..3162a35 100644
--- a/ios/chrome/browser/ui/collection_view/collection_view_controller.h
+++ b/ios/chrome/browser/ui/collection_view/collection_view_controller.h
@@ -5,10 +5,11 @@
 #ifndef IOS_CHROME_BROWSER_UI_COLLECTION_VIEW_COLLECTION_VIEW_CONTROLLER_H_
 #define IOS_CHROME_BROWSER_UI_COLLECTION_VIEW_COLLECTION_VIEW_CONTROLLER_H_
 
+#import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
 #import "ios/chrome/browser/ui/material_components/app_bar_presenting.h"
 #import "ios/third_party/material_components_ios/src/components/Collections/src/MaterialCollections.h"
 
-@class CollectionViewModel;
+@class CollectionViewItem;
 
 typedef NS_ENUM(NSInteger, CollectionViewControllerStyle) {
   // A simple collection view controller.
@@ -24,7 +25,8 @@
     : MDCCollectionViewController<AppBarPresenting>
 
 // The model of this controller.
-@property(nonatomic, readonly) CollectionViewModel* collectionViewModel;
+@property(nonatomic, readonly)
+    CollectionViewModel<CollectionViewItem*>* collectionViewModel;
 
 // Initializer with the desired style.
 - (instancetype)initWithStyle:(CollectionViewControllerStyle)style
diff --git a/ios/chrome/browser/ui/collection_view/collection_view_controller.mm b/ios/chrome/browser/ui/collection_view/collection_view_controller.mm
index 75d4fa7a..3914205 100644
--- a/ios/chrome/browser/ui/collection_view/collection_view_controller.mm
+++ b/ios/chrome/browser/ui/collection_view/collection_view_controller.mm
@@ -72,8 +72,8 @@
          inSectionWithIdentifier:(NSInteger)sectionIdentifier {
   for (CollectionViewItem* item in items) {
     NSIndexPath* indexPath =
-        [_collectionViewModel indexPathForItem:item
-                       inSectionWithIdentifier:sectionIdentifier];
+        [self.collectionViewModel indexPathForItem:item
+                           inSectionWithIdentifier:sectionIdentifier];
     MDCCollectionViewCell* cell =
         base::mac::ObjCCastStrict<MDCCollectionViewCell>(
             [self.collectionView cellForItemAtIndexPath:indexPath]);
@@ -99,14 +99,15 @@
   NSArray* sortedIndexPaths =
       [indexPaths sortedArrayUsingSelector:@selector(compare:)];
   for (NSIndexPath* indexPath in [sortedIndexPaths reverseObjectEnumerator]) {
-    NSInteger sectionIdentifier =
-        [_collectionViewModel sectionIdentifierForSection:indexPath.section];
-    NSInteger itemType = [_collectionViewModel itemTypeForIndexPath:indexPath];
+    NSInteger sectionIdentifier = [self.collectionViewModel
+        sectionIdentifierForSection:indexPath.section];
+    NSInteger itemType =
+        [self.collectionViewModel itemTypeForIndexPath:indexPath];
     NSUInteger index =
-        [_collectionViewModel indexInItemTypeForIndexPath:indexPath];
-    [_collectionViewModel removeItemWithType:itemType
-                   fromSectionWithIdentifier:sectionIdentifier
-                                     atIndex:index];
+        [self.collectionViewModel indexInItemTypeForIndexPath:indexPath];
+    [self.collectionViewModel removeItemWithType:itemType
+                       fromSectionWithIdentifier:sectionIdentifier
+                                         atIndex:index];
   }
 }
 
@@ -145,17 +146,18 @@
 
 - (NSInteger)numberOfSectionsInCollectionView:
     (UICollectionView*)collectionView {
-  return [_collectionViewModel numberOfSections];
+  return [self.collectionViewModel numberOfSections];
 }
 
 - (NSInteger)collectionView:(UICollectionView*)collectionView
      numberOfItemsInSection:(NSInteger)section {
-  return [_collectionViewModel numberOfItemsInSection:section];
+  return [self.collectionViewModel numberOfItemsInSection:section];
 }
 
 - (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
                  cellForItemAtIndexPath:(NSIndexPath*)indexPath {
-  CollectionViewItem* item = [_collectionViewModel itemAtIndexPath:indexPath];
+  CollectionViewItem* item =
+      [self.collectionViewModel itemAtIndexPath:indexPath];
   Class cellClass = [item cellClass];
   NSString* reuseIdentifier = NSStringFromClass(cellClass);
   [self.collectionView registerClass:cellClass
@@ -173,10 +175,10 @@
   CollectionViewItem* item = nil;
   UIAccessibilityTraits traits = UIAccessibilityTraitNone;
   if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
-    item = [_collectionViewModel headerForSection:indexPath.section];
+    item = [self.collectionViewModel headerForSection:indexPath.section];
     traits = UIAccessibilityTraitHeader;
   } else if ([kind isEqualToString:UICollectionElementKindSectionFooter]) {
-    item = [_collectionViewModel footerForSection:indexPath.section];
+    item = [self.collectionViewModel footerForSection:indexPath.section];
   } else {
     return [super collectionView:collectionView
         viewForSupplementaryElementOfKind:kind
@@ -203,7 +205,8 @@
                              layout:
                                  (UICollectionViewLayout*)collectionViewLayout
     referenceSizeForHeaderInSection:(NSInteger)section {
-  CollectionViewItem* item = [_collectionViewModel headerForSection:section];
+  CollectionViewItem* item =
+      [self.collectionViewModel headerForSection:section];
 
   if (item) {
     // TODO(crbug.com/635604): Support arbitrary sized headers.
@@ -216,7 +219,8 @@
                              layout:
                                  (UICollectionViewLayout*)collectionViewLayout
     referenceSizeForFooterInSection:(NSInteger)section {
-  CollectionViewItem* item = [_collectionViewModel footerForSection:section];
+  CollectionViewItem* item =
+      [self.collectionViewModel footerForSection:section];
 
   if (item) {
     // TODO(crbug.com/635604): Support arbitrary sized footers.
diff --git a/ios/chrome/browser/ui/collection_view/collection_view_model.h b/ios/chrome/browser/ui/collection_view/collection_view_model.h
index 8a3d6234..0f0613b 100644
--- a/ios/chrome/browser/ui/collection_view/collection_view_model.h
+++ b/ios/chrome/browser/ui/collection_view/collection_view_model.h
@@ -39,8 +39,11 @@
 // Disclaimer: CollectionViewModel doesn't support a batch update logic. All
 // changes are immediately processed (contrary to the reload/delete/add order of
 // UICollectionView's |performBatchUpdates:completion:|).
-
-@interface CollectionViewModel : NSObject
+// The __covariant modifier allows an instance of CollectionViewModel<A> to be
+// assigned to an instance of CollectionViewModel<B> iff A:B (see unit test for
+// an example).
+@interface CollectionViewModel<__covariant ObjectType : CollectionViewItem*>
+    : NSObject
 
 #pragma mark Modification methods
 
@@ -55,12 +58,12 @@
 
 // Adds an item to the section with the given identifier. Adding several times
 // the same item is undefined behavior.
-- (void)addItem:(CollectionViewItem*)item
+- (void)addItem:(ObjectType)item
     toSectionWithIdentifier:(NSInteger)sectionIdentifier;
 
 // Inserts an item to the section with the given identifier at the given index.
 // |index| must not be greater than the count of elements in the section.
-- (void)insertItem:(CollectionViewItem*)item
+- (void)insertItem:(ObjectType)item
     inSectionWithIdentifier:(NSInteger)sectionIdentifier
                     atIndex:(NSUInteger)index;
 
@@ -82,11 +85,11 @@
 - (void)removeSectionWithIdentifier:(NSInteger)sectionIdentifier;
 
 // Sets the header item for the section with the given |sectionIdentifier|.
-- (void)setHeader:(CollectionViewItem*)header
+- (void)setHeader:(ObjectType)header
     forSectionWithIdentifier:(NSInteger)sectionIdentifier;
 
 // Sets the footer item for the section with the given |sectionIdentifier|.
-- (void)setFooter:(CollectionViewItem*)footer
+- (void)setFooter:(ObjectType)footer
     forSectionWithIdentifier:(NSInteger)sectionIdentifier;
 
 #pragma mark Query model coordinates from index paths
@@ -112,24 +115,23 @@
 - (BOOL)hasItemAtIndexPath:(NSIndexPath*)indexPath;
 
 // Returns the item at the given index path.
-- (CollectionViewItem*)itemAtIndexPath:(NSIndexPath*)indexPath;
+- (ObjectType)itemAtIndexPath:(NSIndexPath*)indexPath;
 
 // Returns the header for the given |section|.
-- (CollectionViewItem*)headerForSection:(NSInteger)section;
+- (ObjectType)headerForSection:(NSInteger)section;
 
 // Returns the footer for the given |section|.
-- (CollectionViewItem*)footerForSection:(NSInteger)section;
+- (ObjectType)footerForSection:(NSInteger)section;
 
 // Returns an array of items in the section with the given identifier.
-- (NSArray*)itemsInSectionWithIdentifier:(NSInteger)sectionIdentifier;
+- (NSArray<ObjectType>*)itemsInSectionWithIdentifier:
+    (NSInteger)sectionIdentifier;
 
 // Returns the header for the section with the given |sectionIdentifier|.
-- (CollectionViewItem*)headerForSectionWithIdentifier:
-    (NSInteger)sectionIdentifier;
+- (ObjectType)headerForSectionWithIdentifier:(NSInteger)sectionIdentifier;
 
 // Returns the footer for the section with the given |sectionIdentifier|.
-- (CollectionViewItem*)footerForSectionWithIdentifier:
-    (NSInteger)sectionIdentifier;
+- (ObjectType)footerForSectionWithIdentifier:(NSInteger)sectionIdentifier;
 
 #pragma mark Query index paths from model coordinates
 
@@ -165,11 +167,11 @@
 #pragma mark Query index paths from items
 
 // Returns whether |item| exists in section for |sectionIdentifier|.
-- (BOOL)hasItem:(CollectionViewItem*)item
+- (BOOL)hasItem:(ObjectType)item
     inSectionWithIdentifier:(NSInteger)sectionIdentifier;
 
 // Returns the index path corresponding to the given |item|.
-- (NSIndexPath*)indexPathForItem:(CollectionViewItem*)itemType
+- (NSIndexPath*)indexPathForItem:(ObjectType)item
          inSectionWithIdentifier:(NSInteger)sectionIdentifier;
 
 #pragma mark UICollectionView data sourcing
diff --git a/ios/chrome/browser/ui/collection_view/collection_view_model.mm b/ios/chrome/browser/ui/collection_view/collection_view_model.mm
index 9132bde..d57b258c 100644
--- a/ios/chrome/browser/ui/collection_view/collection_view_model.mm
+++ b/ios/chrome/browser/ui/collection_view/collection_view_model.mm
@@ -178,7 +178,8 @@
   return [_footers objectForKey:key];
 }
 
-- (NSArray*)itemsInSectionWithIdentifier:(NSInteger)sectionIdentifier {
+- (NSArray<CollectionViewItem*>*)itemsInSectionWithIdentifier:
+    (NSInteger)sectionIdentifier {
   NSInteger section = [self sectionForSectionIdentifier:sectionIdentifier];
   DCHECK_LT(static_cast<NSUInteger>(section), [_sections count]);
   return [_sections objectAtIndex:section];
diff --git a/ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm b/ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm
index 437f5d5e..ae764af 100644
--- a/ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm
+++ b/ios/chrome/browser/ui/collection_view/collection_view_model_unittest.mm
@@ -31,6 +31,11 @@
 
 @end
 
+@interface TestCollectionViewItemSubclass : CollectionViewItem
+@end
+@implementation TestCollectionViewItemSubclass
+@end
+
 namespace {
 
 typedef NS_ENUM(NSInteger, SectionIdentifier) {
@@ -53,6 +58,18 @@
   // No-op.
 }
 
+// Test generic model boxing (check done at compilation time).
+TEST(CollectionViewModelTest, GenericModelBoxing) {
+  CollectionViewModel<TestCollectionViewItemSubclass*>* specificModel =
+      [[CollectionViewModel alloc] init];
+
+  // |generalModel| is a superclass of |specificModel|. So specificModel can be
+  // boxed into generalModel, but not the other way around.
+  // specificModel = generalModel would not compile.
+  CollectionViewModel<CollectionViewItem*>* generalModel = specificModel;
+  generalModel = nil;
+}
+
 TEST(CollectionViewModelTest, EmptyModel) {
   CollectionViewModel* model = [[CollectionViewModel alloc] init];
 
diff --git a/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-9-expected.txt b/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-9-expected.txt
new file mode 100644
index 0000000..97a77c6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-9-expected.txt
@@ -0,0 +1 @@
+<html><head></head><body><div class="line-gutter-backdrop"></div><table><tbody><tr><td class="line-number" value="1"></td><td class="line-content"><span class="html-doctype">&lt;!DOCTYPE html&gt;</span></td></tr><tr><td class="line-number" value="2"></td><td class="line-content"><span class="html-tag">&lt;head&gt;</span></td></tr><tr><td class="line-number" value="3"></td><td class="line-content"><span class="html-tag">&lt;title&gt;</span>Test<span class="html-tag">&lt;/title&gt;</span></td></tr><tr><td class="line-number" value="4"></td><td class="line-content"><span class="html-tag">&lt;script <span class="html-attribute-name">type</span>="<span class="html-attribute-value">text/javascript</span>"&gt;</span></td></tr><tr><td class="line-number" value="5"></td><td class="line-content">"&lt;!--  --!&gt;&lt;script&gt;";</td></tr><tr><td class="line-number" value="6"></td><td class="line-content"><span class="html-end-of-file"></span></td></tr></tbody></table></body></html>
diff --git a/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-9.html b/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-9.html
new file mode 100644
index 0000000..c9c0fe5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/frames/viewsource/viewsource-9.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<head>
+<title>Test</title>
+<script type="text/javascript">
+"<!--  --!><script>";
diff --git a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp
index f35884b..5c35110 100644
--- a/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp
+++ b/third_party/WebKit/Source/core/html/AutoplayUmaHelper.cpp
@@ -322,13 +322,7 @@
       std::min<int64_t>(m_mutedVideoAutoplayOffscreenDurationMS,
                         std::numeric_limits<int32_t>::max()));
 
-  if (m_source == AutoplaySource::Attribute) {
-    DEFINE_STATIC_LOCAL(
-        CustomCountHistogram, durationHistogram,
-        ("Media.Video.Autoplay.Muted.Attribute.OffscreenDuration", 1,
-         maxOffscreenDurationUmaMS, offscreenDurationUmaBucketCount));
-    durationHistogram.count(boundedTime);
-  } else {
+  if (m_source == AutoplaySource::Method) {
     DEFINE_STATIC_LOCAL(
         CustomCountHistogram, durationHistogram,
         ("Media.Video.Autoplay.Muted.PlayMethod.OffscreenDuration", 1,
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLSourceTracker.cpp b/third_party/WebKit/Source/core/html/parser/HTMLSourceTracker.cpp
index aaec23e5..e4e329fb 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLSourceTracker.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLSourceTracker.cpp
@@ -37,10 +37,12 @@
                               HTMLToken& token) {
   if (token.type() == HTMLToken::Uninitialized && !m_isStarted) {
     m_previousSource.clear();
-    if (tokenizer->numberOfBufferedCharacters())
+    if (needToCheckTokenizerBuffer(tokenizer) &&
+        tokenizer->numberOfBufferedCharacters())
       m_previousSource = tokenizer->bufferedCharacters();
-  } else
+  } else {
     m_previousSource.append(m_currentSource);
+  }
 
   m_isStarted = true;
   m_currentSource = currentInput;
@@ -56,8 +58,12 @@
   m_cachedSourceForToken = String();
 
   // FIXME: This work should really be done by the HTMLTokenizer.
+  size_t numberOfBufferedCharacters = 0u;
+  if (needToCheckTokenizerBuffer(tokenizer)) {
+    numberOfBufferedCharacters = tokenizer->numberOfBufferedCharacters();
+  }
   token.end(currentInput.numberOfCharactersConsumed() -
-            tokenizer->numberOfBufferedCharacters());
+            numberOfBufferedCharacters);
 }
 
 String HTMLSourceTracker::sourceForToken(const HTMLToken& token) {
@@ -92,4 +98,13 @@
   return m_cachedSourceForToken;
 }
 
+bool HTMLSourceTracker::needToCheckTokenizerBuffer(HTMLTokenizer* tokenizer) {
+  HTMLTokenizer::State state = tokenizer->getState();
+  // The temporary buffer must not be used unconditionally, because in some
+  // states (e.g. ScriptDataDoubleEscapedStartState), data is appended to
+  // both the temporary buffer and the token itself.
+  return state == HTMLTokenizer::DataState ||
+         HTMLTokenizer::isEndTagBufferingState(state);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLSourceTracker.h b/third_party/WebKit/Source/core/html/parser/HTMLSourceTracker.h
index c2cd289..a6aa449 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLSourceTracker.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLSourceTracker.h
@@ -50,6 +50,8 @@
   String sourceForToken(const HTMLToken&);
 
  private:
+  bool needToCheckTokenizerBuffer(HTMLTokenizer*);
+
   SegmentedString m_previousSource;
   SegmentedString m_currentSource;
 
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp b/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp
index f088cf0..2e1d501 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.cpp
@@ -61,22 +61,6 @@
   return equal(string.impl(), vector.data(), vector.size());
 }
 
-static inline bool isEndTagBufferingState(HTMLTokenizer::State state) {
-  switch (state) {
-    case HTMLTokenizer::RCDATAEndTagOpenState:
-    case HTMLTokenizer::RCDATAEndTagNameState:
-    case HTMLTokenizer::RAWTEXTEndTagOpenState:
-    case HTMLTokenizer::RAWTEXTEndTagNameState:
-    case HTMLTokenizer::ScriptDataEndTagOpenState:
-    case HTMLTokenizer::ScriptDataEndTagNameState:
-    case HTMLTokenizer::ScriptDataEscapedEndTagOpenState:
-    case HTMLTokenizer::ScriptDataEscapedEndTagNameState:
-      return true;
-    default:
-      return false;
-  }
-}
-
 #define HTML_BEGIN_STATE(stateName) BEGIN_STATE(HTMLTokenizer, stateName)
 #define HTML_RECONSUME_IN(stateName) RECONSUME_IN(HTMLTokenizer, stateName)
 #define HTML_ADVANCE_TO(stateName) ADVANCE_TO(HTMLTokenizer, stateName)
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.h b/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.h
index c8ce59d..50b3717 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLTokenizer.h
@@ -180,6 +180,22 @@
             m_state == HTMLTokenizer::RAWTEXTState);
   }
 
+  inline static bool isEndTagBufferingState(HTMLTokenizer::State state) {
+    switch (state) {
+      case HTMLTokenizer::RCDATAEndTagOpenState:
+      case HTMLTokenizer::RCDATAEndTagNameState:
+      case HTMLTokenizer::RAWTEXTEndTagOpenState:
+      case HTMLTokenizer::RAWTEXTEndTagNameState:
+      case HTMLTokenizer::ScriptDataEndTagOpenState:
+      case HTMLTokenizer::ScriptDataEndTagNameState:
+      case HTMLTokenizer::ScriptDataEscapedEndTagOpenState:
+      case HTMLTokenizer::ScriptDataEscapedEndTagNameState:
+        return true;
+      default:
+        return false;
+    }
+  }
+
  private:
   explicit HTMLTokenizer(const HTMLParserOptions&);
 
diff --git a/third_party/WebKit/Source/core/loader/LinkLoader.cpp b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
index f20e490..bd2ba72 100644
--- a/third_party/WebKit/Source/core/loader/LinkLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
@@ -46,10 +46,10 @@
 #include "core/loader/resource/LinkFetchResource.h"
 #include "platform/Prerender.h"
 #include "platform/Timer.h"
+#include "platform/loader/LinkHeader.h"
 #include "platform/loader/fetch/FetchInitiatorTypeNames.h"
 #include "platform/loader/fetch/FetchRequest.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
-#include "platform/network/LinkHeader.h"
 #include "platform/network/mime/MIMETypeRegistry.h"
 #include "public/platform/WebPrerender.h"
 
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index b1fae210..407d8cd 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1108,8 +1108,6 @@
     "network/HTTPHeaderMap.h",
     "network/HTTPParsers.cpp",
     "network/HTTPParsers.h",
-    "network/LinkHeader.cpp",
-    "network/LinkHeader.h",
     "network/NetworkHints.cpp",
     "network/NetworkHints.h",
     "network/NetworkInstrumentation.cpp",
@@ -1436,7 +1434,6 @@
   ]
   deps = [
     "//cc/surfaces:surfaces",
-    "//components/link_header_util:link_header_util",
     "//components/mime_util:mime_util",
     "//device/base/synchronization",
     "//mojo/public/cpp/bindings",
@@ -1749,6 +1746,7 @@
     "instrumentation/tracing/web_process_memory_dump_test.cc",
     "json/JSONParserTest.cpp",
     "json/JSONValuesTest.cpp",
+    "loader/LinkHeaderTest.cpp",
     "loader/fetch/ClientHintsPreferencesTest.cpp",
     "loader/fetch/CrossOriginAccessControlTest.cpp",
     "loader/fetch/FetchUtilsTest.cpp",
@@ -1765,7 +1763,6 @@
     "mojo/KURLSecurityOriginTest.cpp",
     "network/EncodedFormDataTest.cpp",
     "network/HTTPParsersTest.cpp",
-    "network/LinkHeaderTest.cpp",
     "network/NetworkStateNotifierTest.cpp",
     "network/NetworkUtilsTest.cpp",
     "network/ParsedContentTypeTest.cpp",
diff --git a/third_party/WebKit/Source/platform/loader/BUILD.gn b/third_party/WebKit/Source/platform/loader/BUILD.gn
index a9b009f..a250638d 100644
--- a/third_party/WebKit/Source/platform/loader/BUILD.gn
+++ b/third_party/WebKit/Source/platform/loader/BUILD.gn
@@ -19,6 +19,8 @@
   visibility = [ "//third_party/WebKit/Source/platform" ]
 
   sources = [
+    "LinkHeader.cpp",
+    "LinkHeader.h",
     "fetch/AccessControlStatus.h",
     "fetch/CachedMetadata.cpp",
     "fetch/CachedMetadata.h",
@@ -72,6 +74,7 @@
 
   deps = [
     ":make_platform_loader_generated_fetch_initiator_type_names",
+    "//components/link_header_util:link_header_util",
   ]
 
   public_deps = [
diff --git a/third_party/WebKit/Source/platform/loader/DEPS b/third_party/WebKit/Source/platform/loader/DEPS
new file mode 100644
index 0000000..430408b1
--- /dev/null
+++ b/third_party/WebKit/Source/platform/loader/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+    "+components/link_header_util"  # for LinkHeader.cpp
+]
diff --git a/third_party/WebKit/Source/platform/network/LinkHeader.cpp b/third_party/WebKit/Source/platform/loader/LinkHeader.cpp
similarity index 98%
rename from third_party/WebKit/Source/platform/network/LinkHeader.cpp
rename to third_party/WebKit/Source/platform/loader/LinkHeader.cpp
index 173d1c8..5b0c7de 100644
--- a/third_party/WebKit/Source/platform/network/LinkHeader.cpp
+++ b/third_party/WebKit/Source/platform/loader/LinkHeader.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "platform/network/LinkHeader.h"
+#include "platform/loader/LinkHeader.h"
 
 #include "base/strings/string_util.h"
 #include "components/link_header_util/link_header_util.h"
diff --git a/third_party/WebKit/Source/platform/network/LinkHeader.h b/third_party/WebKit/Source/platform/loader/LinkHeader.h
similarity index 100%
rename from third_party/WebKit/Source/platform/network/LinkHeader.h
rename to third_party/WebKit/Source/platform/loader/LinkHeader.h
diff --git a/third_party/WebKit/Source/platform/network/LinkHeaderTest.cpp b/third_party/WebKit/Source/platform/loader/LinkHeaderTest.cpp
similarity index 99%
rename from third_party/WebKit/Source/platform/network/LinkHeaderTest.cpp
rename to third_party/WebKit/Source/platform/loader/LinkHeaderTest.cpp
index 4c23d31f..b6bcf51 100644
--- a/third_party/WebKit/Source/platform/network/LinkHeaderTest.cpp
+++ b/third_party/WebKit/Source/platform/loader/LinkHeaderTest.cpp
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "platform/network/LinkHeader.h"
+#include "platform/loader/LinkHeader.h"
 
-#include "testing/gtest/include/gtest/gtest.h"
 #include <base/macros.h>
+#include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
 namespace {
diff --git a/third_party/WebKit/Source/platform/network/DEPS b/third_party/WebKit/Source/platform/network/DEPS
index 8165dd6..a259d87 100644
--- a/third_party/WebKit/Source/platform/network/DEPS
+++ b/third_party/WebKit/Source/platform/network/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
-    "+components/link_header_util",
     "+components/mime_util",
     "+media",
     "-media/blink",
diff --git a/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
index d9f5851..3676ceeb 100755
--- a/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
+++ b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
@@ -22,6 +22,7 @@
 sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'catapult', 'devil'))
 from devil.android import device_errors
 from devil.android import device_utils
+from devil.android import flag_changer
 from devil.android.perf import cache_control
 from devil.android.sdk import intent
 
@@ -70,7 +71,8 @@
   logcat_timeout = int(timeout_s + delay_to_may_launch_url / 1000.
                        + delay_to_launch_url / 1000.) + 3;
 
-  with device_setup.FlagReplacer(device, _COMMAND_LINE_FILE, chrome_args):
+  with flag_changer.CustomCommandLineFlags(
+      device, _COMMAND_LINE_FILE, chrome_args):
     launch_intent = intent.Intent(
         action='android.intent.action.MAIN',
         package=_TEST_APP_PACKAGE_NAME,
diff --git a/tools/android/loading/controller.py b/tools/android/loading/controller.py
index b15b62d..0cad7f15 100644
--- a/tools/android/loading/controller.py
+++ b/tools/android/loading/controller.py
@@ -40,6 +40,7 @@
 
 sys.path.append(os.path.join(_CATAPULT_DIR, 'devil'))
 from devil.android import device_errors
+from devil.android import flag_changer
 from devil.android.sdk import intent
 
 sys.path.append(
@@ -325,7 +326,7 @@
           'Remote controller doesn\'t support chrome environment variables.'
     package_info = OPTIONS.ChromePackage()
     self._device.ForceStop(package_info.package)
-    with device_setup.FlagReplacer(
+    with flag_changer.CustomCommandLineFlags(
         self._device, package_info.cmdline_file, self._GetChromeArguments()):
       self._DismissCrashDialogIfNeeded()
       start_intent = intent.Intent(
diff --git a/tools/android/loading/device_setup.py b/tools/android/loading/device_setup.py
index e39ab86..19e0d99 100644
--- a/tools/android/loading/device_setup.py
+++ b/tools/android/loading/device_setup.py
@@ -18,7 +18,6 @@
 _CATAPULT_DIR = os.path.join(_SRC_DIR, 'third_party', 'catapult')
 sys.path.append(os.path.join(_CATAPULT_DIR, 'devil'))
 from devil.android import device_utils
-from devil.android import flag_changer
 from devil.android import forwarder
 from devil.android.sdk import adb_wrapper
 from devil.android.sdk import intent
@@ -121,29 +120,6 @@
 
 
 @contextlib.contextmanager
-def FlagReplacer(device, command_line_path, new_flags):
-  """Replaces chrome flags in a context, restores them afterwards.
-
-  Args:
-    device: Device to target, from DeviceUtils. Can be None, in which case this
-      context manager is a no-op.
-    command_line_path: Full path to the command-line file.
-    new_flags: Flags to replace.
-  """
-  # If we're logging requests from a local desktop chrome instance there is no
-  # device.
-  if not device:
-    yield
-    return
-  changer = flag_changer.FlagChanger(device, command_line_path)
-  changer.ReplaceFlags(new_flags)
-  try:
-    yield
-  finally:
-    changer.Restore()
-
-
-@contextlib.contextmanager
 def ForwardPort(device, local, remote):
   """Forwards a local port to a remote one on a device in a context."""
   # If we're logging requests from a local desktop chrome instance there is no
diff --git a/tools/android/loading/wpr_helper.py b/tools/android/loading/wpr_helper.py
index ab655a59..b509d117b 100755
--- a/tools/android/loading/wpr_helper.py
+++ b/tools/android/loading/wpr_helper.py
@@ -17,6 +17,7 @@
 
 sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'catapult', 'devil'))
 from devil.android import device_utils
+from devil.android import flag_changer
 from devil.android.constants import chrome
 from devil.android.perf import cache_control
 from devil.android.sdk import intent
@@ -42,7 +43,7 @@
 
   cmdline_file = package_info.cmdline_file
   package = package_info.package
-  with device_setup.FlagReplacer(device, cmdline_file, chrome_args):
+  with flag_changer.CustomCommandLineFlags(device, cmdline_file, chrome_args):
     device.ForceStop(package)
 
     if cold:
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index ee7faf7..7a57cf1 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -27220,6 +27220,10 @@
 
 <histogram name="Media.Video.Autoplay.Muted.Attribute.OffscreenDuration"
     units="ms">
+  <obsolete>
+    Deprecated as autoplay muted video by attributed is paused when going
+    offscreen since https://crbug.com/683141.
+  </obsolete>
   <owner>avayvod@chromium.org</owner>
   <owner>mlamouri@chromium.org</owner>
   <owner>zqzhang@chromium.org</owner>
diff --git a/tools/resource_prefetch_predictor/prefetch_benchmark.py b/tools/resource_prefetch_predictor/prefetch_benchmark.py
index e31bd1d..fae9d24 100755
--- a/tools/resource_prefetch_predictor/prefetch_benchmark.py
+++ b/tools/resource_prefetch_predictor/prefetch_benchmark.py
@@ -29,6 +29,7 @@
 import devil_chromium
 
 sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'catapult', 'devil'))
+from devil.android import flag_changer
 from devil.android.sdk import intent
 
 import prefetch_predictor_common
@@ -68,7 +69,7 @@
 
   # Make sure that the speculative prefetch predictor is enabled to ensure
   # that the disk database is re-created.
-  with device_setup.FlagReplacer(
+  with flag_changer.CustomCommandLineFlags(
       device, chrome_package.cmdline_file, ['--disable-fre']):
     # Launch Chrome for the first time to recreate the local state.
     launch_intent = intent.Intent(