Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(992)

Side by Side Diff: chrome/browser/ui/login/login_prompt_browsertest.cc

Issue 5814005: Minimize login prompts (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Add browsertest Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 <set>
6 #include <map>
7
8 #include "net/base/auth.h"
cbentzel 2010/12/17 19:22:56 Includes need to be alphabetically ordered.
9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/browser_thread.h"
11 #include "chrome/browser/ui/login/login_prompt.h"
12 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
13 #include "chrome/test/in_process_browser_test.h"
14 #include "chrome/test/ui_test_utils.h"
15 #include "chrome/common/notification_service.h"
16
17 namespace {
18
19 class LoginPromptBrowserTest : public InProcessBrowserTest {
20 public:
21 LoginPromptBrowserTest():
cbentzel 2010/12/17 19:22:56 Nit: the first initializer list argument should be
22 bad_password_(L"incorrect"), bad_username_(L"nouser") {
23 set_show_window(true);
24
25 auth_map_[L"foo"] = AuthInfo(L"testuser", L"foopassword");
26 auth_map_[L"bar"] = AuthInfo(L"testuser", L"barpassword");
27 }
28
29 protected:
30
cbentzel 2010/12/17 19:22:56 Nit: extra newline
31 struct AuthInfo {
32 std::wstring username_;
33 std::wstring password_;
34
35 AuthInfo() {}
36
37 AuthInfo(const std::wstring username,
38 const std::wstring password):
39 username_(username), password_(password) {}
40 };
41
42 NotificationRegistrar registrar_;
43 std::map<std::wstring, AuthInfo> auth_map_;
44 std::wstring bad_password_;
45 std::wstring bad_username_;
46
47 void SetAuthFor(LoginHandler* handler);
cbentzel 2010/12/17 19:22:56 Nit: SetAuthFor needs to be declared before the me
48 };
49
50 const char* kMultiRealmTestPage = "files/login/multi_realm.html";
51 const char* kSingleRealmTestPage = "files/login/single_realm.html";
cbentzel 2010/12/17 19:22:56 Might make sense to move these right above the TES
52
53 void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
54 net::AuthChallengeInfo* challenge = handler->auth_info();
55 std::map<std::wstring, AuthInfo>::iterator i;
cbentzel 2010/12/17 19:22:56 Don't use default constructor for i, assign with a
56
57 ASSERT_TRUE(challenge != NULL);
58 i = auth_map_.find(challenge->realm);
59 EXPECT_NE(auth_map_.end(), i);
60 if (i != auth_map_.end()) {
61 AuthInfo& info = i->second;
cbentzel 2010/12/17 19:22:56 const AuthInfo
62
cbentzel 2010/12/17 19:22:56 Nit: extra newline
63 handler->SetAuth(info.username_, info.password_);
64 }
65 }
66
67 // Maintains a set of LoginHandlers that are currently active and
68 // keeps a count of the notifications that were observed.
69 class LoginPromptBrowserTestObserver : public NotificationObserver {
70 public:
71
cbentzel 2010/12/17 19:22:56 Nit: extra new line
72 LoginPromptBrowserTestObserver():
cbentzel 2010/12/17 19:22:56 Nit: first initializer list argument on same line
73 n_auth_needed(0), n_auth_supplied(0), n_auth_cancelled(0) {}
cbentzel 2010/12/17 19:22:56 Use auth_needed_count rather than n_auth_needed [e
74
75 virtual void Observe(NotificationType type,
76 const NotificationSource& source,
77 const NotificationDetails& details);
78
79 void AddSelf(NotificationRegistrar* registrar,
cbentzel 2010/12/17 19:22:56 Register and Unregister may be clearer than AddSel
80 const NotificationSource& source);
81
82 void RemoveSelf(NotificationRegistrar* registrar,
83 const NotificationSource& source);
84
85 std::set<LoginHandler*> handlers_;
86
87 int n_auth_needed;
88 int n_auth_supplied;
89 int n_auth_cancelled;
90
91 DISALLOW_COPY_AND_ASSIGN(LoginPromptBrowserTestObserver);
92 };
93
94 void LoginPromptBrowserTestObserver::Observe(
95 NotificationType type,
96 const NotificationSource& source,
97 const NotificationDetails& details) {
98
cbentzel 2010/12/17 19:22:56 Nit: extra new line
99 LoginNotificationDetails* login_details =
cbentzel 2010/12/17 19:22:56 The Details cast here is typically done after chec
100 Details<LoginNotificationDetails>(details).ptr();
101
102 if (type == NotificationType::AUTH_NEEDED) {
103 EXPECT_TRUE(handlers_.find(login_details->handler()) == handlers_.end());
104 handlers_.insert(login_details->handler());
105 n_auth_needed++;
106 } else if (type == NotificationType::AUTH_SUPPLIED ||
107 type == NotificationType::AUTH_CANCELLED) {
108 std::set<LoginHandler *>::iterator i;
cbentzel 2010/12/17 19:22:56 Nit: do the handlers_.find on the same line as i d
109
110 i = handlers_.find(login_details->handler());
111 EXPECT_TRUE(i != handlers_.end());
112 if (i != handlers_.end())
113 handlers_.erase(i);
114
115 if (type == NotificationType::AUTH_SUPPLIED)
116 n_auth_supplied++;
117 else
118 n_auth_cancelled++;
119 }
120 }
121
122 void LoginPromptBrowserTestObserver::AddSelf(
123 NotificationRegistrar* registrar,
124 const NotificationSource& source) {
125 registrar->Add(this, NotificationType::AUTH_NEEDED, source);
126 registrar->Add(this, NotificationType::AUTH_SUPPLIED, source);
127 registrar->Add(this, NotificationType::AUTH_CANCELLED, source);
128 }
129
130 void LoginPromptBrowserTestObserver::RemoveSelf(
131 NotificationRegistrar* registrar,
132 const NotificationSource& source) {
133 registrar->Remove(this, NotificationType::AUTH_NEEDED, source);
134 registrar->Remove(this, NotificationType::AUTH_SUPPLIED, source);
135 registrar->Remove(this, NotificationType::AUTH_CANCELLED, source);
136 }
137
138 template <NotificationType::Type T>
139 class WindowedNavigationObserver
140 : public ui_test_utils::WindowedNotificationObserver {
141 public:
142 explicit WindowedNavigationObserver(NavigationController* controller)
143 : ui_test_utils::WindowedNotificationObserver(
144 T, Source<NavigationController>(controller)) {}
145 };
146
147 typedef WindowedNavigationObserver<NotificationType::LOAD_STOP>
148 WindowedLoadStopObserver;
149
150 typedef WindowedNavigationObserver<NotificationType::AUTH_NEEDED>
151 WindowedAuthNeededObserver;
152
153 typedef WindowedNavigationObserver<NotificationType::AUTH_CANCELLED>
154 WindowedAuthCancelledObserver;
155
156 typedef WindowedNavigationObserver<NotificationType::AUTH_SUPPLIED>
157 WindowedAuthSuppliedObserver;
158
159 // Test handling of resource that require authentication even though
cbentzel 2010/12/17 19:22:56 Nit: s/resource/resources
160 // the page they are included on doesn't. In this case we should only
161 // present the minimal number of prompts necessary for successfully
162 // displaying the page. First we check whether cancelling works as
163 // expected.
164 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) {
165 ASSERT_TRUE(test_server()->Start());
166 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
167
168 TabContentsWrapper* contents =
169 browser()->GetSelectedTabContentsWrapper();
170 ASSERT_TRUE(contents != NULL);
cbentzel 2010/12/17 19:22:56 ASSERT_TRUE(contents) is sufficient.
171
172 NavigationController* controller = &contents->controller();
173 LoginPromptBrowserTestObserver observer;
174
175 observer.AddSelf(&registrar_, Source<NavigationController>(controller));
176
177 WindowedLoadStopObserver load_stop_waiter(controller);
cbentzel 2010/12/17 19:22:56 Does the OpenURL trigger LOAD_STOP on the first au
asanka (google) 2010/12/17 21:35:35 LOAD_STOP is received after the page is done loadi
178
179 {
cbentzel 2010/12/17 19:22:56 It doesn't seem like scoping the WindowedAuthNeede
asanka (google) 2010/12/17 21:35:35 I expect the behavior to be identical if the Windo
180 WindowedAuthNeededObserver auth_needed_waiter(controller);
181 browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
182 auth_needed_waiter.Wait();
183 }
184
185 int n_handlers = 0;
186
187 while (observer.n_auth_cancelled < 4) {
cbentzel 2010/12/17 19:22:56 You should make 4 a constant so it's clear what it
188 WindowedAuthNeededObserver auth_needed_waiter(controller);
189
190 while (!observer.handlers_.empty()) {
191 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
192 LoginHandler * handler = *observer.handlers_.begin();
cbentzel 2010/12/17 19:22:56 Nit: LoginHandler* handler
193
194 ASSERT_TRUE(handler != NULL);
cbentzel 2010/12/17 19:22:56 Nit: ASSERT_TRUE(handler);
195 n_handlers++;
196 handler->CancelAuth();
197 auth_cancelled_waiter.Wait();
198 }
199
200 if (observer.n_auth_cancelled < 4)
201 auth_needed_waiter.Wait();
202 }
203
204 load_stop_waiter.Wait();
205
206 EXPECT_EQ(2, n_handlers);
cbentzel 2010/12/17 19:22:56 Add a constant for 2 and indicate that there are o
207 EXPECT_EQ(4, observer.n_auth_needed);
208 EXPECT_EQ(0, observer.n_auth_supplied);
209 EXPECT_EQ(4, observer.n_auth_cancelled);
210
211 observer.RemoveSelf(&registrar_, Source<NavigationController>(controller));
cbentzel 2010/12/17 19:22:56 Should this be done in the destructor for LoginPro
212 }
213
214 // Similar to the MultipleRealmCancellation test above, but tests
215 // whether supplying credentials work as exepcted.
216 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmConfirmation) {
217 ASSERT_TRUE(test_server()->Start());
218 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
219
220 TabContentsWrapper* contents =
221 browser()->GetSelectedTabContentsWrapper();
222 ASSERT_TRUE(contents != NULL);
223
224 NavigationController* controller = &contents->controller();
225 LoginPromptBrowserTestObserver observer;
226
227 observer.AddSelf(&registrar_, Source<NavigationController>(controller));
228
229 WindowedLoadStopObserver load_stop_waiter(controller);
230 int n_handlers = 0;
231
232 {
233 WindowedAuthNeededObserver auth_needed_waiter(controller);
234
235 browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
236 auth_needed_waiter.Wait();
237 }
238
239 while (observer.n_auth_supplied < 4) {
240 WindowedAuthNeededObserver auth_needed_waiter(controller);
241
242 while (!observer.handlers_.empty()) {
243 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
244 LoginHandler * handler = *observer.handlers_.begin();
245
246 ASSERT_TRUE(handler != NULL);
247 n_handlers++;
248 SetAuthFor(handler);
249 auth_supplied_waiter.Wait();
250 }
251
252 if (observer.n_auth_supplied < 4)
253 auth_needed_waiter.Wait();
254 }
255
256 load_stop_waiter.Wait();
257
258 EXPECT_EQ(2, n_handlers);
259 EXPECT_EQ(4, observer.n_auth_needed);
260 EXPECT_EQ(4, observer.n_auth_supplied);
261 EXPECT_EQ(0, observer.n_auth_cancelled);
262
263 observer.RemoveSelf(&registrar_, Source<NavigationController>(controller));
264 }
265
266 // Testing for recovery from an incorrect password for the case where
267 // there are multiple authenticated resources.
268 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, IncorrectConfirmation) {
269 ASSERT_TRUE(test_server()->Start());
270 GURL test_page = test_server()->GetURL(kSingleRealmTestPage);
271
272 TabContentsWrapper* contents =
273 browser()->GetSelectedTabContentsWrapper();
274 ASSERT_TRUE(contents != NULL);
275
276 NavigationController* controller = &contents->controller();
277 LoginPromptBrowserTestObserver observer;
278
279 observer.AddSelf(&registrar_, Source<NavigationController>(controller));
280
281 WindowedLoadStopObserver load_stop_waiter(controller);
282
283 {
284 WindowedAuthNeededObserver auth_needed_waiter(controller);
285 browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
286 auth_needed_waiter.Wait();
287 }
288
289 EXPECT_FALSE(observer.handlers_.empty());
290
291 if (!observer.handlers_.empty()) {
292 WindowedAuthNeededObserver auth_needed_waiter(controller);
293 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
294 LoginHandler * handler = *observer.handlers_.begin();
295
296 ASSERT_TRUE(handler != NULL);
297 handler->SetAuth(bad_username_, bad_password_);
298 auth_supplied_waiter.Wait();
299
300 // The request should be retried after the incorrect password is
301 // supplied. This should result in a new AUTH_NEEDED notification
302 // for the same realm.
303 auth_needed_waiter.Wait();
304 }
305
306 int n_handlers = 0;
307
308 while (observer.n_auth_supplied < 12) {
309 WindowedAuthNeededObserver auth_needed_waiter(controller);
310
311 while (!observer.handlers_.empty()) {
312 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
313 LoginHandler * handler = *observer.handlers_.begin();
314
315 ASSERT_TRUE(handler != NULL);
316 n_handlers++;
317 SetAuthFor(handler);
318 auth_supplied_waiter.Wait();
319 }
320
321 if (observer.n_auth_supplied < 12)
322 auth_needed_waiter.Wait();
323 }
324
325 load_stop_waiter.Wait();
326
327 // n_auth_needed and n_auth_supplied are twice the number of
328 // resources since the incorrect password attempt should have
329 // resulted in a retry for the whole page.
330 EXPECT_EQ(1, n_handlers);
331 EXPECT_EQ(12, observer.n_auth_needed);
332 EXPECT_EQ(12, observer.n_auth_supplied);
333 EXPECT_EQ(0, observer.n_auth_cancelled);
334
335 observer.RemoveSelf(&registrar_, Source<NavigationController>(controller));
336 }
337 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698