Rename MacKeychain to AppleKeychain
Rename MacKeychain to AppleKeychain and add mac and iOS specific implementations (crypto/apple_keychain_ios.mm and crypto/apple_keychain_mac.mm). Rename MockKeychain to MockAppleKeychain and split its implementations in 3 files crypto/mock_apple_keychain.cc, crypto/mock_apple_keychain_ios.cc and crypto/mock_apple_keychain_mac.cc). Review URL: https://chromiumcodereview.appspot.com/10875029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@154123 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@ -10,11 +10,11 @@
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/utf_string_conversions.h"
|
||||
#include "chrome/browser/password_manager/encryptor_password_mac.h"
|
||||
#include "crypto/apple_keychain.h"
|
||||
#include "crypto/encryptor.h"
|
||||
#include "crypto/keychain_mac.h"
|
||||
#include "crypto/symmetric_key.h"
|
||||
|
||||
using crypto::MacKeychain;
|
||||
using crypto::AppleKeychain;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -45,7 +45,7 @@ crypto::SymmetricKey* GetEncryptionKey() {
|
||||
if (use_mock_keychain) {
|
||||
password = "mock_password";
|
||||
} else {
|
||||
MacKeychain keychain;
|
||||
AppleKeychain keychain;
|
||||
EncryptorPassword encryptor_password(keychain);
|
||||
password = encryptor_password.GetEncryptorPassword();
|
||||
}
|
||||
|
@ -10,12 +10,12 @@
|
||||
#include "base/basictypes.h"
|
||||
|
||||
namespace crypto {
|
||||
class MacKeychain;
|
||||
class AppleKeychain;
|
||||
} // namespace crypto
|
||||
|
||||
class EncryptorPassword {
|
||||
public:
|
||||
explicit EncryptorPassword(const crypto::MacKeychain& keychain)
|
||||
explicit EncryptorPassword(const crypto::AppleKeychain& keychain)
|
||||
: keychain_(keychain) {
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ class EncryptorPassword {
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(EncryptorPassword);
|
||||
const crypto::MacKeychain& keychain_;
|
||||
const crypto::AppleKeychain& keychain_;
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_PASSWORD_MANAGER_ENCRYPTOR_PASSWORD_H__
|
||||
|
@ -9,17 +9,17 @@
|
||||
#include "base/base64.h"
|
||||
#include "base/mac/mac_logging.h"
|
||||
#include "base/rand_util.h"
|
||||
#include "crypto/keychain_mac.h"
|
||||
#include "crypto/apple_keychain.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
using crypto::MacKeychain;
|
||||
using crypto::AppleKeychain;
|
||||
|
||||
namespace {
|
||||
|
||||
// Generates a random password and adds it to the Keychain. The added password
|
||||
// is returned from the function. If an error occurs, an empty password is
|
||||
// returned.
|
||||
std::string AddRandomPasswordToKeychain(const MacKeychain& keychain,
|
||||
std::string AddRandomPasswordToKeychain(const AppleKeychain& keychain,
|
||||
const std::string& service_name,
|
||||
const std::string& account_name) {
|
||||
// Generate a password with 128 bits of randomness.
|
||||
|
@ -3,17 +3,17 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "chrome/browser/password_manager/encryptor_password_mac.h"
|
||||
#include "crypto/mock_keychain_mac.h"
|
||||
#include "crypto/mock_apple_keychain.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using crypto::MockKeychain;
|
||||
using crypto::MockAppleKeychain;
|
||||
|
||||
// Test that if we have an existing password in the Keychain and we are
|
||||
// authorized by the user to read it then we get it back correctly.
|
||||
TEST(EncryptorPasswordTest, FindPasswordSuccess) {
|
||||
MockKeychain keychain;
|
||||
MockAppleKeychain keychain;
|
||||
keychain.set_find_generic_result(noErr);
|
||||
EncryptorPassword password(keychain);
|
||||
EXPECT_FALSE(password.GetEncryptorPassword().empty());
|
||||
@ -24,7 +24,7 @@ TEST(EncryptorPasswordTest, FindPasswordSuccess) {
|
||||
// Test that if we do not have an existing password in the Keychain then it
|
||||
// gets added successfully and returned.
|
||||
TEST(EncryptorPasswordTest, FindPasswordNotFound) {
|
||||
MockKeychain keychain;
|
||||
MockAppleKeychain keychain;
|
||||
keychain.set_find_generic_result(errSecItemNotFound);
|
||||
EncryptorPassword password(keychain);
|
||||
EXPECT_EQ(24U, password.GetEncryptorPassword().length());
|
||||
@ -35,7 +35,7 @@ TEST(EncryptorPasswordTest, FindPasswordNotFound) {
|
||||
// Test that if get denied access by the user then we return an empty password.
|
||||
// And we should not try to add one.
|
||||
TEST(EncryptorPasswordTest, FindPasswordNotAuthorized) {
|
||||
MockKeychain keychain;
|
||||
MockAppleKeychain keychain;
|
||||
keychain.set_find_generic_result(errSecAuthFailed);
|
||||
EncryptorPassword password(keychain);
|
||||
EXPECT_TRUE(password.GetEncryptorPassword().empty());
|
||||
@ -46,7 +46,7 @@ TEST(EncryptorPasswordTest, FindPasswordNotAuthorized) {
|
||||
// Test that if some random other error happens then we return an empty
|
||||
// password, and we should not try to add one.
|
||||
TEST(EncryptorPasswordTest, FindPasswordOtherError) {
|
||||
MockKeychain keychain;
|
||||
MockAppleKeychain keychain;
|
||||
keychain.set_find_generic_result(errSecNotAvailable);
|
||||
EncryptorPassword password(keychain);
|
||||
EXPECT_TRUE(password.GetEncryptorPassword().empty());
|
||||
@ -56,7 +56,7 @@ TEST(EncryptorPasswordTest, FindPasswordOtherError) {
|
||||
|
||||
// Test that subsequent additions to the keychain give different passwords.
|
||||
TEST(EncryptorPasswordTest, PasswordsDiffer) {
|
||||
MockKeychain keychain1;
|
||||
MockAppleKeychain keychain1;
|
||||
keychain1.set_find_generic_result(errSecItemNotFound);
|
||||
EncryptorPassword encryptor_password1(keychain1);
|
||||
std::string password1 = encryptor_password1.GetEncryptorPassword();
|
||||
@ -64,7 +64,7 @@ TEST(EncryptorPasswordTest, PasswordsDiffer) {
|
||||
EXPECT_TRUE(keychain1.called_add_generic());
|
||||
EXPECT_EQ(0, keychain1.password_data_count());
|
||||
|
||||
MockKeychain keychain2;
|
||||
MockAppleKeychain keychain2;
|
||||
keychain2.set_find_generic_result(errSecItemNotFound);
|
||||
EncryptorPassword encryptor_password2(keychain2);
|
||||
std::string password2 = encryptor_password2.GetEncryptorPassword();
|
||||
|
@ -21,8 +21,8 @@
|
||||
#include "chrome/browser/password_manager/password_store_win.h"
|
||||
#elif defined(OS_MACOSX)
|
||||
#include "chrome/browser/password_manager/password_store_mac.h"
|
||||
#include "crypto/keychain_mac.h"
|
||||
#include "crypto/mock_keychain_mac.h"
|
||||
#include "crypto/apple_keychain.h"
|
||||
#include "crypto/mock_apple_keychain.h"
|
||||
#elif defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
// Don't do anything. We're going to use the default store.
|
||||
#elif defined(OS_POSIX)
|
||||
@ -115,9 +115,9 @@ PasswordStoreFactory::BuildServiceInstanceFor(Profile* profile) const {
|
||||
WebDataServiceFactory::GetForProfile(profile, Profile::IMPLICIT_ACCESS));
|
||||
#elif defined(OS_MACOSX)
|
||||
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseMockKeychain)) {
|
||||
ps = new PasswordStoreMac(new crypto::MockKeychain(), login_db);
|
||||
ps = new PasswordStoreMac(new crypto::MockAppleKeychain(), login_db);
|
||||
} else {
|
||||
ps = new PasswordStoreMac(new crypto::MacKeychain(), login_db);
|
||||
ps = new PasswordStoreMac(new crypto::AppleKeychain(), login_db);
|
||||
}
|
||||
#elif defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
||||
// For now, we use PasswordStoreDefault. We might want to make a native
|
||||
|
@ -22,16 +22,16 @@
|
||||
#include "chrome/browser/password_manager/password_store_change.h"
|
||||
#include "chrome/common/chrome_notification_types.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "crypto/keychain_mac.h"
|
||||
#include "crypto/apple_keychain.h"
|
||||
|
||||
using crypto::MacKeychain;
|
||||
using crypto::AppleKeychain;
|
||||
using webkit::forms::PasswordForm;
|
||||
|
||||
// Utility class to handle the details of constructing and running a keychain
|
||||
// search from a set of attributes.
|
||||
class KeychainSearch {
|
||||
public:
|
||||
explicit KeychainSearch(const MacKeychain& keychain);
|
||||
explicit KeychainSearch(const AppleKeychain& keychain);
|
||||
~KeychainSearch();
|
||||
|
||||
// Sets up a keycahin search based on an non "null" (NULL for char*,
|
||||
@ -49,12 +49,12 @@ class KeychainSearch {
|
||||
void FindMatchingItems(std::vector<SecKeychainItemRef>* matches);
|
||||
|
||||
private:
|
||||
const MacKeychain* keychain_;
|
||||
const AppleKeychain* keychain_;
|
||||
SecKeychainAttributeList search_attributes_;
|
||||
SecKeychainSearchRef search_ref_;
|
||||
};
|
||||
|
||||
KeychainSearch::KeychainSearch(const MacKeychain& keychain)
|
||||
KeychainSearch::KeychainSearch(const AppleKeychain& keychain)
|
||||
: keychain_(&keychain), search_ref_(NULL) {
|
||||
search_attributes_.count = 0;
|
||||
search_attributes_.attr = NULL;
|
||||
@ -231,7 +231,7 @@ PasswordForm::Scheme SchemeForAuthType(SecAuthenticationType auth_type) {
|
||||
}
|
||||
}
|
||||
|
||||
bool FillPasswordFormFromKeychainItem(const MacKeychain& keychain,
|
||||
bool FillPasswordFormFromKeychainItem(const AppleKeychain& keychain,
|
||||
const SecKeychainItemRef& keychain_item,
|
||||
PasswordForm* form) {
|
||||
DCHECK(form);
|
||||
@ -444,7 +444,8 @@ void MergePasswordForms(std::vector<PasswordForm*>* keychain_forms,
|
||||
}
|
||||
|
||||
std::vector<PasswordForm*> GetPasswordsForForms(
|
||||
const MacKeychain& keychain, std::vector<PasswordForm*>* database_forms) {
|
||||
const AppleKeychain& keychain,
|
||||
std::vector<PasswordForm*>* database_forms) {
|
||||
MacKeychainPasswordFormAdapter keychain_adapter(&keychain);
|
||||
|
||||
std::vector<PasswordForm*> merged_forms;
|
||||
@ -469,7 +470,7 @@ std::vector<PasswordForm*> GetPasswordsForForms(
|
||||
#pragma mark -
|
||||
|
||||
MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter(
|
||||
const MacKeychain* keychain)
|
||||
const AppleKeychain* keychain)
|
||||
: keychain_(keychain), finds_only_owned_(false) {
|
||||
}
|
||||
|
||||
@ -734,7 +735,7 @@ OSType MacKeychainPasswordFormAdapter::CreatorCodeForSearch() {
|
||||
|
||||
#pragma mark -
|
||||
|
||||
PasswordStoreMac::PasswordStoreMac(MacKeychain* keychain,
|
||||
PasswordStoreMac::PasswordStoreMac(AppleKeychain* keychain,
|
||||
LoginDatabase* login_db)
|
||||
: keychain_(keychain), login_metadata_db_(login_db) {
|
||||
DCHECK(keychain_.get());
|
||||
|
@ -18,7 +18,7 @@ class NotificationService;
|
||||
}
|
||||
|
||||
namespace crypto {
|
||||
class MacKeychain;
|
||||
class AppleKeychain;
|
||||
}
|
||||
|
||||
// Implements PasswordStore on top of the OS X Keychain, with an internal
|
||||
@ -30,7 +30,7 @@ class PasswordStoreMac : public PasswordStore {
|
||||
public:
|
||||
// Takes ownership of |keychain| and |login_db|, both of which must be
|
||||
// non-NULL.
|
||||
PasswordStoreMac(crypto::MacKeychain* keychain, LoginDatabase* login_db);
|
||||
PasswordStoreMac(crypto::AppleKeychain* keychain, LoginDatabase* login_db);
|
||||
|
||||
// Initializes |thread_| and |notification_service_|.
|
||||
virtual bool Init() OVERRIDE;
|
||||
@ -87,7 +87,7 @@ class PasswordStoreMac : public PasswordStore {
|
||||
// thread.
|
||||
void CreateNotificationService();
|
||||
|
||||
scoped_ptr<crypto::MacKeychain> keychain_;
|
||||
scoped_ptr<crypto::AppleKeychain> keychain_;
|
||||
scoped_ptr<LoginDatabase> login_metadata_db_;
|
||||
|
||||
// Thread that the synchronous methods are run on.
|
||||
|
@ -11,18 +11,18 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/time.h"
|
||||
#include "crypto/keychain_mac.h"
|
||||
#include "crypto/apple_keychain.h"
|
||||
|
||||
using crypto::MacKeychain;
|
||||
using crypto::AppleKeychain;
|
||||
|
||||
// Adapter that wraps a MacKeychain and provides interaction in terms of
|
||||
// Adapter that wraps a AppleKeychain and provides interaction in terms of
|
||||
// PasswordForms instead of Keychain items.
|
||||
class MacKeychainPasswordFormAdapter {
|
||||
public:
|
||||
// Creates an adapter for |keychain|. This class does not take ownership of
|
||||
// |keychain|, so the caller must make sure that the keychain outlives the
|
||||
// created object.
|
||||
explicit MacKeychainPasswordFormAdapter(const MacKeychain* keychain);
|
||||
explicit MacKeychainPasswordFormAdapter(const AppleKeychain* keychain);
|
||||
|
||||
// Returns PasswordForms for each keychain entry that could be used to fill
|
||||
// |form|. Caller is responsible for deleting the returned forms.
|
||||
@ -67,20 +67,20 @@ class MacKeychainPasswordFormAdapter {
|
||||
|
||||
private:
|
||||
// Returns PasswordForms constructed from the given Keychain items, calling
|
||||
// MacKeychain::Free on all of the keychain items and clearing the vector.
|
||||
// AppleKeychain::Free on all of the keychain items and clearing the vector.
|
||||
// Caller is responsible for deleting the returned forms.
|
||||
std::vector<webkit::forms::PasswordForm*> ConvertKeychainItemsToForms(
|
||||
std::vector<SecKeychainItemRef>* items);
|
||||
|
||||
// Searches |keychain| for the specific keychain entry that corresponds to the
|
||||
// given form, and returns it (or NULL if no match is found). The caller is
|
||||
// responsible for calling MacKeychain::Free on on the returned item.
|
||||
// responsible for calling AppleKeychain::Free on on the returned item.
|
||||
SecKeychainItemRef KeychainItemForForm(
|
||||
const webkit::forms::PasswordForm& form);
|
||||
|
||||
// Returns the Keychain items matching the given signon_realm, scheme, and
|
||||
// optionally path and username (either of both can be NULL).
|
||||
// The caller is responsible for calling MacKeychain::Free on the
|
||||
// The caller is responsible for calling AppleKeychain::Free on the
|
||||
// returned items.
|
||||
std::vector<SecKeychainItemRef> MatchingKeychainItems(
|
||||
const std::string& signon_realm,
|
||||
@ -119,7 +119,7 @@ class MacKeychainPasswordFormAdapter {
|
||||
// a search of all items, regardless of creator.
|
||||
OSType CreatorCodeForSearch();
|
||||
|
||||
const MacKeychain* keychain_;
|
||||
const AppleKeychain* keychain_;
|
||||
|
||||
// If true, Keychain searches are restricted to items created by Chrome.
|
||||
bool finds_only_owned_;
|
||||
@ -140,7 +140,7 @@ namespace internal_keychain_helpers {
|
||||
// becomes an issue, the password storage API will need to be refactored to
|
||||
// allow the password to be retrieved later (accessing other fields doesn't
|
||||
// require authorization).
|
||||
bool FillPasswordFormFromKeychainItem(const MacKeychain& keychain,
|
||||
bool FillPasswordFormFromKeychainItem(const AppleKeychain& keychain,
|
||||
const SecKeychainItemRef& keychain_item,
|
||||
webkit::forms::PasswordForm* form);
|
||||
|
||||
@ -156,7 +156,7 @@ bool FormsMatchForMerge(const webkit::forms::PasswordForm& form_a,
|
||||
// On return, database_forms and keychain_forms will have only unused
|
||||
// entries; for database_forms that means entries for which no corresponding
|
||||
// password can be found (and which aren't blacklist entries), and for
|
||||
// keychain_forms it's entries that weren't merged into at least one database
|
||||
// keychain_forms its entries that weren't merged into at least one database
|
||||
// form.
|
||||
void MergePasswordForms(
|
||||
std::vector<webkit::forms::PasswordForm*>* keychain_forms,
|
||||
@ -167,7 +167,7 @@ void MergePasswordForms(
|
||||
// possible using entries from |keychain| and returns them. On return,
|
||||
// |database_forms| will contain only the forms for which no password was found.
|
||||
std::vector<webkit::forms::PasswordForm*> GetPasswordsForForms(
|
||||
const MacKeychain& keychain,
|
||||
const AppleKeychain& keychain,
|
||||
std::vector<webkit::forms::PasswordForm*>* database_forms);
|
||||
|
||||
} // internal_keychain_helpers
|
||||
|
@ -17,10 +17,10 @@
|
||||
#include "chrome/browser/password_manager/password_store_mac_internal.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
#include "content/public/test/test_browser_thread.h"
|
||||
#include "crypto/mock_keychain_mac.h"
|
||||
#include "crypto/mock_apple_keychain.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
using crypto::MockKeychain;
|
||||
using crypto::MockAppleKeychain;
|
||||
using webkit::forms::PasswordForm;
|
||||
using testing::_;
|
||||
using testing::DoAll;
|
||||
@ -51,7 +51,7 @@ ACTION(QuitUIMessageLoop) {
|
||||
class PasswordStoreMacInternalsTest : public testing::Test {
|
||||
public:
|
||||
virtual void SetUp() {
|
||||
MockKeychain::KeychainTestData test_data[] = {
|
||||
MockAppleKeychain::KeychainTestData test_data[] = {
|
||||
// Basic HTML form.
|
||||
{ kSecAuthenticationTypeHTMLForm, "some.domain.com",
|
||||
kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z",
|
||||
@ -91,7 +91,7 @@ class PasswordStoreMacInternalsTest : public testing::Test {
|
||||
"abc", "123", false },
|
||||
};
|
||||
|
||||
keychain_ = new MockKeychain();
|
||||
keychain_ = new MockAppleKeychain();
|
||||
|
||||
for (unsigned int i = 0; i < arraysize(test_data); ++i) {
|
||||
keychain_->AddTestItem(test_data[i]);
|
||||
@ -120,7 +120,7 @@ class PasswordStoreMacInternalsTest : public testing::Test {
|
||||
EXPECT_TRUE(keychain_->CreatorCodesSetForAddedItems());
|
||||
}
|
||||
|
||||
MockKeychain* keychain_;
|
||||
MockAppleKeychain* keychain_;
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
@ -274,7 +274,7 @@ TEST_F(PasswordStoreMacInternalsTest, TestKeychainToFormTranslation) {
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(expected); ++i) {
|
||||
// Create our fake KeychainItemRef; see MockKeychain docs.
|
||||
// Create our fake KeychainItemRef; see MockAppleKeychain docs.
|
||||
SecKeychainItemRef keychain_item =
|
||||
reinterpret_cast<SecKeychainItemRef>(i + 1);
|
||||
PasswordForm form;
|
||||
@ -514,7 +514,8 @@ TEST_F(PasswordStoreMacInternalsTest, TestKeychainAdd) {
|
||||
"gobbledygook", NULL, NULL, NULL, NULL,
|
||||
L"anonymous", L"knock-knock", false, false, 0 }, false },
|
||||
// Test that failing to update a duplicate (forced using the magic failure
|
||||
// password; see MockKeychain::ItemModifyAttributesAndData) is reported.
|
||||
// password; see MockAppleKeychain::ItemModifyAttributesAndData) is
|
||||
// reported.
|
||||
{ { PasswordForm::SCHEME_HTML, "http://some.domain.com",
|
||||
"http://some.domain.com/insecure.html", NULL, NULL, NULL, NULL,
|
||||
L"joe_user", L"fail_me", false, false, 0 }, false },
|
||||
@ -906,7 +907,7 @@ class PasswordStoreMacTest : public testing::Test {
|
||||
FilePath db_file = db_dir_.path().AppendASCII("login.db");
|
||||
ASSERT_TRUE(login_db_->Init(db_file));
|
||||
|
||||
keychain_ = new MockKeychain();
|
||||
keychain_ = new MockAppleKeychain();
|
||||
|
||||
store_ = new PasswordStoreMac(keychain_, login_db_);
|
||||
ASSERT_TRUE(store_->Init());
|
||||
@ -922,7 +923,7 @@ class PasswordStoreMacTest : public testing::Test {
|
||||
MessageLoopForUI message_loop_;
|
||||
content::TestBrowserThread ui_thread_;
|
||||
|
||||
MockKeychain* keychain_; // Owned by store_.
|
||||
MockAppleKeychain* keychain_; // Owned by store_.
|
||||
LoginDatabase* login_db_; // Owned by store_.
|
||||
scoped_refptr<PasswordStoreMac> store_;
|
||||
ScopedTempDir db_dir_;
|
||||
@ -941,14 +942,14 @@ TEST_F(PasswordStoreMacTest, TestStoreUpdate) {
|
||||
};
|
||||
scoped_ptr<PasswordForm> joint_form(CreatePasswordFormFromData(joint_data));
|
||||
login_db_->AddLogin(*joint_form);
|
||||
MockKeychain::KeychainTestData joint_keychain_data = {
|
||||
MockAppleKeychain::KeychainTestData joint_keychain_data = {
|
||||
kSecAuthenticationTypeHTMLForm, "some.domain.com",
|
||||
kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "20020601171500Z",
|
||||
"joe_user", "sekrit", false };
|
||||
keychain_->AddTestItem(joint_keychain_data);
|
||||
|
||||
// Insert a password into the keychain only.
|
||||
MockKeychain::KeychainTestData keychain_only_data = {
|
||||
MockAppleKeychain::KeychainTestData keychain_only_data = {
|
||||
kSecAuthenticationTypeHTMLForm, "keychain.only.com",
|
||||
kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z",
|
||||
"keychain", "only", false
|
||||
|
@ -10,6 +10,12 @@
|
||||
#include "base/basictypes.h"
|
||||
#include "crypto/crypto_export.h"
|
||||
|
||||
#if defined (OS_IOS)
|
||||
typedef void* SecKeychainRef;
|
||||
typedef void* SecKeychainItemRef;
|
||||
typedef void SecKeychainAttributeList;
|
||||
#endif
|
||||
|
||||
namespace crypto {
|
||||
|
||||
// Wraps the KeychainServices API in a very thin layer, to allow it to be
|
||||
@ -20,11 +26,33 @@ namespace crypto {
|
||||
// SecKeychainFoo). The only exception is Free, which should be used for
|
||||
// anything returned from this class that would normally be freed with
|
||||
// CFRelease (to aid in testing).
|
||||
class CRYPTO_EXPORT MacKeychain {
|
||||
class CRYPTO_EXPORT AppleKeychain {
|
||||
public:
|
||||
MacKeychain();
|
||||
virtual ~MacKeychain();
|
||||
AppleKeychain();
|
||||
virtual ~AppleKeychain();
|
||||
|
||||
virtual OSStatus FindGenericPassword(CFTypeRef keychainOrArray,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32* passwordLength,
|
||||
void** passwordData,
|
||||
SecKeychainItemRef* itemRef) const;
|
||||
|
||||
virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList,
|
||||
void* data) const;
|
||||
|
||||
virtual OSStatus AddGenericPassword(SecKeychainRef keychain,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32 passwordLength,
|
||||
const void* passwordData,
|
||||
SecKeychainItemRef* itemRef) const;
|
||||
|
||||
#if !defined(OS_IOS)
|
||||
virtual OSStatus ItemCopyAttributesAndData(
|
||||
SecKeychainItemRef itemRef,
|
||||
SecKeychainAttributeInfo* info,
|
||||
@ -67,32 +95,12 @@ class CRYPTO_EXPORT MacKeychain {
|
||||
const void* passwordData,
|
||||
SecKeychainItemRef* itemRef) const;
|
||||
|
||||
virtual OSStatus FindGenericPassword(CFTypeRef keychainOrArray,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32* passwordLength,
|
||||
void** passwordData,
|
||||
SecKeychainItemRef* itemRef) const;
|
||||
|
||||
virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList,
|
||||
void* data) const;
|
||||
|
||||
virtual OSStatus AddGenericPassword(SecKeychainRef keychain,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32 passwordLength,
|
||||
const void* passwordData,
|
||||
SecKeychainItemRef* itemRef) const;
|
||||
|
||||
// Calls CFRelease on the given ref, after checking that |ref| is non-NULL.
|
||||
virtual void Free(CFTypeRef ref) const;
|
||||
#endif // !defined(OS_IOS)
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(MacKeychain);
|
||||
DISALLOW_COPY_AND_ASSIGN(AppleKeychain);
|
||||
};
|
||||
|
||||
} // namespace crypto
|
202
crypto/apple_keychain_ios.mm
Normal file
202
crypto/apple_keychain_ios.mm
Normal file
@ -0,0 +1,202 @@
|
||||
// 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 "crypto/apple_keychain.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include "base/mac/foundation_util.h"
|
||||
#include "base/mac/scoped_cftyperef.h"
|
||||
#include "base/memory/scoped_nsobject.h"
|
||||
|
||||
namespace {
|
||||
|
||||
enum KeychainAction {
|
||||
kKeychainActionCreate,
|
||||
kKeychainActionUpdate
|
||||
};
|
||||
|
||||
// Creates a dictionary that can be used to query the keystore.
|
||||
// Ownership follows the Create rule.
|
||||
CFDictionaryRef CreateGenericPasswordQuery(UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName) {
|
||||
CFMutableDictionaryRef query =
|
||||
CFDictionaryCreateMutable(NULL,
|
||||
5,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
// Type of element is generic password.
|
||||
CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword);
|
||||
|
||||
// Set the service name.
|
||||
scoped_nsobject<NSString> service_name_ns(
|
||||
[[NSString alloc] initWithBytes:serviceName
|
||||
length:serviceNameLength
|
||||
encoding:NSUTF8StringEncoding]);
|
||||
CFDictionarySetValue(query, kSecAttrService,
|
||||
base::mac::NSToCFCast(service_name_ns));
|
||||
|
||||
// Set the account name.
|
||||
scoped_nsobject<NSString> account_name_ns(
|
||||
[[NSString alloc] initWithBytes:accountName
|
||||
length:accountNameLength
|
||||
encoding:NSUTF8StringEncoding]);
|
||||
CFDictionarySetValue(query, kSecAttrAccount,
|
||||
base::mac::NSToCFCast(account_name_ns));
|
||||
|
||||
// Use the proper search constants, return only the data of the first match.
|
||||
CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne);
|
||||
CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
|
||||
return query;
|
||||
}
|
||||
|
||||
// Creates a dictionary conatining the data to save into the keychain.
|
||||
// Ownership follows the Create rule.
|
||||
CFDictionaryRef CreateKeychainData(UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32 passwordLength,
|
||||
const void* passwordData,
|
||||
KeychainAction action) {
|
||||
CFMutableDictionaryRef keychain_data =
|
||||
CFDictionaryCreateMutable(NULL,
|
||||
0,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
// Set the password.
|
||||
NSData* password = [NSData dataWithBytes:passwordData length:passwordLength];
|
||||
CFDictionarySetValue(keychain_data, kSecValueData,
|
||||
base::mac::NSToCFCast(password));
|
||||
|
||||
// If this is not a creation, no structural information is needed.
|
||||
if (action != kKeychainActionCreate)
|
||||
return keychain_data;
|
||||
|
||||
// Set the type of the data.
|
||||
CFDictionarySetValue(keychain_data, kSecClass, kSecClassGenericPassword);
|
||||
|
||||
// Only allow access when the device has been unlocked.
|
||||
CFDictionarySetValue(keychain_data,
|
||||
kSecAttrAccessible,
|
||||
kSecAttrAccessibleWhenUnlocked);
|
||||
|
||||
// Set the service name.
|
||||
scoped_nsobject<NSString> service_name_ns(
|
||||
[[NSString alloc] initWithBytes:serviceName
|
||||
length:serviceNameLength
|
||||
encoding:NSUTF8StringEncoding]);
|
||||
CFDictionarySetValue(keychain_data, kSecAttrService,
|
||||
base::mac::NSToCFCast(service_name_ns));
|
||||
|
||||
// Set the account name.
|
||||
scoped_nsobject<NSString> account_name_ns(
|
||||
[[NSString alloc] initWithBytes:accountName
|
||||
length:accountNameLength
|
||||
encoding:NSUTF8StringEncoding]);
|
||||
CFDictionarySetValue(keychain_data, kSecAttrAccount,
|
||||
base::mac::NSToCFCast(account_name_ns));
|
||||
|
||||
return keychain_data;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace crypto {
|
||||
|
||||
AppleKeychain::AppleKeychain() {}
|
||||
|
||||
AppleKeychain::~AppleKeychain() {}
|
||||
|
||||
OSStatus AppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList,
|
||||
void* data) const {
|
||||
free(data);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus AppleKeychain::AddGenericPassword(SecKeychainRef keychain,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32 passwordLength,
|
||||
const void* passwordData,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
base::mac::ScopedCFTypeRef<CFDictionaryRef> query(
|
||||
CreateGenericPasswordQuery(serviceNameLength,
|
||||
serviceName,
|
||||
accountNameLength,
|
||||
accountName));
|
||||
// Check that there is not already a password.
|
||||
OSStatus status = SecItemCopyMatching(query, NULL);
|
||||
if (status == errSecItemNotFound) {
|
||||
// A new entry must be created.
|
||||
base::mac::ScopedCFTypeRef<CFDictionaryRef> keychain_data(
|
||||
CreateKeychainData(serviceNameLength,
|
||||
serviceName,
|
||||
accountNameLength,
|
||||
accountName,
|
||||
passwordLength,
|
||||
passwordData,
|
||||
kKeychainActionCreate));
|
||||
status = SecItemAdd(keychain_data, NULL);
|
||||
} else if (status == noErr) {
|
||||
// The entry must be updated.
|
||||
base::mac::ScopedCFTypeRef<CFDictionaryRef> keychain_data(
|
||||
CreateKeychainData(serviceNameLength,
|
||||
serviceName,
|
||||
accountNameLength,
|
||||
accountName,
|
||||
passwordLength,
|
||||
passwordData,
|
||||
kKeychainActionUpdate));
|
||||
status = SecItemUpdate(query, keychain_data);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32* passwordLength,
|
||||
void** passwordData,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
DCHECK((passwordData && passwordLength) ||
|
||||
(!passwordData && !passwordLength));
|
||||
base::mac::ScopedCFTypeRef<CFDictionaryRef> query(
|
||||
CreateGenericPasswordQuery(serviceNameLength,
|
||||
serviceName,
|
||||
accountNameLength,
|
||||
accountName));
|
||||
|
||||
// Get the keychain item containing the password.
|
||||
CFTypeRef resultRef = NULL;
|
||||
OSStatus status = SecItemCopyMatching(query, &resultRef);
|
||||
base::mac::ScopedCFTypeRef<CFTypeRef> result(resultRef);
|
||||
|
||||
if (status != noErr) {
|
||||
if (passwordData) {
|
||||
*passwordData = NULL;
|
||||
*passwordLength = 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
if (passwordData) {
|
||||
CFDataRef data = base::mac::CFCast<CFDataRef>(result);
|
||||
NSUInteger length = CFDataGetLength(data);
|
||||
*passwordData = malloc(length * sizeof(UInt8));
|
||||
CFDataGetBytes(data, CFRangeMake(0, length), (UInt8*)*passwordData);
|
||||
*passwordLength = length;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
} // namespace crypto
|
@ -2,15 +2,17 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "crypto/keychain_mac.h"
|
||||
#include "crypto/apple_keychain.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
namespace crypto {
|
||||
|
||||
MacKeychain::MacKeychain() {}
|
||||
AppleKeychain::AppleKeychain() {}
|
||||
|
||||
MacKeychain::~MacKeychain() {}
|
||||
AppleKeychain::~AppleKeychain() {}
|
||||
|
||||
OSStatus MacKeychain::ItemCopyAttributesAndData(
|
||||
OSStatus AppleKeychain::ItemCopyAttributesAndData(
|
||||
SecKeychainItemRef itemRef,
|
||||
SecKeychainAttributeInfo* info,
|
||||
SecItemClass* itemClass,
|
||||
@ -21,7 +23,7 @@ OSStatus MacKeychain::ItemCopyAttributesAndData(
|
||||
attrList, length, outData);
|
||||
}
|
||||
|
||||
OSStatus MacKeychain::ItemModifyAttributesAndData(
|
||||
OSStatus AppleKeychain::ItemModifyAttributesAndData(
|
||||
SecKeychainItemRef itemRef,
|
||||
const SecKeychainAttributeList* attrList,
|
||||
UInt32 length,
|
||||
@ -30,17 +32,17 @@ OSStatus MacKeychain::ItemModifyAttributesAndData(
|
||||
data);
|
||||
}
|
||||
|
||||
OSStatus MacKeychain::ItemFreeAttributesAndData(
|
||||
OSStatus AppleKeychain::ItemFreeAttributesAndData(
|
||||
SecKeychainAttributeList* attrList,
|
||||
void* data) const {
|
||||
return SecKeychainItemFreeAttributesAndData(attrList, data);
|
||||
}
|
||||
|
||||
OSStatus MacKeychain::ItemDelete(SecKeychainItemRef itemRef) const {
|
||||
OSStatus AppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const {
|
||||
return SecKeychainItemDelete(itemRef);
|
||||
}
|
||||
|
||||
OSStatus MacKeychain::SearchCreateFromAttributes(
|
||||
OSStatus AppleKeychain::SearchCreateFromAttributes(
|
||||
CFTypeRef keychainOrArray,
|
||||
SecItemClass itemClass,
|
||||
const SecKeychainAttributeList* attrList,
|
||||
@ -49,12 +51,12 @@ OSStatus MacKeychain::SearchCreateFromAttributes(
|
||||
attrList, searchRef);
|
||||
}
|
||||
|
||||
OSStatus MacKeychain::SearchCopyNext(SecKeychainSearchRef searchRef,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
OSStatus AppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
return SecKeychainSearchCopyNext(searchRef, itemRef);
|
||||
}
|
||||
|
||||
OSStatus MacKeychain::AddInternetPassword(
|
||||
OSStatus AppleKeychain::AddInternetPassword(
|
||||
SecKeychainRef keychain,
|
||||
UInt32 serverNameLength,
|
||||
const char* serverName,
|
||||
@ -80,14 +82,14 @@ OSStatus MacKeychain::AddInternetPassword(
|
||||
itemRef);
|
||||
}
|
||||
|
||||
OSStatus MacKeychain::FindGenericPassword(CFTypeRef keychainOrArray,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32* passwordLength,
|
||||
void** passwordData,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32* passwordLength,
|
||||
void** passwordData,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
return SecKeychainFindGenericPassword(keychainOrArray,
|
||||
serviceNameLength,
|
||||
serviceName,
|
||||
@ -98,19 +100,19 @@ OSStatus MacKeychain::FindGenericPassword(CFTypeRef keychainOrArray,
|
||||
itemRef);
|
||||
}
|
||||
|
||||
OSStatus MacKeychain::ItemFreeContent(SecKeychainAttributeList* attrList,
|
||||
void* data) const {
|
||||
OSStatus AppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList,
|
||||
void* data) const {
|
||||
return SecKeychainItemFreeContent(attrList, data);
|
||||
}
|
||||
|
||||
OSStatus MacKeychain::AddGenericPassword(SecKeychainRef keychain,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32 passwordLength,
|
||||
const void* passwordData,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
OSStatus AppleKeychain::AddGenericPassword(SecKeychainRef keychain,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32 passwordLength,
|
||||
const void* passwordData,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
return SecKeychainAddGenericPassword(keychain,
|
||||
serviceNameLength,
|
||||
serviceName,
|
||||
@ -121,7 +123,7 @@ OSStatus MacKeychain::AddGenericPassword(SecKeychainRef keychain,
|
||||
itemRef);
|
||||
}
|
||||
|
||||
void MacKeychain::Free(CFTypeRef ref) const {
|
||||
void AppleKeychain::Free(CFTypeRef ref) const {
|
||||
if (ref)
|
||||
CFRelease(ref);
|
||||
}
|
@ -65,6 +65,13 @@
|
||||
'symmetric_key_win.cc',
|
||||
],
|
||||
}],
|
||||
[ 'OS != "mac" and OS != "ios"', {
|
||||
'sources!': [
|
||||
'apple_keychain.h',
|
||||
'mock_apple_keychain.cc',
|
||||
'mock_apple_keychain.h',
|
||||
],
|
||||
}],
|
||||
[ 'OS == "android"', {
|
||||
'dependencies': [
|
||||
'../third_party/openssl/openssl.gyp:openssl',
|
||||
@ -86,6 +93,12 @@
|
||||
},
|
||||
},
|
||||
],
|
||||
[ 'OS == "ios"', {
|
||||
'sources!': [
|
||||
# This class is stubbed out on iOS.
|
||||
'rsa_private_key.cc',
|
||||
],
|
||||
}],
|
||||
[ 'OS == "mac"', {
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
@ -156,18 +169,13 @@
|
||||
],
|
||||
},],
|
||||
],
|
||||
'target_conditions' : [
|
||||
[ 'OS == "ios"', {
|
||||
'sources!': [
|
||||
# This class is stubbed out on iOS.
|
||||
'rsa_private_key.cc',
|
||||
],
|
||||
}],
|
||||
],
|
||||
'sources': [
|
||||
# NOTE: all transitive dependencies of HMAC on windows need
|
||||
# to be placed in the source list above.
|
||||
'<@(hmac_win64_related_sources)',
|
||||
'apple_keychain.h',
|
||||
'apple_keychain_ios.mm',
|
||||
'apple_keychain_mac.mm',
|
||||
'capi_util.cc',
|
||||
'capi_util.h',
|
||||
'crypto_export.h',
|
||||
@ -188,12 +196,12 @@
|
||||
'encryptor_openssl.cc',
|
||||
'hmac_nss.cc',
|
||||
'hmac_openssl.cc',
|
||||
'keychain_mac.cc',
|
||||
'keychain_mac.h',
|
||||
'mac_security_services_lock.cc',
|
||||
'mac_security_services_lock.h',
|
||||
'mock_keychain_mac.cc',
|
||||
'mock_keychain_mac.h',
|
||||
'mock_apple_keychain.cc',
|
||||
'mock_apple_keychain.h',
|
||||
'mock_apple_keychain_ios.cc',
|
||||
'mock_apple_keychain_mac.cc',
|
||||
'p224_spake.cc',
|
||||
'p224_spake.h',
|
||||
'nss_util.cc',
|
||||
|
61
crypto/mock_apple_keychain.cc
Normal file
61
crypto/mock_apple_keychain.cc
Normal file
@ -0,0 +1,61 @@
|
||||
// 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 "base/logging.h"
|
||||
#include "base/time.h"
|
||||
#include "crypto/mock_apple_keychain.h"
|
||||
|
||||
namespace crypto {
|
||||
|
||||
OSStatus MockAppleKeychain::FindGenericPassword(
|
||||
CFTypeRef keychainOrArray,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32* passwordLength,
|
||||
void** passwordData,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
// When simulating |noErr|, return canned |passwordData| and
|
||||
// |passwordLength|. Otherwise, just return given code.
|
||||
if (find_generic_result_ == noErr) {
|
||||
static const char kPassword[] = "my_password";
|
||||
DCHECK(passwordData);
|
||||
// The function to free this data is mocked so the cast is fine.
|
||||
*passwordData = const_cast<char*>(kPassword);
|
||||
DCHECK(passwordLength);
|
||||
*passwordLength = arraysize(kPassword);
|
||||
password_data_count_++;
|
||||
}
|
||||
|
||||
return find_generic_result_;
|
||||
}
|
||||
|
||||
OSStatus MockAppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList,
|
||||
void* data) const {
|
||||
// No-op.
|
||||
password_data_count_--;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus MockAppleKeychain::AddGenericPassword(
|
||||
SecKeychainRef keychain,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32 passwordLength,
|
||||
const void* passwordData,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
called_add_generic_ = true;
|
||||
|
||||
DCHECK_GT(passwordLength, 0U);
|
||||
DCHECK(passwordData);
|
||||
add_generic_password_ =
|
||||
std::string(const_cast<char*>(static_cast<const char*>(passwordData)),
|
||||
passwordLength);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
} // namespace crypto
|
@ -13,27 +13,47 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "crypto/keychain_mac.h"
|
||||
#include "crypto/apple_keychain.h"
|
||||
|
||||
namespace crypto {
|
||||
|
||||
// Type used for the keys in the std::map(s) and MockKeychain items.
|
||||
typedef uintptr_t MockKeychainItemType;
|
||||
|
||||
// Mock Keychain wrapper for testing code that interacts with the OS X
|
||||
// Keychain. Implemented by storing SecKeychainAttributeList and
|
||||
// KeychainPasswordData values in separate mutable containers and
|
||||
// mapping them to integer keys.
|
||||
//
|
||||
// Note that "const" is pretty much meaningless for this class; the const-ness
|
||||
// of MacKeychain doesn't apply to the actual keychain data, so all of the Mock
|
||||
// data is mutable; don't assume that it won't change over the life of tests.
|
||||
class CRYPTO_EXPORT MockKeychain : public MacKeychain {
|
||||
// of AppleKeychain doesn't apply to the actual keychain data, so all of the
|
||||
// Mock data is mutable; don't assume that it won't change over the life of
|
||||
// tests.
|
||||
class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain {
|
||||
public:
|
||||
MockKeychain();
|
||||
virtual ~MockKeychain();
|
||||
MockAppleKeychain();
|
||||
virtual ~MockAppleKeychain();
|
||||
|
||||
// MacKeychain implementation.
|
||||
// AppleKeychain implementation.
|
||||
virtual OSStatus FindGenericPassword(
|
||||
CFTypeRef keychainOrArray,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32* passwordLength,
|
||||
void** passwordData,
|
||||
SecKeychainItemRef* itemRef) const OVERRIDE;
|
||||
virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList,
|
||||
void* data) const OVERRIDE;
|
||||
virtual OSStatus AddGenericPassword(
|
||||
SecKeychainRef keychain,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32 passwordLength,
|
||||
const void* passwordData,
|
||||
SecKeychainItemRef* itemRef) const OVERRIDE;
|
||||
|
||||
#if !defined(OS_IOS)
|
||||
virtual OSStatus ItemCopyAttributesAndData(
|
||||
SecKeychainItemRef itemRef,
|
||||
SecKeychainAttributeInfo* info,
|
||||
@ -72,26 +92,6 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain {
|
||||
UInt32 passwordLength,
|
||||
const void* passwordData,
|
||||
SecKeychainItemRef* itemRef) const OVERRIDE;
|
||||
virtual OSStatus FindGenericPassword(
|
||||
CFTypeRef keychainOrArray,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32* passwordLength,
|
||||
void** passwordData,
|
||||
SecKeychainItemRef* itemRef) const OVERRIDE;
|
||||
virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList,
|
||||
void* data) const OVERRIDE;
|
||||
virtual OSStatus AddGenericPassword(
|
||||
SecKeychainRef keychain,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32 passwordLength,
|
||||
const void* passwordData,
|
||||
SecKeychainItemRef* itemRef) const OVERRIDE;
|
||||
virtual void Free(CFTypeRef ref) const OVERRIDE;
|
||||
|
||||
// Return the counts of objects returned by Create/Copy functions but never
|
||||
@ -118,6 +118,7 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain {
|
||||
};
|
||||
// Adds a keychain item with the given info to the test set.
|
||||
void AddTestItem(const KeychainTestData& item_data);
|
||||
#endif // !defined(OS_IOS)
|
||||
|
||||
// |FindGenericPassword()| can return different results depending on user
|
||||
// interaction with the system Keychain. For mocking purposes we allow the
|
||||
@ -139,6 +140,15 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain {
|
||||
int password_data_count() const { return password_data_count_; }
|
||||
|
||||
private:
|
||||
|
||||
// Type used for the keys in the std::map(s) and MockAppleKeychain items.
|
||||
typedef uintptr_t MockKeychainItemType;
|
||||
|
||||
// Type of the map holding the mock keychain attributes.
|
||||
typedef std::map<MockKeychainItemType, SecKeychainAttributeList>
|
||||
MockKeychainAttributesMap;
|
||||
|
||||
#if !defined(OS_IOS)
|
||||
// Returns true if the keychain already contains a password that matches the
|
||||
// attributes provided.
|
||||
bool AlreadyContainsInternetPassword(
|
||||
@ -178,10 +188,9 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain {
|
||||
void SetTestDataNegativeItem(MockKeychainItemType item, Boolean value);
|
||||
void SetTestDataCreator(MockKeychainItemType item, OSType value);
|
||||
// Sets the password data and length for the item-th test item.
|
||||
void SetTestDataPasswordBytes(
|
||||
MockKeychainItemType item,
|
||||
const void* data,
|
||||
size_t length);
|
||||
void SetTestDataPasswordBytes(MockKeychainItemType item,
|
||||
const void* data,
|
||||
size_t length);
|
||||
// Sets the password for the item-th test item. As with SetTestDataString,
|
||||
// the data will not be null-terminated.
|
||||
void SetTestDataPasswordString(MockKeychainItemType item, const char* value);
|
||||
@ -199,11 +208,11 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain {
|
||||
UInt32 length;
|
||||
} KeychainPasswordData;
|
||||
|
||||
// Mutable because the MockKeychain API requires its internal keychain storage
|
||||
// to be modifiable by users of this class.
|
||||
// Mutable because the MockAppleKeychain API requires its internal keychain
|
||||
// storage to be modifiable by users of this class.
|
||||
mutable MockKeychainAttributesMap keychain_attr_list_;
|
||||
mutable std::map<MockKeychainItemType,
|
||||
SecKeychainAttributeList> keychain_attr_list_;
|
||||
mutable std::map<MockKeychainItemType, KeychainPasswordData> keychain_data_;
|
||||
KeychainPasswordData> keychain_data_;
|
||||
mutable MockKeychainItemType next_item_key_;
|
||||
|
||||
// Tracks the items that should be returned in subsequent calls to
|
||||
@ -221,6 +230,7 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain {
|
||||
|
||||
// Tracks which items (by key) were added with AddInternetPassword.
|
||||
mutable std::set<MockKeychainItemType> added_via_api_;
|
||||
#endif // !defined(OS_IOS)
|
||||
|
||||
// Result code for the |FindGenericPassword()| method.
|
||||
OSStatus find_generic_result_;
|
20
crypto/mock_apple_keychain_ios.cc
Normal file
20
crypto/mock_apple_keychain_ios.cc
Normal file
@ -0,0 +1,20 @@
|
||||
// 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 "base/logging.h"
|
||||
#include "base/time.h"
|
||||
#include "crypto/mock_apple_keychain.h"
|
||||
|
||||
namespace crypto {
|
||||
|
||||
MockAppleKeychain::MockAppleKeychain()
|
||||
: find_generic_result_(noErr),
|
||||
called_add_generic_(false),
|
||||
password_data_count_(0) {
|
||||
}
|
||||
|
||||
MockAppleKeychain::~MockAppleKeychain() {
|
||||
}
|
||||
|
||||
} // namespace crypto
|
@ -4,15 +4,15 @@
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/time.h"
|
||||
#include "crypto/mock_keychain_mac.h"
|
||||
#include "crypto/mock_apple_keychain.h"
|
||||
|
||||
namespace crypto {
|
||||
|
||||
// static
|
||||
const SecKeychainSearchRef MockKeychain::kDummySearchRef =
|
||||
const SecKeychainSearchRef MockAppleKeychain::kDummySearchRef =
|
||||
reinterpret_cast<SecKeychainSearchRef>(1000);
|
||||
|
||||
MockKeychain::MockKeychain()
|
||||
MockAppleKeychain::MockAppleKeychain()
|
||||
: next_item_key_(0),
|
||||
search_copy_count_(0),
|
||||
keychain_item_copy_count_(0),
|
||||
@ -21,7 +21,7 @@ MockKeychain::MockKeychain()
|
||||
called_add_generic_(false),
|
||||
password_data_count_(0) {}
|
||||
|
||||
void MockKeychain::InitializeKeychainData(MockKeychainItemType key) const {
|
||||
void MockAppleKeychain::InitializeKeychainData(MockKeychainItemType key) const {
|
||||
UInt32 tags[] = { kSecAccountItemAttr,
|
||||
kSecServerItemAttr,
|
||||
kSecPortItemAttr,
|
||||
@ -64,9 +64,10 @@ void MockKeychain::InitializeKeychainData(MockKeychainItemType key) const {
|
||||
}
|
||||
}
|
||||
|
||||
MockKeychain::~MockKeychain() {
|
||||
for (std::map<MockKeychainItemType, SecKeychainAttributeList>::iterator it =
|
||||
keychain_attr_list_.begin(); it != keychain_attr_list_.end(); ++it) {
|
||||
MockAppleKeychain::~MockAppleKeychain() {
|
||||
for (MockKeychainAttributesMap::iterator it = keychain_attr_list_.begin();
|
||||
it != keychain_attr_list_.end();
|
||||
++it) {
|
||||
for (unsigned int i = 0; i < it->second.count; ++i) {
|
||||
if (it->second.attr[i].data)
|
||||
free(it->second.attr[i].data);
|
||||
@ -79,7 +80,7 @@ MockKeychain::~MockKeychain() {
|
||||
keychain_data_.clear();
|
||||
}
|
||||
|
||||
SecKeychainAttribute* MockKeychain::AttributeWithTag(
|
||||
SecKeychainAttribute* MockAppleKeychain::AttributeWithTag(
|
||||
const SecKeychainAttributeList& attribute_list,
|
||||
UInt32 tag) {
|
||||
int attribute_index = -1;
|
||||
@ -96,10 +97,10 @@ SecKeychainAttribute* MockKeychain::AttributeWithTag(
|
||||
return &(attribute_list.attr[attribute_index]);
|
||||
}
|
||||
|
||||
void MockKeychain::SetTestDataBytes(MockKeychainItemType item,
|
||||
UInt32 tag,
|
||||
const void* data,
|
||||
size_t length) {
|
||||
void MockAppleKeychain::SetTestDataBytes(MockKeychainItemType item,
|
||||
UInt32 tag,
|
||||
const void* data,
|
||||
size_t length) {
|
||||
SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
|
||||
tag);
|
||||
attribute->length = length;
|
||||
@ -114,31 +115,30 @@ void MockKeychain::SetTestDataBytes(MockKeychainItemType item,
|
||||
}
|
||||
}
|
||||
|
||||
void MockKeychain::SetTestDataString(
|
||||
MockKeychainItemType item,
|
||||
UInt32 tag,
|
||||
const char* value) {
|
||||
void MockAppleKeychain::SetTestDataString(MockKeychainItemType item,
|
||||
UInt32 tag,
|
||||
const char* value) {
|
||||
SetTestDataBytes(item, tag, value, value ? strlen(value) : 0);
|
||||
}
|
||||
|
||||
void MockKeychain::SetTestDataPort(MockKeychainItemType item, UInt32 value) {
|
||||
void MockAppleKeychain::SetTestDataPort(MockKeychainItemType item,
|
||||
UInt32 value) {
|
||||
SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
|
||||
kSecPortItemAttr);
|
||||
UInt32* data = static_cast<UInt32*>(attribute->data);
|
||||
*data = value;
|
||||
}
|
||||
|
||||
void MockKeychain::SetTestDataProtocol(MockKeychainItemType item,
|
||||
SecProtocolType value) {
|
||||
void MockAppleKeychain::SetTestDataProtocol(MockKeychainItemType item,
|
||||
SecProtocolType value) {
|
||||
SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
|
||||
kSecProtocolItemAttr);
|
||||
SecProtocolType* data = static_cast<SecProtocolType*>(attribute->data);
|
||||
*data = value;
|
||||
}
|
||||
|
||||
void MockKeychain::SetTestDataAuthType(
|
||||
MockKeychainItemType item,
|
||||
SecAuthenticationType value) {
|
||||
void MockAppleKeychain::SetTestDataAuthType(MockKeychainItemType item,
|
||||
SecAuthenticationType value) {
|
||||
SecKeychainAttribute* attribute = AttributeWithTag(
|
||||
keychain_attr_list_[item], kSecAuthenticationTypeItemAttr);
|
||||
SecAuthenticationType* data = static_cast<SecAuthenticationType*>(
|
||||
@ -146,24 +146,25 @@ void MockKeychain::SetTestDataAuthType(
|
||||
*data = value;
|
||||
}
|
||||
|
||||
void MockKeychain::SetTestDataNegativeItem(MockKeychainItemType item,
|
||||
Boolean value) {
|
||||
void MockAppleKeychain::SetTestDataNegativeItem(MockKeychainItemType item,
|
||||
Boolean value) {
|
||||
SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
|
||||
kSecNegativeItemAttr);
|
||||
Boolean* data = static_cast<Boolean*>(attribute->data);
|
||||
*data = value;
|
||||
}
|
||||
|
||||
void MockKeychain::SetTestDataCreator(MockKeychainItemType item, OSType value) {
|
||||
void MockAppleKeychain::SetTestDataCreator(MockKeychainItemType item,
|
||||
OSType value) {
|
||||
SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item],
|
||||
kSecCreatorItemAttr);
|
||||
OSType* data = static_cast<OSType*>(attribute->data);
|
||||
*data = value;
|
||||
}
|
||||
|
||||
void MockKeychain::SetTestDataPasswordBytes(MockKeychainItemType item,
|
||||
const void* data,
|
||||
size_t length) {
|
||||
void MockAppleKeychain::SetTestDataPasswordBytes(MockKeychainItemType item,
|
||||
const void* data,
|
||||
size_t length) {
|
||||
keychain_data_[item].length = length;
|
||||
if (length > 0) {
|
||||
if (keychain_data_[item].data)
|
||||
@ -175,13 +176,12 @@ void MockKeychain::SetTestDataPasswordBytes(MockKeychainItemType item,
|
||||
}
|
||||
}
|
||||
|
||||
void MockKeychain::SetTestDataPasswordString(
|
||||
MockKeychainItemType item,
|
||||
const char* value) {
|
||||
void MockAppleKeychain::SetTestDataPasswordString(MockKeychainItemType item,
|
||||
const char* value) {
|
||||
SetTestDataPasswordBytes(item, value, value ? strlen(value) : 0);
|
||||
}
|
||||
|
||||
OSStatus MockKeychain::ItemCopyAttributesAndData(
|
||||
OSStatus MockAppleKeychain::ItemCopyAttributesAndData(
|
||||
SecKeychainItemRef itemRef,
|
||||
SecKeychainAttributeInfo* info,
|
||||
SecItemClass* itemClass,
|
||||
@ -207,7 +207,7 @@ OSStatus MockKeychain::ItemCopyAttributesAndData(
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus MockKeychain::ItemModifyAttributesAndData(
|
||||
OSStatus MockAppleKeychain::ItemModifyAttributesAndData(
|
||||
SecKeychainItemRef itemRef,
|
||||
const SecKeychainAttributeList* attrList,
|
||||
UInt32 length,
|
||||
@ -224,7 +224,7 @@ OSStatus MockKeychain::ItemModifyAttributesAndData(
|
||||
if (keychain_attr_list_.find(key) == keychain_attr_list_.end())
|
||||
return errSecInvalidItemRef;
|
||||
|
||||
MockKeychain* mutable_this = const_cast<MockKeychain*>(this);
|
||||
MockAppleKeychain* mutable_this = const_cast<MockAppleKeychain*>(this);
|
||||
if (attrList) {
|
||||
for (UInt32 change_attr = 0; change_attr < attrList->count; ++change_attr) {
|
||||
if (attrList->attr[change_attr].tag == kSecCreatorItemAttr) {
|
||||
@ -240,14 +240,14 @@ OSStatus MockKeychain::ItemModifyAttributesAndData(
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus MockKeychain::ItemFreeAttributesAndData(
|
||||
OSStatus MockAppleKeychain::ItemFreeAttributesAndData(
|
||||
SecKeychainAttributeList* attrList,
|
||||
void* data) const {
|
||||
--attribute_data_copy_count_;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus MockKeychain::ItemDelete(SecKeychainItemRef itemRef) const {
|
||||
OSStatus MockAppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const {
|
||||
MockKeychainItemType key =
|
||||
reinterpret_cast<MockKeychainItemType>(itemRef) - 1;
|
||||
|
||||
@ -265,7 +265,7 @@ OSStatus MockKeychain::ItemDelete(SecKeychainItemRef itemRef) const {
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus MockKeychain::SearchCreateFromAttributes(
|
||||
OSStatus MockAppleKeychain::SearchCreateFromAttributes(
|
||||
CFTypeRef keychainOrArray,
|
||||
SecItemClass itemClass,
|
||||
const SecKeychainAttributeList* attrList,
|
||||
@ -273,8 +273,8 @@ OSStatus MockKeychain::SearchCreateFromAttributes(
|
||||
// Figure out which of our mock items matches, and set up the array we'll use
|
||||
// to generate results out of SearchCopyNext.
|
||||
remaining_search_results_.clear();
|
||||
for (std::map<MockKeychainItemType, SecKeychainAttributeList>::const_iterator
|
||||
it = keychain_attr_list_.begin();
|
||||
for (MockKeychainAttributesMap::const_iterator it =
|
||||
keychain_attr_list_.begin();
|
||||
it != keychain_attr_list_.end();
|
||||
++it) {
|
||||
bool mock_item_matches = true;
|
||||
@ -298,7 +298,7 @@ OSStatus MockKeychain::SearchCreateFromAttributes(
|
||||
return noErr;
|
||||
}
|
||||
|
||||
bool MockKeychain::AlreadyContainsInternetPassword(
|
||||
bool MockAppleKeychain::AlreadyContainsInternetPassword(
|
||||
UInt32 serverNameLength,
|
||||
const char* serverName,
|
||||
UInt32 securityDomainLength,
|
||||
@ -310,8 +310,8 @@ bool MockKeychain::AlreadyContainsInternetPassword(
|
||||
UInt16 port,
|
||||
SecProtocolType protocol,
|
||||
SecAuthenticationType authenticationType) const {
|
||||
for (std::map<MockKeychainItemType, SecKeychainAttributeList>::const_iterator
|
||||
it = keychain_attr_list_.begin();
|
||||
for (MockKeychainAttributesMap::const_iterator it =
|
||||
keychain_attr_list_.begin();
|
||||
it != keychain_attr_list_.end();
|
||||
++it) {
|
||||
SecKeychainAttribute* attribute;
|
||||
@ -374,7 +374,7 @@ bool MockKeychain::AlreadyContainsInternetPassword(
|
||||
return false;
|
||||
}
|
||||
|
||||
OSStatus MockKeychain::AddInternetPassword(
|
||||
OSStatus MockAppleKeychain::AddInternetPassword(
|
||||
SecKeychainRef keychain,
|
||||
UInt32 serverNameLength,
|
||||
const char* serverName,
|
||||
@ -411,7 +411,7 @@ OSStatus MockKeychain::AddInternetPassword(
|
||||
// Initialize keychain data storage at the target location.
|
||||
InitializeKeychainData(key);
|
||||
|
||||
MockKeychain* mutable_this = const_cast<MockKeychain*>(this);
|
||||
MockAppleKeychain* mutable_this = const_cast<MockAppleKeychain*>(this);
|
||||
mutable_this->SetTestDataBytes(key, kSecServerItemAttr, serverName,
|
||||
serverNameLength);
|
||||
mutable_this->SetTestDataBytes(key, kSecSecurityDomainItemAttr,
|
||||
@ -441,8 +441,8 @@ OSStatus MockKeychain::AddInternetPassword(
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus MockKeychain::SearchCopyNext(SecKeychainSearchRef searchRef,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
OSStatus MockAppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
if (remaining_search_results_.empty())
|
||||
return errSecItemNotFound;
|
||||
MockKeychainItemType key = remaining_search_results_.front();
|
||||
@ -452,55 +452,7 @@ OSStatus MockKeychain::SearchCopyNext(SecKeychainSearchRef searchRef,
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus MockKeychain::FindGenericPassword(CFTypeRef keychainOrArray,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32* passwordLength,
|
||||
void** passwordData,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
// When simulating |noErr| we return canned |passwordData| and
|
||||
// |passwordLenght|. Otherwise, just return given code.
|
||||
if (find_generic_result_ == noErr) {
|
||||
static char password[] = "my_password";
|
||||
|
||||
DCHECK(passwordData);
|
||||
*passwordData = static_cast<void*>(password);
|
||||
DCHECK(passwordLength);
|
||||
*passwordLength = strlen(password);
|
||||
password_data_count_++;
|
||||
}
|
||||
|
||||
return find_generic_result_;
|
||||
}
|
||||
|
||||
OSStatus MockKeychain::ItemFreeContent(SecKeychainAttributeList* attrList,
|
||||
void* data) const {
|
||||
// No-op.
|
||||
password_data_count_--;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus MockKeychain::AddGenericPassword(SecKeychainRef keychain,
|
||||
UInt32 serviceNameLength,
|
||||
const char* serviceName,
|
||||
UInt32 accountNameLength,
|
||||
const char* accountName,
|
||||
UInt32 passwordLength,
|
||||
const void* passwordData,
|
||||
SecKeychainItemRef* itemRef) const {
|
||||
called_add_generic_ = true;
|
||||
|
||||
DCHECK(passwordLength > 0);
|
||||
DCHECK(passwordData);
|
||||
add_generic_password_ =
|
||||
std::string(const_cast<char*>(static_cast<const char*>(passwordData)),
|
||||
passwordLength);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
void MockKeychain::Free(CFTypeRef ref) const {
|
||||
void MockAppleKeychain::Free(CFTypeRef ref) const {
|
||||
if (!ref)
|
||||
return;
|
||||
|
||||
@ -511,19 +463,19 @@ void MockKeychain::Free(CFTypeRef ref) const {
|
||||
}
|
||||
}
|
||||
|
||||
int MockKeychain::UnfreedSearchCount() const {
|
||||
int MockAppleKeychain::UnfreedSearchCount() const {
|
||||
return search_copy_count_;
|
||||
}
|
||||
|
||||
int MockKeychain::UnfreedKeychainItemCount() const {
|
||||
int MockAppleKeychain::UnfreedKeychainItemCount() const {
|
||||
return keychain_item_copy_count_;
|
||||
}
|
||||
|
||||
int MockKeychain::UnfreedAttributeDataCount() const {
|
||||
int MockAppleKeychain::UnfreedAttributeDataCount() const {
|
||||
return attribute_data_copy_count_;
|
||||
}
|
||||
|
||||
bool MockKeychain::CreatorCodesSetForAddedItems() const {
|
||||
bool MockAppleKeychain::CreatorCodesSetForAddedItems() const {
|
||||
for (std::set<MockKeychainItemType>::const_iterator
|
||||
i = added_via_api_.begin();
|
||||
i != added_via_api_.end();
|
||||
@ -537,7 +489,7 @@ bool MockKeychain::CreatorCodesSetForAddedItems() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void MockKeychain::AddTestItem(const KeychainTestData& item_data) {
|
||||
void MockAppleKeychain::AddTestItem(const KeychainTestData& item_data) {
|
||||
MockKeychainItemType key = next_item_key_++;
|
||||
|
||||
InitializeKeychainData(key);
|
Reference in New Issue
Block a user