blob: aa7e6d52b1c440792acb7fa739d13daf99df5337 [file] [log] [blame]
// 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_INCIDENT_REPORTING_SERVICE_H_
#define CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_INCIDENT_REPORTING_SERVICE_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <vector>
#include "base/compiler_specific.h"
#include "base/feature_list.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#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/incident_reporting/delayed_analysis_callback.h"
#include "chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h"
#include "chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.h"
#include "chrome/browser/safe_browsing/incident_reporting/incident_report_uploader.h"
#include "chrome/browser/safe_browsing/incident_reporting/last_download_finder.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
class Profile;
namespace base {
class TaskRunner;
}
namespace content {
class DownloadManager;
class NotificationDetails;
class NotificationSource;
}
namespace net {
class URLRequestContextGetter;
}
namespace prefs {
namespace mojom {
class TrackedPreferenceValidationDelegate;
}
}
namespace safe_browsing {
#if !defined(GOOGLE_CHROME_BUILD)
extern const base::Feature kIncidentReportingDisableUpload;
#endif
class ClientDownloadRequest;
class ClientIncidentReport;
class ClientIncidentReport_DownloadDetails;
class ClientIncidentReport_EnvironmentData;
class ClientIncidentReport_ExtensionData;
class Incident;
class IncidentReceiver;
class SafeBrowsingDatabaseManager;
class SafeBrowsingService;
// 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 extended reporting are dropped. Process-wide incidents are
// affiliated with a profile that participates in safe browsing extended
// reporting when one becomes available.
// 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.
// Lives on the UI thread.
class IncidentReportingService : public content::NotificationObserver {
public:
explicit IncidentReportingService(SafeBrowsingService* safe_browsing_service);
// All incident collection, data collection, and uploads in progress are
// dropped at destruction.
~IncidentReportingService() override;
// Returns true if incident reporting is enabled for the given profile.
static bool IsEnabledForProfile(Profile* profile);
// Returns an object by which external components can add an incident to the
// service. The object may outlive the service, but will no longer have any
// effect after the service is deleted.
std::unique_ptr<IncidentReceiver> GetIncidentReceiver();
// 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.
std::unique_ptr<prefs::mojom::TrackedPreferenceValidationDelegate>
CreatePreferenceValidationDelegate(Profile* profile);
// Registers |callback| to be run after some delay following process launch.
void RegisterDelayedAnalysisCallback(const DelayedAnalysisCallback& callback);
// Adds |download_manager| to the set monitored for client download request
// storage.
void AddDownloadManager(content::DownloadManager* download_manager);
protected:
// A pointer to a function that populates a protobuf with environment data.
typedef void (*CollectEnvironmentDataFn)(
ClientIncidentReport_EnvironmentData*);
// For testing so that the TaskRunner used for delayed analysis callbacks can
// be specified.
IncidentReportingService(
SafeBrowsingService* safe_browsing_service,
const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
base::TimeDelta delayed_task_interval,
const scoped_refptr<base::TaskRunner>& delayed_task_runner);
// 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<base::TaskRunner>& task_runner);
// Initiates extension collection. Overriden by unit tests to provide fake
// extension data.
virtual void DoExtensionCollection(
ClientIncidentReport_ExtensionData* extension_data);
// 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
// extended reporting, 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 std::unique_ptr<LastDownloadFinder> CreateDownloadFinder(
const LastDownloadFinder::LastDownloadCallback& callback);
// Initiates an upload. Overridden by unit tests to provide a fake uploader.
virtual std::unique_ptr<IncidentReportUploader> StartReportUpload(
const IncidentReportUploader::OnResultCallback& callback,
const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
const ClientIncidentReport& report);
// Returns true if a report is currently being processed.
bool IsProcessingReport() const;
private:
struct ProfileContext;
class UploadContext;
class Receiver;
// 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);
// Returns an initialized profile for which incident reporting is enabled.
Profile* FindEligibleProfile() const;
// Adds |incident_data| relating to the optional |profile| to the service.
void AddIncident(Profile* profile, std::unique_ptr<Incident> incident);
// Clears all data associated with the |incident| relating to the optional
// |profile|.
void ClearIncident(Profile* profile, std::unique_ptr<Incident> incident);
// Returns true if there are incidents waiting to be sent.
bool HasIncidentsToUpload() const;
// Begins processing a report. If processing is already underway, ensures that
// collection tasks have completed or are running.
void BeginReportProcessing();
// Begins the process of collating incidents by waiting for incidents to
// arrive. This function is idempotent.
void BeginIncidentCollation();
// 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 collation has
// completed. Incident report processing continues, either by waiting for
// environment data or the most recent download to arrive or by sending an
// incident report.
void OnCollationTimeout();
// 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(
std::unique_ptr<ClientIncidentReport_EnvironmentData> environment_data);
// 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 and most recent non-binary
// download is complete.
void OnLastDownloadFound(
std::unique_ptr<ClientIncidentReport_DownloadDetails>
last_binary_download,
std::unique_ptr<ClientIncidentReport_NonBinaryDownloadDetails>
last_non_binary_download);
// Processes all received incidents once all data collection is
// complete. Incidents originating from profiles that do not participate in
// safe browsing extended reporting are dropped, incidents that have already
// been reported are pruned, and prune state is cleared for incidents that are
// now clear. Report upload is started if any incidents remain.
void ProcessIncidentsIfCollectionComplete();
// 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,
std::unique_ptr<ClientIncidentResponse> response);
// DownloadProtectionService::ClientDownloadRequestCallback implementation.
void OnClientDownloadRequest(content::DownloadItem* download,
const ClientDownloadRequest* request);
// content::NotificationObserver methods.
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// The safe browsing database manager, through which the whitelist killswitch
// is checked.
scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
// Accessor for an URL context with which reports will be sent.
scoped_refptr<net::URLRequestContextGetter> 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<base::TaskRunner> environment_collection_task_runner_;
// Registrar for observing profile lifecycle notifications.
content::NotificationRegistrar notification_registrar_;
// A subscription for ClientDownloadRequests, used to persist them for later
// use.
ClientDownloadRequestSubscription client_download_request_subscription_;
// 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
// collation_timer_ to fire.
bool collation_timeout_pending_;
// A timer upon the firing of which the service will report received
// incidents.
base::DelayTimer collation_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.
std::unique_ptr<ClientIncidentReport> 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 plus the process-wide (NULL)
// context. A mapping of profiles to contexts holding state about received
// incidents.
std::map<Profile*, std::unique_ptr<ProfileContext>> profiles_;
// Callbacks registered for performing delayed analysis.
DelayedCallbackRunner delayed_analysis_callbacks_;
DownloadMetadataManager download_metadata_manager_;
// The collection of uploads in progress.
std::vector<std::unique_ptr<UploadContext>> uploads_;
// An object that asynchronously searches for the most recent binary download.
// Non-NULL while such a search is outstanding.
std::unique_ptr<LastDownloadFinder> last_download_finder_;
// A factory for handing out weak pointers for IncidentReceiver objects.
base::WeakPtrFactory<IncidentReportingService> 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<IncidentReportingService> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(IncidentReportingService);
};
} // namespace safe_browsing
#endif // CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_INCIDENT_REPORTING_SERVICE_H_