Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / safe_browsing / safe_browsing_service.cc
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
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.
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
125 SafeBrowsingURLRequestContextGetter::SafeBrowsingURLRequestContextGetter(
126     SafeBrowsingService* sb_service)
127     : sb_service_(sb_service),
128       network_task_runner_(
129           BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) {
130 }
131
132 SafeBrowsingURLRequestContextGetter::~SafeBrowsingURLRequestContextGetter() {}
133
134 net::URLRequestContext*
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>
143 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:
154   virtual SafeBrowsingService* CreateSafeBrowsingService() OVERRIDE {
155     return new SafeBrowsingService();
156   }
157
158  private:
159   friend struct base::DefaultLazyInstanceTraits<SafeBrowsingServiceFactoryImpl>;
160
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
170 base::FilePath SafeBrowsingService::GetCookieFilePathForTesting() {
171   return CookieFilePath();
172 }
173
174 // static
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
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
192 bool SafeBrowsingService::IsEnabledByFieldTrial() {
193   const std::string experiment_name =
194       base::FieldTrialList::FindFullName("SafeBrowsingAndroid");
195   return experiment_name == "Enabled";
196 }
197 #endif
198
199 SafeBrowsingService::SafeBrowsingService()
200     : protocol_manager_(NULL),
201       ping_manager_(NULL),
202       enabled_(false) {
203 }
204
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
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
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.
294 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
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>&
313 SafeBrowsingService::ui_manager() const {
314   return ui_manager_;
315 }
316
317 const scoped_refptr<SafeBrowsingDatabaseManager>&
318 SafeBrowsingService::database_manager() const {
319   return database_manager_;
320 }
321
322 SafeBrowsingProtocolManager* SafeBrowsingService::protocol_manager() const {
323   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
324   return protocol_manager_;
325 }
326
327 SafeBrowsingPingManager* SafeBrowsingService::ping_manager() const {
328   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
329   return ping_manager_;
330 }
331
332 scoped_ptr<TrackedPreferenceValidationDelegate>
333 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
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
350 SafeBrowsingUIManager* SafeBrowsingService::CreateUIManager() {
351   return new SafeBrowsingUIManager(this);
352 }
353
354 SafeBrowsingDatabaseManager* SafeBrowsingService::CreateDatabaseManager() {
355 #if defined(FULL_SAFE_BROWSING)
356   return new SafeBrowsingDatabaseManager(this);
357 #else
358   return NULL;
359 #endif
360 }
361
362 void SafeBrowsingService::RegisterAllDelayedAnalysis() {
363   safe_browsing::RegisterBinaryIntegrityAnalysis();
364   safe_browsing::RegisterBlacklistLoadAnalysis();
365 }
366
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
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
403 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
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
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
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
494 void SafeBrowsingService::Stop(bool shutdown) {
495   BrowserThread::PostTask(
496       BrowserThread::IO, FROM_HERE,
497       base::Bind(&SafeBrowsingService::StopOnIOThread, this, shutdown));
498 }
499
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
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
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
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 }