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

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 const and fix braces Created 9 years, 11 months 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
« no previous file with comments | « chrome/browser/ui/login/login_prompt.cc ('k') | chrome/chrome_tests.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 <algorithm>
6 #include <list>
7 #include <map>
8
9 #include "chrome/browser/browser_thread.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/login/login_prompt.h"
12 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
13 #include "chrome/common/notification_service.h"
14 #include "chrome/test/in_process_browser_test.h"
15 #include "chrome/test/ui_test_utils.h"
16 #include "net/base/auth.h"
17
18 namespace {
19
20 class LoginPromptBrowserTest : public InProcessBrowserTest {
21 public:
22 LoginPromptBrowserTest()
23 : bad_password_(L"incorrect"), bad_username_(L"nouser") {
24 set_show_window(true);
25
26 auth_map_[L"foo"] = AuthInfo(L"testuser", L"foopassword");
27 auth_map_[L"bar"] = AuthInfo(L"testuser", L"barpassword");
28 }
29
30 protected:
31 void SetAuthFor(LoginHandler* handler);
32
33 struct AuthInfo {
34 std::wstring username_;
35 std::wstring password_;
36
37 AuthInfo() {}
38
39 AuthInfo(const std::wstring username,
40 const std::wstring password)
41 : username_(username), password_(password) {}
42 };
43
44 std::map<std::wstring, AuthInfo> auth_map_;
45 std::wstring bad_password_;
46 std::wstring bad_username_;
47 };
48
49 void LoginPromptBrowserTest::SetAuthFor(LoginHandler* handler) {
50 const net::AuthChallengeInfo* challenge = handler->auth_info();
51
52 ASSERT_TRUE(challenge);
53 std::map<std::wstring, AuthInfo>::iterator i =
54 auth_map_.find(challenge->realm);
55 EXPECT_TRUE(auth_map_.end() != i);
56 if (i != auth_map_.end()) {
57 const AuthInfo& info = i->second;
58 handler->SetAuth(info.username_, info.password_);
59 }
60 }
61
62 // Maintains a set of LoginHandlers that are currently active and
63 // keeps a count of the notifications that were observed.
64 class LoginPromptBrowserTestObserver : public NotificationObserver {
65 public:
66 LoginPromptBrowserTestObserver()
67 : auth_needed_count_(0),
68 auth_supplied_count_(0),
69 auth_cancelled_count_(0) {}
70
71 virtual void Observe(NotificationType type,
72 const NotificationSource& source,
73 const NotificationDetails& details);
74
75 void AddHandler(LoginHandler* handler);
76
77 void RemoveHandler(LoginHandler* handler);
78
79 void Register(const NotificationSource& source);
80
81 std::list<LoginHandler*> handlers_;
82
83 // The exact number of notifications we receive is depedent on the
84 // number of requests that were dispatched and is subject to a
85 // number of factors that we don't directly control here. The
86 // values below should only be used qualitatively.
87 int auth_needed_count_;
88 int auth_supplied_count_;
89 int auth_cancelled_count_;
90
91 private:
92 NotificationRegistrar registrar_;
93
94 DISALLOW_COPY_AND_ASSIGN(LoginPromptBrowserTestObserver);
95 };
96
97 void LoginPromptBrowserTestObserver::Observe(
98 NotificationType type,
99 const NotificationSource& source,
100 const NotificationDetails& details) {
101 if (type == NotificationType::AUTH_NEEDED) {
102 LoginNotificationDetails* login_details =
103 Details<LoginNotificationDetails>(details).ptr();
104 AddHandler(login_details->handler());
105 auth_needed_count_++;
106 } else if (type == NotificationType::AUTH_SUPPLIED) {
107 AuthSuppliedLoginNotificationDetails* login_details =
108 Details<AuthSuppliedLoginNotificationDetails>(details).ptr();
109 RemoveHandler(login_details->handler());
110 auth_supplied_count_++;
111 } else if (type == NotificationType::AUTH_CANCELLED) {
112 LoginNotificationDetails* login_details =
113 Details<LoginNotificationDetails>(details).ptr();
114 RemoveHandler(login_details->handler());
115 auth_cancelled_count_++;
116 }
117 }
118
119 void LoginPromptBrowserTestObserver::AddHandler(LoginHandler* handler) {
120 std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
121 handlers_.end(),
122 handler);
123 EXPECT_TRUE(i == handlers_.end());
124 if (i == handlers_.end())
125 handlers_.push_back(handler);
126 }
127
128 void LoginPromptBrowserTestObserver::RemoveHandler(LoginHandler* handler) {
129 std::list<LoginHandler*>::iterator i = std::find(handlers_.begin(),
130 handlers_.end(),
131 handler);
132 EXPECT_TRUE(i != handlers_.end());
133 if (i != handlers_.end())
134 handlers_.erase(i);
135 }
136
137 void LoginPromptBrowserTestObserver::Register(
138 const NotificationSource& source) {
139 registrar_.Add(this, NotificationType::AUTH_NEEDED, source);
140 registrar_.Add(this, NotificationType::AUTH_SUPPLIED, source);
141 registrar_.Add(this, NotificationType::AUTH_CANCELLED, source);
142 }
143
144 template <NotificationType::Type T>
145 class WindowedNavigationObserver
146 : public ui_test_utils::WindowedNotificationObserver {
147 public:
148 explicit WindowedNavigationObserver(NavigationController* controller)
149 : ui_test_utils::WindowedNotificationObserver(
150 T, Source<NavigationController>(controller)) {}
151 };
152
153 typedef WindowedNavigationObserver<NotificationType::LOAD_STOP>
154 WindowedLoadStopObserver;
155
156 typedef WindowedNavigationObserver<NotificationType::AUTH_NEEDED>
157 WindowedAuthNeededObserver;
158
159 typedef WindowedNavigationObserver<NotificationType::AUTH_CANCELLED>
160 WindowedAuthCancelledObserver;
161
162 typedef WindowedNavigationObserver<NotificationType::AUTH_SUPPLIED>
163 WindowedAuthSuppliedObserver;
164
165 const char* kMultiRealmTestPage = "files/login/multi_realm.html";
166 const int kMultiRealmTestRealmCount = 2;
167 const int kMultiRealmTestResourceCount = 4;
168
169 const char* kSingleRealmTestPage = "files/login/single_realm.html";
170 const int kSingleRealmTestResourceCount = 6;
171
172 // Test handling of resources that require authentication even though
173 // the page they are included on doesn't. In this case we should only
174 // present the minimal number of prompts necessary for successfully
175 // displaying the page. First we check whether cancelling works as
176 // expected.
177 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmCancellation) {
178 ASSERT_TRUE(test_server()->Start());
179 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
180
181 TabContentsWrapper* contents =
182 browser()->GetSelectedTabContentsWrapper();
183 ASSERT_TRUE(contents);
184
185 NavigationController* controller = &contents->controller();
186 LoginPromptBrowserTestObserver observer;
187
188 observer.Register(Source<NavigationController>(controller));
189
190 WindowedLoadStopObserver load_stop_waiter(controller);
191
192 {
193 WindowedAuthNeededObserver auth_needed_waiter(controller);
194 browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
195 auth_needed_waiter.Wait();
196 }
197
198 int n_handlers = 0;
199
200 while (n_handlers < kMultiRealmTestRealmCount) {
201 WindowedAuthNeededObserver auth_needed_waiter(controller);
202
203 while (!observer.handlers_.empty()) {
204 WindowedAuthCancelledObserver auth_cancelled_waiter(controller);
205 LoginHandler* handler = *observer.handlers_.begin();
206
207 ASSERT_TRUE(handler);
208 n_handlers++;
209 handler->CancelAuth();
210 auth_cancelled_waiter.Wait();
211 }
212
213 if (n_handlers < kMultiRealmTestRealmCount)
214 auth_needed_waiter.Wait();
215 }
216
217 load_stop_waiter.Wait();
218
219 EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
220 EXPECT_EQ(0, observer.auth_supplied_count_);
221 EXPECT_LT(0, observer.auth_needed_count_);
222 EXPECT_LT(0, observer.auth_cancelled_count_);
223 EXPECT_TRUE(test_server()->Stop());
224 }
225
226 // Similar to the MultipleRealmCancellation test above, but tests
227 // whether supplying credentials work as exepcted.
228 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, MultipleRealmConfirmation) {
229 ASSERT_TRUE(test_server()->Start());
230 GURL test_page = test_server()->GetURL(kMultiRealmTestPage);
231
232 TabContentsWrapper* contents =
233 browser()->GetSelectedTabContentsWrapper();
234 ASSERT_TRUE(contents);
235
236 NavigationController* controller = &contents->controller();
237 LoginPromptBrowserTestObserver observer;
238
239 observer.Register(Source<NavigationController>(controller));
240
241 WindowedLoadStopObserver load_stop_waiter(controller);
242 int n_handlers = 0;
243
244 {
245 WindowedAuthNeededObserver auth_needed_waiter(controller);
246
247 browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
248 auth_needed_waiter.Wait();
249 }
250
251 while (n_handlers < kMultiRealmTestRealmCount) {
252 WindowedAuthNeededObserver auth_needed_waiter(controller);
253
254 while (!observer.handlers_.empty()) {
255 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
256 LoginHandler* handler = *observer.handlers_.begin();
257
258 ASSERT_TRUE(handler);
259 n_handlers++;
260 SetAuthFor(handler);
261 auth_supplied_waiter.Wait();
262 }
263
264 if (n_handlers < kMultiRealmTestRealmCount)
265 auth_needed_waiter.Wait();
266 }
267
268 load_stop_waiter.Wait();
269
270 EXPECT_EQ(kMultiRealmTestRealmCount, n_handlers);
271 EXPECT_LT(0, observer.auth_needed_count_);
272 EXPECT_LT(0, observer.auth_supplied_count_);
273 EXPECT_EQ(0, observer.auth_cancelled_count_);
274 EXPECT_TRUE(test_server()->Stop());
275 }
276
277 // Testing for recovery from an incorrect password for the case where
278 // there are multiple authenticated resources.
279 IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, IncorrectConfirmation) {
280 ASSERT_TRUE(test_server()->Start());
281 GURL test_page = test_server()->GetURL(kSingleRealmTestPage);
282
283 TabContentsWrapper* contents =
284 browser()->GetSelectedTabContentsWrapper();
285 ASSERT_TRUE(contents);
286
287 NavigationController* controller = &contents->controller();
288 LoginPromptBrowserTestObserver observer;
289
290 observer.Register(Source<NavigationController>(controller));
291
292 WindowedLoadStopObserver load_stop_waiter(controller);
293
294 {
295 WindowedAuthNeededObserver auth_needed_waiter(controller);
296 browser()->OpenURL(test_page, GURL(), CURRENT_TAB, PageTransition::TYPED);
297 auth_needed_waiter.Wait();
298 }
299
300 EXPECT_FALSE(observer.handlers_.empty());
301
302 if (!observer.handlers_.empty()) {
303 WindowedAuthNeededObserver auth_needed_waiter(controller);
304 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
305 LoginHandler* handler = *observer.handlers_.begin();
306
307 ASSERT_TRUE(handler);
308 handler->SetAuth(bad_username_, bad_password_);
309 auth_supplied_waiter.Wait();
310
311 // The request should be retried after the incorrect password is
312 // supplied. This should result in a new AUTH_NEEDED notification
313 // for the same realm.
314 auth_needed_waiter.Wait();
315 }
316
317 int n_handlers = 0;
318
319 while (n_handlers < 1) {
320 WindowedAuthNeededObserver auth_needed_waiter(controller);
321
322 while (!observer.handlers_.empty()) {
323 WindowedAuthSuppliedObserver auth_supplied_waiter(controller);
324 LoginHandler* handler = *observer.handlers_.begin();
325
326 ASSERT_TRUE(handler);
327 n_handlers++;
328 SetAuthFor(handler);
329 auth_supplied_waiter.Wait();
330 }
331
332 if (n_handlers < 1)
333 auth_needed_waiter.Wait();
334 }
335
336 load_stop_waiter.Wait();
337
338 // The single realm test has only one realm, and thus only one login
339 // prompt.
340 EXPECT_EQ(1, n_handlers);
341 EXPECT_LT(0, observer.auth_needed_count_);
342 EXPECT_LT(0, observer.auth_supplied_count_);
343 EXPECT_EQ(0, observer.auth_cancelled_count_);
344 EXPECT_TRUE(test_server()->Stop());
345 }
346 } // namespace
OLDNEW
« no previous file with comments | « chrome/browser/ui/login/login_prompt.cc ('k') | chrome/chrome_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698