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 20using 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. 24class 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 59PasswordStoreDefault::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 65void PasswordStoreDefault::MigrateHelper::Init() { 66 handles_.insert(web_data_service_->GetAutofillableLogins(this)); 67 handles_.insert(web_data_service_->GetBlacklistLogins(this)); 68} 69 70void 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 101PasswordStoreDefault::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 112PasswordStoreDefault::~PasswordStoreDefault() { 113 // MigrateHelper should always be NULL as Shutdown should be invoked before 114 // the destructor. 115 DCHECK(!migrate_helper_.get()); 116} 117 118void PasswordStoreDefault::Shutdown() { 119 migrate_helper_.reset(); 120} 121 122void PasswordStoreDefault::ReportMetricsImpl() { 123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 124 login_db_->ReportMetrics(); 125} 126 127void 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 138void 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 149void 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 160void 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 180void PasswordStoreDefault::GetLoginsImpl( 181 GetLoginsRequest* request, const webkit_glue::PasswordForm& form) { 182 login_db_->GetLogins(form, &request->value); 183 ForwardLoginsResult(request); 184} 185 186void PasswordStoreDefault::GetAutofillableLoginsImpl( 187 GetLoginsRequest* request) { 188 FillAutofillableLogins(&request->value); 189 ForwardLoginsResult(request); 190} 191 192void PasswordStoreDefault::GetBlacklistLoginsImpl( 193 GetLoginsRequest* request) { 194 FillBlacklistLogins(&request->value); 195 ForwardLoginsResult(request); 196} 197 198bool PasswordStoreDefault::FillAutofillableLogins( 199 std::vector<PasswordForm*>* forms) { 200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 201 return login_db_->GetAutofillableLogins(forms); 202} 203 204bool PasswordStoreDefault::FillBlacklistLogins( 205 std::vector<PasswordForm*>* forms) { 206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 207 return login_db_->GetBlacklistLogins(forms); 208} 209 210void 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