// Copyright 2014 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_SAFE_BROWSING_INCIDENT_REPORTING_SERVICE_H_ #define CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_SERVICE_H_ #include #include #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "chrome/browser/safe_browsing/add_incident_callback.h" #include "chrome/browser/safe_browsing/incident_report_uploader.h" #include "chrome/browser/safe_browsing/last_download_finder.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" class Profile; class SafeBrowsingDatabaseManager; class SafeBrowsingService; class TrackedPreferenceValidationDelegate; namespace base { class TaskRunner; } namespace content { class NotificationDetails; class NotificationSource; } namespace net { class URLRequestContextGetter; } namespace safe_browsing { class ClientIncidentReport; class ClientIncidentReport_DownloadDetails; class ClientIncidentReport_EnvironmentData; class ClientIncidentReport_IncidentData; // A class that manages the collection of incidents and submission of incident // reports to the safe browsing client-side detection service. The service // begins operation when an incident is reported via the AddIncident method. // Incidents reported from a profile that is loading are held until the profile // is fully created. Incidents originating from profiles that do not participate // in safe browsing are dropped. Following the addition of an incident that is // not dropped, the service collects environmental data, finds the most recent // binary download, and waits a bit. Additional incidents that arrive during // this time are collated with the initial incident. Finally, already-reported // incidents are pruned and any remaining are uploaded in an incident report. class IncidentReportingService : public content::NotificationObserver { public: IncidentReportingService(SafeBrowsingService* safe_browsing_service, const scoped_refptr& request_context_getter); // All incident collection, data collection, and uploads in progress are // dropped at destruction. virtual ~IncidentReportingService(); // Returns a callback by which external components can add an incident to the // service on behalf of |profile|. The callback may outlive the service, but // will no longer have any effect after the service is deleted. The callback // must not be run after |profile| has been destroyed. AddIncidentCallback GetAddIncidentCallback(Profile* profile); // Returns a preference validation delegate that adds incidents to the service // for validation failures in |profile|. The delegate may outlive the service, // but incidents reported by it will no longer have any effect after the // service is deleted. The lifetime of the delegate should not extend beyond // that of the profile it services. scoped_ptr CreatePreferenceValidationDelegate(Profile* profile); protected: // A pointer to a function that populates a protobuf with environment data. typedef void (*CollectEnvironmentDataFn)( ClientIncidentReport_EnvironmentData*); // Sets the function called by the service to collect environment data and the // task runner on which it is called. Used by unit tests to provide a fake // environment data collector. void SetCollectEnvironmentHook( CollectEnvironmentDataFn collect_environment_data_hook, const scoped_refptr& task_runner); // Handles the addition of a new profile to the ProfileManager. Creates a new // context for |profile| if one does not exist, drops any received incidents // for the profile if the profile is not participating in safe browsing, and // initiates a new search for the most recent download if a report is being // assembled and the most recent has not been found. Overridden by unit tests // to inject incidents prior to creation. virtual void OnProfileAdded(Profile* profile); // Initiates a search for the most recent binary download. Overriden by unit // tests to provide a fake finder. virtual scoped_ptr CreateDownloadFinder( const LastDownloadFinder::LastDownloadCallback& callback); // Initiates an upload. Overridden by unit tests to provide a fake uploader. virtual scoped_ptr StartReportUpload( const IncidentReportUploader::OnResultCallback& callback, const scoped_refptr& request_context_getter, const ClientIncidentReport& report); private: struct ProfileContext; class UploadContext; // A mapping of profiles to contexts holding state about received incidents. typedef std::map ProfileContextCollection; // Returns the context for |profile|, creating it if it does not exist. ProfileContext* GetOrCreateProfileContext(Profile* profile); // Returns the context for |profile|, or NULL if it is unknown. ProfileContext* GetProfileContext(Profile* profile); // Handles the destruction of a profile. Incidents reported for the profile // but not yet uploaded are dropped. void OnProfileDestroyed(Profile* profile); // Adds |incident_data| to the service. The incident_time_msec field is // populated with the current time if the caller has not already done so. void AddIncident(Profile* profile, scoped_ptr incident_data); // Starts a task to collect environment data in the blocking pool. void BeginEnvironmentCollection(); // Returns true if the environment collection task is outstanding. bool WaitingForEnvironmentCollection(); // Cancels any pending environment collection task and drops any data that has // already been collected. void CancelEnvironmentCollection(); // A callback invoked on the UI thread when environment data collection is // complete. Incident report processing continues, either by waiting for the // collection timeout or by sending an incident report. void OnEnvironmentDataCollected( scoped_ptr environment_data); // Returns true if the service is waiting for additional incidents before // uploading a report. bool WaitingToCollateIncidents(); // Cancels the collection timeout. void CancelIncidentCollection(); // A callback invoked on the UI thread after which incident collection has // completed. Incident report processing continues, either by waiting for // environment data to arrive or by sending an incident report. void OnCollectionTimeout(); // Starts the asynchronous process of finding the most recent executable // download if one is not currently being search for and/or has not already // been found. void BeginDownloadCollection(); // True if the service is waiting to discover the most recent download either // because a task to do so is outstanding, or because one or more profiles // have yet to be added to the ProfileManager. bool WaitingForMostRecentDownload(); // Cancels the search for the most recent executable download. void CancelDownloadCollection(); // A callback invoked on the UI thread by the last download finder when the // search for the most recent binary download is complete. void OnLastDownloadFound( scoped_ptr last_download); // Uploads an incident report if all data collection is complete. Incidents // originating from profiles that do not participate in safe browsing are // dropped. void UploadIfCollectionComplete(); // Cancels all uploads, discarding all reports and responses in progress. void CancelAllReportUploads(); // Continues an upload after checking for the CSD whitelist killswitch. void OnKillSwitchResult(UploadContext* context, bool is_killswitch_on); // Performs processing for a report after succesfully receiving a response. void HandleResponse(const UploadContext& context); // IncidentReportUploader::OnResultCallback implementation. void OnReportUploadResult(UploadContext* context, IncidentReportUploader::Result result, scoped_ptr response); // content::NotificationObserver methods. virtual void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE; base::ThreadChecker thread_checker_; // The safe browsing database manager, through which the whitelist killswitch // is checked. scoped_refptr database_manager_; // Accessor for an URL context with which reports will be sent. scoped_refptr url_request_context_getter_; // A pointer to a function that collects environment data. The function will // be run by |environment_collection_task_runner_|. This is ordinarily // CollectEnvironmentData, but may be overridden by tests; see // SetCollectEnvironmentHook. CollectEnvironmentDataFn collect_environment_data_fn_; // The task runner on which environment collection takes place. This is // ordinarily a runner in the browser's blocking pool that will skip the // collection task at shutdown if it has not yet started. scoped_refptr environment_collection_task_runner_; // Registrar for observing profile lifecycle notifications. content::NotificationRegistrar notification_registrar_; // True when the asynchronous environment collection task has been fired off // but has not yet completed. bool environment_collection_pending_; // True when an incident has been received and the service is waiting for the // upload_timer_ to fire. bool collection_timeout_pending_; // A timer upon the firing of which the service will report received // incidents. base::DelayTimer upload_timer_; // The report currently being assembled. This becomes non-NULL when an initial // incident is reported, and returns to NULL when the report is sent for // upload. scoped_ptr report_; // The time at which the initial incident is reported. base::Time first_incident_time_; // The time at which the last incident is reported. base::TimeTicks last_incident_time_; // The time at which environmental data collection was initiated. base::TimeTicks environment_collection_begin_; // The time at which download collection was initiated. base::TimeTicks last_download_begin_; // Context data for all on-the-record profiles. ProfileContextCollection profiles_; // The collection of uploads in progress. ScopedVector uploads_; // An object that asynchronously searches for the most recent binary download. // Non-NULL while such a search is outstanding. scoped_ptr last_download_finder_; // A factory for handing out weak pointers for AddIncident callbacks. base::WeakPtrFactory receiver_weak_ptr_factory_; // A factory for handing out weak pointers for internal asynchronous tasks // that are posted during normal processing (e.g., environment collection, // safe browsing database checks, and report uploads). base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(IncidentReportingService); }; } // namespace safe_browsing #endif // CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_SERVICE_H_