Commit 9a10ae23 authored by Patrick Monette's avatar Patrick Monette Committed by Commit Bot

Make the ModuleDatabase permanent

The ModuleDatabase is the replacement for the EnumerateModulesModel
that is now needed for the IncompatibleApplicationsWarning and
ThirdPartyModulesBlocking features. It has been enabled on all channels
via the experimentation for the incompatible applications warning.

This CL removes the enumerate_modules_model.* files and remove the
ModuleDatabase feature flag. This means that it will now be permanently
enabled.

Bug: 751136
Change-Id: Id49e49ec213dd1a81021346cdd8084ee407f8229
Reviewed-on: https://chromium-review.googlesource.com/1098016
Commit-Queue: Patrick Monette <pmonette@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567441}
parent d9675d8b
......@@ -1565,8 +1565,6 @@ jumbo_split_static_library("browser") {
"win/chrome_elf_init.h",
"win/chrome_select_file_dialog_factory.cc",
"win/chrome_select_file_dialog_factory.h",
"win/enumerate_modules_model.cc",
"win/enumerate_modules_model.h",
"win/jumplist.cc",
"win/jumplist.h",
"win/jumplist_factory.cc",
......
......@@ -24,7 +24,6 @@
#include "base/task_scheduler/post_task.h"
#include "base/time/time.h"
#include "chrome/browser/prerender/prerender_field_trial.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "components/metrics/persistent_system_profile.h"
......@@ -209,7 +208,6 @@ void SetupDesktopFieldTrials() {
SetupStunProbeTrial();
#if defined(OS_WIN)
SetupStabilityDebugging();
base::FeatureList::IsEnabled(features::kModuleDatabase);
#endif // defined(OS_WIN)
}
......
......@@ -527,8 +527,7 @@ void ChromeBrowserMainPartsWin::PostProfileInit() {
// What truly controls if the blocking is enabled is the presence of the
// module blacklist cache file. This means that to disable the feature, the
// cache must be deleted and the browser relaunched.
if (!base::FeatureList::IsEnabled(features::kModuleDatabase) ||
!ModuleDatabase::IsThirdPartyBlockingPolicyEnabled() ||
if (!ModuleDatabase::IsThirdPartyBlockingPolicyEnabled() ||
!base::FeatureList::IsEnabled(features::kThirdPartyModulesBlocking))
ThirdPartyConflictsManager::DisableThirdPartyModuleBlocking(
base::CreateTaskRunnerWithTraits(
......@@ -541,8 +540,7 @@ void ChromeBrowserMainPartsWin::PostProfileInit() {
// Create the module database and hook up the in-process module watcher. This
// needs to be done before any child processes are initialized as the
// ModuleDatabase is an endpoint for IPC from child processes.
if (base::FeatureList::IsEnabled(features::kModuleDatabase))
SetupModuleDatabase(&module_watcher_);
SetupModuleDatabase(&module_watcher_);
}
void ChromeBrowserMainPartsWin::PostBrowserStart() {
......
......@@ -3363,29 +3363,26 @@ void ChromeContentBrowserClient::ExposeInterfacesToRenderer(
#endif // defined(SAFE_BROWSING_DB_LOCAL) || defined(SAFE_BROWSING_DB_REMOTE)
#if defined(OS_WIN)
if (base::FeatureList::IsEnabled(features::kModuleDatabase)) {
// Add the ModuleEventSink interface. This is the interface used by renderer
// processes to notify the browser of modules in their address space. The
// process handle is not yet available at this point so pass in a callback
// to allow to retrieve a duplicate at the time the interface is actually
// created. It is safe to pass a raw pointer to |render_process_host|: the
// callback will be invoked in the context of ModuleDatabase::GetInstance,
// which is invoked by Mojo initialization, which occurs while the
// |render_process_host| is alive.
auto get_process = base::BindRepeating(
[](content::RenderProcessHost* host) -> base::Process {
return host->GetProcess().Duplicate();
},
base::Unretained(render_process_host));
// The ModuleDatabase is a global singleton so passing an unretained pointer
// is safe.
registry->AddInterface(
base::BindRepeating(&ModuleEventSinkImpl::Create,
std::move(get_process),
content::PROCESS_TYPE_RENDERER,
base::Unretained(ModuleDatabase::GetInstance())),
ui_task_runner);
}
// Add the ModuleEventSink interface. This is the interface used by renderer
// processes to notify the browser of modules in their address space. The
// process handle is not yet available at this point so pass in a callback
// to allow to retrieve a duplicate at the time the interface is actually
// created. It is safe to pass a raw pointer to |render_process_host|: the
// callback will be invoked in the context of ModuleDatabase::GetInstance,
// which is invoked by Mojo initialization, which occurs while the
// |render_process_host| is alive.
auto get_process = base::BindRepeating(
[](content::RenderProcessHost* host) -> base::Process {
return host->GetProcess().Duplicate();
},
base::Unretained(render_process_host));
// The ModuleDatabase is a global singleton so passing an unretained pointer
// is safe.
registry->AddInterface(
base::BindRepeating(&ModuleEventSinkImpl::Create, std::move(get_process),
content::PROCESS_TYPE_RENDERER,
base::Unretained(ModuleDatabase::GetInstance())),
ui_task_runner);
#endif
for (auto* ep : extra_parts_) {
......
......@@ -64,7 +64,7 @@ void EnumerateShellExtensionsOnBlockingSequence(
scoped_refptr<base::SequencedTaskRunner> task_runner,
OnShellExtensionEnumeratedCallback on_shell_extension_enumerated,
base::OnceClosure on_enumeration_finished) {
EnumerateShellExtensionPaths(
internal::EnumerateShellExtensionPaths(
base::BindRepeating(&OnShellExtensionPathEnumerated, task_runner,
std::move(on_shell_extension_enumerated)));
......@@ -76,18 +76,6 @@ void EnumerateShellExtensionsOnBlockingSequence(
const wchar_t kShellExtensionRegistryKey[] =
L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
void EnumerateShellExtensionPaths(
const base::RepeatingCallback<void(const base::FilePath&)>& callback) {
base::AssertBlockingAllowed();
int nb_shell_extensions = 0;
ReadShellExtensions(HKEY_LOCAL_MACHINE, callback, &nb_shell_extensions);
ReadShellExtensions(HKEY_CURRENT_USER, callback, &nb_shell_extensions);
base::UmaHistogramCounts100("ThirdPartyModules.ShellExtensionsCount",
nb_shell_extensions);
}
void EnumerateShellExtensions(
OnShellExtensionEnumeratedCallback on_shell_extension_enumerated,
base::OnceClosure on_enumeration_finished) {
......@@ -100,3 +88,19 @@ void EnumerateShellExtensions(
std::move(on_shell_extension_enumerated),
std::move(on_enumeration_finished)));
}
namespace internal {
void EnumerateShellExtensionPaths(
const base::RepeatingCallback<void(const base::FilePath&)>& callback) {
base::AssertBlockingAllowed();
int nb_shell_extensions = 0;
ReadShellExtensions(HKEY_LOCAL_MACHINE, callback, &nb_shell_extensions);
ReadShellExtensions(HKEY_CURRENT_USER, callback, &nb_shell_extensions);
base::UmaHistogramCounts100("ThirdPartyModules.ShellExtensionsCount",
nb_shell_extensions);
}
} // namespace internal
......@@ -16,13 +16,6 @@ class FilePath;
// The path to the registry key where shell extensions are registered.
extern const wchar_t kShellExtensionRegistryKey[];
// Enumerates registered shell extensions, and invokes |callback| once per shell
// extension found. Must be called on a blocking sequence.
// TODO(pmonette): Move this implementation detail to the .cc file when
// enumerate_modules_model.cc gets deleted.
void EnumerateShellExtensionPaths(
const base::RepeatingCallback<void(const base::FilePath&)>& callback);
// Finds shell extensions installed on the computer by enumerating the registry.
// In addition to the file path, the SizeOfImage and TimeDateStamp of the module
// is returned via the |on_shell_extension_enumerated| callback.
......@@ -32,4 +25,14 @@ void EnumerateShellExtensions(
OnShellExtensionEnumeratedCallback on_shell_extension_enumerated,
base::OnceClosure on_enumeration_finished);
namespace internal {
// Enumerates registered shell extensions, and invokes |callback| once per shell
// extension found. Must be called on a blocking sequence.
// Exposed for testing.
void EnumerateShellExtensionPaths(
const base::RepeatingCallback<void(const base::FilePath&)>& callback);
} // namespace internal
#endif // CHROME_BROWSER_CONFLICTS_ENUMERATE_SHELL_EXTENSIONS_WIN_H_
......@@ -99,7 +99,7 @@ TEST_F(EnumerateShellExtensionsTest, EnumerateShellExtensionPaths) {
}
std::vector<base::FilePath> shell_extension_paths;
EnumerateShellExtensionPaths(
internal::EnumerateShellExtensionPaths(
base::BindRepeating(&OnShellExtensionPathEnumerated,
base::Unretained(&shell_extension_paths)));
......
......@@ -94,12 +94,8 @@ class IncompatibleApplicationsBrowserTest : public InProcessBrowserTest {
ASSERT_NO_FATAL_FAILURE(
registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER));
scoped_feature_list_.InitWithFeatures(
// Enabled features.
{features::kModuleDatabase,
features::kIncompatibleApplicationsWarning},
// Disabled features.
{});
scoped_feature_list_.InitAndEnableFeature(
features::kIncompatibleApplicationsWarning);
ASSERT_NO_FATAL_FAILURE(CreateModuleList());
ASSERT_NO_FATAL_FAILURE(InstallThirdPartyApplication());
......@@ -180,8 +176,7 @@ class IncompatibleApplicationsBrowserTest : public InProcessBrowserTest {
// 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
// kIncompatibleApplicationsWarning features.
// Enables the IncompatibleApplicationsWarning feature.
base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(IncompatibleApplicationsBrowserTest);
......
......@@ -228,7 +228,6 @@ void IncompatibleApplicationsUpdater::RegisterLocalStatePrefs(
// static
bool IncompatibleApplicationsUpdater::IsWarningEnabled() {
return base::win::GetVersion() >= base::win::VERSION_WIN10 &&
base::FeatureList::IsEnabled(features::kModuleDatabase) &&
ModuleDatabase::IsThirdPartyBlockingPolicyEnabled() &&
base::FeatureList::IsEnabled(
features::kIncompatibleApplicationsWarning);
......
......@@ -87,12 +87,8 @@ class ThirdPartyBlockingBrowserTest : public InProcessBrowserTest {
// InProcessBrowserTest:
void SetUp() override {
scoped_feature_list_.InitWithFeatures(
// Enabled features.
{features::kModuleDatabase, features::kIncompatibleApplicationsWarning,
features::kThirdPartyModulesBlocking},
// Disabled features.
{});
scoped_feature_list_.InitAndEnableFeature(
features::kThirdPartyModulesBlocking);
ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
......@@ -138,7 +134,7 @@ class ThirdPartyBlockingBrowserTest : public InProcessBrowserTest {
static_cast<int>(contents.size())));
}
// Enables the features to activate the ModuleBlacklistCacheUpdater.
// Enables the ThirdPartyModulesBlocking feature.
base::test::ScopedFeatureList scoped_feature_list_;
// Temp directory where the third-party module is located.
......
......@@ -29,7 +29,6 @@
#include "components/version_info/version_info.h"
#if defined(OS_WIN)
#include "chrome/browser/win/enumerate_modules_model.h"
#include "chrome/installer/util/install_util.h"
#endif
......
......@@ -2642,8 +2642,6 @@ split_static_library("ui") {
"webui/conflicts_handler.h",
"webui/conflicts_ui.cc",
"webui/conflicts_ui.h",
"webui/module_database_conflicts_handler.cc",
"webui/module_database_conflicts_handler.h",
"webui/settings/chrome_cleanup_handler.cc",
"webui/settings/chrome_cleanup_handler.h",
"webui/settings_utils_win.cc",
......
......@@ -11,13 +11,6 @@
#include "chrome/browser/ui/global_error/global_error_service_factory.h"
#include "chrome/browser/upgrade_detector.h"
#if defined(OS_WIN)
#include "base/feature_list.h"
#include "base/win/windows_version.h"
#include "chrome/browser/win/enumerate_modules_model.h"
#include "chrome/common/chrome_features.h"
#endif
namespace {
// Maps an upgrade level to a severity level.
......
......@@ -13,18 +13,11 @@
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#if defined(OS_WIN)
#include "chrome/browser/win/enumerate_modules_model.h"
#endif
class Profile;
// AppMenuIconController encapsulates the logic for badging the app menu icon
// as a result of various events - such as available updates, errors, etc.
class AppMenuIconController :
#if defined(OS_WIN)
public EnumerateModulesModel::Observer,
#endif
public content::NotificationObserver,
public UpgradeObserver {
public:
......
......@@ -75,10 +75,6 @@
#include "chrome/browser/ui/webui/theme_source.h"
#endif
#if defined(OS_WIN)
#include "chrome/browser/win/enumerate_modules_model.h"
#endif
#if defined(OS_CHROMEOS)
#include "chrome/browser/browser_process_platform_part_chromeos.h"
#include "chrome/browser/chromeos/customization/customization_document.h"
......
......@@ -4,7 +4,6 @@
#include "chrome/browser/ui/webui/conflicts_handler.h"
#include <memory>
#include <utility>
#include "base/bind.h"
......@@ -12,12 +11,18 @@
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/conflicts/module_database_win.h"
#include "chrome/browser/conflicts/module_info_win.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/web_ui.h"
#include "ui/base/l10n/l10n_util.h"
ConflictsHandler::ConflictsHandler() : observer_(this) {}
ConflictsHandler::~ConflictsHandler() = default;
ConflictsHandler::ConflictsHandler() = default;
ConflictsHandler::~ConflictsHandler() {
if (module_list_)
ModuleDatabase::GetInstance()->RemoveObserver(this);
}
void ConflictsHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
......@@ -26,52 +31,67 @@ void ConflictsHandler::RegisterMessages() {
base::Unretained(this)));
}
void ConflictsHandler::OnScanCompleted() {
SendModuleList();
observer_.Remove(EnumerateModulesModel::GetInstance());
}
void ConflictsHandler::OnNewModuleFound(const ModuleInfoKey& module_key,
const ModuleInfoData& module_data) {
DCHECK(module_list_);
void ConflictsHandler::HandleRequestModuleList(const base::ListValue* args) {
auto* model = EnumerateModulesModel::GetInstance();
// Make sure the JS doesn't call 'requestModuleList' more than once.
// TODO(739291): It would be better to kill the renderer instead of the
// browser for malformed messages.
CHECK(!observer_.IsObserving(model));
auto data = std::make_unique<base::DictionaryValue>();
CHECK_EQ(1U, args->GetSize());
CHECK(args->GetString(0, &module_list_callback_id_));
// TODO(pmonette): Set the status when conflicting module detection is added.
constexpr int kGoodStatus = 1;
data->SetInteger("status", kGoodStatus);
// The request is handled asynchronously, and will callback via
// OnScanCompleted on completion.
observer_.Add(model);
base::string16 type_string;
if (module_data.module_types & ModuleInfoData::kTypeShellExtension)
type_string = L"Shell extension";
data->SetString("type_description", type_string);
// Ask the scan to be performed immediately, and not in background mode.
// This ensures the results are available ASAP for the UI.
model->ScanNow(false);
const auto& inspection_result = *module_data.inspection_result;
data->SetString("location", inspection_result.location);
data->SetString("name", inspection_result.basename);
data->SetString("product_name", inspection_result.product_name);
data->SetString("description", inspection_result.description);
data->SetString("version", inspection_result.version);
data->SetString("digital_signer", inspection_result.certificate_info.subject);
module_list_->Append(std::move(data));
}
void ConflictsHandler::SendModuleList() {
auto* loaded_modules = EnumerateModulesModel::GetInstance();
std::unique_ptr<base::ListValue> list = loaded_modules->GetModuleList();
void ConflictsHandler::OnModuleDatabaseIdle() {
DCHECK(module_list_);
DCHECK(!module_list_callback_id_.empty());
ModuleDatabase::GetInstance()->RemoveObserver(this);
// Add the section title and the total count for bad modules found.
int confirmed_bad = loaded_modules->confirmed_bad_modules_detected();
int suspected_bad = loaded_modules->suspected_bad_modules_detected();
base::string16 table_title;
if (!confirmed_bad && !suspected_bad) {
table_title += l10n_util::GetStringFUTF16(
IDS_CONFLICTS_CHECK_PAGE_TABLE_TITLE_SUFFIX_ONE,
base::IntToString16(list->GetSize()));
} else {
table_title += l10n_util::GetStringFUTF16(
IDS_CONFLICTS_CHECK_PAGE_TABLE_TITLE_SUFFIX_TWO,
base::IntToString16(list->GetSize()),
base::IntToString16(confirmed_bad), base::IntToString16(suspected_bad));
}
// TODO(pmonette): Add the number of conflicts when conflicting module
// detection is added.
base::string16 table_title = l10n_util::GetStringFUTF16(
IDS_CONFLICTS_CHECK_PAGE_TABLE_TITLE_SUFFIX_ONE,
base::IntToString16(module_list_->GetSize()));
base::DictionaryValue results;
results.Set("moduleList", std::move(list));
results.SetString("modulesTableTitle", table_title);
results.Set("moduleList", std::move(module_list_));
AllowJavascript();
ResolveJavascriptCallback(base::Value(module_list_callback_id_), results);
}
void ConflictsHandler::HandleRequestModuleList(const base::ListValue* args) {
// Make sure the JS doesn't call 'requestModuleList' more than once.
// TODO(739291): It would be better to kill the renderer instead of the
// browser for malformed messages.
CHECK(!module_list_);
CHECK_EQ(1U, args->GetSize());
CHECK(args->GetString(0, &module_list_callback_id_));
// The request is handled asynchronously, filling up the |module_list_|,
// and will callback via OnModuleDatabaseIdle() on completion.
module_list_ = std::make_unique<base::ListValue>();
auto* module_database = ModuleDatabase::GetInstance();
module_database->IncreaseInspectionPriority();
module_database->AddObserver(this);
}
......@@ -5,17 +5,21 @@
#ifndef CHROME_BROWSER_UI_WEBUI_CONFLICTS_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_CONFLICTS_HANDLER_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "chrome/browser/win/enumerate_modules_model.h"
#include "chrome/browser/conflicts/module_database_observer_win.h"
#include "content/public/browser/web_ui_message_handler.h"
namespace base {
class Listvalue;
}
// This class takes care of sending the list of all loaded modules to the
// chrome://conflicts WebUI page when it is requested.
class ConflictsHandler : public content::WebUIMessageHandler,
public EnumerateModulesModel::Observer {
public ModuleDatabaseObserver {
public:
ConflictsHandler();
~ConflictsHandler() override;
......@@ -24,21 +28,21 @@ class ConflictsHandler : public content::WebUIMessageHandler,
// content::WebUIMessageHandler:
void RegisterMessages() override;
// EnumerateModulesModel::Observer:
void OnScanCompleted() override;
// ModuleDatabaseObserver:
void OnNewModuleFound(const ModuleInfoKey& module_key,
const ModuleInfoData& module_data) override;
void OnModuleDatabaseIdle() override;
// Callback for the "requestModuleList" message.
void HandleRequestModuleList(const base::ListValue* args);
// Sends the module list back to the WebUI page.
void SendModuleList();
ScopedObserver<EnumerateModulesModel, EnumerateModulesModel::Observer>
observer_;
// The ID of the callback that will get invoked with the module list.
std::string module_list_callback_id_;
// Temporarily holds the module list while the modules are being
// enumerated.
std::unique_ptr<base::ListValue> module_list_;
DISALLOW_COPY_AND_ASSIGN(ConflictsHandler);
};
......
......@@ -9,8 +9,6 @@
#include "base/memory/ref_counted_memory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/conflicts_handler.h"
#include "chrome/browser/ui/webui/module_database_conflicts_handler.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/chromium_strings.h"
......@@ -62,12 +60,7 @@ content::WebUIDataSource* CreateConflictsUIHTMLSource() {
ConflictsUI::ConflictsUI(content::WebUI* web_ui)
: content::WebUIController(web_ui) {
if (base::FeatureList::IsEnabled(features::kModuleDatabase)) {
web_ui->AddMessageHandler(
std::make_unique<ModuleDatabaseConflictsHandler>());
} else {
web_ui->AddMessageHandler(std::make_unique<ConflictsHandler>());
}
web_ui->AddMessageHandler(std::make_unique<ConflictsHandler>());
// Set up the about:conflicts source.
Profile* profile = Profile::FromWebUI(web_ui);
......
// 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/ui/webui/module_database_conflicts_handler.h"
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/conflicts/module_database_win.h"
#include "chrome/browser/conflicts/module_info_win.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/web_ui.h"
#include "ui/base/l10n/l10n_util.h"
ModuleDatabaseConflictsHandler::ModuleDatabaseConflictsHandler() = default;
ModuleDatabaseConflictsHandler::~ModuleDatabaseConflictsHandler() {
if (module_list_)
ModuleDatabase::GetInstance()->RemoveObserver(this);
}
void ModuleDatabaseConflictsHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"requestModuleList",
base::BindRepeating(
&ModuleDatabaseConflictsHandler::HandleRequestModuleList,
base::Unretained(this)));
}
void ModuleDatabaseConflictsHandler::OnNewModuleFound(
const ModuleInfoKey& module_key,
const ModuleInfoData& module_data) {
DCHECK(module_list_);
auto data = std::make_unique<base::DictionaryValue>();
// TODO(pmonette): Set the status when conflicting module detection is added.
constexpr int kGoodStatus = 1;
data->SetInteger("status", kGoodStatus);
base::string16 type_string;
if (module_data.module_types & ModuleInfoData::kTypeShellExtension)
type_string = L"Shell extension";
data->SetString("type_description", type_string);
const auto& inspection_result = *module_data.inspection_result;
data->SetString("location", inspection_result.location);
data->SetString("name", inspection_result.basename);
data->SetString("product_name", inspection_result.product_name);
data->SetString("description", inspection_result.description);
data->SetString("version", inspection_result.version);
data->SetString("digital_signer", inspection_result.certificate_info.subject);
module_list_->Append(std::move(data));
}
void ModuleDatabaseConflictsHandler::OnModuleDatabaseIdle() {
DCHECK(module_list_);
DCHECK(!module_list_callback_id_.empty());
ModuleDatabase::GetInstance()->RemoveObserver(this);
// Add the section title and the total count for bad modules found.
// TODO(pmonette): Add the number of conflicts when conflicting module
// detection is added.
base::string16 table_title = l10n_util::GetStringFUTF16(
IDS_CONFLICTS_CHECK_PAGE_TABLE_TITLE_SUFFIX_ONE,
base::IntToString16(module_list_->GetSize()));
base::DictionaryValue results;
results.SetString("modulesTableTitle", table_title);
results.Set("moduleList", std::move(module_list_));
AllowJavascript();
ResolveJavascriptCallback(base::Value(module_list_callback_id_), results);
}
void ModuleDatabaseConflictsHandler::HandleRequestModuleList(
const base::ListValue* args) {
// Make sure the JS doesn't call 'requestModuleList' more than once.
// TODO(739291): It would be better to kill the renderer instead of the
// browser for malformed messages.
CHECK(!module_list_);
CHECK_EQ(1U, args->GetSize());
CHECK(args->GetString(0, &module_list_callback_id_));
// The request is handled asynchronously, filling up the |module_list_|,
// and will callback via OnModuleDatabaseIdle() on completion.
module_list_ = std::make_unique<base::ListValue>();
auto* module_database = ModuleDatabase::GetInstance();
module_database->IncreaseInspectionPriority();
module_database->AddObserver(this);
}
// 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_UI_WEBUI_MODULE_DATABASE_CONFLICTS_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_MODULE_DATABASE_CONFLICTS_HANDLER_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "chrome/browser/conflicts/module_database_observer_win.h"
#include "content/public/browser/web_ui_message_handler.h"
namespace base {
class Listvalue;
}
// This class takes care of sending the list of all loaded modules to the
// chrome://conflicts WebUI page when it is requested. It replaces
// ConflictsHandler when the ModuleDatabase feature is enabled.
class ModuleDatabaseConflictsHandler : public content::WebUIMessageHandler,
public ModuleDatabaseObserver {
public:
ModuleDatabaseConflictsHandler();
~ModuleDatabaseConflictsHandler() override;
private:
// content::WebUIMessageHandler:
void RegisterMessages() override;
// ModuleDatabaseObserver:
void OnNewModuleFound(const ModuleInfoKey& module_key,
const ModuleInfoData& module_data) override;
void OnModuleDatabaseIdle() override;
// Callback for the "requestModuleList" message.
void HandleRequestModuleList(const base::ListValue* args);
// The ID of the callback that will get invoked with the module list.
std::string module_list_callback_id_;
// Temporarily holds the module list while the modules are being
// enumerated.
std::unique_ptr<base::ListValue> module_list_;
DISALLOW_COPY_AND_ASSIGN(ModuleDatabaseConflictsHandler);
};
#endif // CHROME_BROWSER_UI_WEBUI_MODULE_DATABASE_CONFLICTS_HANDLER_H_
This diff is collapsed.
This diff is collapsed.
// Copyright (c) 2011 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/win/enumerate_modules_model.h"
#include <stddef.h>
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
typedef testing::Test EnumerateModulesTest;
// Set up some constants to use as default when creating the structs.
static const ModuleEnumerator::ModuleType kType =
ModuleEnumerator::LOADED_MODULE;
static const ModuleEnumerator::ModuleStatus kStatus =
ModuleEnumerator::NOT_MATCHED;
static const ModuleEnumerator::RecommendedAction kAction =
ModuleEnumerator::NONE;
// This is a list of test cases to normalize.
static const struct NormalizationEntryList {
ModuleEnumerator::Module test_case;
ModuleEnumerator::Module expected;
} kNormalizationTestCases[] = {
{
// Only path normalization needed.
{kType, kStatus, L"c:\\foo\\bar.dll", L"", L"Prod", L"Desc", L"1.0",
kAction},
{kType, kStatus, L"c:\\foo\\", L"bar.dll", L"Prod", L"Desc", L"1.0",
kAction},
}, {
// Lower case normalization.
{kType, kStatus, L"C:\\Foo\\Bar.dll", L"", L"", L"", L"1.0",
kAction},
{kType, kStatus, L"c:\\foo\\", L"bar.dll", L"", L"", L"1.0",
kAction},
}, {
// Version can include strings after the version number. Strip that away.
{kType, kStatus, L"c:\\foo.dll", L"", L"", L"", L"1.0 asdf",
kAction},
{kType, kStatus, L"c:\\", L"foo.dll", L"", L"", L"1.0",
kAction},
}, {
// Commas instead of periods in version string.
{kType, kStatus, L"", L"", L"", L"", L"1, 0", kAction},
{kType, kStatus, L"", L"", L"", L"", L"1.0", kAction},
}, {
// Corner case: No path (not sure this will ever happen).
{kType, kStatus, L"bar.dll", L"", L"", L"", L"", kAction},
{kType, kStatus, L"", L"bar.dll", L"", L"", L"", kAction},
}, {
// Error case: Missing filename (not sure this will ever happen).
{kType, kStatus, L"", L"", L"", L"", L"1.0", kAction},
{kType, kStatus, L"", L"", L"", L"", L"1.0", kAction},
},
};
TEST_F(EnumerateModulesTest, NormalizeEntry) {
for (size_t i = 0; i < arraysize(kNormalizationTestCases); ++i) {
ModuleEnumerator::Module test = kNormalizationTestCases[i].test_case;
ModuleEnumerator::NormalizeModule(&test);
ModuleEnumerator::Module expected = kNormalizationTestCases[i].expected;
SCOPED_TRACE("Test case no: " + base::IntToString(i));
EXPECT_EQ(expected.type, test.type);
EXPECT_EQ(expected.status, test.status);
EXPECT_STREQ(expected.location.c_str(), test.location.c_str());
EXPECT_STREQ(expected.name.c_str(), test.name.c_str());
EXPECT_STREQ(expected.product_name.c_str(), test.product_name.c_str());
EXPECT_STREQ(expected.description.c_str(), test.description.c_str());
EXPECT_STREQ(expected.version.c_str(), test.version.c_str());
EXPECT_EQ(expected.recommended_action, test.recommended_action);
}
}
......@@ -137,8 +137,7 @@ const base::Feature kTabMetricsLogging{"TabMetricsLogging",
#endif
#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
// Enables the blocking of third-party modules. This feature depends on
// ModuleDatabase and IncompatibleApplicationsWarning.
// Enables the blocking of third-party modules.
const base::Feature kThirdPartyModulesBlocking{
"ThirdPartyModulesBlocking", base::FEATURE_DISABLED_BY_DEFAULT};
#endif
......@@ -385,12 +384,6 @@ const base::Feature kMaterialDesignIncognitoNTP{
const base::Feature kModalPermissionPrompts{"ModalPermissionPrompts",
base::FEATURE_ENABLED_BY_DEFAULT};
#if defined(OS_WIN)
// Enables or disables the ModuleDatabase backend for the conflicts UI.
const base::Feature kModuleDatabase{"ModuleDatabase",
base::FEATURE_DISABLED_BY_DEFAULT};
#endif
// Enables the use of native notification centers instead of using the Message
// Center for displaying the toasts. The feature is hardcoded to enabled for
// Chrome OS.
......
......@@ -209,10 +209,6 @@ extern const base::Feature kMaterialDesignIncognitoNTP;
extern const base::Feature kModalPermissionPrompts;
#if defined(OS_WIN)
extern const base::Feature kModuleDatabase;
#endif
#if BUILDFLAG(ENABLE_NATIVE_NOTIFICATIONS)
extern const base::Feature kNativeNotifications;
#endif
......
......@@ -388,25 +388,24 @@ void ChromeContentRendererClient::RenderThreadStarted() {
}
#if defined(OS_WIN)
if (base::FeatureList::IsEnabled(features::kModuleDatabase)) {
thread->GetConnector()->BindInterface(content::mojom::kBrowserServiceName,
&module_event_sink_);
// Rebind the ModuleEventSink to the IO task runner.
// The use of base::Unretained() is safe here because |module_event_sink_|
// is never deleted and is only used on the IO task runner.
thread->GetIOTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&BindModuleEventSink,
base::Unretained(&module_event_sink_),
module_event_sink_.PassInterface()));
// It is safe to pass an unretained pointer to |module_event_sink_|, as it
// is owned by the process singleton ChromeContentRendererClient, which is
// leaked.
module_watcher_ = ModuleWatcher::Create(
base::BindRepeating(&OnModuleEvent, thread->GetIOTaskRunner(),
base::ConstRef(module_event_sink_)));
}
// Bind the ModuleEventSink interface.
thread->GetConnector()->BindInterface(content::mojom::kBrowserServiceName,
&module_event_sink_);
// Rebind the ModuleEventSink to the IO task runner.
// The use of base::Unretained() is safe here because |module_event_sink_|
// is never deleted and is only used on the IO task runner.
thread->GetIOTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&BindModuleEventSink,
base::Unretained(&module_event_sink_),
module_event_sink_.PassInterface()));
// It is safe to pass an unretained pointer to |module_event_sink_|, as it
// is owned by the process singleton ChromeContentRendererClient, which is
// leaked.
module_watcher_ = ModuleWatcher::Create(
base::BindRepeating(&OnModuleEvent, thread->GetIOTaskRunner(),
base::ConstRef(module_event_sink_)));
#endif
chrome_observer_.reset(new ChromeRenderThreadObserver());
......
......@@ -2645,7 +2645,6 @@ test("unit_tests") {
"../browser/webauthn/authenticator_request_scheduler_unittest.cc",
"../browser/webshare/share_target_pref_helper_unittest.cc",
"../browser/win/chrome_elf_init_unittest.cc",
"../browser/win/enumerate_modules_model_unittest.cc",
"../browser/win/jumplist_file_util_unittest.cc",
"../browser/win/jumplist_update_util_unittest.cc",
"../browser/win/taskbar_icon_finder_unittest.cc",
......
......@@ -1857,8 +1857,7 @@
"HelpURL": "https://support.google.com/chrome/?p=blocked"
},
"enable_features": [
"IncompatibleApplicationsWarning",
"ModuleDatabase"
"IncompatibleApplicationsWarning"
]
}
]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment