identity_api.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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>
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <utility>
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/stringprintf.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/app_mode/app_mode_utils.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_function_dispatcher.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_install_prompt.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/permissions_updater.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/signin_manager.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/signin/token_service.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/signin/token_service_factory.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/api/identity.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/extension_manifest_constants.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/page_transition_types.h"
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/window_open_disposition.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS)
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/login/user_manager.h"
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace identity_constants {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidClientId[] = "Invalid OAuth2 Client ID.";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidScopes[] = "Invalid OAuth2 scopes.";
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAuthFailure[] = "OAuth2 request failed: ";
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNoGrant[] = "OAuth2 not granted or revoked.";
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUserRejected[] = "The user did not approve access.";
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUserNotSignedIn[] = "The user is not signed in.";
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kInteractionRequired[] = "User interaction required.";
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidRedirect[] = "Did not redirect to the right URL.";
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOffTheRecord[] = "Identity API is disabled in incognito windows.";
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kCachedIssueAdviceTTLSeconds = 1;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace identity_constants
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const char kChromiumDomainRedirectUrlPattern[] =
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "https://%s.chromiumapp.org/";
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace identity = api::identity;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : should_prompt_for_scopes_(false),
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      should_prompt_for_signin_(false) {}
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IdentityGetAuthTokenFunction::RunImpl() {
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (profile()->IsOffTheRecord()) {
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_ = identity_constants::kOffTheRecord;
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<identity::GetAuthToken::Params> params(
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      identity::GetAuthToken::Params::Create(*args_));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool interactive = params->details.get() &&
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params->details->interactive.get() &&
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      *params->details->interactive;
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_scopes_ = interactive;
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_signin_ = interactive;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check that the necessary information is present in the manifest.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (oauth2_info.client_id.empty()) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = identity_constants::kInvalidClientId;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (oauth2_info.scopes.size() == 0) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = identity_constants::kInvalidScopes;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Balanced in CompleteFunctionWithResult|CompleteFunctionWithError
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HasLoginToken()) {
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!should_prompt_for_signin_) {
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_ = identity_constants::kUserNotSignedIn;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Release();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Display a login prompt.
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StartSigninFlow();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    refresh_token_ = token_service->GetOAuth2LoginRefreshToken();
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::CompleteFunctionWithResult(
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& access_token) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetResult(Value::CreateStringValue(access_token));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendResponse(true);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in RunImpl.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::CompleteFunctionWithError(
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error) {
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_ = error;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendResponse(false);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in RunImpl.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartSigninFlow() {
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // All cached tokens are invalid because the user is not signed in.
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI* id_api =
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(profile_);
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  id_api->EraseAllCachedTokens();
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Display a login prompt. If the subsequent mint fails, don't display the
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // login prompt again.
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_signin_ = false;
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ShowLoginPopup();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartMintTokenFlow(
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IdentityMintRequestQueue::MintType type) {
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mint_token_flow_type_ = type;
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Flows are serialized to prevent excessive traffic to GAIA, and
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to consolidate UI pop-ups.
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::set<std::string> scopes(oauth2_info.scopes.begin(),
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               oauth2_info.scopes.end());
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI* id_api =
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(profile_);
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!should_prompt_for_scopes_) {
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Caller requested no interaction.
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE) {
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // GAIA told us to do a consent UI.
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteFunctionWithError(identity_constants::kNoGrant);
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!id_api->mint_queue()->empty(
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE,
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            GetExtension()->id(), scopes)) {
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Another call is going through a consent UI.
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteFunctionWithError(identity_constants::kNoGrant);
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  id_api->mint_queue()->RequestStart(type,
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     GetExtension()->id(),
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     scopes,
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     this);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() {
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityMintRequestQueue::MintType type = mint_token_flow_type_;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::set<std::string> scopes(oauth2_info.scopes.begin(),
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               oauth2_info.scopes.end());
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile_)->mint_queue()->RequestComplete(type,
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               GetExtension()->id(),
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               scopes,
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               this);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartMintToken(
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IdentityMintRequestQueue::MintType type) {
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI* id_api = IdentityAPI::GetFactoryInstance()->GetForProfile(
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      profile());
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityTokenCacheValue cache_entry = id_api->GetCachedToken(
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetExtension()->id(), oauth2_info.scopes);
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityTokenCacheValue::CacheValueStatus cache_status =
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      cache_entry.status();
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (type == IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE) {
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    switch (cache_status) {
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND:
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        StartGaiaRequest(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case IdentityTokenCacheValue::CACHE_STATUS_TOKEN:
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CompleteMintTokenFlow();
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CompleteFunctionWithResult(cache_entry.token());
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case IdentityTokenCacheValue::CACHE_STATUS_ADVICE:
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CompleteMintTokenFlow();
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        should_prompt_for_signin_ = false;
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        issue_advice_ = cache_entry.issue_advice();
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (cache_status == IdentityTokenCacheValue::CACHE_STATUS_TOKEN) {
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteMintTokenFlow();
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteFunctionWithResult(cache_entry.token());
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ShowOAuthApprovalDialog(issue_advice_);
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnMintTokenSuccess(
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& access_token, int time_to_live) {
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityTokenCacheValue token(access_token,
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                base::TimeDelta::FromSeconds(time_to_live));
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI::GetFactoryInstance()->GetForProfile(profile())->SetCachedToken(
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetExtension()->id(), oauth2_info.scopes, token);
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteFunctionWithResult(access_token);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnMintTokenFailure(
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GoogleServiceAuthError& error) {
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (error.state()) {
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case GoogleServiceAuthError::ACCOUNT_DELETED:
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case GoogleServiceAuthError::ACCOUNT_DISABLED:
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          profile())->ReportAuthError(error);
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (should_prompt_for_signin_) {
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Display a login prompt and try again (once).
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        StartSigninFlow();
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return;
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Return error to caller.
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteFunctionWithError(
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string(identity_constants::kAuthFailure) + error.ToString());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IssueAdviceInfo& issue_advice) {
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI::GetFactoryInstance()->GetForProfile(profile())->SetCachedToken(
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetExtension()->id(), oauth2_info.scopes,
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      IdentityTokenCacheValue(issue_advice));
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_signin_ = false;
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Existing grant was revoked and we used NO_FORCE, so we got info back
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // instead. Start a consent UI if we can.
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  issue_advice_ = issue_advice;
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::SigninSuccess(const std::string& token) {
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  refresh_token_ = token;
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::SigninFailed() {
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnGaiaFlowFailure(
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    GaiaWebAuthFlow::Failure failure,
29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    GoogleServiceAuthError service_error,
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& oauth_error) {
29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CompleteMintTokenFlow();
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string error;
30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (failure) {
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GaiaWebAuthFlow::WINDOW_CLOSED:
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = identity_constants::kUserRejected;
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GaiaWebAuthFlow::INVALID_REDIRECT:
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = identity_constants::kInvalidRedirect;
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GaiaWebAuthFlow::SERVICE_AUTH_ERROR:
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = std::string(identity_constants::kAuthFailure) +
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          service_error.ToString();
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GaiaWebAuthFlow::OAUTH_ERROR:
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = MapOAuth2ErrorToDescription(oauth_error);
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED() << "Unexpected error from gaia web auth flow: " << failure;
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = identity_constants::kInvalidRedirect;
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CompleteFunctionWithError(error);
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnGaiaFlowCompleted(
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& access_token,
33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& expiration) {
33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int time_to_live;
33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!expiration.empty() && base::StringToInt(expiration, &time_to_live)) {
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    IdentityTokenCacheValue token_value(
33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        access_token, base::TimeDelta::FromSeconds(time_to_live));
33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    IdentityAPI::GetFactoryInstance()->GetForProfile(profile())
33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ->SetCachedToken(GetExtension()->id(), oauth2_info.scopes, token_value);
34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CompleteFunctionWithResult(access_token);
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartGaiaRequest(
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    OAuth2MintTokenFlow::Mode mode) {
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mint_token_flow_.reset(CreateMintTokenFlow(mode));
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mint_token_flow_->Start();
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::ShowLoginPopup() {
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  signin_flow_.reset(new IdentitySigninFlow(this, profile()));
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  signin_flow_->Start();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IssueAdviceInfo& issue_advice) {
35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Browser* current_browser = this->GetCurrentBrowser();
36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  chrome::HostDesktopType host_desktop_type =
36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      current_browser ? current_browser->host_desktop_type()
36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      : chrome::GetActiveDesktop();
36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  gaia_web_auth_flow_.reset(new GaiaWebAuthFlow(
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      this, profile(), host_desktop_type, GetExtension()->id(), oauth2_info));
36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  gaia_web_auth_flow_->Start();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OAuth2MintTokenFlow* IdentityGetAuthTokenFunction::CreateMintTokenFlow(
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OAuth2MintTokenFlow::Mode mode) {
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OAuth2MintTokenFlow* mint_token_flow =
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new OAuth2MintTokenFlow(
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          profile()->GetRequestContext(),
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          this,
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          OAuth2MintTokenFlow::Parameters(
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              refresh_token_,
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              GetExtension()->id(),
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              oauth2_info.client_id,
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              oauth2_info.scopes,
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              mode));
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS)
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (chrome::IsRunningInForcedAppMode()) {
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string chrome_client_id;
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string chrome_client_secret;
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (chromeos::UserManager::Get()->GetAppModeChromeClientOAuthInfo(
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           &chrome_client_id, &chrome_client_secret)) {
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mint_token_flow->SetChromeOAuthClientInfo(chrome_client_id,
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                chrome_client_secret);
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return mint_token_flow;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IdentityGetAuthTokenFunction::HasLoginToken() const {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TokenService* token_service = TokenServiceFactory::GetForProfile(profile());
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return token_service->HasOAuthLoginToken();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string IdentityGetAuthTokenFunction::MapOAuth2ErrorToDescription(
40390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& error) {
40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char kOAuth2ErrorAccessDenied[] = "access_denied";
40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char kOAuth2ErrorInvalidScope[] = "invalid_scope";
40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error == kOAuth2ErrorAccessDenied)
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return std::string(identity_constants::kUserRejected);
40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else if (error == kOAuth2ErrorInvalidScope)
41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return std::string(identity_constants::kInvalidScopes);
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else
41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return std::string(identity_constants::kAuthFailure) + error;
41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
41490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityRemoveCachedAuthTokenFunction::IdentityRemoveCachedAuthTokenFunction() {
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityRemoveCachedAuthTokenFunction::
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ~IdentityRemoveCachedAuthTokenFunction() {
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IdentityRemoveCachedAuthTokenFunction::RunImpl() {
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (profile()->IsOffTheRecord()) {
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_ = identity_constants::kOffTheRecord;
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<identity::RemoveCachedAuthToken::Params> params(
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      identity::RemoveCachedAuthToken::Params::Create(*args_));
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI::GetFactoryInstance()->GetForProfile(profile())->EraseCachedToken(
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetExtension()->id(), params->details.token);
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IdentityLaunchWebAuthFlowFunction::IdentityLaunchWebAuthFlowFunction() {}
43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)IdentityLaunchWebAuthFlowFunction::~IdentityLaunchWebAuthFlowFunction() {
43990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (auth_flow_)
44090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    auth_flow_.release()->DetachDelegateAndDelete();
44190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IdentityLaunchWebAuthFlowFunction::RunImpl() {
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (profile()->IsOffTheRecord()) {
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_ = identity_constants::kOffTheRecord;
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<identity::LaunchWebAuthFlow::Params> params(
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      identity::LaunchWebAuthFlow::Params::Create(*args_));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL auth_url(params->details.url);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebAuthFlow::Mode mode =
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params->details.interactive && *params->details.interactive ?
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebAuthFlow::INTERACTIVE : WebAuthFlow::SILENT;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Set up acceptable target URLs. (Does not include chrome-extension
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // scheme for this version of the API.)
460b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  InitFinalRedirectURLPrefix(GetExtension()->id());
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect initial_bounds;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();  // Balanced in OnAuthFlowSuccess/Failure.
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Browser* current_browser = this->GetCurrentBrowser();
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chrome::HostDesktopType host_desktop_type = current_browser ?
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_browser->host_desktop_type() : chrome::GetActiveDesktop();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_flow_.reset(new WebAuthFlow(
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      this, profile(), auth_url, mode, initial_bounds,
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_desktop_type));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_flow_->Start();
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
476b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::InitFinalRedirectURLPrefixForTest(
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& extension_id) {
478b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  InitFinalRedirectURLPrefix(extension_id);
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
481b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::InitFinalRedirectURLPrefix(
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& extension_id) {
483b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (final_url_prefix_.is_empty()) {
484b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    final_url_prefix_ = GURL(base::StringPrintf(
485b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        kChromiumDomainRedirectUrlPattern, extension_id.c_str()));
486b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::OnAuthFlowFailure(
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebAuthFlow::Failure failure) {
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (failure) {
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case WebAuthFlow::WINDOW_CLOSED:
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_ = identity_constants::kUserRejected;
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case WebAuthFlow::INTERACTION_REQUIRED:
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_ = identity_constants::kInteractionRequired;
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NOTREACHED() << "Unexpected error from web auth flow: " << failure;
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_ = identity_constants::kInvalidRedirect;
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendResponse(false);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in RunImpl.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::OnAuthFlowURLChange(
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GURL& redirect_url) {
509b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (redirect_url.GetWithEmptyPath() == final_url_prefix_) {
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetResult(Value::CreateStringValue(redirect_url.spec()));
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(true);
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Release();  // Balanced in RunImpl.
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityTokenCacheValue::IdentityTokenCacheValue()
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : status_(CACHE_STATUS_NOTFOUND) {
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityTokenCacheValue::IdentityTokenCacheValue(
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IssueAdviceInfo& issue_advice) : status_(CACHE_STATUS_ADVICE),
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           issue_advice_(issue_advice) {
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expiration_time_ = base::Time::Now() + base::TimeDelta::FromSeconds(
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      identity_constants::kCachedIssueAdviceTTLSeconds);
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityTokenCacheValue::IdentityTokenCacheValue(
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& token, base::TimeDelta time_to_live)
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : status_(CACHE_STATUS_TOKEN),
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      token_(token) {
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeDelta zero_delta;
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (time_to_live < zero_delta)
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    time_to_live = zero_delta;
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expiration_time_ = base::Time::Now() + time_to_live;
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityTokenCacheValue::~IdentityTokenCacheValue() {
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityTokenCacheValue::CacheValueStatus
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IdentityTokenCacheValue::status() const {
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (is_expired())
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND;
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status_;
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const IssueAdviceInfo& IdentityTokenCacheValue::issue_advice() const {
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return issue_advice_;
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string& IdentityTokenCacheValue::token() const {
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return token_;
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IdentityTokenCacheValue::is_expired() const {
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return status_ == CACHE_STATUS_NOTFOUND ||
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expiration_time_ < base::Time::Now();
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const base::Time& IdentityTokenCacheValue::expiration_time() const {
56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return expiration_time_;
56490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityAPI::IdentityAPI(Profile* profile)
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : profile_(profile),
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      signin_manager_(NULL),
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_(GoogleServiceAuthError::NONE) {
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IdentityAPI::~IdentityAPI() {
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::Initialize() {
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  signin_manager_ = SigninManagerFactory::GetForProfile(profile_);
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  signin_manager_->signin_global_error()->AddProvider(this);
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registrar_.Add(this,
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 chrome::NOTIFICATION_TOKEN_AVAILABLE,
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 content::Source<TokenService>(token_service));
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityMintRequestQueue* IdentityAPI::mint_queue() {
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return &mint_queue_;
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::SetCachedToken(const std::string& extension_id,
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 const std::vector<std::string> scopes,
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 const IdentityTokenCacheValue& token_data) {
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::set<std::string> scopeset(scopes.begin(), scopes.end());
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TokenCacheKey key(extension_id, scopeset);
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
59590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CachedTokens::iterator it = token_cache_.find(key);
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (it != token_cache_.end() && it->second.status() <= token_data.status())
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    token_cache_.erase(it);
598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  token_cache_.insert(std::make_pair(key, token_data));
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::EraseCachedToken(const std::string& extension_id,
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   const std::string& token) {
60490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CachedTokens::iterator it;
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (it = token_cache_.begin(); it != token_cache_.end(); ++it) {
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (it->first.extension_id == extension_id &&
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        it->second.status() == IdentityTokenCacheValue::CACHE_STATUS_TOKEN &&
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        it->second.token() == token) {
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      token_cache_.erase(it);
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::EraseAllCachedTokens() {
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  token_cache_.clear();
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const IdentityTokenCacheValue& IdentityAPI::GetCachedToken(
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& extension_id, const std::vector<std::string> scopes) {
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::set<std::string> scopeset(scopes.begin(), scopes.end());
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TokenCacheKey key(extension_id, scopeset);
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return token_cache_[key];
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const IdentityAPI::CachedTokens& IdentityAPI::GetAllCachedTokens() {
62790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return token_cache_;
62890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
62990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) {
631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!signin_manager_)
632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Initialize();
633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_ = error;
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  signin_manager_->signin_global_error()->AuthStatusChanged();
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::Shutdown() {
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (signin_manager_)
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    signin_manager_->signin_global_error()->RemoveProvider(this);
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static base::LazyInstance<ProfileKeyedAPIFactory<IdentityAPI> >
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    g_factory = LAZY_INSTANCE_INITIALIZER;
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProfileKeyedAPIFactory<IdentityAPI>* IdentityAPI::GetFactoryInstance() {
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return &g_factory.Get();
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GoogleServiceAuthError IdentityAPI::GetAuthStatus() const {
652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return error_;
653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityAPI::Observe(int type,
656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const content::NotificationSource& source,
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const content::NotificationDetails& details) {
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE);
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TokenService::TokenAvailableDetails* token_details =
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      content::Details<TokenService::TokenAvailableDetails>(details).ptr();
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (token_details->service() ==
662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GaiaConstants::kGaiaOAuth2LoginRefreshToken) {
663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_ = GoogleServiceAuthError::AuthErrorNone();
664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    signin_manager_->signin_global_error()->AuthStatusChanged();
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)template <>
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ProfileKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies() {
670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DependsOn(ExtensionSystemFactory::GetInstance());
671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DependsOn(TokenServiceFactory::GetInstance());
672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DependsOn(SigninManagerFactory::GetInstance());
673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityAPI::TokenCacheKey::TokenCacheKey(const std::string& extension_id,
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const std::set<std::string> scopes)
677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : extension_id(extension_id),
678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      scopes(scopes) {
679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityAPI::TokenCacheKey::~TokenCacheKey() {
682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IdentityAPI::TokenCacheKey::operator<(
685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IdentityAPI::TokenCacheKey& rhs) const {
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (extension_id < rhs.extension_id)
687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else if (rhs.extension_id < extension_id)
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return scopes < rhs.scopes;
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
695