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

Unified Diff: chrome/browser/safe_browsing/incident_reporting_service.cc

Issue 379563006: Merge 281089 "Include the latest binary download info in safe br..." (Closed) Base URL: svn://svn.chromium.org/chrome/branches/2062/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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/safe_browsing/incident_reporting_service.cc
===================================================================
--- chrome/browser/safe_browsing/incident_reporting_service.cc (revision 281829)
+++ chrome/browser/safe_browsing/incident_reporting_service.cc (working copy)
@@ -73,8 +73,8 @@
// The incidents collected for this profile pending creation and/or upload.
ScopedVector<ClientIncidentReport_IncidentData> incidents;
- // False until PROFILE_CREATED notification is received.
- bool created;
+ // False until PROFILE_ADDED notification is received.
+ bool added;
private:
DISALLOW_COPY_AND_ASSIGN(ProfileContext);
@@ -98,7 +98,7 @@
DISALLOW_COPY_AND_ASSIGN(UploadContext);
};
-IncidentReportingService::ProfileContext::ProfileContext() : created() {
+IncidentReportingService::ProfileContext::ProfileContext() : added() {
}
IncidentReportingService::ProfileContext::~ProfileContext() {
@@ -132,7 +132,7 @@
receiver_weak_ptr_factory_(this),
weak_ptr_factory_(this) {
notification_registrar_.Add(this,
- chrome::NOTIFICATION_PROFILE_CREATED,
+ chrome::NOTIFICATION_PROFILE_ADDED,
content::NotificationService::AllSources());
notification_registrar_.Add(this,
chrome::NOTIFICATION_PROFILE_DESTROYED,
@@ -146,6 +146,7 @@
weak_ptr_factory_.InvalidateWeakPtrs();
CancelEnvironmentCollection();
+ CancelDownloadCollection();
CancelAllReportUploads();
STLDeleteValues(&profiles_);
@@ -154,7 +155,7 @@
AddIncidentCallback IncidentReportingService::GetAddIncidentCallback(
Profile* profile) {
// Force the context to be created so that incidents added before
- // OnProfileCreated is called are held until the profile's preferences can be
+ // OnProfileAdded is called are held until the profile's preferences can be
// queried.
ignore_result(GetOrCreateProfileContext(profile));
@@ -188,13 +189,21 @@
}
}
-void IncidentReportingService::OnProfileCreated(Profile* profile) {
+void IncidentReportingService::OnProfileAdded(Profile* profile) {
DCHECK(thread_checker_.CalledOnValidThread());
+ // Track the addition of all profiles even when no report is being assembled
+ // so that the service can determine whether or not it can evaluate a
+ // profile's preferences at the time of incident addition.
ProfileContext* context = GetOrCreateProfileContext(profile);
- context->created = true;
+ context->added = true;
- // Drop all incidents if this profile is not participating in safe browsing.
+ // 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) {
@@ -202,19 +211,24 @@
}
context->incidents.clear();
}
+
+ // Take another stab at finding the most recent download if a report is being
+ // assembled and one hasn't been found yet (the LastDownloadFinder operates
+ // only on profiles that have been added to the ProfileManager).
+ BeginDownloadCollection();
}
+scoped_ptr<LastDownloadFinder> IncidentReportingService::CreateDownloadFinder(
+ const LastDownloadFinder::LastDownloadCallback& callback) {
+ return LastDownloadFinder::Create(callback).Pass();
+}
+
scoped_ptr<IncidentReportUploader> IncidentReportingService::StartReportUpload(
const IncidentReportUploader::OnResultCallback& callback,
const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
const ClientIncidentReport& report) {
-#if 0
return IncidentReportUploaderImpl::UploadReport(
callback, request_context_getter, report).Pass();
-#else
- // TODO(grt): Remove this temporary suppression of all uploads.
- return scoped_ptr<IncidentReportUploader>();
-#endif
}
IncidentReportingService::ProfileContext*
@@ -272,21 +286,23 @@
DCHECK(context);
// Drop the incident immediately if profile creation has completed and the
- // profile is not participating in safe browsing.
- if (context->created &&
+ // profile is not participating in safe browsing. Preference evaluation is
+ // deferred until OnProfileAdded() if profile creation has not yet
+ // completed.
+ if (context->added &&
!profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) {
LogIncidentDataType(DROPPED, *incident_data);
return;
}
- // Create a new report if this is the first incident ever or first since last
- // upload.
+ // Start assembling a new report if this is the first incident ever or the
+ // first since the last upload.
if (!report_) {
report_.reset(new ClientIncidentReport());
first_incident_time_ = base::Time::Now();
}
- // Provide time to the new incident if the caller didn't provide it.
+ // Provide time to the new incident if the caller didn't do so.
if (!incident_data->has_incident_time_msec())
incident_data->set_incident_time_msec(base::Time::Now().ToJavaTime());
@@ -306,11 +322,14 @@
upload_timer_.Reset();
BeginEnvironmentCollection();
+ BeginDownloadCollection();
}
void IncidentReportingService::BeginEnvironmentCollection() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(report_);
+ // Nothing to do if environment collection is pending or has already
+ // completed.
if (environment_collection_pending_ || report_->has_environment())
return;
@@ -330,6 +349,10 @@
DCHECK(environment_collection_pending_);
}
+bool IncidentReportingService::WaitingForEnvironmentCollection() {
+ return environment_collection_pending_;
+}
+
void IncidentReportingService::CancelEnvironmentCollection() {
environment_collection_begin_ = base::TimeTicks();
environment_collection_pending_ = false;
@@ -361,6 +384,10 @@
UploadIfCollectionComplete();
}
+bool IncidentReportingService::WaitingToCollateIncidents() {
+ return collection_timeout_pending_;
+}
+
void IncidentReportingService::CancelIncidentCollection() {
collection_timeout_pending_ = false;
last_incident_time_ = base::TimeTicks();
@@ -379,7 +406,7 @@
for (ProfileContextCollection::iterator scan = profiles_.begin();
scan != profiles_.end();
++scan) {
- if (!scan->second->created && !scan->second->incidents.empty()) {
+ if (!scan->second->added && !scan->second->incidents.empty()) {
upload_timer_.Reset();
return;
}
@@ -390,22 +417,91 @@
UploadIfCollectionComplete();
}
-void IncidentReportingService::CollectDownloadDetails(
- ClientIncidentReport_DownloadDetails* download_details) {
+void IncidentReportingService::BeginDownloadCollection() {
DCHECK(thread_checker_.CalledOnValidThread());
- // TODO(grt): collect download info; http://crbug.com/383042.
+ DCHECK(report_);
+ // Nothing to do if a search for the most recent download is already pending
+ // or if one has already been found.
+ if (last_download_finder_ || report_->has_download())
+ return;
+
+ last_download_begin_ = base::TimeTicks::Now();
+ last_download_finder_ = CreateDownloadFinder(
+ base::Bind(&IncidentReportingService::OnLastDownloadFound,
+ weak_ptr_factory_.GetWeakPtr()));
+ // No instance is returned if there are no eligible loaded profiles. Another
+ // search will be attempted in OnProfileAdded() if another profile appears on
+ // the scene.
+ if (!last_download_finder_)
+ last_download_begin_ = base::TimeTicks();
}
+bool IncidentReportingService::WaitingForMostRecentDownload() {
+ DCHECK(report_); // Only call this when a report is being assembled.
+ // The easy case: not waiting if a download has already been found.
+ if (report_->has_download())
+ return false;
+ // The next easy case: waiting if the finder is operating.
+ if (last_download_finder_)
+ return true;
+ // The harder case: waiting if a profile has not yet been added.
+ for (ProfileContextCollection::const_iterator scan = profiles_.begin();
+ scan != profiles_.end();
+ ++scan) {
+ if (!scan->second->added)
+ return true;
+ }
+ // There is no most recent download and there's nothing more to wait for.
+ return false;
+}
+
+void IncidentReportingService::CancelDownloadCollection() {
+ last_download_finder_.reset();
+ last_download_begin_ = base::TimeTicks();
+ if (report_)
+ report_->clear_download();
+}
+
+void IncidentReportingService::OnLastDownloadFound(
+ scoped_ptr<ClientIncidentReport_DownloadDetails> last_download) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(report_);
+
+ UMA_HISTOGRAM_TIMES("SBIRS.FindDownloadedBinaryTime",
+ base::TimeTicks::Now() - last_download_begin_);
+ last_download_begin_ = base::TimeTicks();
+
+ // Harvest the finder.
+ last_download_finder_.reset();
+
+ if (last_download)
+ report_->set_allocated_download(last_download.release());
+
+ UploadIfCollectionComplete();
+}
+
void IncidentReportingService::UploadIfCollectionComplete() {
DCHECK(report_);
- // Bail out if there are still outstanding collection tasks.
- if (environment_collection_pending_ || collection_timeout_pending_)
+ // Bail out if there are still outstanding collection tasks. Completion of any
+ // of these will start another upload attempt.
+ if (WaitingForEnvironmentCollection() ||
+ WaitingToCollateIncidents() ||
+ WaitingForMostRecentDownload()) {
return;
+ }
// Take ownership of the report and clear things for future reports.
scoped_ptr<ClientIncidentReport> report(report_.Pass());
last_incident_time_ = base::TimeTicks();
+ // Drop the report if no executable download was found.
+ if (!report->has_download()) {
+ UMA_HISTOGRAM_ENUMERATION("SBIRS.UploadResult",
+ IncidentReportUploader::UPLOAD_NO_DOWNLOAD,
+ IncidentReportUploader::NUM_UPLOAD_RESULTS);
+ return;
+ }
+
ClientIncidentReport_EnvironmentData_Process* process =
report->mutable_environment()->mutable_process();
@@ -566,10 +662,10 @@
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
- case chrome::NOTIFICATION_PROFILE_CREATED: {
+ case chrome::NOTIFICATION_PROFILE_ADDED: {
Profile* profile = content::Source<Profile>(source).ptr();
if (!profile->IsOffTheRecord())
- OnProfileCreated(profile);
+ OnProfileAdded(profile);
break;
}
case chrome::NOTIFICATION_PROFILE_DESTROYED: {

Powered by Google App Engine
This is Rietveld 408576698