cros: Remove default pinned apps trial.
[chromium-blink-merge.git] / chrome / browser / safe_browsing / safe_browsing_service.cc
blob6f15f1cbe2adf7f03eba08d7e4483ba483363de3
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_store_factory.h"
41 #include "content/public/browser/notification_service.h"
42 #include "net/cookies/cookie_monster.h"
43 #include "net/url_request/url_request_context.h"
44 #include "net/url_request/url_request_context_getter.h"
46 #if defined(OS_WIN)
47 #include "chrome/installer/util/browser_distribution.h"
48 #endif
50 using content::BrowserThread;
52 namespace {
54 // Filename suffix for the cookie database.
55 const base::FilePath::CharType kCookiesFile[] = FILE_PATH_LITERAL(" Cookies");
57 // The default URL prefix where browser fetches chunk updates, hashes,
58 // and reports safe browsing hits and malware details.
59 const char* const kSbDefaultURLPrefix =
60 "https://safebrowsing.google.com/safebrowsing";
62 // The backup URL prefix used when there are issues establishing a connection
63 // with the server at the primary URL.
64 const char* const kSbBackupConnectErrorURLPrefix =
65 "https://alt1-safebrowsing.google.com/safebrowsing";
67 // The backup URL prefix used when there are HTTP-specific issues with the
68 // server at the primary URL.
69 const char* const kSbBackupHttpErrorURLPrefix =
70 "https://alt2-safebrowsing.google.com/safebrowsing";
72 // The backup URL prefix used when there are local network specific issues.
73 const char* const kSbBackupNetworkErrorURLPrefix =
74 "https://alt3-safebrowsing.google.com/safebrowsing";
76 base::FilePath CookieFilePath() {
77 return base::FilePath(
78 SafeBrowsingService::GetBaseFilename().value() + kCookiesFile);
81 } // namespace
83 class SafeBrowsingURLRequestContextGetter
84 : public net::URLRequestContextGetter {
85 public:
86 explicit SafeBrowsingURLRequestContextGetter(
87 SafeBrowsingService* sb_service_);
89 // Implementation for net::UrlRequestContextGetter.
90 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE;
91 virtual scoped_refptr<base::SingleThreadTaskRunner>
92 GetNetworkTaskRunner() const OVERRIDE;
94 protected:
95 virtual ~SafeBrowsingURLRequestContextGetter();
97 private:
98 SafeBrowsingService* const sb_service_; // Owned by BrowserProcess.
99 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
101 base::debug::LeakTracker<SafeBrowsingURLRequestContextGetter> leak_tracker_;
104 SafeBrowsingURLRequestContextGetter::SafeBrowsingURLRequestContextGetter(
105 SafeBrowsingService* sb_service)
106 : sb_service_(sb_service),
107 network_task_runner_(
108 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) {
111 SafeBrowsingURLRequestContextGetter::~SafeBrowsingURLRequestContextGetter() {}
113 net::URLRequestContext*
114 SafeBrowsingURLRequestContextGetter::GetURLRequestContext() {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
116 DCHECK(sb_service_->url_request_context_.get());
118 return sb_service_->url_request_context_.get();
121 scoped_refptr<base::SingleThreadTaskRunner>
122 SafeBrowsingURLRequestContextGetter::GetNetworkTaskRunner() const {
123 return network_task_runner_;
126 // static
127 SafeBrowsingServiceFactory* SafeBrowsingService::factory_ = NULL;
129 // The default SafeBrowsingServiceFactory. Global, made a singleton so we
130 // don't leak it.
131 class SafeBrowsingServiceFactoryImpl : public SafeBrowsingServiceFactory {
132 public:
133 virtual SafeBrowsingService* CreateSafeBrowsingService() OVERRIDE {
134 return new SafeBrowsingService();
137 private:
138 friend struct base::DefaultLazyInstanceTraits<SafeBrowsingServiceFactoryImpl>;
140 SafeBrowsingServiceFactoryImpl() { }
142 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactoryImpl);
145 static base::LazyInstance<SafeBrowsingServiceFactoryImpl>::Leaky
146 g_safe_browsing_service_factory_impl = LAZY_INSTANCE_INITIALIZER;
148 // static
149 base::FilePath SafeBrowsingService::GetCookieFilePathForTesting() {
150 return CookieFilePath();
153 // static
154 base::FilePath SafeBrowsingService::GetBaseFilename() {
155 base::FilePath path;
156 bool result = PathService::Get(chrome::DIR_USER_DATA, &path);
157 DCHECK(result);
158 return path.Append(chrome::kSafeBrowsingBaseFilename);
162 // static
163 SafeBrowsingService* SafeBrowsingService::CreateSafeBrowsingService() {
164 if (!factory_)
165 factory_ = g_safe_browsing_service_factory_impl.Pointer();
166 return factory_->CreateSafeBrowsingService();
169 SafeBrowsingService::SafeBrowsingService()
170 : protocol_manager_(NULL),
171 ping_manager_(NULL),
172 enabled_(false) {
175 SafeBrowsingService::~SafeBrowsingService() {
176 // We should have already been shut down. If we're still enabled, then the
177 // database isn't going to be closed properly, which could lead to corruption.
178 DCHECK(!enabled_);
181 void SafeBrowsingService::Initialize() {
182 startup_metric_utils::ScopedSlowStartupUMA
183 scoped_timer("Startup.SlowStartupSafeBrowsingServiceInitialize");
185 url_request_context_getter_ =
186 new SafeBrowsingURLRequestContextGetter(this);
188 ui_manager_ = CreateUIManager();
190 database_manager_ = CreateDatabaseManager();
192 BrowserThread::PostTask(
193 BrowserThread::IO, FROM_HERE,
194 base::Bind(
195 &SafeBrowsingService::InitURLRequestContextOnIOThread, this,
196 make_scoped_refptr(g_browser_process->system_request_context())));
198 #if defined(FULL_SAFE_BROWSING)
199 if (!CommandLine::ForCurrentProcess()->HasSwitch(
200 switches::kDisableClientSidePhishingDetection)) {
201 csd_service_.reset(safe_browsing::ClientSideDetectionService::Create(
202 url_request_context_getter_.get()));
204 download_service_.reset(new safe_browsing::DownloadProtectionService(
205 this, url_request_context_getter_.get()));
206 #endif
208 // Track the safe browsing preference of existing profiles.
209 // The SafeBrowsingService will be started if any existing profile has the
210 // preference enabled. It will also listen for updates to the preferences.
211 ProfileManager* profile_manager = g_browser_process->profile_manager();
212 if (profile_manager) {
213 std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles();
214 for (size_t i = 0; i < profiles.size(); ++i) {
215 if (profiles[i]->IsOffTheRecord())
216 continue;
217 AddPrefService(profiles[i]->GetPrefs());
221 // Track profile creation and destruction.
222 prefs_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
223 content::NotificationService::AllSources());
224 prefs_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
225 content::NotificationService::AllSources());
228 void SafeBrowsingService::ShutDown() {
229 // Deletes the PrefChangeRegistrars, whose dtors also unregister |this| as an
230 // observer of the preferences.
231 STLDeleteValues(&prefs_map_);
233 // Remove Profile creation/destruction observers.
234 prefs_registrar_.RemoveAll();
236 Stop(true);
237 // The IO thread is going away, so make sure the ClientSideDetectionService
238 // dtor executes now since it may call the dtor of URLFetcher which relies
239 // on it.
240 csd_service_.reset();
241 download_service_.reset();
243 url_request_context_getter_ = NULL;
244 BrowserThread::PostNonNestableTask(
245 BrowserThread::IO, FROM_HERE,
246 base::Bind(&SafeBrowsingService::DestroyURLRequestContextOnIOThread,
247 this));
250 // Binhash verification is only enabled for UMA users for now.
251 bool SafeBrowsingService::DownloadBinHashNeeded() const {
252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
254 #if defined(FULL_SAFE_BROWSING)
255 return (database_manager_->download_protection_enabled() &&
256 ui_manager_->CanReportStats()) ||
257 (download_protection_service() &&
258 download_protection_service()->enabled());
259 #else
260 return false;
261 #endif
264 net::URLRequestContextGetter* SafeBrowsingService::url_request_context() {
265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
266 return url_request_context_getter_.get();
269 const scoped_refptr<SafeBrowsingUIManager>&
270 SafeBrowsingService::ui_manager() const {
271 return ui_manager_;
274 const scoped_refptr<SafeBrowsingDatabaseManager>&
275 SafeBrowsingService::database_manager() const {
276 return database_manager_;
279 SafeBrowsingProtocolManager* SafeBrowsingService::protocol_manager() const {
280 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
281 return protocol_manager_;
284 SafeBrowsingPingManager* SafeBrowsingService::ping_manager() const {
285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
286 return ping_manager_;
289 SafeBrowsingUIManager* SafeBrowsingService::CreateUIManager() {
290 return new SafeBrowsingUIManager(this);
293 SafeBrowsingDatabaseManager* SafeBrowsingService::CreateDatabaseManager() {
295 #if defined(FULL_SAFE_BROWSING)
296 return new SafeBrowsingDatabaseManager(this);
297 #else
298 return NULL;
299 #endif
302 void SafeBrowsingService::InitURLRequestContextOnIOThread(
303 net::URLRequestContextGetter* system_url_request_context_getter) {
304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
305 DCHECK(!url_request_context_.get());
307 scoped_refptr<net::CookieStore> cookie_store(
308 content::CreatePersistentCookieStore(
309 CookieFilePath(),
310 false,
311 NULL,
312 NULL));
314 url_request_context_.reset(new net::URLRequestContext);
315 // |system_url_request_context_getter| may be NULL during tests.
316 if (system_url_request_context_getter) {
317 url_request_context_->CopyFrom(
318 system_url_request_context_getter->GetURLRequestContext());
320 url_request_context_->set_cookie_store(cookie_store.get());
323 void SafeBrowsingService::DestroyURLRequestContextOnIOThread() {
324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
326 url_request_context_->AssertNoURLRequests();
328 // Need to do the CheckForLeaks on IOThread instead of in ShutDown where
329 // url_request_context_getter_ is cleared, since the URLRequestContextGetter
330 // will PostTask to IOTread to delete itself.
331 using base::debug::LeakTracker;
332 LeakTracker<SafeBrowsingURLRequestContextGetter>::CheckForLeaks();
334 url_request_context_.reset();
337 void SafeBrowsingService::StartOnIOThread(
338 net::URLRequestContextGetter* url_request_context_getter) {
339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
340 if (enabled_)
341 return;
342 enabled_ = true;
344 SafeBrowsingProtocolConfig config;
345 // On Windows, get the safe browsing client name from the browser
346 // distribution classes in installer util. These classes don't yet have
347 // an analog on non-Windows builds so just keep the name specified here.
348 #if defined(OS_WIN)
349 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
350 config.client_name = dist->GetSafeBrowsingName();
351 #else
352 #if defined(GOOGLE_CHROME_BUILD)
353 config.client_name = "googlechrome";
354 #else
355 config.client_name = "chromium";
356 #endif
357 #endif
358 CommandLine* cmdline = CommandLine::ForCurrentProcess();
359 config.disable_auto_update =
360 cmdline->HasSwitch(switches::kSbDisableAutoUpdate) ||
361 cmdline->HasSwitch(switches::kDisableBackgroundNetworking);
362 if (cmdline->HasSwitch(switches::kSbURLPrefix)) {
363 config.url_prefix = cmdline->GetSwitchValueASCII(switches::kSbURLPrefix);
364 } else {
365 config.url_prefix = kSbDefaultURLPrefix;
366 config.backup_connect_error_url_prefix = kSbBackupConnectErrorURLPrefix;
367 config.backup_http_error_url_prefix = kSbBackupHttpErrorURLPrefix;
368 config.backup_network_error_url_prefix = kSbBackupNetworkErrorURLPrefix;
371 #if defined(FULL_SAFE_BROWSING)
372 DCHECK(database_manager_.get());
373 database_manager_->StartOnIOThread();
375 DCHECK(!protocol_manager_);
376 protocol_manager_ = SafeBrowsingProtocolManager::Create(
377 database_manager_.get(), url_request_context_getter, config);
378 protocol_manager_->Initialize();
379 #endif
381 DCHECK(!ping_manager_);
382 ping_manager_ = SafeBrowsingPingManager::Create(
383 url_request_context_getter, config);
386 void SafeBrowsingService::StopOnIOThread(bool shutdown) {
387 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
389 #if defined(FULL_SAFE_BROWSING)
390 database_manager_->StopOnIOThread(shutdown);
391 #endif
392 ui_manager_->StopOnIOThread(shutdown);
394 if (enabled_) {
395 enabled_ = false;
397 #if defined(FULL_SAFE_BROWSING)
398 // This cancels all in-flight GetHash requests. Note that database_manager_
399 // relies on the protocol_manager_ so if the latter is destroyed, the
400 // former must be stopped.
401 delete protocol_manager_;
402 protocol_manager_ = NULL;
403 #endif
404 delete ping_manager_;
405 ping_manager_ = NULL;
409 void SafeBrowsingService::Start() {
410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
412 BrowserThread::PostTask(
413 BrowserThread::IO, FROM_HERE,
414 base::Bind(&SafeBrowsingService::StartOnIOThread, this,
415 url_request_context_getter_));
418 void SafeBrowsingService::Stop(bool shutdown) {
419 BrowserThread::PostTask(
420 BrowserThread::IO, FROM_HERE,
421 base::Bind(&SafeBrowsingService::StopOnIOThread, this, shutdown));
424 void SafeBrowsingService::Observe(int type,
425 const content::NotificationSource& source,
426 const content::NotificationDetails& details) {
427 switch (type) {
428 case chrome::NOTIFICATION_PROFILE_CREATED: {
429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
430 Profile* profile = content::Source<Profile>(source).ptr();
431 if (!profile->IsOffTheRecord())
432 AddPrefService(profile->GetPrefs());
433 break;
435 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
437 Profile* profile = content::Source<Profile>(source).ptr();
438 if (!profile->IsOffTheRecord())
439 RemovePrefService(profile->GetPrefs());
440 break;
442 default:
443 NOTREACHED();
447 void SafeBrowsingService::AddPrefService(PrefService* pref_service) {
448 DCHECK(prefs_map_.find(pref_service) == prefs_map_.end());
449 PrefChangeRegistrar* registrar = new PrefChangeRegistrar();
450 registrar->Init(pref_service);
451 registrar->Add(prefs::kSafeBrowsingEnabled,
452 base::Bind(&SafeBrowsingService::RefreshState,
453 base::Unretained(this)));
454 prefs_map_[pref_service] = registrar;
455 RefreshState();
458 void SafeBrowsingService::RemovePrefService(PrefService* pref_service) {
459 if (prefs_map_.find(pref_service) != prefs_map_.end()) {
460 delete prefs_map_[pref_service];
461 prefs_map_.erase(pref_service);
462 RefreshState();
463 } else {
464 NOTREACHED();
468 void SafeBrowsingService::RefreshState() {
469 // Check if any profile requires the service to be active.
470 bool enable = false;
471 std::map<PrefService*, PrefChangeRegistrar*>::iterator iter;
472 for (iter = prefs_map_.begin(); iter != prefs_map_.end(); ++iter) {
473 if (iter->first->GetBoolean(prefs::kSafeBrowsingEnabled)) {
474 enable = true;
475 break;
479 if (enable)
480 Start();
481 else
482 Stop(false);
484 #if defined(FULL_SAFE_BROWSING)
485 if (csd_service_.get())
486 csd_service_->SetEnabledAndRefreshState(enable);
487 if (download_service_.get()) {
488 download_service_->SetEnabled(
489 enable && !CommandLine::ForCurrentProcess()->HasSwitch(
490 switches::kDisableImprovedDownloadProtection));
492 #endif