Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(259)

Side by Side Diff: chrome/browser/safe_browsing/incident_reporting_service.cc

Issue 441453002: Support for process-wide incidents in the safe browsing incident reporting service. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: impl Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/safe_browsing/incident_reporting_service.h" 5 #include "chrome/browser/safe_browsing/incident_reporting_service.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/prefs/pref_service.h" 13 #include "base/prefs/pref_service.h"
14 #include "base/prefs/scoped_user_pref_update.h" 14 #include "base/prefs/scoped_user_pref_update.h"
15 #include "base/process/process_info.h" 15 #include "base/process/process_info.h"
16 #include "base/single_thread_task_runner.h"
16 #include "base/stl_util.h" 17 #include "base/stl_util.h"
17 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "base/thread_task_runner_handle.h"
18 #include "base/threading/sequenced_worker_pool.h" 20 #include "base/threading/sequenced_worker_pool.h"
19 #include "base/values.h" 21 #include "base/values.h"
20 #include "chrome/browser/browser_process.h" 22 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/chrome_notification_types.h" 23 #include "chrome/browser/chrome_notification_types.h"
22 #include "chrome/browser/prefs/tracked/tracked_preference_validation_delegate.h" 24 #include "chrome/browser/prefs/tracked/tracked_preference_validation_delegate.h"
23 #include "chrome/browser/profiles/profile.h" 25 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/safe_browsing/database_manager.h" 26 #include "chrome/browser/safe_browsing/database_manager.h"
25 #include "chrome/browser/safe_browsing/environment_data_collection.h" 27 #include "chrome/browser/safe_browsing/environment_data_collection.h"
26 #include "chrome/browser/safe_browsing/incident_report_uploader_impl.h" 28 #include "chrome/browser/safe_browsing/incident_report_uploader_impl.h"
27 #include "chrome/browser/safe_browsing/preference_validation_delegate.h" 29 #include "chrome/browser/safe_browsing/preference_validation_delegate.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 // The key for a specific instance of an incident. 65 // The key for a specific instance of an incident.
64 std::string key; 66 std::string key;
65 67
66 // A hash digest representing a specific instance of an incident. 68 // A hash digest representing a specific instance of an incident.
67 uint32_t digest; 69 uint32_t digest;
68 }; 70 };
69 71
70 // The amount of time the service will wait to collate incidents. 72 // The amount of time the service will wait to collate incidents.
71 const int64 kDefaultUploadDelayMs = 1000 * 60; // one minute 73 const int64 kDefaultUploadDelayMs = 1000 * 60; // one minute
72 74
75 // The amount of time between running delayed analysis callbacks.
76 const int64 kDefaultCallbackMs = 1000 * 20;
robertshield 2014/08/05 21:26:28 how about kDefaultCallbackIntervalMs ?
grt (UTC plus 2) 2014/08/06 02:37:31 Done.
77
73 // Returns the number of incidents contained in |incident|. The result is 78 // Returns the number of incidents contained in |incident|. The result is
74 // expected to be 1. Used in DCHECKs. 79 // expected to be 1. Used in DCHECKs.
75 size_t CountIncidents(const ClientIncidentReport_IncidentData& incident) { 80 size_t CountIncidents(const ClientIncidentReport_IncidentData& incident) {
76 size_t result = 0; 81 size_t result = 0;
77 if (incident.has_tracked_preference()) 82 if (incident.has_tracked_preference())
78 ++result; 83 ++result;
79 // Add detection for new incident types here. 84 // Add detection for new incident types here.
80 return result; 85 return result;
81 } 86 }
82 87
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 if (!incidents_sent->GetDictionaryWithoutPathExpansion(type_string, 155 if (!incidents_sent->GetDictionaryWithoutPathExpansion(type_string,
151 &type_dict)) { 156 &type_dict)) {
152 type_dict = new base::DictionaryValue(); 157 type_dict = new base::DictionaryValue();
153 incidents_sent->SetWithoutPathExpansion(type_string, type_dict); 158 incidents_sent->SetWithoutPathExpansion(type_string, type_dict);
154 } 159 }
155 type_dict->SetStringWithoutPathExpansion(data.key, 160 type_dict->SetStringWithoutPathExpansion(data.key,
156 base::UintToString(data.digest)); 161 base::UintToString(data.digest));
157 } 162 }
158 } 163 }
159 164
165 // Runs |callback| on the thread to which |thread_runner| belongs. The callback
166 // is run immediately if this function is called on |thread_runner|'s thread.
167 void AddIncidentOnOriginThread(
168 const AddIncidentCallback& callback,
169 scoped_refptr<base::SingleThreadTaskRunner> thread_runner,
170 scoped_ptr<ClientIncidentReport_IncidentData> incident) {
171 if (thread_runner->BelongsToCurrentThread())
172 callback.Run(incident.Pass());
173 else
174 thread_runner->PostTask(FROM_HERE,
175 base::Bind(callback, base::Passed(&incident)));
176 }
177
160 } // namespace 178 } // namespace
161 179
162 struct IncidentReportingService::ProfileContext { 180 struct IncidentReportingService::ProfileContext {
163 ProfileContext(); 181 ProfileContext();
164 ~ProfileContext(); 182 ~ProfileContext();
165 183
166 // The incidents collected for this profile pending creation and/or upload. 184 // The incidents collected for this profile pending creation and/or upload.
167 ScopedVector<ClientIncidentReport_IncidentData> incidents; 185 ScopedVector<ClientIncidentReport_IncidentData> incidents;
168 186
169 // False until PROFILE_ADDED notification is received. 187 // False until PROFILE_ADDED notification is received.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter) 231 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter)
214 : database_manager_(safe_browsing_service ? 232 : database_manager_(safe_browsing_service ?
215 safe_browsing_service->database_manager() : NULL), 233 safe_browsing_service->database_manager() : NULL),
216 url_request_context_getter_(request_context_getter), 234 url_request_context_getter_(request_context_getter),
217 collect_environment_data_fn_(&CollectEnvironmentData), 235 collect_environment_data_fn_(&CollectEnvironmentData),
218 environment_collection_task_runner_( 236 environment_collection_task_runner_(
219 content::BrowserThread::GetBlockingPool() 237 content::BrowserThread::GetBlockingPool()
220 ->GetTaskRunnerWithShutdownBehavior( 238 ->GetTaskRunnerWithShutdownBehavior(
221 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), 239 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)),
222 environment_collection_pending_(), 240 environment_collection_pending_(),
223 collection_timeout_pending_(), 241 collation_timeout_pending_(),
224 upload_timer_(FROM_HERE, 242 collation_timer_(FROM_HERE,
225 base::TimeDelta::FromMilliseconds(kDefaultUploadDelayMs), 243 base::TimeDelta::FromMilliseconds(kDefaultUploadDelayMs),
226 this, 244 this,
227 &IncidentReportingService::OnCollectionTimeout), 245 &IncidentReportingService::OnCollationTimeout),
246 delayed_analysis_callbacks_(
247 base::TimeDelta::FromMilliseconds(kDefaultCallbackMs),
248 content::BrowserThread::GetBlockingPool()),
228 receiver_weak_ptr_factory_(this), 249 receiver_weak_ptr_factory_(this),
229 weak_ptr_factory_(this) { 250 weak_ptr_factory_(this) {
230 notification_registrar_.Add(this, 251 notification_registrar_.Add(this,
231 chrome::NOTIFICATION_PROFILE_ADDED, 252 chrome::NOTIFICATION_PROFILE_ADDED,
232 content::NotificationService::AllSources()); 253 content::NotificationService::AllSources());
233 notification_registrar_.Add(this, 254 notification_registrar_.Add(this,
234 chrome::NOTIFICATION_PROFILE_DESTROYED, 255 chrome::NOTIFICATION_PROFILE_DESTROYED,
235 content::NotificationService::AllSources()); 256 content::NotificationService::AllSources());
236 } 257 }
237 258
(...skipping 25 matching lines...) Expand all
263 scoped_ptr<TrackedPreferenceValidationDelegate> 284 scoped_ptr<TrackedPreferenceValidationDelegate>
264 IncidentReportingService::CreatePreferenceValidationDelegate(Profile* profile) { 285 IncidentReportingService::CreatePreferenceValidationDelegate(Profile* profile) {
265 DCHECK(thread_checker_.CalledOnValidThread()); 286 DCHECK(thread_checker_.CalledOnValidThread());
266 287
267 if (profile->IsOffTheRecord()) 288 if (profile->IsOffTheRecord())
268 return scoped_ptr<TrackedPreferenceValidationDelegate>(); 289 return scoped_ptr<TrackedPreferenceValidationDelegate>();
269 return scoped_ptr<TrackedPreferenceValidationDelegate>( 290 return scoped_ptr<TrackedPreferenceValidationDelegate>(
270 new PreferenceValidationDelegate(GetAddIncidentCallback(profile))); 291 new PreferenceValidationDelegate(GetAddIncidentCallback(profile)));
271 } 292 }
272 293
294 void IncidentReportingService::RegisterDelayedAnalysisCallback(
295 const DelayedAnalysisCallback& callback) {
296 DCHECK(thread_checker_.CalledOnValidThread());
297
298 // |callback| will be run on the blocking pool, so it will likely run the
299 // AddIncidentCallback there as well. Bounce the run of that callback back to
300 // the main thread via AddIncidentOnOriginThread.
robertshield 2014/08/05 21:26:28 s/main/current ?
grt (UTC plus 2) 2014/08/06 02:37:31 Done.
301 delayed_analysis_callbacks_.RegisterCallback(
302 base::Bind(callback,
303 base::Bind(&AddIncidentOnOriginThread,
304 GetAddIncidentCallback(NULL),
305 base::ThreadTaskRunnerHandle::Get())));
306
307 // Start running the callbacks if any profiles are participating in safe
308 // browsing. If none are now, running will commence if/when a participaing
309 // profile is added.
310 if (FindEligibleProfile())
311 delayed_analysis_callbacks_.Start();
312 }
313
273 void IncidentReportingService::SetCollectEnvironmentHook( 314 void IncidentReportingService::SetCollectEnvironmentHook(
274 CollectEnvironmentDataFn collect_environment_data_hook, 315 CollectEnvironmentDataFn collect_environment_data_hook,
275 const scoped_refptr<base::TaskRunner>& task_runner) { 316 const scoped_refptr<base::TaskRunner>& task_runner) {
276 if (collect_environment_data_hook) { 317 if (collect_environment_data_hook) {
277 collect_environment_data_fn_ = collect_environment_data_hook; 318 collect_environment_data_fn_ = collect_environment_data_hook;
278 environment_collection_task_runner_ = task_runner; 319 environment_collection_task_runner_ = task_runner;
279 } else { 320 } else {
280 collect_environment_data_fn_ = &CollectEnvironmentData; 321 collect_environment_data_fn_ = &CollectEnvironmentData;
281 environment_collection_task_runner_ = 322 environment_collection_task_runner_ =
282 content::BrowserThread::GetBlockingPool() 323 content::BrowserThread::GetBlockingPool()
283 ->GetTaskRunnerWithShutdownBehavior( 324 ->GetTaskRunnerWithShutdownBehavior(
284 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 325 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
285 } 326 }
286 } 327 }
287 328
288 void IncidentReportingService::OnProfileAdded(Profile* profile) { 329 void IncidentReportingService::OnProfileAdded(Profile* profile) {
289 DCHECK(thread_checker_.CalledOnValidThread()); 330 DCHECK(thread_checker_.CalledOnValidThread());
290 331
291 // Track the addition of all profiles even when no report is being assembled 332 // Track the addition of all profiles even when no report is being assembled
292 // so that the service can determine whether or not it can evaluate a 333 // so that the service can determine whether or not it can evaluate a
293 // profile's preferences at the time of incident addition. 334 // profile's preferences at the time of incident addition.
294 ProfileContext* context = GetOrCreateProfileContext(profile); 335 ProfileContext* context = GetOrCreateProfileContext(profile);
295 context->added = true; 336 context->added = true;
296 337
338 const bool safe_browsing_enabled =
339 profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled);
340
341 // Start processing delayed analysis callbacks if this new profile
342 // participates in safe browsing.
robertshield 2014/08/05 21:26:28 Re-mention here how Start() is idempotent for repe
grt (UTC plus 2) 2014/08/06 02:37:31 Done.
343 if (safe_browsing_enabled)
344 delayed_analysis_callbacks_.Start();
345
346 // Start a new report if this profile participates in safe browsing and there
347 // are process-wide incidents.
348 if (safe_browsing_enabled && GetProfileContext(NULL))
349 BeginReportProcessing();
350
351 // TODO(grt): register for pref change notifications to start delayed analysis
352 // and/or report processing if sb is currently disabled but subsequently
353 // enabled.
354
297 // Nothing else to do if a report is not being assembled. 355 // Nothing else to do if a report is not being assembled.
298 if (!report_) 356 if (!report_)
299 return; 357 return;
300 358
301 // Drop all incidents received prior to creation if the profile is not 359 // Drop all incidents associated with this profile that were received prior to
302 // participating in safe browsing. 360 // its addition if the profile is not participating in safe browsing.
303 if (!context->incidents.empty() && 361 if (!context->incidents.empty() && !safe_browsing_enabled) {
304 !profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { 362 for (size_t i = 0; i < context->incidents.size(); ++i)
305 for (size_t i = 0; i < context->incidents.size(); ++i) {
306 LogIncidentDataType(DROPPED, *context->incidents[i]); 363 LogIncidentDataType(DROPPED, *context->incidents[i]);
307 }
308 context->incidents.clear(); 364 context->incidents.clear();
309 } 365 }
310 366
311 // Take another stab at finding the most recent download if a report is being 367 // Take another stab at finding the most recent download if a report is being
312 // assembled and one hasn't been found yet (the LastDownloadFinder operates 368 // assembled and one hasn't been found yet (the LastDownloadFinder operates
313 // only on profiles that have been added to the ProfileManager). 369 // only on profiles that have been added to the ProfileManager).
314 BeginDownloadCollection(); 370 BeginDownloadCollection();
315 } 371 }
316 372
317 scoped_ptr<LastDownloadFinder> IncidentReportingService::CreateDownloadFinder( 373 scoped_ptr<LastDownloadFinder> IncidentReportingService::CreateDownloadFinder(
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 // Forget about this profile. Incidents not yet sent for upload are lost. 411 // Forget about this profile. Incidents not yet sent for upload are lost.
356 // No new incidents will be accepted for it. 412 // No new incidents will be accepted for it.
357 delete it->second; 413 delete it->second;
358 profiles_.erase(it); 414 profiles_.erase(it);
359 415
360 // Remove the association with this profile from all pending uploads. 416 // Remove the association with this profile from all pending uploads.
361 for (size_t i = 0; i < uploads_.size(); ++i) 417 for (size_t i = 0; i < uploads_.size(); ++i)
362 uploads_[i]->profiles_to_state.erase(profile); 418 uploads_[i]->profiles_to_state.erase(profile);
363 } 419 }
364 420
421 Profile* IncidentReportingService::FindEligibleProfile() const {
422 Profile* candidate = NULL;
423 for (ProfileContextCollection::const_iterator scan = profiles_.begin();
424 scan != profiles_.end();
425 ++scan) {
426 // Skip over profiles that have yet to be added to the profile manager.
427 // This will also skip over the NULL-profile context used to hold
428 // process-wide incidents.
429 if (!scan->second->added)
430 continue;
431 PrefService* prefs = scan->first->GetPrefs();
432 if (prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled)) {
mattm 2014/08/06 02:10:17 Need to check prefs::kSafeBrowsingEnabled too (ext
grt (UTC plus 2) 2014/08/06 02:37:31 Done.
433 candidate = scan->first;
434 break;
435 }
436 if (!candidate && prefs->GetBoolean(prefs::kSafeBrowsingEnabled))
437 candidate = scan->first;
438 }
439 return candidate;
440 }
441
365 void IncidentReportingService::AddIncident( 442 void IncidentReportingService::AddIncident(
366 Profile* profile, 443 Profile* profile,
367 scoped_ptr<ClientIncidentReport_IncidentData> incident_data) { 444 scoped_ptr<ClientIncidentReport_IncidentData> incident_data) {
368 DCHECK(thread_checker_.CalledOnValidThread()); 445 DCHECK(thread_checker_.CalledOnValidThread());
369 // Incidents outside the context of a profile are not supported at the moment.
370 DCHECK(profile);
371 DCHECK_EQ(1U, CountIncidents(*incident_data)); 446 DCHECK_EQ(1U, CountIncidents(*incident_data));
372 447
373 ProfileContext* context = GetProfileContext(profile); 448 ProfileContext* context = GetProfileContext(profile);
374 // It is forbidden to call this function with a destroyed profile. 449 // It is forbidden to call this function with a destroyed profile.
375 DCHECK(context); 450 DCHECK(context);
451 // If this is a process-wide incident, the context must not indicate that the
452 // profile (which is NULL) has been added to the profile manager.
453 DCHECK(profile || !context->added);
376 454
377 // Drop the incident immediately if profile creation has completed and the 455 // Drop the incident immediately if the profile has already been added to the
378 // profile is not participating in safe browsing. Preference evaluation is 456 // manager and is not participating in safe browsing. Preference evaluation is
379 // deferred until OnProfileAdded() if profile creation has not yet 457 // deferred until OnProfileAdded() otherwise.
380 // completed.
381 if (context->added && 458 if (context->added &&
382 !profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { 459 !profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) {
383 LogIncidentDataType(DROPPED, *incident_data); 460 LogIncidentDataType(DROPPED, *incident_data);
384 return; 461 return;
385 } 462 }
386 463
387 // Start assembling a new report if this is the first incident ever or the
388 // first since the last upload.
389 if (!report_) {
390 report_.reset(new ClientIncidentReport());
391 first_incident_time_ = base::Time::Now();
392 }
393
394 // Provide time to the new incident if the caller didn't do so. 464 // Provide time to the new incident if the caller didn't do so.
395 if (!incident_data->has_incident_time_msec()) 465 if (!incident_data->has_incident_time_msec())
396 incident_data->set_incident_time_msec(base::Time::Now().ToJavaTime()); 466 incident_data->set_incident_time_msec(base::Time::Now().ToJavaTime());
397 467
398 // Take ownership of the incident. 468 // Take ownership of the incident.
399 context->incidents.push_back(incident_data.release()); 469 context->incidents.push_back(incident_data.release());
400 470
471 // Remember when the first incident for this report arrived.
472 if (first_incident_time_.is_null())
473 first_incident_time_ = base::Time::Now();
474 // Log the time between the previous incident and this one.
401 if (!last_incident_time_.is_null()) { 475 if (!last_incident_time_.is_null()) {
402 UMA_HISTOGRAM_TIMES("SBIRS.InterIncidentTime", 476 UMA_HISTOGRAM_TIMES("SBIRS.InterIncidentTime",
403 base::TimeTicks::Now() - last_incident_time_); 477 base::TimeTicks::Now() - last_incident_time_);
404 } 478 }
405 last_incident_time_ = base::TimeTicks::Now(); 479 last_incident_time_ = base::TimeTicks::Now();
406 480
407 // Persist the incident data. 481 // Persist the incident data.
408 482
409 // Restart the delay timer to send the report upon expiration. 483 // Start assembling a new report if this is the first incident ever or the
410 collection_timeout_pending_ = true; 484 // first since the last upload.
411 upload_timer_.Reset(); 485 BeginReportProcessing();
486 }
412 487
488 void IncidentReportingService::BeginReportProcessing() {
489 DCHECK(thread_checker_.CalledOnValidThread());
490
491 // Createa a new report if needed.
mattm 2014/08/06 02:10:17 Createa
grt (UTC plus 2) 2014/08/06 02:37:31 Done.
492 if (!report_)
493 report_.reset(new ClientIncidentReport());
494
495 // Ensure that collection tasks are running (calls are idempotent).
496 BeginIncidentCollation();
413 BeginEnvironmentCollection(); 497 BeginEnvironmentCollection();
414 BeginDownloadCollection(); 498 BeginDownloadCollection();
415 } 499 }
416 500
501 void IncidentReportingService::BeginIncidentCollation() {
502 // Restart the delay timer to send the report upon expiration.
503 collation_timeout_pending_ = true;
504 collation_timer_.Reset();
505 }
506
417 void IncidentReportingService::BeginEnvironmentCollection() { 507 void IncidentReportingService::BeginEnvironmentCollection() {
418 DCHECK(thread_checker_.CalledOnValidThread()); 508 DCHECK(thread_checker_.CalledOnValidThread());
419 DCHECK(report_); 509 DCHECK(report_);
420 // Nothing to do if environment collection is pending or has already 510 // Nothing to do if environment collection is pending or has already
421 // completed. 511 // completed.
422 if (environment_collection_pending_ || report_->has_environment()) 512 if (environment_collection_pending_ || report_->has_environment())
423 return; 513 return;
424 514
425 environment_collection_begin_ = base::TimeTicks::Now(); 515 environment_collection_begin_ = base::TimeTicks::Now();
426 ClientIncidentReport_EnvironmentData* environment_data = 516 ClientIncidentReport_EnvironmentData* environment_data =
(...skipping 28 matching lines...) Expand all
455 DCHECK(environment_collection_pending_); 545 DCHECK(environment_collection_pending_);
456 DCHECK(report_ && !report_->has_environment()); 546 DCHECK(report_ && !report_->has_environment());
457 environment_collection_pending_ = false; 547 environment_collection_pending_ = false;
458 548
459 // CurrentProcessInfo::CreationTime() is missing on some platforms. 549 // CurrentProcessInfo::CreationTime() is missing on some platforms.
460 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX) 550 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
461 base::TimeDelta uptime = 551 base::TimeDelta uptime =
462 first_incident_time_ - base::CurrentProcessInfo::CreationTime(); 552 first_incident_time_ - base::CurrentProcessInfo::CreationTime();
463 environment_data->mutable_process()->set_uptime_msec(uptime.InMilliseconds()); 553 environment_data->mutable_process()->set_uptime_msec(uptime.InMilliseconds());
464 #endif 554 #endif
465 first_incident_time_ = base::Time();
466 555
467 report_->set_allocated_environment(environment_data.release()); 556 report_->set_allocated_environment(environment_data.release());
468 557
469 UMA_HISTOGRAM_TIMES("SBIRS.EnvCollectionTime", 558 UMA_HISTOGRAM_TIMES("SBIRS.EnvCollectionTime",
470 base::TimeTicks::Now() - environment_collection_begin_); 559 base::TimeTicks::Now() - environment_collection_begin_);
471 environment_collection_begin_ = base::TimeTicks(); 560 environment_collection_begin_ = base::TimeTicks();
472 561
473 UploadIfCollectionComplete(); 562 UploadIfCollectionComplete();
474 } 563 }
475 564
476 bool IncidentReportingService::WaitingToCollateIncidents() { 565 bool IncidentReportingService::WaitingToCollateIncidents() {
477 return collection_timeout_pending_; 566 return collation_timeout_pending_;
478 } 567 }
479 568
480 void IncidentReportingService::CancelIncidentCollection() { 569 void IncidentReportingService::CancelIncidentCollection() {
481 collection_timeout_pending_ = false; 570 collation_timeout_pending_ = false;
482 last_incident_time_ = base::TimeTicks(); 571 last_incident_time_ = base::TimeTicks();
483 report_.reset(); 572 report_.reset();
484 } 573 }
485 574
486 void IncidentReportingService::OnCollectionTimeout() { 575 void IncidentReportingService::OnCollationTimeout() {
487 DCHECK(thread_checker_.CalledOnValidThread()); 576 DCHECK(thread_checker_.CalledOnValidThread());
488 577
489 // Exit early if collection was cancelled. 578 // Exit early if collection was cancelled.
490 if (!collection_timeout_pending_) 579 if (!collation_timeout_pending_)
491 return; 580 return;
492 581
493 // Wait another round if incidents have come in from a profile that has yet to 582 // Wait another round if profile-bound incidents have come in from a profile
494 // complete creation. 583 // that has yet to complete creation.
495 for (ProfileContextCollection::iterator scan = profiles_.begin(); 584 for (ProfileContextCollection::iterator scan = profiles_.begin();
496 scan != profiles_.end(); 585 scan != profiles_.end();
497 ++scan) { 586 ++scan) {
498 if (!scan->second->added && !scan->second->incidents.empty()) { 587 if (scan->first && !scan->second->added &&
499 upload_timer_.Reset(); 588 !scan->second->incidents.empty()) {
589 collation_timer_.Reset();
500 return; 590 return;
501 } 591 }
502 } 592 }
503 593
504 collection_timeout_pending_ = false; 594 collation_timeout_pending_ = false;
505 595
506 UploadIfCollectionComplete(); 596 UploadIfCollectionComplete();
507 } 597 }
508 598
509 void IncidentReportingService::BeginDownloadCollection() { 599 void IncidentReportingService::BeginDownloadCollection() {
510 DCHECK(thread_checker_.CalledOnValidThread()); 600 DCHECK(thread_checker_.CalledOnValidThread());
511 DCHECK(report_); 601 DCHECK(report_);
512 // Nothing to do if a search for the most recent download is already pending 602 // Nothing to do if a search for the most recent download is already pending
513 // or if one has already been found. 603 // or if one has already been found.
514 if (last_download_finder_ || report_->has_download()) 604 if (last_download_finder_ || report_->has_download())
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 // Bail out if there are still outstanding collection tasks. Completion of any 664 // Bail out if there are still outstanding collection tasks. Completion of any
575 // of these will start another upload attempt. 665 // of these will start another upload attempt.
576 if (WaitingForEnvironmentCollection() || 666 if (WaitingForEnvironmentCollection() ||
577 WaitingToCollateIncidents() || 667 WaitingToCollateIncidents() ||
578 WaitingForMostRecentDownload()) { 668 WaitingForMostRecentDownload()) {
579 return; 669 return;
580 } 670 }
581 671
582 // Take ownership of the report and clear things for future reports. 672 // Take ownership of the report and clear things for future reports.
583 scoped_ptr<ClientIncidentReport> report(report_.Pass()); 673 scoped_ptr<ClientIncidentReport> report(report_.Pass());
674 first_incident_time_ = base::Time();
584 last_incident_time_ = base::TimeTicks(); 675 last_incident_time_ = base::TimeTicks();
585 676
586 // Drop the report if no executable download was found. 677 // Drop the report if no executable download was found.
587 if (!report->has_download()) { 678 if (!report->has_download()) {
588 UMA_HISTOGRAM_ENUMERATION("SBIRS.UploadResult", 679 UMA_HISTOGRAM_ENUMERATION("SBIRS.UploadResult",
589 IncidentReportUploader::UPLOAD_NO_DOWNLOAD, 680 IncidentReportUploader::UPLOAD_NO_DOWNLOAD,
590 IncidentReportUploader::NUM_UPLOAD_RESULTS); 681 IncidentReportUploader::NUM_UPLOAD_RESULTS);
591 return; 682 return;
592 } 683 }
593 684
594 ClientIncidentReport_EnvironmentData_Process* process = 685 ClientIncidentReport_EnvironmentData_Process* process =
595 report->mutable_environment()->mutable_process(); 686 report->mutable_environment()->mutable_process();
596 687
597 // Not all platforms have a metrics reporting preference. 688 // Not all platforms have a metrics reporting preference.
598 if (g_browser_process->local_state()->FindPreference( 689 if (g_browser_process->local_state()->FindPreference(
599 prefs::kMetricsReportingEnabled)) { 690 prefs::kMetricsReportingEnabled)) {
600 process->set_metrics_consent(g_browser_process->local_state()->GetBoolean( 691 process->set_metrics_consent(g_browser_process->local_state()->GetBoolean(
601 prefs::kMetricsReportingEnabled)); 692 prefs::kMetricsReportingEnabled));
602 } 693 }
603 694
604 // Check for extended consent in any profile while collecting incidents. 695 // Find a profile suitable for tracking process-wide incidents.
605 process->set_extended_consent(false); 696 Profile* analyses_profile = FindEligibleProfile();
mattm 2014/08/06 02:10:17 is "analyses" intentional here? (vs analysis)
grt (UTC plus 2) 2014/08/06 02:37:31 Yeah, it's the profile used for the plural analyse
697 process->set_extended_consent(
698 analyses_profile ? analyses_profile->GetPrefs()->GetBoolean(
699 prefs::kSafeBrowsingExtendedReportingEnabled) :
700 false);
701
702 // Associate process-wide incidents with the analyses profile.
703 ProfileContext* null_context = GetProfileContext(NULL);
704 if (null_context && analyses_profile) {
705 DCHECK(!null_context->incidents.empty());
706 ProfileContext* analyses_context = GetProfileContext(analyses_profile);
707 // Move the incidents to the target context.
708 analyses_context->incidents.insert(analyses_context->incidents.end(),
709 null_context->incidents.begin(),
710 null_context->incidents.end());
711 null_context->incidents.weak_clear();
712 // Delete the process-wide context.
713 delete null_context;
714 profiles_.erase(NULL);
mattm 2014/08/06 02:10:17 Does this mean no more process-wide incidents can
grt (UTC plus 2) 2014/08/06 02:37:31 Nice catch. Any added after this should go into a
715 }
716
606 // Collect incidents across all profiles participating in safe browsing. Drop 717 // Collect incidents across all profiles participating in safe browsing. Drop
607 // incidents if the profile stopped participating before collection completed. 718 // incidents if the profile stopped participating before collection completed.
608 // Prune previously submitted incidents. 719 // Prune previously submitted incidents.
609 // Associate the profiles and their incident data with the upload. 720 // Associate the profiles and their incident data with the upload.
610 size_t prune_count = 0; 721 size_t prune_count = 0;
611 UploadContext::PersistentIncidentStateCollection profiles_to_state; 722 UploadContext::PersistentIncidentStateCollection profiles_to_state;
612 for (ProfileContextCollection::iterator scan = profiles_.begin(); 723 for (ProfileContextCollection::iterator scan = profiles_.begin();
613 scan != profiles_.end(); 724 scan != profiles_.end();
614 ++scan) { 725 ++scan) {
726 // Bypass process-wide incidents that have not yet been associated with a
727 // profile.
728 if (!scan->first)
729 continue;
615 PrefService* prefs = scan->first->GetPrefs(); 730 PrefService* prefs = scan->first->GetPrefs();
616 if (process &&
617 prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled)) {
618 process->set_extended_consent(true);
619 process = NULL; // Don't check any more once one is found.
620 }
621 ProfileContext* context = scan->second; 731 ProfileContext* context = scan->second;
622 if (context->incidents.empty()) 732 if (context->incidents.empty())
623 continue; 733 continue;
624 if (!prefs->GetBoolean(prefs::kSafeBrowsingEnabled)) { 734 if (!prefs->GetBoolean(prefs::kSafeBrowsingEnabled)) {
625 for (size_t i = 0; i < context->incidents.size(); ++i) { 735 for (size_t i = 0; i < context->incidents.size(); ++i) {
626 LogIncidentDataType(DROPPED, *context->incidents[i]); 736 LogIncidentDataType(DROPPED, *context->incidents[i]);
627 } 737 }
628 context->incidents.clear(); 738 context->incidents.clear();
629 continue; 739 continue;
630 } 740 }
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 if (!profile->IsOffTheRecord()) 903 if (!profile->IsOffTheRecord())
794 OnProfileDestroyed(profile); 904 OnProfileDestroyed(profile);
795 break; 905 break;
796 } 906 }
797 default: 907 default:
798 break; 908 break;
799 } 909 }
800 } 910 }
801 911
802 } // namespace safe_browsing 912 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698