OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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_mac.h" | 5 #include "chrome/browser/password_manager/password_store_mac.h" |
6 #include "chrome/browser/password_manager/password_store_mac_internal.h" | 6 #include "chrome/browser/password_manager/password_store_mac_internal.h" |
7 | 7 |
8 #include <CoreServices/CoreServices.h> | 8 #include <CoreServices/CoreServices.h> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 OSStatus result = keychain_->SearchCreateFromAttributes( | 136 OSStatus result = keychain_->SearchCreateFromAttributes( |
137 NULL, kSecInternetPasswordItemClass, &search_attributes_, &search_ref_); | 137 NULL, kSecInternetPasswordItemClass, &search_attributes_, &search_ref_); |
138 | 138 |
139 if (result != noErr) { | 139 if (result != noErr) { |
140 LOG(ERROR) << "Keychain lookup failed with error " << result; | 140 LOG(ERROR) << "Keychain lookup failed with error " << result; |
141 return; | 141 return; |
142 } | 142 } |
143 | 143 |
144 SecKeychainItemRef keychain_item; | 144 SecKeychainItemRef keychain_item; |
145 while (keychain_->SearchCopyNext(search_ref_, &keychain_item) == noErr) { | 145 while (keychain_->SearchCopyNext(search_ref_, &keychain_item) == noErr) { |
146 // Consumer is responsible for deleting the forms when they are done. | 146 // Consumer is responsible for freeing the items. |
147 items->push_back(keychain_item); | 147 items->push_back(keychain_item); |
148 } | 148 } |
149 | 149 |
150 keychain_->Free(search_ref_); | 150 keychain_->Free(search_ref_); |
151 search_ref_ = NULL; | 151 search_ref_ = NULL; |
152 } | 152 } |
153 | 153 |
154 #pragma mark - | 154 #pragma mark - |
155 | 155 |
156 // TODO(stuartmorgan): Convert most of this to private helpers in | 156 // TODO(stuartmorgan): Convert most of this to private helpers in |
157 // MacKeychainPaswordFormAdapter once it has sufficient higher-level public | 157 // MacKeychainPaswordFormAdapter once it has sufficient higher-level public |
158 // methods to provide test coverage. | 158 // methods to provide test coverage. |
159 namespace internal_keychain_helpers { | 159 namespace internal_keychain_helpers { |
160 | 160 |
161 // Takes a PasswordForm's signon_realm and parses it into its component parts, | |
162 // which are returned though the appropriate out parameters. | |
163 // Returns true if it can be successfully parsed, in which case all out params | |
164 // that are non-NULL will be set. If there is no port, port will be 0. | |
165 // If the return value is false, the state of the our params is undefined. | |
166 // | |
167 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. | |
168 bool ExtractSignonRealmComponents(const std::string& signon_realm, | |
169 std::string* server, int* port, | |
170 bool* is_secure, | |
171 std::string* security_domain) { | |
172 // The signon_realm will be the Origin portion of a URL for an HTML form, | |
173 // and the same but with the security domain as a path for HTTP auth. | |
174 GURL realm_as_url(signon_realm); | |
175 if (!realm_as_url.is_valid()) { | |
176 return false; | |
177 } | |
178 | |
179 if (server) | |
180 *server = realm_as_url.host(); | |
181 if (is_secure) | |
182 *is_secure = realm_as_url.SchemeIsSecure(); | |
183 if (port) | |
184 *port = realm_as_url.has_port() ? atoi(realm_as_url.port().c_str()) : 0; | |
185 if (security_domain) { | |
186 // Strip the leading '/' off of the path to get the security domain. | |
187 *security_domain = realm_as_url.path().substr(1); | |
188 } | |
189 return true; | |
190 } | |
191 | |
192 // Returns a URL built from the given components. To create a URL without a | 161 // Returns a URL built from the given components. To create a URL without a |
193 // port, pass kAnyPort for the |port| parameter. | 162 // port, pass kAnyPort for the |port| parameter. |
194 GURL URLFromComponents(bool is_secure, const std::string& host, int port, | 163 GURL URLFromComponents(bool is_secure, const std::string& host, int port, |
195 const std::string& path) { | 164 const std::string& path) { |
196 GURL::Replacements url_components; | 165 GURL::Replacements url_components; |
197 std::string scheme(is_secure ? "https" : "http"); | 166 std::string scheme(is_secure ? "https" : "http"); |
198 url_components.SetSchemeStr(scheme); | 167 url_components.SetSchemeStr(scheme); |
199 url_components.SetHostStr(host); | 168 url_components.SetHostStr(host); |
200 std::string port_string; // Must remain in scope until after we do replacing. | 169 std::string port_string; // Must remain in scope until after we do replacing. |
201 if (port != kAnyPort) { | 170 if (port != kAnyPort) { |
(...skipping 28 matching lines...) Expand all Loading... |
230 &exploded_time.minute, &exploded_time.second); | 199 &exploded_time.minute, &exploded_time.second); |
231 free(time_string); | 200 free(time_string); |
232 | 201 |
233 if (assignments == 6) { | 202 if (assignments == 6) { |
234 *time = base::Time::FromUTCExploded(exploded_time); | 203 *time = base::Time::FromUTCExploded(exploded_time); |
235 return true; | 204 return true; |
236 } | 205 } |
237 return false; | 206 return false; |
238 } | 207 } |
239 | 208 |
240 // Returns the Keychain SecAuthenticationType type corresponding to |scheme|. | |
241 SecAuthenticationType AuthTypeForScheme(PasswordForm::Scheme scheme) { | |
242 switch (scheme) { | |
243 case PasswordForm::SCHEME_HTML: return kSecAuthenticationTypeHTMLForm; | |
244 case PasswordForm::SCHEME_BASIC: return kSecAuthenticationTypeHTTPBasic; | |
245 case PasswordForm::SCHEME_DIGEST: return kSecAuthenticationTypeHTTPDigest; | |
246 case PasswordForm::SCHEME_OTHER: return kSecAuthenticationTypeDefault; | |
247 } | |
248 NOTREACHED(); | |
249 return kSecAuthenticationTypeDefault; | |
250 } | |
251 | |
252 // Returns the PasswordForm Scheme corresponding to |auth_type|. | 209 // Returns the PasswordForm Scheme corresponding to |auth_type|. |
253 PasswordForm::Scheme SchemeForAuthType(SecAuthenticationType auth_type) { | 210 PasswordForm::Scheme SchemeForAuthType(SecAuthenticationType auth_type) { |
254 switch (auth_type) { | 211 switch (auth_type) { |
255 case kSecAuthenticationTypeHTMLForm: return PasswordForm::SCHEME_HTML; | 212 case kSecAuthenticationTypeHTMLForm: return PasswordForm::SCHEME_HTML; |
256 case kSecAuthenticationTypeHTTPBasic: return PasswordForm::SCHEME_BASIC; | 213 case kSecAuthenticationTypeHTTPBasic: return PasswordForm::SCHEME_BASIC; |
257 case kSecAuthenticationTypeHTTPDigest: return PasswordForm::SCHEME_DIGEST; | 214 case kSecAuthenticationTypeHTTPDigest: return PasswordForm::SCHEME_DIGEST; |
258 default: return PasswordForm::SCHEME_OTHER; | 215 default: return PasswordForm::SCHEME_OTHER; |
259 } | 216 } |
260 } | 217 } |
261 | 218 |
262 SecKeychainItemRef MatchingKeychainItem(const MacKeychain& keychain, | |
263 const PasswordForm& form) { | |
264 // We don't store blacklist entries in the keychain, so the answer to "what | |
265 // Keychain item goes with this form" is always "nothing" for blacklists. | |
266 if (form.blacklisted_by_user) { | |
267 return NULL; | |
268 } | |
269 | |
270 // Construct a keychain search based on all the unique attributes. | |
271 std::string server; | |
272 std::string security_domain; | |
273 int port; | |
274 bool is_secure; | |
275 if (!ExtractSignonRealmComponents(form.signon_realm, &server, &port, | |
276 &is_secure, &security_domain)) { | |
277 // TODO(stuartmorgan): Proxies will currently fail here, since their | |
278 // signon_realm is not a URL. We need to detect the proxy case and handle | |
279 // it specially. | |
280 return NULL; | |
281 } | |
282 | |
283 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS | |
284 : kSecProtocolTypeHTTP; | |
285 SecAuthenticationType auth_type = AuthTypeForScheme(form.scheme); | |
286 std::string path = form.origin.path(); | |
287 std::string username = WideToUTF8(form.username_value); | |
288 | |
289 KeychainSearch keychain_search(keychain); | |
290 keychain_search.Init(server.c_str(), port, protocol, auth_type, | |
291 (form.scheme == PasswordForm::SCHEME_HTML) ? | |
292 NULL : security_domain.c_str(), | |
293 path.c_str(), username.c_str()); | |
294 | |
295 std::vector<SecKeychainItemRef> matches; | |
296 keychain_search.FindMatchingItems(&matches); | |
297 | |
298 if (matches.size() == 0) { | |
299 return NULL; | |
300 } | |
301 // Free all items after the first, since we won't be returning them. | |
302 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin() + 1; | |
303 i != matches.end(); ++i) { | |
304 keychain.Free(*i); | |
305 } | |
306 return matches[0]; | |
307 } | |
308 | |
309 bool FillPasswordFormFromKeychainItem(const MacKeychain& keychain, | 219 bool FillPasswordFormFromKeychainItem(const MacKeychain& keychain, |
310 const SecKeychainItemRef& keychain_item, | 220 const SecKeychainItemRef& keychain_item, |
311 PasswordForm* form) { | 221 PasswordForm* form) { |
312 DCHECK(form); | 222 DCHECK(form); |
313 | 223 |
314 SecKeychainAttributeInfo attrInfo; | 224 SecKeychainAttributeInfo attrInfo; |
315 UInt32 tags[] = { kSecAccountItemAttr, | 225 UInt32 tags[] = { kSecAccountItemAttr, |
316 kSecServerItemAttr, | 226 kSecServerItemAttr, |
317 kSecPortItemAttr, | 227 kSecPortItemAttr, |
318 kSecPathItemAttr, | 228 kSecPathItemAttr, |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 } | 413 } |
504 | 414 |
505 } // namespace internal_keychain_helpers | 415 } // namespace internal_keychain_helpers |
506 | 416 |
507 #pragma mark - | 417 #pragma mark - |
508 | 418 |
509 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( | 419 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( |
510 MacKeychain* keychain) : keychain_(keychain) { | 420 MacKeychain* keychain) : keychain_(keychain) { |
511 } | 421 } |
512 | 422 |
513 // Returns PasswordForms for each keychain entry matching |form|. | |
514 // Caller is responsible for deleting the returned forms. | |
515 std::vector<PasswordForm*> | 423 std::vector<PasswordForm*> |
516 MacKeychainPasswordFormAdapter::PasswordsMatchingForm( | 424 MacKeychainPasswordFormAdapter::PasswordsMatchingForm( |
517 const PasswordForm& query_form) { | 425 const PasswordForm& query_form) { |
518 std::vector<SecKeychainItemRef> keychain_items = | 426 std::vector<SecKeychainItemRef> keychain_items = |
519 MatchingKeychainItems(query_form.signon_realm, query_form.scheme); | 427 KeychainItemsForFillingForm(query_form); |
520 | 428 |
521 std::vector<PasswordForm*> keychain_forms = | 429 std::vector<PasswordForm*> keychain_forms = |
522 CreateFormsFromKeychainItems(keychain_items); | 430 CreateFormsFromKeychainItems(keychain_items); |
523 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items.begin(); | 431 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items.begin(); |
524 i != keychain_items.end(); ++i) { | 432 i != keychain_items.end(); ++i) { |
525 keychain_->Free(*i); | 433 keychain_->Free(*i); |
526 } | 434 } |
527 return keychain_forms; | 435 return keychain_forms; |
528 } | 436 } |
529 | 437 |
| 438 PasswordForm* MacKeychainPasswordFormAdapter::PasswordExactlyMatchingForm( |
| 439 const PasswordForm& query_form) { |
| 440 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form); |
| 441 if (keychain_item) { |
| 442 PasswordForm* form = new PasswordForm(); |
| 443 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, |
| 444 keychain_item, |
| 445 form); |
| 446 keychain_->Free(keychain_item); |
| 447 return form; |
| 448 } |
| 449 return NULL; |
| 450 } |
| 451 |
530 bool MacKeychainPasswordFormAdapter::AddLogin(const PasswordForm& form) { | 452 bool MacKeychainPasswordFormAdapter::AddLogin(const PasswordForm& form) { |
531 std::string server; | 453 std::string server; |
532 std::string security_domain; | 454 std::string security_domain; |
533 int port; | 455 int port; |
534 bool is_secure; | 456 bool is_secure; |
535 if (!internal_keychain_helpers::ExtractSignonRealmComponents( | 457 if (!ExtractSignonRealmComponents(form.signon_realm, &server, &port, |
536 form.signon_realm, &server, &port, &is_secure, &security_domain)) { | 458 &is_secure, &security_domain)) { |
537 return false; | 459 return false; |
538 } | 460 } |
539 std::string username = WideToUTF8(form.username_value); | 461 std::string username = WideToUTF8(form.username_value); |
540 std::string password = WideToUTF8(form.password_value); | 462 std::string password = WideToUTF8(form.password_value); |
541 std::string path = form.origin.path(); | 463 std::string path = form.origin.path(); |
542 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS | 464 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS |
543 : kSecProtocolTypeHTTP; | 465 : kSecProtocolTypeHTTP; |
544 SecKeychainItemRef new_item = NULL; | 466 SecKeychainItemRef new_item = NULL; |
545 OSStatus result = keychain_->AddInternetPassword( | 467 OSStatus result = keychain_->AddInternetPassword( |
546 NULL, server.size(), server.c_str(), | 468 NULL, server.size(), server.c_str(), |
547 security_domain.size(), security_domain.c_str(), | 469 security_domain.size(), security_domain.c_str(), |
548 username.size(), username.c_str(), | 470 username.size(), username.c_str(), |
549 path.size(), path.c_str(), | 471 path.size(), path.c_str(), |
550 port, protocol, internal_keychain_helpers::AuthTypeForScheme(form.scheme), | 472 port, protocol, AuthTypeForScheme(form.scheme), |
551 password.size(), password.c_str(), &new_item); | 473 password.size(), password.c_str(), &new_item); |
552 | 474 |
553 if (result == noErr) { | 475 if (result == noErr) { |
554 SetKeychainItemCreatorCode(new_item, kChromeKeychainCreatorCode); | 476 SetKeychainItemCreatorCode(new_item, kChromeKeychainCreatorCode); |
555 keychain_->Free(new_item); | 477 keychain_->Free(new_item); |
556 } else if (result == errSecDuplicateItem) { | 478 } else if (result == errSecDuplicateItem) { |
557 // If we collide with an existing item, find and update it instead. | 479 // If we collide with an existing item, find and update it instead. |
558 SecKeychainItemRef existing_item = | 480 SecKeychainItemRef existing_item = KeychainItemForForm(form); |
559 internal_keychain_helpers::MatchingKeychainItem(*keychain_, form); | |
560 if (!existing_item) { | 481 if (!existing_item) { |
561 return false; | 482 return false; |
562 } | 483 } |
563 bool changed = SetKeychainItemPassword(existing_item, password); | 484 bool changed = SetKeychainItemPassword(existing_item, password); |
564 keychain_->Free(existing_item); | 485 keychain_->Free(existing_item); |
565 return changed; | 486 return changed; |
566 } | 487 } |
567 | 488 |
568 return result == noErr; | 489 return result == noErr; |
569 } | 490 } |
570 | 491 |
571 std::vector<PasswordForm*> | 492 std::vector<PasswordForm*> |
572 MacKeychainPasswordFormAdapter::CreateFormsFromKeychainItems( | 493 MacKeychainPasswordFormAdapter::CreateFormsFromKeychainItems( |
573 const std::vector<SecKeychainItemRef>& items) { | 494 const std::vector<SecKeychainItemRef>& items) { |
574 std::vector<PasswordForm*> keychain_forms; | 495 std::vector<PasswordForm*> keychain_forms; |
575 for (std::vector<SecKeychainItemRef>::const_iterator i = items.begin(); | 496 for (std::vector<SecKeychainItemRef>::const_iterator i = items.begin(); |
576 i != items.end(); ++i) { | 497 i != items.end(); ++i) { |
577 PasswordForm* form = new PasswordForm(); | 498 PasswordForm* form = new PasswordForm(); |
578 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, | 499 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, |
579 *i, form)) { | 500 *i, form)) { |
580 keychain_forms.push_back(form); | 501 keychain_forms.push_back(form); |
581 } | 502 } |
582 } | 503 } |
583 return keychain_forms; | 504 return keychain_forms; |
584 } | 505 } |
585 | 506 |
586 // Searches |keychain| for all items usable for the given signon_realm, and | 507 std::vector<SecKeychainItemRef> |
587 // returns them. The caller is responsible for calling keychain->Free | 508 MacKeychainPasswordFormAdapter::KeychainItemsForFillingForm( |
588 // on each of them when it is finished with them. | 509 const PasswordForm& form) { |
| 510 return MatchingKeychainItems(form.signon_realm, form.scheme, NULL, NULL); |
| 511 } |
| 512 |
| 513 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( |
| 514 const PasswordForm& form) { |
| 515 // We don't store blacklist entries in the keychain, so the answer to "what |
| 516 // Keychain item goes with this form" is always "nothing" for blacklists. |
| 517 if (form.blacklisted_by_user) { |
| 518 return NULL; |
| 519 } |
| 520 |
| 521 std::string path = form.origin.path(); |
| 522 std::string username = WideToUTF8(form.username_value); |
| 523 std::vector<SecKeychainItemRef> matches = MatchingKeychainItems( |
| 524 form.signon_realm, form.scheme, path.c_str(), username.c_str()); |
| 525 |
| 526 if (matches.size() == 0) { |
| 527 return NULL; |
| 528 } |
| 529 // Free all items after the first, since we won't be returning them. |
| 530 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin() + 1; |
| 531 i != matches.end(); ++i) { |
| 532 keychain_->Free(*i); |
| 533 } |
| 534 return matches[0]; |
| 535 } |
| 536 |
589 std::vector<SecKeychainItemRef> | 537 std::vector<SecKeychainItemRef> |
590 MacKeychainPasswordFormAdapter::MatchingKeychainItems( | 538 MacKeychainPasswordFormAdapter::MatchingKeychainItems( |
591 const std::string& signon_realm, PasswordForm::Scheme scheme) { | 539 const std::string& signon_realm, |
| 540 webkit_glue::PasswordForm::Scheme scheme, |
| 541 const char* path, const char* username) { |
592 std::vector<SecKeychainItemRef> matches; | 542 std::vector<SecKeychainItemRef> matches; |
593 // Construct a keychain search based on the signon_realm and scheme. | 543 |
594 std::string server; | 544 std::string server; |
595 std::string security_domain; | 545 std::string security_domain; |
596 int port; | 546 int port; |
597 bool is_secure; | 547 bool is_secure; |
598 if (!internal_keychain_helpers::ExtractSignonRealmComponents( | 548 if (!ExtractSignonRealmComponents(signon_realm, &server, &port, |
599 signon_realm, &server, &port, &is_secure, &security_domain)) { | 549 &is_secure, &security_domain)) { |
600 // TODO(stuartmorgan): Proxies will currently fail here, since their | 550 // TODO(stuartmorgan): Proxies will currently fail here, since their |
601 // signon_realm is not a URL. We need to detect the proxy case and handle | 551 // signon_realm is not a URL. We need to detect the proxy case and handle |
602 // it specially. | 552 // it specially. |
603 return matches; | 553 return matches; |
604 } | 554 } |
605 | |
606 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS | 555 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS |
607 : kSecProtocolTypeHTTP; | 556 : kSecProtocolTypeHTTP; |
608 SecAuthenticationType auth_type = | 557 SecAuthenticationType auth_type = AuthTypeForScheme(scheme); |
609 internal_keychain_helpers::AuthTypeForScheme(scheme); | 558 const char* auth_domain = (scheme == PasswordForm::SCHEME_HTML) ? |
| 559 NULL : security_domain.c_str(); |
610 | 560 |
611 KeychainSearch keychain_search(*keychain_); | 561 KeychainSearch keychain_search(*keychain_); |
612 keychain_search.Init(server.c_str(), port, protocol, auth_type, | 562 keychain_search.Init(server.c_str(), port, protocol, auth_type, |
613 (scheme == PasswordForm::SCHEME_HTML) ? | 563 auth_domain, path, username); |
614 NULL : security_domain.c_str(), | |
615 NULL, NULL); | |
616 keychain_search.FindMatchingItems(&matches); | 564 keychain_search.FindMatchingItems(&matches); |
617 return matches; | 565 return matches; |
618 } | 566 } |
619 | 567 |
| 568 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. |
| 569 bool MacKeychainPasswordFormAdapter::ExtractSignonRealmComponents( |
| 570 const std::string& signon_realm, std::string* server, int* port, |
| 571 bool* is_secure, std::string* security_domain) { |
| 572 // The signon_realm will be the Origin portion of a URL for an HTML form, |
| 573 // and the same but with the security domain as a path for HTTP auth. |
| 574 GURL realm_as_url(signon_realm); |
| 575 if (!realm_as_url.is_valid()) { |
| 576 return false; |
| 577 } |
| 578 |
| 579 if (server) |
| 580 *server = realm_as_url.host(); |
| 581 if (is_secure) |
| 582 *is_secure = realm_as_url.SchemeIsSecure(); |
| 583 if (port) |
| 584 *port = realm_as_url.has_port() ? atoi(realm_as_url.port().c_str()) : 0; |
| 585 if (security_domain) { |
| 586 // Strip the leading '/' off of the path to get the security domain. |
| 587 *security_domain = realm_as_url.path().substr(1); |
| 588 } |
| 589 return true; |
| 590 } |
| 591 |
| 592 // Returns the Keychain SecAuthenticationType type corresponding to |scheme|. |
| 593 SecAuthenticationType MacKeychainPasswordFormAdapter::AuthTypeForScheme( |
| 594 PasswordForm::Scheme scheme) { |
| 595 switch (scheme) { |
| 596 case PasswordForm::SCHEME_HTML: return kSecAuthenticationTypeHTMLForm; |
| 597 case PasswordForm::SCHEME_BASIC: return kSecAuthenticationTypeHTTPBasic; |
| 598 case PasswordForm::SCHEME_DIGEST: return kSecAuthenticationTypeHTTPDigest; |
| 599 case PasswordForm::SCHEME_OTHER: return kSecAuthenticationTypeDefault; |
| 600 } |
| 601 NOTREACHED(); |
| 602 return kSecAuthenticationTypeDefault; |
| 603 } |
| 604 |
620 bool MacKeychainPasswordFormAdapter::SetKeychainItemPassword( | 605 bool MacKeychainPasswordFormAdapter::SetKeychainItemPassword( |
621 const SecKeychainItemRef& keychain_item, const std::string& password) { | 606 const SecKeychainItemRef& keychain_item, const std::string& password) { |
622 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, NULL, | 607 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, NULL, |
623 password.size(), | 608 password.size(), |
624 password.c_str()); | 609 password.c_str()); |
625 return result == noErr; | 610 return result == noErr; |
626 } | 611 } |
627 | 612 |
628 bool MacKeychainPasswordFormAdapter::SetKeychainItemCreatorCode( | 613 bool MacKeychainPasswordFormAdapter::SetKeychainItemCreatorCode( |
629 const SecKeychainItemRef& keychain_item, OSType creator_code) { | 614 const SecKeychainItemRef& keychain_item, OSType creator_code) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 for (std::vector<PasswordForm*>::iterator i = database_forms.begin(); | 674 for (std::vector<PasswordForm*>::iterator i = database_forms.begin(); |
690 i != database_forms.end(); ++i) { | 675 i != database_forms.end(); ++i) { |
691 login_metadata_db_->RemoveLogin(**i); | 676 login_metadata_db_->RemoveLogin(**i); |
692 } | 677 } |
693 // Delete the forms we aren't returning. | 678 // Delete the forms we aren't returning. |
694 STLDeleteElements(&database_forms); | 679 STLDeleteElements(&database_forms); |
695 STLDeleteElements(&keychain_forms); | 680 STLDeleteElements(&keychain_forms); |
696 | 681 |
697 NotifyConsumer(request, merged_forms); | 682 NotifyConsumer(request, merged_forms); |
698 } | 683 } |
OLD | NEW |