1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gmock/include/gmock/gmock.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_temp_dir.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/path_service.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/stl_util-inl.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/keychain_mock_mac.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/password_manager/password_store_consumer.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/password_manager/password_store_mac.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/password_manager/password_store_mac_internal.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_paths.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing webkit_glue::PasswordForm;
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing testing::_;
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing testing::DoAll;
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing testing::WithArg;
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MockPasswordStoreConsumer : public PasswordStoreConsumer {
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochpublic:
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MOCK_METHOD2(OnPasswordStoreRequestDone,
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               void(CancelableRequestProvider::Handle,
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                    const std::vector<webkit_glue::PasswordForm*>&));
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochACTION(STLDeleteElements0) {
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  STLDeleteContainerPointers(arg0.begin(), arg0.end());
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochACTION(QuitUIMessageLoop) {
41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->Quit();
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#pragma mark -
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass PasswordStoreMacInternalsTest : public testing::Test {
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void SetUp() {
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockKeychain::KeychainTestData test_data[] = {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Basic HTML form.
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { kSecAuthenticationTypeHTMLForm, "some.domain.com",
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z",
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "joe_user", "sekrit", false },
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // HTML form with path.
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { kSecAuthenticationTypeHTMLForm, "some.domain.com",
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "19991231235959Z",
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "joe_user", "sekrit", false },
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Secure HTML form with path.
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { kSecAuthenticationTypeHTMLForm, "some.domain.com",
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kSecProtocolTypeHTTPS, "/secure.html", 0, NULL, "20100908070605Z",
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "secure_user", "password", false },
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // True negative item.
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { kSecAuthenticationTypeHTMLForm, "dont.remember.com",
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kSecProtocolTypeHTTP, NULL, 0, NULL, "20000101000000Z",
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "", "", true },
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // De-facto negative item, type one.
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { kSecAuthenticationTypeHTMLForm, "dont.remember.com",
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kSecProtocolTypeHTTP, NULL, 0, NULL, "20000101000000Z",
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "Password Not Stored", "", false },
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // De-facto negative item, type two.
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { kSecAuthenticationTypeHTMLForm, "dont.remember.com",
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kSecProtocolTypeHTTPS, NULL, 0, NULL, "20000101000000Z",
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "Password Not Stored", " ", false },
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // HTTP auth basic, with port and path.
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { kSecAuthenticationTypeHTTPBasic, "some.domain.com",
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kSecProtocolTypeHTTP, "/insecure.html", 4567, "low_security",
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "19980330100000Z",
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "basic_auth_user", "basic", false },
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // HTTP auth digest, secure.
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { kSecAuthenticationTypeHTTPDigest, "some.domain.com",
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kSecProtocolTypeHTTPS, NULL, 0, "high_security", "19980330100000Z",
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "digest_auth_user", "digest", false },
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // An FTP password with an invalid date, for edge-case testing.
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { kSecAuthenticationTypeDefault, "a.server.com",
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        kSecProtocolTypeFTP, NULL, 0, NULL, "20010203040",
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "abc", "123", false },
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Save some extra slots for use by AddInternetPassword.
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    unsigned int capacity = arraysize(test_data) + 3;
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    keychain_ = new MockKeychain(capacity);
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (unsigned int i = 0; i < arraysize(test_data); ++i) {
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      keychain_->AddTestItem(test_data[i]);
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void TearDown() {
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ExpectCreatesAndFreesBalanced();
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ExpectCreatorCodesSet();
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete keychain_;
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Causes a test failure unless everything returned from keychain_'s
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ItemCopyAttributesAndData, SearchCreateFromAttributes, and SearchCopyNext
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // was correctly freed.
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ExpectCreatesAndFreesBalanced() {
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(0, keychain_->UnfreedSearchCount());
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(0, keychain_->UnfreedKeychainItemCount());
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(0, keychain_->UnfreedAttributeDataCount());
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Causes a test failure unless any Keychain items added during the test have
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // their creator code set.
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ExpectCreatorCodesSet() {
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(keychain_->CreatorCodesSetForAddedItems());
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockKeychain* keychain_;
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#pragma mark -
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Struct used for creation of PasswordForms from static arrays of data.
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct PasswordFormData {
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const PasswordForm::Scheme scheme;
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* signon_realm;
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* origin;
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* action;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const wchar_t* submit_element;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const wchar_t* username_element;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const wchar_t* password_element;
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const wchar_t* username_value;  // Set to NULL for a blacklist entry.
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const wchar_t* password_value;
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool preferred;
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool ssl_valid;
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const double creation_time;
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Creates and returns a new PasswordForm built from form_data. Caller is
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// responsible for deleting the object when finished with it.
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic PasswordForm* CreatePasswordFormFromData(
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const PasswordFormData& form_data) {
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordForm* form = new PasswordForm();
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  form->scheme = form_data.scheme;
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  form->preferred = form_data.preferred;
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  form->ssl_valid = form_data.ssl_valid;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  form->date_created = base::Time::FromDoubleT(form_data.creation_time);
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (form_data.signon_realm)
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form->signon_realm = std::string(form_data.signon_realm);
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (form_data.origin)
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form->origin = GURL(form_data.origin);
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (form_data.action)
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form->action = GURL(form_data.action);
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (form_data.submit_element)
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form->submit_element = WideToUTF16(form_data.submit_element);
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (form_data.username_element)
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form->username_element = WideToUTF16(form_data.username_element);
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (form_data.password_element)
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form->password_element = WideToUTF16(form_data.password_element);
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (form_data.username_value) {
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form->username_value = WideToUTF16(form_data.username_value);
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (form_data.password_value)
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      form->password_value = WideToUTF16(form_data.password_value);
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form->blacklisted_by_user = true;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return form;
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Macro to simplify calling CheckFormsAgainstExpectations with a useful label.
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHECK_FORMS(forms, expectations, i) \
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CheckFormsAgainstExpectations(forms, expectations, #forms, i)
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Ensures that the data in |forms| match |expectations|, causing test failures
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// for any discrepencies.
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(stuartmorgan): This is current order-dependent; ideally it shouldn't
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// matter if |forms| and |expectations| are scrambled.
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void CheckFormsAgainstExpectations(
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::vector<PasswordForm*>& forms,
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::vector<PasswordFormData*>& expectations,
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* forms_label, unsigned int test_number) {
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const unsigned int kBufferSize = 128;
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char test_label[kBufferSize];
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  snprintf(test_label, kBufferSize, "%s in test %u", forms_label, test_number);
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(expectations.size(), forms.size()) << test_label;
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (expectations.size() != forms.size())
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned int i = 0; i < expectations.size(); ++i) {
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    snprintf(test_label, kBufferSize, "%s in test %u, item %u",
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             forms_label, test_number, i);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm* form = forms[i];
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordFormData* expectation = expectations[i];
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(expectation->scheme, form->scheme) << test_label;
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(std::string(expectation->signon_realm), form->signon_realm)
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << test_label;
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(GURL(expectation->origin), form->origin) << test_label;
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(GURL(expectation->action), form->action) << test_label;
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(WideToUTF16(expectation->submit_element), form->submit_element)
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << test_label;
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(WideToUTF16(expectation->username_element),
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              form->username_element) << test_label;
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(WideToUTF16(expectation->password_element),
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              form->password_element) << test_label;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (expectation->username_value) {
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(WideToUTF16(expectation->username_value),
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                form->username_value) << test_label;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(WideToUTF16(expectation->password_value),
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                form->password_value) << test_label;
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_TRUE(form->blacklisted_by_user) << test_label;
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(expectation->preferred, form->preferred)  << test_label;
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(expectation->ssl_valid, form->ssl_valid) << test_label;
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_DOUBLE_EQ(expectation->creation_time,
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     form->date_created.ToDoubleT()) << test_label;
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#pragma mark -
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(PasswordStoreMacInternalsTest, TestKeychainToFormTranslation) {
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef struct {
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const PasswordForm::Scheme scheme;
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* signon_realm;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* origin;
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const wchar_t* username;  // Set to NULL to check for a blacklist entry.
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const wchar_t* password;
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const bool ssl_valid;
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int creation_year;
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int creation_month;
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int creation_day;
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int creation_hour;
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int creation_minute;
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int creation_second;
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } TestExpectations;
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestExpectations expected[] = {
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com/", L"joe_user", L"sekrit", false,
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      2002,  6,  1, 17, 15,  0 },
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com/insecure.html", L"joe_user", L"sekrit", false,
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      1999, 12, 31, 23, 59, 59 },
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "https://some.domain.com/",
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "https://some.domain.com/secure.html", L"secure_user", L"password", true,
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      2010,  9,  8,  7,  6,  5 },
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "http://dont.remember.com/",
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://dont.remember.com/", NULL, NULL, false,
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      2000,  1,  1,  0,  0,  0 },
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "http://dont.remember.com/",
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://dont.remember.com/", NULL, NULL, false,
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      2000,  1,  1,  0,  0,  0 },
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "https://dont.remember.com/",
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "https://dont.remember.com/", NULL, NULL, true,
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      2000,  1,  1,  0,  0,  0 },
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security",
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com:4567/insecure.html", L"basic_auth_user", L"basic",
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      false, 1998, 03, 30, 10, 00, 00 },
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security",
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "https://some.domain.com/", L"digest_auth_user", L"digest", true,
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      1998,  3, 30, 10,  0,  0 },
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This one gives us an invalid date, which we will treat as a "NULL" date
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // which is 1601.
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_OTHER, "http://a.server.com/",
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://a.server.com/", L"abc", L"123", false,
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      1601,  1,  1,  0,  0,  0 },
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(expected); ++i) {
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Create our fake KeychainItemRef; see MockKeychain docs.
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SecKeychainItemRef keychain_item =
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        reinterpret_cast<SecKeychainItemRef>(i + 1);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm form;
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem(
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *keychain_, keychain_item, &form);
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(parsed) << "In iteration " << i;
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(expected[i].scheme, form.scheme) << "In iteration " << i;
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(GURL(expected[i].origin), form.origin) << "In iteration " << i;
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(expected[i].ssl_valid, form.ssl_valid) << "In iteration " << i;
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(std::string(expected[i].signon_realm), form.signon_realm)
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << "In iteration " << i;
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (expected[i].username) {
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(WideToUTF16(expected[i].username), form.username_value)
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          << "In iteration " << i;
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(WideToUTF16(expected[i].password), form.password_value)
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          << "In iteration " << i;
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_FALSE(form.blacklisted_by_user) << "In iteration " << i;
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_TRUE(form.blacklisted_by_user) << "In iteration " << i;
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::Time::Exploded exploded_time;
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form.date_created.UTCExplode(&exploded_time);
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(expected[i].creation_year, exploded_time.year)
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         << "In iteration " << i;
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(expected[i].creation_month, exploded_time.month)
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << "In iteration " << i;
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(expected[i].creation_day, exploded_time.day_of_month)
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << "In iteration " << i;
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(expected[i].creation_hour, exploded_time.hour)
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << "In iteration " << i;
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(expected[i].creation_minute, exploded_time.minute)
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << "In iteration " << i;
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(expected[i].creation_second, exploded_time.second)
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << "In iteration " << i;
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Use an invalid ref, to make sure errors are reported.
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(99);
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm form;
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool parsed = internal_keychain_helpers::FillPasswordFormFromKeychainItem(
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *keychain_, keychain_item, &form);
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_FALSE(parsed);
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(PasswordStoreMacInternalsTest, TestKeychainSearch) {
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct TestDataAndExpectation {
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const PasswordFormData data;
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const size_t expected_fill_matches;
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const size_t expected_merge_matches;
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Most fields are left blank because we don't care about them for searching.
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestDataAndExpectation test_data[] = {
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // An HTML form we've seen.
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL, NULL, NULL, NULL, NULL, L"joe_user", NULL, false, false, 0 },
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      2, 2 },
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL, NULL, NULL, NULL, NULL, L"wrong_user", NULL, false, false, 0 },
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      2, 0 },
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // An HTML form we haven't seen
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "http://www.unseendomain.com/",
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL, NULL, NULL, NULL, NULL, L"joe_user", NULL, false, false, 0 },
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      0, 0 },
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Basic auth that should match.
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security",
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL, NULL, NULL, NULL, NULL, L"basic_auth_user", NULL, false, false,
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        0 },
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      1, 1 },
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Basic auth with the wrong port.
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_BASIC, "http://some.domain.com:1111/low_security",
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL, NULL, NULL, NULL, NULL, L"basic_auth_user", NULL, false, false,
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        0 },
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      0, 0 },
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Digest auth we've saved under https, visited with http.
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_DIGEST, "http://some.domain.com/high_security",
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL, NULL, NULL, NULL, NULL, L"digest_auth_user", NULL, false, false,
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        0 },
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      0, 0 },
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Digest auth that should match.
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security",
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL, NULL, NULL, NULL, NULL, L"wrong_user", NULL, false, true, 0 },
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      1, 0 },
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Digest auth with the wrong domain.
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/other_domain",
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL, NULL, NULL, NULL, NULL, L"digest_auth_user", NULL, false, true,
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        0 },
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      0, 0 },
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Garbage forms should have no matches.
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "foo/bar/baz",
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, false, 0 }, 0, 0 },
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MacKeychainPasswordFormAdapter keychain_adapter(keychain_);
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_);
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  owned_keychain_adapter.SetFindsOnlyOwnedItems(true);
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<PasswordForm> query_form(
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        CreatePasswordFormFromData(test_data[i].data));
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Check matches treating the form as a fill target.
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<PasswordForm*> matching_items =
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        keychain_adapter.PasswordsFillingForm(*query_form);
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(test_data[i].expected_fill_matches, matching_items.size());
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    STLDeleteElements(&matching_items);
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Check matches treating the form as a merging target.
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(test_data[i].expected_merge_matches > 0,
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              keychain_adapter.HasPasswordsMergeableWithForm(*query_form));
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    matching_items = keychain_adapter.PasswordsMergeableWithForm(*query_form);
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(test_data[i].expected_merge_matches, matching_items.size());
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    STLDeleteElements(&matching_items);
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // None of the pre-seeded items are owned by us, so none should match an
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // owned-passwords-only search.
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    matching_items = owned_keychain_adapter.PasswordsFillingForm(*query_form);
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(0U, matching_items.size());
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    STLDeleteElements(&matching_items);
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Changes just the origin path of |form|.
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void SetPasswordFormPath(PasswordForm* form, const char* path) {
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL::Replacements replacement;
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string new_value(path);
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  replacement.SetPathStr(new_value);
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  form->origin = form->origin.ReplaceComponents(replacement);
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Changes just the signon_realm port of |form|.
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void SetPasswordFormPort(PasswordForm* form, const char* port) {
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL::Replacements replacement;
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string new_value(port);
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  replacement.SetPortStr(new_value);
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL signon_gurl = GURL(form->signon_realm);
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  form->signon_realm = signon_gurl.ReplaceComponents(replacement).spec();
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Changes just the signon_ream auth realm of |form|.
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void SetPasswordFormRealm(PasswordForm* form, const char* realm) {
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL::Replacements replacement;
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string new_value(realm);
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  replacement.SetPathStr(new_value);
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL signon_gurl = GURL(form->signon_realm);
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  form->signon_realm = signon_gurl.ReplaceComponents(replacement).spec();
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(PasswordStoreMacInternalsTest, TestKeychainExactSearch) {
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MacKeychainPasswordFormAdapter keychain_adapter(keychain_);
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData base_form_data[] = {
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com/insecure.html",
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL, NULL, NULL, NULL, L"joe_user", NULL, true, false, 0 },
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_BASIC, "http://some.domain.com:4567/low_security",
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com:4567/insecure.html",
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL, NULL, NULL, NULL, L"basic_auth_user", NULL, true, false, 0 },
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_DIGEST, "https://some.domain.com/high_security",
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "https://some.domain.com",
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL, NULL, NULL, NULL, L"digest_auth_user", NULL, true, true, 0 },
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned int i = 0; i < arraysize(base_form_data); ++i) {
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Create a base form and make sure we find a match.
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<PasswordForm> base_form(CreatePasswordFormFromData(
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        base_form_data[i]));
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(keychain_adapter.HasPasswordsMergeableWithForm(*base_form));
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm* match =
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        keychain_adapter.PasswordExactlyMatchingForm(*base_form);
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(match != NULL);
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (match) {
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(base_form->scheme, match->scheme);
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(base_form->origin, match->origin);
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(base_form->username_value, match->username_value);
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete match;
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Make sure that the matching isn't looser than it should be by checking
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // that slightly altered forms don't match.
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<PasswordForm*> modified_forms;
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    modified_forms.push_back(new PasswordForm(*base_form));
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    modified_forms.back()->username_value = ASCIIToUTF16("wrong_user");
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    modified_forms.push_back(new PasswordForm(*base_form));
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetPasswordFormPath(modified_forms.back(), "elsewhere.html");
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    modified_forms.push_back(new PasswordForm(*base_form));
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    modified_forms.back()->scheme = PasswordForm::SCHEME_OTHER;
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    modified_forms.push_back(new PasswordForm(*base_form));
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetPasswordFormPort(modified_forms.back(), "1234");
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    modified_forms.push_back(new PasswordForm(*base_form));
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    modified_forms.back()->blacklisted_by_user = true;
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (base_form->scheme == PasswordForm::SCHEME_BASIC ||
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        base_form->scheme == PasswordForm::SCHEME_DIGEST) {
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      modified_forms.push_back(new PasswordForm(*base_form));
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SetPasswordFormRealm(modified_forms.back(), "incorrect");
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (unsigned int j = 0; j < modified_forms.size(); ++j) {
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      PasswordForm* match =
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          keychain_adapter.PasswordExactlyMatchingForm(*modified_forms[j]);
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(NULL, match) << "In modified version " << j << " of base form "
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             << i;
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    STLDeleteElements(&modified_forms);
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(PasswordStoreMacInternalsTest, TestKeychainAdd) {
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct TestDataAndExpectation {
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordFormData data;
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool should_succeed;
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestDataAndExpectation test_data[] = {
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Test a variety of scheme/port/protocol/path variations.
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "http://web.site.com/",
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL,
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"anonymous", L"knock-knock", false, false, 0 }, true },
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "https://web.site.com/",
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "https://web.site.com/", NULL, NULL, NULL, NULL,
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"admin", L"p4ssw0rd", false, false, 0 }, true },
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_BASIC, "http://a.site.com:2222/therealm",
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://a.site.com:2222/", NULL, NULL, NULL, NULL,
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"username", L"password", false, false, 0 }, true },
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_DIGEST, "https://digest.site.com/differentrealm",
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "https://digest.site.com/secure.html", NULL, NULL, NULL, NULL,
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"testname", L"testpass", false, false, 0 }, true },
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Make sure that garbage forms are rejected.
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "gobbledygook",
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "gobbledygook", NULL, NULL, NULL, NULL,
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"anonymous", L"knock-knock", false, false, 0 }, false },
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Test that failing to update a duplicate (forced using the magic failure
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // password; see MockKeychain::ItemModifyAttributesAndData) is reported.
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "http://some.domain.com",
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/insecure.html", NULL, NULL, NULL, NULL,
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"joe_user", L"fail_me", false, false, 0 }, false },
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_);
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  owned_keychain_adapter.SetFindsOnlyOwnedItems(true);
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<PasswordForm> in_form(
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        CreatePasswordFormFromData(test_data[i].data));
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool add_succeeded = owned_keychain_adapter.AddPassword(*in_form);
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(test_data[i].should_succeed, add_succeeded);
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (add_succeeded) {
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_TRUE(owned_keychain_adapter.HasPasswordsMergeableWithForm(
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          *in_form));
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      scoped_ptr<PasswordForm> out_form(
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          owned_keychain_adapter.PasswordExactlyMatchingForm(*in_form));
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_TRUE(out_form.get() != NULL);
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(out_form->scheme, in_form->scheme);
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(out_form->signon_realm, in_form->signon_realm);
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(out_form->origin, in_form->origin);
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(out_form->username_value, in_form->username_value);
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(out_form->password_value, in_form->password_value);
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Test that adding duplicate item updates the existing item.
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordFormData data = {
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      PasswordForm::SCHEME_HTML, "http://some.domain.com",
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com/insecure.html", NULL,
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL, NULL, NULL, L"joe_user", L"updated_password", false, false, 0
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<PasswordForm> update_form(CreatePasswordFormFromData(data));
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MacKeychainPasswordFormAdapter keychain_adapter(keychain_);
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(keychain_adapter.AddPassword(*update_form));
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(2);
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm stored_form;
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_,
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                                keychain_item,
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                                &stored_form);
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(update_form->password_value, stored_form.password_value);
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(PasswordStoreMacInternalsTest, TestKeychainRemove) {
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct TestDataAndExpectation {
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordFormData data;
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool should_succeed;
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestDataAndExpectation test_data[] = {
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Test deletion of an item that we add.
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "http://web.site.com/",
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL,
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"anonymous", L"knock-knock", false, false, 0 }, true },
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Make sure we don't delete items we don't own.
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/insecure.html", NULL, NULL, NULL, NULL,
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"joe_user", NULL, true, false, 0 }, false },
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_);
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  owned_keychain_adapter.SetFindsOnlyOwnedItems(true);
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add our test item so that we can delete it.
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordForm* add_form = CreatePasswordFormFromData(test_data[0].data);
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(owned_keychain_adapter.AddPassword(*add_form));
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete add_form;
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        test_data[i].data));
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(test_data[i].should_succeed,
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              owned_keychain_adapter.RemovePassword(*form));
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MacKeychainPasswordFormAdapter keychain_adapter(keychain_);
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm* match = keychain_adapter.PasswordExactlyMatchingForm(*form);
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(test_data[i].should_succeed, match == NULL);
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (match) {
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete match;
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(PasswordStoreMacInternalsTest, TestFormMatch) {
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordForm base_form;
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base_form.signon_realm = std::string("http://some.domain.com/");
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base_form.origin = GURL("http://some.domain.com/page.html");
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base_form.username_value = ASCIIToUTF16("joe_user");
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Check that everything unimportant can be changed.
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm different_form(base_form);
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.username_element = ASCIIToUTF16("username");
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.submit_element = ASCIIToUTF16("submit");
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.username_element = ASCIIToUTF16("password");
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.password_value = ASCIIToUTF16("sekrit");
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.action = GURL("http://some.domain.com/action.cgi");
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.ssl_valid = true;
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.preferred = true;
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.date_created = base::Time::Now();
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(internal_keychain_helpers::FormsMatchForMerge(base_form,
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                              different_form));
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Check that path differences don't prevent a match.
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base_form.origin = GURL("http://some.domain.com/other_page.html");
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(internal_keychain_helpers::FormsMatchForMerge(base_form,
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                              different_form));
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check that any one primary key changing is enough to prevent matching.
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm different_form(base_form);
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.scheme = PasswordForm::SCHEME_DIGEST;
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_FALSE(internal_keychain_helpers::FormsMatchForMerge(base_form,
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                               different_form));
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm different_form(base_form);
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.signon_realm = std::string("http://some.domain.com:8080/");
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_FALSE(internal_keychain_helpers::FormsMatchForMerge(base_form,
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                               different_form));
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm different_form(base_form);
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.username_value = ASCIIToUTF16("john.doe");
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_FALSE(internal_keychain_helpers::FormsMatchForMerge(base_form,
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                               different_form));
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm different_form(base_form);
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    different_form.blacklisted_by_user = true;
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_FALSE(internal_keychain_helpers::FormsMatchForMerge(base_form,
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                               different_form));
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Blacklist forms should *never* match for merging, even when identical
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (and certainly not when only one is a blacklist entry).
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm form_a(base_form);
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    form_a.blacklisted_by_user = true;
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm form_b(form_a);
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_FALSE(internal_keychain_helpers::FormsMatchForMerge(form_a, form_b));
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(PasswordStoreMacInternalsTest, TestFormMerge) {
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set up a bunch of test data to use in varying combinations.
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData keychain_user_1 =
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/", "", L"", L"", L"", L"joe_user", L"sekrit",
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        false, false, 1010101010 };
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData keychain_user_1_with_path =
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/page.html",
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "", L"", L"", L"", L"joe_user", L"otherpassword",
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        false, false, 1010101010 };
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData keychain_user_2 =
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/", "", L"", L"", L"", L"john.doe", L"sesame",
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        false, false, 958739876 };
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData keychain_blacklist =
681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/", "", L"", L"", L"", NULL, NULL,
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        false, false, 1010101010 };
684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData db_user_1 =
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/", "http://some.domain.com/action.cgi",
688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"submit", L"username", L"password", L"joe_user", L"",
689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        true, false, 1212121212 };
690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData db_user_1_with_path =
691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/page.html",
693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/handlepage.cgi",
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"submit", L"username", L"password", L"joe_user", L"",
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        true, false, 1234567890 };
696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData db_user_3_with_path =
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/page.html",
699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/handlepage.cgi",
700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"submit", L"username", L"password", L"second-account", L"",
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        true, false, 1240000000 };
702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData database_blacklist_with_path =
703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/path.html", "http://some.domain.com/action.cgi",
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"submit", L"username", L"password", NULL, NULL,
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        true, false, 1212121212 };
707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData merged_user_1 =
709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/", "http://some.domain.com/action.cgi",
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"submit", L"username", L"password", L"joe_user", L"sekrit",
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        true, false, 1212121212 };
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData merged_user_1_with_db_path =
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/page.html",
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/handlepage.cgi",
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"submit", L"username", L"password", L"joe_user", L"sekrit",
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        true, false, 1234567890 };
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData merged_user_1_with_both_paths =
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/page.html",
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/handlepage.cgi",
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"submit", L"username", L"password", L"joe_user", L"otherpassword",
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        true, false, 1234567890 };
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Build up the big multi-dimensional array of data sets that will actually
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // drive the test. Use vectors rather than arrays so that initialization is
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // simple.
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  enum {
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    KEYCHAIN_INPUT = 0,
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DATABASE_INPUT,
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MERGE_OUTPUT,
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    KEYCHAIN_OUTPUT,
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DATABASE_OUTPUT,
735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MERGE_IO_ARRAY_COUNT  // termination marker
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const unsigned int kTestCount = 4;
738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector< std::vector< std::vector<PasswordFormData*> > > test_data(
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MERGE_IO_ARRAY_COUNT, std::vector< std::vector<PasswordFormData*> >(
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          kTestCount, std::vector<PasswordFormData*>()));
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int current_test = 0;
742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Test a merge with a few accounts in both systems, with partial overlap.
744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CHECK(current_test < kTestCount);
745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[KEYCHAIN_INPUT][current_test].push_back(&keychain_user_1);
746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[KEYCHAIN_INPUT][current_test].push_back(&keychain_user_2);
747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[DATABASE_INPUT][current_test].push_back(&db_user_1);
748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[DATABASE_INPUT][current_test].push_back(&db_user_1_with_path);
749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[DATABASE_INPUT][current_test].push_back(&db_user_3_with_path);
750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[MERGE_OUTPUT][current_test].push_back(&merged_user_1);
751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[MERGE_OUTPUT][current_test].push_back(&merged_user_1_with_db_path);
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[KEYCHAIN_OUTPUT][current_test].push_back(&keychain_user_2);
753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[DATABASE_OUTPUT][current_test].push_back(&db_user_3_with_path);
754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Test a merge where Chrome has a blacklist entry, and the keychain has
756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // a stored account.
757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ++current_test;
758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CHECK(current_test < kTestCount);
759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[KEYCHAIN_INPUT][current_test].push_back(&keychain_user_1);
760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[DATABASE_INPUT][current_test].push_back(
761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &database_blacklist_with_path);
762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We expect both to be present because a blacklist could be specific to a
763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // subpath, and we want access to the password on other paths.
764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[MERGE_OUTPUT][current_test].push_back(
765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &database_blacklist_with_path);
766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[KEYCHAIN_OUTPUT][current_test].push_back(&keychain_user_1);
767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Test a merge where Chrome has an account, and Keychain has a blacklist
769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (from another browser) and the Chrome password data.
770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ++current_test;
771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CHECK(current_test < kTestCount);
772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[KEYCHAIN_INPUT][current_test].push_back(&keychain_blacklist);
773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[KEYCHAIN_INPUT][current_test].push_back(&keychain_user_1);
774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[DATABASE_INPUT][current_test].push_back(&db_user_1);
775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[MERGE_OUTPUT][current_test].push_back(&merged_user_1);
776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[KEYCHAIN_OUTPUT][current_test].push_back(&keychain_blacklist);
777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Test that matches are done using exact path when possible.
779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ++current_test;
780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CHECK(current_test < kTestCount);
781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[KEYCHAIN_INPUT][current_test].push_back(&keychain_user_1);
782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[KEYCHAIN_INPUT][current_test].push_back(&keychain_user_1_with_path);
783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[DATABASE_INPUT][current_test].push_back(&db_user_1);
784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[DATABASE_INPUT][current_test].push_back(&db_user_1_with_path);
785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[MERGE_OUTPUT][current_test].push_back(&merged_user_1);
786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  test_data[MERGE_OUTPUT][current_test].push_back(
787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &merged_user_1_with_both_paths);
788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned int test_case = 0; test_case <= current_test; ++test_case) {
790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<PasswordForm*> keychain_forms;
791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (std::vector<PasswordFormData*>::iterator i =
792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             test_data[KEYCHAIN_INPUT][test_case].begin();
793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         i != test_data[KEYCHAIN_INPUT][test_case].end(); ++i) {
794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      keychain_forms.push_back(CreatePasswordFormFromData(*(*i)));
795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<PasswordForm*> database_forms;
797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (std::vector<PasswordFormData*>::iterator i =
798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             test_data[DATABASE_INPUT][test_case].begin();
799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         i != test_data[DATABASE_INPUT][test_case].end(); ++i) {
800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      database_forms.push_back(CreatePasswordFormFromData(*(*i)));
801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<PasswordForm*> merged_forms;
804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    internal_keychain_helpers::MergePasswordForms(&keychain_forms,
805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                  &database_forms,
806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                  &merged_forms);
807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CHECK_FORMS(keychain_forms, test_data[KEYCHAIN_OUTPUT][test_case],
809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                test_case);
810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CHECK_FORMS(database_forms, test_data[DATABASE_OUTPUT][test_case],
811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                test_case);
812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CHECK_FORMS(merged_forms, test_data[MERGE_OUTPUT][test_case], test_case);
813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    STLDeleteElements(&keychain_forms);
815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    STLDeleteElements(&database_forms);
816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    STLDeleteElements(&merged_forms);
817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
820c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(PasswordStoreMacInternalsTest, TestPasswordBulkLookup) {
821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData db_data[] = {
822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com/", "http://some.domain.com/action.cgi",
824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      L"submit", L"username", L"password", L"joe_user", L"",
825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true, false, 1212121212 },
826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com/page.html",
828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com/handlepage.cgi",
829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      L"submit", L"username", L"password", L"joe_user", L"",
830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true, false, 1234567890 },
831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com/page.html",
833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com/handlepage.cgi",
834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      L"submit", L"username", L"password", L"second-account", L"",
835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true, false, 1240000000 },
836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "http://dont.remember.com/",
837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://dont.remember.com/",
838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://dont.remember.com/handlepage.cgi",
839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      L"submit", L"username", L"password", L"joe_user", L"",
840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true, false, 1240000000 },
841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://some.domain.com/path.html", "http://some.domain.com/action.cgi",
843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      L"submit", L"username", L"password", NULL, NULL,
844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true, false, 1212121212 },
845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<PasswordForm*> database_forms;
847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(db_data); ++i) {
848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    database_forms.push_back(CreatePasswordFormFromData(db_data[i]));
849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<PasswordForm*> merged_forms =
851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      internal_keychain_helpers::GetPasswordsForForms(*keychain_,
852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                      &database_forms);
853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(2U, database_forms.size());
854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_EQ(3U, merged_forms.size());
855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ASCIIToUTF16("sekrit"), merged_forms[0]->password_value);
856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ASCIIToUTF16("sekrit"), merged_forms[1]->password_value);
85772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(merged_forms[2]->blacklisted_by_user);
858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  STLDeleteElements(&database_forms);
860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  STLDeleteElements(&merged_forms);
861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(PasswordStoreMacInternalsTest, TestPasswordGetAll) {
864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MacKeychainPasswordFormAdapter keychain_adapter(keychain_);
865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_);
866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  owned_keychain_adapter.SetFindsOnlyOwnedItems(true);
867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add a few passwords of various types so that we own some.
869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData owned_password_data[] = {
870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_HTML, "http://web.site.com/",
871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://web.site.com/path/to/page.html", NULL, NULL, NULL, NULL,
872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      L"anonymous", L"knock-knock", false, false, 0 },
873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_BASIC, "http://a.site.com:2222/therealm",
874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "http://a.site.com:2222/", NULL, NULL, NULL, NULL,
875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      L"username", L"password", false, false, 0 },
876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { PasswordForm::SCHEME_DIGEST, "https://digest.site.com/differentrealm",
877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "https://digest.site.com/secure.html", NULL, NULL, NULL, NULL,
878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      L"testname", L"testpass", false, false, 0 },
879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned int i = 0; i < arraysize(owned_password_data); ++i) {
881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(
882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        owned_password_data[i]));
883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    owned_keychain_adapter.AddPassword(*form);
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<PasswordForm*> all_passwords =
887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      keychain_adapter.GetAllPasswordFormPasswords();
888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(8 + arraysize(owned_password_data), all_passwords.size());
889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  STLDeleteElements(&all_passwords);
890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<PasswordForm*> owned_passwords =
892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      owned_keychain_adapter.GetAllPasswordFormPasswords();
893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(arraysize(owned_password_data), owned_passwords.size());
894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  STLDeleteElements(&owned_passwords);
895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#pragma mark -
898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass PasswordStoreMacTest : public testing::Test {
900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
901731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  PasswordStoreMacTest() : ui_thread_(BrowserThread::UI, &message_loop_) {}
902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void SetUp() {
904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    login_db_ = new LoginDatabase();
905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_TRUE(db_dir_.CreateUniqueTempDir());
906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FilePath db_file = db_dir_.path().AppendASCII("login.db");
907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_TRUE(login_db_->Init(db_file));
908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    keychain_ = new MockKeychain(3);
910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    store_ = new PasswordStoreMac(keychain_, login_db_);
912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_TRUE(store_->Init());
913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void TearDown() {
9163dff810fe0cc4962a5fa554318e9bf8bc45f5274Kristian Monsen    store_->Shutdown();
917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MessageLoop::current()->Run();
919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoopForUI message_loop_;
923731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread ui_thread_;
924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockKeychain* keychain_;  // Owned by store_.
926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LoginDatabase* login_db_;  // Owned by store_.
927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<PasswordStoreMac> store_;
928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ScopedTempDir db_dir_;
929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
931c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(PasswordStoreMacTest, TestStoreUpdate) {
932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Insert a password into both the database and the keychain.
933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is done manually, rather than through store_->AddLogin, because the
934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Mock Keychain isn't smart enough to be able to support update generically,
935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // so some.domain.com triggers special handling to test it that make inserting
936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // fail.
937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PasswordFormData joint_data = {
938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordForm::SCHEME_HTML, "http://some.domain.com/",
939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "http://some.domain.com/insecure.html", "login.cgi",
940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    L"username", L"password", L"submit", L"joe_user", L"sekrit", true, false, 1
941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<PasswordForm> joint_form(CreatePasswordFormFromData(joint_data));
943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  login_db_->AddLogin(*joint_form);
944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockKeychain::KeychainTestData joint_keychain_data = {
945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kSecAuthenticationTypeHTMLForm, "some.domain.com",
946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "20020601171500Z",
947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "joe_user", "sekrit", false };
948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  keychain_->AddTestItem(joint_keychain_data);
949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Insert a password into the keychain only.
951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockKeychain::KeychainTestData keychain_only_data = {
952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kSecAuthenticationTypeHTMLForm, "keychain.only.com",
953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z",
954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "keychain", "only", false
955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  keychain_->AddTestItem(keychain_only_data);
957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct UpdateData {
959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PasswordFormData form_data;
960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* password;  // NULL indicates no entry should be present.
961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make a series of update calls.
964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateData updates[] = {
965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Update the keychain+db passwords (the normal password update case).
966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "http://some.domain.com/",
967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://some.domain.com/insecure.html", "login.cgi",
968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"username", L"password", L"submit", L"joe_user", L"53krit",
969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        true, false, 2 },
970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "53krit",
971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Update the keychain-only password; this simulates the initial use of a
973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // password stored by another browsers.
974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "http://keychain.only.com/",
975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://keychain.only.com/login.html", "login.cgi",
976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"username", L"password", L"submit", L"keychain", L"only",
977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        true, false, 2 },
978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "only",
979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Update a password that doesn't exist in either location. This tests the
981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // case where a form is filled, then the stored login is removed, then the
982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // form is submitted.
983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { { PasswordForm::SCHEME_HTML, "http://different.com/",
984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "http://different.com/index.html", "login.cgi",
985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        L"username", L"password", L"submit", L"abc", L"123",
986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        true, false, 2 },
987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL,
988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(updates); ++i) {
991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(
992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        updates[i].form_data));
993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    store_->UpdateLogin(*form);
994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Do a store-level query to wait for all the operations above to be done.
997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockPasswordStoreConsumer consumer;
998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ON_CALL(consumer, OnPasswordStoreRequestDone(_, _)).WillByDefault(
999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      QuitUIMessageLoop());
1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_CALL(consumer, OnPasswordStoreRequestDone(_, _)).WillOnce(
1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DoAll(WithArg<1>(STLDeleteElements0()), QuitUIMessageLoop()));
1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  store_->GetLogins(*joint_form, &consumer);
1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->Run();
1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MacKeychainPasswordFormAdapter keychain_adapter(keychain_);
1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(updates); ++i) {
1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<PasswordForm> query_form(
1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        CreatePasswordFormFromData(updates[i].form_data));
1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<PasswordForm*> matching_items =
1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        keychain_adapter.PasswordsFillingForm(*query_form);
1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (updates[i].password) {
1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_GT(matching_items.size(), 0U) << "iteration " << i;
1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (matching_items.size() >= 1)
1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        EXPECT_EQ(ASCIIToUTF16(updates[i].password),
1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  matching_items[0]->password_value) << "iteration " << i;
1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(0U, matching_items.size()) << "iteration " << i;
1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    STLDeleteElements(&matching_items);
1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    login_db_->GetLogins(*query_form, &matching_items);
1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(updates[i].password ? 1U : 0U, matching_items.size())
1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << "iteration " << i;
1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    STLDeleteElements(&matching_items);
1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1028