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