OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_gnome_x.h" | 5 #include "chrome/browser/password_manager/native_backend_gnome_x.h" |
6 | 6 |
7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
8 #include <gnome-keyring.h> | 8 #include <gnome-keyring.h> |
9 | 9 |
10 #include <map> | 10 #include <map> |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
152 base::StringToInt64(string_attr_map["date_synced"], &date_synced); | 152 base::StringToInt64(string_attr_map["date_synced"], &date_synced); |
153 form->date_synced = base::Time::FromInternalValue(date_synced); | 153 form->date_synced = base::Time::FromInternalValue(date_synced); |
154 form->display_name = UTF8ToUTF16(string_attr_map["display_name"]); | 154 form->display_name = UTF8ToUTF16(string_attr_map["display_name"]); |
155 form->avatar_url = GURL(string_attr_map["avatar_url"]); | 155 form->avatar_url = GURL(string_attr_map["avatar_url"]); |
156 form->federation_url = GURL(string_attr_map["federation_url"]); | 156 form->federation_url = GURL(string_attr_map["federation_url"]); |
157 form->skip_zero_click = uint_attr_map["skip_zero_click"]; | 157 form->skip_zero_click = uint_attr_map["skip_zero_click"]; |
158 | 158 |
159 return form.Pass(); | 159 return form.Pass(); |
160 } | 160 } |
161 | 161 |
162 // Parse all the results from the given GList into a | 162 // Returns all the results from |found|. If not NULL, |lookup_form| is used to |
163 // ScopedVector<autofill::PasswordForm>, and free the GList. PasswordForms are | 163 // filter out results -- only credentials with signon realms passing the PSL |
164 // allocated on the heap, and should be deleted by the consumer. If not NULL, | 164 // matching against |lookup_form->signon_realm| will be kept. PSL matched |
165 // |lookup_form| is used to filter out results -- only credentials with signon | 165 // results get their signon_realm, origin, and action rewritten to those of |
166 // realms passing the PSL matching against |lookup_form->signon_realm| will be | 166 // |lookup_form_|, with the original signon_realm saved into the result's |
167 // kept. PSL matched results get their signon_realm, origin, and action | 167 // original_signon_realm data member. |
168 // rewritten to those of |lookup_form_|, with the original signon_realm saved | 168 ScopedVector<autofill::PasswordForm> ConvertFormList( |
169 // into the result's original_signon_realm data member. | 169 GList* found, |
170 void ConvertFormList(GList* found, | 170 const PasswordForm* lookup_form) { |
171 const PasswordForm* lookup_form, | 171 ScopedVector<autofill::PasswordForm> forms; |
172 ScopedVector<autofill::PasswordForm>* forms) { | |
173 password_manager::PSLDomainMatchMetric psl_domain_match_metric = | 172 password_manager::PSLDomainMatchMetric psl_domain_match_metric = |
174 password_manager::PSL_DOMAIN_MATCH_NONE; | 173 password_manager::PSL_DOMAIN_MATCH_NONE; |
175 for (GList* element = g_list_first(found); element != NULL; | 174 for (GList* element = g_list_first(found); element != NULL; |
176 element = g_list_next(element)) { | 175 element = g_list_next(element)) { |
177 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); | 176 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); |
178 GnomeKeyringAttributeList* attrs = data->attributes; | 177 GnomeKeyringAttributeList* attrs = data->attributes; |
179 | 178 |
180 scoped_ptr<PasswordForm> form(FormFromAttributes(attrs)); | 179 scoped_ptr<PasswordForm> form(FormFromAttributes(attrs)); |
181 if (form) { | 180 if (form) { |
182 if (lookup_form && form->signon_realm != lookup_form->signon_realm) { | 181 if (lookup_form && form->signon_realm != lookup_form->signon_realm) { |
183 // This is not an exact match, we try PSL matching. | 182 // This is not an exact match, we try PSL matching. |
184 if (lookup_form->scheme != PasswordForm::SCHEME_HTML || | 183 if (lookup_form->scheme != PasswordForm::SCHEME_HTML || |
185 form->scheme != PasswordForm::SCHEME_HTML || | 184 form->scheme != PasswordForm::SCHEME_HTML || |
186 !(password_manager::IsPublicSuffixDomainMatch( | 185 !(password_manager::IsPublicSuffixDomainMatch( |
187 lookup_form->signon_realm, form->signon_realm))) { | 186 lookup_form->signon_realm, form->signon_realm))) { |
188 continue; | 187 continue; |
189 } | 188 } |
190 psl_domain_match_metric = password_manager::PSL_DOMAIN_MATCH_FOUND; | 189 psl_domain_match_metric = password_manager::PSL_DOMAIN_MATCH_FOUND; |
191 form->original_signon_realm = form->signon_realm; | 190 form->original_signon_realm = form->signon_realm; |
192 form->signon_realm = lookup_form->signon_realm; | 191 form->signon_realm = lookup_form->signon_realm; |
193 form->origin = lookup_form->origin; | 192 form->origin = lookup_form->origin; |
194 form->action = lookup_form->action; | 193 form->action = lookup_form->action; |
195 } | 194 } |
196 if (data->secret) { | 195 if (data->secret) { |
197 form->password_value = UTF8ToUTF16(data->secret); | 196 form->password_value = UTF8ToUTF16(data->secret); |
198 } else { | 197 } else { |
199 LOG(WARNING) << "Unable to access password from list element!"; | 198 LOG(WARNING) << "Unable to access password from list element!"; |
200 } | 199 } |
201 forms->push_back(form.release()); | 200 forms.push_back(form.release()); |
202 } else { | 201 } else { |
203 LOG(WARNING) << "Could not initialize PasswordForm from attributes!"; | 202 LOG(WARNING) << "Could not initialize PasswordForm from attributes!"; |
204 } | 203 } |
205 } | 204 } |
206 if (lookup_form) { | 205 if (lookup_form) { |
207 const GURL signon_realm(lookup_form->signon_realm); | 206 const GURL signon_realm(lookup_form->signon_realm); |
208 std::string registered_domain = | 207 std::string registered_domain = |
209 password_manager::GetRegistryControlledDomain(signon_realm); | 208 password_manager::GetRegistryControlledDomain(signon_realm); |
210 UMA_HISTOGRAM_ENUMERATION( | 209 UMA_HISTOGRAM_ENUMERATION( |
211 "PasswordManager.PslDomainMatchTriggering", | 210 "PasswordManager.PslDomainMatchTriggering", |
212 password_manager::ShouldPSLDomainMatchingApply(registered_domain) | 211 password_manager::ShouldPSLDomainMatchingApply(registered_domain) |
213 ? psl_domain_match_metric | 212 ? psl_domain_match_metric |
214 : password_manager::PSL_DOMAIN_MATCH_NOT_USED, | 213 : password_manager::PSL_DOMAIN_MATCH_NOT_USED, |
215 password_manager::PSL_DOMAIN_MATCH_COUNT); | 214 password_manager::PSL_DOMAIN_MATCH_COUNT); |
216 } | 215 } |
216 return forms.Pass(); | |
217 } | 217 } |
218 | 218 |
219 // Schema is analagous to the fields in PasswordForm. | 219 // Schema is analagous to the fields in PasswordForm. |
220 // TODO(gcasto): Adding 'form_data' would be nice, but we would need to | 220 // TODO(gcasto): Adding 'form_data' would be nice, but we would need to |
221 // serialize in a way that is guaranteed to not have any embedded NULLs. Pickle | 221 // serialize in a way that is guaranteed to not have any embedded NULLs. Pickle |
222 // doesn't make this guarantee, so we just don't serialize this field. Since | 222 // doesn't make this guarantee, so we just don't serialize this field. Since |
223 // it's only used to crowd source data collection it doesn't matter that much | 223 // it's only used to crowd source data collection it doesn't matter that much |
224 // if it's not available on this platform. | 224 // if it's not available on this platform. |
225 const GnomeKeyringPasswordSchema kGnomeSchema = { | 225 const GnomeKeyringPasswordSchema kGnomeSchema = { |
226 GNOME_KEYRING_ITEM_GENERIC_SECRET, { | 226 GNOME_KEYRING_ITEM_GENERIC_SECRET, { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
276 void UpdateLoginSearch(const PasswordForm& form, const char* app_string); | 276 void UpdateLoginSearch(const PasswordForm& form, const char* app_string); |
277 void RemoveLogin(const PasswordForm& form, const char* app_string); | 277 void RemoveLogin(const PasswordForm& form, const char* app_string); |
278 void GetLogins(const PasswordForm& form, const char* app_string); | 278 void GetLogins(const PasswordForm& form, const char* app_string); |
279 void GetLoginsList(uint32_t blacklisted_by_user, const char* app_string); | 279 void GetLoginsList(uint32_t blacklisted_by_user, const char* app_string); |
280 void GetAllLogins(const char* app_string); | 280 void GetAllLogins(const char* app_string); |
281 | 281 |
282 // Use after AddLogin, RemoveLogin. | 282 // Use after AddLogin, RemoveLogin. |
283 GnomeKeyringResult WaitResult(); | 283 GnomeKeyringResult WaitResult(); |
284 | 284 |
285 // Use after AddLoginSearch, UpdateLoginSearch, GetLogins, GetLoginsList, | 285 // Use after AddLoginSearch, UpdateLoginSearch, GetLogins, GetLoginsList, |
286 // GetAllLogins. | 286 // GetAllLogins. Replaces the content of |forms| with found logins. |
287 GnomeKeyringResult WaitResult(ScopedVector<autofill::PasswordForm>* forms); | 287 GnomeKeyringResult WaitResult(ScopedVector<autofill::PasswordForm>* forms); |
288 | 288 |
289 private: | 289 private: |
290 struct GnomeKeyringAttributeListFreeDeleter { | 290 struct GnomeKeyringAttributeListFreeDeleter { |
291 inline void operator()(void* list) const { | 291 inline void operator()(void* list) const { |
292 gnome_keyring_attribute_list_free( | 292 gnome_keyring_attribute_list_free( |
293 static_cast<GnomeKeyringAttributeList*>(list)); | 293 static_cast<GnomeKeyringAttributeList*>(list)); |
294 } | 294 } |
295 }; | 295 }; |
296 | 296 |
297 typedef scoped_ptr<GnomeKeyringAttributeList, | 297 typedef scoped_ptr<GnomeKeyringAttributeList, |
298 GnomeKeyringAttributeListFreeDeleter> ScopedAttributeList; | 298 GnomeKeyringAttributeListFreeDeleter> ScopedAttributeList; |
299 | 299 |
300 // Helper methods to abbreviate Gnome Keyring long API names. | 300 // Helper methods to abbreviate Gnome Keyring long API names. |
301 static void AppendString(ScopedAttributeList* list, | 301 static void AppendString(ScopedAttributeList* list, |
302 const char* name, | 302 const char* name, |
303 const char* value); | 303 const char* value); |
304 static void AppendString(ScopedAttributeList* list, | 304 static void AppendString(ScopedAttributeList* list, |
305 const char* name, | 305 const char* name, |
306 const std::string& value); | 306 const std::string& value); |
307 static void AppendUint32(ScopedAttributeList* list, | 307 static void AppendUint32(ScopedAttributeList* list, |
308 const char* name, | 308 const char* name, |
309 guint32 value); | 309 guint32 value); |
310 | 310 |
311 // All these callbacks are called on UI thread. | 311 // All these callbacks are called on UI thread. |
312 static void OnOperationDone(GnomeKeyringResult result, gpointer data); | 312 static void OnOperationDone(GnomeKeyringResult result, gpointer data); |
313 | 313 |
314 // This is marked as static, but acts on the GKRMethod instance pointed to by | |
315 // |data|. Saves the result to |result_|. If the result is OK, overwrites | |
316 // |forms_| with the found credentials. Clears |forms_| otherwise. | |
314 static void OnOperationGetList(GnomeKeyringResult result, GList* list, | 317 static void OnOperationGetList(GnomeKeyringResult result, GList* list, |
315 gpointer data); | 318 gpointer data); |
316 | 319 |
317 base::WaitableEvent event_; | 320 base::WaitableEvent event_; |
318 GnomeKeyringResult result_; | 321 GnomeKeyringResult result_; |
319 ScopedVector<autofill::PasswordForm> forms_; | 322 ScopedVector<autofill::PasswordForm> forms_; |
320 // If the credential search is specified by a single form and needs to use PSL | 323 // If the credential search is specified by a single form and needs to use PSL |
321 // matching, then the specifying form is stored in |lookup_form_|. If PSL | 324 // matching, then the specifying form is stored in |lookup_form_|. If PSL |
322 // matching is used to find a result, then the results signon realm, origin | 325 // matching is used to find a result, then the results signon realm, origin |
323 // and action are stored are replaced by those of |lookup_form_|. | 326 // and action are stored are replaced by those of |lookup_form_|. |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
473 GnomeKeyringResult GKRMethod::WaitResult() { | 476 GnomeKeyringResult GKRMethod::WaitResult() { |
474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
475 event_.Wait(); | 478 event_.Wait(); |
476 return result_; | 479 return result_; |
477 } | 480 } |
478 | 481 |
479 GnomeKeyringResult GKRMethod::WaitResult( | 482 GnomeKeyringResult GKRMethod::WaitResult( |
480 ScopedVector<autofill::PasswordForm>* forms) { | 483 ScopedVector<autofill::PasswordForm>* forms) { |
481 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 484 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
482 event_.Wait(); | 485 event_.Wait(); |
483 if (forms->empty()) { | 486 forms->swap(forms_); |
vabr (Chromium)
2015/02/11 17:19:14
https://codereview.chromium.org/7712024 introduced
| |
484 // Normal case. Avoid extra allocation by swapping. | |
485 forms->swap(forms_); | |
486 } else { | |
487 // Rare case. Append forms_ to *forms. | |
488 forms->insert(forms->end(), forms_.begin(), forms_.end()); | |
489 forms_.weak_clear(); | |
490 } | |
491 return result_; | 487 return result_; |
492 } | 488 } |
493 | 489 |
494 // static | 490 // static |
495 void GKRMethod::AppendString(GKRMethod::ScopedAttributeList* list, | 491 void GKRMethod::AppendString(GKRMethod::ScopedAttributeList* list, |
496 const char* name, | 492 const char* name, |
497 const char* value) { | 493 const char* value) { |
498 gnome_keyring_attribute_list_append_string(list->get(), name, value); | 494 gnome_keyring_attribute_list_append_string(list->get(), name, value); |
499 } | 495 } |
500 | 496 |
(...skipping 18 matching lines...) Expand all Loading... | |
519 method->event_.Signal(); | 515 method->event_.Signal(); |
520 } | 516 } |
521 | 517 |
522 // static | 518 // static |
523 void GKRMethod::OnOperationGetList(GnomeKeyringResult result, GList* list, | 519 void GKRMethod::OnOperationGetList(GnomeKeyringResult result, GList* list, |
524 gpointer data) { | 520 gpointer data) { |
525 GKRMethod* method = static_cast<GKRMethod*>(data); | 521 GKRMethod* method = static_cast<GKRMethod*>(data); |
526 method->result_ = result; | 522 method->result_ = result; |
527 method->forms_.clear(); | 523 method->forms_.clear(); |
528 // |list| will be freed after this callback returns, so convert it now. | 524 // |list| will be freed after this callback returns, so convert it now. |
529 ConvertFormList(list, method->lookup_form_.get(), &method->forms_); | 525 if (result == GNOME_KEYRING_RESULT_OK) |
526 method->forms_ = ConvertFormList(list, method->lookup_form_.get()); | |
530 method->lookup_form_.reset(NULL); | 527 method->lookup_form_.reset(NULL); |
531 method->event_.Signal(); | 528 method->event_.Signal(); |
532 } | 529 } |
533 | 530 |
534 } // namespace | 531 } // namespace |
535 | 532 |
536 NativeBackendGnome::NativeBackendGnome(LocalProfileId id) | 533 NativeBackendGnome::NativeBackendGnome(LocalProfileId id) |
537 : profile_id_(id) { | 534 : profile_id_(id) { |
538 app_string_ = GetProfileSpecificAppString(); | 535 app_string_ = GetProfileSpecificAppString(); |
539 } | 536 } |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
705 | 702 |
706 bool NativeBackendGnome::GetBlacklistLogins( | 703 bool NativeBackendGnome::GetBlacklistLogins( |
707 ScopedVector<autofill::PasswordForm>* forms) { | 704 ScopedVector<autofill::PasswordForm>* forms) { |
708 return GetLoginsList(false, forms); | 705 return GetLoginsList(false, forms); |
709 } | 706 } |
710 | 707 |
711 bool NativeBackendGnome::GetLoginsList( | 708 bool NativeBackendGnome::GetLoginsList( |
712 bool autofillable, | 709 bool autofillable, |
713 ScopedVector<autofill::PasswordForm>* forms) { | 710 ScopedVector<autofill::PasswordForm>* forms) { |
714 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 711 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
712 forms->clear(); | |
715 | 713 |
716 uint32_t blacklisted_by_user = !autofillable; | 714 uint32_t blacklisted_by_user = !autofillable; |
717 | 715 |
718 GKRMethod method; | 716 GKRMethod method; |
719 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 717 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
720 base::Bind(&GKRMethod::GetLoginsList, | 718 base::Bind(&GKRMethod::GetLoginsList, |
721 base::Unretained(&method), | 719 base::Unretained(&method), |
722 blacklisted_by_user, app_string_.c_str())); | 720 blacklisted_by_user, app_string_.c_str())); |
723 GnomeKeyringResult result = method.WaitResult(forms); | 721 GnomeKeyringResult result = method.WaitResult(forms); |
724 if (result == GNOME_KEYRING_RESULT_NO_MATCH) | 722 if (result == GNOME_KEYRING_RESULT_NO_MATCH) |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
801 } | 799 } |
802 return ok; | 800 return ok; |
803 } | 801 } |
804 | 802 |
805 std::string NativeBackendGnome::GetProfileSpecificAppString() const { | 803 std::string NativeBackendGnome::GetProfileSpecificAppString() const { |
806 // Originally, the application string was always just "chrome" and used only | 804 // Originally, the application string was always just "chrome" and used only |
807 // so that we had *something* to search for since GNOME Keyring won't search | 805 // so that we had *something* to search for since GNOME Keyring won't search |
808 // for nothing. Now we use it to distinguish passwords for different profiles. | 806 // for nothing. Now we use it to distinguish passwords for different profiles. |
809 return base::StringPrintf("%s-%d", kGnomeKeyringAppString, profile_id_); | 807 return base::StringPrintf("%s-%d", kGnomeKeyringAppString, profile_id_); |
810 } | 808 } |
OLD | NEW |