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.
5 #ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_EXPERIMENTAL_IDENTITY_API_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_EXPERIMENTAL_IDENTITY_API_H_
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/weak_ptr.h"
13 #include "chrome/browser/extensions/api/identity/experimental_web_auth_flow.h"
14 #include "chrome/browser/extensions/api/identity/identity_mint_queue.h"
15 #include "chrome/browser/extensions/api/identity/identity_signin_flow.h"
16 #include "chrome/browser/extensions/chrome_extension_function.h"
17 #include "chrome/browser/extensions/extension_install_prompt.h"
18 #include "google_apis/gaia/oauth2_mint_token_flow.h"
19 #include "google_apis/gaia/oauth2_token_service.h"
21 namespace extensions {
23 // TODO(courage): These functions exist to support some apps that were
24 // whitelisted to use the experimental API. Remove them once those
25 // apps have migrated.
27 // experimental.identity.getAuthToken fetches an OAuth 2 function for
28 // the caller. The request has three sub-flows: non-interactive,
29 // interactive, and sign-in.
31 // In the non-interactive flow, getAuthToken requests a token from
32 // GAIA. GAIA may respond with a token, an error, or "consent
33 // required". In the consent required cases, getAuthToken proceeds to
34 // the second, interactive phase.
36 // The interactive flow presents a scope approval dialog to the
37 // user. If the user approves the request, a grant will be recorded on
38 // the server, and an access token will be returned to the caller.
40 // In some cases we need to display a sign-in dialog. Normally the
41 // profile will be signed in already, but if it turns out we need a
42 // new login token, there is a sign-in flow. If that flow completes
43 // successfully, getAuthToken proceeds to the non-interactive flow.
44 class ExperimentalIdentityGetAuthTokenFunction
45 : public ChromeAsyncExtensionFunction,
46 public ExtensionInstallPrompt::Delegate,
47 public OAuth2MintTokenFlow::Delegate,
48 public IdentitySigninFlow::Delegate,
49 public OAuth2TokenService::Consumer {
51 DECLARE_EXTENSION_FUNCTION("experimental.identity.getAuthToken",
52 EXPERIMENTAL_IDENTITY_GETAUTHTOKEN);
54 ExperimentalIdentityGetAuthTokenFunction();
55 virtual bool RunImpl() OVERRIDE;
58 virtual ~ExperimentalIdentityGetAuthTokenFunction();
61 friend class ExperimentalGetAuthTokenFunctionTest;
62 friend class ExperimentalMockGetAuthTokenFunction;
64 // Helpers to report async function results to the caller.
65 void CompleteFunctionWithResult(const std::string& access_token);
66 void CompleteFunctionWithError(const std::string& error);
68 // Initiate/complete the sub-flows.
69 void StartSigninFlow();
70 void StartMintTokenFlow(IdentityMintRequestQueue::MintType type);
72 // OAuth2MintTokenFlow::Delegate implementation:
73 virtual void OnMintTokenSuccess(const std::string& access_token,
74 int time_to_live) OVERRIDE;
75 virtual void OnMintTokenFailure(
76 const GoogleServiceAuthError& error) OVERRIDE;
77 virtual void OnIssueAdviceSuccess(
78 const IssueAdviceInfo& issue_advice) OVERRIDE;
80 // IdentitySigninFlow::Delegate implementation:
81 virtual void SigninSuccess() OVERRIDE;
82 virtual void SigninFailed() OVERRIDE;
84 // ExtensionInstallPrompt::Delegate implementation:
85 virtual void InstallUIProceed() OVERRIDE;
86 virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
88 // OAuth2TokenService::Consumer implementation:
89 virtual void OnGetTokenSuccess(
90 const OAuth2TokenService::Request* request,
91 const std::string& access_token,
92 const base::Time& expiration_time) OVERRIDE;
93 virtual void OnGetTokenFailure(
94 const OAuth2TokenService::Request* request,
95 const GoogleServiceAuthError& error) OVERRIDE;
97 // Starts a login access token request.
98 virtual void StartLoginAccessTokenRequest();
100 // Starts a mint token request to GAIA.
101 void StartGaiaRequest(const std::string& login_access_token);
103 // Methods for invoking UI. Overridable for testing.
104 virtual void ShowLoginPopup();
105 virtual void ShowOAuthApprovalDialog(const IssueAdviceInfo& issue_advice);
106 // Caller owns the returned instance.
107 virtual OAuth2MintTokenFlow* CreateMintTokenFlow(
108 const std::string& login_access_token);
110 // Checks if there is a master login token to mint tokens for the extension.
111 virtual bool HasLoginToken() const;
113 bool should_prompt_for_scopes_;
114 scoped_ptr<OAuth2MintTokenFlow> mint_token_flow_;
115 OAuth2MintTokenFlow::Mode gaia_mint_token_mode_;
116 bool should_prompt_for_signin_;
118 // When launched in interactive mode, and if there is no existing grant,
119 // a permissions prompt will be popped up to the user.
120 IssueAdviceInfo issue_advice_;
121 scoped_ptr<ExtensionInstallPrompt> install_ui_;
122 scoped_ptr<IdentitySigninFlow> signin_flow_;
123 scoped_ptr<OAuth2TokenService::Request> login_token_request_;
126 class ExperimentalIdentityLaunchWebAuthFlowFunction
127 : public ChromeAsyncExtensionFunction,
128 public ExperimentalWebAuthFlow::Delegate {
130 DECLARE_EXTENSION_FUNCTION("experimental.identity.launchWebAuthFlow",
131 EXPERIMENTAL_IDENTITY_LAUNCHWEBAUTHFLOW);
132 ExperimentalIdentityLaunchWebAuthFlowFunction();
134 // URL checking helpers. Public for testing.
135 // Checks to see if the current URL ends the flow.
136 bool IsFinalRedirectURL(const GURL& url) const;
138 // Unit tests may override extension_id.
139 void InitFinalRedirectURLPrefixesForTest(const std::string& extension_id);
142 virtual ~ExperimentalIdentityLaunchWebAuthFlowFunction();
143 virtual bool RunImpl() OVERRIDE;
145 // Helper to initialize final URLs vector.
146 void InitFinalRedirectURLPrefixes(const std::string& extension_id);
148 scoped_ptr<ExperimentalWebAuthFlow> auth_flow_;
149 std::vector<GURL> final_prefixes_;
152 // ExperimentalWebAuthFlow::Delegate implementation.
153 virtual void OnAuthFlowFailure(ExperimentalWebAuthFlow::Failure failure)
155 virtual void OnAuthFlowURLChange(const GURL& redirect_url) OVERRIDE;
158 } // namespace extensions
160 #endif // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_EXPERIMENTAL_IDENTITY_API_H_