12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/database_manager.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind_helpers.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/leak_tracker.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread_restrictions.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/browser_process.h" 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/prerender/prerender_field_trial.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/client_side_detection_service.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/download_protection_service.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/malware_details.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/protocol_manager.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/safe_browsing_database.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/safe_browsing_service.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/ui_manager.h" 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_constants.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_paths.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_switches.h" 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/metrics/metrics_service.h" 3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "components/startup_metric_utils/startup_metric_utils.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_service.h" 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "url/url_constants.h" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Timeout for match checks, e.g. download URLs, hashes. 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kCheckTimeoutMs = 10000; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Records disposition information about the check. |hit| should be 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |true| if there were any prefix hits in |full_hashes|. 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RecordGetHashCheckStatus( 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool hit, 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_util::ListType check_type, 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<SBFullHashResult>& full_hashes) { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingProtocolManager::ResultType result; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (full_hashes.empty()) { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_EMPTY; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (hit) { 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_HIT; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_MISS; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_download = check_type == safe_browsing_util::BINURL; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingProtocolManager::RecordGetHashResult(is_download, result); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool IsExpectedThreat( 6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const SBThreatType threat_type, 6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::vector<SBThreatType>& expected_threats) { 6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return expected_threats.end() != std::find(expected_threats.begin(), 6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expected_threats.end(), 6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) threat_type); 6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Return the list id from the first result in |full_hashes| which matches 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |hash|, or INVALID if none match. 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)safe_browsing_util::ListType GetHashThreatListType( 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const SBFullHash& hash, 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<SBFullHashResult>& full_hashes, 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t* index) { 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t i = 0; i < full_hashes.size(); ++i) { 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (SBFullHashEqual(hash, full_hashes[i].hash)) { 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (index) 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *index = i; 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return static_cast<safe_browsing_util::ListType>(full_hashes[i].list_id); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return safe_browsing_util::INVALID; 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Given a URL, compare all the possible host + path full hashes to the set of 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// provided full hashes. Returns the list id of the a matching result from 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// |full_hashes|, or INVALID if none match. 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)safe_browsing_util::ListType GetUrlThreatListType( 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const GURL& url, 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<SBFullHashResult>& full_hashes, 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t* index) { 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (full_hashes.empty()) 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return safe_browsing_util::INVALID; 960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) std::vector<std::string> patterns; 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) safe_browsing_util::GeneratePatternsToCheck(url, &patterns); 990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t i = 0; i < patterns.size(); ++i) { 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci safe_browsing_util::ListType threat = GetHashThreatListType( 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SBFullHashForString(patterns[i]), full_hashes, index); 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (threat != safe_browsing_util::INVALID) 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return threat; 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return safe_browsing_util::INVALID; 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SBThreatType GetThreatTypeFromListType(safe_browsing_util::ListType list_type) { 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (list_type) { 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case safe_browsing_util::PHISH: 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return SB_THREAT_TYPE_URL_PHISHING; 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case safe_browsing_util::MALWARE: 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return SB_THREAT_TYPE_URL_MALWARE; 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case safe_browsing_util::BINURL: 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return SB_THREAT_TYPE_BINARY_MALWARE_URL; 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case safe_browsing_util::EXTENSIONBLACKLIST: 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return SB_THREAT_TYPE_EXTENSION; 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) default: 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DVLOG(1) << "Unknown safe browsing list id " << list_type; 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return SB_THREAT_TYPE_SAFE; 1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SBThreatType SafeBrowsingDatabaseManager::GetHashThreatType( 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const SBFullHash& hash, 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<SBFullHashResult>& full_hashes) { 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return GetThreatTypeFromListType( 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetHashThreatListType(hash, full_hashes, NULL)); 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)SBThreatType SafeBrowsingDatabaseManager::GetUrlThreatType( 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const GURL& url, 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<SBFullHashResult>& full_hashes, 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t* index) { 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return GetThreatTypeFromListType( 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetUrlThreatListType(url, full_hashes, index)); 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SafeBrowsingDatabaseManager::SafeBrowsingCheck::SafeBrowsingCheck( 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<GURL>& urls, 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<SBFullHash>& full_hashes, 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Client* client, 14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) safe_browsing_util::ListType check_type, 14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::vector<SBThreatType>& expected_threats) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : urls(urls), 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_results(urls.size(), SB_THREAT_TYPE_SAFE), 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url_metadata(urls.size()), 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) full_hashes(full_hashes), 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) full_hash_results(full_hashes.size(), SB_THREAT_TYPE_SAFE), 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client(client), 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) need_get_hash(false), 15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) check_type(check_type), 15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expected_threats(expected_threats) { 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(urls.empty(), !full_hashes.empty()) 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Exactly one of urls and full_hashes must be set"; 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SafeBrowsingDatabaseManager::SafeBrowsingCheck::~SafeBrowsingCheck() {} 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::Client::OnSafeBrowsingResult( 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SafeBrowsingCheck& check) { 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(check.urls.size(), check.url_results.size()); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(check.full_hashes.size(), check.full_hash_results.size()); 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!check.urls.empty()) { 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(check.full_hashes.empty()); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (check.check_type) { 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case safe_browsing_util::MALWARE: 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case safe_browsing_util::PHISH: 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(1u, check.urls.size()); 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnCheckBrowseUrlResult( 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci check.urls[0], check.url_results[0], check.url_metadata[0]); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case safe_browsing_util::BINURL: 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(check.urls.size(), check.url_results.size()); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnCheckDownloadUrlResult( 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check.urls, 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *std::max_element(check.url_results.begin(), 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check.url_results.end())); 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (!check.full_hashes.empty()) { 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (check.check_type) { 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case safe_browsing_util::EXTENSIONBLACKLIST: { 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<std::string> unsafe_extension_ids; 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < check.full_hashes.size(); ++i) { 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string extension_id = 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_util::SBFullHashToString(check.full_hashes[i]); 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (check.full_hash_results[i] == SB_THREAT_TYPE_EXTENSION) 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsafe_extension_ids.insert(extension_id); 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnCheckExtensionsResult(unsafe_extension_ids); 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SafeBrowsingDatabaseManager::SafeBrowsingDatabaseManager( 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<SafeBrowsingService>& service) 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : sb_service_(service), 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_(NULL), 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enabled_(false), 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_download_protection_(false), 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_csd_whitelist_(false), 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_download_whitelist_(false), 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_extension_blacklist_(false), 21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) enable_side_effect_free_whitelist_(false), 2190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) enable_ip_blacklist_(false), 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) update_in_progress_(false), 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_update_in_progress_(false), 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closing_database_(false), 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check_timeout_(base::TimeDelta::FromMilliseconds(kCheckTimeoutMs)) { 224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(sb_service_.get() != NULL); 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Android only supports a subset of FULL_SAFE_BROWSING. 2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(shess): This shouldn't be OS-driven <http://crbug.com/394379> 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if !defined(OS_ANDROID) 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CommandLine* cmdline = CommandLine::ForCurrentProcess(); 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_download_protection_ = 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !cmdline->HasSwitch(switches::kSbDisableDownloadProtection); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We only download the csd-whitelist if client-side phishing detection is 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // enabled. 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_csd_whitelist_ = 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !cmdline->HasSwitch(switches::kDisableClientSidePhishingDetection); 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(noelutz): remove this boolean variable since it should always be true 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if SafeBrowsing is enabled. Unfortunately, we have no test data for this 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // list right now. This means that we need to be able to disable this list 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for the SafeBrowsing test to pass. 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_download_whitelist_ = enable_csd_whitelist_; 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(kalman): there really shouldn't be a flag for this. 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_extension_blacklist_ = 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !cmdline->HasSwitch(switches::kSbDisableExtensionBlacklist); 24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) enable_side_effect_free_whitelist_ = 24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) prerender::IsSideEffectFreeWhitelistEnabled() && 25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !cmdline->HasSwitch(switches::kSbDisableSideEffectFreeWhitelist); 25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // The client-side IP blacklist feature is tightly integrated with client-side 2530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // phishing protection for now. 2540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) enable_ip_blacklist_ = enable_csd_whitelist_; 2550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) enum SideEffectFreeWhitelistStatus { 25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SIDE_EFFECT_FREE_WHITELIST_ENABLED, 25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SIDE_EFFECT_FREE_WHITELIST_DISABLED, 25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SIDE_EFFECT_FREE_WHITELIST_STATUS_MAX 26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) }; 26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SideEffectFreeWhitelistStatus side_effect_free_whitelist_status = 26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) enable_side_effect_free_whitelist_ ? SIDE_EFFECT_FREE_WHITELIST_ENABLED : 26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SIDE_EFFECT_FREE_WHITELIST_DISABLED; 26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("SB2.SideEffectFreeWhitelistStatus", 26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) side_effect_free_whitelist_status, 26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SIDE_EFFECT_FREE_WHITELIST_STATUS_MAX); 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SafeBrowsingDatabaseManager::~SafeBrowsingDatabaseManager() { 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We should have already been shut down. If we're still enabled, then the 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // database isn't going to be closed properly, which could lead to corruption. 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!enabled_); 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SafeBrowsingDatabaseManager::CanCheckUrl(const GURL& url) const { 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return url.SchemeIs(url::kFtpScheme) || 280010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) url.SchemeIs(url::kHttpScheme) || 281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) url.SchemeIs(url::kHttpsScheme); 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SafeBrowsingDatabaseManager::CheckDownloadUrl( 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<GURL>& url_chain, 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Client* client) { 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_ || !enable_download_protection_) 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We need to check the database for url prefix, and later may fetch the url 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from the safebrowsing backends. These need to be asynchronous. 29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SafeBrowsingCheck* check = 29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new SafeBrowsingCheck(url_chain, 29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::vector<SBFullHash>(), 29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) client, 29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) safe_browsing_util::BINURL, 29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::vector<SBThreatType>(1, 29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SB_THREAT_TYPE_BINARY_MALWARE_URL)); 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartSafeBrowsingCheck( 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check, 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::CheckDownloadUrlOnSBThread, this, 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check)); 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SafeBrowsingDatabaseManager::CheckExtensionIDs( 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::set<std::string>& extension_ids, 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Client* client) { 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_ || !enable_extension_blacklist_) 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<SBFullHash> extension_id_hashes; 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::transform(extension_ids.begin(), extension_ids.end(), 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::back_inserter(extension_id_hashes), 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_util::StringToSBFullHash); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck* check = new SafeBrowsingCheck( 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<GURL>(), 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension_id_hashes, 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client, 32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) safe_browsing_util::EXTENSIONBLACKLIST, 32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::vector<SBThreatType>(1, SB_THREAT_TYPE_EXTENSION)); 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartSafeBrowsingCheck( 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check, 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::CheckExtensionIDsOnSBThread, 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check)); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool SafeBrowsingDatabaseManager::CheckSideEffectFreeWhitelistUrl( 33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const GURL& url) { 33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!enabled_) 33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!CanCheckUrl(url)) 34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return database_->ContainsSideEffectFreeWhitelistUrl(url); 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool SafeBrowsingDatabaseManager::MatchMalwareIP( 3470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const std::string& ip_address) { 3480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 3490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!enabled_ || !enable_ip_blacklist_ || !MakeDatabaseAvailable()) { 3500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; // Fail open. 3510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 3520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return database_->ContainsMalwareIP(ip_address); 3530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 3540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SafeBrowsingDatabaseManager::MatchCsdWhitelistUrl(const GURL& url) { 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_ || !enable_csd_whitelist_ || !MakeDatabaseAvailable()) { 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // There is something funky going on here -- for example, perhaps the user 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // has not restarted since enabling metrics reporting, so we haven't 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // enabled the csd whitelist yet. Just to be safe we return true in this 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // case. 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return database_->ContainsCsdWhitelistedUrl(url); 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SafeBrowsingDatabaseManager::MatchDownloadWhitelistUrl(const GURL& url) { 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_ || !enable_download_whitelist_ || !MakeDatabaseAvailable()) { 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return database_->ContainsDownloadWhitelistedUrl(url); 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SafeBrowsingDatabaseManager::MatchDownloadWhitelistString( 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& str) { 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_ || !enable_download_whitelist_ || !MakeDatabaseAvailable()) { 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return database_->ContainsDownloadWhitelistedString(str); 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 38458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochbool SafeBrowsingDatabaseManager::IsMalwareKillSwitchOn() { 38558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 38658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch if (!enabled_ || !MakeDatabaseAvailable()) { 38758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch return true; 38858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch } 38958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch return database_->IsMalwareIPMatchKillSwitchOn(); 39058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch} 39158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool SafeBrowsingDatabaseManager::IsCsdWhitelistKillSwitchOn() { 393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!enabled_ || !MakeDatabaseAvailable()) { 395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return database_->IsCsdWhitelistKillSwitchOn(); 398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SafeBrowsingDatabaseManager::CheckBrowseUrl(const GURL& url, 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Client* client) { 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_) 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CanCheckUrl(url)) 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 40958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::vector<SBThreatType> expected_threats; 41058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expected_threats.push_back(SB_THREAT_TYPE_URL_MALWARE); 41158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expected_threats.push_back(SB_THREAT_TYPE_URL_PHISHING); 41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::TimeTicks start = base::TimeTicks::Now(); 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!MakeDatabaseAvailable()) { 41558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) QueuedCheck queued_check(safe_browsing_util::MALWARE, // or PHISH 41658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) client, 41758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) url, 41858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expected_threats, 41958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) start); 42058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) queued_checks_.push_back(queued_check); 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<SBPrefix> prefix_hits; 425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::vector<SBFullHashResult> cache_hits; 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool prefix_match = 428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) database_->ContainsBrowseUrl(url, &prefix_hits, &cache_hits); 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_TIMES("SB2.FilterCheck", base::TimeTicks::Now() - start); 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!prefix_match) 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; // URL is okay. 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Needs to be asynchronous, since we could be in the constructor of a 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ResourceDispatcherHost event handler which can't pause there. 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck* check = new SafeBrowsingCheck(std::vector<GURL>(1, url), 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<SBFullHash>(), 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client, 44058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) safe_browsing_util::MALWARE, 44158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expected_threats); 442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) check->need_get_hash = cache_hits.empty(); 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->prefix_hits.swap(prefix_hits); 444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) check->cache_hits.swap(cache_hits); 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) checks_.insert(check); 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::IO, FROM_HERE, 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::OnCheckDone, this, check)); 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::CancelCheck(Client* client) { 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (CurrentChecks::iterator i = checks_.begin(); i != checks_.end(); ++i) { 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We can't delete matching checks here because the db thread has a copy of 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the pointer. Instead, we simply NULL out the client, and when the db 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // thread calls us back, we'll clean up the check. 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*i)->client == client) 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*i)->client = NULL; 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Scan the queued clients store. Clients may be here if they requested a URL 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // check before the database has finished loading. 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::deque<QueuedCheck>::iterator it(queued_checks_.begin()); 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != queued_checks_.end(); ) { 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In this case it's safe to delete matches entirely since nothing has a 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // pointer to them. 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->client == client) 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it = queued_checks_.erase(it); 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++it; 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::HandleGetHashResults( 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck* check, 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<SBFullHashResult>& full_hashes, 480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::TimeDelta& cache_lifetime) { 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_) 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the service has been shut down, |check| should have been deleted. 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(checks_.find(check) != checks_.end()); 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |start| is set before calling |GetFullHash()|, which should be 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the only path which gets to here. 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!check->start.is_null()); 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_LONG_TIMES("SB2.Network", 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks::Now() - check->start); 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<SBPrefix> prefixes = check->prefix_hits; 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnHandleGetHashResults(check, full_hashes); // 'check' is deleted here. 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Cache the GetHash results. 499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (cache_lifetime != base::TimeDelta() && MakeDatabaseAvailable()) 500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) database_->CacheHashResults(prefixes, full_hashes, cache_lifetime); 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::GetChunks(GetChunksCallback callback) { 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(enabled_); 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!callback.is_null()); 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, base::Bind( 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &SafeBrowsingDatabaseManager::GetAllChunksFromDatabase, this, callback)); 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 511f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void SafeBrowsingDatabaseManager::AddChunks( 512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& list, 513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<ScopedVector<SBChunkData> > chunks, 514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AddChunksCallback callback) { 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(enabled_); 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!callback.is_null()); 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, base::Bind( 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &SafeBrowsingDatabaseManager::AddDatabaseChunks, this, list, 520f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Passed(&chunks), callback)); 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::DeleteChunks( 524f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<std::vector<SBChunkDelete> > chunk_deletes) { 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(enabled_); 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, base::Bind( 528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &SafeBrowsingDatabaseManager::DeleteDatabaseChunks, this, 529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::Passed(&chunk_deletes))); 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::UpdateStarted() { 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(enabled_); 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!update_in_progress_); 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) update_in_progress_ = true; 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::UpdateFinished(bool update_succeeded) { 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(enabled_); 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (update_in_progress_) { 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) update_in_progress_ = false; 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::DatabaseUpdateFinished, 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, update_succeeded)); 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::ResetDatabase() { 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(enabled_); 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, base::Bind( 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &SafeBrowsingDatabaseManager::OnResetDatabase, this)); 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::LogPauseDelay(base::TimeDelta time) { 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_LONG_TIMES("SB2.Delay", time); 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::StartOnIOThread() { 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (enabled_) 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!safe_browsing_thread_.get()); 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_thread_.reset(new base::Thread("Chrome_SafeBrowsingThread")); 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!safe_browsing_thread_->Start()) 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enabled_ = true; 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MakeDatabaseAvailable(); 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::StopOnIOThread(bool shutdown) { 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoStopOnIOThread(); 5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (shutdown) { 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sb_service_ = NULL; 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 58468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SafeBrowsingDatabaseManager::NotifyDatabaseUpdateFinished( 58568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool update_succeeded) { 58668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) content::NotificationService::current()->Notify( 58768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE, 58868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) content::Source<SafeBrowsingDatabaseManager>(this), 58968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) content::Details<bool>(&update_succeeded)); 59068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 59168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 59258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)SafeBrowsingDatabaseManager::QueuedCheck::QueuedCheck( 59358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const safe_browsing_util::ListType check_type, 59458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Client* client, 59558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const GURL& url, 59658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::vector<SBThreatType>& expected_threats, 59758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const base::TimeTicks& start) 59858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) : check_type(check_type), 59958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) client(client), 60058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) url(url), 60158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expected_threats(expected_threats), 60258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) start(start) { 60358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 60458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 60558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)SafeBrowsingDatabaseManager::QueuedCheck::~QueuedCheck() { 60658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 60758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::DoStopOnIOThread() { 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_) 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enabled_ = false; 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete queued checks, calling back any clients with 'SB_THREAT_TYPE_SAFE'. 6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (!queued_checks_.empty()) { 6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueuedCheck queued = queued_checks_.front(); 6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (queued.client) { 6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck sb_check(std::vector<GURL>(1, queued.url), 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<SBFullHash>(), 6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued.client, 62158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) queued.check_type, 62258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) queued.expected_threats); 6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued.client->OnSafeBrowsingResult(sb_check); 6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_checks_.pop_front(); 6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 628a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Close the database. Cases to avoid: 629a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // * If |closing_database_| is true, continuing will queue up a second 630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // request, |closing_database_| will be reset after handling the first 631a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // request, and if any functions on the db thread recreate the database, we 632a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // could start using it on the IO thread and then have the second request 633a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // handler delete it out from under us. 634a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // * If |database_| is NULL, then either no creation request is in flight, in 635a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // which case we don't need to do anything, or one is in flight, in which 636a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // case the database will be recreated before our deletion request is 637a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // handled, and could be used on the IO thread in that time period, leading 638a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // to the same problem as above. 639a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Checking DatabaseAvailable() avoids both of these. 640a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (DatabaseAvailable()) { 641a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) closing_database_ = true; 642a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, 643a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::OnCloseDatabase, this)); 644a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Flush the database thread. Any in-progress database check results will be 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ignored and cleaned up below. 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note that to avoid leaking the database, we rely on the fact that no new 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // tasks will be added to the db thread between the call above and this one. 6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See comments on the declaration of |safe_browsing_thread_|. 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A ScopedAllowIO object is required to join the thread when calling Stop. 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See http://crbug.com/72696. Note that we call Stop() first to clear out 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // any remaining tasks before clearing safe_browsing_thread_. 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join; 6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_thread_->Stop(); 6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_thread_.reset(); 6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete pending checks, calling back any clients with 'SB_THREAT_TYPE_SAFE'. 6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We have to do this after the db thread returns because methods on it can 6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // have copies of these pointers, so deleting them might lead to accessing 6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // garbage. 6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (CurrentChecks::iterator it = checks_.begin(); 6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != checks_.end(); ++it) { 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck* check = *it; 6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (check->client) 6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->client->OnSafeBrowsingResult(*check); 6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLDeleteElements(&checks_); 6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gethash_requests_.clear(); 6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SafeBrowsingDatabaseManager::DatabaseAvailable() const { 6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock lock(database_lock_); 6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !closing_database_ && (database_ != NULL); 6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SafeBrowsingDatabaseManager::MakeDatabaseAvailable() { 6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(enabled_); 6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (DatabaseAvailable()) 6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_thread_->message_loop()->PostTask( 6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(base::IgnoreResult(&SafeBrowsingDatabaseManager::GetDatabase), 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this)); 6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SafeBrowsingDatabase* SafeBrowsingDatabaseManager::GetDatabase() { 69490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), 69590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) safe_browsing_thread_->message_loop()); 6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (database_) 6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return database_; 6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) startup_metric_utils::ScopedSlowStartupUMA 6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_timer("Startup.SlowStartupSafeBrowsingGetDatabase"); 7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::TimeTicks before = base::TimeTicks::Now(); 7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingDatabase* database = 7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingDatabase::Create(enable_download_protection_, 7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_csd_whitelist_, 7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_download_whitelist_, 70690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) enable_extension_blacklist_, 7070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) enable_side_effect_free_whitelist_, 7080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) enable_ip_blacklist_); 7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database->Init(SafeBrowsingService::GetBaseFilename()); 7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Acquiring the lock here guarantees correct ordering between the writes to 7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the new database object above, and the setting of |databse_| below. 7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock lock(database_lock_); 7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_ = database; 7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::IO, FROM_HERE, 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::DatabaseLoadComplete, this)); 7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_TIMES("SB2.DatabaseOpen", base::TimeTicks::Now() - before); 7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return database_; 7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::OnCheckDone(SafeBrowsingCheck* check) { 7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_) 7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the service has been shut down, |check| should have been deleted. 7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(checks_.find(check) != checks_.end()); 7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (check->client && check->need_get_hash) { 7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We have a partial match so we need to query Google for the full hash. 7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Clean up will happen in HandleGetHashResults. 7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if we have a GetHash request already in progress for this particular 7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // prefix. If so, we just append ourselves to the list of interested parties 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // when the results arrive. We only do this for checks involving one prefix, 7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // since that is the common case (multiple prefixes will issue the request 7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // as normal). 7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (check->prefix_hits.size() == 1) { 7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SBPrefix prefix = check->prefix_hits[0]; 7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetHashRequests::iterator it = gethash_requests_.find(prefix); 7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it != gethash_requests_.end()) { 7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // There's already a request in progress. 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->second.push_back(check); 7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No request in progress, so we're the first for this prefix. 7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetHashRequestors requestors; 7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) requestors.push_back(check); 7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gethash_requests_[prefix] = requestors; 7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Reset the start time so that we can measure the network time without the 7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // database time. 7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->start = base::TimeTicks::Now(); 7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note: If |this| is deleted or stopped, the protocol_manager will 7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // be destroyed as well - hence it's OK to do unretained in this case. 764a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_download = check->check_type == safe_browsing_util::BINURL; 7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sb_service_->protocol_manager()->GetFullHash( 7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->prefix_hits, 7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::HandleGetHashResults, 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this), 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check), 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_download); 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We may have cached results for previous GetHash queries. Since 7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // this data comes from cache, don't histogram hits. 774116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool is_threat = HandleOneCheck(check, check->cache_hits); 775116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // cache_hits should only contain hits for a fullhash we searched for, so if 776116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // we got to this point it should always result in a threat match. 777116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(is_threat); 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::GetAllChunksFromDatabase( 7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetChunksCallback callback) { 78390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), 78490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) safe_browsing_thread_->message_loop()); 7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool database_error = true; 7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<SBListChunkRanges> lists; 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!database_update_in_progress_); 7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_update_in_progress_ = true; 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetDatabase(); // This guarantees that |database_| is non-NULL. 7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (database_->UpdateStarted(&lists)) { 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_error = false; 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_->UpdateFinished(false); 7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::IO, FROM_HERE, 7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::OnGetAllChunksFromDatabase, 8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, lists, database_error, callback)); 8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::OnGetAllChunksFromDatabase( 8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<SBListChunkRanges>& lists, bool database_error, 8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetChunksCallback callback) { 8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (enabled_) 8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(lists, database_error); 8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::OnAddChunksComplete( 8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChunksCallback callback) { 8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (enabled_) 8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(); 8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::DatabaseLoadComplete() { 8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_) 8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LOCAL_HISTOGRAM_COUNTS("SB.QueueDepth", queued_checks_.size()); 8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (queued_checks_.empty()) 8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the database isn't already available, calling CheckUrl() in the loop 8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // below will add the check back to the queue, and we'll infinite-loop. 8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(DatabaseAvailable()); 8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (!queued_checks_.empty()) { 8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QueuedCheck check = queued_checks_.front(); 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!check.start.is_null()); 8331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LOCAL_HISTOGRAM_TIMES("SB.QueueDelay", 8341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::TimeTicks::Now() - check.start); 8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If CheckUrl() determines the URL is safe immediately, it doesn't call the 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // client's handler function (because normally it's being directly called by 8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the client). Since we're not the client, we have to convey this result. 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (check.client && CheckBrowseUrl(check.url, check.client)) { 8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck sb_check(std::vector<GURL>(1, check.url), 8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<SBFullHash>(), 8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check.client, 84258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) check.check_type, 84358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) check.expected_threats); 8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check.client->OnSafeBrowsingResult(sb_check); 8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_checks_.pop_front(); 8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::AddDatabaseChunks( 851f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& list_name, 852f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<ScopedVector<SBChunkData> > chunks, 8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChunksCallback callback) { 85490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), 85590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) safe_browsing_thread_->message_loop()); 856f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (chunks) 857f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) GetDatabase()->InsertChunks(list_name, chunks->get()); 8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::IO, FROM_HERE, 8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::OnAddChunksComplete, this, 8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback)); 8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::DeleteDatabaseChunks( 865f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<std::vector<SBChunkDelete> > chunk_deletes) { 86690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), 86790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) safe_browsing_thread_->message_loop()); 868f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (chunk_deletes) 8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetDatabase()->DeleteChunks(*chunk_deletes); 8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::DatabaseUpdateFinished( 8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool update_succeeded) { 87490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), 87590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) safe_browsing_thread_->message_loop()); 8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetDatabase()->UpdateFinished(update_succeeded); 8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(database_update_in_progress_); 8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_update_in_progress_ = false; 8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::UI, FROM_HERE, 8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::NotifyDatabaseUpdateFinished, 8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, update_succeeded)); 8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::OnCloseDatabase() { 88690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), 88790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) safe_browsing_thread_->message_loop()); 8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(closing_database_); 8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Because |closing_database_| is true, nothing on the IO thread will be 8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // accessing the database, so it's safe to delete and then NULL the pointer. 8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete database_; 8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_ = NULL; 8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Acquiring the lock here guarantees correct ordering between the resetting 8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // of |database_| above and of |closing_database_| below, which ensures there 8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // won't be a window during which the IO thread falsely believes the database 8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is available. 8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock lock(database_lock_); 9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closing_database_ = false; 9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::OnResetDatabase() { 90490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), 90590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) safe_browsing_thread_->message_loop()); 9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetDatabase()->ResetDatabase(); 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::OnHandleGetHashResults( 9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck* check, 9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<SBFullHashResult>& full_hashes) { 9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_util::ListType check_type = check->check_type; 9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SBPrefix prefix = check->prefix_hits[0]; 9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetHashRequests::iterator it = gethash_requests_.find(prefix); 9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (check->prefix_hits.size() > 1 || it == gethash_requests_.end()) { 9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool hit = HandleOneCheck(check, full_hashes); 9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RecordGetHashCheckStatus(hit, check_type, full_hashes); 9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Call back all interested parties, noting if any has a hit. 9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetHashRequestors& requestors = it->second; 9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool hit = false; 9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (GetHashRequestors::iterator r = requestors.begin(); 9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) r != requestors.end(); ++r) { 9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (HandleOneCheck(*r, full_hashes)) 9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hit = true; 9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RecordGetHashCheckStatus(hit, check_type, full_hashes); 9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gethash_requests_.erase(it); 9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SafeBrowsingDatabaseManager::HandleOneCheck( 9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck* check, 9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<SBFullHashResult>& full_hashes) { 9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(check); 9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_threat = false; 9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 943f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // TODO(shess): GetHashThreadListType() contains a loop, 944f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // GetUrlThreatListType() a loop around that loop. Having another loop out 945f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // here concerns me. It is likely that SAFE is an expected outcome, which 946f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // means all of those loops run to completion. Refactoring this to generate a 947f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // set of sorted items to compare in sequence would probably improve things. 948f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // 949f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Additionally, the set of patterns generated from the urls is very similar 950f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // to the patterns generated in ContainsBrowseUrl() and other database checks, 951f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // which are called from this code. Refactoring that across the checks could 952f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // interact well with batching the checks here. 953f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < check->urls.size(); ++i) { 9551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t threat_index; 9561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SBThreatType threat = 9571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetUrlThreatType(check->urls[i], full_hashes, &threat_index); 95858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (threat != SB_THREAT_TYPE_SAFE && 95958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) IsExpectedThreat(threat, check->expected_threats)) { 9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->url_results[i] = threat; 9611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci check->url_metadata[i] = full_hashes[threat_index].metadata; 9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_threat = true; 9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < check->full_hashes.size(); ++i) { 967f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SBThreatType threat = GetHashThreatType(check->full_hashes[i], full_hashes); 96858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (threat != SB_THREAT_TYPE_SAFE && 96958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) IsExpectedThreat(threat, check->expected_threats)) { 9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->full_hash_results[i] = threat; 9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_threat = true; 9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheckDone(check); 9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return is_threat; 9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::CheckDownloadUrlOnSBThread( 9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck* check) { 98190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), 98290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) safe_browsing_thread_->message_loop()); 9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(enable_download_protection_); 9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<SBPrefix> prefix_hits; 9862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!database_->ContainsDownloadUrl(check->urls, &prefix_hits)) { 9882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Good, we don't have hash for this url prefix. 9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::IO, FROM_HERE, 9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::CheckDownloadUrlDone, this, 9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check)); 9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->need_get_hash = true; 9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->prefix_hits.clear(); 9982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->prefix_hits = prefix_hits; 9992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 10002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::IO, FROM_HERE, 10012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::OnCheckDone, this, check)); 10022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::CheckExtensionIDsOnSBThread( 10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck* check) { 100690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), 100790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) safe_browsing_thread_->message_loop()); 10082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<SBPrefix> prefixes; 10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<SBFullHash>::iterator it = check->full_hashes.begin(); 10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != check->full_hashes.end(); ++it) { 10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prefixes.push_back((*it).prefix); 10132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 10142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_->ContainsExtensionPrefixes(prefixes, &check->prefix_hits); 10152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (check->prefix_hits.empty()) { 10172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No matches for any extensions. 10182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 10192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::IO, 10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::SafeBrowsingCheckDone, this, 10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check)); 10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Some prefixes matched, we need to ask Google whether they're legit. 10252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->need_get_hash = true; 10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask( 10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::IO, 10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::OnCheckDone, this, check)); 10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::TimeoutCallback(SafeBrowsingCheck* check) { 10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(check); 10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_) 10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(checks_.find(check) != checks_.end()); 10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (check->client) { 10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->client->OnSafeBrowsingResult(*check); 10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->client = NULL; 10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::CheckDownloadUrlDone( 10482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck* check) { 10492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(enable_download_protection_); 10502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheckDone(check); 10512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::SafeBrowsingCheckDone( 10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck* check) { 10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(check); 10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enabled_) 10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(1) << "SafeBrowsingCheckDone"; 10622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(checks_.find(check) != checks_.end()); 10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (check->client) 10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->client->OnSafeBrowsingResult(*check); 10652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) checks_.erase(check); 10662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete check; 10672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SafeBrowsingDatabaseManager::StartSafeBrowsingCheck( 10702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeBrowsingCheck* check, 10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Closure& task) { 10722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->timeout_factory_.reset( 10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new base::WeakPtrFactory<SafeBrowsingDatabaseManager>(this)); 10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) checks_.insert(check); 10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, task); 10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 107990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask(FROM_HERE, 10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SafeBrowsingDatabaseManager::TimeoutCallback, 10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check->timeout_factory_->GetWeakPtr(), check), 10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) check_timeout_); 10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1084