1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/safe_browsing/safe_browsing_service.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h" 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/lazy_instance.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/path_service.h" 11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/stl_util-inl.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/threading/thread_restrictions.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/metrics/metrics_service.h" 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h" 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile_manager.h" 1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/safe_browsing/malware_details.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/safe_browsing/protocol_manager.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/safe_browsing/safe_browsing_database.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_util.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_constants.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_paths.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_switches.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h" 28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/registry_controlled_domain.h" 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/url_request/url_request_context_getter.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/installer/util/browser_distribution.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsennamespace { 383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The default URL prefix where browser fetches chunk updates, hashes, 4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// and reports safe browsing hits. 413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenconst char* const kSbDefaultInfoURLPrefix = 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "http://safebrowsing.clients.google.com/safebrowsing"; 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// The default URL prefix where browser fetches MAC client key and reports 4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// malware details. 463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenconst char* const kSbDefaultMacKeyURLPrefix = 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "https://sb-ssl.google.com/safebrowsing"; 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// When download url check takes this long, client's callback will be called 50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// without waiting for the result. 51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst int64 kDownloadUrlCheckTimeoutMs = 10000; 52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Similar to kDownloadUrlCheckTimeoutMs, but for download hash checks. 54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst int64 kDownloadHashCheckTimeoutMs = 10000; 55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// TODO(lzheng): Replace this with Profile* ProfileManager::GetDefaultProfile(). 573f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenProfile* GetDefaultProfile() { 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath user_data_dir; 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProfileManager* profile_manager = g_browser_process->profile_manager(); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return profile_manager->GetDefaultProfile(user_data_dir); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Records disposition information about the check. |hit| should be 653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// |true| if there were any prefix hits in |full_hashes|. 663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid RecordGetHashCheckStatus( 67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool hit, 68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool is_download, 69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const std::vector<SBFullHashResult>& full_hashes) { 703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen SafeBrowsingProtocolManager::ResultType result; 713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (full_hashes.empty()) { 723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_EMPTY; 733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } else if (hit) { 743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_HIT; 753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } else { 763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen result = SafeBrowsingProtocolManager::GET_HASH_FULL_HASH_MISS; 773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingProtocolManager::RecordGetHashResult(is_download, result); 793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} // namespace 823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 83201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// static 84201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochSafeBrowsingServiceFactory* SafeBrowsingService::factory_ = NULL; 85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 86201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// The default SafeBrowsingServiceFactory. Global, made a singleton so we 87201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// don't leak it. 88201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochclass SafeBrowsingServiceFactoryImpl : public SafeBrowsingServiceFactory { 89201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch public: 90201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch virtual SafeBrowsingService* CreateSafeBrowsingService() { 91201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return new SafeBrowsingService(); 92201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 93201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 94201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch private: 9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen friend struct base::DefaultLazyInstanceTraits<SafeBrowsingServiceFactoryImpl>; 96201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 97201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SafeBrowsingServiceFactoryImpl() { } 98201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 99201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactoryImpl); 100201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}; 101201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic base::LazyInstance<SafeBrowsingServiceFactoryImpl> 10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen g_safe_browsing_service_factory_impl(base::LINKER_INITIALIZED); 10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstruct SafeBrowsingService::WhiteListedEntry { 106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int render_process_host_id; 107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int render_view_id; 108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string domain; 109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UrlCheckResult result; 110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}; 111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 112513209b27ff55e2841eac0e4120199c23acce758Ben MurdochSafeBrowsingService::UnsafeResource::UnsafeResource() 113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : resource_type(ResourceType::MAIN_FRAME), 114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen threat_type(SAFE), 115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch client(NULL), 116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch render_process_host_id(-1), 117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch render_view_id(-1) { 118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 120513209b27ff55e2841eac0e4120199c23acce758Ben MurdochSafeBrowsingService::UnsafeResource::~UnsafeResource() {} 121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 122513209b27ff55e2841eac0e4120199c23acce758Ben MurdochSafeBrowsingService::SafeBrowsingCheck::SafeBrowsingCheck() 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : full_hash(NULL), 124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client(NULL), 125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch need_get_hash(false), 126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen result(SAFE), 127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen is_download(false), 128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen timeout_task(NULL) { 129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 131513209b27ff55e2841eac0e4120199c23acce758Ben MurdochSafeBrowsingService::SafeBrowsingCheck::~SafeBrowsingCheck() {} 132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SafeBrowsingService::Client::OnSafeBrowsingResult( 134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const SafeBrowsingCheck& check) { 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!check.urls.empty()) { 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(!check.full_hash.get()); 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!check.is_download) { 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(1U, check.urls.size()); 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnBrowseUrlCheckResult(check.urls[0], check.result); 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnDownloadUrlCheckResult(check.urls, check.result); 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else if (check.full_hash.get()) { 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnDownloadHashCheckResult( 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen safe_browsing_util::SBFullHashToString(*check.full_hash), 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen check.result); 148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NOTREACHED(); 150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 153201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch/* static */ 154201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochSafeBrowsingService* SafeBrowsingService::CreateSafeBrowsingService() { 155201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!factory_) 15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen factory_ = g_safe_browsing_service_factory_impl.Pointer(); 157201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return factory_->CreateSafeBrowsingService(); 158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 159201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSafeBrowsingService::SafeBrowsingService() 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : database_(NULL), 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protocol_manager_(NULL), 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enabled_(false), 16421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen enable_download_protection_(false), 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen enable_csd_whitelist_(false), 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch update_in_progress_(false), 1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick database_update_in_progress_(false), 168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen closing_database_(false), 169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen download_urlcheck_timeout_ms_(kDownloadUrlCheckTimeoutMs), 170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen download_hashcheck_timeout_ms_(kDownloadHashCheckTimeoutMs) { 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::Initialize() { 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get the profile's preference for SafeBrowsing. 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* pref_service = GetDefaultProfile()->GetPrefs(); 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pref_service->GetBoolean(prefs::kSafeBrowsingEnabled)) 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Start(); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::ShutDown() { 181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &SafeBrowsingService::OnIOShutdown)); 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SafeBrowsingService::CanCheckUrl(const GURL& url) const { 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return url.SchemeIs(chrome::kFtpScheme) || 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url.SchemeIs(chrome::kHttpScheme) || 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url.SchemeIs(chrome::kHttpsScheme); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Only report SafeBrowsing related stats when UMA is enabled and 19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// safe browsing is enabled. 19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SafeBrowsingService::CanReportStats() const { 19572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const MetricsService* metrics = g_browser_process->metrics_service(); 19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const PrefService* pref_service = GetDefaultProfile()->GetPrefs(); 19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return metrics && metrics->reporting_active() && 19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen pref_service && pref_service->GetBoolean(prefs::kSafeBrowsingEnabled); 19972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 20072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Binhash verification is only enabled for UMA users for now. 20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SafeBrowsingService::DownloadBinHashNeeded() const { 20372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return enable_download_protection_ && CanReportStats(); 20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SafeBrowsingService::CheckDownloadUrl(const std::vector<GURL>& url_chain, 20721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Client* client) { 20821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 20921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!enabled_ || !enable_download_protection_) 21021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 21121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 21221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // We need to check the database for url prefix, and later may fetch the url 21321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // from the safebrowsing backends. These need to be asynchronous. 21421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SafeBrowsingCheck* check = new SafeBrowsingCheck(); 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen check->urls = url_chain; 216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen StartDownloadCheck( 217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check, 218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client, 219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableMethod(this, 220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &SafeBrowsingService::CheckDownloadUrlOnSBThread, 221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check), 222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen download_urlcheck_timeout_ms_); 223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 22521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool SafeBrowsingService::CheckDownloadHash(const std::string& full_hash, 227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen Client* client) { 228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(!full_hash.empty()); 230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!enabled_ || !enable_download_protection_ || full_hash.empty()) 231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return true; 23221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // We need to check the database for url prefix, and later may fetch the url 234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // from the safebrowsing backends. These need to be asynchronous. 235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingCheck* check = new SafeBrowsingCheck(); 236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->full_hash.reset(new SBFullHash); 237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen safe_browsing_util::StringToSBFullHash(full_hash, check->full_hash.get()); 238dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen StartDownloadCheck( 239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check, 240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client, 241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableMethod(this, 242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &SafeBrowsingService::CheckDownloadHashOnSBThread, 243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check), 244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen download_hashcheck_timeout_ms_); 24521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 24621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 24721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SafeBrowsingService::MatchCsdWhitelistUrl(const GURL& url) { 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!enabled_ || !enable_csd_whitelist_ || !MakeDatabaseAvailable()) { 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // There is something funky going on here -- for example, perhaps the user 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // has not restarted since enabling metrics reporting, so we haven't 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // enabled the csd whitelist yet. Just to be safe we return true in this 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // case. 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return database_->ContainsCsdWhitelistedUrl(url); 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 26021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool SafeBrowsingService::CheckBrowseUrl(const GURL& url, 26121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Client* client) { 262731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!enabled_) 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!CanCheckUrl(url)) 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const base::TimeTicks start = base::TimeTicks::Now(); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!MakeDatabaseAvailable()) { 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QueuedCheck check; 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch check.client = client; 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch check.url = url; 274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check.start = start; 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queued_checks_.push_back(check); 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string list; 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SBPrefix> prefix_hits; 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SBFullHashResult> full_hits; 28221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool prefix_match = 28321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen database_->ContainsBrowseUrl(url, &list, &prefix_hits, 28421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen &full_hits, 28521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen protocol_manager_->last_update()); 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UMA_HISTOGRAM_TIMES("SB2.FilterCheck", base::TimeTicks::Now() - start); 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!prefix_match) 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; // URL is okay. 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Needs to be asynchronous, since we could be in the constructor of a 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ResourceDispatcherHost event handler which can't pause there. 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SafeBrowsingCheck* check = new SafeBrowsingCheck(); 295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen check->urls.push_back(url); 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch check->client = client; 297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->result = SAFE; 298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->is_download = false; 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch check->need_get_hash = full_hits.empty(); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch check->prefix_hits.swap(prefix_hits); 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch check->full_hits.swap(full_hits); 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch checks_.insert(check); 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 304731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 305731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &SafeBrowsingService::OnCheckDone, check)); 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::CancelCheck(Client* client) { 312731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (CurrentChecks::iterator i = checks_.begin(); i != checks_.end(); ++i) { 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We can't delete matching checks here because the db thread has a copy of 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the pointer. Instead, we simply NULL out the client, and when the db 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // thread calls us back, we'll clean up the check. 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((*i)->client == client) 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*i)->client = NULL; 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Scan the queued clients store. Clients may be here if they requested a URL 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // check before the database has finished loading. 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::deque<QueuedCheck>::iterator it(queued_checks_.begin()); 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != queued_checks_.end(); ) { 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // In this case it's safe to delete matches entirely since nothing has a 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // pointer to them. 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it->client == client) 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it = queued_checks_.erase(it); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++it; 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SafeBrowsingService::DisplayBlockingPage( 33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const GURL& url, 33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const GURL& original_url, 33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::vector<GURL>& redirect_urls, 33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ResourceType::Type resource_type, 33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UrlCheckResult result, 34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Client* client, 34172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int render_process_host_id, 34272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int render_view_id) { 343731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check if the user has already ignored our warning for this render_view 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and domain. 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < white_listed_entries_.size(); ++i) { 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const WhiteListedEntry& entry = white_listed_entries_[i]; 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry.render_process_host_id == render_process_host_id && 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.render_view_id == render_view_id && 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.result == result && 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.domain == 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::RegistryControlledDomainService::GetDomainAndRegistry(url)) { 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &SafeBrowsingService::NotifyClientBlockingComplete, 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client, true)); 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UnsafeResource resource; 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource.url = url; 3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick resource.original_url = original_url; 36472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen resource.redirect_urls = redirect_urls; 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource.resource_type = resource_type; 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource.threat_type= result; 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource.client = client; 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource.render_process_host_id = render_process_host_id; 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource.render_view_id = render_view_id; 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The blocking page must be created from the UI thread. 372731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 373731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod( 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &SafeBrowsingService::DoDisplayBlockingPage, resource)); 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::HandleGetHashResults( 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SafeBrowsingCheck* check, 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<SBFullHashResult>& full_hashes, 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool can_cache) { 382731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!enabled_) 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 387dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If the service has been shut down, |check| should have been deleted. 388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(checks_.find(check) != checks_.end()); 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 390dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // |start| is set before calling |GetFullHash()|, which should be 391dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // the only path which gets to here. 392dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(!check->start.is_null()); 393dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UMA_HISTOGRAM_LONG_TIMES("SB2.Network", 394dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen base::TimeTicks::Now() - check->start); 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SBPrefix> prefixes = check->prefix_hits; 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnHandleGetHashResults(check, full_hashes); // 'check' is deleted here. 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (can_cache && MakeDatabaseAvailable()) { 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Cache the GetHash results in memory: 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch database_->CacheHashResults(prefixes, full_hashes); 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::HandleChunk(const std::string& list, 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SBChunkList* chunks) { 407731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(enabled_); 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &SafeBrowsingService::HandleChunkForDatabase, list, chunks)); 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::HandleChunkDelete( 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SBChunkDelete>* chunk_deletes) { 415731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(enabled_); 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &SafeBrowsingService::DeleteChunks, chunk_deletes)); 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::UpdateStarted() { 422731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(enabled_); 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!update_in_progress_); 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch update_in_progress_ = true; 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &SafeBrowsingService::GetAllChunksFromDatabase)); 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::UpdateFinished(bool update_succeeded) { 431731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(enabled_); 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (update_in_progress_) { 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch update_in_progress_ = false; 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &SafeBrowsingService::DatabaseUpdateFinished, 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch update_succeeded)); 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SafeBrowsingService::IsUpdateInProgress() const { 443731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return update_in_progress_; 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::OnBlockingPageDone( 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<UnsafeResource>& resources, 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool proceed) { 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<UnsafeResource>::const_iterator iter = resources.begin(); 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iter != resources.end(); ++iter) { 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const UnsafeResource& resource = *iter; 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotifyClientBlockingComplete(resource.client, proceed); 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (proceed) { 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Whitelist this domain and warning type for the given tab. 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WhiteListedEntry entry; 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.render_process_host_id = resource.render_process_host_id; 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.render_view_id = resource.render_view_id; 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.domain = net::RegistryControlledDomainService::GetDomainAndRegistry( 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource.url); 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.result = resource.threat_type; 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch white_listed_entries_.push_back(entry); 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::OnNewMacKeys(const std::string& client_key, 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& wrapped_key) { 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* prefs = g_browser_process->local_state(); 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (prefs) { 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->SetString(prefs::kSafeBrowsingClientKey, client_key); 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->SetString(prefs::kSafeBrowsingWrappedKey, wrapped_key); 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::OnEnable(bool enabled) { 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (enabled) 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Start(); 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ShutDown(); 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::RegisterPrefs(PrefService* prefs) { 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->RegisterStringPref(prefs::kSafeBrowsingClientKey, ""); 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->RegisterStringPref(prefs::kSafeBrowsingWrappedKey, ""); 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::CloseDatabase() { 491731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Cases to avoid: 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * If |closing_database_| is true, continuing will queue up a second 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // request, |closing_database_| will be reset after handling the first 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // request, and if any functions on the db thread recreate the database, we 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // could start using it on the IO thread and then have the second request 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // handler delete it out from under us. 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * If |database_| is NULL, then either no creation request is in flight, in 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // which case we don't need to do anything, or one is in flight, in which 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // case the database will be recreated before our deletion request is 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // handled, and could be used on the IO thread in that time period, leading 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to the same problem as above. 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // * If |queued_checks_| is non-empty and |database_| is non-NULL, we're 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // about to be called back (in DatabaseLoadComplete()). This will call 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // CheckUrl(), which will want the database. Closing the database here 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // would lead to an infinite loop in DatabaseLoadComplete(), and even if it 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // didn't, it would be pointless since we'd just want to recreate. 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The first two cases above are handled by checking DatabaseAvailable(). 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!DatabaseAvailable() || !queued_checks_.empty()) 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch closing_database_ = true; 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (safe_browsing_thread_.get()) { 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &SafeBrowsingService::OnCloseDatabase)); 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::ResetDatabase() { 522731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(enabled_); 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &SafeBrowsingService::OnResetDatabase)); 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 528dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SafeBrowsingService::LogPauseDelay(base::TimeDelta time) { 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_LONG_TIMES("SB2.Delay", time); 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSafeBrowsingService::~SafeBrowsingService() { 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We should have already been shut down. If we're still enabled, then the 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // database isn't going to be closed properly, which could lead to corruption. 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!enabled_); 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::OnIOInitialize( 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& client_key, 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& wrapped_key, 541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::URLRequestContextGetter* request_context_getter) { 542731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enabled_ = true; 54421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MakeDatabaseAvailable(); 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // On Windows, get the safe browsing client name from the browser 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // distribution classes in installer util. These classes don't yet have 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // an analog on non-Windows builds so just keep the name specified here. 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string client_name(dist->GetSafeBrowsingName()); 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(GOOGLE_CHROME_BUILD) 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string client_name("googlechrome"); 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string client_name("chromium"); 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CommandLine* cmdline = CommandLine::ForCurrentProcess(); 5613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool disable_auto_update = 5623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick cmdline->HasSwitch(switches::kSbDisableAutoUpdate) || 5633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick cmdline->HasSwitch(switches::kDisableBackgroundNetworking); 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string info_url_prefix = 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cmdline->HasSwitch(switches::kSbInfoURLPrefix) ? 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cmdline->GetSwitchValueASCII(switches::kSbInfoURLPrefix) : 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kSbDefaultInfoURLPrefix; 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string mackey_url_prefix = 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cmdline->HasSwitch(switches::kSbMacKeyURLPrefix) ? 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cmdline->GetSwitchValueASCII(switches::kSbMacKeyURLPrefix) : 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kSbDefaultMacKeyURLPrefix; 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(!protocol_manager_); 57421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen protocol_manager_ = 57521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SafeBrowsingProtocolManager::Create(this, 57621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen client_name, 57721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen client_key, 57821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen wrapped_key, 57921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen request_context_getter, 58021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen info_url_prefix, 58121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen mackey_url_prefix, 58221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen disable_auto_update); 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protocol_manager_->Initialize(); 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::OnIOShutdown() { 588731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!enabled_) 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enabled_ = false; 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This cancels all in-flight GetHash requests. 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete protocol_manager_; 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protocol_manager_ = NULL; 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 598dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Delete queued checks, calling back any clients with 'SAFE'. 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we don't do this here we may fail to close the database below. 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (!queued_checks_.empty()) { 601dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen QueuedCheck queued = queued_checks_.front(); 602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (queued.client) { 603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingCheck sb_check; 604ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sb_check.urls.push_back(queued.url); 605dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sb_check.client = queued.client; 606dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sb_check.result = SAFE; 607dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen queued.client->OnSafeBrowsingResult(sb_check); 608dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queued_checks_.pop_front(); 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Close the database. We don't simply DeleteSoon() because if a close is 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // already pending, we'll double-free, and we don't set |database_| to NULL 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // because if there is still anything running on the db thread, it could 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // create a new database object (via GetDatabase()) that would then leak. 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CloseDatabase(); 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Flush the database thread. Any in-progress database check results will be 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ignored and cleaned up below. 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note that to avoid leaking the database, we rely on the fact that no new 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // tasks will be added to the db thread between the call above and this one. 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See comments on the declaration of |safe_browsing_thread_|. 62472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen { 62572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // A ScopedAllowIO object is required to join the thread when calling Stop. 62672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // See http://crbug.com/72696. 62772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join; 62872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen safe_browsing_thread_.reset(); 62972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 631dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Delete pending checks, calling back any clients with 'SAFE'. We have 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to do this after the db thread returns because methods on it can have 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // copies of these pointers, so deleting them might lead to accessing garbage. 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (CurrentChecks::iterator it = checks_.begin(); 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != checks_.end(); ++it) { 636dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingCheck* check = *it; 637dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (check->client) { 638dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->result = SAFE; 639dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->client->OnSafeBrowsingResult(*check); 640dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 641dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (check->timeout_task) 642dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->timeout_task->Cancel(); 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 644dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen STLDeleteElements(&checks_); 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gethash_requests_.clear(); 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SafeBrowsingService::DatabaseAvailable() const { 65072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock lock(database_lock_); 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return !closing_database_ && (database_ != NULL); 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SafeBrowsingService::MakeDatabaseAvailable() { 655731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(enabled_); 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (DatabaseAvailable()) 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &SafeBrowsingService::GetDatabase)); 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSafeBrowsingDatabase* SafeBrowsingService::GetDatabase() { 6653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (database_) 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return database_; 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath path; 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool result = PathService::Get(chrome::DIR_USER_DATA, &path); 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(result); 67221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen path = path.Append(chrome::kSafeBrowsingBaseFilename); 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 674dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const base::TimeTicks before = base::TimeTicks::Now(); 67521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 67621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SafeBrowsingDatabase* database = 677ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingDatabase::Create(enable_download_protection_, 678ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen enable_csd_whitelist_); 67921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch database->Init(path); 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Acquiring the lock here guarantees correct ordering between the writes to 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the new database object above, and the setting of |databse_| below. 68472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock lock(database_lock_); 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch database_ = database; 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 688731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 689731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &SafeBrowsingService::DatabaseLoadComplete)); 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 692dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UMA_HISTOGRAM_TIMES("SB2.DatabaseOpen", base::TimeTicks::Now() - before); 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return database_; 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::OnCheckDone(SafeBrowsingCheck* check) { 697731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 699dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!enabled_) 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 702dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If the service has been shut down, |check| should have been deleted. 703dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(checks_.find(check) != checks_.end()); 704dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (check->client && check->need_get_hash) { 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We have a partial match so we need to query Google for the full hash. 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clean up will happen in HandleGetHashResults. 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See if we have a GetHash request already in progress for this particular 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // prefix. If so, we just append ourselves to the list of interested parties 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when the results arrive. We only do this for checks involving one prefix, 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // since that is the common case (multiple prefixes will issue the request 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // as normal). 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (check->prefix_hits.size() == 1) { 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SBPrefix prefix = check->prefix_hits[0]; 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetHashRequests::iterator it = gethash_requests_.find(prefix); 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it != gethash_requests_.end()) { 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // There's already a request in progress. 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it->second.push_back(check); 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No request in progress, so we're the first for this prefix. 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetHashRequestors requestors; 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch requestors.push_back(check); 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gethash_requests_[prefix] = requestors; 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Reset the start time so that we can measure the network time without the 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // database time. 731dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->start = base::TimeTicks::Now(); 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protocol_manager_->GetFullHash(check, check->prefix_hits); 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 7343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // We may have cached results for previous GetHash queries. Since 7353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // this data comes from cache, don't histogram hits. 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HandleOneCheck(check, check->full_hits); 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::GetAllChunksFromDatabase() { 7413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); 7423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool database_error = true; 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SBListChunkRanges> lists; 7453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!database_update_in_progress_); 7463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick database_update_in_progress_ = true; 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetDatabase(); // This guarantees that |database_| is non-NULL. 7483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (database_->UpdateStarted(&lists)) { 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch database_error = false; 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch database_->UpdateFinished(false); 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 754731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 755731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod( 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &SafeBrowsingService::OnGetAllChunksFromDatabase, lists, 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch database_error)); 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::OnGetAllChunksFromDatabase( 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<SBListChunkRanges>& lists, bool database_error) { 763731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (enabled_) 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protocol_manager_->OnGetChunksComplete(lists, database_error); 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::OnChunkInserted() { 769731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (enabled_) 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protocol_manager_->OnChunkInserted(); 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::DatabaseLoadComplete() { 775731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!enabled_) 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HISTOGRAM_COUNTS("SB.QueueDepth", queued_checks_.size()); 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (queued_checks_.empty()) 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the database isn't already available, calling CheckUrl() in the loop 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // below will add the check back to the queue, and we'll infinite-loop. 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(DatabaseAvailable()); 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (!queued_checks_.empty()) { 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QueuedCheck check = queued_checks_.front(); 788dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(!check.start.is_null()); 789dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen HISTOGRAM_TIMES("SB.QueueDelay", base::TimeTicks::Now() - check.start); 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If CheckUrl() determines the URL is safe immediately, it doesn't call the 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // client's handler function (because normally it's being directly called by 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the client). Since we're not the client, we have to convey this result. 793dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (check.client && CheckBrowseUrl(check.url, check.client)) { 794dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingCheck sb_check; 795ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sb_check.urls.push_back(check.url); 796dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sb_check.client = check.client; 797dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sb_check.result = SAFE; 798dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check.client->OnSafeBrowsingResult(sb_check); 799dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch queued_checks_.pop_front(); 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::HandleChunkForDatabase( 80521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& list_name, SBChunkList* chunks) { 8063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (chunks) { 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetDatabase()->InsertChunks(list_name, *chunks); 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete chunks; 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 811731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 812731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &SafeBrowsingService::OnChunkInserted)); 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::DeleteChunks( 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SBChunkDelete>* chunk_deletes) { 8183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (chunk_deletes) { 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetDatabase()->DeleteChunks(*chunk_deletes); 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete chunk_deletes; 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSafeBrowsingService::UrlCheckResult SafeBrowsingService::GetResultFromListname( 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& list_name) { 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (safe_browsing_util::IsPhishingList(list_name)) { 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return URL_PHISHING; 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (safe_browsing_util::IsMalwareList(list_name)) { 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return URL_MALWARE; 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (safe_browsing_util::IsBadbinurlList(list_name)) { 836dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return BINARY_MALWARE_URL; 837dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 838dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 839dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (safe_browsing_util::IsBadbinhashList(list_name)) { 840dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return BINARY_MALWARE_HASH; 84121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 84221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 843513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DVLOG(1) << "Unknown safe browsing list " << list_name; 844dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return SAFE; 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::NotifyClientBlockingComplete(Client* client, 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool proceed) { 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client->OnBlockingPageComplete(proceed); 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::DatabaseUpdateFinished(bool update_succeeded) { 8533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetDatabase()->UpdateFinished(update_succeeded); 8553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(database_update_in_progress_); 8563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick database_update_in_progress_ = false; 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::Start() { 860ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!safe_browsing_thread_.get()); 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch safe_browsing_thread_.reset(new base::Thread("Chrome_SafeBrowsingThread")); 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!safe_browsing_thread_->Start()) 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Retrieve client MAC keys. 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* local_state = g_browser_process->local_state(); 868ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(local_state); 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string client_key, wrapped_key; 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (local_state) { 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_key = 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->GetString(prefs::kSafeBrowsingClientKey); 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch wrapped_key = 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->GetString(prefs::kSafeBrowsingWrappedKey); 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We will issue network fetches using the default profile's request context. 878ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<net::URLRequestContextGetter> request_context_getter( 879513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GetDefaultProfile()->GetRequestContext()); 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 881ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CommandLine* cmdline = CommandLine::ForCurrentProcess(); 882ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen enable_download_protection_ = 883ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !cmdline->HasSwitch(switches::kSbDisableDownloadProtection); 884ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 885ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We only download the csd-whitelist if client-side phishing detection is 886ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // enabled and if the user has opted in with stats collection. Note: we 887ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // cannot check whether the metrics_service() object is created because it 888ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // may be initialized after this method is called. 889ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#ifdef OS_CHROMEOS 890ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Client-side detection is disabled on ChromeOS for now, so don't bother 891ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // downloading the whitelist. 892ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen enable_csd_whitelist_ = false; 893ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#else 894ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen enable_csd_whitelist_ = 895ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (!cmdline->HasSwitch(switches::kDisableClientSidePhishingDetection) && 896ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen local_state && local_state->GetBoolean(prefs::kMetricsReportingEnabled)); 897ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 898ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 899731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 900731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod( 902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &SafeBrowsingService::OnIOInitialize, client_key, wrapped_key, 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request_context_getter)); 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::OnCloseDatabase() { 9073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(closing_database_); 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Because |closing_database_| is true, nothing on the IO thread will be 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // accessing the database, so it's safe to delete and then NULL the pointer. 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete database_; 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch database_ = NULL; 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Acquiring the lock here guarantees correct ordering between the resetting 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of |database_| above and of |closing_database_| below, which ensures there 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // won't be a window during which the IO thread falsely believes the database 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is available. 91972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock lock(database_lock_); 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch closing_database_ = false; 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::OnResetDatabase() { 9243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetDatabase()->ResetDatabase(); 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::CacheHashResults( 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<SBPrefix>& prefixes, 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<SBFullHashResult>& full_hashes) { 9313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetDatabase()->CacheHashResults(prefixes, full_hashes); 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::OnHandleGetHashResults( 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SafeBrowsingCheck* check, 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<SBFullHashResult>& full_hashes) { 938731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 939dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool is_download = check->is_download; 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SBPrefix prefix = check->prefix_hits[0]; 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetHashRequests::iterator it = gethash_requests_.find(prefix); 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (check->prefix_hits.size() > 1 || it == gethash_requests_.end()) { 9433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const bool hit = HandleOneCheck(check, full_hashes); 944dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen RecordGetHashCheckStatus(hit, is_download, full_hashes); 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Call back all interested parties, noting if any has a hit. 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetHashRequestors& requestors = it->second; 9503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool hit = false; 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (GetHashRequestors::iterator r = requestors.begin(); 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch r != requestors.end(); ++r) { 9533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (HandleOneCheck(*r, full_hashes)) 9543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen hit = true; 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 956dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen RecordGetHashCheckStatus(hit, is_download, full_hashes); 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gethash_requests_.erase(it); 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenbool SafeBrowsingService::HandleOneCheck( 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SafeBrowsingCheck* check, 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<SBFullHashResult>& full_hashes) { 964731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 965dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(check); 9663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 9673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Always calculate the index, for recording hits. 968dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int index = -1; 969ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!check->urls.empty()) { 970ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < check->urls.size(); ++i) { 971ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen index = safe_browsing_util::GetUrlHashIndex(check->urls[i], full_hashes); 972ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (index != -1) 973ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 974ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 975ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 976dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen index = safe_browsing_util::GetHashIndex(*(check->full_hash), full_hashes); 977ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 9783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 9793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // |client| is NULL if the request was cancelled. 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (check->client) { 981dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->result = SAFE; 9823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (index != -1) 983dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->result = GetResultFromListname(full_hashes[index].list_name); 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 985dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingCheckDone(check); 9863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return (index != -1); 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingService::DoDisplayBlockingPage( 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const UnsafeResource& resource) { 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tab might have been closed. 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* wc = 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_util::GetTabContentsByID(resource.render_process_host_id, 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource.render_view_id); 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!wc) { 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tab is gone and we did not have a chance at showing the interstitial. 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Just act as "Don't Proceed" was chosen. 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<UnsafeResource> resources; 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resources.push_back(resource); 1001731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 1002731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod( 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, &SafeBrowsingService::OnBlockingPageDone, resources, false)); 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1008dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (resource.threat_type != SafeBrowsingService::SAFE && CanReportStats()) { 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL page_url = wc->GetURL(); 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL referrer_url; 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NavigationEntry* entry = wc->controller().GetActiveEntry(); 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry) 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch referrer_url = entry->referrer(); 10143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool is_subresource = resource.resource_type != ResourceType::MAIN_FRAME; 10153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 10163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // When the malicious url is on the main frame, and resource.original_url 10173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // is not the same as the resource.url, that means we have a redirect from 10183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // resource.original_url to resource.url. 10193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Also, at this point, page_url points to the _previous_ page that we 10203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // were on. We replace page_url with resource.original_url and referrer 10213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // with page_url. 10223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!is_subresource && 10233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick !resource.original_url.is_empty() && 10243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick resource.original_url != resource.url) { 10253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick referrer_url = page_url; 10263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick page_url = resource.original_url; 10273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1028dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ReportSafeBrowsingHit(resource.url, page_url, referrer_url, is_subresource, 1029ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen resource.threat_type, std::string() /* post_data */); 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SafeBrowsingBlockingPage::ShowBlockingPage(this, resource); 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1035dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// A safebrowsing hit is sent after a blocking page for malware/phishing 1036dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// or after the warning dialog for download urls, only for UMA users. 1037731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SafeBrowsingService::ReportSafeBrowsingHit( 1038731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GURL& malicious_url, 1039731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GURL& page_url, 1040731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const GURL& referrer_url, 1041731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool is_subresource, 1042ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingService::UrlCheckResult threat_type, 1043ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& post_data) { 1044dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1045dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!CanReportStats()) 1046dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 1047dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1048dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::PostTask( 1049dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::IO, FROM_HERE, 1050dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableMethod( 1051dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this, 1052dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &SafeBrowsingService::ReportSafeBrowsingHitOnIOThread, 1053dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen malicious_url, 1054dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen page_url, 1055dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen referrer_url, 1056dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen is_subresource, 1057ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen threat_type, 1058ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen post_data)); 1059dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1060dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1061dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SafeBrowsingService::ReportSafeBrowsingHitOnIOThread( 1062dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const GURL& malicious_url, 1063dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const GURL& page_url, 1064dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const GURL& referrer_url, 1065dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool is_subresource, 1066ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SafeBrowsingService::UrlCheckResult threat_type, 1067ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& post_data) { 1068731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!enabled_) 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1072513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DVLOG(1) << "ReportSafeBrowsingHit: " << malicious_url << " " << page_url 1073513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << " " << referrer_url << " " << is_subresource << " " 1074513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << threat_type; 1075731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick protocol_manager_->ReportSafeBrowsingHit(malicious_url, page_url, 1076731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick referrer_url, is_subresource, 1077ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen threat_type, post_data); 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 107921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1080dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// If the user had opted-in to send MalwareDetails, this gets called 1081ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// when the report is ready. 1082ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SafeBrowsingService::SendSerializedMalwareDetails( 1083ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& serialized) { 108421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1085ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!serialized.empty()) { 108621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DVLOG(1) << "Sending serialized malware details."; 1087ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen protocol_manager_->ReportMalwareDetails(serialized); 108821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 108921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 1090dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1091dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SafeBrowsingService::CheckDownloadHashOnSBThread( 1092dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingCheck* check) { 1093dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); 1094dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(enable_download_protection_); 1095dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1096dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!database_->ContainsDownloadHashPrefix(check->full_hash->prefix)) { 1097dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Good, we don't have hash for this url prefix. 1098dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->result = SAFE; 1099dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::PostTask( 1100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::IO, FROM_HERE, 1101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableMethod(this, 1102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &SafeBrowsingService::CheckDownloadHashDone, 1103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check)); 1104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 1105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 1106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->need_get_hash = true; 1108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->prefix_hits.push_back(check->full_hash->prefix); 1109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::PostTask( 1110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::IO, FROM_HERE, 1111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableMethod(this, &SafeBrowsingService::OnCheckDone, check)); 1112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SafeBrowsingService::CheckDownloadUrlOnSBThread(SafeBrowsingCheck* check) { 1115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(MessageLoop::current(), safe_browsing_thread_->message_loop()); 1116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(enable_download_protection_); 1117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<SBPrefix> prefix_hits; 1119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!database_->ContainsDownloadUrl(check->urls, &prefix_hits)) { 1121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Good, we don't have hash for this url prefix. 1122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->result = SAFE; 1123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::PostTask( 1124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::IO, FROM_HERE, 1125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableMethod(this, 1126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &SafeBrowsingService::CheckDownloadUrlDone, 1127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check)); 1128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 1129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 1130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->need_get_hash = true; 1132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->prefix_hits.clear(); 1133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen check->prefix_hits = prefix_hits; 1134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::PostTask( 1135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BrowserThread::IO, FROM_HERE, 1136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableMethod(this, &SafeBrowsingService::OnCheckDone, check)); 1137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SafeBrowsingService::TimeoutCallback(SafeBrowsingCheck* check) { 1140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(check); 1142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!enabled_) 1144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 1145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(checks_.find(check) != checks_.end()); 1147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(check->result, SAFE); 1148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (check->client) { 1149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->client->OnSafeBrowsingResult(*check); 1150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->client = NULL; 1151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 1152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->timeout_task = NULL; 1153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SafeBrowsingService::CheckDownloadUrlDone(SafeBrowsingCheck* check) { 1156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(enable_download_protection_); 1157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingCheckDone(check); 1158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SafeBrowsingService::CheckDownloadHashDone(SafeBrowsingCheck* check) { 1161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(enable_download_protection_); 1162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SafeBrowsingCheckDone(check); 1163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SafeBrowsingService::SafeBrowsingCheckDone(SafeBrowsingCheck* check) { 1166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(check); 1168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!enabled_) 1170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 1171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(1) << "SafeBrowsingCheckDone: " << check->result; 1173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(checks_.find(check) != checks_.end()); 1174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (check->client) 1175dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->client->OnSafeBrowsingResult(*check); 1176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (check->timeout_task) 1177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->timeout_task->Cancel(); 1178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen checks_.erase(check); 1179dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete check; 1180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SafeBrowsingService::StartDownloadCheck(SafeBrowsingCheck* check, 1183dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen Client* client, 1184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CancelableTask* task, 1185dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 timeout_ms) { 1186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->client = client; 1188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->result = SAFE; 1189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->is_download = true; 1190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen check->timeout_task = 1191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableMethod(this, &SafeBrowsingService::TimeoutCallback, check); 1192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen checks_.insert(check); 1193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen safe_browsing_thread_->message_loop()->PostTask(FROM_HERE, task); 1195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MessageLoop::current()->PostDelayedTask( 1197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FROM_HERE, check->timeout_task, timeout_ms); 1198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1199