Rename the usage of Problematic Programs to Incompatible Applications

This is to make the terminology consistent for all the classes related
to the Incompatible Applications Warning, which is the name used in
the UI.

Tbr: [email protected],[email protected], [email protected]
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: Id4ec87a73d67985458f38d623b7f10a4979d594b
Reviewed-on: https://chromium-review.googlesource.com/993699
Commit-Queue: Patrick Monette <[email protected]>
Reviewed-by: Peter Kasting <[email protected]>
Reviewed-by: Demetrios Papadopoulos <[email protected]>
Reviewed-by: Dominic Battré <[email protected]>
Cr-Commit-Position: refs/heads/master@{#557664}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index fc2ec3d5..2aeab74 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3012,14 +3012,14 @@
       sources += [
         "component_updater/third_party_module_list_component_installer_win.cc",
         "component_updater/third_party_module_list_component_installer_win.h",
-        "conflicts/installed_programs_win.cc",
-        "conflicts/installed_programs_win.h",
+        "conflicts/incompatible_applications_updater_win.cc",
+        "conflicts/incompatible_applications_updater_win.h",
+        "conflicts/installed_applications_win.cc",
+        "conflicts/installed_applications_win.h",
         "conflicts/module_list_filter_win.cc",
         "conflicts/module_list_filter_win.h",
         "conflicts/msi_util_win.cc",
         "conflicts/msi_util_win.h",
-        "conflicts/problematic_programs_updater_win.cc",
-        "conflicts/problematic_programs_updater_win.h",
         "conflicts/registry_key_watcher_win.cc",
         "conflicts/registry_key_watcher_win.h",
         "conflicts/third_party_conflicts_manager_win.cc",
diff --git a/chrome/browser/conflicts/incompatible_applications_browsertest.cc b/chrome/browser/conflicts/incompatible_applications_browsertest.cc
index 701eb30..ee49e8f 100644
--- a/chrome/browser/conflicts/incompatible_applications_browsertest.cc
+++ b/chrome/browser/conflicts/incompatible_applications_browsertest.cc
@@ -16,8 +16,8 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/win/windows_version.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/conflicts/incompatible_applications_updater_win.h"
 #include "chrome/browser/conflicts/module_database_win.h"
-#include "chrome/browser/conflicts/problematic_programs_updater_win.h"
 #include "chrome/browser/conflicts/proto/module_list.pb.h"
 #include "chrome/browser/conflicts/third_party_conflicts_manager_win.h"
 #include "chrome/common/chrome_features.h"
@@ -26,28 +26,28 @@
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
 
-// This class allows to wait until the kProblematicPrograms preference is
-// modified. This can only happen if a new problematic program is found, since
-// the pref starts empty during testing.
+// This class allows to wait until the kIncompatibleApplications preference is
+// modified. This can only happen if a new incompatible application is found,
+// since the pref starts empty during testing.
 //
 // Note: The browser process must be initialized before the creation of an
 // instance of this class.
-class ProblematicProgramsObserver {
+class IncompatibleApplicationsObserver {
  public:
-  ProblematicProgramsObserver() {
+  IncompatibleApplicationsObserver() {
     pref_change_registrar_.Init(g_browser_process->local_state());
     pref_change_registrar_.Add(
-        prefs::kProblematicPrograms,
-        base::BindRepeating(
-            &ProblematicProgramsObserver::OnProblematicProgramsChanged,
-            base::Unretained(this)));
+        prefs::kIncompatibleApplications,
+        base::BindRepeating(&IncompatibleApplicationsObserver::
+                                OnIncompatibleApplicationsChanged,
+                            base::Unretained(this)));
   }
 
-  ~ProblematicProgramsObserver() = default;
+  ~IncompatibleApplicationsObserver() = default;
 
-  // Wait until the kProblematicPrograms preference is modified.
-  void WaitForProblematicProgramsChanged() {
-    if (problematic_programs_changed_)
+  // Wait until the kIncompatibleApplications preference is modified.
+  void WaitForIncompatibleApplicationsChanged() {
+    if (incompatible_applications_changed_)
       return;
 
     base::RunLoop run_loop;
@@ -57,26 +57,26 @@
 
  private:
   // Callback for |pref_change_registrar_|.
-  void OnProblematicProgramsChanged() {
-    problematic_programs_changed_ = true;
+  void OnIncompatibleApplicationsChanged() {
+    incompatible_applications_changed_ = true;
 
     if (run_loop_quit_closure_)
       std::move(run_loop_quit_closure_).Run();
   }
 
-  bool problematic_programs_changed_ = false;
+  bool incompatible_applications_changed_ = false;
 
   PrefChangeRegistrar pref_change_registrar_;
 
   base::RepeatingClosure run_loop_quit_closure_;
 
-  DISALLOW_COPY_AND_ASSIGN(ProblematicProgramsObserver);
+  DISALLOW_COPY_AND_ASSIGN(IncompatibleApplicationsObserver);
 };
 
 class IncompatibleApplicationsBrowserTest : public InProcessBrowserTest {
  protected:
-  // The name of the program deemed incompatible.
-  static constexpr wchar_t kProgramName[] = L"FooBar123";
+  // The name of the application deemed incompatible.
+  static constexpr wchar_t kApplicationName[] = L"FooBar123";
 
   IncompatibleApplicationsBrowserTest() = default;
   ~IncompatibleApplicationsBrowserTest() override = default;
@@ -96,7 +96,7 @@
         {});
 
     ASSERT_NO_FATAL_FAILURE(CreateModuleList());
-    ASSERT_NO_FATAL_FAILURE(InstallThirdPartyProgram());
+    ASSERT_NO_FATAL_FAILURE(InstallThirdPartyApplication());
 
     InProcessBrowserTest::SetUp();
   }
@@ -109,7 +109,7 @@
   // Returns the path to the DLL that is injected into the process.
   base::FilePath GetDllPath() const {
     return scoped_temp_dir_.GetPath()
-        .Append(kProgramName)
+        .Append(kApplicationName)
         .Append(L"foo_bar.dll");
   }
 
@@ -128,9 +128,9 @@
               static_cast<int>(contents.size()));
   }
 
-  // Registers an uninstallation entry for the third-party program, and creates
-  // a DLL meant to be injected into the process.
-  void InstallThirdPartyProgram() {
+  // Registers an uninstallation entry for the third-party application, and
+  // creates a DLL meant to be injected into the process.
+  void InstallThirdPartyApplication() {
     // This module should not be a static dependency of the test executable, but
     // should be a build-system dependency or a module that is present on any
     // Windows machine.
@@ -138,14 +138,14 @@
     static constexpr wchar_t kRegistryKeyPathFormat[] =
         L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%ls";
 
-    // Note: Using the program name for the product id.
+    // Note: Using the application name for the product id.
     const base::string16 registry_key_path =
-        base::StringPrintf(kRegistryKeyPathFormat, kProgramName);
+        base::StringPrintf(kRegistryKeyPathFormat, kApplicationName);
     base::win::RegKey registry_key(HKEY_CURRENT_USER, registry_key_path.c_str(),
                                    KEY_WRITE);
 
     const base::FilePath dll_path = GetDllPath();
-    ASSERT_EQ(registry_key.WriteValue(L"DisplayName", kProgramName),
+    ASSERT_EQ(registry_key.WriteValue(L"DisplayName", kApplicationName),
               ERROR_SUCCESS);
     ASSERT_EQ(registry_key.WriteValue(L"InstallLocation",
                                       dll_path.DirName().value().c_str()),
@@ -157,7 +157,7 @@
         ERROR_SUCCESS);
 
     // Copy the test DLL to the install directory so that it will get associated
-    // with the program by the ProblematicProgramsUpdater.
+    // with the application by the IncompatibleApplicationsUpdater.
     base::FilePath test_dll_path;
     ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &test_dll_path));
     test_dll_path = test_dll_path.Append(kTestDllName);
@@ -169,8 +169,8 @@
   // Temp directory used to host the install directory and the module list.
   base::ScopedTempDir scoped_temp_dir_;
 
-  // Overrides HKLM and HKCU so that the InstalledPrograms instance doesn't pick
-  // up real programs on the test machine.
+  // Overrides HKLM and HKCU so that the InstalledApplications instance doesn't
+  // pick up real applications on the test machine.
   registry_util::RegistryOverrideManager registry_override_manager_;
 
   // The third party conflicts code is gated behind the kModuleDatabase and
@@ -181,7 +181,7 @@
 };
 
 // static
-constexpr wchar_t IncompatibleApplicationsBrowserTest::kProgramName[];
+constexpr wchar_t IncompatibleApplicationsBrowserTest::kApplicationName[];
 
 // This is an integration test for the identification of incompatible
 // applications.
@@ -202,8 +202,8 @@
   module_database->IncreaseInspectionPriority();
 
   // Create the observer early so the change is guaranteed to be observed.
-  auto problematic_programs_observer =
-      std::make_unique<ProblematicProgramsObserver>();
+  auto incompatible_applications_observer =
+      std::make_unique<IncompatibleApplicationsObserver>();
 
   // Simulate the download of the module list component.
   module_database->third_party_conflicts_manager()->LoadModuleList(
@@ -214,15 +214,16 @@
   base::ScopedNativeLibrary dll(GetDllPath());
   ASSERT_TRUE(dll.is_valid());
 
-  // Wait until the program gets marked as problematic.
-  problematic_programs_observer->WaitForProblematicProgramsChanged();
+  // Wait until the application gets marked as problematic.
+  incompatible_applications_observer->WaitForIncompatibleApplicationsChanged();
 
   // Verify the cache.
-  EXPECT_TRUE(ProblematicProgramsUpdater::HasCachedPrograms());
-  auto problematic_programs = ProblematicProgramsUpdater::GetCachedPrograms();
-  ASSERT_EQ(problematic_programs.size(), 1u);
-  const auto& problematic_program = problematic_programs[0];
-  EXPECT_EQ(problematic_program.info.name, kProgramName);
-  EXPECT_EQ(problematic_program.blacklist_action->message_type(),
+  EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
+  auto incompatible_applications =
+      IncompatibleApplicationsUpdater::GetCachedApplications();
+  ASSERT_EQ(incompatible_applications.size(), 1u);
+  const auto& incompatible_application = incompatible_applications[0];
+  EXPECT_EQ(incompatible_application.info.name, kApplicationName);
+  EXPECT_EQ(incompatible_application.blacklist_action->message_type(),
             chrome::conflicts::BlacklistMessageType::UNINSTALL);
 }
diff --git a/chrome/browser/conflicts/incompatible_applications_updater_win.cc b/chrome/browser/conflicts/incompatible_applications_updater_win.cc
new file mode 100644
index 0000000..0dc9a02
--- /dev/null
+++ b/chrome/browser/conflicts/incompatible_applications_updater_win.cc
@@ -0,0 +1,345 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/conflicts/incompatible_applications_updater_win.h"
+
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "base/win/registry.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/conflicts/module_database_win.h"
+#include "chrome/browser/conflicts/module_info_util_win.h"
+#include "chrome/browser/conflicts/module_list_filter_win.h"
+#include "chrome/browser/conflicts/third_party_metrics_recorder_win.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace {
+
+// Serializes a vector of IncompatibleApplications to JSON.
+base::Value ConvertToDictionary(
+    const std::vector<IncompatibleApplicationsUpdater::IncompatibleApplication>&
+        applications) {
+  base::Value result(base::Value::Type::DICTIONARY);
+
+  for (const auto& application : applications) {
+    base::Value element(base::Value::Type::DICTIONARY);
+
+    // The registry location is necessary to quickly figure out if that
+    // application is still installed on the computer.
+    element.SetKey(
+        "registry_is_hkcu",
+        base::Value(application.info.registry_root == HKEY_CURRENT_USER));
+    element.SetKey("registry_key_path",
+                   base::Value(application.info.registry_key_path));
+    element.SetKey(
+        "registry_wow64_access",
+        base::Value(static_cast<int>(application.info.registry_wow64_access)));
+
+    // And then the actual information needed to display a warning to the user.
+    element.SetKey("allow_load",
+                   base::Value(application.blacklist_action->allow_load()));
+    element.SetKey("type",
+                   base::Value(application.blacklist_action->message_type()));
+    element.SetKey("message_url",
+                   base::Value(application.blacklist_action->message_url()));
+
+    result.SetKey(base::UTF16ToUTF8(application.info.name), std::move(element));
+  }
+
+  return result;
+}
+
+// Deserializes a IncompatibleApplication named |name| from |value|. Returns
+// null if |value| is not a dict containing all required fields.
+std::unique_ptr<IncompatibleApplicationsUpdater::IncompatibleApplication>
+ConvertToIncompatibleApplication(const std::string& name,
+                                 const base::Value& value) {
+  if (!value.is_dict())
+    return nullptr;
+
+  const base::Value* registry_is_hkcu_value =
+      value.FindKeyOfType("registry_is_hkcu", base::Value::Type::BOOLEAN);
+  const base::Value* registry_key_path_value =
+      value.FindKeyOfType("registry_key_path", base::Value::Type::STRING);
+  const base::Value* registry_wow64_access_value =
+      value.FindKeyOfType("registry_wow64_access", base::Value::Type::INTEGER);
+  const base::Value* allow_load_value =
+      value.FindKeyOfType("allow_load", base::Value::Type::BOOLEAN);
+  const base::Value* type_value =
+      value.FindKeyOfType("type", base::Value::Type::INTEGER);
+  const base::Value* message_url_value =
+      value.FindKeyOfType("message_url", base::Value::Type::STRING);
+
+  // All of the above are required for a valid application.
+  if (!registry_is_hkcu_value || !registry_key_path_value ||
+      !registry_wow64_access_value || !allow_load_value || !type_value ||
+      !message_url_value) {
+    return nullptr;
+  }
+
+  InstalledApplications::ApplicationInfo application_info = {
+      base::UTF8ToUTF16(name),
+      registry_is_hkcu_value->GetBool() ? HKEY_CURRENT_USER
+                                        : HKEY_LOCAL_MACHINE,
+      base::UTF8ToUTF16(registry_key_path_value->GetString()),
+      static_cast<REGSAM>(registry_wow64_access_value->GetInt())};
+
+  auto blacklist_action =
+      std::make_unique<chrome::conflicts::BlacklistAction>();
+  blacklist_action->set_allow_load(allow_load_value->GetBool());
+  blacklist_action->set_message_type(
+      static_cast<chrome::conflicts::BlacklistMessageType>(
+          type_value->GetInt()));
+  blacklist_action->set_message_url(message_url_value->GetString());
+
+  return std::make_unique<
+      IncompatibleApplicationsUpdater::IncompatibleApplication>(
+      std::move(application_info), std::move(blacklist_action));
+}
+
+// Returns true if |application| references an existing application in the
+// registry.
+//
+// Used to filter out stale applications from the cache. This can happen if a
+// application was uninstalled between the time it was found and Chrome was
+// relaunched.
+bool IsValidApplication(
+    const IncompatibleApplicationsUpdater::IncompatibleApplication&
+        application) {
+  return base::win::RegKey(
+             application.info.registry_root,
+             application.info.registry_key_path.c_str(),
+             KEY_QUERY_VALUE | application.info.registry_wow64_access)
+      .Valid();
+}
+
+// Clears the cache of all the applications whose name is in
+// |state_application_names|.
+void RemoveStaleApplications(
+    const std::vector<std::string>& stale_application_names) {
+  // Early exit because DictionaryPrefUpdate will write to the pref even if it
+  // doesn't contain a value.
+  if (stale_application_names.empty())
+    return;
+
+  DictionaryPrefUpdate update(g_browser_process->local_state(),
+                              prefs::kIncompatibleApplications);
+  base::Value* existing_applications = update.Get();
+
+  for (const auto& application_name : stale_application_names) {
+    bool removed = existing_applications->RemoveKey(application_name);
+    DCHECK(removed);
+  }
+}
+
+// Applies the given |function| object to each valid IncompatibleApplication
+// found in the kIncompatibleApplications preference.
+//
+// The signature of the function must be equivalent to the following:
+//   bool Function(std::unique_ptr<IncompatibleApplication> application));
+//
+// The return value of |function| indicates if the enumeration should continue
+// (true) or be stopped (false).
+//
+// This function takes care of removing invalid entries that are found during
+// the enumeration.
+template <class UnaryFunction>
+void EnumerateAndTrimIncompatibleApplications(UnaryFunction function) {
+  std::vector<std::string> stale_application_names;
+  for (const auto& item : g_browser_process->local_state()
+                              ->FindPreference(prefs::kIncompatibleApplications)
+                              ->GetValue()
+                              ->DictItems()) {
+    auto application =
+        ConvertToIncompatibleApplication(item.first, item.second);
+
+    if (!application || !IsValidApplication(*application)) {
+      // Mark every invalid application as stale so they are removed from the
+      // cache.
+      stale_application_names.push_back(item.first);
+      continue;
+    }
+
+    // Notify the caller and stop the enumeration if requested by the function.
+    if (!function(std::move(application)))
+      break;
+  }
+
+  RemoveStaleApplications(stale_application_names);
+}
+
+}  // namespace
+
+// -----------------------------------------------------------------------------
+// IncompatibleApplication
+
+IncompatibleApplicationsUpdater::IncompatibleApplication::
+    IncompatibleApplication(
+        InstalledApplications::ApplicationInfo info,
+        std::unique_ptr<chrome::conflicts::BlacklistAction> blacklist_action)
+    : info(std::move(info)), blacklist_action(std::move(blacklist_action)) {}
+
+IncompatibleApplicationsUpdater::IncompatibleApplication::
+    ~IncompatibleApplication() = default;
+
+IncompatibleApplicationsUpdater::IncompatibleApplication::
+    IncompatibleApplication(
+        IncompatibleApplication&& incompatible_application) = default;
+
+IncompatibleApplicationsUpdater::IncompatibleApplication&
+IncompatibleApplicationsUpdater::IncompatibleApplication::operator=(
+    IncompatibleApplication&& incompatible_application) = default;
+
+// -----------------------------------------------------------------------------
+// IncompatibleApplicationsUpdater
+
+IncompatibleApplicationsUpdater::IncompatibleApplicationsUpdater(
+    const CertificateInfo& exe_certificate_info,
+    const ModuleListFilter& module_list_filter,
+    const InstalledApplications& installed_applications)
+    : exe_certificate_info_(exe_certificate_info),
+      module_list_filter_(module_list_filter),
+      installed_applications_(installed_applications) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+}
+
+IncompatibleApplicationsUpdater::~IncompatibleApplicationsUpdater() = default;
+
+// static
+void IncompatibleApplicationsUpdater::RegisterLocalStatePrefs(
+    PrefRegistrySimple* registry) {
+  registry->RegisterDictionaryPref(prefs::kIncompatibleApplications);
+  registry->RegisterDictionaryPref(prefs::kProblematicPrograms);
+}
+
+// static
+bool IncompatibleApplicationsUpdater::IsWarningEnabled() {
+  return ModuleDatabase::GetInstance() &&
+         ModuleDatabase::GetInstance()->third_party_conflicts_manager();
+}
+
+// static
+bool IncompatibleApplicationsUpdater::HasCachedApplications() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  bool found_valid_application = false;
+
+  EnumerateAndTrimIncompatibleApplications(
+      [&found_valid_application](
+          std::unique_ptr<IncompatibleApplication> application) {
+        found_valid_application = true;
+
+        // Break the enumeration.
+        return false;
+      });
+
+  return found_valid_application;
+}
+
+// static
+std::vector<IncompatibleApplicationsUpdater::IncompatibleApplication>
+IncompatibleApplicationsUpdater::GetCachedApplications() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  std::vector<IncompatibleApplication> valid_applications;
+
+  EnumerateAndTrimIncompatibleApplications(
+      [&valid_applications](
+          std::unique_ptr<IncompatibleApplication> application) {
+        valid_applications.push_back(std::move(*application));
+
+        // Continue the enumeration.
+        return true;
+      });
+
+  return valid_applications;
+}
+
+void IncompatibleApplicationsUpdater::OnNewModuleFound(
+    const ModuleInfoKey& module_key,
+    const ModuleInfoData& module_data) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  // Only consider loaded modules.
+  // TODO(pmonette): Also consider blocked modules when that becomes possible.
+  if ((module_data.module_types & ModuleInfoData::kTypeLoadedModule) == 0)
+    return;
+
+  // Explicitly whitelist modules whose signing cert's Subject field matches the
+  // one in the current executable. No attempt is made to check the validity of
+  // module signatures or of signing certs.
+  if (exe_certificate_info_.type != CertificateType::NO_CERTIFICATE &&
+      exe_certificate_info_.subject ==
+          module_data.inspection_result->certificate_info.subject) {
+    return;
+  }
+
+  // Skip modules whitelisted by the Module List component.
+  if (module_list_filter_.IsWhitelisted(module_key, module_data))
+    return;
+
+  // Also skip a module if it cannot be associated with an installed application
+  // on the user's computer.
+  std::vector<InstalledApplications::ApplicationInfo> associated_applications;
+  if (!installed_applications_.GetInstalledApplications(
+          module_key.module_path, &associated_applications)) {
+    return;
+  }
+
+  std::unique_ptr<chrome::conflicts::BlacklistAction> blacklist_action =
+      module_list_filter_.IsBlacklisted(module_key, module_data);
+  if (!blacklist_action) {
+    // The default behavior is to suggest to uninstall.
+    blacklist_action = std::make_unique<chrome::conflicts::BlacklistAction>();
+    blacklist_action->set_allow_load(true);
+    blacklist_action->set_message_type(
+        chrome::conflicts::BlacklistMessageType::UNINSTALL);
+    blacklist_action->set_message_url(std::string());
+  }
+
+  for (auto&& associated_application : associated_applications) {
+    incompatible_applications_.emplace_back(
+        std::move(associated_application),
+        std::make_unique<chrome::conflicts::BlacklistAction>(
+            *blacklist_action));
+  }
+}
+
+void IncompatibleApplicationsUpdater::OnModuleDatabaseIdle() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  // On the first call to OnModuleDatabaseIdle(), the previous value must always
+  // be overwritten.
+  if (before_first_idle_)
+    g_browser_process->local_state()->ClearPref(
+        prefs::kIncompatibleApplications);
+  before_first_idle_ = false;
+
+  // If there is no new incompatible application, there is nothing to do.
+  if (incompatible_applications_.empty())
+    return;
+
+  // The conversion of the accumulated applications to a json dictionary takes
+  // care of eliminating duplicates.
+  base::Value new_applications =
+      ConvertToDictionary(incompatible_applications_);
+  incompatible_applications_.clear();
+
+  // Update the existing dictionary.
+  DictionaryPrefUpdate update(g_browser_process->local_state(),
+                              prefs::kIncompatibleApplications);
+  base::Value* existing_applications = update.Get();
+  for (auto&& element : new_applications.DictItems()) {
+    existing_applications->SetKey(std::move(element.first),
+                                  std::move(element.second));
+  }
+}
diff --git a/chrome/browser/conflicts/incompatible_applications_updater_win.h b/chrome/browser/conflicts/incompatible_applications_updater_win.h
new file mode 100644
index 0000000..e6f1c8ed
--- /dev/null
+++ b/chrome/browser/conflicts/incompatible_applications_updater_win.h
@@ -0,0 +1,85 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CONFLICTS_INCOMPATIBLE_APPLICATIONS_UPDATER_WIN_H_
+#define CHROME_BROWSER_CONFLICTS_INCOMPATIBLE_APPLICATIONS_UPDATER_WIN_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "chrome/browser/conflicts/installed_applications_win.h"
+#include "chrome/browser/conflicts/module_database_observer_win.h"
+#include "chrome/browser/conflicts/proto/module_list.pb.h"
+
+struct CertificateInfo;
+class ModuleListFilter;
+class PrefRegistrySimple;
+
+// Maintains a list of incompatible applications that are installed on the
+// machine. These applications cause unwanted DLLs to be loaded into Chrome.
+//
+// Because the list is expensive to build, it is cached into the Local State
+// file so that it is available at startup.
+class IncompatibleApplicationsUpdater : public ModuleDatabaseObserver {
+ public:
+  struct IncompatibleApplication {
+    IncompatibleApplication(
+        InstalledApplications::ApplicationInfo info,
+        std::unique_ptr<chrome::conflicts::BlacklistAction> blacklist_action);
+    ~IncompatibleApplication();
+
+    // Needed for std::remove_if().
+    IncompatibleApplication(IncompatibleApplication&& incompatible_application);
+    IncompatibleApplication& operator=(
+        IncompatibleApplication&& incompatible_application);
+
+    InstalledApplications::ApplicationInfo info;
+    std::unique_ptr<chrome::conflicts::BlacklistAction> blacklist_action;
+  };
+
+  // Creates an instance of the updater.
+  // The parameters must outlive the lifetime of this class.
+  IncompatibleApplicationsUpdater(
+      const CertificateInfo& exe_certificate_info,
+      const ModuleListFilter& module_list_filter,
+      const InstalledApplications& installed_applications);
+  ~IncompatibleApplicationsUpdater() override;
+
+  static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+
+  // Returns true if the tracking of incompatible applications is enabled. The
+  // return value will not change throughout the lifetime of the process.
+  static bool IsWarningEnabled();
+
+  // Returns true if the cache contains at least one incompatible application.
+  // Only call this if IsIncompatibleApplicationsWarningEnabled() returns true.
+  static bool HasCachedApplications();
+
+  // Returns all the cached incompatible applications.
+  // Only call this if IsIncompatibleApplicationsWarningEnabled() returns true.
+  static std::vector<IncompatibleApplication> GetCachedApplications();
+
+  // ModuleDatabaseObserver:
+  void OnNewModuleFound(const ModuleInfoKey& module_key,
+                        const ModuleInfoData& module_data) override;
+  void OnModuleDatabaseIdle() override;
+
+ private:
+  const CertificateInfo& exe_certificate_info_;
+
+  const ModuleListFilter& module_list_filter_;
+
+  const InstalledApplications& installed_applications_;
+
+  // Temporarily holds incompatible applications that were recently found.
+  std::vector<IncompatibleApplication> incompatible_applications_;
+
+  // Becomes false on the first call to OnModuleDatabaseIdle.
+  bool before_first_idle_ = true;
+
+  DISALLOW_COPY_AND_ASSIGN(IncompatibleApplicationsUpdater);
+};
+
+#endif  // CHROME_BROWSER_CONFLICTS_INCOMPATIBLE_APPLICATIONS_UPDATER_WIN_H_
diff --git a/chrome/browser/conflicts/incompatible_applications_updater_win_unittest.cc b/chrome/browser/conflicts/incompatible_applications_updater_win_unittest.cc
new file mode 100644
index 0000000..cab2e15
--- /dev/null
+++ b/chrome/browser/conflicts/incompatible_applications_updater_win_unittest.cc
@@ -0,0 +1,325 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/conflicts/incompatible_applications_updater_win.h"
+
+#include <map>
+#include <string>
+#include <utility>
+
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/test_reg_util_win.h"
+#include "base/win/registry.h"
+#include "chrome/browser/conflicts/module_info_win.h"
+#include "chrome/browser/conflicts/module_list_filter_win.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// Mocks an empty whitelist and blacklist.
+class MockModuleListFilter : public ModuleListFilter {
+ public:
+  MockModuleListFilter() = default;
+  ~MockModuleListFilter() override = default;
+
+  bool IsWhitelisted(base::StringPiece module_basename_hash,
+                     base::StringPiece module_code_id_hash) const override {
+    return false;
+  }
+
+  std::unique_ptr<chrome::conflicts::BlacklistAction> IsBlacklisted(
+      const ModuleInfoKey& module_key,
+      const ModuleInfoData& module_data) const override {
+    return nullptr;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockModuleListFilter);
+};
+
+class MockInstalledApplications : public InstalledApplications {
+ public:
+  MockInstalledApplications() = default;
+  ~MockInstalledApplications() override = default;
+
+  void AddIncompatibleApplication(const base::FilePath& file_path,
+                                  ApplicationInfo application_info) {
+    applications_.insert({file_path, std::move(application_info)});
+  }
+
+  bool GetInstalledApplications(
+      const base::FilePath& file,
+      std::vector<ApplicationInfo>* applications) const override {
+    auto range = applications_.equal_range(file);
+
+    if (std::distance(range.first, range.second) == 0)
+      return false;
+
+    for (auto it = range.first; it != range.second; ++it)
+      applications->push_back(it->second);
+    return true;
+  }
+
+ private:
+  std::multimap<base::FilePath, ApplicationInfo> applications_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockInstalledApplications);
+};
+
+constexpr wchar_t kCertificatePath[] = L"CertificatePath";
+constexpr wchar_t kCertificateSubject[] = L"CertificateSubject";
+
+constexpr wchar_t kDllPath1[] = L"c:\\path\\to\\module.dll";
+constexpr wchar_t kDllPath2[] = L"c:\\some\\shellextension.dll";
+
+// Returns a new ModuleInfoData marked as loaded into the process but otherwise
+// empty.
+ModuleInfoData CreateLoadedModuleInfoData() {
+  ModuleInfoData module_data;
+  module_data.module_types |= ModuleInfoData::kTypeLoadedModule;
+  module_data.inspection_result = std::make_unique<ModuleInspectionResult>();
+  return module_data;
+}
+
+// Returns a new ModuleInfoData marked as loaded into the process with a
+// CertificateInfo that matches kCertificateSubject.
+ModuleInfoData CreateSignedLoadedModuleInfoData() {
+  ModuleInfoData module_data = CreateLoadedModuleInfoData();
+
+  module_data.inspection_result->certificate_info.type =
+      CertificateType::CERTIFICATE_IN_FILE;
+  module_data.inspection_result->certificate_info.path =
+      base::FilePath(kCertificatePath);
+  module_data.inspection_result->certificate_info.subject = kCertificateSubject;
+
+  return module_data;
+}
+
+}  // namespace
+
+class IncompatibleApplicationsUpdaterTest : public testing::Test {
+ protected:
+  IncompatibleApplicationsUpdaterTest()
+      : dll1_(kDllPath1),
+        dll2_(kDllPath2),
+        scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) {
+    exe_certificate_info_.type = CertificateType::CERTIFICATE_IN_FILE;
+    exe_certificate_info_.path = base::FilePath(kCertificatePath);
+    exe_certificate_info_.subject = kCertificateSubject;
+  }
+
+  void SetUp() override {
+    ASSERT_NO_FATAL_FAILURE(
+        registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER));
+  }
+
+  enum class Option {
+    ADD_REGISTRY_ENTRY,
+    NO_REGISTRY_ENTRY,
+  };
+  void AddIncompatibleApplication(const base::FilePath& injected_module_path,
+                                  const base::string16& application_name,
+                                  Option option) {
+    static constexpr wchar_t kUninstallRegKeyFormat[] =
+        L"dummy\\uninstall\\%ls";
+
+    const base::string16 registry_key_path =
+        base::StringPrintf(kUninstallRegKeyFormat, application_name.c_str());
+
+    installed_applications_.AddIncompatibleApplication(
+        injected_module_path, {application_name, HKEY_CURRENT_USER,
+                               registry_key_path, KEY_WOW64_32KEY});
+
+    if (option == Option::ADD_REGISTRY_ENTRY) {
+      base::win::RegKey reg_key(HKEY_CURRENT_USER, registry_key_path.c_str(),
+                                KEY_WOW64_32KEY | KEY_CREATE_SUB_KEY);
+    }
+  }
+
+  CertificateInfo& exe_certificate_info() { return exe_certificate_info_; }
+  MockModuleListFilter& module_list_filter() { return module_list_filter_; }
+  MockInstalledApplications& installed_applications() {
+    return installed_applications_;
+  }
+
+  const base::FilePath dll1_;
+  const base::FilePath dll2_;
+
+ private:
+  content::TestBrowserThreadBundle test_browser_thread_bundle_;
+  ScopedTestingLocalState scoped_testing_local_state_;
+  registry_util::RegistryOverrideManager registry_override_manager_;
+
+  CertificateInfo exe_certificate_info_;
+  MockModuleListFilter module_list_filter_;
+  MockInstalledApplications installed_applications_;
+
+  DISALLOW_COPY_AND_ASSIGN(IncompatibleApplicationsUpdaterTest);
+};
+
+// Tests that when the Local State cache is empty, no incompatible applications
+// are returned.
+TEST_F(IncompatibleApplicationsUpdaterTest, EmptyCache) {
+  EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
+  EXPECT_TRUE(IncompatibleApplicationsUpdater::GetCachedApplications().empty());
+}
+
+// IncompatibleApplicationsUpdater doesn't do anything when there is no
+// registered installed applications.
+TEST_F(IncompatibleApplicationsUpdaterTest, NoIncompatibleApplications) {
+  auto incompatible_applications_updater =
+      std::make_unique<IncompatibleApplicationsUpdater>(
+          exe_certificate_info(), module_list_filter(),
+          installed_applications());
+
+  // Simulate some arbitrary module loading into the process.
+  incompatible_applications_updater->OnNewModuleFound(
+      ModuleInfoKey(dll1_, 0, 0, 0), CreateLoadedModuleInfoData());
+  incompatible_applications_updater->OnModuleDatabaseIdle();
+
+  EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
+  EXPECT_TRUE(IncompatibleApplicationsUpdater::GetCachedApplications().empty());
+}
+
+TEST_F(IncompatibleApplicationsUpdaterTest, OneIncompatibility) {
+  AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
+
+  auto incompatible_applications_updater =
+      std::make_unique<IncompatibleApplicationsUpdater>(
+          exe_certificate_info(), module_list_filter(),
+          installed_applications());
+
+  // Simulate the module loading into the process.
+  incompatible_applications_updater->OnNewModuleFound(
+      ModuleInfoKey(dll1_, 0, 0, 0), CreateLoadedModuleInfoData());
+  incompatible_applications_updater->OnModuleDatabaseIdle();
+
+  EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
+  auto application_names =
+      IncompatibleApplicationsUpdater::GetCachedApplications();
+  ASSERT_EQ(1u, application_names.size());
+  EXPECT_EQ(L"Foo", application_names[0].info.name);
+}
+
+TEST_F(IncompatibleApplicationsUpdaterTest, SameModuleMultipleApplications) {
+  AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
+  AddIncompatibleApplication(dll1_, L"Bar", Option::ADD_REGISTRY_ENTRY);
+
+  auto incompatible_applications_updater =
+      std::make_unique<IncompatibleApplicationsUpdater>(
+          exe_certificate_info(), module_list_filter(),
+          installed_applications());
+
+  // Simulate the module loading into the process.
+  incompatible_applications_updater->OnNewModuleFound(
+      ModuleInfoKey(dll1_, 0, 0, 0), CreateLoadedModuleInfoData());
+  incompatible_applications_updater->OnModuleDatabaseIdle();
+
+  EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
+  auto application_names =
+      IncompatibleApplicationsUpdater::GetCachedApplications();
+  ASSERT_EQ(2u, application_names.size());
+}
+
+TEST_F(IncompatibleApplicationsUpdaterTest,
+       MultipleCallsToOnModuleDatabaseIdle) {
+  AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
+  AddIncompatibleApplication(dll2_, L"Bar", Option::ADD_REGISTRY_ENTRY);
+
+  auto incompatible_applications_updater =
+      std::make_unique<IncompatibleApplicationsUpdater>(
+          exe_certificate_info(), module_list_filter(),
+          installed_applications());
+
+  // Simulate the module loading into the process.
+  incompatible_applications_updater->OnNewModuleFound(
+      ModuleInfoKey(dll1_, 0, 0, 0), CreateLoadedModuleInfoData());
+  incompatible_applications_updater->OnModuleDatabaseIdle();
+
+  // Add an additional module.
+  incompatible_applications_updater->OnNewModuleFound(
+      ModuleInfoKey(dll2_, 0, 0, 0), CreateLoadedModuleInfoData());
+  incompatible_applications_updater->OnModuleDatabaseIdle();
+
+  EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
+  auto application_names =
+      IncompatibleApplicationsUpdater::GetCachedApplications();
+  ASSERT_EQ(2u, application_names.size());
+}
+
+// This is meant to test that cached incompatible applications are persisted
+// through browser restarts, via the Local State file.
+//
+// Since this isn't really doable in a unit test, this test at least check that
+// the list isn't tied to the lifetime of the IncompatibleApplicationsUpdater
+// instance. It is assumed that the Local State file works as intended.
+TEST_F(IncompatibleApplicationsUpdaterTest, PersistsThroughRestarts) {
+  AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
+
+  auto incompatible_applications_updater =
+      std::make_unique<IncompatibleApplicationsUpdater>(
+          exe_certificate_info(), module_list_filter(),
+          installed_applications());
+
+  // Simulate the module loading into the process.
+  incompatible_applications_updater->OnNewModuleFound(
+      ModuleInfoKey(dll1_, 0, 0, 0), CreateLoadedModuleInfoData());
+  incompatible_applications_updater->OnModuleDatabaseIdle();
+
+  EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
+
+  // Delete the instance.
+  incompatible_applications_updater = nullptr;
+
+  EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
+}
+
+// Tests that applications that do not have a registry entry are removed.
+TEST_F(IncompatibleApplicationsUpdaterTest, StaleEntriesRemoved) {
+  AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
+  AddIncompatibleApplication(dll2_, L"Bar", Option::NO_REGISTRY_ENTRY);
+
+  auto incompatible_applications_updater =
+      std::make_unique<IncompatibleApplicationsUpdater>(
+          exe_certificate_info(), module_list_filter(),
+          installed_applications());
+
+  // Simulate the modules loading into the process.
+  incompatible_applications_updater->OnNewModuleFound(
+      ModuleInfoKey(dll1_, 0, 0, 0), CreateLoadedModuleInfoData());
+  incompatible_applications_updater->OnNewModuleFound(
+      ModuleInfoKey(dll2_, 0, 0, 0), CreateLoadedModuleInfoData());
+  incompatible_applications_updater->OnModuleDatabaseIdle();
+
+  EXPECT_TRUE(IncompatibleApplicationsUpdater::HasCachedApplications());
+  auto application_names =
+      IncompatibleApplicationsUpdater::GetCachedApplications();
+  ASSERT_EQ(1u, application_names.size());
+  EXPECT_EQ(L"Foo", application_names[0].info.name);
+}
+
+// Tests that modules with a matching certificate subject are whitelisted.
+TEST_F(IncompatibleApplicationsUpdaterTest,
+       WhitelistMatchingCertificateSubject) {
+  AddIncompatibleApplication(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
+
+  auto incompatible_applications_updater =
+      std::make_unique<IncompatibleApplicationsUpdater>(
+          exe_certificate_info(), module_list_filter(),
+          installed_applications());
+
+  // Simulate the module loading into the process.
+  incompatible_applications_updater->OnNewModuleFound(
+      ModuleInfoKey(dll1_, 0, 0, 0), CreateSignedLoadedModuleInfoData());
+  incompatible_applications_updater->OnModuleDatabaseIdle();
+
+  EXPECT_FALSE(IncompatibleApplicationsUpdater::HasCachedApplications());
+  auto application_names =
+      IncompatibleApplicationsUpdater::GetCachedApplications();
+  ASSERT_EQ(0u, application_names.size());
+}
diff --git a/chrome/browser/conflicts/installed_programs_win.cc b/chrome/browser/conflicts/installed_applications_win.cc
similarity index 79%
rename from chrome/browser/conflicts/installed_programs_win.cc
rename to chrome/browser/conflicts/installed_applications_win.cc
index 9fe1b80..811382d9 100644
--- a/chrome/browser/conflicts/installed_programs_win.cc
+++ b/chrome/browser/conflicts/installed_applications_win.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/conflicts/installed_programs_win.h"
+#include "chrome/browser/conflicts/installed_applications_win.h"
 
 #include <algorithm>
 
@@ -96,26 +96,28 @@
 
 }  // namespace
 
