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"
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"
48 #include "chrome/installer/util/browser_distribution.h"
51 using content::BrowserThread
;
55 // Filename suffix for the cookie database.
56 const base::FilePath::CharType kCookiesFile
[] = FILE_PATH_LITERAL(" Cookies");
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";
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";
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";
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";
77 base::FilePath
CookieFilePath() {
78 return base::FilePath(
79 SafeBrowsingService::GetBaseFilename().value() + kCookiesFile
);
84 class SafeBrowsingURLRequestContextGetter
85 : public net::URLRequestContextGetter
{
87 explicit SafeBrowsingURLRequestContextGetter(
88 SafeBrowsingService
* sb_service_
);
90 // Implementation for net::UrlRequestContextGetter.
91 virtual net::URLRequestContext
* GetURLRequestContext() OVERRIDE
;
92 virtual scoped_refptr
<base::SingleThreadTaskRunner
>
93 GetNetworkTaskRunner() const OVERRIDE
;
96 virtual ~SafeBrowsingURLRequestContextGetter();
99 SafeBrowsingService
* const sb_service_
; // Owned by BrowserProcess.
100 scoped_refptr
<base::SingleThreadTaskRunner
> network_task_runner_
;
102 base::debug::LeakTracker
<SafeBrowsingURLRequestContextGetter
> leak_tracker_
;
105 SafeBrowsingURLRequestContextGetter::SafeBrowsingURLRequestContextGetter(
106 SafeBrowsingService
* sb_service
)
107 : sb_service_(sb_service
),
108 network_task_runner_(
109 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
)) {
112 SafeBrowsingURLRequestContextGetter::~SafeBrowsingURLRequestContextGetter() {}
114 net::URLRequestContext
*
115 SafeBrowsingURLRequestContextGetter::GetURLRequestContext() {
116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
117 DCHECK(sb_service_
->url_request_context_
.get());
119 return sb_service_
->url_request_context_
.get();
122 scoped_refptr
<base::SingleThreadTaskRunner
>
123 SafeBrowsingURLRequestContextGetter::GetNetworkTaskRunner() const {
124 return network_task_runner_
;
128 SafeBrowsingServiceFactory
* SafeBrowsingService::factory_
= NULL
;
130 // The default SafeBrowsingServiceFactory. Global, made a singleton so we
132 class SafeBrowsingServiceFactoryImpl
: public SafeBrowsingServiceFactory
{
134 virtual SafeBrowsingService
* CreateSafeBrowsingService() OVERRIDE
{
135 return new SafeBrowsingService();
139 friend struct base::DefaultLazyInstanceTraits
<SafeBrowsingServiceFactoryImpl
>;
141 SafeBrowsingServiceFactoryImpl() { }
143 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactoryImpl
);
146 static base::LazyInstance
<SafeBrowsingServiceFactoryImpl
>::Leaky
147 g_safe_browsing_service_factory_impl
= LAZY_INSTANCE_INITIALIZER
;
150 base::FilePath
SafeBrowsingService::GetCookieFilePathForTesting() {
151 return CookieFilePath();
155 base::FilePath
SafeBrowsingService::GetBaseFilename() {
157 bool result
= PathService::Get(chrome::DIR_USER_DATA
, &path
);
159 return path
.Append(chrome::kSafeBrowsingBaseFilename
);
164 SafeBrowsingService
* SafeBrowsingService::CreateSafeBrowsingService() {
166 factory_
= g_safe_browsing_service_factory_impl
.Pointer();
167 return factory_
->CreateSafeBrowsingService();
170 SafeBrowsingService::SafeBrowsingService()
171 : protocol_manager_(NULL
),
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.
182 void SafeBrowsingService::Initialize() {
183 startup_metric_utils::ScopedSlowStartupUMA
184 scoped_timer("Startup.SlowStartupSafeBrowsingServiceInitialize");
186 url_request_context_getter_
=
187 new SafeBrowsingURLRequestContextGetter(this);
189 ui_manager_
= CreateUIManager();
191 database_manager_
= CreateDatabaseManager();
193 BrowserThread::PostTask(
194 BrowserThread::IO
, FROM_HERE
,
196 &SafeBrowsingService::InitURLRequestContextOnIOThread
, this,
197 make_scoped_refptr(g_browser_process
->system_request_context())));
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()));
205 download_service_
.reset(new safe_browsing::DownloadProtectionService(
206 this, url_request_context_getter_
.get()));
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())
218 AddPrefService(profiles
[i
]->GetPrefs());
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());
229 void SafeBrowsingService::ShutDown() {
230 // Deletes the PrefChangeRegistrars, whose dtors also unregister |this| as an
231 // observer of the preferences.
232 STLDeleteValues(&prefs_map_
);
234 // Remove Profile creation/destruction observers.
235 prefs_registrar_
.RemoveAll();
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
241 csd_service_
.reset();
242 download_service_
.reset();
244 url_request_context_getter_
= NULL
;
245 BrowserThread::PostNonNestableTask(
246 BrowserThread::IO
, FROM_HERE
,
247 base::Bind(&SafeBrowsingService::DestroyURLRequestContextOnIOThread
,
251 // Binhash verification is only enabled for UMA users for now.
252 bool SafeBrowsingService::DownloadBinHashNeeded() const {
253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
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());
265 net::URLRequestContextGetter
* SafeBrowsingService::url_request_context() {
266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
267 return url_request_context_getter_
.get();
270 const scoped_refptr
<SafeBrowsingUIManager
>&
271 SafeBrowsingService::ui_manager() const {
275 const scoped_refptr
<SafeBrowsingDatabaseManager
>&
276 SafeBrowsingService::database_manager() const {
277 return database_manager_
;
280 SafeBrowsingProtocolManager
* SafeBrowsingService::protocol_manager() const {
281 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
282 return protocol_manager_
;
285 SafeBrowsingPingManager
* SafeBrowsingService::ping_manager() const {
286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
287 return ping_manager_
;
290 SafeBrowsingUIManager
* SafeBrowsingService::CreateUIManager() {
291 return new SafeBrowsingUIManager(this);
294 SafeBrowsingDatabaseManager
* SafeBrowsingService::CreateDatabaseManager() {
296 #if defined(FULL_SAFE_BROWSING)
297 return new SafeBrowsingDatabaseManager(this);
303 void SafeBrowsingService::InitURLRequestContextOnIOThread(
304 net::URLRequestContextGetter
* system_url_request_context_getter
) {
305 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
306 DCHECK(!url_request_context_
.get());
308 scoped_refptr
<net::CookieStore
> cookie_store(
309 content::CreateCookieStore(
310 content::CookieStoreConfig(
312 content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES
,
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());
322 url_request_context_
->set_cookie_store(cookie_store
.get());
325 void SafeBrowsingService::DestroyURLRequestContextOnIOThread() {
326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
328 url_request_context_
->AssertNoURLRequests();
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();
336 url_request_context_
.reset();
339 SafeBrowsingProtocolConfig
SafeBrowsingService::GetProtocolConfig() const {
340 SafeBrowsingProtocolConfig config
;
341 // On Windows, get the safe browsing client name from the browser
342 // distribution classes in installer util. These classes don't yet have
343 // an analog on non-Windows builds so just keep the name specified here.
345 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
346 config
.client_name
= dist
->GetSafeBrowsingName();
348 #if defined(GOOGLE_CHROME_BUILD)
349 config
.client_name
= "googlechrome";
351 config
.client_name
= "chromium";
354 CommandLine
* cmdline
= CommandLine::ForCurrentProcess();
355 config
.disable_auto_update
=
356 cmdline
->HasSwitch(switches::kSbDisableAutoUpdate
) ||
357 cmdline
->HasSwitch(switches::kDisableBackgroundNetworking
);
358 if (cmdline
->HasSwitch(switches::kSbURLPrefix
)) {
359 config
.url_prefix
= cmdline
->GetSwitchValueASCII(switches::kSbURLPrefix
);
361 config
.url_prefix
= kSbDefaultURLPrefix
;
362 config
.backup_connect_error_url_prefix
= kSbBackupConnectErrorURLPrefix
;
363 config
.backup_http_error_url_prefix
= kSbBackupHttpErrorURLPrefix
;
364 config
.backup_network_error_url_prefix
= kSbBackupNetworkErrorURLPrefix
;
370 void SafeBrowsingService::StartOnIOThread(
371 net::URLRequestContextGetter
* url_request_context_getter
) {
372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
377 SafeBrowsingProtocolConfig config
= GetProtocolConfig();
379 #if defined(FULL_SAFE_BROWSING)
380 DCHECK(database_manager_
.get());
381 database_manager_
->StartOnIOThread();
383 DCHECK(!protocol_manager_
);
384 protocol_manager_
= SafeBrowsingProtocolManager::Create(
385 database_manager_
.get(), url_request_context_getter
, config
);
386 protocol_manager_
->Initialize();
389 DCHECK(!ping_manager_
);
390 ping_manager_
= SafeBrowsingPingManager::Create(
391 url_request_context_getter
, config
);
394 void SafeBrowsingService::StopOnIOThread(bool shutdown
) {
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
397 #if defined(FULL_SAFE_BROWSING)
398 database_manager_
->StopOnIOThread(shutdown
);
400 ui_manager_
->StopOnIOThread(shutdown
);
405 #if defined(FULL_SAFE_BROWSING)
406 // This cancels all in-flight GetHash requests. Note that database_manager_
407 // relies on the protocol_manager_ so if the latter is destroyed, the
408 // former must be stopped.
409 delete protocol_manager_
;
410 protocol_manager_
= NULL
;
412 delete ping_manager_
;
413 ping_manager_
= NULL
;
417 void SafeBrowsingService::Start() {
418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
420 BrowserThread::PostTask(
421 BrowserThread::IO
, FROM_HERE
,
422 base::Bind(&SafeBrowsingService::StartOnIOThread
, this,
423 url_request_context_getter_
));
426 void SafeBrowsingService::Stop(bool shutdown
) {
427 BrowserThread::PostTask(
428 BrowserThread::IO
, FROM_HERE
,
429 base::Bind(&SafeBrowsingService::StopOnIOThread
, this, shutdown
));
432 void SafeBrowsingService::Observe(int type
,
433 const content::NotificationSource
& source
,
434 const content::NotificationDetails
& details
) {
436 case chrome::NOTIFICATION_PROFILE_CREATED
: {
437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
438 Profile
* profile
= content::Source
<Profile
>(source
).ptr();
439 if (!profile
->IsOffTheRecord())
440 AddPrefService(profile
->GetPrefs());
443 case chrome::NOTIFICATION_PROFILE_DESTROYED
: {
444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
445 Profile
* profile
= content::Source
<Profile
>(source
).ptr();
446 if (!profile
->IsOffTheRecord())
447 RemovePrefService(profile
->GetPrefs());
455 void SafeBrowsingService::AddPrefService(PrefService
* pref_service
) {
456 DCHECK(prefs_map_
.find(pref_service
) == prefs_map_
.end());
457 PrefChangeRegistrar
* registrar
= new PrefChangeRegistrar();
458 registrar
->Init(pref_service
);
459 registrar
->Add(prefs::kSafeBrowsingEnabled
,
460 base::Bind(&SafeBrowsingService::RefreshState
,
461 base::Unretained(this)));
462 prefs_map_
[pref_service
] = registrar
;
466 void SafeBrowsingService::RemovePrefService(PrefService
* pref_service
) {
467 if (prefs_map_
.find(pref_service
) != prefs_map_
.end()) {
468 delete prefs_map_
[pref_service
];
469 prefs_map_
.erase(pref_service
);
476 void SafeBrowsingService::RefreshState() {
477 // Check if any profile requires the service to be active.
479 std::map
<PrefService
*, PrefChangeRegistrar
*>::iterator iter
;
480 for (iter
= prefs_map_
.begin(); iter
!= prefs_map_
.end(); ++iter
) {
481 if (iter
->first
->GetBoolean(prefs::kSafeBrowsingEnabled
)) {
492 #if defined(FULL_SAFE_BROWSING)
493 if (csd_service_
.get())
494 csd_service_
->SetEnabledAndRefreshState(enable
);
495 if (download_service_
.get()) {
496 download_service_
->SetEnabled(
497 enable
&& !CommandLine::ForCurrentProcess()->HasSwitch(
498 switches::kDisableImprovedDownloadProtection
));