- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / identity / identity_api.h
1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_API_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_API_H_
7
8 #include <map>
9 #include <set>
10 #include <string>
11 #include <utility>
12 #include <vector>
13
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/weak_ptr.h"
16 #include "chrome/browser/extensions/api/identity/account_tracker.h"
17 #include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h"
18 #include "chrome/browser/extensions/api/identity/identity_mint_queue.h"
19 #include "chrome/browser/extensions/api/identity/identity_signin_flow.h"
20 #include "chrome/browser/extensions/api/identity/web_auth_flow.h"
21 #include "chrome/browser/extensions/api/profile_keyed_api_factory.h"
22 #include "chrome/browser/extensions/chrome_extension_function.h"
23 #include "chrome/browser/signin/signin_global_error.h"
24 #include "google_apis/gaia/oauth2_mint_token_flow.h"
25 #include "google_apis/gaia/oauth2_token_service.h"
26
27 class GoogleServiceAuthError;
28 class MockGetAuthTokenFunction;
29 class Profile;
30
31 #if defined(OS_CHROMEOS)
32 namespace chromeos {
33 class DeviceOAuth2TokenService;
34 }
35 #endif
36
37 namespace extensions {
38
39 class GetAuthTokenFunctionTest;
40 class MockGetAuthTokenFunction;
41
42 namespace identity_constants {
43 extern const char kInvalidClientId[];
44 extern const char kInvalidScopes[];
45 extern const char kAuthFailure[];
46 extern const char kNoGrant[];
47 extern const char kUserRejected[];
48 extern const char kUserNotSignedIn[];
49 extern const char kInteractionRequired[];
50 extern const char kInvalidRedirect[];
51 extern const char kOffTheRecord[];
52 extern const char kPageLoadFailure[];
53 }  // namespace identity_constants
54
55 // identity.getAuthToken fetches an OAuth 2 function for the
56 // caller. The request has three sub-flows: non-interactive,
57 // interactive, and sign-in.
58 //
59 // In the non-interactive flow, getAuthToken requests a token from
60 // GAIA. GAIA may respond with a token, an error, or "consent
61 // required". In the consent required cases, getAuthToken proceeds to
62 // the second, interactive phase.
63 //
64 // The interactive flow presents a scope approval dialog to the
65 // user. If the user approves the request, a grant will be recorded on
66 // the server, and an access token will be returned to the caller.
67 //
68 // In some cases we need to display a sign-in dialog. Normally the
69 // profile will be signed in already, but if it turns out we need a
70 // new login token, there is a sign-in flow. If that flow completes
71 // successfully, getAuthToken proceeds to the non-interactive flow.
72 class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
73                                      public GaiaWebAuthFlow::Delegate,
74                                      public IdentityMintRequestQueue::Request,
75                                      public OAuth2MintTokenFlow::Delegate,
76                                      public IdentitySigninFlow::Delegate,
77                                      public OAuth2TokenService::Consumer {
78  public:
79   DECLARE_EXTENSION_FUNCTION("identity.getAuthToken",
80                              EXPERIMENTAL_IDENTITY_GETAUTHTOKEN);
81
82   IdentityGetAuthTokenFunction();
83
84  protected:
85   virtual ~IdentityGetAuthTokenFunction();
86
87  private:
88   FRIEND_TEST_ALL_PREFIXES(GetAuthTokenFunctionTest,
89                            ComponentWithChromeClientId);
90   FRIEND_TEST_ALL_PREFIXES(GetAuthTokenFunctionTest,
91                            ComponentWithNormalClientId);
92   friend class MockGetAuthTokenFunction;
93
94   // ExtensionFunction:
95   virtual bool RunImpl() OVERRIDE;
96
97   // Helpers to report async function results to the caller.
98   void CompleteFunctionWithResult(const std::string& access_token);
99   void CompleteFunctionWithError(const std::string& error);
100
101   // Initiate/complete the sub-flows.
102   void StartSigninFlow();
103   void StartMintTokenFlow(IdentityMintRequestQueue::MintType type);
104   void CompleteMintTokenFlow();
105
106   // IdentityMintRequestQueue::Request implementation:
107   virtual void StartMintToken(IdentityMintRequestQueue::MintType type) OVERRIDE;
108
109   // OAuth2MintTokenFlow::Delegate implementation:
110   virtual void OnMintTokenSuccess(const std::string& access_token,
111                                   int time_to_live) OVERRIDE;
112   virtual void OnMintTokenFailure(
113       const GoogleServiceAuthError& error) OVERRIDE;
114   virtual void OnIssueAdviceSuccess(
115       const IssueAdviceInfo& issue_advice) OVERRIDE;
116
117   // IdentitySigninFlow::Delegate implementation:
118   virtual void SigninSuccess() OVERRIDE;
119   virtual void SigninFailed() OVERRIDE;
120
121   // GaiaWebAuthFlow::Delegate implementation:
122   virtual void OnGaiaFlowFailure(GaiaWebAuthFlow::Failure failure,
123                                  GoogleServiceAuthError service_error,
124                                  const std::string& oauth_error) OVERRIDE;
125   virtual void OnGaiaFlowCompleted(const std::string& access_token,
126                                    const std::string& expiration) OVERRIDE;
127
128   // OAuth2TokenService::Consumer implementation:
129   virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
130                                  const std::string& access_token,
131                                  const base::Time& expiration_time) OVERRIDE;
132   virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
133                                  const GoogleServiceAuthError& error) OVERRIDE;
134
135   // Starts a login access token request.
136   virtual void StartLoginAccessTokenRequest();
137
138 #if defined(OS_CHROMEOS)
139   // Starts a login access token request for device robot account. This method
140   // will be called only in enterprise kiosk mode in ChromeOS.
141   virtual void StartDeviceLoginAccessTokenRequest();
142
143   // Continuation of StartDeviceLoginAccessTokenRequest().
144   virtual void DidGetTokenService(chromeos::DeviceOAuth2TokenService* service);
145 #endif
146
147   // Starts a mint token request to GAIA.
148   void StartGaiaRequest(const std::string& login_access_token);
149
150   // Methods for invoking UI. Overridable for testing.
151   virtual void ShowLoginPopup();
152   virtual void ShowOAuthApprovalDialog(const IssueAdviceInfo& issue_advice);
153   // Caller owns the returned instance.
154   virtual OAuth2MintTokenFlow* CreateMintTokenFlow(
155       const std::string& login_access_token);
156
157   // Checks if there is a master login token to mint tokens for the extension.
158   virtual bool HasLoginToken() const;
159
160   // Maps OAuth2 protocol errors to an error message returned to the
161   // developer in chrome.runtime.lastError.
162   std::string MapOAuth2ErrorToDescription(const std::string& error);
163
164   std::string GetOAuth2ClientId() const;
165
166   bool should_prompt_for_scopes_;
167   IdentityMintRequestQueue::MintType mint_token_flow_type_;
168   scoped_ptr<OAuth2MintTokenFlow> mint_token_flow_;
169   OAuth2MintTokenFlow::Mode gaia_mint_token_mode_;
170   bool should_prompt_for_signin_;
171
172   std::string oauth2_client_id_;
173   // When launched in interactive mode, and if there is no existing grant,
174   // a permissions prompt will be popped up to the user.
175   IssueAdviceInfo issue_advice_;
176   scoped_ptr<GaiaWebAuthFlow> gaia_web_auth_flow_;
177   scoped_ptr<IdentitySigninFlow> signin_flow_;
178   scoped_ptr<OAuth2TokenService::Request> login_token_request_;
179 };
180
181 class IdentityRemoveCachedAuthTokenFunction
182     : public ChromeSyncExtensionFunction {
183  public:
184   DECLARE_EXTENSION_FUNCTION("identity.removeCachedAuthToken",
185                              EXPERIMENTAL_IDENTITY_REMOVECACHEDAUTHTOKEN)
186   IdentityRemoveCachedAuthTokenFunction();
187
188  protected:
189   virtual ~IdentityRemoveCachedAuthTokenFunction();
190
191   // SyncExtensionFunction implementation:
192   virtual bool RunImpl() OVERRIDE;
193 };
194
195 class IdentityLaunchWebAuthFlowFunction : public ChromeAsyncExtensionFunction,
196                                           public WebAuthFlow::Delegate {
197  public:
198   DECLARE_EXTENSION_FUNCTION("identity.launchWebAuthFlow",
199                              EXPERIMENTAL_IDENTITY_LAUNCHWEBAUTHFLOW);
200
201   IdentityLaunchWebAuthFlowFunction();
202
203   // Tests may override extension_id.
204   void InitFinalRedirectURLPrefixForTest(const std::string& extension_id);
205
206  private:
207   virtual ~IdentityLaunchWebAuthFlowFunction();
208   virtual bool RunImpl() OVERRIDE;
209
210   // WebAuthFlow::Delegate implementation.
211   virtual void OnAuthFlowFailure(WebAuthFlow::Failure failure) OVERRIDE;
212   virtual void OnAuthFlowURLChange(const GURL& redirect_url) OVERRIDE;
213   virtual void OnAuthFlowTitleChange(const std::string& title) OVERRIDE {}
214
215   // Helper to initialize final URL prefix.
216   void InitFinalRedirectURLPrefix(const std::string& extension_id);
217
218   scoped_ptr<WebAuthFlow> auth_flow_;
219   GURL final_url_prefix_;
220 };
221
222 class IdentityTokenCacheValue {
223  public:
224   IdentityTokenCacheValue();
225   explicit IdentityTokenCacheValue(const IssueAdviceInfo& issue_advice);
226   IdentityTokenCacheValue(const std::string& token,
227                           base::TimeDelta time_to_live);
228   ~IdentityTokenCacheValue();
229
230   // Order of these entries is used to determine whether or not new
231   // entries supercede older ones in SetCachedToken.
232   enum CacheValueStatus {
233     CACHE_STATUS_NOTFOUND,
234     CACHE_STATUS_ADVICE,
235     CACHE_STATUS_TOKEN
236   };
237
238   CacheValueStatus status() const;
239   const IssueAdviceInfo& issue_advice() const;
240   const std::string& token() const;
241   const base::Time& expiration_time() const;
242
243  private:
244   bool is_expired() const;
245
246   CacheValueStatus status_;
247   IssueAdviceInfo issue_advice_;
248   std::string token_;
249   base::Time expiration_time_;
250 };
251
252 class IdentityAPI : public ProfileKeyedAPI,
253                     public AccountTracker::Observer {
254  public:
255   struct TokenCacheKey {
256     TokenCacheKey(const std::string& extension_id,
257                   const std::set<std::string> scopes);
258     ~TokenCacheKey();
259     bool operator<(const TokenCacheKey& rhs) const;
260     std::string extension_id;
261     std::set<std::string> scopes;
262   };
263
264   typedef std::map<TokenCacheKey, IdentityTokenCacheValue> CachedTokens;
265
266   explicit IdentityAPI(Profile* profile);
267   virtual ~IdentityAPI();
268
269   // Request serialization queue for getAuthToken.
270   IdentityMintRequestQueue* mint_queue();
271
272   // Token cache
273   void SetCachedToken(const std::string& extension_id,
274                       const std::vector<std::string> scopes,
275                       const IdentityTokenCacheValue& token_data);
276   void EraseCachedToken(const std::string& extension_id,
277                         const std::string& token);
278   void EraseAllCachedTokens();
279   const IdentityTokenCacheValue& GetCachedToken(
280       const std::string& extension_id, const std::vector<std::string> scopes);
281
282   const CachedTokens& GetAllCachedTokens();
283
284   void ReportAuthError(const GoogleServiceAuthError& error);
285
286   // ProfileKeyedAPI implementation.
287   virtual void Shutdown() OVERRIDE;
288   static ProfileKeyedAPIFactory<IdentityAPI>* GetFactoryInstance();
289
290   // AccountTracker::Observer implementation:
291   virtual void OnAccountAdded(const AccountIds& ids) OVERRIDE;
292   virtual void OnAccountRemoved(const AccountIds& ids) OVERRIDE;
293   virtual void OnAccountSignInChanged(const AccountIds& ids, bool is_signed_in)
294       OVERRIDE;
295
296  private:
297   friend class ProfileKeyedAPIFactory<IdentityAPI>;
298
299   // ProfileKeyedAPI implementation.
300   static const char* service_name() {
301     return "IdentityAPI";
302   }
303   static const bool kServiceIsNULLWhileTesting = true;
304
305   Profile* profile_;
306   IdentityMintRequestQueue mint_queue_;
307   CachedTokens token_cache_;
308   AccountTracker account_tracker_;
309 };
310
311 template <>
312 void ProfileKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies();
313
314 }  // namespace extensions
315
316 #endif  // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_API_H_