This source file includes following definitions.
- SimulateOnFillPasswordForm
- SetUp
- TearDown
- UpdateOriginForHTML
- UpdateUsernameAndPasswordElements
- ClearUsernameAndPasswordFields
- SimulateUsernameChangeForElement
- LayoutMainFrame
- SimulateUsernameChange
- ExpectNoSuggestionsPopup
- SimulateKeyDownEvent
- CheckTextFieldsStateForElements
- CheckTextFieldsState
- CheckTextFieldsDOMState
- CheckUsernameSelection
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/test/base/chrome_render_view_test.h"
#include "components/autofill/content/common/autofill_messages.h"
#include "components/autofill/content/renderer/autofill_agent.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/password_autofill_agent.h"
#include "components/autofill/content/renderer/test_password_autofill_agent.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/password_autofill_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebFormElement.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebInputElement.h"
#include "third_party/WebKit/public/web/WebNode.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/events/keycodes/keyboard_codes.h"
using autofill::PasswordForm;
using base::ASCIIToUTF16;
using base::UTF16ToUTF8;
using blink::WebDocument;
using blink::WebElement;
using blink::WebFrame;
using blink::WebInputElement;
using blink::WebString;
using blink::WebView;
namespace {
const char kUsernameName[] = "username";
const char kPasswordName[] = "password";
const char kAliceUsername[] = "alice";
const char kAlicePassword[] = "password";
const char kBobUsername[] = "bob";
const char kBobPassword[] = "secret";
const char kCarolUsername[] = "Carol";
const char kCarolPassword[] = "test";
const char kCarolAlternateUsername[] = "RealCarolUsername";
const char kFormHTML[] =
    "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
    "  <INPUT type='text' id='username'/>"
    "  <INPUT type='password' id='password'/>"
    "  <INPUT type='submit' value='Login'/>"
    "</FORM>";
const char kVisibleFormHTML[] =
    "<head> <style> form {display: inline;} </style> </head>"
    "<body>"
    "  <form>"
    "    <div>"
    "      <input type='password' id='password'/>"
    "    </div>"
    "  </form>"
    "</body>";
const char kEmptyFormHTML[] =
    "<head> <style> form {display: inline;} </style> </head>"
    "<body> <form> </form> </body>";
const char kNonVisibleFormHTML[] =
    "<head> <style> form {display: none;} </style> </head>"
    "<body>"
    "  <form>"
    "    <div>"
    "      <input type='password' id='password'/>"
    "    </div>"
    "  </form>"
    "</body>";
const char kEmptyWebpage[] =
    "<html>"
    "   <head>"
    "   </head>"
    "   <body>"
    "   </body>"
    "</html>";
const char kRedirectionWebpage[] =
    "<html>"
    "   <head>"
    "       <meta http-equiv='Content-Type' content='text/html'>"
    "       <title>Redirection page</title>"
    "       <script></script>"
    "   </head>"
    "   <body>"
    "       <script type='text/javascript'>"
    "         function test(){}"
    "       </script>"
    "   </body>"
    "</html>";
const char kSimpleWebpage[] =
    "<html>"
    "   <head>"
    "       <meta charset='utf-8' />"
    "       <title>Title</title>"
    "   </head>"
    "   <body>"
    "       <form name='LoginTestForm'>"
    "           <input type='text' id='username'/>"
    "           <input type='password' id='password'/>"
    "           <input type='submit' value='Login'/>"
    "       </form>"
    "   </body>"
    "</html>";
const char kWebpageWithDynamicContent[] =
    "<html>"
    "   <head>"
    "       <meta charset='utf-8' />"
    "       <title>Title</title>"
    "   </head>"
    "   <body>"
    "       <script type='text/javascript'>"
    "           function addParagraph() {"
    "             var p = document.createElement('p');"
    "             document.body.appendChild(p);"
    "            }"
    "           window.onload = addParagraph;"
    "       </script>"
    "   </body>"
    "</html>";
const char kJavaScriptClick[] =
    "var event = new MouseEvent('click', {"
    "   'view': window,"
    "   'bubbles': true,"
    "   'cancelable': true"
    "});"
    "var form = document.getElementById('myform1');"
    "form.dispatchEvent(event);"
    "console.log('clicked!');";
const char kOnChangeDetectionScript[] =
    "<script>"
    "  usernameOnchangeCalled = false;"
    "  passwordOnchangeCalled = false;"
    "  document.getElementById('username').onchange = function() {"
    "    usernameOnchangeCalled = true;"
    "  };"
    "  document.getElementById('password').onchange = function() {"
    "    passwordOnchangeCalled = true;"
    "  };"
    "</script>";
}  
namespace autofill {
class PasswordAutofillAgentTest : public ChromeRenderViewTest {
 public:
  PasswordAutofillAgentTest() {
  }
  
  
  
