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:
MigrateHelper(Profile * profile,WebDataService * web_data_service,PasswordStore * password_store)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
~MigrateHelper()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
Init()65 void PasswordStoreDefault::MigrateHelper::Init() {
66 handles_.insert(web_data_service_->GetAutofillableLogins(this));
67 handles_.insert(web_data_service_->GetBlacklistLogins(this));
68 }
69
OnWebDataServiceRequestDone(WebDataService::Handle handle,const WDTypedResult * result)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
PasswordStoreDefault(LoginDatabase * login_db,Profile * profile,WebDataService * web_data_service)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
~PasswordStoreDefault()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
Shutdown()118 void PasswordStoreDefault::Shutdown() {
119 migrate_helper_.reset();
120 }
121
ReportMetricsImpl()122 void PasswordStoreDefault::ReportMetricsImpl() {
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
124 login_db_->ReportMetrics();
125 }
126
AddLoginImpl(const PasswordForm & form)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
UpdateLoginImpl(const PasswordForm & form)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
RemoveLoginImpl(const PasswordForm & form)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
RemoveLoginsCreatedBetweenImpl(const base::Time & delete_begin,const base::Time & delete_end)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
GetLoginsImpl(GetLoginsRequest * request,const webkit_glue::PasswordForm & form)180 void PasswordStoreDefault::GetLoginsImpl(
181 GetLoginsRequest* request, const webkit_glue::PasswordForm& form) {
182 login_db_->GetLogins(form, &request->value);
183 ForwardLoginsResult(request);
184 }
185
GetAutofillableLoginsImpl(GetLoginsRequest * request)186 void PasswordStoreDefault::GetAutofillableLoginsImpl(
187 GetLoginsRequest* request) {
188 FillAutofillableLogins(&request->value);
189 ForwardLoginsResult(request);
190 }
191
GetBlacklistLoginsImpl(GetLoginsRequest * request)192 void PasswordStoreDefault::GetBlacklistLoginsImpl(
193 GetLoginsRequest* request) {
194 FillBlacklistLogins(&request->value);
195 ForwardLoginsResult(request);
196 }
197
FillAutofillableLogins(std::vector<PasswordForm * > * forms)198 bool PasswordStoreDefault::FillAutofillableLogins(
199 std::vector<PasswordForm*>* forms) {
200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
201 return login_db_->GetAutofillableLogins(forms);
202 }
203
FillBlacklistLogins(std::vector<PasswordForm * > * forms)204 bool PasswordStoreDefault::FillBlacklistLogins(
205 std::vector<PasswordForm*>* forms) {
206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
207 return login_db_->GetBlacklistLogins(forms);
208 }
209
MigrateIfNecessary()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