Home | History | Annotate | Download | only in safe_browsing
      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 }
    567