Home | History | Annotate | Download | only in autofill
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <vector>
      6 
      7 #include "base/basictypes.h"
      8 #include "base/file_path.h"
      9 #include "base/string_util.h"
     10 #include "base/utf_string_conversions.h"
     11 #include "chrome/browser/autofill/autofill_common_test.h"
     12 #include "chrome/browser/autofill/autofill_type.h"
     13 #include "chrome/browser/autofill/data_driven_test.h"
     14 #include "chrome/browser/autofill/form_structure.h"
     15 #include "chrome/browser/autofill/personal_data_manager.h"
     16 #include "googleurl/src/gurl.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
     19 #include "webkit/glue/form_data.h"
     20 
     21 namespace {
     22 
     23 const FilePath::CharType kTestName[] = FILE_PATH_LITERAL("merge");
     24 const FilePath::CharType kFileNamePattern[] = FILE_PATH_LITERAL("*.in");
     25 
     26 const char kFieldSeparator[] = ": ";
     27 const char kProfileSeparator[] = "---";
     28 const size_t kFieldOffset = arraysize(kFieldSeparator) - 1;
     29 
     30 const AutofillFieldType kProfileFieldTypes[] = {
     31   NAME_FIRST,
     32   NAME_MIDDLE,
     33   NAME_LAST,
     34   EMAIL_ADDRESS,
     35   COMPANY_NAME,
     36   ADDRESS_HOME_LINE1,
     37   ADDRESS_HOME_LINE2,
     38   ADDRESS_HOME_CITY,
     39   ADDRESS_HOME_STATE,
     40   ADDRESS_HOME_ZIP,
     41   ADDRESS_HOME_COUNTRY,
     42   PHONE_HOME_WHOLE_NUMBER,
     43   PHONE_FAX_WHOLE_NUMBER,
     44 };
     45 
     46 // Serializes the |profiles| into a string.
     47 std::string SerializeProfiles(const std::vector<AutofillProfile*>& profiles) {
     48   std::string result;
     49   for (size_t i = 0; i < profiles.size(); ++i) {
     50     result += kProfileSeparator;
     51     result += "\n";
     52     for (size_t j = 0; j < arraysize(kProfileFieldTypes); ++j) {
     53       AutofillFieldType type = kProfileFieldTypes[j];
     54       std::vector<string16> values;
     55       profiles[i]->GetMultiInfo(type, &values);
     56       for (size_t k = 0; k < values.size(); ++k) {
     57         result += AutofillType::FieldTypeToString(type);
     58         result += kFieldSeparator;
     59         result += UTF16ToUTF8(values[k]);
     60         result += "\n";
     61       }
     62     }
     63   }
     64 
     65   return result;
     66 }
     67 
     68 class PersonalDataManagerMock : public PersonalDataManager {
     69  public:
     70   PersonalDataManagerMock();
     71   virtual ~PersonalDataManagerMock();
     72 
     73   // Reset the saved profiles.
     74   void Reset();
     75 
     76   // PersonalDataManager:
     77   virtual void SaveImportedProfile(const AutofillProfile& profile) OVERRIDE;
     78   virtual const std::vector<AutofillProfile*>& web_profiles() OVERRIDE;
     79 
     80  private:
     81   ScopedVector<AutofillProfile> profiles_;
     82 
     83   DISALLOW_COPY_AND_ASSIGN(PersonalDataManagerMock);
     84 };
     85 
     86 PersonalDataManagerMock::PersonalDataManagerMock() : PersonalDataManager() {
     87 }
     88 
     89 PersonalDataManagerMock::~PersonalDataManagerMock() {
     90 }
     91 
     92 void PersonalDataManagerMock::Reset() {
     93   profiles_.reset();
     94 }
     95 
     96 void PersonalDataManagerMock::SaveImportedProfile(
     97     const AutofillProfile& profile) {
     98   std::vector<AutofillProfile> profiles;
     99   if (!MergeProfile(profile, profiles_.get(), &profiles))
    100     profiles_.push_back(new AutofillProfile(profile));
    101 }
    102 
    103 const std::vector<AutofillProfile*>& PersonalDataManagerMock::web_profiles() {
    104   return profiles_.get();
    105 }
    106 
    107 }  // namespace
    108 
    109 // A data-driven test for verifying merging of Autofill profiles. Each input is
    110 // a structured dump of a set of implicitly detected autofill profiles. The
    111 // corresponding output file is a dump of the saved profiles that result from
    112 // importing the input profiles. The output file format is identical to the
    113 // input format.
    114 class AutofillMergeTest : public testing::Test, public DataDrivenTest {
    115  protected:
    116   AutofillMergeTest();
    117   virtual ~AutofillMergeTest();
    118 
    119   // testing::Test:
    120   virtual void SetUp();
    121 
    122   // DataDrivenTest:
    123   virtual void GenerateResults(const std::string& input,
    124                                std::string* output) OVERRIDE;
    125 
    126   // Deserializes a set of Autofill profiles from |profiles|, imports each
    127   // sequentially, and fills |merged_profiles| with the serialized result.
    128   void MergeProfiles(const std::string& profiles, std::string* merged_profiles);
    129 
    130   scoped_refptr<PersonalDataManagerMock> personal_data_;
    131 
    132  private:
    133   DISALLOW_COPY_AND_ASSIGN(AutofillMergeTest);
    134 };
    135 
    136 AutofillMergeTest::AutofillMergeTest() : DataDrivenTest() {
    137 }
    138 
    139 AutofillMergeTest::~AutofillMergeTest() {
    140 }
    141 
    142 void AutofillMergeTest::SetUp() {
    143   autofill_test::DisableSystemServices(NULL);
    144 
    145   personal_data_ = new PersonalDataManagerMock();
    146 }
    147 
    148 void AutofillMergeTest::GenerateResults(const std::string& input,
    149                                         std::string* output) {
    150   MergeProfiles(input, output);
    151 }
    152 
    153 void AutofillMergeTest::MergeProfiles(const std::string& profiles,
    154                                       std::string* merged_profiles) {
    155   // Start with no saved profiles.
    156   personal_data_->Reset();
    157 
    158   // Create a test form.
    159   webkit_glue::FormData form;
    160   form.name = ASCIIToUTF16("MyTestForm");
    161   form.method = ASCIIToUTF16("POST");
    162   form.origin = GURL("https://www.example.com/origin.html");
    163   form.action = GURL("https://www.example.com/action.html");
    164   form.user_submitted = true;
    165 
    166   // Parse the input line by line.
    167   std::vector<std::string> lines;
    168   Tokenize(profiles, "\n", &lines);
    169   for (size_t i = 0; i < lines.size(); ++i) {
    170     std::string line = lines[i];
    171 
    172     if (line != kProfileSeparator) {
    173       // Add a field to the current profile.
    174       size_t separator_pos = line.find(kFieldSeparator);
    175       ASSERT_NE(std::string::npos, separator_pos);
    176       string16 field_type = UTF8ToUTF16(line.substr(0, separator_pos));
    177       string16 value = UTF8ToUTF16(line.substr(separator_pos + kFieldOffset));
    178 
    179       webkit_glue::FormField field(field_type,
    180                                    field_type,
    181                                    value,
    182                                    ASCIIToUTF16("text"),
    183                                    WebKit::WebInputElement::defaultMaxLength(),
    184                                    false);
    185       form.fields.push_back(field);
    186     }
    187 
    188     // The first line is always a profile separator, and the last profile is not
    189     // followed by an explicit separator.
    190     if ((i > 0 && line == kProfileSeparator) || i == lines.size() - 1) {
    191       // Reached the end of a profile.  Try to import it.
    192       FormStructure form_structure(form);
    193       for (size_t i = 0; i < form_structure.field_count(); ++i) {
    194         // Set the heuristic type for each field, which is currently serialized
    195         // into the field's name.
    196         AutofillField* field =
    197             const_cast<AutofillField*>(form_structure.field(i));
    198         AutofillFieldType type =
    199             AutofillType::StringToFieldType(UTF16ToUTF8(field->name));
    200         field->set_heuristic_type(type);
    201       }
    202       std::vector<const FormStructure*> form_structures(1, &form_structure);
    203 
    204       // Import the profile.
    205       const CreditCard* imported_credit_card;
    206       personal_data_->ImportFormData(form_structures, &imported_credit_card);
    207       EXPECT_FALSE(imported_credit_card);
    208 
    209       // Clear the |form| to start a new profile.
    210       form.fields.clear();
    211     }
    212   }
    213 
    214   *merged_profiles = SerializeProfiles(personal_data_->web_profiles());
    215 }
    216 
    217 TEST_F(AutofillMergeTest, DataDrivenMergeProfiles) {
    218   RunDataDrivenTest(GetInputDirectory(kTestName), GetOutputDirectory(kTestName),
    219                     kFileNamePattern);
    220 }
    221