| Index: chrome/browser/safe_browsing/incident_reporting_service.cc
|
| diff --git a/chrome/browser/safe_browsing/incident_reporting_service.cc b/chrome/browser/safe_browsing/incident_reporting_service.cc
|
| index 6c8ce1b9f562fb94fc295ca70e1b3993c8c8d856..ccb2bc3a66b5f25c93db8b0cd3e8d2f3a7aa0d8e 100644
|
| --- a/chrome/browser/safe_browsing/incident_reporting_service.cc
|
| +++ b/chrome/browser/safe_browsing/incident_reporting_service.cc
|
| @@ -70,6 +70,9 @@ struct PersistentIncidentState {
|
| // The amount of time the service will wait to collate incidents.
|
| const int64 kDefaultUploadDelayMs = 1000 * 60; // one minute
|
|
|
| +// The amount of time between running delayed analysis callbacks.
|
| +const int64 kDefaultCallbackMs = 1000 * 20;
|
| +
|
| // Returns the number of incidents contained in |incident|. The result is
|
| // expected to be 1. Used in DCHECKs.
|
| size_t CountIncidents(const ClientIncidentReport_IncidentData& incident) {
|
| @@ -225,6 +228,9 @@ IncidentReportingService::IncidentReportingService(
|
| base::TimeDelta::FromMilliseconds(kDefaultUploadDelayMs),
|
| this,
|
| &IncidentReportingService::OnCollectionTimeout),
|
| + delayed_analysis_callbacks_(
|
| + base::TimeDelta::FromMilliseconds(kDefaultCallbackMs),
|
| + content::BrowserThread::GetBlockingPool()),
|
| receiver_weak_ptr_factory_(this),
|
| weak_ptr_factory_(this) {
|
| notification_registrar_.Add(this,
|
| @@ -270,6 +276,17 @@ IncidentReportingService::CreatePreferenceValidationDelegate(Profile* profile) {
|
| new PreferenceValidationDelegate(GetAddIncidentCallback(profile)));
|
| }
|
|
|
| +void IncidentReportingService::RegisterDelayedAnalysisCallback(
|
| + const DelayedAnalysisCallback& callback) {
|
| + delayed_analysis_callbacks_.RegisterCallback(
|
| + base::Bind(callback, GetAddIncidentCallback(NULL)));
|
| +
|
| + // Start running the callbacks if any profiles are participating in safe
|
| + // browsing.
|
| + if (FindEligibleProfile())
|
| + delayed_analysis_callbacks_.Start();
|
| +}
|
| +
|
| void IncidentReportingService::SetCollectEnvironmentHook(
|
| CollectEnvironmentDataFn collect_environment_data_hook,
|
| const scoped_refptr<base::TaskRunner>& task_runner) {
|
| @@ -294,17 +311,23 @@ void IncidentReportingService::OnProfileAdded(Profile* profile) {
|
| ProfileContext* context = GetOrCreateProfileContext(profile);
|
| context->added = true;
|
|
|
| + const bool safe_browsing_enabled =
|
| + profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled);
|
| +
|
| + // Start processing delayed analysis callbacks if this new profile
|
| + // participates in safe browsing.
|
| + if (safe_browsing_enabled)
|
| + delayed_analysis_callbacks_.Start();
|
| +
|
| // Nothing else to do if a report is not being assembled.
|
| if (!report_)
|
| return;
|
|
|
| - // Drop all incidents received prior to creation if the profile is not
|
| - // participating in safe browsing.
|
| - if (!context->incidents.empty() &&
|
| - !profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) {
|
| - for (size_t i = 0; i < context->incidents.size(); ++i) {
|
| + // Drop all incidents associated with this profile that were received prior to
|
| + // its addition if the profile is not participating in safe browsing.
|
| + if (!context->incidents.empty() && !safe_browsing_enabled) {
|
| + for (size_t i = 0; i < context->incidents.size(); ++i)
|
| LogIncidentDataType(DROPPED, *context->incidents[i]);
|
| - }
|
| context->incidents.clear();
|
| }
|
|
|
| @@ -362,17 +385,39 @@ void IncidentReportingService::OnProfileDestroyed(Profile* profile) {
|
| uploads_[i]->profiles_to_state.erase(profile);
|
| }
|
|
|
| +Profile* IncidentReportingService::FindEligibleProfile() const {
|
| + Profile* candidate = NULL;
|
| + for (ProfileContextCollection::const_iterator scan = profiles_.begin();
|
| + scan != profiles_.end();
|
| + ++scan) {
|
| + // Skip over profiles that have yet to be added to the profile manager.
|
| + // This will also skip over the NULL-profile context used to hold
|
| + // process-wide incidents.
|
| + if (!scan->second->added)
|
| + continue;
|
| + PrefService* prefs = scan->first->GetPrefs();
|
| + if (prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled)) {
|
| + candidate = scan->first;
|
| + break;
|
| + }
|
| + if (!candidate && prefs->GetBoolean(prefs::kSafeBrowsingEnabled))
|
| + candidate = scan->first;
|
| + }
|
| + return candidate;
|
| +}
|
| +
|
| void IncidentReportingService::AddIncident(
|
| Profile* profile,
|
| scoped_ptr<ClientIncidentReport_IncidentData> incident_data) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| - // Incidents outside the context of a profile are not supported at the moment.
|
| - DCHECK(profile);
|
| DCHECK_EQ(1U, CountIncidents(*incident_data));
|
|
|
| ProfileContext* context = GetProfileContext(profile);
|
| // It is forbidden to call this function with a destroyed profile.
|
| DCHECK(context);
|
| + // If this is a process-wide incident, the context must not indicate that the
|
| + // profile (which is NULL) has been added to the profile manager.
|
| + DCHECK(profile || !context->added);
|
|
|
| // Drop the incident immediately if profile creation has completed and the
|
| // profile is not participating in safe browsing. Preference evaluation is
|
| @@ -490,12 +535,13 @@ void IncidentReportingService::OnCollectionTimeout() {
|
| if (!collection_timeout_pending_)
|
| return;
|
|
|
| - // Wait another round if incidents have come in from a profile that has yet to
|
| - // complete creation.
|
| + // Wait another round if profile-bound incidents have come in from a profile
|
| + // that has yet to complete creation.
|
| for (ProfileContextCollection::iterator scan = profiles_.begin();
|
| scan != profiles_.end();
|
| ++scan) {
|
| - if (!scan->second->added && !scan->second->incidents.empty()) {
|
| + if (scan->first && !scan->second->added &&
|
| + !scan->second->incidents.empty()) {
|
| upload_timer_.Reset();
|
| return;
|
| }
|
| @@ -601,8 +647,28 @@ void IncidentReportingService::UploadIfCollectionComplete() {
|
| prefs::kMetricsReportingEnabled));
|
| }
|
|
|
| - // Check for extended consent in any profile while collecting incidents.
|
| - process->set_extended_consent(false);
|
| + // Find a profile suitable for tracking process-wide incidents.
|
| + Profile* analyses_profile = FindEligibleProfile();
|
| + process->set_extended_consent(
|
| + analyses_profile ? analyses_profile->GetPrefs()->GetBoolean(
|
| + prefs::kSafeBrowsingExtendedReportingEnabled) :
|
| + false);
|
| +
|
| + // Associate process-wide incidents with the analyses profile.
|
| + ProfileContext* null_context = GetProfileContext(NULL);
|
| + if (null_context && analyses_profile) {
|
| + DCHECK(!null_context->incidents.empty());
|
| + ProfileContext* analyses_context = GetProfileContext(analyses_profile);
|
| + // Move the incidents to the target context.
|
| + analyses_context->incidents.insert(analyses_context->incidents.end(),
|
| + null_context->incidents.begin(),
|
| + null_context->incidents.end());
|
| + null_context->incidents.weak_clear();
|
| + // Delete the process-wide context.
|
| + delete null_context;
|
| + profiles_.erase(NULL);
|
| + }
|
| +
|
| // Collect incidents across all profiles participating in safe browsing. Drop
|
| // incidents if the profile stopped participating before collection completed.
|
| // Prune previously submitted incidents.
|
| @@ -612,12 +678,11 @@ void IncidentReportingService::UploadIfCollectionComplete() {
|
| for (ProfileContextCollection::iterator scan = profiles_.begin();
|
| scan != profiles_.end();
|
| ++scan) {
|
| + // Bypass process-wide incidents that have not yet been associated with a
|
| + // profile.
|
| + if (!scan->first)
|
| + continue;
|
| PrefService* prefs = scan->first->GetPrefs();
|
| - if (process &&
|
| - prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled)) {
|
| - process->set_extended_consent(true);
|
| - process = NULL; // Don't check any more once one is found.
|
| - }
|
| ProfileContext* context = scan->second;
|
| if (context->incidents.empty())
|
| continue;
|
|
|