-InstalledPrograms::InstalledPrograms()
-    : InstalledPrograms(std::make_unique<MsiUtil>()) {}
+InstalledApplications::InstalledApplications()
+    : InstalledApplications(std::make_unique<MsiUtil>()) {}
 
-InstalledPrograms::~InstalledPrograms() = default;
+InstalledApplications::~InstalledApplications() = default;
 
-bool InstalledPrograms::GetInstalledPrograms(
+bool InstalledApplications::GetInstalledApplications(
     const base::FilePath& file,
-    std::vector<ProgramInfo>* programs) const {
+    std::vector<ApplicationInfo>* applications) const {
   // First, check if an exact file match exists in the installed files list.
-  if (GetProgramsFromInstalledFiles(file, programs))
+  if (GetApplicationsFromInstalledFiles(file, applications))
     return true;
 
   // Then try to find a parent directory in the install directories list.
-  return GetProgramsFromInstallDirectories(file, programs);
+  return GetApplicationsFromInstallDirectories(file, applications);
 }
 
-InstalledPrograms::InstalledPrograms(std::unique_ptr<MsiUtil> msi_util) {
+InstalledApplications::InstalledApplications(
+    std::unique_ptr<MsiUtil> msi_util) {
   base::AssertBlockingAllowed();
 
-  SCOPED_UMA_HISTOGRAM_TIMER("ThirdPartyModules.InstalledPrograms.GetDataTime");
+  SCOPED_UMA_HISTOGRAM_TIMER(
+      "ThirdPartyModules.InstalledApplications.GetDataTime");
 
   // Iterate over all the variants of the uninstall registry key.
   static constexpr wchar_t kUninstallKeyPath[] =
@@ -133,9 +135,9 @@
     for (base::win::RegistryKeyIterator i(combination.first, kUninstallKeyPath,
                                           combination.second);
          i.Valid(); ++i) {
-      CheckRegistryKeyForInstalledProgram(combination.first, kUninstallKeyPath,
-                                          combination.second, i.Name(),
-                                          *msi_util);
+      CheckRegistryKeyForInstalledApplication(
+          combination.first, kUninstallKeyPath, combination.second, i.Name(),
+          *msi_util);
     }
   }
 
@@ -145,7 +147,7 @@
   SortByFilePaths(&install_directories_);
 }
 
-void InstalledPrograms::CheckRegistryKeyForInstalledProgram(
+void InstalledApplications::CheckRegistryKeyForInstalledApplication(
     HKEY hkey,
     const base::string16& key_path,
     REGSAM wow64access,
@@ -159,7 +161,7 @@
   if (!candidate.Valid())
     return;
 
-  // System components are not displayed in the Add or remove programs list.
+  // System components are not displayed in the Add or remove applications list.
   if (IsSystemComponent(candidate))
     return;
 
@@ -168,7 +170,7 @@
   if (!GetValue(candidate, L"UninstallString", &uninstall_string))
     return;
 
-  // Ignore Microsoft programs.
+  // Ignore Microsoft applications.
   base::string16 publisher;
   if (GetValue(candidate, L"Publisher", &publisher) &&
       base::StartsWith(publisher, L"Microsoft", base::CompareCase::SENSITIVE)) {
@@ -184,29 +186,31 @@
 
   base::FilePath install_path;
   if (GetInstallPathUsingInstallLocation(candidate, &install_path)) {
-    programs_.push_back({std::move(display_name), hkey,
-                         std::move(candidate_key_path), wow64access});
+    applications_.push_back({std::move(display_name), hkey,
+                             std::move(candidate_key_path), wow64access});
 
-    const size_t program_index = programs_.size() - 1;
-    install_directories_.emplace_back(std::move(install_path), program_index);
+    const size_t application_index = applications_.size() - 1;
+    install_directories_.emplace_back(std::move(install_path),
+                                      application_index);
     return;
   }
 
   std::vector<base::FilePath> installed_files;
   if (GetInstalledFilesUsingMsiGuid(key_name, msi_util, &installed_files)) {
-    programs_.push_back({std::move(display_name), hkey,
-                         std::move(candidate_key_path), wow64access});
+    applications_.push_back({std::move(display_name), hkey,
+                             std::move(candidate_key_path), wow64access});
 
-    const size_t program_index = programs_.size() - 1;
+    const size_t application_index = applications_.size() - 1;
     for (auto& installed_file : installed_files) {
-      installed_files_.emplace_back(std::move(installed_file), program_index);
+      installed_files_.emplace_back(std::move(installed_file),
+                                    application_index);
     }
   }
 }
 
-bool InstalledPrograms::GetProgramsFromInstalledFiles(
+bool InstalledApplications::GetApplicationsFromInstalledFiles(
     const base::FilePath& file,
-    std::vector<ProgramInfo>* programs) const {
+    std::vector<ApplicationInfo>* applications) const {
   // This functor is used to find all exact items by their key in a collection
   // of key/value pairs.
   struct FilePathLess {
@@ -229,16 +233,16 @@
   if (nb_matches == 0)
     return false;
 
-  programs->reserve(programs->size() + nb_matches);
+  applications->reserve(applications->size() + nb_matches);
   for (auto iter = equal_range.first; iter != equal_range.second; ++iter)
-    programs->push_back(programs_[iter->second]);
+    applications->push_back(applications_[iter->second]);
 
   return true;
 }
 
-bool InstalledPrograms::GetProgramsFromInstallDirectories(
+bool InstalledApplications::GetApplicationsFromInstallDirectories(
     const base::FilePath& file,
-    std::vector<ProgramInfo>* programs) const {
+    std::vector<ApplicationInfo>* applications) const {
   // This functor is used to find all matching items by their key in a
   // collection of key/value pairs. This also takes advantage of the fact that
   // only the first element of the pair is a directory.
@@ -264,16 +268,17 @@
                        file, FilePathParentLess());
 
   // Skip cases where there are multiple matches because there is no way to know
-  // which program is the real owner of the |file| with the data owned by us.
+  // which application is the real owner of the |file| with the data owned by
+  // us.
   if (std::distance(equal_range.first, equal_range.second) != 1)
     return false;
 
-  programs->push_back(programs_[equal_range.first->second]);
+  applications->push_back(applications_[equal_range.first->second]);
   return true;
 }
 
-bool operator<(const InstalledPrograms::ProgramInfo& lhs,
-               const InstalledPrograms::ProgramInfo& rhs) {
+bool operator<(const InstalledApplications::ApplicationInfo& lhs,
+               const InstalledApplications::ApplicationInfo& rhs) {
   return std::tie(lhs.name, lhs.registry_root, lhs.registry_key_path,
                   lhs.registry_wow64_access) <
          std::tie(rhs.name, rhs.registry_root, rhs.registry_key_path,
diff --git a/chrome/browser/conflicts/installed_applications_win.h b/chrome/browser/conflicts/installed_applications_win.h
new file mode 100644
index 0000000..99779f3
--- /dev/null
+++ b/chrome/browser/conflicts/installed_applications_win.h
@@ -0,0 +1,118 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CONFLICTS_INSTALLED_APPLICATIONS_WIN_H_
+#define CHROME_BROWSER_CONFLICTS_INSTALLED_APPLICATIONS_WIN_H_
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "base/win/windows_types.h"
+
+class MsiUtil;
+
+// This class inspects the user's installed applications and builds a mapping of
+// files to its associated application.
+//
+// Installed applications are found by searching the
+// "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" registry key and
+// its variants. There are 2 cases that are covered:
+//
+// 1 - If the application's installer did its due dilligence, it populated the
+//     "InstallLocation" registry key with the directory where it was installed,
+//     and all the files under that directory are assumed to be owned by this
+//     application.
+//
+//     In the event of 2 conflicting "InstallLocation", both are ignored as this
+//     method doesn't let us know for sure who is the owner of any enclosing
+//     files.
+//
+// 2 - If the application's entry is a valid MSI Product GUID, the complete list
+// of
+//     associated file is used to exactly match a given file to a application.
+//
+//     If multiple products installed the same file as the same component,
+//     Windows keeps a reference count of that component so that the file
+//     doesn't get removed if one of them is uninstalled. So both applications
+//     are returned by GetInstalledApplications().
+//
+//  Note: Applications may be skipped and so would not be returned by
+//        GetInstalledApplications() for the following reasons:
+//        - The application is owned by Microsoft.
+//        - The uninstall entry is marked as a system component.
+//        - The uninstall entry has no display name.
+//        - The uninstall entry has no UninstallString.
+//
+class InstalledApplications {
+ public:
+  struct ApplicationInfo {
+    base::string16 name;
+
+    // Holds the path to the uninstall entry in the registry.
+    HKEY registry_root;
+    base::string16 registry_key_path;
+    REGSAM registry_wow64_access;
+  };
+
+  // Initializes this instance with the list of installed applications. While
+  // the constructor must be called in a sequence that allows blocking, its
+  // public method can be used without such restrictions.
+  InstalledApplications();
+
+  virtual ~InstalledApplications();
+
+  // Given a |file|, checks if it matches an installed application on the user's
+  // machine and appends all the matching applications to |applications|.
+  // Virtual to allow mocking.
+  virtual bool GetInstalledApplications(
+      const base::FilePath& file,
+      std::vector<ApplicationInfo>* applications) const;
+
+ protected:
+  // Protected so that tests can subclass InstalledApplications and access it.
+  explicit InstalledApplications(std::unique_ptr<MsiUtil> msi_util);
+
+ private:
+  // If the registry key references a valid installed application, this function
+  // adds an entry to |applications_| with its list of files or installation
+  // directory to their associated vector.
+  void CheckRegistryKeyForInstalledApplication(HKEY hkey,
+                                               const base::string16& key_path,
+                                               REGSAM wow64access,
+                                               const base::string16& key_name,
+                                               const MsiUtil& msi_util);
+
+  bool GetApplicationsFromInstalledFiles(
+      const base::FilePath& file,
+      std::vector<ApplicationInfo>* applications) const;
+  bool GetApplicationsFromInstallDirectories(
+      const base::FilePath& file,
+      std::vector<ApplicationInfo>* applications) const;
+
+  // Applications are stored in this vector because multiple entries in
+  // |installed_files| could point to the same one. This is to avoid
+  // duplicating them.
+  std::vector<ApplicationInfo> applications_;
+
+  // Contains all the files from applications installed via Microsoft Installer.
+  // The second part of the pair is the index into |applications|.
+  std::vector<std::pair<base::FilePath, size_t>> installed_files_;
+
+  // For some applications, the best information available is the directory of
+  // the installation. The compare functor treats file paths where one is the
+  // parent of the other as equal.
+  // The second part of the pair is the index into |applications|.
+  std::vector<std::pair<base::FilePath, size_t>> install_directories_;
+
+  DISALLOW_COPY_AND_ASSIGN(InstalledApplications);
+};
+
+bool operator<(const InstalledApplications::ApplicationInfo& lhs,
+               const InstalledApplications::ApplicationInfo& rhs);
+
+#endif  // CHROME_BROWSER_CONFLICTS_INSTALLED_APPLICATIONS_WIN_H_
diff --git a/chrome/browser/conflicts/installed_applications_win_unittest.cc b/chrome/browser/conflicts/installed_applications_win_unittest.cc
new file mode 100644
index 0000000..01b3929
--- /dev/null
+++ b/chrome/browser/conflicts/installed_applications_win_unittest.cc
@@ -0,0 +1,340 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/conflicts/installed_applications_win.h"
+
+#include <map>
+
+#include "base/macros.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/test_reg_util_win.h"
+#include "base/win/registry.h"
+#include "chrome/browser/conflicts/msi_util_win.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+static const wchar_t kRegistryKeyPathFormat[] =
+    L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%ls";
+
+struct CommonInfo {
+  base::string16 product_id;
+  bool is_system_component;
+  bool is_microsoft_published;
+  base::string16 display_name;
+  base::string16 uninstall_string;
+};
+
+struct InstallLocationApplicationInfo {
+  CommonInfo common_info;
+  base::string16 install_location;
+};
+
+struct MsiApplicationInfo {
+  CommonInfo common_info;
+  std::vector<base::string16> components;
+};
+
+class MockMsiUtil : public MsiUtil {
+ public:
+  MockMsiUtil(const std::map<base::string16, std::vector<base::string16>>&
+                  component_paths_map)
+      : component_paths_map_(component_paths_map) {}
+
+  bool GetMsiComponentPaths(
+      const base::string16& product_guid,
+      std::vector<base::string16>* component_paths) const override {
+    auto iter = component_paths_map_.find(product_guid);
+    if (iter == component_paths_map_.end())
+      return false;
+
+    *component_paths = iter->second;
+    return true;
+  }
+
+ private:
+  const std::map<base::string16, std::vector<base::string16>>&
+      component_paths_map_;
+};
+
+class TestInstalledApplications : public InstalledApplications {
+ public:
+  explicit TestInstalledApplications(std::unique_ptr<MsiUtil> msi_util)
+      : InstalledApplications(std::move(msi_util)) {}
+};
+
+class InstalledApplicationsTest : public testing::Test {
+ public:
+  InstalledApplicationsTest() = default;
+  ~InstalledApplicationsTest() override = default;
+
+  // ASSERT_NO_FATAL_FAILURE cannot be used in a constructor so the registry
+  // hive overrides are done here.
+  void SetUp() override {
+    ASSERT_NO_FATAL_FAILURE(
+        registry_override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE));
+    ASSERT_NO_FATAL_FAILURE(
+        registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER));
+  }
+
+  void AddCommonInfo(const CommonInfo& common_info,
+                     base::win::RegKey* registry_key) {
+    registry_key->WriteValue(L"SystemComponent",
+                             common_info.is_system_component ? 1 : 0);
+    registry_key->WriteValue(L"UninstallString",
+                             common_info.uninstall_string.c_str());
+    if (common_info.is_microsoft_published)
+      registry_key->WriteValue(L"Publisher", L"Microsoft Corporation");
+    registry_key->WriteValue(L"DisplayName", common_info.display_name.c_str());
+  }
+
+  void AddFakeApplication(const MsiApplicationInfo& application_info) {
+    const base::string16 registry_key_path =
+        base::StringPrintf(kRegistryKeyPathFormat,
+                           application_info.common_info.product_id.c_str());
+    base::win::RegKey registry_key(HKEY_CURRENT_USER, registry_key_path.c_str(),
+                                   KEY_WRITE);
+
+    AddCommonInfo(application_info.common_info, &registry_key);
+
+    component_paths_map_.insert(
+        {application_info.common_info.product_id, application_info.components});
+  }
+
+  void AddFakeApplication(
+      const InstallLocationApplicationInfo& application_info) {
+    const base::string16 registry_key_path =
+        base::StringPrintf(kRegistryKeyPathFormat,
+                           application_info.common_info.product_id.c_str());
+    base::win::RegKey registry_key(HKEY_CURRENT_USER, registry_key_path.c_str(),
+                                   KEY_WRITE);
+
+    AddCommonInfo(application_info.common_info, &registry_key);
+
+    registry_key.WriteValue(L"InstallLocation",
+                            application_info.install_location.c_str());
+  }
+
+  TestInstalledApplications& installed_applications() {
+    return *installed_applications_;
+  }
+
+  void InitializeInstalledApplications() {
+    installed_applications_ = std::make_unique<TestInstalledApplications>(
+        std::make_unique<MockMsiUtil>(component_paths_map_));
+  }
+
+ private:
+  registry_util::RegistryOverrideManager registry_override_manager_;
+
+  std::unique_ptr<TestInstalledApplications> installed_applications_;
+
+  std::map<base::string16, std::vector<base::string16>> component_paths_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(InstalledApplicationsTest);
+};
+
+}  // namespace
+
+// Checks that registry entries with invalid information are skipped.
+TEST_F(InstalledApplicationsTest, InvalidEntries) {
+  const wchar_t kValidDisplayName[] = L"ADisplayName";
+  const wchar_t kValidUninstallString[] = L"c:\\an\\UninstallString.exe";
+  const wchar_t kInstallLocation[] = L"c:\\application files\\application\\";
+
+  InstallLocationApplicationInfo kTestCases[] = {
+      {
+          {
+              L"Is SystemComponent", true, false, kValidDisplayName,
+              kValidUninstallString,
+          },
+          kInstallLocation,
+      },
+      {
+          {
+              L"Is Microsoft published", false, true, kValidDisplayName,
+              kValidUninstallString,
+          },
+          kInstallLocation,
+      },
+      {
+          {
+              L"Missing DisplayName", false, false, L"", kValidUninstallString,
+          },
+          kInstallLocation,
+      },
+      {
+          {
+              L"Missing UninstallString", false, false, kValidDisplayName, L"",
+          },
+          kInstallLocation,
+      },
+  };
+
+  for (const auto& test_case : kTestCases)
+    AddFakeApplication(test_case);
+
+  InitializeInstalledApplications();
+
+  // None of the invalid entries were picked up.
+  const base::FilePath valid_child_file =
+      base::FilePath(kInstallLocation).Append(L"file.dll");
+  std::vector<InstalledApplications::ApplicationInfo> applications;
+  EXPECT_FALSE(installed_applications().GetInstalledApplications(
+      valid_child_file, &applications));
+}
+
+// Tests InstalledApplications on a valid entry with an InstallLocation.
+TEST_F(InstalledApplicationsTest, InstallLocation) {
+  const wchar_t kValidDisplayName[] = L"ADisplayName";
+  const wchar_t kValidUninstallString[] = L"c:\\an\\UninstallString.exe";
+  const wchar_t kInstallLocation[] = L"c:\\application files\\application\\";
+
+  InstallLocationApplicationInfo kTestCase = {
+      {
+          L"Completely valid", false, false, kValidDisplayName,
+          kValidUninstallString,
+      },
+      kInstallLocation,
+  };
+
+  AddFakeApplication(kTestCase);
+
+  InitializeInstalledApplications();
+
+  // Child file path.
+  const base::FilePath valid_child_file =
+      base::FilePath(kInstallLocation).Append(L"file.dll");
+  std::vector<InstalledApplications::ApplicationInfo> applications;
+  EXPECT_TRUE(installed_applications().GetInstalledApplications(
+      valid_child_file, &applications));
+  ASSERT_EQ(1u, applications.size());
+  EXPECT_EQ(kTestCase.common_info.display_name, applications[0].name);
+  EXPECT_EQ(HKEY_CURRENT_USER, applications[0].registry_root);
+  EXPECT_FALSE(applications[0].registry_key_path.empty());
+  EXPECT_EQ(0u, applications[0].registry_wow64_access);
+
+  // Non-child file path.
+  const base::FilePath invalid_child_file(
+      L"c:\\application files\\another application\\test.dll");
+  EXPECT_FALSE(installed_applications().GetInstalledApplications(
+      invalid_child_file, &applications));
+}
+
+// Tests InstalledApplications on a valid MSI entry.
+TEST_F(InstalledApplicationsTest, Msi) {
+  const wchar_t kValidDisplayName[] = L"ADisplayName";
+  const wchar_t kValidUninstallString[] = L"c:\\an\\UninstallString.exe";
+
+  MsiApplicationInfo kTestCase = {
+      {
+          L"Completely valid", false, false, kValidDisplayName,
+          kValidUninstallString,
+      },
+      {
+          L"c:\\application files\\application\\file1.dll",
+          L"c:\\application files\\application\\file2.dll",
+          L"c:\\application files\\application\\sub\\file3.dll",
+          L"c:\\windows\\system32\\file4.dll",
+      },
+  };
+
+  AddFakeApplication(kTestCase);
+
+  InitializeInstalledApplications();
+
+  // Checks that all the files match the application.
+  for (const auto& component : kTestCase.components) {
+    std::vector<InstalledApplications::ApplicationInfo> applications;
+    EXPECT_TRUE(installed_applications().GetInstalledApplications(
+        base::FilePath(component), &applications));
+    ASSERT_EQ(1u, applications.size());
+    EXPECT_EQ(kTestCase.common_info.display_name, applications[0].name);
+    EXPECT_EQ(HKEY_CURRENT_USER, applications[0].registry_root);
+    EXPECT_FALSE(applications[0].registry_key_path.empty());
+    EXPECT_EQ(0u, applications[0].registry_wow64_access);
+  }
+
+  // Any other file shouldn't work.
+  const base::FilePath invalid_child_file(
+      L"c:\\application files\\another application\\test.dll");
+  std::vector<InstalledApplications::ApplicationInfo> applications;
+  EXPECT_FALSE(installed_applications().GetInstalledApplications(
+      invalid_child_file, &applications));
+}
+
+// Checks that if a file matches an InstallLocation and an MSI component, only
+// the MSI application will be considered.
+TEST_F(InstalledApplicationsTest, PrioritizeMsi) {
+  const wchar_t kValidUninstallString[] = L"c:\\an\\UninstallString.exe";
+  const wchar_t kInstallLocationDisplayName[] = L"InstallLocation DisplayName";
+  const wchar_t kMsiDisplayName[] = L"Msi DisplayName";
+  const wchar_t kInstallLocation[] = L"c:\\application files\\application\\";
+  const wchar_t kMsiComponent[] =
+      L"c:\\application files\\application\\file.dll";
+
+  InstallLocationApplicationInfo kInstallLocationFakeApplication = {
+      {
+          L"GUID1", false, false, kInstallLocationDisplayName,
+          kValidUninstallString,
+      },
+      kInstallLocation,
+  };
+
+  MsiApplicationInfo kMsiFakeApplication = {
+      {
+          L"GUID2", false, false, kMsiDisplayName, kValidUninstallString,
+      },
+      {
+          kMsiComponent,
+      },
+  };
+
+  AddFakeApplication(kInstallLocationFakeApplication);
+  AddFakeApplication(kMsiFakeApplication);
+
+  InitializeInstalledApplications();
+
+  std::vector<InstalledApplications::ApplicationInfo> applications;
+  EXPECT_TRUE(installed_applications().GetInstalledApplications(
+      base::FilePath(kMsiComponent), &applications));
+  ASSERT_EQ(1u, applications.size());
+  EXPECT_NE(kInstallLocationDisplayName, applications[0].name);
+  EXPECT_EQ(kMsiDisplayName, applications[0].name);
+}
+
+// Tests that if 2 entries with conflicting InstallLocation exist, both are
+// ignored.
+TEST_F(InstalledApplicationsTest, ConflictingInstallLocations) {
+  const wchar_t kValidUninstallString[] = L"c:\\an\\UninstallString.exe";
+  const wchar_t kDisplayName1[] = L"DisplayName1";
+  const wchar_t kDisplayName2[] = L"DisplayName2";
+  const wchar_t kInstallLocationParent[] = L"c:\\application files\\company\\";
+  const wchar_t kInstallLocationChild[] =
+      L"c:\\application files\\company\\application";
+  const wchar_t kFile[] =
+      L"c:\\application files\\company\\application\\file.dll";
+
+  InstallLocationApplicationInfo kFakeApplication1 = {
+      {
+          L"GUID1", false, false, kDisplayName1, kValidUninstallString,
+      },
+      kInstallLocationParent,
+  };
+  InstallLocationApplicationInfo kFakeApplication2 = {
+      {
+          L"GUID2", false, false, kDisplayName2, kValidUninstallString,
+      },
+      kInstallLocationChild,
+  };
+
+  AddFakeApplication(kFakeApplication1);
+  AddFakeApplication(kFakeApplication2);
+
+  InitializeInstalledApplications();
+
+  std::vector<InstalledApplications::ApplicationInfo> applications;
+  EXPECT_FALSE(installed_applications().GetInstalledApplications(
+      base::FilePath(kFile), &applications));
+}
diff --git a/chrome/browser/conflicts/installed_programs_win.h b/chrome/browser/conflicts/installed_programs_win.h
deleted file mode 100644
index 72dd6d191..0000000
--- a/chrome/browser/conflicts/installed_programs_win.h
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CONFLICTS_INSTALLED_PROGRAMS_WIN_H_
-#define CHROME_BROWSER_CONFLICTS_INSTALLED_PROGRAMS_WIN_H_
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "base/win/windows_types.h"
-
-class MsiUtil;
-
-// This class inspects the user's installed programs and builds a mapping of
-// files to its associated program.
-//
-// Installed programs are found by searching the
-// "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" registry key and
-// its variants. There are 2 cases that are covered:
-//
-// 1 - If the program's installer did its due dilligence, it populated the
-//     "InstallLocation" registry key with the directory where it was installed,
-//     and all the files under that directory are assumed to be owned by this
-//     program.
-//
-//     In the event of 2 conflicting "InstallLocation", both are ignored as this
-//     method doesn't let us know for sure who is the owner of any enclosing
-//     files.
-//
-// 2 - If the program's entry is a valid MSI Product GUID, the complete list of
-//     associated file is used to exactly match a given file to a program.
-//
-//     If multiple products installed the same file as the same component,
-//     Windows keeps a reference count of that component so that the file
-//     doesn't get removed if one of them is uninstalled. So both programs are
-//     returned by GetInstalledPrograms().
-//
-//  Note: Programs may be skipped and so would not be returned by
-//        GetInstalledPrograms() for the following reasons:
-//        - The program is owned by Microsoft.
-//        - The uninstall entry is marked as a system component.
-//        - The uninstall entry has no display name.
-//        - The uninstall entry has no UninstallString.
-//
-class InstalledPrograms {
- public:
-  struct ProgramInfo {
-    base::string16 name;
-
-    // Holds the path to the uninstall entry in the registry.
-    HKEY registry_root;
-    base::string16 registry_key_path;
-    REGSAM registry_wow64_access;
-  };
-
-  // Initializes this instance with the list of installed programs. While the
-  // constructor must be called in a sequence that allows blocking, its public
-  // method can be used without such restrictions.
-  InstalledPrograms();
-
-  virtual ~InstalledPrograms();
-
-  // Given a |file|, checks if it matches an installed program on the user's
-  // machine and appends all the matching programs to |programs|.
-  // Virtual to allow mocking.
-  virtual bool GetInstalledPrograms(const base::FilePath& file,
-                                    std::vector<ProgramInfo>* programs) const;
-
- protected:
-  // Protected so that tests can subclass InstalledPrograms and access it.
-  explicit InstalledPrograms(std::unique_ptr<MsiUtil> msi_util);
-
- private:
-  // If the registry key references a valid installed program, this function
-  // adds an entry to |programs_| with its list of files or installation
-  // directory to their associated vector.
-  void CheckRegistryKeyForInstalledProgram(HKEY hkey,
-                                           const base::string16& key_path,
-                                           REGSAM wow64access,
-                                           const base::string16& key_name,
-                                           const MsiUtil& msi_util);
-
-  bool GetProgramsFromInstalledFiles(const base::FilePath& file,
-                                     std::vector<ProgramInfo>* programs) const;
-  bool GetProgramsFromInstallDirectories(
-      const base::FilePath& file,
-      std::vector<ProgramInfo>* programs) const;
-
-  // Programs are stored in this vector because multiple entries in
-  // |installed_files| could point to the same one. This is to avoid
-  // duplicating them.
-  std::vector<ProgramInfo> programs_;
-
-  // Contains all the files from programs installed via Microsoft Installer.
-  // The second part of the pair is the index into |programs|.
-  std::vector<std::pair<base::FilePath, size_t>> installed_files_;
-
-  // For some programs, the best information available is the directory of the
-  // installation. The compare functor treats file paths where one is the
-  // parent of the other as equal.
-  // The second part of the pair is the index into |programs|.
-  std::vector<std::pair<base::FilePath, size_t>> install_directories_;
-
-  DISALLOW_COPY_AND_ASSIGN(InstalledPrograms);
-};
-
-bool operator<(const InstalledPrograms::ProgramInfo& lhs,
-               const InstalledPrograms::ProgramInfo& rhs);
-
-#endif  // CHROME_BROWSER_CONFLICTS_INSTALLED_PROGRAMS_WIN_H_
diff --git a/chrome/browser/conflicts/installed_programs_win_unittest.cc b/chrome/browser/conflicts/installed_programs_win_unittest.cc
deleted file mode 100644
index 0a8f3664..0000000
--- a/chrome/browser/conflicts/installed_programs_win_unittest.cc
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/conflicts/installed_programs_win.h"
-
-#include <map>
-
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/test_reg_util_win.h"
-#include "base/win/registry.h"
-#include "chrome/browser/conflicts/msi_util_win.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-static const wchar_t kRegistryKeyPathFormat[] =
-    L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%ls";
-
-struct CommonInfo {
-  base::string16 product_id;
-  bool is_system_component;
-  bool is_microsoft_published;
-  base::string16 display_name;
-  base::string16 uninstall_string;
-};
-
-struct InstallLocationProgramInfo {
-  CommonInfo common_info;
-  base::string16 install_location;
-};
-
-struct MsiProgramInfo {
-  CommonInfo common_info;
-  std::vector<base::string16> components;
-};
-
-class MockMsiUtil : public MsiUtil {
- public:
-  MockMsiUtil(const std::map<base::string16, std::vector<base::string16>>&
-                  component_paths_map)
-      : component_paths_map_(component_paths_map) {}
-
-  bool GetMsiComponentPaths(
-      const base::string16& product_guid,
-      std::vector<base::string16>* component_paths) const override {
-    auto iter = component_paths_map_.find(product_guid);
-    if (iter == component_paths_map_.end())
-      return false;
-
-    *component_paths = iter->second;
-    return true;
-  }
-
- private:
-  const std::map<base::string16, std::vector<base::string16>>&
-      component_paths_map_;
-};
-
-class TestInstalledPrograms : public InstalledPrograms {
- public:
-  explicit TestInstalledPrograms(std::unique_ptr<MsiUtil> msi_util)
-      : InstalledPrograms(std::move(msi_util)) {}
-};
-
-class InstalledProgramsTest : public testing::Test {
- public:
-  InstalledProgramsTest() = default;
-  ~InstalledProgramsTest() override = default;
-
-  // ASSERT_NO_FATAL_FAILURE cannot be used in a constructor so the registry
-  // hive overrides are done here.
-  void SetUp() override {
-    ASSERT_NO_FATAL_FAILURE(
-        registry_override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE));
-    ASSERT_NO_FATAL_FAILURE(
-        registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER));
-  }
-
-  void AddCommonInfo(const CommonInfo& common_info,
-                     base::win::RegKey* registry_key) {
-    registry_key->WriteValue(L"SystemComponent",
-                             common_info.is_system_component ? 1 : 0);
-    registry_key->WriteValue(L"UninstallString",
-                             common_info.uninstall_string.c_str());
-    if (common_info.is_microsoft_published)
-      registry_key->WriteValue(L"Publisher", L"Microsoft Corporation");
-    registry_key->WriteValue(L"DisplayName", common_info.display_name.c_str());
-  }
-
-  void AddFakeProgram(const MsiProgramInfo& program_info) {
-    const base::string16 registry_key_path = base::StringPrintf(
-        kRegistryKeyPathFormat, program_info.common_info.product_id.c_str());
-    base::win::RegKey registry_key(HKEY_CURRENT_USER, registry_key_path.c_str(),
-                                   KEY_WRITE);
-
-    AddCommonInfo(program_info.common_info, &registry_key);
-
-    component_paths_map_.insert(
-        {program_info.common_info.product_id, program_info.components});
-  }
-
-  void AddFakeProgram(const InstallLocationProgramInfo& program_info) {
-    const base::string16 registry_key_path = base::StringPrintf(
-        kRegistryKeyPathFormat, program_info.common_info.product_id.c_str());
-    base::win::RegKey registry_key(HKEY_CURRENT_USER, registry_key_path.c_str(),
-                                   KEY_WRITE);
-
-    AddCommonInfo(program_info.common_info, &registry_key);
-
-    registry_key.WriteValue(L"InstallLocation",
-                            program_info.install_location.c_str());
-  }
-
-  TestInstalledPrograms& installed_programs() { return *installed_programs_; }
-
-  void InitializeInstalledPrograms() {
-    installed_programs_ = std::make_unique<TestInstalledPrograms>(
-        std::make_unique<MockMsiUtil>(component_paths_map_));
-  }
-
- private:
-  registry_util::RegistryOverrideManager registry_override_manager_;
-
-  std::unique_ptr<TestInstalledPrograms> installed_programs_;
-
-  std::map<base::string16, std::vector<base::string16>> component_paths_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(InstalledProgramsTest);
-};
-
-}  // namespace
-
-// Checks that registry entries with invalid information are skipped.
-TEST_F(InstalledProgramsTest, InvalidEntries) {
-  const wchar_t kValidDisplayName[] = L"ADisplayName";
-  const wchar_t kValidUninstallString[] = L"c:\\an\\UninstallString.exe";
-  const wchar_t kInstallLocation[] = L"c:\\program files\\program\\";
-
-  InstallLocationProgramInfo kTestCases[] = {
-      {
-          {
-              L"Is SystemComponent", true, false, kValidDisplayName,
-              kValidUninstallString,
-          },
-          kInstallLocation,
-      },
-      {
-          {
-              L"Is Microsoft published", false, true, kValidDisplayName,
-              kValidUninstallString,
-          },
-          kInstallLocation,
-      },
-      {
-          {
-              L"Missing DisplayName", false, false, L"", kValidUninstallString,
-          },
-          kInstallLocation,
-      },
-      {
-          {
-              L"Missing UninstallString", false, false, kValidDisplayName, L"",
-          },
-          kInstallLocation,
-      },
-  };
-
-  for (const auto& test_case : kTestCases)
-    AddFakeProgram(test_case);
-
-  InitializeInstalledPrograms();
-
-  // None of the invalid entries were picked up.
-  const base::FilePath valid_child_file =
-      base::FilePath(kInstallLocation).Append(L"file.dll");
-  std::vector<InstalledPrograms::ProgramInfo> programs;
-  EXPECT_FALSE(
-      installed_programs().GetInstalledPrograms(valid_child_file, &programs));
-}
-
-// Tests InstalledPrograms on a valid entry with an InstallLocation.
-TEST_F(InstalledProgramsTest, InstallLocation) {
-  const wchar_t kValidDisplayName[] = L"ADisplayName";
-  const wchar_t kValidUninstallString[] = L"c:\\an\\UninstallString.exe";
-  const wchar_t kInstallLocation[] = L"c:\\program files\\program\\";
-
-  InstallLocationProgramInfo kTestCase = {
-      {
-          L"Completely valid", false, false, kValidDisplayName,
-          kValidUninstallString,
-      },
-      kInstallLocation,
-  };
-
-  AddFakeProgram(kTestCase);
-
-  InitializeInstalledPrograms();
-
-  // Child file path.
-  const base::FilePath valid_child_file =
-      base::FilePath(kInstallLocation).Append(L"file.dll");
-  std::vector<InstalledPrograms::ProgramInfo> programs;
-  EXPECT_TRUE(
-      installed_programs().GetInstalledPrograms(valid_child_file, &programs));
-  ASSERT_EQ(1u, programs.size());
-  EXPECT_EQ(kTestCase.common_info.display_name, programs[0].name);
-  EXPECT_EQ(HKEY_CURRENT_USER, programs[0].registry_root);
-  EXPECT_FALSE(programs[0].registry_key_path.empty());
-  EXPECT_EQ(0u, programs[0].registry_wow64_access);
-
-  // Non-child file path.
-  const base::FilePath invalid_child_file(
-      L"c:\\program files\\another program\\test.dll");
-  EXPECT_FALSE(
-      installed_programs().GetInstalledPrograms(invalid_child_file, &programs));
-}
-
-// Tests InstalledPrograms on a valid MSI entry.
-TEST_F(InstalledProgramsTest, Msi) {
-  const wchar_t kValidDisplayName[] = L"ADisplayName";
-  const wchar_t kValidUninstallString[] = L"c:\\an\\UninstallString.exe";
-
-  MsiProgramInfo kTestCase = {
-      {
-          L"Completely valid", false, false, kValidDisplayName,
-          kValidUninstallString,
-      },
-      {
-          L"c:\\program files\\program\\file1.dll",
-          L"c:\\program files\\program\\file2.dll",
-          L"c:\\program files\\program\\sub\\file3.dll",
-          L"c:\\windows\\system32\\file4.dll",
-      },
-  };
-
-  AddFakeProgram(kTestCase);
-
-  InitializeInstalledPrograms();
-
-  // Checks that all the files match the program.
-  for (const auto& component : kTestCase.components) {
-    std::vector<InstalledPrograms::ProgramInfo> programs;
-    EXPECT_TRUE(installed_programs().GetInstalledPrograms(
-        base::FilePath(component), &programs));
-    ASSERT_EQ(1u, programs.size());
-    EXPECT_EQ(kTestCase.common_info.display_name, programs[0].name);
-    EXPECT_EQ(HKEY_CURRENT_USER, programs[0].registry_root);
-    EXPECT_FALSE(programs[0].registry_key_path.empty());
-    EXPECT_EQ(0u, programs[0].registry_wow64_access);
-  }
-
-  // Any other file shouldn't work.
-  const base::FilePath invalid_child_file(
-      L"c:\\program files\\another program\\test.dll");
-  std::vector<InstalledPrograms::ProgramInfo> programs;
-  EXPECT_FALSE(
-      installed_programs().GetInstalledPrograms(invalid_child_file, &programs));
-}
-
-// Checks that if a file matches an InstallLocation and an MSI component, only
-// the MSI program will be considered.
-TEST_F(InstalledProgramsTest, PrioritizeMsi) {
-  const wchar_t kValidUninstallString[] = L"c:\\an\\UninstallString.exe";
-  const wchar_t kInstallLocationDisplayName[] = L"InstallLocation DisplayName";
-  const wchar_t kMsiDisplayName[] = L"Msi DisplayName";
-  const wchar_t kInstallLocation[] = L"c:\\program files\\program\\";
-  const wchar_t kMsiComponent[] = L"c:\\program files\\program\\file.dll";
-
-  InstallLocationProgramInfo kInstallLocationFakeProgram = {
-      {
-          L"GUID1", false, false, kInstallLocationDisplayName,
-          kValidUninstallString,
-      },
-      kInstallLocation,
-  };
-
-  MsiProgramInfo kMsiFakeProgram = {
-      {
-          L"GUID2", false, false, kMsiDisplayName, kValidUninstallString,
-      },
-      {
-          kMsiComponent,
-      },
-  };
-
-  AddFakeProgram(kInstallLocationFakeProgram);
-  AddFakeProgram(kMsiFakeProgram);
-
-  InitializeInstalledPrograms();
-
-  std::vector<InstalledPrograms::ProgramInfo> programs;
-  EXPECT_TRUE(installed_programs().GetInstalledPrograms(
-      base::FilePath(kMsiComponent), &programs));
-  ASSERT_EQ(1u, programs.size());
-  EXPECT_NE(kInstallLocationDisplayName, programs[0].name);
-  EXPECT_EQ(kMsiDisplayName, programs[0].name);
-}
-
-// Tests that if 2 entries with conflicting InstallLocation exist, both are
-// ignored.
-TEST_F(InstalledProgramsTest, ConflictingInstallLocations) {
-  const wchar_t kValidUninstallString[] = L"c:\\an\\UninstallString.exe";
-  const wchar_t kDisplayName1[] = L"DisplayName1";
-  const wchar_t kDisplayName2[] = L"DisplayName2";
-  const wchar_t kInstallLocationParent[] = L"c:\\program files\\company\\";
-  const wchar_t kInstallLocationChild[] =
-      L"c:\\program files\\company\\program";
-  const wchar_t kFile[] = L"c:\\program files\\company\\program\\file.dll";
-
-  InstallLocationProgramInfo kFakeProgram1 = {
-      {
-          L"GUID1", false, false, kDisplayName1, kValidUninstallString,
-      },
-      kInstallLocationParent,
-  };
-  InstallLocationProgramInfo kFakeProgram2 = {
-      {
-          L"GUID2", false, false, kDisplayName2, kValidUninstallString,
-      },
-      kInstallLocationChild,
-  };
-
-  AddFakeProgram(kFakeProgram1);
-  AddFakeProgram(kFakeProgram2);
-
-  InitializeInstalledPrograms();
-
-  std::vector<InstalledPrograms::ProgramInfo> programs;
-  EXPECT_FALSE(installed_programs().GetInstalledPrograms(base::FilePath(kFile),
-                                                         &programs));
-}
diff --git a/chrome/browser/conflicts/module_database_win.h b/chrome/browser/conflicts/module_database_win.h
index 80bb624..18ef3b3 100644
--- a/chrome/browser/conflicts/module_database_win.h
+++ b/chrome/browser/conflicts/module_database_win.h
@@ -33,7 +33,7 @@
 // A class that keeps track of all modules loaded across Chrome processes.
 //
 // It is also the main class behind third-party modules tracking, and owns the
-// different classes that required to identify problematic programs and
+// different classes that required to identify incompatible applications and
 // record metrics.
 //
 // This is effectively a singleton, but doesn't use base::Singleton. The intent
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win.cc b/chrome/browser/conflicts/problematic_programs_updater_win.cc
deleted file mode 100644
index 81a76a24..0000000
--- a/chrome/browser/conflicts/problematic_programs_updater_win.cc
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/conflicts/problematic_programs_updater_win.h"
-
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "base/win/registry.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/conflicts/module_database_win.h"
-#include "chrome/browser/conflicts/module_info_util_win.h"
-#include "chrome/browser/conflicts/module_list_filter_win.h"
-#include "chrome/browser/conflicts/third_party_metrics_recorder_win.h"
-#include "chrome/common/pref_names.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/scoped_user_pref_update.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace {
-
-// Serializes a vector of ProblematicPrograms to JSON.
-base::Value ConvertToDictionary(
-    const std::vector<ProblematicProgramsUpdater::ProblematicProgram>&
-        programs) {
-  base::Value result(base::Value::Type::DICTIONARY);
-
-  for (const auto& program : programs) {
-    base::Value element(base::Value::Type::DICTIONARY);
-
-    // The registry location is necessary to quickly figure out if that program
-    // is still installed on the computer.
-    element.SetKey("registry_is_hkcu", base::Value(program.info.registry_root ==
-                                                   HKEY_CURRENT_USER));
-    element.SetKey("registry_key_path",
-                   base::Value(program.info.registry_key_path));
-    element.SetKey(
-        "registry_wow64_access",
-        base::Value(static_cast<int>(program.info.registry_wow64_access)));
-
-    // And then the actual information needed to display a warning to the user.
-    element.SetKey("allow_load",
-                   base::Value(program.blacklist_action->allow_load()));
-    element.SetKey("type",
-                   base::Value(program.blacklist_action->message_type()));
-    element.SetKey("message_url",
-                   base::Value(program.blacklist_action->message_url()));
-
-    result.SetKey(base::UTF16ToUTF8(program.info.name), std::move(element));
-  }
-
-  return result;
-}
-
-// Deserializes a ProblematicProgram named |name| from |value|. Returns null if
-// |value| is not a dict containing all required fields.
-std::unique_ptr<ProblematicProgramsUpdater::ProblematicProgram>
-ConvertToProblematicProgram(const std::string& name, const base::Value& value) {
-  if (!value.is_dict())
-    return nullptr;
-
-  const base::Value* registry_is_hkcu_value =
-      value.FindKeyOfType("registry_is_hkcu", base::Value::Type::BOOLEAN);
-  const base::Value* registry_key_path_value =
-      value.FindKeyOfType("registry_key_path", base::Value::Type::STRING);
-  const base::Value* registry_wow64_access_value =
-      value.FindKeyOfType("registry_wow64_access", base::Value::Type::INTEGER);
-  const base::Value* allow_load_value =
-      value.FindKeyOfType("allow_load", base::Value::Type::BOOLEAN);
-  const base::Value* type_value =
-      value.FindKeyOfType("type", base::Value::Type::INTEGER);
-  const base::Value* message_url_value =
-      value.FindKeyOfType("message_url", base::Value::Type::STRING);
-
-  // All of the above are required for a valid program.
-  if (!registry_is_hkcu_value || !registry_key_path_value ||
-      !registry_wow64_access_value || !allow_load_value || !type_value ||
-      !message_url_value) {
-    return nullptr;
-  }
-
-  InstalledPrograms::ProgramInfo program_info = {
-      base::UTF8ToUTF16(name),
-      registry_is_hkcu_value->GetBool() ? HKEY_CURRENT_USER
-                                        : HKEY_LOCAL_MACHINE,
-      base::UTF8ToUTF16(registry_key_path_value->GetString()),
-      static_cast<REGSAM>(registry_wow64_access_value->GetInt())};
-
-  auto blacklist_action =
-      std::make_unique<chrome::conflicts::BlacklistAction>();
-  blacklist_action->set_allow_load(allow_load_value->GetBool());
-  blacklist_action->set_message_type(
-      static_cast<chrome::conflicts::BlacklistMessageType>(
-          type_value->GetInt()));
-  blacklist_action->set_message_url(message_url_value->GetString());
-
-  return std::make_unique<ProblematicProgramsUpdater::ProblematicProgram>(
-      std::move(program_info), std::move(blacklist_action));
-}
-
-// Returns true if |program| references an existing program in the registry.
-//
-// Used to filter out stale programs from the cache. This can happen if a
-// program was uninstalled between the time it was found and Chrome was
-// relaunched.
-bool IsValidProgram(
-    const ProblematicProgramsUpdater::ProblematicProgram& program) {
-  return base::win::RegKey(program.info.registry_root,
-                           program.info.registry_key_path.c_str(),
-                           KEY_QUERY_VALUE | program.info.registry_wow64_access)
-      .Valid();
-}
-
-// Clears the cache of all the programs whose name is in |state_program_names|.
-void RemoveStalePrograms(const std::vector<std::string>& stale_program_names) {
-  // Early exit because DictionaryPrefUpdate will write to the pref even if it
-  // doesn't contain a value.
-  if (stale_program_names.empty())
-    return;
-
-  DictionaryPrefUpdate update(g_browser_process->local_state(),
-                              prefs::kProblematicPrograms);
-  base::Value* existing_programs = update.Get();
-
-  for (const auto& program_name : stale_program_names) {
-    bool removed = existing_programs->RemoveKey(program_name);
-    DCHECK(removed);
-  }
-}
-
-// Applies the given |function| object to each valid ProblematicProgram found
-// in the kProblematicPrograms preference.
-//
-// The signature of the function must be equivalent to the following:
-//   bool Function(std::unique_ptr<ProblematicProgram> program));
-//
-// The return value of |function| indicates if the enumeration should continue
-// (true) or be stopped (false).
-//
-// This function takes care of removing invalid entries that are found during
-// the enumeration.
-template <class UnaryFunction>
-void EnumerateAndTrimProblematicPrograms(UnaryFunction function) {
-  std::vector<std::string> stale_program_names;
-  for (const auto& item : g_browser_process->local_state()
-                              ->FindPreference(prefs::kProblematicPrograms)
-                              ->GetValue()
-                              ->DictItems()) {
-    auto program = ConvertToProblematicProgram(item.first, item.second);
-
-    if (!program || !IsValidProgram(*program)) {
-      // Mark every invalid program as stale so they are removed from the cache.
-      stale_program_names.push_back(item.first);
-      continue;
-    }
-
-    // Notify the caller and stop the enumeration if requested by the function.
-    if (!function(std::move(program)))
-      break;
-  }
-
-  RemoveStalePrograms(stale_program_names);
-}
-
-}  // namespace
-
-// ProblematicProgram ----------------------------------------------------------
-
-ProblematicProgramsUpdater::ProblematicProgram::ProblematicProgram(
-    InstalledPrograms::ProgramInfo info,
-    std::unique_ptr<chrome::conflicts::BlacklistAction> blacklist_action)
-    : info(std::move(info)), blacklist_action(std::move(blacklist_action)) {}
-
-ProblematicProgramsUpdater::ProblematicProgram::~ProblematicProgram() = default;
-
-ProblematicProgramsUpdater::ProblematicProgram::ProblematicProgram(
-    ProblematicProgram&& problematic_program) = default;
-
-ProblematicProgramsUpdater::ProblematicProgram&
-ProblematicProgramsUpdater::ProblematicProgram::operator=(
-    ProblematicProgram&& problematic_program) = default;
-
-// ProblematicProgramsUpdater --------------------------------------------------
-
-ProblematicProgramsUpdater::ProblematicProgramsUpdater(
-    const CertificateInfo& exe_certificate_info,
-    const ModuleListFilter& module_list_filter,
-    const InstalledPrograms& installed_programs)
-    : exe_certificate_info_(exe_certificate_info),
-      module_list_filter_(module_list_filter),
-      installed_programs_(installed_programs) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-}
-
-ProblematicProgramsUpdater::~ProblematicProgramsUpdater() = default;
-
-// static
-void ProblematicProgramsUpdater::RegisterLocalStatePrefs(
-    PrefRegistrySimple* registry) {
-  registry->RegisterDictionaryPref(prefs::kProblematicPrograms);
-}
-
-// static
-bool ProblematicProgramsUpdater::IsIncompatibleApplicationsWarningEnabled() {
-  return ModuleDatabase::GetInstance() &&
-         ModuleDatabase::GetInstance()->third_party_conflicts_manager();
-}
-
-// static
-bool ProblematicProgramsUpdater::HasCachedPrograms() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  bool found_valid_program = false;
-
-  EnumerateAndTrimProblematicPrograms(
-      [&found_valid_program](std::unique_ptr<ProblematicProgram> program) {
-        found_valid_program = true;
-
-        // Break the enumeration.
-        return false;
-      });
-
-  return found_valid_program;
-}
-
-// static
-std::vector<ProblematicProgramsUpdater::ProblematicProgram>
-ProblematicProgramsUpdater::GetCachedPrograms() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  std::vector<ProblematicProgram> valid_programs;
-
-  EnumerateAndTrimProblematicPrograms(
-      [&valid_programs](std::unique_ptr<ProblematicProgram> program) {
-        valid_programs.push_back(std::move(*program));
-
-        // Continue the enumeration.
-        return true;
-      });
-
-  return valid_programs;
-}
-
-void ProblematicProgramsUpdater::OnNewModuleFound(
-    const ModuleInfoKey& module_key,
-    const ModuleInfoData& module_data) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  // Only consider loaded modules that are not shell extensions or IMEs.
-  static constexpr uint32_t kModuleTypesBitmask =
-      ModuleInfoData::kTypeLoadedModule | ModuleInfoData::kTypeShellExtension |
-      ModuleInfoData::kTypeIme;
-  if ((module_data.module_types & kModuleTypesBitmask) !=
-      ModuleInfoData::kTypeLoadedModule) {
-    return;
-  }
-
-  // Explicitly whitelist modules whose signing cert's Subject field matches the
-  // one in the current executable. No attempt is made to check the validity of
-  // module signatures or of signing certs.
-  if (exe_certificate_info_.type != CertificateType::NO_CERTIFICATE &&
-      exe_certificate_info_.subject ==
-          module_data.inspection_result->certificate_info.subject) {
-    return;
-  }
-
-  // Skip modules whitelisted by the Module List component.
-  if (module_list_filter_.IsWhitelisted(module_key, module_data))
-    return;
-
-  // Also skip a module if it cannot be associated with an installed program
-  // on the user's computer.
-  std::vector<InstalledPrograms::ProgramInfo> associated_programs;
-  if (!installed_programs_.GetInstalledPrograms(module_key.module_path,
-                                                &associated_programs)) {
-    return;
-  }
-
-  std::unique_ptr<chrome::conflicts::BlacklistAction> blacklist_action =
-      module_list_filter_.IsBlacklisted(module_key, module_data);
-  if (!blacklist_action) {
-    // The default behavior is to suggest to uninstall.
-    blacklist_action = std::make_unique<chrome::conflicts::BlacklistAction>();
-    blacklist_action->set_allow_load(true);
-    blacklist_action->set_message_type(
-        chrome::conflicts::BlacklistMessageType::UNINSTALL);
-    blacklist_action->set_message_url(std::string());
-  }
-
-  for (auto&& associated_program : associated_programs) {
-    problematic_programs_.emplace_back(
-        std::move(associated_program),
-        std::make_unique<chrome::conflicts::BlacklistAction>(
-            *blacklist_action));
-  }
-}
-
-void ProblematicProgramsUpdater::OnModuleDatabaseIdle() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  // On the first call to OnModuleDatabaseIdle(), the previous value must always
-  // be overwritten.
-  if (before_first_idle_)
-    g_browser_process->local_state()->ClearPref(prefs::kProblematicPrograms);
-  before_first_idle_ = false;
-
-  // If there is no new problematic programs, there is nothing to do.
-  if (problematic_programs_.empty())
-    return;
-
-  // The conversion of the accumulated programs to a json dictionary takes care
-  // of eliminating duplicates.
-  base::Value new_programs = ConvertToDictionary(problematic_programs_);
-  problematic_programs_.clear();
-
-  // Update the existing dictionary.
-  DictionaryPrefUpdate update(g_browser_process->local_state(),
-                              prefs::kProblematicPrograms);
-  base::Value* existing_programs = update.Get();
-  for (auto&& element : new_programs.DictItems()) {
-    existing_programs->SetKey(std::move(element.first),
-                              std::move(element.second));
-  }
-}
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win.h b/chrome/browser/conflicts/problematic_programs_updater_win.h
deleted file mode 100644
index da7dd84..0000000
--- a/chrome/browser/conflicts/problematic_programs_updater_win.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CONFLICTS_PROBLEMATIC_PROGRAMS_UPDATER_WIN_H_
-#define CHROME_BROWSER_CONFLICTS_PROBLEMATIC_PROGRAMS_UPDATER_WIN_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "chrome/browser/conflicts/installed_programs_win.h"
-#include "chrome/browser/conflicts/module_database_observer_win.h"
-#include "chrome/browser/conflicts/proto/module_list.pb.h"
-
-struct CertificateInfo;
-class ModuleListFilter;
-class PrefRegistrySimple;
-
-// Maintains a list of problematic programs that are installed on the machine.
-// These programs cause unwanted DLLs to be loaded into Chrome.
-//
-// Because the list is expensive to build, it is cached into the Local State
-// file so that it is available at startup.
-class ProblematicProgramsUpdater : public ModuleDatabaseObserver {
- public:
-  struct ProblematicProgram {
-    ProblematicProgram(
-        InstalledPrograms::ProgramInfo info,
-        std::unique_ptr<chrome::conflicts::BlacklistAction> blacklist_action);
-    ~ProblematicProgram();
-
-    // Needed for std::remove_if().
-    ProblematicProgram(ProblematicProgram&& problematic_program);
-    ProblematicProgram& operator=(ProblematicProgram&& problematic_program);
-
-    InstalledPrograms::ProgramInfo info;
-    std::unique_ptr<chrome::conflicts::BlacklistAction> blacklist_action;
-  };
-
-  // Creates an instance of the updater.
-  // The parameters must outlive the lifetime of this class.
-  ProblematicProgramsUpdater(const CertificateInfo& exe_certificate_info,
-                             const ModuleListFilter& module_list_filter,
-                             const InstalledPrograms& installed_programs);
-  ~ProblematicProgramsUpdater() override;
-
-  static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
-
-  // Returns true if the tracking of incompatible applications is enabled. The
-  // return value will not change throughout the lifetime of the process.
-  static bool IsIncompatibleApplicationsWarningEnabled();
-
-  // Returns true if the cache contains at least one problematic program.
-  // Only call this if IsIncompatibleApplicationsWarningEnabled() returns true.
-  static bool HasCachedPrograms();
-
-  // Returns all the cached problematic programs.
-  // Only call this if IsIncompatibleApplicationsWarningEnabled() returns true.
-  static std::vector<ProblematicProgram> GetCachedPrograms();
-
-  // ModuleDatabaseObserver:
-  void OnNewModuleFound(const ModuleInfoKey& module_key,
-                        const ModuleInfoData& module_data) override;
-  void OnModuleDatabaseIdle() override;
-
- private:
-  const CertificateInfo& exe_certificate_info_;
-
-  const ModuleListFilter& module_list_filter_;
-
-  const InstalledPrograms& installed_programs_;
-
-  // Temporarily holds problematic programs that were recently found.
-  std::vector<ProblematicProgram> problematic_programs_;
-
-  // Becomes false on the first call to OnModuleDatabaseIdle.
-  bool before_first_idle_ = true;
-
-  DISALLOW_COPY_AND_ASSIGN(ProblematicProgramsUpdater);
-};
-
-#endif  // CHROME_BROWSER_CONFLICTS_PROBLEMATIC_PROGRAMS_UPDATER_WIN_H_
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc b/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc
deleted file mode 100644
index da9fdc1..0000000
--- a/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/conflicts/problematic_programs_updater_win.h"
-
-#include <map>
-#include <string>
-#include <utility>
-
-#include "base/logging.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/test_reg_util_win.h"
-#include "base/win/registry.h"
-#include "chrome/browser/conflicts/module_info_win.h"
-#include "chrome/browser/conflicts/module_list_filter_win.h"
-#include "chrome/test/base/scoped_testing_local_state.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// Mocks an empty whitelist and blacklist.
-class MockModuleListFilter : public ModuleListFilter {
- public:
-  MockModuleListFilter() = default;
-  ~MockModuleListFilter() override = default;
-
-  bool IsWhitelisted(base::StringPiece module_basename_hash,
-                     base::StringPiece module_code_id_hash) const override {
-    return false;
-  }
-
-  std::unique_ptr<chrome::conflicts::BlacklistAction> IsBlacklisted(
-      const ModuleInfoKey& module_key,
-      const ModuleInfoData& module_data) const override {
-    return nullptr;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockModuleListFilter);
-};
-
-class MockInstalledPrograms : public InstalledPrograms {
- public:
-  MockInstalledPrograms() = default;
-  ~MockInstalledPrograms() override = default;
-
-  void AddInstalledProgram(const base::FilePath& file_path,
-                           ProgramInfo program_info) {
-    programs_.insert({file_path, std::move(program_info)});
-  }
-
-  bool GetInstalledPrograms(const base::FilePath& file,
-                            std::vector<ProgramInfo>* programs) const override {
-    auto range = programs_.equal_range(file);
-
-    if (std::distance(range.first, range.second) == 0)
-      return false;
-
-    for (auto it = range.first; it != range.second; ++it)
-      programs->push_back(it->second);
-    return true;
-  }
-
- private:
-  std::multimap<base::FilePath, ProgramInfo> programs_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockInstalledPrograms);
-};
-
-constexpr wchar_t kCertificatePath[] = L"CertificatePath";
-constexpr wchar_t kCertificateSubject[] = L"CertificateSubject";
-
-constexpr wchar_t kDllPath1[] = L"c:\\path\\to\\module.dll";
-constexpr wchar_t kDllPath2[] = L"c:\\some\\shellextension.dll";
-
-// Returns a new ModuleInfoData marked as loaded into the process but otherwise
-// empty.
-ModuleInfoData CreateLoadedModuleInfoData() {
-  ModuleInfoData module_data;
-  module_data.module_types |= ModuleInfoData::kTypeLoadedModule;
-  module_data.inspection_result = std::make_unique<ModuleInspectionResult>();
-  return module_data;
-}
-
-// Returns a new ModuleInfoData marked as loaded into the process with a
-// CertificateInfo that matches kCertificateSubject.
-ModuleInfoData CreateSignedLoadedModuleInfoData() {
-  ModuleInfoData module_data = CreateLoadedModuleInfoData();
-
-  module_data.inspection_result->certificate_info.type =
-      CertificateType::CERTIFICATE_IN_FILE;
-  module_data.inspection_result->certificate_info.path =
-      base::FilePath(kCertificatePath);
-  module_data.inspection_result->certificate_info.subject = kCertificateSubject;
-
-  return module_data;
-}
-
-}  // namespace
-
-class ProblematicProgramsUpdaterTest : public testing::Test {
- protected:
-  ProblematicProgramsUpdaterTest()
-      : dll1_(kDllPath1),
-        dll2_(kDllPath2),
-        scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) {
-    exe_certificate_info_.type = CertificateType::CERTIFICATE_IN_FILE;
-    exe_certificate_info_.path = base::FilePath(kCertificatePath);
-    exe_certificate_info_.subject = kCertificateSubject;
-  }
-
-  void SetUp() override {
-    ASSERT_NO_FATAL_FAILURE(
-        registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER));
-  }
-
-  enum class Option {
-    ADD_REGISTRY_ENTRY,
-    NO_REGISTRY_ENTRY,
-  };
-  void AddProblematicProgram(const base::FilePath& injected_module_path,
-                             const base::string16& program_name,
-                             Option option) {
-    static constexpr wchar_t kUninstallRegKeyFormat[] =
-        L"dummy\\uninstall\\%ls";
-
-    const base::string16 registry_key_path =
-        base::StringPrintf(kUninstallRegKeyFormat, program_name.c_str());
-
-    installed_programs_.AddInstalledProgram(
-        injected_module_path,
-        {program_name, HKEY_CURRENT_USER, registry_key_path, KEY_WOW64_32KEY});
-
-    if (option == Option::ADD_REGISTRY_ENTRY) {
-      base::win::RegKey reg_key(HKEY_CURRENT_USER, registry_key_path.c_str(),
-                                KEY_WOW64_32KEY | KEY_CREATE_SUB_KEY);
-    }
-  }
-
-  CertificateInfo& exe_certificate_info() { return exe_certificate_info_; }
-  MockModuleListFilter& module_list_filter() { return module_list_filter_; }
-  MockInstalledPrograms& installed_programs() { return installed_programs_; }
-
-  const base::FilePath dll1_;
-  const base::FilePath dll2_;
-
- private:
-  content::TestBrowserThreadBundle test_browser_thread_bundle_;
-  ScopedTestingLocalState scoped_testing_local_state_;
-  registry_util::RegistryOverrideManager registry_override_manager_;
-
-  CertificateInfo exe_certificate_info_;
-  MockModuleListFilter module_list_filter_;
-  MockInstalledPrograms installed_programs_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProblematicProgramsUpdaterTest);
-};
-
-// Tests that when the Local State cache is empty, no problematic programs are
-// returned.
-TEST_F(ProblematicProgramsUpdaterTest, EmptyCache) {
-  EXPECT_FALSE(ProblematicProgramsUpdater::HasCachedPrograms());
-  EXPECT_TRUE(ProblematicProgramsUpdater::GetCachedPrograms().empty());
-}
-
-// ProblematicProgramsUpdater doesn't do anything when there is no registered
-// installed programs.
-TEST_F(ProblematicProgramsUpdaterTest, NoProblematicPrograms) {
-  auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(
-          exe_certificate_info(), module_list_filter(), installed_programs());
-
-  // Simulate some arbitrary module loading into the process.
-  problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
-                                                 CreateLoadedModuleInfoData());
-  problematic_programs_updater->OnModuleDatabaseIdle();
-
-  EXPECT_FALSE(ProblematicProgramsUpdater::HasCachedPrograms());
-  EXPECT_TRUE(ProblematicProgramsUpdater::GetCachedPrograms().empty());
-}
-
-TEST_F(ProblematicProgramsUpdaterTest, OneConflict) {
-  AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
-
-  auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(
-          exe_certificate_info(), module_list_filter(), installed_programs());
-
-  // Simulate the module loading into the process.
-  problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
-                                                 CreateLoadedModuleInfoData());
-  problematic_programs_updater->OnModuleDatabaseIdle();
-
-  EXPECT_TRUE(ProblematicProgramsUpdater::HasCachedPrograms());
-  auto program_names = ProblematicProgramsUpdater::GetCachedPrograms();
-  ASSERT_EQ(1u, program_names.size());
-  EXPECT_EQ(L"Foo", program_names[0].info.name);
-}
-
-TEST_F(ProblematicProgramsUpdaterTest, SameModuleMultiplePrograms) {
-  AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
-  AddProblematicProgram(dll1_, L"Bar", Option::ADD_REGISTRY_ENTRY);
-
-  auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(
-          exe_certificate_info(), module_list_filter(), installed_programs());
-
-  // Simulate the module loading into the process.
-  problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
-                                                 CreateLoadedModuleInfoData());
-  problematic_programs_updater->OnModuleDatabaseIdle();
-
-  EXPECT_TRUE(ProblematicProgramsUpdater::HasCachedPrograms());
-  auto program_names = ProblematicProgramsUpdater::GetCachedPrograms();
-  ASSERT_EQ(2u, program_names.size());
-}
-
-TEST_F(ProblematicProgramsUpdaterTest, MultipleCallsToOnModuleDatabaseIdle) {
-  AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
-  AddProblematicProgram(dll2_, L"Bar", Option::ADD_REGISTRY_ENTRY);
-
-  auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(
-          exe_certificate_info(), module_list_filter(), installed_programs());
-
-  // Simulate the module loading into the process.
-  problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
-                                                 CreateLoadedModuleInfoData());
-  problematic_programs_updater->OnModuleDatabaseIdle();
-
-  // Add an additional module.
-  problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll2_, 0, 0, 0),
-                                                 CreateLoadedModuleInfoData());
-  problematic_programs_updater->OnModuleDatabaseIdle();
-
-  EXPECT_TRUE(ProblematicProgramsUpdater::HasCachedPrograms());
-  auto program_names = ProblematicProgramsUpdater::GetCachedPrograms();
-  ASSERT_EQ(2u, program_names.size());
-}
-
-// This is meant to test that cached problematic programs are persisted
-// through browser restarts, via the Local State file.
-//
-// Since this isn't really doable in a unit test, this test at least check that
-// the list isn't tied to the lifetime of the ProblematicProgramsUpdater
-// instance. It is assumed that the Local State file works as intended.
-TEST_F(ProblematicProgramsUpdaterTest, PersistsThroughRestarts) {
-  AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
-
-  auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(
-          exe_certificate_info(), module_list_filter(), installed_programs());
-
-  // Simulate the module loading into the process.
-  problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
-                                                 CreateLoadedModuleInfoData());
-  problematic_programs_updater->OnModuleDatabaseIdle();
-
-  EXPECT_TRUE(ProblematicProgramsUpdater::HasCachedPrograms());
-
-  // Delete the instance.
-  problematic_programs_updater = nullptr;
-
-  EXPECT_TRUE(ProblematicProgramsUpdater::HasCachedPrograms());
-}
-
-// Tests that programs that do not have a registry entry are removed.
-TEST_F(ProblematicProgramsUpdaterTest, StaleEntriesRemoved) {
-  AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
-  AddProblematicProgram(dll2_, L"Bar", Option::NO_REGISTRY_ENTRY);
-
-  auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(
-          exe_certificate_info(), module_list_filter(), installed_programs());
-
-  // Simulate the modules loading into the process.
-  problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
-                                                 CreateLoadedModuleInfoData());
-  problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll2_, 0, 0, 0),
-                                                 CreateLoadedModuleInfoData());
-  problematic_programs_updater->OnModuleDatabaseIdle();
-
-  EXPECT_TRUE(ProblematicProgramsUpdater::HasCachedPrograms());
-  auto program_names = ProblematicProgramsUpdater::GetCachedPrograms();
-  ASSERT_EQ(1u, program_names.size());
-  EXPECT_EQ(L"Foo", program_names[0].info.name);
-}
-
-// Tests that modules with a matching certificate subject are whitelisted.
-TEST_F(ProblematicProgramsUpdaterTest, WhitelistMatchingCertificateSubject) {
-  AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
-
-  auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(
-          exe_certificate_info(), module_list_filter(), installed_programs());
-
-  // Simulate the module loading into the process.
-  problematic_programs_updater->OnNewModuleFound(
-      ModuleInfoKey(dll1_, 0, 0, 0), CreateSignedLoadedModuleInfoData());
-  problematic_programs_updater->OnModuleDatabaseIdle();
-
-  EXPECT_FALSE(ProblematicProgramsUpdater::HasCachedPrograms());
-  auto program_names = ProblematicProgramsUpdater::GetCachedPrograms();
-  ASSERT_EQ(0u, program_names.size());
-}
-
-// Registered modules are defined as either a shell extension or an IME.
-TEST_F(ProblematicProgramsUpdaterTest, IgnoreRegisteredModules) {
-  AddProblematicProgram(dll1_, L"Shell Extension", Option::ADD_REGISTRY_ENTRY);
-  AddProblematicProgram(dll2_, L"Input Method Editor",
-                        Option::ADD_REGISTRY_ENTRY);
-
-  auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(
-          exe_certificate_info(), module_list_filter(), installed_programs());
-
-  // Set the respective bit for registered modules.
-  auto module_data1 = CreateLoadedModuleInfoData();
-  module_data1.module_types |= ModuleInfoData::kTypeShellExtension;
-  auto module_data2 = CreateLoadedModuleInfoData();
-  module_data2.module_types |= ModuleInfoData::kTypeIme;
-
-  // Simulate the modules loading into the process.
-  problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
-                                                 module_data1);
-  problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll2_, 0, 0, 0),
-                                                 module_data2);
-  problematic_programs_updater->OnModuleDatabaseIdle();
-
-  EXPECT_FALSE(ProblematicProgramsUpdater::HasCachedPrograms());
-  auto program_names = ProblematicProgramsUpdater::GetCachedPrograms();
-  ASSERT_EQ(0u, program_names.size());
-}
diff --git a/chrome/browser/conflicts/third_party_conflicts_manager_win.cc b/chrome/browser/conflicts/third_party_conflicts_manager_win.cc
index 90b39dd..3a0d8a08e 100644
--- a/chrome/browser/conflicts/third_party_conflicts_manager_win.cc
+++ b/chrome/browser/conflicts/third_party_conflicts_manager_win.cc
@@ -11,11 +11,11 @@
 #include "base/location.h"
 #include "base/path_service.h"
 #include "base/task_scheduler/post_task.h"
