1 // Copyright 2014 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.
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_util.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
13 #include "components/signin/core/browser/account_service_flag_fetcher.h"
14 #include "google_apis/gaia/gaia_urls.h"
15 #include "net/url_request/test_url_fetcher_factory.h"
16 #include "net/url_request/url_request_test_util.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 const char kAccountId
[] = "user@gmail.com";
21 const char kDifferentAccountId
[] = "some_other_user@gmail.com";
23 const int kGaiaAuthFetcherURLFetcherID
= 0;
25 // TODO(treib): This class should really live in components/signin/ next to the
26 // AccountServiceFlagFetcher, but it uses the FakePO2TS which lives in
27 // chrome/browser/ (because it uses the AndroidPO2TS which depends on stuff from
28 // chrome/browser/). So when the AndroidPO2TS is componentized, then this should
30 class AccountServiceFlagFetcherTest
: public testing::Test
{
32 AccountServiceFlagFetcherTest()
33 : request_context_(new net::TestURLRequestContextGetter(
34 base::ThreadTaskRunnerHandle::Get())) {
35 service_flags_
.push_back("some_flag");
36 service_flags_
.push_back("another_flag");
37 service_flags_
.push_back("andonemore");
40 MOCK_METHOD2(OnFlagsFetched
,
41 void(AccountServiceFlagFetcher::ResultCode result
,
42 const std::vector
<std::string
>& flags
));
45 net::TestURLFetcher
* GetLoginURLFetcher() {
46 net::TestURLFetcher
* fetcher
=
47 url_fetcher_factory_
.GetFetcherByID(kGaiaAuthFetcherURLFetcherID
);
50 EXPECT_EQ(GaiaUrls::GetInstance()->oauth1_login_url(),
51 fetcher
->GetOriginalURL());
56 net::TestURLFetcher
* GetGetUserInfoURLFetcher() {
57 net::TestURLFetcher
* fetcher
=
58 url_fetcher_factory_
.GetFetcherByID(kGaiaAuthFetcherURLFetcherID
);
61 EXPECT_EQ(GaiaUrls::GetInstance()->get_user_info_url(),
62 fetcher
->GetOriginalURL());
67 void SendValidLoginResponse() {
68 net::TestURLFetcher
* fetcher
= GetLoginURLFetcher();
70 net::URLRequestStatus(net::URLRequestStatus::SUCCESS
, 0));
71 fetcher
->set_response_code(net::HTTP_OK
);
72 fetcher
->SetResponseString(std::string("SID=sid\nLSID=lsid\nAuth=auth\n"));
73 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
76 void SendFailedLoginResponse() {
77 net::TestURLFetcher
* fetcher
= GetLoginURLFetcher();
79 net::URLRequestStatus(net::URLRequestStatus::CANCELED
, 0));
80 fetcher
->set_response_code(net::HTTP_OK
);
81 fetcher
->SetResponseString(std::string());
82 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
85 void SendValidGetUserInfoResponse() {
86 net::TestURLFetcher
* fetcher
= GetGetUserInfoURLFetcher();
88 net::URLRequestStatus(net::URLRequestStatus::SUCCESS
, 0));
89 fetcher
->set_response_code(net::HTTP_OK
);
90 fetcher
->SetResponseString(BuildGetUserInfoResponse());
91 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
94 void SendInvalidGetUserInfoResponse() {
95 net::TestURLFetcher
* fetcher
= GetGetUserInfoURLFetcher();
97 net::URLRequestStatus(net::URLRequestStatus::SUCCESS
, 0));
98 fetcher
->set_response_code(net::HTTP_OK
);
99 fetcher
->SetResponseString(std::string("allServicesIsMissing=true"));
100 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
103 void SendFailedGetUserInfoResponse() {
104 net::TestURLFetcher
* fetcher
= GetGetUserInfoURLFetcher();
106 net::URLRequestStatus(net::URLRequestStatus::CANCELED
, 0));
107 fetcher
->set_response_code(net::HTTP_OK
);
108 fetcher
->SetResponseString(std::string());
109 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
112 std::string
BuildGetUserInfoResponse() const {
113 return "allServices=" + JoinString(service_flags_
, ',');
116 base::MessageLoop message_loop_
;
117 FakeProfileOAuth2TokenService token_service_
;
118 scoped_refptr
<net::TestURLRequestContextGetter
> request_context_
;
119 net::TestURLFetcherFactory url_fetcher_factory_
;
120 net::ResponseCookies cookies_
;
121 std::vector
<std::string
> service_flags_
;
124 TEST_F(AccountServiceFlagFetcherTest
, Success
) {
125 token_service_
.UpdateCredentials(kAccountId
, "refresh_token");
127 AccountServiceFlagFetcher
fetcher(
130 request_context_
.get(),
131 base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched
,
132 base::Unretained(this)));
134 // Since a refresh token is already available, we should immediately get a
135 // request for an access token.
136 EXPECT_EQ(1U, token_service_
.GetPendingRequests().size());
138 token_service_
.IssueAllTokensForAccount(
141 base::Time::Now() + base::TimeDelta::FromHours(1));
143 SendValidLoginResponse();
145 EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::SUCCESS
,
147 SendValidGetUserInfoResponse();
150 TEST_F(AccountServiceFlagFetcherTest
, SuccessAfterWaitingForRefreshToken
) {
151 AccountServiceFlagFetcher
fetcher(
154 request_context_
.get(),
155 base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched
,
156 base::Unretained(this)));
158 // Since there is no refresh token yet, we should not get a request for an
159 // access token at this point.
160 EXPECT_EQ(0U, token_service_
.GetPendingRequests().size());
162 token_service_
.UpdateCredentials(kAccountId
, "refresh_token");
164 // Now there is a refresh token and we should have got a request for an
166 EXPECT_EQ(1U, token_service_
.GetPendingRequests().size());
168 token_service_
.IssueAllTokensForAccount(
171 base::Time::Now() + base::TimeDelta::FromHours(1));
173 SendValidLoginResponse();
175 EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::SUCCESS
,
177 SendValidGetUserInfoResponse();
180 TEST_F(AccountServiceFlagFetcherTest
, NoRefreshToken
) {
181 AccountServiceFlagFetcher
fetcher(
184 request_context_
.get(),
185 base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched
,
186 base::Unretained(this)));
188 token_service_
.UpdateCredentials(kDifferentAccountId
, "refresh_token");
190 // Credentials for a different user should be ignored, i.e. not result in a
191 // request for an access token.
192 EXPECT_EQ(0U, token_service_
.GetPendingRequests().size());
194 // After all refresh tokens have been loaded, there is still no token for our
195 // user, so we expect a token error.
196 EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::TOKEN_ERROR
,
197 std::vector
<std::string
>()));
198 token_service_
.IssueAllRefreshTokensLoaded();
201 TEST_F(AccountServiceFlagFetcherTest
, GetTokenFailure
) {
202 token_service_
.UpdateCredentials(kAccountId
, "refresh_token");
204 AccountServiceFlagFetcher
fetcher(
207 request_context_
.get(),
208 base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched
,
209 base::Unretained(this)));
211 // On failure to get an access token we expect a token error.
212 EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::TOKEN_ERROR
,
213 std::vector
<std::string
>()));
214 token_service_
.IssueErrorForAllPendingRequestsForAccount(
216 GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
));
219 TEST_F(AccountServiceFlagFetcherTest
, ClientLoginFailure
) {
220 token_service_
.UpdateCredentials(kAccountId
, "refresh_token");
222 AccountServiceFlagFetcher
fetcher(
225 request_context_
.get(),
226 base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched
,
227 base::Unretained(this)));
229 token_service_
.IssueAllTokensForAccount(
232 base::Time::Now() + base::TimeDelta::FromHours(1));
234 // Login failure should result in a service error.
235 EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::SERVICE_ERROR
,
236 std::vector
<std::string
>()));
237 SendFailedLoginResponse();
240 TEST_F(AccountServiceFlagFetcherTest
, GetUserInfoInvalidResponse
) {
241 token_service_
.UpdateCredentials(kAccountId
, "refresh_token");
243 AccountServiceFlagFetcher
fetcher(
246 request_context_
.get(),
247 base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched
,
248 base::Unretained(this)));
250 token_service_
.IssueAllTokensForAccount(
253 base::Time::Now() + base::TimeDelta::FromHours(1));
255 SendValidLoginResponse();
257 // Invalid response data from GetUserInfo should result in a service error.
258 EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::SERVICE_ERROR
,
259 std::vector
<std::string
>()));
260 SendInvalidGetUserInfoResponse();
263 TEST_F(AccountServiceFlagFetcherTest
, GetUserInfoFailure
) {
264 token_service_
.UpdateCredentials(kAccountId
, "refresh_token");
266 AccountServiceFlagFetcher
fetcher(
269 request_context_
.get(),
270 base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched
,
271 base::Unretained(this)));
273 token_service_
.IssueAllTokensForAccount(
276 base::Time::Now() + base::TimeDelta::FromHours(1));
278 SendValidLoginResponse();
280 // Failed GetUserInfo call should result in a service error.
281 EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::SERVICE_ERROR
,
282 std::vector
<std::string
>()));
283 SendFailedGetUserInfoResponse();
286 TEST_F(AccountServiceFlagFetcherTest
, DestroyFetcher
) {
287 token_service_
.UpdateCredentials(kAccountId
, "refresh_token");
289 // When the fetcher is destroyed before the request completes, OnFlagsFetched
290 // should not be called.
291 EXPECT_CALL(*this, OnFlagsFetched(testing::_
, testing::_
)).Times(0);
293 AccountServiceFlagFetcher
fetcher(
296 request_context_
.get(),
297 base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched
,
298 base::Unretained(this)));
300 token_service_
.IssueAllTokensForAccount(
303 base::Time::Now() + base::TimeDelta::FromHours(1));
305 SendValidLoginResponse();
306 // Do not send a GetUserInfo response, but make sure the request is there.
307 GetGetUserInfoURLFetcher();