| // Copyright (c) 2010 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_ |
| #pragma once |
| |
| #include <deque> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/hash_tables.h" |
| #include "base/lock.h" |
| #include "base/ref_counted.h" |
| #include "base/scoped_ptr.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 PrefService; |
| class SafeBrowsingDatabase; |
| class SafeBrowsingProtocolManager; |
| class SafeBrowsingServiceFactory; |
| class URLRequestContextGetter; |
| |
| namespace base { |
| class Thread; |
| } |
| |
| // Construction needs to happen on the main thread. |
| class SafeBrowsingService |
| : public base::RefCountedThreadSafe<SafeBrowsingService> { |
| 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 { |
| UnsafeResource(); |
| ~UnsafeResource(); |
| |
| GURL url; |
| GURL original_url; |
| ResourceType::Type resource_type; |
| UrlCheckResult threat_type; |
| Client* client; |
| int render_process_host_id; |
| int render_view_id; |
| }; |
| |
| // Bundle of SafeBrowsing state for one URL check. |
| struct SafeBrowsingCheck { |
| SafeBrowsingCheck(); |
| ~SafeBrowsingCheck(); |
| |
| GURL url; |
| Client* client; |
| bool need_get_hash; |
| base::Time start; // Time that check was sent to SB service. |
| UrlCheckResult result; |
| std::vector<SBPrefix> prefix_hits; |
| std::vector<SBFullHashResult> full_hits; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SafeBrowsingCheck); |
| }; |
| |
| // Makes the passed |factory| the factory used to instanciate |
| // a SafeBrowsingService. Useful for tests. |
| static void RegisterFactory(SafeBrowsingServiceFactory* factory) { |
| factory_ = factory; |
| } |
| |
| // Create an instance of the safe browsing service. |
| static SafeBrowsingService* CreateSafeBrowsingService(); |
| |
| // Called on the UI thread to initialize the service. |
| void Initialize(); |
| |
| // Called on the main thread to let us know that the io_thread is going away. |
| void ShutDown(); |
| |
| // Returns true if the url's scheme can be checked. |
| bool CanCheckUrl(const GURL& url) const; |
| |
| // Called on the IO thread to check 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. |
| virtual bool CheckUrl(const GURL& url, Client* client); |
| |
| // Called on the IO thread to cancel a pending check if the result is no |
| // longer needed. |
| void CancelCheck(Client* client); |
| |
| // Called on the IO thread to display an interstitial page. |
| // |url| is the url of the resource that matches a safe browsing list. |
| // If the request contained a chain of redirects, |url| is the last url |
| // in the chain, and |original_url| is the first one (the root of the |
| // chain). Otherwise, |original_url| = |url|. |
| void DisplayBlockingPage(const GURL& url, |
| const GURL& original_url, |
| ResourceType::Type resource_type, |
| UrlCheckResult result, |
| Client* client, |
| int render_process_host_id, |
| int render_view_id); |
| |
| // Called on the IO thread when the SafeBrowsingProtocolManager has received |
| // the full hash results for prefix hits detected in the database. |
| void HandleGetHashResults( |
| SafeBrowsingCheck* check, |
| const std::vector<SBFullHashResult>& full_hashes, |
| bool can_cache); |
| |
| // Called on the IO thread. |
| void HandleChunk(const std::string& list, SBChunkList* chunks); |
| void HandleChunkDelete(std::vector<SBChunkDelete>* chunk_deletes); |
| |
| // Update management. Called on the IO thread. |
| void UpdateStarted(); |
| void UpdateFinished(bool update_succeeded); |
| // Whether there is an update in progress. Called on the IO thread. |
| bool IsUpdateInProgress() const; |
| |
| // The blocking page on the UI thread has completed. |
| void OnBlockingPageDone(const std::vector<UnsafeResource>& resources, |
| bool proceed); |
| |
| // Called on the UI thread when the SafeBrowsingProtocolManager has received |
| // updated MAC keys. |
| void OnNewMacKeys(const std::string& client_key, |
| const std::string& wrapped_key); |
| |
| // Notification on the UI thread from the advanced options UI. |
| void OnEnable(bool enabled); |
| |
| bool enabled() const { return enabled_; } |
| |
| // Preference handling. |
| static void RegisterPrefs(PrefService* prefs); |
| |
| // Called on the IO thread to try to close the database, freeing the memory |
| // associated with it. The database will be automatically reopened as needed. |
| // |
| // NOTE: Actual database closure is asynchronous, and until it happens, the IO |
| // thread is not allowed to access it; may not actually trigger a close if one |
| // is already pending or doing so would cause problems. |
| void CloseDatabase(); |
| |
| // Called on the IO thread to reset the 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); |
| |
| protected: |
| // Creates the safe browsing service. Need to initialize before using. |
| SafeBrowsingService(); |
| |
| virtual ~SafeBrowsingService(); |
| |
| private: |
| friend class SafeBrowsingServiceFactoryImpl; |
| |
| typedef std::set<SafeBrowsingCheck*> CurrentChecks; |
| typedef std::vector<SafeBrowsingCheck*> GetHashRequestors; |
| typedef base::hash_map<SBPrefix, GetHashRequestors> GetHashRequests; |
| |
| // Used for whitelisting a render view when the user ignores our warning. |
| struct WhiteListedEntry; |
| |
| // Clients that we've queued up for checking later once the database is ready. |
| struct QueuedCheck { |
| Client* client; |
| GURL url; |
| base::Time start; |
| }; |
| |
| friend class base::RefCountedThreadSafe<SafeBrowsingService>; |
| friend class SafeBrowsingServiceTest; |
| |
| // Called to initialize objects that are used on the io_thread. |
| void OnIOInitialize(const std::string& client_key, |
| const std::string& wrapped_key, |
| URLRequestContextGetter* request_context_getter); |
| |
| // Called to shutdown operations on the io_thread. |
| void OnIOShutdown(); |
| |
| // Returns whether |database_| exists and is accessible. |
| bool DatabaseAvailable() const; |
| |
| // Called on the IO thread. If the database does not exist, queues up a call |
| // on the db thread to create it. Returns whether the database is available. |
| // |
| // Note that this is only needed outside the db thread, since functions on the |
| // db thread can call GetDatabase() directly. |
| bool MakeDatabaseAvailable(); |
| |
| // Should only be called on db thread as SafeBrowsingDatabase is not |
| // threadsafe. |
| SafeBrowsingDatabase* GetDatabase(); |
| |
| // 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 IO thread with the results of all chunks. |
| void OnGetAllChunksFromDatabase(const std::vector<SBListChunkRanges>& lists, |
| bool database_error); |
| |
| // Called on the IO thread after the database reports that it added a chunk. |
| void OnChunkInserted(); |
| |
| // Notification that the database is done loading its bloom filter. We may |
| // have had to queue checks until the database is ready, and if so, this |
| // checks them. |
| void DatabaseLoadComplete(); |
| |
| // 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, |
| SBChunkList* chunks); |
| |
| void DeleteChunks(std::vector<SBChunkDelete>* chunk_deletes); |
| |
| static UrlCheckResult GetResultFromListname(const std::string& list_name); |
| |
| void NotifyClientBlockingComplete(Client* client, bool proceed); |
| |
| void DatabaseUpdateFinished(bool update_succeeded); |
| |
| // Start up SafeBrowsing objects. This can be called at browser start, or when |
| // the user checks the "Enable SafeBrowsing" option in the Advanced options |
| // UI. |
| void Start(); |
| |
| // Called on the db thread to close the database. See CloseDatabase(). |
| void OnCloseDatabase(); |
| |
| // Runs on the db thread to reset the database. We assume that resetting the |
| // database is a synchronous operation. |
| void OnResetDatabase(); |
| |
| // Store in-memory the GetHash response. Runs on the database thread. |
| void CacheHashResults(const std::vector<SBPrefix>& prefixes, |
| const std::vector<SBFullHashResult>& full_hashes); |
| |
| // Internal worker function for processing full hashes. |
| void OnHandleGetHashResults(SafeBrowsingCheck* check, |
| const std::vector<SBFullHashResult>& full_hashes); |
| |
| void HandleOneCheck(SafeBrowsingCheck* check, |
| const std::vector<SBFullHashResult>& full_hashes); |
| |
| // Invoked on the UI thread to show the blocking page. |
| void DoDisplayBlockingPage(const UnsafeResource& resource); |
| |
| // Report any pages that contain malware or phishing to the SafeBrowsing |
| // service. |
| void ReportSafeBrowsingHit(const GURL& malicious_url, |
| const GURL& page_url, |
| const GURL& referrer_url, |
| bool is_subresource, |
| UrlCheckResult threat_type); |
| |
| // The factory used to instanciate a SafeBrowsingService object. |
| // Useful for tests, so they can provide their own implementation of |
| // SafeBrowsingService. |
| static SafeBrowsingServiceFactory* factory_; |
| |
| CurrentChecks checks_; |
| |
| // Used for issuing only one GetHash request for a given prefix. |
| 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_; |
| |
| // Lock used to prevent possible data races due to compiler optimizations. |
| mutable Lock database_lock_; |
| |
| // Handles interaction with SafeBrowsing servers. |
| SafeBrowsingProtocolManager* protocol_manager_; |
| |
| std::vector<WhiteListedEntry> 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. |
| // |
| // Note: Functions that run on this thread should run synchronously and return |
| // to the IO thread, not post additional tasks back to this thread, lest we |
| // cause a race condition at shutdown time that leads to a database leak. |
| scoped_ptr<base::Thread> safe_browsing_thread_; |
| |
| // Indicates if we're currently in an update cycle. |
| bool update_in_progress_; |
| |
| // When true, newly fetched chunks may not in the database yet since the |
| // database is still updating. |
| bool database_update_in_progress_; |
| |
| // Indicates if we're in the midst of trying to close the database. If this |
| // is true, nothing on the IO thread should access the database. |
| bool closing_database_; |
| |
| std::deque<QueuedCheck> queued_checks_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SafeBrowsingService); |
| }; |
| |
| // Factory for creating SafeBrowsingService. Useful for tests. |
| class SafeBrowsingServiceFactory { |
| public: |
| SafeBrowsingServiceFactory() { } |
| virtual ~SafeBrowsingServiceFactory() { } |
| virtual SafeBrowsingService* CreateSafeBrowsingService() = 0; |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactory); |
| }; |
| |
| #endif // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ |