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

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

Issue 2407001: Linux: bring GNOME Keyring and KWallet integration back into a compilable state. (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
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/password_manager/password_store_gnome.h" 5 #include "chrome/browser/password_manager/password_store_gnome.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
11 #include "base/task.h" 11 #include "base/task.h"
12 #include "base/time.h" 12 #include "base/time.h"
13 #include "base/utf_string_conversions.h"
13 14
14 using std::map; 15 using std::map;
15 using std::string; 16 using std::string;
16 using std::vector; 17 using std::vector;
18 using webkit_glue::PasswordForm;
19
20 #define GNOME_KEYRING_APPLICATION_CHROME "chrome"
17 21
18 // Schema is analagous to the fields in PasswordForm. 22 // Schema is analagous to the fields in PasswordForm.
19 const GnomeKeyringPasswordSchema PasswordStoreGnome::kGnomeSchema = { 23 const GnomeKeyringPasswordSchema PasswordStoreGnome::kGnomeSchema = {
20 GNOME_KEYRING_ITEM_GENERIC_SECRET, { 24 GNOME_KEYRING_ITEM_GENERIC_SECRET, {
21 { "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, 25 { "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
22 { "action_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, 26 { "action_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
23 { "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, 27 { "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
24 { "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, 28 { "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
25 { "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, 29 { "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
26 { "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, 30 { "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
27 { "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, 31 { "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
28 { "ssl_valid", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, 32 { "ssl_valid", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
29 { "preferred", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, 33 { "preferred", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
30 { "date_created", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, 34 { "date_created", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
31 { "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, 35 { "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
32 { "scheme", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, 36 { "scheme", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 },
37 // This field is always "chrome" so that we can search for it.
38 { "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
33 { NULL } 39 { NULL }
34 } 40 }
35 }; 41 };
36 42
37 PasswordStoreGnome::PasswordStoreGnome() { 43 PasswordStoreGnome::PasswordStoreGnome(LoginDatabase* login_db,
44 Profile* profile,
45 WebDataService* web_data_service) {
38 } 46 }
39 47
40 PasswordStoreGnome::~PasswordStoreGnome() { 48 PasswordStoreGnome::~PasswordStoreGnome() {
41 } 49 }
42 50
43 bool PasswordStoreGnome::Init() { 51 bool PasswordStoreGnome::Init() {
44 return PasswordStore::Init() && gnome_keyring_is_available(); 52 return PasswordStore::Init() && gnome_keyring_is_available();
45 } 53 }
46 54
47 void PasswordStoreGnome::AddLoginImpl(const PasswordForm& form) { 55 void PasswordStoreGnome::AddLoginImpl(const PasswordForm& form) {
48 AutoLock l(gnome_keyring_lock_); 56 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
49 GnomeKeyringResult result = gnome_keyring_store_password_sync( 57 AddLoginHelper(form, base::Time::Now());
50 &kGnomeSchema,
51 NULL, // Default keyring.
52 // TODO(johnmaguire@google.com): Localise this.
53 "Form password stored by Chrome",
54 WideToASCII(form.password_value).c_str(),
55 "origin_url", form.origin.spec().c_str(),
56 "action_url", form.action.spec().c_str(),
57 "username_element", form.username_element.c_str(),
58 "username_value", form.username_value.c_str(),
59 "password_element", form.password_element.c_str(),
60 "submit_element", form.submit_element.c_str(),
61 "signon_realm", form.signon_realm.c_str(),
62 "ssl_valid", form.ssl_valid,
63 "preferred", form.preferred,
64 "date_created", Int64ToString(base::Time::Now().ToTimeT()).c_str(),
65 "blacklisted_by_user", form.blacklisted_by_user,
66 "scheme", form.scheme,
67 NULL);
68
69 if (result != GNOME_KEYRING_RESULT_OK) {
70 LOG(ERROR) << "Keyring save failed: "
71 << gnome_keyring_result_to_message(result);
72 }
73 } 58 }
74 59
75 void PasswordStoreGnome::UpdateLoginImpl(const PasswordForm& form) { 60 void PasswordStoreGnome::UpdateLoginImpl(const PasswordForm& form) {
76 AddLoginImpl(form); // Add & Update are the same in gnome keyring. 61 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by
62 // origin_url, username_element, username_value, password_element, and
63 // signon_realm. We then compare the result to the updated form. If they
64 // differ in any of the action, password_value, ssl_valid, or preferred
65 // fields, then we add a new login with those fields updated and only delete
66 // the original on success.
67 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
68 GList* found = NULL;
69 // Search gnome keyring for matching passwords.
70 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync(
71 GNOME_KEYRING_ITEM_GENERIC_SECRET,
72 &found,
73 "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
74 form.origin.spec().c_str(),
75 "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
76 UTF16ToUTF8(form.username_element).c_str(),
77 "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
78 UTF16ToUTF8(form.username_value).c_str(),
79 "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
80 UTF16ToUTF8(form.password_element).c_str(),
81 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
82 form.signon_realm.c_str(),
83 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
84 GNOME_KEYRING_APPLICATION_CHROME,
85 NULL);
86 vector<PasswordForm*> forms;
87 if (result == GNOME_KEYRING_RESULT_OK) {
88 FillFormVector(found, &forms);
89 for (size_t i = 0; i < forms.size(); ++i) {
90 if (forms[i]->action != form.action ||
91 forms[i]->password_value != form.password_value ||
92 forms[i]->ssl_valid != form.ssl_valid ||
93 forms[i]->preferred != form.preferred) {
94 PasswordForm updated = *forms[i];
95 updated.action = form.action;
96 updated.password_value = form.password_value;
97 updated.ssl_valid = form.ssl_valid;
98 updated.preferred = form.preferred;
99 if (AddLoginHelper(updated, updated.date_created))
100 RemoveLoginImpl(*forms[i]);
101 }
102 delete forms[i];
103 }
104 } else {
105 LOG(ERROR) << "Keyring find failed: "
106 << gnome_keyring_result_to_message(result);
107 }
77 } 108 }
78 109
79 void PasswordStoreGnome::RemoveLoginImpl(const PasswordForm& form) { 110 void PasswordStoreGnome::RemoveLoginImpl(const PasswordForm& form) {
80 AutoLock l(gnome_keyring_lock_); 111 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
112 // We find forms using the same fields as LoginDatabase::RemoveLogin().
81 GnomeKeyringResult result = gnome_keyring_delete_password_sync( 113 GnomeKeyringResult result = gnome_keyring_delete_password_sync(
82 &kGnomeSchema, 114 &kGnomeSchema,
83 "origin_url", form.origin.spec().c_str(), 115 "origin_url", form.origin.spec().c_str(),
84 "action_url", form.action.spec().c_str(), 116 "action_url", form.action.spec().c_str(),
85 "username_element", form.username_element.c_str(), 117 "username_element", UTF16ToUTF8(form.username_element).c_str(),
86 "username_value", form.username_value.c_str(), 118 "username_value", UTF16ToUTF8(form.username_value).c_str(),
87 "password_element", form.password_element.c_str(), 119 "password_element", UTF16ToUTF8(form.password_element).c_str(),
88 "submit_element", form.submit_element.c_str(), 120 "submit_element", UTF16ToUTF8(form.submit_element).c_str(),
121 "signon_realm", form.signon_realm.c_str(),
122 NULL);
123 if (result != GNOME_KEYRING_RESULT_OK) {
124 LOG(ERROR) << "Keyring delete failed: "
125 << gnome_keyring_result_to_message(result);
126 }
127 }
128
129 void PasswordStoreGnome::RemoveLoginsCreatedBetweenImpl(
130 const base::Time& delete_begin,
131 const base::Time& delete_end) {
132 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
133 GList* found = NULL;
134 // Search GNOME keyring for all passwords, then delete the ones in the range.
135 // We need to search for something, otherwise we get no results - so we search
136 // for the fixed application string.
137 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync(
138 GNOME_KEYRING_ITEM_GENERIC_SECRET,
139 &found,
140 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
141 GNOME_KEYRING_APPLICATION_CHROME,
142 NULL);
143 if (result == GNOME_KEYRING_RESULT_OK) {
144 // We could walk the list and delete items as we find them, but it is much
145 // easier to build the vector and use RemoveLoginImpl() to delete them.
146 vector<PasswordForm*> forms;
147 FillFormVector(found, &forms);
148 for (size_t i = 0; i < forms.size(); ++i) {
149 if (delete_begin <= forms[i]->date_created &&
150 (delete_end.is_null() || forms[i]->date_created < delete_end)) {
151 RemoveLoginImpl(*forms[i]);
152 }
153 delete forms[i];
154 }
155 } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) {
156 LOG(ERROR) << "Keyring find failed: "
157 << gnome_keyring_result_to_message(result);
158 }
159 }
160
161 void PasswordStoreGnome::GetLoginsImpl(GetLoginsRequest* request,
162 const PasswordForm& form) {
163 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
164 GList* found = NULL;
165 // Search gnome keyring for matching passwords.
166 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync(
167 GNOME_KEYRING_ITEM_GENERIC_SECRET,
168 &found,
169 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
170 form.signon_realm.c_str(),
171 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
172 GNOME_KEYRING_APPLICATION_CHROME,
173 NULL);
174 vector<PasswordForm*> forms;
175 if (result == GNOME_KEYRING_RESULT_OK) {
176 FillFormVector(found, &forms);
177 } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) {
178 LOG(ERROR) << "Keyring find failed: "
179 << gnome_keyring_result_to_message(result);
180 }
181 NotifyConsumer(request, forms);
182 }
183
184 void PasswordStoreGnome::GetAutofillableLoginsImpl(
185 GetLoginsRequest* request) {
186 std::vector<PasswordForm*> forms;
187 FillAutofillableLogins(&forms);
188 NotifyConsumer(request, forms);
189 }
190
191 void PasswordStoreGnome::GetBlacklistLoginsImpl(
192 GetLoginsRequest* request) {
193 std::vector<PasswordForm*> forms;
194 FillBlacklistLogins(&forms);
195 NotifyConsumer(request, forms);
196 }
197
198 bool PasswordStoreGnome::FillAutofillableLogins(
199 std::vector<PasswordForm*>* forms) {
200 return FillSomeLogins(true, forms);
201 }
202
203 bool PasswordStoreGnome::FillBlacklistLogins(
204 std::vector<PasswordForm*>* forms) {
205 return FillSomeLogins(false, forms);
206 }
207
208 bool PasswordStoreGnome::AddLoginHelper(const PasswordForm& form,
209 const base::Time& date_created) {
210 GnomeKeyringResult result = gnome_keyring_store_password_sync(
211 &kGnomeSchema,
212 NULL, // Default keyring.
213 form.origin.spec().c_str(), // Display name.
214 UTF16ToUTF8(form.password_value).c_str(),
215 "origin_url", form.origin.spec().c_str(),
216 "action_url", form.action.spec().c_str(),
217 "username_element", UTF16ToUTF8(form.username_element).c_str(),
218 "username_value", UTF16ToUTF8(form.username_value).c_str(),
219 "password_element", UTF16ToUTF8(form.password_element).c_str(),
220 "submit_element", UTF16ToUTF8(form.submit_element).c_str(),
89 "signon_realm", form.signon_realm.c_str(), 221 "signon_realm", form.signon_realm.c_str(),
90 "ssl_valid", form.ssl_valid, 222 "ssl_valid", form.ssl_valid,
91 "preferred", form.preferred, 223 "preferred", form.preferred,
92 "date_created", Int64ToString(form.date_created.ToTimeT()).c_str(), 224 "date_created", Int64ToString(date_created.ToTimeT()).c_str(),
93 "blacklisted_by_user", form.blacklisted_by_user, 225 "blacklisted_by_user", form.blacklisted_by_user,
94 "scheme", form.scheme, 226 "scheme", form.scheme,
95 NULL); 227 "application", GNOME_KEYRING_APPLICATION_CHROME,
228 NULL);
229
96 if (result != GNOME_KEYRING_RESULT_OK) { 230 if (result != GNOME_KEYRING_RESULT_OK) {
97 LOG(ERROR) << "Keyring delete failed: " 231 LOG(ERROR) << "Keyring save failed: "
98 << gnome_keyring_result_to_message(result); 232 << gnome_keyring_result_to_message(result);
99 } 233 return false;
100 } 234 }
101 235 return true;
102 void PasswordStoreGnome::GetLoginsImpl(GetLoginsRequest* request) { 236 }
103 AutoLock l(gnome_keyring_lock_); 237
104 GList* found = NULL; 238 bool PasswordStoreGnome::FillSomeLogins(
239 bool autofillable,
240 std::vector<PasswordForm*>* forms) {
241 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
242 GList* found = NULL;
243 uint32_t blacklisted_by_user = !autofillable;
105 // Search gnome keyring for matching passwords. 244 // Search gnome keyring for matching passwords.
106 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( 245 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync(
107 GNOME_KEYRING_ITEM_GENERIC_SECRET, 246 GNOME_KEYRING_ITEM_GENERIC_SECRET,
108 &found, 247 &found,
109 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, 248 "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32,
110 request->form.signon_realm.c_str(), 249 blacklisted_by_user,
111 NULL); 250 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
112 vector<PasswordForm*> forms; 251 GNOME_KEYRING_APPLICATION_CHROME,
113 if (result == GNOME_KEYRING_RESULT_NO_MATCH) { 252 NULL);
114 NotifyConsumer(request, forms); 253 if (result == GNOME_KEYRING_RESULT_OK) {
115 return; 254 FillFormVector(found, forms);
116 } else if (result != GNOME_KEYRING_RESULT_OK) { 255 } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) {
117 LOG(ERROR) << "Keyring find failed: " 256 LOG(ERROR) << "Keyring find failed: "
118 << gnome_keyring_result_to_message(result); 257 << gnome_keyring_result_to_message(result);
119 NotifyConsumer(request, forms); 258 return false;
120 return; 259 }
121 } 260 return true;
122 261 }
123 // Parse all the results from the returned GList into a 262
124 // vector<PasswordForm*>. PasswordForms are allocated on the heap. These 263 void PasswordStoreGnome::FillFormVector(GList* found,
125 // will be deleted by the consumer. 264 std::vector<PasswordForm*>* forms) {
126 GList* element = g_list_first(found); 265 GList* element = g_list_first(found);
127 while (element != NULL) { 266 while (element != NULL) {
128 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); 267 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data);
129 char* password = data->secret; 268 char* password = data->secret;
130 269
131 GnomeKeyringAttributeList* attributes = data->attributes; 270 GnomeKeyringAttributeList* attributes = data->attributes;
132 // Read the string & int attributes into the appropriate map. 271 // Read the string and int attributes into the appropriate map.
133 map<string, string> string_attribute_map; 272 map<string, string> string_attribute_map;
134 map<string, uint32> uint_attribute_map; 273 map<string, uint32> uint_attribute_map;
135 for (unsigned int i = 0; i < attributes->len; ++i) { 274 for (unsigned int i = 0; i < attributes->len; ++i) {
136 GnomeKeyringAttribute attribute = 275 GnomeKeyringAttribute attribute =
137 gnome_keyring_attribute_list_index(attributes, i); 276 gnome_keyring_attribute_list_index(attributes, i);
138 if (attribute.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { 277 if (attribute.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) {
139 string_attribute_map[string(attribute.name)] = 278 string_attribute_map[string(attribute.name)] =
140 string(attribute.value.string); 279 string(attribute.value.string);
141 } else if (attribute.type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) { 280 } else if (attribute.type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) {
142 uint_attribute_map[string(attribute.name)] = attribute.value.integer; 281 uint_attribute_map[string(attribute.name)] = attribute.value.integer;
143 } 282 }
144 } 283 }
145 284
146 PasswordForm* form = new PasswordForm(); 285 PasswordForm* form = new PasswordForm();
147 form->origin = GURL(string_attribute_map["origin_url"]); 286 form->origin = GURL(string_attribute_map["origin_url"]);
148 form->action = GURL(string_attribute_map["action_url"]); 287 form->action = GURL(string_attribute_map["action_url"]);
149 form->username_element = 288 form->username_element =
150 ASCIIToWide(string(string_attribute_map["username_element"])); 289 UTF8ToUTF16(string(string_attribute_map["username_element"]));
151 form->username_value = 290 form->username_value =
152 ASCIIToWide(string(string_attribute_map["username_value"])); 291 UTF8ToUTF16(string(string_attribute_map["username_value"]));
153 form->password_element = 292 form->password_element =
154 ASCIIToWide(string(string_attribute_map["password_element"])); 293 UTF8ToUTF16(string(string_attribute_map["password_element"]));
155 form->password_value = ASCIIToWide(string(password)); 294 form->password_value = UTF8ToUTF16(string(password));
156 form->submit_element = 295 form->submit_element =
157 ASCIIToWide(string(string_attribute_map["submit_element"])); 296 UTF8ToUTF16(string(string_attribute_map["submit_element"]));
158 form->signon_realm = uint_attribute_map["signon_realm"]; 297 form->signon_realm = string_attribute_map["signon_realm"];
159 form->ssl_valid = uint_attribute_map["ssl_valid"]; 298 form->ssl_valid = uint_attribute_map["ssl_valid"];
160 form->preferred = uint_attribute_map["preferred"]; 299 form->preferred = uint_attribute_map["preferred"];
161 string date = string_attribute_map["date_created"]; 300 string date = string_attribute_map["date_created"];
162 int64 date_created = 0; 301 int64 date_created = 0;
163 DCHECK(StringToInt64(date, &date_created) && date_created != 0); 302 bool date_ok = StringToInt64(date, &date_created);
303 DCHECK(date_ok);
304 DCHECK(date_created != 0);
164 form->date_created = base::Time::FromTimeT(date_created); 305 form->date_created = base::Time::FromTimeT(date_created);
165 form->blacklisted_by_user = uint_attribute_map["blacklisted_by_user"]; 306 form->blacklisted_by_user = uint_attribute_map["blacklisted_by_user"];
166 form->scheme = 307 form->scheme = static_cast<PasswordForm::Scheme>(
167 static_cast<PasswordForm::Scheme>(uint_attribute_map["scheme"]); 308 uint_attribute_map["scheme"]);
168 309
169 forms.push_back(form); 310 forms->push_back(form);
170 311
171 element = g_list_next(element); 312 element = g_list_next(element);
172 } 313 }
173 gnome_keyring_found_list_free(found); 314 gnome_keyring_found_list_free(found);
174 found = NULL;
175
176 NotifyConsumer(request, forms);
177 } 315 }
OLDNEW
« no previous file with comments | « chrome/browser/password_manager/password_store_gnome.h ('k') | chrome/browser/password_manager/password_store_kwallet.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698