// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <vector>

#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/string16.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/autofill/autofill_cc_infobar_delegate.h"
#include "chrome/browser/autofill/autofill_common_test.h"
#include "chrome/browser/autofill/autofill_manager.h"
#include "chrome/browser/autofill/autofill_metrics.h"
#include "chrome/browser/autofill/personal_data_manager.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "content/browser/tab_contents/test_tab_contents.h"
#include "chrome/browser/ui/tab_contents/test_tab_contents_wrapper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/glue/form_data.h"
#include "webkit/glue/form_field.h"

using webkit_glue::FormData;
using webkit_glue::FormField;

namespace {

class MockAutofillMetrics : public AutofillMetrics {
 public:
  MockAutofillMetrics() {}
  MOCK_CONST_METHOD1(Log, void(CreditCardInfoBarMetric metric));
  MOCK_CONST_METHOD3(Log, void(HeuristicTypeQualityMetric metric,
                               AutofillFieldType field_type,
                               const std::string& experiment_id));
  MOCK_CONST_METHOD3(Log, void(PredictedTypeQualityMetric metric,
                               AutofillFieldType field_type,
                               const std::string& experiment_id));
  MOCK_CONST_METHOD2(Log, void(QualityMetric metric,
                               const std::string& experiment_id));
  MOCK_CONST_METHOD1(Log, void(ServerQueryMetric metric));
  MOCK_CONST_METHOD3(Log, void(ServerTypeQualityMetric metric,
                               AutofillFieldType field_type,
                               const std::string& experiment_id));
  MOCK_CONST_METHOD1(LogIsAutofillEnabledAtPageLoad, void(bool enabled));
  MOCK_CONST_METHOD1(LogIsAutofillEnabledAtStartup, void(bool enabled));
  MOCK_CONST_METHOD1(LogStoredProfileCount, void(size_t num_profiles));
  MOCK_CONST_METHOD1(LogAddressSuggestionsCount, void(size_t num_suggestions));

 private:
  DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
};

class TestPersonalDataManager : public PersonalDataManager {
 public:
  TestPersonalDataManager() : autofill_enabled_(true) {
    set_metric_logger(new MockAutofillMetrics);
    CreateTestAutofillProfiles(&web_profiles_);
  }

  // Overridden to avoid a trip to the database. This should be a no-op except
  // for the side-effect of logging the profile count.
  virtual void LoadProfiles() OVERRIDE {
    std::vector<AutofillProfile*> profiles;
    web_profiles_.release(&profiles);
    WDResult<std::vector<AutofillProfile*> > result(AUTOFILL_PROFILES_RESULT,
                                                    profiles);
    ReceiveLoadedProfiles(0, &result);
  }

  // Overridden to avoid a trip to the database.
  virtual void LoadCreditCards() OVERRIDE {}

  // Adds |profile| to |web_profiles_| and takes ownership of the profile's
  // memory.
  virtual void AddProfile(AutofillProfile* profile) {
    web_profiles_.push_back(profile);
  }

  const MockAutofillMetrics* metric_logger() const {
    return static_cast<const MockAutofillMetrics*>(
        PersonalDataManager::metric_logger());
  }

  void set_autofill_enabled(bool autofill_enabled) {
    autofill_enabled_ = autofill_enabled;
  }

  virtual bool IsAutofillEnabled() const OVERRIDE {
    return autofill_enabled_;
  }

  MOCK_METHOD1(SaveImportedCreditCard,
               void(const CreditCard& imported_credit_card));

 private:
  void CreateTestAutofillProfiles(ScopedVector<AutofillProfile>* profiles) {
    AutofillProfile* profile = new AutofillProfile;
    autofill_test::SetProfileInfo(profile, "Elvis", "Aaron",
                                  "Presley", "theking@gmail.com", "RCA",
                                  "3734 Elvis Presley Blvd.", "Apt. 10",
                                  "Memphis", "Tennessee", "38116", "USA",
                                  "12345678901", "");
    profile->set_guid("00000000-0000-0000-0000-000000000001");
    profiles->push_back(profile);
    profile = new AutofillProfile;
    autofill_test::SetProfileInfo(profile, "Charles", "Hardin",
                                  "Holley", "buddy@gmail.com", "Decca",
                                  "123 Apple St.", "unit 6", "Lubbock",
                                  "Texas", "79401", "USA", "2345678901",
                                  "");
    profile->set_guid("00000000-0000-0000-0000-000000000002");
    profiles->push_back(profile);
  }

