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