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"
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/profiler/scoped_tracker.h"
19 #include "base/stl_util.h"
20 #include "base/strings/string_util.h"
21 #include "base/threading/thread.h"
22 #include "base/threading/thread_restrictions.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/chrome_notification_types.h"
25 #include "chrome/browser/prefs/tracked/tracked_preference_validation_delegate.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/profiles/profile_manager.h"
28 #include "chrome/browser/safe_browsing/client_side_detection_service.h"
29 #include "chrome/browser/safe_browsing/database_manager.h"
30 #include "chrome/browser/safe_browsing/download_protection_service.h"
31 #include "chrome/browser/safe_browsing/malware_details.h"
32 #include "chrome/browser/safe_browsing/ping_manager.h"
33 #include "chrome/browser/safe_browsing/protocol_manager.h"
34 #include "chrome/browser/safe_browsing/safe_browsing_database.h"
35 #include "chrome/browser/safe_browsing/ui_manager.h"
36 #include "chrome/common/chrome_constants.h"
37 #include "chrome/common/chrome_paths.h"
38 #include "chrome/common/chrome_switches.h"
39 #include "chrome/common/pref_names.h"
40 #include "chrome/common/url_constants.h"
41 #include "components/startup_metric_utils/startup_metric_utils.h"
42 #include "components/variations/variations_associated_data.h"
43 #include "content/public/browser/browser_thread.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/extras/sqlite/cookie_crypto_delegate.h"
48 #include "net/url_request/url_request_context.h"
49 #include "net/url_request/url_request_context_getter.h"
52 #include "chrome/installer/util/browser_distribution.h"
55 #if defined(FULL_SAFE_BROWSING)
56 #include "chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer.h"
57 #include "chrome/browser/safe_browsing/incident_reporting/blacklist_load_analyzer.h"
58 #include "chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h"
59 #include "chrome/browser/safe_browsing/incident_reporting/off_domain_inclusion_detector.h"
60 #include "chrome/browser/safe_browsing/incident_reporting/script_request_detector.h"
61 #include "chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_analyzer.h"
64 using content::BrowserThread
;
68 // Filename suffix for the cookie database.
69 const base::FilePath::CharType kCookiesFile
[] = FILE_PATH_LITERAL(" Cookies");
71 // The default URL prefix where browser fetches chunk updates, hashes,
72 // and reports safe browsing hits and malware details.
73 const char* const kSbDefaultURLPrefix
=
74 "https://safebrowsing.google.com/safebrowsing";
76 // The backup URL prefix used when there are issues establishing a connection
77 // with the server at the primary URL.
78 const char* const kSbBackupConnectErrorURLPrefix
=
79 "https://alt1-safebrowsing.google.com/safebrowsing";
81 // The backup URL prefix used when there are HTTP-specific issues with the
82 // server at the primary URL.
83 const char* const kSbBackupHttpErrorURLPrefix
=
84 "https://alt2-safebrowsing.google.com/safebrowsing";
86 // The backup URL prefix used when there are local network specific issues.
87 const char* const kSbBackupNetworkErrorURLPrefix
=
88 "https://alt3-safebrowsing.google.com/safebrowsing";
90 base::FilePath
CookieFilePath() {
91 return base::FilePath(
92 SafeBrowsingService::GetBaseFilename().value() + kCookiesFile
);
95 #if defined(FULL_SAFE_BROWSING)
96 // Returns true if the incident reporting service is enabled via a field trial.
97 bool IsIncidentReportingServiceEnabled() {
98 const std::string group_name
= base::FieldTrialList::FindFullName(
99 "SafeBrowsingIncidentReportingService");
100 return group_name
== "Enabled";
102 #endif // defined(FULL_SAFE_BROWSING)
106 class SafeBrowsingURLRequestContextGetter
107 : public net::URLRequestContextGetter
{
109 explicit SafeBrowsingURLRequestContextGetter(
110 SafeBrowsingService
* sb_service_
);
112 // Implementation for net::UrlRequestContextGetter.
113 net::URLRequestContext
* GetURLRequestContext() override
;
114 scoped_refptr
<base::SingleThreadTaskRunner
> GetNetworkTaskRunner()
118 ~SafeBrowsingURLRequestContextGetter() override
;
121 SafeBrowsingService
* const sb_service_
; // Owned by BrowserProcess.
122 scoped_refptr
<base::SingleThreadTaskRunner
> network_task_runner_
;
124 base::debug::LeakTracker
<SafeBrowsingURLRequestContextGetter
> leak_tracker_
;
127 SafeBrowsingURLRequestContextGetter::SafeBrowsingURLRequestContextGetter(
128 SafeBrowsingService
* sb_service
)
129 : sb_service_(sb_service
),
130 network_task_runner_(
131 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
)) {
134 SafeBrowsingURLRequestContextGetter::~SafeBrowsingURLRequestContextGetter() {}
136 net::URLRequestContext
*
137 SafeBrowsingURLRequestContextGetter::GetURLRequestContext() {
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
139 DCHECK(sb_service_
->url_request_context_
.get());
141 return sb_service_
->url_request_context_
.get();
144 scoped_refptr
<base::SingleThreadTaskRunner
>
145 SafeBrowsingURLRequestContextGetter::GetNetworkTaskRunner() const {
146 return network_task_runner_
;
150 SafeBrowsingServiceFactory
* SafeBrowsingService::factory_
= NULL
;
152 // The default SafeBrowsingServiceFactory. Global, made a singleton so we
154 class SafeBrowsingServiceFactoryImpl
: public SafeBrowsingServiceFactory
{
156 SafeBrowsingService
* CreateSafeBrowsingService() override
{
157 return new SafeBrowsingService();
161 friend struct base::DefaultLazyInstanceTraits
<SafeBrowsingServiceFactoryImpl
>;
163 SafeBrowsingServiceFactoryImpl() { }
165 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactoryImpl
);
168 static base::LazyInstance
<SafeBrowsingServiceFactoryImpl
>::Leaky
169 g_safe_browsing_service_factory_impl
= LAZY_INSTANCE_INITIALIZER
;
172 base::FilePath
SafeBrowsingService::GetCookieFilePathForTesting() {
173 return CookieFilePath();
177 base::FilePath
SafeBrowsingService::GetBaseFilename() {
179 bool result
= PathService::Get(chrome::DIR_USER_DATA
, &path
);
181 return path
.Append(chrome::kSafeBrowsingBaseFilename
);
186 SafeBrowsingService
* SafeBrowsingService::CreateSafeBrowsingService() {
188 factory_
= g_safe_browsing_service_factory_impl
.Pointer();
189 return factory_
->CreateSafeBrowsingService();
193 SafeBrowsingService::SafeBrowsingService()
194 : protocol_manager_(NULL
),
199 SafeBrowsingService::~SafeBrowsingService() {
200 // We should have already been shut down. If we're still enabled, then the
201 // database isn't going to be closed properly, which could lead to corruption.
205 void SafeBrowsingService::Initialize() {
206 startup_metric_utils::ScopedSlowStartupUMA
207 scoped_timer("Startup.SlowStartupSafeBrowsingServiceInitialize");
209 url_request_context_getter_
=
210 new SafeBrowsingURLRequestContextGetter(this);
212 ui_manager_
= CreateUIManager();
214 database_manager_
= CreateDatabaseManager();
216 BrowserThread::PostTask(
217 BrowserThread::IO
, FROM_HERE
,
219 &SafeBrowsingService::InitURLRequestContextOnIOThread
, this,
220 make_scoped_refptr(g_browser_process
->system_request_context())));
222 #if defined(FULL_SAFE_BROWSING)
223 #if !defined(OS_ANDROID)
224 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
225 switches::kDisableClientSidePhishingDetection
)) {
226 csd_service_
.reset(safe_browsing::ClientSideDetectionService::Create(
227 url_request_context_getter_
.get()));
229 download_service_
.reset(new safe_browsing::DownloadProtectionService(
230 this, url_request_context_getter_
.get()));
233 if (IsIncidentReportingServiceEnabled()) {
234 incident_service_
.reset(new safe_browsing::IncidentReportingService(
235 this, url_request_context_getter_
));
236 script_request_detector_
.reset(new safe_browsing::ScriptRequestDetector(
237 incident_service_
->GetIncidentReceiver()));
240 off_domain_inclusion_detector_
.reset(
241 new safe_browsing::OffDomainInclusionDetector(database_manager_
));
244 // Track the safe browsing preference of existing profiles.
245 // The SafeBrowsingService will be started if any existing profile has the
246 // preference enabled. It will also listen for updates to the preferences.
247 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
248 if (profile_manager
) {
249 std::vector
<Profile
*> profiles
= profile_manager
->GetLoadedProfiles();
250 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
251 if (profiles
[i
]->IsOffTheRecord())
253 AddPrefService(profiles
[i
]->GetPrefs());
257 // Track profile creation and destruction.
258 prefs_registrar_
.Add(this, chrome::NOTIFICATION_PROFILE_CREATED
,
259 content::NotificationService::AllSources());
260 prefs_registrar_
.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED
,
261 content::NotificationService::AllSources());
263 #if defined(FULL_SAFE_BROWSING)
264 // Register all the delayed analysis to the incident reporting service.
265 RegisterAllDelayedAnalysis();
269 void SafeBrowsingService::ShutDown() {
270 // Deletes the PrefChangeRegistrars, whose dtors also unregister |this| as an
271 // observer of the preferences.
272 STLDeleteValues(&prefs_map_
);
274 // Remove Profile creation/destruction observers.
275 prefs_registrar_
.RemoveAll();
278 // The IO thread is going away, so make sure the ClientSideDetectionService
279 // dtor executes now since it may call the dtor of URLFetcher which relies
281 csd_service_
.reset();
283 #if defined(FULL_SAFE_BROWSING)
284 off_domain_inclusion_detector_
.reset();
285 script_request_detector_
.reset();
286 incident_service_
.reset();
289 download_service_
.reset();
291 url_request_context_getter_
= NULL
;
292 BrowserThread::PostNonNestableTask(
293 BrowserThread::IO
, FROM_HERE
,
294 base::Bind(&SafeBrowsingService::DestroyURLRequestContextOnIOThread
,
298 // Binhash verification is only enabled for UMA users for now.
299 bool SafeBrowsingService::DownloadBinHashNeeded() const {
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
302 #if defined(FULL_SAFE_BROWSING)
303 return (database_manager_
->download_protection_enabled() &&
304 ui_manager_
->CanReportStats()) ||
305 (download_protection_service() &&
306 download_protection_service()->enabled());
312 net::URLRequestContextGetter
* SafeBrowsingService::url_request_context() {
313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
314 return url_request_context_getter_
.get();
317 const scoped_refptr
<SafeBrowsingUIManager
>&
318 SafeBrowsingService::ui_manager() const {
322 const scoped_refptr
<SafeBrowsingDatabaseManager
>&
323 SafeBrowsingService::database_manager() const {
324 return database_manager_
;
327 SafeBrowsingProtocolManager
* SafeBrowsingService::protocol_manager() const {
328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
329 return protocol_manager_
;
332 SafeBrowsingPingManager
* SafeBrowsingService::ping_manager() const {
333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
334 return ping_manager_
;
337 scoped_ptr
<TrackedPreferenceValidationDelegate
>
338 SafeBrowsingService::CreatePreferenceValidationDelegate(
339 Profile
* profile
) const {
340 #if defined(FULL_SAFE_BROWSING)
341 if (incident_service_
)
342 return incident_service_
->CreatePreferenceValidationDelegate(profile
);
344 return scoped_ptr
<TrackedPreferenceValidationDelegate
>();
347 #if defined(FULL_SAFE_BROWSING)
348 void SafeBrowsingService::RegisterDelayedAnalysisCallback(
349 const safe_browsing::DelayedAnalysisCallback
& callback
) {
350 if (incident_service_
)
351 incident_service_
->RegisterDelayedAnalysisCallback(callback
);
355 void SafeBrowsingService::AddDownloadManager(
356 content::DownloadManager
* download_manager
) {
357 #if defined(FULL_SAFE_BROWSING)
358 if (incident_service_
)
359 incident_service_
->AddDownloadManager(download_manager
);
363 void SafeBrowsingService::OnResourceRequest(const net::URLRequest
* request
) {
364 #if defined(FULL_SAFE_BROWSING)
365 if (off_domain_inclusion_detector_
)
366 off_domain_inclusion_detector_
->OnResourceRequest(request
);
367 if (script_request_detector_
)
368 script_request_detector_
->OnResourceRequest(request
);
372 SafeBrowsingUIManager
* SafeBrowsingService::CreateUIManager() {
373 return new SafeBrowsingUIManager(this);
376 SafeBrowsingDatabaseManager
* SafeBrowsingService::CreateDatabaseManager() {
377 #if defined(FULL_SAFE_BROWSING)
378 return new SafeBrowsingDatabaseManager(this);
384 void SafeBrowsingService::RegisterAllDelayedAnalysis() {
385 #if defined(FULL_SAFE_BROWSING)
386 safe_browsing::RegisterBinaryIntegrityAnalysis();
387 safe_browsing::RegisterBlacklistLoadAnalysis();
388 safe_browsing::RegisterVariationsSeedSignatureAnalysis();
394 void SafeBrowsingService::InitURLRequestContextOnIOThread(
395 net::URLRequestContextGetter
* system_url_request_context_getter
) {
396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
397 DCHECK(!url_request_context_
.get());
399 scoped_refptr
<net::CookieStore
> cookie_store(
400 content::CreateCookieStore(
401 content::CookieStoreConfig(
403 content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES
,
407 url_request_context_
.reset(new net::URLRequestContext
);
408 // |system_url_request_context_getter| may be NULL during tests.
409 if (system_url_request_context_getter
) {
410 url_request_context_
->CopyFrom(
411 system_url_request_context_getter
->GetURLRequestContext());
413 url_request_context_
->set_cookie_store(cookie_store
.get());
416 void SafeBrowsingService::DestroyURLRequestContextOnIOThread() {
417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
419 url_request_context_
->AssertNoURLRequests();
421 // Need to do the CheckForLeaks on IOThread instead of in ShutDown where
422 // url_request_context_getter_ is cleared, since the URLRequestContextGetter
423 // will PostTask to IOTread to delete itself.
424 using base::debug::LeakTracker
;
425 LeakTracker
<SafeBrowsingURLRequestContextGetter
>::CheckForLeaks();
427 url_request_context_
.reset();
430 SafeBrowsingProtocolConfig
SafeBrowsingService::GetProtocolConfig() const {
431 SafeBrowsingProtocolConfig config
;
432 // On Windows, get the safe browsing client name from the browser
433 // distribution classes in installer util. These classes don't yet have
434 // an analog on non-Windows builds so just keep the name specified here.
436 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
437 config
.client_name
= dist
->GetSafeBrowsingName();
439 #if defined(GOOGLE_CHROME_BUILD)
440 config
.client_name
= "googlechrome";
442 config
.client_name
= "chromium";
445 // Mark client string to allow server to differentiate mobile.
446 #if defined(OS_ANDROID)
447 config
.client_name
.append("-a");
448 #elif defined(OS_IOS)
449 config
.client_name
.append("-i");
452 #endif // defined(OS_WIN)
453 base::CommandLine
* cmdline
= base::CommandLine::ForCurrentProcess();
454 config
.disable_auto_update
=
455 cmdline
->HasSwitch(switches::kSbDisableAutoUpdate
) ||
456 cmdline
->HasSwitch(switches::kDisableBackgroundNetworking
);
457 config
.url_prefix
= kSbDefaultURLPrefix
;
458 config
.backup_connect_error_url_prefix
= kSbBackupConnectErrorURLPrefix
;
459 config
.backup_http_error_url_prefix
= kSbBackupHttpErrorURLPrefix
;
460 config
.backup_network_error_url_prefix
= kSbBackupNetworkErrorURLPrefix
;
465 void SafeBrowsingService::StartOnIOThread(
466 net::URLRequestContextGetter
* url_request_context_getter
) {
467 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
472 SafeBrowsingProtocolConfig config
= GetProtocolConfig();
474 #if defined(FULL_SAFE_BROWSING)
475 DCHECK(database_manager_
.get());
476 database_manager_
->StartOnIOThread();
478 DCHECK(!protocol_manager_
);
479 protocol_manager_
= SafeBrowsingProtocolManager::Create(
480 database_manager_
.get(), url_request_context_getter
, config
);
481 protocol_manager_
->Initialize();
484 DCHECK(!ping_manager_
);
485 ping_manager_
= SafeBrowsingPingManager::Create(
486 url_request_context_getter
, config
);
489 void SafeBrowsingService::StopOnIOThread(bool shutdown
) {
490 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
492 #if defined(FULL_SAFE_BROWSING)
493 database_manager_
->StopOnIOThread(shutdown
);
495 ui_manager_
->StopOnIOThread(shutdown
);
500 #if defined(FULL_SAFE_BROWSING)
501 // This cancels all in-flight GetHash requests. Note that database_manager_
502 // relies on the protocol_manager_ so if the latter is destroyed, the
503 // former must be stopped.
504 delete protocol_manager_
;
505 protocol_manager_
= NULL
;
507 delete ping_manager_
;
508 ping_manager_
= NULL
;
512 void SafeBrowsingService::Start() {
513 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
515 BrowserThread::PostTask(
516 BrowserThread::IO
, FROM_HERE
,
517 base::Bind(&SafeBrowsingService::StartOnIOThread
, this,
518 url_request_context_getter_
));
521 void SafeBrowsingService::Stop(bool shutdown
) {
522 BrowserThread::PostTask(
523 BrowserThread::IO
, FROM_HERE
,
524 base::Bind(&SafeBrowsingService::StopOnIOThread
, this, shutdown
));
527 void SafeBrowsingService::Observe(int type
,
528 const content::NotificationSource
& source
,
529 const content::NotificationDetails
& details
) {
531 case chrome::NOTIFICATION_PROFILE_CREATED
: {
532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
533 Profile
* profile
= content::Source
<Profile
>(source
).ptr();
534 if (!profile
->IsOffTheRecord())
535 AddPrefService(profile
->GetPrefs());
538 case chrome::NOTIFICATION_PROFILE_DESTROYED
: {
539 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
540 Profile
* profile
= content::Source
<Profile
>(source
).ptr();
541 if (!profile
->IsOffTheRecord())
542 RemovePrefService(profile
->GetPrefs());
550 void SafeBrowsingService::AddPrefService(PrefService
* pref_service
) {
551 DCHECK(prefs_map_
.find(pref_service
) == prefs_map_
.end());
552 PrefChangeRegistrar
* registrar
= new PrefChangeRegistrar();
553 registrar
->Init(pref_service
);
554 registrar
->Add(prefs::kSafeBrowsingEnabled
,
555 base::Bind(&SafeBrowsingService::RefreshState
,
556 base::Unretained(this)));
557 prefs_map_
[pref_service
] = registrar
;
561 void SafeBrowsingService::RemovePrefService(PrefService
* pref_service
) {
562 if (prefs_map_
.find(pref_service
) != prefs_map_
.end()) {
563 delete prefs_map_
[pref_service
];
564 prefs_map_
.erase(pref_service
);
571 void SafeBrowsingService::RefreshState() {
572 // Check if any profile requires the service to be active.
574 std::map
<PrefService
*, PrefChangeRegistrar
*>::iterator iter
;
575 for (iter
= prefs_map_
.begin(); iter
!= prefs_map_
.end(); ++iter
) {
576 if (iter
->first
->GetBoolean(prefs::kSafeBrowsingEnabled
)) {
582 // TODO(asvitkine): Experimental code for measuring start up impact of SB.
583 // Remove when experimentation is complete. http://crbug.com/450037
584 if (!variations::GetVariationParamValue("LightSpeed", "DisableSB").empty())
592 #if defined(FULL_SAFE_BROWSING)
594 csd_service_
->SetEnabledAndRefreshState(enable
);
595 if (download_service_
)
596 download_service_
->SetEnabled(enable
);