  bool autofill_enabled_;

  DISALLOW_COPY_AND_ASSIGN(TestPersonalDataManager);
};

class TestAutofillManager : public AutofillManager {
 public:
  TestAutofillManager(TabContents* tab_contents,
                      TestPersonalDataManager* personal_manager)
      : AutofillManager(tab_contents, personal_manager),
        autofill_enabled_(true) {
    set_metric_logger(new MockAutofillMetrics);
  }
  virtual ~TestAutofillManager() {}

  virtual bool IsAutofillEnabled() const { return autofill_enabled_; }

  void set_autofill_enabled(bool autofill_enabled) {
    autofill_enabled_ = autofill_enabled;
  }

  const MockAutofillMetrics* metric_logger() const {
    return static_cast<const MockAutofillMetrics*>(
        AutofillManager::metric_logger());
  }

  void AddSeenForm(FormStructure* form) {
    form_structures()->push_back(form);
  }

 private:
  bool autofill_enabled_;

  DISALLOW_COPY_AND_ASSIGN(TestAutofillManager);
};

class TestFormStructure : public FormStructure {
 public:
  explicit TestFormStructure(const FormData& form) : FormStructure(form) {}
  virtual ~TestFormStructure() {}

  void SetFieldTypes(const std::vector<AutofillFieldType>& heuristic_types,
                     const std::vector<AutofillFieldType>& server_types) {
    ASSERT_EQ(field_count(), heuristic_types.size());
    ASSERT_EQ(field_count(), server_types.size());

    for (size_t i = 0; i < field_count(); ++i) {
      AutofillField* field = (*fields())[i];
      ASSERT_TRUE(field);
      field->set_heuristic_type(heuristic_types[i]);
      field->set_server_type(server_types[i]);
    }

    UpdateAutofillCount();
  }

  virtual std::string server_experiment_id() const OVERRIDE {
    return server_experiment_id_;
  }
  void set_server_experiment_id(const std::string& server_experiment_id) {
    server_experiment_id_ = server_experiment_id;
  }

 private:
  std::string server_experiment_id_;
  DISALLOW_COPY_AND_ASSIGN(TestFormStructure);
};

}  // namespace

class AutofillMetricsTest : public TabContentsWrapperTestHarness {
 public:
  AutofillMetricsTest() {}
  virtual ~AutofillMetricsTest() {
    // Order of destruction is important as AutofillManager relies on
    // PersonalDataManager to be around when it gets destroyed.
    autofill_manager_.reset(NULL);
    test_personal_data_ = NULL;
  }

  virtual void SetUp() {
    TabContentsWrapperTestHarness::SetUp();
    test_personal_data_ = new TestPersonalDataManager();
    autofill_manager_.reset(new TestAutofillManager(contents(),
                                                    test_personal_data_.get()));
  }

 protected:
  scoped_ptr<TestAutofillManager> autofill_manager_;
  scoped_refptr<TestPersonalDataManager> test_personal_data_;

 private:
  DISALLOW_COPY_AND_ASSIGN(AutofillMetricsTest);
};

// Test that we log quality metrics appropriately.
TEST_F(AutofillMetricsTest, QualityMetrics) {
  // Set up our form data.
  FormData form;
  form.name = ASCIIToUTF16("TestForm");
  form.method = ASCIIToUTF16("POST");
  form.origin = GURL("http://example.com/form.html");
  form.action = GURL("http://example.com/submit.html");
  form.user_submitted = true;

  std::vector<AutofillFieldType> heuristic_types, server_types;
  FormField field;

  autofill_test::CreateTestFormField(
      "Autofilled", "autofilled", "Elvis Presley", "text", &field);
  field.is_autofilled = true;
  form.fields.push_back(field);
  heuristic_types.push_back(NAME_FULL);
  server_types.push_back(NAME_FIRST);

  autofill_test::CreateTestFormField(
      "Autofill Failed", "autofillfailed", "buddy@gmail.com", "text", &field);
  form.fields.push_back(field);
  heuristic_types.push_back(PHONE_HOME_NUMBER);
  server_types.push_back(EMAIL_ADDRESS);

  autofill_test::CreateTestFormField(
      "Empty", "empty", "", "text", &field);
  form.fields.push_back(field);
  heuristic_types.push_back(NAME_FULL);
  server_types.push_back(NAME_FIRST);

  autofill_test::CreateTestFormField(
      "Unknown", "unknown", "garbage", "text", &field);
  form.fields.push_back(field);
  heuristic_types.push_back(PHONE_HOME_NUMBER);
  server_types.push_back(EMAIL_ADDRESS);

  autofill_test::CreateTestFormField(
      "Select", "select", "USA", "select-one", &field);
  form.fields.push_back(field);
  heuristic_types.push_back(UNKNOWN_TYPE);
  server_types.push_back(NO_SERVER_DATA);

  autofill_test::CreateTestFormField(
      "Phone", "phone", "2345678901", "tel", &field);
  field.is_autofilled = true;
  form.fields.push_back(field);
  heuristic_types.push_back(PHONE_HOME_CITY_AND_NUMBER);
  server_types.push_back(PHONE_HOME_WHOLE_NUMBER);

  // Simulate having seen this form on page load.
  // |form_structure| will be owned by |autofill_manager_|.
  TestFormStructure* form_structure = new TestFormStructure(form);
  form_structure->SetFieldTypes(heuristic_types, server_types);
  autofill_manager_->AddSeenForm(form_structure);

  // Establish our expectations.
  ::testing::InSequence dummy;
  // Autofilled field
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::HEURISTIC_TYPE_MATCH,
                  UNKNOWN_TYPE, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::SERVER_TYPE_MISMATCH,
                  UNKNOWN_TYPE, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::PREDICTED_TYPE_MISMATCH,
                  UNKNOWN_TYPE, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_AUTOFILLED, std::string()));
  // Non-autofilled field for which we had data
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::HEURISTIC_TYPE_MISMATCH,
                  EMAIL_ADDRESS, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::SERVER_TYPE_MATCH,
                  EMAIL_ADDRESS, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::PREDICTED_TYPE_MATCH,
                  EMAIL_ADDRESS, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_NOT_AUTOFILLED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_MISMATCH,
                  std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_MATCH,
                  std::string()));
  // Empty field
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
  // Unknown field
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
  // <select> field
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::HEURISTIC_TYPE_UNKNOWN,
                  ADDRESS_HOME_COUNTRY, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::SERVER_TYPE_UNKNOWN,
                  ADDRESS_HOME_COUNTRY, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::PREDICTED_TYPE_UNKNOWN,
                  ADDRESS_HOME_COUNTRY, std::string()));
  // Phone field
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::HEURISTIC_TYPE_MATCH,
                  PHONE_HOME_WHOLE_NUMBER, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::SERVER_TYPE_MATCH,
                  PHONE_HOME_WHOLE_NUMBER, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::PREDICTED_TYPE_MATCH,
                  PHONE_HOME_WHOLE_NUMBER, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_AUTOFILLED, std::string()));

  // Simulate form submission.
  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));
}