-#include "chrome/browser/conflicts/installed_programs_win.h"
+#include "chrome/browser/conflicts/incompatible_applications_updater_win.h"
+#include "chrome/browser/conflicts/installed_applications_win.h"
 #include "chrome/browser/conflicts/module_database_win.h"
 #include "chrome/browser/conflicts/module_info_util_win.h"
 #include "chrome/browser/conflicts/module_list_filter_win.h"
-#include "chrome/browser/conflicts/problematic_programs_updater_win.h"
 
 namespace {
 
@@ -68,9 +68,11 @@
       FROM_HERE,
       {base::MayBlock(), base::TaskPriority::BACKGROUND,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-      base::BindOnce([]() { return std::make_unique<InstalledPrograms>(); }),
-      base::BindOnce(&ThirdPartyConflictsManager::OnInstalledProgramsCreated,
-                     weak_ptr_factory_.GetWeakPtr()));
+      base::BindOnce(
+          []() { return std::make_unique<InstalledApplications>(); }),
+      base::BindOnce(
+          &ThirdPartyConflictsManager::OnInstalledApplicationsCreated,
+          weak_ptr_factory_.GetWeakPtr()));
 }
 
 void ThirdPartyConflictsManager::LoadModuleList(const base::FilePath& path) {
@@ -92,8 +94,8 @@
     std::unique_ptr<CertificateInfo> exe_certificate_info) {
   exe_certificate_info_ = std::move(exe_certificate_info);
 
-  if (module_list_filter_ && installed_programs_)
-    InitializeProblematicProgramsUpdater();
+  if (module_list_filter_ && installed_applications_)
+    InitializeIncompatibleApplicationsUpdater();
 }
 
 void ThirdPartyConflictsManager::OnModuleListFilterCreated(
@@ -101,7 +103,7 @@
   module_list_filter_ = std::move(module_list_filter);
 
   // A valid |module_list_filter_| is critical to the blocking of third-party
-  // modules. By returning early here, the |problematic_programs_updater_|
+  // modules. By returning early here, the |incompatible_applications_updater_|
   // instance never gets created, thus disabling the identification of
   // incompatible applications.
   if (!module_list_filter_) {
@@ -111,24 +113,26 @@
     return;
   }
 
-  if (exe_certificate_info_ && installed_programs_)
-    InitializeProblematicProgramsUpdater();
+  if (exe_certificate_info_ && installed_applications_)
+    InitializeIncompatibleApplicationsUpdater();
 }
 
