1// Copyright 2014 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 "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h"
6
7#include "base/metrics/histogram_samples.h"
8#include "chrome/browser/ui/browser.h"
9#include "chrome/browser/ui/passwords/manage_passwords_test.h"
10#include "chrome/browser/ui/tabs/tab_strip_model.h"
11#include "chrome/browser/ui/views/frame/browser_view.h"
12#include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h"
13#include "chrome/browser/ui/views/passwords/manage_passwords_icon_view.h"
14#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
15#include "chrome/test/base/interactive_test_utils.h"
16#include "components/password_manager/core/browser/password_manager_metrics_util.h"
17#include "components/password_manager/core/browser/stub_password_manager_client.h"
18#include "content/public/browser/notification_types.h"
19#include "content/public/browser/render_view_host.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22namespace {
23
24const char kDisplayDispositionMetric[] = "PasswordBubble.DisplayDisposition";
25
26}  // namespace
27
28namespace metrics_util = password_manager::metrics_util;
29
30class ManagePasswordsBubbleViewTest : public ManagePasswordsTest {
31 public:
32  ManagePasswordsBubbleViewTest() {}
33  virtual ~ManagePasswordsBubbleViewTest() {}
34
35  virtual ManagePasswordsIcon* view() OVERRIDE {
36    BrowserView* browser_view = static_cast<BrowserView*>(browser()->window());
37    return browser_view->GetToolbarView()
38        ->location_bar()
39        ->manage_passwords_icon_view();
40  }
41
42 private:
43  DISALLOW_COPY_AND_ASSIGN(ManagePasswordsBubbleViewTest);
44};
45
46IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest, BasicOpenAndClose) {
47  EXPECT_FALSE(ManagePasswordsBubbleView::IsShowing());
48  ManagePasswordsBubbleView::ShowBubble(
49      browser()->tab_strip_model()->GetActiveWebContents(),
50      ManagePasswordsBubble::USER_ACTION);
51  EXPECT_TRUE(ManagePasswordsBubbleView::IsShowing());
52  const ManagePasswordsBubbleView* bubble =
53      ManagePasswordsBubbleView::manage_password_bubble();
54  EXPECT_TRUE(bubble->initially_focused_view());
55  EXPECT_EQ(bubble->initially_focused_view(),
56            bubble->GetFocusManager()->GetFocusedView());
57  ManagePasswordsBubbleView::CloseBubble();
58  EXPECT_FALSE(ManagePasswordsBubbleView::IsShowing());
59
60  // And, just for grins, ensure that we can re-open the bubble.
61  ManagePasswordsBubbleView::ShowBubble(
62      browser()->tab_strip_model()->GetActiveWebContents(),
63      ManagePasswordsBubble::USER_ACTION);
64  EXPECT_TRUE(ManagePasswordsBubbleView::manage_password_bubble()->
65      GetFocusManager()->GetFocusedView());
66  EXPECT_TRUE(ManagePasswordsBubbleView::IsShowing());
67  ManagePasswordsBubbleView::CloseBubble();
68  EXPECT_FALSE(ManagePasswordsBubbleView::IsShowing());
69}
70
71// Same as 'BasicOpenAndClose', but use the command rather than the static
72// method directly.
73IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest, CommandControlsBubble) {
74  // The command only works if the icon is visible, so get into management mode.
75  SetupManagingPasswords();
76  EXPECT_FALSE(ManagePasswordsBubbleView::IsShowing());
77  ExecuteManagePasswordsCommand();
78  EXPECT_TRUE(ManagePasswordsBubbleView::IsShowing());
79  const ManagePasswordsBubbleView* bubble =
80      ManagePasswordsBubbleView::manage_password_bubble();
81  EXPECT_TRUE(bubble->initially_focused_view());
82  EXPECT_EQ(bubble->initially_focused_view(),
83            bubble->GetFocusManager()->GetFocusedView());
84  ManagePasswordsBubbleView::CloseBubble();
85  EXPECT_FALSE(ManagePasswordsBubbleView::IsShowing());
86
87  // And, just for grins, ensure that we can re-open the bubble.
88  ExecuteManagePasswordsCommand();
89  EXPECT_TRUE(ManagePasswordsBubbleView::IsShowing());
90  ManagePasswordsBubbleView::CloseBubble();
91  EXPECT_FALSE(ManagePasswordsBubbleView::IsShowing());
92}
93
94IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest,
95                       CommandExecutionInManagingState) {
96  SetupManagingPasswords();
97  ExecuteManagePasswordsCommand();
98
99  scoped_ptr<base::HistogramSamples> samples(
100      GetSamples(kDisplayDispositionMetric));
101  EXPECT_EQ(
102      0,
103      samples->GetCount(
104          metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING));
105  EXPECT_EQ(0,
106            samples->GetCount(
107                metrics_util::MANUAL_WITH_PASSWORD_PENDING));
108  EXPECT_EQ(1,
109            samples->GetCount(
110                metrics_util::MANUAL_MANAGE_PASSWORDS));
111}
112
113IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest,
114                       CommandExecutionInAutomaticState) {
115  // Open with pending password: automagical!
116  SetupPendingPassword();
117
118  // Bubble should not be focused by default.
119  EXPECT_FALSE(ManagePasswordsBubbleView::manage_password_bubble()->
120      GetFocusManager()->GetFocusedView());
121  // Bubble can be active if user clicks it.
122  EXPECT_TRUE(ManagePasswordsBubbleView::manage_password_bubble()->
123      CanActivate());
124
125  scoped_ptr<base::HistogramSamples> samples(
126      GetSamples(kDisplayDispositionMetric));
127  EXPECT_EQ(
128      1,
129      samples->GetCount(
130          metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING));
131  EXPECT_EQ(0,
132            samples->GetCount(
133                metrics_util::MANUAL_WITH_PASSWORD_PENDING));
134  EXPECT_EQ(0,
135            samples->GetCount(
136                metrics_util::MANUAL_MANAGE_PASSWORDS));
137}
138
139IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest,
140                       CommandExecutionInPendingState) {
141  // Open once with pending password: automagical!
142  SetupPendingPassword();
143  ManagePasswordsBubbleView::CloseBubble();
144  // This opening should be measured as manual.
145  ExecuteManagePasswordsCommand();
146
147  scoped_ptr<base::HistogramSamples> samples(
148      GetSamples(kDisplayDispositionMetric));
149  EXPECT_EQ(
150      1,
151      samples->GetCount(
152          metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING));
153  EXPECT_EQ(1,
154            samples->GetCount(
155                metrics_util::MANUAL_WITH_PASSWORD_PENDING));
156  EXPECT_EQ(0,
157            samples->GetCount(
158                metrics_util::MANUAL_MANAGE_PASSWORDS));
159}
160
161IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest,
162                       CommandExecutionInAutomaticSaveState) {
163  SetupAutomaticPassword();
164  ManagePasswordsBubbleView::CloseBubble();
165  // Re-opening should count as manual.
166  ExecuteManagePasswordsCommand();
167
168 scoped_ptr<base::HistogramSamples> samples(
169      GetSamples(kDisplayDispositionMetric));
170  EXPECT_EQ(
171      1,
172      samples->GetCount(
173          metrics_util::AUTOMATIC_GENERATED_PASSWORD_CONFIRMATION));
174  EXPECT_EQ(0,
175            samples->GetCount(
176                metrics_util::MANUAL_WITH_PASSWORD_PENDING));
177  EXPECT_EQ(1,
178            samples->GetCount(
179                metrics_util::MANUAL_MANAGE_PASSWORDS));
180}
181
182IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest, CloseOnClick) {
183  ManagePasswordsBubbleView::ShowBubble(
184      browser()->tab_strip_model()->GetActiveWebContents(),
185      ManagePasswordsBubble::AUTOMATIC);
186  EXPECT_TRUE(ManagePasswordsBubbleView::IsShowing());
187  EXPECT_FALSE(ManagePasswordsBubbleView::manage_password_bubble()->
188      GetFocusManager()->GetFocusedView());
189  ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER);
190  EXPECT_FALSE(ManagePasswordsBubbleView::IsShowing());
191}
192
193IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest, CloseOnKey) {
194  content::WindowedNotificationObserver focus_observer(
195      content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
196      content::NotificationService::AllSources());
197  ui_test_utils::NavigateToURL(
198      browser(),
199      GURL("data:text/html;charset=utf-8,<input type=\"text\" autofocus>"));
200  focus_observer.Wait();
201  content::WebContents* web_contents =
202      browser()->tab_strip_model()->GetActiveWebContents();
203  ManagePasswordsBubbleView::ShowBubble(web_contents,
204                                        ManagePasswordsBubble::AUTOMATIC);
205  EXPECT_TRUE(ManagePasswordsBubbleView::IsShowing());
206  EXPECT_FALSE(ManagePasswordsBubbleView::manage_password_bubble()->
207      GetFocusManager()->GetFocusedView());
208  EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER));
209  EXPECT_TRUE(web_contents->GetRenderViewHost()->IsFocusedElementEditable());
210  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_K,
211      false, false, false, false));
212  EXPECT_FALSE(ManagePasswordsBubbleView::IsShowing());
213}
214
215IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest, TwoTabsWithBubble) {
216  // Set up the first tab with the bubble.
217  SetupPendingPassword();
218  EXPECT_TRUE(ManagePasswordsBubbleView::IsShowing());
219  // Set up the second tab.
220  AddTabAtIndex(0, GURL("chrome://newtab"), ui::PAGE_TRANSITION_TYPED);
221  EXPECT_FALSE(ManagePasswordsBubbleView::IsShowing());
222  ManagePasswordsBubbleView::ShowBubble(
223      browser()->tab_strip_model()->GetActiveWebContents(),
224      ManagePasswordsBubble::AUTOMATIC);
225  EXPECT_TRUE(ManagePasswordsBubbleView::IsShowing());
226  TabStripModel* tab_model = browser()->tab_strip_model();
227  EXPECT_EQ(0, tab_model->active_index());
228  // Back to the first tab.
229  tab_model->ActivateTabAt(1, true);
230  EXPECT_FALSE(ManagePasswordsBubbleView::IsShowing());
231}
232