Chromium Code Reviews| Index: chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc |
| diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc |
| index f5bafc5eee4fcd780873baaa5c2bcdadf1ca0065..8c5c80d6e3e0bd407f1e437caa1474e27a5770dd 100644 |
| --- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc |
| +++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc |
| @@ -26,6 +26,7 @@ |
| #include "chrome/browser/safe_browsing/database_manager.h" |
| #include "chrome/browser/safe_browsing/incident_reporting/environment_data_collection.h" |
| #include "chrome/browser/safe_browsing/incident_reporting/incident.h" |
| +#include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h" |
| #include "chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl.h" |
| #include "chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate.h" |
| #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
| @@ -166,19 +167,6 @@ void CleanLegacyPruneState(Profile* profile) { |
| pref_update.Get()->RemoveWithoutPathExpansion(incident_type, NULL); |
| } |
| -// Runs |callback| on the thread to which |thread_runner| belongs. The callback |
| -// is run immediately if this function is called on |thread_runner|'s thread. |
| -void AddIncidentOnOriginThread( |
| - const AddIncidentCallback& callback, |
| - scoped_refptr<base::SingleThreadTaskRunner> thread_runner, |
| - scoped_ptr<Incident> incident) { |
| - if (thread_runner->BelongsToCurrentThread()) |
| - callback.Run(incident.Pass()); |
| - else |
| - thread_runner->PostTask(FROM_HERE, |
| - base::Bind(callback, base::Passed(&incident))); |
| -} |
| - |
| } // namespace |
| struct IncidentReportingService::ProfileContext { |
| @@ -217,6 +205,70 @@ class IncidentReportingService::UploadContext { |
| DISALLOW_COPY_AND_ASSIGN(UploadContext); |
| }; |
| +// An IncidentReceiver that is weakly-bound to the service and transparently |
| +// bounces process-wide incidents back to the main thread for handling. |
| +class IncidentReportingService::Receiver : public IncidentReceiver { |
| + public: |
| + explicit Receiver(const base::WeakPtr<IncidentReportingService>& service); |
| + ~Receiver() override; |
| + |
| + // IncidentReceiver methods: |
| + void AddIncidentForProfile(Profile* profile, |
| + scoped_ptr<Incident> incident) override; |
| + void AddIncidentForProcess(scoped_ptr<Incident> incident) override; |
| + |
| + private: |
| + static void AddIncidentOnUIThread( |
| + const base::WeakPtr<IncidentReportingService>& service, |
| + Profile* profile, |
| + scoped_ptr<Incident> incident); |
| + |
| + base::WeakPtr<IncidentReportingService> service_; |
| + scoped_refptr<base::SingleThreadTaskRunner> thread_runner_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Receiver); |
| +}; |
| + |
| +IncidentReportingService::Receiver::Receiver( |
| + const base::WeakPtr<IncidentReportingService>& service) |
| + : service_(service), |
| + thread_runner_(base::ThreadTaskRunnerHandle::Get()) { |
| +} |
| + |
| +IncidentReportingService::Receiver::~Receiver() { |
| +} |
| + |
| +void IncidentReportingService::Receiver::AddIncidentForProfile( |
| + Profile* profile, |
| + scoped_ptr<Incident> incident) { |
| + DCHECK(thread_runner_->BelongsToCurrentThread()); |
|
robertshield
2015/02/03 02:54:42
For my own education: this DCHECK in practice chec
grt (UTC plus 2)
2015/02/03 03:27:59
I wish I didn't have to use BrowserThread anywhere
|
| + DCHECK(profile); |
| + AddIncidentOnUIThread(service_, profile, incident.Pass()); |
| +} |
| + |
| +void IncidentReportingService::Receiver::AddIncidentForProcess( |
| + scoped_ptr<Incident> incident) { |
| + if (thread_runner_->BelongsToCurrentThread()) { |
| + AddIncidentOnUIThread(service_, nullptr, incident.Pass()); |
| + } else if (!thread_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&IncidentReportingService::Receiver::AddIncidentOnUIThread, |
| + service_, nullptr, base::Passed(&incident)))) { |
| + LogIncidentDataType(DISCARDED, *incident); |
| + } |
| +} |
| + |
| +// static |
| +void IncidentReportingService::Receiver::AddIncidentOnUIThread( |
| + const base::WeakPtr<IncidentReportingService>& service, |
| + Profile* profile, |
| + scoped_ptr<Incident> incident) { |
| + if (service) |
| + service->AddIncident(profile, incident.Pass()); |
| + else |
| + LogIncidentDataType(DISCARDED, *incident); |
| +} |
| + |
| IncidentReportingService::ProfileContext::ProfileContext() : added() { |
| } |
| @@ -293,16 +345,8 @@ IncidentReportingService::~IncidentReportingService() { |
| STLDeleteValues(&profiles_); |
| } |
| -AddIncidentCallback IncidentReportingService::GetAddIncidentCallback( |
| - Profile* profile) { |
| - // Force the context to be created so that incidents added before |
| - // OnProfileAdded is called are held until the profile's preferences can be |
| - // queried. |
| - ignore_result(GetOrCreateProfileContext(profile)); |
| - |
| - return base::Bind(&IncidentReportingService::AddIncident, |
| - receiver_weak_ptr_factory_.GetWeakPtr(), |
| - profile); |
| +scoped_ptr<IncidentReceiver> IncidentReportingService::GetIncidentReceiver() { |
| + return make_scoped_ptr(new Receiver(receiver_weak_ptr_factory_.GetWeakPtr())); |
| } |
| scoped_ptr<TrackedPreferenceValidationDelegate> |
| @@ -312,21 +356,17 @@ IncidentReportingService::CreatePreferenceValidationDelegate(Profile* profile) { |
| if (profile->IsOffTheRecord()) |
| return scoped_ptr<TrackedPreferenceValidationDelegate>(); |
| return scoped_ptr<TrackedPreferenceValidationDelegate>( |
| - new PreferenceValidationDelegate(GetAddIncidentCallback(profile))); |
| + new PreferenceValidationDelegate(profile, GetIncidentReceiver())); |
| } |
| void IncidentReportingService::RegisterDelayedAnalysisCallback( |
| const DelayedAnalysisCallback& callback) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| - // |callback| will be run on the blocking pool, so it will likely run the |
| - // AddIncidentCallback there as well. Bounce the run of that callback back to |
| - // the current thread via AddIncidentOnOriginThread. |
| + // |callback| will be run on the blocking pool. The receiver will bounce back |
| + // to the origin thread if needed. |
| delayed_analysis_callbacks_.RegisterCallback( |
| - base::Bind(callback, |
| - base::Bind(&AddIncidentOnOriginThread, |
| - GetAddIncidentCallback(NULL), |
| - base::ThreadTaskRunnerHandle::Get()))); |
| + base::Bind(callback, base::Passed(GetIncidentReceiver()))); |
| // Start running the callbacks if any profiles are participating in safe |
| // browsing. If none are now, running will commence if/when a participaing |
| @@ -518,9 +558,11 @@ void IncidentReportingService::AddIncident(Profile* profile, |
| scoped_ptr<Incident> incident) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| - ProfileContext* context = GetProfileContext(profile); |
| - // It is forbidden to call this function with a destroyed profile. |
| - DCHECK(context); |
| + // Ignore incidents from off-the-record profiles. |
| + if (profile && profile->IsOffTheRecord()) |
| + return; |
| + |
| + ProfileContext* context = GetOrCreateProfileContext(profile); |
| // 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); |