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

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

Issue 411793004: More fine-grained pruning in safe browsing incident reporting service. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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/hash.h"
12 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
13 #include "base/prefs/pref_service.h" 14 #include "base/prefs/pref_service.h"
15 #include "base/prefs/scoped_user_pref_update.h"
14 #include "base/process/process_info.h" 16 #include "base/process/process_info.h"
15 #include "base/stl_util.h" 17 #include "base/stl_util.h"
18 #include "base/strings/string_number_conversions.h"
16 #include "base/threading/sequenced_worker_pool.h" 19 #include "base/threading/sequenced_worker_pool.h"
20 #include "base/values.h"
17 #include "chrome/browser/browser_process.h" 21 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/chrome_notification_types.h" 22 #include "chrome/browser/chrome_notification_types.h"
19 #include "chrome/browser/prefs/tracked/tracked_preference_validation_delegate.h" 23 #include "chrome/browser/prefs/tracked/tracked_preference_validation_delegate.h"
20 #include "chrome/browser/profiles/profile.h" 24 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/safe_browsing/database_manager.h" 25 #include "chrome/browser/safe_browsing/database_manager.h"
22 #include "chrome/browser/safe_browsing/environment_data_collection.h" 26 #include "chrome/browser/safe_browsing/environment_data_collection.h"
23 #include "chrome/browser/safe_browsing/incident_report_uploader_impl.h" 27 #include "chrome/browser/safe_browsing/incident_report_uploader_impl.h"
24 #include "chrome/browser/safe_browsing/preference_validation_delegate.h" 28 #include "chrome/browser/safe_browsing/preference_validation_delegate.h"
25 #include "chrome/browser/safe_browsing/safe_browsing_service.h" 29 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
26 #include "chrome/common/pref_names.h" 30 #include "chrome/common/pref_names.h"
(...skipping 11 matching lines...) Expand all
38 // the histogram. 42 // the histogram.
39 TRACKED_PREFERENCE = 1, 43 TRACKED_PREFERENCE = 1,
40 NUM_INCIDENT_TYPES 44 NUM_INCIDENT_TYPES
41 }; 45 };
42 46
43 enum IncidentDisposition { 47 enum IncidentDisposition {
44 DROPPED, 48 DROPPED,
45 ACCEPTED, 49 ACCEPTED,
46 }; 50 };
47 51
52 // The state persisted for a specific instance of an incident to enable pruning
53 // of previously-reported incidents.
54 struct PersistentIncidentState {
55 // The type of the incident.
56 IncidentType type;
57
58 // The key for a specific instance of an incident.
59 std::string key;
60
61 // A hash digest representing a specific instance of an incident.
62 uint32_t digest;
63 };
64
48 const int64 kDefaultUploadDelayMs = 1000 * 60; // one minute 65 const int64 kDefaultUploadDelayMs = 1000 * 60; // one minute
49 66
67 // Handlers for a specific type of incident.
68 struct IncidentTypeHandlers {
69 // The type of incident to which these handlers apply.
70 IncidentType type;
71
72 // A function that returns a unique key representing an incident.
73 std::string (*get_key_fn)(const ClientIncidentReport_IncidentData&);
74
75 // A function that returns a hash digest of an incident's data.
76 uint32_t (*get_digest_fn)(const ClientIncidentReport_IncidentData&);
77 };
78
79 // Forward declarations of incident type handler functions.
80 std::string GetTrackedPreferenceIncidentKey(
81 const ClientIncidentReport_IncidentData& incident_data);
82 uint32_t GetTrackedPreferenceIncidentDigest(
83 const ClientIncidentReport_IncidentData& incident_data);
84
85 // The collection of handlers for all incident types.
86 const IncidentTypeHandlers kIncidentTypeHandlers[] = {
87 {TRACKED_PREFERENCE,
88 &GetTrackedPreferenceIncidentKey,
89 &GetTrackedPreferenceIncidentDigest},
90 };
91
92 // Returns the type of incident contained in |incident_data|.
93 IncidentType GetIncidentType(
94 const ClientIncidentReport_IncidentData& incident_data) {
95 // Add logic once other types are supported.
96 DCHECK(incident_data.has_tracked_preference());
97
98 return TRACKED_PREFERENCE;
99 }
100
101 // Returns the handlers for a given type of incident.
102 const IncidentTypeHandlers* GetIncidentTypeHandlers(IncidentType type) {
103 for (size_t i = 0; i < arraysize(kIncidentTypeHandlers); ++i) {
104 if (kIncidentTypeHandlers[i].type == type)
105 return &kIncidentTypeHandlers[i];
106 }
107 NOTREACHED();
108 return NULL;
109 }
110
111 // Computes a simple hash digest over the serialized form of |message|.
112 uint32_t HashMessage(const google::protobuf::MessageLite& message) {
113 std::string message_string;
114 if (!message.SerializeToString(&message_string)) {
115 NOTREACHED();
116 return 0;
117 }
118 return base::Hash(message_string);
119 }
120
121 // Returns the path of the tracked preference.
122 std::string GetTrackedPreferenceIncidentKey(
123 const ClientIncidentReport_IncidentData& incident_data) {
124 DCHECK(incident_data.has_tracked_preference());
125 return incident_data.tracked_preference().path();
126 }
127
128 // Returns a digest computed over the tracked preference incident data.
129 uint32_t GetTrackedPreferenceIncidentDigest(
130 const ClientIncidentReport_IncidentData& incident_data) {
131 DCHECK(incident_data.has_tracked_preference());
132 return HashMessage(incident_data.tracked_preference());
133 }
134
135 // Logs the type of incident in |incident_data| to a user metrics histogram.
50 void LogIncidentDataType( 136 void LogIncidentDataType(
51 IncidentDisposition disposition, 137 IncidentDisposition disposition,
52 const ClientIncidentReport_IncidentData& incident_data) { 138 const ClientIncidentReport_IncidentData& incident_data) {
53 IncidentType type = TRACKED_PREFERENCE; 139 IncidentType type = GetIncidentType(incident_data);
54
55 // Add a switch statement once other types are supported.
56 DCHECK(incident_data.has_tracked_preference());
57
58 if (disposition == ACCEPTED) { 140 if (disposition == ACCEPTED) {
59 UMA_HISTOGRAM_ENUMERATION("SBIRS.Incident", type, NUM_INCIDENT_TYPES); 141 UMA_HISTOGRAM_ENUMERATION("SBIRS.Incident", type, NUM_INCIDENT_TYPES);
60 } else { 142 } else {
61 DCHECK_EQ(disposition, DROPPED); 143 DCHECK_EQ(disposition, DROPPED);
62 UMA_HISTOGRAM_ENUMERATION("SBIRS.DroppedIncident", type, 144 UMA_HISTOGRAM_ENUMERATION("SBIRS.DroppedIncident", type,
63 NUM_INCIDENT_TYPES); 145 NUM_INCIDENT_TYPES);
64 } 146 }
65 } 147 }
66 148
149 // Computes the persistent state for an incident.
150 PersistentIncidentState ComputeIncidentState(
151 const ClientIncidentReport_IncidentData& incident) {
152 PersistentIncidentState state;
153
154 state.type = GetIncidentType(incident);
155 const IncidentTypeHandlers* handlers = GetIncidentTypeHandlers(state.type);
156 state.key = handlers->get_key_fn(incident);
157 state.digest = handlers->get_digest_fn(incident);
158
159 return state;
160 }
161
162 // Returns true if the incident described by |state| has already been reported
163 // based on the bookkeeping in the |incidents_sent| preference dictionary.
164 bool IncidentHasBeenReported(const base::DictionaryValue* incidents_sent,
165 const PersistentIncidentState& state) {
166 const base::DictionaryValue* type_dict = NULL;
167 int digest = 0;
168 return (incidents_sent &&
169 incidents_sent->GetDictionaryWithoutPathExpansion(
170 base::IntToString(state.type), &type_dict) &&
171 type_dict->GetIntegerWithoutPathExpansion(state.key, &digest) &&
172 static_cast<uint32_t>(digest) == state.digest);
173 }
174
175 // Marks the incidents described by |states| as having been reported
176 // in |incidents_set|.
177 void MarkIncidentsAsReported(const std::vector<PersistentIncidentState>& states,
178 base::DictionaryValue* incidents_sent) {
179 for (size_t i = 0; i < states.size(); ++i) {
180 const PersistentIncidentState& data = states[i];
gab 2014/07/23 13:58:10 Use a std::vector::const_iterator rather than loop
grt (UTC plus 2) 2014/07/23 14:45:18 I used to do that, but had the indexing hammered i
181 base::DictionaryValue* type_dict = NULL;
182 std::string type_string(base::IntToString(data.type));
gab 2014/07/23 13:58:11 optional: const (I know you sometimes don't like
grt (UTC plus 2) 2014/07/23 14:45:18 Yeah, I'm not too excited about that, but okay. ;-
183 if (!incidents_sent->GetDictionaryWithoutPathExpansion(type_string,
184 &type_dict)) {
185 type_dict = new base::DictionaryValue();
186 incidents_sent->SetWithoutPathExpansion(type_string, type_dict);
187 }
188 type_dict->SetIntegerWithoutPathExpansion(data.key, data.digest);
gab 2014/07/23 13:58:10 In IncidentHasBeenReported() you explicitly cast f
grt (UTC plus 2) 2014/07/23 14:45:18 Good catch. I'm surprised the compiler didn't warn
189 }
190 }
191
67 } // namespace 192 } // namespace
68 193
69 struct IncidentReportingService::ProfileContext { 194 struct IncidentReportingService::ProfileContext {
70 ProfileContext(); 195 ProfileContext();
71 ~ProfileContext(); 196 ~ProfileContext();
72 197
73 // The incidents collected for this profile pending creation and/or upload. 198 // The incidents collected for this profile pending creation and/or upload.
74 ScopedVector<ClientIncidentReport_IncidentData> incidents; 199 ScopedVector<ClientIncidentReport_IncidentData> incidents;
75 200
76 // False until PROFILE_ADDED notification is received. 201 // False until PROFILE_ADDED notification is received.
77 bool added; 202 bool added;
78 203
79 private: 204 private:
80 DISALLOW_COPY_AND_ASSIGN(ProfileContext); 205 DISALLOW_COPY_AND_ASSIGN(ProfileContext);
81 }; 206 };
82 207
83 class IncidentReportingService::UploadContext { 208 class IncidentReportingService::UploadContext {
84 public: 209 public:
210 typedef std::map<Profile*, std::vector<PersistentIncidentState> >
211 PersistentIncidentStateCollection;
212
85 explicit UploadContext(scoped_ptr<ClientIncidentReport> report); 213 explicit UploadContext(scoped_ptr<ClientIncidentReport> report);
86 ~UploadContext(); 214 ~UploadContext();
87 215
88 // The report being uploaded. 216 // The report being uploaded.
89 scoped_ptr<ClientIncidentReport> report; 217 scoped_ptr<ClientIncidentReport> report;
90 218
91 // The uploader in use. This is NULL until the CSD killswitch is checked. 219 // The uploader in use. This is NULL until the CSD killswitch is checked.
92 scoped_ptr<IncidentReportUploader> uploader; 220 scoped_ptr<IncidentReportUploader> uploader;
93 221
94 // The set of profiles from which incidents in |report| originated. 222 // A mapping of profiles to the data to be persisted upon successful upload.
95 std::vector<Profile*> profiles; 223 PersistentIncidentStateCollection profiles_to_state;
96 224
97 private: 225 private:
98 DISALLOW_COPY_AND_ASSIGN(UploadContext); 226 DISALLOW_COPY_AND_ASSIGN(UploadContext);
99 }; 227 };
100 228
101 IncidentReportingService::ProfileContext::ProfileContext() : added() { 229 IncidentReportingService::ProfileContext::ProfileContext() : added() {
102 } 230 }
103 231
104 IncidentReportingService::ProfileContext::~ProfileContext() { 232 IncidentReportingService::ProfileContext::~ProfileContext() {
105 } 233 }
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 if (it == profiles_.end()) 382 if (it == profiles_.end())
255 return; 383 return;
256 384
257 // TODO(grt): Persist incidents for upload on future profile load. 385 // TODO(grt): Persist incidents for upload on future profile load.
258 386
259 // Forget about this profile. Incidents not yet sent for upload are lost. 387 // Forget about this profile. Incidents not yet sent for upload are lost.
260 // No new incidents will be accepted for it. 388 // No new incidents will be accepted for it.
261 delete it->second; 389 delete it->second;
262 profiles_.erase(it); 390 profiles_.erase(it);
263 391
264 // Remove the association with this profile from any pending uploads. 392 // Remove the association with this profile from all pending uploads.
265 for (size_t i = 0; i < uploads_.size(); ++i) { 393 for (size_t i = 0; i < uploads_.size(); ++i)
gab 2014/07/23 13:58:11 Use iterator?
266 UploadContext* upload = uploads_[i]; 394 uploads_[i]->profiles_to_state.erase(profile);
267 std::vector<Profile*>::iterator it =
268 std::find(upload->profiles.begin(), upload->profiles.end(), profile);
269 if (it != upload->profiles.end()) {
270 *it = upload->profiles.back();
271 upload->profiles.resize(upload->profiles.size() - 1);
272 break;
273 }
274 }
275 } 395 }
276 396
277 void IncidentReportingService::AddIncident( 397 void IncidentReportingService::AddIncident(
278 Profile* profile, 398 Profile* profile,
279 scoped_ptr<ClientIncidentReport_IncidentData> incident_data) { 399 scoped_ptr<ClientIncidentReport_IncidentData> incident_data) {
280 DCHECK(thread_checker_.CalledOnValidThread()); 400 DCHECK(thread_checker_.CalledOnValidThread());
281 // Incidents outside the context of a profile are not supported at the moment. 401 // Incidents outside the context of a profile are not supported at the moment.
282 DCHECK(profile); 402 DCHECK(profile);
283 403
284 ProfileContext* context = GetProfileContext(profile); 404 ProfileContext* context = GetProfileContext(profile);
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 if (g_browser_process->local_state()->FindPreference( 629 if (g_browser_process->local_state()->FindPreference(
510 prefs::kMetricsReportingEnabled)) { 630 prefs::kMetricsReportingEnabled)) {
511 process->set_metrics_consent(g_browser_process->local_state()->GetBoolean( 631 process->set_metrics_consent(g_browser_process->local_state()->GetBoolean(
512 prefs::kMetricsReportingEnabled)); 632 prefs::kMetricsReportingEnabled));
513 } 633 }
514 634
515 // Check for extended consent in any profile while collecting incidents. 635 // Check for extended consent in any profile while collecting incidents.
516 process->set_extended_consent(false); 636 process->set_extended_consent(false);
517 // Collect incidents across all profiles participating in safe browsing. Drop 637 // Collect incidents across all profiles participating in safe browsing. Drop
518 // incidents if the profile stopped participating before collection completed. 638 // incidents if the profile stopped participating before collection completed.
519 // Prune incidents if the profile has already submitted any incidents. 639 // Prune previously submitted incidents.
520 // Associate the participating profiles with the upload. 640 // Associate the profiles and their incident data with the upload.
521 size_t prune_count = 0; 641 size_t prune_count = 0;
522 std::vector<Profile*> profiles; 642 std::map<Profile*, std::vector<PersistentIncidentState> > profiles_to_state;
523 for (ProfileContextCollection::iterator scan = profiles_.begin(); 643 for (ProfileContextCollection::iterator scan = profiles_.begin();
524 scan != profiles_.end(); 644 scan != profiles_.end();
525 ++scan) { 645 ++scan) {
526 PrefService* prefs = scan->first->GetPrefs(); 646 PrefService* prefs = scan->first->GetPrefs();
527 if (process && 647 if (process &&
528 prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled)) { 648 prefs->GetBoolean(prefs::kSafeBrowsingExtendedReportingEnabled)) {
529 process->set_extended_consent(true); 649 process->set_extended_consent(true);
530 process = NULL; // Don't check any more once one is found. 650 process = NULL; // Don't check any more once one is found.
531 } 651 }
532 ProfileContext* context = scan->second; 652 ProfileContext* context = scan->second;
533 if (context->incidents.empty()) 653 if (context->incidents.empty())
534 continue; 654 continue;
535 if (!prefs->GetBoolean(prefs::kSafeBrowsingEnabled)) { 655 if (!prefs->GetBoolean(prefs::kSafeBrowsingEnabled)) {
536 for (size_t i = 0; i < context->incidents.size(); ++i) { 656 for (size_t i = 0; i < context->incidents.size(); ++i) {
537 LogIncidentDataType(DROPPED, *context->incidents[i]); 657 LogIncidentDataType(DROPPED, *context->incidents[i]);
538 } 658 }
539 context->incidents.clear(); 659 context->incidents.clear();
540 } else if (prefs->GetBoolean(prefs::kSafeBrowsingIncidentReportSent)) { 660 continue;
541 // Prune all incidents. 661 }
542 // TODO(grt): Only prune previously submitted incidents; 662 std::vector<PersistentIncidentState> states;
543 // http://crbug.com/383043. 663 const base::DictionaryValue* incidents_sent =
544 prune_count += context->incidents.size(); 664 prefs->GetDictionary(prefs::kSafeBrowsingIncidentsSent);
665 // Prep persistent data and prune any incidents already sent.
666 for (size_t i = 0; i < context->incidents.size(); ++i) {
gab 2014/07/23 13:58:10 Iterator?
667 ClientIncidentReport_IncidentData* incident = context->incidents[i];
668 PersistentIncidentState state = ComputeIncidentState(*incident);
gab 2014/07/23 13:58:11 const
grt (UTC plus 2) 2014/07/23 14:45:18 Done.
669 if (IncidentHasBeenReported(incidents_sent, state)) {
670 ++prune_count;
671 delete context->incidents[i];
672 context->incidents[i] = NULL;
673 } else {
674 states.push_back(state);
675 }
676 }
677 if (prefs->GetBoolean(prefs::kSafeBrowsingIncidentReportSent)) {
678 // Prune all incidents as if they had been reported, migrating to the new
679 // technique. TODO(grt): remove this branch after it has shipped.
680 for (size_t i = 0; i < context->incidents.size(); ++i) {
681 if (context->incidents[i])
682 ++prune_count;
683 }
545 context->incidents.clear(); 684 context->incidents.clear();
685 prefs->ClearPref(prefs::kSafeBrowsingIncidentReportSent);
686 DictionaryPrefUpdate pref_update(prefs,
687 prefs::kSafeBrowsingIncidentsSent);
688 MarkIncidentsAsReported(states, pref_update.Get());
546 } else { 689 } else {
547 for (size_t i = 0; i < context->incidents.size(); ++i) { 690 for (size_t i = 0; i < context->incidents.size(); ++i) {
548 ClientIncidentReport_IncidentData* incident = context->incidents[i]; 691 ClientIncidentReport_IncidentData* incident = context->incidents[i];
549 LogIncidentDataType(ACCEPTED, *incident); 692 if (incident) {
550 // Ownership of the incident is passed to the report. 693 LogIncidentDataType(ACCEPTED, *incident);
551 report->mutable_incident()->AddAllocated(incident); 694 // Ownership of the incident is passed to the report.
695 report->mutable_incident()->AddAllocated(incident);
696 }
552 } 697 }
553 context->incidents.weak_clear(); 698 context->incidents.weak_clear();
554 profiles.push_back(scan->first); 699 std::vector<PersistentIncidentState>& profile_states =
700 profiles_to_state[scan->first];
701 profile_states.swap(states);
555 } 702 }
556 } 703 }
557 704
558 const int count = report->incident_size(); 705 const int count = report->incident_size();
559 // Abandon the request if all incidents were dropped with none pruned. 706 // Abandon the request if all incidents were dropped with none pruned.
560 if (!count && !prune_count) 707 if (!count && !prune_count)
561 return; 708 return;
562 709
563 UMA_HISTOGRAM_COUNTS_100("SBIRS.IncidentCount", count + prune_count); 710 UMA_HISTOGRAM_COUNTS_100("SBIRS.IncidentCount", count + prune_count);
564 711
565 { 712 {
566 double prune_pct = static_cast<double>(prune_count); 713 double prune_pct = static_cast<double>(prune_count);
567 prune_pct = prune_pct * 100.0 / (count + prune_count); 714 prune_pct = prune_pct * 100.0 / (count + prune_count);
568 prune_pct = round(prune_pct); 715 prune_pct = round(prune_pct);
569 UMA_HISTOGRAM_PERCENTAGE("SBIRS.PruneRatio", static_cast<int>(prune_pct)); 716 UMA_HISTOGRAM_PERCENTAGE("SBIRS.PruneRatio", static_cast<int>(prune_pct));
570 } 717 }
571 // Abandon the report if all incidents were pruned. 718 // Abandon the report if all incidents were pruned.
572 if (!count) 719 if (!count)
573 return; 720 return;
574 721
575 scoped_ptr<UploadContext> context(new UploadContext(report.Pass())); 722 scoped_ptr<UploadContext> context(new UploadContext(report.Pass()));
576 context->profiles.swap(profiles); 723 context->profiles_to_state.swap(profiles_to_state);
577 if (!database_manager_) { 724 if (!database_manager_) {
578 // No database manager during testing. Take ownership of the context and 725 // No database manager during testing. Take ownership of the context and
579 // continue processing. 726 // continue processing.
580 UploadContext* temp_context = context.get(); 727 UploadContext* temp_context = context.get();
581 uploads_.push_back(context.release()); 728 uploads_.push_back(context.release());
582 IncidentReportingService::OnKillSwitchResult(temp_context, false); 729 IncidentReportingService::OnKillSwitchResult(temp_context, false);
583 } else { 730 } else {
584 if (content::BrowserThread::PostTaskAndReplyWithResult( 731 if (content::BrowserThread::PostTaskAndReplyWithResult(
585 content::BrowserThread::IO, 732 content::BrowserThread::IO,
586 FROM_HERE, 733 FROM_HERE,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 scoped_ptr<ClientIncidentResponse>()); 768 scoped_ptr<ClientIncidentResponse>());
622 } 769 }
623 } else { 770 } else {
624 OnReportUploadResult(context, 771 OnReportUploadResult(context,
625 IncidentReportUploader::UPLOAD_SUPPRESSED, 772 IncidentReportUploader::UPLOAD_SUPPRESSED,
626 scoped_ptr<ClientIncidentResponse>()); 773 scoped_ptr<ClientIncidentResponse>());
627 } 774 }
628 } 775 }
629 776
630 void IncidentReportingService::HandleResponse(const UploadContext& context) { 777 void IncidentReportingService::HandleResponse(const UploadContext& context) {
631 for (size_t i = 0; i < context.profiles.size(); ++i) { 778 for (UploadContext::PersistentIncidentStateCollection::const_iterator scan =
632 context.profiles[i]->GetPrefs()->SetBoolean( 779 context.profiles_to_state.begin();
633 prefs::kSafeBrowsingIncidentReportSent, true); 780 scan != context.profiles_to_state.end();
781 ++scan) {
782 DictionaryPrefUpdate pref_update(scan->first->GetPrefs(),
783 prefs::kSafeBrowsingIncidentsSent);
784 MarkIncidentsAsReported(scan->second, pref_update.Get());
634 } 785 }
635 } 786 }
636 787
637 void IncidentReportingService::OnReportUploadResult( 788 void IncidentReportingService::OnReportUploadResult(
638 UploadContext* context, 789 UploadContext* context,
639 IncidentReportUploader::Result result, 790 IncidentReportUploader::Result result,
640 scoped_ptr<ClientIncidentResponse> response) { 791 scoped_ptr<ClientIncidentResponse> response) {
641 DCHECK(thread_checker_.CalledOnValidThread()); 792 DCHECK(thread_checker_.CalledOnValidThread());
642 793
643 UMA_HISTOGRAM_ENUMERATION( 794 UMA_HISTOGRAM_ENUMERATION(
(...skipping 29 matching lines...) Expand all
673 if (!profile->IsOffTheRecord()) 824 if (!profile->IsOffTheRecord())
674 OnProfileDestroyed(profile); 825 OnProfileDestroyed(profile);
675 break; 826 break;
676 } 827 }
677 default: 828 default:
678 break; 829 break;
679 } 830 }
680 } 831 }
681 832
682 } // namespace safe_browsing 833 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698