• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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