safe_browsing_service.h revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2010 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// The Safe Browsing service is responsible for downloading anti-phishing and 6// anti-malware tables and checking urls against them. 7 8#ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ 9#define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ 10#pragma once 11 12#include <deque> 13#include <set> 14#include <string> 15#include <vector> 16 17#include "base/hash_tables.h" 18#include "base/lock.h" 19#include "base/ref_counted.h" 20#include "base/scoped_ptr.h" 21#include "base/time.h" 22#include "chrome/browser/safe_browsing/safe_browsing_util.h" 23#include "googleurl/src/gurl.h" 24#include "webkit/glue/resource_type.h" 25 26class MalwareDetails; 27class PrefService; 28class SafeBrowsingDatabase; 29class SafeBrowsingProtocolManager; 30class SafeBrowsingServiceFactory; 31class URLRequestContextGetter; 32 33namespace base { 34class Thread; 35} 36 37// Construction needs to happen on the main thread. 38class SafeBrowsingService 39 : public base::RefCountedThreadSafe<SafeBrowsingService> { 40 public: 41 // Users of this service implement this interface to be notified 42 // asynchronously of the result. 43 enum UrlCheckResult { 44 URL_SAFE, 45 URL_PHISHING, 46 URL_MALWARE, 47 BINARY_MALWARE, // This binary is a malware. 48 }; 49 50 class Client { 51 public: 52 virtual ~Client() {} 53 54 void OnSafeBrowsingResult(const GURL& url, UrlCheckResult result) { 55 OnBrowseUrlCheckResult(url, result); 56 OnDownloadUrlCheckResult(url, result); 57 // TODO(lzheng): This is not implemented yet. 58 // OnDownloadHashCheckResult(url, result); 59 } 60 61 // Called when the user has made a decision about how to handle the 62 // SafeBrowsing interstitial page. 63 virtual void OnBlockingPageComplete(bool proceed) {} 64 65 protected: 66 // Called when the result of checking a browse URL is known. 67 virtual void OnBrowseUrlCheckResult(const GURL& url, 68 UrlCheckResult result) {} 69 70 // Called when the result of checking a download URL is known. 71 virtual void OnDownloadUrlCheckResult(const GURL& url, 72 UrlCheckResult result) {} 73 74 // Called when the result of checking a download binary hash is known. 75 virtual void OnDownloadHashCheckResult(const GURL& url, 76 UrlCheckResult result) {} 77 }; 78 79 // Structure used to pass parameters between the IO and UI thread when 80 // interacting with the blocking page. 81 struct UnsafeResource { 82 UnsafeResource(); 83 ~UnsafeResource(); 84 85 GURL url; 86 GURL original_url; 87 ResourceType::Type resource_type; 88 UrlCheckResult threat_type; 89 Client* client; 90 int render_process_host_id; 91 int render_view_id; 92 }; 93 94 // Bundle of SafeBrowsing state for one URL check. 95 struct SafeBrowsingCheck { 96 SafeBrowsingCheck(); 97 ~SafeBrowsingCheck(); 98 99 GURL url; 100 Client* client; 101 bool need_get_hash; 102 base::Time start; // Time that check was sent to SB service. 103 UrlCheckResult result; 104 std::vector<SBPrefix> prefix_hits; 105 std::vector<SBFullHashResult> full_hits; 106 107 private: 108 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingCheck); 109 }; 110 111 // Makes the passed |factory| the factory used to instanciate 112 // a SafeBrowsingService. Useful for tests. 113 static void RegisterFactory(SafeBrowsingServiceFactory* factory) { 114 factory_ = factory; 115 } 116 117 // Create an instance of the safe browsing service. 118 static SafeBrowsingService* CreateSafeBrowsingService(); 119 120 // Called on the UI thread to initialize the service. 121 void Initialize(); 122 123 // Called on the main thread to let us know that the io_thread is going away. 124 void ShutDown(); 125 126 // Returns true if the url's scheme can be checked. 127 bool CanCheckUrl(const GURL& url) const; 128 129 // Called on the IO thread to check if the given url is safe or not. If we 130 // can synchronously determine that the url is safe, CheckUrl returns true. 131 // Otherwise it returns false, and "client" is called asynchronously with the 132 // result when it is ready. 133 virtual bool CheckBrowseUrl(const GURL& url, Client* client); 134 135 // Check if the prefix for |url| is in safebrowsing download add lists. 136 // Result will be passed to callback in |client|. 137 bool CheckDownloadUrl(const GURL& url, Client* client); 138 139 // Called on the IO thread to cancel a pending check if the result is no 140 // longer needed. 141 void CancelCheck(Client* client); 142 143 // Called on the IO thread to display an interstitial page. 144 // |url| is the url of the resource that matches a safe browsing list. 145 // If the request contained a chain of redirects, |url| is the last url 146 // in the chain, and |original_url| is the first one (the root of the 147 // chain). Otherwise, |original_url| = |url|. 148 void DisplayBlockingPage(const GURL& url, 149 const GURL& original_url, 150 ResourceType::Type resource_type, 151 UrlCheckResult result, 152 Client* client, 153 int render_process_host_id, 154 int render_view_id); 155 156 // Called on the IO thread when the SafeBrowsingProtocolManager has received 157 // the full hash results for prefix hits detected in the database. 158 void HandleGetHashResults( 159 SafeBrowsingCheck* check, 160 const std::vector<SBFullHashResult>& full_hashes, 161 bool can_cache); 162 163 // Called on the IO thread. 164 void HandleChunk(const std::string& list, SBChunkList* chunks); 165 void HandleChunkDelete(std::vector<SBChunkDelete>* chunk_deletes); 166 167 // Update management. Called on the IO thread. 168 void UpdateStarted(); 169 void UpdateFinished(bool update_succeeded); 170 // Whether there is an update in progress. Called on the IO thread. 171 bool IsUpdateInProgress() const; 172 173 // The blocking page on the UI thread has completed. 174 void OnBlockingPageDone(const std::vector<UnsafeResource>& resources, 175 bool proceed); 176 177 // Called on the UI thread when the SafeBrowsingProtocolManager has received 178 // updated MAC keys. 179 void OnNewMacKeys(const std::string& client_key, 180 const std::string& wrapped_key); 181 182 // Notification on the UI thread from the advanced options UI. 183 void OnEnable(bool enabled); 184 185 bool enabled() const { return enabled_; } 186 187 // Preference handling. 188 static void RegisterPrefs(PrefService* prefs); 189 190 // Called on the IO thread to try to close the database, freeing the memory 191 // associated with it. The database will be automatically reopened as needed. 192 // 193 // NOTE: Actual database closure is asynchronous, and until it happens, the IO 194 // thread is not allowed to access it; may not actually trigger a close if one 195 // is already pending or doing so would cause problems. 196 void CloseDatabase(); 197 198 // Called on the IO thread to reset the database. 199 void ResetDatabase(); 200 201 // Log the user perceived delay caused by SafeBrowsing. This delay is the time 202 // delta starting from when we would have started reading data from the 203 // network, and ending when the SafeBrowsing check completes indicating that 204 // the current page is 'safe'. 205 void LogPauseDelay(base::TimeDelta time); 206 207 // When a safebrowsing blocking page goes away, it calls this method 208 // so the service can serialize and send MalwareDetails. 209 virtual void ReportMalwareDetails(scoped_refptr<MalwareDetails> details); 210 211 protected: 212 // Creates the safe browsing service. Need to initialize before using. 213 SafeBrowsingService(); 214 215 virtual ~SafeBrowsingService(); 216 217 private: 218 friend class SafeBrowsingServiceFactoryImpl; 219 220 typedef std::set<SafeBrowsingCheck*> CurrentChecks; 221 typedef std::vector<SafeBrowsingCheck*> GetHashRequestors; 222 typedef base::hash_map<SBPrefix, GetHashRequestors> GetHashRequests; 223 224 // Used for whitelisting a render view when the user ignores our warning. 225 struct WhiteListedEntry; 226 227 // Clients that we've queued up for checking later once the database is ready. 228 struct QueuedCheck { 229 Client* client; 230 GURL url; 231 base::Time start; 232 }; 233 234 friend class base::RefCountedThreadSafe<SafeBrowsingService>; 235 friend class SafeBrowsingServiceTest; 236 237 // Called to initialize objects that are used on the io_thread. 238 void OnIOInitialize(const std::string& client_key, 239 const std::string& wrapped_key, 240 URLRequestContextGetter* request_context_getter); 241 242 // Called to shutdown operations on the io_thread. 243 void OnIOShutdown(); 244 245 // Returns whether |database_| exists and is accessible. 246 bool DatabaseAvailable() const; 247 248 // Called on the IO thread. If the database does not exist, queues up a call 249 // on the db thread to create it. Returns whether the database is available. 250 // 251 // Note that this is only needed outside the db thread, since functions on the 252 // db thread can call GetDatabase() directly. 253 bool MakeDatabaseAvailable(); 254 255 // Should only be called on db thread as SafeBrowsingDatabase is not 256 // threadsafe. 257 SafeBrowsingDatabase* GetDatabase(); 258 259 // Called on the IO thread with the check result. 260 void OnCheckDone(SafeBrowsingCheck* info); 261 262 // Called on the database thread to retrieve chunks. 263 void GetAllChunksFromDatabase(); 264 265 // Called on the IO thread with the results of all chunks. 266 void OnGetAllChunksFromDatabase(const std::vector<SBListChunkRanges>& lists, 267 bool database_error); 268 269 // Called on the IO thread after the database reports that it added a chunk. 270 void OnChunkInserted(); 271 272 // Notification that the database is done loading its bloom filter. We may 273 // have had to queue checks until the database is ready, and if so, this 274 // checks them. 275 void DatabaseLoadComplete(); 276 277 // Called on the database thread to add/remove chunks and host keys. 278 // Callee will free the data when it's done. 279 void HandleChunkForDatabase(const std::string& list, 280 SBChunkList* chunks); 281 282 void DeleteChunks(std::vector<SBChunkDelete>* chunk_deletes); 283 284 static UrlCheckResult GetResultFromListname(const std::string& list_name); 285 286 void NotifyClientBlockingComplete(Client* client, bool proceed); 287 288 void DatabaseUpdateFinished(bool update_succeeded); 289 290 // Start up SafeBrowsing objects. This can be called at browser start, or when 291 // the user checks the "Enable SafeBrowsing" option in the Advanced options 292 // UI. 293 void Start(); 294 295 // Called on the db thread to close the database. See CloseDatabase(). 296 void OnCloseDatabase(); 297 298 // Runs on the db thread to reset the database. We assume that resetting the 299 // database is a synchronous operation. 300 void OnResetDatabase(); 301 302 // Store in-memory the GetHash response. Runs on the database thread. 303 void CacheHashResults(const std::vector<SBPrefix>& prefixes, 304 const std::vector<SBFullHashResult>& full_hashes); 305 306 // Internal worker function for processing full hashes. 307 void OnHandleGetHashResults(SafeBrowsingCheck* check, 308 const std::vector<SBFullHashResult>& full_hashes); 309 310 // Run one check against |full_hashes|. Returns |true| if the check 311 // finds a match in |full_hashes|. 312 bool HandleOneCheck(SafeBrowsingCheck* check, 313 const std::vector<SBFullHashResult>& full_hashes); 314 315 // Invoked on the UI thread to show the blocking page. 316 void DoDisplayBlockingPage(const UnsafeResource& resource); 317 318 // As soon as we create a blocking page, we schedule this method to 319 // report hits to the malware or phishing list to the server. 320 void ReportSafeBrowsingHit(const GURL& malicious_url, 321 const GURL& page_url, 322 const GURL& referrer_url, 323 bool is_subresource, 324 UrlCheckResult threat_type); 325 326 // Invoked by CheckDownloadUrl. It checks the download URL on 327 // safe_browsing_thread_. 328 void CheckDownloadUrlOnSBThread(SafeBrowsingCheck* check); 329 330 // Call the Client's callback in IO thread after CheckDownloadUrl finishes. 331 void CheckDownloadUrlDone(SafeBrowsingCheck* check, UrlCheckResult result); 332 333 // The factory used to instanciate a SafeBrowsingService object. 334 // Useful for tests, so they can provide their own implementation of 335 // SafeBrowsingService. 336 static SafeBrowsingServiceFactory* factory_; 337 338 CurrentChecks checks_; 339 340 // Used for issuing only one GetHash request for a given prefix. 341 GetHashRequests gethash_requests_; 342 343 // The sqlite database. We don't use a scoped_ptr because it needs to be 344 // destructed on a different thread than this object. 345 SafeBrowsingDatabase* database_; 346 347 // Lock used to prevent possible data races due to compiler optimizations. 348 mutable Lock database_lock_; 349 350 // Handles interaction with SafeBrowsing servers. 351 SafeBrowsingProtocolManager* protocol_manager_; 352 353 std::vector<WhiteListedEntry> white_listed_entries_; 354 355 // Whether the service is running. 'enabled_' is used by SafeBrowsingService 356 // on the IO thread during normal operations. 357 bool enabled_; 358 359 // Indicate if download_protection is enabled by command switch 360 // so we allow this feature to be exersized. 361 bool enable_download_protection_; 362 363 // The SafeBrowsing thread that runs database operations. 364 // 365 // Note: Functions that run on this thread should run synchronously and return 366 // to the IO thread, not post additional tasks back to this thread, lest we 367 // cause a race condition at shutdown time that leads to a database leak. 368 scoped_ptr<base::Thread> safe_browsing_thread_; 369 370 // Indicates if we're currently in an update cycle. 371 bool update_in_progress_; 372 373 // When true, newly fetched chunks may not in the database yet since the 374 // database is still updating. 375 bool database_update_in_progress_; 376 377 // Indicates if we're in the midst of trying to close the database. If this 378 // is true, nothing on the IO thread should access the database. 379 bool closing_database_; 380 381 std::deque<QueuedCheck> queued_checks_; 382 383 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingService); 384}; 385 386// Factory for creating SafeBrowsingService. Useful for tests. 387class SafeBrowsingServiceFactory { 388 public: 389 SafeBrowsingServiceFactory() { } 390 virtual ~SafeBrowsingServiceFactory() { } 391 virtual SafeBrowsingService* CreateSafeBrowsingService() = 0; 392 private: 393 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactory); 394}; 395 396#endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ 397