1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/safe_browsing/safe_browsing_service.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/callback.h" 10 #include "base/command_line.h" 11 #include "base/debug/leak_tracker.h" 12 #include "base/lazy_instance.h" 13 #include "base/path_service.h" 14 #include "base/prefs/pref_change_registrar.h" 15 #include "base/prefs/pref_service.h" 16 #include "base/stl_util.h" 17 #include "base/strings/string_util.h" 18 #include "base/threading/thread.h" 19 #include "base/threading/thread_restrictions.h" 20 #include "chrome/browser/browser_process.h" 21 #include "chrome/browser/chrome_notification_types.h" 22 #include "chrome/browser/metrics/metrics_service.h" 23 #include "chrome/browser/profiles/profile.h" 24 #include "chrome/browser/profiles/profile_manager.h" 25 #include "chrome/browser/safe_browsing/client_side_detection_service.h" 26 #include "chrome/browser/safe_browsing/database_manager.h" 27 #include "chrome/browser/safe_browsing/download_protection_service.h" 28 #include "chrome/browser/safe_browsing/malware_details.h" 29 #include "chrome/browser/safe_browsing/ping_manager.h" 30 #include "chrome/browser/safe_browsing/protocol_manager.h" 31 #include "chrome/browser/safe_browsing/safe_browsing_database.h" 32 #include "chrome/browser/safe_browsing/ui_manager.h" 33 #include "chrome/common/chrome_constants.h" 34 #include "chrome/common/chrome_paths.h" 35 #include "chrome/common/chrome_switches.h" 36 #include "chrome/common/pref_names.h" 37 #include "chrome/common/url_constants.h" 38 #include "components/startup_metric_utils/startup_metric_utils.h" 39 #include "content/public/browser/browser_thread.h" 40 #include "content/public/browser/cookie_crypto_delegate.h" 41 #include "content/public/browser/cookie_store_factory.h" 42 #include "content/public/browser/notification_service.h" 43 #include "net/cookies/cookie_monster.h" 44 #include "net/url_request/url_request_context.h" 45 #include "net/url_request/url_request_context_getter.h" 46 47 #if defined(OS_WIN) 48 #include "chrome/installer/util/browser_distribution.h" 49 #endif 50 51 using content::BrowserThread; 52 53 namespace { 54 55 // Filename suffix for the cookie database. 56 const base::FilePath::CharType kCookiesFile[] = FILE_PATH_LITERAL(" Cookies"); 57 58 // The default URL prefix where browser fetches chunk updates, hashes, 59 // and reports safe browsing hits and malware details. 60 const char* const kSbDefaultURLPrefix = 61 "https://safebrowsing.google.com/safebrowsing"; 62 63 // The backup URL prefix used when there are issues establishing a connection 64 // with the server at the primary URL. 65 const char* const kSbBackupConnectErrorURLPrefix = 66 "https://alt1-safebrowsing.google.com/safebrowsing"; 67 68 // The backup URL prefix used when there are HTTP-specific issues with the 69 // server at the primary URL. 70 const char* const kSbBackupHttpErrorURLPrefix = 71 "https://alt2-safebrowsing.google.com/safebrowsing"; 72 73 // The backup URL prefix used when there are local network specific issues. 74 const char* const kSbBackupNetworkErrorURLPrefix = 75 "https://alt3-safebrowsing.google.com/safebrowsing"; 76 77 base::FilePath CookieFilePath() { 78 return base::FilePath( 79 SafeBrowsingService::GetBaseFilename().value() + kCookiesFile); 80 } 81 82 } // namespace 83 84 class SafeBrowsingURLRequestContextGetter 85 : public net::URLRequestContextGetter { 86 public: 87 explicit SafeBrowsingURLRequestContextGetter( 88 SafeBrowsingService* sb_service_); 89 90 // Implementation for net::UrlRequestContextGetter. 91 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE; 92 virtual scoped_refptr<base::SingleThreadTaskRunner> 93 GetNetworkTaskRunner() const OVERRIDE; 94 95 protected: 96 virtual ~SafeBrowsingURLRequestContextGetter(); 97 98 private: 99 SafeBrowsingService* const sb_service_; // Owned by BrowserProcess. 100 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; 101 102 base::debug::LeakTracker<SafeBrowsingURLRequestContextGetter> leak_tracker_; 103 }; 104 105 SafeBrowsingURLRequestContextGetter::SafeBrowsingURLRequestContextGetter( 106 SafeBrowsingService* sb_service) 107 : sb_service_(sb_service), 108 network_task_runner_( 109 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) { 110 } 111 112 SafeBrowsingURLRequestContextGetter::~SafeBrowsingURLRequestContextGetter() {} 113 114 net::URLRequestContext* 115 SafeBrowsingURLRequestContextGetter::GetURLRequestContext() { 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 117 DCHECK(sb_service_->url_request_context_.get()); 118 119 return sb_service_->url_request_context_.get(); 120 } 121 122 scoped_refptr<base::SingleThreadTaskRunner> 123 SafeBrowsingURLRequestContextGetter::GetNetworkTaskRunner() const { 124 return network_task_runner_; 125 } 126 127 // static 128 SafeBrowsingServiceFactory* SafeBrowsingService::factory_ = NULL; 129 130 // The default SafeBrowsingServiceFactory. Global, made a singleton so we 131 // don't leak it. 132 class SafeBrowsingServiceFactoryImpl : public SafeBrowsingServiceFactory { 133 public: 134 virtual SafeBrowsingService* CreateSafeBrowsingService() OVERRIDE { 135 return new SafeBrowsingService(); 136 } 137 138 private: 139 friend struct base::DefaultLazyInstanceTraits<SafeBrowsingServiceFactoryImpl>; 140 141 SafeBrowsingServiceFactoryImpl() { } 142 143 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactoryImpl); 144 }; 145 146 static base::LazyInstance<SafeBrowsingServiceFactoryImpl>::Leaky 147 g_safe_browsing_service_factory_impl = LAZY_INSTANCE_INITIALIZER; 148 149 // static 150 base::FilePath SafeBrowsingService::GetCookieFilePathForTesting() { 151 return CookieFilePath(); 152 } 153 154 // static 155 base::FilePath SafeBrowsingService::GetBaseFilename() { 156 base::FilePath path; 157 bool result = PathService::Get(chrome::DIR_USER_DATA, &path); 158 DCHECK(result); 159 return path.Append(chrome::kSafeBrowsingBaseFilename); 160 } 161 162 163 // static 164 SafeBrowsingService* SafeBrowsingService::CreateSafeBrowsingService() { 165 if (!factory_) 166 factory_ = g_safe_browsing_service_factory_impl.Pointer(); 167 return factory_->CreateSafeBrowsingService(); 168 } 169 170 SafeBrowsingService::SafeBrowsingService() 171 : protocol_manager_(NULL), 172 ping_manager_(NULL), 173 enabled_(false) { 174 } 175 176 SafeBrowsingService::~SafeBrowsingService() { 177 // We should have already been shut down. If we're still enabled, then the 178 // database isn't going to be closed properly, which could lead to corruption. 179 DCHECK(!enabled_); 180 } 181 182 void SafeBrowsingService::Initialize() { 183 startup_metric_utils::ScopedSlowStartupUMA 184 scoped_timer("Startup.SlowStartupSafeBrowsingServiceInitialize"); 185 186 url_request_context_getter_ = 187 new SafeBrowsingURLRequestContextGetter(this); 188 189 ui_manager_ = CreateUIManager(); 190 191 database_manager_ = CreateDatabaseManager(); 192 193 BrowserThread::PostTask( 194 BrowserThread::IO, FROM_HERE, 195 base::Bind( 196 &SafeBrowsingService::InitURLRequestContextOnIOThread, this, 197 make_scoped_refptr(g_browser_process->system_request_context()))); 198 199 #if defined(FULL_SAFE_BROWSING) 200 if (!CommandLine::ForCurrentProcess()->HasSwitch( 201 switches::kDisableClientSidePhishingDetection)) { 202 csd_service_.reset(safe_browsing::ClientSideDetectionService::Create( 203 url_request_context_getter_.get())); 204 } 205 download_service_.reset(new safe_browsing::DownloadProtectionService( 206 this, url_request_context_getter_.get())); 207 #endif 208 209 // Track the safe browsing preference of existing profiles. 210 // The SafeBrowsingService will be started if any existing profile has the 211 // preference enabled. It will also listen for updates to the preferences. 212 ProfileManager* profile_manager = g_browser_process->profile_manager(); 213 if (profile_manager) { 214 std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles(); 215 for (size_t i = 0; i < profiles.size(); ++i) { 216 if (profiles[i]->IsOffTheRecord()) 217 continue; 218 AddPrefService(profiles[i]->GetPrefs()); 219 } 220 } 221 222 // Track profile creation and destruction. 223 prefs_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, 224 content::NotificationService::AllSources()); 225 prefs_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 226 content::NotificationService::AllSources()); 227 } 228 229 void SafeBrowsingService::ShutDown() { 230 // Deletes the PrefChangeRegistrars, whose dtors also unregister |this| as an 231 // observer of the preferences. 232 STLDeleteValues(&prefs_map_); 233 234 // Remove Profile creation/destruction observers. 235 prefs_registrar_.RemoveAll(); 236 237 Stop(true); 238 // The IO thread is going away, so make sure the ClientSideDetectionService 239 // dtor executes now since it may call the dtor of URLFetcher which relies 240 // on it. 241 csd_service_.reset(); 242 download_service_.reset(); 243 244 url_request_context_getter_ = NULL; 245 BrowserThread::PostNonNestableTask( 246 BrowserThread::IO, FROM_HERE, 247 base::Bind(&SafeBrowsingService::DestroyURLRequestContextOnIOThread, 248 this)); 249 } 250 251 // Binhash verification is only enabled for UMA users for now. 252 bool SafeBrowsingService::DownloadBinHashNeeded() const { 253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 254 255 #if defined(FULL_SAFE_BROWSING) 256 return (database_manager_->download_protection_enabled() && 257 ui_manager_->CanReportStats()) || 258 (download_protection_service() && 259 download_protection_service()->enabled()); 260 #else 261 return false; 262 #endif 263 } 264 265 net::URLRequestContextGetter* SafeBrowsingService::url_request_context() { 266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 267 return url_request_context_getter_.get(); 268 } 269 270 const scoped_refptr<SafeBrowsingUIManager>& 271 SafeBrowsingService::ui_manager() const { 272 return ui_manager_; 273 } 274 275 const scoped_refptr<SafeBrowsingDatabaseManager>& 276 SafeBrowsingService::database_manager() const { 277 return database_manager_; 278 } 279 280 SafeBrowsingProtocolManager* SafeBrowsingService::protocol_manager() const { 281 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 282 return protocol_manager_; 283 } 284 285 SafeBrowsingPingManager* SafeBrowsingService::ping_manager() const { 286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 287 return ping_manager_; 288 } 289 290 SafeBrowsingUIManager* SafeBrowsingService::CreateUIManager() { 291 return new SafeBrowsingUIManager(this); 292 } 293 294 SafeBrowsingDatabaseManager* SafeBrowsingService::CreateDatabaseManager() { 295 296 #if defined(FULL_SAFE_BROWSING) 297 return new SafeBrowsingDatabaseManager(this); 298 #else 299 return NULL; 300 #endif 301 } 302 303 void SafeBrowsingService::InitURLRequestContextOnIOThread( 304 net::URLRequestContextGetter* system_url_request_context_getter) { 305 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 306 DCHECK(!url_request_context_.get()); 307 308 scoped_refptr<net::CookieStore> cookie_store( 309 content::CreatePersistentCookieStore( 310 CookieFilePath(), 311 false, 312 NULL, 313 NULL, 314 scoped_ptr<content::CookieCryptoDelegate>())); 315 316 url_request_context_.reset(new net::URLRequestContext); 317 // |system_url_request_context_getter| may be NULL during tests. 318 if (system_url_request_context_getter) { 319 url_request_context_->CopyFrom( 320 system_url_request_context_getter->GetURLRequestContext()); 321 } 322 url_request_context_->set_cookie_store(cookie_store.get()); 323 } 324 325 void SafeBrowsingService::DestroyURLRequestContextOnIOThread() { 326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 327 328 url_request_context_->AssertNoURLRequests(); 329 330 // Need to do the CheckForLeaks on IOThread instead of in ShutDown where 331 // url_request_context_getter_ is cleared, since the URLRequestContextGetter 332 // will PostTask to IOTread to delete itself. 333 using base::debug::LeakTracker; 334 LeakTracker<SafeBrowsingURLRequestContextGetter>::CheckForLeaks(); 335 336 url_request_context_.reset(); 337 } 338 339 void SafeBrowsingService::StartOnIOThread( 340 net::URLRequestContextGetter* url_request_context_getter) { 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 342 if (enabled_) 343 return; 344 enabled_ = true; 345 346 SafeBrowsingProtocolConfig config; 347 // On Windows, get the safe browsing client name from the browser 348 // distribution classes in installer util. These classes don't yet have 349 // an analog on non-Windows builds so just keep the name specified here. 350 #if defined(OS_WIN) 351 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 352 config.client_name = dist->GetSafeBrowsingName(); 353 #else 354 #if defined(GOOGLE_CHROME_BUILD) 355 config.client_name = "googlechrome"; 356 #else 357 config.client_name = "chromium"; 358 #endif 359 #endif 360 CommandLine* cmdline = CommandLine::ForCurrentProcess(); 361 config.disable_auto_update = 362 cmdline->HasSwitch(switches::kSbDisableAutoUpdate) || 363 cmdline->HasSwitch(switches::kDisableBackgroundNetworking); 364 if (cmdline->HasSwitch(switches::kSbURLPrefix)) { 365 config.url_prefix = cmdline->GetSwitchValueASCII(switches::kSbURLPrefix); 366 } else { 367 config.url_prefix = kSbDefaultURLPrefix; 368 config.backup_connect_error_url_prefix = kSbBackupConnectErrorURLPrefix; 369 config.backup_http_error_url_prefix = kSbBackupHttpErrorURLPrefix; 370 config.backup_network_error_url_prefix = kSbBackupNetworkErrorURLPrefix; 371 } 372 373 #if defined(FULL_SAFE_BROWSING) 374 DCHECK(database_manager_.get()); 375 database_manager_->StartOnIOThread(); 376 377 DCHECK(!protocol_manager_); 378 protocol_manager_ = SafeBrowsingProtocolManager::Create( 379 database_manager_.get(), url_request_context_getter, config); 380 protocol_manager_->Initialize(); 381 #endif 382 383 DCHECK(!ping_manager_); 384 ping_manager_ = SafeBrowsingPingManager::Create( 385 url_request_context_getter, config); 386 } 387 388 void SafeBrowsingService::StopOnIOThread(bool shutdown) { 389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 390 391 #if defined(FULL_SAFE_BROWSING) 392 database_manager_->StopOnIOThread(shutdown); 393 #endif 394 ui_manager_->StopOnIOThread(shutdown); 395 396 if (enabled_) { 397 enabled_ = false; 398 399 #if defined(FULL_SAFE_BROWSING) 400 // This cancels all in-flight GetHash requests. Note that database_manager_ 401 // relies on the protocol_manager_ so if the latter is destroyed, the 402 // former must be stopped. 403 delete protocol_manager_; 404 protocol_manager_ = NULL; 405 #endif 406 delete ping_manager_; 407 ping_manager_ = NULL; 408 } 409 } 410 411 void SafeBrowsingService::Start() { 412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 413 414 BrowserThread::PostTask( 415 BrowserThread::IO, FROM_HERE, 416 base::Bind(&SafeBrowsingService::StartOnIOThread, this, 417 url_request_context_getter_)); 418 } 419 420 void SafeBrowsingService::Stop(bool shutdown) { 421 BrowserThread::PostTask( 422 BrowserThread::IO, FROM_HERE, 423 base::Bind(&SafeBrowsingService::StopOnIOThread, this, shutdown)); 424 } 425 426 void SafeBrowsingService::Observe(int type, 427 const content::NotificationSource& source, 428 const content::NotificationDetails& details) { 429 switch (type) { 430 case chrome::NOTIFICATION_PROFILE_CREATED: { 431 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 432 Profile* profile = content::Source<Profile>(source).ptr(); 433 if (!profile->IsOffTheRecord()) 434 AddPrefService(profile->GetPrefs()); 435 break; 436 } 437 case chrome::NOTIFICATION_PROFILE_DESTROYED: { 438 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 439 Profile* profile = content::Source<Profile>(source).ptr(); 440 if (!profile->IsOffTheRecord()) 441 RemovePrefService(profile->GetPrefs()); 442 break; 443 } 444 default: 445 NOTREACHED(); 446 } 447 } 448 449 void SafeBrowsingService::AddPrefService(PrefService* pref_service) { 450 DCHECK(prefs_map_.find(pref_service) == prefs_map_.end()); 451 PrefChangeRegistrar* registrar = new PrefChangeRegistrar(); 452 registrar->Init(pref_service); 453 registrar->Add(prefs::kSafeBrowsingEnabled, 454 base::Bind(&SafeBrowsingService::RefreshState, 455 base::Unretained(this))); 456 prefs_map_[pref_service] = registrar; 457 RefreshState(); 458 } 459 460 void SafeBrowsingService::RemovePrefService(PrefService* pref_service) { 461 if (prefs_map_.find(pref_service) != prefs_map_.end()) { 462 delete prefs_map_[pref_service]; 463 prefs_map_.erase(pref_service); 464 RefreshState(); 465 } else { 466 NOTREACHED(); 467 } 468 } 469 470 void SafeBrowsingService::RefreshState() { 471 // Check if any profile requires the service to be active. 472 bool enable = false; 473 std::map<PrefService*, PrefChangeRegistrar*>::iterator iter; 474 for (iter = prefs_map_.begin(); iter != prefs_map_.end(); ++iter) { 475 if (iter->first->GetBoolean(prefs::kSafeBrowsingEnabled)) { 476 enable = true; 477 break; 478 } 479 } 480 481 if (enable) 482 Start(); 483 else 484 Stop(false); 485 486 #if defined(FULL_SAFE_BROWSING) 487 if (csd_service_.get()) 488 csd_service_->SetEnabledAndRefreshState(enable); 489 if (download_service_.get()) { 490 download_service_->SetEnabled( 491 enable && !CommandLine::ForCurrentProcess()->HasSwitch( 492 switches::kDisableImprovedDownloadProtection)); 493 } 494 #endif 495 } 496