blob: 6cb3695d645e201d7b9c64b29374b76fbee9628b [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/enterprise/connectors/connectors_manager.h"
#include <memory>
#include "base/check.h"
#include "base/values.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/enterprise/connectors/reporting/browser_crash_event_router.h"
#include "chrome/browser/enterprise/connectors/reporting/extension_install_event_router.h"
#include "components/prefs/pref_service.h"
#include "url/gurl.h"
namespace enterprise_connectors {
ConnectorsManager::ConnectorsManager(
std::unique_ptr<BrowserCrashEventRouter> browser_crash_event_router,
std::unique_ptr<ExtensionInstallEventRouter> extension_install_event_router,
PrefService* pref_service,
const ServiceProviderConfig* config,
bool observe_prefs)
: service_provider_config_(config),
browser_crash_event_router_(std::move(browser_crash_event_router)),
extension_install_event_router_(
std::move(extension_install_event_router)) {
DCHECK(browser_crash_event_router_) << "Crash event router is null";
DCHECK(extension_install_event_router_) << "Extension event router is null";
if (observe_prefs)
StartObservingPrefs(pref_service);
extension_install_event_router_->StartObserving();
}
ConnectorsManager::~ConnectorsManager() = default;
bool ConnectorsManager::IsConnectorEnabled(AnalysisConnector connector) const {
if (analysis_connector_settings_.count(connector) == 1)
return true;
const char* pref = ConnectorPref(connector);
return pref && pref_change_registrar_.prefs()->HasPrefPath(pref);
}
bool ConnectorsManager::IsConnectorEnabled(ReportingConnector connector) const {
if (reporting_connector_settings_.count(connector) == 1)
return true;
const char* pref = ConnectorPref(connector);
return pref && pref_change_registrar_.prefs()->HasPrefPath(pref);
}
absl::optional<ReportingSettings> ConnectorsManager::GetReportingSettings(
ReportingConnector connector) {
if (!IsConnectorEnabled(connector))
return absl::nullopt;
if (reporting_connector_settings_.count(connector) == 0)
CacheReportingConnectorPolicy(connector);
// If the connector is still not in memory, it means the pref is set to an
// empty list or that it is not a list.
if (reporting_connector_settings_.count(connector) == 0)
return absl::nullopt;
// While multiple services can be set by the connector policies, only the
// first one is considered for now.
return reporting_connector_settings_[connector][0].GetReportingSettings();
}
absl::optional<AnalysisSettings> ConnectorsManager::GetAnalysisSettings(
const GURL& url,
AnalysisConnector connector) {
if (!IsConnectorEnabled(connector))
return absl::nullopt;
if (analysis_connector_settings_.count(connector) == 0)
CacheAnalysisConnectorPolicy(connector);
// If the connector is still not in memory, it means the pref is set to an
// empty list or that it is not a list.
if (analysis_connector_settings_.count(connector) == 0)
return absl::nullopt;
// While multiple services can be set by the connector policies, only the
// first one is considered for now.
return analysis_connector_settings_[connector][0].GetAnalysisSettings(url);
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
absl::optional<AnalysisSettings> ConnectorsManager::GetAnalysisSettings(
content::BrowserContext* context,
const storage::FileSystemURL& source_url,
const storage::FileSystemURL& destination_url,
AnalysisConnector connector) {
if (!IsConnectorEnabled(connector))
return absl::nullopt;
if (analysis_connector_settings_.count(connector) == 0)
CacheAnalysisConnectorPolicy(connector);
// If the connector is still not in memory, it means the pref is set to an
// empty list or that it is not a list.
if (analysis_connector_settings_.count(connector) == 0)
return absl::nullopt;
// While multiple services can be set by the connector policies, only the
// first one is considered for now.
return analysis_connector_settings_[connector][0].GetAnalysisSettings(
context, source_url, destination_url);
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
absl::optional<AnalysisSettings>
ConnectorsManager::GetAnalysisSettingsFromConnectorPolicy(
const GURL& url,
AnalysisConnector connector) {
if (analysis_connector_settings_.count(connector) == 0)
CacheAnalysisConnectorPolicy(connector);
// If the connector is still not in memory, it means the pref is set to an
// empty list or that it is not a list.
if (analysis_connector_settings_.count(connector) == 0)
return absl::nullopt;
// While multiple services can be set by the connector policies, only the
// first one is considered for now.
return analysis_connector_settings_[connector][0].GetAnalysisSettings(url);
}
void ConnectorsManager::CacheAnalysisConnectorPolicy(
AnalysisConnector connector) {
analysis_connector_settings_.erase(connector);
// Connectors with non-existing policies should not reach this code.
const char* pref = ConnectorPref(connector);
DCHECK(pref);
const base::Value::List& policy_value =
pref_change_registrar_.prefs()->GetList(pref);
for (const base::Value& service_settings : policy_value)
analysis_connector_settings_[connector].emplace_back(
service_settings, *service_provider_config_);
}
void ConnectorsManager::CacheReportingConnectorPolicy(
ReportingConnector connector) {
reporting_connector_settings_.erase(connector);
// Connectors with non-existing policies should not reach this code.
const char* pref = ConnectorPref(connector);
DCHECK(pref);
const base::Value::List& policy_value =
pref_change_registrar_.prefs()->GetList(pref);
for (const base::Value& service_settings : policy_value)
reporting_connector_settings_[connector].emplace_back(
service_settings, *service_provider_config_);
}
bool ConnectorsManager::DelayUntilVerdict(AnalysisConnector connector) {
if (IsConnectorEnabled(connector)) {
if (analysis_connector_settings_.count(connector) == 0)
CacheAnalysisConnectorPolicy(connector);
if (analysis_connector_settings_.count(connector) &&
!analysis_connector_settings_.at(connector).empty()) {
return analysis_connector_settings_.at(connector)
.at(0)
.ShouldBlockUntilVerdict();
}
}
return false;
}
absl::optional<std::u16string> ConnectorsManager::GetCustomMessage(
AnalysisConnector connector,
const std::string& tag) {
if (IsConnectorEnabled(connector)) {
if (analysis_connector_settings_.count(connector) == 0)
CacheAnalysisConnectorPolicy(connector);
if (analysis_connector_settings_.count(connector) &&
!analysis_connector_settings_.at(connector).empty()) {
return analysis_connector_settings_.at(connector).at(0).GetCustomMessage(
tag);
}
}
return absl::nullopt;
}
absl::optional<GURL> ConnectorsManager::GetLearnMoreUrl(
AnalysisConnector connector,
const std::string& tag) {
if (IsConnectorEnabled(connector)) {
if (analysis_connector_settings_.count(connector) == 0)
CacheAnalysisConnectorPolicy(connector);
if (analysis_connector_settings_.count(connector) &&
!analysis_connector_settings_.at(connector).empty()) {
return analysis_connector_settings_.at(connector).at(0).GetLearnMoreUrl(
tag);
}
}
return absl::nullopt;
}
bool ConnectorsManager::GetBypassJustificationRequired(
AnalysisConnector connector,
const std::string& tag) {
if (IsConnectorEnabled(connector)) {
if (analysis_connector_settings_.count(connector) == 0)
CacheAnalysisConnectorPolicy(connector);
if (analysis_connector_settings_.count(connector) &&
!analysis_connector_settings_.at(connector).empty()) {
return analysis_connector_settings_.at(connector)
.at(0)
.GetBypassJustificationRequired(tag);
}
}
return false;
}
std::vector<std::string> ConnectorsManager::GetAnalysisServiceProviderNames(
AnalysisConnector connector) {
if (IsConnectorEnabled(connector)) {
if (analysis_connector_settings_.count(connector) == 0) {
CacheAnalysisConnectorPolicy(connector);
}
if (analysis_connector_settings_.count(connector) &&
!analysis_connector_settings_.at(connector).empty()) {
// There can only be one provider right now, but the system is designed to
// support multiples, so return a vector.
return {analysis_connector_settings_.at(connector)
.at(0)
.service_provider_name()};
}
}
return {};
}
std::vector<std::string> ConnectorsManager::GetReportingServiceProviderNames(
ReportingConnector connector) {
if (!IsConnectorEnabled(connector))
return {};
if (reporting_connector_settings_.count(connector) == 0)
CacheReportingConnectorPolicy(connector);
if (reporting_connector_settings_.count(connector) &&
!reporting_connector_settings_.at(connector).empty()) {
// There can only be one provider right now, but the system is designed to
// support multiples, so return a vector.
return {reporting_connector_settings_.at(connector)
.at(0)
.service_provider_name()};
}
return {};
}
std::vector<const AnalysisConfig*> ConnectorsManager::GetAnalysisServiceConfigs(
AnalysisConnector connector) {
if (IsConnectorEnabled(connector)) {
if (analysis_connector_settings_.count(connector) == 0) {
CacheAnalysisConnectorPolicy(connector);
}
if (analysis_connector_settings_.count(connector) &&
!analysis_connector_settings_.at(connector).empty()) {
// There can only be one provider right now, but the system is designed to
// support multiples, so return a vector.
return {
analysis_connector_settings_.at(connector).at(0).GetAnalysisConfig()};
}
}
return {};
}
void ConnectorsManager::StartObservingPrefs(PrefService* pref_service) {
pref_change_registrar_.Init(pref_service);
StartObservingPref(AnalysisConnector::FILE_ATTACHED);
StartObservingPref(AnalysisConnector::FILE_DOWNLOADED);
StartObservingPref(AnalysisConnector::BULK_DATA_ENTRY);
StartObservingPref(AnalysisConnector::PRINT);
#if BUILDFLAG(IS_CHROMEOS_ASH)
StartObservingPref(AnalysisConnector::FILE_TRANSFER);
#endif
StartObservingPref(ReportingConnector::SECURITY_EVENT);
}
void ConnectorsManager::StartObservingPref(AnalysisConnector connector) {
const char* pref = ConnectorPref(connector);
DCHECK(pref);
if (!pref_change_registrar_.IsObserved(pref)) {
pref_change_registrar_.Add(
pref,
base::BindRepeating(&ConnectorsManager::CacheAnalysisConnectorPolicy,
base::Unretained(this), connector));
}
}
void ConnectorsManager::StartObservingPref(ReportingConnector connector) {
const char* pref = ConnectorPref(connector);
DCHECK(pref);
if (!pref_change_registrar_.IsObserved(pref)) {
pref_change_registrar_.Add(
pref,
base::BindRepeating(&ConnectorsManager::CacheReportingConnectorPolicy,
base::Unretained(this), connector));
}
}
const ConnectorsManager::AnalysisConnectorsSettings&
ConnectorsManager::GetAnalysisConnectorsSettingsForTesting() const {
return analysis_connector_settings_;
}
const ConnectorsManager::ReportingConnectorsSettings&
ConnectorsManager::GetReportingConnectorsSettingsForTesting() const {
return reporting_connector_settings_;
}
} // namespace enterprise_connectors