| 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 "base/scoped_ptr.h" | |
| 6 #include "base/scoped_temp_dir.h" | |
| 7 #include "base/test/test_file_util.h" | |
| 8 #include "base/waitable_event.h" | |
| 9 #include "chrome/browser/password_manager/encryptor.h" | |
| 10 #include "chrome/browser/sync/engine/auth_watcher.h" | |
| 11 #include "chrome/browser/sync/engine/syncer_thread.h" | |
| 12 #include "chrome/browser/sync/util/user_settings.h" | |
| 13 #include "chrome/common/deprecated/event_sys-inl.h" | |
| 14 #include "chrome/common/net/http_return.h" | |
| 15 #include "chrome/common/net/gaia/gaia_authenticator.h" | |
| 16 #include "chrome/test/sync/engine/mock_connection_manager.h" | |
| 17 #include "chrome/test/sync/engine/test_directory_setter_upper.h" | |
| 18 #include "testing/gtest/include/gtest/gtest.h" | |
| 19 | |
| 20 static FilePath::CharType kUserSettingsDB[] = | |
| 21 FILE_PATH_LITERAL("Settings.sqlite3"); | |
| 22 static const char* kTestUserAgent = "useragent"; | |
| 23 static const char* kTestServiceId = "serviceid"; | |
| 24 static const char* kTestGaiaURL = "http://gaia_url"; | |
| 25 static const char* kUserDisplayName = "Mr. Auth Watcher"; | |
| 26 static const char* kUserDisplayEmail = "authwatcherdisplay@gmail.com"; | |
| 27 static const char* kTestEmail = "authwatchertest@gmail.com"; | |
| 28 static const char* kWrongPassword = "wrongpassword"; | |
| 29 static const char* kCorrectPassword = "correctpassword"; | |
| 30 static const char* kValidSID = "validSID"; | |
| 31 static const char* kValidLSID = "validLSID"; | |
| 32 static const char* kInvalidAuthToken = "invalidAuthToken"; | |
| 33 static const char* kValidAuthToken = "validAuthToken"; | |
| 34 | |
| 35 namespace browser_sync { | |
| 36 | |
| 37 class GaiaAuthMockForAuthWatcher : public gaia::GaiaAuthenticator { | |
| 38 public: | |
| 39 GaiaAuthMockForAuthWatcher() : GaiaAuthenticator( | |
| 40 kTestUserAgent, kTestServiceId, kTestGaiaURL), | |
| 41 use_bad_auth_token_(false) {} | |
| 42 virtual ~GaiaAuthMockForAuthWatcher() {} | |
| 43 | |
| 44 virtual int GetBackoffDelaySeconds( | |
| 45 int current_backoff_delay) { | |
| 46 return SyncerThread::GetRecommendedDelaySeconds(current_backoff_delay); | |
| 47 } | |
| 48 | |
| 49 void SendBadAuthTokenForNextRequest() { use_bad_auth_token_ = true; } | |
| 50 | |
| 51 std::string renewed_token() { | |
| 52 return renewed_token_; | |
| 53 } | |
| 54 | |
| 55 protected: | |
| 56 bool PerformGaiaRequest(const AuthParams& params, AuthResults* results) { | |
| 57 if (params.password == kWrongPassword) { | |
| 58 results->auth_error = gaia::BadAuthentication; | |
| 59 return false; | |
| 60 } | |
| 61 if (params.password == kCorrectPassword) { | |
| 62 results->sid = kValidSID; | |
| 63 results->lsid = kValidLSID; | |
| 64 results->auth_token = kValidAuthToken; | |
| 65 } | |
| 66 if (use_bad_auth_token_) { | |
| 67 results->auth_token = kInvalidAuthToken; | |
| 68 use_bad_auth_token_ = false; | |
| 69 } | |
| 70 return true; | |
| 71 } | |
| 72 | |
| 73 void RenewAuthToken(const std::string& auth_token) { | |
| 74 renewed_token_ = auth_token; | |
| 75 } | |
| 76 | |
| 77 private: | |
| 78 // Whether we should send an invalid auth token on the next request. | |
| 79 bool use_bad_auth_token_; | |
| 80 std::string renewed_token_; | |
| 81 }; | |
| 82 | |
| 83 class AuthWatcherTest : public testing::Test { | |
| 84 public: | |
| 85 AuthWatcherTest() : metadb_(kUserDisplayEmail), | |
| 86 consumer_ready(false, false), | |
| 87 event_produced(false, false), | |
| 88 last_event_reason_(AuthWatcherEvent::ILLEGAL_VALUE) {} | |
| 89 virtual void SetUp() { | |
| 90 #if defined(OS_MACOSX) | |
| 91 // Need to mock the Keychain for unit tests on Mac to avoid possible | |
| 92 // blocking UI. |SetAuthTokenForService| uses Encryptor. | |
| 93 Encryptor::UseMockKeychain(true); | |
| 94 #endif | |
| 95 metadb_.SetUp(); | |
| 96 connection_.reset(new MockConnectionManager(metadb_.manager(), | |
| 97 metadb_.name())); | |
| 98 // Mock out data that would normally be sent back from a server. | |
| 99 connection()->SetAuthenticationResponseInfo(kValidAuthToken, | |
| 100 kUserDisplayName, kUserDisplayEmail, "ID"); | |
| 101 user_settings_.reset(new UserSettings()); | |
| 102 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
| 103 FilePath user_settings_path = temp_dir_.path().Append(kUserSettingsDB); | |
| 104 user_settings_->Init(user_settings_path); | |
| 105 gaia_auth_ = new GaiaAuthMockForAuthWatcher(); | |
| 106 auth_watcher_ = new AuthWatcher(metadb_.manager(), connection_.get(), | |
| 107 kTestUserAgent, kTestServiceId, kTestGaiaURL, | |
| 108 user_settings_.get(), gaia_auth_); | |
| 109 authwatcher_hookup_.reset(NewEventListenerHookup(auth_watcher_->channel(), | |
| 110 this, &AuthWatcherTest::HandleAuthWatcherEvent)); | |
| 111 } | |
| 112 | |
| 113 virtual void TearDown() { | |
| 114 metadb_.TearDown(); | |
| 115 auth_watcher_->Shutdown(); | |
| 116 EXPECT_FALSE(auth_watcher()->message_loop()); | |
| 117 } | |
| 118 | |
| 119 void HandleAuthWatcherEvent(const AuthWatcherEvent& event) { | |
| 120 if (event.what_happened == AuthWatcherEvent::AUTHWATCHER_DESTROYED) | |
| 121 return; | |
| 122 consumer_ready.Wait(); // Block progress until the test is ready. | |
| 123 | |
| 124 last_event_reason_ = event.what_happened; | |
| 125 if (event.what_happened == AuthWatcherEvent::AUTH_SUCCEEDED) | |
| 126 user_email_ = event.user_email; | |
| 127 | |
| 128 event_produced.Signal(); | |
| 129 } | |
| 130 | |
| 131 AuthWatcherEvent::WhatHappened ConsumeNextEvent() { | |
| 132 consumer_ready.Signal(); | |
| 133 event_produced.Wait(); | |
| 134 return last_event_reason_; | |
| 135 } | |
| 136 | |
| 137 AuthWatcher* auth_watcher() { return auth_watcher_.get(); } | |
| 138 MockConnectionManager* connection() { return connection_.get(); } | |
| 139 GaiaAuthMockForAuthWatcher* gaia_auth() { return gaia_auth_; } | |
| 140 const std::string& user_email() { return user_email_; } | |
| 141 | |
| 142 private: | |
| 143 // Responsible for creating / deleting a temp dir containing user settings DB. | |
| 144 ScopedTempDir temp_dir_; | |
| 145 | |
| 146 // The event listener hookup registered for HandleAuthWatcherEvent. | |
| 147 scoped_ptr<EventListenerHookup> authwatcher_hookup_; | |
| 148 | |
| 149 // The sync engine pieces necessary to run an AuthWatcher. | |
| 150 TriggeredOpenTestDirectorySetterUpper metadb_; | |
| 151 scoped_ptr<MockConnectionManager> connection_; | |
| 152 scoped_ptr<UserSettings> user_settings_; | |
| 153 GaiaAuthMockForAuthWatcher* gaia_auth_; // Owned by auth_watcher_. | |
| 154 scoped_refptr<AuthWatcher> auth_watcher_; | |
| 155 | |
| 156 // This is used to block the AuthWatcherThread when it raises events until we | |
| 157 // are ready to read the event. It is not a manual-reset event, so it goes | |
| 158 // straight back to non-signaled after one thread (the main thread) is | |
| 159 // signaled (or "consumes" the signaled state). | |
| 160 base::WaitableEvent consumer_ready; | |
| 161 | |
| 162 // This is signaled by the AuthWatcherThread after it sets last_event_reason_ | |
| 163 // and possibly user_email_ for us to read. | |
| 164 base::WaitableEvent event_produced; | |
| 165 | |
| 166 // The 'WhatHappened' value from the last AuthWatcherEvent we handled. | |
| 167 AuthWatcherEvent::WhatHappened last_event_reason_; | |
| 168 | |
| 169 // Set when we receive an AUTH_SUCCEEDED event. | |
| 170 std::string user_email_; | |
| 171 | |
| 172 DISALLOW_COPY_AND_ASSIGN(AuthWatcherTest); | |
| 173 }; | |
| 174 | |
| 175 TEST_F(AuthWatcherTest, Construction) { | |
| 176 EXPECT_TRUE(auth_watcher()->message_loop()); | |
| 177 EXPECT_EQ("SyncEngine_AuthWatcherThread", | |
| 178 auth_watcher()->message_loop()->thread_name()); | |
| 179 EXPECT_TRUE(auth_watcher()->auth_backend_thread_.IsRunning()); | |
| 180 EXPECT_EQ(AuthWatcher::NOT_AUTHENTICATED, auth_watcher()->status()); | |
| 181 } | |
| 182 | |
| 183 TEST_F(AuthWatcherTest, AuthenticateGaiaAuthFailure) { | |
| 184 auth_watcher()->Authenticate(kTestEmail, kWrongPassword, | |
| 185 std::string(), // captcha_token | |
| 186 std::string()); // captcha_value | |
| 187 | |
| 188 EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent()); | |
| 189 EXPECT_EQ(AuthWatcherEvent::GAIA_AUTH_FAILED, ConsumeNextEvent()); | |
| 190 } | |
| 191 | |
| 192 TEST_F(AuthWatcherTest, AuthenticateBadAuthToken) { | |
| 193 gaia_auth()->SendBadAuthTokenForNextRequest(); | |
| 194 auth_watcher()->Authenticate(kTestEmail, kCorrectPassword, std::string(), | |
| 195 std::string()); | |
| 196 EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent()); | |
| 197 EXPECT_EQ(AuthWatcherEvent::SERVICE_AUTH_FAILED, ConsumeNextEvent()); | |
| 198 } | |
| 199 | |
| 200 TEST_F(AuthWatcherTest, AuthenticateSuccess) { | |
| 201 auth_watcher()->Authenticate(kTestEmail, kCorrectPassword, std::string(), | |
| 202 std::string()); | |
| 203 EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent()); | |
| 204 EXPECT_EQ(AuthWatcherEvent::AUTH_SUCCEEDED, ConsumeNextEvent()); | |
| 205 | |
| 206 // The server responds with a different email than what we used in the call | |
| 207 // to Authenticate, and the AuthWatcher should have told us about. | |
| 208 EXPECT_EQ(kUserDisplayEmail, user_email()); | |
| 209 } | |
| 210 | |
| 211 TEST_F(AuthWatcherTest, AuthenticateWithTokenBadAuthToken) { | |
| 212 auth_watcher()->AuthenticateWithToken(kTestEmail, kInvalidAuthToken); | |
| 213 EXPECT_EQ(AuthWatcherEvent::SERVICE_AUTH_FAILED, ConsumeNextEvent()); | |
| 214 } | |
| 215 | |
| 216 TEST_F(AuthWatcherTest, AuthenticateWithTokenSuccess) { | |
| 217 auth_watcher()->AuthenticateWithToken(kTestEmail, kValidAuthToken); | |
| 218 EXPECT_EQ(AuthWatcherEvent::AUTH_SUCCEEDED, ConsumeNextEvent()); | |
| 219 EXPECT_EQ(kUserDisplayEmail, user_email()); | |
| 220 } | |
| 221 | |
| 222 // Just check that the thread task was properly issued. | |
| 223 TEST_F(AuthWatcherTest, RenewAuthToken) { | |
| 224 auth_watcher()->Authenticate(kTestEmail, kCorrectPassword, std::string(), | |
| 225 std::string()); | |
| 226 EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent()); | |
| 227 EXPECT_EQ(AuthWatcherEvent::AUTH_SUCCEEDED, ConsumeNextEvent()); | |
| 228 | |
| 229 auth_watcher()->RenewAuthToken("updated_token"); | |
| 230 EXPECT_EQ(AuthWatcherEvent::AUTH_RENEWED, ConsumeNextEvent()); | |
| 231 EXPECT_EQ(gaia_auth()->renewed_token(), "updated_token"); | |
| 232 EXPECT_EQ(connection()->auth_token(), "updated_token"); | |
| 233 } | |
| 234 | |
| 235 } // namespace browser_sync | |
| OLD | NEW |