-void ThirdPartyConflictsManager::OnInstalledProgramsCreated(
-    std::unique_ptr<InstalledPrograms> installed_programs) {
-  installed_programs_ = std::move(installed_programs);
+void ThirdPartyConflictsManager::OnInstalledApplicationsCreated(
+    std::unique_ptr<InstalledApplications> installed_applications) {
+  installed_applications_ = std::move(installed_applications);
 
   if (exe_certificate_info_ && module_list_filter_)
-    InitializeProblematicProgramsUpdater();
+    InitializeIncompatibleApplicationsUpdater();
 }
 
-void ThirdPartyConflictsManager::InitializeProblematicProgramsUpdater() {
+void ThirdPartyConflictsManager::InitializeIncompatibleApplicationsUpdater() {
   DCHECK(exe_certificate_info_);
   DCHECK(module_list_filter_);
-  DCHECK(installed_programs_);
+  DCHECK(installed_applications_);
 
-  problematic_programs_updater_ = std::make_unique<ProblematicProgramsUpdater>(
-      *exe_certificate_info_, *module_list_filter_, *installed_programs_);
-  module_database_->AddObserver(problematic_programs_updater_.get());
+  incompatible_applications_updater_ =
+      std::make_unique<IncompatibleApplicationsUpdater>(
+          *exe_certificate_info_, *module_list_filter_,
+          *installed_applications_);
+  module_database_->AddObserver(incompatible_applications_updater_.get());
 }
diff --git a/chrome/browser/conflicts/third_party_conflicts_manager_win.h b/chrome/browser/conflicts/third_party_conflicts_manager_win.h
index faec1a3..92f53cb 100644
--- a/chrome/browser/conflicts/third_party_conflicts_manager_win.h
+++ b/chrome/browser/conflicts/third_party_conflicts_manager_win.h
@@ -12,10 +12,10 @@
 #include "chrome/browser/conflicts/module_database_observer_win.h"
 
 struct CertificateInfo;
-class InstalledPrograms;
+class InstalledApplications;
 class ModuleDatabase;
 class ModuleListFilter;
-class ProblematicProgramsUpdater;
+class IncompatibleApplicationsUpdater;
 
 namespace base {
 class FilePath;
@@ -43,13 +43,14 @@
   void OnModuleListFilterCreated(
       std::unique_ptr<ModuleListFilter> module_list_filter);
 
-  // Called when |installed_programs_| finishes its initialization.
-  void OnInstalledProgramsCreated(
-      std::unique_ptr<InstalledPrograms> installed_programs);
+  // Called when |installed_applications_| finishes its initialization.
+  void OnInstalledApplicationsCreated(
+      std::unique_ptr<InstalledApplications> installed_applications);
 
-  // Initializes |problematic_programs_updater_| when the exe_certificate_info_,
-  // the module_list_filter_ and the installed_programs_ are available.
-  void InitializeProblematicProgramsUpdater();
+  // Initializes |incompatible_applications_updater_| when the
+  // exe_certificate_info_, the module_list_filter_ and the
+  // installed_applications_ are available.
+  void InitializeIncompatibleApplicationsUpdater();
 
   ModuleDatabase* module_database_;
 
@@ -58,7 +59,7 @@
   bool module_list_received_;
 
   // Indicates if the OnModuleDatabaseIdle() function has been called once
-  // already. Used to prevent the creation of multiple InstalledPrograms
+  // already. Used to prevent the creation of multiple InstalledApplications
   // instances.
   bool on_module_database_idle_called_;
 
@@ -68,11 +69,12 @@
   // Filters third-party modules against a whitelist and a blacklist.
   std::unique_ptr<ModuleListFilter> module_list_filter_;
 
-  // Retrieves the list of installed programs.
-  std::unique_ptr<InstalledPrograms> installed_programs_;
+  // Retrieves the list of installed applications.
+  std::unique_ptr<InstalledApplications> installed_applications_;
 
-  // Maintains the cache of problematic programs.
-  std::unique_ptr<ProblematicProgramsUpdater> problematic_programs_updater_;
+  // Maintains the cache of incompatible applications.
+  std::unique_ptr<IncompatibleApplicationsUpdater>
+      incompatible_applications_updater_;
 
   base::WeakPtrFactory<ThirdPartyConflictsManager> weak_ptr_factory_;
 
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index cddcc943..00bb7e3 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -274,8 +274,8 @@
 #include "chrome/browser/apps/app_launch_for_metro_restart_win.h"
 #include "chrome/browser/component_updater/sw_reporter_installer_win.h"
 #if defined(GOOGLE_CHROME_BUILD)
+#include "chrome/browser/conflicts/incompatible_applications_updater_win.h"
 #include "chrome/browser/conflicts/module_database_win.h"
-#include "chrome/browser/conflicts/problematic_programs_updater_win.h"
 #endif  // defined(GOOGLE_CHROME_BUILD)
 #include "chrome/browser/safe_browsing/chrome_cleaner/settings_resetter_win.h"
 #include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_prefs_manager.h"
@@ -460,8 +460,8 @@
   desktop_ios_promotion::RegisterLocalPrefs(registry);
   password_manager::PasswordManager::RegisterLocalPrefs(registry);
 #if defined(GOOGLE_CHROME_BUILD)
+  IncompatibleApplicationsUpdater::RegisterLocalStatePrefs(registry);
   ModuleDatabase::RegisterLocalStatePrefs(registry);
-  ProblematicProgramsUpdater::RegisterLocalStatePrefs(registry);
 #endif  // defined(GOOGLE_CHROME_BUILD)
 #endif
 
@@ -708,6 +708,11 @@
   // Added 1/2018.
   local_state->ClearPref(kShowFirstRunBubbleOption);
 #endif  // defined(OS_ANDROID)
+
+#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
+  // Added 5/2018.
+  local_state->ClearPref(prefs::kProblematicPrograms);
+#endif
 }
 
 // This method should be periodically pruned of year+ old migrations.
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.js b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.js
index 72dd7f1..ee406fe4 100644
--- a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.js
+++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.js
@@ -6,7 +6,7 @@
  * @fileoverview
  * 'incompatible-application-item' represents one item in a "list-box" of
  * incompatible applications, as defined in
- * chrome/browser/conflicts/problematic_programs_updater_win.h.
+ * chrome/browser/conflicts/incompatible_applications_updater_win.h.
  * This element contains a button that can be used to remove or update the
  * incompatible application, depending on the value of the action-type property.
  *
@@ -41,7 +41,7 @@
   properties: {
     /**
      * The name of the application to be displayed. Also used for the UNINSTALL
-     * action, where the name is passed to the startProgramUninstallation()
+     * action, where the name is passed to the startApplicationUninstallation()
      * call.
      */
     applicationName: String,
@@ -77,7 +77,7 @@
    */
   onActionTap_: function() {
     if (this.actionType === settings.ActionTypes.UNINSTALL) {
-      this.browserProxy_.startProgramUninstallation(this.applicationName);
+      this.browserProxy_.startApplicationUninstallation(this.applicationName);
     } else if (
         this.actionType === settings.ActionTypes.MORE_INFO ||
         this.actionType === settings.ActionTypes.UPGRADE) {
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.js b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.js
index 7017e0a46..4eb017b 100644
--- a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.js
+++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.js
@@ -42,10 +42,11 @@
     requestIncompatibleApplicationsList() {}
 
     /**
-     * Launches the Apps & Features page that allows uninstalling 'programName'.
-     * @param {string} programName
+     * Launches the Apps & Features page that allows uninstalling
+     * 'applicationName'.
+     * @param {string} applicationName
      */
-    startProgramUninstallation(programName) {}
+    startApplicationUninstallation(applicationName) {}
 
     /**
      * Opens the specified URL in a new tab.
@@ -86,8 +87,8 @@
     }
 
     /** @override */
-    startProgramUninstallation(programName) {
-      chrome.send('startProgramUninstallation', [programName]);
+    startApplicationUninstallation(applicationName) {
+      chrome.send('startApplicationUninstallation', [applicationName]);
     }
 
     /** @override */
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index cec2604..7be261b 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -89,7 +89,7 @@
 #include "base/win/windows_version.h"
 #include "chrome/browser/apps/app_launch_for_metro_restart_win.h"
 #if defined(GOOGLE_CHROME_BUILD)
-#include "chrome/browser/conflicts/problematic_programs_updater_win.h"
+#include "chrome/browser/conflicts/incompatible_applications_updater_win.h"
 #endif  // defined(GOOGLE_CHROME_BUILD)
 #include "chrome/browser/notifications/notification_platform_bridge_win.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
@@ -679,9 +679,8 @@
     // Check if there are any incompatible applications cached from the last
     // Chrome run.
     has_incompatible_applications =
-        ProblematicProgramsUpdater::
-            IsIncompatibleApplicationsWarningEnabled() &&
-        ProblematicProgramsUpdater::HasCachedPrograms();
+        IncompatibleApplicationsUpdater::IsWarningEnabled() &&
+        IncompatibleApplicationsUpdater::HasCachedApplications();
   }
 #endif
   const auto session_startup_pref =
diff --git a/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.cc b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.cc
index 4772084..16bed878 100644
--- a/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.cc
+++ b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.cc
@@ -15,7 +15,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "base/win/registry.h"
-#include "chrome/browser/conflicts/problematic_programs_updater_win.h"
+#include "chrome/browser/conflicts/incompatible_applications_updater_win.h"
 #include "chrome/browser/conflicts/registry_key_watcher_win.h"
 #include "chrome/browser/conflicts/uninstall_application_win.h"
 #include "chrome/grit/generated_resources.h"
@@ -34,10 +34,10 @@
                               HandleRequestIncompatibleApplicationsList,
                           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "startProgramUninstallation",
-      base::BindRepeating(
-          &IncompatibleApplicationsHandler::HandleStartProgramUninstallation,
-          base::Unretained(this)));
+      "startApplicationUninstallation",
+      base::BindRepeating(&IncompatibleApplicationsHandler::
+                              HandleStartApplicationUninstallation,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getSubtitlePluralString",
       base::BindRepeating(
@@ -71,54 +71,58 @@
   // requestIncompatibleApplicationsList().
   registry_key_watchers_.clear();
 
-  std::vector<ProblematicProgramsUpdater::ProblematicProgram>
-      problematic_programs = ProblematicProgramsUpdater::GetCachedPrograms();
+  std::vector<IncompatibleApplicationsUpdater::IncompatibleApplication>
+      incompatible_applications =
+          IncompatibleApplicationsUpdater::GetCachedApplications();
 
   base::Value application_list(base::Value::Type::LIST);
-  application_list.GetList().reserve(problematic_programs.size());
+  application_list.GetList().reserve(incompatible_applications.size());
 
-  for (const auto& program : problematic_programs) {
+  for (const auto& application : incompatible_applications) {
     // Set up a registry watcher for each problem application.
     // Since this instance owns the watcher, it is safe to use
     // base::Unretained() because the callback won't be invoked when the watcher
     // gets deleted.
     auto registry_key_watcher = RegistryKeyWatcher::Create(
-        program.info.registry_root, program.info.registry_key_path.c_str(),
-        program.info.registry_wow64_access,
+        application.info.registry_root,
+        application.info.registry_key_path.c_str(),
+        application.info.registry_wow64_access,
         base::BindOnce(&IncompatibleApplicationsHandler::OnApplicationRemoved,
-                       base::Unretained(this), program.info));
+                       base::Unretained(this), application.info));
 
     // Only keep the watcher if it was successfully initialized. A failure here
-    // is unlikely, but the worst that can happen is that the |program| will not
-    // get removed from the list automatically in the Incompatible Applications
-    // subpage.
+    // is unlikely, but the worst that can happen is that the |application| will
+    // not get removed from the list automatically in the Incompatible
+    // Applications subpage.
     if (registry_key_watcher) {
       registry_key_watchers_.insert(
-          {program.info, std::move(registry_key_watcher)});
+          {application.info, std::move(registry_key_watcher)});
     }
 
     // Also add the application to the list that is passed to the javascript.
     base::Value dict(base::Value::Type::DICTIONARY);
-    dict.SetKey("name", base::Value(program.info.name));
-    dict.SetKey("type", base::Value(program.blacklist_action->message_type()));
-    dict.SetKey("url", base::Value(program.blacklist_action->message_url()));
+    dict.SetKey("name", base::Value(application.info.name));
+    dict.SetKey("type",
+                base::Value(application.blacklist_action->message_type()));
+    dict.SetKey("url",
+                base::Value(application.blacklist_action->message_url()));
     application_list.GetList().push_back(std::move(dict));
   }
 
   UMA_HISTOGRAM_COUNTS_100("IncompatibleApplicationsPage.NumApplications",
-                           problematic_programs.size());
+                           incompatible_applications.size());
 
   const base::Value& callback_id = args->GetList().front();
   ResolveJavascriptCallback(callback_id, application_list);
 }
 
-void IncompatibleApplicationsHandler::HandleStartProgramUninstallation(
+void IncompatibleApplicationsHandler::HandleStartApplicationUninstallation(
     const base::ListValue* args) {
   CHECK_EQ(1u, args->GetList().size());
   base::RecordAction(base::UserMetricsAction(
       "IncompatibleApplicationsPage.UninstallationStarted"));
 
-  // Open the Apps & Settings page with the program name highlighted.
+  // Open the Apps & Settings page with the application name highlighted.
   uninstall_application::LaunchUninstallFlow(
       base::UTF8ToUTF16(args->GetList()[0].GetString()));
 }
@@ -156,13 +160,13 @@
 }
 
 void IncompatibleApplicationsHandler::OnApplicationRemoved(
-    const InstalledPrograms::ProgramInfo& program) {
+    const InstalledApplications::ApplicationInfo& application) {
   base::RecordAction(base::UserMetricsAction(
       "IncompatibleApplicationsPage.ApplicationRemoved"));
 
-  registry_key_watchers_.erase(program);
+  registry_key_watchers_.erase(application);
   FireWebUIListener("incompatible-application-removed",
-                    base::Value(program.name));
+                    base::Value(application.name));
 }
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h
index b7518f69a..114fdb9 100644
--- a/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h
+++ b/chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h
@@ -9,7 +9,7 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "chrome/browser/conflicts/installed_programs_win.h"
+#include "chrome/browser/conflicts/installed_applications_win.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 
 class RegistryKeyWatcher;
@@ -35,8 +35,8 @@
   // Sends the list of incompatible applications to the caller via a promise.
   void HandleRequestIncompatibleApplicationsList(const base::ListValue* args);
 
-  // Initiates the uninstallation of the program passed using |args|.
-  void HandleStartProgramUninstallation(const base::ListValue* args);
+  // Initiates the uninstallation of the application passed using |args|.
+  void HandleStartApplicationUninstallation(const base::ListValue* args);
 
   void HandleGetSubtitlePluralString(const base::ListValue* args);
   void HandleGetSubtitleNoAdminRightsPluralString(const base::ListValue* args);
@@ -44,10 +44,12 @@
   void GetPluralString(int id, const base::ListValue* args);
 
   // Callback for the registry key watchers.
-  void OnApplicationRemoved(const InstalledPrograms::ProgramInfo& program);
+  void OnApplicationRemoved(
+      const InstalledApplications::ApplicationInfo& application);
 
   // Container for the watchers.
-  std::map<InstalledPrograms::ProgramInfo, std::unique_ptr<RegistryKeyWatcher>>
+  std::map<InstalledApplications::ApplicationInfo,
+           std::unique_ptr<RegistryKeyWatcher>>
       registry_key_watchers_;
 
   DISALLOW_COPY_AND_ASSIGN(IncompatibleApplicationsHandler);
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index cd7e0ab..46a1af2 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -56,7 +56,7 @@
 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
 #include "chrome/browser/ui/webui/settings/chrome_cleanup_handler.h"
 #if defined(GOOGLE_CHROME_BUILD)
-#include "chrome/browser/conflicts/problematic_programs_updater_win.h"
+#include "chrome/browser/conflicts/incompatible_applications_updater_win.h"
 #include "chrome/browser/conflicts/token_util_win.h"
 #include "chrome/browser/ui/webui/settings/incompatible_applications_handler_win.h"
 #include "chrome/grit/chrome_unscaled_resources.h"
@@ -229,8 +229,8 @@
 
 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
   bool has_incompatible_applications =
-      ProblematicProgramsUpdater::IsIncompatibleApplicationsWarningEnabled() &&
-      ProblematicProgramsUpdater::HasCachedPrograms();
+      IncompatibleApplicationsUpdater::IsWarningEnabled() &&
+      IncompatibleApplicationsUpdater::HasCachedApplications();
   html_source->AddBoolean("showIncompatibleApplications",
                           has_incompatible_applications);
   html_source->AddBoolean("hasAdminRights", HasAdminRights());