Home | History | Annotate | Download | only in password_manager
      1 // Copyright (c) 2011 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/password_manager/password_store_default.h"
      6 
      7 #include <set>
      8 
      9 #include "base/logging.h"
     10 #include "base/stl_util-inl.h"
     11 #include "chrome/browser/password_manager/password_store_change.h"
     12 #include "chrome/browser/prefs/pref_service.h"
     13 #include "chrome/browser/profiles/profile.h"
     14 #include "chrome/browser/webdata/web_data_service.h"
     15 #include "chrome/common/chrome_constants.h"
     16 #include "chrome/common/pref_names.h"
     17 #include "content/browser/browser_thread.h"
     18 #include "content/common/notification_service.h"
     19 
     20 using webkit_glue::PasswordForm;
     21 
     22 // MigrateHelper handles migration from WebDB to PasswordStore. It runs
     23 // entirely on the UI thread and is owned by PasswordStoreDefault.
     24 class PasswordStoreDefault::MigrateHelper : public WebDataServiceConsumer {
     25  public:
     26   MigrateHelper(Profile* profile,
     27                 WebDataService* web_data_service,
     28                 PasswordStore* password_store)
     29       : profile_(profile),
     30         web_data_service_(web_data_service),
     31         password_store_(password_store) {
     32   }
     33   ~MigrateHelper();
     34 
     35   void Init();
     36 
     37   // WebDataServiceConsumer:
     38   virtual void OnWebDataServiceRequestDone(
     39       WebDataService::Handle handle,
     40       const WDTypedResult *result) OVERRIDE;
     41 
     42  private:
     43   typedef std::set<WebDataService::Handle> Handles;
     44 
     45   Profile* profile_;
     46 
     47   scoped_refptr<WebDataService> web_data_service_;
     48 
     49   // This creates a cycle between us and PasswordStore. The cycle is broken
     50   // from PasswordStoreDefault::Shutdown, which deletes us.
     51   scoped_refptr<PasswordStore> password_store_;
     52 
     53   // Set of handles from requesting data from the WebDB.
     54   Handles handles_;
     55 
     56   DISALLOW_COPY_AND_ASSIGN(MigrateHelper);
     57 };
     58 
     59 PasswordStoreDefault::MigrateHelper::~MigrateHelper() {
     60   for (Handles::const_iterator i = handles_.begin(); i != handles_.end(); ++i)
     61     web_data_service_->CancelRequest(*i);
     62   handles_.clear();
     63 }
     64 
     65 void PasswordStoreDefault::MigrateHelper::Init() {
     66   handles_.insert(web_data_service_->GetAutofillableLogins(this));
     67   handles_.insert(web_data_service_->GetBlacklistLogins(this));
     68 }
     69 
     70 void PasswordStoreDefault::MigrateHelper::OnWebDataServiceRequestDone(
     71     WebDataService::Handle handle,
     72     const WDTypedResult* result) {
     73   typedef std::vector<const PasswordForm*> PasswordForms;
     74 
     75   DCHECK(handles_.end() != handles_.find(handle));
     76   DCHECK(password_store_);
     77 
     78   handles_.erase(handle);
     79   if (!result)
     80     return;
     81 
     82   if (PASSWORD_RESULT != result->GetType()) {
     83     NOTREACHED();
     84     return;
     85   }
     86 
     87   const PasswordForms& forms =
     88       static_cast<const WDResult<PasswordForms>*>(result)->GetValue();
     89   for (PasswordForms::const_iterator it = forms.begin();
     90        it != forms.end(); ++it) {
     91     password_store_->AddLogin(**it);
     92     web_data_service_->RemoveLogin(**it);
     93     delete *it;
     94   }
     95   if (handles_.empty()) {
     96     profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated,
     97                                               true);
     98   }
     99 }
    100 
    101 PasswordStoreDefault::PasswordStoreDefault(LoginDatabase* login_db,
    102                                            Profile* profile,
    103                                            WebDataService* web_data_service)
    104     : web_data_service_(web_data_service),
    105       login_db_(login_db), profile_(profile) {
    106   DCHECK(login_db);
    107   DCHECK(profile);
    108   DCHECK(web_data_service);
    109   MigrateIfNecessary();
    110 }
    111 
    112 PasswordStoreDefault::~PasswordStoreDefault() {
    113   // MigrateHelper should always be NULL as Shutdown should be invoked before
    114   // the destructor.
    115   DCHECK(!migrate_helper_.get());
    116 }
    117 
    118 void PasswordStoreDefault::Shutdown() {
    119   migrate_helper_.reset();
    120 }
    121 
    122 void PasswordStoreDefault::ReportMetricsImpl() {
    123   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
    124   login_db_->ReportMetrics();
    125 }
    126 
    127 void PasswordStoreDefault::AddLoginImpl(const PasswordForm& form) {
    128   if (login_db_->AddLogin(form)) {
    129     PasswordStoreChangeList changes;
    130     changes.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
    131     NotificationService::current()->Notify(
    132         NotificationType::LOGINS_CHANGED,
    133         Source<PasswordStore>(this),
    134         Details<PasswordStoreChangeList>(&changes));
    135   }
    136 }
    137 
    138 void PasswordStoreDefault::UpdateLoginImpl(const PasswordForm& form) {
    139   if (login_db_->UpdateLogin(form, NULL)) {
    140     PasswordStoreChangeList changes;
    141     changes.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form));
    142     NotificationService::current()->Notify(
    143         NotificationType::LOGINS_CHANGED,
    144         Source<PasswordStore>(this),
    145         Details<PasswordStoreChangeList>(&changes));
    146   }
    147 }
    148 
    149 void PasswordStoreDefault::RemoveLoginImpl(const PasswordForm& form) {
    150   if (login_db_->RemoveLogin(form)) {
    151     PasswordStoreChangeList changes;
    152     changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form));
    153     NotificationService::current()->Notify(
    154         NotificationType::LOGINS_CHANGED,
    155         Source<PasswordStore>(this),
    156         Details<PasswordStoreChangeList>(&changes));
    157   }
    158 }
    159 
    160 void PasswordStoreDefault::RemoveLoginsCreatedBetweenImpl(
    161     const base::Time& delete_begin, const base::Time& delete_end) {
    162   std::vector<PasswordForm*> forms;
    163   if (login_db_->GetLoginsCreatedBetween(delete_begin, delete_end, &forms)) {
    164     if (login_db_->RemoveLoginsCreatedBetween(delete_begin, delete_end)) {
    165       PasswordStoreChangeList changes;
    166       for (std::vector<PasswordForm*>::const_iterator it = forms.begin();
    167            it != forms.end(); ++it) {
    168         changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE,
    169                                               **it));
    170       }
    171       NotificationService::current()->Notify(
    172           NotificationType::LOGINS_CHANGED,
    173           Source<PasswordStore>(this),
    174           Details<PasswordStoreChangeList>(&changes));
    175     }
    176   }
    177   STLDeleteElements(&forms);
    178 }
    179 
    180 void PasswordStoreDefault::GetLoginsImpl(
    181     GetLoginsRequest* request, const webkit_glue::PasswordForm& form) {
    182   login_db_->GetLogins(form, &request->value);
    183   ForwardLoginsResult(request);
    184 }
    185 
    186 void PasswordStoreDefault::GetAutofillableLoginsImpl(
    187     GetLoginsRequest* request) {
    188   FillAutofillableLogins(&request->value);
    189   ForwardLoginsResult(request);
    190 }
    191 
    192 void PasswordStoreDefault::GetBlacklistLoginsImpl(
    193     GetLoginsRequest* request) {
    194   FillBlacklistLogins(&request->value);
    195   ForwardLoginsResult(request);
    196 }
    197 
    198 bool PasswordStoreDefault::FillAutofillableLogins(
    199          std::vector<PasswordForm*>* forms) {
    200   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
    201   return login_db_->GetAutofillableLogins(forms);
    202 }
    203 
    204 bool PasswordStoreDefault::FillBlacklistLogins(
    205          std::vector<PasswordForm*>* forms) {
    206   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
    207   return login_db_->GetBlacklistLogins(forms);
    208 }
    209 
    210 void PasswordStoreDefault::MigrateIfNecessary() {
    211   PrefService* prefs = profile_->GetPrefs();
    212   if (prefs->FindPreference(prefs::kLoginDatabaseMigrated))
    213     return;
    214   DCHECK(!migrate_helper_.get());
    215   migrate_helper_.reset(new MigrateHelper(profile_, web_data_service_, this));
    216   migrate_helper_->Init();
    217 }
    218