identity_api.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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)#include "chrome/browser/extensions/api/identity/identity_api.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <set>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/stringprintf.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/app_mode/app_mode_utils.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_function_dispatcher.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_install_prompt.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/permissions_updater.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/signin_manager.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/signin/token_service.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/signin/token_service_factory.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/api/identity.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/extension_manifest_constants.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/page_transition_types.h"
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/window_open_disposition.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/login/user_manager.h"
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace identity_constants {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidClientId[] = "Invalid OAuth2 Client ID.";
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidScopes[] = "Invalid OAuth2 scopes.";
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAuthFailure[] = "OAuth2 request failed: ";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNoGrant[] = "OAuth2 not granted or revoked.";
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUserRejected[] = "The user did not approve access.";
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUserNotSignedIn[] = "The user is not signed in.";
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kInteractionRequired[] = "User interaction required.";
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidRedirect[] = "Did not redirect to the right URL.";
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOffTheRecord[] = "Identity API is disabled in incognito windows.";
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kCachedIssueAdviceTTLSeconds = 1;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace identity_constants
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const char kChromiumDomainRedirectUrlPattern[] =
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "https://%s.chromiumapp.org/";
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace identity = api::identity;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : should_prompt_for_scopes_(false),
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      should_prompt_for_signin_(false) {}
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IdentityGetAuthTokenFunction::RunImpl() {
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (profile()->IsOffTheRecord()) {
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_ = identity_constants::kOffTheRecord;
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<identity::GetAuthToken::Params> params(
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      identity::GetAuthToken::Params::Create(*args_));
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool interactive = params->details.get() &&
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params->details->interactive.get() &&
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      *params->details->interactive;
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_scopes_ = interactive;
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_signin_ = interactive;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check that the necessary information is present in the manifest.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (oauth2_info.client_id.empty()) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = identity_constants::kInvalidClientId;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (oauth2_info.scopes.size() == 0) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = identity_constants::kInvalidScopes;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Balanced in CompleteFunctionWithResult|CompleteFunctionWithError
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HasLoginToken()) {
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!should_prompt_for_signin_) {
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_ = identity_constants::kUserNotSignedIn;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Release();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Display a login prompt.
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StartSigninFlow();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    refresh_token_ = token_service->GetOAuth2LoginRefreshToken();
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::CompleteFunctionWithResult(
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& access_token) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetResult(Value::CreateStringValue(access_token));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendResponse(true);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in RunImpl.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::CompleteFunctionWithError(
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error) {
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_ = error;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendResponse(false);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in RunImpl.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartSigninFlow() {
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // All cached tokens are invalid because the user is not signed in.
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI* id_api =
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(profile_);
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  id_api->EraseAllCachedTokens();
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Display a login prompt. If the subsequent mint fails, don't display the
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // login prompt again.
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_signin_ = false;
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ShowLoginPopup();
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartMintTokenFlow(
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IdentityMintRequestQueue::MintType type) {
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mint_token_flow_type_ = type;
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Flows are serialized to prevent excessive traffic to GAIA, and
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to consolidate UI pop-ups.
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::set<std::string> scopes(oauth2_info.scopes.begin(),
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               oauth2_info.scopes.end());
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI* id_api =
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(profile_);
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!should_prompt_for_scopes_) {
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Caller requested no interaction.
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE) {
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // GAIA told us to do a consent UI.
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteFunctionWithError(identity_constants::kNoGrant);
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!id_api->mint_queue()->empty(
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE,
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            GetExtension()->id(), scopes)) {
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Another call is going through a consent UI.
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteFunctionWithError(identity_constants::kNoGrant);
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  id_api->mint_queue()->RequestStart(type,
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     GetExtension()->id(),
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     scopes,
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     this);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() {
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityMintRequestQueue::MintType type = mint_token_flow_type_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::set<std::string> scopes(oauth2_info.scopes.begin(),
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               oauth2_info.scopes.end());
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile_)->mint_queue()->RequestComplete(type,
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               GetExtension()->id(),
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               scopes,
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               this);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartMintToken(
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IdentityMintRequestQueue::MintType type) {
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI* id_api = IdentityAPI::GetFactoryInstance()->GetForProfile(
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile());
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityTokenCacheValue cache_entry = id_api->GetCachedToken(
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetExtension()->id(), oauth2_info.scopes);
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityTokenCacheValue::CacheValueStatus cache_status =
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      cache_entry.status();
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (type == IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE) {
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    switch (cache_status) {
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND:
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        StartGaiaRequest(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case IdentityTokenCacheValue::CACHE_STATUS_TOKEN:
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CompleteMintTokenFlow();
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CompleteFunctionWithResult(cache_entry.token());
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case IdentityTokenCacheValue::CACHE_STATUS_ADVICE:
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CompleteMintTokenFlow();
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        should_prompt_for_signin_ = false;
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        issue_advice_ = cache_entry.issue_advice();
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (cache_status == IdentityTokenCacheValue::CACHE_STATUS_TOKEN) {
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteMintTokenFlow();
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteFunctionWithResult(cache_entry.token());
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      install_ui_.reset(new ExtensionInstallPrompt(GetAssociatedWebContents()));
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ShowOAuthApprovalDialog(issue_advice_);
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnMintTokenSuccess(
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& access_token, int time_to_live) {
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityTokenCacheValue token(access_token,
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                base::TimeDelta::FromSeconds(time_to_live));
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI::GetFactoryInstance()->GetForProfile(profile())->SetCachedToken(
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetExtension()->id(), oauth2_info.scopes, token);
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteFunctionWithResult(access_token);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnMintTokenFailure(
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GoogleServiceAuthError& error) {
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (error.state()) {
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case GoogleServiceAuthError::ACCOUNT_DELETED:
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case GoogleServiceAuthError::ACCOUNT_DISABLED:
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          profile())->ReportAuthError(error);
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (should_prompt_for_signin_) {
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Display a login prompt and try again (once).
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        StartSigninFlow();
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return;
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Return error to caller.
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteFunctionWithError(
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string(identity_constants::kAuthFailure) + error.ToString());
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IssueAdviceInfo& issue_advice) {
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI::GetFactoryInstance()->GetForProfile(profile())->SetCachedToken(
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetExtension()->id(), oauth2_info.scopes,
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      IdentityTokenCacheValue(issue_advice));
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_signin_ = false;
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Existing grant was revoked and we used NO_FORCE, so we got info back
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // instead. Start a consent UI if we can.
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  issue_advice_ = issue_advice;
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::SigninSuccess(const std::string& token) {
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  refresh_token_ = token;
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::SigninFailed() {
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::InstallUIProceed() {
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The user has accepted the scopes, so we may now force (recording a grant
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // and receiving a token).
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartGaiaRequest(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE);
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::InstallUIAbort(bool user_initiated) {
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteFunctionWithError(identity_constants::kUserRejected);
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartGaiaRequest(
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    OAuth2MintTokenFlow::Mode mode) {
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mint_token_flow_.reset(CreateMintTokenFlow(mode));
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mint_token_flow_->Start();
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::ShowLoginPopup() {
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  signin_flow_.reset(new IdentitySigninFlow(this, profile()));
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  signin_flow_->Start();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog(
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IssueAdviceInfo& issue_advice) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  install_ui_->ConfirmIssueAdvice(this, GetExtension(), issue_advice);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OAuth2MintTokenFlow* IdentityGetAuthTokenFunction::CreateMintTokenFlow(
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OAuth2MintTokenFlow::Mode mode) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OAuth2MintTokenFlow* mint_token_flow =
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new OAuth2MintTokenFlow(
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          profile()->GetRequestContext(),
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          this,
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          OAuth2MintTokenFlow::Parameters(
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              refresh_token_,
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              GetExtension()->id(),
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              oauth2_info.client_id,
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              oauth2_info.scopes,
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              mode));
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS)
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (chrome::IsRunningInForcedAppMode()) {
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string chrome_client_id;
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string chrome_client_secret;
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (chromeos::UserManager::Get()->GetAppModeChromeClientOAuthInfo(
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           &chrome_client_id, &chrome_client_secret)) {
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mint_token_flow->SetChromeOAuthClientInfo(chrome_client_id,
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                chrome_client_secret);
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return mint_token_flow;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IdentityGetAuthTokenFunction::HasLoginToken() const {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return token_service->HasOAuthLoginToken();
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityRemoveCachedAuthTokenFunction::IdentityRemoveCachedAuthTokenFunction() {
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityRemoveCachedAuthTokenFunction::
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ~IdentityRemoveCachedAuthTokenFunction() {
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IdentityRemoveCachedAuthTokenFunction::RunImpl() {
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (profile()->IsOffTheRecord()) {
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_ = identity_constants::kOffTheRecord;
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<identity::RemoveCachedAuthToken::Params> params(
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      identity::RemoveCachedAuthToken::Params::Create(*args_));
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI::GetFactoryInstance()->GetForProfile(profile())->EraseCachedToken(
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetExtension()->id(), params->details.token);
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IdentityLaunchWebAuthFlowFunction::IdentityLaunchWebAuthFlowFunction() {}
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IdentityLaunchWebAuthFlowFunction::~IdentityLaunchWebAuthFlowFunction() {}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IdentityLaunchWebAuthFlowFunction::RunImpl() {
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (profile()->IsOffTheRecord()) {
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_ = identity_constants::kOffTheRecord;
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<identity::LaunchWebAuthFlow::Params> params(
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      identity::LaunchWebAuthFlow::Params::Create(*args_));
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL auth_url(params->details.url);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebAuthFlow::Mode mode =
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params->details.interactive && *params->details.interactive ?
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebAuthFlow::INTERACTIVE : WebAuthFlow::SILENT;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Set up acceptable target URLs. (Does not include chrome-extension
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // scheme for this version of the API.)
394b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  InitFinalRedirectURLPrefix(GetExtension()->id());
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect initial_bounds;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();  // Balanced in OnAuthFlowSuccess/Failure.
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Browser* current_browser = this->GetCurrentBrowser();
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chrome::HostDesktopType host_desktop_type = current_browser ?
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_browser->host_desktop_type() : chrome::GetActiveDesktop();
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_flow_.reset(new WebAuthFlow(
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      this, profile(), auth_url, mode, initial_bounds,
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_desktop_type));
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_flow_->Start();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
410b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::InitFinalRedirectURLPrefixForTest(
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& extension_id) {
412b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  InitFinalRedirectURLPrefix(extension_id);
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
415b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::InitFinalRedirectURLPrefix(
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& extension_id) {
417b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (final_url_prefix_.is_empty()) {
418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    final_url_prefix_ = GURL(base::StringPrintf(
419b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        kChromiumDomainRedirectUrlPattern, extension_id.c_str()));
420b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::OnAuthFlowFailure(
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebAuthFlow::Failure failure) {
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (failure) {
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case WebAuthFlow::WINDOW_CLOSED:
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_ = identity_constants::kUserRejected;
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case WebAuthFlow::INTERACTION_REQUIRED:
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_ = identity_constants::kInteractionRequired;
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NOTREACHED() << "Unexpected error from web auth flow: " << failure;
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_ = identity_constants::kInvalidRedirect;
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendResponse(false);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in RunImpl.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::OnAuthFlowURLChange(
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GURL& redirect_url) {
443b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (redirect_url.GetWithEmptyPath() == final_url_prefix_) {
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetResult(Value::CreateStringValue(redirect_url.spec()));
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(true);
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Release();  // Balanced in RunImpl.
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityTokenCacheValue::IdentityTokenCacheValue()
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : status_(CACHE_STATUS_NOTFOUND) {
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityTokenCacheValue::IdentityTokenCacheValue(
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IssueAdviceInfo& issue_advice) : status_(CACHE_STATUS_ADVICE),
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           issue_advice_(issue_advice) {
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expiration_time_ = base::Time::Now() + base::TimeDelta::FromSeconds(
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      identity_constants::kCachedIssueAdviceTTLSeconds);
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityTokenCacheValue::IdentityTokenCacheValue(
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& token, base::TimeDelta time_to_live)
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : status_(CACHE_STATUS_TOKEN),
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      token_(token) {
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeDelta zero_delta;
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (time_to_live < zero_delta)
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    time_to_live = zero_delta;
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expiration_time_ = base::Time::Now() + time_to_live;
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityTokenCacheValue::~IdentityTokenCacheValue() {
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityTokenCacheValue::CacheValueStatus
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IdentityTokenCacheValue::status() const {
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (is_expired())
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND;
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status_;
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const IssueAdviceInfo& IdentityTokenCacheValue::issue_advice() const {
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return issue_advice_;
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string& IdentityTokenCacheValue::token() const {
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return token_;
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IdentityTokenCacheValue::is_expired() const {
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return status_ == CACHE_STATUS_NOTFOUND ||
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expiration_time_ < base::Time::Now();
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityAPI::IdentityAPI(Profile* profile)
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : profile_(profile),
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      signin_manager_(NULL),
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_(GoogleServiceAuthError::NONE) {
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IdentityAPI::~IdentityAPI() {
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::Initialize() {
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  signin_manager_ = SigninManagerFactory::GetForProfile(profile_);
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  signin_manager_->signin_global_error()->AddProvider(this);
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registrar_.Add(this,
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 chrome::NOTIFICATION_TOKEN_AVAILABLE,
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 content::Source<TokenService>(token_service));
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityMintRequestQueue* IdentityAPI::mint_queue() {
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return &mint_queue_;
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::SetCachedToken(const std::string& extension_id,
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 const std::vector<std::string> scopes,
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 const IdentityTokenCacheValue& token_data) {
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::set<std::string> scopeset(scopes.begin(), scopes.end());
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TokenCacheKey key(extension_id, scopeset);
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::map<TokenCacheKey, IdentityTokenCacheValue>::iterator it =
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      token_cache_.find(key);
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (it != token_cache_.end() && it->second.status() <= token_data.status())
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    token_cache_.erase(it);
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  token_cache_.insert(std::make_pair(key, token_data));
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::EraseCachedToken(const std::string& extension_id,
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   const std::string& token) {
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::map<TokenCacheKey, IdentityTokenCacheValue>::iterator it;
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (it = token_cache_.begin(); it != token_cache_.end(); ++it) {
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (it->first.extension_id == extension_id &&
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        it->second.status() == IdentityTokenCacheValue::CACHE_STATUS_TOKEN &&
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        it->second.token() == token) {
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      token_cache_.erase(it);
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::EraseAllCachedTokens() {
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  token_cache_.clear();
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const IdentityTokenCacheValue& IdentityAPI::GetCachedToken(
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& extension_id, const std::vector<std::string> scopes) {
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::set<std::string> scopeset(scopes.begin(), scopes.end());
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TokenCacheKey key(extension_id, scopeset);
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return token_cache_[key];
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) {
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!signin_manager_)
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Initialize();
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_ = error;
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  signin_manager_->signin_global_error()->AuthStatusChanged();
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::Shutdown() {
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (signin_manager_)
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    signin_manager_->signin_global_error()->RemoveProvider(this);
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static base::LazyInstance<ProfileKeyedAPIFactory<IdentityAPI> >
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    g_factory = LAZY_INSTANCE_INITIALIZER;
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProfileKeyedAPIFactory<IdentityAPI>* IdentityAPI::GetFactoryInstance() {
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return &g_factory.Get();
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GoogleServiceAuthError IdentityAPI::GetAuthStatus() const {
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return error_;
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::Observe(int type,
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const content::NotificationSource& source,
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const content::NotificationDetails& details) {
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE);
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TokenService::TokenAvailableDetails* token_details =
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::Details<TokenService::TokenAvailableDetails>(details).ptr();
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (token_details->service() ==
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_ = GoogleServiceAuthError::AuthErrorNone();
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    signin_manager_->signin_global_error()->AuthStatusChanged();
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)template <>
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ProfileKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies() {
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DependsOn(ExtensionSystemFactory::GetInstance());
598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DependsOn(TokenServiceFactory::GetInstance());
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DependsOn(SigninManagerFactory::GetInstance());
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityAPI::TokenCacheKey::TokenCacheKey(const std::string& extension_id,
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const std::set<std::string> scopes)
604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : extension_id(extension_id),
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      scopes(scopes) {
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityAPI::TokenCacheKey::~TokenCacheKey() {
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IdentityAPI::TokenCacheKey::operator<(
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IdentityAPI::TokenCacheKey& rhs) const {
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (extension_id < rhs.extension_id)
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else if (rhs.extension_id < extension_id)
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return scopes < rhs.scopes;
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
622