Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/safe_browsing/database_manager.h" | 5 #include "chrome/browser/safe_browsing/database_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 | |
| 7 #include "base/bind.h" | 9 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 9 #include "base/callback.h" | 11 #include "base/callback.h" |
| 10 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 11 #include "base/debug/leak_tracker.h" | 13 #include "base/debug/leak_tracker.h" |
| 12 #include "base/path_service.h" | 14 #include "base/path_service.h" |
| 13 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 14 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 15 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
| 16 #include "base/threading/thread_restrictions.h" | 18 #include "base/threading/thread_restrictions.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 28 #include "chrome/common/chrome_paths.h" | 30 #include "chrome/common/chrome_paths.h" |
| 29 #include "chrome/common/chrome_switches.h" | 31 #include "chrome/common/chrome_switches.h" |
| 30 #include "chrome/common/url_constants.h" | 32 #include "chrome/common/url_constants.h" |
| 31 #include "content/public/browser/browser_thread.h" | 33 #include "content/public/browser/browser_thread.h" |
| 32 #include "content/public/browser/notification_service.h" | 34 #include "content/public/browser/notification_service.h" |
| 33 | 35 |
| 34 using content::BrowserThread; | 36 using content::BrowserThread; |
| 35 | 37 |
| 36 namespace { | 38 namespace { |
| 37 | 39 |
| 38 // When download url check takes this long, client's callback will be called | 40 // Timeout for match checks, e.g. download URLs, hashes. |
| 39 // without waiting for the result. | 41 const int kCheckTimeoutMs = 10000; |
| 40 const int64 kDownloadUrlCheckTimeoutMs = 10000; | |
| 41 | |
| 42 // Similar to kDownloadUrlCheckTimeoutMs, but for download hash checks. | |
| 43 const int64 kDownloadHashCheckTimeoutMs = 10000; | |
| 44 | 42 |
| 45 // Records disposition information about the check. |hit| should be | 43 // Records disposition information about the check. |hit| should be |
| 46 // |true| if there were any prefix hits in |full_hashes|. | 44 // |true| if there were any prefix hits in |full_hashes|. |
| 47 void RecordGetHashCheckStatus( | 45 void RecordGetHashCheckStatus( |
| 48 bool hit, | 46 bool hit, |
| 49 bool is_download, | 47 safe_browsing_util::ListType check_type, |
| 50 const std::vector<SBFullHashResult>& full_hashes) { | 48 const std::vector<SBFullHashResult>& full_hashes) { |
| 51 SafeBrowsingProtocolManager::ResultType result; | 49 SafeBrowsingProtocolManager::ResultType result; |
| 52 if (full_hashes.empty()) { | 50 if (full_hashes.empty()) { |
| 53 result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_EMPTY; | 51 result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_EMPTY; |
| 54 } else if (hit) { | 52 } else if (hit) { |
| 55 result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_HIT; | 53 result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_HIT; |
| 56 } else { | 54 } else { |
| 57 result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_MISS; | 55 result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_MISS; |
| 58 } | 56 } |
| 57 bool is_download = check_type == safe_browsing_util::BINURL || | |
| 58 check_type == safe_browsing_util::BINHASH; | |
| 59 SafeBrowsingProtocolManager::RecordGetHashResult(is_download, result); | 59 SafeBrowsingProtocolManager::RecordGetHashResult(is_download, result); |
| 60 } | 60 } |
| 61 | 61 |
| 62 } // namespace | 62 } // namespace |
| 63 | 63 |
| 64 SafeBrowsingDatabaseManager::SafeBrowsingCheck::SafeBrowsingCheck() | 64 SafeBrowsingDatabaseManager::SafeBrowsingCheck::SafeBrowsingCheck( |
| 65 : full_hash(NULL), | 65 const std::vector<GURL>& urls, |
| 66 client(NULL), | 66 const std::vector<SBFullHash>& full_hashes, |
| 67 Client* client, | |
| 68 safe_browsing_util::ListType check_type) | |
| 69 : urls(urls), | |
| 70 url_results(urls.size(), SB_THREAT_TYPE_SAFE), | |
| 71 full_hashes(full_hashes), | |
| 72 full_hash_results(full_hashes.size(), SB_THREAT_TYPE_SAFE), | |
| 73 client(client), | |
| 67 need_get_hash(false), | 74 need_get_hash(false), |
| 68 threat_type(SB_THREAT_TYPE_SAFE), | 75 check_type(check_type), |
| 69 is_download(false), | |
| 70 timeout_factory_(NULL) { | 76 timeout_factory_(NULL) { |
| 77 DCHECK(urls.empty() || full_hashes.empty()); | |
| 78 DCHECK(!urls.empty() || !full_hashes.empty()); | |
|
Scott Hess - ex-Googler
2013/01/17 19:24:42
I don't think the meaning of the check is obvious,
not at google - send to devlin
2013/01/18 01:02:42
Done.
| |
| 71 } | 79 } |
| 72 | 80 |
| 73 SafeBrowsingDatabaseManager::SafeBrowsingCheck::~SafeBrowsingCheck() {} | 81 SafeBrowsingDatabaseManager::SafeBrowsingCheck::~SafeBrowsingCheck() {} |
| 74 | 82 |
| 75 void SafeBrowsingDatabaseManager::Client::OnSafeBrowsingResult( | 83 void SafeBrowsingDatabaseManager::Client::OnSafeBrowsingResult( |
| 76 const SafeBrowsingCheck& check) { | 84 const SafeBrowsingCheck& check) { |
| 77 if (!check.urls.empty()) { | 85 if (!check.urls.empty()) { |
| 78 | 86 DCHECK(check.full_hashes.empty()); |
| 79 DCHECK(!check.full_hash.get()); | 87 switch (check.check_type) { |
| 80 if (!check.is_download) { | 88 case safe_browsing_util::MALWARE: |
| 81 DCHECK_EQ(1U, check.urls.size()); | 89 case safe_browsing_util::PHISH: |
| 82 OnCheckBrowseUrlResult(check.urls[0], check.threat_type); | 90 DCHECK_EQ(1u, check.urls.size()); |
| 83 } else { | 91 DCHECK_EQ(1u, check.url_results.size()); |
| 84 OnCheckDownloadUrlResult(check.urls, check.threat_type); | 92 OnCheckBrowseUrlResult(check.urls[0], check.url_results[0]); |
| 93 break; | |
| 94 case safe_browsing_util::BINURL: | |
| 95 DCHECK_EQ(check.urls.size(), check.url_results.size()); | |
| 96 OnCheckDownloadUrlResult( | |
| 97 check.urls, | |
| 98 *std::max_element(check.url_results.begin(), | |
| 99 check.url_results.end())); | |
| 100 break; | |
| 101 default: | |
| 102 NOTREACHED(); | |
| 85 } | 103 } |
| 86 } else if (check.full_hash.get()) { | 104 } else if (!check.full_hashes.empty()) { |
| 87 OnCheckDownloadHashResult( | 105 switch (check.check_type) { |
| 88 safe_browsing_util::SBFullHashToString(*check.full_hash), | 106 case safe_browsing_util::BINHASH: |
| 89 check.threat_type); | 107 DCHECK_EQ(1u, check.full_hashes.size()); |
| 108 DCHECK_EQ(1u, check.full_hash_results.size()); | |
| 109 OnCheckDownloadHashResult( | |
| 110 safe_browsing_util::SBFullHashToString(check.full_hashes[0]), | |
| 111 check.full_hash_results[0]); | |
| 112 break; | |
| 113 default: | |
| 114 NOTREACHED(); | |
| 115 } | |
| 90 } else { | 116 } else { |
| 91 NOTREACHED(); | 117 NOTREACHED(); |
| 92 } | 118 } |
| 93 } | 119 } |
| 94 | 120 |
| 95 SafeBrowsingDatabaseManager::SafeBrowsingDatabaseManager( | 121 SafeBrowsingDatabaseManager::SafeBrowsingDatabaseManager( |
| 96 const scoped_refptr<SafeBrowsingService>& service) | 122 const scoped_refptr<SafeBrowsingService>& service) |
| 97 : sb_service_(service), | 123 : sb_service_(service), |
| 98 database_(NULL), | 124 database_(NULL), |
| 99 enabled_(false), | 125 enabled_(false), |
| 100 enable_download_protection_(false), | 126 enable_download_protection_(false), |
| 101 enable_csd_whitelist_(false), | 127 enable_csd_whitelist_(false), |
| 102 enable_download_whitelist_(false), | 128 enable_download_whitelist_(false), |
| 103 update_in_progress_(false), | 129 update_in_progress_(false), |
| 104 database_update_in_progress_(false), | 130 database_update_in_progress_(false), |
| 105 closing_database_(false), | 131 closing_database_(false), |
| 106 download_urlcheck_timeout_ms_(kDownloadUrlCheckTimeoutMs), | 132 check_timeout_(base::TimeDelta::FromMilliseconds(kCheckTimeoutMs)) { |
| 107 download_hashcheck_timeout_ms_(kDownloadHashCheckTimeoutMs) { | |
| 108 DCHECK(sb_service_ != NULL); | 133 DCHECK(sb_service_ != NULL); |
| 109 | 134 |
| 110 CommandLine* cmdline = CommandLine::ForCurrentProcess(); | 135 CommandLine* cmdline = CommandLine::ForCurrentProcess(); |
| 111 enable_download_protection_ = | 136 enable_download_protection_ = |
| 112 !cmdline->HasSwitch(switches::kSbDisableDownloadProtection); | 137 !cmdline->HasSwitch(switches::kSbDisableDownloadProtection); |
| 113 | 138 |
| 114 // We only download the csd-whitelist if client-side phishing detection is | 139 // We only download the csd-whitelist if client-side phishing detection is |
| 115 // enabled. | 140 // enabled. |
| 116 enable_csd_whitelist_ = | 141 enable_csd_whitelist_ = |
| 117 !cmdline->HasSwitch(switches::kDisableClientSidePhishingDetection); | 142 !cmdline->HasSwitch(switches::kDisableClientSidePhishingDetection); |
| 118 | 143 |
| 119 // TODO(noelutz): remove this boolean variable since it should always be true | 144 // TODO(noelutz): remove this boolean variable since it should always be true |
| 120 // if SafeBrowsing is enabled. Unfortunately, we have no test data for this | 145 // if SafeBrowsing is enabled. Unfortunately, we have no test data for this |
| 121 // list right now. This means that we need to be able to disable this list | 146 // list right now. This means that we need to be able to disable this list |
| 122 // for the SafeBrowsing test to pass. | 147 // for the SafeBrowsing test to pass. |
| 123 enable_download_whitelist_ = enable_csd_whitelist_; | 148 enable_download_whitelist_ = enable_csd_whitelist_; |
| 124 | |
| 125 } | 149 } |
| 126 | 150 |
| 127 SafeBrowsingDatabaseManager::~SafeBrowsingDatabaseManager() { | 151 SafeBrowsingDatabaseManager::~SafeBrowsingDatabaseManager() { |
| 128 // We should have already been shut down. If we're still enabled, then the | 152 // We should have already been shut down. If we're still enabled, then the |
| 129 // database isn't going to be closed properly, which could lead to corruption. | 153 // database isn't going to be closed properly, which could lead to corruption. |
| 130 DCHECK(!enabled_); | 154 DCHECK(!enabled_); |
| 131 } | 155 } |
| 132 | 156 |
| 133 bool SafeBrowsingDatabaseManager::CanCheckUrl(const GURL& url) const { | 157 bool SafeBrowsingDatabaseManager::CanCheckUrl(const GURL& url) const { |
| 134 return url.SchemeIs(chrome::kFtpScheme) || | 158 return url.SchemeIs(chrome::kFtpScheme) || |
| 135 url.SchemeIs(chrome::kHttpScheme) || | 159 url.SchemeIs(chrome::kHttpScheme) || |
| 136 url.SchemeIs(chrome::kHttpsScheme); | 160 url.SchemeIs(chrome::kHttpsScheme); |
| 137 } | 161 } |
| 138 | 162 |
| 139 bool SafeBrowsingDatabaseManager::CheckDownloadUrl( | 163 bool SafeBrowsingDatabaseManager::CheckDownloadUrl( |
| 140 const std::vector<GURL>& url_chain, | 164 const std::vector<GURL>& url_chain, |
| 141 Client* client) { | 165 Client* client) { |
| 142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 143 if (!enabled_ || !enable_download_protection_) | 167 if (!enabled_ || !enable_download_protection_) |
| 144 return true; | 168 return true; |
| 145 | 169 |
| 146 // We need to check the database for url prefix, and later may fetch the url | 170 // We need to check the database for url prefix, and later may fetch the url |
| 147 // from the safebrowsing backends. These need to be asynchronous. | 171 // from the safebrowsing backends. These need to be asynchronous. |
| 148 SafeBrowsingCheck* check = new SafeBrowsingCheck(); | 172 SafeBrowsingCheck* check = new SafeBrowsingCheck(url_chain, |
| 149 check->urls = url_chain; | 173 std::vector<SBFullHash>(), |
| 150 StartDownloadCheck( | 174 client, |
| 175 safe_browsing_util::BINURL); | |
| 176 StartSafeBrowsingCheck( | |
| 151 check, | 177 check, |
| 152 client, | |
| 153 base::Bind(&SafeBrowsingDatabaseManager::CheckDownloadUrlOnSBThread, this, | 178 base::Bind(&SafeBrowsingDatabaseManager::CheckDownloadUrlOnSBThread, this, |
| 154 check), | 179 check)); |
| 155 download_urlcheck_timeout_ms_); | |
| 156 return false; | 180 return false; |
| 157 } | 181 } |
| 158 | 182 |
| 159 bool SafeBrowsingDatabaseManager::CheckDownloadHash( | 183 bool SafeBrowsingDatabaseManager::CheckDownloadHash( |
| 160 const std::string& full_hash, | 184 const std::string& full_hash, |
| 161 Client* client) { | 185 Client* client) { |
| 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 163 DCHECK(!full_hash.empty()); | 187 DCHECK(!full_hash.empty()); |
| 164 if (!enabled_ || !enable_download_protection_ || full_hash.empty()) | 188 if (!enabled_ || !enable_download_protection_ || full_hash.empty()) |
| 165 return true; | 189 return true; |
| 166 | 190 |
| 167 // We need to check the database for url prefix, and later may fetch the url | 191 // We need to check the database for url prefix, and later may fetch the url |
| 168 // from the safebrowsing backends. These need to be asynchronous. | 192 // from the safebrowsing backends. These need to be asynchronous. |
| 169 SafeBrowsingCheck* check = new SafeBrowsingCheck(); | 193 std::vector<SBFullHash> full_hashes( |
| 170 check->full_hash.reset(new SBFullHash); | 194 1, safe_browsing_util::StringToSBFullHash(full_hash)); |
| 171 safe_browsing_util::StringToSBFullHash(full_hash, check->full_hash.get()); | 195 SafeBrowsingCheck* check = new SafeBrowsingCheck(std::vector<GURL>(), |
| 172 StartDownloadCheck( | 196 full_hashes, |
| 197 client, | |
| 198 safe_browsing_util::BINHASH); | |
| 199 StartSafeBrowsingCheck( | |
| 173 check, | 200 check, |
| 174 client, | |
| 175 base::Bind(&SafeBrowsingDatabaseManager::CheckDownloadHashOnSBThread,this, | 201 base::Bind(&SafeBrowsingDatabaseManager::CheckDownloadHashOnSBThread,this, |
| 176 check), | 202 check)); |
| 177 download_hashcheck_timeout_ms_); | |
| 178 return false; | 203 return false; |
| 179 } | 204 } |
| 180 | 205 |
| 181 bool SafeBrowsingDatabaseManager::MatchCsdWhitelistUrl(const GURL& url) { | 206 bool SafeBrowsingDatabaseManager::MatchCsdWhitelistUrl(const GURL& url) { |
| 182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 183 if (!enabled_ || !enable_csd_whitelist_ || !MakeDatabaseAvailable()) { | 208 if (!enabled_ || !enable_csd_whitelist_ || !MakeDatabaseAvailable()) { |
| 184 // There is something funky going on here -- for example, perhaps the user | 209 // There is something funky going on here -- for example, perhaps the user |
| 185 // has not restarted since enabling metrics reporting, so we haven't | 210 // has not restarted since enabling metrics reporting, so we haven't |
| 186 // enabled the csd whitelist yet. Just to be safe we return true in this | 211 // enabled the csd whitelist yet. Just to be safe we return true in this |
| 187 // case. | 212 // case. |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 213 if (!enabled_) | 238 if (!enabled_) |
| 214 return true; | 239 return true; |
| 215 | 240 |
| 216 if (!CanCheckUrl(url)) | 241 if (!CanCheckUrl(url)) |
| 217 return true; | 242 return true; |
| 218 | 243 |
| 219 const base::TimeTicks start = base::TimeTicks::Now(); | 244 const base::TimeTicks start = base::TimeTicks::Now(); |
| 220 if (!MakeDatabaseAvailable()) { | 245 if (!MakeDatabaseAvailable()) { |
| 221 QueuedCheck check; | 246 QueuedCheck check; |
| 247 check.check_type = safe_browsing_util::MALWARE; // or PHISH | |
| 222 check.client = client; | 248 check.client = client; |
| 223 check.url = url; | 249 check.url = url; |
| 224 check.start = start; | 250 check.start = start; |
| 225 queued_checks_.push_back(check); | 251 queued_checks_.push_back(check); |
| 226 return false; | 252 return false; |
| 227 } | 253 } |
| 228 | 254 |
| 229 std::string list; | 255 std::string list; |
| 230 std::vector<SBPrefix> prefix_hits; | 256 std::vector<SBPrefix> prefix_hits; |
| 231 std::vector<SBFullHashResult> full_hits; | 257 std::vector<SBFullHashResult> full_hits; |
| 232 | 258 |
| 233 bool prefix_match = | 259 bool prefix_match = |
| 234 database_->ContainsBrowseUrl(url, &list, &prefix_hits, &full_hits, | 260 database_->ContainsBrowseUrl(url, &list, &prefix_hits, &full_hits, |
| 235 sb_service_->protocol_manager()->last_update()); | 261 sb_service_->protocol_manager()->last_update()); |
| 236 | 262 |
| 237 UMA_HISTOGRAM_TIMES("SB2.FilterCheck", base::TimeTicks::Now() - start); | 263 UMA_HISTOGRAM_TIMES("SB2.FilterCheck", base::TimeTicks::Now() - start); |
| 238 | 264 |
| 239 if (!prefix_match) | 265 if (!prefix_match) |
| 240 return true; // URL is okay. | 266 return true; // URL is okay. |
| 241 | 267 |
| 242 // Needs to be asynchronous, since we could be in the constructor of a | 268 // Needs to be asynchronous, since we could be in the constructor of a |
| 243 // ResourceDispatcherHost event handler which can't pause there. | 269 // ResourceDispatcherHost event handler which can't pause there. |
| 244 SafeBrowsingCheck* check = new SafeBrowsingCheck(); | 270 SafeBrowsingCheck* check = new SafeBrowsingCheck(std::vector<GURL>(1, url), |
| 245 check->urls.push_back(url); | 271 std::vector<SBFullHash>(), |
| 246 check->client = client; | 272 client, |
| 247 check->threat_type = SB_THREAT_TYPE_SAFE; | 273 safe_browsing_util::MALWARE); |
| 248 check->is_download = false; | |
| 249 check->need_get_hash = full_hits.empty(); | 274 check->need_get_hash = full_hits.empty(); |
| 250 check->prefix_hits.swap(prefix_hits); | 275 check->prefix_hits.swap(prefix_hits); |
| 251 check->full_hits.swap(full_hits); | 276 check->full_hits.swap(full_hits); |
| 252 checks_.insert(check); | 277 checks_.insert(check); |
| 253 | 278 |
| 254 BrowserThread::PostTask( | 279 BrowserThread::PostTask( |
| 255 BrowserThread::IO, FROM_HERE, | 280 BrowserThread::IO, FROM_HERE, |
| 256 base::Bind(&SafeBrowsingDatabaseManager::OnCheckDone, this, check)); | 281 base::Bind(&SafeBrowsingDatabaseManager::OnCheckDone, this, check)); |
| 257 | 282 |
| 258 return false; | 283 return false; |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 if (!enabled_) | 421 if (!enabled_) |
| 397 return; | 422 return; |
| 398 | 423 |
| 399 enabled_ = false; | 424 enabled_ = false; |
| 400 | 425 |
| 401 // Delete queued checks, calling back any clients with 'SB_THREAT_TYPE_SAFE'. | 426 // Delete queued checks, calling back any clients with 'SB_THREAT_TYPE_SAFE'. |
| 402 // If we don't do this here we may fail to close the database below. | 427 // If we don't do this here we may fail to close the database below. |
| 403 while (!queued_checks_.empty()) { | 428 while (!queued_checks_.empty()) { |
| 404 QueuedCheck queued = queued_checks_.front(); | 429 QueuedCheck queued = queued_checks_.front(); |
| 405 if (queued.client) { | 430 if (queued.client) { |
| 406 SafeBrowsingCheck sb_check; | 431 SafeBrowsingCheck sb_check(std::vector<GURL>(1, queued.url), |
| 407 sb_check.urls.push_back(queued.url); | 432 std::vector<SBFullHash>(), |
| 408 sb_check.client = queued.client; | 433 queued.client, |
| 409 sb_check.threat_type = SB_THREAT_TYPE_SAFE; | 434 queued.check_type); |
| 410 queued.client->OnSafeBrowsingResult(sb_check); | 435 queued.client->OnSafeBrowsingResult(sb_check); |
| 411 } | 436 } |
| 412 queued_checks_.pop_front(); | 437 queued_checks_.pop_front(); |
| 413 } | 438 } |
| 414 | 439 |
| 415 // Close the database. We don't simply DeleteSoon() because if a close is | 440 // Close the database. We don't simply DeleteSoon() because if a close is |
| 416 // already pending, we'll double-free, and we don't set |database_| to NULL | 441 // already pending, we'll double-free, and we don't set |database_| to NULL |
| 417 // because if there is still anything running on the db thread, it could | 442 // because if there is still anything running on the db thread, it could |
| 418 // create a new database object (via GetDatabase()) that would then leak. | 443 // create a new database object (via GetDatabase()) that would then leak. |
| 419 CloseDatabase(); | 444 CloseDatabase(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 431 safe_browsing_thread_.reset(); | 456 safe_browsing_thread_.reset(); |
| 432 } | 457 } |
| 433 | 458 |
| 434 // Delete pending checks, calling back any clients with 'SB_THREAT_TYPE_SAFE'. | 459 // Delete pending checks, calling back any clients with 'SB_THREAT_TYPE_SAFE'. |
| 435 // We have to do this after the db thread returns because methods on it can | 460 // We have to do this after the db thread returns because methods on it can |
| 436 // have copies of these pointers, so deleting them might lead to accessing | 461 // have copies of these pointers, so deleting them might lead to accessing |
| 437 // garbage. | 462 // garbage. |
| 438 for (CurrentChecks::iterator it = checks_.begin(); | 463 for (CurrentChecks::iterator it = checks_.begin(); |
| 439 it != checks_.end(); ++it) { | 464 it != checks_.end(); ++it) { |
| 440 SafeBrowsingCheck* check = *it; | 465 SafeBrowsingCheck* check = *it; |
| 441 if (check->client) { | 466 if (check->client) |
| 442 check->threat_type = SB_THREAT_TYPE_SAFE; | |
| 443 check->client->OnSafeBrowsingResult(*check); | 467 check->client->OnSafeBrowsingResult(*check); |
| 444 } | |
| 445 } | 468 } |
| 446 STLDeleteElements(&checks_); | 469 STLDeleteElements(&checks_); |
| 447 | 470 |
| 448 gethash_requests_.clear(); | 471 gethash_requests_.clear(); |
| 449 } | 472 } |
| 450 | 473 |
| 451 bool SafeBrowsingDatabaseManager::DatabaseAvailable() const { | 474 bool SafeBrowsingDatabaseManager::DatabaseAvailable() const { |
| 452 base::AutoLock lock(database_lock_); | 475 base::AutoLock lock(database_lock_); |
| 453 return !closing_database_ && (database_ != NULL); | 476 return !closing_database_ && (database_ != NULL); |
| 454 } | 477 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 554 GetHashRequestors requestors; | 577 GetHashRequestors requestors; |
| 555 requestors.push_back(check); | 578 requestors.push_back(check); |
| 556 gethash_requests_[prefix] = requestors; | 579 gethash_requests_[prefix] = requestors; |
| 557 } | 580 } |
| 558 | 581 |
| 559 // Reset the start time so that we can measure the network time without the | 582 // Reset the start time so that we can measure the network time without the |
| 560 // database time. | 583 // database time. |
| 561 check->start = base::TimeTicks::Now(); | 584 check->start = base::TimeTicks::Now(); |
| 562 // Note: If |this| is deleted or stopped, the protocol_manager will | 585 // Note: If |this| is deleted or stopped, the protocol_manager will |
| 563 // be destroyed as well - hence it's OK to do unretained in this case. | 586 // be destroyed as well - hence it's OK to do unretained in this case. |
| 587 bool is_download = check->check_type == safe_browsing_util::BINURL || | |
| 588 check->check_type == safe_browsing_util::BINHASH; | |
| 564 sb_service_->protocol_manager()->GetFullHash( | 589 sb_service_->protocol_manager()->GetFullHash( |
| 565 check->prefix_hits, | 590 check->prefix_hits, |
| 566 base::Bind(&SafeBrowsingDatabaseManager::HandleGetHashResults, | 591 base::Bind(&SafeBrowsingDatabaseManager::HandleGetHashResults, |
| 567 base::Unretained(this), | 592 base::Unretained(this), |
| 568 check), | 593 check), |
| 569 check->is_download); | 594 is_download); |
| 570 } else { | 595 } else { |
| 571 // We may have cached results for previous GetHash queries. Since | 596 // We may have cached results for previous GetHash queries. Since |
| 572 // this data comes from cache, don't histogram hits. | 597 // this data comes from cache, don't histogram hits. |
| 573 HandleOneCheck(check, check->full_hits); | 598 HandleOneCheck(check, check->full_hits); |
| 574 } | 599 } |
| 575 } | 600 } |
| 576 | 601 |
| 577 void SafeBrowsingDatabaseManager::GetAllChunksFromDatabase( | 602 void SafeBrowsingDatabaseManager::GetAllChunksFromDatabase( |
| 578 GetChunksCallback callback) { | 603 GetChunksCallback callback) { |
| 579 DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); | 604 DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 623 // below will add the check back to the queue, and we'll infinite-loop. | 648 // below will add the check back to the queue, and we'll infinite-loop. |
| 624 DCHECK(DatabaseAvailable()); | 649 DCHECK(DatabaseAvailable()); |
| 625 while (!queued_checks_.empty()) { | 650 while (!queued_checks_.empty()) { |
| 626 QueuedCheck check = queued_checks_.front(); | 651 QueuedCheck check = queued_checks_.front(); |
| 627 DCHECK(!check.start.is_null()); | 652 DCHECK(!check.start.is_null()); |
| 628 HISTOGRAM_TIMES("SB.QueueDelay", base::TimeTicks::Now() - check.start); | 653 HISTOGRAM_TIMES("SB.QueueDelay", base::TimeTicks::Now() - check.start); |
| 629 // If CheckUrl() determines the URL is safe immediately, it doesn't call the | 654 // If CheckUrl() determines the URL is safe immediately, it doesn't call the |
| 630 // client's handler function (because normally it's being directly called by | 655 // client's handler function (because normally it's being directly called by |
| 631 // the client). Since we're not the client, we have to convey this result. | 656 // the client). Since we're not the client, we have to convey this result. |
| 632 if (check.client && CheckBrowseUrl(check.url, check.client)) { | 657 if (check.client && CheckBrowseUrl(check.url, check.client)) { |
| 633 SafeBrowsingCheck sb_check; | 658 SafeBrowsingCheck sb_check(std::vector<GURL>(1, check.url), |
| 634 sb_check.urls.push_back(check.url); | 659 std::vector<SBFullHash>(), |
| 635 sb_check.client = check.client; | 660 check.client, |
| 636 sb_check.threat_type = SB_THREAT_TYPE_SAFE; | 661 check.check_type); |
| 637 check.client->OnSafeBrowsingResult(sb_check); | 662 check.client->OnSafeBrowsingResult(sb_check); |
| 638 } | 663 } |
| 639 queued_checks_.pop_front(); | 664 queued_checks_.pop_front(); |
| 640 } | 665 } |
| 641 } | 666 } |
| 642 | 667 |
| 643 void SafeBrowsingDatabaseManager::AddDatabaseChunks( | 668 void SafeBrowsingDatabaseManager::AddDatabaseChunks( |
| 644 const std::string& list_name, SBChunkList* chunks, | 669 const std::string& list_name, SBChunkList* chunks, |
| 645 AddChunksCallback callback) { | 670 AddChunksCallback callback) { |
| 646 DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); | 671 DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 731 const std::vector<SBPrefix>& prefixes, | 756 const std::vector<SBPrefix>& prefixes, |
| 732 const std::vector<SBFullHashResult>& full_hashes) { | 757 const std::vector<SBFullHashResult>& full_hashes) { |
| 733 DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); | 758 DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); |
| 734 GetDatabase()->CacheHashResults(prefixes, full_hashes); | 759 GetDatabase()->CacheHashResults(prefixes, full_hashes); |
| 735 } | 760 } |
| 736 | 761 |
| 737 void SafeBrowsingDatabaseManager::OnHandleGetHashResults( | 762 void SafeBrowsingDatabaseManager::OnHandleGetHashResults( |
| 738 SafeBrowsingCheck* check, | 763 SafeBrowsingCheck* check, |
| 739 const std::vector<SBFullHashResult>& full_hashes) { | 764 const std::vector<SBFullHashResult>& full_hashes) { |
| 740 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 765 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 741 bool is_download = check->is_download; | 766 safe_browsing_util::ListType check_type = check->check_type; |
| 742 SBPrefix prefix = check->prefix_hits[0]; | 767 SBPrefix prefix = check->prefix_hits[0]; |
| 743 GetHashRequests::iterator it = gethash_requests_.find(prefix); | 768 GetHashRequests::iterator it = gethash_requests_.find(prefix); |
| 744 if (check->prefix_hits.size() > 1 || it == gethash_requests_.end()) { | 769 if (check->prefix_hits.size() > 1 || it == gethash_requests_.end()) { |
| 745 const bool hit = HandleOneCheck(check, full_hashes); | 770 const bool hit = HandleOneCheck(check, full_hashes); |
| 746 RecordGetHashCheckStatus(hit, is_download, full_hashes); | 771 RecordGetHashCheckStatus(hit, check_type, full_hashes); |
| 747 return; | 772 return; |
| 748 } | 773 } |
| 749 | 774 |
| 750 // Call back all interested parties, noting if any has a hit. | 775 // Call back all interested parties, noting if any has a hit. |
| 751 GetHashRequestors& requestors = it->second; | 776 GetHashRequestors& requestors = it->second; |
| 752 bool hit = false; | 777 bool hit = false; |
| 753 for (GetHashRequestors::iterator r = requestors.begin(); | 778 for (GetHashRequestors::iterator r = requestors.begin(); |
| 754 r != requestors.end(); ++r) { | 779 r != requestors.end(); ++r) { |
| 755 if (HandleOneCheck(*r, full_hashes)) | 780 if (HandleOneCheck(*r, full_hashes)) |
| 756 hit = true; | 781 hit = true; |
| 757 } | 782 } |
| 758 RecordGetHashCheckStatus(hit, is_download, full_hashes); | 783 RecordGetHashCheckStatus(hit, check_type, full_hashes); |
| 759 | 784 |
| 760 gethash_requests_.erase(it); | 785 gethash_requests_.erase(it); |
| 761 } | 786 } |
| 762 | 787 |
| 763 bool SafeBrowsingDatabaseManager::HandleOneCheck( | 788 bool SafeBrowsingDatabaseManager::HandleOneCheck( |
| 764 SafeBrowsingCheck* check, | 789 SafeBrowsingCheck* check, |
| 765 const std::vector<SBFullHashResult>& full_hashes) { | 790 const std::vector<SBFullHashResult>& full_hashes) { |
| 766 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 791 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 767 DCHECK(check); | 792 DCHECK(check); |
| 768 | 793 |
| 769 // Always calculate the index, for recording hits. | 794 bool is_threat = false; |
| 770 int index = -1; | 795 |
| 771 if (!check->urls.empty()) { | 796 for (size_t i = 0; i < check->urls.size(); ++i) { |
| 772 for (size_t i = 0; i < check->urls.size(); ++i) { | 797 int index = |
| 773 index = safe_browsing_util::GetUrlHashIndex(check->urls[i], full_hashes); | 798 safe_browsing_util::GetUrlHashIndex(check->urls[i], full_hashes); |
| 774 if (index != -1) | 799 if (index == -1) |
| 775 break; | 800 continue; |
| 801 SBThreatType threat = | |
| 802 GetThreatTypeFromListname(full_hashes[index].list_name); | |
| 803 if (threat != SB_THREAT_TYPE_SAFE) { | |
| 804 check->url_results[i] = threat; | |
| 805 is_threat = true; | |
| 806 } else { | |
| 807 NOTREACHED(); | |
| 776 } | 808 } |
| 777 } else { | |
| 778 index = safe_browsing_util::GetHashIndex(*(check->full_hash), full_hashes); | |
| 779 } | 809 } |
| 780 | 810 |
| 781 // |client| is NULL if the request was cancelled. | 811 for (size_t i = 0; i < check->full_hashes.size(); ++i) { |
| 782 if (check->client) { | 812 int index = |
| 783 check->threat_type = SB_THREAT_TYPE_SAFE; | 813 safe_browsing_util::GetHashIndex(check->full_hashes[i], full_hashes); |
| 784 if (index != -1) { | 814 if (index == -1) |
| 785 check->threat_type = GetThreatTypeFromListname( | 815 continue; |
| 786 full_hashes[index].list_name); | 816 SBThreatType threat = |
| 817 GetThreatTypeFromListname(full_hashes[index].list_name); | |
| 818 if (threat != SB_THREAT_TYPE_SAFE) { | |
| 819 check->full_hash_results[i] = threat; | |
| 820 is_threat = true; | |
| 821 } else { | |
| 822 NOTREACHED(); | |
| 787 } | 823 } |
| 788 } | 824 } |
| 825 | |
| 789 SafeBrowsingCheckDone(check); | 826 SafeBrowsingCheckDone(check); |
| 790 return (index != -1); | 827 return is_threat; |
| 791 } | 828 } |
| 792 | 829 |
| 793 void SafeBrowsingDatabaseManager::CheckDownloadHashOnSBThread( | 830 void SafeBrowsingDatabaseManager::CheckDownloadHashOnSBThread( |
| 794 SafeBrowsingCheck* check) { | 831 SafeBrowsingCheck* check) { |
| 795 DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); | 832 DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); |
| 796 DCHECK(enable_download_protection_); | 833 DCHECK(enable_download_protection_); |
| 797 | 834 |
| 798 if (!database_->ContainsDownloadHashPrefix(check->full_hash->prefix)) { | 835 DCHECK_EQ(1u, check->full_hashes.size()); |
| 836 SBFullHash full_hash = check->full_hashes[0]; | |
| 837 | |
| 838 if (!database_->ContainsDownloadHashPrefix(full_hash.prefix)) { | |
| 799 // Good, we don't have hash for this url prefix. | 839 // Good, we don't have hash for this url prefix. |
| 800 check->threat_type = SB_THREAT_TYPE_SAFE; | |
| 801 BrowserThread::PostTask( | 840 BrowserThread::PostTask( |
| 802 BrowserThread::IO, FROM_HERE, | 841 BrowserThread::IO, FROM_HERE, |
| 803 base::Bind(&SafeBrowsingDatabaseManager::CheckDownloadHashDone, this, | 842 base::Bind(&SafeBrowsingDatabaseManager::CheckDownloadHashDone, this, |
| 804 check)); | 843 check)); |
| 805 return; | 844 return; |
| 806 } | 845 } |
| 807 | 846 |
| 808 check->need_get_hash = true; | 847 check->need_get_hash = true; |
| 809 check->prefix_hits.push_back(check->full_hash->prefix); | 848 check->prefix_hits.push_back(full_hash.prefix); |
| 810 BrowserThread::PostTask( | 849 BrowserThread::PostTask( |
| 811 BrowserThread::IO, FROM_HERE, | 850 BrowserThread::IO, FROM_HERE, |
| 812 base::Bind(&SafeBrowsingDatabaseManager::OnCheckDone, this, check)); | 851 base::Bind(&SafeBrowsingDatabaseManager::OnCheckDone, this, check)); |
| 813 } | 852 } |
| 814 | 853 |
| 815 void SafeBrowsingDatabaseManager::CheckDownloadUrlOnSBThread( | 854 void SafeBrowsingDatabaseManager::CheckDownloadUrlOnSBThread( |
| 816 SafeBrowsingCheck* check) { | 855 SafeBrowsingCheck* check) { |
| 817 DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); | 856 DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); |
| 818 DCHECK(enable_download_protection_); | 857 DCHECK(enable_download_protection_); |
| 819 | 858 |
| 820 std::vector<SBPrefix> prefix_hits; | 859 std::vector<SBPrefix> prefix_hits; |
| 821 | 860 |
| 822 if (!database_->ContainsDownloadUrl(check->urls, &prefix_hits)) { | 861 if (!database_->ContainsDownloadUrl(check->urls, &prefix_hits)) { |
| 823 // Good, we don't have hash for this url prefix. | 862 // Good, we don't have hash for this url prefix. |
| 824 check->threat_type = SB_THREAT_TYPE_SAFE; | |
| 825 BrowserThread::PostTask( | 863 BrowserThread::PostTask( |
| 826 BrowserThread::IO, FROM_HERE, | 864 BrowserThread::IO, FROM_HERE, |
| 827 base::Bind(&SafeBrowsingDatabaseManager::CheckDownloadUrlDone, this, | 865 base::Bind(&SafeBrowsingDatabaseManager::CheckDownloadUrlDone, this, |
| 828 check)); | 866 check)); |
| 829 return; | 867 return; |
| 830 } | 868 } |
| 831 | 869 |
| 832 check->need_get_hash = true; | 870 check->need_get_hash = true; |
| 833 check->prefix_hits.clear(); | 871 check->prefix_hits.clear(); |
| 834 check->prefix_hits = prefix_hits; | 872 check->prefix_hits = prefix_hits; |
| 835 BrowserThread::PostTask( | 873 BrowserThread::PostTask( |
| 836 BrowserThread::IO, FROM_HERE, | 874 BrowserThread::IO, FROM_HERE, |
| 837 base::Bind(&SafeBrowsingDatabaseManager::OnCheckDone, this, check)); | 875 base::Bind(&SafeBrowsingDatabaseManager::OnCheckDone, this, check)); |
| 838 } | 876 } |
| 839 | 877 |
| 840 void SafeBrowsingDatabaseManager::TimeoutCallback(SafeBrowsingCheck* check) { | 878 void SafeBrowsingDatabaseManager::TimeoutCallback(SafeBrowsingCheck* check) { |
| 841 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 879 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 842 DCHECK(check); | 880 DCHECK(check); |
| 843 | 881 |
| 844 if (!enabled_) | 882 if (!enabled_) |
| 845 return; | 883 return; |
| 846 | 884 |
| 847 DCHECK(checks_.find(check) != checks_.end()); | 885 DCHECK(checks_.find(check) != checks_.end()); |
| 848 DCHECK_EQ(check->threat_type, SB_THREAT_TYPE_SAFE); | |
| 849 if (check->client) { | 886 if (check->client) { |
| 850 check->client->OnSafeBrowsingResult(*check); | 887 check->client->OnSafeBrowsingResult(*check); |
| 851 check->client = NULL; | 888 check->client = NULL; |
| 852 } | 889 } |
| 853 } | 890 } |
| 854 | 891 |
| 855 void SafeBrowsingDatabaseManager::CheckDownloadUrlDone( | 892 void SafeBrowsingDatabaseManager::CheckDownloadUrlDone( |
| 856 SafeBrowsingCheck* check) { | 893 SafeBrowsingCheck* check) { |
| 857 DCHECK(enable_download_protection_); | 894 DCHECK(enable_download_protection_); |
| 858 SafeBrowsingCheckDone(check); | 895 SafeBrowsingCheckDone(check); |
| 859 } | 896 } |
| 860 | 897 |
| 861 void SafeBrowsingDatabaseManager::CheckDownloadHashDone( | 898 void SafeBrowsingDatabaseManager::CheckDownloadHashDone( |
| 862 SafeBrowsingCheck* check) { | 899 SafeBrowsingCheck* check) { |
| 863 DCHECK(enable_download_protection_); | 900 DCHECK(enable_download_protection_); |
| 864 SafeBrowsingCheckDone(check); | 901 SafeBrowsingCheckDone(check); |
| 865 } | 902 } |
| 866 | 903 |
| 867 void SafeBrowsingDatabaseManager::SafeBrowsingCheckDone( | 904 void SafeBrowsingDatabaseManager::SafeBrowsingCheckDone( |
| 868 SafeBrowsingCheck* check) { | 905 SafeBrowsingCheck* check) { |
| 869 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 906 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 870 DCHECK(check); | 907 DCHECK(check); |
| 871 | 908 |
| 872 if (!enabled_) | 909 if (!enabled_) |
| 873 return; | 910 return; |
| 874 | 911 |
| 875 VLOG(1) << "SafeBrowsingCheckDone: " << check->threat_type; | 912 VLOG(1) << "SafeBrowsingCheckDone"; |
| 876 DCHECK(checks_.find(check) != checks_.end()); | 913 DCHECK(checks_.find(check) != checks_.end()); |
| 877 if (check->client) | 914 if (check->client) |
| 878 check->client->OnSafeBrowsingResult(*check); | 915 check->client->OnSafeBrowsingResult(*check); |
| 879 checks_.erase(check); | 916 checks_.erase(check); |
| 880 delete check; | 917 delete check; |
| 881 } | 918 } |
| 882 | 919 |
| 883 void SafeBrowsingDatabaseManager::StartDownloadCheck(SafeBrowsingCheck* check, | 920 void SafeBrowsingDatabaseManager::StartSafeBrowsingCheck( |
| 884 Client* client, | 921 SafeBrowsingCheck* check, |
| 885 const base::Closure& task, | 922 const base::Closure& task) { |
| 886 int64 timeout_ms) { | |
| 887 | |
| 888 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 923 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 889 check->client = client; | |
| 890 check->threat_type = SB_THREAT_TYPE_SAFE; | |
| 891 check->is_download = true; | |
| 892 check->timeout_factory_.reset( | 924 check->timeout_factory_.reset( |
| 893 new base::WeakPtrFactory<SafeBrowsingDatabaseManager>(this)); | 925 new base::WeakPtrFactory<SafeBrowsingDatabaseManager>(this)); |
| 894 checks_.insert(check); | 926 checks_.insert(check); |
| 895 | 927 |
| 896 safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, task); | 928 safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, task); |
| 897 | 929 |
| 898 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 930 MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 899 base::Bind(&SafeBrowsingDatabaseManager::TimeoutCallback, | 931 base::Bind(&SafeBrowsingDatabaseManager::TimeoutCallback, |
| 900 check->timeout_factory_->GetWeakPtr(), check), | 932 check->timeout_factory_->GetWeakPtr(), check), |
| 901 base::TimeDelta::FromMilliseconds(timeout_ms)); | 933 check_timeout_); |
| 902 } | 934 } |
| OLD | NEW |