blob: bd024728cc21f67c66c27fa115f6478106a61f81 [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_SERVICE_H_
#define CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_SERVICE_H_
#include <stdint.h>
#include <map>
#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<net::URLRequestContextGetter>&
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<TrackedPreferenceValidationDelegate>
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<base::TaskRunner>& 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<LastDownloadFinder> CreateDownloadFinder(
const LastDownloadFinder::LastDownloadCallback& callback);
// Initiates an upload. Overridden by unit tests to provide a fake uploader.
virtual scoped_ptr<IncidentReportUploader> StartReportUpload(
const IncidentReportUploader::OnResultCallback& callback,
const scoped_refptr<net::URLRequestContextGetter>& 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<Profile*, ProfileContext*> 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<ClientIncidentReport_IncidentData> 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<ClientIncidentReport_EnvironmentData> 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<ClientIncidentReport_DownloadDetails> 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<ClientIncidentResponse> 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<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_;
// 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<IncidentReportingService> 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<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.
ProfileContextCollection profiles_;
// The collection of uploads in progress.
ScopedVector<UploadContext> uploads_;
// An object that asynchronously searches for the most recent binary download.
// Non-NULL while such a search is outstanding.
scoped_ptr<LastDownloadFinder> last_download_finder_;
// A factory for handing out weak pointers for AddIncident callbacks.
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_SERVICE_H_