// Test that we log the appropriate additional metrics when Autofill failed.
TEST_F(AutofillMetricsTest, QualityMetricsForFailure) {
  // Set up our form data.
  FormData form;
  form.name = ASCIIToUTF16("TestForm");
  form.method = ASCIIToUTF16("POST");
  form.origin = GURL("http://example.com/form.html");
  form.action = GURL("http://example.com/submit.html");
  form.user_submitted = true;

  struct {
    const char* label;
    const char* name;
    const char* value;
    AutofillFieldType heuristic_type;
    AutofillFieldType server_type;
    AutofillMetrics::QualityMetric heuristic_metric;
    AutofillMetrics::QualityMetric server_metric;
  } failure_cases[] = {
    {
      "Heuristics unknown, server unknown", "0,0", "Elvis",
      UNKNOWN_TYPE, NO_SERVER_DATA,
      AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_UNKNOWN,
      AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_UNKNOWN
    },
    {
      "Heuristics match, server unknown", "1,0", "Aaron",
      NAME_MIDDLE, NO_SERVER_DATA,
      AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_MATCH,
      AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_UNKNOWN
    },
    {
      "Heuristics mismatch, server unknown", "2,0", "Presley",
      PHONE_HOME_NUMBER, NO_SERVER_DATA,
      AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_MISMATCH,
      AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_UNKNOWN
    },
    {
      "Heuristics unknown, server match", "0,1", "theking@gmail.com",
      UNKNOWN_TYPE, EMAIL_ADDRESS,
      AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_UNKNOWN,
      AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_MATCH
    },
    {
      "Heuristics match, server match", "1,1", "3734 Elvis Presley Blvd.",
      ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE1,
      AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_MATCH,
      AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_MATCH
    },
    {
      "Heuristics mismatch, server match", "2,1", "Apt. 10",
      PHONE_HOME_NUMBER, ADDRESS_HOME_LINE2,
      AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_MISMATCH,
      AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_MATCH
    },
    {
      "Heuristics unknown, server mismatch", "0,2", "Memphis",
      UNKNOWN_TYPE, PHONE_HOME_NUMBER,
      AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_UNKNOWN,
      AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_MISMATCH
    },
    {
      "Heuristics match, server mismatch", "1,2", "Tennessee",
      ADDRESS_HOME_STATE, PHONE_HOME_NUMBER,
      AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_MATCH,
      AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_MISMATCH
    },
    {
      "Heuristics mismatch, server mismatch", "2,2", "38116",
      PHONE_HOME_NUMBER, PHONE_HOME_NUMBER,
      AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_MISMATCH,
      AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_MISMATCH
    }
  };

  std::vector<AutofillFieldType> heuristic_types, server_types;
  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(failure_cases); ++i) {
    FormField field;
    autofill_test::CreateTestFormField(failure_cases[i].label,
                                       failure_cases[i].name,
                                       failure_cases[i].value, "text", &field);
    form.fields.push_back(field);
    heuristic_types.push_back(failure_cases[i].heuristic_type);
    server_types.push_back(failure_cases[i].server_type);

  }

  // Simulate having seen this form with the desired heuristic and server types.
  // |form_structure| will be owned by |autofill_manager_|.
  TestFormStructure* form_structure = new TestFormStructure(form);
  form_structure->SetFieldTypes(heuristic_types, server_types);
  autofill_manager_->AddSeenForm(form_structure);

  // Establish our expectations.
  ::testing::FLAGS_gmock_verbose = "error";
  ::testing::InSequence dummy;
  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(failure_cases); ++i) {
    EXPECT_CALL(*autofill_manager_->metric_logger(),
                Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
    EXPECT_CALL(*autofill_manager_->metric_logger(),
                Log(AutofillMetrics::FIELD_NOT_AUTOFILLED, std::string()));
    EXPECT_CALL(*autofill_manager_->metric_logger(),
                Log(failure_cases[i].heuristic_metric, std::string()));
    EXPECT_CALL(*autofill_manager_->metric_logger(),
                Log(failure_cases[i].server_metric, std::string()));
  }

  // Simulate form submission.
  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));
}

