Home | History | Annotate | Download | only in autofill
      1 // Copyright (c) 2012 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 "base/strings/utf_string_conversions.h"
      6 #include "chrome/test/base/chrome_render_view_test.h"
      7 #include "components/autofill/content/common/autofill_messages.h"
      8 #include "components/autofill/content/renderer/autofill_agent.h"
      9 #include "components/autofill/core/common/form_data.h"
     10 #include "components/autofill/core/common/form_field_data.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 #include "third_party/WebKit/public/platform/WebString.h"
     13 #include "third_party/WebKit/public/web/WebDocument.h"
     14 #include "third_party/WebKit/public/web/WebInputElement.h"
     15 
     16 using blink::WebDocument;
     17 using blink::WebFrame;
     18 using blink::WebInputElement;
     19 using blink::WebString;
     20 
     21 namespace autofill {
     22 
     23 typedef Tuple5<int,
     24                autofill::FormData,
     25                autofill::FormFieldData,
     26                gfx::RectF,
     27                bool> AutofillQueryParam;
     28 
     29 TEST_F(ChromeRenderViewTest, SendForms) {
     30   // Don't want any delay for form state sync changes. This will still post a
     31   // message so updates will get coalesced, but as soon as we spin the message
     32   // loop, it will generate an update.
     33   SendContentStateImmediately();
     34 
     35   LoadHTML("<form method=\"POST\">"
     36            "  <input type=\"text\" id=\"firstname\"/>"
     37            "  <input type=\"text\" id=\"middlename\"/>"
     38            "  <input type=\"text\" id=\"lastname\" autoComplete=\"off\"/>"
     39            "  <input type=\"hidden\" id=\"email\"/>"
     40            "  <select id=\"state\"/>"
     41            "    <option>?</option>"
     42            "    <option>California</option>"
     43            "    <option>Texas</option>"
     44            "  </select>"
     45            "</form>");
     46 
     47   // Verify that "FormsSeen" sends the expected number of fields.
     48   const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
     49       AutofillHostMsg_FormsSeen::ID);
     50   ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
     51   AutofillHostMsg_FormsSeen::Param params;
     52   AutofillHostMsg_FormsSeen::Read(message, &params);
     53   const std::vector<FormData>& forms = params.a;
     54   ASSERT_EQ(1UL, forms.size());
     55   ASSERT_EQ(4UL, forms[0].fields.size());
     56 
     57   FormFieldData expected;
     58 
     59   expected.name = ASCIIToUTF16("firstname");
     60   expected.value = base::string16();
     61   expected.form_control_type = "text";
     62   expected.max_length = WebInputElement::defaultMaxLength();
     63   EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[0]);
     64 
     65   expected.name = ASCIIToUTF16("middlename");
     66   expected.value = base::string16();
     67   expected.form_control_type = "text";
     68   expected.max_length = WebInputElement::defaultMaxLength();
     69   EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[1]);
     70 
     71   expected.name = ASCIIToUTF16("lastname");
     72   expected.value = base::string16();
     73   expected.form_control_type = "text";
     74   expected.autocomplete_attribute = "off";
     75   expected.max_length = WebInputElement::defaultMaxLength();
     76   EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[2]);
     77   expected.autocomplete_attribute = std::string();  // reset
     78 
     79   expected.name = ASCIIToUTF16("state");
     80   expected.value = ASCIIToUTF16("?");
     81   expected.form_control_type = "select-one";
     82   expected.max_length = 0;
     83   EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[3]);
     84 
     85   // Verify that |didAcceptAutofillSuggestion()| sends the expected number of
     86   // fields.
     87   WebFrame* web_frame = GetMainFrame();
     88   WebDocument document = web_frame->document();
     89   WebInputElement firstname =
     90       document.getElementById("firstname").to<WebInputElement>();
     91 
     92   // Make sure to query for Autofill suggestions before selecting one.
     93   autofill_agent_->element_ = firstname;
     94   autofill_agent_->QueryAutofillSuggestions(firstname, false, false);
     95 
     96   // Fill the form with a suggestion that contained a label.  Labeled items
     97   // indicate Autofill as opposed to Autocomplete.  We're testing this
     98   // distinction below with the |AutofillHostMsg_FillAutofillFormData::ID|
     99   // message.
    100   autofill_agent_->FillAutofillFormData(
    101       firstname,
    102       1,
    103       AutofillAgent::AUTOFILL_PREVIEW);
    104 
    105   ProcessPendingMessages();
    106   const IPC::Message* message2 =
    107       render_thread_->sink().GetUniqueMessageMatching(
    108           AutofillHostMsg_FillAutofillFormData::ID);
    109   ASSERT_NE(static_cast<IPC::Message*>(NULL), message2);
    110   AutofillHostMsg_FillAutofillFormData::Param params2;
    111   AutofillHostMsg_FillAutofillFormData::Read(message2, &params2);
    112   const FormData& form2 = params2.b;
    113   ASSERT_EQ(3UL, form2.fields.size());
    114 
    115   expected.name = ASCIIToUTF16("firstname");
    116   expected.value = base::string16();
    117   expected.form_control_type = "text";
    118   expected.max_length = WebInputElement::defaultMaxLength();
    119   EXPECT_FORM_FIELD_DATA_EQUALS(expected, form2.fields[0]);
    120 
    121   expected.name = ASCIIToUTF16("middlename");
    122   expected.value = base::string16();
    123   expected.form_control_type = "text";
    124   expected.max_length = WebInputElement::defaultMaxLength();
    125   EXPECT_FORM_FIELD_DATA_EQUALS(expected, form2.fields[1]);
    126 
    127   expected.name = ASCIIToUTF16("state");
    128   expected.value = ASCIIToUTF16("?");
    129   expected.form_control_type = "select-one";
    130   expected.max_length = 0;
    131   EXPECT_FORM_FIELD_DATA_EQUALS(expected, form2.fields[2]);
    132 }
    133 
    134 TEST_F(ChromeRenderViewTest, EnsureNoFormSeenIfTooFewFields) {
    135   // Don't want any delay for form state sync changes. This will still post a
    136   // message so updates will get coalesced, but as soon as we spin the message
    137   // loop, it will generate an update.
    138   SendContentStateImmediately();
    139 
    140   LoadHTML("<form method=\"POST\">"
    141            "  <input type=\"text\" id=\"firstname\"/>"
    142            "  <input type=\"text\" id=\"middlename\"/>"
    143            "</form>");
    144 
    145   // Verify that "FormsSeen" isn't sent, as there are too few fields.
    146   const IPC::Message* message = render_thread_->sink().GetFirstMessageMatching(
    147       AutofillHostMsg_FormsSeen::ID);
    148   ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
    149   AutofillHostMsg_FormsSeen::Param params;
    150   AutofillHostMsg_FormsSeen::Read(message, &params);
    151   const std::vector<FormData>& forms = params.a;
    152   ASSERT_EQ(0UL, forms.size());
    153 }
    154 
    155 TEST_F(ChromeRenderViewTest, ShowAutofillWarning) {
    156   // Don't want any delay for form state sync changes.  This will still post a
    157   // message so updates will get coalesced, but as soon as we spin the message
    158   // loop, it will generate an update.
    159   SendContentStateImmediately();
    160 
    161   LoadHTML("<form method=\"POST\" autocomplete=\"Off\">"
    162            "  <input id=\"firstname\" autocomplete=\"OFF\"/>"
    163            "  <input id=\"middlename\"/>"
    164            "  <input id=\"lastname\"/>"
    165            "</form>");
    166 
    167   // Verify that "QueryFormFieldAutofill" isn't sent prior to a user
    168   // interaction.
    169   const IPC::Message* message0 = render_thread_->sink().GetFirstMessageMatching(
    170       AutofillHostMsg_QueryFormFieldAutofill::ID);
    171   EXPECT_EQ(static_cast<IPC::Message*>(NULL), message0);
    172 
    173   WebFrame* web_frame = GetMainFrame();
    174   WebDocument document = web_frame->document();
    175   WebInputElement firstname =
    176       document.getElementById("firstname").to<WebInputElement>();
    177   WebInputElement middlename =
    178       document.getElementById("middlename").to<WebInputElement>();
    179 
    180   // Simulate attempting to Autofill the form from the first element, which
    181   // specifies autocomplete="off".  This should still trigger an IPC which
    182   // shouldn't display warnings.
    183   autofill_agent_->InputElementClicked(firstname, true, true);
    184   const IPC::Message* message1 = render_thread_->sink().GetFirstMessageMatching(
    185       AutofillHostMsg_QueryFormFieldAutofill::ID);
    186   EXPECT_NE(static_cast<IPC::Message*>(NULL), message1);
    187 
    188   AutofillQueryParam query_param;
    189   AutofillHostMsg_QueryFormFieldAutofill::Read(message1, &query_param);
    190   EXPECT_FALSE(query_param.e);
    191   render_thread_->sink().ClearMessages();
    192 
    193   // Simulate attempting to Autofill the form from the second element, which
    194   // does not specify autocomplete="off".  This should trigger an IPC that will
    195   // show warnings, as we *do* show warnings for elements that don't themselves
    196   // set autocomplete="off", but for which the form does.
    197   autofill_agent_->InputElementClicked(middlename, true, true);
    198   const IPC::Message* message2 = render_thread_->sink().GetFirstMessageMatching(
    199       AutofillHostMsg_QueryFormFieldAutofill::ID);
    200   ASSERT_NE(static_cast<IPC::Message*>(NULL), message2);
    201 
    202   AutofillHostMsg_QueryFormFieldAutofill::Read(message2, &query_param);
    203   EXPECT_TRUE(query_param.e);
    204 }
    205 
    206 }  // namespace autofill
    207