  void SimulateOnFillPasswordForm(
      const PasswordFormFillData& fill_data) {
    AutofillMsg_FillPasswordForm msg(0, fill_data);
    password_autofill_->OnMessageReceived(msg);
  }
  virtual void SetUp() {
    ChromeRenderViewTest::SetUp();
    
    username1_ = ASCIIToUTF16(kAliceUsername);
    password1_ = ASCIIToUTF16(kAlicePassword);
    username2_ = ASCIIToUTF16(kBobUsername);
    password2_ = ASCIIToUTF16(kBobPassword);
    username3_ = ASCIIToUTF16(kCarolUsername);
    password3_ = ASCIIToUTF16(kCarolPassword);
    alternate_username3_ = ASCIIToUTF16(kCarolAlternateUsername);
    FormFieldData username_field;
    username_field.name = ASCIIToUTF16(kUsernameName);
    username_field.value = username1_;
    fill_data_.basic_data.fields.push_back(username_field);
    FormFieldData password_field;
    password_field.name = ASCIIToUTF16(kPasswordName);
    password_field.value = password1_;
    password_field.form_control_type = "password";
    fill_data_.basic_data.fields.push_back(password_field);
    PasswordAndRealm password2;
    password2.password = password2_;
    fill_data_.additional_logins[username2_] = password2;
    PasswordAndRealm password3;
    password3.password = password3_;
    fill_data_.additional_logins[username3_] = password3;
    UsernamesCollectionKey key;
    key.username = username3_;
    key.password = password3_;
    key.realm = "google.com";
    fill_data_.other_possible_usernames[key].push_back(alternate_username3_);
    
    
    UpdateOriginForHTML(kFormHTML);
    fill_data_.basic_data.action = GURL("http://www.bidule.com");
    LoadHTML(kFormHTML);
    
    UpdateUsernameAndPasswordElements();
  }
  virtual void TearDown() {
    username_element_.reset();
    password_element_.reset();
    ChromeRenderViewTest::TearDown();
  }
  void UpdateOriginForHTML(const std::string& html) {
    std::string origin = "data:text/html;charset=utf-8," + html;
    fill_data_.basic_data.origin = GURL(origin);
  }
  void UpdateUsernameAndPasswordElements() {
    WebDocument document = GetMainFrame()->document();
    WebElement element =
        document.getElementById(WebString::fromUTF8(kUsernameName));
    ASSERT_FALSE(element.isNull());
    username_element_ = element.to<blink::WebInputElement>();
    element = document.getElementById(WebString::fromUTF8(kPasswordName));
    ASSERT_FALSE(element.isNull());
    password_element_ = element.to<blink::WebInputElement>();
  }
  void ClearUsernameAndPasswordFields() {
    username_element_.setValue("");
    username_element_.setAutofilled(false);
    password_element_.setValue("");
    password_element_.setAutofilled(false);
  }
  void SimulateUsernameChangeForElement(const std::string& username,
                                        bool move_caret_to_end,
                                        WebFrame* input_frame,
                                        WebInputElement& username_input) {
    username_input.setValue(WebString::fromUTF8(username));
    
    
    while (!username_input.focused())
      input_frame->document().frame()->view()->advanceFocus(false);
    if (move_caret_to_end)
      username_input.setSelectionRange(username.length(), username.length());
    autofill_agent_->textFieldDidChange(username_input);
    
    
    
    
    
    
    base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
        &PasswordAutofillAgentTest::LayoutMainFrame, base::Unretained(this)));
    base::MessageLoop::current()->RunUntilIdle();
  }
  void LayoutMainFrame() {
    GetMainFrame()->view()->layout();
  }
  void SimulateUsernameChange(const std::string& username,
                              bool move_caret_to_end) {
    SimulateUsernameChangeForElement(username, move_caret_to_end,
                                     GetMainFrame(), username_element_);
  }
  
  
  void ExpectNoSuggestionsPopup() {
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    if (!ShouldIgnoreAutocompleteOffForPasswordFields()) {
      EXPECT_TRUE(autofill_agent_->password_autofill_agent_->ShowSuggestions(
          username_element_));
      EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
          AutofillHostMsg_ShowPasswordSuggestions::ID));
    }
  }
  void SimulateKeyDownEvent(const WebInputElement& element,
                            ui::KeyboardCode key_code) {
    blink::WebKeyboardEvent key_event;
    key_event.windowsKeyCode = key_code;
    autofill_agent_->textFieldDidReceiveKeyDown(element, key_event);
  }
  void CheckTextFieldsStateForElements(const WebInputElement& username_element,
                                       const std::string& username,
                                       bool username_autofilled,
                                       const WebInputElement& password_element,
                                       const std::string& password,
                                       bool password_autofilled,
                                       bool checkSuggestedValue = true) {
    EXPECT_EQ(username,
              static_cast<std::string>(username_element.value().utf8()));
    EXPECT_EQ(username_autofilled, username_element.isAutofilled());
    EXPECT_EQ(password,
              static_cast<std::string>(
                  checkSuggestedValue ? password_element.suggestedValue().utf8()
                                      : password_element.value().utf8()));
    EXPECT_EQ(password_autofilled, password_element.isAutofilled());
  }
  
  
  void CheckTextFieldsState(const std::string& username,
                            bool username_autofilled,
                            const std::string& password,
                            bool password_autofilled) {
    CheckTextFieldsStateForElements(username_element_, username,
                                    username_autofilled, password_element_,
                                    password, password_autofilled);
  }
  
  
  void CheckTextFieldsDOMState(const std::string& username,
                               bool username_autofilled,
                               const std::string& password,
                               bool password_autofilled) {
    CheckTextFieldsStateForElements(username_element_,
                                    username,
                                    username_autofilled,
                                    password_element_,
                                    password,
                                    password_autofilled,
                                    false);
  }
  void CheckUsernameSelection(int start, int end) {
    EXPECT_EQ(start, username_element_.selectionStart());
    EXPECT_EQ(end, username_element_.selectionEnd());
  }
  base::string16 username1_;
  base::string16 username2_;
  base::string16 username3_;
  base::string16 password1_;
  base::string16 password2_;
  base::string16 password3_;
  base::string16 alternate_username3_;
  PasswordFormFillData fill_data_;
  WebInputElement username_element_;
  WebInputElement password_element_;
 private:
  DISALLOW_COPY_AND_ASSIGN(PasswordAutofillAgentTest);
};
TEST_F(PasswordAutofillAgentTest, InitialAutocomplete) {
  
  
  
  SimulateOnFillPasswordForm(fill_data_);
  
  CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
}
TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForEmptyAction) {
  const char kEmptyActionFormHTML[] =
      "<FORM name='LoginTestForm'>"
      "  <INPUT type='text' id='username'/>"
      "  <INPUT type='password' id='password'/>"
      "  <INPUT type='submit' value='Login'/>"
      "</FORM>";
  LoadHTML(kEmptyActionFormHTML);
  
  WebDocument document = GetMainFrame()->document();
  WebElement element =
      document.getElementById(WebString::fromUTF8(kUsernameName));
  ASSERT_FALSE(element.isNull());
  username_element_ = element.to<blink::WebInputElement>();
  element = document.getElementById(WebString::fromUTF8(kPasswordName));
  ASSERT_FALSE(element.isNull());
  password_element_ = element.to<blink::WebInputElement>();
  
  UpdateOriginForHTML(kEmptyActionFormHTML);
  fill_data_.basic_data.action = fill_data_.basic_data.origin;
  
  
  SimulateOnFillPasswordForm(fill_data_);
  
  CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
}
TEST_F(PasswordAutofillAgentTest, NoInitialAutocompleteForReadOnlyPassword) {
  password_element_.setAttribute(WebString::fromUTF8("readonly"),
                                 WebString::fromUTF8("true"));
  
  
  SimulateOnFillPasswordForm(fill_data_);
  CheckTextFieldsState(std::string(), false, std::string(), false);
}
TEST_F(PasswordAutofillAgentTest,
       AutocompletePasswordForReadonlyUsernameMatched) {
  username_element_.setValue(username3_);
  username_element_.setAttribute(WebString::fromUTF8("readonly"),
                                 WebString::fromUTF8("true"));
  
  SimulateOnFillPasswordForm(fill_data_);
  CheckTextFieldsState(UTF16ToUTF8(username3_), false,
                       UTF16ToUTF8(password3_), true);
}
TEST_F(PasswordAutofillAgentTest,
       NoAutocompletePasswordForReadonlyUsernameUnmatched) {
  username_element_.setValue(WebString::fromUTF8(""));
  username_element_.setAttribute(WebString::fromUTF8("readonly"),
                                 WebString::fromUTF8("true"));
  SimulateOnFillPasswordForm(fill_data_);
  CheckTextFieldsState(std::string(), false, std::string(), false);
}
TEST_F(PasswordAutofillAgentTest, NoAutocompleteForFilledFieldUnmatched) {
  username_element_.setValue(WebString::fromUTF8("bogus"));
  
  
  SimulateOnFillPasswordForm(fill_data_);
  
  CheckTextFieldsState("bogus", false, std::string(), false);
}
TEST_F(PasswordAutofillAgentTest, NoPartialMatchForPrefilledUsername) {
  username_element_.setValue(WebString::fromUTF8("ali"));
  SimulateOnFillPasswordForm(fill_data_);
  CheckTextFieldsState("ali", false, std::string(), false);
}
TEST_F(PasswordAutofillAgentTest, InputWithNoForms) {
  const char kNoFormInputs[] =
      "<input type='text' id='username'/>"
      "<input type='password' id='password'/>";
  LoadHTML(kNoFormInputs);
  SimulateOnFillPasswordForm(fill_data_);
  
  CheckTextFieldsState(std::string(), false, std::string(), false);
}
TEST_F(PasswordAutofillAgentTest, NoAutocompleteForTextFieldPasswords) {
  const char kTextFieldPasswordFormHTML[] =
      "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
      "  <INPUT type='text' id='username'/>"
      "  <INPUT type='text' id='password'/>"
      "  <INPUT type='submit' value='Login'/>"
      "</FORM>";
  LoadHTML(kTextFieldPasswordFormHTML);
  
  WebDocument document = GetMainFrame()->document();
  WebElement element =
      document.getElementById(WebString::fromUTF8(kUsernameName));
  ASSERT_FALSE(element.isNull());
  username_element_ = element.to<blink::WebInputElement>();
  element = document.getElementById(WebString::fromUTF8(kPasswordName));
  ASSERT_FALSE(element.isNull());
  password_element_ = element.to<blink::WebInputElement>();
  
  UpdateOriginForHTML(kTextFieldPasswordFormHTML);
  SimulateOnFillPasswordForm(fill_data_);
  
  CheckTextFieldsState(std::string(), false, std::string(), false);
}
TEST_F(PasswordAutofillAgentTest, NoAutocompleteForPasswordFieldUsernames) {
  const char kPasswordFieldUsernameFormHTML[] =
      "<FORM name='LoginTestForm' action='http://www.bidule.com'>"
      "  <INPUT type='password' id='username'/>"
      "  <INPUT type='password' id='password'/>"
      "  <INPUT type='submit' value='Login'/>"
      "</FORM>";
  LoadHTML(kPasswordFieldUsernameFormHTML);
  
  WebDocument document = GetMainFrame()->document();
  WebElement element =
      document.getElementById(WebString::fromUTF8(kUsernameName));
  ASSERT_FALSE(element.isNull());
  username_element_ = element.to<blink::WebInputElement>();
  element = document.getElementById(WebString::fromUTF8(kPasswordName));
  ASSERT_FALSE(element.isNull());
  password_element_ = element.to<blink::WebInputElement>();
  
  UpdateOriginForHTML(kPasswordFieldUsernameFormHTML);
  SimulateOnFillPasswordForm(fill_data_);
  
  CheckTextFieldsState(std::string(), false, std::string(), false);
}
TEST_F(PasswordAutofillAgentTest, InitialAutocompleteForMatchingFilledField) {
  username_element_.setValue(WebString::fromUTF8(kAliceUsername));
  
  
  SimulateOnFillPasswordForm(fill_data_);
  
  CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
}
TEST_F(PasswordAutofillAgentTest, PasswordClearOnEdit) {
  
  
  SimulateOnFillPasswordForm(fill_data_);
  
  SimulateUsernameChange("alicia", true);
  
  CheckTextFieldsState("alicia", false, std::string(), false);
}
TEST_F(PasswordAutofillAgentTest, WaitUsername) {
  
  fill_data_.wait_for_username = true;
  SimulateOnFillPasswordForm(fill_data_);
  
  CheckTextFieldsState(std::string(), false, std::string(), false);
  
  SimulateUsernameChange("a", true);
  CheckTextFieldsState("a", false, std::string(), false);
  SimulateUsernameChange("al", true);
  CheckTextFieldsState("al", false, std::string(), false);
  SimulateUsernameChange(kAliceUsername, true);
  CheckTextFieldsState(kAliceUsername, false, std::string(), false);
  
  
  username_element_.setValue("a");
  autofill_agent_->textFieldDidEndEditing(username_element_);
  CheckTextFieldsState("a", false, std::string(), false);
  username_element_.setValue("al");
  autofill_agent_->textFieldDidEndEditing(username_element_);
  CheckTextFieldsState("al", false, std::string(), false);
  username_element_.setValue("alices");
  autofill_agent_->textFieldDidEndEditing(username_element_);
  CheckTextFieldsState("alices", false, std::string(), false);
  username_element_.setValue(ASCIIToUTF16(kAliceUsername));
  autofill_agent_->textFieldDidEndEditing(username_element_);
  CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
}
TEST_F(PasswordAutofillAgentTest, InlineAutocomplete) {
  
  SimulateOnFillPasswordForm(fill_data_);
  
  ClearUsernameAndPasswordFields();
  
  SimulateUsernameChange("a", true);
  
  
  CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
  
  CheckUsernameSelection(1, 5);
  
  SimulateUsernameChange("al", true);
  
  
  CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
  CheckUsernameSelection(2, 5);
  
  SimulateKeyDownEvent(username_element_, ui::VKEY_BACK);
  SimulateUsernameChange("alic", true);
  CheckTextFieldsState("alic", false, std::string(), false);
  CheckUsernameSelection(4, 4);  
  
  SimulateKeyDownEvent(username_element_, ui::VKEY_A);
  
  
  
  
  SimulateUsernameChange("alf", true);
  CheckTextFieldsState("alf", false, std::string(), false);
  CheckUsernameSelection(3, 3);  
  
  SimulateUsernameChange("b", true);
  
  CheckTextFieldsState(kBobUsername, true, kBobPassword, true);
  CheckUsernameSelection(1, 3);
  
  SimulateUsernameChange("C", true);
  
  CheckTextFieldsState(kCarolUsername, true, kCarolPassword, true);
  CheckUsernameSelection(1, 5);
  
  
  
  SimulateUsernameChange("c", true);
  CheckTextFieldsState("c", false, std::string(), false);
  CheckUsernameSelection(1, 1);
  
  SimulateUsernameChange("R", true);
  CheckTextFieldsState(kCarolAlternateUsername, true, kCarolPassword, true);
  CheckUsernameSelection(1, 17);
}
TEST_F(PasswordAutofillAgentTest, IsWebNodeVisibleTest) {
  blink::WebVector<blink::WebFormElement> forms1, forms2, forms3;
  blink::WebFrame* frame;
  LoadHTML(kVisibleFormHTML);
  frame = GetMainFrame();
  frame->document().forms(forms1);
  ASSERT_EQ(1u, forms1.size());
  EXPECT_TRUE(IsWebNodeVisible(forms1[0]));
  LoadHTML(kEmptyFormHTML);
  frame = GetMainFrame();
  frame->document().forms(forms2);
  ASSERT_EQ(1u, forms2.size());
  EXPECT_FALSE(IsWebNodeVisible(forms2[0]));
  LoadHTML(kNonVisibleFormHTML);
  frame = GetMainFrame();
  frame->document().forms(forms3);
  ASSERT_EQ(1u, forms3.size());
  EXPECT_FALSE(IsWebNodeVisible(forms3[0]));
}
TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest) {
  render_thread_->sink().ClearMessages();
  LoadHTML(kVisibleFormHTML);
  const IPC::Message* message = render_thread_->sink()
      .GetFirstMessageMatching(AutofillHostMsg_PasswordFormsRendered::ID);
  EXPECT_TRUE(message);
  Tuple1<std::vector<autofill::PasswordForm> > param;
  AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m);
  EXPECT_TRUE(param.a.size());
  render_thread_->sink().ClearMessages();
  LoadHTML(kEmptyFormHTML);
  message = render_thread_->sink().GetFirstMessageMatching(
      AutofillHostMsg_PasswordFormsRendered::ID);
  EXPECT_TRUE(message);
  AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m);
  EXPECT_FALSE(param.a.size());
  render_thread_->sink().ClearMessages();
  LoadHTML(kNonVisibleFormHTML);
  message = render_thread_->sink().GetFirstMessageMatching(
      AutofillHostMsg_PasswordFormsRendered::ID);
  EXPECT_TRUE(message);
  AutofillHostMsg_PasswordFormsRendered::Read(message, ¶m);
  EXPECT_FALSE(param.a.size());
}
TEST_F(PasswordAutofillAgentTest, SendPasswordFormsTest_Redirection) {
  render_thread_->sink().ClearMessages();
  LoadHTML(kEmptyWebpage);
  EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
      AutofillHostMsg_PasswordFormsRendered::ID));
  render_thread_->sink().ClearMessages();
  LoadHTML(kRedirectionWebpage);
  EXPECT_FALSE(render_thread_->sink().GetFirstMessageMatching(
      AutofillHostMsg_PasswordFormsRendered::ID));
  render_thread_->sink().ClearMessages();
  LoadHTML(kSimpleWebpage);
  EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
      AutofillHostMsg_PasswordFormsRendered::ID));
  render_thread_->sink().ClearMessages();
  LoadHTML(kWebpageWithDynamicContent);
  EXPECT_TRUE(render_thread_->sink().GetFirstMessageMatching(
      AutofillHostMsg_PasswordFormsRendered::ID));
}
TEST_F(PasswordAutofillAgentTest, IframeNoFillTest) {
  const char kIframeName[] = "iframe";
  const char kWebpageWithIframeStart[] =
      "<html>"
      "   <head>"
      "       <meta charset='utf-8' />"
      "       <title>Title</title>"
      "   </head>"
      "   <body>"
      "       <iframe name='iframe' src=\"";
  const char kWebpageWithIframeEnd[] =
      "\"></iframe>"
      "   </body>"
      "</html>";
  std::string origin("data:text/html;charset=utf-8,");
  origin += kSimpleWebpage;
  std::string page_html(kWebpageWithIframeStart);
  page_html += origin;
  page_html += kWebpageWithIframeEnd;
  LoadHTML(page_html.c_str());
  
  fill_data_.basic_data.origin = GURL(origin);
  fill_data_.basic_data.action = GURL(origin);
  SimulateOnFillPasswordForm(fill_data_);
  
  
  WebFrame* iframe = GetMainFrame()->findChildByName(kIframeName);
  ASSERT_TRUE(iframe);
  WebDocument document = iframe->document();
  WebElement username_element = document.getElementById(kUsernameName);
  WebElement password_element = document.getElementById(kPasswordName);
  ASSERT_FALSE(username_element.isNull());
  ASSERT_FALSE(password_element.isNull());
  WebInputElement username_input = username_element.to<WebInputElement>();
  WebInputElement password_input = password_element.to<WebInputElement>();
  ASSERT_FALSE(username_element.isNull());
  CheckTextFieldsStateForElements(username_input, "", false,
                                  password_input, "", false);
  
  
  SimulateUsernameChangeForElement(kAliceUsername, true,
                                   iframe, username_input);
  CheckTextFieldsStateForElements(username_input, kAliceUsername, true,
                                  password_input, kAlicePassword, true);
}
TEST_F(PasswordAutofillAgentTest, GestureRequiredTest) {
  
  SimulateOnFillPasswordForm(fill_data_);
  
  CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
  
  
  
  CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true);
  
  SimulateElementClick(kUsernameName);
  CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
}
TEST_F(PasswordAutofillAgentTest, NoDOMActivationTest) {
  
  SimulateOnFillPasswordForm(fill_data_);
  ExecuteJavaScript(kJavaScriptClick);
  CheckTextFieldsDOMState(kAliceUsername, true, "", true);
}
TEST_F(PasswordAutofillAgentTest, SelectUsernameWithUsernameAutofillOff) {
  
  SimulateOnFillPasswordForm(fill_data_);
  
  username_element_.setAttribute(WebString::fromUTF8("autocomplete"),
                                 WebString::fromUTF8("off"));
  
  SimulateUsernameChange(kAliceUsername, true);
  ExpectNoSuggestionsPopup();
}
TEST_F(PasswordAutofillAgentTest,
       SelectUnknownUsernameWithUsernameAutofillOff) {
  
  SimulateOnFillPasswordForm(fill_data_);
  
  username_element_.setAttribute(WebString::fromUTF8("autocomplete"),
                                 WebString::fromUTF8("off"));
  
  SimulateUsernameChange("foo", true);
  ExpectNoSuggestionsPopup();
}
TEST_F(PasswordAutofillAgentTest, SelectUsernameWithPasswordAutofillOff) {
  
  SimulateOnFillPasswordForm(fill_data_);
  
  password_element_.setAttribute(WebString::fromUTF8("autocomplete"),
                                 WebString::fromUTF8("off"));
 
  SimulateUsernameChange(kAliceUsername, true);
  ExpectNoSuggestionsPopup();
}
TEST_F(PasswordAutofillAgentTest,
       SelectUnknownUsernameWithPasswordAutofillOff) {
  
  SimulateOnFillPasswordForm(fill_data_);
  
  password_element_.setAttribute(WebString::fromUTF8("autocomplete"),
                                 WebString::fromUTF8("off"));
  
  SimulateUsernameChange("foo", true);
  ExpectNoSuggestionsPopup();
}
TEST_F(PasswordAutofillAgentTest,
       PasswordAutofillTriggersOnChangeEventsOnLoad) {
  std::string html = std::string(kFormHTML) + kOnChangeDetectionScript;
  LoadHTML(html.c_str());
  UpdateOriginForHTML(html);
  UpdateUsernameAndPasswordElements();
  
  
  SimulateOnFillPasswordForm(fill_data_);
  
  CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true);
  
  
  CheckTextFieldsDOMState(kAliceUsername, true, std::string(), true);
  
  
  int username_onchange_called = -1;
  int password_onchange_called = -1;
  ASSERT_TRUE(
      ExecuteJavaScriptAndReturnIntValue(
          ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
          &username_onchange_called));
  EXPECT_EQ(1, username_onchange_called);
  ASSERT_TRUE(
      ExecuteJavaScriptAndReturnIntValue(
          ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
          &password_onchange_called));
  
  
  
  SimulateElementClick(kUsernameName);
  CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
  
  
  ASSERT_TRUE(
      ExecuteJavaScriptAndReturnIntValue(
          ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
          &password_onchange_called));
  EXPECT_EQ(1, password_onchange_called);
}
TEST_F(PasswordAutofillAgentTest,
       PasswordAutofillTriggersOnChangeEventsWaitForUsername) {
  std::string html = std::string(kFormHTML) + kOnChangeDetectionScript;
  LoadHTML(html.c_str());
  UpdateOriginForHTML(html);
  UpdateUsernameAndPasswordElements();
  
  
  fill_data_.wait_for_username = true;
  SimulateOnFillPasswordForm(fill_data_);
  
  CheckTextFieldsState(std::string(), false, std::string(), false);
  
  
  SimulateElementClick(kUsernameName);
  
  username_element_.setValue(ASCIIToUTF16(kAliceUsername), true);
  autofill_agent_->textFieldDidEndEditing(username_element_);
  
  CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
  
  
  int username_onchange_called = -1;
  int password_onchange_called = -1;
  ASSERT_TRUE(
      ExecuteJavaScriptAndReturnIntValue(
          ASCIIToUTF16("usernameOnchangeCalled ? 1 : 0"),
          &username_onchange_called));
  EXPECT_EQ(1, username_onchange_called);
  ASSERT_TRUE(
      ExecuteJavaScriptAndReturnIntValue(
          ASCIIToUTF16("passwordOnchangeCalled ? 1 : 0"),
          &password_onchange_called));
  EXPECT_EQ(1, password_onchange_called);
}
}