diff options
author | lzheng@chromium.org <lzheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-29 21:53:18 +0000 |
---|---|---|
committer | lzheng@chromium.org <lzheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-29 21:53:18 +0000 |
commit | 894c4e8a8146bfa89c66d4e4ab629d589fabd9ba (patch) | |
tree | c8bb18e20e6115b340cc9e62b3f9639626d58cac /chrome/browser/safe_browsing | |
parent | 878f43f91009570f2ddf3380236259635d26c82a (diff) | |
download | chromium_src-894c4e8a8146bfa89c66d4e4ab629d589fabd9ba.zip chromium_src-894c4e8a8146bfa89c66d4e4ab629d589fabd9ba.tar.gz chromium_src-894c4e8a8146bfa89c66d4e4ab629d589fabd9ba.tar.bz2 |
Add switches and apis in safebrowsing protocol_manager that will allow end-to-end test later.
BUG=6787,47318
TEST=protocol_manager_unittest.cc
Review URL: http://codereview.chromium.org/2868030
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51177 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/safe_browsing')
-rw-r--r-- | chrome/browser/safe_browsing/protocol_manager.cc | 164 | ||||
-rw-r--r-- | chrome/browser/safe_browsing/protocol_manager.h | 94 | ||||
-rw-r--r-- | chrome/browser/safe_browsing/protocol_manager_unittest.cc | 122 | ||||
-rw-r--r-- | chrome/browser/safe_browsing/safe_browsing_service.cc | 31 | ||||
-rw-r--r-- | chrome/browser/safe_browsing/safe_browsing_service.h | 2 |
5 files changed, 330 insertions, 83 deletions
diff --git a/chrome/browser/safe_browsing/protocol_manager.cc b/chrome/browser/safe_browsing/protocol_manager.cc index 5a8baae..ff4338a 100644 --- a/chrome/browser/safe_browsing/protocol_manager.cc +++ b/chrome/browser/safe_browsing/protocol_manager.cc @@ -34,26 +34,6 @@ static const int kSbTimerStartIntervalSec = 5 * 60; // The maximum time, in seconds, to wait for a response to an update request. static const int kSbMaxUpdateWaitSec = 10; -// Update URL for querying about the latest set of chunk updates. -static const char* const kSbUpdateUrl = - "http://safebrowsing.clients.google.com/safebrowsing/downloads?client=%s" - "&appver=%s&pver=2.2"; - -// GetHash request URL for retrieving full hashes. -static const char* const kSbGetHashUrl = - "http://safebrowsing.clients.google.com/safebrowsing/gethash?client=%s" - "&appver=%s&pver=2.2"; - -// New MAC client key requests URL. -static const char* const kSbNewKeyUrl = - "https://sb-ssl.google.com/safebrowsing/newkey?client=%s&appver=%s" - "&pver=2.2"; - -// URL for reporting malware pages. -static const char* const kSbMalwareReportUrl = - "http://safebrowsing.clients.google.com/safebrowsing/report?evts=malblhit" - "&evtd=%s&evtr=%s&evhr=%s&client=%s&appver=%s"; - // Maximum back off multiplier. static const int kSbMaxBackOff = 8; @@ -65,7 +45,10 @@ SafeBrowsingProtocolManager::SafeBrowsingProtocolManager( const std::string& client_name, const std::string& client_key, const std::string& wrapped_key, - URLRequestContextGetter* request_context_getter) + URLRequestContextGetter* request_context_getter, + const std::string& info_url_prefix, + const std::string& mackey_url_prefix, + bool disable_auto_update) : sb_service_(sb_service), request_type_(NO_REQUEST), update_error_count_(0), @@ -80,15 +63,18 @@ SafeBrowsingProtocolManager::SafeBrowsingProtocolManager( wrapped_key_(wrapped_key), update_size_(0), client_name_(client_name), - request_context_getter_(request_context_getter) { + request_context_getter_(request_context_getter), + info_url_prefix_(info_url_prefix), + mackey_url_prefix_(mackey_url_prefix), + disable_auto_update_(disable_auto_update) { + DCHECK(!info_url_prefix_.empty() && !mackey_url_prefix_.empty()); + // Set the backoff multiplier fuzz to a random value between 0 and 1. back_off_fuzz_ = static_cast<float>(base::RandDouble()); - // The first update must happen between 1-5 minutes of start up. next_update_sec_ = base::RandInt(60, kSbTimerStartIntervalSec); - scoped_ptr<FileVersionInfo> version_info( - chrome_app::GetChromeVersionInfo()); + scoped_ptr<FileVersionInfo> version_info(chrome_app::GetChromeVersionInfo()); if (!version_info.get()) version_ = "0.1"; else @@ -122,16 +108,8 @@ void SafeBrowsingProtocolManager::GetFullHash( sb_service_->HandleGetHashResults(check, full_hashes, false); return; } - - std::string url = StringPrintf(kSbGetHashUrl, - client_name_.c_str(), - version_.c_str()); - if (!client_key_.empty()) { - url.append("&wrkey="); - url.append(wrapped_key_); - } - - GURL gethash_url(url); + bool use_mac = !client_key_.empty(); + GURL gethash_url = GetHashUrl(use_mac); URLFetcher* fetcher = new URLFetcher(gethash_url, URLFetcher::POST, this); hash_requests_[fetcher] = check; @@ -448,14 +426,24 @@ void SafeBrowsingProtocolManager::Initialize() { } void SafeBrowsingProtocolManager::ScheduleNextUpdate(bool back_off) { - DCHECK(next_update_sec_ > 0); - - // Unschedule any current timer. - update_timer_.Stop(); + DCHECK_GT(next_update_sec_, 0); + if (disable_auto_update_) { + // Unschedule any current timer. + update_timer_.Stop(); + return; + } // Reschedule with the new update. const int next_update = GetNextUpdateTime(back_off); - update_timer_.Start(TimeDelta::FromMilliseconds(next_update), this, + ForceScheduleNextUpdate(next_update); +} + +void SafeBrowsingProtocolManager::ForceScheduleNextUpdate( + const int next_update_msec) { + DCHECK_GE(next_update_msec, 0); + // Unschedule any current timer. + update_timer_.Stop(); + update_timer_.Start(TimeDelta::FromMilliseconds(next_update_msec), this, &SafeBrowsingProtocolManager::GetNextUpdate); } @@ -513,10 +501,7 @@ void SafeBrowsingProtocolManager::IssueChunkRequest() { ChunkUrl next_chunk = chunk_request_urls_.front(); DCHECK(!next_chunk.url.empty()); - if (!StartsWithASCII(next_chunk.url, "http://", false) && - !StartsWithASCII(next_chunk.url, "https://", false)) - next_chunk.url = "http://" + next_chunk.url; - GURL chunk_url(next_chunk.url); + GURL chunk_url = NextChunkUrl(next_chunk.url); request_type_ = CHUNK_REQUEST; request_.reset(new URLFetcher(chunk_url, URLFetcher::GET, this)); request_->set_load_flags(net::LOAD_DISABLE_CACHE); @@ -526,9 +511,7 @@ void SafeBrowsingProtocolManager::IssueChunkRequest() { } void SafeBrowsingProtocolManager::IssueKeyRequest() { - GURL key_url(StringPrintf(kSbNewKeyUrl, - client_name_.c_str(), - version_.c_str())); + GURL key_url = MacKeyUrl(); request_type_ = GETKEY_REQUEST; request_.reset(new URLFetcher(key_url, URLFetcher::GET, this)); request_->set_load_flags(net::LOAD_DISABLE_CACHE); @@ -538,7 +521,7 @@ void SafeBrowsingProtocolManager::IssueKeyRequest() { void SafeBrowsingProtocolManager::OnGetChunksComplete( const std::vector<SBListChunkRanges>& lists, bool database_error) { - DCHECK(request_type_ == UPDATE_REQUEST); + DCHECK_EQ(request_type_, UPDATE_REQUEST); if (database_error) { UpdateFinished(false); ScheduleNextUpdate(false); @@ -570,15 +553,7 @@ void SafeBrowsingProtocolManager::OnGetChunksComplete( list_data.append(FormatList( SBListChunkRanges(safe_browsing_util::kMalwareList), use_mac)); - std::string url = StringPrintf(kSbUpdateUrl, - client_name_.c_str(), - version_.c_str()); - if (use_mac) { - url.append("&wrkey="); - url.append(wrapped_key_); - } - - GURL update_url(url); + GURL update_url = UpdateUrl(use_mac); request_.reset(new URLFetcher(update_url, URLFetcher::POST, this)); request_->set_load_flags(net::LOAD_DISABLE_CACHE); request_->set_request_context(request_context_getter_); @@ -593,7 +568,7 @@ void SafeBrowsingProtocolManager::OnGetChunksComplete( // If we haven't heard back from the server with an update response, this method // will run. Close the current update session and schedule another update. void SafeBrowsingProtocolManager::UpdateResponseTimeout() { - DCHECK(request_type_ == UPDATE_REQUEST); + DCHECK_EQ(request_type_, UPDATE_REQUEST); request_.reset(); UpdateFinished(false); ScheduleNextUpdate(false); @@ -613,14 +588,7 @@ void SafeBrowsingProtocolManager::OnChunkInserted() { void SafeBrowsingProtocolManager::ReportMalware(const GURL& malware_url, const GURL& page_url, const GURL& referrer_url) { - std::string report_str = StringPrintf( - kSbMalwareReportUrl, - EscapeQueryParamValue(malware_url.spec(), true).c_str(), - EscapeQueryParamValue(page_url.spec(), true).c_str(), - EscapeQueryParamValue(referrer_url.spec(), true).c_str(), - client_name_.c_str(), - version_.c_str()); - GURL report_url(report_str); + GURL report_url = MalwareReportUrl(malware_url, page_url, referrer_url); URLFetcher* report = new URLFetcher(report_url, URLFetcher::GET, this); report->set_load_flags(net::LOAD_DISABLE_CACHE); report->set_request_context(request_context_getter_); @@ -667,3 +635,67 @@ void SafeBrowsingProtocolManager::UpdateFinished(bool success) { update_size_ = 0; sb_service_->UpdateFinished(success); } + +std::string SafeBrowsingProtocolManager::ComposeUrl( + const std::string& prefix, const std::string& method, + const std::string& client_name, const std::string& version, + const std::string& additional_query) { + DCHECK(!prefix.empty() && !method.empty() && + !client_name.empty() && !version.empty()); + std::string url = StringPrintf("%s/%s?client=%s&appver=%s&pver=2.2", + prefix.c_str(), method.c_str(), + client_name.c_str(), version.c_str()); + if (!additional_query.empty()) { + url.append(additional_query); + } + return url; +} + +GURL SafeBrowsingProtocolManager::UpdateUrl(bool use_mac) const { + std::string url = ComposeUrl(info_url_prefix_, "downloads", client_name_, + version_, additional_query_); + if (use_mac) { + url.append("&wrkey="); + url.append(wrapped_key_); + } + return GURL(url); +} + +GURL SafeBrowsingProtocolManager::GetHashUrl(bool use_mac) const { + std::string url= ComposeUrl(info_url_prefix_, "gethash", client_name_, + version_, additional_query_); + if (use_mac) { + url.append("&wrkey="); + url.append(wrapped_key_); + } + return GURL(url); +} + +GURL SafeBrowsingProtocolManager::MacKeyUrl() const { + return GURL(ComposeUrl(mackey_url_prefix_, "newkey", client_name_, version_, + additional_query_)); +} + +GURL SafeBrowsingProtocolManager::MalwareReportUrl( + const GURL& malware_url, const GURL& page_url, + const GURL& referrer_url) const { + std::string url = ComposeUrl(info_url_prefix_, "report", client_name_, + version_, additional_query_); + return GURL(StringPrintf("%s&evts=malblhit&evtd=%s&evtr=%s&evhr=%s", + url.c_str(), EscapeQueryParamValue(malware_url.spec(), true).c_str(), + EscapeQueryParamValue(page_url.spec(), true).c_str(), + EscapeQueryParamValue(referrer_url.spec(), true).c_str())); +} + +GURL SafeBrowsingProtocolManager::NextChunkUrl(const std::string& url) const { + std::string next_url; + if (!StartsWithASCII(url, "http://", false) && + !StartsWithASCII(url, "https://", false)) { + next_url = "http://" + url; + } else { + next_url = url; + } + if (!additional_query_.empty()) + next_url += additional_query_; + return GURL(next_url); +} diff --git a/chrome/browser/safe_browsing/protocol_manager.h b/chrome/browser/safe_browsing/protocol_manager.h index 1526fe5..4bd997c 100644 --- a/chrome/browser/safe_browsing/protocol_manager.h +++ b/chrome/browser/safe_browsing/protocol_manager.h @@ -46,20 +46,31 @@ struct hash<const URLFetcher*> { class SafeBrowsingProtocolManager : public URLFetcher::Delegate { FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestBackOffTimes); FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestChunkStrings); + FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestGetHashUrl); FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestGetHashBackOffTimes); + FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestMacKeyUrl); + FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, + TestMalwareReportUrl); + FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestNextChunkUrl); + FRIEND_TEST_ALL_PREFIXES(SafeBrowsingProtocolManagerTest, TestUpdateUrl); public: // Constructs a SafeBrowsingProtocolManager for |sb_service| that issues - // network requests using |request_context_getter|. + // network requests using |request_context_getter|. When |disable_auto_update| + // is true, protocol manager won't schedule next update until + // ForceScheduleNextUpdate is called. SafeBrowsingProtocolManager(SafeBrowsingService* sb_service, const std::string& client_name, const std::string& client_key, const std::string& wrapped_key, - URLRequestContextGetter* request_context_getter); + URLRequestContextGetter* request_context_getter, + const std::string& info_url_prefix, + const std::string& mackey_url_prefix, + bool disable_auto_update); ~SafeBrowsingProtocolManager(); - // Set up the update schedule and internal state for making periodic requests + // Sets up the update schedule and internal state for making periodic requests // of the SafeBrowsing service. void Initialize(); @@ -76,6 +87,11 @@ class SafeBrowsingProtocolManager : public URLFetcher::Delegate { void GetFullHash(SafeBrowsingService::SafeBrowsingCheck* check, const std::vector<SBPrefix>& prefixes); + // Forces the start of next update after |next_update_msec| in msec. + void ForceScheduleNextUpdate(int next_update_msec); + + bool is_initial_request() const { return initial_request_; } + // Scheduled update callback. void GetNextUpdate(); @@ -92,11 +108,22 @@ class SafeBrowsingProtocolManager : public URLFetcher::Delegate { // The last time we received an update. base::Time last_update() const { return last_update_; } - // Report a malware resource to the SafeBrowsing service. + // Reports a malware resource to the SafeBrowsing service. void ReportMalware(const GURL& malware_url, const GURL& page_url, const GURL& referrer_url); + // Setter for additional_query_. To make sure the additional_query_ won't + // be changed in the middle of an update, caller (e.g.: SafeBrowsingService) + // should call this after callbacks triggered in UpdateFinished() or before + // IssueUpdateRequest(). + void set_additional_query(const std::string& query) { + additional_query_ = query; + } + const std::string& additional_query() const { + return additional_query_; + } + private: // Internal API for fetching information from the SafeBrowsing servers. The // GetHash requests are higher priority since they can block user requests @@ -108,6 +135,29 @@ class SafeBrowsingProtocolManager : public URLFetcher::Delegate { GETKEY_REQUEST // Update the client's MAC key }; + // Composes a URL using |prefix|, |method| (e.g.: gethash, download, + // newkey, report), |client_name| and |version|. When not empty, + // |additional_query| is appended to the URL. + static std::string ComposeUrl(const std::string& prefix, + const std::string& method, + const std::string& client_name, + const std::string& version, + const std::string& additional_query); + + // Generates Update URL for querying about the latest set of chunk updates. + // Append "wrkey=xxx" to the URL when |use_mac| is true. + GURL UpdateUrl(bool use_mac) const; + // Generates GetHash request URL for retrieving full hashes. + // Append "wrkey=xxx" to the URL when |use_mac| is true. + GURL GetHashUrl(bool use_mac) const; + // Generates new MAC client key request URL. + GURL MacKeyUrl() const; + // Generates URL for reporting malware pages. + GURL MalwareReportUrl(const GURL& malware_url, const GURL& page_url, + const GURL& referrer_url) const; + // Composes a ChunkUrl based on input string. + GURL NextChunkUrl(const std::string& input) const; + // Returns the time (in milliseconds) for the next update request. If // 'back_off' is true, the time returned will increment an error count and // return the appriate next time (see ScheduleNextUpdate below). @@ -118,38 +168,41 @@ class SafeBrowsingProtocolManager : public URLFetcher::Delegate { // 2nd and 5th, and 'error_count' is incremented with each call. int GetNextBackOffTime(int* error_count, int* multiplier); - // Manage our update with the next allowable update time. If 'back_off_' is + // Manages our update with the next allowable update time. If 'back_off_' is // true, we must decrease the frequency of requests of the SafeBrowsing // service according to section 5 of the protocol specification. + // When disable_auto_update_ is set, ScheduleNextUpdate will do nothing. + // ForceScheduleNextUpdate has to be called to trigger the update. void ScheduleNextUpdate(bool back_off); - // Send a request for a list of chunks we should download to the SafeBrowsing + // Sends a request for a list of chunks we should download to the SafeBrowsing // servers. In order to format this request, we need to send all the chunk // numbers for each list that we have to the server. Getting the chunk numbers // requires a database query (run on the database thread), and the request // is sent upon completion of that query in OnGetChunksComplete. void IssueUpdateRequest(); - // Send a request for a chunk to the SafeBrowsing servers. + // Sends a request for a chunk to the SafeBrowsing servers. void IssueChunkRequest(); - // Get a key from the SafeBrowsing servers for use with MAC. This should only + // Gets a key from the SafeBrowsing servers for use with MAC. This should only // be called once per client unless the server directly tells us to update. void IssueKeyRequest(); - // Format a string returned from the database into: + // Formats a string returned from the database into: // "list_name;a:<add_chunk_ranges>:s:<sub_chunk_ranges>:mac\n" static std::string FormatList(const SBListChunkRanges& list, bool use_mac); - // Run the protocol parser on received data and update the SafeBrowsingService - // with the new content. Returns 'true' on successful parse, 'false' on error. + // Runs the protocol parser on received data and update the + // SafeBrowsingService with the new content. Returns 'true' on successful + // parse, 'false' on error. bool HandleServiceResponse(const GURL& url, const char* data, int length); // If the SafeBrowsing service wants us to re-key, we clear our key state and // issue the request. void HandleReKey(); - // Update internal state for each GetHash response error, assuming that the + // Updates internal state for each GetHash response error, assuming that the // current time is |now|. void HandleGetHashError(const base::Time& now); @@ -232,7 +285,7 @@ class SafeBrowsingProtocolManager : public URLFetcher::Delegate { // Used for measuring chunk request latency. base::Time chunk_request_start_; - // Track the size of each update (in bytes). + // Tracks the size of each update (in bytes). int update_size_; // Track outstanding malware report fetchers for clean up. @@ -241,9 +294,24 @@ class SafeBrowsingProtocolManager : public URLFetcher::Delegate { // The safe browsing client name sent in each request. std::string client_name_; + // A string that is appended to the end of URLs for download, gethash, + // newkey, malware report and chunk update requests. + std::string additional_query_; + // The context we use to issue network requests. scoped_refptr<URLRequestContextGetter> request_context_getter_; + // URL prefix where browser fetches safebrowsing chunk updates, hashes, and + // reports malware. + std::string info_url_prefix_; + + // URL prefix where browser fetches MAC client key. + std::string mackey_url_prefix_; + + // When true, protocol manager will not start an update unless + // ForceScheduleNextUpdate() is called. This is set for testing purpose. + bool disable_auto_update_; + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingProtocolManager); }; diff --git a/chrome/browser/safe_browsing/protocol_manager_unittest.cc b/chrome/browser/safe_browsing/protocol_manager_unittest.cc index e8d64d0..4f45893 100644 --- a/chrome/browser/safe_browsing/protocol_manager_unittest.cc +++ b/chrome/browser/safe_browsing/protocol_manager_unittest.cc @@ -11,12 +11,23 @@ using base::Time; using base::TimeDelta; +static const char kInfoUrlPrefix[] = "http://info.prefix.com/foo"; +static const char kMacKeyUrlPrefix[] = "https://key.prefix.com/bar"; +static const char kClient[] = "unittest"; +static const char kAppVer[] = "1.0"; +static const char kClientKey[] = "SCg9lcLHd0dfksXgYsacwQ=="; +static const char kWrappedKey[] = + "AKEgNisjLl7iRYrjWHmpd_XwCiilxrw8nNaYH47tiQ7pDe9cEErjVHGZaPPUau5h61tbXSDqA" + "BiJZnDFByc_g8B5vTwxkhBf9g=="; +static const char kAdditionalQuery[] = "&additional_query"; + class SafeBrowsingProtocolManagerTest : public testing::Test { }; // Ensure that we respect section 5 of the SafeBrowsing protocol specification. TEST_F(SafeBrowsingProtocolManagerTest, TestBackOffTimes) { - SafeBrowsingProtocolManager pm(NULL, "", "", "", NULL); + SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, + kInfoUrlPrefix, kMacKeyUrlPrefix, false); pm.next_update_sec_ = 1800; DCHECK(pm.back_off_fuzz_ >= 0.0 && pm.back_off_fuzz_ <= 1.0); @@ -54,7 +65,8 @@ TEST_F(SafeBrowsingProtocolManagerTest, TestBackOffTimes) { // Test string combinations with and without MAC. TEST_F(SafeBrowsingProtocolManagerTest, TestChunkStrings) { - SafeBrowsingProtocolManager pm(NULL, "", "", "", NULL); + SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, + kInfoUrlPrefix, kMacKeyUrlPrefix, false); // Add and Sub chunks. SBListChunkRanges phish("goog-phish-shavar"); @@ -87,7 +99,8 @@ TEST_F(SafeBrowsingProtocolManagerTest, TestChunkStrings) { } TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashBackOffTimes) { - SafeBrowsingProtocolManager pm(NULL, "", "", "", NULL); + SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, + kInfoUrlPrefix, kMacKeyUrlPrefix, false); // No errors or back off time yet. EXPECT_EQ(pm.gethash_error_count_, 0); @@ -137,3 +150,106 @@ TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashBackOffTimes) { EXPECT_EQ(pm.gethash_error_count_, 7); EXPECT_TRUE(pm.next_gethash_time_== now + TimeDelta::FromMinutes(480)); } + +TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashUrl) { + SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, + kInfoUrlPrefix, kMacKeyUrlPrefix, false); + pm.version_ = kAppVer; + EXPECT_EQ("http://info.prefix.com/foo/gethash?client=unittest&appver=1.0&" + "pver=2.2", pm.GetHashUrl(false).spec()); + EXPECT_EQ("http://info.prefix.com/foo/gethash?client=unittest&appver=1.0&" + "pver=2.2&wrkey=AKEgNisjLl7iRYrjWHmpd_XwCiilxrw8nNaYH47tiQ7pDe9cE" + "ErjVHGZaPPUau5h61tbXSDqABiJZnDFByc_g8B5vTwxkhBf9g==", + pm.GetHashUrl(true).spec()); + + pm.set_additional_query("&additional_query"); + EXPECT_EQ("http://info.prefix.com/foo/gethash?client=unittest&appver=1.0&" + "pver=2.2&additional_query", + pm.GetHashUrl(false).spec()); + EXPECT_EQ("http://info.prefix.com/foo/gethash?client=unittest&appver=1.0&" + "pver=2.2&additional_query&wrkey=AKEgNisjLl7iRYrjWHmpd_XwCiilxrw8" + "nNaYH47tiQ7pDe9cEErjVHGZaPPUau5h61tbXSDqABiJZnDFByc_g8B5vTwxkhBf" + "9g==", pm.GetHashUrl(true).spec()); +} + +TEST_F(SafeBrowsingProtocolManagerTest, TestUpdateUrl) { + SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, + kInfoUrlPrefix, kMacKeyUrlPrefix, false); + pm.version_ = kAppVer; + + EXPECT_EQ("http://info.prefix.com/foo/downloads?client=unittest&appver=1.0&" + "pver=2.2", pm.UpdateUrl(false).spec()); + EXPECT_EQ("http://info.prefix.com/foo/downloads?client=unittest&appver=1.0&" + "pver=2.2&wrkey=AKEgNisjLl7iRYrjWHmpd_XwCiilxrw8nNaYH47tiQ7pDe9cE" + "ErjVHGZaPPUau5h61tbXSDqABiJZnDFByc_g8B5vTwxkhBf9g==", + pm.UpdateUrl(true).spec()); + + pm.set_additional_query("&additional_query"); + EXPECT_EQ("http://info.prefix.com/foo/downloads?client=unittest&appver=1.0&" + "pver=2.2&additional_query", pm.UpdateUrl(false).spec()); + EXPECT_EQ("http://info.prefix.com/foo/downloads?client=unittest&appver=1.0&" + "pver=2.2&additional_query&wrkey=AKEgNisjLl7iRYrjWHmpd_XwCiilxrw8" + "nNaYH47tiQ7pDe9cEErjVHGZaPPUau5h61tbXSDqABiJZnDFByc_g8B5vTwxkhBf" + "9g==", pm.UpdateUrl(true).spec()); +} + +TEST_F(SafeBrowsingProtocolManagerTest, TestMalwareReportUrl) { + SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, + kInfoUrlPrefix, kMacKeyUrlPrefix, false); + pm.version_ = kAppVer; + + GURL malware_url("http://malware.url.com"); + GURL page_url("http://page.url.com"); + GURL referrer_url("http://referrer.url.com"); + EXPECT_EQ("http://info.prefix.com/foo/report?client=unittest&appver=1.0&" + "pver=2.2&evts=malblhit&evtd=http%3A%2F%2Fmalware.url.com%2F&" + "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer." + "url.com%2F", + pm.MalwareReportUrl(malware_url, page_url, referrer_url).spec()); + + pm.set_additional_query("&additional_query"); + EXPECT_EQ("http://info.prefix.com/foo/report?client=unittest&appver=1.0&" + "pver=2.2&additional_query&evts=malblhit&" + "evtd=http%3A%2F%2Fmalware.url.com%2F&" + "evtr=http%3A%2F%2Fpage.url.com%2F&evhr=http%3A%2F%2Freferrer." + "url.com%2F", + pm.MalwareReportUrl(malware_url, page_url, referrer_url).spec()); +} + +TEST_F(SafeBrowsingProtocolManagerTest, TestMacKeyUrl) { + SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, + kInfoUrlPrefix, kMacKeyUrlPrefix, false); + pm.version_ = kAppVer; + + EXPECT_EQ("https://key.prefix.com/bar/newkey?client=unittest&appver=1.0&" + "pver=2.2", pm.MacKeyUrl().spec()); + + pm.set_additional_query("&additional_query"); + EXPECT_EQ("https://key.prefix.com/bar/newkey?client=unittest&appver=1.0&" + "pver=2.2&additional_query", pm.MacKeyUrl().spec()); +} + +TEST_F(SafeBrowsingProtocolManagerTest, TestNextChunkUrl) { + SafeBrowsingProtocolManager pm(NULL, kClient, kClientKey, kWrappedKey, NULL, + kInfoUrlPrefix, kMacKeyUrlPrefix, false); + pm.version_ = kAppVer; + + std::string url_partial = "localhost:1234/foo/bar?foo"; + std::string url_http_full = "http://localhost:1234/foo/bar?foo"; + std::string url_https_full = "https://localhost:1234/foo/bar?foo"; + + EXPECT_EQ("http://localhost:1234/foo/bar?foo", + pm.NextChunkUrl(url_partial).spec()); + EXPECT_EQ("http://localhost:1234/foo/bar?foo", + pm.NextChunkUrl(url_http_full).spec()); + EXPECT_EQ("https://localhost:1234/foo/bar?foo", + pm.NextChunkUrl(url_https_full).spec()); + + pm.set_additional_query("&additional_query"); + EXPECT_EQ("http://localhost:1234/foo/bar?foo&additional_query", + pm.NextChunkUrl(url_partial).spec()); + EXPECT_EQ("http://localhost:1234/foo/bar?foo&additional_query", + pm.NextChunkUrl(url_http_full).spec()); + EXPECT_EQ("https://localhost:1234/foo/bar?foo&additional_query", + pm.NextChunkUrl(url_https_full).spec()); +} diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index ea5da62..a5aaa12 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc @@ -6,6 +6,7 @@ #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "base/callback.h" +#include "base/command_line.h" #include "base/path_service.h" #include "base/string_util.h" #include "chrome/browser/browser_process.h" @@ -20,6 +21,7 @@ #include "chrome/browser/chrome_thread.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/net/url_request_context_getter.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" @@ -32,6 +34,15 @@ using base::Time; using base::TimeDelta; +// The default URL prefix where browser fetches chunk updates, hashes, +// and reports malware. +static const char* const kSbDefaultInfoURLPrefix = + "http://safebrowsing.clients.google.com/safebrowsing"; + +// The default URL prefix where browser fetches MAC client key. +static const char* const kSbDefaultMacKeyURLPrefix = + "https://sb-ssl.google.com/safebrowsing"; + static Profile* GetDefaultProfile() { FilePath user_data_dir; PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); @@ -233,6 +244,11 @@ void SafeBrowsingService::UpdateFinished(bool update_succeeded) { } } +bool SafeBrowsingService::IsUpdateInProgress() const { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); + return update_in_progress_; +} + void SafeBrowsingService::OnBlockingPageDone( const std::vector<UnsafeResource>& resources, bool proceed) { @@ -345,12 +361,25 @@ void SafeBrowsingService::OnIOInitialize( std::string client_name("chromium"); #endif #endif + CommandLine* cmdline = CommandLine::ForCurrentProcess(); + bool disable_auto_update = cmdline->HasSwitch(switches::kSbDisableAutoUpdate); + std::string info_url_prefix = + cmdline->HasSwitch(switches::kSbInfoURLPrefix) ? + cmdline->GetSwitchValueASCII(switches::kSbInfoURLPrefix) : + kSbDefaultInfoURLPrefix; + std::string mackey_url_prefix = + cmdline->HasSwitch(switches::kSbMacKeyURLPrefix) ? + cmdline->GetSwitchValueASCII(switches::kSbMacKeyURLPrefix) : + kSbDefaultMacKeyURLPrefix; protocol_manager_ = new SafeBrowsingProtocolManager(this, client_name, client_key, wrapped_key, - request_context_getter); + request_context_getter, + info_url_prefix, + mackey_url_prefix, + disable_auto_update); // Balance the reference added by Start(). request_context_getter->Release(); diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h index 873dcb3..c8415b1 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.h +++ b/chrome/browser/safe_browsing/safe_browsing_service.h @@ -122,6 +122,8 @@ class SafeBrowsingService // 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, |