| // 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. |
| // |
| // The Safe Browsing service is responsible for downloading anti-phishing and |
| // anti-malware tables and checking urls against them. |
| |
| #ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ |
| #define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| |
| #include "base/callback_list.h" |
| #include "base/files/file_path.h" |
| #include "base/functional/callback.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/scoped_multi_source_observation.h" |
| #include "base/task/sequenced_task_runner_helpers.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/net/proxy_config_monitor.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/profiles/profile_manager_observer.h" |
| #include "chrome/browser/profiles/profile_observer.h" |
| #include "chrome/browser/safe_browsing/phishy_interaction_tracker.h" |
| #include "chrome/browser/safe_browsing/safe_browsing_pref_change_handler.h" |
| #include "chrome/browser/safe_browsing/services_delegate.h" |
| #include "components/safe_browsing/buildflags.h" |
| #include "components/safe_browsing/content/browser/safe_browsing_service_interface.h" |
| #include "components/safe_browsing/core/browser/db/util.h" |
| #include "components/safe_browsing/core/browser/ping_manager.h" |
| #include "components/safe_browsing/core/common/proto/csd.pb.h" |
| #include "components/safe_browsing/core/common/safe_browsing_prefs.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "services/network/public/mojom/network_context.mojom-forward.h" |
| |
| #if BUILDFLAG(FULL_SAFE_BROWSING) |
| #include "chrome/browser/safe_browsing/incident_reporting/delayed_analysis_callback.h" |
| #endif |
| |
| class PrefChangeRegistrar; |
| class PrefService; |
| |
| namespace content { |
| class DownloadManager; |
| } |
| |
| namespace download { |
| class DownloadItem; |
| } |
| |
| namespace network { |
| namespace mojom { |
| class NetworkContext; |
| } |
| class SharedURLLoaderFactory; |
| } // namespace network |
| |
| namespace prefs { |
| namespace mojom { |
| class TrackedPreferenceValidationDelegate; |
| } |
| } // namespace prefs |
| |
| namespace extensions { |
| class SafeBrowsingPrivateApiUnitTest; |
| } // namespace extensions |
| |
| namespace safe_browsing { |
| #if BUILDFLAG(SAFE_BROWSING_DOWNLOAD_PROTECTION) |
| class DownloadProtectionService; |
| #endif |
| class PasswordProtectionService; |
| class SafeBrowsingDatabaseManager; |
| class SafeBrowsingServiceFactory; |
| class SafeBrowsingUIManager; |
| class TriggerManager; |
| class HashRealTimeService; |
| |
| // Construction needs to happen on the main thread. |
| // The SafeBrowsingServiceImpl owns both the UI and Database managers which do |
| // the heavylifting of safebrowsing service. Both of these managers stay |
| // alive until SafeBrowsingServiceImpl is destroyed, however, they are disabled |
| // permanently when Shutdown method is called. |
| class SafeBrowsingServiceImpl : public SafeBrowsingServiceInterface, |
| public ProfileManagerObserver, |
| public ProfileObserver { |
| public: |
| SafeBrowsingServiceImpl(const SafeBrowsingServiceImpl&) = delete; |
| SafeBrowsingServiceImpl& operator=(const SafeBrowsingServiceImpl&) = delete; |
| |
| static base::FilePath GetCookieFilePathForTesting(); |
| |
| static base::FilePath GetBaseFilename(); |
| |
| // Helper function to determine if a user meets the requirements to be shown |
| // a ESB promo. |
| static bool IsUserEligibleForESBPromo(Profile* profile); |
| |
| // Called on the UI thread to initialize the service. |
| void Initialize(); |
| |
| // Called on the main thread to let us know that the io_thread is going away. |
| void ShutDown(); |
| |
| // NOTE(vakh): This is not the most reliable way to find out if extended |
| // reporting has been enabled. That's why it starts with estimated_. It |
| // returns true if any of the profiles have extended reporting enabled. It may |
| // be called on any thread. That can lead to a race condition, but that's |
| // acceptable. |
| ExtendedReportingLevel estimated_extended_reporting_by_prefs() const { |
| return estimated_extended_reporting_by_prefs_; |
| } |
| |
| // Get current enabled status. Must be called on IO thread. |
| bool enabled() const { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| return enabled_; |
| } |
| |
| // Whether the service is enabled by the current set of profiles. |
| bool enabled_by_prefs() const { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| return enabled_by_prefs_; |
| } |
| |
| #if BUILDFLAG(SAFE_BROWSING_DOWNLOAD_PROTECTION) |
| // The DownloadProtectionService is not valid after the |
| // SafeBrowsingServiceImpl is destroyed. |
| DownloadProtectionService* download_protection_service() const { |
| return services_delegate_->GetDownloadService(); |
| } |
| #endif |
| |
| // Get the NetworkContext or URLLoaderFactory attached to |browser_context|. |
| // Called on UI thread. |
| network::mojom::NetworkContext* GetNetworkContext( |
| content::BrowserContext* browser_context) override; |
| virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory( |
| content::BrowserContext* browser_context); |
| |
| // Returns the minimum allowed timestamp for referrer chains. Used by the |
| // URL lookup service. |
| base::Time GetMinAllowedTimestampForReferrerChains(Profile* profile); |
| |
| // Flushes above two interfaces to avoid races in tests. |
| void FlushNetworkInterfaceForTesting( |
| content::BrowserContext* browser_context); |
| |
| void SetURLLoaderFactoryForTesting( |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) { |
| url_loader_factory_for_testing_ = url_loader_factory; |
| } |
| |
| const scoped_refptr<SafeBrowsingUIManager>& ui_manager() const; |
| |
| const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager() |
| const override; |
| |
| ReferrerChainProvider* GetReferrerChainProviderFromBrowserContext( |
| content::BrowserContext* browser_context) override; |
| |
| #if BUILDFLAG(IS_ANDROID) |
| internal::ReferringAppInfo GetReferringAppInfo( |
| content::WebContents* web_contents) override; |
| #endif |
| |
| TriggerManager* trigger_manager() const; |
| |
| // Gets PasswordProtectionService by profile. |
| PasswordProtectionService* GetPasswordProtectionService( |
| Profile* profile) const; |
| |
| // Returns a preference validation delegate that adds incidents to the |
| // incident reporting service for validation failures. Returns NULL if the |
| // service is not applicable for the given profile. |
| std::unique_ptr<prefs::mojom::TrackedPreferenceValidationDelegate> |
| CreatePreferenceValidationDelegate(Profile* profile) const; |
| |
| // Registers |callback| to be run after some delay following process launch. |
| // |callback| will be dropped if the service is not applicable for the |
| // process. |
| void RegisterDelayedAnalysisCallback(DelayedAnalysisCallback callback); |
| |
| // Adds |download_manager| to the set monitored by safe browsing. |
| void AddDownloadManager(content::DownloadManager* download_manager); |
| |
| // Gets the hash-prefix real-time lookup service associated with the profile, |
| // or creates one if one does not already exist. |
| HashRealTimeService* GetHashRealTimeService(Profile* profile); |
| |
| // Adds a listener for when SafeBrowsing preferences might have changed. |
| // To get the current state, the callback should call enabled_by_prefs(). |
| // Should only be called on the UI thread. |
| virtual base::CallbackListSubscription RegisterStateCallback( |
| const base::RepeatingClosure& callback); |
| |
| #if BUILDFLAG(SAFE_BROWSING_DOWNLOAD_PROTECTION) |
| // Sends download report to backend. |
| // TODO(crbug.com/355577227): Rename to MaybeSendDownloadReport. |
| virtual void SendDownloadReport( |
| download::DownloadItem* download, |
| ClientSafeBrowsingReportRequest::ReportType report_type, |
| bool did_proceed, |
| std::optional<bool> show_download_in_folder); |
| |
| // Persists download report on disk and sends it to backend on next startup. |
| // TODO(crbug.com/355577227): Rename to |
| // MaybePersistDownloadReportAndSendOnNextStartup. |
| virtual void PersistDownloadReportAndSendOnNextStartup( |
| download::DownloadItem* download, |
| ClientSafeBrowsingReportRequest::ReportType report_type, |
| bool did_proceed, |
| std::optional<bool> show_download_in_folder); |
| #endif // BUILDFLAG(SAFE_BROWSING_DOWNLOAD_PROTECTION) |
| |
| #if BUILDFLAG(FULL_SAFE_BROWSING) |
| // Sends phishy site report to backend. Returns true if the report is sent |
| // successfully. |
| virtual bool SendPhishyInteractionsReport( |
| Profile* profile, |
| const GURL& url, |
| const GURL& page_url, |
| const PhishySiteInteractionMap& phishy_interaction_data); |
| #endif // BUILDFLAG(FULL_SAFE_BROWSING) |
| |
| // Sends NOTIFICATION_PERMISSION_ACCEPTED report to backend if the user |
| // bypassed a warning before granting a notification permission. Returns true |
| // if the report is sent successfully. The profile and render_frame_host are |
| // used to help fill the referrer_chain. The profile also help us obtain the |
| // browser's ChromePingManagerFactory for sending the report. The other |
| // parameters are for filling in their respective |
| // NOTIFICATION_PERMISSION_ACCEPTED report fields. |
| virtual bool 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); |
| |
| // Create the default v4 protocol config struct. This just calls into a helper |
| // function, but it's still useful so that TestSafeBrowsingService can |
| // override it. |
| virtual V4ProtocolConfig GetV4ProtocolConfig() const; |
| |
| // Report the external app redirect to Safe Browsing if the following |
| // conditions are met: |
| // - User is opted in to ESB and not Incognito |
| // - The user has not redirected to this app recently |
| // - Neither the current page nor the destination app are allowlisted. |
| void ReportExternalAppRedirect(content::WebContents* web_contents, |
| std::string_view app_name, |
| std::string_view uri) override; |
| |
| protected: |
| // Creates the safe browsing service. Need to initialize before using. |
| SafeBrowsingServiceImpl(); |
| |
| ~SafeBrowsingServiceImpl() override; |
| |
| virtual SafeBrowsingUIManager* CreateUIManager(); |
| |
| // Registers all the delayed analysis with the incident reporting service. |
| // This is where you register your process-wide, profile-independent analysis. |
| virtual void RegisterAllDelayedAnalysis(); |
| |
| std::unique_ptr<ServicesDelegate> services_delegate_; |
| |
| private: |
| friend class SafeBrowsingServiceFactoryImpl; |
| friend struct content::BrowserThread::DeleteOnThread< |
| content::BrowserThread::UI>; |
| friend class base::DeleteHelper<SafeBrowsingServiceImpl>; |
| friend class SafeBrowsingBlockingPageTestBase; |
| friend class SafeBrowsingBlockingQuietPageTest; |
| friend class extensions::SafeBrowsingPrivateApiUnitTest; |
| friend class SafeBrowsingServerTest; |
| friend class SafeBrowsingUIManagerTest; |
| friend class TestSafeBrowsingService; |
| friend class TestSafeBrowsingServiceFactory; |
| friend class V4SafeBrowsingServiceTest; |
| friend class SendNotificationsAcceptedTest; |
| |
| FRIEND_TEST_ALL_PREFIXES( |
| SafeBrowsingServiceTest, |
| SaveExtendedReportingPrefValueOnProfileAddedFeatureFlagEnabled); |
| FRIEND_TEST_ALL_PREFIXES( |
| SafeBrowsingServiceTest, |
| SaveExtendedReportingPrefValueOnProfileAddedFeatureFlagDisabled); |
| FRIEND_TEST_ALL_PREFIXES(SafeBrowsingServiceTest, |
| TestMinAllowedTimeForReferrerChains); |
| FRIEND_TEST_ALL_PREFIXES( |
| SafeBrowsingServiceTest, |
| TestMinAllowedTimeForReferrerChains_EsbEnabledOnStartup); |
| FRIEND_TEST_ALL_PREFIXES( |
| SafeBrowsingServiceTest, |
| TestMinAllowedTimeForReferrerChains_MbbEnabledOnStartup); |
| FRIEND_TEST_ALL_PREFIXES( |
| SafeBrowsingServiceTest, |
| TestMinAllowedTimeForReferrerChains_MultipleProfiles); |
| FRIEND_TEST_ALL_PREFIXES(SafeBrowsingServiceTest, |
| EnhancedProtectionPrefChange_SingleProfile); |
| FRIEND_TEST_ALL_PREFIXES( |
| SafeBrowsingServiceTest, |
| EnhancedProtectionPrefChange_SupportsMultipleProfiles); |
| FRIEND_TEST_ALL_PREFIXES(V4SafeBrowsingServiceTest, |
| NotificationsAcceptedReportSentWithCorrectOrigins); |
| FRIEND_TEST_ALL_PREFIXES(V4SafeBrowsingServiceTest, |
| NotificationsAcceptedReportSentWithReferrerChain); |
| |
| void SetDatabaseManagerForTest(SafeBrowsingDatabaseManager* database_manager); |
| |
| // Start up SafeBrowsing objects. This can be called at browser start, or when |
| // the user checks the "Enable SafeBrowsing" option in the Advanced options |
| // UI. |
| void Start(); |
| |
| // Stops the SafeBrowsingServiceImpl. This can be called when the safe |
| // browsing preference is disabled. When shutdown is true, operation is |
| // permanently shutdown and cannot be restarted. |
| void Stop(bool shutdown); |
| |
| // ProfileManagerObserver: |
| void OnProfileAdded(Profile* profile) override; |
| |
| // ProfileObserver: |
| void OnOffTheRecordProfileCreated(Profile* off_the_record) override; |
| void OnProfileWillBeDestroyed(Profile* profile) override; |
| |
| // Creates services for |profile|, which may be normal or off the record. |
| void CreateServicesForProfile(Profile* profile); |
| |
| // Refreshes the state (calls RefreshState()), updates the min allowed time |
| // for referrer chains, and potentially shows a toast about Enhanced |
| // Protection setting changes when its preference value updates. |
| void EnhancedProtectionPrefChange(Profile* profile); |
| |
| // Maybe show a toast about Enhanced Protection setting changes. Called when |
| // its preference value updates. |
| void MaybeShowEnhancedProtectionSettingChangeToast(Profile* profile); |
| |
| // Checks if any profile is currently using the safe browsing service, and |
| // starts or stops the service accordingly. |
| void RefreshState(); |
| |
| // Updates the minimum allowed timestamp for referrer chains based on pref |
| // changes. |
| void UpdateMinAllowedTimeForReferrerChains(Profile* profile); |
| |
| void CreateTriggerManager(); |
| |
| // Creates a configured NetworkContextParams when the network service is in |
| // use. |
| network::mojom::NetworkContextParamsPtr CreateNetworkContextParams(); |
| |
| // Logs metrics related to cookies. |
| void RecordStartupCookieMetrics(Profile* profile); |
| |
| // Fills out_referrer_chain with the referrer chain value. |
| void FillReferrerChain(Profile* profile, |
| content::RenderFrameHost* render_frame_host, |
| google::protobuf::RepeatedPtrField<ReferrerChainEntry>* |
| out_referrer_chain); |
| |
| // Helper method that allows us to return true for tests. If not for tests, |
| // check with the ui manager. |
| bool IsURLAllowlisted(const GURL& url, |
| content::RenderFrameHost* primary_main_frame); |
| |
| void SetUrlIsAllowlistedForTesting() { |
| url_is_allowlisted_for_testing_ = true; |
| } |
| |
| void MaybeSendExternalAppRedirectReport( |
| Profile* profile, |
| const std::string& app_name, |
| std::unique_ptr<ClientSafeBrowsingReportRequest> report, |
| bool should_send); |
| |
| std::unique_ptr<ProxyConfigMonitor> proxy_config_monitor_; |
| |
| // Whether SafeBrowsing Extended Reporting is enabled by the current set of |
| // profiles. Updated on the UI thread. |
| ExtendedReportingLevel estimated_extended_reporting_by_prefs_; |
| |
| // Whether the service has been shutdown. |
| bool shutdown_; |
| |
| // Whether the service is running. 'enabled_' is used by |
| // SafeBrowsingServiceImpl on the IO thread during normal operations. |
| bool enabled_; |
| |
| // Whether SafeBrowsing is enabled by the current set of profiles. |
| // Accessed on UI thread. |
| bool enabled_by_prefs_; |
| |
| // Tracks existing PrefServices, and the safe browsing preference on each. |
| // This is used to determine if any profile is currently using the safe |
| // browsing service, and to start it up or shut it down accordingly. |
| // Accessed on UI thread. |
| std::map<PrefService*, std::unique_ptr<PrefChangeRegistrar>> prefs_map_; |
| |
| // Tracks existing PrefServices. This is used to clear the cached user |
| // population whenever a relevant pref is changed. |
| std::map<PrefService*, std::unique_ptr<PrefChangeRegistrar>> |
| user_population_prefs_; |
| |
| // Maps each profile to the time that real-time URL lookups are enabled. |
| std::map<Profile*, std::optional<base::Time>> |
| min_allowed_time_for_referrer_chains_; |
| |
| // Callbacks when SafeBrowsing state might have changed. |
| // Should only be accessed on the UI thread. |
| base::RepeatingClosureList state_callback_list_; |
| |
| // The UI manager handles showing interstitials. Accessed on both UI and IO |
| // thread. |
| scoped_refptr<SafeBrowsingUIManager> ui_manager_; |
| |
| base::ScopedMultiSourceObservation<Profile, ProfileObserver> |
| observed_profiles_{this}; |
| |
| std::unique_ptr<TriggerManager> trigger_manager_; |
| |
| bool url_is_allowlisted_for_testing_ = false; |
| |
| scoped_refptr<network::SharedURLLoaderFactory> |
| url_loader_factory_for_testing_; |
| |
| // Manages the logic for handling preference changes, including displaying |
| // specific UI elements in response to certain preference changes. |
| std::map<Profile*, std::unique_ptr<SafeBrowsingPrefChangeHandler>> |
| pref_change_handlers_map_; |
| }; |
| |
| // TODO(crbug.com/41437292): Remove this once dependencies are using the |
| // SafeBrowsingServiceInterface. |
| class SafeBrowsingService : public SafeBrowsingServiceImpl { |
| public: |
| SafeBrowsingService() = default; |
| |
| protected: |
| ~SafeBrowsingService() override = default; |
| }; |
| |
| SafeBrowsingServiceFactory* GetSafeBrowsingServiceFactory(); |
| |
| } // namespace safe_browsing |
| |
| #endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ |