Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 // This file should not be build on Android but is currently getting built. | 5 // This file should not be build on Android but is currently getting built. |
| 6 // TODO(vakh): Fix that: http://crbug.com/621647 | 6 // TODO(vakh): Fix that: http://crbug.com/621647 |
| 7 | 7 |
| 8 #include "components/safe_browsing_db/v4_local_database_manager.h" | 8 #include "components/safe_browsing_db/v4_local_database_manager.h" |
| 9 | 9 |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/bind_helpers.h" | |
| 12 #include "base/callback.h" | 13 #include "base/callback.h" |
| 14 #include "base/memory/ptr_util.h" | |
| 13 #include "content/public/browser/browser_thread.h" | 15 #include "content/public/browser/browser_thread.h" |
| 14 | 16 |
| 15 using content::BrowserThread; | 17 using content::BrowserThread; |
| 16 | 18 |
| 17 namespace safe_browsing { | 19 namespace safe_browsing { |
| 18 | 20 |
| 19 namespace { | 21 namespace { |
| 20 | 22 |
| 23 const ThreatSeverity kLeastSeverity = | |
| 24 std::numeric_limits<ThreatSeverity>::max(); | |
| 25 | |
| 21 // TODO(vakh): Implement this to populate the vector appopriately. | 26 // TODO(vakh): Implement this to populate the vector appopriately. |
| 22 // Filed as http://crbug.com/608075 | 27 // Filed as http://crbug.com/608075 |
| 28 // Any stores added/removed to/from here likely need an update in | |
| 29 // GetSBThreatTypeForList and GetThreatSeverity. | |
| 30 // TODO(vakh): Add a compile-time check or DCHECK to enforce this. | |
| 23 StoreIdAndFileNames GetStoreIdAndFileNames() { | 31 StoreIdAndFileNames GetStoreIdAndFileNames() { |
| 24 return StoreIdAndFileNames( | 32 return StoreIdAndFileNames( |
| 25 {StoreIdAndFileName(GetUrlMalwareId(), "UrlMalware.store"), | 33 {StoreIdAndFileName(GetUrlMalwareId(), "UrlMalware.store"), |
| 26 StoreIdAndFileName(GetUrlSocEngId(), "UrlSoceng.store")}); | 34 StoreIdAndFileName(GetUrlSocEngId(), "UrlSoceng.store")}); |
| 27 } | 35 } |
| 28 | 36 |
| 37 // Returns the SBThreatType corresponding to a given SafeBrowsing list. | |
| 38 SBThreatType GetSBThreatTypeForList(const UpdateListIdentifier& list_id) { | |
| 39 if (list_id == GetChromeUrlApiId()) { | |
| 40 return SB_THREAT_TYPE_API_ABUSE; | |
| 41 } else if (list_id == GetUrlMalwareId()) { | |
| 42 return SB_THREAT_TYPE_URL_MALWARE; | |
| 43 } else if (list_id == GetUrlSocEngId()) { | |
| 44 return SB_THREAT_TYPE_URL_PHISHING; | |
| 45 } else { | |
| 46 NOTREACHED() << "Unknown list encountered in GetSBThreatTypeForList"; | |
| 47 return SB_THREAT_TYPE_SAFE; | |
| 48 } | |
| 49 } | |
| 50 | |
| 51 // Returns the severity information about a given SafeBrowsing list. The lowest | |
| 52 // value is 0, which represents the most severe list. | |
| 53 ThreatSeverity GetThreatSeverity(const UpdateListIdentifier& list_id) { | |
| 54 switch (list_id.threat_type) { | |
| 55 case MALWARE_THREAT: | |
| 56 case SOCIAL_ENGINEERING_PUBLIC: | |
| 57 return 0; | |
| 58 case API_ABUSE: | |
| 59 return 1; | |
| 60 default: | |
| 61 NOTREACHED() << "Unexpected ThreatType encountered in GetThreatSeverity"; | |
| 62 return kLeastSeverity; | |
| 63 } | |
| 64 } | |
| 65 | |
| 29 } // namespace | 66 } // namespace |
| 30 | 67 |
| 68 V4LocalDatabaseManager::PendingCheck::PendingCheck( | |
| 69 Client* client, | |
| 70 ClientCallbackType client_callback_type, | |
| 71 const GURL& url) | |
| 72 : client(client), | |
| 73 client_callback_type(client_callback_type), | |
| 74 url(url), | |
| 75 result_threat_type(SB_THREAT_TYPE_SAFE) {} | |
| 76 | |
| 77 V4LocalDatabaseManager::PendingCheck::~PendingCheck() {} | |
| 78 | |
| 31 V4LocalDatabaseManager::V4LocalDatabaseManager(const base::FilePath& base_path) | 79 V4LocalDatabaseManager::V4LocalDatabaseManager(const base::FilePath& base_path) |
| 32 : base_path_(base_path), | 80 : base_path_(base_path), |
| 33 enabled_(false), | 81 enabled_(false), |
| 34 store_id_file_names_(GetStoreIdAndFileNames()) { | 82 store_id_file_names_(GetStoreIdAndFileNames()) { |
| 35 DCHECK(!base_path_.empty()); | 83 DCHECK(!base_path_.empty()); |
| 36 DCHECK(!store_id_file_names_.empty()); | 84 DCHECK(!store_id_file_names_.empty()); |
| 37 | 85 |
| 38 DVLOG(1) << "V4LocalDatabaseManager::V4LocalDatabaseManager: " | 86 DVLOG(1) << "V4LocalDatabaseManager::V4LocalDatabaseManager: " |
| 39 << "base_path_: " << base_path_.AsUTF8Unsafe(); | 87 << "base_path_: " << base_path_.AsUTF8Unsafe(); |
| 40 } | 88 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 } | 181 } |
| 134 | 182 |
| 135 bool V4LocalDatabaseManager::IsCsdWhitelistKillSwitchOn() { | 183 bool V4LocalDatabaseManager::IsCsdWhitelistKillSwitchOn() { |
| 136 // TODO(vakh): Implement this skeleton. | 184 // TODO(vakh): Implement this skeleton. |
| 137 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 185 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 138 return true; | 186 return true; |
| 139 } | 187 } |
| 140 | 188 |
| 141 bool V4LocalDatabaseManager::CheckBrowseUrl(const GURL& url, Client* client) { | 189 bool V4LocalDatabaseManager::CheckBrowseUrl(const GURL& url, Client* client) { |
| 142 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 190 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 191 | |
| 143 if (!enabled_ || !CanCheckUrl(url)) { | 192 if (!enabled_ || !CanCheckUrl(url)) { |
| 144 return true; | 193 return true; |
| 145 } | 194 } |
| 146 | 195 |
| 147 if (v4_database_) { | 196 if (v4_database_) { |
| 148 std::unordered_set<FullHash> full_hashes; | 197 std::unordered_set<FullHash> full_hashes; |
| 149 V4ProtocolManagerUtil::UrlToFullHashes(url, &full_hashes); | 198 V4ProtocolManagerUtil::UrlToFullHashes(url, &full_hashes); |
| 150 | 199 |
| 151 std::unordered_set<UpdateListIdentifier> stores_to_look( | 200 std::unordered_set<UpdateListIdentifier> stores_to_look( |
| 152 {GetUrlMalwareId(), GetUrlSocEngId()}); | 201 {GetUrlMalwareId(), GetUrlSocEngId()}); |
| 153 std::unordered_set<HashPrefix> matched_hash_prefixes; | 202 std::unordered_set<HashPrefix> matched_hash_prefixes; |
| 154 std::unordered_set<UpdateListIdentifier> matched_stores; | 203 std::unordered_set<UpdateListIdentifier> matched_stores; |
| 155 StoreAndHashPrefixes matched_store_and_full_hashes; | 204 StoreAndHashPrefixes matched_store_and_hash_prefixes; |
| 156 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes; | 205 FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes; |
| 157 for (const auto& full_hash : full_hashes) { | 206 for (const auto& full_hash : full_hashes) { |
| 158 matched_store_and_full_hashes.clear(); | 207 matched_store_and_hash_prefixes.clear(); |
| 159 v4_database_->GetStoresMatchingFullHash(full_hash, stores_to_look, | 208 v4_database_->GetStoresMatchingFullHash(full_hash, stores_to_look, |
| 160 &matched_store_and_full_hashes); | 209 &matched_store_and_hash_prefixes); |
| 161 if (!matched_store_and_full_hashes.empty()) { | 210 if (!matched_store_and_hash_prefixes.empty()) { |
| 162 full_hash_to_store_and_hash_prefixes[full_hash] = | 211 full_hash_to_store_and_hash_prefixes[full_hash] = |
| 163 matched_store_and_full_hashes; | 212 matched_store_and_hash_prefixes; |
| 164 } | 213 } |
| 165 } | 214 } |
| 166 | 215 |
| 167 if (full_hash_to_store_and_hash_prefixes.empty()) { | 216 if (full_hash_to_store_and_hash_prefixes.empty()) { |
| 168 return true; | 217 return true; |
| 169 } else { | 218 } else { |
| 170 // TODO(vakh): Pass more information to the callback for it to be able to | 219 std::unique_ptr<PendingCheck> pending_check = |
| 171 // do something meaningful. | 220 base::MakeUnique<PendingCheck>( |
| 221 client, ClientCallbackType::CHECK_BROWSE_URL, url); | |
| 222 | |
| 172 v4_get_hash_protocol_manager_->GetFullHashes( | 223 v4_get_hash_protocol_manager_->GetFullHashes( |
| 173 full_hash_to_store_and_hash_prefixes, | 224 full_hash_to_store_and_hash_prefixes, |
| 174 base::Bind(&V4LocalDatabaseManager::OnFullHashResponse, | 225 base::Bind(&V4LocalDatabaseManager::OnFullHashResponse, |
| 175 base::Unretained(this))); | 226 base::Unretained(this), base::Passed(&pending_check))); |
| 227 | |
| 228 pending_clients_.insert(client); | |
|
Scott Hess - ex-Googler
2016/09/20 21:55:55
It looks to me like GetFullHashes() can return syn
vakh (use Gerrit instead)
2016/09/21 17:43:40
Good catch. Changed.
| |
| 229 | |
| 176 return false; | 230 return false; |
| 177 } | 231 } |
| 178 } else { | 232 } else { |
| 179 // TODO(vakh): Queue the check and process it when the database becomes | 233 // TODO(vakh): Queue the check and process it when the database becomes |
| 180 // ready. | 234 // ready. |
| 181 return false; | 235 return false; |
| 182 } | 236 } |
| 183 } | 237 } |
| 184 | 238 |
| 239 // static | |
| 240 void V4LocalDatabaseManager::GetSeverestThreatTypeAndMetadata( | |
| 241 SBThreatType* result_threat_type, | |
| 242 ThreatMetadata* metadata, | |
| 243 const std::vector<FullHashInfo>& full_hash_infos) { | |
| 244 DCHECK(result_threat_type); | |
| 245 DCHECK(metadata); | |
| 246 | |
| 247 ThreatSeverity most_severe_yet = kLeastSeverity; | |
| 248 for (const FullHashInfo& fhi : full_hash_infos) { | |
| 249 ThreatSeverity severity = GetThreatSeverity(fhi.list_id); | |
| 250 if (severity < most_severe_yet) { | |
| 251 most_severe_yet = severity; | |
| 252 *result_threat_type = GetSBThreatTypeForList(fhi.list_id); | |
| 253 *metadata = fhi.metadata; | |
| 254 } | |
| 255 } | |
| 256 } | |
| 257 | |
| 185 void V4LocalDatabaseManager::OnFullHashResponse( | 258 void V4LocalDatabaseManager::OnFullHashResponse( |
| 259 std::unique_ptr<PendingCheck> pending_check, | |
| 186 const std::vector<FullHashInfo>& full_hash_infos) { | 260 const std::vector<FullHashInfo>& full_hash_infos) { |
| 261 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 262 | |
| 263 if (!enabled_) { | |
| 264 DCHECK(pending_clients_.empty()); | |
| 265 return; | |
| 266 } | |
| 267 | |
| 268 auto it = pending_clients_.find(pending_check->client); | |
| 269 if (it == pending_clients_.end()) { | |
| 270 // The check has since been cancelled. | |
| 271 return; | |
| 272 } | |
| 273 | |
| 274 if (full_hash_infos.empty()) { | |
| 275 // The resource is not known to be unsafe. Respond right away. | |
| 276 RespondToClient(std::move(pending_check)); | |
|
Scott Hess - ex-Googler
2016/09/20 21:55:55
Shouldn't this also erase()?
AFAICT, this if() cl
vakh (use Gerrit instead)
2016/09/21 17:43:40
Done.
| |
| 277 return; | |
| 278 } | |
| 279 | |
| 280 GetSeverestThreatTypeAndMetadata(&pending_check->result_threat_type, | |
| 281 &pending_check->url_metadata, | |
| 282 full_hash_infos); | |
| 283 | |
| 284 RespondToClient(std::move(pending_check)); | |
| 285 pending_clients_.erase(it); | |
| 286 } | |
| 287 | |
| 288 void V4LocalDatabaseManager::RespondToClient( | |
| 289 std::unique_ptr<PendingCheck> pending_check) { | |
| 290 DCHECK(pending_check.get()); | |
| 291 DCHECK_EQ(ClientCallbackType::CHECK_BROWSE_URL, | |
| 292 pending_check->client_callback_type); | |
| 187 // TODO(vakh): Implement this skeleton. | 293 // TODO(vakh): Implement this skeleton. |
| 188 } | 294 } |
| 189 | 295 |
| 190 void V4LocalDatabaseManager::CancelCheck(Client* client) { | 296 void V4LocalDatabaseManager::CancelCheck(Client* client) { |
| 191 // TODO(vakh): Implement this skeleton. | |
| 192 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 297 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 193 DCHECK(enabled_); | 298 DCHECK(enabled_); |
| 299 | |
| 300 auto it = pending_clients_.find(client); | |
| 301 if (it != pending_clients_.end()) { | |
| 302 pending_clients_.erase(it); | |
| 303 } | |
| 304 | |
| 305 // TODO(vakh): Handle the case of queued checks. | |
| 194 } | 306 } |
| 195 | 307 |
| 196 void V4LocalDatabaseManager::StartOnIOThread( | 308 void V4LocalDatabaseManager::StartOnIOThread( |
| 197 net::URLRequestContextGetter* request_context_getter, | 309 net::URLRequestContextGetter* request_context_getter, |
| 198 const V4ProtocolConfig& config) { | 310 const V4ProtocolConfig& config) { |
| 199 SafeBrowsingDatabaseManager::StartOnIOThread(request_context_getter, config); | 311 SafeBrowsingDatabaseManager::StartOnIOThread(request_context_getter, config); |
| 200 | 312 |
| 201 db_updated_callback_ = base::Bind(&V4LocalDatabaseManager::DatabaseUpdated, | 313 db_updated_callback_ = base::Bind(&V4LocalDatabaseManager::DatabaseUpdated, |
| 202 base::Unretained(this)); | 314 base::Unretained(this)); |
| 203 | 315 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 255 // Schedule the deletion of v4_database off IO thread. | 367 // Schedule the deletion of v4_database off IO thread. |
| 256 V4Database::Destroy(std::move(v4_database)); | 368 V4Database::Destroy(std::move(v4_database)); |
| 257 } | 369 } |
| 258 } | 370 } |
| 259 | 371 |
| 260 void V4LocalDatabaseManager::StopOnIOThread(bool shutdown) { | 372 void V4LocalDatabaseManager::StopOnIOThread(bool shutdown) { |
| 261 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 373 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 262 | 374 |
| 263 enabled_ = false; | 375 enabled_ = false; |
| 264 | 376 |
| 377 pending_clients_.clear(); | |
| 378 | |
| 265 // Delete the V4Database. Any pending writes to disk are completed. | 379 // Delete the V4Database. Any pending writes to disk are completed. |
| 266 // This operation happens on the task_runner on which v4_database_ operates | 380 // This operation happens on the task_runner on which v4_database_ operates |
| 267 // and doesn't block the IO thread. | 381 // and doesn't block the IO thread. |
| 268 V4Database::Destroy(std::move(v4_database_)); | 382 V4Database::Destroy(std::move(v4_database_)); |
| 269 | 383 |
| 270 // Delete the V4UpdateProtocolManager. | 384 // Delete the V4UpdateProtocolManager. |
| 271 // This cancels any in-flight update request. | 385 // This cancels any in-flight update request. |
| 272 v4_update_protocol_manager_.reset(); | 386 v4_update_protocol_manager_.reset(); |
| 273 | 387 |
| 274 db_updated_callback_.Reset(); | 388 db_updated_callback_.Reset(); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 293 std::unordered_set<UpdateListIdentifier> | 407 std::unordered_set<UpdateListIdentifier> |
| 294 V4LocalDatabaseManager::GetStoresForFullHashRequests() { | 408 V4LocalDatabaseManager::GetStoresForFullHashRequests() { |
| 295 std::unordered_set<UpdateListIdentifier> stores_for_full_hash; | 409 std::unordered_set<UpdateListIdentifier> stores_for_full_hash; |
| 296 for (auto it : store_id_file_names_) { | 410 for (auto it : store_id_file_names_) { |
| 297 stores_for_full_hash.insert(it.list_id); | 411 stores_for_full_hash.insert(it.list_id); |
| 298 } | 412 } |
| 299 return stores_for_full_hash; | 413 return stores_for_full_hash; |
| 300 } | 414 } |
| 301 | 415 |
| 302 } // namespace safe_browsing | 416 } // namespace safe_browsing |
| OLD | NEW |