// Test that we behave sanely when the cached form differs from the submitted
// one.
TEST_F(AutofillMetricsTest, SaneMetricsWithCacheMismatch) {
  // Set up our form data.
  FormData form;
  form.name = ASCIIToUTF16("TestForm");
  form.method = ASCIIToUTF16("POST");
  form.origin = GURL("http://example.com/form.html");
  form.action = GURL("http://example.com/submit.html");
  form.user_submitted = true;

  std::vector<AutofillFieldType> heuristic_types, server_types;

  FormField field;
  autofill_test::CreateTestFormField(
      "Both match", "match", "Elvis Presley", "text", &field);
  field.is_autofilled = true;
  form.fields.push_back(field);
  heuristic_types.push_back(NAME_FULL);
  server_types.push_back(NAME_FULL);
  autofill_test::CreateTestFormField(
      "Both mismatch", "mismatch", "buddy@gmail.com", "text", &field);
  form.fields.push_back(field);
  heuristic_types.push_back(PHONE_HOME_NUMBER);
  server_types.push_back(PHONE_HOME_NUMBER);
  autofill_test::CreateTestFormField(
      "Only heuristics match", "mixed", "Memphis", "text", &field);
  form.fields.push_back(field);
  heuristic_types.push_back(ADDRESS_HOME_CITY);
  server_types.push_back(PHONE_HOME_NUMBER);
  autofill_test::CreateTestFormField(
      "Unknown", "unknown", "garbage", "text", &field);
  form.fields.push_back(field);
  heuristic_types.push_back(UNKNOWN_TYPE);
  server_types.push_back(UNKNOWN_TYPE);

  // Simulate having seen this form with the desired heuristic and server types.
  // |form_structure| will be owned by |autofill_manager_|.
  TestFormStructure* form_structure = new TestFormStructure(form);
  form_structure->SetFieldTypes(heuristic_types, server_types);
  autofill_manager_->AddSeenForm(form_structure);

  // Add a field and re-arrange the remaining form fields before submitting.
  std::vector<FormField> cached_fields = form.fields;
  form.fields.clear();
  autofill_test::CreateTestFormField(
      "New field", "new field", "Tennessee", "text", &field);
  form.fields.push_back(field);
  form.fields.push_back(cached_fields[2]);
  form.fields.push_back(cached_fields[1]);
  form.fields.push_back(cached_fields[3]);
  form.fields.push_back(cached_fields[0]);

  // Establish our expectations.
  ::testing::InSequence dummy;
  // New field
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::HEURISTIC_TYPE_UNKNOWN,
                  ADDRESS_HOME_STATE, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::SERVER_TYPE_UNKNOWN,
                  ADDRESS_HOME_STATE, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::PREDICTED_TYPE_UNKNOWN,
                  ADDRESS_HOME_STATE, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_NOT_AUTOFILLED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_UNKNOWN,
                  std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_UNKNOWN,
                  std::string()));
  // Only heuristics match
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::HEURISTIC_TYPE_MATCH,
                  ADDRESS_HOME_CITY, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::SERVER_TYPE_MISMATCH,
                  ADDRESS_HOME_CITY, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::PREDICTED_TYPE_MISMATCH,
                  ADDRESS_HOME_CITY, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_NOT_AUTOFILLED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_MATCH,
                  std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_MISMATCH,
                  std::string()));
  // Both mismatch
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::HEURISTIC_TYPE_MISMATCH,
                  EMAIL_ADDRESS, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::SERVER_TYPE_MISMATCH,
                  EMAIL_ADDRESS, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::PREDICTED_TYPE_MISMATCH,
                  EMAIL_ADDRESS, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_NOT_AUTOFILLED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_MISMATCH,
                  std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_MISMATCH,
                  std::string()));
  // Unknown
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
  // Both match
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::HEURISTIC_TYPE_MATCH,
                  UNKNOWN_TYPE, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::SERVER_TYPE_MATCH,
                  UNKNOWN_TYPE, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::PREDICTED_TYPE_MATCH,
                  UNKNOWN_TYPE, std::string()));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_AUTOFILLED, std::string()));

  // Simulate form submission.
  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));
}

// Test that we don't log quality metrics for non-autofillable forms.
TEST_F(AutofillMetricsTest, NoQualityMetricsForNonAutofillableForms) {
  // Forms must include at least three fields to be auto-fillable.
  FormData form;
  form.name = ASCIIToUTF16("TestForm");
  form.method = ASCIIToUTF16("POST");
  form.origin = GURL("http://example.com/form.html");
  form.action = GURL("http://example.com/submit.html");
  form.user_submitted = true;

  FormField field;
  autofill_test::CreateTestFormField(
      "Autofilled", "autofilled", "Elvis Presley", "text", &field);
  field.is_autofilled = true;
  form.fields.push_back(field);
  autofill_test::CreateTestFormField(
      "Autofill Failed", "autofillfailed", "buddy@gmail.com", "text", &field);
  form.fields.push_back(field);

  // Simulate form submission.
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string())).Times(0);
  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));

  // Search forms are not auto-fillable.
  form.action = GURL("http://example.com/search?q=Elvis%20Presley");
  autofill_test::CreateTestFormField(
      "Empty", "empty", "", "text", &field);
  form.fields.push_back(field);

  // Simulate form submission.
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, std::string())).Times(0);
  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));
}

