| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 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/bind.h" | |
| 6 #include "base/memory/scoped_ptr.h" | |
| 7 #include "base/strings/stringprintf.h" | |
| 8 #include "chrome/browser/managed_mode/managed_user_refresh_token_fetcher.h" | |
| 9 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" | |
| 10 #include "chrome/test/base/testing_profile.h" | |
| 11 #include "content/public/test/test_browser_thread_bundle.h" | |
| 12 #include "google_apis/gaia/gaia_constants.h" | |
| 13 #include "google_apis/gaia/gaia_oauth_client.h" | |
| 14 #include "google_apis/gaia/gaia_urls.h" | |
| 15 #include "google_apis/gaia/google_service_auth_error.h" | |
| 16 #include "google_apis/gaia/oauth2_token_service.h" | |
| 17 #include "net/base/net_errors.h" | |
| 18 #include "net/base/url_util.h" | |
| 19 #include "net/http/http_request_headers.h" | |
| 20 #include "net/http/http_status_code.h" | |
| 21 #include "net/url_request/test_url_fetcher_factory.h" | |
| 22 #include "net/url_request/url_fetcher_delegate.h" | |
| 23 #include "testing/gtest/include/gtest/gtest.h" | |
| 24 | |
| 25 namespace { | |
| 26 | |
| 27 const char kAccountId[] = "account_id"; | |
| 28 const char kDeviceName[] = "Compy"; | |
| 29 const char kManagedUserId[] = "abcdef"; | |
| 30 | |
| 31 const char kAccessToken[] = "accesstoken"; | |
| 32 const char kAuthorizationCode[] = "authorizationcode"; | |
| 33 const char kManagedUserToken[] = "managedusertoken"; | |
| 34 const char kOAuth2RefreshToken[] = "refreshtoken"; | |
| 35 | |
| 36 const char kIssueTokenResponseFormat[] = | |
| 37 "{" | |
| 38 " \"code\": \"%s\"" | |
| 39 "}"; | |
| 40 | |
| 41 const char kGetRefreshTokenResponseFormat[] = | |
| 42 "{" | |
| 43 " \"access_token\": \"<ignored>\"," | |
| 44 " \"expires_in\": 12345," | |
| 45 " \"refresh_token\": \"%s\"" | |
| 46 "}"; | |
| 47 | |
| 48 // Utility methods -------------------------------------------------- | |
| 49 | |
| 50 // Slightly hacky way to extract a value from a URL-encoded POST request body. | |
| 51 bool GetValueForKey(const std::string& encoded_string, | |
| 52 const std::string& key, | |
| 53 std::string* value) { | |
| 54 GURL url("http://example.com/?" + encoded_string); | |
| 55 return net::GetValueForKeyInQuery(url, key, value); | |
| 56 } | |
| 57 | |
| 58 void SendResponse(net::TestURLFetcher* url_fetcher, | |
| 59 const std::string& response) { | |
| 60 url_fetcher->set_status( | |
| 61 net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0)); | |
| 62 url_fetcher->set_response_code(net::HTTP_OK); | |
| 63 url_fetcher->SetResponseString(response); | |
| 64 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); | |
| 65 } | |
| 66 | |
| 67 void SetNetworkError(net::TestURLFetcher* url_fetcher, int error) { | |
| 68 url_fetcher->set_status( | |
| 69 net::URLRequestStatus(net::URLRequestStatus::FAILED, error)); | |
| 70 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); | |
| 71 } | |
| 72 | |
| 73 void SetHttpError(net::TestURLFetcher* url_fetcher, int error) { | |
| 74 url_fetcher->set_status(net::URLRequestStatus()); | |
| 75 url_fetcher->set_response_code(error); | |
| 76 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); | |
| 77 } | |
| 78 | |
| 79 void VerifyTokenRequest( | |
| 80 std::vector<FakeProfileOAuth2TokenService::PendingRequest> requests) { | |
| 81 ASSERT_EQ(1u, requests.size()); | |
| 82 EXPECT_EQ(1u, requests[0].scopes.size()); | |
| 83 EXPECT_EQ(1u, requests[0].scopes.count(GaiaConstants::kOAuth1LoginScope)); | |
| 84 } | |
| 85 | |
| 86 } // namespace | |
| 87 | |
| 88 class ManagedUserRefreshTokenFetcherTest : public testing::Test { | |
| 89 public: | |
| 90 ManagedUserRefreshTokenFetcherTest(); | |
| 91 virtual ~ManagedUserRefreshTokenFetcherTest() {} | |
| 92 | |
| 93 protected: | |
| 94 void StartFetching(); | |
| 95 | |
| 96 net::TestURLFetcher* GetIssueTokenRequest(); | |
| 97 net::TestURLFetcher* GetRefreshTokenRequest(); | |
| 98 | |
| 99 void MakeOAuth2TokenServiceRequestSucceed(); | |
| 100 void MakeOAuth2TokenServiceRequestFail(GoogleServiceAuthError::State error); | |
| 101 void MakeIssueTokenRequestSucceed(); | |
| 102 void MakeRefreshTokenFetchSucceed(); | |
| 103 | |
| 104 void Reset(); | |
| 105 | |
| 106 const GoogleServiceAuthError& error() const { return error_; } | |
| 107 const std::string& token() const { return token_; } | |
| 108 | |
| 109 private: | |
| 110 void OnTokenFetched(const GoogleServiceAuthError& error, | |
| 111 const std::string& token); | |
| 112 | |
| 113 content::TestBrowserThreadBundle thread_bundle_; | |
| 114 TestingProfile profile_; | |
| 115 FakeProfileOAuth2TokenService oauth2_token_service_; | |
| 116 net::TestURLFetcherFactory url_fetcher_factory_; | |
| 117 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher_; | |
| 118 | |
| 119 GoogleServiceAuthError error_; | |
| 120 std::string token_; | |
| 121 base::WeakPtrFactory<ManagedUserRefreshTokenFetcherTest> weak_ptr_factory_; | |
| 122 }; | |
| 123 | |
| 124 ManagedUserRefreshTokenFetcherTest::ManagedUserRefreshTokenFetcherTest() | |
| 125 : token_fetcher_( | |
| 126 ManagedUserRefreshTokenFetcher::Create(&oauth2_token_service_, | |
| 127 kAccountId, | |
| 128 profile_.GetRequestContext())), | |
| 129 error_(GoogleServiceAuthError::NONE), | |
| 130 weak_ptr_factory_(this) {} | |
| 131 | |
| 132 void ManagedUserRefreshTokenFetcherTest::StartFetching() { | |
| 133 oauth2_token_service_.IssueRefreshToken(kOAuth2RefreshToken); | |
| 134 token_fetcher_->Start(kManagedUserId, kDeviceName, | |
| 135 base::Bind( | |
| 136 &ManagedUserRefreshTokenFetcherTest::OnTokenFetched, | |
| 137 weak_ptr_factory_.GetWeakPtr())); | |
| 138 } | |
| 139 | |
| 140 net::TestURLFetcher* | |
| 141 ManagedUserRefreshTokenFetcherTest::GetIssueTokenRequest() { | |
| 142 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(1); | |
| 143 if (!url_fetcher) | |
| 144 return NULL; | |
| 145 | |
| 146 EXPECT_EQ(GaiaUrls::GetInstance()->oauth2_issue_token_url(), | |
| 147 url_fetcher->GetOriginalURL()); | |
| 148 std::string access_token; | |
| 149 net::HttpRequestHeaders headers; | |
| 150 url_fetcher->GetExtraRequestHeaders(&headers); | |
| 151 EXPECT_TRUE(headers.GetHeader("Authorization", &access_token)); | |
| 152 EXPECT_EQ(std::string("Bearer ") + kAccessToken, access_token); | |
| 153 const std::string upload_data = url_fetcher->upload_data(); | |
| 154 std::string managed_user_id; | |
| 155 EXPECT_TRUE(GetValueForKey(upload_data, "profile_id", &managed_user_id)); | |
| 156 EXPECT_EQ(kManagedUserId, managed_user_id); | |
| 157 std::string device_name; | |
| 158 EXPECT_TRUE(GetValueForKey(upload_data, "device_name", &device_name)); | |
| 159 EXPECT_EQ(kDeviceName, device_name); | |
| 160 return url_fetcher; | |
| 161 } | |
| 162 | |
| 163 net::TestURLFetcher* | |
| 164 ManagedUserRefreshTokenFetcherTest::GetRefreshTokenRequest() { | |
| 165 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID( | |
| 166 gaia::GaiaOAuthClient::kUrlFetcherId); | |
| 167 if (!url_fetcher) | |
| 168 return NULL; | |
| 169 | |
| 170 EXPECT_EQ(GaiaUrls::GetInstance()->oauth2_token_url(), | |
| 171 url_fetcher->GetOriginalURL()); | |
| 172 std::string auth_code; | |
| 173 EXPECT_TRUE(GetValueForKey(url_fetcher->upload_data(), "code", &auth_code)); | |
| 174 EXPECT_EQ(kAuthorizationCode, auth_code); | |
| 175 return url_fetcher; | |
| 176 } | |
| 177 | |
| 178 void | |
| 179 ManagedUserRefreshTokenFetcherTest::MakeOAuth2TokenServiceRequestSucceed() { | |
| 180 std::vector<FakeProfileOAuth2TokenService::PendingRequest> requests = | |
| 181 oauth2_token_service_.GetPendingRequests(); | |
| 182 VerifyTokenRequest(requests); | |
| 183 base::Time expiration_date = base::Time::Now() + | |
| 184 base::TimeDelta::FromHours(1); | |
| 185 oauth2_token_service_.IssueTokenForScope(requests[0].scopes, | |
| 186 kAccessToken, | |
| 187 expiration_date); | |
| 188 } | |
| 189 | |
| 190 void | |
| 191 ManagedUserRefreshTokenFetcherTest::MakeOAuth2TokenServiceRequestFail( | |
| 192 GoogleServiceAuthError::State error) { | |
| 193 std::vector<FakeProfileOAuth2TokenService::PendingRequest> requests = | |
| 194 oauth2_token_service_.GetPendingRequests(); | |
| 195 VerifyTokenRequest(requests); | |
| 196 oauth2_token_service_.IssueErrorForScope(requests[0].scopes, | |
| 197 GoogleServiceAuthError(error)); | |
| 198 } | |
| 199 | |
| 200 void ManagedUserRefreshTokenFetcherTest::MakeIssueTokenRequestSucceed() { | |
| 201 SendResponse(GetIssueTokenRequest(), | |
| 202 base::StringPrintf(kIssueTokenResponseFormat, | |
| 203 kAuthorizationCode)); | |
| 204 } | |
| 205 | |
| 206 void ManagedUserRefreshTokenFetcherTest::MakeRefreshTokenFetchSucceed() { | |
| 207 SendResponse(GetRefreshTokenRequest(), | |
| 208 base::StringPrintf(kGetRefreshTokenResponseFormat, | |
| 209 kManagedUserToken)); | |
| 210 } | |
| 211 | |
| 212 void ManagedUserRefreshTokenFetcherTest::Reset() { | |
| 213 token_fetcher_.reset(); | |
| 214 } | |
| 215 | |
| 216 void ManagedUserRefreshTokenFetcherTest::OnTokenFetched( | |
| 217 const GoogleServiceAuthError& error, | |
| 218 const std::string& token) { | |
| 219 error_ = error; | |
| 220 token_ = token; | |
| 221 } | |
| 222 | |
| 223 // Tests -------------------------------------------------------- | |
| 224 | |
| 225 TEST_F(ManagedUserRefreshTokenFetcherTest, Success) { | |
| 226 StartFetching(); | |
| 227 MakeOAuth2TokenServiceRequestSucceed(); | |
| 228 MakeIssueTokenRequestSucceed(); | |
| 229 MakeRefreshTokenFetchSucceed(); | |
| 230 | |
| 231 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); | |
| 232 EXPECT_EQ(kManagedUserToken, token()); | |
| 233 } | |
| 234 | |
| 235 TEST_F(ManagedUserRefreshTokenFetcherTest, ExpiredAccessToken) { | |
| 236 StartFetching(); | |
| 237 MakeOAuth2TokenServiceRequestSucceed(); | |
| 238 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED); | |
| 239 MakeOAuth2TokenServiceRequestSucceed(); | |
| 240 MakeIssueTokenRequestSucceed(); | |
| 241 MakeRefreshTokenFetchSucceed(); | |
| 242 | |
| 243 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); | |
| 244 EXPECT_EQ(kManagedUserToken, token()); | |
| 245 } | |
| 246 | |
| 247 TEST_F(ManagedUserRefreshTokenFetcherTest, ExpiredAccessTokenRetry) { | |
| 248 // If we get a 401 error for the second time, we should give up instead of | |
| 249 // retrying again. | |
| 250 StartFetching(); | |
| 251 MakeOAuth2TokenServiceRequestSucceed(); | |
| 252 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED); | |
| 253 MakeOAuth2TokenServiceRequestSucceed(); | |
| 254 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED); | |
| 255 | |
| 256 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); | |
| 257 EXPECT_EQ(net::ERR_FAILED, error().network_error()); | |
| 258 EXPECT_EQ(std::string(), token()); | |
| 259 } | |
| 260 | |
| 261 TEST_F(ManagedUserRefreshTokenFetcherTest, MalformedIssueTokenResponse) { | |
| 262 StartFetching(); | |
| 263 MakeOAuth2TokenServiceRequestSucceed(); | |
| 264 SendResponse(GetIssueTokenRequest(), "choke"); | |
| 265 | |
| 266 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); | |
| 267 EXPECT_EQ(net::ERR_INVALID_RESPONSE, error().network_error()); | |
| 268 EXPECT_EQ(std::string(), token()); | |
| 269 } | |
| 270 | |
| 271 TEST_F(ManagedUserRefreshTokenFetcherTest, FetchAccessTokenFailure) { | |
| 272 StartFetching(); | |
| 273 MakeOAuth2TokenServiceRequestFail( | |
| 274 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); | |
| 275 | |
| 276 EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, error().state()); | |
| 277 EXPECT_EQ(std::string(), token()); | |
| 278 } | |
| 279 | |
| 280 TEST_F(ManagedUserRefreshTokenFetcherTest, IssueTokenNetworkError) { | |
| 281 StartFetching(); | |
| 282 MakeOAuth2TokenServiceRequestSucceed(); | |
| 283 SetNetworkError(GetIssueTokenRequest(), net::ERR_SSL_PROTOCOL_ERROR); | |
| 284 | |
| 285 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); | |
| 286 EXPECT_EQ(net::ERR_SSL_PROTOCOL_ERROR, error().network_error()); | |
| 287 EXPECT_EQ(std::string(), token()); | |
| 288 } | |
| 289 | |
| 290 TEST_F(ManagedUserRefreshTokenFetcherTest, FetchRefreshTokenNetworkError) { | |
| 291 StartFetching(); | |
| 292 MakeOAuth2TokenServiceRequestSucceed(); | |
| 293 MakeIssueTokenRequestSucceed(); | |
| 294 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED); | |
| 295 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); | |
| 296 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED); | |
| 297 | |
| 298 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); | |
| 299 EXPECT_EQ(net::ERR_FAILED, error().network_error()); | |
| 300 EXPECT_EQ(std::string(), token()); | |
| 301 } | |
| 302 | |
| 303 TEST_F(ManagedUserRefreshTokenFetcherTest, | |
| 304 FetchRefreshTokenTransientNetworkError) { | |
| 305 StartFetching(); | |
| 306 MakeOAuth2TokenServiceRequestSucceed(); | |
| 307 MakeIssueTokenRequestSucceed(); | |
| 308 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED); | |
| 309 | |
| 310 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); | |
| 311 MakeRefreshTokenFetchSucceed(); | |
| 312 | |
| 313 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); | |
| 314 EXPECT_EQ(kManagedUserToken, token()); | |
| 315 } | |
| 316 | |
| 317 TEST_F(ManagedUserRefreshTokenFetcherTest, FetchRefreshTokenBadRequest) { | |
| 318 StartFetching(); | |
| 319 MakeOAuth2TokenServiceRequestSucceed(); | |
| 320 MakeIssueTokenRequestSucceed(); | |
| 321 SetHttpError(GetRefreshTokenRequest(), net::HTTP_BAD_REQUEST); | |
| 322 | |
| 323 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); | |
| 324 EXPECT_EQ(net::ERR_FAILED, error().network_error()); | |
| 325 EXPECT_EQ(std::string(), token()); | |
| 326 } | |
| 327 | |
| 328 TEST_F(ManagedUserRefreshTokenFetcherTest, CancelWhileFetchingAccessToken) { | |
| 329 StartFetching(); | |
| 330 Reset(); | |
| 331 | |
| 332 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); | |
| 333 EXPECT_EQ(std::string(), token()); | |
| 334 } | |
| 335 | |
| 336 TEST_F(ManagedUserRefreshTokenFetcherTest, CancelWhileCallingIssueToken) { | |
| 337 StartFetching(); | |
| 338 MakeOAuth2TokenServiceRequestSucceed(); | |
| 339 Reset(); | |
| 340 | |
| 341 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); | |
| 342 EXPECT_EQ(std::string(), token()); | |
| 343 } | |
| 344 | |
| 345 TEST_F(ManagedUserRefreshTokenFetcherTest, CancelWhileFetchingRefreshToken) { | |
| 346 StartFetching(); | |
| 347 MakeOAuth2TokenServiceRequestSucceed(); | |
| 348 MakeIssueTokenRequestSucceed(); | |
| 349 Reset(); | |
| 350 | |
| 351 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); | |
| 352 EXPECT_EQ(std::string(), token()); | |
| 353 } | |
| OLD | NEW |