#include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h"
+#include "base/debug/trace_event.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_manager.h"
+#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/base/escape.h"
GaiaWebAuthFlow::GaiaWebAuthFlow(Delegate* delegate,
Profile* profile,
- const std::string& extension_id,
- const OAuth2Info& oauth2_info,
+ const ExtensionTokenKey* token_key,
+ const std::string& oauth2_client_id,
const std::string& locale)
: delegate_(delegate),
- profile_(profile) {
+ profile_(profile),
+ account_id_(token_key->account_id) {
+ TRACE_EVENT_ASYNC_BEGIN2("identity",
+ "GaiaWebAuthFlow",
+ this,
+ "extension_id",
+ token_key->extension_id,
+ "account_id",
+ token_key->account_id);
+
const char kOAuth2RedirectPathFormat[] = "/%s#";
const char kOAuth2AuthorizeFormat[] =
"?response_type=token&approval_prompt=force&authuser=0&"
"origin=chrome-extension://%s/&"
"redirect_uri=%s:/%s&"
"hl=%s";
+ // Additional parameters to pass if device_id is enabled.
+ const char kOAuth2AuthorizeFormatDeviceIdAddendum[] =
+ "&device_id=%s&"
+ "device_type=chrome";
+ std::vector<std::string> scopes(token_key->scopes.begin(),
+ token_key->scopes.end());
std::vector<std::string> client_id_parts;
- base::SplitString(oauth2_info.client_id, '.', &client_id_parts);
+ base::SplitString(oauth2_client_id, '.', &client_id_parts);
std::reverse(client_id_parts.begin(), client_id_parts.end());
redirect_scheme_ = JoinString(client_id_parts, '.');
-
- redirect_path_prefix_ =
- base::StringPrintf(kOAuth2RedirectPathFormat, extension_id.c_str());
-
+ std::string signin_scoped_device_id;
+ // profile_ can be nullptr in unittests.
+ SigninClient* signin_client =
+ profile_ ? ChromeSigninClientFactory::GetForProfile(profile_) : nullptr;
+ if (signin_client)
+ signin_scoped_device_id = signin_client->GetSigninScopedDeviceId();
+
+ redirect_path_prefix_ = base::StringPrintf(kOAuth2RedirectPathFormat,
+ token_key->extension_id.c_str());
+
+ std::string oauth2_authorize_params = base::StringPrintf(
+ kOAuth2AuthorizeFormat,
+ oauth2_client_id.c_str(),
+ net::EscapeUrlEncodedData(JoinString(scopes, ' '), true).c_str(),
+ token_key->extension_id.c_str(),
+ redirect_scheme_.c_str(),
+ token_key->extension_id.c_str(),
+ locale.c_str());
+ if (!signin_scoped_device_id.empty()) {
+ oauth2_authorize_params += base::StringPrintf(
+ kOAuth2AuthorizeFormatDeviceIdAddendum,
+ net::EscapeUrlEncodedData(signin_scoped_device_id, true).c_str());
+ }
auth_url_ = GaiaUrls::GetInstance()->oauth2_auth_url().Resolve(
- base::StringPrintf(kOAuth2AuthorizeFormat,
- oauth2_info.client_id.c_str(),
- net::EscapeUrlEncodedData(
- JoinString(oauth2_info.scopes, ' '), true).c_str(),
- extension_id.c_str(),
- redirect_scheme_.c_str(),
- extension_id.c_str(),
- locale.c_str()));
+ oauth2_authorize_params);
}
GaiaWebAuthFlow::~GaiaWebAuthFlow() {
+ TRACE_EVENT_ASYNC_END0("identity", "GaiaWebAuthFlow", this);
+
if (web_flow_)
web_flow_.release()->DetachDelegateAndDelete();
}
void GaiaWebAuthFlow::Start() {
- ubertoken_fetcher_.reset(new UbertokenFetcher(profile_, this));
- ubertoken_fetcher_->StartFetchingToken();
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
+ ubertoken_fetcher_.reset(new UbertokenFetcher(token_service,
+ this,
+ GaiaConstants::kChromeSource,
+ profile_->GetRequestContext()));
+ ubertoken_fetcher_->StartFetchingToken(account_id_);
}
void GaiaWebAuthFlow::OnUbertokenSuccess(const std::string& token) {
+ TRACE_EVENT_ASYNC_STEP_PAST0(
+ "identity", "GaiaWebAuthFlow", this, "OnUbertokenSuccess");
+
const char kMergeSessionQueryFormat[] = "?uberauth=%s&"
"continue=%s&"
"source=appsv2";
}
void GaiaWebAuthFlow::OnUbertokenFailure(const GoogleServiceAuthError& error) {
+ TRACE_EVENT_ASYNC_STEP_PAST1("identity",
+ "GaiaWebAuthFlow",
+ this,
+ "OnUbertokenSuccess",
+ "error",
+ error.ToString());
+
+ DVLOG(1) << "OnUbertokenFailure: " << error.error_message();
delegate_->OnGaiaFlowFailure(
GaiaWebAuthFlow::SERVICE_AUTH_ERROR, error, std::string());
}
gaia_failure = GaiaWebAuthFlow::WINDOW_CLOSED;
break;
case WebAuthFlow::LOAD_FAILED:
+ DVLOG(1) << "OnAuthFlowFailure LOAD_FAILED";
gaia_failure = GaiaWebAuthFlow::LOAD_FAILED;
break;
default:
break;
}
+ TRACE_EVENT_ASYNC_STEP_PAST1("identity",
+ "GaiaWebAuthFlow",
+ this,
+ "OnAuthFlowFailure",
+ "error",
+ gaia_failure);
+
delegate_->OnGaiaFlowFailure(
gaia_failure,
GoogleServiceAuthError(GoogleServiceAuthError::NONE),
}
void GaiaWebAuthFlow::OnAuthFlowURLChange(const GURL& url) {
+ TRACE_EVENT_ASYNC_STEP_PAST0("identity",
+ "GaiaWebAuthFlow",
+ this,
+ "OnAuthFlowURLChange");
+
const char kOAuth2RedirectAccessTokenKey[] = "access_token";
const char kOAuth2RedirectErrorKey[] = "error";
const char kOAuth2ExpiresInKey[] = "expires_in";
std::string fragment = url.GetContent().substr(
redirect_path_prefix_.length(), std::string::npos);
- std::vector<std::pair<std::string, std::string> > pairs;
+ base::StringPairs pairs;
base::SplitStringIntoKeyValuePairs(fragment, '=', '&', &pairs);
std::string access_token;
std::string error;
std::string expiration;
- for (std::vector<std::pair<std::string, std::string> >::iterator
- it = pairs.begin();
+ for (base::StringPairs::iterator it = pairs.begin();
it != pairs.end();
++it) {
if (it->first == kOAuth2RedirectAccessTokenKey)