13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_MANAGER_H_ 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_MANAGER_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A class that implements Chrome's interface with the SafeBrowsing protocol. 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The SafeBrowsingProtocolManager handles formatting and making requests of, 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// and handling responses from, Google's SafeBrowsing servers. This class uses 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The SafeBrowsingProtocolParser class to do the actual parsing. 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <deque> 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/gtest_prod_util.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/hash_tables.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/timer.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/safe_browsing/chunk_range.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/safe_browsing/protocol_parser.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/safe_browsing/safe_browsing_service.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/safe_browsing/safe_browsing_util.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/net/url_fetcher.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsennamespace net { 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass URLRequestStatus; 323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} // namespace net 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(COMPILER_GCC) 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Allows us to use URLFetchers in a hash_map with gcc (MSVC is okay without 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// specifying this). 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace __gnu_cxx { 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate<> 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct hash<const URLFetcher*> { 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t operator()(const URLFetcher* fetcher) const { 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return reinterpret_cast<size_t>(fetcher); 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass SafeBrowsingProtocolManager; 4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Interface of a factory to create ProtocolManager. Useful for tests. 4921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass SBProtocolManagerFactory { 5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public: 5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SBProtocolManagerFactory() {} 5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual ~SBProtocolManagerFactory() {} 5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual SafeBrowsingProtocolManager* CreateProtocolManager( 5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SafeBrowsingService* sb_service, 5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& client_name, 5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& client_key, 5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& wrapped_key, 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::URLRequestContextGetter* request_context_getter, 5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& info_url_prefix, 6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& mackey_url_prefix, 6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool disable_auto_update) = 0; 6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private: 6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DISALLOW_COPY_AND_ASSIGN(SBProtocolManagerFactory); 6421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SafeBrowsingProtocolManager : public URLFetcher::Delegate { 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestBackOffTimes); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestChunkStrings); 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestGetHashUrl); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TestGetHashBackOffTimes); 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestMacKeyUrl); 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, 7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen TestSafeBrowsingHitUrl); 7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, 7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen TestMalwareDetailsUrl); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestNextChunkUrl); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestUpdateUrl); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class SafeBrowsingServiceTest; 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual ~SafeBrowsingProtocolManager(); 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Makes the passed |factory| the factory used to instantiate 8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // a SafeBrowsingService. Useful for tests. 8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen static void RegisterFactory(SBProtocolManagerFactory* factory) { 8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen factory_ = factory; 8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Create an instance of the safe browsing service. 9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen static SafeBrowsingProtocolManager* Create( 9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SafeBrowsingService* sb_service, 9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& client_name, 9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& client_key, 9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& wrapped_key, 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::URLRequestContextGetter* request_context_getter, 9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& info_url_prefix, 9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& mackey_url_prefix, 9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool disable_auto_update); 10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sets up the update schedule and internal state for making periodic requests 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of the SafeBrowsing service. 10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual void Initialize(); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // URLFetcher::Delegate interface. 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnURLFetchComplete(const URLFetcher* source, 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, 1083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const net::URLRequestStatus& status, 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int response_code, 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ResponseCookies& cookies, 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& data); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // API used by the SafeBrowsingService for issuing queries. When the results 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // are available, SafeBrowsingService::HandleGetHashResults is called. 11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual void GetFullHash(SafeBrowsingService::SafeBrowsingCheck* check, 11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::vector<SBPrefix>& prefixes); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Forces the start of next update after |next_update_msec| in msec. 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ForceScheduleNextUpdate(int next_update_msec); 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Scheduled update callback. 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void GetNextUpdate(); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called by the SafeBrowsingService when our request for a list of all chunks 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for each list is done. If database_error is true, that means the protocol 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // manager shouldn't fetch updates since they can't be written to disk. It 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should try again later to open the database. 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnGetChunksComplete(const std::vector<SBListChunkRanges>& list, 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool database_error); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called after the chunks that were parsed were inserted in the database. 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnChunkInserted(); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 134731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // For UMA users we report to Google when a SafeBrowsing interstitial is shown 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // to the user. |threat_type| should be one of the types known by 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // SafeBrowsingHitUrl. 137731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick void ReportSafeBrowsingHit(const GURL& malicious_url, 138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GURL& page_url, 139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GURL& referrer_url, 140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool is_subresource, 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingService::UrlCheckResult threat_type, 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& post_data); 143731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 14421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Users can opt-in on the SafeBrowsing interstitial to send detailed 14521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // malware reports. |report| is the serialized report. 14621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void ReportMalwareDetails(const std::string& report); 14721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool is_initial_request() const { return initial_request_; } 14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // The last time we received an update. 15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::Time last_update() const { return last_update_; } 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Setter for additional_query_. To make sure the additional_query_ won't 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be changed in the middle of an update, caller (e.g.: SafeBrowsingService) 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should call this after callbacks triggered in UpdateFinished() or before 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // IssueUpdateRequest(). 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void set_additional_query(const std::string& query) { 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch additional_query_ = query; 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& additional_query() const { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return additional_query_; 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Enumerate failures for histogramming purposes. DO NOT CHANGE THE 1653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // ORDERING OF THESE VALUES. 1663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen enum ResultType { 1673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // 200 response code means that the server recognized the hash 1683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // prefix, while 204 is an empty response indicating that the 1693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // server did not recognize it. 1703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen GET_HASH_STATUS_200, 1713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen GET_HASH_STATUS_204, 1723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Subset of successful responses which returned no full hashes. 1743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // This includes the 204 case, and also 200 responses for stale 1753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // prefixes (deleted at the server but yet deleted on the client). 1763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen GET_HASH_FULL_HASH_EMPTY, 1773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Subset of successful responses for which one or more of the 1793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // full hashes matched (should lead to an interstitial). 1803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen GET_HASH_FULL_HASH_HIT, 1813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Subset of successful responses which weren't empty and have no 1833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // matches. It means that there was a prefix collision which was 1843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // cleared up by the full hashes. 1853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen GET_HASH_FULL_HASH_MISS, 1863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Memory space for histograms is determined by the max. ALWAYS 1883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // ADD NEW VALUES BEFORE THIS ONE. 1893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen GET_HASH_RESULT_MAX 1903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen }; 1913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Record a GetHash result. |is_download| indicates if the get 193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // hash is triggered by download related lookup. 194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen static void RecordGetHashResult(bool is_download, 195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ResultType result_type); 1963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 19721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen protected: 19821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Constructs a SafeBrowsingProtocolManager for |sb_service| that issues 19921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // network requests using |request_context_getter|. When |disable_auto_update| 20021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // is true, protocol manager won't schedule next update until 20121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // ForceScheduleNextUpdate is called. 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingProtocolManager( 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingService* sb_service, 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& client_name, 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& client_key, 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& wrapped_key, 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::URLRequestContextGetter* request_context_getter, 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& http_url_prefix, 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& https_url_prefix, 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool disable_auto_update); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 21221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen friend class SBProtocolManagerFactoryImpl; 21321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Internal API for fetching information from the SafeBrowsing servers. The 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GetHash requests are higher priority since they can block user requests 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so are handled separately. 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum SafeBrowsingRequestType { 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NO_REQUEST = 0, // No requests in progress 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UPDATE_REQUEST, // Request for redirect URLs 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHUNK_REQUEST, // Request for a specific chunk 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GETKEY_REQUEST // Update the client's MAC key 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Composes a URL using |prefix|, |method| (e.g.: gethash, download, 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // newkey, report), |client_name| and |version|. When not empty, 2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // |additional_query| is appended to the URL with an additional "&" 2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // in the front. 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static std::string ComposeUrl(const std::string& prefix, 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& method, 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& client_name, 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& version, 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& additional_query); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Generates Update URL for querying about the latest set of chunk updates. 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Append "wrkey=xxx" to the URL when |use_mac| is true. 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL UpdateUrl(bool use_mac) const; 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Generates GetHash request URL for retrieving full hashes. 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Append "wrkey=xxx" to the URL when |use_mac| is true. 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL GetHashUrl(bool use_mac) const; 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Generates new MAC client key request URL. 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL MacKeyUrl() const; 24221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Generates URL for reporting safe browsing hits for UMA users. 24321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen GURL SafeBrowsingHitUrl( 244731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GURL& malicious_url, const GURL& page_url, const GURL& referrer_url, 245731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool is_subresource, 246731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SafeBrowsingService::UrlCheckResult threat_type) const; 24721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Generates URL for reporting malware details for users who opt-in. 24821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen GURL MalwareDetailsUrl() const; 24921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Composes a ChunkUrl based on input string. 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL NextChunkUrl(const std::string& input) const; 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns the time (in milliseconds) for the next update request. If 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 'back_off' is true, the time returned will increment an error count and 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // return the appriate next time (see ScheduleNextUpdate below). 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int GetNextUpdateTime(bool back_off); 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Worker function for calculating GetHash and Update backoff times (in 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // seconds). 'Multiplier' is doubled for each consecutive error between the 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2nd and 5th, and 'error_count' is incremented with each call. 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int GetNextBackOffTime(int* error_count, int* multiplier); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Manages our update with the next allowable update time. If 'back_off_' is 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // true, we must decrease the frequency of requests of the SafeBrowsing 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // service according to section 5 of the protocol specification. 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When disable_auto_update_ is set, ScheduleNextUpdate will do nothing. 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ForceScheduleNextUpdate has to be called to trigger the update. 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ScheduleNextUpdate(bool back_off); 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sends a request for a list of chunks we should download to the SafeBrowsing 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // servers. In order to format this request, we need to send all the chunk 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // numbers for each list that we have to the server. Getting the chunk numbers 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // requires a database query (run on the database thread), and the request 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is sent upon completion of that query in OnGetChunksComplete. 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void IssueUpdateRequest(); 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sends a request for a chunk to the SafeBrowsing servers. 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void IssueChunkRequest(); 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Gets a key from the SafeBrowsing servers for use with MAC. This should only 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be called once per client unless the server directly tells us to update. 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void IssueKeyRequest(); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Formats a string returned from the database into: 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // "list_name;a:<add_chunk_ranges>:s:<sub_chunk_ranges>:mac\n" 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static std::string FormatList(const SBListChunkRanges& list, bool use_mac); 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Runs the protocol parser on received data and update the 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SafeBrowsingService with the new content. Returns 'true' on successful 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // parse, 'false' on error. 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool HandleServiceResponse(const GURL& url, const char* data, int length); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the SafeBrowsing service wants us to re-key, we clear our key state and 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // issue the request. 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void HandleReKey(); 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Updates internal state for each GetHash response error, assuming that the 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // current time is |now|. 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void HandleGetHashError(const base::Time& now); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Helper function for update completion. 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void UpdateFinished(bool success); 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A callback that runs if we timeout waiting for a response to an update 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // request. We use this to properly set our update state. 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void UpdateResponseTimeout(); 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 30921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // The factory that controls the creation of SafeBrowsingProtocolManager. 31021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // This is used by tests. 31121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen static SBProtocolManagerFactory* factory_; 31221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Main SafeBrowsing interface object. 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SafeBrowsingService* sb_service_; 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Current active request (in case we need to cancel) for updates or chunks 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // from the SafeBrowsing service. We can only have one of these outstanding 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // at any given time unlike GetHash requests, which are tracked separately. 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<URLFetcher> request_; 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The kind of request that is currently in progress. 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SafeBrowsingRequestType request_type_; 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The number of HTTP response errors, used for request backoff timing. 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int update_error_count_; 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int gethash_error_count_; 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Multipliers which double (max == 8) for each error after the second. 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int update_back_off_mult_; 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int gethash_back_off_mult_; 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Multiplier between 0 and 1 to spread clients over an interval. 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch float back_off_fuzz_; 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The list for which we are make a request. 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string list_name_; 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For managing the next earliest time to query the SafeBrowsing servers for 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // updates. 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int next_update_sec_; 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::OneShotTimer<SafeBrowsingProtocolManager> update_timer_; 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // All chunk requests that need to be made, along with their MAC. 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::deque<ChunkUrl> chunk_request_urls_; 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Map of GetHash requests. 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef base::hash_map<const URLFetcher*, 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SafeBrowsingService::SafeBrowsingCheck*> HashRequests; 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HashRequests hash_requests_; 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The next scheduled update has special behavior for the first 2 requests. 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum UpdateRequestState { 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FIRST_REQUEST = 0, 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECOND_REQUEST, 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NORMAL_REQUEST 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateRequestState update_state_; 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We'll attempt to get keys once per browser session if we don't already have 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // them. They are not essential to operation, but provide a layer of 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // verification. 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool initial_request_; 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // True if the service has been given an add/sub chunk but it hasn't been 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // added to the database yet. 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool chunk_pending_to_write_; 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The keys used for MAC. Empty keys mean we aren't using MAC. 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string client_key_; 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string wrapped_key_; 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The last time we successfully received an update. 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time last_update_; 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // While in GetHash backoff, we can't make another GetHash until this time. 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time next_gethash_time_; 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Current product version sent in each request. 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string version_; 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Used for measuring chunk request latency. 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time chunk_request_start_; 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tracks the size of each update (in bytes). 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int update_size_; 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 387731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Track outstanding SafeBrowsing report fetchers for clean up. 38821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // We add both "hit" and "detail" fetchers in this set. 389731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::set<const URLFetcher*> safebrowsing_reports_; 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The safe browsing client name sent in each request. 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string client_name_; 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A string that is appended to the end of URLs for download, gethash, 39521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // newkey, safebrowsing hits and chunk update requests. 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string additional_query_; 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The context we use to issue network requests. 399ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<net::URLRequestContextGetter> request_context_getter_; 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // URL prefix where browser fetches safebrowsing chunk updates, hashes, and 40221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // reports hits to the safebrowsing list for UMA users. 40321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::string http_url_prefix_; 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // URL prefix where browser fetches MAC client key, and reports detailed 40621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // malware reports for users who opt-in. 40721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::string https_url_prefix_; 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When true, protocol manager will not start an update unless 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ForceScheduleNextUpdate() is called. This is set for testing purpose. 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool disable_auto_update_; 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(SafeBrowsingProtocolManager); 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_MANAGER_H_ 417