blob: 2b999654d6837ae94b9bfface0b14e805b0dd58f [file] [log] [blame]
// Copyright 2012 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/safe_browsing/safe_browsing_service.h"
#include <stddef.h>
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "chrome/browser/browser_features.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/download/download_item_warning_data.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
#include "chrome/browser/safe_browsing/chrome_password_protection_service_factory.h"
#include "chrome/browser/safe_browsing/chrome_ping_manager_factory.h"
#include "chrome/browser/safe_browsing/chrome_safe_browsing_blocking_page_factory.h"
#include "chrome/browser/safe_browsing/chrome_ui_manager_delegate.h"
#include "chrome/browser/safe_browsing/chrome_user_population_helper.h"
#include "chrome/browser/safe_browsing/chrome_v4_protocol_config_provider.h"
#include "chrome/browser/safe_browsing/network_context_service.h"
#include "chrome/browser/safe_browsing/network_context_service_factory.h"
#include "chrome/browser/safe_browsing/safe_browsing_metrics_collector_factory.h"
#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager_factory.h"
#include "chrome/browser/safe_browsing/services_delegate.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "components/download/public/common/download_item.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.h"
#include "components/safe_browsing/content/browser/triggers/trigger_manager.h"
#include "components/safe_browsing/content/browser/ui_manager.h"
#include "components/safe_browsing/content/browser/web_ui/safe_browsing_ui.h"
#include "components/safe_browsing/content/common/file_type_policies.h"
#include "components/safe_browsing/core/browser/db/database_manager.h"
#include "components/safe_browsing/core/browser/ping_manager.h"
#include "components/safe_browsing/core/browser/realtime/policy_engine.h"
#include "components/safe_browsing/core/browser/referrer_chain_provider.h"
#include "components/safe_browsing/core/browser/safe_browsing_metrics_collector.h"
#include "components/safe_browsing/core/common/features.h"
#include "components/safe_browsing/core/common/safe_browsing_policy_handler.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/safe_browsing/core/common/safebrowsing_constants.h"
#include "components/unified_consent/pref_names.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_item_utils.h"
#include "services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h"
#include "services/network/public/cpp/features.h"
#include "services/preferences/public/mojom/tracked_preference_validation_delegate.mojom.h"
#if BUILDFLAG(IS_WIN)
#include "chrome/install_static/install_util.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "chrome/browser/safe_browsing/android/safe_browsing_referring_app_bridge_android.h"
#endif
#if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
#include "components/safe_browsing/content/browser/password_protection/password_protection_service.h"
#endif
#if BUILDFLAG(FULL_SAFE_BROWSING)
#include "chrome/browser/safe_browsing/download_protection/download_protection_service.h"
#include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
#include "chrome/browser/safe_browsing/hash_realtime_service_factory.h"
#include "chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chromeos/ash/components/browser_context_helper/browser_context_types.h"
#endif
using content::BrowserThread;
namespace safe_browsing {
namespace {
// The number of user gestures to trace back for the referrer chain.
const int kReferrerChainUserGestureLimit = 2;
#if BUILDFLAG(FULL_SAFE_BROWSING)
void PopulateDownloadWarningActions(download::DownloadItem* download,
ClientSafeBrowsingReportRequest* report) {
for (auto& event :
DownloadItemWarningData::GetWarningActionEvents(download)) {
report->mutable_download_warning_actions()->Add(
DownloadItemWarningData::ConstructCsbrrDownloadWarningAction(event));
}
base::UmaHistogramCounts100(
"SafeBrowsing.ClientSafeBrowsingReport.DownloadWarningActionSize",
report->download_warning_actions_size());
}
std::unique_ptr<ClientSafeBrowsingReportRequest> CreateDownloadReport(
download::DownloadItem* download,
ClientSafeBrowsingReportRequest::ReportType report_type,
bool did_proceed,
std::optional<bool> show_download_in_folder) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
Profile* profile = Profile::FromBrowserContext(
content::DownloadItemUtils::GetBrowserContext(download));
auto report = std::make_unique<ClientSafeBrowsingReportRequest>();
report->set_type(report_type);
report->set_download_verdict(
DownloadProtectionService::GetDownloadProtectionVerdict(download));
report->set_url(download->GetURL().spec());
report->set_did_proceed(did_proceed);
if (show_download_in_folder.has_value()) {
report->set_show_download_in_folder(show_download_in_folder.value());
}
std::string token = DownloadProtectionService::GetDownloadPingToken(download);
if (!token.empty()) {
report->set_token(std::move(token));
}
if (IsExtendedReportingEnabled(*profile->GetPrefs())) {
PopulateDownloadWarningActions(download, report.get());
base::Time warning_first_shown_time =
DownloadItemWarningData::WarningFirstShownTime(download);
if (!warning_first_shown_time.is_null() &&
base::FeatureList::IsEnabled(kDownloadReportWithoutUserDecision)) {
report->set_warning_shown_timestamp_msec(
warning_first_shown_time.InMillisecondsSinceUnixEpoch());
}
}
return report;
}
#endif
void OnGotCookies(
std::unique_ptr<mojo::Remote<network::mojom::CookieManager>> remote,
const std::vector<net::CanonicalCookie>& cookies) {
base::UmaHistogramBoolean("SafeBrowsing.HasCookieAtStartup2",
!cookies.empty());
if (!cookies.empty()) {
base::TimeDelta age = base::Time::Now() - cookies.front().CreationDate();
// Cookies can be up to 6 months old. Using millisecond precision over such
// a long time period overflows numeric limits. Instead, use a counts
// histogram and lower granularity.
base::UmaHistogramCounts10000("SafeBrowsing.CookieAgeHours2",
age.InHours());
}
}
} // namespace
// static
base::FilePath SafeBrowsingService::GetCookieFilePathForTesting() {
return base::FilePath(SafeBrowsingService::GetBaseFilename().value() +
safe_browsing::kCookiesFile);
}
// static
base::FilePath SafeBrowsingService::GetBaseFilename() {
base::FilePath path;
bool result = base::PathService::Get(chrome::DIR_USER_DATA, &path);
DCHECK(result);
return path.Append(safe_browsing::kSafeBrowsingBaseFilename);
}
// static
bool SafeBrowsingService::IsUserEligibleForESBPromo(Profile* profile) {
if (IsSafeBrowsingPolicyManaged(*profile->GetPrefs()) ||
profile->IsOffTheRecord()) {
return false;
}
return GetSafeBrowsingState(*profile->GetPrefs()) ==
SafeBrowsingState::STANDARD_PROTECTION;
}
SafeBrowsingService::SafeBrowsingService()
: services_delegate_(ServicesDelegate::Create(this)),
estimated_extended_reporting_by_prefs_(SBER_LEVEL_OFF),
shutdown_(false),
enabled_(false),
enabled_by_prefs_(false) {}
SafeBrowsingService::~SafeBrowsingService() {
// We should have already been shut down. If we're still enabled, then the
// database isn't going to be closed properly, which could lead to corruption.
DCHECK(!enabled_);
}
void SafeBrowsingService::Initialize() {
// Ensure FileTypePolicies's Singleton is instantiated during startup.
// This guarantees we'll log UMA metrics about its state.
FileTypePolicies::GetInstance();
base::FilePath user_data_dir;
bool result = base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
DCHECK(result);
WebUIInfoSingleton::GetInstance()->set_safe_browsing_service(this);
ui_manager_ = CreateUIManager();
services_delegate_->Initialize();
// Needs to happen after |ui_manager_| is created.
CreateTriggerManager();
// Track profile creation and destruction.
if (g_browser_process->profile_manager()) {
g_browser_process->profile_manager()->AddObserver(this);
DCHECK_EQ(0U,
g_browser_process->profile_manager()->GetLoadedProfiles().size());
}
// Register all the delayed analysis to the incident reporting service.
RegisterAllDelayedAnalysis();
}
void SafeBrowsingService::ShutDown() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
shutdown_ = true;
// Remove Profile creation/destruction observers.
if (g_browser_process->profile_manager()) {
g_browser_process->profile_manager()->RemoveObserver(this);
}
observed_profiles_.RemoveAllObservations();
// Delete the PrefChangeRegistrars, whose dtors also unregister |this| as an
// observer of the preferences.
prefs_map_.clear();
user_population_prefs_.clear();
Stop(true);
services_delegate_->ShutdownServices();
WebUIInfoSingleton::GetInstance()->set_safe_browsing_service(nullptr);
proxy_config_monitor_.reset();
}
network::mojom::NetworkContext* SafeBrowsingService::GetNetworkContext(
content::BrowserContext* browser_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
NetworkContextService* service =
NetworkContextServiceFactory::GetForBrowserContext(browser_context);
if (!service) {
return nullptr;
}
return service->GetNetworkContext();
}
scoped_refptr<network::SharedURLLoaderFactory>
SafeBrowsingService::GetURLLoaderFactory(
content::BrowserContext* browser_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (url_loader_factory_for_testing_) {
return url_loader_factory_for_testing_;
}
NetworkContextService* service =
NetworkContextServiceFactory::GetForBrowserContext(browser_context);
if (!service) {
return nullptr;
}
return service->GetURLLoaderFactory();
}
void SafeBrowsingService::FlushNetworkInterfaceForTesting(
content::BrowserContext* browser_context) {
NetworkContextService* service =
NetworkContextServiceFactory::GetForBrowserContext(browser_context);
if (!service) {
return;
}
service->FlushNetworkInterfaceForTesting();
}
const scoped_refptr<SafeBrowsingUIManager>& SafeBrowsingService::ui_manager()
const {
return ui_manager_;
}
const scoped_refptr<SafeBrowsingDatabaseManager>&
SafeBrowsingService::database_manager() const {
return services_delegate_->database_manager();
}
ReferrerChainProvider*
SafeBrowsingService::GetReferrerChainProviderFromBrowserContext(
content::BrowserContext* browser_context) {
return SafeBrowsingNavigationObserverManagerFactory::GetForBrowserContext(
browser_context);
}
#if BUILDFLAG(IS_ANDROID)
LoginReputationClientRequest::ReferringAppInfo
SafeBrowsingService::GetReferringAppInfo(content::WebContents* web_contents) {
return safe_browsing::GetReferringAppInfo(web_contents);
}
#endif
TriggerManager* SafeBrowsingService::trigger_manager() const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return trigger_manager_.get();
}
PasswordProtectionService* SafeBrowsingService::GetPasswordProtectionService(
Profile* profile) const {
if (IsSafeBrowsingEnabled(*profile->GetPrefs())) {
return ChromePasswordProtectionServiceFactory::GetForProfile(profile);
}
return nullptr;
}
std::unique_ptr<prefs::mojom::TrackedPreferenceValidationDelegate>
SafeBrowsingService::CreatePreferenceValidationDelegate(
Profile* profile) const {
return services_delegate_->CreatePreferenceValidationDelegate(profile);
}
void SafeBrowsingService::RegisterDelayedAnalysisCallback(
DelayedAnalysisCallback callback) {
services_delegate_->RegisterDelayedAnalysisCallback(std::move(callback));
}
void SafeBrowsingService::AddDownloadManager(
content::DownloadManager* download_manager) {
services_delegate_->AddDownloadManager(download_manager);
}
HashRealTimeService* SafeBrowsingService::GetHashRealTimeService(
Profile* profile) {
#if BUILDFLAG(FULL_SAFE_BROWSING)
return safe_browsing::HashRealTimeServiceFactory::GetForProfile(profile);
#else
return nullptr;
#endif
}
SafeBrowsingUIManager* SafeBrowsingService::CreateUIManager() {
return new SafeBrowsingUIManager(
std::make_unique<ChromeSafeBrowsingUIManagerDelegate>(),
std::make_unique<ChromeSafeBrowsingBlockingPageFactory>(),
GURL(chrome::kChromeUINewTabURL));
}
void SafeBrowsingService::RegisterAllDelayedAnalysis() {
#if BUILDFLAG(FULL_SAFE_BROWSING)
RegisterBinaryIntegrityAnalysis();
#endif
}
V4ProtocolConfig SafeBrowsingService::GetV4ProtocolConfig() const {
return safe_browsing::GetV4ProtocolConfig();
}
void SafeBrowsingService::SetDatabaseManagerForTest(
SafeBrowsingDatabaseManager* database_manager) {
services_delegate_->SetDatabaseManagerForTest(database_manager);
}
void SafeBrowsingService::Start() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!enabled_) {
enabled_ = true;
services_delegate_->StartOnSBThread(
g_browser_process->shared_url_loader_factory(), GetV4ProtocolConfig());
}
}
void SafeBrowsingService::Stop(bool shutdown) {
ui_manager_->Stop(shutdown);
services_delegate_->StopOnSBThread(shutdown);
enabled_ = false;
}
void SafeBrowsingService::OnProfileAdded(Profile* profile) {
// Some services are disabled by default based on the profile type, e.g. the
// System Profile, in which Safe browsing is not needed.
if (AreKeyedServicesDisabledForProfileByDefault(profile)) {
return;
}
// Start following the safe browsing preference on |pref_service|.
PrefService* pref_service = profile->GetPrefs();
DCHECK(prefs_map_.find(pref_service) == prefs_map_.end());
std::unique_ptr<PrefChangeRegistrar> registrar =
std::make_unique<PrefChangeRegistrar>();
registrar->Init(pref_service);
registrar->Add(prefs::kSafeBrowsingEnabled,
base::BindRepeating(&SafeBrowsingService::RefreshState,
base::Unretained(this)));
// ClientSideDetectionService will need to be refresh the models
// renderers have if extended-reporting changes.
registrar->Add(prefs::kSafeBrowsingScoutReportingEnabled,
base::BindRepeating(&SafeBrowsingService::RefreshState,
base::Unretained(this)));
registrar->Add(prefs::kSafeBrowsingEnhanced,
base::BindRepeating(&SafeBrowsingService::RefreshState,
base::Unretained(this)));
prefs_map_[pref_service] = std::move(registrar);
RefreshState();
registrar = std::make_unique<PrefChangeRegistrar>();
registrar->Init(pref_service);
registrar->Add(prefs::kSafeBrowsingEnabled,
base::BindRepeating(&ClearCachedUserPopulation, profile,
NoCachedPopulationReason::kChangeSbPref));
registrar->Add(prefs::kSafeBrowsingScoutReportingEnabled,
base::BindRepeating(&ClearCachedUserPopulation, profile,
NoCachedPopulationReason::kChangeSbPref));
registrar->Add(prefs::kSafeBrowsingEnhanced,
base::BindRepeating(&ClearCachedUserPopulation, profile,
NoCachedPopulationReason::kChangeSbPref));
registrar->Add(
unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled,
base::BindRepeating(&ClearCachedUserPopulation, profile,
NoCachedPopulationReason::kChangeMbbPref));
user_population_prefs_[pref_service] = std::move(registrar);
// Record the current pref state for standard protection.
UMA_HISTOGRAM_BOOLEAN(kSafeBrowsingEnabledHistogramName,
pref_service->GetBoolean(prefs::kSafeBrowsingEnabled));
// Record the current pref state for enhanced protection. Enhanced protection
// is a subset of the standard protection. Thus, |kSafeBrowsingEnabled| count
// should always be more than the count of enhanced protection.
UMA_HISTOGRAM_BOOLEAN("SafeBrowsing.Pref.Enhanced",
pref_service->GetBoolean(prefs::kSafeBrowsingEnhanced));
// Record the current enhanced protection pref state for regular profiles only
if (profiles::IsRegularUserProfile(profile)) {
UMA_HISTOGRAM_BOOLEAN(
"SafeBrowsing.Pref.Enhanced.RegularProfile",
pref_service->GetBoolean(prefs::kSafeBrowsingEnhanced));
}
// Extended Reporting metrics are handled together elsewhere.
RecordExtendedReportingMetrics(*pref_service);
SafeBrowsingMetricsCollectorFactory::GetForProfile(profile)->StartLogging();
CreateServicesForProfile(profile);
RecordStartupCookieMetrics(profile);
}
void SafeBrowsingService::OnOffTheRecordProfileCreated(
Profile* off_the_record) {
CreateServicesForProfile(off_the_record);
}
void SafeBrowsingService::OnProfileWillBeDestroyed(Profile* profile) {
observed_profiles_.RemoveObservation(profile);
services_delegate_->RemoveTelemetryService(profile);
services_delegate_->OnProfileWillBeDestroyed(profile);
PrefService* pref_service = profile->GetPrefs();
DCHECK(pref_service);
prefs_map_.erase(pref_service);
user_population_prefs_.erase(pref_service);
}
void SafeBrowsingService::CreateServicesForProfile(Profile* profile) {
services_delegate_->CreateTelemetryService(profile);
observed_profiles_.AddObservation(profile);
}
base::CallbackListSubscription SafeBrowsingService::RegisterStateCallback(
const base::RepeatingClosure& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return state_callback_list_.Add(callback);
}
void SafeBrowsingService::RefreshState() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Check if any profile requires the service to be active.
enabled_by_prefs_ = false;
estimated_extended_reporting_by_prefs_ = SBER_LEVEL_OFF;
for (const auto& pref : prefs_map_) {
if (IsSafeBrowsingEnabled(*pref.first)) {
enabled_by_prefs_ = true;
ExtendedReportingLevel erl =
safe_browsing::GetExtendedReportingLevel(*pref.first);
if (erl != SBER_LEVEL_OFF) {
estimated_extended_reporting_by_prefs_ = erl;
}
}
}
if (enabled_by_prefs_) {
Start();
} else {
Stop(false);
}
state_callback_list_.Notify();
services_delegate_->RefreshState(enabled_by_prefs_);
}
#if BUILDFLAG(FULL_SAFE_BROWSING)
bool SafeBrowsingService::SendDownloadReport(
download::DownloadItem* download,
ClientSafeBrowsingReportRequest::ReportType report_type,
bool did_proceed,
std::optional<bool> show_download_in_folder) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto report = CreateDownloadReport(download, report_type, did_proceed,
show_download_in_folder);
Profile* profile = Profile::FromBrowserContext(
content::DownloadItemUtils::GetBrowserContext(download));
return ChromePingManagerFactory::GetForBrowserContext(profile)
->ReportThreatDetails(std::move(report)) ==
PingManager::ReportThreatDetailsResult::SUCCESS;
}
bool SafeBrowsingService::PersistDownloadReportAndSendOnNextStartup(
download::DownloadItem* download,
ClientSafeBrowsingReportRequest::ReportType report_type,
bool did_proceed,
std::optional<bool> show_download_in_folder) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto report = CreateDownloadReport(download, report_type, did_proceed,
show_download_in_folder);
Profile* profile = Profile::FromBrowserContext(
content::DownloadItemUtils::GetBrowserContext(download));
PingManager::PersistThreatDetailsResult result =
ChromePingManagerFactory::GetForBrowserContext(profile)
->PersistThreatDetailsAndReportOnNextStartup(std::move(report));
base::UmaHistogramEnumeration(
"SafeBrowsing.ClientSafeBrowsingReport.PersistDownloadReportResult",
result);
return result == PingManager::PersistThreatDetailsResult::kPersistTaskPosted;
}
bool SafeBrowsingService::SendPhishyInteractionsReport(
Profile* profile,
const GURL& url,
const GURL& page_url,
const PhishySiteInteractionMap& phishy_interaction_data) {
if (!profile || !IsExtendedReportingEnabled(*profile->GetPrefs())) {
return false;
}
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto report = std::make_unique<ClientSafeBrowsingReportRequest>();
report->set_type(ClientSafeBrowsingReportRequest::PHISHY_SITE_INTERACTIONS);
report->set_url(url.spec());
report->set_page_url(page_url.spec());
for (auto const& interaction_type : phishy_interaction_data) {
if (interaction_type.second.occurrence_count > 0) {
// Create PhishySiteInteraction object and add to report.
ClientSafeBrowsingReportRequest::PhishySiteInteraction
new_phishy_site_interaction;
new_phishy_site_interaction.set_phishy_site_interaction_type(
interaction_type.first);
new_phishy_site_interaction.set_occurrence_count(
interaction_type.second.occurrence_count);
new_phishy_site_interaction.set_first_interaction_timestamp_msec(
interaction_type.second.first_timestamp);
new_phishy_site_interaction.set_last_interaction_timestamp_msec(
interaction_type.second.last_timestamp);
report->mutable_phishy_site_interactions()->Add()->Swap(
&new_phishy_site_interaction);
}
}
return ChromePingManagerFactory::GetForBrowserContext(profile)
->ReportThreatDetails(std::move(report)) ==
PingManager::ReportThreatDetailsResult::SUCCESS;
}
#endif
bool SafeBrowsingService::MaybeSendNotificationsAcceptedReport(
content::RenderFrameHost* render_frame_host,
Profile* profile,
const GURL& url,
const GURL& page_url,
const GURL& permission_prompt_origin,
base::TimeDelta permission_prompt_display_duration_sec) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!profile || !IsExtendedReportingEnabled(*profile->GetPrefs()) ||
!base::FeatureList::IsEnabled(
kCreateNotificationsAcceptedClientSafeBrowsingReports)) {
return false;
}
// Only send report if the UnsafeResource was allowlisted, due to the user
// bypassing an interstitial. Note that we want to check the
// permission_prompt_origin URL because if an interstitial was shown, then it
// was warning the user about the URL where the permission request originated.
if (!IsURLAllowlisted(permission_prompt_origin, render_frame_host)) {
return false;
}
auto report = std::make_unique<ClientSafeBrowsingReportRequest>();
report->set_type(
ClientSafeBrowsingReportRequest::NOTIFICATION_PERMISSION_ACCEPTED);
report->set_url(url.spec());
report->set_page_url(page_url.spec());
report->mutable_permission_prompt_info()->set_origin(
permission_prompt_origin.spec());
report->mutable_permission_prompt_info()->set_display_duration_sec(
permission_prompt_display_duration_sec.InSeconds());
FillReferrerChain(profile, render_frame_host,
report->mutable_referrer_chain());
return ChromePingManagerFactory::GetForBrowserContext(profile)
->ReportThreatDetails(std::move(report)) ==
PingManager::ReportThreatDetailsResult::SUCCESS;
}
void SafeBrowsingService::CreateTriggerManager() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
trigger_manager_ = std::make_unique<TriggerManager>(
ui_manager_.get(), g_browser_process->local_state());
}
network::mojom::NetworkContextParamsPtr
SafeBrowsingService::CreateNetworkContextParams() {
auto params = SystemNetworkContextManager::GetInstance()
->CreateDefaultNetworkContextParams();
// |proxy_config_monitor_| should be deleted after shutdown, so don't
// re-create it.
if (shutdown_) {
return params;
}
if (!proxy_config_monitor_) {
proxy_config_monitor_ =
std::make_unique<ProxyConfigMonitor>(g_browser_process->local_state());
}
proxy_config_monitor_->AddToNetworkContextParams(params.get());
return params;
}
void SafeBrowsingService::RecordStartupCookieMetrics(Profile* profile) {
// Exclude system profiles.
if (!profile->IsRegularProfile() && !profile->IsIncognitoProfile()) {
return;
}
network::mojom::NetworkContext* network_context = GetNetworkContext(profile);
if (!network_context) {
return;
}
auto cookie_manager_remote =
std::make_unique<mojo::Remote<network::mojom::CookieManager>>();
network_context->GetCookieManager(
cookie_manager_remote->BindNewPipeAndPassReceiver());
mojo::Remote<network::mojom::CookieManager>* cookie_manager_raw =
cookie_manager_remote.get();
(*cookie_manager_raw)
->GetAllCookies(
base::BindOnce(&OnGotCookies, std::move(cookie_manager_remote)));
}
void SafeBrowsingService::FillReferrerChain(
Profile* profile,
content::RenderFrameHost* render_frame_host,
google::protobuf::RepeatedPtrField<ReferrerChainEntry>*
out_referrer_chain) {
ReferrerChainProvider* provider =
GetReferrerChainProviderFromBrowserContext(profile);
if (!provider) {
return;
}
provider->IdentifyReferrerChainByRenderFrameHost(
render_frame_host, kReferrerChainUserGestureLimit, out_referrer_chain);
}
bool SafeBrowsingService::IsURLAllowlisted(
const GURL& url,
content::RenderFrameHost* primary_main_frame) {
if (url_is_allowlisted_for_testing_) {
return true;
}
security_interstitials::UnsafeResource resource;
resource.url = url;
resource.original_url = url;
resource.is_subresource = false;
resource.threat_type = SBThreatType::SB_THREAT_TYPE_URL_PHISHING;
const content::GlobalRenderFrameHostId primary_main_frame_id =
primary_main_frame->GetGlobalId();
resource.render_process_id = primary_main_frame_id.child_id;
resource.render_frame_token = primary_main_frame->GetFrameToken().value();
return ui_manager_->IsAllowlisted(resource);
}
// The default SafeBrowsingServiceFactory. Global, made a singleton so we
// don't leak it.
class SafeBrowsingServiceFactoryImpl : public SafeBrowsingServiceFactory {
public:
// TODO(crbug.com/41437292): Once callers of this function are no longer
// downcasting it to the SafeBrowsingService, we can make this a
// scoped_refptr.
SafeBrowsingServiceInterface* CreateSafeBrowsingService() override {
return new SafeBrowsingService();
}
SafeBrowsingServiceFactoryImpl(const SafeBrowsingServiceFactoryImpl&) =
delete;
SafeBrowsingServiceFactoryImpl& operator=(
const SafeBrowsingServiceFactoryImpl&) = delete;
private:
friend class base::NoDestructor<SafeBrowsingServiceFactoryImpl>;
SafeBrowsingServiceFactoryImpl() {}
};
SafeBrowsingServiceFactory* GetSafeBrowsingServiceFactory() {
static base::NoDestructor<SafeBrowsingServiceFactoryImpl> factory;
return factory.get();
}
} // namespace safe_browsing