| OLD | NEW |
| 1 // Copyright (c) 2010 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/native_backend_gnome_x.h" |
| 6 | 6 |
| 7 #if defined(DLOPEN_GNOME_KEYRING) | 7 #if defined(DLOPEN_GNOME_KEYRING) |
| 8 #include <dlfcn.h> | 8 #include <dlfcn.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| 11 #include <map> | 11 #include <map> |
| 12 #include <string> | 12 #include <string> |
| 13 | 13 |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 16 #include "base/task.h" | |
| 17 #include "base/time.h" | 16 #include "base/time.h" |
| 18 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
| 18 #include "chrome/browser/chrome_thread.h" |
| 19 | 19 |
| 20 using std::map; | 20 using std::map; |
| 21 using std::string; | 21 using std::string; |
| 22 using std::vector; | |
| 23 using webkit_glue::PasswordForm; | 22 using webkit_glue::PasswordForm; |
| 24 | 23 |
| 25 /* Many of the gnome_keyring_* functions use variable arguments, which makes | 24 /* Many of the gnome_keyring_* functions use variable arguments, which makes |
| 26 * them difficult if not impossible to wrap in C. Therefore, we want the | 25 * them difficult if not impossible to wrap in C. Therefore, we want the |
| 27 * actual uses below to either call the functions directly (if we are linking | 26 * actual uses below to either call the functions directly (if we are linking |
| 28 * against libgnome-keyring), or call them via appropriately-typed function | 27 * against libgnome-keyring), or call them via appropriately-typed function |
| 29 * pointers (if we are dynamically loading libgnome-keyring). | 28 * pointers (if we are dynamically loading libgnome-keyring). |
| 30 * | 29 * |
| 31 * Thus, instead of making a wrapper class with two implementations, we use | 30 * Thus, instead of making a wrapper class with two implementations, we use |
| 32 * the preprocessor to rename the calls below in the dynamic load case, and | 31 * the preprocessor to rename the calls below in the dynamic load case, and |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 return true; | 128 return true; |
| 130 } | 129 } |
| 131 | 130 |
| 132 } // namespace | 131 } // namespace |
| 133 | 132 |
| 134 #endif // DLOPEN_GNOME_KEYRING | 133 #endif // DLOPEN_GNOME_KEYRING |
| 135 | 134 |
| 136 #define GNOME_KEYRING_APPLICATION_CHROME "chrome" | 135 #define GNOME_KEYRING_APPLICATION_CHROME "chrome" |
| 137 | 136 |
| 138 // Schema is analagous to the fields in PasswordForm. | 137 // Schema is analagous to the fields in PasswordForm. |
| 139 const GnomeKeyringPasswordSchema PasswordStoreGnome::kGnomeSchema = { | 138 const GnomeKeyringPasswordSchema NativeBackendGnome::kGnomeSchema = { |
| 140 GNOME_KEYRING_ITEM_GENERIC_SECRET, { | 139 GNOME_KEYRING_ITEM_GENERIC_SECRET, { |
| 141 { "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 140 { "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
| 142 { "action_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 141 { "action_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
| 143 { "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 142 { "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
| 144 { "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 143 { "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
| 145 { "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 144 { "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
| 146 { "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 145 { "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
| 147 { "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 146 { "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
| 148 { "ssl_valid", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, | 147 { "ssl_valid", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, |
| 149 { "preferred", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, | 148 { "preferred", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, |
| 150 { "date_created", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 149 { "date_created", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
| 151 { "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, | 150 { "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, |
| 152 { "scheme", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, | 151 { "scheme", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, |
| 153 // This field is always "chrome" so that we can search for it. | 152 // This field is always "chrome" so that we can search for it. |
| 154 { "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 153 { "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
| 155 { NULL } | 154 { NULL } |
| 156 } | 155 } |
| 157 }; | 156 }; |
| 158 | 157 |
| 159 PasswordStoreGnome::PasswordStoreGnome(LoginDatabase* login_db, | 158 NativeBackendGnome::NativeBackendGnome() { |
| 160 Profile* profile, | |
| 161 WebDataService* web_data_service) { | |
| 162 } | 159 } |
| 163 | 160 |
| 164 PasswordStoreGnome::~PasswordStoreGnome() { | 161 NativeBackendGnome::~NativeBackendGnome() { |
| 165 } | 162 } |
| 166 | 163 |
| 167 bool PasswordStoreGnome::Init() { | 164 bool NativeBackendGnome::Init() { |
| 168 return PasswordStore::Init() && | 165 return LoadGnomeKeyring() && gnome_keyring_is_available(); |
| 169 LoadGnomeKeyring() && | |
| 170 gnome_keyring_is_available(); | |
| 171 } | 166 } |
| 172 | 167 |
| 173 void PasswordStoreGnome::AddLoginImpl(const PasswordForm& form) { | 168 bool NativeBackendGnome::AddLogin(const PasswordForm& form) { |
| 174 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); | 169 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 175 AddLoginHelper(form, base::Time::Now()); | 170 GnomeKeyringResult result = gnome_keyring_store_password_sync( |
| 171 &kGnomeSchema, |
| 172 NULL, // Default keyring. |
| 173 form.origin.spec().c_str(), // Display name. |
| 174 UTF16ToUTF8(form.password_value).c_str(), |
| 175 "origin_url", form.origin.spec().c_str(), |
| 176 "action_url", form.action.spec().c_str(), |
| 177 "username_element", UTF16ToUTF8(form.username_element).c_str(), |
| 178 "username_value", UTF16ToUTF8(form.username_value).c_str(), |
| 179 "password_element", UTF16ToUTF8(form.password_element).c_str(), |
| 180 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), |
| 181 "signon_realm", form.signon_realm.c_str(), |
| 182 "ssl_valid", form.ssl_valid, |
| 183 "preferred", form.preferred, |
| 184 "date_created", Int64ToString(form.date_created.ToTimeT()).c_str(), |
| 185 "blacklisted_by_user", form.blacklisted_by_user, |
| 186 "scheme", form.scheme, |
| 187 "application", GNOME_KEYRING_APPLICATION_CHROME, |
| 188 NULL); |
| 189 |
| 190 if (result != GNOME_KEYRING_RESULT_OK) { |
| 191 LOG(ERROR) << "Keyring save failed: " |
| 192 << gnome_keyring_result_to_message(result); |
| 193 return false; |
| 194 } |
| 195 return true; |
| 176 } | 196 } |
| 177 | 197 |
| 178 void PasswordStoreGnome::UpdateLoginImpl(const PasswordForm& form) { | 198 bool NativeBackendGnome::UpdateLogin(const PasswordForm& form) { |
| 179 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by | 199 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by |
| 180 // origin_url, username_element, username_value, password_element, and | 200 // origin_url, username_element, username_value, password_element, and |
| 181 // signon_realm. We then compare the result to the updated form. If they | 201 // signon_realm. We then compare the result to the updated form. If they |
| 182 // differ in any of the action, password_value, ssl_valid, or preferred | 202 // differ in any of the action, password_value, ssl_valid, or preferred |
| 183 // fields, then we add a new login with those fields updated and only delete | 203 // fields, then we add a new login with those fields updated and only delete |
| 184 // the original on success. | 204 // the original on success. |
| 185 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); | 205 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 186 GList* found = NULL; | 206 GList* found = NULL; |
| 187 // Search gnome keyring for matching passwords. | 207 // Search gnome keyring for matching passwords. |
| 188 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( | 208 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( |
| 189 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 209 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
| 190 &found, | 210 &found, |
| 191 "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 211 "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 192 form.origin.spec().c_str(), | 212 form.origin.spec().c_str(), |
| 193 "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 213 "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 194 UTF16ToUTF8(form.username_element).c_str(), | 214 UTF16ToUTF8(form.username_element).c_str(), |
| 195 "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 215 "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 196 UTF16ToUTF8(form.username_value).c_str(), | 216 UTF16ToUTF8(form.username_value).c_str(), |
| 197 "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 217 "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 198 UTF16ToUTF8(form.password_element).c_str(), | 218 UTF16ToUTF8(form.password_element).c_str(), |
| 199 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 219 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 200 form.signon_realm.c_str(), | 220 form.signon_realm.c_str(), |
| 201 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 221 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 202 GNOME_KEYRING_APPLICATION_CHROME, | 222 GNOME_KEYRING_APPLICATION_CHROME, |
| 203 NULL); | 223 NULL); |
| 204 vector<PasswordForm*> forms; | 224 if (result != GNOME_KEYRING_RESULT_OK) { |
| 205 if (result == GNOME_KEYRING_RESULT_OK) { | |
| 206 FillFormVector(found, &forms); | |
| 207 for (size_t i = 0; i < forms.size(); ++i) { | |
| 208 if (forms[i]->action != form.action || | |
| 209 forms[i]->password_value != form.password_value || | |
| 210 forms[i]->ssl_valid != form.ssl_valid || | |
| 211 forms[i]->preferred != form.preferred) { | |
| 212 PasswordForm updated = *forms[i]; | |
| 213 updated.action = form.action; | |
| 214 updated.password_value = form.password_value; | |
| 215 updated.ssl_valid = form.ssl_valid; | |
| 216 updated.preferred = form.preferred; | |
| 217 if (AddLoginHelper(updated, updated.date_created)) | |
| 218 RemoveLoginImpl(*forms[i]); | |
| 219 } | |
| 220 delete forms[i]; | |
| 221 } | |
| 222 } else { | |
| 223 LOG(ERROR) << "Keyring find failed: " | 225 LOG(ERROR) << "Keyring find failed: " |
| 224 << gnome_keyring_result_to_message(result); | 226 << gnome_keyring_result_to_message(result); |
| 227 return false; |
| 225 } | 228 } |
| 229 bool ok = true; |
| 230 PasswordFormList forms; |
| 231 ConvertFormList(found, &forms); |
| 232 for (size_t i = 0; i < forms.size(); ++i) { |
| 233 if (forms[i]->action != form.action || |
| 234 forms[i]->password_value != form.password_value || |
| 235 forms[i]->ssl_valid != form.ssl_valid || |
| 236 forms[i]->preferred != form.preferred) { |
| 237 PasswordForm updated = *forms[i]; |
| 238 updated.action = form.action; |
| 239 updated.password_value = form.password_value; |
| 240 updated.ssl_valid = form.ssl_valid; |
| 241 updated.preferred = form.preferred; |
| 242 if (AddLogin(updated)) |
| 243 RemoveLogin(*forms[i]); |
| 244 else |
| 245 ok = false; |
| 246 } |
| 247 delete forms[i]; |
| 248 } |
| 249 return ok; |
| 226 } | 250 } |
| 227 | 251 |
| 228 void PasswordStoreGnome::RemoveLoginImpl(const PasswordForm& form) { | 252 bool NativeBackendGnome::RemoveLogin(const PasswordForm& form) { |
| 229 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); | 253 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 230 // We find forms using the same fields as LoginDatabase::RemoveLogin(). | 254 // We find forms using the same fields as LoginDatabase::RemoveLogin(). |
| 231 GnomeKeyringResult result = gnome_keyring_delete_password_sync( | 255 GnomeKeyringResult result = gnome_keyring_delete_password_sync( |
| 232 &kGnomeSchema, | 256 &kGnomeSchema, |
| 233 "origin_url", form.origin.spec().c_str(), | 257 "origin_url", form.origin.spec().c_str(), |
| 234 "action_url", form.action.spec().c_str(), | 258 "action_url", form.action.spec().c_str(), |
| 235 "username_element", UTF16ToUTF8(form.username_element).c_str(), | 259 "username_element", UTF16ToUTF8(form.username_element).c_str(), |
| 236 "username_value", UTF16ToUTF8(form.username_value).c_str(), | 260 "username_value", UTF16ToUTF8(form.username_value).c_str(), |
| 237 "password_element", UTF16ToUTF8(form.password_element).c_str(), | 261 "password_element", UTF16ToUTF8(form.password_element).c_str(), |
| 238 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), | 262 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), |
| 239 "signon_realm", form.signon_realm.c_str(), | 263 "signon_realm", form.signon_realm.c_str(), |
| 240 NULL); | 264 NULL); |
| 241 if (result != GNOME_KEYRING_RESULT_OK) { | 265 if (result != GNOME_KEYRING_RESULT_OK) { |
| 242 LOG(ERROR) << "Keyring delete failed: " | 266 LOG(ERROR) << "Keyring delete failed: " |
| 243 << gnome_keyring_result_to_message(result); | 267 << gnome_keyring_result_to_message(result); |
| 268 return false; |
| 244 } | 269 } |
| 270 return true; |
| 245 } | 271 } |
| 246 | 272 |
| 247 void PasswordStoreGnome::RemoveLoginsCreatedBetweenImpl( | 273 bool NativeBackendGnome::RemoveLoginsCreatedBetween( |
| 248 const base::Time& delete_begin, | 274 const base::Time& delete_begin, |
| 249 const base::Time& delete_end) { | 275 const base::Time& delete_end) { |
| 250 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); | 276 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 251 GList* found = NULL; | 277 bool ok = true; |
| 252 // Search GNOME keyring for all passwords, then delete the ones in the range. | 278 // We could walk the list and delete items as we find them, but it is much |
| 253 // We need to search for something, otherwise we get no results - so we search | 279 // easier to build the list and use RemoveLogin() to delete them. |
| 254 // for the fixed application string. | 280 PasswordFormList forms; |
| 255 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( | 281 if (!GetAllLogins(&forms)) |
| 256 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 282 return false; |
| 257 &found, | 283 |
| 258 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 284 for (size_t i = 0; i < forms.size(); ++i) { |
| 259 GNOME_KEYRING_APPLICATION_CHROME, | 285 if (delete_begin <= forms[i]->date_created && |
| 260 NULL); | 286 (delete_end.is_null() || forms[i]->date_created < delete_end)) { |
| 261 if (result == GNOME_KEYRING_RESULT_OK) { | 287 if (!RemoveLogin(*forms[i])) |
| 262 // We could walk the list and delete items as we find them, but it is much | 288 ok = false; |
| 263 // easier to build the vector and use RemoveLoginImpl() to delete them. | |
| 264 vector<PasswordForm*> forms; | |
| 265 FillFormVector(found, &forms); | |
| 266 for (size_t i = 0; i < forms.size(); ++i) { | |
| 267 if (delete_begin <= forms[i]->date_created && | |
| 268 (delete_end.is_null() || forms[i]->date_created < delete_end)) { | |
| 269 RemoveLoginImpl(*forms[i]); | |
| 270 } | |
| 271 delete forms[i]; | |
| 272 } | 289 } |
| 273 } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) { | 290 delete forms[i]; |
| 274 LOG(ERROR) << "Keyring find failed: " | |
| 275 << gnome_keyring_result_to_message(result); | |
| 276 } | 291 } |
| 292 return ok; |
| 277 } | 293 } |
| 278 | 294 |
| 279 void PasswordStoreGnome::GetLoginsImpl(GetLoginsRequest* request, | 295 bool NativeBackendGnome::GetLogins(const PasswordForm& form, |
| 280 const PasswordForm& form) { | 296 PasswordFormList* forms) { |
| 281 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); | 297 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 282 GList* found = NULL; | 298 GList* found = NULL; |
| 283 // Search gnome keyring for matching passwords. | 299 // Search gnome keyring for matching passwords. |
| 284 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( | 300 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( |
| 285 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 301 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
| 286 &found, | 302 &found, |
| 287 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 303 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 288 form.signon_realm.c_str(), | 304 form.signon_realm.c_str(), |
| 289 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 305 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 290 GNOME_KEYRING_APPLICATION_CHROME, | 306 GNOME_KEYRING_APPLICATION_CHROME, |
| 291 NULL); | 307 NULL); |
| 292 vector<PasswordForm*> forms; | 308 if (result == GNOME_KEYRING_RESULT_NO_MATCH) |
| 293 if (result == GNOME_KEYRING_RESULT_OK) { | 309 return true; |
| 294 FillFormVector(found, &forms); | 310 if (result != GNOME_KEYRING_RESULT_OK) { |
| 295 } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) { | |
| 296 LOG(ERROR) << "Keyring find failed: " | 311 LOG(ERROR) << "Keyring find failed: " |
| 297 << gnome_keyring_result_to_message(result); | 312 << gnome_keyring_result_to_message(result); |
| 298 } | |
| 299 NotifyConsumer(request, forms); | |
| 300 } | |
| 301 | |
| 302 void PasswordStoreGnome::GetAutofillableLoginsImpl( | |
| 303 GetLoginsRequest* request) { | |
| 304 std::vector<PasswordForm*> forms; | |
| 305 FillAutofillableLogins(&forms); | |
| 306 NotifyConsumer(request, forms); | |
| 307 } | |
| 308 | |
| 309 void PasswordStoreGnome::GetBlacklistLoginsImpl( | |
| 310 GetLoginsRequest* request) { | |
| 311 std::vector<PasswordForm*> forms; | |
| 312 FillBlacklistLogins(&forms); | |
| 313 NotifyConsumer(request, forms); | |
| 314 } | |
| 315 | |
| 316 bool PasswordStoreGnome::FillAutofillableLogins( | |
| 317 std::vector<PasswordForm*>* forms) { | |
| 318 return FillSomeLogins(true, forms); | |
| 319 } | |
| 320 | |
| 321 bool PasswordStoreGnome::FillBlacklistLogins( | |
| 322 std::vector<PasswordForm*>* forms) { | |
| 323 return FillSomeLogins(false, forms); | |
| 324 } | |
| 325 | |
| 326 bool PasswordStoreGnome::AddLoginHelper(const PasswordForm& form, | |
| 327 const base::Time& date_created) { | |
| 328 GnomeKeyringResult result = gnome_keyring_store_password_sync( | |
| 329 &kGnomeSchema, | |
| 330 NULL, // Default keyring. | |
| 331 form.origin.spec().c_str(), // Display name. | |
| 332 UTF16ToUTF8(form.password_value).c_str(), | |
| 333 "origin_url", form.origin.spec().c_str(), | |
| 334 "action_url", form.action.spec().c_str(), | |
| 335 "username_element", UTF16ToUTF8(form.username_element).c_str(), | |
| 336 "username_value", UTF16ToUTF8(form.username_value).c_str(), | |
| 337 "password_element", UTF16ToUTF8(form.password_element).c_str(), | |
| 338 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), | |
| 339 "signon_realm", form.signon_realm.c_str(), | |
| 340 "ssl_valid", form.ssl_valid, | |
| 341 "preferred", form.preferred, | |
| 342 "date_created", Int64ToString(date_created.ToTimeT()).c_str(), | |
| 343 "blacklisted_by_user", form.blacklisted_by_user, | |
| 344 "scheme", form.scheme, | |
| 345 "application", GNOME_KEYRING_APPLICATION_CHROME, | |
| 346 NULL); | |
| 347 | |
| 348 if (result != GNOME_KEYRING_RESULT_OK) { | |
| 349 LOG(ERROR) << "Keyring save failed: " | |
| 350 << gnome_keyring_result_to_message(result); | |
| 351 return false; | 313 return false; |
| 352 } | 314 } |
| 315 ConvertFormList(found, forms); |
| 353 return true; | 316 return true; |
| 354 } | 317 } |
| 355 | 318 |
| 356 bool PasswordStoreGnome::FillSomeLogins( | 319 bool NativeBackendGnome::GetLoginsCreatedBetween(const base::Time& get_begin, |
| 357 bool autofillable, | 320 const base::Time& get_end, |
| 358 std::vector<PasswordForm*>* forms) { | 321 PasswordFormList* forms) { |
| 322 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 323 // We could walk the list and add items as we find them, but it is much |
| 324 // easier to build the list and then filter the results. |
| 325 PasswordFormList all_forms; |
| 326 if (!GetAllLogins(&all_forms)) |
| 327 return false; |
| 328 |
| 329 forms->reserve(forms->size() + all_forms.size()); |
| 330 for (size_t i = 0; i < all_forms.size(); ++i) { |
| 331 if (get_begin <= all_forms[i]->date_created && |
| 332 (get_end.is_null() || all_forms[i]->date_created < get_end)) { |
| 333 forms->push_back(all_forms[i]); |
| 334 } else { |
| 335 delete all_forms[i]; |
| 336 } |
| 337 } |
| 338 |
| 339 return true; |
| 340 } |
| 341 |
| 342 bool NativeBackendGnome::GetAutofillableLogins(PasswordFormList* forms) { |
| 343 return GetLoginsList(forms, true); |
| 344 } |
| 345 |
| 346 bool NativeBackendGnome::GetBlacklistLogins(PasswordFormList* forms) { |
| 347 return GetLoginsList(forms, false); |
| 348 } |
| 349 |
| 350 bool NativeBackendGnome::GetLoginsList(PasswordFormList* forms, |
| 351 bool autofillable) { |
| 359 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); | 352 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 360 GList* found = NULL; | 353 GList* found = NULL; |
| 361 uint32_t blacklisted_by_user = !autofillable; | 354 uint32_t blacklisted_by_user = !autofillable; |
| 362 // Search gnome keyring for matching passwords. | 355 // Search gnome keyring for matching passwords. |
| 363 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( | 356 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( |
| 364 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 357 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
| 365 &found, | 358 &found, |
| 366 "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32, | 359 "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32, |
| 367 blacklisted_by_user, | 360 blacklisted_by_user, |
| 368 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 361 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 369 GNOME_KEYRING_APPLICATION_CHROME, | 362 GNOME_KEYRING_APPLICATION_CHROME, |
| 370 NULL); | 363 NULL); |
| 371 if (result == GNOME_KEYRING_RESULT_OK) { | 364 if (result == GNOME_KEYRING_RESULT_NO_MATCH) |
| 372 FillFormVector(found, forms); | 365 return true; |
| 373 } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) { | 366 if (result != GNOME_KEYRING_RESULT_OK) { |
| 374 LOG(ERROR) << "Keyring find failed: " | 367 LOG(ERROR) << "Keyring find failed: " |
| 375 << gnome_keyring_result_to_message(result); | 368 << gnome_keyring_result_to_message(result); |
| 376 return false; | 369 return false; |
| 377 } | 370 } |
| 371 ConvertFormList(found, forms); |
| 378 return true; | 372 return true; |
| 379 } | 373 } |
| 380 | 374 |
| 381 void PasswordStoreGnome::FillFormVector(GList* found, | 375 bool NativeBackendGnome::GetAllLogins(PasswordFormList* forms) { |
| 382 std::vector<PasswordForm*>* forms) { | 376 GList* found = NULL; |
| 377 // We need to search for something, otherwise we get no results - so we search |
| 378 // for the fixed application string. |
| 379 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( |
| 380 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
| 381 &found, |
| 382 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 383 GNOME_KEYRING_APPLICATION_CHROME, |
| 384 NULL); |
| 385 if (result == GNOME_KEYRING_RESULT_NO_MATCH) |
| 386 return true; |
| 387 if (result != GNOME_KEYRING_RESULT_OK) { |
| 388 LOG(ERROR) << "Keyring find failed: " |
| 389 << gnome_keyring_result_to_message(result); |
| 390 return false; |
| 391 } |
| 392 ConvertFormList(found, forms); |
| 393 return true; |
| 394 } |
| 395 |
| 396 void NativeBackendGnome::ConvertFormList(GList* found, |
| 397 PasswordFormList* forms) { |
| 383 GList* element = g_list_first(found); | 398 GList* element = g_list_first(found); |
| 384 while (element != NULL) { | 399 while (element != NULL) { |
| 385 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); | 400 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); |
| 386 char* password = data->secret; | 401 char* password = data->secret; |
| 387 | 402 |
| 388 GnomeKeyringAttributeList* attributes = data->attributes; | 403 GnomeKeyringAttributeList* attributes = data->attributes; |
| 389 // Read the string and int attributes into the appropriate map. | 404 // Read the string and int attributes into the appropriate map. |
| 390 map<string, string> string_attribute_map; | 405 map<string, string> string_attribute_map; |
| 391 map<string, uint32> uint_attribute_map; | 406 map<string, uint32> uint_attribute_map; |
| 392 for (unsigned int i = 0; i < attributes->len; ++i) { | 407 for (unsigned int i = 0; i < attributes->len; ++i) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 form->blacklisted_by_user = uint_attribute_map["blacklisted_by_user"]; | 439 form->blacklisted_by_user = uint_attribute_map["blacklisted_by_user"]; |
| 425 form->scheme = static_cast<PasswordForm::Scheme>( | 440 form->scheme = static_cast<PasswordForm::Scheme>( |
| 426 uint_attribute_map["scheme"]); | 441 uint_attribute_map["scheme"]); |
| 427 | 442 |
| 428 forms->push_back(form); | 443 forms->push_back(form); |
| 429 | 444 |
| 430 element = g_list_next(element); | 445 element = g_list_next(element); |
| 431 } | 446 } |
| 432 gnome_keyring_found_list_free(found); | 447 gnome_keyring_found_list_free(found); |
| 433 } | 448 } |
| OLD | NEW |