blob: b641d80b15599d3bc32539e6d55cea9c44bc646c [file] [log] [blame]
// Copyright 2015 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 "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/password_manager/password_manager_test_base.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/ui/browser.h"
#include "components/password_manager/core/browser/test_password_store.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "ui/events/keycodes/keyboard_codes.h"
namespace {
void SimulateUserTypingInField(content::RenderViewHost* render_view_host,
content::WebContents* web_contents,
const std::string& field_id) {
std::string focus("document.getElementById('" + field_id + "').focus();");
ASSERT_TRUE(content::ExecuteScript(render_view_host, focus));
content::SimulateKeyPress(web_contents, ui::DomKey::FromCharacter('O'),
ui::DomCode::US_O, ui::VKEY_O, false, false, false,
false);
content::SimulateKeyPress(web_contents, ui::DomKey::FromCharacter('R'),
ui::DomCode::US_R, ui::VKEY_R, false, false, false,
false);
content::SimulateKeyPress(web_contents, ui::DomKey::FromCharacter('A'),
ui::DomCode::US_A, ui::VKEY_A, false, false, false,
false);
content::SimulateKeyPress(web_contents, ui::DomKey::FromCharacter('R'),
ui::DomCode::US_R, ui::VKEY_R, false, false, false,
false);
content::SimulateKeyPress(web_contents, ui::DomKey::FromCharacter('Y'),
ui::DomCode::US_Y, ui::VKEY_Y, false, false, false,
false);
}
} // namespace
namespace password_manager {
// TODO(crbug.com/616627): Flaky on Mac, CrOS and Linux.
#if defined(OS_MACOSX) || defined(OS_CHROMEOS) || defined(OS_LINUX)
#define MAYBE_UsernameChanged DISABLED_UsernameChanged
#else
#define MAYBE_UsernameChanged UsernameChanged
#endif
IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, MAYBE_UsernameChanged) {
scoped_refptr<password_manager::TestPasswordStore> password_store =
static_cast<password_manager::TestPasswordStore*>(
PasswordStoreFactory::GetForProfile(
browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
NavigateToFile("/password/signup_form.html");
NavigationObserver observer(WebContents());
std::unique_ptr<BubbleObserver> prompt_observer(
new BubbleObserver(WebContents()));
std::string fill_and_submit =
"document.getElementById('username_field').value = 'temp';"
"document.getElementById('password_field').value = 'random';"
"document.getElementById('input_submit_button').click()";
ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), fill_and_submit));
observer.Wait();
EXPECT_TRUE(prompt_observer->IsShowingSavePrompt());
prompt_observer->AcceptSavePrompt();
// Spin the message loop to make sure the password store had a chance to save
// the password.
base::RunLoop run_loop;
run_loop.RunUntilIdle();
EXPECT_FALSE(password_store->IsEmpty());
// Reload the original page to have the saved credentials autofilled.
NavigationObserver reload_observer(WebContents());
NavigateToFile("/password/signup_form.html");
reload_observer.Wait();
// Let the user interact with the page, so that DOM gets modification events,
// needed for autofilling fields.
content::SimulateMouseClickAt(
WebContents(), 0, blink::WebMouseEvent::Button::Left, gfx::Point(1, 1));
WaitForElementValue("username_field", "temp");
WaitForElementValue("password_field", "random");
// Change username and submit. This should add the characters "ORARY" to the
// already autofilled username.
SimulateUserTypingInField(RenderViewHost(), WebContents(), "username_field");
// TODO(gcasto): Not sure why this click is required.
content::SimulateMouseClickAt(
WebContents(), 0, blink::WebMouseEvent::Button::Left, gfx::Point(1, 1));
WaitForElementValue("username_field", "tempORARY");
NavigationObserver second_observer(WebContents());
std::unique_ptr<BubbleObserver> second_prompt_observer(
new BubbleObserver(WebContents()));
std::string submit =
"document.getElementById('input_submit_button').click();";
ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
second_observer.Wait();
EXPECT_TRUE(second_prompt_observer->IsShowingSavePrompt());
second_prompt_observer->AcceptSavePrompt();
// Spin the message loop to make sure the password store had a chance to save
// the password.
base::RunLoop third_run_loop;
third_run_loop.RunUntilIdle();
EXPECT_FALSE(password_store->IsEmpty());
// Verify that there are two saved password, the old password and the new
// password.
password_manager::TestPasswordStore::PasswordMap stored_passwords =
password_store->stored_passwords();
EXPECT_EQ(1u, stored_passwords.size());
EXPECT_EQ(2u, stored_passwords.begin()->second.size());
EXPECT_EQ(base::UTF8ToUTF16("temp"),
(stored_passwords.begin()->second)[0].username_value);
EXPECT_EQ(base::UTF8ToUTF16("tempORARY"),
(stored_passwords.begin()->second)[1].username_value);
}
} // namespace password_manager