Roll src/third_party/WebKit 8b42d1d:744641d (svn 186770:186771)
[chromium-blink-merge.git] / chrome / browser / safe_browsing / safe_browsing_service.cc
blob7cd72e3e53b2e47e8e3cf6480b00a53dc924835b
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.
5 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback.h"
12 #include "base/command_line.h"
13 #include "base/debug/leak_tracker.h"
14 #include "base/lazy_instance.h"
15 #include "base/path_service.h"
16 #include "base/prefs/pref_change_registrar.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/stl_util.h"
19 #include "base/strings/string_util.h"
20 #include "base/threading/thread.h"
21 #include "base/threading/thread_restrictions.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/chrome_notification_types.h"
24 #include "chrome/browser/prefs/tracked/tracked_preference_validation_delegate.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/profiles/profile_manager.h"
27 #include "chrome/browser/safe_browsing/client_side_detection_service.h"
28 #include "chrome/browser/safe_browsing/database_manager.h"
29 #include "chrome/browser/safe_browsing/download_protection_service.h"
30 #include "chrome/browser/safe_browsing/malware_details.h"
31 #include "chrome/browser/safe_browsing/ping_manager.h"
32 #include "chrome/browser/safe_browsing/protocol_manager.h"
33 #include "chrome/browser/safe_browsing/safe_browsing_database.h"
34 #include "chrome/browser/safe_browsing/ui_manager.h"
35 #include "chrome/common/chrome_constants.h"
36 #include "chrome/common/chrome_paths.h"
37 #include "chrome/common/chrome_switches.h"
38 #include "chrome/common/pref_names.h"
39 #include "chrome/common/url_constants.h"
40 #include "components/metrics/metrics_service.h"
41 #include "components/startup_metric_utils/startup_metric_utils.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/cookie_crypto_delegate.h"
44 #include "content/public/browser/cookie_store_factory.h"
45 #include "content/public/browser/notification_service.h"
46 #include "net/cookies/cookie_monster.h"
47 #include "net/url_request/url_request_context.h"
48 #include "net/url_request/url_request_context_getter.h"
50 #if defined(OS_WIN)
51 #include "chrome/installer/util/browser_distribution.h"
52 #endif
54 #if defined(FULL_SAFE_BROWSING)
55 #include "chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer.h"
56 #include "chrome/browser/safe_browsing/incident_reporting/blacklist_load_analyzer.h"
57 #include "chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h"
58 #include "chrome/browser/safe_browsing/incident_reporting/off_domain_inclusion_detector.h"
59 #endif
61 using content::BrowserThread;
63 namespace {
65 // Filename suffix for the cookie database.
66 const base::FilePath::CharType kCookiesFile[] = FILE_PATH_LITERAL(" Cookies");
68 // The default URL prefix where browser fetches chunk updates, hashes,
69 // and reports safe browsing hits and malware details.
70 const char* const kSbDefaultURLPrefix =
71 "https://safebrowsing.google.com/safebrowsing";
73 // The backup URL prefix used when there are issues establishing a connection
74 // with the server at the primary URL.
75 const char* const kSbBackupConnectErrorURLPrefix =
76 "https://alt1-safebrowsing.google.com/safebrowsing";
78 // The backup URL prefix used when there are HTTP-specific issues with the
79 // server at the primary URL.
80 const char* const kSbBackupHttpErrorURLPrefix =
81 "https://alt2-safebrowsing.google.com/safebrowsing";
83 // The backup URL prefix used when there are local network specific issues.
84 const char* const kSbBackupNetworkErrorURLPrefix =
85 "https://alt3-safebrowsing.google.com/safebrowsing";
87 base::FilePath CookieFilePath() {
88 return base::FilePath(
89 SafeBrowsingService::GetBaseFilename().value() + kCookiesFile);
92 #if defined(FULL_SAFE_BROWSING)
93 // Returns true if the incident reporting service is enabled via a field trial.
94 bool IsIncidentReportingServiceEnabled() {
95 const std::string group_name = base::FieldTrialList::FindFullName(
96 "SafeBrowsingIncidentReportingService");
97 return group_name == "Enabled";
99 #endif // defined(FULL_SAFE_BROWSING)
101 } // namespace
103 class SafeBrowsingURLRequestContextGetter
104 : public net::URLRequestContextGetter {
105 public:
106 explicit SafeBrowsingURLRequestContextGetter(
107 SafeBrowsingService* sb_service_);
109 // Implementation for net::UrlRequestContextGetter.
110 net::URLRequestContext* GetURLRequestContext() override;
111 scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
112 const override;
114 protected:
115 ~SafeBrowsingURLRequestContextGetter() override;
117 private:
118 SafeBrowsingService* const sb_service_; // Owned by BrowserProcess.
119 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
121 base::debug::LeakTracker<SafeBrowsingURLRequestContextGetter> leak_tracker_;
124 SafeBrowsingURLRequestContextGetter::SafeBrowsingURLRequestContextGetter(
125 SafeBrowsingService* sb_service)
126 : sb_service_(sb_service),
127 network_task_runner_(
128 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) {
131 SafeBrowsingURLRequestContextGetter::~SafeBrowsingURLRequestContextGetter() {}
133 net::URLRequestContext*
134 SafeBrowsingURLRequestContextGetter::GetURLRequestContext() {
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
136 DCHECK(sb_service_->url_request_context_.get());
138 return sb_service_->url_request_context_.get();
141 scoped_refptr<base::SingleThreadTaskRunner>
142 SafeBrowsingURLRequestContextGetter::GetNetworkTaskRunner() const {
143 return network_task_runner_;
146 // static
147 SafeBrowsingServiceFactory* SafeBrowsingService::factory_ = NULL;
149 // The default SafeBrowsingServiceFactory. Global, made a singleton so we
150 // don't leak it.
151 class SafeBrowsingServiceFactoryImpl : public SafeBrowsingServiceFactory {
152 public:
153 SafeBrowsingService* CreateSafeBrowsingService() override {
154 return new SafeBrowsingService();
157 private:
158 friend struct base::DefaultLazyInstanceTraits<SafeBrowsingServiceFactoryImpl>;
160 SafeBrowsingServiceFactoryImpl() { }
162 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactoryImpl);
165 static base::LazyInstance<SafeBrowsingServiceFactoryImpl>::Leaky
166 g_safe_browsing_service_factory_impl = LAZY_INSTANCE_INITIALIZER;
168 // static
169 base::FilePath SafeBrowsingService::GetCookieFilePathForTesting() {
170 return CookieFilePath();
173 // static
174 base::FilePath SafeBrowsingService::GetBaseFilename() {
175 base::FilePath path;
176 bool result = PathService::Get(chrome::DIR_USER_DATA, &path);
177 DCHECK(result);
178 return path.Append(chrome::kSafeBrowsingBaseFilename);
182 // static
183 SafeBrowsingService* SafeBrowsingService::CreateSafeBrowsingService() {
184 if (!factory_)
185 factory_ = g_safe_browsing_service_factory_impl.Pointer();
186 return factory_->CreateSafeBrowsingService();
190 SafeBrowsingService::SafeBrowsingService()
191 : protocol_manager_(NULL),
192 ping_manager_(NULL),
193 enabled_(false) {
196 SafeBrowsingService::~SafeBrowsingService() {
197 // We should have already been shut down. If we're still enabled, then the
198 // database isn't going to be closed properly, which could lead to corruption.
199 DCHECK(!enabled_);
202 void SafeBrowsingService::Initialize() {
203 startup_metric_utils::ScopedSlowStartupUMA
204 scoped_timer("Startup.SlowStartupSafeBrowsingServiceInitialize");
206 url_request_context_getter_ =
207 new SafeBrowsingURLRequestContextGetter(this);
209 ui_manager_ = CreateUIManager();
211 database_manager_ = CreateDatabaseManager();
213 BrowserThread::PostTask(
214 BrowserThread::IO, FROM_HERE,
215 base::Bind(
216 &SafeBrowsingService::InitURLRequestContextOnIOThread, this,
217 make_scoped_refptr(g_browser_process->system_request_context())));
219 #if defined(FULL_SAFE_BROWSING)
220 #if !defined(OS_ANDROID)
221 if (!CommandLine::ForCurrentProcess()->HasSwitch(
222 switches::kDisableClientSidePhishingDetection)) {
223 csd_service_.reset(safe_browsing::ClientSideDetectionService::Create(
224 url_request_context_getter_.get()));
226 download_service_.reset(new safe_browsing::DownloadProtectionService(
227 this, url_request_context_getter_.get()));
228 #endif
230 if (IsIncidentReportingServiceEnabled()) {
231 incident_service_.reset(new safe_browsing::IncidentReportingService(
232 this, url_request_context_getter_));
235 off_domain_inclusion_detector_.reset(
236 new safe_browsing::OffDomainInclusionDetector);
237 #endif
239 // Track the safe browsing preference of existing profiles.
240 // The SafeBrowsingService will be started if any existing profile has the
241 // preference enabled. It will also listen for updates to the preferences.
242 ProfileManager* profile_manager = g_browser_process->profile_manager();
243 if (profile_manager) {
244 std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles();
245 for (size_t i = 0; i < profiles.size(); ++i) {
246 if (profiles[i]->IsOffTheRecord())
247 continue;
248 AddPrefService(profiles[i]->GetPrefs());
252 // Track profile creation and destruction.
253 prefs_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
254 content::NotificationService::AllSources());
255 prefs_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
256 content::NotificationService::AllSources());
258 #if defined(FULL_SAFE_BROWSING)
259 // Register all the delayed analysis to the incident reporting service.
260 RegisterAllDelayedAnalysis();
261 #endif
264 void SafeBrowsingService::ShutDown() {
265 // Deletes the PrefChangeRegistrars, whose dtors also unregister |this| as an
266 // observer of the preferences.
267 STLDeleteValues(&prefs_map_);
269 // Remove Profile creation/destruction observers.
270 prefs_registrar_.RemoveAll();
272 Stop(true);
273 // The IO thread is going away, so make sure the ClientSideDetectionService
274 // dtor executes now since it may call the dtor of URLFetcher which relies
275 // on it.
276 csd_service_.reset();
278 #if defined(FULL_SAFE_BROWSING)
279 off_domain_inclusion_detector_.reset();
280 incident_service_.reset();
281 #endif
283 download_service_.reset();
285 url_request_context_getter_ = NULL;
286 BrowserThread::PostNonNestableTask(
287 BrowserThread::IO, FROM_HERE,
288 base::Bind(&SafeBrowsingService::DestroyURLRequestContextOnIOThread,
289 this));
292 // Binhash verification is only enabled for UMA users for now.
293 bool SafeBrowsingService::DownloadBinHashNeeded() const {
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
296 #if defined(FULL_SAFE_BROWSING)
297 return (database_manager_->download_protection_enabled() &&
298 ui_manager_->CanReportStats()) ||
299 (download_protection_service() &&
300 download_protection_service()->enabled());
301 #else
302 return false;
303 #endif
306 net::URLRequestContextGetter* SafeBrowsingService::url_request_context() {
307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
308 return url_request_context_getter_.get();
311 const scoped_refptr<SafeBrowsingUIManager>&
312 SafeBrowsingService::ui_manager() const {
313 return ui_manager_;
316 const scoped_refptr<SafeBrowsingDatabaseManager>&
317 SafeBrowsingService::database_manager() const {
318 return database_manager_;
321 SafeBrowsingProtocolManager* SafeBrowsingService::protocol_manager() const {
322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
323 return protocol_manager_;
326 SafeBrowsingPingManager* SafeBrowsingService::ping_manager() const {
327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
328 return ping_manager_;
331 scoped_ptr<TrackedPreferenceValidationDelegate>
332 SafeBrowsingService::CreatePreferenceValidationDelegate(
333 Profile* profile) const {
334 #if defined(FULL_SAFE_BROWSING)
335 if (incident_service_)
336 return incident_service_->CreatePreferenceValidationDelegate(profile);
337 #endif
338 return scoped_ptr<TrackedPreferenceValidationDelegate>();
341 #if defined(FULL_SAFE_BROWSING)
342 void SafeBrowsingService::RegisterDelayedAnalysisCallback(
343 const safe_browsing::DelayedAnalysisCallback& callback) {
344 if (incident_service_)
345 incident_service_->RegisterDelayedAnalysisCallback(callback);
347 #endif
349 void SafeBrowsingService::AddDownloadManager(
350 content::DownloadManager* download_manager) {
351 #if defined(FULL_SAFE_BROWSING)
352 if (incident_service_)
353 incident_service_->AddDownloadManager(download_manager);
354 #endif
357 void SafeBrowsingService::OnResourceRequest(const net::URLRequest* request) {
358 #if defined(FULL_SAFE_BROWSING)
359 if (off_domain_inclusion_detector_)
360 off_domain_inclusion_detector_->OnResourceRequest(request);
361 #endif
364 SafeBrowsingUIManager* SafeBrowsingService::CreateUIManager() {
365 return new SafeBrowsingUIManager(this);
368 SafeBrowsingDatabaseManager* SafeBrowsingService::CreateDatabaseManager() {
369 #if defined(FULL_SAFE_BROWSING)
370 return new SafeBrowsingDatabaseManager(this);
371 #else
372 return NULL;
373 #endif
376 void SafeBrowsingService::RegisterAllDelayedAnalysis() {
377 #if defined(FULL_SAFE_BROWSING)
378 safe_browsing::RegisterBinaryIntegrityAnalysis();
379 safe_browsing::RegisterBlacklistLoadAnalysis();
380 #else
381 NOTREACHED();
382 #endif
385 void SafeBrowsingService::InitURLRequestContextOnIOThread(
386 net::URLRequestContextGetter* system_url_request_context_getter) {
387 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
388 DCHECK(!url_request_context_.get());
390 scoped_refptr<net::CookieStore> cookie_store(
391 content::CreateCookieStore(
392 content::CookieStoreConfig(
393 CookieFilePath(),
394 content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES,
395 NULL,
396 NULL)));
398 url_request_context_.reset(new net::URLRequestContext);
399 // |system_url_request_context_getter| may be NULL during tests.
400 if (system_url_request_context_getter) {
401 url_request_context_->CopyFrom(
402 system_url_request_context_getter->GetURLRequestContext());
404 url_request_context_->set_cookie_store(cookie_store.get());
407 void SafeBrowsingService::DestroyURLRequestContextOnIOThread() {
408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
410 url_request_context_->AssertNoURLRequests();
412 // Need to do the CheckForLeaks on IOThread instead of in ShutDown where
413 // url_request_context_getter_ is cleared, since the URLRequestContextGetter
414 // will PostTask to IOTread to delete itself.
415 using base::debug::LeakTracker;
416 LeakTracker<SafeBrowsingURLRequestContextGetter>::CheckForLeaks();
418 url_request_context_.reset();
421 SafeBrowsingProtocolConfig SafeBrowsingService::GetProtocolConfig() const {
422 SafeBrowsingProtocolConfig config;
423 // On Windows, get the safe browsing client name from the browser
424 // distribution classes in installer util. These classes don't yet have
425 // an analog on non-Windows builds so just keep the name specified here.
426 #if defined(OS_WIN)
427 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
428 config.client_name = dist->GetSafeBrowsingName();
429 #else
430 #if defined(GOOGLE_CHROME_BUILD)
431 config.client_name = "googlechrome";
432 #else
433 config.client_name = "chromium";
434 #endif
436 // Mark client string to allow server to differentiate mobile.
437 #if defined(OS_ANDROID)
438 config.client_name.append("-a");
439 #elif defined(OS_IOS)
440 config.client_name.append("-i");
441 #endif
443 #endif // defined(OS_WIN)
444 CommandLine* cmdline = CommandLine::ForCurrentProcess();
445 config.disable_auto_update =
446 cmdline->HasSwitch(switches::kSbDisableAutoUpdate) ||
447 cmdline->HasSwitch(switches::kDisableBackgroundNetworking);
448 config.url_prefix = kSbDefaultURLPrefix;
449 config.backup_connect_error_url_prefix = kSbBackupConnectErrorURLPrefix;
450 config.backup_http_error_url_prefix = kSbBackupHttpErrorURLPrefix;
451 config.backup_network_error_url_prefix = kSbBackupNetworkErrorURLPrefix;
453 return config;
456 void SafeBrowsingService::StartOnIOThread(
457 net::URLRequestContextGetter* url_request_context_getter) {
458 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
459 if (enabled_)
460 return;
461 enabled_ = true;
463 SafeBrowsingProtocolConfig config = GetProtocolConfig();
465 #if defined(FULL_SAFE_BROWSING)
466 DCHECK(database_manager_.get());
467 database_manager_->StartOnIOThread();
469 DCHECK(!protocol_manager_);
470 protocol_manager_ = SafeBrowsingProtocolManager::Create(
471 database_manager_.get(), url_request_context_getter, config);
472 protocol_manager_->Initialize();
473 #endif
475 DCHECK(!ping_manager_);
476 ping_manager_ = SafeBrowsingPingManager::Create(
477 url_request_context_getter, config);
480 void SafeBrowsingService::StopOnIOThread(bool shutdown) {
481 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
483 #if defined(FULL_SAFE_BROWSING)
484 database_manager_->StopOnIOThread(shutdown);
485 #endif
486 ui_manager_->StopOnIOThread(shutdown);
488 if (enabled_) {
489 enabled_ = false;
491 #if defined(FULL_SAFE_BROWSING)
492 // This cancels all in-flight GetHash requests. Note that database_manager_
493 // relies on the protocol_manager_ so if the latter is destroyed, the
494 // former must be stopped.
495 delete protocol_manager_;
496 protocol_manager_ = NULL;
497 #endif
498 delete ping_manager_;
499 ping_manager_ = NULL;
503 void SafeBrowsingService::Start() {
504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
506 BrowserThread::PostTask(
507 BrowserThread::IO, FROM_HERE,
508 base::Bind(&SafeBrowsingService::StartOnIOThread, this,
509 url_request_context_getter_));
512 void SafeBrowsingService::Stop(bool shutdown) {
513 BrowserThread::PostTask(
514 BrowserThread::IO, FROM_HERE,
515 base::Bind(&SafeBrowsingService::StopOnIOThread, this, shutdown));
518 void SafeBrowsingService::Observe(int type,
519 const content::NotificationSource& source,
520 const content::NotificationDetails& details) {
521 switch (type) {
522 case chrome::NOTIFICATION_PROFILE_CREATED: {
523 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
524 Profile* profile = content::Source<Profile>(source).ptr();
525 if (!profile->IsOffTheRecord())
526 AddPrefService(profile->GetPrefs());
527 break;
529 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
531 Profile* profile = content::Source<Profile>(source).ptr();
532 if (!profile->IsOffTheRecord())
533 RemovePrefService(profile->GetPrefs());
534 break;
536 default:
537 NOTREACHED();
541 void SafeBrowsingService::AddPrefService(PrefService* pref_service) {
542 DCHECK(prefs_map_.find(pref_service) == prefs_map_.end());
543 PrefChangeRegistrar* registrar = new PrefChangeRegistrar();
544 registrar->Init(pref_service);
545 registrar->Add(prefs::kSafeBrowsingEnabled,
546 base::Bind(&SafeBrowsingService::RefreshState,
547 base::Unretained(this)));
548 prefs_map_[pref_service] = registrar;
549 RefreshState();
552 void SafeBrowsingService::RemovePrefService(PrefService* pref_service) {
553 if (prefs_map_.find(pref_service) != prefs_map_.end()) {
554 delete prefs_map_[pref_service];
555 prefs_map_.erase(pref_service);
556 RefreshState();
557 } else {
558 NOTREACHED();
562 void SafeBrowsingService::RefreshState() {
563 // Check if any profile requires the service to be active.
564 bool enable = false;
565 std::map<PrefService*, PrefChangeRegistrar*>::iterator iter;
566 for (iter = prefs_map_.begin(); iter != prefs_map_.end(); ++iter) {
567 if (iter->first->GetBoolean(prefs::kSafeBrowsingEnabled)) {
568 enable = true;
569 break;
573 if (enable)
574 Start();
575 else
576 Stop(false);
578 #if defined(FULL_SAFE_BROWSING)
579 if (csd_service_)
580 csd_service_->SetEnabledAndRefreshState(enable);
581 if (download_service_)
582 download_service_->SetEnabled(enable);
583 #endif