// Test that we recored the experiment id appropriately.
TEST_F(AutofillMetricsTest, QualityMetricsWithExperimentId) {
  // Set up our form data.
  FormData form;
  form.name = ASCIIToUTF16("TestForm");
  form.method = ASCIIToUTF16("POST");
  form.origin = GURL("http://example.com/form.html");
  form.action = GURL("http://example.com/submit.html");
  form.user_submitted = true;

  std::vector<AutofillFieldType> heuristic_types, server_types;
  FormField field;

  autofill_test::CreateTestFormField(
      "Autofilled", "autofilled", "Elvis Presley", "text", &field);
  field.is_autofilled = true;
  form.fields.push_back(field);
  heuristic_types.push_back(NAME_FULL);
  server_types.push_back(NAME_FIRST);

  autofill_test::CreateTestFormField(
      "Autofill Failed", "autofillfailed", "buddy@gmail.com", "text", &field);
  form.fields.push_back(field);
  heuristic_types.push_back(PHONE_HOME_NUMBER);
  server_types.push_back(EMAIL_ADDRESS);

  autofill_test::CreateTestFormField(
      "Empty", "empty", "", "text", &field);
  form.fields.push_back(field);
  heuristic_types.push_back(NAME_FULL);
  server_types.push_back(NAME_FIRST);

  autofill_test::CreateTestFormField(
      "Unknown", "unknown", "garbage", "text", &field);
  form.fields.push_back(field);
  heuristic_types.push_back(PHONE_HOME_NUMBER);
  server_types.push_back(EMAIL_ADDRESS);

  autofill_test::CreateTestFormField(
      "Select", "select", "USA", "select-one", &field);
  form.fields.push_back(field);
  heuristic_types.push_back(UNKNOWN_TYPE);
  server_types.push_back(NO_SERVER_DATA);

  const std::string experiment_id = "ThatOughtaDoIt";

  // Simulate having seen this form on page load.
  // |form_structure| will be owned by |autofill_manager_|.
  TestFormStructure* form_structure = new TestFormStructure(form);
  form_structure->SetFieldTypes(heuristic_types, server_types);
  form_structure->set_server_experiment_id(experiment_id);
  autofill_manager_->AddSeenForm(form_structure);

  // Establish our expectations.
  ::testing::InSequence dummy;
  // Autofilled field
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::HEURISTIC_TYPE_MATCH,
                  UNKNOWN_TYPE, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::SERVER_TYPE_MISMATCH,
                  UNKNOWN_TYPE, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::PREDICTED_TYPE_MISMATCH,
                  UNKNOWN_TYPE, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_AUTOFILLED, experiment_id));
  // Non-autofilled field for which we had data
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::HEURISTIC_TYPE_MISMATCH,
                  EMAIL_ADDRESS, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::SERVER_TYPE_MATCH,
                  EMAIL_ADDRESS, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::PREDICTED_TYPE_MATCH,
                  EMAIL_ADDRESS, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_NOT_AUTOFILLED, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::NOT_AUTOFILLED_HEURISTIC_TYPE_MISMATCH,
                  experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::NOT_AUTOFILLED_SERVER_TYPE_MATCH,
                  experiment_id));
  // Empty field
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, experiment_id));
  // Unknown field
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, experiment_id));
  // <select> field
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::FIELD_SUBMITTED, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::HEURISTIC_TYPE_UNKNOWN,
                  ADDRESS_HOME_COUNTRY, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::SERVER_TYPE_UNKNOWN,
                  ADDRESS_HOME_COUNTRY, experiment_id));
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              Log(AutofillMetrics::PREDICTED_TYPE_UNKNOWN,
                  ADDRESS_HOME_COUNTRY, experiment_id));

  // Simulate form submission.
  EXPECT_NO_FATAL_FAILURE(autofill_manager_->OnFormSubmitted(form));
}

