identity_api.cc revision 010d83a9304c5a91596085d917d248abff47903a
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"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/prefs/pref_service.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/app_mode/app_mode_utils.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/browser_process.h"
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/signin/signin_global_error.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/signin/signin_manager_factory.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/api/identity.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h"
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/pref_names.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/signin/core/browser/profile_oauth2_token_service.h"
30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "components/signin/core/browser/signin_manager.h"
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h"
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extension_function_dispatcher.h"
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "google_apis/gaia/gaia_urls.h"
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS)
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/login/user_manager.h"
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace identity_constants {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidClientId[] = "Invalid OAuth2 Client ID.";
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidScopes[] = "Invalid OAuth2 scopes.";
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAuthFailure[] = "OAuth2 request failed: ";
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNoGrant[] = "OAuth2 not granted or revoked.";
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUserRejected[] = "The user did not approve access.";
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUserNotSignedIn[] = "The user is not signed in.";
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kInteractionRequired[] = "User interaction required.";
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidRedirect[] = "Did not redirect to the right URL.";
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kOffTheRecord[] = "Identity API is disabled in incognito windows.";
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kPageLoadFailure[] = "Authorization page could not be loaded.";
58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char kCanceled[] = "canceled";
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kCachedIssueAdviceTTLSeconds = 1;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace identity_constants
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const char kChromiumDomainRedirectUrlPattern[] =
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "https://%s.chromiumapp.org/";
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string GetPrimaryAccountId(content::BrowserContext* context) {
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SigninManagerBase* signin_manager =
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      SigninManagerFactory::GetForProfile(Profile::FromBrowserContext(context));
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return signin_manager->GetAuthenticatedAccountId();
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace identity = api::identity;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochIdentityTokenCacheValue::IdentityTokenCacheValue()
79e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    : status_(CACHE_STATUS_NOTFOUND) {}
80e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
81e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochIdentityTokenCacheValue::IdentityTokenCacheValue(
82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const IssueAdviceInfo& issue_advice)
83e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    : status_(CACHE_STATUS_ADVICE), issue_advice_(issue_advice) {
84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  expiration_time_ =
85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      base::Time::Now() + base::TimeDelta::FromSeconds(
86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                              identity_constants::kCachedIssueAdviceTTLSeconds);
87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochIdentityTokenCacheValue::IdentityTokenCacheValue(const std::string& token,
90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                                 base::TimeDelta time_to_live)
91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    : status_(CACHE_STATUS_TOKEN), token_(token) {
92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Remove 20 minutes from the ttl so cached tokens will have some time
93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // to live any time they are returned.
94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  time_to_live -= base::TimeDelta::FromMinutes(20);
95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::TimeDelta zero_delta;
97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (time_to_live < zero_delta)
98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    time_to_live = zero_delta;
99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  expiration_time_ = base::Time::Now() + time_to_live;
101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
103e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochIdentityTokenCacheValue::~IdentityTokenCacheValue() {}
104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochIdentityTokenCacheValue::CacheValueStatus IdentityTokenCacheValue::status()
106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const {
107e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (is_expired())
108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND;
109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  else
110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return status_;
111e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
113e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst IssueAdviceInfo& IdentityTokenCacheValue::issue_advice() const {
114e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return issue_advice_;
115e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
116e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst std::string& IdentityTokenCacheValue::token() const { return token_; }
118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool IdentityTokenCacheValue::is_expired() const {
120e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return status_ == CACHE_STATUS_NOTFOUND ||
121e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch         expiration_time_ < base::Time::Now();
122e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst base::Time& IdentityTokenCacheValue::expiration_time() const {
125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return expiration_time_;
126e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
127e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
128e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochIdentityAPI::IdentityAPI(content::BrowserContext* context)
129e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    : browser_context_(context),
130e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      account_tracker_(Profile::FromBrowserContext(context)) {
131e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  account_tracker_.AddObserver(this);
132e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
133e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
134e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochIdentityAPI::~IdentityAPI() {}
135e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
136e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochIdentityMintRequestQueue* IdentityAPI::mint_queue() { return &mint_queue_; }
137e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
138e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityAPI::SetCachedToken(const ExtensionTokenKey& key,
139e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 const IdentityTokenCacheValue& token_data) {
140e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CachedTokens::iterator it = token_cache_.find(key);
141e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (it != token_cache_.end() && it->second.status() <= token_data.status())
142e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    token_cache_.erase(it);
143e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  token_cache_.insert(std::make_pair(key, token_data));
145e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
146e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
147e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityAPI::EraseCachedToken(const std::string& extension_id,
148e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   const std::string& token) {
149e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CachedTokens::iterator it;
150e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (it = token_cache_.begin(); it != token_cache_.end(); ++it) {
151e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (it->first.extension_id == extension_id &&
152e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        it->second.status() == IdentityTokenCacheValue::CACHE_STATUS_TOKEN &&
153e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        it->second.token() == token) {
154e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      token_cache_.erase(it);
155e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      break;
156e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
157e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
158e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
159e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
160e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityAPI::EraseAllCachedTokens() { token_cache_.clear(); }
161e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
162e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst IdentityTokenCacheValue& IdentityAPI::GetCachedToken(
163e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const ExtensionTokenKey& key) {
164e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return token_cache_[key];
165e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
166e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
167e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst IdentityAPI::CachedTokens& IdentityAPI::GetAllCachedTokens() {
168e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return token_cache_;
169e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
170e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
171e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityAPI::ReportAuthError(const GoogleServiceAuthError& error) {
172e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  account_tracker_.ReportAuthError(GetPrimaryAccountId(browser_context_),
173e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                   error);
174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
175e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
176e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochGoogleServiceAuthError IdentityAPI::GetAuthStatusForTest() const {
177e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return account_tracker_.GetAuthStatus();
178e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
179e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
180e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityAPI::Shutdown() {
181e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  FOR_EACH_OBSERVER(ShutdownObserver, shutdown_observer_list_, OnShutdown());
182e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  account_tracker_.RemoveObserver(this);
183e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  account_tracker_.Shutdown();
184e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
185e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
186e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochstatic base::LazyInstance<BrowserContextKeyedAPIFactory<IdentityAPI> >
187e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    g_factory = LAZY_INSTANCE_INITIALIZER;
188e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
189e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// static
190e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBrowserContextKeyedAPIFactory<IdentityAPI>* IdentityAPI::GetFactoryInstance() {
191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return g_factory.Pointer();
192e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
193e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
194e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityAPI::OnAccountAdded(const AccountIds& ids) {}
195e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
196e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityAPI::OnAccountRemoved(const AccountIds& ids) {}
197e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
198e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityAPI::OnAccountSignInChanged(const AccountIds& ids,
199e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                         bool is_signed_in) {
200e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  api::identity::AccountInfo account_info;
201e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  account_info.id = ids.gaia;
202e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
203e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  scoped_ptr<base::ListValue> args =
204e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      api::identity::OnSignInChanged::Create(account_info, is_signed_in);
205e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  scoped_ptr<Event> event(new Event(api::identity::OnSignInChanged::kEventName,
206e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                    args.Pass(),
207e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                    browser_context_));
208e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
2090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter::Get(browser_context_)->BroadcastEvent(event.Pass());
210e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
211e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
212e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityAPI::AddShutdownObserver(ShutdownObserver* observer) {
213e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shutdown_observer_list_.AddObserver(observer);
214e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
215e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
216e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityAPI::RemoveShutdownObserver(ShutdownObserver* observer) {
217e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shutdown_observer_list_.RemoveObserver(observer);
218e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
219e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
220e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochtemplate <>
221e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid BrowserContextKeyedAPIFactory<IdentityAPI>::DeclareFactoryDependencies() {
222e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
223e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
224e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
225e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : OAuth2TokenService::Consumer("extensions_identity_api"),
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      should_prompt_for_scopes_(false),
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      should_prompt_for_signin_(false) {}
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool IdentityGetAuthTokenFunction::RunAsync() {
2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (GetProfile()->IsOffTheRecord()) {
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_ = identity_constants::kOffTheRecord;
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<identity::GetAuthToken::Params> params(
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      identity::GetAuthToken::Params::Create(*args_));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool interactive = params->details.get() &&
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params->details->interactive.get() &&
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      *params->details->interactive;
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_scopes_ = interactive;
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_signin_ = interactive;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check that the necessary information is present in the manifest.
252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  oauth2_client_id_ = GetOAuth2ClientId();
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (oauth2_client_id_.empty()) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = identity_constants::kInvalidClientId;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (oauth2_info.scopes.size() == 0) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = identity_constants::kInvalidScopes;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::set<std::string> scopes(oauth2_info.scopes.begin(),
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               oauth2_info.scopes.end());
265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  token_key_.reset(new ExtensionTokenKey(
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetExtension()->id(), GetPrimaryAccountId(GetProfile()), scopes));
267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
268e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // From here on out, results must be returned asynchronously.
269e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  StartAsyncRun();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_CHROMEOS)
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  policy::BrowserPolicyConnectorChromeOS* connector =
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      g_browser_process->platform_part()->browser_policy_connector_chromeos();
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (chromeos::UserManager::Get()->IsLoggedInAsKioskApp() &&
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      connector->IsEnterpriseManaged()) {
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return true;
278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HasLoginToken()) {
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!should_prompt_for_signin_) {
283e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
284e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return true;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Display a login prompt.
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StartSigninFlow();
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityGetAuthTokenFunction::StartAsyncRun() {
296e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Balanced in CompleteAsyncRun
297e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  AddRef();
298e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  extensions::IdentityAPI::GetFactoryInstance()
299e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      ->Get(GetProfile())
300e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      ->AddShutdownObserver(this);
301e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
302e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
303e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityGetAuthTokenFunction::CompleteAsyncRun(bool success) {
304e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  extensions::IdentityAPI::GetFactoryInstance()
305e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      ->Get(GetProfile())
306e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      ->RemoveShutdownObserver(this);
307e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
308e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  SendResponse(success);
309e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  Release();  // Balanced in StartAsyncRun
310e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
311e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::CompleteFunctionWithResult(
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& access_token) {
314e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SetResult(new base::StringValue(access_token));
316e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CompleteAsyncRun(true);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::CompleteFunctionWithError(
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& error) {
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  error_ = error;
322e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CompleteAsyncRun(false);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartSigninFlow() {
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // All cached tokens are invalid because the user is not signed in.
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI* id_api =
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      extensions::IdentityAPI::GetFactoryInstance()->Get(GetProfile());
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  id_api->EraseAllCachedTokens();
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Display a login prompt. If the subsequent mint fails, don't display the
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // login prompt again.
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_signin_ = false;
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ShowLoginPopup();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartMintTokenFlow(
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IdentityMintRequestQueue::MintType type) {
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mint_token_flow_type_ = type;
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Flows are serialized to prevent excessive traffic to GAIA, and
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to consolidate UI pop-ups.
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityAPI* id_api =
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      extensions::IdentityAPI::GetFactoryInstance()->Get(GetProfile());
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!should_prompt_for_scopes_) {
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Caller requested no interaction.
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE) {
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // GAIA told us to do a consent UI.
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteFunctionWithError(identity_constants::kNoGrant);
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!id_api->mint_queue()->empty(
354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE, *token_key_)) {
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Another call is going through a consent UI.
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteFunctionWithError(identity_constants::kNoGrant);
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  id_api->mint_queue()->RequestStart(type, *token_key_, this);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() {
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityMintRequestQueue::MintType type = mint_token_flow_type_;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::set<std::string> scopes(oauth2_info.scopes.begin(),
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               oauth2_info.scopes.end());
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  extensions::IdentityAPI::GetFactoryInstance()
371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ->Get(GetProfile())
3721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ->mint_queue()
373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ->RequestComplete(type, *token_key_, this);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartMintToken(
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IdentityMintRequestQueue::MintType type) {
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  IdentityAPI* id_api = IdentityAPI::GetFactoryInstance()->Get(GetProfile());
380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  IdentityTokenCacheValue cache_entry = id_api->GetCachedToken(*token_key_);
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityTokenCacheValue::CacheValueStatus cache_status =
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      cache_entry.status();
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (type == IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE) {
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    switch (cache_status) {
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND:
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(OS_CHROMEOS)
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // Always force minting token for ChromeOS kiosk app.
389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (chromeos::UserManager::Get()->IsLoggedInAsKioskApp()) {
3908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE;
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          policy::BrowserPolicyConnectorChromeOS* connector =
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              g_browser_process->platform_part()
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  ->browser_policy_connector_chromeos();
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          if (connector->IsEnterpriseManaged()) {
3958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            StartDeviceLoginAccessTokenRequest();
396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          } else {
3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            StartLoginAccessTokenRequest();
398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          }
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          return;
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        if (oauth2_info.auto_approve)
4047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          // oauth2_info.auto_approve is protected by a whitelist in
4057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          // _manifest_features.json hence only selected extensions take
4067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          // advantage of forcefully minting the token.
4077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE;
4087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        else
4097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE;
4107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        StartLoginAccessTokenRequest();
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case IdentityTokenCacheValue::CACHE_STATUS_TOKEN:
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CompleteMintTokenFlow();
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CompleteFunctionWithResult(cache_entry.token());
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case IdentityTokenCacheValue::CACHE_STATUS_ADVICE:
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CompleteMintTokenFlow();
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        should_prompt_for_signin_ = false;
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        issue_advice_ = cache_entry.issue_advice();
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (cache_status == IdentityTokenCacheValue::CACHE_STATUS_TOKEN) {
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteMintTokenFlow();
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CompleteFunctionWithResult(cache_entry.token());
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ShowOAuthApprovalDialog(issue_advice_);
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnMintTokenSuccess(
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& access_token, int time_to_live) {
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IdentityTokenCacheValue token(access_token,
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                base::TimeDelta::FromSeconds(time_to_live));
441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  IdentityAPI::GetFactoryInstance()->Get(GetProfile())->SetCachedToken(
442a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      *token_key_, token);
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteFunctionWithResult(access_token);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnMintTokenFailure(
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GoogleServiceAuthError& error) {
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (error.state()) {
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case GoogleServiceAuthError::ACCOUNT_DELETED:
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case GoogleServiceAuthError::ACCOUNT_DISABLED:
4561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      extensions::IdentityAPI::GetFactoryInstance()
457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          ->Get(GetProfile())
4581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          ->ReportAuthError(error);
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (should_prompt_for_signin_) {
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Display a login prompt and try again (once).
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        StartSigninFlow();
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return;
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Return error to caller.
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteFunctionWithError(
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string(identity_constants::kAuthFailure) + error.ToString());
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IssueAdviceInfo& issue_advice) {
476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  IdentityAPI::GetFactoryInstance()->Get(GetProfile())->SetCachedToken(
477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      *token_key_, IdentityTokenCacheValue(issue_advice));
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  should_prompt_for_signin_ = false;
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Existing grant was revoked and we used NO_FORCE, so we got info back
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // instead. Start a consent UI if we can.
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  issue_advice_ = issue_advice;
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid IdentityGetAuthTokenFunction::SigninSuccess() {
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::SigninFailed() {
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
49590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnGaiaFlowFailure(
49690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    GaiaWebAuthFlow::Failure failure,
49790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    GoogleServiceAuthError service_error,
49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& oauth_error) {
49990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CompleteMintTokenFlow();
50090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string error;
50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (failure) {
50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GaiaWebAuthFlow::WINDOW_CLOSED:
50490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = identity_constants::kUserRejected;
50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
50690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GaiaWebAuthFlow::INVALID_REDIRECT:
50890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = identity_constants::kInvalidRedirect;
50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
51090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
51190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GaiaWebAuthFlow::SERVICE_AUTH_ERROR:
51290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = std::string(identity_constants::kAuthFailure) +
51390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          service_error.ToString();
51490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
51590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case GaiaWebAuthFlow::OAUTH_ERROR:
51790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = MapOAuth2ErrorToDescription(oauth_error);
51890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
51990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case GaiaWebAuthFlow::LOAD_FAILED:
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      error = identity_constants::kPageLoadFailure;
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
52490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
52590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      NOTREACHED() << "Unexpected error from gaia web auth flow: " << failure;
52690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error = identity_constants::kInvalidRedirect;
52790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
52890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
52990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
53090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CompleteFunctionWithError(error);
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void IdentityGetAuthTokenFunction::OnGaiaFlowCompleted(
53490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& access_token,
53590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& expiration) {
53690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
53790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int time_to_live;
53890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!expiration.empty() && base::StringToInt(expiration, &time_to_live)) {
53990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    IdentityTokenCacheValue token_value(
54090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        access_token, base::TimeDelta::FromSeconds(time_to_live));
541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    IdentityAPI::GetFactoryInstance()->Get(GetProfile())->SetCachedToken(
542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        *token_key_, token_value);
54390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CompleteMintTokenFlow();
54690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CompleteFunctionWithResult(access_token);
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IdentityGetAuthTokenFunction::OnGetTokenSuccess(
550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const OAuth2TokenService::Request* request,
551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& access_token,
552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const base::Time& expiration_time) {
5538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  login_token_request_.reset();
5548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  StartGaiaRequest(access_token);
555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IdentityGetAuthTokenFunction::OnGetTokenFailure(
558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const OAuth2TokenService::Request* request,
559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const GoogleServiceAuthError& error) {
5608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  login_token_request_.reset();
561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OnGaiaFlowFailure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR, error, std::string());
562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
564e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IdentityGetAuthTokenFunction::OnShutdown() {
565e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  gaia_web_auth_flow_.reset();
566e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  signin_flow_.reset();
567e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  login_token_request_.reset();
568e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  extensions::IdentityAPI::GetFactoryInstance()
569e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      ->Get(GetProfile())
570e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      ->mint_queue()
571e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      ->RequestCancel(*token_key_, this);
572e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CompleteFunctionWithError(identity_constants::kCanceled);
573e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
574e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
5758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_CHROMEOS)
5768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartDeviceLoginAccessTokenRequest() {
577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  chromeos::DeviceOAuth2TokenService* service =
578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      chromeos::DeviceOAuth2TokenServiceFactory::Get();
5798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Since robot account refresh tokens are scoped down to [any-api] only,
5808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // request access token for [any-api] instead of login.
5818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  OAuth2TokenService::ScopeSet scopes;
5828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  scopes.insert(GaiaConstants::kAnyApiOAuth2Scope);
5838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  login_token_request_ =
5848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      service->StartRequest(service->GetRobotAccountId(),
5858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            scopes,
5868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                            this);
5878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
5888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif
5898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid IdentityGetAuthTokenFunction::StartLoginAccessTokenRequest() {
591a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ProfileOAuth2TokenService* service =
5921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::string primary_account_id = GetPrimaryAccountId(GetProfile());
594a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#if defined(OS_CHROMEOS)
595a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (chrome::IsRunningInForcedAppMode()) {
596a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::string app_client_id;
597a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::string app_client_secret;
598a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (chromeos::UserManager::Get()->GetAppModeChromeClientOAuthInfo(
599a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)           &app_client_id, &app_client_secret)) {
600a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      login_token_request_ =
6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          service->StartRequestForClient(primary_account_id,
60268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                         app_client_id,
603a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         app_client_secret,
604a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         OAuth2TokenService::ScopeSet(),
605a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         this);
606a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return;
607a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
608a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
609a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif
61068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  login_token_request_ = service->StartRequest(
6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      primary_account_id, OAuth2TokenService::ScopeSet(), this);
6127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
6137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::StartGaiaRequest(
6157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& login_access_token) {
6167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!login_access_token.empty());
6177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  mint_token_flow_.reset(CreateMintTokenFlow(login_access_token));
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mint_token_flow_->Start();
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityGetAuthTokenFunction::ShowLoginPopup() {
6221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  signin_flow_.reset(new IdentitySigninFlow(this, GetProfile()));
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  signin_flow_->Start();
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog(
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IssueAdviceInfo& issue_advice) {
62890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const std::string locale = g_browser_process->local_state()->GetString(
630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      prefs::kApplicationLocale);
63190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
63290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  gaia_web_auth_flow_.reset(new GaiaWebAuthFlow(
6331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      this, GetProfile(), GetExtension()->id(), oauth2_info, locale));
63490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  gaia_web_auth_flow_->Start();
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OAuth2MintTokenFlow* IdentityGetAuthTokenFunction::CreateMintTokenFlow(
6387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& login_access_token) {
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  OAuth2MintTokenFlow* mint_token_flow = new OAuth2MintTokenFlow(
6421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      GetProfile()->GetRequestContext(),
6431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      this,
6441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      OAuth2MintTokenFlow::Parameters(login_access_token,
6451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      GetExtension()->id(),
6461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      oauth2_client_id_,
6471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      oauth2_info.scopes,
6481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                      gaia_mint_token_mode_));
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return mint_token_flow;
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IdentityGetAuthTokenFunction::HasLoginToken() const {
65368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ProfileOAuth2TokenService* token_service =
6541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile());
65568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return token_service->RefreshTokenIsAvailable(
6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetPrimaryAccountId(GetProfile()));
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string IdentityGetAuthTokenFunction::MapOAuth2ErrorToDescription(
66090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& error) {
66190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char kOAuth2ErrorAccessDenied[] = "access_denied";
66290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char kOAuth2ErrorInvalidScope[] = "invalid_scope";
66390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
66490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error == kOAuth2ErrorAccessDenied)
66590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return std::string(identity_constants::kUserRejected);
66690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else if (error == kOAuth2ErrorInvalidScope)
66790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return std::string(identity_constants::kInvalidScopes);
66890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else
66990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return std::string(identity_constants::kAuthFailure) + error;
67090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
67190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string IdentityGetAuthTokenFunction::GetOAuth2ClientId() const {
673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(GetExtension());
674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string client_id = oauth2_info.client_id;
675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Component apps using auto_approve may use Chrome's client ID by
677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // omitting the field.
678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (client_id.empty() && GetExtension()->location() == Manifest::COMPONENT &&
679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      oauth2_info.auto_approve) {
680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return client_id;
683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityRemoveCachedAuthTokenFunction::IdentityRemoveCachedAuthTokenFunction() {
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)IdentityRemoveCachedAuthTokenFunction::
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ~IdentityRemoveCachedAuthTokenFunction() {
690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool IdentityRemoveCachedAuthTokenFunction::RunSync() {
6931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (GetProfile()->IsOffTheRecord()) {
694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_ = identity_constants::kOffTheRecord;
695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<identity::RemoveCachedAuthToken::Params> params(
699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      identity::RemoveCachedAuthToken::Params::Create(*args_));
700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
701a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  IdentityAPI::GetFactoryInstance()->Get(GetProfile())->EraseCachedToken(
702a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetExtension()->id(), params->details.token);
703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IdentityLaunchWebAuthFlowFunction::IdentityLaunchWebAuthFlowFunction() {}
70790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
70890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)IdentityLaunchWebAuthFlowFunction::~IdentityLaunchWebAuthFlowFunction() {
70990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (auth_flow_)
71090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    auth_flow_.release()->DetachDelegateAndDelete();
71190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
713010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool IdentityLaunchWebAuthFlowFunction::RunAsync() {
7141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (GetProfile()->IsOffTheRecord()) {
715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    error_ = identity_constants::kOffTheRecord;
716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
718c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<identity::LaunchWebAuthFlow::Params> params(
720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      identity::LaunchWebAuthFlow::Params::Create(*args_));
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL auth_url(params->details.url);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebAuthFlow::Mode mode =
725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      params->details.interactive && *params->details.interactive ?
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebAuthFlow::INTERACTIVE : WebAuthFlow::SILENT;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Set up acceptable target URLs. (Does not include chrome-extension
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // scheme for this version of the API.)
730b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  InitFinalRedirectURLPrefix(GetExtension()->id());
731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();  // Balanced in OnAuthFlowSuccess/Failure.
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  auth_flow_.reset(new WebAuthFlow(this, GetProfile(), auth_url, mode));
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_flow_->Start();
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
739b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::InitFinalRedirectURLPrefixForTest(
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& extension_id) {
741b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  InitFinalRedirectURLPrefix(extension_id);
742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
744b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::InitFinalRedirectURLPrefix(
745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& extension_id) {
746b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (final_url_prefix_.is_empty()) {
747b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    final_url_prefix_ = GURL(base::StringPrintf(
748b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        kChromiumDomainRedirectUrlPattern, extension_id.c_str()));
749b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::OnAuthFlowFailure(
753c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WebAuthFlow::Failure failure) {
754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (failure) {
755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case WebAuthFlow::WINDOW_CLOSED:
756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_ = identity_constants::kUserRejected;
757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case WebAuthFlow::INTERACTION_REQUIRED:
759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_ = identity_constants::kInteractionRequired;
760c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case WebAuthFlow::LOAD_FAILED:
762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      error_ = identity_constants::kPageLoadFailure;
763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NOTREACHED() << "Unexpected error from web auth flow: " << failure;
766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      error_ = identity_constants::kInvalidRedirect;
767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendResponse(false);
770010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  Release();  // Balanced in RunAsync.
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IdentityLaunchWebAuthFlowFunction::OnAuthFlowURLChange(
774c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GURL& redirect_url) {
775b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (redirect_url.GetWithEmptyPath() == final_url_prefix_) {
7763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SetResult(new base::StringValue(redirect_url.spec()));
777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SendResponse(true);
778010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    Release();  // Balanced in RunAsync.
779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
783