device_oauth2_token_service_unittest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/prefs/testing_pref_service.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/signin/oauth2_token_service_test_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/scoped_testing_local_state.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_browser_process.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/cryptohome/mock_cryptohome_library.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_oauth_client.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_status_code.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/test_url_fetcher_factory.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_test_util.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AnyNumber;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Return;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::StrEq;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::StrictMock;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kOAuthTokenServiceUrlFetcherId = 0;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kValidatorUrlFetcherId = gaia::GaiaOAuthClient::kUrlFetcherId;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestDeviceOAuth2TokenService : public DeviceOAuth2TokenService {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TestDeviceOAuth2TokenService(net::URLRequestContextGetter* getter,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        PrefService* local_state)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : DeviceOAuth2TokenService(getter, local_state) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetRobotAccountIdPolicyValue(const std::string& id) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    robot_account_id_ = id;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skip calling into the policy subsystem and return our test value.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual std::string GetRobotAccountId() OVERRIDE {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return robot_account_id_;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string robot_account_id_;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestDeviceOAuth2TokenService);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DeviceOAuth2TokenServiceTest : public testing::Test {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeviceOAuth2TokenServiceTest()
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ui_thread_(content::BrowserThread::UI, &message_loop_),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        request_context_getter_(new net::TestURLRequestContextGetter(
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            message_loop_.message_loop_proxy())),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        oauth2_service_(request_context_getter_.get(),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        scoped_testing_local_state_.Get()) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    oauth2_service_.max_refresh_token_validation_retries_ = 0;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    oauth2_service_.set_max_authorization_token_fetch_retries_for_testing(0);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DeviceOAuth2TokenServiceTest() {}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Most tests just want a noop crypto impl with a dummy refresh token value in
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Local State (if the value is an empty string, it will be ignored).
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetUpDefaultValues() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cryptohome_library_.reset(chromeos::CryptohomeLibrary::GetTestImpl());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chromeos::CryptohomeLibrary::SetForTest(cryptohome_library_.get());
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetDeviceRefreshTokenInLocalState("device_refresh_token_4_test");
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    oauth2_service_.SetRobotAccountIdPolicyValue("service_acct@g.com");
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AssertConsumerTokensAndErrors(0, 0);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<OAuth2TokenService::Request> StartTokenRequest() {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return oauth2_service_.StartRequest(std::set<std::string>(), &consumer_);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CryptohomeLibrary::SetForTest(NULL);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::RunLoop().RunUntilIdle();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Utility method to set a value in Local State for the device refresh token
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (it must have a non-empty value or it won't be used).
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetDeviceRefreshTokenInLocalState(const std::string& refresh_token) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_testing_local_state_.Get()->SetManagedPref(
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        prefs::kDeviceRobotAnyApiRefreshToken,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Value::CreateStringValue(refresh_token));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetValidTokenInfoResponse(const std::string email) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "{ \"email\": \"" + email + "\","
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           "  \"user_id\": \"1234567890\" }";
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A utility method to return fake URL results, for testing the refresh token
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // validation logic.  For a successful validation attempt, this method will be
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // called three times for the steps listed below (steps 1 and 2 happen in
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parallel).
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Step 1a: fetch the access token for the tokeninfo API.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Step 1b: call the tokeninfo API.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Step 2:  Fetch the access token for the requested scope
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //          (in this case, cloudprint).
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReturnOAuthUrlFetchResults(int fetcher_id,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  net::HttpStatusCode response_code,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const std::string&  response_string);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AssertConsumerTokensAndErrors(int num_tokens, int num_errors);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::MessageLoop message_loop_;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedTestingLocalState scoped_testing_local_state_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestURLFetcherFactory factory_;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestDeviceOAuth2TokenService oauth2_service_;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestingOAuth2TokenServiceConsumer consumer_;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<chromeos::CryptohomeLibrary> cryptohome_library_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceOAuth2TokenServiceTest::ReturnOAuthUrlFetchResults(
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int fetcher_id,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::HttpStatusCode response_code,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string&  response_string) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(fetcher_id);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(fetcher);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->set_response_code(response_code);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->SetResponseString(response_string);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->delegate()->OnURLFetchComplete(fetcher);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceOAuth2TokenServiceTest::AssertConsumerTokensAndErrors(
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_tokens,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_errors) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(num_tokens, consumer_.number_of_successful_tokens_);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(num_errors, consumer_.number_of_errors_);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DeviceOAuth2TokenServiceTest, SaveEncryptedToken) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StrictMock<MockCryptohomeLibrary> mock_cryptohome_library;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CryptohomeLibrary::SetForTest(&mock_cryptohome_library);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(mock_cryptohome_library, DecryptWithSystemSalt(StrEq("")))
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Times(1)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillOnce(Return(""));
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(mock_cryptohome_library,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              EncryptWithSystemSalt(StrEq("test-token")))
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Times(1)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillOnce(Return("encrypted"));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(mock_cryptohome_library,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              DecryptWithSystemSalt(StrEq("encrypted")))
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Times(1)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillOnce(Return("test-token"));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ("", oauth2_service_.GetRefreshToken());
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  oauth2_service_.SetAndSaveRefreshToken("test-token");
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ("test-token", oauth2_service_.GetRefreshToken());
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This call won't invoke decrypt again, since the value is cached.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ("test-token", oauth2_service_.GetRefreshToken());
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DeviceOAuth2TokenServiceTest, RefreshTokenValidation_Success) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetUpDefaultValues();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReturnOAuthUrlFetchResults(
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kValidatorUrlFetcherId,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::HTTP_OK,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetValidTokenResponse("tokeninfo_access_token", 3600));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReturnOAuthUrlFetchResults(
183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      kValidatorUrlFetcherId,
184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      net::HTTP_OK,
185a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      GetValidTokenInfoResponse("service_acct@g.com"));
186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ReturnOAuthUrlFetchResults(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kOAuthTokenServiceUrlFetcherId,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::HTTP_OK,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetValidTokenResponse("scoped_access_token", 3600));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertConsumerTokensAndErrors(1, 0);
193
194  EXPECT_EQ("scoped_access_token", consumer_.last_token_);
195}
196
197TEST_F(DeviceOAuth2TokenServiceTest,
198       RefreshTokenValidation_Failure_TokenInfoAccessTokenHttpError) {
199  SetUpDefaultValues();
200  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
201
202  ReturnOAuthUrlFetchResults(
203      kValidatorUrlFetcherId,
204      net::HTTP_UNAUTHORIZED,
205      "");
206
207  // TokenInfo API call skipped (error returned in previous step).
208
209  // CloudPrint access token fetch is successful, but consumer still given error
210  // due to bad refresh token.
211  ReturnOAuthUrlFetchResults(
212      kOAuthTokenServiceUrlFetcherId,
213      net::HTTP_OK,
214      GetValidTokenResponse("ignored_scoped_access_token", 3600));
215
216  AssertConsumerTokensAndErrors(0, 1);
217}
218
219TEST_F(DeviceOAuth2TokenServiceTest,
220       RefreshTokenValidation_Failure_TokenInfoAccessTokenInvalidResponse) {
221  SetUpDefaultValues();
222  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
223
224  ReturnOAuthUrlFetchResults(
225      kValidatorUrlFetcherId,
226      net::HTTP_OK,
227      "invalid response");
228
229  // TokenInfo API call skipped (error returned in previous step).
230
231  ReturnOAuthUrlFetchResults(
232      kOAuthTokenServiceUrlFetcherId,
233      net::HTTP_OK,
234      GetValidTokenResponse("ignored_scoped_access_token", 3600));
235
236  // CloudPrint access token fetch is successful, but consumer still given error
237  // due to bad refresh token.
238  AssertConsumerTokensAndErrors(0, 1);
239}
240
241TEST_F(DeviceOAuth2TokenServiceTest,
242       RefreshTokenValidation_Failure_TokenInfoApiCallHttpError) {
243  SetUpDefaultValues();
244  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
245
246  ReturnOAuthUrlFetchResults(
247      kValidatorUrlFetcherId,
248      net::HTTP_OK,
249      GetValidTokenResponse("tokeninfo_access_token", 3600));
250
251  ReturnOAuthUrlFetchResults(
252      kValidatorUrlFetcherId,
253      net::HTTP_INTERNAL_SERVER_ERROR,
254      "");
255
256  ReturnOAuthUrlFetchResults(
257      kOAuthTokenServiceUrlFetcherId,
258      net::HTTP_OK,
259      GetValidTokenResponse("ignored_scoped_access_token", 3600));
260
261  // CloudPrint access token fetch is successful, but consumer still given error
262  // due to bad refresh token.
263  AssertConsumerTokensAndErrors(0, 1);
264}
265
266TEST_F(DeviceOAuth2TokenServiceTest,
267       RefreshTokenValidation_Failure_TokenInfoApiCallInvalidResponse) {
268  SetUpDefaultValues();
269  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
270
271  ReturnOAuthUrlFetchResults(
272      kValidatorUrlFetcherId,
273      net::HTTP_OK,
274      GetValidTokenResponse("tokeninfo_access_token", 3600));
275
276  ReturnOAuthUrlFetchResults(
277      kValidatorUrlFetcherId,
278      net::HTTP_OK,
279      "invalid response");
280
281  ReturnOAuthUrlFetchResults(
282      kOAuthTokenServiceUrlFetcherId,
283      net::HTTP_OK,
284      GetValidTokenResponse("ignored_scoped_access_token", 3600));
285
286  // CloudPrint access token fetch is successful, but consumer still given error
287  // due to bad refresh token.
288  AssertConsumerTokensAndErrors(0, 1);
289}
290
291TEST_F(DeviceOAuth2TokenServiceTest,
292       RefreshTokenValidation_Failure_CloudPrintAccessTokenHttpError) {
293  SetUpDefaultValues();
294  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
295
296  ReturnOAuthUrlFetchResults(
297      kValidatorUrlFetcherId,
298      net::HTTP_OK,
299      GetValidTokenResponse("tokeninfo_access_token", 3600));
300
301  ReturnOAuthUrlFetchResults(
302      kValidatorUrlFetcherId,
303      net::HTTP_OK,
304      GetValidTokenInfoResponse("service_acct@g.com"));
305
306  ReturnOAuthUrlFetchResults(
307      kOAuthTokenServiceUrlFetcherId,
308      net::HTTP_BAD_REQUEST,
309      "");
310
311  AssertConsumerTokensAndErrors(0, 1);
312}
313
314TEST_F(DeviceOAuth2TokenServiceTest,
315       RefreshTokenValidation_Failure_CloudPrintAccessTokenInvalidResponse) {
316  SetUpDefaultValues();
317  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
318
319  ReturnOAuthUrlFetchResults(
320      kValidatorUrlFetcherId,
321      net::HTTP_OK,
322      GetValidTokenResponse("tokeninfo_access_token", 3600));
323
324  ReturnOAuthUrlFetchResults(
325      kValidatorUrlFetcherId,
326      net::HTTP_OK,
327      GetValidTokenInfoResponse("service_acct@g.com"));
328
329  ReturnOAuthUrlFetchResults(
330      kOAuthTokenServiceUrlFetcherId,
331      net::HTTP_OK,
332      "invalid request");
333
334  AssertConsumerTokensAndErrors(0, 1);
335}
336
337TEST_F(DeviceOAuth2TokenServiceTest, RefreshTokenValidation_Failure_BadOwner) {
338  SetUpDefaultValues();
339  scoped_ptr<OAuth2TokenService::Request> request = StartTokenRequest();
340
341  oauth2_service_.SetRobotAccountIdPolicyValue("WRONG_service_acct@g.com");
342
343  // The requested token comes in before any of the validation calls complete,
344  // but the consumer still gets an error, since the results don't get returned
345  // until validation is over.
346  ReturnOAuthUrlFetchResults(
347      kOAuthTokenServiceUrlFetcherId,
348      net::HTTP_OK,
349      GetValidTokenResponse("ignored_scoped_access_token", 3600));
350  AssertConsumerTokensAndErrors(0, 0);
351
352  ReturnOAuthUrlFetchResults(
353      kValidatorUrlFetcherId,
354      net::HTTP_OK,
355      GetValidTokenResponse("tokeninfo_access_token", 3600));
356  AssertConsumerTokensAndErrors(0, 0);
357
358  ReturnOAuthUrlFetchResults(
359      kValidatorUrlFetcherId,
360      net::HTTP_OK,
361      GetValidTokenInfoResponse("service_acct@g.com"));
362
363  // All fetches were successful, but consumer still given error since
364  // the token owner doesn't match the policy value.
365  AssertConsumerTokensAndErrors(0, 1);
366}
367
368}  // namespace chromeos
369