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