safe_browsing_service.h revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
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 PrefService;
27class SafeBrowsingDatabase;
28class SafeBrowsingProtocolManager;
29class URLRequestContextGetter;
30
31namespace base {
32class Thread;
33}
34
35// Construction needs to happen on the main thread.
36class SafeBrowsingService
37    : public base::RefCountedThreadSafe<SafeBrowsingService> {
38 public:
39  // Users of this service implement this interface to be notified
40  // asynchronously of the result.
41  enum UrlCheckResult {
42    URL_SAFE,
43    URL_PHISHING,
44    URL_MALWARE,
45  };
46
47  class Client {
48   public:
49    virtual ~Client() {}
50
51    // Called when the result of checking a URL is known.
52    virtual void OnUrlCheckResult(const GURL& url, UrlCheckResult result) = 0;
53
54    // Called when the user has made a decision about how to handle the
55    // SafeBrowsing interstitial page.
56    virtual void OnBlockingPageComplete(bool proceed) = 0;
57  };
58
59  // Structure used to pass parameters between the IO and UI thread when
60  // interacting with the blocking page.
61  struct UnsafeResource {
62    GURL url;
63    GURL original_url;
64    ResourceType::Type resource_type;
65    UrlCheckResult threat_type;
66    Client* client;
67    int render_process_host_id;
68    int render_view_id;
69  };
70
71  // Bundle of SafeBrowsing state for one URL check.
72  struct SafeBrowsingCheck {
73    GURL url;
74    Client* client;
75    bool need_get_hash;
76    base::Time start;  // Time that check was sent to SB service.
77    UrlCheckResult result;
78    std::vector<SBPrefix> prefix_hits;
79    std::vector<SBFullHashResult> full_hits;
80  };
81
82  // Creates the safe browsing service.  Need to initialize before using.
83  SafeBrowsingService();
84
85  // Called on the UI thread to initialize the service.
86  void Initialize();
87
88  // Called on the main thread to let us know that the io_thread is going away.
89  void ShutDown();
90
91  // Returns true if the url's scheme can be checked.
92  bool CanCheckUrl(const GURL& url) const;
93
94  // Called on the IO thread to check if the given url is safe or not.  If we
95  // can synchronously determine that the url is safe, CheckUrl returns true.
96  // Otherwise it returns false, and "client" is called asynchronously with the
97  // result when it is ready.
98  bool CheckUrl(const GURL& url, Client* client);
99
100  // Called on the IO thread to cancel a pending check if the result is no
101  // longer needed.
102  void CancelCheck(Client* client);
103
104  // Called on the IO thread to display an interstitial page.
105  // |url| is the url of the resource that matches a safe browsing list.
106  // If the request contained a chain of redirects, |url| is the last url
107  // in the chain, and |original_url| is the first one (the root of the
108  // chain). Otherwise, |original_url| = |url|.
109  void DisplayBlockingPage(const GURL& url,
110                           const GURL& original_url,
111                           ResourceType::Type resource_type,
112                           UrlCheckResult result,
113                           Client* client,
114                           int render_process_host_id,
115                           int render_view_id);
116
117  // Called on the IO thread when the SafeBrowsingProtocolManager has received
118  // the full hash results for prefix hits detected in the database.
119  void HandleGetHashResults(
120      SafeBrowsingCheck* check,
121      const std::vector<SBFullHashResult>& full_hashes,
122      bool can_cache);
123
124  // Called on the IO thread.
125  void HandleChunk(const std::string& list, SBChunkList* chunks);
126  void HandleChunkDelete(std::vector<SBChunkDelete>* chunk_deletes);
127
128  // Update management.  Called on the IO thread.
129  void UpdateStarted();
130  void UpdateFinished(bool update_succeeded);
131  // Whether there is an update in progress. Called on the IO thread.
132  bool IsUpdateInProgress() const;
133
134  // The blocking page on the UI thread has completed.
135  void OnBlockingPageDone(const std::vector<UnsafeResource>& resources,
136                          bool proceed);
137
138  // Called on the UI thread when the SafeBrowsingProtocolManager has received
139  // updated MAC keys.
140  void OnNewMacKeys(const std::string& client_key,
141                    const std::string& wrapped_key);
142
143  // Notification on the UI thread from the advanced options UI.
144  void OnEnable(bool enabled);
145
146  bool enabled() const { return enabled_; }
147
148  // Preference handling.
149  static void RegisterPrefs(PrefService* prefs);
150
151  // Called on the IO thread to try to close the database, freeing the memory
152  // associated with it.  The database will be automatically reopened as needed.
153  //
154  // NOTE: Actual database closure is asynchronous, and until it happens, the IO
155  // thread is not allowed to access it; may not actually trigger a close if one
156  // is already pending or doing so would cause problems.
157  void CloseDatabase();
158
159  // Called on the IO thread to reset the database.
160  void ResetDatabase();
161
162  // Log the user perceived delay caused by SafeBrowsing. This delay is the time
163  // delta starting from when we would have started reading data from the
164  // network, and ending when the SafeBrowsing check completes indicating that
165  // the current page is 'safe'.
166  void LogPauseDelay(base::TimeDelta time);
167
168 private:
169  typedef std::set<SafeBrowsingCheck*> CurrentChecks;
170  typedef std::vector<SafeBrowsingCheck*> GetHashRequestors;
171  typedef base::hash_map<SBPrefix, GetHashRequestors> GetHashRequests;
172
173  // Used for whitelisting a render view when the user ignores our warning.
174  struct WhiteListedEntry {
175    int render_process_host_id;
176    int render_view_id;
177    std::string domain;
178    UrlCheckResult result;
179  };
180
181  // Clients that we've queued up for checking later once the database is ready.
182  struct QueuedCheck {
183    Client* client;
184    GURL url;
185    base::Time start;
186  };
187
188  friend class base::RefCountedThreadSafe<SafeBrowsingService>;
189  friend class SafeBrowsingServiceTest;
190
191  ~SafeBrowsingService();
192
193  // Called to initialize objects that are used on the io_thread.
194  void OnIOInitialize(const std::string& client_key,
195                      const std::string& wrapped_key,
196                      URLRequestContextGetter* request_context_getter);
197
198  // Called to shutdown operations on the io_thread.
199  void OnIOShutdown();
200
201  // Returns whether |database_| exists and is accessible.
202  bool DatabaseAvailable() const;
203
204  // Called on the IO thread.  If the database does not exist, queues up a call
205  // on the db thread to create it.  Returns whether the database is available.
206  //
207  // Note that this is only needed outside the db thread, since functions on the
208  // db thread can call GetDatabase() directly.
209  bool MakeDatabaseAvailable();
210
211  // Should only be called on db thread as SafeBrowsingDatabase is not
212  // threadsafe.
213  SafeBrowsingDatabase* GetDatabase();
214
215  // Called on the IO thread with the check result.
216  void OnCheckDone(SafeBrowsingCheck* info);
217
218  // Called on the database thread to retrieve chunks.
219  void GetAllChunksFromDatabase();
220
221  // Called on the IO thread with the results of all chunks.
222  void OnGetAllChunksFromDatabase(const std::vector<SBListChunkRanges>& lists,
223                                  bool database_error);
224
225  // Called on the IO thread after the database reports that it added a chunk.
226  void OnChunkInserted();
227
228  // Notification that the database is done loading its bloom filter.  We may
229  // have had to queue checks until the database is ready, and if so, this
230  // checks them.
231  void DatabaseLoadComplete();
232
233  // Called on the database thread to add/remove chunks and host keys.
234  // Callee will free the data when it's done.
235  void HandleChunkForDatabase(const std::string& list,
236                              SBChunkList* chunks);
237
238  void DeleteChunks(std::vector<SBChunkDelete>* chunk_deletes);
239
240  static UrlCheckResult GetResultFromListname(const std::string& list_name);
241
242  void NotifyClientBlockingComplete(Client* client, bool proceed);
243
244  void DatabaseUpdateFinished(bool update_succeeded);
245
246  // Start up SafeBrowsing objects. This can be called at browser start, or when
247  // the user checks the "Enable SafeBrowsing" option in the Advanced options
248  // UI.
249  void Start();
250
251  // Called on the db thread to close the database.  See CloseDatabase().
252  void OnCloseDatabase();
253
254  // Runs on the db thread to reset the database. We assume that resetting the
255  // database is a synchronous operation.
256  void OnResetDatabase();
257
258  // Store in-memory the GetHash response. Runs on the database thread.
259  void CacheHashResults(const std::vector<SBPrefix>& prefixes,
260                        const std::vector<SBFullHashResult>& full_hashes);
261
262  // Internal worker function for processing full hashes.
263  void OnHandleGetHashResults(SafeBrowsingCheck* check,
264                              const std::vector<SBFullHashResult>& full_hashes);
265
266  void HandleOneCheck(SafeBrowsingCheck* check,
267                      const std::vector<SBFullHashResult>& full_hashes);
268
269  // Invoked on the UI thread to show the blocking page.
270  void DoDisplayBlockingPage(const UnsafeResource& resource);
271
272  // Report any pages that contain malware sub-resources to the SafeBrowsing
273  // service.
274  void ReportMalware(const GURL& malware_url,
275                     const GURL& page_url,
276                     const GURL& referrer_url,
277                     bool is_subresource);
278
279  CurrentChecks checks_;
280
281  // Used for issuing only one GetHash request for a given prefix.
282  GetHashRequests gethash_requests_;
283
284  // The sqlite database.  We don't use a scoped_ptr because it needs to be
285  // destructed on a different thread than this object.
286  SafeBrowsingDatabase* database_;
287
288  // Lock used to prevent possible data races due to compiler optimizations.
289  mutable Lock database_lock_;
290
291  // Handles interaction with SafeBrowsing servers.
292  SafeBrowsingProtocolManager* protocol_manager_;
293
294  std::vector<WhiteListedEntry> white_listed_entries_;
295
296  // Whether the service is running. 'enabled_' is used by SafeBrowsingService
297  // on the IO thread during normal operations.
298  bool enabled_;
299
300  // The SafeBrowsing thread that runs database operations.
301  //
302  // Note: Functions that run on this thread should run synchronously and return
303  // to the IO thread, not post additional tasks back to this thread, lest we
304  // cause a race condition at shutdown time that leads to a database leak.
305  scoped_ptr<base::Thread> safe_browsing_thread_;
306
307  // Indicates if we're currently in an update cycle.
308  bool update_in_progress_;
309
310  // When true, newly fetched chunks may not in the database yet since the
311  // database is still updating.
312  bool database_update_in_progress_;
313
314  // Indicates if we're in the midst of trying to close the database.  If this
315  // is true, nothing on the IO thread should access the database.
316  bool closing_database_;
317
318  std::deque<QueuedCheck> queued_checks_;
319
320  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingService);
321};
322
323#endif  // CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_
324