15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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)#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_API_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_API_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <map>
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <set>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <utility>
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
16e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/observer_list.h"
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/extensions/api/identity/extension_token_key.h"
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/extensions/api/identity/identity_mint_queue.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/extensions/api/identity/identity_signin_flow.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/identity/web_auth_flow.h"
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/extensions/chrome_extension_function.h"
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/signin/profile_identity_provider.h"
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/browser_context_keyed_api_factory.h"
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "google_apis/gaia/account_tracker.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/oauth2_mint_token_flow.h"
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "google_apis/gaia/oauth2_token_service.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GoogleServiceAuthError;
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass MockGetAuthTokenFunction;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace content {
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class BrowserContext;
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class GetAuthTokenFunctionTest;
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class MockGetAuthTokenFunction;
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace identity_constants {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const char kInvalidClientId[];
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const char kInvalidScopes[];
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const char kAuthFailure[];
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const char kNoGrant[];
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const char kUserRejected[];
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const char kUserNotSignedIn[];
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)extern const char kInteractionRequired[];
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const char kInvalidRedirect[];
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)extern const char kOffTheRecord[];
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)extern const char kPageLoadFailure[];
52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochextern const char kCanceled[];
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace identity_constants
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochclass IdentityTokenCacheValue {
56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch public:
57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  IdentityTokenCacheValue();
58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  explicit IdentityTokenCacheValue(const IssueAdviceInfo& issue_advice);
59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  IdentityTokenCacheValue(const std::string& token,
60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                          base::TimeDelta time_to_live);
61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ~IdentityTokenCacheValue();
62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
63e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Order of these entries is used to determine whether or not new
64e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // entries supercede older ones in SetCachedToken.
65e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  enum CacheValueStatus {
66e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    CACHE_STATUS_NOTFOUND,
67e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    CACHE_STATUS_ADVICE,
68e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    CACHE_STATUS_TOKEN
69e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  };
70e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
71e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CacheValueStatus status() const;
72e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const IssueAdviceInfo& issue_advice() const;
73e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const std::string& token() const;
74e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const base::Time& expiration_time() const;
75e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch private:
77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  bool is_expired() const;
78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
79e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CacheValueStatus status_;
80e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  IssueAdviceInfo issue_advice_;
81e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  std::string token_;
82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::Time expiration_time_;
83e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch};
84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochclass IdentityAPI : public BrowserContextKeyedAPI,
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    public gaia::AccountTracker::Observer {
87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch public:
88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  typedef std::map<ExtensionTokenKey, IdentityTokenCacheValue> CachedTokens;
89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  class ShutdownObserver {
91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch   public:
92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    virtual void OnShutdown() = 0;
93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  };
94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  explicit IdentityAPI(content::BrowserContext* context);
96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  virtual ~IdentityAPI();
97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Request serialization queue for getAuthToken.
99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  IdentityMintRequestQueue* mint_queue();
100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Token cache
102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void SetCachedToken(const ExtensionTokenKey& key,
103e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      const IdentityTokenCacheValue& token_data);
104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void EraseCachedToken(const std::string& extension_id,
105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                        const std::string& token);
106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void EraseAllCachedTokens();
107e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const IdentityTokenCacheValue& GetCachedToken(const ExtensionTokenKey& key);
108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const CachedTokens& GetAllCachedTokens();
110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Account queries.
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<std::string> GetAccounts() const;
11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::string FindAccountKeyByGaiaId(const std::string& gaia_id);
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
115e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // BrowserContextKeyedAPI implementation.
116e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  virtual void Shutdown() OVERRIDE;
117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  static BrowserContextKeyedAPIFactory<IdentityAPI>* GetFactoryInstance();
118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // gaia::AccountTracker::Observer implementation:
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void OnAccountAdded(const gaia::AccountIds& ids) OVERRIDE;
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void OnAccountRemoved(const gaia::AccountIds& ids) OVERRIDE;
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void OnAccountSignInChanged(const gaia::AccountIds& ids,
123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                      bool is_signed_in) OVERRIDE;
124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void AddShutdownObserver(ShutdownObserver* observer);
126e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void RemoveShutdownObserver(ShutdownObserver* observer);
127e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void SetAccountStateForTest(gaia::AccountIds ids, bool is_signed_in);
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
130e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch private:
131e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  friend class BrowserContextKeyedAPIFactory<IdentityAPI>;
132e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
133e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // BrowserContextKeyedAPI implementation.
134e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  static const char* service_name() { return "IdentityAPI"; }
135e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  static const bool kServiceIsNULLWhileTesting = true;
136e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
137e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  content::BrowserContext* browser_context_;
138e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  IdentityMintRequestQueue mint_queue_;
139e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CachedTokens token_cache_;
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ProfileIdentityProvider profile_identity_provider_;
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  gaia::AccountTracker account_tracker_;
142e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ObserverList<ShutdownObserver> shutdown_observer_list_;
143e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch};
144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
145e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochtemplate <>
146e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid BrowserContextKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies();
147e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class IdentityGetAccountsFunction : public ChromeUIThreadExtensionFunction {
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DECLARE_EXTENSION_FUNCTION("identity.getAccounts",
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             IDENTITY_GETACCOUNTS);
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  IdentityGetAccountsFunction();
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~IdentityGetAccountsFunction();
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // UIThreadExtensionFunction implementation.
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ExtensionFunction::ResponseAction Run() OVERRIDE;
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// identity.getAuthToken fetches an OAuth 2 function for the
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// caller. The request has three sub-flows: non-interactive,
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// interactive, and sign-in.
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// In the non-interactive flow, getAuthToken requests a token from
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// GAIA. GAIA may respond with a token, an error, or "consent
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// required". In the consent required cases, getAuthToken proceeds to
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the second, interactive phase.
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The interactive flow presents a scope approval dialog to the
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// user. If the user approves the request, a grant will be recorded on
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the server, and an access token will be returned to the caller.
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// In some cases we need to display a sign-in dialog. Normally the
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// profile will be signed in already, but if it turns out we need a
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// new login token, there is a sign-in flow. If that flow completes
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// successfully, getAuthToken proceeds to the non-interactive flow.
1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     public GaiaWebAuthFlow::Delegate,
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     public IdentityMintRequestQueue::Request,
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     public OAuth2MintTokenFlow::Delegate,
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     public IdentitySigninFlow::Delegate,
184e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                     public OAuth2TokenService::Consumer,
185e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                     public IdentityAPI::ShutdownObserver {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DECLARE_EXTENSION_FUNCTION("identity.getAuthToken",
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             EXPERIMENTAL_IDENTITY_GETAUTHTOKEN);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdentityGetAuthTokenFunction();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const ExtensionTokenKey* GetExtensionTokenKeyForTest() {
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return token_key_.get();
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~IdentityGetAuthTokenFunction();
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // IdentitySigninFlow::Delegate implementation:
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual void SigninSuccess() OVERRIDE;
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual void SigninFailed() OVERRIDE;
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // GaiaWebAuthFlow::Delegate implementation:
20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual void OnGaiaFlowFailure(GaiaWebAuthFlow::Failure failure,
20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 GoogleServiceAuthError service_error,
20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 const std::string& oauth_error) OVERRIDE;
20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual void OnGaiaFlowCompleted(const std::string& access_token,
20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                   const std::string& expiration) OVERRIDE;
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Starts a login access token request.
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void StartLoginAccessTokenRequest();
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // OAuth2TokenService::Consumer implementation:
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 const std::string& access_token,
21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 const base::Time& expiration_time) OVERRIDE;
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 const GoogleServiceAuthError& error) OVERRIDE;
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<OAuth2TokenService::Request> login_token_request_;
22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  FRIEND_TEST_ALL_PREFIXES(GetAuthTokenFunctionTest,
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           ComponentWithChromeClientId);
225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  FRIEND_TEST_ALL_PREFIXES(GetAuthTokenFunctionTest,
226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           ComponentWithNormalClientId);
227e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  FRIEND_TEST_ALL_PREFIXES(GetAuthTokenFunctionTest, InteractiveQueueShutdown);
228e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  FRIEND_TEST_ALL_PREFIXES(GetAuthTokenFunctionTest, NoninteractiveShutdown);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ExtensionFunction:
231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  virtual bool RunAsync() OVERRIDE;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Helpers to report async function results to the caller.
234e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void StartAsyncRun();
235e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void CompleteAsyncRun(bool success);
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void CompleteFunctionWithResult(const std::string& access_token);
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void CompleteFunctionWithError(const std::string& error);
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Initiate/complete the sub-flows.
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StartSigninFlow();
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StartMintTokenFlow(IdentityMintRequestQueue::MintType type);
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void CompleteMintTokenFlow();
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // IdentityMintRequestQueue::Request implementation:
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void StartMintToken(IdentityMintRequestQueue::MintType type) OVERRIDE;
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OAuth2MintTokenFlow::Delegate implementation:
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnMintTokenSuccess(const std::string& access_token,
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  int time_to_live) OVERRIDE;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnMintTokenFailure(
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GoogleServiceAuthError& error) OVERRIDE;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnIssueAdviceSuccess(
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const IssueAdviceInfo& issue_advice) OVERRIDE;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // IdentityAPI::ShutdownObserver implementation:
256e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  virtual void OnShutdown() OVERRIDE;
257e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
2588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_CHROMEOS)
2598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Starts a login access token request for device robot account. This method
2608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // will be called only in enterprise kiosk mode in ChromeOS.
2618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  virtual void StartDeviceLoginAccessTokenRequest();
2628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif
2638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Starts a mint token request to GAIA.
2657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void StartGaiaRequest(const std::string& login_access_token);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Methods for invoking UI. Overridable for testing.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ShowLoginPopup();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ShowOAuthApprovalDialog(const IssueAdviceInfo& issue_advice);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Caller owns the returned instance.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual OAuth2MintTokenFlow* CreateMintTokenFlow(
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const std::string& login_access_token);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checks if there is a master login token to mint tokens for the extension.
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool HasLoginToken() const;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Maps OAuth2 protocol errors to an error message returned to the
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // developer in chrome.runtime.lastError.
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string MapOAuth2ErrorToDescription(const std::string& error);
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string GetOAuth2ClientId() const;
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool should_prompt_for_scopes_;
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityMintRequestQueue::MintType mint_token_flow_type_;
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<OAuth2MintTokenFlow> mint_token_flow_;
2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  OAuth2MintTokenFlow::Mode gaia_mint_token_mode_;
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool should_prompt_for_signin_;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<ExtensionTokenKey> token_key_;
290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string oauth2_client_id_;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When launched in interactive mode, and if there is no existing grant,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a permissions prompt will be popped up to the user.
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IssueAdviceInfo issue_advice_;
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<GaiaWebAuthFlow> gaia_web_auth_flow_;
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<IdentitySigninFlow> signin_flow_;
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class IdentityGetProfileUserInfoFunction
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : public ChromeUIThreadExtensionFunction {
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public:
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DECLARE_EXTENSION_FUNCTION("identity.getProfileUserInfo",
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                             IDENTITY_GETPROFILEUSERINFO);
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  IdentityGetProfileUserInfoFunction();
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private:
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual ~IdentityGetProfileUserInfoFunction();
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // UIThreadExtensionFunction implementation.
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  virtual ExtensionFunction::ResponseAction Run() OVERRIDE;
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class IdentityRemoveCachedAuthTokenFunction
3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    : public ChromeSyncExtensionFunction {
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DECLARE_EXTENSION_FUNCTION("identity.removeCachedAuthToken",
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             EXPERIMENTAL_IDENTITY_REMOVECACHEDAUTHTOKEN)
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityRemoveCachedAuthTokenFunction();
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~IdentityRemoveCachedAuthTokenFunction();
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // SyncExtensionFunction implementation:
3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual bool RunSync() OVERRIDE;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class IdentityLaunchWebAuthFlowFunction : public ChromeAsyncExtensionFunction,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          public WebAuthFlow::Delegate {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DECLARE_EXTENSION_FUNCTION("identity.launchWebAuthFlow",
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             EXPERIMENTAL_IDENTITY_LAUNCHWEBAUTHFLOW);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdentityLaunchWebAuthFlowFunction();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Tests may override extension_id.
336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  void InitFinalRedirectURLPrefixForTest(const std::string& extension_id);
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~IdentityLaunchWebAuthFlowFunction();
340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  virtual bool RunAsync() OVERRIDE;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebAuthFlow::Delegate implementation.
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnAuthFlowFailure(WebAuthFlow::Failure failure) OVERRIDE;
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnAuthFlowURLChange(const GURL& redirect_url) OVERRIDE;
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnAuthFlowTitleChange(const std::string& title) OVERRIDE {}
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
347b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Helper to initialize final URL prefix.
348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  void InitFinalRedirectURLPrefix(const std::string& extension_id);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WebAuthFlow> auth_flow_;
351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  GURL final_url_prefix_;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_API_H_
357