// Test that the profile count is logged correctly.
TEST_F(AutofillMetricsTest, StoredProfileCount) {
  // The metric should be logged when the profiles are first loaded.
  EXPECT_CALL(*test_personal_data_->metric_logger(),
              LogStoredProfileCount(2)).Times(1);
  test_personal_data_->LoadProfiles();

  // The metric should only be logged once.
  EXPECT_CALL(*test_personal_data_->metric_logger(),
              LogStoredProfileCount(::testing::_)).Times(0);
  test_personal_data_->LoadProfiles();
}

// Test that we correctly log whether Autofill is enabled.
TEST_F(AutofillMetricsTest, AutofillIsEnabledAtStartup) {
  test_personal_data_->set_autofill_enabled(true);
  EXPECT_CALL(*test_personal_data_->metric_logger(),
              LogIsAutofillEnabledAtStartup(true)).Times(1);
  test_personal_data_->Init(NULL);

  test_personal_data_->set_autofill_enabled(false);
  EXPECT_CALL(*test_personal_data_->metric_logger(),
              LogIsAutofillEnabledAtStartup(false)).Times(1);
  test_personal_data_->Init(NULL);
}

// Test that we log the number of Autofill suggestions when filling a form.
TEST_F(AutofillMetricsTest, AddressSuggestionsCount) {
  // Set up our form data.
  FormData form;
  form.name = ASCIIToUTF16("TestForm");
  form.method = ASCIIToUTF16("POST");
  form.origin = GURL("http://example.com/form.html");
  form.action = GURL("http://example.com/submit.html");
  form.user_submitted = true;

  FormField field;
  std::vector<AutofillFieldType> field_types;
  autofill_test::CreateTestFormField("Name", "name", "", "text", &field);
  form.fields.push_back(field);
  field_types.push_back(NAME_FULL);
  autofill_test::CreateTestFormField("Email", "email", "", "email", &field);
  form.fields.push_back(field);
  field_types.push_back(EMAIL_ADDRESS);
  autofill_test::CreateTestFormField("Phone", "phone", "", "tel", &field);
  form.fields.push_back(field);
  field_types.push_back(PHONE_HOME_NUMBER);

  // Simulate having seen this form on page load.
  // |form_structure| will be owned by |autofill_manager_|.
  TestFormStructure* form_structure = new TestFormStructure(form);
  form_structure->SetFieldTypes(field_types, field_types);
  autofill_manager_->AddSeenForm(form_structure);

  // Establish our expectations.
  ::testing::FLAGS_gmock_verbose = "error";
  ::testing::InSequence dummy;
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              LogAddressSuggestionsCount(2)).Times(1);

  // Simulate activating the autofill popup for the phone field.
  autofill_manager_->OnQueryFormFieldAutofill(0, form, field);

  // Simulate activating the autofill popup for the email field after typing.
  // No new metric should be logged, since we're still on the same page.
  autofill_test::CreateTestFormField("Email", "email", "b", "email", &field);
  autofill_manager_->OnQueryFormFieldAutofill(0, form, field);

  // Reset the autofill manager state.
  autofill_manager_->Reset();
  form_structure = new TestFormStructure(form);
  form_structure->SetFieldTypes(field_types, field_types);
  autofill_manager_->AddSeenForm(form_structure);

  // Establish our expectations.
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              LogAddressSuggestionsCount(1)).Times(1);

  // Simulate activating the autofill popup for the email field after typing.
  autofill_manager_->OnQueryFormFieldAutofill(0, form, field);

  // Reset the autofill manager state again.
  autofill_manager_->Reset();
  form_structure = new TestFormStructure(form);
  form_structure->SetFieldTypes(field_types, field_types);
  autofill_manager_->AddSeenForm(form_structure);

  // Establish our expectations.
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              LogAddressSuggestionsCount(::testing::_)).Times(0);

  // Simulate activating the autofill popup for the email field after typing.
  form.fields[0].is_autofilled = true;
  autofill_manager_->OnQueryFormFieldAutofill(0, form, field);
}

