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 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_INCIDENT_REPORTING_SERVICE_H_ 6 #define CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_INCIDENT_REPORTING_SERVICE_H_ 7 8 #include <stdint.h> 9 10 #include <map> 11 12 #include "base/compiler_specific.h" 13 #include "base/macros.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_vector.h" 17 #include "base/memory/weak_ptr.h" 18 #include "base/threading/thread_checker.h" 19 #include "base/time/time.h" 20 #include "base/timer/timer.h" 21 #include "chrome/browser/safe_browsing/incident_reporting/add_incident_callback.h" 22 #include "chrome/browser/safe_browsing/incident_reporting/delayed_analysis_callback.h" 23 #include "chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h" 24 #include "chrome/browser/safe_browsing/incident_reporting/incident_report_uploader.h" 25 #include "chrome/browser/safe_browsing/incident_reporting/last_download_finder.h" 26 #include "content/public/browser/notification_observer.h" 27 #include "content/public/browser/notification_registrar.h" 28 29 class Profile; 30 class SafeBrowsingDatabaseManager; 31 class SafeBrowsingService; 32 class TrackedPreferenceValidationDelegate; 33 34 namespace base { 35 class TaskRunner; 36 } 37 38 namespace content { 39 class NotificationDetails; 40 class NotificationSource; 41 } 42 43 namespace net { 44 class URLRequestContextGetter; 45 } 46 47 namespace safe_browsing { 48 49 class ClientIncidentReport; 50 class ClientIncidentReport_DownloadDetails; 51 class ClientIncidentReport_EnvironmentData; 52 class ClientIncidentReport_IncidentData; 53 54 // A class that manages the collection of incidents and submission of incident 55 // reports to the safe browsing client-side detection service. The service 56 // begins operation when an incident is reported via the AddIncident method. 57 // Incidents reported from a profile that is loading are held until the profile 58 // is fully created. Incidents originating from profiles that do not participate 59 // in safe browsing are dropped. Process-wide incidents are affiliated with a 60 // profile that participates in safe browsing when one becomes available. 61 // Following the addition of an incident that is not dropped, the service 62 // collects environmental data, finds the most recent binary download, and waits 63 // a bit. Additional incidents that arrive during this time are collated with 64 // the initial incident. Finally, already-reported incidents are pruned and any 65 // remaining are uploaded in an incident report. 66 class IncidentReportingService : public content::NotificationObserver { 67 public: 68 IncidentReportingService(SafeBrowsingService* safe_browsing_service, 69 const scoped_refptr<net::URLRequestContextGetter>& 70 request_context_getter); 71 72 // All incident collection, data collection, and uploads in progress are 73 // dropped at destruction. 74 virtual ~IncidentReportingService(); 75 76 // Returns a callback by which external components can add an incident to the 77 // service on behalf of |profile|. The callback may outlive the service, but 78 // will no longer have any effect after the service is deleted. The callback 79 // must not be run after |profile| has been destroyed. 80 AddIncidentCallback GetAddIncidentCallback(Profile* profile); 81 82 // Returns a preference validation delegate that adds incidents to the service 83 // for validation failures in |profile|. The delegate may outlive the service, 84 // but incidents reported by it will no longer have any effect after the 85 // service is deleted. The lifetime of the delegate should not extend beyond 86 // that of the profile it services. 87 scoped_ptr<TrackedPreferenceValidationDelegate> 88 CreatePreferenceValidationDelegate(Profile* profile); 89 90 // Registers |callback| to be run after some delay following process launch. 91 void RegisterDelayedAnalysisCallback(const DelayedAnalysisCallback& callback); 92 93 protected: 94 // A pointer to a function that populates a protobuf with environment data. 95 typedef void (*CollectEnvironmentDataFn)( 96 ClientIncidentReport_EnvironmentData*); 97 98 // For testing so that the TaskRunner used for delayed analysis callbacks can 99 // be specified. 100 IncidentReportingService( 101 SafeBrowsingService* safe_browsing_service, 102 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter, 103 base::TimeDelta delayed_task_interval, 104 const scoped_refptr<base::TaskRunner>& delayed_task_runner); 105 106 // Sets the function called by the service to collect environment data and the 107 // task runner on which it is called. Used by unit tests to provide a fake 108 // environment data collector. 109 void SetCollectEnvironmentHook( 110 CollectEnvironmentDataFn collect_environment_data_hook, 111 const scoped_refptr<base::TaskRunner>& task_runner); 112 113 // Handles the addition of a new profile to the ProfileManager. Creates a new 114 // context for |profile| if one does not exist, drops any received incidents 115 // for the profile if the profile is not participating in safe browsing, and 116 // initiates a new search for the most recent download if a report is being 117 // assembled and the most recent has not been found. Overridden by unit tests 118 // to inject incidents prior to creation. 119 virtual void OnProfileAdded(Profile* profile); 120 121 // Initiates a search for the most recent binary download. Overriden by unit 122 // tests to provide a fake finder. 123 virtual scoped_ptr<LastDownloadFinder> CreateDownloadFinder( 124 const LastDownloadFinder::LastDownloadCallback& callback); 125 126 // Initiates an upload. Overridden by unit tests to provide a fake uploader. 127 virtual scoped_ptr<IncidentReportUploader> StartReportUpload( 128 const IncidentReportUploader::OnResultCallback& callback, 129 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter, 130 const ClientIncidentReport& report); 131 132 // Returns true if a report is currently being processed. 133 bool IsProcessingReport() const; 134 135 private: 136 struct ProfileContext; 137 class UploadContext; 138 139 // A mapping of profiles to contexts holding state about received incidents. 140 typedef std::map<Profile*, ProfileContext*> ProfileContextCollection; 141 142 // Returns the context for |profile|, creating it if it does not exist. 143 ProfileContext* GetOrCreateProfileContext(Profile* profile); 144 145 // Returns the context for |profile|, or NULL if it is unknown. 146 ProfileContext* GetProfileContext(Profile* profile); 147 148 // Handles the destruction of a profile. Incidents reported for the profile 149 // but not yet uploaded are dropped. 150 void OnProfileDestroyed(Profile* profile); 151 152 // Returns an initialized profile that participates in safe browsing. Profiles 153 // participating in extended safe browsing are preferred. 154 Profile* FindEligibleProfile() const; 155 156 // Adds |incident_data| to the service. The incident_time_msec field is 157 // populated with the current time if the caller has not already done so. 158 void AddIncident(Profile* profile, 159 scoped_ptr<ClientIncidentReport_IncidentData> incident_data); 160 161 // Begins processing a report. If processing is already underway, ensures that 162 // collection tasks have completed or are running. 163 void BeginReportProcessing(); 164 165 // Begins the process of collating incidents by waiting for incidents to 166 // arrive. This function is idempotent. 167 void BeginIncidentCollation(); 168 169 // Starts a task to collect environment data in the blocking pool. 170 void BeginEnvironmentCollection(); 171 172 // Returns true if the environment collection task is outstanding. 173 bool WaitingForEnvironmentCollection(); 174 175 // Cancels any pending environment collection task and drops any data that has 176 // already been collected. 177 void CancelEnvironmentCollection(); 178 179 // A callback invoked on the UI thread when environment data collection is 180 // complete. Incident report processing continues, either by waiting for the 181 // collection timeout or by sending an incident report. 182 void OnEnvironmentDataCollected( 183 scoped_ptr<ClientIncidentReport_EnvironmentData> environment_data); 184 185 // Returns true if the service is waiting for additional incidents before 186 // uploading a report. 187 bool WaitingToCollateIncidents(); 188 189 // Cancels the collection timeout. 190 void CancelIncidentCollection(); 191 192 // A callback invoked on the UI thread after which incident collation has 193 // completed. Incident report processing continues, either by waiting for 194 // environment data or the most recent download to arrive or by sending an 195 // incident report. 196 void OnCollationTimeout(); 197 198 // Starts the asynchronous process of finding the most recent executable 199 // download if one is not currently being search for and/or has not already 200 // been found. 201 void BeginDownloadCollection(); 202 203 // True if the service is waiting to discover the most recent download either 204 // because a task to do so is outstanding, or because one or more profiles 205 // have yet to be added to the ProfileManager. 206 bool WaitingForMostRecentDownload(); 207 208 // Cancels the search for the most recent executable download. 209 void CancelDownloadCollection(); 210 211 // A callback invoked on the UI thread by the last download finder when the 212 // search for the most recent binary download is complete. 213 void OnLastDownloadFound( 214 scoped_ptr<ClientIncidentReport_DownloadDetails> last_download); 215 216 // Uploads an incident report if all data collection is complete. Incidents 217 // originating from profiles that do not participate in safe browsing are 218 // dropped. 219 void UploadIfCollectionComplete(); 220 221 // Cancels all uploads, discarding all reports and responses in progress. 222 void CancelAllReportUploads(); 223 224 // Continues an upload after checking for the CSD whitelist killswitch. 225 void OnKillSwitchResult(UploadContext* context, bool is_killswitch_on); 226 227 // Performs processing for a report after succesfully receiving a response. 228 void HandleResponse(const UploadContext& context); 229 230 // IncidentReportUploader::OnResultCallback implementation. 231 void OnReportUploadResult(UploadContext* context, 232 IncidentReportUploader::Result result, 233 scoped_ptr<ClientIncidentResponse> response); 234 235 // content::NotificationObserver methods. 236 virtual void Observe(int type, 237 const content::NotificationSource& source, 238 const content::NotificationDetails& details) OVERRIDE; 239 240 base::ThreadChecker thread_checker_; 241 242 // The safe browsing database manager, through which the whitelist killswitch 243 // is checked. 244 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; 245 246 // Accessor for an URL context with which reports will be sent. 247 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; 248 249 // A pointer to a function that collects environment data. The function will 250 // be run by |environment_collection_task_runner_|. This is ordinarily 251 // CollectEnvironmentData, but may be overridden by tests; see 252 // SetCollectEnvironmentHook. 253 CollectEnvironmentDataFn collect_environment_data_fn_; 254 255 // The task runner on which environment collection takes place. This is 256 // ordinarily a runner in the browser's blocking pool that will skip the 257 // collection task at shutdown if it has not yet started. 258 scoped_refptr<base::TaskRunner> environment_collection_task_runner_; 259 260 // Registrar for observing profile lifecycle notifications. 261 content::NotificationRegistrar notification_registrar_; 262 263 // True when the asynchronous environment collection task has been fired off 264 // but has not yet completed. 265 bool environment_collection_pending_; 266 267 // True when an incident has been received and the service is waiting for the 268 // collation_timer_ to fire. 269 bool collation_timeout_pending_; 270 271 // A timer upon the firing of which the service will report received 272 // incidents. 273 base::DelayTimer<IncidentReportingService> collation_timer_; 274 275 // The report currently being assembled. This becomes non-NULL when an initial 276 // incident is reported, and returns to NULL when the report is sent for 277 // upload. 278 scoped_ptr<ClientIncidentReport> report_; 279 280 // The time at which the initial incident is reported. 281 base::Time first_incident_time_; 282 283 // The time at which the last incident is reported. 284 base::TimeTicks last_incident_time_; 285 286 // The time at which environmental data collection was initiated. 287 base::TimeTicks environment_collection_begin_; 288 289 // The time at which download collection was initiated. 290 base::TimeTicks last_download_begin_; 291 292 // Context data for all on-the-record profiles plus the process-wide (NULL) 293 // context. 294 ProfileContextCollection profiles_; 295 296 // Callbacks registered for performing delayed analysis. 297 DelayedCallbackRunner delayed_analysis_callbacks_; 298 299 // The collection of uploads in progress. 300 ScopedVector<UploadContext> uploads_; 301 302 // An object that asynchronously searches for the most recent binary download. 303 // Non-NULL while such a search is outstanding. 304 scoped_ptr<LastDownloadFinder> last_download_finder_; 305 306 // A factory for handing out weak pointers for AddIncident callbacks. 307 base::WeakPtrFactory<IncidentReportingService> receiver_weak_ptr_factory_; 308 309 // A factory for handing out weak pointers for internal asynchronous tasks 310 // that are posted during normal processing (e.g., environment collection, 311 // safe browsing database checks, and report uploads). 312 base::WeakPtrFactory<IncidentReportingService> weak_ptr_factory_; 313 314 DISALLOW_COPY_AND_ASSIGN(IncidentReportingService); 315 }; 316 317 } // namespace safe_browsing 318 319 #endif // CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_INCIDENT_REPORTING_SERVICE_H_ 320