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