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