identity_api.h revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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_
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_API_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <utility>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (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"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/identity/identity_mint_queue.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/identity/identity_signin_flow.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/identity/web_auth_flow.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/profile_keyed_api_factory.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_function.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/oauth2_token_service.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/signin/signin_global_error.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gaia/oauth2_mint_token_flow.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GoogleServiceAuthError;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockGetAuthTokenFunction;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Profile;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SigninManagerBase;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GetAuthTokenFunctionTest;
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MockGetAuthTokenFunction;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace identity_constants {
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern const char kInvalidClientId[];
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern const char kInvalidScopes[];
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern const char kAuthFailure[];
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern const char kNoGrant[];
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern const char kUserRejected[];
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern const char kUserNotSignedIn[];
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern const char kInteractionRequired[];
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern const char kInvalidRedirect[];
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern const char kOffTheRecord[];
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern const char kPageLoadFailure[];
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace identity_constants
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// identity.getAuthToken fetches an OAuth 2 function for the
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// caller. The request has three sub-flows: non-interactive,
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// interactive, and sign-in.
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// In the non-interactive flow, getAuthToken requests a token from
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// GAIA. GAIA may respond with a token, an error, or "consent
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// required". In the consent required cases, getAuthToken proceeds to
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the second, interactive phase.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The interactive flow presents a scope approval dialog to the
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// user. If the user approves the request, a grant will be recorded on
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the server, and an access token will be returned to the caller.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In some cases we need to display a sign-in dialog. Normally the
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// profile will be signed in already, but if it turns out we need a
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// new login token, there is a sign-in flow. If that flow completes
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// successfully, getAuthToken proceeds to the non-interactive flow.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IdentityGetAuthTokenFunction : public AsyncExtensionFunction,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     public GaiaWebAuthFlow::Delegate,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     public IdentityMintRequestQueue::Request,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     public OAuth2MintTokenFlow::Delegate,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     public IdentitySigninFlow::Delegate,
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                     public OAuth2TokenService::Consumer {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DECLARE_EXTENSION_FUNCTION("identity.getAuthToken",
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             EXPERIMENTAL_IDENTITY_GETAUTHTOKEN);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdentityGetAuthTokenFunction();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~IdentityGetAuthTokenFunction();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(GetAuthTokenFunctionTest,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ComponentWithChromeClientId);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(GetAuthTokenFunctionTest,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ComponentWithNormalClientId);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class MockGetAuthTokenFunction;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ExtensionFunction:
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool RunImpl() OVERRIDE;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helpers to report async function results to the caller.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CompleteFunctionWithResult(const std::string& access_token);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CompleteFunctionWithError(const std::string& error);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initiate/complete the sub-flows.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartSigninFlow();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartMintTokenFlow(IdentityMintRequestQueue::MintType type);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CompleteMintTokenFlow();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IdentityMintRequestQueue::Request implementation:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void StartMintToken(IdentityMintRequestQueue::MintType type) OVERRIDE;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OAuth2MintTokenFlow::Delegate implementation:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnMintTokenSuccess(const std::string& access_token,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int time_to_live) OVERRIDE;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnMintTokenFailure(
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GoogleServiceAuthError& error) OVERRIDE;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnIssueAdviceSuccess(
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const IssueAdviceInfo& issue_advice) OVERRIDE;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IdentitySigninFlow::Delegate implementation:
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SigninSuccess(const std::string& token) OVERRIDE;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SigninFailed() OVERRIDE;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GaiaWebAuthFlow::Delegate implementation:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnGaiaFlowFailure(GaiaWebAuthFlow::Failure failure,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 GoogleServiceAuthError service_error,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& oauth_error) OVERRIDE;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnGaiaFlowCompleted(const std::string& access_token,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const std::string& expiration) OVERRIDE;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OAuth2TokenService::Consumer implementation:
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& access_token,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const base::Time& expiration_time) OVERRIDE;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const GoogleServiceAuthError& error) OVERRIDE;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starts a mint token request to GAIA.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartGaiaRequest(OAuth2MintTokenFlow::Mode mode);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Methods for invoking UI. Overridable for testing.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ShowLoginPopup();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ShowOAuthApprovalDialog(const IssueAdviceInfo& issue_advice);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Caller owns the returned instance.
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual OAuth2MintTokenFlow* CreateMintTokenFlow(
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      OAuth2MintTokenFlow::Mode mode);
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Checks if there is a master login token to mint tokens for the extension.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasLoginToken() const;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maps OAuth2 protocol errors to an error message returned to the
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // developer in chrome.runtime.lastError.
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string MapOAuth2ErrorToDescription(const std::string& error);
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string GetOAuth2ClientId() const;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool should_prompt_for_scopes_;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdentityMintRequestQueue::MintType mint_token_flow_type_;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<OAuth2MintTokenFlow> mint_token_flow_;
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string refresh_token_;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool should_prompt_for_signin_;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string oauth2_client_id_;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When launched in interactive mode, and if there is no existing grant,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a permissions prompt will be popped up to the user.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IssueAdviceInfo issue_advice_;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<GaiaWebAuthFlow> gaia_web_auth_flow_;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<IdentitySigninFlow> signin_flow_;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<OAuth2TokenService::Request> device_token_request_;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IdentityRemoveCachedAuthTokenFunction : public SyncExtensionFunction {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DECLARE_EXTENSION_FUNCTION("identity.removeCachedAuthToken",
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             EXPERIMENTAL_IDENTITY_REMOVECACHEDAUTHTOKEN)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdentityRemoveCachedAuthTokenFunction();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~IdentityRemoveCachedAuthTokenFunction();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SyncExtensionFunction implementation:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool RunImpl() OVERRIDE;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IdentityLaunchWebAuthFlowFunction : public AsyncExtensionFunction,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          public WebAuthFlow::Delegate {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DECLARE_EXTENSION_FUNCTION("identity.launchWebAuthFlow",
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             EXPERIMENTAL_IDENTITY_LAUNCHWEBAUTHFLOW);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdentityLaunchWebAuthFlowFunction();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tests may override extension_id.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitFinalRedirectURLPrefixForTest(const std::string& extension_id);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~IdentityLaunchWebAuthFlowFunction();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool RunImpl() OVERRIDE;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebAuthFlow::Delegate implementation.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnAuthFlowFailure(WebAuthFlow::Failure failure) OVERRIDE;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnAuthFlowURLChange(const GURL& redirect_url) OVERRIDE;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnAuthFlowTitleChange(const std::string& title) OVERRIDE {}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper to initialize final URL prefix.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitFinalRedirectURLPrefix(const std::string& extension_id);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WebAuthFlow> auth_flow_;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL final_url_prefix_;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class IdentityTokenCacheValue {
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityTokenCacheValue();
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit IdentityTokenCacheValue(const IssueAdviceInfo& issue_advice);
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityTokenCacheValue(const std::string& token,
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          base::TimeDelta time_to_live);
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ~IdentityTokenCacheValue();
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Order of these entries is used to determine whether or not new
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // entries supercede older ones in SetCachedToken.
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  enum CacheValueStatus {
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CACHE_STATUS_NOTFOUND,
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CACHE_STATUS_ADVICE,
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CACHE_STATUS_TOKEN
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CacheValueStatus status() const;
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const IssueAdviceInfo& issue_advice() const;
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string& token() const;
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::Time& expiration_time() const;
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool is_expired() const;
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CacheValueStatus status_;
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IssueAdviceInfo issue_advice_;
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string token_;
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::Time expiration_time_;
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class IdentityAPI : public ProfileKeyedAPI,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    public SigninGlobalError::AuthStatusProvider,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    public content::NotificationObserver {
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  struct TokenCacheKey {
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TokenCacheKey(const std::string& extension_id,
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  const std::set<std::string> scopes);
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ~TokenCacheKey();
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool operator<(const TokenCacheKey& rhs) const;
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string extension_id;
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::set<std::string> scopes;
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  typedef std::map<TokenCacheKey, IdentityTokenCacheValue> CachedTokens;
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit IdentityAPI(Profile* profile);
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~IdentityAPI();
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Initialize();
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Request serialization queue for getAuthToken.
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityMintRequestQueue* mint_queue();
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Token cache
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void SetCachedToken(const std::string& extension_id,
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      const std::vector<std::string> scopes,
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      const IdentityTokenCacheValue& token_data);
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void EraseCachedToken(const std::string& extension_id,
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        const std::string& token);
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void EraseAllCachedTokens();
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const IdentityTokenCacheValue& GetCachedToken(
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const std::string& extension_id, const std::vector<std::string> scopes);
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const CachedTokens& GetAllCachedTokens();
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ReportAuthError(const GoogleServiceAuthError& error);
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // ProfileKeyedAPI implementation.
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void Shutdown() OVERRIDE;
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static ProfileKeyedAPIFactory<IdentityAPI>* GetFactoryInstance();
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // AuthStatusProvider implementation.
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual GoogleServiceAuthError GetAuthStatus() const OVERRIDE;
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // content::NotificationObserver implementation.
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void Observe(int type,
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       const content::NotificationSource& source,
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE;
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  friend class ProfileKeyedAPIFactory<IdentityAPI>;
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // ProfileKeyedAPI implementation.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* service_name() {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "IdentityAPI";
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const bool kServiceIsNULLWhileTesting = true;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile_;
291  SigninManagerBase* signin_manager_;
292  GoogleServiceAuthError error_;
293  // Used to listen to notifications from the TokenService.
294  content::NotificationRegistrar registrar_;
295  IdentityMintRequestQueue mint_queue_;
296  CachedTokens token_cache_;
297};
298
299template <>
300void ProfileKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies();
301
302}  // namespace extensions
303
304#endif  // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_API_H_
305