| Index: chrome/browser/mac/keychain_reauthorize.mm | 
| diff --git a/chrome/browser/mac/keychain_reauthorize.mm b/chrome/browser/mac/keychain_reauthorize.mm | 
| deleted file mode 100644 | 
| index 24d046db710f7e682dba897e217e780cfec9225b..0000000000000000000000000000000000000000 | 
| --- a/chrome/browser/mac/keychain_reauthorize.mm | 
| +++ /dev/null | 
| @@ -1,526 +0,0 @@ | 
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| -// Use of this source code is governed by a BSD-style license that can be | 
| -// found in the LICENSE file. | 
| - | 
| -#include "chrome/browser/mac/keychain_reauthorize.h" | 
| - | 
| -#import <Foundation/Foundation.h> | 
| -#include <Security/Security.h> | 
| - | 
| -#include <algorithm> | 
| -#include <string> | 
| -#include <vector> | 
| - | 
| -#include "base/basictypes.h" | 
| -#include "base/mac/foundation_util.h" | 
| -#include "base/mac/scoped_cftyperef.h" | 
| -#include "base/memory/scoped_ptr.h" | 
| -#include "base/metrics/histogram.h" | 
| -#include "base/strings/stringprintf.h" | 
| -#include "base/strings/sys_string_conversions.h" | 
| -#include "chrome/browser/mac/security_wrappers.h" | 
| - | 
| -namespace chrome { | 
| - | 
| -namespace { | 
| - | 
| -// Returns the requirement string embedded within a SecTrustedApplicationRef, | 
| -// or an empty string on error. | 
| -std::string RequirementStringForApplication( | 
| -    SecTrustedApplicationRef application); | 
| - | 
| -// Returns the set of requirement strings that ought to be reauthorized. In a | 
| -// bundled application, the requirement string from |application| will also be | 
| -// added to the hard-coded list. This allows an at-launch reauthorization to | 
| -// re-reauthorize anything done by a previous at-update reauthorization. | 
| -// Although items reauthorized during the at-update step will work properly in | 
| -// every way, they contain a reference to the missing reauthorization stub | 
| -// executable from the disk image in the Keychain, resulting in no icon and | 
| -// a weird name like "com.google" (non-Canary) or "com.google.Chrome" | 
| -// (Canary). Because reauthorization is controlled by a preference that limits | 
| -// it to a single successful run at update and a single successful run at | 
| -// launch, protection already exists against perpetually reauthorizing items. | 
| -// This addition exists simply to make the Keychain Access UI match | 
| -// expectations. | 
| -std::vector<std::string> GetRequirementMatches( | 
| -    SecTrustedApplicationRef application); | 
| - | 
| -// Reauthorizes an ACL by examining all of the applications it names, and upon | 
| -// finding any whose requirement matches any element of requirement_matches, | 
| -// replaces them with this_application. At most one instance of | 
| -// this_application will be added to the ACL. Subsequent applications whose | 
| -// requirement matches any element of requirement_matches will be removed from | 
| -// the ACL. Only the ACL is changed, nothing is written to disk. Returns true | 
| -// if any reauthorization is performed and thus acl is modified, and false | 
| -// otherwise. | 
| -bool ReauthorizeACL( | 
| -    SecACLRef acl, | 
| -    const std::vector<std::string>& requirement_matches, | 
| -    SecTrustedApplicationRef this_application); | 
| - | 
| -// Reauthorizes a list of ACLs by calling ReauthorizeACL for each ACL in the | 
| -// list. Only the ACL list is changed, nothing is written to disk. Returns | 
| -// true if ReauthorizeTrue returns true for any ACL in acl_list, indicating | 
| -// that at least one ACL in acl_list was modified and thus at least one child | 
| -// child of acl_list was reauthorized. | 
| -bool ReauthorizeACLList( | 
| -    CFArrayRef acl_list, | 
| -    const std::vector<std::string>& requirement_matches, | 
| -    SecTrustedApplicationRef this_application); | 
| - | 
| -// Reauthorizes a SecKeychainItemRef by calling ReauthorizeACLList to perform | 
| -// reauthorization on all ACLs that it contains. Nothing is written to disk. | 
| -// If any reauthorization was performed, returns a CrSKeychainItemAndAccess | 
| -// object containing the item and its access information. Otherwise, returns | 
| -// NULL. | 
| -CrSKeychainItemAndAccess* KCItemToKCItemAndReauthorizedAccess( | 
| -    SecKeychainItemRef item, | 
| -    const std::vector<std::string>& requirement_matches, | 
| -    SecTrustedApplicationRef this_application); | 
| - | 
| -// Reauthorizes multiple Keychain items by calling | 
| -// KCItemToKCItemAndReauthorizedAccess for each item returned by a Keychain | 
| -// search. Nothing is written to disk. Reauthorized items are returned. | 
| -std::vector<CrSKeychainItemAndAccess> KCSearchToKCItemsAndReauthorizedAccesses( | 
| -    SecKeychainSearchRef search, | 
| -    const std::vector<std::string>& requirement_matches, | 
| -    SecTrustedApplicationRef this_application); | 
| - | 
| -// Given a SecKeychainAttributeList, strips out any zero-length attributes and | 
| -// returns a vector containing the remaining attributes. | 
| -std::vector<SecKeychainAttribute> KCAttributesWithoutZeroLength( | 
| -    SecKeychainAttributeList* old_attribute_list); | 
| - | 
| -// Given a CrSKeychainItemAndAccess that has had its access field | 
| -// reauthorized, places the reauthorized form into the Keychain by deleting | 
| -// the old item and replacing it with a new one whose access policy matches | 
| -// the reauthorized form. The new item is written to disk and becomes part of | 
| -// the Keychain, replacing what had been there previously. | 
| -void WriteKCItemAndReauthorizedAccess( | 
| -    const CrSKeychainItemAndAccess& item_and_reauthorized_access); | 
| - | 
| -// Given a vector of CrSKeychainItemAndAccess objects, places the reauthorized | 
| -// forms of all of them into the Keychain by calling | 
| -// WriteKCItemAndReauthorizedAccess for each. The new items are written to | 
| -// disk and become part of the Keychain, replacing what had been there | 
| -// previously. | 
| -void WriteKCItemsAndReauthorizedAccesses( | 
| -    const std::vector<CrSKeychainItemAndAccess>& | 
| -        items_and_reauthorized_accesses); | 
| - | 
| -}  // namespace | 
| - | 
| -void KeychainReauthorize() { | 
| -  ScopedSecKeychainSetUserInteractionAllowed user_interaction_allowed(FALSE); | 
| - | 
| -  // Apple's documentation (Keychain Services Reference, Constants/Mac OS X | 
| -  // Keychain Services API Constants/Keychain Item Class Constants) says to | 
| -  // use CSSM_DL_DB_RECORD_ALL_KEYS, but that doesn't work. | 
| -  // CSSM_DL_DB_RECORD_ANY (as used by SecurityTool's keychain-dump) does | 
| -  // work. | 
| -  base::ScopedCFTypeRef<SecKeychainSearchRef> search( | 
| -      CrSKeychainSearchCreateFromAttributes(NULL, CSSM_DL_DB_RECORD_ANY, NULL)); | 
| - | 
| -  base::ScopedCFTypeRef<SecTrustedApplicationRef> this_application( | 
| -      CrSTrustedApplicationCreateFromPath(NULL)); | 
| - | 
| -  std::vector<std::string> requirement_matches = | 
| -      GetRequirementMatches(this_application); | 
| - | 
| -  std::vector<CrSKeychainItemAndAccess> items_and_reauthorized_accesses = | 
| -      KCSearchToKCItemsAndReauthorizedAccesses(search, | 
| -                                               requirement_matches, | 
| -                                               this_application); | 
| - | 
| -  WriteKCItemsAndReauthorizedAccesses(items_and_reauthorized_accesses); | 
| -} | 
| - | 
| -void KeychainReauthorizeIfNeeded(NSString* pref_key, int max_tries) { | 
| -  NSUserDefaults* user_defaults = [NSUserDefaults standardUserDefaults]; | 
| -  int pref_value = [user_defaults integerForKey:pref_key]; | 
| - | 
| -  if (pref_value < max_tries) { | 
| -    if (pref_value > 0) { | 
| -      // Logs the number of previous tries that didn't complete. | 
| -      if (base::mac::AmIBundled()) { | 
| -        UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeeded", pref_value); | 
| -      } else { | 
| -        UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededAtUpdate", | 
| -                             pref_value); | 
| -      } | 
| -    } | 
| - | 
| -    ++pref_value; | 
| -    [user_defaults setInteger:pref_value forKey:pref_key]; | 
| -    [user_defaults synchronize]; | 
| - | 
| -    KeychainReauthorize(); | 
| - | 
| -    [user_defaults setInteger:max_tries forKey:pref_key]; | 
| -    NSString* success_pref_key = [pref_key stringByAppendingString:@"Success"]; | 
| -    [user_defaults setBool:YES forKey:success_pref_key]; | 
| -    [user_defaults synchronize]; | 
| - | 
| -    // Logs the try number (1, 2) that succeeded. | 
| -    if (base::mac::AmIBundled()) { | 
| -      UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededSuccess", | 
| -                           pref_value); | 
| -    } else { | 
| -      UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededAtUpdateSuccess", | 
| -                           pref_value); | 
| -    } | 
| -  } | 
| -} | 
| - | 
| -namespace { | 
| - | 
| -std::string RequirementStringForApplication( | 
| -    SecTrustedApplicationRef application) { | 
| -  base::ScopedCFTypeRef<SecRequirementRef> requirement( | 
| -      CrSTrustedApplicationCopyRequirement(application)); | 
| -  base::ScopedCFTypeRef<CFStringRef> requirement_string_cf( | 
| -      CrSRequirementCopyString(requirement, kSecCSDefaultFlags)); | 
| -  if (!requirement_string_cf) { | 
| -    return std::string(); | 
| -  } | 
| - | 
| -  std::string requirement_string = | 
| -      base::SysCFStringRefToUTF8(requirement_string_cf); | 
| - | 
| -  return requirement_string; | 
| -} | 
| - | 
| -std::vector<std::string> GetRequirementMatches( | 
| -      SecTrustedApplicationRef application) { | 
| -  // See the designated requirement for a signed released build: | 
| -  // codesign -d -r- "Google Chrome.app" | 
| -  // | 
| -  // Export the certificates from a signed released build: | 
| -  // codesign -v --extract-certificates=/tmp/cert. "Google Chrome.app" | 
| -  // (The extracted leaf certificate is at /tmp/cert.0; intermediates and root | 
| -  // are at successive numbers.) | 
| -  // | 
| -  // Show some information about the exported certificates: | 
| -  // openssl x509 -inform DER -in /tmp/cert.0 -noout -text -fingerprint | 
| -  // (The "SHA1 Fingerprint" value printed by -fingerprint should match the | 
| -  // hash used in a codesign designated requirement after allowing for obvious | 
| -  // formatting differences.) | 
| - | 
| -  const char* const kIdentifierMatches[] = { | 
| -#if defined(GOOGLE_CHROME_BUILD) | 
| -    "com.google.Chrome", | 
| -    "com.google.Chrome.canary", | 
| -#else | 
| -    "org.chromium.Chromium", | 
| -#endif | 
| -  }; | 
| - | 
| -  const char* const kLeafCertificateHashMatches[] = { | 
| -    // Only official released builds of Google Chrome have ever been signed | 
| -    // (with a certificate that anyone knows about or cares about). | 
| -#if defined(GOOGLE_CHROME_BUILD) | 
| -    // This is the new certificate that has not yet been used to sign Chrome, | 
| -    // but will be. Once used, the reauthorization code will become obsolete | 
| -    // until it's needed for some other purpose in the future. | 
| -    // Subject: UID=EQHXZ8M8AV, CN=Developer ID Application: Google Inc., | 
| -    //     OU=EQHXZ8M8AV, O=Google Inc., C=US | 
| -    // Issuer: CN=Developer ID Certification Authority, | 
| -    //     OU=Apple Certification Authority, O=Apple Inc., C=US | 
| -    // Validity: 2012-04-26 14:10:10 UTC to 2017-04-27 14:10:10 UTC | 
| -    // "85cee8254216185620ddc8851c7a9fc4dfe120ef", | 
| - | 
| -    // This certificate was used on 2011-12-20 and 2011-12-21, but the "since | 
| -    // 2010-07-19" one below was restored afterwards as an interim fix to the | 
| -    // Keychain authorization problem. See http://crbug.com/108238 and | 
| -    // http://crbug.com/62605. | 
| -    // Subject: C=US, ST=California, L=Mountain View, O=Google Inc, | 
| -    //     OU=Digital ID Class 3 - Java Object Signing, CN=Google Inc | 
| -    // Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, | 
| -    //     OU=Terms of use at https://www.verisign.com/rpa (c)10, | 
| -    //     CN=VeriSign Class 3 Code Signing 2010 CA | 
| -    // Validity: 2011-11-14 00:00:00 UTC to 2014-11-13 23:59:59 UTC | 
| -    "06c92bec3bbf32068cb9208563d004169448ee21", | 
| - | 
| -    // This certificate has been used since 2010-07-19, except for the brief | 
| -    // period when the certificate above was used. | 
| -    // Subject: C=US, ST=California, L=Mountain View, O=Google Inc, | 
| -    //     OU=Digital ID Class 3 - Java Object Signing, CN=Google Inc | 
| -    // Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, | 
| -    //    OU=Terms of use at https://www.verisign.com/rpa (c)09, | 
| -    //    CN=VeriSign Class 3 Code Signing 2009-2 CA | 
| -    // Validity: 2010-02-22 00:00:00 UTC to 2012-02-22 23:59:59 UTC | 
| -    "9481882581d8178db8b1649c0eaa4f9eb11288f0", | 
| - | 
| -    // This certificate was used for all public Chrome releases prior to | 
| -    // 2010-07-19. | 
| -    // Subject: C=US, ST=California, L=Mountain View, O=Google Inc, | 
| -    //     OU=Digital ID Class 3 - Netscape Object Signing, CN=Google Inc | 
| -    // Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, | 
| -    //     OU=Terms of use at https://www.verisign.com/rpa (c)04, | 
| -    //     CN=VeriSign Class 3 Code Signing 2004 CA | 
| -    // Validity: 2007-06-19 00:00:00 UTC to 2010-06-18 23:59:59 UTC | 
| -    "fe5008fe0da7a2033816752d6eafe95214f5a7e1", | 
| -#endif | 
| -  }; | 
| - | 
| -  std::vector<std::string> requirement_matches; | 
| -  requirement_matches.reserve(arraysize(kIdentifierMatches) * | 
| -                              ARRAYSIZE_UNSAFE(kLeafCertificateHashMatches)); | 
| - | 
| -  for (size_t identifier_index = 0; | 
| -       identifier_index < arraysize(kIdentifierMatches); | 
| -       ++identifier_index) { | 
| -    for (size_t leaf_certificate_hash_index = 0; | 
| -         leaf_certificate_hash_index < | 
| -             ARRAYSIZE_UNSAFE(kLeafCertificateHashMatches); | 
| -         ++leaf_certificate_hash_index) { | 
| -      requirement_matches.push_back(base::StringPrintf( | 
| -          "identifier \"%s\" and certificate leaf = H\"%s\"", | 
| -          kIdentifierMatches[identifier_index], | 
| -          kLeafCertificateHashMatches[leaf_certificate_hash_index])); | 
| -    } | 
| -  } | 
| - | 
| -  if (application && base::mac::AmIBundled()) { | 
| -    std::string application_requirement = | 
| -        RequirementStringForApplication(application); | 
| -    requirement_matches.push_back(application_requirement); | 
| -  } | 
| - | 
| -  return requirement_matches; | 
| -} | 
| - | 
| -std::vector<CrSKeychainItemAndAccess> KCSearchToKCItemsAndReauthorizedAccesses( | 
| -    SecKeychainSearchRef search, | 
| -    const std::vector<std::string>& requirement_matches, | 
| -    SecTrustedApplicationRef this_application) { | 
| -  std::vector<CrSKeychainItemAndAccess> items_and_accesses; | 
| - | 
| -  base::ScopedCFTypeRef<SecKeychainItemRef> item; | 
| -  while (item.reset(CrSKeychainSearchCopyNext(search)), item) { | 
| -    scoped_ptr<CrSKeychainItemAndAccess> item_and_access( | 
| -        KCItemToKCItemAndReauthorizedAccess(item, | 
| -                                            requirement_matches, | 
| -                                            this_application)); | 
| - | 
| -    if (item_and_access.get()) { | 
| -      items_and_accesses.push_back(*item_and_access); | 
| -    } | 
| -  } | 
| - | 
| -  return items_and_accesses; | 
| -} | 
| - | 
| -CrSKeychainItemAndAccess* KCItemToKCItemAndReauthorizedAccess( | 
| -    SecKeychainItemRef item, | 
| -    const std::vector<std::string>& requirement_matches, | 
| -    SecTrustedApplicationRef this_application) { | 
| -  if (!CrSKeychainItemTestAccess(item)) { | 
| -    return NULL; | 
| -  } | 
| - | 
| -  base::ScopedCFTypeRef<SecAccessRef> access(CrSKeychainItemCopyAccess(item)); | 
| -  base::ScopedCFTypeRef<CFArrayRef> acl_list(CrSAccessCopyACLList(access)); | 
| -  if (!acl_list) { | 
| -    return NULL; | 
| -  } | 
| - | 
| -  bool acl_list_modified = ReauthorizeACLList(acl_list, | 
| -                                              requirement_matches, | 
| -                                              this_application); | 
| -  if (!acl_list_modified) { | 
| -    return NULL; | 
| -  } | 
| - | 
| -  return new CrSKeychainItemAndAccess(item, access); | 
| -} | 
| - | 
| -bool ReauthorizeACLList( | 
| -    CFArrayRef acl_list, | 
| -    const std::vector<std::string>& requirement_matches, | 
| -    SecTrustedApplicationRef this_application) { | 
| -  bool acl_list_modified = false; | 
| - | 
| -  CFIndex acl_count = CFArrayGetCount(acl_list); | 
| -  for (CFIndex acl_index = 0; acl_index < acl_count; ++acl_index) { | 
| -    SecACLRef acl = base::mac::CFCast<SecACLRef>( | 
| -        CFArrayGetValueAtIndex(acl_list, acl_index)); | 
| -    if (!acl) { | 
| -      continue; | 
| -    } | 
| - | 
| -    if (ReauthorizeACL(acl, requirement_matches, this_application)) { | 
| -      acl_list_modified = true; | 
| -    } | 
| -  } | 
| - | 
| -  return acl_list_modified; | 
| -} | 
| - | 
| -bool ReauthorizeACL( | 
| -    SecACLRef acl, | 
| -    const std::vector<std::string>& requirement_matches, | 
| -    SecTrustedApplicationRef this_application) { | 
| -  scoped_ptr<CrSACLSimpleContents> acl_simple_contents( | 
| -      CrSACLCopySimpleContents(acl)); | 
| -  if (!acl_simple_contents.get() || | 
| -      !acl_simple_contents->application_list) { | 
| -    return false; | 
| -  } | 
| - | 
| -  CFMutableArrayRef application_list_mutable = NULL; | 
| -  bool added_this_application = false; | 
| - | 
| -  CFIndex application_count = | 
| -      CFArrayGetCount(acl_simple_contents->application_list); | 
| -  for (CFIndex application_index = 0; | 
| -       application_index < application_count; | 
| -       ++application_index) { | 
| -    SecTrustedApplicationRef application = | 
| -        base::mac::CFCast<SecTrustedApplicationRef>( | 
| -            CFArrayGetValueAtIndex(acl_simple_contents->application_list, | 
| -                                   application_index)); | 
| -    std::string requirement_string = | 
| -        RequirementStringForApplication(application); | 
| -    if (requirement_string.empty()) { | 
| -      continue; | 
| -    } | 
| - | 
| -    if (std::find(requirement_matches.begin(), | 
| -                  requirement_matches.end(), | 
| -                  requirement_string) != requirement_matches.end()) { | 
| -      if (!application_list_mutable) { | 
| -        application_list_mutable = | 
| -            CFArrayCreateMutableCopy(NULL, | 
| -                                     application_count, | 
| -                                     acl_simple_contents->application_list); | 
| -        acl_simple_contents->application_list.reset( | 
| -            application_list_mutable); | 
| -      } | 
| - | 
| -      if (!added_this_application) { | 
| -        CFArraySetValueAtIndex(application_list_mutable, | 
| -                               application_index, | 
| -                               this_application); | 
| -        added_this_application = true; | 
| -      } else { | 
| -        // Even though it's more bookkeeping to walk a list in the forward | 
| -        // direction when there are removals, it's done here anyway to | 
| -        // keep this_application at the position of the first match. | 
| -        CFArrayRemoveValueAtIndex(application_list_mutable, | 
| -                                  application_index); | 
| -        --application_index; | 
| -        --application_count; | 
| -      } | 
| -    } | 
| -  } | 
| - | 
| -  if (!application_list_mutable) { | 
| -    return false; | 
| -  } | 
| - | 
| -  if (!CrSACLSetSimpleContents(acl, *acl_simple_contents.get())) { | 
| -    return false; | 
| -  } | 
| - | 
| -  return true; | 
| -} | 
| - | 
| -void WriteKCItemsAndReauthorizedAccesses( | 
| -    const std::vector<CrSKeychainItemAndAccess>& | 
| -        items_and_reauthorized_accesses) { | 
| -  for (std::vector<CrSKeychainItemAndAccess>::const_iterator iterator = | 
| -           items_and_reauthorized_accesses.begin(); | 
| -       iterator != items_and_reauthorized_accesses.end(); | 
| -       ++iterator) { | 
| -    WriteKCItemAndReauthorizedAccess(*iterator); | 
| -  } | 
| -} | 
| - | 
| -void WriteKCItemAndReauthorizedAccess( | 
| -    const CrSKeychainItemAndAccess& item_and_reauthorized_access) { | 
| -  SecKeychainItemRef old_item = item_and_reauthorized_access.item(); | 
| -  base::ScopedCFTypeRef<SecKeychainRef> keychain( | 
| -      CrSKeychainItemCopyKeychain(old_item)); | 
| - | 
| -  ScopedCrSKeychainItemAttributesAndData old_attributes_and_data( | 
| -      CrSKeychainItemCopyAttributesAndData(keychain, old_item)); | 
| -  if (!old_attributes_and_data.get()) { | 
| -    return; | 
| -  } | 
| - | 
| -  // CrSKeychainItemCreateFromContent (SecKeychainItemCreateFromContent) | 
| -  // returns errKCNoSuchAttr (errSecNoSuchAttr) when asked to add an item of | 
| -  // type kSecPrivateKeyItemClass. This would happen after the original | 
| -  // private key was deleted, resulting in data loss. I can't figure out how | 
| -  // SecKeychainItemCreateFromContent wants private keys added. Skip them, | 
| -  // only doing the reauthorization for Keychain item types known to work, | 
| -  // the item types expected to be used by most users and those that are | 
| -  // synced. See http://crbug.com/130738 and | 
| -  // http://lists.apple.com/archives/apple-cdsa/2006/Jan/msg00025.html . | 
| -  switch (old_attributes_and_data.item_class()) { | 
| -    case kSecInternetPasswordItemClass: | 
| -    case kSecGenericPasswordItemClass: | 
| -      break; | 
| -    default: | 
| -      return; | 
| -  } | 
| - | 
| -  // SecKeychainItemCreateFromContent fails if any attribute is zero-length, | 
| -  // but old_attributes_and_data can contain zero-length attributes. Create | 
| -  // a new attribute list devoid of zero-length attributes. | 
| -  // | 
| -  // This is awkward: only the logic to build the | 
| -  // std::vector<SecKeychainAttribute> is in KCAttributesWithoutZeroLength | 
| -  // because the storage used for the new attribute list (the vector) needs to | 
| -  // persist through the lifetime of this function. | 
| -  // KCAttributesWithoutZeroLength doesn't return a | 
| -  // CrSKeychainItemAttributesAndData (which could be held here in a | 
| -  // ScopedCrSKeychainItemAttributesAndData) because it's more convenient to | 
| -  // build the attribute list using std::vector and point the data at the copy | 
| -  // in old_attributes_and_data, thus making nothing in new_attributes a | 
| -  // strongly-held reference. | 
| -  std::vector<SecKeychainAttribute> new_attributes = | 
| -      KCAttributesWithoutZeroLength(old_attributes_and_data.attribute_list()); | 
| -  SecKeychainAttributeList new_attribute_list; | 
| -  new_attribute_list.count = new_attributes.size(); | 
| -  new_attribute_list.attr = | 
| -      new_attribute_list.count ? &new_attributes[0] : NULL; | 
| -  CrSKeychainItemAttributesAndData new_attributes_and_data = | 
| -      *old_attributes_and_data.get(); | 
| -  new_attributes_and_data.attribute_list = &new_attribute_list; | 
| - | 
| -  // Delete the item last, to give everything else above a chance to bail | 
| -  // out early, and to ensure that the old item is still present while it | 
| -  // may still be used by the above code. | 
| -  if (!CrSKeychainItemDelete(old_item)) { | 
| -    return; | 
| -  } | 
| - | 
| -  base::ScopedCFTypeRef<SecKeychainItemRef> new_item( | 
| -      CrSKeychainItemCreateFromContent(new_attributes_and_data, | 
| -                                       keychain, | 
| -                                       item_and_reauthorized_access.access())); | 
| -} | 
| - | 
| -std::vector<SecKeychainAttribute> KCAttributesWithoutZeroLength( | 
| -    SecKeychainAttributeList* old_attribute_list) { | 
| -  UInt32 old_attribute_count = old_attribute_list->count; | 
| -  std::vector<SecKeychainAttribute> new_attributes; | 
| -  new_attributes.reserve(old_attribute_count); | 
| -  for (UInt32 old_attribute_index = 0; | 
| -       old_attribute_index < old_attribute_count; | 
| -       ++old_attribute_index) { | 
| -    SecKeychainAttribute* attribute = | 
| -        &old_attribute_list->attr[old_attribute_index]; | 
| -    if (attribute->length) { | 
| -      new_attributes.push_back(*attribute); | 
| -    } | 
| -  } | 
| - | 
| -  return new_attributes; | 
| -} | 
| - | 
| -}  // namespace | 
| - | 
| -}  // namespace chrome | 
|  |