12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/blacklist.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <iterator>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/ref_counted.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/stl_util.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/browser_process.h"
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_prefs.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/safe_browsing_service.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/safe_browsing_util.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_details.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_source.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread;
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The safe browsing database manager to use. Make this a global/static variable
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// rather than a member of Blacklist because Blacklist accesses the real
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// database manager before it has a chance to get a fake one.
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class LazySafeBrowsingDatabaseManager {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LazySafeBrowsingDatabaseManager() {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (g_browser_process && g_browser_process->safe_browsing_service()) {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      instance_ =
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          g_browser_process->safe_browsing_service()->database_manager();
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<SafeBrowsingDatabaseManager> get() {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return instance_;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set(scoped_refptr<SafeBrowsingDatabaseManager> instance) {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    instance_ = instance;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<SafeBrowsingDatabaseManager> instance_;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static base::LazyInstance<LazySafeBrowsingDatabaseManager> g_database_manager =
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Implementation of SafeBrowsingDatabaseManager::Client, the class which is
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// called back from safebrowsing queries.
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Constructed on any thread but lives on the IO from then on.
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SafeBrowsingClientImpl
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public SafeBrowsingDatabaseManager::Client,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      public base::RefCountedThreadSafe<SafeBrowsingClientImpl> {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef base::Callback<void(const std::set<std::string>&)> OnResultCallback;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Constructs a client to query the database manager for |extension_ids| and
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // run |callback| with the IDs of those which have been blacklisted.
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SafeBrowsingClientImpl(
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::set<std::string>& extension_ids,
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const OnResultCallback& callback)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : callback_message_loop_(base::MessageLoopProxy::current()),
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        callback_(callback) {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserThread::IO,
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&SafeBrowsingClientImpl::StartCheck, this,
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   g_database_manager.Get().get(),
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   extension_ids));
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  friend class base::RefCountedThreadSafe<SafeBrowsingClientImpl>;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SafeBrowsingClientImpl() {}
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Pass |database_manager| as a parameter to avoid touching
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SafeBrowsingService on the IO thread.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void StartCheck(scoped_refptr<SafeBrowsingDatabaseManager> database_manager,
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  const std::set<std::string>& extension_ids) {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (database_manager->CheckExtensionIDs(extension_ids, this)) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Definitely not blacklisted. Callback immediately.
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback_message_loop_->PostTask(
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          FROM_HERE,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(callback_, std::set<std::string>()));
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Something might be blacklisted, response will come in
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // OnCheckExtensionsResult.
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddRef();  // Balanced in OnCheckExtensionsResult
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnCheckExtensionsResult(
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::set<std::string>& hits) OVERRIDE {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback_message_loop_->PostTask(FROM_HERE, base::Bind(callback_, hits));
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Release();  // Balanced in StartCheck.
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> callback_message_loop_;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnResultCallback callback_;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingClientImpl);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void CheckOneExtensionState(
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const Blacklist::IsBlacklistedCallback& callback,
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const Blacklist::BlacklistStateMap& state_map) {
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  callback.Run(state_map.empty() ? Blacklist::NOT_BLACKLISTED
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                 : state_map.begin()->second);
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void GetMalwareFromBlacklistStateMap(
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const Blacklist::GetMalwareIDsCallback& callback,
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const Blacklist::BlacklistStateMap& state_map) {
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::set<std::string> malware;
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (Blacklist::BlacklistStateMap::const_iterator it = state_map.begin();
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       it != state_map.end(); ++it) {
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (it->second == Blacklist::BLACKLISTED_MALWARE)
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      malware.insert(it->first);
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  callback.Run(malware);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Blacklist::Observer::Observer(Blacklist* blacklist) : blacklist_(blacklist) {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  blacklist_->AddObserver(this);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Blacklist::Observer::~Observer() {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  blacklist_->RemoveObserver(this);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Blacklist::ScopedDatabaseManagerForTest::ScopedDatabaseManagerForTest(
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<SafeBrowsingDatabaseManager> database_manager)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : original_(GetDatabaseManager()) {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetDatabaseManager(database_manager);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Blacklist::ScopedDatabaseManagerForTest::~ScopedDatabaseManagerForTest() {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetDatabaseManager(original_);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)Blacklist::Blacklist(ExtensionPrefs* prefs) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<SafeBrowsingDatabaseManager> database_manager =
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      g_database_manager.Get().get();
16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (database_manager) {
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    registrar_.Add(
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        this,
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE,
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        content::Source<SafeBrowsingDatabaseManager>(database_manager.get()));
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Clear out the old prefs-backed blacklist, stored as empty extension entries
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // with just a "blacklisted" property.
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // TODO(kalman): Delete this block of code, see http://crbug.com/295882.
17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::set<std::string> blacklisted = prefs->GetBlacklistedExtensions();
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (std::set<std::string>::iterator it = blacklisted.begin();
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       it != blacklisted.end(); ++it) {
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!prefs->GetInstalledExtensionInfo(*it))
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      prefs->DeleteExtensionPrefs(*it);
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Blacklist::~Blacklist() {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Blacklist::GetBlacklistedIDs(const std::set<std::string>& ids,
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const GetBlacklistedIDsCallback& callback) {
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (ids.empty() || !g_database_manager.Get().get().get()) {
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::MessageLoopProxy::current()->PostTask(
1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        FROM_HERE, base::Bind(callback, BlacklistStateMap()));
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Constructing the SafeBrowsingClientImpl begins the process of asking
1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // safebrowsing for the blacklisted extensions. The set of blacklisted
1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // extensions returned by SafeBrowsing will then be passed to
1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // GetBlacklistStateIDs to get the particular BlacklistState for each id.
1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  new SafeBrowsingClientImpl(
1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ids, base::Bind(&Blacklist::GetBlacklistStateForIDs, AsWeakPtr(),
1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                      callback));
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Blacklist::GetMalwareIDs(const std::set<std::string>& ids,
2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                              const GetMalwareIDsCallback& callback) {
2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GetBlacklistedIDs(ids, base::Bind(&GetMalwareFromBlacklistStateMap,
2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                    callback));
2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Blacklist::IsBlacklisted(const std::string& extension_id,
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const IsBlacklistedCallback& callback) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::set<std::string> check;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  check.insert(extension_id);
2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GetBlacklistedIDs(check, base::Bind(&CheckOneExtensionState, callback));
2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Blacklist::GetBlacklistStateForIDs(
2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GetBlacklistedIDsCallback& callback,
2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const std::set<std::string>& blacklisted_ids) {
2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::set<std::string> ids_unknown_state;
2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BlacklistStateMap extensions_state;
2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (std::set<std::string>::const_iterator it = blacklisted_ids.begin();
2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       it != blacklisted_ids.end(); ++it) {
2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    BlacklistStateMap::const_iterator cache_it =
2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        blacklist_state_cache_.find(*it);
2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (cache_it == blacklist_state_cache_.end())
2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ids_unknown_state.insert(*it);
2281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    else
2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extensions_state[*it] = cache_it->second;
2301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (ids_unknown_state.empty()) {
2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    callback.Run(extensions_state);
2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else {
2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // After the extension blacklist states have been downloaded, call this
2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // functions again, but prevent infinite cycle in case server is offline
2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // or some other reason prevents us from receiving the blacklist state for
2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // these extensions.
2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    RequestExtensionsBlacklistState(
2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        ids_unknown_state,
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        base::Bind(&Blacklist::ReturnBlacklistStateMap, AsWeakPtr(),
2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                   callback, blacklisted_ids));
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Blacklist::ReturnBlacklistStateMap(
2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GetBlacklistedIDsCallback& callback,
2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const std::set<std::string>& blacklisted_ids) {
2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BlacklistStateMap extensions_state;
2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (std::set<std::string>::const_iterator it = blacklisted_ids.begin();
2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       it != blacklisted_ids.end(); ++it) {
2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    BlacklistStateMap::const_iterator cache_it =
2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        blacklist_state_cache_.find(*it);
2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (cache_it != blacklist_state_cache_.end())
2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extensions_state[*it] = cache_it->second;
2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // If for some reason we still haven't cached the state of this extension,
2571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // we silently skip it.
2581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  callback.Run(extensions_state);
2611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void Blacklist::RequestExtensionsBlacklistState(
2641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const std::set<std::string> ids, base::Callback<void()> callback) {
2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // This is a stub. The request will be made here, but the server is not up
2671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // yet. For compatibility with current blacklist logic, mark all extensions
2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // as malicious.
2691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (std::set<std::string>::const_iterator it = ids.begin();
2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       it != ids.end();
2711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       ++it) {
2721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    blacklist_state_cache_[*it] = BLACKLISTED_MALWARE;
2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  callback.Run();
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Blacklist::AddObserver(Observer* observer) {
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.AddObserver(observer);
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Blacklist::RemoveObserver(Observer* observer) {
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.RemoveObserver(observer);
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Blacklist::SetDatabaseManager(
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<SafeBrowsingDatabaseManager> database_manager) {
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_database_manager.Get().set(database_manager);
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<SafeBrowsingDatabaseManager> Blacklist::GetDatabaseManager() {
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return g_database_manager.Get().get();
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Blacklist::Observe(int type,
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        const content::NotificationSource& source,
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        const content::NotificationDetails& details) {
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE, type);
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observers_, OnBlacklistUpdated());
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
306