Upstream version 7.36.149.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 "base/bind.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"
46
47 #if defined(OS_WIN)
48 #include "chrome/installer/util/browser_distribution.h"
49 #endif
50
51 using content::BrowserThread;
52
53 namespace {
54
55 // Filename suffix for the cookie database.
56 const base::FilePath::CharType kCookiesFile[] = FILE_PATH_LITERAL(" Cookies");
57
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";
62
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";
67
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";
72
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";
76
77 base::FilePath CookieFilePath() {
78   return base::FilePath(
79       SafeBrowsingService::GetBaseFilename().value() + kCookiesFile);
80 }
81
82 }  // namespace
83
84 class SafeBrowsingURLRequestContextGetter
85     : public net::URLRequestContextGetter {
86  public:
87   explicit SafeBrowsingURLRequestContextGetter(
88       SafeBrowsingService* sb_service_);
89
90   // Implementation for net::UrlRequestContextGetter.
91   virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE;
92   virtual scoped_refptr<base::SingleThreadTaskRunner>
93       GetNetworkTaskRunner() const OVERRIDE;
94
95  protected:
96   virtual ~SafeBrowsingURLRequestContextGetter();
97
98  private:
99   SafeBrowsingService* const sb_service_;  // Owned by BrowserProcess.
100   scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
101
102   base::debug::LeakTracker<SafeBrowsingURLRequestContextGetter> leak_tracker_;
103 };
104
105 SafeBrowsingURLRequestContextGetter::SafeBrowsingURLRequestContextGetter(
106     SafeBrowsingService* sb_service)
107     : sb_service_(sb_service),
108       network_task_runner_(
109           BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) {
110 }
111
112 SafeBrowsingURLRequestContextGetter::~SafeBrowsingURLRequestContextGetter() {}
113
114 net::URLRequestContext*
115 SafeBrowsingURLRequestContextGetter::GetURLRequestContext() {
116   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
117   DCHECK(sb_service_->url_request_context_.get());
118
119   return sb_service_->url_request_context_.get();
120 }
121
122 scoped_refptr<base::SingleThreadTaskRunner>
123 SafeBrowsingURLRequestContextGetter::GetNetworkTaskRunner() const {
124   return network_task_runner_;
125 }
126
127 // static
128 SafeBrowsingServiceFactory* SafeBrowsingService::factory_ = NULL;
129
130 // The default SafeBrowsingServiceFactory.  Global, made a singleton so we
131 // don't leak it.
132 class SafeBrowsingServiceFactoryImpl : public SafeBrowsingServiceFactory {
133  public:
134   virtual SafeBrowsingService* CreateSafeBrowsingService() OVERRIDE {
135     return new SafeBrowsingService();
136   }
137
138  private:
139   friend struct base::DefaultLazyInstanceTraits<SafeBrowsingServiceFactoryImpl>;
140
141   SafeBrowsingServiceFactoryImpl() { }
142
143   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactoryImpl);
144 };
145
146 static base::LazyInstance<SafeBrowsingServiceFactoryImpl>::Leaky
147     g_safe_browsing_service_factory_impl = LAZY_INSTANCE_INITIALIZER;
148
149 // static
150 base::FilePath SafeBrowsingService::GetCookieFilePathForTesting() {
151   return CookieFilePath();
152 }
153
154 // static
155 base::FilePath SafeBrowsingService::GetBaseFilename() {
156   base::FilePath path;
157   bool result = PathService::Get(chrome::DIR_USER_DATA, &path);
158   DCHECK(result);
159   return path.Append(chrome::kSafeBrowsingBaseFilename);
160 }
161
162
163 // static
164 SafeBrowsingService* SafeBrowsingService::CreateSafeBrowsingService() {
165   if (!factory_)
166     factory_ = g_safe_browsing_service_factory_impl.Pointer();
167   return factory_->CreateSafeBrowsingService();
168 }
169
170 SafeBrowsingService::SafeBrowsingService()
171     : protocol_manager_(NULL),
172       ping_manager_(NULL),
173       enabled_(false) {
174 }
175
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.
179   DCHECK(!enabled_);
180 }
181
182 void SafeBrowsingService::Initialize() {
183   startup_metric_utils::ScopedSlowStartupUMA
184       scoped_timer("Startup.SlowStartupSafeBrowsingServiceInitialize");
185
186   url_request_context_getter_ =
187       new SafeBrowsingURLRequestContextGetter(this);
188
189   ui_manager_ = CreateUIManager();
190
191   database_manager_ = CreateDatabaseManager();
192
193   BrowserThread::PostTask(
194       BrowserThread::IO, FROM_HERE,
195       base::Bind(
196           &SafeBrowsingService::InitURLRequestContextOnIOThread, this,
197           make_scoped_refptr(g_browser_process->system_request_context())));
198
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()));
204   }
205   download_service_.reset(new safe_browsing::DownloadProtectionService(
206       this, url_request_context_getter_.get()));
207 #endif
208
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())
217         continue;
218       AddPrefService(profiles[i]->GetPrefs());
219     }
220   }
221
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());
227 }
228
229 void SafeBrowsingService::ShutDown() {
230   // Deletes the PrefChangeRegistrars, whose dtors also unregister |this| as an
231   // observer of the preferences.
232   STLDeleteValues(&prefs_map_);
233
234   // Remove Profile creation/destruction observers.
235   prefs_registrar_.RemoveAll();
236
237   Stop(true);
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
240   // on it.
241   csd_service_.reset();
242   download_service_.reset();
243
244   url_request_context_getter_ = NULL;
245   BrowserThread::PostNonNestableTask(
246       BrowserThread::IO, FROM_HERE,
247       base::Bind(&SafeBrowsingService::DestroyURLRequestContextOnIOThread,
248                  this));
249 }
250
251 // Binhash verification is only enabled for UMA users for now.
252 bool SafeBrowsingService::DownloadBinHashNeeded() const {
253   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
254
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());
260 #else
261   return false;
262 #endif
263 }
264
265 net::URLRequestContextGetter* SafeBrowsingService::url_request_context() {
266   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
267   return url_request_context_getter_.get();
268 }
269
270 const scoped_refptr<SafeBrowsingUIManager>&
271 SafeBrowsingService::ui_manager() const {
272   return ui_manager_;
273 }
274
275 const scoped_refptr<SafeBrowsingDatabaseManager>&
276 SafeBrowsingService::database_manager() const {
277   return database_manager_;
278 }
279
280 SafeBrowsingProtocolManager* SafeBrowsingService::protocol_manager() const {
281   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
282   return protocol_manager_;
283 }
284
285 SafeBrowsingPingManager* SafeBrowsingService::ping_manager() const {
286   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
287   return ping_manager_;
288 }
289
290 SafeBrowsingUIManager* SafeBrowsingService::CreateUIManager() {
291   return new SafeBrowsingUIManager(this);
292 }
293
294 SafeBrowsingDatabaseManager* SafeBrowsingService::CreateDatabaseManager() {
295
296 #if defined(FULL_SAFE_BROWSING)
297   return new SafeBrowsingDatabaseManager(this);
298 #else
299   return NULL;
300 #endif
301 }
302
303 void SafeBrowsingService::InitURLRequestContextOnIOThread(
304     net::URLRequestContextGetter* system_url_request_context_getter) {
305   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
306   DCHECK(!url_request_context_.get());
307
308   scoped_refptr<net::CookieStore> cookie_store(
309       content::CreateCookieStore(
310           content::CookieStoreConfig(
311               CookieFilePath(),
312               content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES,
313               NULL,
314               NULL)));
315
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());
321   }
322   url_request_context_->set_cookie_store(cookie_store.get());
323 }
324
325 void SafeBrowsingService::DestroyURLRequestContextOnIOThread() {
326   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
327
328   url_request_context_->AssertNoURLRequests();
329
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();
335
336   url_request_context_.reset();
337 }
338
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.
344 #if defined(OS_WIN)
345   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
346   config.client_name = dist->GetSafeBrowsingName();
347 #else
348 #if defined(GOOGLE_CHROME_BUILD)
349   config.client_name = "googlechrome";
350 #else
351   config.client_name = "chromium";
352 #endif
353 #endif
354   CommandLine* cmdline = CommandLine::ForCurrentProcess();
355   config.disable_auto_update =
356       cmdline->HasSwitch(switches::kSbDisableAutoUpdate) ||
357       cmdline->HasSwitch(switches::kDisableBackgroundNetworking);
358   config.url_prefix = kSbDefaultURLPrefix;
359   config.backup_connect_error_url_prefix = kSbBackupConnectErrorURLPrefix;
360   config.backup_http_error_url_prefix = kSbBackupHttpErrorURLPrefix;
361   config.backup_network_error_url_prefix = kSbBackupNetworkErrorURLPrefix;
362
363   return config;
364 }
365
366 void SafeBrowsingService::StartOnIOThread(
367     net::URLRequestContextGetter* url_request_context_getter) {
368   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
369   if (enabled_)
370     return;
371   enabled_ = true;
372
373   SafeBrowsingProtocolConfig config = GetProtocolConfig();
374
375 #if defined(FULL_SAFE_BROWSING)
376   DCHECK(database_manager_.get());
377   database_manager_->StartOnIOThread();
378
379   DCHECK(!protocol_manager_);
380   protocol_manager_ = SafeBrowsingProtocolManager::Create(
381       database_manager_.get(), url_request_context_getter, config);
382   protocol_manager_->Initialize();
383 #endif
384
385   DCHECK(!ping_manager_);
386   ping_manager_ = SafeBrowsingPingManager::Create(
387       url_request_context_getter, config);
388 }
389
390 void SafeBrowsingService::StopOnIOThread(bool shutdown) {
391   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
392
393 #if defined(FULL_SAFE_BROWSING)
394   database_manager_->StopOnIOThread(shutdown);
395 #endif
396   ui_manager_->StopOnIOThread(shutdown);
397
398   if (enabled_) {
399     enabled_ = false;
400
401 #if defined(FULL_SAFE_BROWSING)
402     // This cancels all in-flight GetHash requests. Note that database_manager_
403     // relies on the protocol_manager_ so if the latter is destroyed, the
404     // former must be stopped.
405     delete protocol_manager_;
406     protocol_manager_ = NULL;
407 #endif
408     delete ping_manager_;
409     ping_manager_ = NULL;
410   }
411 }
412
413 void SafeBrowsingService::Start() {
414   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
415
416   BrowserThread::PostTask(
417       BrowserThread::IO, FROM_HERE,
418       base::Bind(&SafeBrowsingService::StartOnIOThread, this,
419                  url_request_context_getter_));
420 }
421
422 void SafeBrowsingService::Stop(bool shutdown) {
423   BrowserThread::PostTask(
424       BrowserThread::IO, FROM_HERE,
425       base::Bind(&SafeBrowsingService::StopOnIOThread, this, shutdown));
426 }
427
428 void SafeBrowsingService::Observe(int type,
429                                   const content::NotificationSource& source,
430                                   const content::NotificationDetails& details) {
431   switch (type) {
432     case chrome::NOTIFICATION_PROFILE_CREATED: {
433       DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
434       Profile* profile = content::Source<Profile>(source).ptr();
435       if (!profile->IsOffTheRecord())
436         AddPrefService(profile->GetPrefs());
437       break;
438     }
439     case chrome::NOTIFICATION_PROFILE_DESTROYED: {
440       DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
441       Profile* profile = content::Source<Profile>(source).ptr();
442       if (!profile->IsOffTheRecord())
443         RemovePrefService(profile->GetPrefs());
444       break;
445     }
446     default:
447       NOTREACHED();
448   }
449 }
450
451 void SafeBrowsingService::AddPrefService(PrefService* pref_service) {
452   DCHECK(prefs_map_.find(pref_service) == prefs_map_.end());
453   PrefChangeRegistrar* registrar = new PrefChangeRegistrar();
454   registrar->Init(pref_service);
455   registrar->Add(prefs::kSafeBrowsingEnabled,
456                  base::Bind(&SafeBrowsingService::RefreshState,
457                             base::Unretained(this)));
458   prefs_map_[pref_service] = registrar;
459   RefreshState();
460 }
461
462 void SafeBrowsingService::RemovePrefService(PrefService* pref_service) {
463   if (prefs_map_.find(pref_service) != prefs_map_.end()) {
464     delete prefs_map_[pref_service];
465     prefs_map_.erase(pref_service);
466     RefreshState();
467   } else {
468     NOTREACHED();
469   }
470 }
471
472 void SafeBrowsingService::RefreshState() {
473   // Check if any profile requires the service to be active.
474   bool enable = false;
475   std::map<PrefService*, PrefChangeRegistrar*>::iterator iter;
476   for (iter = prefs_map_.begin(); iter != prefs_map_.end(); ++iter) {
477     if (iter->first->GetBoolean(prefs::kSafeBrowsingEnabled)) {
478       enable = true;
479       break;
480     }
481   }
482
483   if (enable)
484     Start();
485   else
486     Stop(false);
487
488 #if defined(FULL_SAFE_BROWSING)
489   if (csd_service_.get())
490     csd_service_->SetEnabledAndRefreshState(enable);
491   if (download_service_.get()) {
492     download_service_->SetEnabled(enable);
493   }
494 #endif
495 }