// Test that we log whether Autofill is enabled when filling a form.
TEST_F(AutofillMetricsTest, AutofillIsEnabledAtPageLoad) {
  // Establish our expectations.
  ::testing::FLAGS_gmock_verbose = "error";
  ::testing::InSequence dummy;
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              LogIsAutofillEnabledAtPageLoad(true)).Times(1);

  autofill_manager_->set_autofill_enabled(true);
  autofill_manager_->OnFormsSeen(std::vector<FormData>());

  // Reset the autofill manager state.
  autofill_manager_->Reset();

  // Establish our expectations.
  EXPECT_CALL(*autofill_manager_->metric_logger(),
              LogIsAutofillEnabledAtPageLoad(false)).Times(1);

  autofill_manager_->set_autofill_enabled(false);
  autofill_manager_->OnFormsSeen(std::vector<FormData>());
}

// Test that credit card infobar metrics are logged correctly.
TEST_F(AutofillMetricsTest, CreditCardInfoBar) {
  MockAutofillMetrics metric_logger;
  CreditCard* credit_card;
  AutofillCCInfoBarDelegate* infobar;
  ::testing::InSequence dummy;

  // Accept the infobar.
  EXPECT_CALL(metric_logger, Log(AutofillMetrics::CREDIT_CARD_INFOBAR_SHOWN));
  credit_card = new CreditCard();
  infobar = new AutofillCCInfoBarDelegate(contents(),
                                          credit_card,
                                          test_personal_data_.get(),
                                          &metric_logger);

  EXPECT_CALL(*test_personal_data_.get(), SaveImportedCreditCard(*credit_card));
  EXPECT_CALL(metric_logger,
              Log(AutofillMetrics::CREDIT_CARD_INFOBAR_ACCEPTED)).Times(1);
  EXPECT_CALL(metric_logger,
              Log(AutofillMetrics::CREDIT_CARD_INFOBAR_IGNORED)).Times(0);
  EXPECT_TRUE(infobar->Accept());
  infobar->InfoBarClosed();

  // Cancel the infobar.
  EXPECT_CALL(metric_logger, Log(AutofillMetrics::CREDIT_CARD_INFOBAR_SHOWN));
  credit_card = new CreditCard();
  infobar = new AutofillCCInfoBarDelegate(contents(),
                                          credit_card,
                                          test_personal_data_.get(),
                                          &metric_logger);

  EXPECT_CALL(metric_logger,
              Log(AutofillMetrics::CREDIT_CARD_INFOBAR_DENIED)).Times(1);
  EXPECT_CALL(metric_logger,
              Log(AutofillMetrics::CREDIT_CARD_INFOBAR_IGNORED)).Times(0);
  EXPECT_TRUE(infobar->Cancel());
  infobar->InfoBarClosed();

  // Dismiss the infobar.
  EXPECT_CALL(metric_logger, Log(AutofillMetrics::CREDIT_CARD_INFOBAR_SHOWN));
  credit_card = new CreditCard();
  infobar = new AutofillCCInfoBarDelegate(contents(),
                                          credit_card,
                                          test_personal_data_.get(),
                                          &metric_logger);

  EXPECT_CALL(metric_logger,
              Log(AutofillMetrics::CREDIT_CARD_INFOBAR_DENIED)).Times(1);
  EXPECT_CALL(metric_logger,
              Log(AutofillMetrics::CREDIT_CARD_INFOBAR_IGNORED)).Times(0);
  infobar->InfoBarDismissed();
  infobar->InfoBarClosed();

  // Ignore the infobar.
  EXPECT_CALL(metric_logger, Log(AutofillMetrics::CREDIT_CARD_INFOBAR_SHOWN));
  credit_card = new CreditCard();
  infobar = new AutofillCCInfoBarDelegate(contents(),
                                          credit_card,
                                          test_personal_data_.get(),
                                          &metric_logger);

  EXPECT_CALL(metric_logger,
              Log(AutofillMetrics::CREDIT_CARD_INFOBAR_IGNORED)).Times(1);
  infobar->InfoBarClosed();
}