Chromium Code Reviews| OLD | NEW |
|---|---|
| (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(®istrar_, 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(®istrar_, 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(®istrar_, 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(®istrar_, 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(®istrar_, 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(®istrar_, Source<NavigationController>(controller)); | |
| 336 } | |
| 337 } | |
| OLD | NEW |