Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / password_manager / password_manager_test_base.cc
blob275b674af1763bf0619cd0c62001764a26449a14
1 // Copyright 2015 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.
5 #include "chrome/browser/password_manager/password_manager_test_base.h"
7 #include "base/command_line.h"
8 #include "base/run_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "chrome/browser/infobars/infobar_service.h"
11 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
12 #include "chrome/browser/password_manager/password_store_factory.h"
13 #include "chrome/browser/password_manager/test_password_store_service.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/test/base/ui_test_utils.h"
19 #include "components/autofill/core/browser/autofill_test_utils.h"
20 #include "components/infobars/core/confirm_infobar_delegate.h"
21 #include "components/infobars/core/infobar.h"
22 #include "components/infobars/core/infobar_manager.h"
23 #include "components/password_manager/core/browser/test_password_store.h"
24 #include "components/password_manager/core/common/password_manager_switches.h"
25 #include "content/public/browser/render_frame_host.h"
26 #include "content/public/browser/render_view_host.h"
27 #include "content/public/test/browser_test_utils.h"
28 #include "content/public/test/test_utils.h"
29 #include "net/test/embedded_test_server/embedded_test_server.h"
31 NavigationObserver::NavigationObserver(content::WebContents* web_contents)
32 : content::WebContentsObserver(web_contents),
33 quit_on_entry_committed_(false),
34 message_loop_runner_(new content::MessageLoopRunner) {
36 NavigationObserver::~NavigationObserver() {
39 void NavigationObserver::DidFinishLoad(
40 content::RenderFrameHost* render_frame_host,
41 const GURL& validated_url) {
42 render_frame_host_ = render_frame_host;
43 if (!wait_for_path_.empty()) {
44 if (validated_url.path() == wait_for_path_)
45 message_loop_runner_->Quit();
46 } else if (!render_frame_host->GetParent()) {
47 message_loop_runner_->Quit();
51 void NavigationObserver::NavigationEntryCommitted(
52 const content::LoadCommittedDetails& load_details) {
53 if (quit_on_entry_committed_)
54 message_loop_runner_->Quit();
57 void NavigationObserver::Wait() {
58 message_loop_runner_->Run();
61 PromptObserver::PromptObserver() {
63 PromptObserver::~PromptObserver() {
66 bool PromptObserver::IsShowingUpdatePrompt() const {
67 // TODO(dvadym): Make this method pure virtual as soon as update UI is
68 // implemented for infobar. http://crbug.com/359315
69 return false;
72 void PromptObserver::Accept() const {
73 ASSERT_TRUE(IsShowingPrompt());
74 AcceptImpl();
77 void PromptObserver::AcceptUpdatePrompt(
78 const autofill::PasswordForm& form) const {
79 EXPECT_TRUE(IsShowingUpdatePrompt());
80 AcceptUpdatePromptImpl(form);
83 class InfoBarObserver : public PromptObserver,
84 public infobars::InfoBarManager::Observer {
85 public:
86 explicit InfoBarObserver(content::WebContents* web_contents)
87 : infobar_is_being_shown_(false),
88 infobar_service_(InfoBarService::FromWebContents(web_contents)) {
89 infobar_service_->AddObserver(this);
92 ~InfoBarObserver() override {
93 if (infobar_service_)
94 infobar_service_->RemoveObserver(this);
97 private:
98 // PromptObserver:
99 bool IsShowingPrompt() const override { return infobar_is_being_shown_; }
101 void AcceptImpl() const override {
102 EXPECT_EQ(1u, infobar_service_->infobar_count());
103 if (!infobar_service_->infobar_count())
104 return; // Let the test finish to gather possibly more diagnostics.
106 // ConfirmInfoBarDelegate::Accept returning true means the infobar is
107 // immediately closed. Checking the return value is preferred to testing
108 // IsShowingPrompt() here, for it avoids the delay until the closing
109 // notification is received.
110 EXPECT_TRUE(infobar_service_->infobar_at(0)
111 ->delegate()
112 ->AsConfirmInfoBarDelegate()
113 ->Accept());
116 // infobars::InfoBarManager::Observer:
117 void OnInfoBarAdded(infobars::InfoBar* infobar) override {
118 infobar_is_being_shown_ = true;
121 void OnInfoBarRemoved(infobars::InfoBar* infobar, bool animate) override {
122 infobar_is_being_shown_ = false;
125 void OnManagerShuttingDown(infobars::InfoBarManager* manager) override {
126 ASSERT_EQ(infobar_service_, manager);
127 infobar_service_->RemoveObserver(this);
128 infobar_service_ = nullptr;
131 bool infobar_is_being_shown_;
132 InfoBarService* infobar_service_;
134 DISALLOW_COPY_AND_ASSIGN(InfoBarObserver);
137 class BubbleObserver : public PromptObserver {
138 public:
139 explicit BubbleObserver(content::WebContents* web_contents)
140 : ui_controller_(
141 ManagePasswordsUIController::FromWebContents(web_contents)) {}
143 ~BubbleObserver() override {}
145 private:
146 // PromptObserver:
147 bool IsShowingPrompt() const override {
148 return ui_controller_->PasswordPendingUserDecision();
151 bool IsShowingUpdatePrompt() const override {
152 return ui_controller_->state() ==
153 password_manager::ui::PENDING_PASSWORD_UPDATE_STATE;
156 void AcceptImpl() const override {
157 ui_controller_->SavePassword();
158 EXPECT_FALSE(IsShowingPrompt());
161 void AcceptUpdatePromptImpl(
162 const autofill::PasswordForm& form) const override {
163 ui_controller_->UpdatePassword(form);
164 EXPECT_FALSE(IsShowingUpdatePrompt());
166 ManagePasswordsUIController* const ui_controller_;
168 DISALLOW_COPY_AND_ASSIGN(BubbleObserver);
171 scoped_ptr<PromptObserver> PromptObserver::Create(
172 content::WebContents* web_contents) {
173 if (ChromePasswordManagerClient::IsTheHotNewBubbleUIEnabled()) {
174 return scoped_ptr<PromptObserver>(new BubbleObserver(web_contents));
175 } else {
176 return scoped_ptr<PromptObserver>(new InfoBarObserver(web_contents));
180 PasswordManagerBrowserTestBase::PasswordManagerBrowserTestBase() {
182 PasswordManagerBrowserTestBase::~PasswordManagerBrowserTestBase() {
185 void PasswordManagerBrowserTestBase::SetUpOnMainThread() {
186 // Use TestPasswordStore to remove a possible race. Normally the
187 // PasswordStore does its database manipulation on the DB thread, which
188 // creates a possible race during navigation. Specifically the
189 // PasswordManager will ignore any forms in a page if the load from the
190 // PasswordStore has not completed.
191 PasswordStoreFactory::GetInstance()->SetTestingFactory(
192 browser()->profile(), TestPasswordStoreService::Build);
193 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
194 ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
195 password_manager::switches::kEnableAutomaticPasswordSaving));
198 void PasswordManagerBrowserTestBase::TearDownOnMainThread() {
199 ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
202 content::WebContents* PasswordManagerBrowserTestBase::WebContents() {
203 return browser()->tab_strip_model()->GetActiveWebContents();
206 content::RenderViewHost* PasswordManagerBrowserTestBase::RenderViewHost() {
207 return WebContents()->GetRenderViewHost();
210 void PasswordManagerBrowserTestBase::NavigateToFile(const std::string& path) {
211 NavigationObserver observer(WebContents());
212 GURL url = embedded_test_server()->GetURL(path);
213 ui_test_utils::NavigateToURL(browser(), url);
214 observer.Wait();
217 void PasswordManagerBrowserTestBase::VerifyPasswordIsSavedAndFilled(
218 const std::string& filename,
219 const std::string& submission_script,
220 const std::string& expected_element,
221 const std::string& expected_value) {
222 password_manager::TestPasswordStore* password_store =
223 static_cast<password_manager::TestPasswordStore*>(
224 PasswordStoreFactory::GetForProfile(
225 browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS).get());
226 EXPECT_TRUE(password_store->IsEmpty());
228 NavigateToFile(filename);
230 NavigationObserver observer(WebContents());
231 scoped_ptr<PromptObserver> prompt_observer(
232 PromptObserver::Create(WebContents()));
233 ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submission_script));
234 observer.Wait();
236 prompt_observer->Accept();
238 // Spin the message loop to make sure the password store had a chance to save
239 // the password.
240 base::RunLoop run_loop;
241 run_loop.RunUntilIdle();
242 ASSERT_FALSE(password_store->IsEmpty());
244 NavigateToFile(filename);
246 // Let the user interact with the page, so that DOM gets modification events,
247 // needed for autofilling fields.
248 content::SimulateMouseClickAt(
249 WebContents(), 0, blink::WebMouseEvent::ButtonLeft, gfx::Point(1, 1));
251 // Wait until that interaction causes the password value to be revealed.
252 WaitForElementValue(expected_element, expected_value);
255 void PasswordManagerBrowserTestBase::WaitForElementValue(
256 const std::string& element_id,
257 const std::string& expected_value) {
258 WaitForElementValue("null", element_id, expected_value);
261 void PasswordManagerBrowserTestBase::WaitForElementValue(
262 const std::string& iframe_id,
263 const std::string& element_id,
264 const std::string& expected_value) {
265 enum ReturnCodes { // Possible results of the JavaScript code.
266 RETURN_CODE_OK,
267 RETURN_CODE_NO_ELEMENT,
268 RETURN_CODE_WRONG_VALUE,
269 RETURN_CODE_INVALID,
271 const std::string value_check_function = base::StringPrintf(
272 "function valueCheck() {"
273 " if (%s)"
274 " var element = document.getElementById("
275 " '%s').contentDocument.getElementById('%s');"
276 " else "
277 " var element = document.getElementById('%s');"
278 " return element && element.value == '%s';"
279 "}",
280 iframe_id.c_str(), iframe_id.c_str(), element_id.c_str(),
281 element_id.c_str(), expected_value.c_str());
282 const std::string script =
283 value_check_function +
284 base::StringPrintf(
285 "if (valueCheck()) {"
286 " /* Spin the event loop with setTimeout. */"
287 " setTimeout(window.domAutomationController.send(%d), 0);"
288 "} else {"
289 " if (%s)"
290 " var element = document.getElementById("
291 " '%s').contentDocument.getElementById('%s');"
292 " else "
293 " var element = document.getElementById('%s');"
294 " if (!element)"
295 " window.domAutomationController.send(%d);"
296 " element.onchange = function() {"
297 " if (valueCheck()) {"
298 " /* Spin the event loop with setTimeout. */"
299 " setTimeout(window.domAutomationController.send(%d), 0);"
300 " } else {"
301 " window.domAutomationController.send(%d);"
302 " }"
303 " };"
304 "}",
305 RETURN_CODE_OK, iframe_id.c_str(), iframe_id.c_str(),
306 element_id.c_str(), element_id.c_str(), RETURN_CODE_NO_ELEMENT,
307 RETURN_CODE_OK, RETURN_CODE_WRONG_VALUE);
308 int return_value = RETURN_CODE_INVALID;
309 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(RenderViewHost(), script,
310 &return_value));
311 EXPECT_EQ(RETURN_CODE_OK, return_value)
312 << "element_id = " << element_id
313 << ", expected_value = " << expected_value;
316 void PasswordManagerBrowserTestBase::CheckElementValue(
317 const std::string& element_id,
318 const std::string& expected_value) {
319 CheckElementValue("null", element_id, expected_value);
322 void PasswordManagerBrowserTestBase::CheckElementValue(
323 const std::string& iframe_id,
324 const std::string& element_id,
325 const std::string& expected_value) {
326 const std::string value_check_script = base::StringPrintf(
327 "if (%s)"
328 " var element = document.getElementById("
329 " '%s').contentDocument.getElementById('%s');"
330 "else "
331 " var element = document.getElementById('%s');"
332 "window.domAutomationController.send(element && element.value == '%s');",
333 iframe_id.c_str(), iframe_id.c_str(), element_id.c_str(),
334 element_id.c_str(), expected_value.c_str());
335 bool return_value = false;
336 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
337 RenderViewHost(), value_check_script, &return_value));
338 EXPECT_TRUE(return_value) << "element_id = " << element_id
339 << ", expected_value = " << expected_value;