// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // The Safe Browsing service is responsible for downloading anti-phishing and // anti-malware tables and checking urls against them. #ifndef CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ #define CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ #include #include #include #include #include "base/hash_tables.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/system_monitor.h" #include "base/thread.h" #include "base/time.h" #include "chrome/browser/safe_browsing/safe_browsing_util.h" #include "googleurl/src/gurl.h" #include "webkit/glue/resource_type.h" class BloomFilter; class MessageLoop; class PrefService; class SafeBrowsingBlockingPage; class SafeBrowsingDatabase; class SafeBrowsingProtocolManager; // Construction needs to happen on the main thread. class SafeBrowsingService : public base::RefCountedThreadSafe, public base::SystemMonitor::PowerObserver { public: // Users of this service implement this interface to be notified // asynchronously of the result. enum UrlCheckResult { URL_SAFE, URL_PHISHING, URL_MALWARE, }; class Client { public: virtual ~Client() {} // Called when the result of checking a URL is known. virtual void OnUrlCheckResult(const GURL& url, UrlCheckResult result) = 0; // Called when the user has made a decision about how to handle the // SafeBrowsing interstitial page. virtual void OnBlockingPageComplete(bool proceed) = 0; }; // Structure used to pass parameters between the IO and UI thread when // interacting with the blocking page. struct UnsafeResource { GURL url; ResourceType::Type resource_type; UrlCheckResult threat_type; Client* client; int render_process_host_id; int render_view_id; }; // Creates the safe browsing service. Need to initialize before using. SafeBrowsingService(); ~SafeBrowsingService(); // Initializes the service. io_loop is the message loop that the // caller of this service (ResourceDispatcherHost) wants to be notified on // for check results. db_loop is the message loop for the thread to do // the database work. void Initialize(MessageLoop* io_loop); // Called to initialize objects that are used on the io_thread. void OnIOInitialize(MessageLoop* notify_loop, const std::string& client_key, const std::string& wrapped_key); // Called to initialize objects that are used on the db_thread. void OnDBInitialize(); // Called to shutdown operations on the io_thread. void OnIOShutdown(); // Called on the main thread to let us know that the io_thread is going away. void ShutDown(); // Called on the IO thread. // Returns true if the url's scheme can be checked. bool CanCheckUrl(const GURL& url) const; // Checks if the given url is safe or not. If we can synchronously determine // that the url is safe, CheckUrl returns true. Otherwise it returns false, // and "client" is called asynchronously with the result when it is ready. bool CheckUrl(const GURL& url, Client* client); // For the new SafeBrowsingDatabase, which runs the check synchronously. bool CheckUrlNew(const GURL& url, Client* client); // Cancels a pending check if the result is no longer needed. void CancelCheck(Client* client); // Displays an interstitial page. void DisplayBlockingPage(const GURL& url, ResourceType::Type resource_type, UrlCheckResult result, Client* client, MessageLoop* ui_loop, int render_process_host_id, int render_view_id); // Bundle of SafeBrowsing state for one URL check. struct SafeBrowsingCheck { GURL url; Client* client; bool need_get_hash; base::Time start; // Time that check was sent to SB service. base::TimeDelta db_time; // How long DB look-up took. UrlCheckResult result; std::vector prefix_hits; std::vector full_hits; }; // API used by the SafeBrowsingProtocolManager to interface with the // SafeBrowsing storage system. void HandleGetHashResults( SafeBrowsingCheck* check, const std::vector& full_hashes, bool can_cache); void HandleChunk(const std::string& list, std::deque* chunks); void HandleChunkDelete(std::vector* chunk_deletes); // Update management. void UpdateStarted(); void UpdateFinished(bool update_succeeded); // The blocking page on the UI thread has completed. void OnBlockingPageDone(const std::vector& resources, bool proceed); // Called when the SafeBrowsingProtocolManager has received updated MAC keys. void OnNewMacKeys(const std::string& client_key, const std::string& wrapped_key); // Notification from the advanced options UI. void OnEnable(bool enabled); bool enabled() const { return enabled_; } // Called by the database (on the db thread) when a chunk insertion is // complete. void ChunkInserted(); // Notification from the database when it's done loading its bloom filter. void DatabaseLoadComplete(bool database_error); // Preference handling. static void RegisterPrefs(PrefService* prefs); // The SafeBrowsing system has instructed us to reset our database. void ResetDatabase(); // Log the user perceived delay caused by SafeBrowsing. This delay is the time // delta starting from when we would have started reading data from the // network, and ending when the SafeBrowsing check completes indicating that // the current page is 'safe'. void LogPauseDelay(base::TimeDelta time); // PowerObserver notifications // We defer SafeBrowsing work for a short duration when the computer comes // out of a suspend state to avoid thrashing the disk. void OnPowerStateChange(base::SystemMonitor*) {}; void OnSuspend(base::SystemMonitor*); void OnResume(base::SystemMonitor*); bool new_safe_browsing() const { return new_safe_browsing_; } private: // Should only be called on db thread as SafeBrowsingDatabase is not // threadsafe. SafeBrowsingDatabase* GetDatabase(); // Release the final reference to the database on the db thread. void ReleaseDatabase(SafeBrowsingDatabase* database); // Called on the database thread to check a url. void CheckDatabase(SafeBrowsingCheck* info, base::Time last_update); // Called on the IO thread with the check result. void OnCheckDone(SafeBrowsingCheck* info); // Called on the database thread to retrieve chunks. void GetAllChunksFromDatabase(); // Called on the IOthread with the results of all chunks. void OnGetAllChunksFromDatabase(const std::vector& lists, bool database_error); // Called on the IO thread after the database reports that it added a chunk. void OnChunkInserted(); // Called on the database thread to add/remove chunks and host keys. // Callee will free the data when it's done. void HandleChunkForDatabase(const std::string& list, std::deque* chunks); void DeleteChunks(std::vector* chunk_deletes); static UrlCheckResult GetResultFromListname(const std::string& list_name); void NotifyClientBlockingComplete(Client* client, bool proceed); void DatabaseUpdateFinished(bool update_succeeded); void Start(); void Stop(); // Runs on the db thread to reset the database. We assume that resetting the // database is a synchronous operation. void OnResetDatabase(); // Runs on the io thread when the reset is complete. void OnResetComplete(); // Store in-memory the GetHash response. Runs on the database thread. void CacheHashResults(const std::vector& prefixes, const std::vector& full_hashes); // Internal worker function for processing full hashes. void OnHandleGetHashResults(SafeBrowsingCheck* check, const std::vector& full_hashes); void HandleOneCheck(SafeBrowsingCheck* check, const std::vector& full_hashes); // Runs on the database thread to inform the database we've resumed from a low // power state. void HandleResume(); // Invoked on the UI thread to show the blocking page. void DoDisplayBlockingPage(const UnsafeResource& resource); // During a reset or the initial load we may have to queue checks until the // database is ready. This method is run once the database has loaded (or if // we shut down SafeBrowsing before the database has finished loading). void RunQueuedClients(); void OnUpdateComplete(bool update_succeeded); MessageLoop* io_loop_; typedef std::set CurrentChecks; CurrentChecks checks_; // Used for issuing only one GetHash request for a given prefix. typedef std::vector GetHashRequestors; typedef base::hash_map GetHashRequests; GetHashRequests gethash_requests_; // The sqlite database. We don't use a scoped_ptr because it needs to be // destructed on a different thread than this object. SafeBrowsingDatabase* database_; // Handles interaction with SafeBrowsing servers. SafeBrowsingProtocolManager* protocol_manager_; // Used for whitelisting a render view when the user ignores our warning. struct WhiteListedEntry { int render_process_host_id; int render_view_id; std::string domain; UrlCheckResult result; }; std::vector white_listed_entries_; // Whether the service is running. 'enabled_' is used by SafeBrowsingService // on the IO thread during normal operations. bool enabled_; // The SafeBrowsing thread that runs database operations. scoped_ptr db_thread_; // Indicates if we are in the process of resetting the database. bool resetting_; // Indicates if we are using the new bloom filter based database. bool new_safe_browsing_; // Indicates if the database has finished initialization. bool database_loaded_; // Indicates if we're currently in an update cycle. bool update_in_progress_; // Clients that we've queued up for checking later once the database is ready. typedef struct { Client* client; GURL url; base::Time start; } QueuedCheck; std::deque queued_checks_; DISALLOW_COPY_AND_ASSIGN(SafeBrowsingService); }; #endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_