| OLD | NEW |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 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/native_backend_libsecret.h" | 5 #include "chrome/browser/password_manager/native_backend_libsecret.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <libsecret/secret.h> | 10 #include <libsecret/secret.h> |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 bool NativeBackendLibsecret::Init() { | 173 bool NativeBackendLibsecret::Init() { |
| 174 return LibsecretLoader::EnsureLibsecretLoaded(); | 174 return LibsecretLoader::EnsureLibsecretLoaded(); |
| 175 } | 175 } |
| 176 | 176 |
| 177 password_manager::PasswordStoreChangeList NativeBackendLibsecret::AddLogin( | 177 password_manager::PasswordStoreChangeList NativeBackendLibsecret::AddLogin( |
| 178 const PasswordForm& form) { | 178 const PasswordForm& form) { |
| 179 // Based on LoginDatabase::AddLogin(), we search for an existing match based | 179 // Based on LoginDatabase::AddLogin(), we search for an existing match based |
| 180 // on origin_url, username_element, username_value, password_element and | 180 // on origin_url, username_element, username_value, password_element and |
| 181 // signon_realm first, remove that, and then add the new entry. | 181 // signon_realm first, remove that, and then add the new entry. |
| 182 password_manager::PasswordStoreChangeList changes; | 182 password_manager::PasswordStoreChangeList changes; |
| 183 ScopedVector<autofill::PasswordForm> forms; | 183 std::vector<std::unique_ptr<PasswordForm>> forms; |
| 184 if (!AddUpdateLoginSearch(form, &forms)) | 184 if (!AddUpdateLoginSearch(form, &forms)) |
| 185 return changes; | 185 return changes; |
| 186 | 186 |
| 187 if (forms.size() > 0) { | 187 if (forms.size() > 0) { |
| 188 password_manager::PasswordStoreChangeList temp_changes; | 188 password_manager::PasswordStoreChangeList temp_changes; |
| 189 if (forms.size() > 1) { | 189 if (forms.size() > 1) { |
| 190 LOG(WARNING) << "Adding login when there are " << forms.size() | 190 LOG(WARNING) << "Adding login when there are " << forms.size() |
| 191 << " matching logins already!"; | 191 << " matching logins already!"; |
| 192 } | 192 } |
| 193 for (const PasswordForm* old_form : forms) { | 193 for (const auto& old_form : forms) { |
| 194 if (!RemoveLogin(*old_form, &temp_changes)) | 194 if (!RemoveLogin(*old_form, &temp_changes)) |
| 195 return changes; | 195 return changes; |
| 196 } | 196 } |
| 197 changes.push_back(password_manager::PasswordStoreChange( | 197 changes.push_back(password_manager::PasswordStoreChange( |
| 198 password_manager::PasswordStoreChange::REMOVE, *forms[0])); | 198 password_manager::PasswordStoreChange::REMOVE, *forms[0])); |
| 199 } | 199 } |
| 200 if (RawAddLogin(form)) { | 200 if (RawAddLogin(form)) { |
| 201 changes.push_back(password_manager::PasswordStoreChange( | 201 changes.push_back(password_manager::PasswordStoreChange( |
| 202 password_manager::PasswordStoreChange::ADD, form)); | 202 password_manager::PasswordStoreChange::ADD, form)); |
| 203 } | 203 } |
| 204 return changes; | 204 return changes; |
| 205 } | 205 } |
| 206 | 206 |
| 207 bool NativeBackendLibsecret::UpdateLogin( | 207 bool NativeBackendLibsecret::UpdateLogin( |
| 208 const PasswordForm& form, | 208 const PasswordForm& form, |
| 209 password_manager::PasswordStoreChangeList* changes) { | 209 password_manager::PasswordStoreChangeList* changes) { |
| 210 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by | 210 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by |
| 211 // origin_url, username_element, username_value, password_element, and | 211 // origin_url, username_element, username_value, password_element, and |
| 212 // signon_realm. We then compare the result to the updated form. If they | 212 // signon_realm. We then compare the result to the updated form. If they |
| 213 // differ in any of the mutable fields, then we remove the original, and | 213 // differ in any of the mutable fields, then we remove the original, and |
| 214 // then add the new entry. We'd add the new one first, and then delete the | 214 // then add the new entry. We'd add the new one first, and then delete the |
| 215 // original, but then the delete might actually delete the newly-added entry! | 215 // original, but then the delete might actually delete the newly-added entry! |
| 216 DCHECK(changes); | 216 DCHECK(changes); |
| 217 ScopedVector<autofill::PasswordForm> forms; | 217 std::vector<std::unique_ptr<PasswordForm>> forms; |
| 218 if (!AddUpdateLoginSearch(form, &forms)) | 218 if (!AddUpdateLoginSearch(form, &forms)) |
| 219 return false; | 219 return false; |
| 220 if (forms.empty()) | 220 if (forms.empty()) |
| 221 return true; | 221 return true; |
| 222 if (forms.size() == 1 && *forms.front() == form) | 222 if (forms.size() == 1 && *forms.front() == form) |
| 223 return true; | 223 return true; |
| 224 | 224 |
| 225 password_manager::PasswordStoreChangeList temp_changes; | 225 password_manager::PasswordStoreChangeList temp_changes; |
| 226 for (const PasswordForm* keychain_form : forms) { | 226 for (const auto& keychain_form : forms) { |
| 227 // Remove all the obsolete forms. Note that RemoveLogin can remove any form | 227 // Remove all the obsolete forms. Note that RemoveLogin can remove any form |
| 228 // matching the unique key. Thus, it's important to call it the right number | 228 // matching the unique key. Thus, it's important to call it the right number |
| 229 // of times. | 229 // of times. |
| 230 if (!RemoveLogin(*keychain_form, &temp_changes)) | 230 if (!RemoveLogin(*keychain_form, &temp_changes)) |
| 231 return false; | 231 return false; |
| 232 } | 232 } |
| 233 | 233 |
| 234 if (RawAddLogin(form)) { | 234 if (RawAddLogin(form)) { |
| 235 password_manager::PasswordStoreChange change( | 235 password_manager::PasswordStoreChange change( |
| 236 password_manager::PasswordStoreChange::UPDATE, form); | 236 password_manager::PasswordStoreChange::UPDATE, form); |
| 237 changes->push_back(change); | 237 changes->push_back(change); |
| 238 return true; | 238 return true; |
| 239 } | 239 } |
| 240 return false; | 240 return false; |
| 241 } | 241 } |
| 242 | 242 |
| 243 bool NativeBackendLibsecret::RemoveLogin( | 243 bool NativeBackendLibsecret::RemoveLogin( |
| 244 const autofill::PasswordForm& form, | 244 const PasswordForm& form, |
| 245 password_manager::PasswordStoreChangeList* changes) { | 245 password_manager::PasswordStoreChangeList* changes) { |
| 246 DCHECK(changes); | 246 DCHECK(changes); |
| 247 GError* error = nullptr; | 247 GError* error = nullptr; |
| 248 if (LibsecretLoader::secret_password_clear_sync( | 248 if (LibsecretLoader::secret_password_clear_sync( |
| 249 &kLibsecretSchema, nullptr, &error, "origin_url", | 249 &kLibsecretSchema, nullptr, &error, "origin_url", |
| 250 form.origin.spec().c_str(), "username_element", | 250 form.origin.spec().c_str(), "username_element", |
| 251 UTF16ToUTF8(form.username_element).c_str(), "username_value", | 251 UTF16ToUTF8(form.username_element).c_str(), "username_value", |
| 252 UTF16ToUTF8(form.username_value).c_str(), "password_element", | 252 UTF16ToUTF8(form.username_value).c_str(), "password_element", |
| 253 UTF16ToUTF8(form.password_element).c_str(), "signon_realm", | 253 UTF16ToUTF8(form.password_element).c_str(), "signon_realm", |
| 254 form.signon_realm.c_str(), "application", app_string_.c_str(), | 254 form.signon_realm.c_str(), "application", app_string_.c_str(), |
| (...skipping 21 matching lines...) Expand all Loading... |
| 276 bool NativeBackendLibsecret::RemoveLoginsSyncedBetween( | 276 bool NativeBackendLibsecret::RemoveLoginsSyncedBetween( |
| 277 base::Time delete_begin, | 277 base::Time delete_begin, |
| 278 base::Time delete_end, | 278 base::Time delete_end, |
| 279 password_manager::PasswordStoreChangeList* changes) { | 279 password_manager::PasswordStoreChangeList* changes) { |
| 280 return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes); | 280 return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes); |
| 281 } | 281 } |
| 282 | 282 |
| 283 bool NativeBackendLibsecret::DisableAutoSignInForOrigins( | 283 bool NativeBackendLibsecret::DisableAutoSignInForOrigins( |
| 284 const base::Callback<bool(const GURL&)>& origin_filter, | 284 const base::Callback<bool(const GURL&)>& origin_filter, |
| 285 password_manager::PasswordStoreChangeList* changes) { | 285 password_manager::PasswordStoreChangeList* changes) { |
| 286 ScopedVector<autofill::PasswordForm> all_forms; | 286 std::vector<std::unique_ptr<PasswordForm>> all_forms; |
| 287 if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms)) | 287 if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms)) |
| 288 return false; | 288 return false; |
| 289 | 289 |
| 290 for (auto* form : all_forms) { | 290 for (const std::unique_ptr<PasswordForm>& form : all_forms) { |
| 291 if (origin_filter.Run(form->origin) && !form->skip_zero_click) { | 291 if (origin_filter.Run(form->origin) && !form->skip_zero_click) { |
| 292 form->skip_zero_click = true; | 292 form->skip_zero_click = true; |
| 293 if (!UpdateLogin(*form, changes)) | 293 if (!UpdateLogin(*form, changes)) |
| 294 return false; | 294 return false; |
| 295 } | 295 } |
| 296 } | 296 } |
| 297 | 297 |
| 298 return true; | 298 return true; |
| 299 } | 299 } |
| 300 | 300 |
| 301 bool NativeBackendLibsecret::GetLogins( | 301 bool NativeBackendLibsecret::GetLogins( |
| 302 const PasswordStore::FormDigest& form, | 302 const PasswordStore::FormDigest& form, |
| 303 ScopedVector<autofill::PasswordForm>* forms) { | 303 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
| 304 return GetLoginsList(&form, ALL_LOGINS, forms); | 304 return GetLoginsList(&form, ALL_LOGINS, forms); |
| 305 } | 305 } |
| 306 | 306 |
| 307 bool NativeBackendLibsecret::AddUpdateLoginSearch( | 307 bool NativeBackendLibsecret::AddUpdateLoginSearch( |
| 308 const autofill::PasswordForm& lookup_form, | 308 const PasswordForm& lookup_form, |
| 309 ScopedVector<autofill::PasswordForm>* forms) { | 309 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
| 310 if (!ensured_keyring_unlocked_) { | 310 if (!ensured_keyring_unlocked_) { |
| 311 LibsecretLoader::EnsureKeyringUnlocked(); | 311 LibsecretLoader::EnsureKeyringUnlocked(); |
| 312 ensured_keyring_unlocked_ = true; | 312 ensured_keyring_unlocked_ = true; |
| 313 } | 313 } |
| 314 | 314 |
| 315 LibsecretAttributesBuilder attrs; | 315 LibsecretAttributesBuilder attrs; |
| 316 attrs.Append("origin_url", lookup_form.origin.spec()); | 316 attrs.Append("origin_url", lookup_form.origin.spec()); |
| 317 attrs.Append("username_element", UTF16ToUTF8(lookup_form.username_element)); | 317 attrs.Append("username_element", UTF16ToUTF8(lookup_form.username_element)); |
| 318 attrs.Append("username_value", UTF16ToUTF8(lookup_form.username_value)); | 318 attrs.Append("username_value", UTF16ToUTF8(lookup_form.username_value)); |
| 319 attrs.Append("password_element", UTF16ToUTF8(lookup_form.password_element)); | 319 attrs.Append("password_element", UTF16ToUTF8(lookup_form.password_element)); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 | 388 |
| 389 if (error) { | 389 if (error) { |
| 390 LOG(ERROR) << "Libsecret add raw login failed: " << error->message; | 390 LOG(ERROR) << "Libsecret add raw login failed: " << error->message; |
| 391 g_error_free(error); | 391 g_error_free(error); |
| 392 return false; | 392 return false; |
| 393 } | 393 } |
| 394 return true; | 394 return true; |
| 395 } | 395 } |
| 396 | 396 |
| 397 bool NativeBackendLibsecret::GetAutofillableLogins( | 397 bool NativeBackendLibsecret::GetAutofillableLogins( |
| 398 ScopedVector<autofill::PasswordForm>* forms) { | 398 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
| 399 return GetLoginsList(nullptr, AUTOFILLABLE_LOGINS, forms); | 399 return GetLoginsList(nullptr, AUTOFILLABLE_LOGINS, forms); |
| 400 } | 400 } |
| 401 | 401 |
| 402 bool NativeBackendLibsecret::GetBlacklistLogins( | 402 bool NativeBackendLibsecret::GetBlacklistLogins( |
| 403 ScopedVector<autofill::PasswordForm>* forms) { | 403 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
| 404 return GetLoginsList(nullptr, BLACKLISTED_LOGINS, forms); | 404 return GetLoginsList(nullptr, BLACKLISTED_LOGINS, forms); |
| 405 } | 405 } |
| 406 | 406 |
| 407 bool NativeBackendLibsecret::GetAllLogins( | 407 bool NativeBackendLibsecret::GetAllLogins( |
| 408 ScopedVector<autofill::PasswordForm>* forms) { | 408 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
| 409 return GetLoginsList(nullptr, ALL_LOGINS, forms); | 409 return GetLoginsList(nullptr, ALL_LOGINS, forms); |
| 410 } | 410 } |
| 411 | 411 |
| 412 bool NativeBackendLibsecret::GetLoginsList( | 412 bool NativeBackendLibsecret::GetLoginsList( |
| 413 const PasswordStore::FormDigest* lookup_form, | 413 const PasswordStore::FormDigest* lookup_form, |
| 414 GetLoginsListOptions options, | 414 GetLoginsListOptions options, |
| 415 ScopedVector<autofill::PasswordForm>* forms) { | 415 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
| 416 if (!ensured_keyring_unlocked_) { | 416 if (!ensured_keyring_unlocked_) { |
| 417 LibsecretLoader::EnsureKeyringUnlocked(); | 417 LibsecretLoader::EnsureKeyringUnlocked(); |
| 418 ensured_keyring_unlocked_ = true; | 418 ensured_keyring_unlocked_ = true; |
| 419 } | 419 } |
| 420 | 420 |
| 421 LibsecretAttributesBuilder attrs; | 421 LibsecretAttributesBuilder attrs; |
| 422 attrs.Append("application", app_string_); | 422 attrs.Append("application", app_string_); |
| 423 if (options != ALL_LOGINS) | 423 if (options != ALL_LOGINS) |
| 424 attrs.Append("blacklisted_by_user", options == BLACKLISTED_LOGINS); | 424 attrs.Append("blacklisted_by_user", options == BLACKLISTED_LOGINS); |
| 425 if (lookup_form && | 425 if (lookup_form && |
| (...skipping 16 matching lines...) Expand all Loading... |
| 442 if (found) | 442 if (found) |
| 443 g_list_free(found); | 443 g_list_free(found); |
| 444 return false; | 444 return false; |
| 445 } | 445 } |
| 446 | 446 |
| 447 *forms = ConvertFormList(found, lookup_form); | 447 *forms = ConvertFormList(found, lookup_form); |
| 448 if (lookup_form) | 448 if (lookup_form) |
| 449 return true; | 449 return true; |
| 450 | 450 |
| 451 // Get rid of the forms with the same sync tags. | 451 // Get rid of the forms with the same sync tags. |
| 452 ScopedVector<autofill::PasswordForm> duplicates; | 452 std::vector<std::unique_ptr<PasswordForm>> duplicates; |
| 453 std::vector<std::vector<autofill::PasswordForm*>> tag_groups; | 453 std::vector<std::vector<PasswordForm*>> tag_groups; |
| 454 password_manager_util::FindDuplicates(forms, &duplicates, &tag_groups); | 454 password_manager_util::FindDuplicates(forms, &duplicates, &tag_groups); |
| 455 if (duplicates.empty()) | 455 if (duplicates.empty()) |
| 456 return true; | 456 return true; |
| 457 for (const auto& group : tag_groups) { | 457 for (const auto& group : tag_groups) { |
| 458 if (group.size() > 1) { | 458 if (group.size() > 1) { |
| 459 // There are duplicates. Readd the first form. AddLogin() is smart enough | 459 // There are duplicates. Readd the first form. AddLogin() is smart enough |
| 460 // to clean the previous ones. | 460 // to clean the previous ones. |
| 461 password_manager::PasswordStoreChangeList changes = AddLogin(*group[0]); | 461 password_manager::PasswordStoreChangeList changes = AddLogin(*group[0]); |
| 462 if (changes.empty() || | 462 if (changes.empty() || |
| 463 changes.back().type() != password_manager::PasswordStoreChange::ADD) | 463 changes.back().type() != password_manager::PasswordStoreChange::ADD) |
| 464 return false; | 464 return false; |
| 465 } | 465 } |
| 466 } | 466 } |
| 467 return true; | 467 return true; |
| 468 } | 468 } |
| 469 | 469 |
| 470 bool NativeBackendLibsecret::GetLoginsBetween( | 470 bool NativeBackendLibsecret::GetLoginsBetween( |
| 471 base::Time get_begin, | 471 base::Time get_begin, |
| 472 base::Time get_end, | 472 base::Time get_end, |
| 473 TimestampToCompare date_to_compare, | 473 TimestampToCompare date_to_compare, |
| 474 ScopedVector<autofill::PasswordForm>* forms) { | 474 std::vector<std::unique_ptr<PasswordForm>>* forms) { |
| 475 forms->clear(); | 475 forms->clear(); |
| 476 ScopedVector<autofill::PasswordForm> all_forms; | 476 std::vector<std::unique_ptr<PasswordForm>> all_forms; |
| 477 if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms)) | 477 if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms)) |
| 478 return false; | 478 return false; |
| 479 | 479 |
| 480 base::Time autofill::PasswordForm::*date_member = | 480 base::Time PasswordForm::*date_member = date_to_compare == CREATION_TIMESTAMP |
| 481 date_to_compare == CREATION_TIMESTAMP | 481 ? &PasswordForm::date_created |
| 482 ? &autofill::PasswordForm::date_created | 482 : &PasswordForm::date_synced; |
| 483 : &autofill::PasswordForm::date_synced; | 483 for (std::unique_ptr<PasswordForm>& saved_form : all_forms) { |
| 484 for (auto*& saved_form : all_forms) { | 484 if (get_begin <= saved_form.get()->*date_member && |
| 485 if (get_begin <= saved_form->*date_member && | 485 (get_end.is_null() || saved_form.get()->*date_member < get_end)) { |
| 486 (get_end.is_null() || saved_form->*date_member < get_end)) { | 486 forms->push_back(std::move(saved_form)); |
| 487 forms->push_back(saved_form); | |
| 488 saved_form = nullptr; | |
| 489 } | 487 } |
| 490 } | 488 } |
| 491 | 489 |
| 492 return true; | 490 return true; |
| 493 } | 491 } |
| 494 | 492 |
| 495 bool NativeBackendLibsecret::RemoveLoginsBetween( | 493 bool NativeBackendLibsecret::RemoveLoginsBetween( |
| 496 base::Time get_begin, | 494 base::Time get_begin, |
| 497 base::Time get_end, | 495 base::Time get_end, |
| 498 TimestampToCompare date_to_compare, | 496 TimestampToCompare date_to_compare, |
| 499 password_manager::PasswordStoreChangeList* changes) { | 497 password_manager::PasswordStoreChangeList* changes) { |
| 500 DCHECK(changes); | 498 DCHECK(changes); |
| 501 changes->clear(); | 499 changes->clear(); |
| 502 ScopedVector<autofill::PasswordForm> forms; | 500 std::vector<std::unique_ptr<PasswordForm>> forms; |
| 503 if (!GetLoginsBetween(get_begin, get_end, date_to_compare, &forms)) | 501 if (!GetLoginsBetween(get_begin, get_end, date_to_compare, &forms)) |
| 504 return false; | 502 return false; |
| 505 | 503 |
| 506 for (size_t i = 0; i < forms.size(); ++i) { | 504 for (size_t i = 0; i < forms.size(); ++i) { |
| 507 if (!RemoveLogin(*forms[i], changes)) | 505 if (!RemoveLogin(*forms[i], changes)) |
| 508 return false; | 506 return false; |
| 509 } | 507 } |
| 510 return true; | 508 return true; |
| 511 } | 509 } |
| 512 | 510 |
| 513 ScopedVector<autofill::PasswordForm> NativeBackendLibsecret::ConvertFormList( | 511 std::vector<std::unique_ptr<PasswordForm>> |
| 512 NativeBackendLibsecret::ConvertFormList( |
| 514 GList* found, | 513 GList* found, |
| 515 const PasswordStore::FormDigest* lookup_form) { | 514 const PasswordStore::FormDigest* lookup_form) { |
| 516 ScopedVector<autofill::PasswordForm> forms; | 515 std::vector<std::unique_ptr<PasswordForm>> forms; |
| 517 password_manager::PSLDomainMatchMetric psl_domain_match_metric = | 516 password_manager::PSLDomainMatchMetric psl_domain_match_metric = |
| 518 password_manager::PSL_DOMAIN_MATCH_NONE; | 517 password_manager::PSL_DOMAIN_MATCH_NONE; |
| 519 GError* error = nullptr; | 518 GError* error = nullptr; |
| 520 const bool allow_psl_match = | 519 const bool allow_psl_match = |
| 521 lookup_form && password_manager::ShouldPSLDomainMatchingApply( | 520 lookup_form && password_manager::ShouldPSLDomainMatchingApply( |
| 522 password_manager::GetRegistryControlledDomain( | 521 password_manager::GetRegistryControlledDomain( |
| 523 GURL(lookup_form->signon_realm))); | 522 GURL(lookup_form->signon_realm))); |
| 524 for (GList* element = g_list_first(found); element != nullptr; | 523 for (GList* element = g_list_first(found); element != nullptr; |
| 525 element = g_list_next(element)) { | 524 element = g_list_next(element)) { |
| 526 SecretItem* secretItem = static_cast<SecretItem*>(element->data); | 525 SecretItem* secretItem = static_cast<SecretItem*>(element->data); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 if (lookup_form) { | 569 if (lookup_form) { |
| 571 UMA_HISTOGRAM_ENUMERATION("PasswordManager.PslDomainMatchTriggering", | 570 UMA_HISTOGRAM_ENUMERATION("PasswordManager.PslDomainMatchTriggering", |
| 572 allow_psl_match | 571 allow_psl_match |
| 573 ? psl_domain_match_metric | 572 ? psl_domain_match_metric |
| 574 : password_manager::PSL_DOMAIN_MATCH_NOT_USED, | 573 : password_manager::PSL_DOMAIN_MATCH_NOT_USED, |
| 575 password_manager::PSL_DOMAIN_MATCH_COUNT); | 574 password_manager::PSL_DOMAIN_MATCH_COUNT); |
| 576 } | 575 } |
| 577 g_list_free(found); | 576 g_list_free(found); |
| 578 return forms; | 577 return forms; |
| 579 } | 578 } |
| OLD | NEW |