Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / safe_browsing / safe_browsing_service.cc
blob1efca62ef6b6d660e68c247e4ece7aea40f1a20b
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.
5 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
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"
47 #if defined(OS_WIN)
48 #include "chrome/installer/util/browser_distribution.h"
49 #endif
51 using content::BrowserThread;
53 namespace {
55 // Filename suffix for the cookie database.
56 const base::FilePath::CharType kCookiesFile[] = FILE_PATH_LITERAL(" Cookies");
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";
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";
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";
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";
77 base::FilePath CookieFilePath() {
78 return base::FilePath(
79 SafeBrowsingService::GetBaseFilename().value() + kCookiesFile);
82 } // namespace
84 class SafeBrowsingURLRequestContextGetter
85 : public net::URLRequestContextGetter {
86 public:
87 explicit SafeBrowsingURLRequestContextGetter(
88 SafeBrowsingService* sb_service_);
90 // Implementation for net::UrlRequestContextGetter.
91 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE;
92 virtual scoped_refptr<base::SingleThreadTaskRunner>
93 GetNetworkTaskRunner() const OVERRIDE;
95 protected:
96 virtual ~SafeBrowsingURLRequestContextGetter();
98 private:
99 SafeBrowsingService* const sb_service_; // Owned by BrowserProcess.
100 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
102 base::debug::LeakTracker<SafeBrowsingURLRequestContextGetter> leak_tracker_;
105 SafeBrowsingURLRequestContextGetter::SafeBrowsingURLRequestContextGetter(
106 SafeBrowsingService* sb_service)
107 : sb_service_(sb_service),
108 network_task_runner_(
109 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) {
112 SafeBrowsingURLRequestContextGetter::~SafeBrowsingURLRequestContextGetter() {}
114 net::URLRequestContext*
115 SafeBrowsingURLRequestContextGetter::GetURLRequestContext() {
116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
117 DCHECK(sb_service_->url_request_context_.get());
119 return sb_service_->url_request_context_.get();
122 scoped_refptr<base::SingleThreadTaskRunner>
123 SafeBrowsingURLRequestContextGetter::GetNetworkTaskRunner() const {
124 return network_task_runner_;
127 // static
128 SafeBrowsingServiceFactory* SafeBrowsingService::factory_ = NULL;
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();
138 private:
139 friend struct base::DefaultLazyInstanceTraits<SafeBrowsingServiceFactoryImpl>;
141 SafeBrowsingServiceFactoryImpl() { }
143 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactoryImpl);
146 static base::LazyInstance<SafeBrowsingServiceFactoryImpl>::Leaky
147 g_safe_browsing_service_factory_impl = LAZY_INSTANCE_INITIALIZER;
149 // static
150 base::FilePath SafeBrowsingService::GetCookieFilePathForTesting() {
151 return CookieFilePath();
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);
163 // static
164 SafeBrowsingService* SafeBrowsingService::CreateSafeBrowsingService() {
165 if (!factory_)
166 factory_ = g_safe_browsing_service_factory_impl.Pointer();
167 return factory_->CreateSafeBrowsingService();
170 SafeBrowsingService::SafeBrowsingService()
171 : protocol_manager_(NULL),
172 ping_manager_(NULL),
173 enabled_(false) {
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_);
182 void SafeBrowsingService::Initialize() {
183 startup_metric_utils::ScopedSlowStartupUMA
184 scoped_timer("Startup.SlowStartupSafeBrowsingServiceInitialize");
186 url_request_context_getter_ =
187 new SafeBrowsingURLRequestContextGetter(this);
189 ui_manager_ = CreateUIManager();
191 database_manager_ = CreateDatabaseManager();
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())));
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()));
205 download_service_.reset(new safe_browsing::DownloadProtectionService(
206 this, url_request_context_getter_.get()));
207 #endif
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());
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());
229 void SafeBrowsingService::ShutDown() {
230 // Deletes the PrefChangeRegistrars, whose dtors also unregister |this| as an
231 // observer of the preferences.
232 STLDeleteValues(&prefs_map_);
234 // Remove Profile creation/destruction observers.
235 prefs_registrar_.RemoveAll();
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();
244 url_request_context_getter_ = NULL;
245 BrowserThread::PostNonNestableTask(
246 BrowserThread::IO, FROM_HERE,
247 base::Bind(&SafeBrowsingService::DestroyURLRequestContextOnIOThread,
248 this));
251 // Binhash verification is only enabled for UMA users for now.
252 bool SafeBrowsingService::DownloadBinHashNeeded() const {
253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
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
265 net::URLRequestContextGetter* SafeBrowsingService::url_request_context() {
266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
267 return url_request_context_getter_.get();
270 const scoped_refptr<SafeBrowsingUIManager>&
271 SafeBrowsingService::ui_manager() const {
272 return ui_manager_;
275 const scoped_refptr<SafeBrowsingDatabaseManager>&
276 SafeBrowsingService::database_manager() const {
277 return database_manager_;
280 SafeBrowsingProtocolManager* SafeBrowsingService::protocol_manager() const {
281 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
282 return protocol_manager_;
285 SafeBrowsingPingManager* SafeBrowsingService::ping_manager() const {
286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
287 return ping_manager_;
290 SafeBrowsingUIManager* SafeBrowsingService::CreateUIManager() {
291 return new SafeBrowsingUIManager(this);
294 SafeBrowsingDatabaseManager* SafeBrowsingService::CreateDatabaseManager() {
296 #if defined(FULL_SAFE_BROWSING)
297 return new SafeBrowsingDatabaseManager(this);
298 #else
299 return NULL;
300 #endif
303 void SafeBrowsingService::InitURLRequestContextOnIOThread(
304 net::URLRequestContextGetter* system_url_request_context_getter) {
305 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
306 DCHECK(!url_request_context_.get());
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)));
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());
322 url_request_context_->set_cookie_store(cookie_store.get());
325 void SafeBrowsingService::DestroyURLRequestContextOnIOThread() {
326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
328 url_request_context_->AssertNoURLRequests();
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();
336 url_request_context_.reset();
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 if (cmdline->HasSwitch(switches::kSbURLPrefix)) {
359 config.url_prefix = cmdline->GetSwitchValueASCII(switches::kSbURLPrefix);
360 } else {
361 config.url_prefix = kSbDefaultURLPrefix;
362 config.backup_connect_error_url_prefix = kSbBackupConnectErrorURLPrefix;
363 config.backup_http_error_url_prefix = kSbBackupHttpErrorURLPrefix;
364 config.backup_network_error_url_prefix = kSbBackupNetworkErrorURLPrefix;
367 return config;
370 void SafeBrowsingService::StartOnIOThread(
371 net::URLRequestContextGetter* url_request_context_getter) {
372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
373 if (enabled_)
374 return;
375 enabled_ = true;
377 SafeBrowsingProtocolConfig config = GetProtocolConfig();
379 #if defined(FULL_SAFE_BROWSING)
380 DCHECK(database_manager_.get());
381 database_manager_->StartOnIOThread();
383 DCHECK(!protocol_manager_);
384 protocol_manager_ = SafeBrowsingProtocolManager::Create(
385 database_manager_.get(), url_request_context_getter, config);
386 protocol_manager_->Initialize();
387 #endif
389 DCHECK(!ping_manager_);
390 ping_manager_ = SafeBrowsingPingManager::Create(
391 url_request_context_getter, config);
394 void SafeBrowsingService::StopOnIOThread(bool shutdown) {
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
397 #if defined(FULL_SAFE_BROWSING)
398 database_manager_->StopOnIOThread(shutdown);
399 #endif
400 ui_manager_->StopOnIOThread(shutdown);
402 if (enabled_) {
403 enabled_ = false;
405 #if defined(FULL_SAFE_BROWSING)
406 // This cancels all in-flight GetHash requests. Note that database_manager_
407 // relies on the protocol_manager_ so if the latter is destroyed, the
408 // former must be stopped.
409 delete protocol_manager_;
410 protocol_manager_ = NULL;
411 #endif
412 delete ping_manager_;
413 ping_manager_ = NULL;
417 void SafeBrowsingService::Start() {
418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
420 BrowserThread::PostTask(
421 BrowserThread::IO, FROM_HERE,
422 base::Bind(&SafeBrowsingService::StartOnIOThread, this,
423 url_request_context_getter_));
426 void SafeBrowsingService::Stop(bool shutdown) {
427 BrowserThread::PostTask(
428 BrowserThread::IO, FROM_HERE,
429 base::Bind(&SafeBrowsingService::StopOnIOThread, this, shutdown));
432 void SafeBrowsingService::Observe(int type,
433 const content::NotificationSource& source,
434 const content::NotificationDetails& details) {
435 switch (type) {
436 case chrome::NOTIFICATION_PROFILE_CREATED: {
437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
438 Profile* profile = content::Source<Profile>(source).ptr();
439 if (!profile->IsOffTheRecord())
440 AddPrefService(profile->GetPrefs());
441 break;
443 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
445 Profile* profile = content::Source<Profile>(source).ptr();
446 if (!profile->IsOffTheRecord())
447 RemovePrefService(profile->GetPrefs());
448 break;
450 default:
451 NOTREACHED();
455 void SafeBrowsingService::AddPrefService(PrefService* pref_service) {
456 DCHECK(prefs_map_.find(pref_service) == prefs_map_.end());
457 PrefChangeRegistrar* registrar = new PrefChangeRegistrar();
458 registrar->Init(pref_service);
459 registrar->Add(prefs::kSafeBrowsingEnabled,
460 base::Bind(&SafeBrowsingService::RefreshState,
461 base::Unretained(this)));
462 prefs_map_[pref_service] = registrar;
463 RefreshState();
466 void SafeBrowsingService::RemovePrefService(PrefService* pref_service) {
467 if (prefs_map_.find(pref_service) != prefs_map_.end()) {
468 delete prefs_map_[pref_service];
469 prefs_map_.erase(pref_service);
470 RefreshState();
471 } else {
472 NOTREACHED();
476 void SafeBrowsingService::RefreshState() {
477 // Check if any profile requires the service to be active.
478 bool enable = false;
479 std::map<PrefService*, PrefChangeRegistrar*>::iterator iter;
480 for (iter = prefs_map_.begin(); iter != prefs_map_.end(); ++iter) {
481 if (iter->first->GetBoolean(prefs::kSafeBrowsingEnabled)) {
482 enable = true;
483 break;
487 if (enable)
488 Start();
489 else
490 Stop(false);
492 #if defined(FULL_SAFE_BROWSING)
493 if (csd_service_.get())
494 csd_service_->SetEnabledAndRefreshState(enable);
495 if (download_service_.get()) {
496 download_service_->SetEnabled(
497 enable && !CommandLine::ForCurrentProcess()->HasSwitch(
498 switches::kDisableImprovedDownloadProtection));
500 #endif