Chromium Code Reviews| Index: chrome/browser/password_manager/password_manager_browsertest.cc |
| diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..192f7e52447bbdf27f9a6165b8aac754fa849bf2 |
| --- /dev/null |
| +++ b/chrome/browser/password_manager/password_manager_browsertest.cc |
| @@ -0,0 +1,144 @@ |
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
|
Ilya Sherman
2013/03/22 03:26:48
ultra nit: Omit the "(c)"
Garrett Casto
2013/03/22 21:05:05
Done.
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <string> |
| + |
| +#include "chrome/browser/api/infobars/confirm_infobar_delegate.h" |
| +#include "chrome/browser/api/infobars/infobar_service.h" |
| +#include "chrome/browser/ui/browser.h" |
| +#include "chrome/browser/ui/tabs/tab_strip_model.h" |
| +#include "chrome/common/chrome_notification_types.h" |
| +#include "chrome/test/base/in_process_browser_test.h" |
| +#include "chrome/test/base/ui_test_utils.h" |
| +#include "content/public/browser/notification_observer.h" |
| +#include "content/public/browser/notification_registrar.h" |
| +#include "content/public/browser/notification_service.h" |
| +#include "content/public/browser/render_view_host.h" |
| +#include "content/public/browser/web_contents.h" |
| +#include "content/public/browser/web_contents_observer.h" |
| +#include "content/public/test/browser_test_utils.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| +#include "ui/base/keycodes/keyboard_codes.h" |
| + |
| +class NavigationObserver : public content::NotificationObserver, |
| + public content::WebContentsObserver { |
| + public: |
| + explicit NavigationObserver(Browser* browser) |
|
Ilya Sherman
2013/03/22 03:26:48
nit: Can you pass in just the WebContents, rather
Garrett Casto
2013/03/22 21:05:05
Done.
|
| + : content::WebContentsObserver( |
| + browser->tab_strip_model()->GetActiveWebContents()), |
| + has_run_message_loop_(false), |
| + done_loading_(false), |
| + info_bar_shown_(false), |
| + browser_(browser), |
| + infobar_service_(NULL) { |
| + registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, |
| + content::NotificationService::AllSources()); |
|
Ilya Sherman
2013/03/22 03:26:48
nit: Can you listen to notifications from a specif
Garrett Casto
2013/03/22 21:05:05
Changed to use a specific source. I don't think th
|
| + } |
| + |
| + virtual ~NavigationObserver() { |
| + if (!infobar_service_) |
| + return; |
| + |
| + InfoBarDelegate* infobar = NULL; |
| + if (infobar_service_->GetInfoBarCount() > 0 && |
| + (infobar = infobar_service_->GetInfoBarDelegateAt(0))) { |
| + infobar_service_->RemoveInfoBar(infobar); |
|
Ilya Sherman
2013/03/22 03:26:48
Hmm, why do you need to do this manually? Doesn't
Garrett Casto
2013/03/22 21:05:05
I actually just pulled this from autofill_browsert
|
| + } |
| + } |
| + |
| + void Wait() { |
| + if (!done_loading_) { |
| + has_run_message_loop_ = true; |
| + content::RunMessageLoop(); |
| + } |
| + } |
| + |
| + bool InfoBarWasShown() { |
| + return info_bar_shown_; |
| + } |
| + |
| + // content::NotificationObserver: |
| + virtual void Observe(int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) OVERRIDE { |
| + // Accept in the infobar. |
| + infobar_service_ = InfoBarService::FromWebContents( |
| + browser_->tab_strip_model()->GetActiveWebContents()); |
| + InfoBarDelegate* infobar = infobar_service_->GetInfoBarDelegateAt(0); |
| + |
| + ConfirmInfoBarDelegate* confirm_infobar = |
| + infobar->AsConfirmInfoBarDelegate(); |
| + confirm_infobar->Accept(); |
| + info_bar_shown_ = true; |
| + } |
| + |
| + // content::WebContentsObserver |
| + virtual void DidFinishLoad(int64 frame_id, |
| + const GURL& validated_url, |
| + bool is_main_frame, |
| + content::RenderViewHost* render_view_host) { |
| + done_loading_ = true; |
| + if (has_run_message_loop_) { |
| + MessageLoopForUI::current()->Quit(); |
| + has_run_message_loop_ = false; |
| + } |
| + } |
| + |
| + private: |
| + bool has_run_message_loop_; |
|
Ilya Sherman
2013/03/22 03:26:48
Use content::MessageLoopRunner instead.
Garrett Casto
2013/03/22 21:05:05
Done.
|
| + bool done_loading_; |
| + bool info_bar_shown_; |
| + content::NotificationRegistrar registrar_; |
| + Browser* browser_; |
| + InfoBarService* infobar_service_; |
| +}; |
|
Ilya Sherman
2013/03/22 03:26:48
nit: Tuck this into an anonymous namespace.
Garrett Casto
2013/03/22 21:05:05
Done.
|
| + |
| +class PasswordManagerBrowserTest : public InProcessBrowserTest { |
| + protected: |
| + content::RenderViewHost* render_view_host() { |
|
Ilya Sherman
2013/03/22 03:26:48
nit: This should use MixedCaps rather than hacker_
Garrett Casto
2013/03/22 21:05:05
Done.
|
| + return browser()->tab_strip_model()->GetActiveWebContents()-> |
| + GetRenderViewHost(); |
| + } |
| +}; |
| + |
| +IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, PromptForXHRSubmit) { |
|
Ilya Sherman
2013/03/22 03:26:48
As long as you're adding test coverage (thanks!),
Garrett Casto
2013/03/22 21:05:05
There is actually a full pyauto test suite for the
Ilya Sherman
2013/03/23 01:10:58
Ok, fair enough :)
|
| + ASSERT_TRUE(test_server()->Start()); |
| + |
| + GURL url = test_server()->GetURL("files/password/password_xhr_submit.html"); |
| + ui_test_utils::NavigateToURL(browser(), url); |
| + |
| + // Verify that we show the save password prompt if a form returns false |
| + // in it's onsubmit handler but instead logs in/navigates via XHR. |
|
Ilya Sherman
2013/03/22 03:26:48
nit: "it's" -> "its"
Garrett Casto
2013/03/22 21:05:05
Done.
|
| + // Note that calling 'submit()' on a form with javascript doesn't call |
| + // the onsubmit handler, so we click the submit button instead. |
| + NavigationObserver observer(browser()); |
| + std::string fill_and_submit = |
| + "document.getElementById('username_field').value = 'temp';" |
| + "document.getElementById('password_field').value = 'random';" |
| + "document.getElementById('submit_button').click()"; |
| + ASSERT_TRUE(content::ExecuteScript(render_view_host(), fill_and_submit)); |
|
Ilya Sherman
2013/03/22 03:26:48
Can you have the loaded page send a result when it
Garrett Casto
2013/03/22 21:05:05
I'm not sure what exactly you have in mind here. I
Ilya Sherman
2013/03/23 01:10:58
Hmm, I kind of ignored the fact that the JavaScrip
|
| + observer.Wait(); |
| + ASSERT_TRUE(observer.InfoBarWasShown()); |
|
Ilya Sherman
2013/03/22 03:26:48
nit: I think this can be EXPECT_TRUE.
Garrett Casto
2013/03/22 21:05:05
Done.
|
| +} |
| + |
| +IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoPromptForOtherXHR) { |
| + ASSERT_TRUE(test_server()->Start()); |
| + |
| + GURL url = test_server()->GetURL("files/password/password_xhr_submit.html"); |
| + ui_test_utils::NavigateToURL(browser(), url); |
| + |
| + // Verify that if random XHR navigation occurs, we don't try and save the |
| + // password. |
| + // |
| + // We may want to change this functionality in the future to account for |
| + // cases where the element that users click on isn't a submit button. |
| + NavigationObserver observer(browser()); |
| + std::string fill_and_navigate = |
| + "document.getElementById('username_field').value = 'temp';" |
| + "document.getElementById('password_field').value = 'random';" |
| + "send_xhr()"; |
| + ASSERT_TRUE(content::ExecuteScript(render_view_host(), fill_and_navigate)); |
| + observer.Wait(); |
| + ASSERT_FALSE(observer.InfoBarWasShown()); |
|
Ilya Sherman
2013/03/22 03:26:48
nit: I think this can be EXPECT_FALSE.
Garrett Casto
2013/03/22 21:05:05
Done.
|
| +} |