Refactor WebsiteSettings to operate on a SecurityInfo
[chromium-blink-merge.git] / chrome / browser / safe_browsing / safe_browsing_service.cc
blob0ae7ba6309c62ffa4ae245dcebfd6603a5860a1f
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 <vector>
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/lazy_instance.h"
14 #include "base/metrics/field_trial.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/profiles/profile.h"
25 #include "chrome/browser/profiles/profile_manager.h"
26 #include "chrome/browser/safe_browsing/client_side_detection_service.h"
27 #include "chrome/browser/safe_browsing/database_manager.h"
28 #include "chrome/browser/safe_browsing/download_protection_service.h"
29 #include "chrome/browser/safe_browsing/malware_details.h"
30 #include "chrome/browser/safe_browsing/ping_manager.h"
31 #include "chrome/browser/safe_browsing/protocol_manager.h"
32 #include "chrome/browser/safe_browsing/safe_browsing_database.h"
33 #include "chrome/browser/safe_browsing/ui_manager.h"
34 #include "chrome/common/chrome_constants.h"
35 #include "chrome/common/chrome_paths.h"
36 #include "chrome/common/chrome_switches.h"
37 #include "chrome/common/pref_names.h"
38 #include "chrome/common/url_constants.h"
39 #include "components/user_prefs/tracked/tracked_preference_validation_delegate.h"
40 #include "components/variations/variations_associated_data.h"
41 #include "content/public/browser/browser_thread.h"
42 #include "content/public/browser/cookie_store_factory.h"
43 #include "content/public/browser/notification_service.h"
44 #include "net/cookies/cookie_monster.h"
45 #include "net/extras/sqlite/cookie_crypto_delegate.h"
46 #include "net/url_request/url_request_context.h"
47 #include "net/url_request/url_request_context_getter.h"
49 #if defined(OS_WIN)
50 #include "chrome/installer/util/browser_distribution.h"
51 #endif
53 #if defined(SAFE_BROWSING_DB_LOCAL)
54 #include "chrome/browser/safe_browsing/local_database_manager.h"
55 #elif defined(SAFE_BROWSING_DB_REMOTE)
56 #include "chrome/browser/safe_browsing/remote_database_manager.h"
57 #endif
59 #if defined(FULL_SAFE_BROWSING)
60 #include "chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer.h"
61 #include "chrome/browser/safe_browsing/incident_reporting/blacklist_load_analyzer.h"
62 #include "chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h"
63 #include "chrome/browser/safe_browsing/incident_reporting/off_domain_inclusion_detector.h"
64 #include "chrome/browser/safe_browsing/incident_reporting/resource_request_detector.h"
65 #include "chrome/browser/safe_browsing/incident_reporting/variations_seed_signature_analyzer.h"
66 #endif
68 using content::BrowserThread;
70 namespace {
72 // Filename suffix for the cookie database.
73 const base::FilePath::CharType kCookiesFile[] = FILE_PATH_LITERAL(" Cookies");
75 // The default URL prefix where browser fetches chunk updates, hashes,
76 // and reports safe browsing hits and malware details.
77 const char kSbDefaultURLPrefix[] =
78 "https://safebrowsing.google.com/safebrowsing";
80 // The backup URL prefix used when there are issues establishing a connection
81 // with the server at the primary URL.
82 const char kSbBackupConnectErrorURLPrefix[] =
83 "https://alt1-safebrowsing.google.com/safebrowsing";
85 // The backup URL prefix used when there are HTTP-specific issues with the
86 // server at the primary URL.
87 const char kSbBackupHttpErrorURLPrefix[] =
88 "https://alt2-safebrowsing.google.com/safebrowsing";
90 // The backup URL prefix used when there are local network specific issues.
91 const char kSbBackupNetworkErrorURLPrefix[] =
92 "https://alt3-safebrowsing.google.com/safebrowsing";
94 base::FilePath CookieFilePath() {
95 return base::FilePath(
96 SafeBrowsingService::GetBaseFilename().value() + kCookiesFile);
99 #if defined(FULL_SAFE_BROWSING)
100 // Returns true if the incident reporting service is enabled via a field trial.
101 bool IsIncidentReportingServiceEnabled() {
102 const std::string group_name = base::FieldTrialList::FindFullName(
103 "SafeBrowsingIncidentReportingService");
104 return group_name == "Enabled";
106 #endif // defined(FULL_SAFE_BROWSING)
108 #if defined(SAFE_BROWSING_DB_REMOTE)
109 // Android field trial
110 const char kAndroidFieldExperiment[] = "SafeBrowsingAndroid";
111 const char kAndroidFieldParam[] = "enabled";
112 const char kAndroidCheckAllTypesParam[] = "check_all_resource_types";
113 const char kAndroidFieldParamEnabledValue[] = "true";
114 #endif // defined(SAFE_BROWSING_DB_REMOTE)
115 } // namespace
117 class SafeBrowsingURLRequestContextGetter
118 : public net::URLRequestContextGetter {
119 public:
120 explicit SafeBrowsingURLRequestContextGetter(
121 SafeBrowsingService* sb_service_);
123 // Implementation for net::UrlRequestContextGetter.
124 net::URLRequestContext* GetURLRequestContext() override;
125 scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
126 const override;
128 // Shuts down any pending requests using the getter, and nulls out
129 // |sb_service_|.
130 void SafeBrowsingServiceShuttingDown();
132 protected:
133 ~SafeBrowsingURLRequestContextGetter() override;
135 private:
136 SafeBrowsingService* sb_service_; // Owned by BrowserProcess.
137 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
140 SafeBrowsingURLRequestContextGetter::SafeBrowsingURLRequestContextGetter(
141 SafeBrowsingService* sb_service)
142 : sb_service_(sb_service),
143 network_task_runner_(
144 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) {
147 net::URLRequestContext*
148 SafeBrowsingURLRequestContextGetter::GetURLRequestContext() {
149 DCHECK_CURRENTLY_ON(BrowserThread::IO);
151 // Check if the service has been shut down.
152 if (!sb_service_)
153 return nullptr;
155 DCHECK(sb_service_->url_request_context_.get());
156 return sb_service_->url_request_context_.get();
159 scoped_refptr<base::SingleThreadTaskRunner>
160 SafeBrowsingURLRequestContextGetter::GetNetworkTaskRunner() const {
161 return network_task_runner_;
164 void SafeBrowsingURLRequestContextGetter::SafeBrowsingServiceShuttingDown() {
165 sb_service_ = nullptr;
166 URLRequestContextGetter::NotifyContextShuttingDown();
169 SafeBrowsingURLRequestContextGetter::~SafeBrowsingURLRequestContextGetter() {}
171 // static
172 SafeBrowsingServiceFactory* SafeBrowsingService::factory_ = NULL;
174 // The default SafeBrowsingServiceFactory. Global, made a singleton so we
175 // don't leak it.
176 class SafeBrowsingServiceFactoryImpl : public SafeBrowsingServiceFactory {
177 public:
178 SafeBrowsingService* CreateSafeBrowsingService() override {
179 return new SafeBrowsingService();
182 private:
183 friend struct base::DefaultLazyInstanceTraits<SafeBrowsingServiceFactoryImpl>;
185 SafeBrowsingServiceFactoryImpl() { }
187 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceFactoryImpl);
190 static base::LazyInstance<SafeBrowsingServiceFactoryImpl>::Leaky
191 g_safe_browsing_service_factory_impl = LAZY_INSTANCE_INITIALIZER;
193 // static
194 base::FilePath SafeBrowsingService::GetCookieFilePathForTesting() {
195 return CookieFilePath();
198 // static
199 base::FilePath SafeBrowsingService::GetBaseFilename() {
200 base::FilePath path;
201 bool result = PathService::Get(chrome::DIR_USER_DATA, &path);
202 DCHECK(result);
203 return path.Append(chrome::kSafeBrowsingBaseFilename);
207 // static
208 SafeBrowsingService* SafeBrowsingService::CreateSafeBrowsingService() {
209 if (!factory_)
210 factory_ = g_safe_browsing_service_factory_impl.Pointer();
211 return factory_->CreateSafeBrowsingService();
214 SafeBrowsingService::SafeBrowsingService()
215 : protocol_manager_(NULL),
216 ping_manager_(NULL),
217 enabled_(false),
218 enabled_by_prefs_(false) {
219 #if defined(SAFE_BROWSING_DB_REMOTE)
220 const std::string enabled_param = variations::GetVariationParamValue(
221 kAndroidFieldExperiment, kAndroidFieldParam);
222 is_android_field_trial_enabled_ =
223 (enabled_param == kAndroidFieldParamEnabledValue);
225 const std::string check_all_types_param = variations::GetVariationParamValue(
226 kAndroidFieldExperiment, kAndroidCheckAllTypesParam);
227 if (check_all_types_param == kAndroidFieldParamEnabledValue) {
228 resource_types_to_check_ = CHECK_ALL_RESOURCE_TYPES;
229 } else {
230 // Default
231 resource_types_to_check_ = CHECK_ONLY_DANGEROUS_TYPES;
233 #endif // defined(SAFE_BROWSING_DB_REMOTE)
236 SafeBrowsingService::~SafeBrowsingService() {
237 // We should have already been shut down. If we're still enabled, then the
238 // database isn't going to be closed properly, which could lead to corruption.
239 DCHECK(!enabled_);
242 void SafeBrowsingService::Initialize() {
243 url_request_context_getter_ =
244 new SafeBrowsingURLRequestContextGetter(this);
246 ui_manager_ = CreateUIManager();
248 database_manager_ = CreateDatabaseManager();
250 BrowserThread::PostTask(
251 BrowserThread::IO, FROM_HERE,
252 base::Bind(
253 &SafeBrowsingService::InitURLRequestContextOnIOThread, this,
254 make_scoped_refptr(g_browser_process->system_request_context())));
256 #if defined(FULL_SAFE_BROWSING)
257 #if defined(SAFE_BROWSING_CSD)
258 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
259 switches::kDisableClientSidePhishingDetection)) {
260 csd_service_.reset(safe_browsing::ClientSideDetectionService::Create(
261 url_request_context_getter_.get()));
263 #endif // defined(SAFE_BROWSING_CSD)
265 // TODO(nparker): Adding SAFE_BROWSING_SERVICE_DOWNLOAD to control this might
266 // allow removing FULL_SAFE_BROWSING above.
267 #if !defined(OS_ANDROID)
268 download_service_.reset(new safe_browsing::DownloadProtectionService(
269 this, url_request_context_getter_.get()));
270 #endif
272 if (IsIncidentReportingServiceEnabled()) {
273 incident_service_.reset(new safe_browsing::IncidentReportingService(
274 this, url_request_context_getter_));
275 resource_request_detector_.reset(new safe_browsing::ResourceRequestDetector(
276 incident_service_->GetIncidentReceiver()));
279 off_domain_inclusion_detector_.reset(
280 new safe_browsing::OffDomainInclusionDetector(database_manager_));
281 #endif // !defined(FULL_SAFE_BROWSING)
283 // Track the safe browsing preference of existing profiles.
284 // The SafeBrowsingService will be started if any existing profile has the
285 // preference enabled. It will also listen for updates to the preferences.
286 ProfileManager* profile_manager = g_browser_process->profile_manager();
287 if (profile_manager) {
288 std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles();
289 for (size_t i = 0; i < profiles.size(); ++i) {
290 if (profiles[i]->IsOffTheRecord())
291 continue;
292 AddPrefService(profiles[i]->GetPrefs());
296 // Track profile creation and destruction.
297 prefs_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
298 content::NotificationService::AllSources());
299 prefs_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
300 content::NotificationService::AllSources());
302 #if defined(FULL_SAFE_BROWSING)
303 // Register all the delayed analysis to the incident reporting service.
304 RegisterAllDelayedAnalysis();
305 #endif
308 void SafeBrowsingService::ShutDown() {
309 // Deletes the PrefChangeRegistrars, whose dtors also unregister |this| as an
310 // observer of the preferences.
311 STLDeleteValues(&prefs_map_);
313 // Remove Profile creation/destruction observers.
314 prefs_registrar_.RemoveAll();
316 Stop(true);
317 // The IO thread is going away, so make sure the ClientSideDetectionService
318 // dtor executes now since it may call the dtor of URLFetcher which relies
319 // on it.
320 csd_service_.reset();
322 #if defined(FULL_SAFE_BROWSING)
323 off_domain_inclusion_detector_.reset();
324 resource_request_detector_.reset();
325 incident_service_.reset();
326 #endif
328 download_service_.reset();
330 BrowserThread::PostNonNestableTask(
331 BrowserThread::IO, FROM_HERE,
332 base::Bind(&SafeBrowsingService::DestroyURLRequestContextOnIOThread,
333 this, url_request_context_getter_));
335 // Release the URLRequestContextGetter after passing it to the IOThread. It
336 // has to be released now rather than in the destructor because it can only
337 // be deleted on the IOThread, and the SafeBrowsingService outlives the IO
338 // thread.
339 url_request_context_getter_ = nullptr;
342 // Binhash verification is only enabled for UMA users for now.
343 bool SafeBrowsingService::DownloadBinHashNeeded() const {
344 DCHECK_CURRENTLY_ON(BrowserThread::UI);
346 #if defined(FULL_SAFE_BROWSING)
347 return (database_manager_->download_protection_enabled() &&
348 ui_manager_->CanReportStats()) ||
349 (download_protection_service() &&
350 download_protection_service()->enabled());
351 #else
352 return false;
353 #endif
356 net::URLRequestContextGetter* SafeBrowsingService::url_request_context() {
357 DCHECK_CURRENTLY_ON(BrowserThread::UI);
358 return url_request_context_getter_.get();
361 const scoped_refptr<SafeBrowsingUIManager>&
362 SafeBrowsingService::ui_manager() const {
363 return ui_manager_;
366 const scoped_refptr<SafeBrowsingDatabaseManager>&
367 SafeBrowsingService::database_manager() const {
368 return database_manager_;
371 SafeBrowsingProtocolManager* SafeBrowsingService::protocol_manager() const {
372 DCHECK_CURRENTLY_ON(BrowserThread::IO);
373 return protocol_manager_;
376 SafeBrowsingPingManager* SafeBrowsingService::ping_manager() const {
377 DCHECK_CURRENTLY_ON(BrowserThread::IO);
378 return ping_manager_;
381 scoped_ptr<TrackedPreferenceValidationDelegate>
382 SafeBrowsingService::CreatePreferenceValidationDelegate(
383 Profile* profile) const {
384 #if defined(FULL_SAFE_BROWSING)
385 if (incident_service_)
386 return incident_service_->CreatePreferenceValidationDelegate(profile);
387 #endif
388 return scoped_ptr<TrackedPreferenceValidationDelegate>();
391 #if defined(FULL_SAFE_BROWSING)
392 void SafeBrowsingService::RegisterDelayedAnalysisCallback(
393 const safe_browsing::DelayedAnalysisCallback& callback) {
394 if (incident_service_)
395 incident_service_->RegisterDelayedAnalysisCallback(callback);
397 #endif
399 void SafeBrowsingService::AddDownloadManager(
400 content::DownloadManager* download_manager) {
401 #if defined(FULL_SAFE_BROWSING)
402 if (incident_service_)
403 incident_service_->AddDownloadManager(download_manager);
404 #endif
407 void SafeBrowsingService::OnResourceRequest(const net::URLRequest* request) {
408 #if defined(FULL_SAFE_BROWSING)
409 if (off_domain_inclusion_detector_)
410 off_domain_inclusion_detector_->OnResourceRequest(request);
411 if (resource_request_detector_)
412 resource_request_detector_->OnResourceRequest(request);
413 #endif
416 SafeBrowsingUIManager* SafeBrowsingService::CreateUIManager() {
417 return new SafeBrowsingUIManager(this);
420 SafeBrowsingDatabaseManager* SafeBrowsingService::CreateDatabaseManager() {
421 #if defined(SAFE_BROWSING_DB_LOCAL)
422 return new LocalSafeBrowsingDatabaseManager(this);
423 #elif defined(SAFE_BROWSING_DB_REMOTE)
424 return new RemoteSafeBrowsingDatabaseManager();
425 #else
426 return NULL;
427 #endif
430 void SafeBrowsingService::RegisterAllDelayedAnalysis() {
431 #if defined(FULL_SAFE_BROWSING)
432 safe_browsing::RegisterBinaryIntegrityAnalysis();
433 safe_browsing::RegisterBlacklistLoadAnalysis();
434 safe_browsing::RegisterVariationsSeedSignatureAnalysis();
435 #else
436 NOTREACHED();
437 #endif
440 void SafeBrowsingService::InitURLRequestContextOnIOThread(
441 net::URLRequestContextGetter* system_url_request_context_getter) {
442 DCHECK_CURRENTLY_ON(BrowserThread::IO);
443 DCHECK(!url_request_context_.get());
445 scoped_refptr<net::CookieStore> cookie_store(
446 content::CreateCookieStore(
447 content::CookieStoreConfig(
448 CookieFilePath(),
449 content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES,
450 NULL,
451 NULL)));
453 url_request_context_.reset(new net::URLRequestContext);
454 // |system_url_request_context_getter| may be NULL during tests.
455 if (system_url_request_context_getter) {
456 url_request_context_->CopyFrom(
457 system_url_request_context_getter->GetURLRequestContext());
459 url_request_context_->set_cookie_store(cookie_store.get());
462 void SafeBrowsingService::DestroyURLRequestContextOnIOThread(
463 scoped_refptr<SafeBrowsingURLRequestContextGetter> context_getter) {
464 DCHECK_CURRENTLY_ON(BrowserThread::IO);
466 context_getter->SafeBrowsingServiceShuttingDown();
467 url_request_context_.reset();
470 SafeBrowsingProtocolConfig SafeBrowsingService::GetProtocolConfig() const {
471 SafeBrowsingProtocolConfig config;
472 // On Windows, get the safe browsing client name from the browser
473 // distribution classes in installer util. These classes don't yet have
474 // an analog on non-Windows builds so just keep the name specified here.
475 #if defined(OS_WIN)
476 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
477 config.client_name = dist->GetSafeBrowsingName();
478 #else
479 #if defined(GOOGLE_CHROME_BUILD)
480 config.client_name = "googlechrome";
481 #else
482 config.client_name = "chromium";
483 #endif
485 // Mark client string to allow server to differentiate mobile.
486 #if defined(OS_ANDROID)
487 config.client_name.append("-a");
488 #elif defined(OS_IOS)
489 config.client_name.append("-i");
490 #endif
492 #endif // defined(OS_WIN)
493 base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
494 config.disable_auto_update =
495 cmdline->HasSwitch(switches::kSbDisableAutoUpdate) ||
496 cmdline->HasSwitch(switches::kDisableBackgroundNetworking);
497 config.url_prefix = kSbDefaultURLPrefix;
498 config.backup_connect_error_url_prefix = kSbBackupConnectErrorURLPrefix;
499 config.backup_http_error_url_prefix = kSbBackupHttpErrorURLPrefix;
500 config.backup_network_error_url_prefix = kSbBackupNetworkErrorURLPrefix;
502 return config;
505 // Any tests that create a DatabaseManager that isn't derived from
506 // LocalSafeBrowsingDatabaseManager should override this to return NULL.
507 SafeBrowsingProtocolManagerDelegate*
508 SafeBrowsingService::GetProtocolManagerDelegate() {
509 #if defined(SAFE_BROWSING_DB_LOCAL)
510 return static_cast<LocalSafeBrowsingDatabaseManager*>(
511 database_manager_.get());
512 #else
513 NOTREACHED();
514 return NULL;
515 #endif
518 void SafeBrowsingService::StartOnIOThread(
519 net::URLRequestContextGetter* url_request_context_getter) {
520 DCHECK_CURRENTLY_ON(BrowserThread::IO);
521 if (enabled_)
522 return;
523 enabled_ = true;
525 SafeBrowsingProtocolConfig config = GetProtocolConfig();
527 #if defined(SAFE_BROWSING_DB_LOCAL) || defined(SAFE_BROWSING_DB_REMOTE)
528 DCHECK(database_manager_.get());
529 database_manager_->StartOnIOThread();
530 #endif
532 #if defined(SAFE_BROWSING_DB_LOCAL)
533 SafeBrowsingProtocolManagerDelegate* protocol_manager_delegate =
534 GetProtocolManagerDelegate();
535 if (protocol_manager_delegate) {
536 protocol_manager_ = SafeBrowsingProtocolManager::Create(
537 protocol_manager_delegate, url_request_context_getter, config);
538 protocol_manager_->Initialize();
540 #endif
542 DCHECK(!ping_manager_);
543 ping_manager_ = SafeBrowsingPingManager::Create(
544 url_request_context_getter, config);
547 void SafeBrowsingService::StopOnIOThread(bool shutdown) {
548 DCHECK_CURRENTLY_ON(BrowserThread::IO);
550 #if defined(SAFE_BROWSING_DB_LOCAL) || defined(SAFE_BROWSING_DB_REMOTE)
551 database_manager_->StopOnIOThread(shutdown);
552 #endif
553 ui_manager_->StopOnIOThread(shutdown);
555 if (enabled_) {
556 enabled_ = false;
558 #if defined(SAFE_BROWSING_DB_LOCAL)
559 // This cancels all in-flight GetHash requests. Note that database_manager_
560 // relies on the protocol_manager_ so if the latter is destroyed, the
561 // former must be stopped.
562 if (protocol_manager_) {
563 delete protocol_manager_;
564 protocol_manager_ = NULL;
566 #endif
567 delete ping_manager_;
568 ping_manager_ = NULL;
572 void SafeBrowsingService::Start() {
573 DCHECK_CURRENTLY_ON(BrowserThread::UI);
575 BrowserThread::PostTask(
576 BrowserThread::IO, FROM_HERE,
577 base::Bind(&SafeBrowsingService::StartOnIOThread, this,
578 url_request_context_getter_));
581 void SafeBrowsingService::Stop(bool shutdown) {
582 BrowserThread::PostTask(
583 BrowserThread::IO, FROM_HERE,
584 base::Bind(&SafeBrowsingService::StopOnIOThread, this, shutdown));
587 void SafeBrowsingService::Observe(int type,
588 const content::NotificationSource& source,
589 const content::NotificationDetails& details) {
590 switch (type) {
591 case chrome::NOTIFICATION_PROFILE_CREATED: {
592 DCHECK_CURRENTLY_ON(BrowserThread::UI);
593 Profile* profile = content::Source<Profile>(source).ptr();
594 if (!profile->IsOffTheRecord())
595 AddPrefService(profile->GetPrefs());
596 break;
598 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
599 DCHECK_CURRENTLY_ON(BrowserThread::UI);
600 Profile* profile = content::Source<Profile>(source).ptr();
601 if (!profile->IsOffTheRecord())
602 RemovePrefService(profile->GetPrefs());
603 break;
605 default:
606 NOTREACHED();
610 void SafeBrowsingService::AddPrefService(PrefService* pref_service) {
611 DCHECK(prefs_map_.find(pref_service) == prefs_map_.end());
612 PrefChangeRegistrar* registrar = new PrefChangeRegistrar();
613 registrar->Init(pref_service);
614 registrar->Add(prefs::kSafeBrowsingEnabled,
615 base::Bind(&SafeBrowsingService::RefreshState,
616 base::Unretained(this)));
617 // ClientSideDetectionService will need to be refresh the models
618 // renderers have if extended-reporting changes.
619 registrar->Add(prefs::kSafeBrowsingExtendedReportingEnabled,
620 base::Bind(&SafeBrowsingService::RefreshState,
621 base::Unretained(this)));
622 prefs_map_[pref_service] = registrar;
623 RefreshState();
626 void SafeBrowsingService::RemovePrefService(PrefService* pref_service) {
627 if (prefs_map_.find(pref_service) != prefs_map_.end()) {
628 delete prefs_map_[pref_service];
629 prefs_map_.erase(pref_service);
630 RefreshState();
631 } else {
632 NOTREACHED();
636 scoped_ptr<SafeBrowsingService::StateSubscription>
637 SafeBrowsingService::RegisterStateCallback(
638 const base::Callback<void(void)>& callback) {
639 DCHECK_CURRENTLY_ON(BrowserThread::UI);
640 return state_callback_list_.Add(callback);
643 void SafeBrowsingService::RefreshState() {
644 DCHECK_CURRENTLY_ON(BrowserThread::UI);
645 // Check if any profile requires the service to be active.
646 bool enable = false;
647 std::map<PrefService*, PrefChangeRegistrar*>::iterator iter;
648 for (iter = prefs_map_.begin(); iter != prefs_map_.end(); ++iter) {
649 if (iter->first->GetBoolean(prefs::kSafeBrowsingEnabled)) {
650 enable = true;
651 break;
655 enabled_by_prefs_ = enable;
657 if (enable)
658 Start();
659 else
660 Stop(false);
662 state_callback_list_.Notify();
664 #if defined(FULL_SAFE_BROWSING)
665 if (csd_service_)
666 csd_service_->SetEnabledAndRefreshState(enable);
667 if (download_service_)
668 download_service_->SetEnabled(enable);
669 #endif