Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / shell / browser / api / identity / identity_api.cc
blobbf8ad1f8fdace351a81d6560279ba6e22278a8f4
1 // Copyright 2014 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 #include "extensions/shell/browser/api/identity/identity_api.h"
7 #include <set>
8 #include <string>
10 #include "base/guid.h"
11 #include "content/public/browser/browser_context.h"
12 #include "extensions/common/manifest_handlers/oauth2_manifest_handler.h"
13 #include "extensions/shell/browser/shell_oauth2_token_service.h"
14 #include "extensions/shell/common/api/identity.h"
15 #include "google_apis/gaia/gaia_auth_util.h"
17 namespace extensions {
18 namespace shell {
20 namespace {
21 const char kIdentityApiId[] = "identity_api";
22 const char kErrorNoUserAccount[] = "No user account.";
23 const char kErrorNoRefreshToken[] = "No refresh token.";
24 const char kErrorNoScopesInManifest[] = "No scopes in manifest.";
25 const char kErrorUserPermissionRequired[] =
26 "User permission required but not available in app_shell";
27 } // namespace
29 IdentityAPI::IdentityAPI(content::BrowserContext* context)
30 : device_id_(base::GenerateGUID()) {
33 IdentityAPI::~IdentityAPI() {
36 // static
37 IdentityAPI* IdentityAPI::Get(content::BrowserContext* context) {
38 return BrowserContextKeyedAPIFactory<IdentityAPI>::Get(context);
41 // static
42 BrowserContextKeyedAPIFactory<IdentityAPI>* IdentityAPI::GetFactoryInstance() {
43 static base::LazyInstance<BrowserContextKeyedAPIFactory<IdentityAPI>>
44 factory = LAZY_INSTANCE_INITIALIZER;
45 return factory.Pointer();
48 ///////////////////////////////////////////////////////////////////////////////
50 IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
51 : OAuth2TokenService::Consumer(kIdentityApiId) {
54 IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {
57 void IdentityGetAuthTokenFunction::SetMintTokenFlowForTesting(
58 OAuth2MintTokenFlow* flow) {
59 mint_token_flow_.reset(flow);
62 ExtensionFunction::ResponseAction IdentityGetAuthTokenFunction::Run() {
63 scoped_ptr<api::identity::GetAuthToken::Params> params(
64 api::identity::GetAuthToken::Params::Create(*args_));
65 EXTENSION_FUNCTION_VALIDATE(params.get());
67 ShellOAuth2TokenService* service = ShellOAuth2TokenService::GetInstance();
68 std::string account_id = service->AccountId();
69 if (account_id.empty())
70 return RespondNow(Error(kErrorNoUserAccount));
72 if (!service->RefreshTokenIsAvailable(account_id))
73 return RespondNow(Error(kErrorNoRefreshToken));
75 // Verify that we have scopes.
76 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension());
77 if (oauth2_info.scopes.empty())
78 return RespondNow(Error(kErrorNoScopesInManifest));
80 // Balanced in OnGetTokenFailure() and in the OAuth2MintTokenFlow callbacks.
81 AddRef();
83 // First, fetch a logged-in-user access token for the Chrome project client ID
84 // and client secret. This token is used later to get a second access token
85 // that will be returned to the app.
86 std::set<std::string> no_scopes;
87 access_token_request_ =
88 service->StartRequest(service->AccountId(), no_scopes, this);
89 return RespondLater();
92 void IdentityGetAuthTokenFunction::OnGetTokenSuccess(
93 const OAuth2TokenService::Request* request,
94 const std::string& access_token,
95 const base::Time& expiration_time) {
96 // Tests may override the mint token flow.
97 if (!mint_token_flow_) {
98 const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension());
99 DCHECK(!oauth2_info.scopes.empty());
101 mint_token_flow_.reset(new OAuth2MintTokenFlow(
102 this,
103 OAuth2MintTokenFlow::Parameters(
104 extension()->id(),
105 oauth2_info.client_id,
106 oauth2_info.scopes,
107 IdentityAPI::Get(browser_context())->device_id(),
108 OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE)));
111 // Use the logging-in-user access token to mint an access token for this app.
112 mint_token_flow_->Start(browser_context()->GetRequestContext(), access_token);
115 void IdentityGetAuthTokenFunction::OnGetTokenFailure(
116 const OAuth2TokenService::Request* request,
117 const GoogleServiceAuthError& error) {
118 Respond(Error(error.ToString()));
119 Release(); // Balanced in Run().
122 void IdentityGetAuthTokenFunction::OnMintTokenSuccess(
123 const std::string& access_token,
124 int time_to_live) {
125 Respond(OneArgument(new base::StringValue(access_token)));
126 Release(); // Balanced in Run().
129 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
130 const IssueAdviceInfo& issue_advice) {
131 Respond(Error(kErrorUserPermissionRequired));
132 Release(); // Balanced in Run().
135 void IdentityGetAuthTokenFunction::OnMintTokenFailure(
136 const GoogleServiceAuthError& error) {
137 Respond(Error(error.ToString()));
138 Release(); // Balanced in Run().
141 ///////////////////////////////////////////////////////////////////////////////
143 IdentityRemoveCachedAuthTokenFunction::IdentityRemoveCachedAuthTokenFunction() {
146 IdentityRemoveCachedAuthTokenFunction::
147 ~IdentityRemoveCachedAuthTokenFunction() {
150 ExtensionFunction::ResponseAction IdentityRemoveCachedAuthTokenFunction::Run() {
151 scoped_ptr<api::identity::RemoveCachedAuthToken::Params> params(
152 api::identity::RemoveCachedAuthToken::Params::Create(*args_));
153 EXTENSION_FUNCTION_VALIDATE(params.get());
154 // This stub identity API does not maintain a token cache, so there is nothing
155 // to remove.
156 return RespondNow(NoArguments());
159 } // namespace shell
160 } // namespace extensions