1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifndef GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_IMPL_H_
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_IMPL_H_
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <string>
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <vector>
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/gtest_prod_util.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "google_apis/gaia/oauth2_access_token_consumer.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "google_apis/gaia/oauth2_access_token_fetcher.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "url/gurl.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class OAuth2AccessTokenFetcherImplTest;
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace base {
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class Time;
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace net {
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class URLFetcher;
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class URLRequestContextGetter;
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class URLRequestStatus;
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Abstracts the details to get OAuth2 access token token from
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// OAuth2 refresh token.
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// See "Using the Refresh Token" section in:
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// http://code.google.com/apis/accounts/docs/OAuth2WebServer.html
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// This class should be used on a single thread, but it can be whichever thread
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// that you like.
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Also, do not reuse the same instance. Once Start() is called, the instance
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// should not be reused.
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Usage:
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// * Create an instance with a consumer.
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// * Call Start()
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// * The consumer passed in the constructor will be called on the same
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//   thread Start was called with the results.
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// This class can handle one request at a time. To parallelize requests,
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// create multiple instances.
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class OAuth2AccessTokenFetcherImpl : public OAuth2AccessTokenFetcher,
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     public net::URLFetcherDelegate {
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  OAuth2AccessTokenFetcherImpl(OAuth2AccessTokenConsumer* consumer,
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               net::URLRequestContextGetter* getter,
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                               const std::string& refresh_token);
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual ~OAuth2AccessTokenFetcherImpl();
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Implementation of OAuth2AccessTokenFetcher
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void Start(const std::string& client_id,
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     const std::string& client_secret,
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     const std::vector<std::string>& scopes) OVERRIDE;
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void CancelRequest() OVERRIDE;
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Implementation of net::URLFetcherDelegate
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  enum State {
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    INITIAL,
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    GET_ACCESS_TOKEN_STARTED,
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    GET_ACCESS_TOKEN_DONE,
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ERROR_STATE,
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  };
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Helper methods for the flow.
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void StartGetAccessToken();
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void EndGetAccessToken(const net::URLFetcher* source);
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Helper mehtods for reporting back results.
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void OnGetTokenSuccess(const std::string& access_token,
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         const base::Time& expiration_time);
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void OnGetTokenFailure(const GoogleServiceAuthError& error);
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Other helpers.
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static GURL MakeGetAccessTokenUrl();
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static std::string MakeGetAccessTokenBody(
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const std::string& client_id,
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const std::string& client_secret,
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const std::string& refresh_token,
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const std::vector<std::string>& scopes);
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static bool ParseGetAccessTokenSuccessResponse(const net::URLFetcher* source,
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                 std::string* access_token,
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                 int* expires_in);
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static bool ParseGetAccessTokenFailureResponse(const net::URLFetcher* source,
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                 std::string* error);
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // State that is set during construction.
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  net::URLRequestContextGetter* const getter_;
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string refresh_token_;
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  State state_;
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // While a fetch is in progress.
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<net::URLFetcher> fetcher_;
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string client_id_;
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string client_secret_;
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<std::string> scopes_;
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  friend class OAuth2AccessTokenFetcherImplTest;
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherImplTest,
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           ParseGetAccessTokenResponse);
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherImplTest,
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           MakeGetAccessTokenBody);
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OAuth2AccessTokenFetcherImpl);
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  // GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_IMPL_H_
119