Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: chrome/browser/password_manager/password_store_x.cc

Issue 2806002: Linux: refactor GNOME Keyring and KWallet integration to allow migration. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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_x.h"
6
7 #include <map>
8 #include <vector>
9
10 #include "base/logging.h"
11 #include "base/stl_util-inl.h"
12 #include "chrome/browser/chrome_thread.h"
13 #include "chrome/browser/password_manager/password_store_change.h"
14 #include "chrome/common/notification_service.h"
15
16 using std::vector;
17 using webkit_glue::PasswordForm;
18
19 PasswordStoreX::PasswordStoreX(LoginDatabase* login_db,
20 Profile* profile,
21 WebDataService* web_data_service,
22 NativeBackend* backend)
23 : PasswordStoreDefault(login_db, profile, web_data_service),
24 backend_(backend), migration_checked_(!backend), allow_fallback_(false) {
25 }
26
27 PasswordStoreX::~PasswordStoreX() {
28 }
29
30 void PasswordStoreX::AddLoginImpl(const PasswordForm& form) {
31 CheckMigration();
32 if (use_native_backend() && backend_->AddLogin(form)) {
33 PasswordStoreChangeList changes;
34 changes.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
35 NotificationService::current()->Notify(
36 NotificationType::LOGINS_CHANGED,
37 NotificationService::AllSources(),
38 Details<PasswordStoreChangeList>(&changes));
39 allow_fallback_ = false;
40 } else if (allow_default_store()) {
41 PasswordStoreDefault::AddLoginImpl(form);
42 }
43 }
44
45 void PasswordStoreX::UpdateLoginImpl(const PasswordForm& form) {
46 CheckMigration();
47 if (use_native_backend() && backend_->UpdateLogin(form)) {
48 PasswordStoreChangeList changes;
49 changes.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form));
50 NotificationService::current()->Notify(
51 NotificationType::LOGINS_CHANGED,
52 NotificationService::AllSources(),
53 Details<PasswordStoreChangeList>(&changes));
54 allow_fallback_ = false;
55 } else if (allow_default_store()) {
56 PasswordStoreDefault::UpdateLoginImpl(form);
57 }
58 }
59
60 void PasswordStoreX::RemoveLoginImpl(const PasswordForm& form) {
61 CheckMigration();
62 if (use_native_backend() && backend_->RemoveLogin(form)) {
63 PasswordStoreChangeList changes;
64 changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form));
65 NotificationService::current()->Notify(
66 NotificationType::LOGINS_CHANGED,
67 NotificationService::AllSources(),
68 Details<PasswordStoreChangeList>(&changes));
69 allow_fallback_ = false;
70 } else if (allow_default_store()) {
71 PasswordStoreDefault::RemoveLoginImpl(form);
72 }
73 }
74
75 void PasswordStoreX::RemoveLoginsCreatedBetweenImpl(
76 const base::Time& delete_begin,
77 const base::Time& delete_end) {
78 CheckMigration();
79 vector<PasswordForm*> forms;
80 if (use_native_backend() &&
81 backend_->GetLoginsCreatedBetween(delete_begin, delete_end, &forms) &&
82 backend_->RemoveLoginsCreatedBetween(delete_begin, delete_end)) {
83 PasswordStoreChangeList changes;
84 for (vector<PasswordForm*>::const_iterator it = forms.begin();
85 it != forms.end(); ++it) {
86 changes.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE,
87 **it));
88 }
89 NotificationService::current()->Notify(
90 NotificationType::LOGINS_CHANGED,
91 NotificationService::AllSources(),
92 Details<PasswordStoreChangeList>(&changes));
93 allow_fallback_ = false;
94 } else if (allow_default_store()) {
95 PasswordStoreDefault::RemoveLoginsCreatedBetweenImpl(delete_begin,
96 delete_end);
97 }
98 STLDeleteElements(&forms);
99 }
100
101 void PasswordStoreX::GetLoginsImpl(GetLoginsRequest* request,
102 const PasswordForm& form) {
103 CheckMigration();
104 vector<PasswordForm*> forms;
105 if (use_native_backend() && backend_->GetLogins(form, &forms)) {
106 NotifyConsumer(request, forms);
107 allow_fallback_ = false;
108 } else if (allow_default_store()) {
109 PasswordStoreDefault::GetLoginsImpl(request, form);
110 } else {
111 // The consumer will be left hanging unless we reply.
112 NotifyConsumer(request, forms);
113 }
114 }
115
116 void PasswordStoreX::GetAutofillableLoginsImpl(GetLoginsRequest* request) {
117 CheckMigration();
118 vector<PasswordForm*> forms;
119 if (use_native_backend() && backend_->GetAutofillableLogins(&forms)) {
120 NotifyConsumer(request, forms);
121 allow_fallback_ = false;
122 } else if (allow_default_store()) {
123 PasswordStoreDefault::GetAutofillableLoginsImpl(request);
124 } else {
125 // The consumer will be left hanging unless we reply.
126 NotifyConsumer(request, forms);
127 }
128 }
129
130 void PasswordStoreX::GetBlacklistLoginsImpl(GetLoginsRequest* request) {
131 CheckMigration();
132 vector<PasswordForm*> forms;
133 if (use_native_backend() && backend_->GetBlacklistLogins(&forms)) {
134 NotifyConsumer(request, forms);
135 allow_fallback_ = false;
136 } else if (allow_default_store()) {
137 PasswordStoreDefault::GetBlacklistLoginsImpl(request);
138 } else {
139 // The consumer will be left hanging unless we reply.
140 NotifyConsumer(request, forms);
141 }
142 }
143
144 bool PasswordStoreX::FillAutofillableLogins(vector<PasswordForm*>* forms) {
145 CheckMigration();
146 if (use_native_backend() && backend_->GetAutofillableLogins(forms)) {
147 allow_fallback_ = false;
148 return true;
149 }
150 if (allow_default_store())
151 return PasswordStoreDefault::FillAutofillableLogins(forms);
152 return false;
153 }
154
155 bool PasswordStoreX::FillBlacklistLogins(vector<PasswordForm*>* forms) {
156 CheckMigration();
157 if (use_native_backend() && backend_->GetBlacklistLogins(forms)) {
158 allow_fallback_ = false;
159 return true;
160 }
161 if (allow_default_store())
162 return PasswordStoreDefault::FillBlacklistLogins(forms);
163 return false;
164 }
165
166 void PasswordStoreX::CheckMigration() {
167 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
168 if (migration_checked_ || !backend_.get())
169 return;
170 migration_checked_ = true;
171 ssize_t migrated = MigrateLogins();
172 if (migrated > 0) {
173 LOG(INFO) << "Migrated " << migrated << " passwords to native store.";
174 } else if (migrated == 0) {
175 // As long as we are able to migrate some passwords, we know the native
176 // store is working. But if there is nothing to migrate, the "migration"
177 // can succeed even when the native store would fail. In this case we
178 // allow a later fallback to the default store. Once any later operation
179 // succeeds on the native store, we will no longer allow it.
180 allow_fallback_ = true;
181 } else {
182 LOG(WARNING) << "Native password store migration failed! " <<
183 "Falling back on default (unencrypted) store.";
184 backend_.reset(NULL);
185 }
186 }
187
188 bool PasswordStoreX::allow_default_store() {
189 if (allow_fallback_) {
190 LOG(WARNING) << "Native password store failed! " <<
191 "Falling back on default (unencrypted) store.";
192 backend_.reset(NULL);
193 // Don't warn again. We'll use the default store because backend_ is NULL.
194 allow_fallback_ = false;
195 }
196 return !backend_.get();
197 }
198
199 ssize_t PasswordStoreX::MigrateLogins() {
200 DCHECK(backend_.get());
201 vector<PasswordForm*> forms;
202 bool ok = PasswordStoreDefault::FillAutofillableLogins(&forms) &&
203 PasswordStoreDefault::FillBlacklistLogins(&forms);
204 if (ok) {
205 // We add all the passwords (and blacklist entries) to the native backend
206 // before attempting to remove any from the login database, to make sure we
207 // don't somehow end up with some of the passwords in one store and some in
208 // another. We'll always have at least one intact store this way.
209 for (size_t i = 0; i < forms.size(); ++i) {
210 if (!backend_->AddLogin(*forms[i])) {
211 ok = false;
212 break;
213 }
214 }
215 if (ok) {
216 for (size_t i = 0; i < forms.size(); ++i) {
217 // If even one of these calls to RemoveLoginImpl() succeeds, then we
218 // should prefer the native backend to the now-incomplete login
219 // database. Thus we want to return a success status even in the case
220 // where some fail. The only real problem with this is that we might
221 // leave passwords in the login database and never come back to clean
222 // them out if any of these calls do fail.
223 // TODO(mdm): Really we should just delete the login database file.
224 PasswordStoreDefault::RemoveLoginImpl(*forms[i]);
225 }
226 }
227 }
228 ssize_t result = ok ? forms.size() : -1;
229 STLDeleteElements(&forms);
230 return result;
231 }
OLDNEW
« no previous file with comments | « chrome/browser/password_manager/password_store_x.h ('k') | chrome/browser/password_manager/password_store_x_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698